Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: src/IceCfg.cpp

Issue 802003003: Subzero: Clean up live range construction. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/IceCfgNode.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/IceCfgNode.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698