Index: src/IceCfgNode.cpp |
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp |
index 9dbe7df11440610c2484cae8b1e9fc0322945fa3..b5b39ab53e545391633f47c2c0a28d08bdb8c35a 100644 |
--- a/src/IceCfgNode.cpp |
+++ b/src/IceCfgNode.cpp |
@@ -624,10 +624,16 @@ void CfgNode::livenessLightweight() { |
// Performs liveness analysis on the block. Returns true if the incoming |
// 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); |
+// the node's predecessors need to be processed again.) The ScratchBV is |
John
2016/02/29 15:12:31
Really, ScratchBV should not be part of the interf
Jim Stichnoth
2016/02/29 22:58:26
Done.
|
+// allocated by the caller and reused across successive calls to avoid |
+// unnecessary memory allocation. |
+bool CfgNode::liveness(Liveness *Liveness, LivenessBV *ScratchBV) { |
+ const SizeT NumVars = Liveness->getNumVarsInNode(this); |
+ const SizeT NumGlobalVars = Liveness->getNumGlobalVars(); |
+ LivenessBV &Live = *ScratchBV; |
John
2016/02/29 15:12:31
Why are you incurring the extra memory de-referenc
Jim Stichnoth
2016/02/29 22:58:26
I don't think that's an actual dereference happeni
|
+ Live.reserve(NumVars); |
+ Live.clear(); |
+ |
LiveBeginEndMap *LiveBegin = nullptr; |
LiveBeginEndMap *LiveEnd = nullptr; |
// Mark the beginning and ending of each variable's live range with the |
@@ -642,9 +648,12 @@ 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); |
John
2016/02/29 15:12:31
auto?
Jim Stichnoth
2016/02/29 22:58:26
I'd kinda rather not in this case.
I'd be happier
|
+ 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()) |
@@ -653,8 +662,11 @@ bool CfgNode::liveness(Liveness *Liveness) { |
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 +688,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 +707,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 +790,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()); |
@@ -1350,10 +1362,9 @@ 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()) { |
+ if (Func->isVerbose(IceV_Liveness) && Liveness != nullptr && |
John
2016/02/29 15:12:31
this test is testing different things. it is (to m
Jim Stichnoth
2016/02/29 22:58:26
Done.
|
+ !Liveness->getLiveIn(this).empty()) { |
+ const LivenessBV &LiveIn = Liveness->getLiveIn(this); |
Str << " // LiveIn:"; |
for (SizeT i = 0; i < LiveIn.size(); ++i) { |
if (LiveIn[i]) { |
@@ -1376,10 +1387,9 @@ 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()) { |
+ if (Func->isVerbose(IceV_Liveness) && 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]) { |