Index: src/IceCfg.cpp |
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp |
index 83d8e2664cd70cc9b4cea2fcc69e12af943a0a6f..c30e02a28ccdef113dc0f99122f6beeaf77584c7 100644 |
--- a/src/IceCfg.cpp |
+++ b/src/IceCfg.cpp |
@@ -205,9 +205,9 @@ void Cfg::liveness(LivenessMode Mode) { |
// Collect timing for just the portion that constructs the live |
// range intervals based on the end-of-live-range computation, for a |
// finer breakdown of the cost. |
+ TimerMarker T1(TimerStack::TT_liveRange, this); |
// Make a final pass over instructions to delete dead instructions |
// and build each Variable's live range. |
- TimerMarker T1(TimerStack::TT_liveRange, this); |
for (CfgNode *Node : Nodes) |
Node->livenessPostprocess(Mode, getLiveness()); |
if (Mode == Liveness_Intervals) { |
@@ -246,7 +246,6 @@ void Cfg::liveness(LivenessMode Mode) { |
if (Var->getWeight().isInf()) |
Var->setLiveRangeInfiniteWeight(); |
} |
- dump(); |
} |
} |
@@ -257,24 +256,37 @@ bool Cfg::validateLiveness() const { |
bool Valid = true; |
Ostream &Str = Ctx->getStrDump(); |
for (CfgNode *Node : Nodes) { |
+ Inst *FirstInst = NULL; |
for (Inst *Inst : Node->getInsts()) { |
if (Inst->isDeleted()) |
continue; |
if (llvm::isa<InstFakeKill>(Inst)) |
continue; |
+ if (FirstInst == NULL) |
+ FirstInst = Inst; |
InstNumberT InstNumber = Inst->getNumber(); |
- Variable *Dest = Inst->getDest(); |
- if (Dest) { |
- // TODO: This instruction should actually begin Dest's live |
- // range, so we could probably test that this instruction is |
- // the beginning of some segment of Dest's live range. But |
- // this wouldn't work with non-SSA temporaries during |
- // lowering. |
- if (!Dest->getLiveRange().containsValue(InstNumber)) { |
- Valid = false; |
- Str << "Liveness error: inst " << Inst->getNumber() << " dest "; |
- Dest->dump(this); |
- Str << " live range " << Dest->getLiveRange() << "\n"; |
+ if (Variable *Dest = Inst->getDest()) { |
+ if (!Dest->getIgnoreLiveness()) { |
+ bool Invalid = false; |
+ const bool IsDest = true; |
+ if (!Dest->getLiveRange().containsValue(InstNumber, IsDest)) |
+ Invalid = true; |
+ // Check that this instruction actually *begins* Dest's live |
+ // range, by checking that Dest is not live in the previous |
+ // instruction. As a special exception, we don't check this |
+ // for the first instruction of the block, because a Phi |
+ // temporary may be live at the end of the previous block, |
+ // and if it is also assigned in the first instruction of |
+ // this block, the adjacent live ranges get merged. |
+ if (Inst != FirstInst && !Inst->isDestNonKillable() && |
+ Dest->getLiveRange().containsValue(InstNumber - 1, IsDest)) |
+ Invalid = true; |
+ if (Invalid) { |
+ Valid = false; |
+ Str << "Liveness error: inst " << Inst->getNumber() << " dest "; |
+ Dest->dump(this); |
+ Str << " live range " << Dest->getLiveRange() << "\n"; |
+ } |
} |
} |
for (SizeT I = 0; I < Inst->getSrcSize(); ++I) { |
@@ -282,7 +294,9 @@ bool Cfg::validateLiveness() const { |
SizeT NumVars = Src->getNumVars(); |
for (SizeT J = 0; J < NumVars; ++J) { |
const Variable *Var = Src->getVar(J); |
- if (!Var->getLiveRange().containsValue(InstNumber)) { |
+ const bool IsDest = false; |
+ if (!Var->getIgnoreLiveness() && |
+ !Var->getLiveRange().containsValue(InstNumber, IsDest)) { |
Valid = false; |
Str << "Liveness error: inst " << Inst->getNumber() << " var "; |
Var->dump(this); |