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 /// \file | 10 /// \file |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "IceInstVarIter.h" | 25 #include "IceInstVarIter.h" |
26 #include "IceLiveness.h" | 26 #include "IceLiveness.h" |
27 #include "IceLoopAnalyzer.h" | 27 #include "IceLoopAnalyzer.h" |
28 #include "IceOperand.h" | 28 #include "IceOperand.h" |
29 #include "IceTargetLowering.h" | 29 #include "IceTargetLowering.h" |
30 | 30 |
31 namespace Ice { | 31 namespace Ice { |
32 | 32 |
33 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) | 33 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) |
34 : Ctx(Ctx), SequenceNumber(SequenceNumber), | 34 : Ctx(Ctx), SequenceNumber(SequenceNumber), |
35 VMask(Ctx->getFlags().getVerbose()), NextInstNumber(Inst::NumberInitial), | 35 VMask(Ctx->getFlags().getVerbose()), FunctionName(), |
36 Live(nullptr) { | 36 NextInstNumber(Inst::NumberInitial), Live(nullptr) { |
37 Allocator.reset(new ArenaAllocator()); | 37 Allocator.reset(new ArenaAllocator()); |
| 38 NodeStrings.reset(new StringPool); |
| 39 VarStrings.reset(new StringPool); |
38 CfgLocalAllocatorScope _(this); | 40 CfgLocalAllocatorScope _(this); |
39 Target = | 41 Target = |
40 TargetLowering::createLowering(Ctx->getFlags().getTargetArch(), this); | 42 TargetLowering::createLowering(Ctx->getFlags().getTargetArch(), this); |
41 VMetadata.reset(new VariablesMetadata(this)); | 43 VMetadata.reset(new VariablesMetadata(this)); |
42 TargetAssembler = Target->createAssembler(); | 44 TargetAssembler = Target->createAssembler(); |
43 | 45 |
44 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) { | 46 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) { |
45 // If -randomize-pool-immediates=randomize, create a random number | 47 // If -randomize-pool-immediates=randomize, create a random number |
46 // generator to generate a cookie for constant blinding. | 48 // generator to generate a cookie for constant blinding. |
47 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), | 49 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), |
48 RPE_ConstantBlinding, this->SequenceNumber); | 50 RPE_ConstantBlinding, this->SequenceNumber); |
49 ConstantBlindingCookie = | 51 ConstantBlindingCookie = |
50 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1); | 52 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1); |
51 } | 53 } |
52 } | 54 } |
53 | 55 |
54 Cfg::~Cfg() { assert(CfgAllocatorTraits::current() == nullptr); } | 56 Cfg::~Cfg() { |
| 57 assert(CfgAllocatorTraits::current() == nullptr); |
| 58 if (GlobalContext::getFlags().getDumpStrings()) { |
| 59 OstreamLocker _(Ctx); |
| 60 Ostream &Str = Ctx->getStrDump(); |
| 61 getNodeStrings()->dump(Str); |
| 62 getVarStrings()->dump(Str); |
| 63 } |
| 64 } |
55 | 65 |
56 /// Create a string like "foo(i=123:b=9)" indicating the function name, number | 66 /// Create a string like "foo(i=123:b=9)" indicating the function name, number |
57 /// of high-level instructions, and number of basic blocks. This string is only | 67 /// of high-level instructions, and number of basic blocks. This string is only |
58 /// used for dumping and other diagnostics, and the idea is that given a set of | 68 /// used for dumping and other diagnostics, and the idea is that given a set of |
59 /// functions to debug a problem on, it's easy to find the smallest or simplest | 69 /// functions to debug a problem on, it's easy to find the smallest or simplest |
60 /// function to attack. Note that the counts may change somewhat depending on | 70 /// function to attack. Note that the counts may change somewhat depending on |
61 /// what point it is called during the translation passes. | 71 /// what point it is called during the translation passes. |
62 IceString Cfg::getFunctionNameAndSize() const { | 72 std::string Cfg::getFunctionNameAndSize() const { |
63 if (!BuildDefs::dump()) | 73 if (!BuildDefs::dump()) |
64 return getFunctionName(); | 74 return getFunctionName().toString(); |
65 SizeT NodeCount = 0; | 75 SizeT NodeCount = 0; |
66 SizeT InstCount = 0; | 76 SizeT InstCount = 0; |
67 for (CfgNode *Node : getNodes()) { | 77 for (CfgNode *Node : getNodes()) { |
68 ++NodeCount; | 78 ++NodeCount; |
69 // Note: deleted instructions are *not* ignored. | 79 // Note: deleted instructions are *not* ignored. |
70 InstCount += Node->getPhis().size(); | 80 InstCount += Node->getPhis().size(); |
71 for (Inst &I : Node->getInsts()) { | 81 for (Inst &I : Node->getInsts()) { |
72 if (!llvm::isa<InstTarget>(&I)) | 82 if (!llvm::isa<InstTarget>(&I)) |
73 ++InstCount; | 83 ++InstCount; |
74 } | 84 } |
75 } | 85 } |
76 return getFunctionName() + "(i=" + std::to_string(InstCount) + ":b=" + | 86 return getFunctionName() + "(i=" + std::to_string(InstCount) + ":b=" + |
77 std::to_string(NodeCount) + ")"; | 87 std::to_string(NodeCount) + ")"; |
78 } | 88 } |
79 | 89 |
80 void Cfg::setError(const IceString &Message) { | 90 void Cfg::setError(const std::string &Message) { |
81 HasError = true; | 91 HasError = true; |
82 ErrorMessage = Message; | 92 ErrorMessage = Message; |
83 } | 93 } |
84 | 94 |
85 CfgNode *Cfg::makeNode() { | 95 CfgNode *Cfg::makeNode() { |
86 SizeT LabelIndex = Nodes.size(); | 96 SizeT LabelIndex = Nodes.size(); |
87 auto *Node = CfgNode::create(this, LabelIndex); | 97 auto *Node = CfgNode::create(this, LabelIndex); |
88 Nodes.push_back(Node); | 98 Nodes.push_back(Node); |
89 return Node; | 99 return Node; |
90 } | 100 } |
(...skipping 26 matching lines...) Expand all Loading... |
117 | 127 |
118 // Returns whether the stack frame layout has been computed yet. This is used | 128 // Returns whether the stack frame layout has been computed yet. This is used |
119 // for dumping the stack frame location of Variables. | 129 // for dumping the stack frame location of Variables. |
120 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } | 130 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } |
121 | 131 |
122 namespace { | 132 namespace { |
123 constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$"; | 133 constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$"; |
124 constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$"; | 134 constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$"; |
125 } // end of anonymous namespace | 135 } // end of anonymous namespace |
126 | 136 |
127 void Cfg::createNodeNameDeclaration(const IceString &NodeAsmName) { | 137 void Cfg::createNodeNameDeclaration(const std::string &NodeAsmName) { |
128 auto *Var = VariableDeclaration::create(GlobalInits.get()); | 138 auto *Var = VariableDeclaration::create(GlobalInits.get()); |
129 Var->setName(BlockNameGlobalPrefix + NodeAsmName); | 139 Var->setName(Ctx, BlockNameGlobalPrefix + NodeAsmName); |
130 Var->setIsConstant(true); | 140 Var->setIsConstant(true); |
131 Var->addInitializer(VariableDeclaration::DataInitializer::create( | 141 Var->addInitializer(VariableDeclaration::DataInitializer::create( |
132 GlobalInits.get(), NodeAsmName.data(), NodeAsmName.size() + 1)); | 142 GlobalInits.get(), NodeAsmName.data(), NodeAsmName.size() + 1)); |
133 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64); | 143 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64); |
134 Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes. | 144 Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes. |
135 GlobalInits->push_back(Var); | 145 GlobalInits->push_back(Var); |
136 } | 146 } |
137 | 147 |
138 void Cfg::createBlockProfilingInfoDeclaration( | 148 void Cfg::createBlockProfilingInfoDeclaration( |
139 const IceString &NodeAsmName, VariableDeclaration *NodeNameDeclaration) { | 149 const std::string &NodeAsmName, VariableDeclaration *NodeNameDeclaration) { |
140 auto *Var = VariableDeclaration::create(GlobalInits.get()); | 150 auto *Var = VariableDeclaration::create(GlobalInits.get()); |
141 Var->setName(BlockStatsGlobalPrefix + NodeAsmName); | 151 Var->setName(Ctx, BlockStatsGlobalPrefix + NodeAsmName); |
142 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64); | 152 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64); |
143 Var->addInitializer(VariableDeclaration::ZeroInitializer::create( | 153 Var->addInitializer(VariableDeclaration::ZeroInitializer::create( |
144 GlobalInits.get(), Int64ByteSize)); | 154 GlobalInits.get(), Int64ByteSize)); |
145 | 155 |
146 const RelocOffsetT NodeNameDeclarationOffset = 0; | 156 const RelocOffsetT NodeNameDeclarationOffset = 0; |
147 Var->addInitializer(VariableDeclaration::RelocInitializer::create( | 157 Var->addInitializer(VariableDeclaration::RelocInitializer::create( |
148 GlobalInits.get(), NodeNameDeclaration, | 158 GlobalInits.get(), NodeNameDeclaration, |
149 {RelocOffset::create(Ctx, NodeNameDeclarationOffset)})); | 159 {RelocOffset::create(Ctx, NodeNameDeclarationOffset)})); |
150 Var->setAlignment(Int64ByteSize); | 160 Var->setAlignment(Int64ByteSize); |
151 GlobalInits->push_back(Var); | 161 GlobalInits->push_back(Var); |
152 } | 162 } |
153 | 163 |
154 void Cfg::profileBlocks() { | 164 void Cfg::profileBlocks() { |
155 if (GlobalInits == nullptr) | 165 if (GlobalInits == nullptr) |
156 GlobalInits.reset(new VariableDeclarationList()); | 166 GlobalInits.reset(new VariableDeclarationList()); |
157 | 167 |
158 for (CfgNode *Node : Nodes) { | 168 for (CfgNode *Node : Nodes) { |
159 const IceString NodeAsmName = Node->getAsmName(); | 169 const std::string NodeAsmName = Node->getAsmName(); |
160 createNodeNameDeclaration(NodeAsmName); | 170 createNodeNameDeclaration(NodeAsmName); |
161 createBlockProfilingInfoDeclaration(NodeAsmName, GlobalInits->back()); | 171 createBlockProfilingInfoDeclaration(NodeAsmName, GlobalInits->back()); |
162 Node->profileExecutionCount(GlobalInits->back()); | 172 Node->profileExecutionCount(GlobalInits->back()); |
163 } | 173 } |
164 } | 174 } |
165 | 175 |
166 bool Cfg::isProfileGlobal(const VariableDeclaration &Var) { | 176 bool Cfg::isProfileGlobal(const VariableDeclaration &Var) { |
167 return Var.getName().find(BlockStatsGlobalPrefix) == 0; | 177 if (!Var.getName().hasStdString()) |
| 178 return false; |
| 179 return Var.getName().toString().find(BlockStatsGlobalPrefix) == 0; |
168 } | 180 } |
169 | 181 |
170 void Cfg::addCallToProfileSummary() { | 182 void Cfg::addCallToProfileSummary() { |
171 // The call(s) to __Sz_profile_summary are added by the profiler in functions | 183 // The call(s) to __Sz_profile_summary are added by the profiler in functions |
172 // that cause the program to exit. This function is defined in | 184 // that cause the program to exit. This function is defined in |
173 // runtime/szrt_profiler.c. | 185 // runtime/szrt_profiler.c. |
174 Constant *ProfileSummarySym = | 186 Constant *ProfileSummarySym = |
175 Ctx->getConstantExternSym("__Sz_profile_summary"); | 187 Ctx->getConstantExternSym(Ctx->getGlobalString("__Sz_profile_summary")); |
176 constexpr SizeT NumArgs = 0; | 188 constexpr SizeT NumArgs = 0; |
177 constexpr Variable *Void = nullptr; | 189 constexpr Variable *Void = nullptr; |
178 constexpr bool HasTailCall = false; | 190 constexpr bool HasTailCall = false; |
179 auto *Call = | 191 auto *Call = |
180 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall); | 192 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall); |
181 getEntryNode()->getInsts().push_front(Call); | 193 getEntryNode()->getInsts().push_front(Call); |
182 } | 194 } |
183 | 195 |
184 void Cfg::translate() { | 196 void Cfg::translate() { |
185 if (hasError()) | 197 if (hasError()) |
186 return; | 198 return; |
187 if (BuildDefs::dump()) { | 199 if (BuildDefs::dump()) { |
188 const IceString &TimingFocusOn = | 200 const std::string TimingFocusOn = |
189 getContext()->getFlags().getTimingFocusOn(); | 201 getContext()->getFlags().getTimingFocusOn(); |
190 const IceString &Name = getFunctionName(); | 202 const std::string Name = getFunctionName().toString(); |
191 if (TimingFocusOn == "*" || TimingFocusOn == Name) { | 203 if (TimingFocusOn == "*" || TimingFocusOn == Name) { |
192 setFocusedTiming(); | 204 setFocusedTiming(); |
193 getContext()->resetTimer(GlobalContext::TSK_Default); | 205 getContext()->resetTimer(GlobalContext::TSK_Default); |
194 getContext()->setTimerName(GlobalContext::TSK_Default, Name); | 206 getContext()->setTimerName(GlobalContext::TSK_Default, Name); |
195 } | 207 } |
196 if (isVerbose(IceV_Status)) { | 208 if (isVerbose(IceV_Status)) { |
197 getContext()->getStrDump() << ">>>Translating " | 209 getContext()->getStrDump() << ">>>Translating " |
198 << getFunctionNameAndSize() << "\n"; | 210 << getFunctionNameAndSize() << "\n"; |
199 } | 211 } |
200 } | 212 } |
201 TimerMarker T_func(getContext(), getFunctionName()); | 213 TimerMarker T_func(getContext(), getFunctionName().toStringOrEmpty()); |
202 TimerMarker T(TimerStack::TT_translate, this); | 214 TimerMarker T(TimerStack::TT_translate, this); |
203 | 215 |
204 dump("Initial CFG"); | 216 dump("Initial CFG"); |
205 | 217 |
206 if (getContext()->getFlags().getEnableBlockProfile()) { | 218 if (getContext()->getFlags().getEnableBlockProfile()) { |
207 profileBlocks(); | 219 profileBlocks(); |
208 // TODO(jpp): this is fragile, at best. Figure out a better way of | 220 // TODO(jpp): this is fragile, at best. Figure out a better way of |
209 // detecting exit functions. | 221 // detecting exit functions. |
210 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) { | 222 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) { |
211 addCallToProfileSummary(); | 223 addCallToProfileSummary(); |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 for (const InstJumpTable *JT : JumpTables) | 971 for (const InstJumpTable *JT : JumpTables) |
960 for (SizeT I = 0; I < JT->getNumTargets(); ++I) | 972 for (SizeT I = 0; I < JT->getNumTargets(); ++I) |
961 JT->getTarget(I)->setNeedsAlignment(); | 973 JT->getTarget(I)->setNeedsAlignment(); |
962 } | 974 } |
963 | 975 |
964 // ======================== Dump routines ======================== // | 976 // ======================== Dump routines ======================== // |
965 | 977 |
966 // emitTextHeader() is not target-specific (apart from what is abstracted by | 978 // emitTextHeader() is not target-specific (apart from what is abstracted by |
967 // the Assembler), so it is defined here rather than in the target lowering | 979 // the Assembler), so it is defined here rather than in the target lowering |
968 // class. | 980 // class. |
969 void Cfg::emitTextHeader(const IceString &Name, GlobalContext *Ctx, | 981 void Cfg::emitTextHeader(GlobalString Name, GlobalContext *Ctx, |
970 const Assembler *Asm) { | 982 const Assembler *Asm) { |
971 if (!BuildDefs::dump()) | 983 if (!BuildDefs::dump()) |
972 return; | 984 return; |
973 Ostream &Str = Ctx->getStrEmit(); | 985 Ostream &Str = Ctx->getStrEmit(); |
974 Str << "\t.text\n"; | 986 Str << "\t.text\n"; |
975 if (Ctx->getFlags().getFunctionSections()) | 987 if (Ctx->getFlags().getFunctionSections()) |
976 Str << "\t.section\t.text." << Name << ",\"ax\",%progbits\n"; | 988 Str << "\t.section\t.text." << Name << ",\"ax\",%progbits\n"; |
977 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) { | 989 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) { |
978 Str << "\t.globl\t" << Name << "\n"; | 990 Str << "\t.globl\t" << Name << "\n"; |
979 Str << "\t.type\t" << Name << ",%function\n"; | 991 Str << "\t.type\t" << Name << ",%function\n"; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 } | 1147 } |
1136 } | 1148 } |
1137 // Print each basic block | 1149 // Print each basic block |
1138 for (CfgNode *Node : Nodes) | 1150 for (CfgNode *Node : Nodes) |
1139 Node->dump(this); | 1151 Node->dump(this); |
1140 if (isVerbose(IceV_Instructions)) | 1152 if (isVerbose(IceV_Instructions)) |
1141 Str << "}\n"; | 1153 Str << "}\n"; |
1142 } | 1154 } |
1143 | 1155 |
1144 } // end of namespace Ice | 1156 } // end of namespace Ice |
OLD | NEW |