| OLD | NEW |
| 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===// | 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) 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 CfgNode class, including the complexities | 10 // This file implements the CfgNode class, including the complexities |
| 11 // of instruction insertion and in-edge calculation. | 11 // of instruction insertion and in-edge calculation. |
| 12 // | 12 // |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
| 16 #include "IceCfgNode.h" | 16 #include "IceCfgNode.h" |
| 17 #include "IceInst.h" | 17 #include "IceInst.h" |
| 18 #include "IceLiveness.h" | 18 #include "IceLiveness.h" |
| 19 #include "IceOperand.h" | 19 #include "IceOperand.h" |
| 20 #include "IceTargetLowering.h" | 20 #include "IceTargetLowering.h" |
| 21 | 21 |
| 22 namespace Ice { | 22 namespace Ice { |
| 23 | 23 |
| 24 CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber, IceString Name) | 24 CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber, IceString Name) |
| 25 : Func(Func), Number(LabelNumber), Name(Name), HasReturn(false) {} | 25 : Func(Func), Number(LabelNumber), Name(Name), HasReturn(false), |
| 26 InstCountEstimate(0) {} |
| 26 | 27 |
| 27 // Returns the name the node was created with. If no name was given, | 28 // Returns the name the node was created with. If no name was given, |
| 28 // it synthesizes a (hopefully) unique name. | 29 // it synthesizes a (hopefully) unique name. |
| 29 IceString CfgNode::getName() const { | 30 IceString CfgNode::getName() const { |
| 30 if (!Name.empty()) | 31 if (!Name.empty()) |
| 31 return Name; | 32 return Name; |
| 32 char buf[30]; | 33 char buf[30]; |
| 33 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); | 34 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); |
| 34 return buf; | 35 return buf; |
| 35 } | 36 } |
| 36 | 37 |
| 37 // Adds an instruction to either the Phi list or the regular | 38 // Adds an instruction to either the Phi list or the regular |
| 38 // instruction list. Validates that all Phis are added before all | 39 // instruction list. Validates that all Phis are added before all |
| 39 // regular instructions. | 40 // regular instructions. |
| 40 void CfgNode::appendInst(Inst *Inst) { | 41 void CfgNode::appendInst(Inst *Inst) { |
| 42 ++InstCountEstimate; |
| 41 if (InstPhi *Phi = llvm::dyn_cast<InstPhi>(Inst)) { | 43 if (InstPhi *Phi = llvm::dyn_cast<InstPhi>(Inst)) { |
| 42 if (!Insts.empty()) { | 44 if (!Insts.empty()) { |
| 43 Func->setError("Phi instruction added to the middle of a block"); | 45 Func->setError("Phi instruction added to the middle of a block"); |
| 44 return; | 46 return; |
| 45 } | 47 } |
| 46 Phis.push_back(Phi); | 48 Phis.push_back(Phi); |
| 47 } else { | 49 } else { |
| 48 Insts.push_back(Inst); | 50 Insts.push_back(Inst); |
| 49 } | 51 } |
| 50 } | 52 } |
| 51 | 53 |
| 52 // Renumbers the non-deleted instructions in the node. This needs to | 54 // Renumbers the non-deleted instructions in the node. This needs to |
| 53 // be done in preparation for live range analysis. The instruction | 55 // be done in preparation for live range analysis. The instruction |
| 54 // numbers in a block must be monotonically increasing. The range of | 56 // numbers in a block must be monotonically increasing. The range of |
| 55 // instruction numbers in a block, from lowest to highest, must not | 57 // instruction numbers in a block, from lowest to highest, must not |
| 56 // overlap with the range of any other block. | 58 // overlap with the range of any other block. |
| 57 void CfgNode::renumberInstructions() { | 59 void CfgNode::renumberInstructions() { |
| 60 InstNumberT FirstNumber = Func->getNextInstNumber(); |
| 58 for (InstPhi *I : Phis) | 61 for (InstPhi *I : Phis) |
| 59 I->renumber(Func); | 62 I->renumber(Func); |
| 60 for (Inst *I : Insts) | 63 for (Inst *I : Insts) |
| 61 I->renumber(Func); | 64 I->renumber(Func); |
| 65 InstCountEstimate = Func->getNextInstNumber() - FirstNumber; |
| 62 } | 66 } |
| 63 | 67 |
| 64 // When a node is created, the OutEdges are immediately knows, but the | 68 // When a node is created, the OutEdges are immediately knows, but the |
| 65 // InEdges have to be built up incrementally. After the CFG has been | 69 // InEdges have to be built up incrementally. After the CFG has been |
| 66 // constructed, the computePredecessors() pass finalizes it by | 70 // constructed, the computePredecessors() pass finalizes it by |
| 67 // creating the InEdges list. | 71 // creating the InEdges list. |
| 68 void CfgNode::computePredecessors() { | 72 void CfgNode::computePredecessors() { |
| 69 OutEdges = (*Insts.rbegin())->getTerminatorEdges(); | 73 OutEdges = (*Insts.rbegin())->getTerminatorEdges(); |
| 70 for (CfgNode *Succ : OutEdges) | 74 for (CfgNode *Succ : OutEdges) |
| 71 Succ->InEdges.push_back(this); | 75 Succ->InEdges.push_back(this); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 if (llvm::isa<InstRet>(*Orig)) | 248 if (llvm::isa<InstRet>(*Orig)) |
| 245 setHasReturn(); | 249 setHasReturn(); |
| 246 Target->lower(); | 250 Target->lower(); |
| 247 // Ensure target lowering actually moved the cursor. | 251 // Ensure target lowering actually moved the cursor. |
| 248 assert(Context.getCur() != Orig); | 252 assert(Context.getCur() != Orig); |
| 249 } | 253 } |
| 250 } | 254 } |
| 251 | 255 |
| 252 void CfgNode::livenessLightweight() { | 256 void CfgNode::livenessLightweight() { |
| 253 SizeT NumVars = Func->getNumVariables(); | 257 SizeT NumVars = Func->getNumVariables(); |
| 254 llvm::BitVector Live(NumVars); | 258 LivenessBV Live(NumVars); |
| 255 // Process regular instructions in reverse order. | 259 // Process regular instructions in reverse order. |
| 256 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. | 260 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. |
| 257 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { | 261 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { |
| 258 if ((*I)->isDeleted()) | 262 if ((*I)->isDeleted()) |
| 259 continue; | 263 continue; |
| 260 (*I)->livenessLightweight(Func, Live); | 264 (*I)->livenessLightweight(Func, Live); |
| 261 } | 265 } |
| 262 for (InstPhi *I : Phis) { | 266 for (InstPhi *I : Phis) { |
| 263 if (I->isDeleted()) | 267 if (I->isDeleted()) |
| 264 continue; | 268 continue; |
| 265 I->livenessLightweight(Func, Live); | 269 I->livenessLightweight(Func, Live); |
| 266 } | 270 } |
| 267 } | 271 } |
| 268 | 272 |
| 269 // Performs liveness analysis on the block. Returns true if the | 273 // Performs liveness analysis on the block. Returns true if the |
| 270 // incoming liveness changed from before, false if it stayed the same. | 274 // incoming liveness changed from before, false if it stayed the same. |
| 271 // (If it changes, the node's predecessors need to be processed | 275 // (If it changes, the node's predecessors need to be processed |
| 272 // again.) | 276 // again.) |
| 273 bool CfgNode::liveness(Liveness *Liveness) { | 277 bool CfgNode::liveness(Liveness *Liveness) { |
| 274 SizeT NumVars = Liveness->getNumVarsInNode(this); | 278 SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 275 llvm::BitVector Live(NumVars); | 279 LivenessBV Live(NumVars); |
| 280 LiveBeginEndMap *LiveBegin = NULL; |
| 281 LiveBeginEndMap *LiveEnd = NULL; |
| 276 // Mark the beginning and ending of each variable's live range | 282 // Mark the beginning and ending of each variable's live range |
| 277 // with the sentinel instruction number 0. | 283 // with the sentinel instruction number 0. |
| 278 std::vector<InstNumberT> &LiveBegin = Liveness->getLiveBegin(this); | 284 if (Liveness->getMode() == Liveness_Intervals) { |
| 279 std::vector<InstNumberT> &LiveEnd = Liveness->getLiveEnd(this); | 285 LiveBegin = Liveness->getLiveBegin(this); |
| 280 InstNumberT Sentinel = Inst::NumberSentinel; | 286 LiveEnd = Liveness->getLiveEnd(this); |
| 281 LiveBegin.assign(NumVars, Sentinel); | 287 LiveBegin->clear(); |
| 282 LiveEnd.assign(NumVars, Sentinel); | 288 LiveEnd->clear(); |
| 289 // Guess that the number of live ranges beginning is roughly the |
| 290 // number of instructions, and same for live ranges ending. |
| 291 LiveBegin->reserve(getInstCountEstimate()); |
| 292 LiveEnd->reserve(getInstCountEstimate()); |
| 293 } |
| 283 // Initialize Live to be the union of all successors' LiveIn. | 294 // Initialize Live to be the union of all successors' LiveIn. |
| 284 for (CfgNode *Succ : OutEdges) { | 295 for (CfgNode *Succ : OutEdges) { |
| 285 Live |= Liveness->getLiveIn(Succ); | 296 Live |= Liveness->getLiveIn(Succ); |
| 286 // Mark corresponding argument of phis in successor as live. | 297 // Mark corresponding argument of phis in successor as live. |
| 287 for (InstPhi *I : Succ->Phis) | 298 for (InstPhi *I : Succ->Phis) |
| 288 I->livenessPhiOperand(Live, this, Liveness); | 299 I->livenessPhiOperand(Live, this, Liveness); |
| 289 } | 300 } |
| 290 Liveness->getLiveOut(this) = Live; | 301 Liveness->getLiveOut(this) = Live; |
| 291 | 302 |
| 292 // Process regular instructions in reverse order. | 303 // Process regular instructions in reverse order. |
| 293 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. | 304 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. |
| 294 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { | 305 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { |
| 295 if ((*I)->isDeleted()) | 306 if ((*I)->isDeleted()) |
| 296 continue; | 307 continue; |
| 297 (*I)->liveness((*I)->getNumber(), Live, Liveness, this); | 308 (*I)->liveness((*I)->getNumber(), Live, Liveness, LiveBegin, LiveEnd); |
| 298 } | 309 } |
| 299 // Process phis in forward order so that we can override the | 310 // Process phis in forward order so that we can override the |
| 300 // instruction number to be that of the earliest phi instruction in | 311 // instruction number to be that of the earliest phi instruction in |
| 301 // the block. | 312 // the block. |
| 302 InstNumberT FirstPhiNumber = Inst::NumberSentinel; | 313 InstNumberT FirstPhiNumber = Inst::NumberSentinel; |
| 303 for (InstPhi *I : Phis) { | 314 for (InstPhi *I : Phis) { |
| 304 if (I->isDeleted()) | 315 if (I->isDeleted()) |
| 305 continue; | 316 continue; |
| 306 if (FirstPhiNumber == Inst::NumberSentinel) | 317 if (FirstPhiNumber == Inst::NumberSentinel) |
| 307 FirstPhiNumber = I->getNumber(); | 318 FirstPhiNumber = I->getNumber(); |
| 308 I->liveness(FirstPhiNumber, Live, Liveness, this); | 319 I->liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd); |
| 309 } | 320 } |
| 310 | 321 |
| 311 // When using the sparse representation, after traversing the | 322 // When using the sparse representation, after traversing the |
| 312 // instructions in the block, the Live bitvector should only contain | 323 // instructions in the block, the Live bitvector should only contain |
| 313 // set bits for global variables upon block entry. We validate this | 324 // set bits for global variables upon block entry. We validate this |
| 314 // by shrinking the Live vector and then testing it against the | 325 // by shrinking the Live vector and then testing it against the |
| 315 // pre-shrunk version. (The shrinking is required, but the | 326 // pre-shrunk version. (The shrinking is required, but the |
| 316 // validation is not.) | 327 // validation is not.) |
| 317 llvm::BitVector LiveOrig = Live; | 328 LivenessBV LiveOrig = Live; |
| 318 Live.resize(Liveness->getNumGlobalVars()); | 329 Live.resize(Liveness->getNumGlobalVars()); |
| 319 // Non-global arguments in the entry node are allowed to be live on | 330 // Non-global arguments in the entry node are allowed to be live on |
| 320 // entry. | 331 // entry. |
| 321 bool IsEntry = (Func->getEntryNode() == this); | 332 bool IsEntry = (Func->getEntryNode() == this); |
| 322 if (!(IsEntry || Live == LiveOrig)) { | 333 if (!(IsEntry || Live == LiveOrig)) { |
| 323 // This is a fatal liveness consistency error. Print some | 334 // This is a fatal liveness consistency error. Print some |
| 324 // diagnostics and abort. | 335 // diagnostics and abort. |
| 325 Ostream &Str = Func->getContext()->getStrDump(); | 336 Ostream &Str = Func->getContext()->getStrDump(); |
| 326 Func->resetCurrentNode(); | 337 Func->resetCurrentNode(); |
| 327 Str << "LiveOrig-Live ="; | 338 Str << "LiveOrig-Live ="; |
| 328 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { | 339 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) { |
| 329 if (LiveOrig.test(i)) { | 340 if (LiveOrig.test(i)) { |
| 330 Str << " "; | 341 Str << " "; |
| 331 Liveness->getVariable(i, this)->dump(Func); | 342 Liveness->getVariable(i, this)->dump(Func); |
| 332 } | 343 } |
| 333 } | 344 } |
| 334 Str << "\n"; | 345 Str << "\n"; |
| 335 llvm_unreachable("Fatal inconsistency in liveness analysis"); | 346 llvm_unreachable("Fatal inconsistency in liveness analysis"); |
| 336 } | 347 } |
| 337 | 348 |
| 338 bool Changed = false; | 349 bool Changed = false; |
| 339 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); | 350 LivenessBV &LiveIn = Liveness->getLiveIn(this); |
| 340 // Add in current LiveIn | 351 // Add in current LiveIn |
| 341 Live |= LiveIn; | 352 Live |= LiveIn; |
| 342 // Check result, set LiveIn=Live | 353 // Check result, set LiveIn=Live |
| 343 Changed = (Live != LiveIn); | 354 Changed = (Live != LiveIn); |
| 344 if (Changed) | 355 if (Changed) |
| 345 LiveIn = Live; | 356 LiveIn = Live; |
| 346 return Changed; | 357 return Changed; |
| 347 } | 358 } |
| 348 | 359 |
| 360 #ifndef NDEBUG |
| 361 namespace { |
| 362 |
| 363 bool comparePair(const LiveBeginEndMapEntry &A, const LiveBeginEndMapEntry &B) { |
| 364 return A.first == B.first; |
| 365 } |
| 366 |
| 367 } // end of anonymous namespace |
| 368 #endif // NDEBUG |
| 369 |
| 349 // Now that basic liveness is complete, remove dead instructions that | 370 // Now that basic liveness is complete, remove dead instructions that |
| 350 // were tentatively marked as dead, and compute actual live ranges. | 371 // were tentatively marked as dead, and compute actual live ranges. |
| 351 // It is assumed that within a single basic block, a live range begins | 372 // It is assumed that within a single basic block, a live range begins |
| 352 // at most once and ends at most once. This is certainly true for | 373 // at most once and ends at most once. This is certainly true for |
| 353 // pure SSA form. It is also true once phis are lowered, since each | 374 // pure SSA form. It is also true once phis are lowered, since each |
| 354 // assignment to the phi-based temporary is in a different basic | 375 // assignment to the phi-based temporary is in a different basic |
| 355 // block, and there is a single read that ends the live in the basic | 376 // block, and there is a single read that ends the live in the basic |
| 356 // block that contained the actual phi instruction. | 377 // block that contained the actual phi instruction. |
| 357 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { | 378 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { |
| 358 InstNumberT FirstInstNum = Inst::NumberSentinel; | 379 InstNumberT FirstInstNum = Inst::NumberSentinel; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 389 } | 410 } |
| 390 } | 411 } |
| 391 } | 412 } |
| 392 } | 413 } |
| 393 } | 414 } |
| 394 if (Mode != Liveness_Intervals) | 415 if (Mode != Liveness_Intervals) |
| 395 return; | 416 return; |
| 396 TimerMarker T1(TimerStack::TT_liveRangeCtor, Func); | 417 TimerMarker T1(TimerStack::TT_liveRangeCtor, Func); |
| 397 | 418 |
| 398 SizeT NumVars = Liveness->getNumVarsInNode(this); | 419 SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 399 SizeT NumGlobals = Liveness->getNumGlobalVars(); | 420 LivenessBV &LiveIn = Liveness->getLiveIn(this); |
| 400 llvm::BitVector &LiveIn = Liveness->getLiveIn(this); | 421 LivenessBV &LiveOut = Liveness->getLiveOut(this); |
| 401 llvm::BitVector &LiveOut = Liveness->getLiveOut(this); | 422 LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this); |
| 402 std::vector<InstNumberT> &LiveBegin = Liveness->getLiveBegin(this); | 423 LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this); |
| 403 std::vector<InstNumberT> &LiveEnd = Liveness->getLiveEnd(this); | 424 std::sort(MapBegin.begin(), MapBegin.end()); |
| 404 for (SizeT i = 0; i < NumVars; ++i) { | 425 std::sort(MapEnd.begin(), MapEnd.end()); |
| 405 // Deal with the case where the variable is both live-in and | 426 // Verify there are no duplicates. |
| 406 // live-out, but LiveEnd comes before LiveBegin. In this case, we | 427 assert(std::adjacent_find(MapBegin.begin(), MapBegin.end(), comparePair) == |
| 407 // need to add two segments to the live range because there is a | 428 MapBegin.end()); |
| 408 // hole in the middle. This would typically happen as a result of | 429 assert(std::adjacent_find(MapEnd.begin(), MapEnd.end(), comparePair) == |
| 409 // phi lowering in the presence of loopback edges. | 430 MapEnd.end()); |
| 410 bool IsGlobal = (i < NumGlobals); | 431 |
| 411 if (IsGlobal && LiveIn[i] && LiveOut[i] && LiveBegin[i] > LiveEnd[i]) { | 432 LivenessBV LiveInAndOut = LiveIn; |
| 412 Variable *Var = Liveness->getVariable(i, this); | 433 LiveInAndOut &= LiveOut; |
| 413 Liveness->addLiveRange(Var, FirstInstNum, LiveEnd[i], 1); | 434 |
| 414 Liveness->addLiveRange(Var, LiveBegin[i], LastInstNum + 1, 1); | 435 // Iterate in parallel across the sorted MapBegin[] and MapEnd[]. |
| 415 continue; | 436 auto IBB = MapBegin.begin(), IEB = MapEnd.begin(); |
| 437 auto IBE = MapBegin.end(), IEE = MapEnd.end(); |
| 438 while (IBB != IBE || IEB != IEE) { |
| 439 SizeT i1 = IBB == IBE ? NumVars : IBB->first; |
| 440 SizeT i2 = IEB == IEE ? NumVars : IEB->first; |
| 441 SizeT i = std::min(i1, i2); |
| 442 // i1 is the Variable number of the next MapBegin entry, and i2 is |
| 443 // the Variable number of the next MapEnd entry. If i1==i2, then |
| 444 // the Variable's live range begins and ends in this block. If |
| 445 // i1<i2, then i1's live range begins at instruction IBB->second |
| 446 // and extends through the end of the block. If i1>i2, then i2's |
| 447 // live range begins at the first instruction of the block and |
| 448 // ends at IEB->second. In any case, we choose the lesser of i1 |
| 449 // and i2 and proceed accordingly. |
| 450 InstNumberT LB = i == i1 ? IBB->second : FirstInstNum; |
| 451 InstNumberT LE = i == i2 ? IEB->second : LastInstNum + 1; |
| 452 |
| 453 Variable *Var = Liveness->getVariable(i, this); |
| 454 if (!Var->getIgnoreLiveness()) { |
| 455 if (LB > LE) { |
| 456 Liveness->addLiveRange(Var, FirstInstNum, LE, 1); |
| 457 Liveness->addLiveRange(Var, LB, LastInstNum + 1, 1); |
| 458 // Assert that Var is a global variable by checking that its |
| 459 // liveness index is less than the number of globals. This |
| 460 // ensures that the LiveInAndOut[] access is valid. |
| 461 assert(i < Liveness->getNumGlobalVars()); |
| 462 LiveInAndOut[i] = false; |
| 463 } else { |
| 464 Liveness->addLiveRange(Var, LB, LE, 1); |
| 465 } |
| 416 } | 466 } |
| 417 InstNumberT Begin = (IsGlobal && LiveIn[i]) ? FirstInstNum : LiveBegin[i]; | 467 if (i == i1) |
| 418 InstNumberT End = (IsGlobal && LiveOut[i]) ? LastInstNum + 1 : LiveEnd[i]; | 468 ++IBB; |
| 419 if (Begin == Inst::NumberSentinel && End == Inst::NumberSentinel) | 469 if (i == i2) |
| 420 continue; | 470 ++IEB; |
| 421 if (Begin <= FirstInstNum) | 471 } |
| 422 Begin = FirstInstNum; | 472 // Process the variables that are live across the entire block. |
| 423 if (End == Inst::NumberSentinel) | 473 for (int i = LiveInAndOut.find_first(); i != -1; |
| 424 End = LastInstNum + 1; | 474 i = LiveInAndOut.find_next(i)) { |
| 425 Variable *Var = Liveness->getVariable(i, this); | 475 Variable *Var = Liveness->getVariable(i, this); |
| 426 Liveness->addLiveRange(Var, Begin, End, 1); | 476 Liveness->addLiveRange(Var, FirstInstNum, LastInstNum + 1, 1); |
| 427 } | 477 } |
| 428 } | 478 } |
| 429 | 479 |
| 430 void CfgNode::doBranchOpt(const CfgNode *NextNode) { | 480 void CfgNode::doBranchOpt(const CfgNode *NextNode) { |
| 431 TargetLowering *Target = Func->getTarget(); | 481 TargetLowering *Target = Func->getTarget(); |
| 432 // Check every instruction for a branch optimization opportunity. | 482 // Check every instruction for a branch optimization opportunity. |
| 433 // It may be more efficient to iterate in reverse and stop after the | 483 // It may be more efficient to iterate in reverse and stop after the |
| 434 // first opportunity, unless there is some target lowering where we | 484 // first opportunity, unless there is some target lowering where we |
| 435 // have the possibility of multiple such optimizations per block | 485 // have the possibility of multiple such optimizations per block |
| 436 // (currently not the case for x86 lowering). | 486 // (currently not the case for x86 lowering). |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 bool First = true; | 547 bool First = true; |
| 498 for (CfgNode *I : InEdges) { | 548 for (CfgNode *I : InEdges) { |
| 499 if (!First) | 549 if (!First) |
| 500 Str << ", "; | 550 Str << ", "; |
| 501 First = false; | 551 First = false; |
| 502 Str << "%" << I->getName(); | 552 Str << "%" << I->getName(); |
| 503 } | 553 } |
| 504 Str << "\n"; | 554 Str << "\n"; |
| 505 } | 555 } |
| 506 // Dump the live-in variables. | 556 // Dump the live-in variables. |
| 507 llvm::BitVector LiveIn; | 557 LivenessBV LiveIn; |
| 508 if (Liveness) | 558 if (Liveness) |
| 509 LiveIn = Liveness->getLiveIn(this); | 559 LiveIn = Liveness->getLiveIn(this); |
| 510 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) { | 560 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) { |
| 511 Str << " // LiveIn:"; | 561 Str << " // LiveIn:"; |
| 512 for (SizeT i = 0; i < LiveIn.size(); ++i) { | 562 for (SizeT i = 0; i < LiveIn.size(); ++i) { |
| 513 if (LiveIn[i]) { | 563 if (LiveIn[i]) { |
| 514 Str << " %" << Liveness->getVariable(i, this)->getName(); | 564 Str << " %" << Liveness->getVariable(i, this)->getName(); |
| 515 } | 565 } |
| 516 } | 566 } |
| 517 Str << "\n"; | 567 Str << "\n"; |
| 518 } | 568 } |
| 519 // Dump each instruction. | 569 // Dump each instruction. |
| 520 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 570 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
| 521 for (InstPhi *I : Phis) | 571 for (InstPhi *I : Phis) |
| 522 I->dumpDecorated(Func); | 572 I->dumpDecorated(Func); |
| 523 for (Inst *I : Insts) | 573 for (Inst *I : Insts) |
| 524 I->dumpDecorated(Func); | 574 I->dumpDecorated(Func); |
| 525 } | 575 } |
| 526 // Dump the live-out variables. | 576 // Dump the live-out variables. |
| 527 llvm::BitVector LiveOut; | 577 LivenessBV LiveOut; |
| 528 if (Liveness) | 578 if (Liveness) |
| 529 LiveOut = Liveness->getLiveOut(this); | 579 LiveOut = Liveness->getLiveOut(this); |
| 530 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { | 580 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { |
| 531 Str << " // LiveOut:"; | 581 Str << " // LiveOut:"; |
| 532 for (SizeT i = 0; i < LiveOut.size(); ++i) { | 582 for (SizeT i = 0; i < LiveOut.size(); ++i) { |
| 533 if (LiveOut[i]) { | 583 if (LiveOut[i]) { |
| 534 Str << " %" << Liveness->getVariable(i, this)->getName(); | 584 Str << " %" << Liveness->getVariable(i, this)->getName(); |
| 535 } | 585 } |
| 536 } | 586 } |
| 537 Str << "\n"; | 587 Str << "\n"; |
| 538 } | 588 } |
| 539 // Dump list of successor nodes. | 589 // Dump list of successor nodes. |
| 540 if (Func->getContext()->isVerbose(IceV_Succs)) { | 590 if (Func->getContext()->isVerbose(IceV_Succs)) { |
| 541 Str << " // succs = "; | 591 Str << " // succs = "; |
| 542 bool First = true; | 592 bool First = true; |
| 543 for (CfgNode *I : OutEdges) { | 593 for (CfgNode *I : OutEdges) { |
| 544 if (!First) | 594 if (!First) |
| 545 Str << ", "; | 595 Str << ", "; |
| 546 First = false; | 596 First = false; |
| 547 Str << "%" << I->getName(); | 597 Str << "%" << I->getName(); |
| 548 } | 598 } |
| 549 Str << "\n"; | 599 Str << "\n"; |
| 550 } | 600 } |
| 551 } | 601 } |
| 552 | 602 |
| 553 } // end of namespace Ice | 603 } // end of namespace Ice |
| OLD | NEW |