| 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 |