Subzero: Improve debugging controls, plus minor refactoring. 1. Decorate the list of live-in and live-out variables with register assignments in the dump() output. This helps one to assess register pressure. 2. Fix a bug where the DisableInternal flag wasn't being honored for function definitions. 3. Add a -translate-only=<symbol> to limit translation to a single function or global variable. This makes it easier to focus on debugging a single function. 4. Change the -no-phi-edge-split option to -phi-edge-split and invert the meaning, to better not avoid the non double negatives. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/673783002
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp index cc77908..ed962d1 100644 --- a/src/IceCfg.cpp +++ b/src/IceCfg.cpp
@@ -65,17 +65,12 @@ void Cfg::translate() { if (hasError()) return; - VerboseMask OldVerboseMask = getContext()->getVerbose(); const IceString &TimingFocusOn = getContext()->getFlags().TimingFocusOn; if (TimingFocusOn == "*" || TimingFocusOn == getFunctionName()) { setFocusedTiming(); getContext()->resetTimer(GlobalContext::TSK_Default); getContext()->setTimerName(GlobalContext::TSK_Default, getFunctionName()); } - bool VerboseFocus = - (getContext()->getFlags().VerboseFocusOn == getFunctionName()); - if (VerboseFocus) - getContext()->setVerbose(IceV_All); TimerMarker T(TimerStack::TT_translate, this); dump("Initial CFG"); @@ -87,8 +82,6 @@ dump("Final output"); if (getFocusedTiming()) getContext()->dumpTimers(); - if (VerboseFocus) - getContext()->setVerbose(OldVerboseMask); } void Cfg::computePredecessors() { @@ -150,9 +143,6 @@ void Cfg::genFrame() { TimerMarker T(TimerStack::TT_genFrame, this); getTarget()->addProlog(Entry); - // TODO: Consider folding epilog generation into the final - // emission/assembly pass to avoid an extra iteration over the node - // list. Or keep a separate list of exit nodes. for (CfgNode *Node : Nodes) if (Node->getHasReturn()) getTarget()->addEpilog(Node); @@ -323,7 +313,7 @@ IceString MangledName = getContext()->mangleName(getFunctionName()); if (Ctx->getFlags().FunctionSections) Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n"; - if (!getInternal()) { + if (!getInternal() || Ctx->getFlags().DisableInternal) { Str << "\t.globl\t" << MangledName << "\n"; Str << "\t.type\t" << MangledName << ",@function\n"; } @@ -347,7 +337,7 @@ // Print function name+args if (getContext()->isVerbose(IceV_Instructions)) { Str << "define "; - if (getInternal()) + if (getInternal() && !Ctx->getFlags().DisableInternal) Str << "internal "; Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "("; for (SizeT i = 0; i < Args.size(); ++i) {
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp index 767c9c3..4e4d36b 100644 --- a/src/IceCfgNode.cpp +++ b/src/IceCfgNode.cpp
@@ -30,9 +30,7 @@ IceString CfgNode::getName() const { if (!Name.empty()) return Name; - char buf[30]; - snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); - return buf; + return "__" + std::to_string(getIndex()); } // Adds an instruction to either the Phi list or the regular @@ -65,7 +63,7 @@ InstCountEstimate = Func->getNextInstNumber() - FirstNumber; } -// When a node is created, the OutEdges are immediately knows, but the +// When a node is created, the OutEdges are immediately known, but the // InEdges have to be built up incrementally. After the CFG has been // constructed, the computePredecessors() pass finalizes it by // creating the InEdges list. @@ -557,7 +555,12 @@ Str << " // LiveIn:"; for (SizeT i = 0; i < LiveIn.size(); ++i) { if (LiveIn[i]) { - Str << " %" << Liveness->getVariable(i, this)->getName(); + Variable *Var = Liveness->getVariable(i, this); + Str << " %" << Var->getName(); + if (Func->getContext()->isVerbose(IceV_RegOrigins) && Var->hasReg()) { + Str << ":" << Func->getTarget()->getRegName(Var->getRegNum(), + Var->getType()); + } } } Str << "\n"; @@ -577,7 +580,12 @@ Str << " // LiveOut:"; for (SizeT i = 0; i < LiveOut.size(); ++i) { if (LiveOut[i]) { - Str << " %" << Liveness->getVariable(i, this)->getName(); + Variable *Var = Liveness->getVariable(i, this); + Str << " %" << Var->getName(); + if (Func->getContext()->isVerbose(IceV_RegOrigins) && Var->hasReg()) { + Str << ":" << Func->getTarget()->getRegName(Var->getRegNum(), + Var->getType()); + } } } Str << "\n";
diff --git a/src/IceClFlags.h b/src/IceClFlags.h index d1a71ae..d610c6a 100644 --- a/src/IceClFlags.h +++ b/src/IceClFlags.h
@@ -35,6 +35,7 @@ bool DataSections; bool UseIntegratedAssembler; bool UseSandboxing; + bool PhiEdgeSplit; bool DumpStats; bool AllowUninitializedGlobals; bool TimeEachFunction; @@ -42,6 +43,7 @@ IceString DefaultFunctionPrefix; IceString TimingFocusOn; IceString VerboseFocusOn; + IceString TranslateOnly; }; } // end of namespace Ice
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp index dbacd58..9419866 100644 --- a/src/IceInstX8632.cpp +++ b/src/IceInstX8632.cpp
@@ -136,9 +136,7 @@ Number(Target->makeNextLabelNumber()) {} IceString InstX8632Label::getName(const Cfg *Func) const { - char buf[30]; - snprintf(buf, llvm::array_lengthof(buf), "%u", Number); - return ".L" + Func->getFunctionName() + "$local$__" + buf; + return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); } InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue,
diff --git a/src/IceLiveness.cpp b/src/IceLiveness.cpp index 79578a5..f16eb84 100644 --- a/src/IceLiveness.cpp +++ b/src/IceLiveness.cpp
@@ -77,10 +77,8 @@ assert(NumGlobals == TmpNumGlobals); // Process each node. - const NodeList &LNodes = Func->getNodes(); - SizeT NumLNodes = LNodes.size(); - for (SizeT i = 0; i < NumLNodes; ++i) { - LivenessNode &Node = Nodes[LNodes[i]->getIndex()]; + for (const CfgNode *LNode : Func->getNodes()) { + LivenessNode &Node = Nodes[LNode->getIndex()]; // NumLocals, LiveToVarMap already initialized Node.LiveIn.resize(NumGlobals); Node.LiveOut.resize(NumGlobals);
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp index 98e8f6f..a2ee8f4 100644 --- a/src/IceOperand.cpp +++ b/src/IceOperand.cpp
@@ -171,9 +171,7 @@ IceString Variable::getName() const { if (!Name.empty()) return Name; - char buf[30]; - snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); - return buf; + return "__" + std::to_string(getIndex()); } Variable Variable::asType(Type Ty) {
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp index 98b18dc..8ea5882 100644 --- a/src/IceTargetLoweringX8632.cpp +++ b/src/IceTargetLoweringX8632.cpp
@@ -4451,7 +4451,7 @@ // If external and not initialized, this must be a cross test. // Don't generate a declaration for such cases. - bool IsExternal = Var.isExternal(); + bool IsExternal = Var.isExternal() || Ctx->getFlags().DisableInternal; if (IsExternal && !Var.hasInitializer()) return; bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
diff --git a/src/IceTranslator.cpp b/src/IceTranslator.cpp index dad0fa9..0391b6c 100644 --- a/src/IceTranslator.cpp +++ b/src/IceTranslator.cpp
@@ -28,6 +28,16 @@ using namespace Ice; +namespace { + +// Match a symbol name against a match string. An empty match string +// means match everything. Returns true if there is a match. +bool matchSymbolName(const IceString &SymbolName, const IceString &Match) { + return Match.empty() || Match == SymbolName; +} + +} // end of anonymous namespace + Translator::~Translator() {} IceString Translator::createUnnamedName(const IceString &Prefix, SizeT Index) { @@ -58,9 +68,13 @@ void Translator::translateFcn(Cfg *Fcn) { Ctx->resetStats(); Func.reset(Fcn); - if (Ctx->getFlags().DisableInternal) - Func->setInternal(false); - if (Ctx->getFlags().DisableTranslation) { + VerboseMask OldVerboseMask = Ctx->getVerbose(); + if (!matchSymbolName(Func->getFunctionName(), Ctx->getFlags().VerboseFocusOn)) + Ctx->setVerbose(IceV_None); + + if (Ctx->getFlags().DisableTranslation || + !matchSymbolName(Func->getFunctionName(), + Ctx->getFlags().TranslateOnly)) { Func->dump(); } else { Func->translate(); @@ -72,6 +86,8 @@ Func->emit(); Ctx->dumpStats(Func->getFunctionName()); } + + Ctx->setVerbose(OldVerboseMask); } void Translator::emitConstants() { @@ -84,12 +100,15 @@ llvm::OwningPtr<TargetGlobalInitLowering> GlobalLowering( TargetGlobalInitLowering::createLowering(Ctx->getTargetArch(), Ctx)); bool DisableTranslation = Ctx->getFlags().DisableTranslation; - bool DumpGlobalVariables = Ctx->isVerbose(); + bool DumpGlobalVariables = + Ctx->isVerbose() && Ctx->getFlags().VerboseFocusOn.empty(); Ostream &Stream = Ctx->getStrDump(); + const IceString &TranslateOnly = Ctx->getFlags().TranslateOnly; for (const Ice::VariableDeclaration *Global : VariableDeclarations) { if (DumpGlobalVariables) Global->dump(getContext(), Stream); - if(!DisableTranslation) + if (!DisableTranslation && + matchSymbolName(Global->getName(), TranslateOnly)) GlobalLowering->lower(*Global); } GlobalLowering.reset();
diff --git a/src/llvm2ice.cpp b/src/llvm2ice.cpp index 3546b84..9897740 100644 --- a/src/llvm2ice.cpp +++ b/src/llvm2ice.cpp
@@ -93,6 +93,9 @@ cl::desc("Externalize all symbols")); static cl::opt<bool> DisableTranslation("notranslate", cl::desc("Disable Subzero translation")); +static cl::opt<std::string> +TranslateOnly("translate-only", cl::desc("Translate only the given function"), + cl::init("")); static cl::opt<bool> SubzeroTimingEnabled( "timing", cl::desc("Enable breakdown timing of Subzero translation")); @@ -111,10 +114,10 @@ cl::desc("Temporarily enable full verbosity for a specific function"), cl::init("")); -// This is currently unused, and is a placeholder for lit tests. static cl::opt<bool> - DisablePhiEdgeSplit("no-phi-edge-split", - cl::desc("Disable edge splitting for Phi lowering")); +EnablePhiEdgeSplit("phi-edge-split", + cl::desc("Enable edge splitting for Phi lowering"), + cl::init(true)); static cl::opt<bool> DumpStats("stats", @@ -197,6 +200,7 @@ Flags.DataSections = DataSections; Flags.UseIntegratedAssembler = UseIntegratedAssembler; Flags.UseSandboxing = UseSandboxing; + Flags.PhiEdgeSplit = EnablePhiEdgeSplit; Flags.DumpStats = DumpStats; Flags.AllowUninitializedGlobals = AllowUninitializedGlobals; Flags.TimeEachFunction = TimeEachFunction; @@ -204,6 +208,7 @@ Flags.DefaultFunctionPrefix = DefaultFunctionPrefix; Flags.TimingFocusOn = TimingFocusOn; Flags.VerboseFocusOn = VerboseFocusOn; + Flags.TranslateOnly = TranslateOnly; Ice::GlobalContext Ctx(Ls, Os, VMask, TargetArch, OptLevel, TestPrefix, Flags);