| OLD | NEW |
| 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// | 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the Cfg class, including constant pool | 10 // This file implements the Cfg class, including constant pool |
| 11 // management. | 11 // management. |
| 12 // | 12 // |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "assembler.h" | 15 #include "assembler.h" |
| 16 #include "IceCfg.h" | 16 #include "IceCfg.h" |
| 17 #include "IceCfgNode.h" | 17 #include "IceCfgNode.h" |
| 18 #include "IceClFlags.h" | 18 #include "IceClFlags.h" |
| 19 #include "IceDefs.h" | 19 #include "IceDefs.h" |
| 20 #include "IceELFObjectWriter.h" | 20 #include "IceELFObjectWriter.h" |
| 21 #include "IceGlobalInits.h" |
| 21 #include "IceInst.h" | 22 #include "IceInst.h" |
| 22 #include "IceLiveness.h" | 23 #include "IceLiveness.h" |
| 23 #include "IceOperand.h" | 24 #include "IceOperand.h" |
| 24 #include "IceTargetLowering.h" | 25 #include "IceTargetLowering.h" |
| 25 | 26 |
| 26 namespace Ice { | 27 namespace Ice { |
| 27 | 28 |
| 28 ICE_TLS_DEFINE_FIELD(const Cfg *, Cfg, CurrentCfg); | 29 ICE_TLS_DEFINE_FIELD(const Cfg *, Cfg, CurrentCfg); |
| 29 | 30 |
| 30 ArenaAllocator<> *getCurrentCfgAllocator() { | 31 ArenaAllocator<> *getCurrentCfgAllocator() { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 69 |
| 69 void Cfg::addImplicitArg(Variable *Arg) { | 70 void Cfg::addImplicitArg(Variable *Arg) { |
| 70 Arg->setIsImplicitArg(); | 71 Arg->setIsImplicitArg(); |
| 71 ImplicitArgs.push_back(Arg); | 72 ImplicitArgs.push_back(Arg); |
| 72 } | 73 } |
| 73 | 74 |
| 74 // Returns whether the stack frame layout has been computed yet. This | 75 // Returns whether the stack frame layout has been computed yet. This |
| 75 // is used for dumping the stack frame location of Variables. | 76 // is used for dumping the stack frame location of Variables. |
| 76 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } | 77 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } |
| 77 | 78 |
| 79 namespace { |
| 80 constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$"; |
| 81 constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$"; |
| 82 |
| 83 VariableDeclaration *nodeNameDeclaration(const IceString &NodeAsmName) { |
| 84 VariableDeclaration *Var = VariableDeclaration::create(); |
| 85 Var->setName(BlockNameGlobalPrefix + NodeAsmName); |
| 86 Var->setIsConstant(true); |
| 87 Var->addInitializer(new VariableDeclaration::DataInitializer( |
| 88 NodeAsmName.data(), NodeAsmName.size() + 1)); |
| 89 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64); |
| 90 Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes. |
| 91 return Var; |
| 92 } |
| 93 |
| 94 VariableDeclaration * |
| 95 blockProfilingInfoDeclaration(const IceString &NodeAsmName, |
| 96 VariableDeclaration *NodeNameDeclaration) { |
| 97 VariableDeclaration *Var = VariableDeclaration::create(); |
| 98 Var->setName(BlockStatsGlobalPrefix + NodeAsmName); |
| 99 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64); |
| 100 Var->addInitializer(new VariableDeclaration::ZeroInitializer(Int64ByteSize)); |
| 101 |
| 102 const RelocOffsetT NodeNameDeclarationOffset = 0; |
| 103 Var->addInitializer(new VariableDeclaration::RelocInitializer( |
| 104 NodeNameDeclaration, NodeNameDeclarationOffset)); |
| 105 Var->setAlignment(Int64ByteSize); |
| 106 return Var; |
| 107 } |
| 108 |
| 109 } // end of anonymous namespace |
| 110 |
| 111 void Cfg::profileBlocks() { |
| 112 if (GlobalInits == nullptr) |
| 113 GlobalInits.reset(new VariableDeclarationList()); |
| 114 |
| 115 for (CfgNode *Node : Nodes) { |
| 116 IceString NodeAsmName = Node->getAsmName(); |
| 117 GlobalInits->push_back(nodeNameDeclaration(NodeAsmName)); |
| 118 GlobalInits->push_back( |
| 119 blockProfilingInfoDeclaration(NodeAsmName, GlobalInits->back())); |
| 120 Node->profileExecutionCount(GlobalInits->back()); |
| 121 } |
| 122 } |
| 123 |
| 124 bool Cfg::isProfileGlobal(const VariableDeclaration &Var) { |
| 125 return Var.getName().find(BlockStatsGlobalPrefix) == 0; |
| 126 } |
| 127 |
| 128 void Cfg::addCallToProfileSummary() { |
| 129 // The call(s) to __Sz_profile_summary are added by the profiler in functions |
| 130 // that cause the program to exit. This function is defined in |
| 131 // runtime/szrt_profiler.c. |
| 132 Constant *ProfileSummarySym = |
| 133 Ctx->getConstantExternSym("__Sz_profile_summary"); |
| 134 constexpr SizeT NumArgs = 0; |
| 135 constexpr Variable *Void = nullptr; |
| 136 constexpr bool HasTailCall = false; |
| 137 auto *Call = |
| 138 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall); |
| 139 getEntryNode()->getInsts().push_front(Call); |
| 140 } |
| 141 |
| 78 void Cfg::translate() { | 142 void Cfg::translate() { |
| 79 if (hasError()) | 143 if (hasError()) |
| 80 return; | 144 return; |
| 81 // FunctionTimer conditionally pushes/pops a TimerMarker if | 145 // FunctionTimer conditionally pushes/pops a TimerMarker if |
| 82 // TimeEachFunction is enabled. | 146 // TimeEachFunction is enabled. |
| 83 std::unique_ptr<TimerMarker> FunctionTimer; | 147 std::unique_ptr<TimerMarker> FunctionTimer; |
| 84 if (ALLOW_DUMP) { | 148 if (ALLOW_DUMP) { |
| 85 const IceString &TimingFocusOn = | 149 const IceString &TimingFocusOn = |
| 86 getContext()->getFlags().getTimingFocusOn(); | 150 getContext()->getFlags().getTimingFocusOn(); |
| 87 const IceString &Name = getFunctionName(); | 151 const IceString &Name = getFunctionName(); |
| 88 if (TimingFocusOn == "*" || TimingFocusOn == Name) { | 152 if (TimingFocusOn == "*" || TimingFocusOn == Name) { |
| 89 setFocusedTiming(); | 153 setFocusedTiming(); |
| 90 getContext()->resetTimer(GlobalContext::TSK_Default); | 154 getContext()->resetTimer(GlobalContext::TSK_Default); |
| 91 getContext()->setTimerName(GlobalContext::TSK_Default, Name); | 155 getContext()->setTimerName(GlobalContext::TSK_Default, Name); |
| 92 } | 156 } |
| 93 if (getContext()->getFlags().getTimeEachFunction()) | 157 if (getContext()->getFlags().getTimeEachFunction()) |
| 94 FunctionTimer.reset(new TimerMarker( | 158 FunctionTimer.reset(new TimerMarker( |
| 95 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name), | 159 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name), |
| 96 getContext(), GlobalContext::TSK_Funcs)); | 160 getContext(), GlobalContext::TSK_Funcs)); |
| 97 } | 161 } |
| 98 TimerMarker T(TimerStack::TT_translate, this); | 162 TimerMarker T(TimerStack::TT_translate, this); |
| 99 | 163 |
| 100 dump("Initial CFG"); | 164 dump("Initial CFG"); |
| 101 | 165 |
| 166 if (getContext()->getFlags().getEnableBlockProfile()) { |
| 167 profileBlocks(); |
| 168 // TODO(jpp): this is fragile, at best. Figure out a better way of detecting |
| 169 // exit functions. |
| 170 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) { |
| 171 addCallToProfileSummary(); |
| 172 } |
| 173 dump("Profiled CFG"); |
| 174 } |
| 175 |
| 102 // The set of translation passes and their order are determined by | 176 // The set of translation passes and their order are determined by |
| 103 // the target. | 177 // the target. |
| 104 getTarget()->translate(); | 178 getTarget()->translate(); |
| 105 | 179 |
| 106 dump("Final output"); | 180 dump("Final output"); |
| 107 if (getFocusedTiming()) | 181 if (getFocusedTiming()) |
| 108 getContext()->dumpTimers(); | 182 getContext()->dumpTimers(); |
| 109 } | 183 } |
| 110 | 184 |
| 111 void Cfg::computeInOutEdges() { | 185 void Cfg::computeInOutEdges() { |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 } | 615 } |
| 542 } | 616 } |
| 543 // Print each basic block | 617 // Print each basic block |
| 544 for (CfgNode *Node : Nodes) | 618 for (CfgNode *Node : Nodes) |
| 545 Node->dump(this); | 619 Node->dump(this); |
| 546 if (isVerbose(IceV_Instructions)) | 620 if (isVerbose(IceV_Instructions)) |
| 547 Str << "}\n"; | 621 Str << "}\n"; |
| 548 } | 622 } |
| 549 | 623 |
| 550 } // end of namespace Ice | 624 } // end of namespace Ice |
| OLD | NEW |