| 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);
|
|
|