Index: src/IceCfgNode.cpp |
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp |
index 661dd7320229d2405d4e8c4d787c49568d807e7c..b7530781eaf277cfc439a56ffa3ef6de78c9cc4a 100644 |
--- a/src/IceCfgNode.cpp |
+++ b/src/IceCfgNode.cpp |
@@ -756,9 +756,12 @@ void CfgNode::contractIfEmpty() { |
return; |
Inst *Branch = NULL; |
for (Inst *I : Insts) { |
- if (!I->isDeleted() && !I->isUnconditionalBranch()) |
+ if (I->isDeleted()) |
+ continue; |
+ if (I->isUnconditionalBranch()) |
+ Branch = I; |
+ else if (!I->isRedundantAssign()) |
return; |
- Branch = I; |
} |
Branch->setDeleted(); |
assert(OutEdges.size() == 1); |
@@ -798,9 +801,73 @@ void CfgNode::doBranchOpt(const CfgNode *NextNode) { |
// ======================== Dump routines ======================== // |
+namespace { |
+ |
+// Helper functions for emit(). |
+ |
+void emitRegisterUsage(Ostream &Str, const Cfg *Func, const CfgNode *Node, |
+ bool IsLiveIn, std::vector<SizeT> &LiveRegCount) { |
+ Liveness *Liveness = Func->getLiveness(); |
+ const LivenessBV *Live; |
+ if (IsLiveIn) { |
+ Live = &Liveness->getLiveIn(Node); |
+ Str << "\t\t\t\t# LiveIn="; |
+ } else { |
+ Live = &Liveness->getLiveOut(Node); |
+ Str << "\t\t\t\t# LiveOut="; |
+ } |
+ if (!Live->empty()) { |
+ bool First = true; |
+ for (SizeT i = 0; i < Live->size(); ++i) { |
+ if ((*Live)[i]) { |
+ Variable *Var = Liveness->getVariable(i, Node); |
+ if (Var->hasReg()) { |
+ if (IsLiveIn) |
+ ++LiveRegCount[Var->getRegNum()]; |
+ if (!First) |
+ Str << ","; |
+ First = false; |
+ Var->emit(Func); |
+ } |
+ } |
+ } |
+ } |
+ Str << "\n"; |
+} |
+ |
+void emitLiveRangesEnded(Ostream &Str, const Cfg *Func, const Inst *Instr, |
+ std::vector<SizeT> &LiveRegCount) { |
+ bool First = true; |
+ Variable *Dest = Instr->getDest(); |
+ if (Dest && Dest->hasReg()) |
+ ++LiveRegCount[Dest->getRegNum()]; |
+ for (SizeT I = 0; I < Instr->getSrcSize(); ++I) { |
+ Operand *Src = Instr->getSrc(I); |
+ SizeT NumVars = Src->getNumVars(); |
+ for (SizeT J = 0; J < NumVars; ++J) { |
+ const Variable *Var = Src->getVar(J); |
+ if (Var->hasReg()) { |
+ if (Instr->isLastUse(Var) && |
+ --LiveRegCount[Var->getRegNum()] == 0) { |
+ if (First) |
+ Str << " \t# END="; |
+ else |
+ Str << ","; |
+ Var->emit(Func); |
+ First = false; |
+ } |
+ } |
+ } |
+ } |
+} |
+ |
+} // end of anonymous namespace |
+ |
void CfgNode::emit(Cfg *Func) const { |
Func->setCurrentNode(this); |
Ostream &Str = Func->getContext()->getStrEmit(); |
+ Liveness *Liveness = Func->getLiveness(); |
+ bool DecorateAsm = Liveness && Func->getContext()->getFlags().DecorateAsm; |
if (Func->getEntryNode() == this) { |
Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; |
} |
@@ -809,6 +876,10 @@ void CfgNode::emit(Cfg *Func) const { |
Assembler *Asm = Func->getAssembler<Assembler>(); |
Asm->BindCfgNodeLabel(getIndex()); |
} |
+ std::vector<SizeT> LiveRegCount(Func->getTarget()->getNumRegisters()); |
+ if (DecorateAsm) |
+ emitRegisterUsage(Str, Func, this, true, LiveRegCount); |
+ |
for (InstPhi *Phi : Phis) { |
if (Phi->isDeleted()) |
continue; |
@@ -819,10 +890,18 @@ void CfgNode::emit(Cfg *Func) const { |
for (Inst *I : Insts) { |
if (I->isDeleted()) |
continue; |
+ if (I->isRedundantAssign()) { |
+ Variable *Dest = I->getDest(); |
+ if (DecorateAsm && Dest->hasReg() && !I->isLastUse(I->getSrc(0))) |
+ ++LiveRegCount[Dest->getRegNum()]; |
+ continue; |
+ } |
if (Func->useIntegratedAssembler()) { |
I->emitIAS(Func); |
} else { |
I->emit(Func); |
+ if (DecorateAsm) |
+ emitLiveRangesEnded(Str, Func, I, LiveRegCount); |
Str << "\n"; |
} |
// Update emitted instruction count, plus fill/spill count for |
@@ -841,6 +920,8 @@ void CfgNode::emit(Cfg *Func) const { |
} |
} |
} |
+ if (DecorateAsm) |
+ emitRegisterUsage(Str, Func, this, false, LiveRegCount); |
} |
void CfgNode::dump(Cfg *Func) const { |