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

Side by Side Diff: src/IceCfg.cpp

Issue 1341423002: Reflow comments to use the full width. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix spelling and rebase Created 5 years, 3 months 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 | « src/IceCfg.h ('k') | 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 /// \file 10 /// \file
11 /// This file implements the Cfg class, including constant pool 11 /// This file implements the Cfg class, including constant pool management.
12 /// management.
13 /// 12 ///
14 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
15 14
16 #include "IceCfg.h" 15 #include "IceCfg.h"
17 16
18 #include "IceAssembler.h" 17 #include "IceAssembler.h"
19 #include "IceCfgNode.h" 18 #include "IceCfgNode.h"
20 #include "IceClFlags.h" 19 #include "IceClFlags.h"
21 #include "IceDefs.h" 20 #include "IceDefs.h"
22 #include "IceELFObjectWriter.h" 21 #include "IceELFObjectWriter.h"
(...skipping 16 matching lines...) Expand all
39 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) 38 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
40 : Ctx(Ctx), SequenceNumber(SequenceNumber), 39 : Ctx(Ctx), SequenceNumber(SequenceNumber),
41 VMask(Ctx->getFlags().getVerbose()), NextInstNumber(Inst::NumberInitial), 40 VMask(Ctx->getFlags().getVerbose()), NextInstNumber(Inst::NumberInitial),
42 Allocator(new ArenaAllocator<>()), Live(nullptr), 41 Allocator(new ArenaAllocator<>()), Live(nullptr),
43 Target(TargetLowering::createLowering(Ctx->getFlags().getTargetArch(), 42 Target(TargetLowering::createLowering(Ctx->getFlags().getTargetArch(),
44 this)), 43 this)),
45 VMetadata(new VariablesMetadata(this)), 44 VMetadata(new VariablesMetadata(this)),
46 TargetAssembler(TargetLowering::createAssembler( 45 TargetAssembler(TargetLowering::createAssembler(
47 Ctx->getFlags().getTargetArch(), this)) { 46 Ctx->getFlags().getTargetArch(), this)) {
48 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) { 47 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) {
49 // If -randomize-pool-immediates=randomize, create a random number generator 48 // If -randomize-pool-immediates=randomize, create a random number
50 // to generate a cookie for constant blinding. 49 // generator to generate a cookie for constant blinding.
51 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), 50 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
52 RPE_ConstantBlinding, this->SequenceNumber); 51 RPE_ConstantBlinding, this->SequenceNumber);
53 ConstantBlindingCookie = 52 ConstantBlindingCookie =
54 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1); 53 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1);
55 } 54 }
56 } 55 }
57 56
58 Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); } 57 Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); }
59 58
60 void Cfg::setError(const IceString &Message) { 59 void Cfg::setError(const IceString &Message) {
(...skipping 18 matching lines...) Expand all
79 void Cfg::addArg(Variable *Arg) { 78 void Cfg::addArg(Variable *Arg) {
80 Arg->setIsArg(); 79 Arg->setIsArg();
81 Args.push_back(Arg); 80 Args.push_back(Arg);
82 } 81 }
83 82
84 void Cfg::addImplicitArg(Variable *Arg) { 83 void Cfg::addImplicitArg(Variable *Arg) {
85 Arg->setIsImplicitArg(); 84 Arg->setIsImplicitArg();
86 ImplicitArgs.push_back(Arg); 85 ImplicitArgs.push_back(Arg);
87 } 86 }
88 87
89 // Returns whether the stack frame layout has been computed yet. This 88 // Returns whether the stack frame layout has been computed yet. This is used
90 // is used for dumping the stack frame location of Variables. 89 // for dumping the stack frame location of Variables.
91 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } 90 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
92 91
93 namespace { 92 namespace {
94 constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$"; 93 constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$";
95 constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$"; 94 constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$";
96 95
97 VariableDeclaration *nodeNameDeclaration(GlobalContext *Ctx, 96 VariableDeclaration *nodeNameDeclaration(GlobalContext *Ctx,
98 const IceString &NodeAsmName) { 97 const IceString &NodeAsmName) {
99 VariableDeclaration *Var = VariableDeclaration::create(Ctx); 98 VariableDeclaration *Var = VariableDeclaration::create(Ctx);
100 Var->setName(BlockNameGlobalPrefix + NodeAsmName); 99 Var->setName(BlockNameGlobalPrefix + NodeAsmName);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 constexpr Variable *Void = nullptr; 149 constexpr Variable *Void = nullptr;
151 constexpr bool HasTailCall = false; 150 constexpr bool HasTailCall = false;
152 auto *Call = 151 auto *Call =
153 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall); 152 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall);
154 getEntryNode()->getInsts().push_front(Call); 153 getEntryNode()->getInsts().push_front(Call);
155 } 154 }
156 155
157 void Cfg::translate() { 156 void Cfg::translate() {
158 if (hasError()) 157 if (hasError())
159 return; 158 return;
160 // FunctionTimer conditionally pushes/pops a TimerMarker if 159 // FunctionTimer conditionally pushes/pops a TimerMarker if TimeEachFunction
161 // TimeEachFunction is enabled. 160 // is enabled.
162 std::unique_ptr<TimerMarker> FunctionTimer; 161 std::unique_ptr<TimerMarker> FunctionTimer;
163 if (BuildDefs::dump()) { 162 if (BuildDefs::dump()) {
164 const IceString &TimingFocusOn = 163 const IceString &TimingFocusOn =
165 getContext()->getFlags().getTimingFocusOn(); 164 getContext()->getFlags().getTimingFocusOn();
166 const IceString &Name = getFunctionName(); 165 const IceString &Name = getFunctionName();
167 if (TimingFocusOn == "*" || TimingFocusOn == Name) { 166 if (TimingFocusOn == "*" || TimingFocusOn == Name) {
168 setFocusedTiming(); 167 setFocusedTiming();
169 getContext()->resetTimer(GlobalContext::TSK_Default); 168 getContext()->resetTimer(GlobalContext::TSK_Default);
170 getContext()->setTimerName(GlobalContext::TSK_Default, Name); 169 getContext()->setTimerName(GlobalContext::TSK_Default, Name);
171 } 170 }
172 if (getContext()->getFlags().getTimeEachFunction()) 171 if (getContext()->getFlags().getTimeEachFunction())
173 FunctionTimer.reset(new TimerMarker( 172 FunctionTimer.reset(new TimerMarker(
174 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name), 173 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name),
175 getContext(), GlobalContext::TSK_Funcs)); 174 getContext(), GlobalContext::TSK_Funcs));
176 } 175 }
177 TimerMarker T(TimerStack::TT_translate, this); 176 TimerMarker T(TimerStack::TT_translate, this);
178 177
179 dump("Initial CFG"); 178 dump("Initial CFG");
180 179
181 if (getContext()->getFlags().getEnableBlockProfile()) { 180 if (getContext()->getFlags().getEnableBlockProfile()) {
182 profileBlocks(); 181 profileBlocks();
183 // TODO(jpp): this is fragile, at best. Figure out a better way of detecting 182 // TODO(jpp): this is fragile, at best. Figure out a better way of
184 // exit functions. 183 // detecting exit functions.
185 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) { 184 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) {
186 addCallToProfileSummary(); 185 addCallToProfileSummary();
187 } 186 }
188 dump("Profiled CFG"); 187 dump("Profiled CFG");
189 } 188 }
190 189
191 // The set of translation passes and their order are determined by 190 // The set of translation passes and their order are determined by the
192 // the target. 191 // target.
193 getTarget()->translate(); 192 getTarget()->translate();
194 193
195 dump("Final output"); 194 dump("Final output");
196 if (getFocusedTiming()) 195 if (getFocusedTiming())
197 getContext()->dumpTimers(); 196 getContext()->dumpTimers();
198 } 197 }
199 198
200 void Cfg::computeInOutEdges() { 199 void Cfg::computeInOutEdges() {
201 // Compute the out-edges. 200 // Compute the out-edges.
202 for (CfgNode *Node : Nodes) 201 for (CfgNode *Node : Nodes)
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 } 265 }
267 266
268 void Cfg::advancedPhiLowering() { 267 void Cfg::advancedPhiLowering() {
269 TimerMarker T(TimerStack::TT_advancedPhiLowering, this); 268 TimerMarker T(TimerStack::TT_advancedPhiLowering, this);
270 // Clear all previously computed live ranges (but not live-in/live-out bit 269 // Clear all previously computed live ranges (but not live-in/live-out bit
271 // vectors or last-use markers), because the follow-on register allocation is 270 // vectors or last-use markers), because the follow-on register allocation is
272 // only concerned with live ranges across the newly created blocks. 271 // only concerned with live ranges across the newly created blocks.
273 for (Variable *Var : Variables) { 272 for (Variable *Var : Variables) {
274 Var->getLiveRange().reset(); 273 Var->getLiveRange().reset();
275 } 274 }
276 // This splits edges and appends new nodes to the end of the node 275 // This splits edges and appends new nodes to the end of the node list. This
277 // list. This can invalidate iterators, so don't use an iterator. 276 // can invalidate iterators, so don't use an iterator.
278 SizeT NumNodes = getNumNodes(); 277 SizeT NumNodes = getNumNodes();
279 SizeT NumVars = getNumVariables(); 278 SizeT NumVars = getNumVariables();
280 for (SizeT I = 0; I < NumNodes; ++I) 279 for (SizeT I = 0; I < NumNodes; ++I)
281 Nodes[I]->advancedPhiLowering(); 280 Nodes[I]->advancedPhiLowering();
282 281
283 TimerMarker TT(TimerStack::TT_lowerPhiAssignments, this); 282 TimerMarker TT(TimerStack::TT_lowerPhiAssignments, this);
284 if (true) { 283 if (true) {
285 // The following code does an in-place update of liveness and live ranges as 284 // The following code does an in-place update of liveness and live ranges
286 // a result of adding the new phi edge split nodes. 285 // as a result of adding the new phi edge split nodes.
287 getLiveness()->initPhiEdgeSplits(Nodes.begin() + NumNodes, 286 getLiveness()->initPhiEdgeSplits(Nodes.begin() + NumNodes,
288 Variables.begin() + NumVars); 287 Variables.begin() + NumVars);
289 TimerMarker TTT(TimerStack::TT_liveness, this); 288 TimerMarker TTT(TimerStack::TT_liveness, this);
290 // Iterate over the newly added nodes to add their liveness info. 289 // Iterate over the newly added nodes to add their liveness info.
291 for (auto I = Nodes.begin() + NumNodes, E = Nodes.end(); I != E; ++I) { 290 for (auto I = Nodes.begin() + NumNodes, E = Nodes.end(); I != E; ++I) {
292 InstNumberT FirstInstNum = getNextInstNumber(); 291 InstNumberT FirstInstNum = getNextInstNumber();
293 (*I)->renumberInstructions(); 292 (*I)->renumberInstructions();
294 InstNumberT LastInstNum = getNextInstNumber() - 1; 293 InstNumberT LastInstNum = getNextInstNumber() - 1;
295 (*I)->liveness(getLiveness()); 294 (*I)->liveness(getLiveness());
296 (*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum); 295 (*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
297 } 296 }
298 } else { 297 } else {
299 // The following code does a brute-force recalculation of live ranges as a 298 // The following code does a brute-force recalculation of live ranges as a
300 // result of adding the new phi edge split nodes. The liveness calculation 299 // result of adding the new phi edge split nodes. The liveness calculation
301 // is particularly expensive because the new nodes are not yet in a proper 300 // is particularly expensive because the new nodes are not yet in a proper
302 // topological order and so convergence is slower. 301 // topological order and so convergence is slower.
303 // 302 //
304 // This code is kept here for reference and can be temporarily enabled in 303 // This code is kept here for reference and can be temporarily enabled in
305 // case the incremental code is under suspicion. 304 // case the incremental code is under suspicion.
306 renumberInstructions(); 305 renumberInstructions();
307 liveness(Liveness_Intervals); 306 liveness(Liveness_Intervals);
308 getVMetadata()->init(VMK_All); 307 getVMetadata()->init(VMK_All);
309 } 308 }
310 Target->regAlloc(RAK_Phi); 309 Target->regAlloc(RAK_Phi);
311 } 310 }
312 311
313 // Find a reasonable placement for nodes that have not yet been 312 // Find a reasonable placement for nodes that have not yet been placed, while
314 // placed, while maintaining the same relative ordering among already 313 // maintaining the same relative ordering among already placed nodes.
315 // placed nodes.
316 void Cfg::reorderNodes() { 314 void Cfg::reorderNodes() {
317 // TODO(ascull): it would be nice if the switch tests were always followed 315 // TODO(ascull): it would be nice if the switch tests were always followed by
318 // by the default case to allow for fall through. 316 // the default case to allow for fall through.
319 using PlacedList = std::list<CfgNode *>; 317 using PlacedList = std::list<CfgNode *>;
320 PlacedList Placed; // Nodes with relative placement locked down 318 PlacedList Placed; // Nodes with relative placement locked down
321 PlacedList Unreachable; // Unreachable nodes 319 PlacedList Unreachable; // Unreachable nodes
322 PlacedList::iterator NoPlace = Placed.end(); 320 PlacedList::iterator NoPlace = Placed.end();
323 // Keep track of where each node has been tentatively placed so that 321 // Keep track of where each node has been tentatively placed so that we can
324 // we can manage insertions into the middle. 322 // manage insertions into the middle.
325 std::vector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace); 323 std::vector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace);
326 for (CfgNode *Node : Nodes) { 324 for (CfgNode *Node : Nodes) {
327 // The "do ... while(0);" construct is to factor out the 325 // The "do ... while(0);" construct is to factor out the --PlaceIndex and
328 // --PlaceIndex and assert() statements before moving to the next 326 // assert() statements before moving to the next node.
329 // node.
330 do { 327 do {
331 if (Node != getEntryNode() && Node->getInEdges().empty()) { 328 if (Node != getEntryNode() && Node->getInEdges().empty()) {
332 // The node has essentially been deleted since it is not a 329 // The node has essentially been deleted since it is not a successor of
333 // successor of any other node. 330 // any other node.
334 Unreachable.push_back(Node); 331 Unreachable.push_back(Node);
335 PlaceIndex[Node->getIndex()] = Unreachable.end(); 332 PlaceIndex[Node->getIndex()] = Unreachable.end();
336 Node->setNeedsPlacement(false); 333 Node->setNeedsPlacement(false);
337 continue; 334 continue;
338 } 335 }
339 if (!Node->needsPlacement()) { 336 if (!Node->needsPlacement()) {
340 // Add to the end of the Placed list. 337 // Add to the end of the Placed list.
341 Placed.push_back(Node); 338 Placed.push_back(Node);
342 PlaceIndex[Node->getIndex()] = Placed.end(); 339 PlaceIndex[Node->getIndex()] = Placed.end();
343 continue; 340 continue;
344 } 341 }
345 Node->setNeedsPlacement(false); 342 Node->setNeedsPlacement(false);
346 // Assume for now that the unplaced node is from edge-splitting 343 // Assume for now that the unplaced node is from edge-splitting and
347 // and therefore has 1 in-edge and 1 out-edge (actually, possibly 344 // therefore has 1 in-edge and 1 out-edge (actually, possibly more than 1
348 // more than 1 in-edge if the predecessor node was contracted). 345 // in-edge if the predecessor node was contracted). If this changes in
349 // If this changes in the future, rethink the strategy. 346 // the future, rethink the strategy.
350 assert(Node->getInEdges().size() >= 1); 347 assert(Node->getInEdges().size() >= 1);
351 assert(Node->getOutEdges().size() == 1); 348 assert(Node->getOutEdges().size() == 1);
352 349
353 // If it's a (non-critical) edge where the successor has a single 350 // If it's a (non-critical) edge where the successor has a single
354 // in-edge, then place it before the successor. 351 // in-edge, then place it before the successor.
355 CfgNode *Succ = Node->getOutEdges().front(); 352 CfgNode *Succ = Node->getOutEdges().front();
356 if (Succ->getInEdges().size() == 1 && 353 if (Succ->getInEdges().size() == 1 &&
357 PlaceIndex[Succ->getIndex()] != NoPlace) { 354 PlaceIndex[Succ->getIndex()] != NoPlace) {
358 Placed.insert(PlaceIndex[Succ->getIndex()], Node); 355 Placed.insert(PlaceIndex[Succ->getIndex()], Node);
359 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()]; 356 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()];
360 continue; 357 continue;
361 } 358 }
362 359
363 // Otherwise, place it after the (first) predecessor. 360 // Otherwise, place it after the (first) predecessor.
364 CfgNode *Pred = Node->getInEdges().front(); 361 CfgNode *Pred = Node->getInEdges().front();
365 auto PredPosition = PlaceIndex[Pred->getIndex()]; 362 auto PredPosition = PlaceIndex[Pred->getIndex()];
366 // It shouldn't be the case that PredPosition==NoPlace, but if 363 // It shouldn't be the case that PredPosition==NoPlace, but if that
367 // that somehow turns out to be true, we just insert Node before 364 // somehow turns out to be true, we just insert Node before
368 // PredPosition=NoPlace=Placed.end() . 365 // PredPosition=NoPlace=Placed.end() .
369 if (PredPosition != NoPlace) 366 if (PredPosition != NoPlace)
370 ++PredPosition; 367 ++PredPosition;
371 Placed.insert(PredPosition, Node); 368 Placed.insert(PredPosition, Node);
372 PlaceIndex[Node->getIndex()] = PredPosition; 369 PlaceIndex[Node->getIndex()] = PredPosition;
373 } while (0); 370 } while (0);
374 371
375 --PlaceIndex[Node->getIndex()]; 372 --PlaceIndex[Node->getIndex()];
376 assert(*PlaceIndex[Node->getIndex()] == Node); 373 assert(*PlaceIndex[Node->getIndex()] == Node);
377 } 374 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (Node->getHasReturn()) 465 if (Node->getHasReturn())
469 getTarget()->addEpilog(Node); 466 getTarget()->addEpilog(Node);
470 } 467 }
471 468
472 void Cfg::computeLoopNestDepth() { 469 void Cfg::computeLoopNestDepth() {
473 TimerMarker T(TimerStack::TT_computeLoopNestDepth, this); 470 TimerMarker T(TimerStack::TT_computeLoopNestDepth, this);
474 LoopAnalyzer LA(this); 471 LoopAnalyzer LA(this);
475 LA.computeLoopNestDepth(); 472 LA.computeLoopNestDepth();
476 } 473 }
477 474
478 // This is a lightweight version of live-range-end calculation. Marks the last 475 // This is a lightweight version of live-range-end calculation. Marks the last
479 // use of only those variables whose definition and uses are completely with a 476 // use of only those variables whose definition and uses are completely with a
480 // single block. It is a quick single pass and doesn't need to iterate until 477 // single block. It is a quick single pass and doesn't need to iterate until
481 // convergence. 478 // convergence.
482 void Cfg::livenessLightweight() { 479 void Cfg::livenessLightweight() {
483 TimerMarker T(TimerStack::TT_livenessLightweight, this); 480 TimerMarker T(TimerStack::TT_livenessLightweight, this);
484 getVMetadata()->init(VMK_Uses); 481 getVMetadata()->init(VMK_Uses);
485 for (CfgNode *Node : Nodes) 482 for (CfgNode *Node : Nodes)
486 Node->livenessLightweight(); 483 Node->livenessLightweight();
487 } 484 }
488 485
489 void Cfg::liveness(LivenessMode Mode) { 486 void Cfg::liveness(LivenessMode Mode) {
490 TimerMarker T(TimerStack::TT_liveness, this); 487 TimerMarker T(TimerStack::TT_liveness, this);
(...skipping 15 matching lines...) Expand all
506 NeedToProcess[Pred->getIndex()] = true; 503 NeedToProcess[Pred->getIndex()] = true;
507 } 504 }
508 } 505 }
509 } 506 }
510 } 507 }
511 if (Mode == Liveness_Intervals) { 508 if (Mode == Liveness_Intervals) {
512 // Reset each variable's live range. 509 // Reset each variable's live range.
513 for (Variable *Var : Variables) 510 for (Variable *Var : Variables)
514 Var->resetLiveRange(); 511 Var->resetLiveRange();
515 } 512 }
516 // Make a final pass over each node to delete dead instructions, 513 // Make a final pass over each node to delete dead instructions, collect the
517 // collect the first and last instruction numbers, and add live 514 // first and last instruction numbers, and add live range segments for that
518 // range segments for that node. 515 // node.
519 for (CfgNode *Node : Nodes) { 516 for (CfgNode *Node : Nodes) {
520 InstNumberT FirstInstNum = Inst::NumberSentinel; 517 InstNumberT FirstInstNum = Inst::NumberSentinel;
521 InstNumberT LastInstNum = Inst::NumberSentinel; 518 InstNumberT LastInstNum = Inst::NumberSentinel;
522 for (Inst &I : Node->getPhis()) { 519 for (Inst &I : Node->getPhis()) {
523 I.deleteIfDead(); 520 I.deleteIfDead();
524 if (Mode == Liveness_Intervals && !I.isDeleted()) { 521 if (Mode == Liveness_Intervals && !I.isDeleted()) {
525 if (FirstInstNum == Inst::NumberSentinel) 522 if (FirstInstNum == Inst::NumberSentinel)
526 FirstInstNum = I.getNumber(); 523 FirstInstNum = I.getNumber();
527 assert(I.getNumber() > LastInstNum); 524 assert(I.getNumber() > LastInstNum);
528 LastInstNum = I.getNumber(); 525 LastInstNum = I.getNumber();
529 } 526 }
530 } 527 }
531 for (Inst &I : Node->getInsts()) { 528 for (Inst &I : Node->getInsts()) {
532 I.deleteIfDead(); 529 I.deleteIfDead();
533 if (Mode == Liveness_Intervals && !I.isDeleted()) { 530 if (Mode == Liveness_Intervals && !I.isDeleted()) {
534 if (FirstInstNum == Inst::NumberSentinel) 531 if (FirstInstNum == Inst::NumberSentinel)
535 FirstInstNum = I.getNumber(); 532 FirstInstNum = I.getNumber();
536 assert(I.getNumber() > LastInstNum); 533 assert(I.getNumber() > LastInstNum);
537 LastInstNum = I.getNumber(); 534 LastInstNum = I.getNumber();
538 } 535 }
539 } 536 }
540 if (Mode == Liveness_Intervals) { 537 if (Mode == Liveness_Intervals) {
541 // Special treatment for live in-args. Their liveness needs to 538 // Special treatment for live in-args. Their liveness needs to extend
542 // extend beyond the beginning of the function, otherwise an arg 539 // beyond the beginning of the function, otherwise an arg whose only use
543 // whose only use is in the first instruction will end up having 540 // is in the first instruction will end up having the trivial live range
544 // the trivial live range [2,2) and will *not* interfere with 541 // [2,2) and will *not* interfere with other arguments. So if the first
545 // other arguments. So if the first instruction of the method 542 // instruction of the method is "r=arg1+arg2", both args may be assigned
546 // is "r=arg1+arg2", both args may be assigned the same 543 // the same register. This is accomplished by extending the entry block's
547 // register. This is accomplished by extending the entry 544 // instruction range from [2,n) to [1,n) which will transform the
548 // block's instruction range from [2,n) to [1,n) which will 545 // problematic [2,2) live ranges into [1,2).
549 // transform the problematic [2,2) live ranges into [1,2).
550 if (Node == getEntryNode()) { 546 if (Node == getEntryNode()) {
551 // TODO(stichnot): Make it a strict requirement that the entry 547 // TODO(stichnot): Make it a strict requirement that the entry node
552 // node gets the lowest instruction numbers, so that extending 548 // gets the lowest instruction numbers, so that extending the live
553 // the live range for in-args is guaranteed to work. 549 // range for in-args is guaranteed to work.
554 FirstInstNum = Inst::NumberExtended; 550 FirstInstNum = Inst::NumberExtended;
555 } 551 }
556 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum); 552 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
557 } 553 }
558 } 554 }
559 } 555 }
560 556
561 // Traverse every Variable of every Inst and verify that it 557 // Traverse every Variable of every Inst and verify that it appears within the
562 // appears within the Variable's computed live range. 558 // Variable's computed live range.
563 bool Cfg::validateLiveness() const { 559 bool Cfg::validateLiveness() const {
564 TimerMarker T(TimerStack::TT_validateLiveness, this); 560 TimerMarker T(TimerStack::TT_validateLiveness, this);
565 bool Valid = true; 561 bool Valid = true;
566 OstreamLocker L(Ctx); 562 OstreamLocker L(Ctx);
567 Ostream &Str = Ctx->getStrDump(); 563 Ostream &Str = Ctx->getStrDump();
568 for (CfgNode *Node : Nodes) { 564 for (CfgNode *Node : Nodes) {
569 Inst *FirstInst = nullptr; 565 Inst *FirstInst = nullptr;
570 for (Inst &Inst : Node->getInsts()) { 566 for (Inst &Inst : Node->getInsts()) {
571 if (Inst.isDeleted()) 567 if (Inst.isDeleted())
572 continue; 568 continue;
573 if (FirstInst == nullptr) 569 if (FirstInst == nullptr)
574 FirstInst = &Inst; 570 FirstInst = &Inst;
575 InstNumberT InstNumber = Inst.getNumber(); 571 InstNumberT InstNumber = Inst.getNumber();
576 if (Variable *Dest = Inst.getDest()) { 572 if (Variable *Dest = Inst.getDest()) {
577 if (!Dest->getIgnoreLiveness()) { 573 if (!Dest->getIgnoreLiveness()) {
578 bool Invalid = false; 574 bool Invalid = false;
579 const bool IsDest = true; 575 const bool IsDest = true;
580 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest)) 576 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest))
581 Invalid = true; 577 Invalid = true;
582 // Check that this instruction actually *begins* Dest's live 578 // Check that this instruction actually *begins* Dest's live range,
583 // range, by checking that Dest is not live in the previous 579 // by checking that Dest is not live in the previous instruction. As
584 // instruction. As a special exception, we don't check this 580 // a special exception, we don't check this for the first instruction
585 // for the first instruction of the block, because a Phi 581 // of the block, because a Phi temporary may be live at the end of
586 // temporary may be live at the end of the previous block, 582 // the previous block, and if it is also assigned in the first
587 // and if it is also assigned in the first instruction of 583 // instruction of this block, the adjacent live ranges get merged.
588 // this block, the adjacent live ranges get merged.
589 if (static_cast<class Inst *>(&Inst) != FirstInst && 584 if (static_cast<class Inst *>(&Inst) != FirstInst &&
590 !Inst.isDestNonKillable() && 585 !Inst.isDestNonKillable() &&
591 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest)) 586 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
592 Invalid = true; 587 Invalid = true;
593 if (Invalid) { 588 if (Invalid) {
594 Valid = false; 589 Valid = false;
595 Str << "Liveness error: inst " << Inst.getNumber() << " dest "; 590 Str << "Liveness error: inst " << Inst.getNumber() << " dest ";
596 Dest->dump(this); 591 Dest->dump(this);
597 Str << " live range " << Dest->getLiveRange() << "\n"; 592 Str << " live range " << Dest->getLiveRange() << "\n";
598 } 593 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 } 630 }
636 631
637 void Cfg::markNodesForSandboxing() { 632 void Cfg::markNodesForSandboxing() {
638 for (const InstJumpTable *JT : JumpTables) 633 for (const InstJumpTable *JT : JumpTables)
639 for (SizeT I = 0; I < JT->getNumTargets(); ++I) 634 for (SizeT I = 0; I < JT->getNumTargets(); ++I)
640 JT->getTarget(I)->setNeedsAlignment(); 635 JT->getTarget(I)->setNeedsAlignment();
641 } 636 }
642 637
643 // ======================== Dump routines ======================== // 638 // ======================== Dump routines ======================== //
644 639
645 // emitTextHeader() is not target-specific (apart from what is 640 // emitTextHeader() is not target-specific (apart from what is abstracted by
646 // abstracted by the Assembler), so it is defined here rather than in 641 // the Assembler), so it is defined here rather than in the target lowering
647 // the target lowering class. 642 // class.
648 void Cfg::emitTextHeader(const IceString &MangledName, GlobalContext *Ctx, 643 void Cfg::emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
649 const Assembler *Asm) { 644 const Assembler *Asm) {
650 if (!BuildDefs::dump()) 645 if (!BuildDefs::dump())
651 return; 646 return;
652 Ostream &Str = Ctx->getStrEmit(); 647 Ostream &Str = Ctx->getStrEmit();
653 Str << "\t.text\n"; 648 Str << "\t.text\n";
654 if (Ctx->getFlags().getFunctionSections()) 649 if (Ctx->getFlags().getFunctionSections())
655 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n"; 650 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
656 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) { 651 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) {
657 Str << "\t.globl\t" << MangledName << "\n"; 652 Str << "\t.globl\t" << MangledName << "\n";
658 Str << "\t.type\t" << MangledName << ",%function\n"; 653 Str << "\t.type\t" << MangledName << ",%function\n";
659 } 654 }
660 Str << "\t" << Asm->getAlignDirective() << " " 655 Str << "\t" << Asm->getAlignDirective() << " "
661 << Asm->getBundleAlignLog2Bytes() << ",0x"; 656 << Asm->getBundleAlignLog2Bytes() << ",0x";
662 for (uint8_t I : Asm->getNonExecBundlePadding()) 657 for (uint8_t I : Asm->getNonExecBundlePadding())
663 Str.write_hex(I); 658 Str.write_hex(I);
664 Str << "\n"; 659 Str << "\n";
665 Str << MangledName << ":\n"; 660 Str << MangledName << ":\n";
666 } 661 }
667 662
668 void Cfg::deleteJumpTableInsts() { 663 void Cfg::deleteJumpTableInsts() {
669 for (InstJumpTable *JumpTable : JumpTables) 664 for (InstJumpTable *JumpTable : JumpTables)
670 JumpTable->setDeleted(); 665 JumpTable->setDeleted();
671 } 666 }
672 667
673 void Cfg::emitJumpTables() { 668 void Cfg::emitJumpTables() {
674 switch (Ctx->getFlags().getOutFileType()) { 669 switch (Ctx->getFlags().getOutFileType()) {
675 case FT_Elf: 670 case FT_Elf:
676 case FT_Iasm: { 671 case FT_Iasm: {
677 // The emission needs to be delayed until the after the text section so save 672 // The emission needs to be delayed until the after the text section so
678 // the offsets in the global context. 673 // save the offsets in the global context.
679 IceString MangledName = Ctx->mangleName(getFunctionName()); 674 IceString MangledName = Ctx->mangleName(getFunctionName());
680 for (const InstJumpTable *JumpTable : JumpTables) { 675 for (const InstJumpTable *JumpTable : JumpTables) {
681 SizeT NumTargets = JumpTable->getNumTargets(); 676 SizeT NumTargets = JumpTable->getNumTargets();
682 JumpTableData &JT = 677 JumpTableData &JT =
683 Ctx->addJumpTable(MangledName, JumpTable->getId(), NumTargets); 678 Ctx->addJumpTable(MangledName, JumpTable->getId(), NumTargets);
684 for (SizeT I = 0; I < NumTargets; ++I) { 679 for (SizeT I = 0; I < NumTargets; ++I) {
685 SizeT Index = JumpTable->getTarget(I)->getIndex(); 680 SizeT Index = JumpTable->getTarget(I)->getIndex();
686 JT.pushTarget(getAssembler()->getCfgNodeLabel(Index)->getPosition()); 681 JT.pushTarget(getAssembler()->getCfgNodeLabel(Index)->getPosition());
687 } 682 }
688 } 683 }
(...skipping 30 matching lines...) Expand all
719 << Asm->getBundleAlignLog2Bytes() << "\n"; 714 << Asm->getBundleAlignLog2Bytes() << "\n";
720 } 715 }
721 Node->emit(this); 716 Node->emit(this);
722 } 717 }
723 emitJumpTables(); 718 emitJumpTables();
724 Str << "\n"; 719 Str << "\n";
725 } 720 }
726 721
727 void Cfg::emitIAS() { 722 void Cfg::emitIAS() {
728 TimerMarker T(TimerStack::TT_emit, this); 723 TimerMarker T(TimerStack::TT_emit, this);
729 // The emitIAS() routines emit into the internal assembler buffer, 724 // The emitIAS() routines emit into the internal assembler buffer, so there's
730 // so there's no need to lock the streams. 725 // no need to lock the streams.
731 deleteJumpTableInsts(); 726 deleteJumpTableInsts();
732 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); 727 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
733 for (CfgNode *Node : Nodes) { 728 for (CfgNode *Node : Nodes) {
734 if (NeedSandboxing && Node->needsAlignment()) 729 if (NeedSandboxing && Node->needsAlignment())
735 getAssembler()->alignCfgNode(); 730 getAssembler()->alignCfgNode();
736 Node->emitIAS(this); 731 Node->emitIAS(this);
737 } 732 }
738 emitJumpTables(); 733 emitJumpTables();
739 } 734 }
740 735
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 } 773 }
779 } 774 }
780 // Print each basic block 775 // Print each basic block
781 for (CfgNode *Node : Nodes) 776 for (CfgNode *Node : Nodes)
782 Node->dump(this); 777 Node->dump(this);
783 if (isVerbose(IceV_Instructions)) 778 if (isVerbose(IceV_Instructions))
784 Str << "}\n"; 779 Str << "}\n";
785 } 780 }
786 781
787 } // end of namespace Ice 782 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceCfg.h ('k') | src/IceCfgNode.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698