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 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 ImplicitArgs.push_back(Arg); | 62 ImplicitArgs.push_back(Arg); |
63 } | 63 } |
64 | 64 |
65 // Returns whether the stack frame layout has been computed yet. This | 65 // Returns whether the stack frame layout has been computed yet. This |
66 // is used for dumping the stack frame location of Variables. | 66 // is used for dumping the stack frame location of Variables. |
67 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } | 67 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } |
68 | 68 |
69 void Cfg::translate() { | 69 void Cfg::translate() { |
70 if (hasError()) | 70 if (hasError()) |
71 return; | 71 return; |
72 TimerMarker T("translate", getContext()); | |
72 | 73 |
73 dump("Initial CFG"); | 74 dump("Initial CFG"); |
74 | 75 |
75 Timer T_translate; | |
76 // The set of translation passes and their order are determined by | 76 // The set of translation passes and their order are determined by |
77 // the target. | 77 // the target. |
78 getTarget()->translate(); | 78 getTarget()->translate(); |
79 T_translate.printElapsedUs(getContext(), "translate()"); | |
80 | 79 |
81 dump("Final output"); | 80 dump("Final output"); |
82 } | 81 } |
83 | 82 |
84 void Cfg::computePredecessors() { | 83 void Cfg::computePredecessors() { |
85 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 84 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
86 (*I)->computePredecessors(); | 85 (*I)->computePredecessors(); |
87 } | 86 } |
88 } | 87 } |
89 | 88 |
90 void Cfg::renumberInstructions() { | 89 void Cfg::renumberInstructions() { |
90 TimerMarker T("renumberInstructions", getContext()); | |
91 NextInstNumber = 1; | 91 NextInstNumber = 1; |
92 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 92 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
93 (*I)->renumberInstructions(); | 93 (*I)->renumberInstructions(); |
94 } | 94 } |
95 } | 95 } |
96 | 96 |
97 // placePhiLoads() must be called before placePhiStores(). | 97 // placePhiLoads() must be called before placePhiStores(). |
98 void Cfg::placePhiLoads() { | 98 void Cfg::placePhiLoads() { |
99 TimerMarker T("placePhiLoads", getContext()); | |
99 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 100 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
100 (*I)->placePhiLoads(); | 101 (*I)->placePhiLoads(); |
101 } | 102 } |
102 } | 103 } |
103 | 104 |
104 // placePhiStores() must be called after placePhiLoads(). | 105 // placePhiStores() must be called after placePhiLoads(). |
105 void Cfg::placePhiStores() { | 106 void Cfg::placePhiStores() { |
107 TimerMarker T("placePhiStores", getContext()); | |
106 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 108 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
107 (*I)->placePhiStores(); | 109 (*I)->placePhiStores(); |
108 } | 110 } |
109 } | 111 } |
110 | 112 |
111 void Cfg::deletePhis() { | 113 void Cfg::deletePhis() { |
114 TimerMarker T("deletePhis", getContext()); | |
112 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 115 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
113 (*I)->deletePhis(); | 116 (*I)->deletePhis(); |
114 } | 117 } |
115 } | 118 } |
116 | 119 |
117 void Cfg::doArgLowering() { | 120 void Cfg::doArgLowering() { |
121 TimerMarker T("doArgLowering", getContext()); | |
118 getTarget()->lowerArguments(); | 122 getTarget()->lowerArguments(); |
119 } | 123 } |
120 | 124 |
121 void Cfg::doAddressOpt() { | 125 void Cfg::doAddressOpt() { |
126 TimerMarker T("doAddressOpt", getContext()); | |
122 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 127 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
123 (*I)->doAddressOpt(); | 128 (*I)->doAddressOpt(); |
124 } | 129 } |
125 } | 130 } |
126 | 131 |
127 void Cfg::doNopInsertion() { | 132 void Cfg::doNopInsertion() { |
133 TimerMarker T("doNopInsertion", getContext()); | |
128 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 134 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
129 (*I)->doNopInsertion(); | 135 (*I)->doNopInsertion(); |
130 } | 136 } |
131 } | 137 } |
132 | 138 |
133 void Cfg::genCode() { | 139 void Cfg::genCode() { |
140 TimerMarker T("genCode", getContext()); | |
134 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 141 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
135 (*I)->genCode(); | 142 (*I)->genCode(); |
136 } | 143 } |
137 } | 144 } |
138 | 145 |
139 // Compute the stack frame layout. | 146 // Compute the stack frame layout. |
140 void Cfg::genFrame() { | 147 void Cfg::genFrame() { |
148 TimerMarker T("genFrame", getContext()); | |
141 getTarget()->addProlog(Entry); | 149 getTarget()->addProlog(Entry); |
142 // TODO: Consider folding epilog generation into the final | 150 // TODO: Consider folding epilog generation into the final |
143 // emission/assembly pass to avoid an extra iteration over the node | 151 // emission/assembly pass to avoid an extra iteration over the node |
144 // list. Or keep a separate list of exit nodes. | 152 // list. Or keep a separate list of exit nodes. |
145 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 153 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
146 CfgNode *Node = *I; | 154 CfgNode *Node = *I; |
147 if (Node->getHasReturn()) | 155 if (Node->getHasReturn()) |
148 getTarget()->addEpilog(Node); | 156 getTarget()->addEpilog(Node); |
149 } | 157 } |
150 } | 158 } |
151 | 159 |
152 // This is a lightweight version of live-range-end calculation. Marks | 160 // This is a lightweight version of live-range-end calculation. Marks |
153 // the last use of only those variables whose definition and uses are | 161 // the last use of only those variables whose definition and uses are |
154 // completely with a single block. It is a quick single pass and | 162 // completely with a single block. It is a quick single pass and |
155 // doesn't need to iterate until convergence. | 163 // doesn't need to iterate until convergence. |
156 void Cfg::livenessLightweight() { | 164 void Cfg::livenessLightweight() { |
165 TimerMarker T("livenessLightweight", getContext()); | |
157 getVMetadata()->init(); | 166 getVMetadata()->init(); |
158 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 167 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
159 (*I)->livenessLightweight(); | 168 (*I)->livenessLightweight(); |
160 } | 169 } |
161 } | 170 } |
162 | 171 |
163 void Cfg::liveness(LivenessMode Mode) { | 172 void Cfg::liveness(LivenessMode Mode) { |
173 TimerMarker T("liveness", getContext()); | |
164 Live.reset(new Liveness(this, Mode)); | 174 Live.reset(new Liveness(this, Mode)); |
165 getVMetadata()->init(); | 175 getVMetadata()->init(); |
166 Live->init(); | 176 Live->init(); |
167 // Initialize with all nodes needing to be processed. | 177 // Initialize with all nodes needing to be processed. |
168 llvm::BitVector NeedToProcess(Nodes.size(), true); | 178 llvm::BitVector NeedToProcess(Nodes.size(), true); |
169 while (NeedToProcess.any()) { | 179 while (NeedToProcess.any()) { |
170 // Iterate in reverse topological order to speed up convergence. | 180 // Iterate in reverse topological order to speed up convergence. |
171 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend(); | 181 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend(); |
172 I != E; ++I) { | 182 I != E; ++I) { |
173 CfgNode *Node = *I; | 183 CfgNode *Node = *I; |
(...skipping 18 matching lines...) Expand all Loading... | |
192 // Reset each variable's live range. | 202 // Reset each variable's live range. |
193 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); | 203 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); |
194 I != E; ++I) { | 204 I != E; ++I) { |
195 if (Variable *Var = *I) | 205 if (Variable *Var = *I) |
196 Var->resetLiveRange(); | 206 Var->resetLiveRange(); |
197 } | 207 } |
198 } | 208 } |
199 // Collect timing for just the portion that constructs the live | 209 // Collect timing for just the portion that constructs the live |
200 // range intervals based on the end-of-live-range computation, for a | 210 // range intervals based on the end-of-live-range computation, for a |
201 // finer breakdown of the cost. | 211 // finer breakdown of the cost. |
202 Timer T_liveRange; | |
203 // Make a final pass over instructions to delete dead instructions | 212 // Make a final pass over instructions to delete dead instructions |
204 // and build each Variable's live range. | 213 // and build each Variable's live range. |
205 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 214 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
206 (*I)->livenessPostprocess(Mode, getLiveness()); | 215 (*I)->livenessPostprocess(Mode, getLiveness()); |
207 } | 216 } |
208 if (Mode == Liveness_Intervals) { | 217 if (Mode == Liveness_Intervals) { |
209 // Special treatment for live in-args. Their liveness needs to | 218 // Special treatment for live in-args. Their liveness needs to |
210 // extend beyond the beginning of the function, otherwise an arg | 219 // extend beyond the beginning of the function, otherwise an arg |
211 // whose only use is in the first instruction will end up having | 220 // whose only use is in the first instruction will end up having |
212 // the trivial live range [1,1) and will *not* interfere with | 221 // the trivial live range [1,1) and will *not* interfere with |
(...skipping 21 matching lines...) Expand all Loading... | |
234 // Remove Variable::LiveRange and redirect to | 243 // Remove Variable::LiveRange and redirect to |
235 // Liveness::LiveRanges. TODO: make sure Variable weights | 244 // Liveness::LiveRanges. TODO: make sure Variable weights |
236 // are applied properly. | 245 // are applied properly. |
237 SizeT NumVars = Variables.size(); | 246 SizeT NumVars = Variables.size(); |
238 for (SizeT i = 0; i < NumVars; ++i) { | 247 for (SizeT i = 0; i < NumVars; ++i) { |
239 Variable *Var = Variables[i]; | 248 Variable *Var = Variables[i]; |
240 Var->setLiveRange(Live->getLiveRange(Var)); | 249 Var->setLiveRange(Live->getLiveRange(Var)); |
241 if (Var->getWeight().isInf()) | 250 if (Var->getWeight().isInf()) |
242 Var->setLiveRangeInfiniteWeight(); | 251 Var->setLiveRangeInfiniteWeight(); |
243 } | 252 } |
244 T_liveRange.printElapsedUs(getContext(), "live range construction"); | |
245 dump(); | 253 dump(); |
246 } | 254 } |
247 } | 255 } |
248 | 256 |
249 // Traverse every Variable of every Inst and verify that it | 257 // Traverse every Variable of every Inst and verify that it |
250 // appears within the Variable's computed live range. | 258 // appears within the Variable's computed live range. |
251 bool Cfg::validateLiveness() const { | 259 bool Cfg::validateLiveness() const { |
260 TimerMarker T("validateLiveness", getContext()); | |
252 bool Valid = true; | 261 bool Valid = true; |
253 Ostream &Str = Ctx->getStrDump(); | 262 Ostream &Str = Ctx->getStrDump(); |
254 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1; | 263 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1; |
255 ++I1) { | 264 ++I1) { |
256 CfgNode *Node = *I1; | 265 CfgNode *Node = *I1; |
257 InstList &Insts = Node->getInsts(); | 266 InstList &Insts = Node->getInsts(); |
258 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end(); | 267 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end(); |
259 I2 != E2; ++I2) { | 268 I2 != E2; ++I2) { |
260 Inst *Inst = *I2; | 269 Inst *Inst = *I2; |
261 if (Inst->isDeleted()) | 270 if (Inst->isDeleted()) |
(...skipping 27 matching lines...) Expand all Loading... | |
289 Str << " live range " << Var->getLiveRange() << "\n"; | 298 Str << " live range " << Var->getLiveRange() << "\n"; |
290 } | 299 } |
291 } | 300 } |
292 } | 301 } |
293 } | 302 } |
294 } | 303 } |
295 return Valid; | 304 return Valid; |
296 } | 305 } |
297 | 306 |
298 void Cfg::doBranchOpt() { | 307 void Cfg::doBranchOpt() { |
308 TimerMarker T("doBranchOpt", getContext()); | |
299 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 309 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
300 NodeList::iterator NextNode = I; | 310 NodeList::iterator NextNode = I; |
301 ++NextNode; | 311 ++NextNode; |
302 (*I)->doBranchOpt(*NextNode); | 312 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode); |
Jim Stichnoth
2014/09/28 14:26:39
This was a bug pointed out by valgrind.
| |
303 } | 313 } |
304 } | 314 } |
305 | 315 |
306 // ======================== Dump routines ======================== // | 316 // ======================== Dump routines ======================== // |
307 | 317 |
308 void Cfg::emit() { | 318 void Cfg::emit() { |
319 TimerMarker T("emit", getContext()); | |
309 Ostream &Str = Ctx->getStrEmit(); | 320 Ostream &Str = Ctx->getStrEmit(); |
310 Timer T_emit; | |
311 if (!Ctx->testAndSetHasEmittedFirstMethod()) { | 321 if (!Ctx->testAndSetHasEmittedFirstMethod()) { |
312 // Print a helpful command for assembling the output. | 322 // Print a helpful command for assembling the output. |
313 // TODO: have the Target emit the header | 323 // TODO: have the Target emit the header |
314 // TODO: need a per-file emit in addition to per-CFG | 324 // TODO: need a per-file emit in addition to per-CFG |
315 Str << "# $LLVM_BIN_PATH/llvm-mc" | 325 Str << "# $LLVM_BIN_PATH/llvm-mc" |
316 << " -arch=x86" | 326 << " -arch=x86" |
317 << " -x86-asm-syntax=intel" | 327 << " -x86-asm-syntax=intel" |
318 << " -filetype=obj" | 328 << " -filetype=obj" |
319 << " -o=MyObj.o" | 329 << " -o=MyObj.o" |
320 << "\n\n"; | 330 << "\n\n"; |
(...skipping 11 matching lines...) Expand all Loading... | |
332 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end(); | 342 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end(); |
333 I != E; ++I) { | 343 I != E; ++I) { |
334 Str.write_hex(*I); | 344 Str.write_hex(*I); |
335 } | 345 } |
336 Str << "\n"; | 346 Str << "\n"; |
337 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; | 347 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; |
338 ++I) { | 348 ++I) { |
339 (*I)->emit(this); | 349 (*I)->emit(this); |
340 } | 350 } |
341 Str << "\n"; | 351 Str << "\n"; |
342 T_emit.printElapsedUs(Ctx, "emit()"); | |
343 } | 352 } |
344 | 353 |
345 // Dumps the IR with an optional introductory message. | 354 // Dumps the IR with an optional introductory message. |
346 void Cfg::dump(const IceString &Message) { | 355 void Cfg::dump(const IceString &Message) { |
347 if (!Ctx->isVerbose()) | 356 if (!Ctx->isVerbose()) |
348 return; | 357 return; |
349 Ostream &Str = Ctx->getStrDump(); | 358 Ostream &Str = Ctx->getStrDump(); |
350 if (!Message.empty()) | 359 if (!Message.empty()) |
351 Str << "================ " << Message << " ================\n"; | 360 Str << "================ " << Message << " ================\n"; |
352 setCurrentNode(getEntryNode()); | 361 setCurrentNode(getEntryNode()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; | 393 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; |
385 ++I) { | 394 ++I) { |
386 (*I)->dump(this); | 395 (*I)->dump(this); |
387 } | 396 } |
388 if (getContext()->isVerbose(IceV_Instructions)) { | 397 if (getContext()->isVerbose(IceV_Instructions)) { |
389 Str << "}\n"; | 398 Str << "}\n"; |
390 } | 399 } |
391 } | 400 } |
392 | 401 |
393 } // end of namespace Ice | 402 } // end of namespace Ice |
OLD | NEW |