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

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

Powered by Google App Engine
This is Rietveld 408576698