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 "IceCfg.h" | 15 #include "IceCfg.h" |
16 #include "IceCfgNode.h" | 16 #include "IceCfgNode.h" |
17 #include "IceClFlags.h" | 17 #include "IceClFlags.h" |
18 #include "IceDefs.h" | 18 #include "IceDefs.h" |
19 #include "IceInst.h" | 19 #include "IceInst.h" |
20 #include "IceLiveness.h" | 20 #include "IceLiveness.h" |
21 #include "IceOperand.h" | 21 #include "IceOperand.h" |
22 #include "IceTargetLowering.h" | 22 #include "IceTargetLowering.h" |
23 | 23 |
24 namespace Ice { | 24 namespace Ice { |
25 | 25 |
26 Cfg::Cfg(GlobalContext *Ctx) | 26 Cfg::Cfg(GlobalContext *Ctx) |
27 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void), | 27 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void), |
28 IsInternalLinkage(false), HasError(false), FocusedTiming(false), | 28 IsInternalLinkage(false), HasError(false), FocusedTiming(false), |
29 ErrorMessage(""), Entry(NULL), NextInstNumber(1), Live(nullptr), | 29 ErrorMessage(""), Entry(NULL), NextInstNumber(Inst::NumberInitial), |
| 30 Live(nullptr), |
30 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)), | 31 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)), |
31 VMetadata(new VariablesMetadata(this)), | 32 VMetadata(new VariablesMetadata(this)), |
32 TargetAssembler( | 33 TargetAssembler( |
33 TargetLowering::createAssembler(Ctx->getTargetArch(), this)), | 34 TargetLowering::createAssembler(Ctx->getTargetArch(), this)), |
34 CurrentNode(NULL) { | 35 CurrentNode(NULL) { |
35 assert(!Ctx->isIRGenerationDisabled() && | 36 assert(!Ctx->isIRGenerationDisabled() && |
36 "Attempt to build cfg when IR generation disabled"); | 37 "Attempt to build cfg when IR generation disabled"); |
37 } | 38 } |
38 | 39 |
39 Cfg::~Cfg() {} | 40 Cfg::~Cfg() {} |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 getContext()->dumpTimers(); | 90 getContext()->dumpTimers(); |
90 } | 91 } |
91 | 92 |
92 void Cfg::computePredecessors() { | 93 void Cfg::computePredecessors() { |
93 for (CfgNode *Node : Nodes) | 94 for (CfgNode *Node : Nodes) |
94 Node->computePredecessors(); | 95 Node->computePredecessors(); |
95 } | 96 } |
96 | 97 |
97 void Cfg::renumberInstructions() { | 98 void Cfg::renumberInstructions() { |
98 TimerMarker T(TimerStack::TT_renumberInstructions, this); | 99 TimerMarker T(TimerStack::TT_renumberInstructions, this); |
99 NextInstNumber = 1; | 100 NextInstNumber = Inst::NumberInitial; |
100 for (CfgNode *Node : Nodes) | 101 for (CfgNode *Node : Nodes) |
101 Node->renumberInstructions(); | 102 Node->renumberInstructions(); |
102 } | 103 } |
103 | 104 |
104 // placePhiLoads() must be called before placePhiStores(). | 105 // placePhiLoads() must be called before placePhiStores(). |
105 void Cfg::placePhiLoads() { | 106 void Cfg::placePhiLoads() { |
106 TimerMarker T(TimerStack::TT_placePhiLoads, this); | 107 TimerMarker T(TimerStack::TT_placePhiLoads, this); |
107 for (CfgNode *Node : Nodes) | 108 for (CfgNode *Node : Nodes) |
108 Node->placePhiLoads(); | 109 Node->placePhiLoads(); |
109 } | 110 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 | 250 |
250 void Cfg::liveness(LivenessMode Mode) { | 251 void Cfg::liveness(LivenessMode Mode) { |
251 TimerMarker T(TimerStack::TT_liveness, this); | 252 TimerMarker T(TimerStack::TT_liveness, this); |
252 Live.reset(new Liveness(this, Mode)); | 253 Live.reset(new Liveness(this, Mode)); |
253 getVMetadata()->init(VMK_Uses); | 254 getVMetadata()->init(VMK_Uses); |
254 Live->init(); | 255 Live->init(); |
255 // Initialize with all nodes needing to be processed. | 256 // Initialize with all nodes needing to be processed. |
256 llvm::BitVector NeedToProcess(Nodes.size(), true); | 257 llvm::BitVector NeedToProcess(Nodes.size(), true); |
257 while (NeedToProcess.any()) { | 258 while (NeedToProcess.any()) { |
258 // Iterate in reverse topological order to speed up convergence. | 259 // Iterate in reverse topological order to speed up convergence. |
259 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. | |
260 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) { | 260 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) { |
261 CfgNode *Node = *I; | 261 CfgNode *Node = *I; |
262 if (NeedToProcess[Node->getIndex()]) { | 262 if (NeedToProcess[Node->getIndex()]) { |
263 NeedToProcess[Node->getIndex()] = false; | 263 NeedToProcess[Node->getIndex()] = false; |
264 bool Changed = Node->liveness(getLiveness()); | 264 bool Changed = Node->liveness(getLiveness()); |
265 if (Changed) { | 265 if (Changed) { |
266 // If the beginning-of-block liveness changed since the last | 266 // If the beginning-of-block liveness changed since the last |
267 // iteration, mark all in-edges as needing to be processed. | 267 // iteration, mark all in-edges as needing to be processed. |
268 for (CfgNode *Pred : Node->getInEdges()) | 268 for (CfgNode *Pred : Node->getInEdges()) |
269 NeedToProcess[Pred->getIndex()] = true; | 269 NeedToProcess[Pred->getIndex()] = true; |
270 } | 270 } |
271 } | 271 } |
272 } | 272 } |
273 } | 273 } |
274 if (Mode == Liveness_Intervals) { | 274 if (Mode == Liveness_Intervals) { |
275 // Reset each variable's live range. | 275 // Reset each variable's live range. |
276 for (Variable *Var : Variables) | 276 for (Variable *Var : Variables) |
277 Var->resetLiveRange(); | 277 Var->resetLiveRange(); |
278 } | 278 } |
279 // Collect timing for just the portion that constructs the live | 279 // Make a final pass over each node to delete dead instructions, |
280 // range intervals based on the end-of-live-range computation, for a | 280 // collect the first and last instruction numbers, and add live |
281 // finer breakdown of the cost. | 281 // range segments for that node. |
282 TimerMarker T1(TimerStack::TT_liveRange, this); | 282 for (CfgNode *Node : Nodes) { |
283 // Make a final pass over instructions to delete dead instructions | 283 InstNumberT FirstInstNum = Inst::NumberSentinel; |
284 // and build each Variable's live range. | 284 InstNumberT LastInstNum = Inst::NumberSentinel; |
285 for (CfgNode *Node : Nodes) | 285 for (auto I = Node->getPhis().begin(), E = Node->getPhis().end(); I != E; |
286 Node->livenessPostprocess(Mode, getLiveness()); | 286 ++I) { |
287 if (Mode == Liveness_Intervals) { | 287 I->deleteIfDead(); |
288 // Special treatment for live in-args. Their liveness needs to | 288 if (Mode == Liveness_Intervals && !I->isDeleted()) { |
289 // extend beyond the beginning of the function, otherwise an arg | 289 if (FirstInstNum == Inst::NumberSentinel) |
290 // whose only use is in the first instruction will end up having | 290 FirstInstNum = I->getNumber(); |
291 // the trivial live range [1,1) and will *not* interfere with | 291 assert(I->getNumber() > LastInstNum); |
292 // other arguments. So if the first instruction of the method is | 292 LastInstNum = I->getNumber(); |
293 // "r=arg1+arg2", both args may be assigned the same register. | |
294 for (SizeT I = 0; I < Args.size(); ++I) { | |
295 Variable *Arg = Args[I]; | |
296 if (!Arg->getLiveRange().isEmpty()) { | |
297 // Add live range [-1,0) with weight 0. TODO: Here and below, | |
298 // use better symbolic constants along the lines of | |
299 // Inst::NumberDeleted and Inst::NumberSentinel instead of -1 | |
300 // and 0. | |
301 Arg->addLiveRange(-1, 0, 0); | |
302 } | 293 } |
303 // Do the same for i64 args that may have been lowered into i32 | 294 } |
304 // Lo and Hi components. | 295 for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E; |
305 Variable *Lo = Arg->getLo(); | 296 ++I) { |
306 if (Lo && !Lo->getLiveRange().isEmpty()) | 297 I->deleteIfDead(); |
307 Lo->addLiveRange(-1, 0, 0); | 298 if (Mode == Liveness_Intervals && !I->isDeleted()) { |
308 Variable *Hi = Arg->getHi(); | 299 if (FirstInstNum == Inst::NumberSentinel) |
309 if (Hi && !Hi->getLiveRange().isEmpty()) | 300 FirstInstNum = I->getNumber(); |
310 Hi->addLiveRange(-1, 0, 0); | 301 assert(I->getNumber() > LastInstNum); |
| 302 LastInstNum = I->getNumber(); |
| 303 } |
| 304 } |
| 305 if (Mode == Liveness_Intervals) { |
| 306 // Special treatment for live in-args. Their liveness needs to |
| 307 // extend beyond the beginning of the function, otherwise an arg |
| 308 // whose only use is in the first instruction will end up having |
| 309 // the trivial live range [2,2) and will *not* interfere with |
| 310 // other arguments. So if the first instruction of the method |
| 311 // is "r=arg1+arg2", both args may be assigned the same |
| 312 // register. This is accomplished by extending the entry |
| 313 // block's instruction range from [2,n) to [1,n) which will |
| 314 // transform the problematic [2,2) live ranges into [1,2). |
| 315 if (FirstInstNum == Inst::NumberInitial) |
| 316 FirstInstNum = Inst::NumberExtended; |
| 317 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum); |
311 } | 318 } |
312 } | 319 } |
313 } | 320 } |
314 | 321 |
315 // Traverse every Variable of every Inst and verify that it | 322 // Traverse every Variable of every Inst and verify that it |
316 // appears within the Variable's computed live range. | 323 // appears within the Variable's computed live range. |
317 bool Cfg::validateLiveness() const { | 324 bool Cfg::validateLiveness() const { |
318 TimerMarker T(TimerStack::TT_validateLiveness, this); | 325 TimerMarker T(TimerStack::TT_validateLiveness, this); |
319 bool Valid = true; | 326 bool Valid = true; |
320 Ostream &Str = Ctx->getStrDump(); | 327 Ostream &Str = Ctx->getStrDump(); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 } | 509 } |
503 } | 510 } |
504 // Print each basic block | 511 // Print each basic block |
505 for (CfgNode *Node : Nodes) | 512 for (CfgNode *Node : Nodes) |
506 Node->dump(this); | 513 Node->dump(this); |
507 if (getContext()->isVerbose(IceV_Instructions)) | 514 if (getContext()->isVerbose(IceV_Instructions)) |
508 Str << "}\n"; | 515 Str << "}\n"; |
509 } | 516 } |
510 | 517 |
511 } // end of namespace Ice | 518 } // end of namespace Ice |
OLD | NEW |