| Index: src/IceCfgNode.cpp
|
| diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
|
| index dbbfc186a9c9ced499a864a8c20fced057de3faa..a3f6dd5fd30093232c2c7dd403a4a0d4dc923249 100644
|
| --- a/src/IceCfgNode.cpp
|
| +++ b/src/IceCfgNode.cpp
|
| @@ -681,6 +681,61 @@ bool CfgNode::liveness(Liveness *Liveness) {
|
| return Changed;
|
| }
|
|
|
| +// Validate the integrity of the live ranges in this block. If there are any
|
| +// errors, it prints details and returns false. On success, it returns true.
|
| +bool CfgNode::livenessValidateIntervals(Liveness *Liveness) {
|
| + if (!BuildDefs::asserts())
|
| + return true;
|
| +
|
| + // Verify there are no duplicates.
|
| + auto ComparePair =
|
| + [](const LiveBeginEndMapEntry &A, const LiveBeginEndMapEntry &B) {
|
| + return A.first == B.first;
|
| + };
|
| + LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this);
|
| + LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this);
|
| + if (std::adjacent_find(MapBegin.begin(), MapBegin.end(), ComparePair) ==
|
| + MapBegin.end() &&
|
| + std::adjacent_find(MapEnd.begin(), MapEnd.end(), ComparePair) ==
|
| + MapEnd.end())
|
| + return true;
|
| +
|
| + // There is definitely a liveness error. All paths from here return false.
|
| + if (!BuildDefs::dump())
|
| + return false;
|
| +
|
| + // Print all the errors.
|
| + if (BuildDefs::dump()) {
|
| + GlobalContext *Ctx = Func->getContext();
|
| + OstreamLocker L(Ctx);
|
| + Ostream &Str = Ctx->getStrDump();
|
| + if (Func->isVerbose()) {
|
| + Str << "Live range errors in the following block:\n";
|
| + dump(Func);
|
| + }
|
| + for (auto Start = MapBegin.begin();
|
| + (Start = std::adjacent_find(Start, MapBegin.end(), ComparePair)) !=
|
| + MapBegin.end();
|
| + ++Start) {
|
| + auto Next = Start + 1;
|
| + Str << "Duplicate LR begin, block " << getName() << ", instructions "
|
| + << Start->second << " & " << Next->second << ", variable "
|
| + << Liveness->getVariable(Start->first, this)->getName(Func) << "\n";
|
| + }
|
| + for (auto Start = MapEnd.begin();
|
| + (Start = std::adjacent_find(Start, MapEnd.end(), ComparePair)) !=
|
| + MapEnd.end();
|
| + ++Start) {
|
| + auto Next = Start + 1;
|
| + Str << "Duplicate LR end, block " << getName() << ", instructions "
|
| + << Start->second << " & " << Next->second << ", variable "
|
| + << Liveness->getVariable(Start->first, this)->getName(Func) << "\n";
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| // Once basic liveness is complete, compute actual live ranges. It is assumed
|
| // that within a single basic block, a live range begins at most once and ends
|
| // at most once. This is certainly true for pure SSA form. It is also true once
|
| @@ -698,16 +753,11 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
|
| LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this);
|
| std::sort(MapBegin.begin(), MapBegin.end());
|
| std::sort(MapEnd.begin(), MapEnd.end());
|
| - // Verify there are no duplicates.
|
| - auto ComparePair =
|
| - [](const LiveBeginEndMapEntry &A, const LiveBeginEndMapEntry &B) {
|
| - return A.first == B.first;
|
| - };
|
| - (void)ComparePair;
|
| - assert(std::adjacent_find(MapBegin.begin(), MapBegin.end(), ComparePair) ==
|
| - MapBegin.end());
|
| - assert(std::adjacent_find(MapEnd.begin(), MapEnd.end(), ComparePair) ==
|
| - MapEnd.end());
|
| +
|
| + if (!livenessValidateIntervals(Liveness)) {
|
| + llvm::report_fatal_error("livenessAddIntervals: Liveness error");
|
| + return;
|
| + }
|
|
|
| LivenessBV LiveInAndOut = LiveIn;
|
| LiveInAndOut &= LiveOut;
|
| @@ -875,11 +925,11 @@ void emitLiveRangesEnded(Ostream &Str, const Cfg *Func, const Inst *Instr,
|
| bool First = true;
|
| Variable *Dest = Instr->getDest();
|
| // Normally we increment the live count for the dest register. But we
|
| - // shouldn't if the instruction's IsDestNonKillable flag is set, because this
|
| + // shouldn't if the instruction's IsDestRedefined flag is set, because this
|
| // means that the target lowering created this instruction as a non-SSA
|
| // assignment; i.e., a different, previous instruction started the dest
|
| // variable's live range.
|
| - if (!Instr->isDestNonKillable() && Dest && Dest->hasReg())
|
| + if (!Instr->isDestRedefined() && Dest && Dest->hasReg())
|
| ++LiveRegCount[Dest->getRegNum()];
|
| FOREACH_VAR_IN_INST(Var, *Instr) {
|
| bool ShouldReport = Instr->isLastUse(Var);
|
|
|