| Index: src/IceCfgNode.cpp
|
| diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
|
| index 9dbe7df11440610c2484cae8b1e9fc0322945fa3..6cadcf65ec63f87139fc9c373caa748aa84b697a 100644
|
| --- a/src/IceCfgNode.cpp
|
| +++ b/src/IceCfgNode.cpp
|
| @@ -626,8 +626,11 @@ void CfgNode::livenessLightweight() {
|
| // liveness changed from before, false if it stayed the same. (If it changes,
|
| // the node's predecessors need to be processed again.)
|
| bool CfgNode::liveness(Liveness *Liveness) {
|
| - SizeT NumVars = Liveness->getNumVarsInNode(this);
|
| - LivenessBV Live(NumVars);
|
| + const SizeT NumVars = Liveness->getNumVarsInNode(this);
|
| + const SizeT NumGlobalVars = Liveness->getNumGlobalVars();
|
| + LivenessBV &Live = Liveness->getScratchBV();
|
| + Live.clear();
|
| +
|
| LiveBeginEndMap *LiveBegin = nullptr;
|
| LiveBeginEndMap *LiveEnd = nullptr;
|
| // Mark the beginning and ending of each variable's live range with the
|
| @@ -642,19 +645,25 @@ bool CfgNode::liveness(Liveness *Liveness) {
|
| LiveBegin->reserve(getInstCountEstimate());
|
| LiveEnd->reserve(getInstCountEstimate());
|
| }
|
| +
|
| // Initialize Live to be the union of all successors' LiveIn.
|
| for (CfgNode *Succ : OutEdges) {
|
| - Live |= Liveness->getLiveIn(Succ);
|
| + const LivenessBV &LiveIn = Liveness->getLiveIn(Succ);
|
| + assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars);
|
| + Live |= LiveIn;
|
| // Mark corresponding argument of phis in successor as live.
|
| for (Inst &I : Succ->Phis) {
|
| if (I.isDeleted())
|
| continue;
|
| - auto *Phi = llvm::dyn_cast<InstPhi>(&I);
|
| + auto *Phi = llvm::cast<InstPhi>(&I);
|
| Phi->livenessPhiOperand(Live, this, Liveness);
|
| }
|
| }
|
| + assert(Live.empty() || Live.size() == NumGlobalVars);
|
| Liveness->getLiveOut(this) = Live;
|
|
|
| + // Expand Live so it can hold locals in addition to globals.
|
| + Live.resize(NumVars);
|
| // Process regular instructions in reverse order.
|
| for (Inst &I : reverse_range(Insts)) {
|
| if (I.isDeleted())
|
| @@ -676,20 +685,17 @@ bool CfgNode::liveness(Liveness *Liveness) {
|
|
|
| // When using the sparse representation, after traversing the instructions in
|
| // the block, the Live bitvector should only contain set bits for global
|
| - // variables upon block entry. We validate this by shrinking the Live vector
|
| - // and then testing it against the pre-shrunk version. (The shrinking is
|
| - // required, but the validation is not.)
|
| - LivenessBV LiveOrig = Live;
|
| - Live.resize(Liveness->getNumGlobalVars());
|
| - if (Live != LiveOrig) {
|
| + // variables upon block entry. We validate this by testing the upper bits of
|
| + // the Live bitvector.
|
| + if (Live.find_next(NumGlobalVars) != -1) {
|
| if (BuildDefs::dump()) {
|
| // This is a fatal liveness consistency error. Print some diagnostics and
|
| // abort.
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Func->resetCurrentNode();
|
| - Str << "LiveOrig-Live =";
|
| - for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) {
|
| - if (LiveOrig.test(i)) {
|
| + Str << "Invalid Live =";
|
| + for (SizeT i = NumGlobalVars; i < Live.size(); ++i) {
|
| + if (Live.test(i)) {
|
| Str << " ";
|
| Liveness->getVariable(i, this)->dump(Func);
|
| }
|
| @@ -698,9 +704,12 @@ bool CfgNode::liveness(Liveness *Liveness) {
|
| }
|
| llvm::report_fatal_error("Fatal inconsistency in liveness analysis");
|
| }
|
| + // Now truncate Live to prevent LiveIn from growing.
|
| + Live.resize(NumGlobalVars);
|
|
|
| bool Changed = false;
|
| LivenessBV &LiveIn = Liveness->getLiveIn(this);
|
| + assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars);
|
| // Add in current LiveIn
|
| Live |= LiveIn;
|
| // Check result, set LiveIn=Live
|
| @@ -778,9 +787,9 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
|
| InstNumberT LastInstNum) {
|
| TimerMarker T1(TimerStack::TT_liveRange, Func);
|
|
|
| - SizeT NumVars = Liveness->getNumVarsInNode(this);
|
| - LivenessBV &LiveIn = Liveness->getLiveIn(this);
|
| - LivenessBV &LiveOut = Liveness->getLiveOut(this);
|
| + const SizeT NumVars = Liveness->getNumVarsInNode(this);
|
| + const LivenessBV &LiveIn = Liveness->getLiveIn(this);
|
| + const LivenessBV &LiveOut = Liveness->getLiveOut(this);
|
| LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this);
|
| LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this);
|
| std::sort(MapBegin.begin(), MapBegin.end());
|
| @@ -791,7 +800,8 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
|
| return;
|
| }
|
|
|
| - LivenessBV LiveInAndOut = LiveIn;
|
| + LivenessBV &LiveInAndOut = Liveness->getScratchBV();
|
| + LiveInAndOut = LiveIn;
|
| LiveInAndOut &= LiveOut;
|
|
|
| // Iterate in parallel across the sorted MapBegin[] and MapEnd[].
|
| @@ -1350,23 +1360,23 @@ void CfgNode::dump(Cfg *Func) const {
|
| Str << "\n";
|
| }
|
| // Dump the live-in variables.
|
| - LivenessBV LiveIn;
|
| - if (Liveness)
|
| - LiveIn = Liveness->getLiveIn(this);
|
| - if (Func->isVerbose(IceV_Liveness) && !LiveIn.empty()) {
|
| - Str << " // LiveIn:";
|
| - for (SizeT i = 0; i < LiveIn.size(); ++i) {
|
| - if (LiveIn[i]) {
|
| - Variable *Var = Liveness->getVariable(i, this);
|
| - Str << " %" << Var->getName(Func);
|
| - if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) {
|
| - Str << ":"
|
| - << Func->getTarget()->getRegName(Var->getRegNum(),
|
| - Var->getType());
|
| + if (Func->isVerbose(IceV_Liveness)) {
|
| + if (Liveness != nullptr && !Liveness->getLiveIn(this).empty()) {
|
| + const LivenessBV &LiveIn = Liveness->getLiveIn(this);
|
| + Str << " // LiveIn:";
|
| + for (SizeT i = 0; i < LiveIn.size(); ++i) {
|
| + if (LiveIn[i]) {
|
| + Variable *Var = Liveness->getVariable(i, this);
|
| + Str << " %" << Var->getName(Func);
|
| + if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) {
|
| + Str << ":"
|
| + << Func->getTarget()->getRegName(Var->getRegNum(),
|
| + Var->getType());
|
| + }
|
| }
|
| }
|
| + Str << "\n";
|
| }
|
| - Str << "\n";
|
| }
|
| // Dump each instruction.
|
| if (Func->isVerbose(IceV_Instructions)) {
|
| @@ -1376,23 +1386,23 @@ void CfgNode::dump(Cfg *Func) const {
|
| I.dumpDecorated(Func);
|
| }
|
| // Dump the live-out variables.
|
| - LivenessBV LiveOut;
|
| - if (Liveness)
|
| - LiveOut = Liveness->getLiveOut(this);
|
| - if (Func->isVerbose(IceV_Liveness) && !LiveOut.empty()) {
|
| - Str << " // LiveOut:";
|
| - for (SizeT i = 0; i < LiveOut.size(); ++i) {
|
| - if (LiveOut[i]) {
|
| - Variable *Var = Liveness->getVariable(i, this);
|
| - Str << " %" << Var->getName(Func);
|
| - if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) {
|
| - Str << ":"
|
| - << Func->getTarget()->getRegName(Var->getRegNum(),
|
| - Var->getType());
|
| + if (Func->isVerbose(IceV_Liveness)) {
|
| + if (Liveness != nullptr && !Liveness->getLiveOut(this).empty()) {
|
| + const LivenessBV &LiveOut = Liveness->getLiveOut(this);
|
| + Str << " // LiveOut:";
|
| + for (SizeT i = 0; i < LiveOut.size(); ++i) {
|
| + if (LiveOut[i]) {
|
| + Variable *Var = Liveness->getVariable(i, this);
|
| + Str << " %" << Var->getName(Func);
|
| + if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) {
|
| + Str << ":"
|
| + << Func->getTarget()->getRegName(Var->getRegNum(),
|
| + Var->getType());
|
| + }
|
| }
|
| }
|
| + Str << "\n";
|
| }
|
| - Str << "\n";
|
| }
|
| // Dump list of successor nodes.
|
| if (Func->isVerbose(IceV_Succs)) {
|
|
|