| 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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 // Renumbers the non-deleted instructions in the node. This needs to | 53 // Renumbers the non-deleted instructions in the node. This needs to |
| 54 // be done in preparation for live range analysis. The instruction | 54 // be done in preparation for live range analysis. The instruction |
| 55 // numbers in a block must be monotonically increasing. The range of | 55 // numbers in a block must be monotonically increasing. The range of |
| 56 // instruction numbers in a block, from lowest to highest, must not | 56 // instruction numbers in a block, from lowest to highest, must not |
| 57 // overlap with the range of any other block. | 57 // overlap with the range of any other block. |
| 58 void CfgNode::renumberInstructions() { | 58 void CfgNode::renumberInstructions() { |
| 59 InstNumberT FirstNumber = Func->getNextInstNumber(); | 59 InstNumberT FirstNumber = Func->getNextInstNumber(); |
| 60 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) | 60 for (Inst &I : Phis) |
| 61 I->renumber(Func); | 61 I.renumber(Func); |
| 62 for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) | 62 for (Inst &I : Insts) |
| 63 I->renumber(Func); | 63 I.renumber(Func); |
| 64 InstCountEstimate = Func->getNextInstNumber() - FirstNumber; | 64 InstCountEstimate = Func->getNextInstNumber() - FirstNumber; |
| 65 } | 65 } |
| 66 | 66 |
| 67 // When a node is created, the OutEdges are immediately known, but the | 67 // When a node is created, the OutEdges are immediately known, but the |
| 68 // InEdges have to be built up incrementally. After the CFG has been | 68 // InEdges have to be built up incrementally. After the CFG has been |
| 69 // constructed, the computePredecessors() pass finalizes it by | 69 // constructed, the computePredecessors() pass finalizes it by |
| 70 // creating the InEdges list. | 70 // creating the InEdges list. |
| 71 void CfgNode::computePredecessors() { | 71 void CfgNode::computePredecessors() { |
| 72 OutEdges = Insts.rbegin()->getTerminatorEdges(); | 72 OutEdges = Insts.rbegin()->getTerminatorEdges(); |
| 73 for (CfgNode *Succ : OutEdges) | 73 for (CfgNode *Succ : OutEdges) |
| 74 Succ->InEdges.push_back(this); | 74 Succ->InEdges.push_back(this); |
| 75 } | 75 } |
| 76 | 76 |
| 77 // This does part 1 of Phi lowering, by creating a new dest variable | 77 // This does part 1 of Phi lowering, by creating a new dest variable |
| 78 // for each Phi instruction, replacing the Phi instruction's dest with | 78 // for each Phi instruction, replacing the Phi instruction's dest with |
| 79 // that variable, and adding an explicit assignment of the old dest to | 79 // that variable, and adding an explicit assignment of the old dest to |
| 80 // the new dest. For example, | 80 // the new dest. For example, |
| 81 // a=phi(...) | 81 // a=phi(...) |
| 82 // changes to | 82 // changes to |
| 83 // "a_phi=phi(...); a=a_phi". | 83 // "a_phi=phi(...); a=a_phi". |
| 84 // | 84 // |
| 85 // This is in preparation for part 2 which deletes the Phi | 85 // This is in preparation for part 2 which deletes the Phi |
| 86 // instructions and appends assignment instructions to predecessor | 86 // instructions and appends assignment instructions to predecessor |
| 87 // blocks. Note that this transformation preserves SSA form. | 87 // blocks. Note that this transformation preserves SSA form. |
| 88 void CfgNode::placePhiLoads() { | 88 void CfgNode::placePhiLoads() { |
| 89 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 89 for (Inst &I : Phis) { |
| 90 auto Phi = llvm::dyn_cast<InstPhi>(I); | 90 auto Phi = llvm::dyn_cast<InstPhi>(&I); |
| 91 Insts.insert(Insts.begin(), Phi->lower(Func)); | 91 Insts.insert(Insts.begin(), Phi->lower(Func)); |
| 92 } | 92 } |
| 93 } | 93 } |
| 94 | 94 |
| 95 // This does part 2 of Phi lowering. For each Phi instruction at each | 95 // This does part 2 of Phi lowering. For each Phi instruction at each |
| 96 // out-edge, create a corresponding assignment instruction, and add | 96 // out-edge, create a corresponding assignment instruction, and add |
| 97 // all the assignments near the end of this block. They need to be | 97 // all the assignments near the end of this block. They need to be |
| 98 // added before any branch instruction, and also if the block ends | 98 // added before any branch instruction, and also if the block ends |
| 99 // with a compare instruction followed by a branch instruction that we | 99 // with a compare instruction followed by a branch instruction that we |
| 100 // may want to fuse, it's better to insert the new assignments before | 100 // may want to fuse, it's better to insert the new assignments before |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 } else { | 179 } else { |
| 180 ++InsertionPoint; | 180 ++InsertionPoint; |
| 181 } | 181 } |
| 182 } | 182 } |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 | 185 |
| 186 // Consider every out-edge. | 186 // Consider every out-edge. |
| 187 for (CfgNode *Succ : OutEdges) { | 187 for (CfgNode *Succ : OutEdges) { |
| 188 // Consider every Phi instruction at the out-edge. | 188 // Consider every Phi instruction at the out-edge. |
| 189 for (auto I = Succ->Phis.begin(), E = Succ->Phis.end(); I != E; ++I) { | 189 for (Inst &I : Succ->Phis) { |
| 190 auto Phi = llvm::dyn_cast<InstPhi>(I); | 190 auto Phi = llvm::dyn_cast<InstPhi>(&I); |
| 191 Operand *Operand = Phi->getOperandForTarget(this); | 191 Operand *Operand = Phi->getOperandForTarget(this); |
| 192 assert(Operand); | 192 assert(Operand); |
| 193 Variable *Dest = I->getDest(); | 193 Variable *Dest = I.getDest(); |
| 194 assert(Dest); | 194 assert(Dest); |
| 195 InstAssign *NewInst = InstAssign::create(Func, Dest, Operand); | 195 InstAssign *NewInst = InstAssign::create(Func, Dest, Operand); |
| 196 if (CmpInstDest == Operand) | 196 if (CmpInstDest == Operand) |
| 197 Insts.insert(SafeInsertionPoint, NewInst); | 197 Insts.insert(SafeInsertionPoint, NewInst); |
| 198 else | 198 else |
| 199 Insts.insert(InsertionPoint, NewInst); | 199 Insts.insert(InsertionPoint, NewInst); |
| 200 } | 200 } |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 // Deletes the phi instructions after the loads and stores are placed. | 204 // Deletes the phi instructions after the loads and stores are placed. |
| 205 void CfgNode::deletePhis() { | 205 void CfgNode::deletePhis() { |
| 206 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) | 206 for (Inst &I : Phis) |
| 207 I->setDeleted(); | 207 I.setDeleted(); |
| 208 } | 208 } |
| 209 | 209 |
| 210 // Splits the edge from Pred to this node by creating a new node and | 210 // Splits the edge from Pred to this node by creating a new node and |
| 211 // hooking up the in and out edges appropriately. (The EdgeIndex | 211 // hooking up the in and out edges appropriately. (The EdgeIndex |
| 212 // parameter is only used to make the new node's name unique when | 212 // parameter is only used to make the new node's name unique when |
| 213 // there are multiple edges between the same pair of nodes.) The new | 213 // there are multiple edges between the same pair of nodes.) The new |
| 214 // node's instruction list is initialized to the empty list, with no | 214 // node's instruction list is initialized to the empty list, with no |
| 215 // terminator instruction. If there are multiple edges from Pred to | 215 // terminator instruction. If there are multiple edges from Pred to |
| 216 // this node, only one edge is split, and the particular choice of | 216 // this node, only one edge is split, and the particular choice of |
| 217 // edge is undefined. This could happen with a switch instruction, or | 217 // edge is undefined. This could happen with a switch instruction, or |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 struct { | 312 struct { |
| 313 InstPhi *Phi; | 313 InstPhi *Phi; |
| 314 Variable *Dest; | 314 Variable *Dest; |
| 315 Operand *Src; | 315 Operand *Src; |
| 316 bool Processed; | 316 bool Processed; |
| 317 size_t NumPred; // number of entries whose Src is this Dest | 317 size_t NumPred; // number of entries whose Src is this Dest |
| 318 int32_t Weight; // preference for topological order | 318 int32_t Weight; // preference for topological order |
| 319 } Desc[getPhis().size()]; | 319 } Desc[getPhis().size()]; |
| 320 | 320 |
| 321 size_t NumPhis = 0; | 321 size_t NumPhis = 0; |
| 322 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 322 for (Inst &I : Phis) { |
| 323 auto Inst = llvm::dyn_cast<InstPhi>(I); | 323 auto Inst = llvm::dyn_cast<InstPhi>(&I); |
| 324 if (!Inst->isDeleted()) { | 324 if (!Inst->isDeleted()) { |
| 325 Desc[NumPhis].Phi = Inst; | 325 Desc[NumPhis].Phi = Inst; |
| 326 Desc[NumPhis].Dest = Inst->getDest(); | 326 Desc[NumPhis].Dest = Inst->getDest(); |
| 327 ++NumPhis; | 327 ++NumPhis; |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 if (NumPhis == 0) | 330 if (NumPhis == 0) |
| 331 return; | 331 return; |
| 332 | 332 |
| 333 SizeT InEdgeIndex = 0; | 333 SizeT InEdgeIndex = 0; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 | 468 |
| 469 Func->getTarget()->lowerPhiAssignments(Split, Assignments); | 469 Func->getTarget()->lowerPhiAssignments(Split, Assignments); |
| 470 | 470 |
| 471 // Renumber the instructions to be monotonically increasing so | 471 // Renumber the instructions to be monotonically increasing so |
| 472 // that addNode() doesn't assert when multi-definitions are added | 472 // that addNode() doesn't assert when multi-definitions are added |
| 473 // out of order. | 473 // out of order. |
| 474 Split->renumberInstructions(); | 474 Split->renumberInstructions(); |
| 475 Func->getVMetadata()->addNode(Split); | 475 Func->getVMetadata()->addNode(Split); |
| 476 } | 476 } |
| 477 | 477 |
| 478 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) | 478 for (Inst &I : Phis) |
| 479 I->setDeleted(); | 479 I.setDeleted(); |
| 480 } | 480 } |
| 481 | 481 |
| 482 // Does address mode optimization. Pass each instruction to the | 482 // Does address mode optimization. Pass each instruction to the |
| 483 // TargetLowering object. If it returns a new instruction | 483 // TargetLowering object. If it returns a new instruction |
| 484 // (representing the optimized address mode), then insert the new | 484 // (representing the optimized address mode), then insert the new |
| 485 // instruction and delete the old. | 485 // instruction and delete the old. |
| 486 void CfgNode::doAddressOpt() { | 486 void CfgNode::doAddressOpt() { |
| 487 TargetLowering *Target = Func->getTarget(); | 487 TargetLowering *Target = Func->getTarget(); |
| 488 LoweringContext &Context = Target->getContext(); | 488 LoweringContext &Context = Target->getContext(); |
| 489 Context.init(this); | 489 Context.init(this); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 void CfgNode::livenessLightweight() { | 532 void CfgNode::livenessLightweight() { |
| 533 SizeT NumVars = Func->getNumVariables(); | 533 SizeT NumVars = Func->getNumVariables(); |
| 534 LivenessBV Live(NumVars); | 534 LivenessBV Live(NumVars); |
| 535 // Process regular instructions in reverse order. | 535 // Process regular instructions in reverse order. |
| 536 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. | 536 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. |
| 537 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { | 537 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { |
| 538 if (I->isDeleted()) | 538 if (I->isDeleted()) |
| 539 continue; | 539 continue; |
| 540 I->livenessLightweight(Func, Live); | 540 I->livenessLightweight(Func, Live); |
| 541 } | 541 } |
| 542 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 542 for (Inst &I : Phis) { |
| 543 if (I->isDeleted()) | 543 if (I.isDeleted()) |
| 544 continue; | 544 continue; |
| 545 I->livenessLightweight(Func, Live); | 545 I.livenessLightweight(Func, Live); |
| 546 } | 546 } |
| 547 } | 547 } |
| 548 | 548 |
| 549 // Performs liveness analysis on the block. Returns true if the | 549 // Performs liveness analysis on the block. Returns true if the |
| 550 // incoming liveness changed from before, false if it stayed the same. | 550 // incoming liveness changed from before, false if it stayed the same. |
| 551 // (If it changes, the node's predecessors need to be processed | 551 // (If it changes, the node's predecessors need to be processed |
| 552 // again.) | 552 // again.) |
| 553 bool CfgNode::liveness(Liveness *Liveness) { | 553 bool CfgNode::liveness(Liveness *Liveness) { |
| 554 SizeT NumVars = Liveness->getNumVarsInNode(this); | 554 SizeT NumVars = Liveness->getNumVarsInNode(this); |
| 555 LivenessBV Live(NumVars); | 555 LivenessBV Live(NumVars); |
| 556 LiveBeginEndMap *LiveBegin = nullptr; | 556 LiveBeginEndMap *LiveBegin = nullptr; |
| 557 LiveBeginEndMap *LiveEnd = nullptr; | 557 LiveBeginEndMap *LiveEnd = nullptr; |
| 558 // Mark the beginning and ending of each variable's live range | 558 // Mark the beginning and ending of each variable's live range |
| 559 // with the sentinel instruction number 0. | 559 // with the sentinel instruction number 0. |
| 560 if (Liveness->getMode() == Liveness_Intervals) { | 560 if (Liveness->getMode() == Liveness_Intervals) { |
| 561 LiveBegin = Liveness->getLiveBegin(this); | 561 LiveBegin = Liveness->getLiveBegin(this); |
| 562 LiveEnd = Liveness->getLiveEnd(this); | 562 LiveEnd = Liveness->getLiveEnd(this); |
| 563 LiveBegin->clear(); | 563 LiveBegin->clear(); |
| 564 LiveEnd->clear(); | 564 LiveEnd->clear(); |
| 565 // Guess that the number of live ranges beginning is roughly the | 565 // Guess that the number of live ranges beginning is roughly the |
| 566 // number of instructions, and same for live ranges ending. | 566 // number of instructions, and same for live ranges ending. |
| 567 LiveBegin->reserve(getInstCountEstimate()); | 567 LiveBegin->reserve(getInstCountEstimate()); |
| 568 LiveEnd->reserve(getInstCountEstimate()); | 568 LiveEnd->reserve(getInstCountEstimate()); |
| 569 } | 569 } |
| 570 // Initialize Live to be the union of all successors' LiveIn. | 570 // Initialize Live to be the union of all successors' LiveIn. |
| 571 for (CfgNode *Succ : OutEdges) { | 571 for (CfgNode *Succ : OutEdges) { |
| 572 Live |= Liveness->getLiveIn(Succ); | 572 Live |= Liveness->getLiveIn(Succ); |
| 573 // Mark corresponding argument of phis in successor as live. | 573 // Mark corresponding argument of phis in successor as live. |
| 574 for (auto I = Succ->Phis.begin(), E = Succ->Phis.end(); I != E; ++I) { | 574 for (Inst &I : Succ->Phis) { |
| 575 auto Phi = llvm::dyn_cast<InstPhi>(I); | 575 auto Phi = llvm::dyn_cast<InstPhi>(&I); |
| 576 Phi->livenessPhiOperand(Live, this, Liveness); | 576 Phi->livenessPhiOperand(Live, this, Liveness); |
| 577 } | 577 } |
| 578 } | 578 } |
| 579 Liveness->getLiveOut(this) = Live; | 579 Liveness->getLiveOut(this) = Live; |
| 580 | 580 |
| 581 // Process regular instructions in reverse order. | 581 // Process regular instructions in reverse order. |
| 582 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { | 582 for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) { |
| 583 if (I->isDeleted()) | 583 if (I->isDeleted()) |
| 584 continue; | 584 continue; |
| 585 I->liveness(I->getNumber(), Live, Liveness, LiveBegin, LiveEnd); | 585 I->liveness(I->getNumber(), Live, Liveness, LiveBegin, LiveEnd); |
| 586 } | 586 } |
| 587 // Process phis in forward order so that we can override the | 587 // Process phis in forward order so that we can override the |
| 588 // instruction number to be that of the earliest phi instruction in | 588 // instruction number to be that of the earliest phi instruction in |
| 589 // the block. | 589 // the block. |
| 590 SizeT NumNonDeadPhis = 0; | 590 SizeT NumNonDeadPhis = 0; |
| 591 InstNumberT FirstPhiNumber = Inst::NumberSentinel; | 591 InstNumberT FirstPhiNumber = Inst::NumberSentinel; |
| 592 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 592 for (Inst &I : Phis) { |
| 593 if (I->isDeleted()) | 593 if (I.isDeleted()) |
| 594 continue; | 594 continue; |
| 595 if (FirstPhiNumber == Inst::NumberSentinel) | 595 if (FirstPhiNumber == Inst::NumberSentinel) |
| 596 FirstPhiNumber = I->getNumber(); | 596 FirstPhiNumber = I.getNumber(); |
| 597 if (I->liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd)) | 597 if (I.liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd)) |
| 598 ++NumNonDeadPhis; | 598 ++NumNonDeadPhis; |
| 599 } | 599 } |
| 600 | 600 |
| 601 // When using the sparse representation, after traversing the | 601 // When using the sparse representation, after traversing the |
| 602 // instructions in the block, the Live bitvector should only contain | 602 // instructions in the block, the Live bitvector should only contain |
| 603 // set bits for global variables upon block entry. We validate this | 603 // set bits for global variables upon block entry. We validate this |
| 604 // by shrinking the Live vector and then testing it against the | 604 // by shrinking the Live vector and then testing it against the |
| 605 // pre-shrunk version. (The shrinking is required, but the | 605 // pre-shrunk version. (The shrinking is required, but the |
| 606 // validation is not.) | 606 // validation is not.) |
| 607 LivenessBV LiveOrig = Live; | 607 LivenessBV LiveOrig = Live; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 } | 717 } |
| 718 } | 718 } |
| 719 | 719 |
| 720 // If this node contains only deleted instructions, and ends in an | 720 // If this node contains only deleted instructions, and ends in an |
| 721 // unconditional branch, contract the node by repointing all its | 721 // unconditional branch, contract the node by repointing all its |
| 722 // in-edges to its successor. | 722 // in-edges to its successor. |
| 723 void CfgNode::contractIfEmpty() { | 723 void CfgNode::contractIfEmpty() { |
| 724 if (InEdges.empty()) | 724 if (InEdges.empty()) |
| 725 return; | 725 return; |
| 726 Inst *Branch = nullptr; | 726 Inst *Branch = nullptr; |
| 727 for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) { | 727 for (Inst &I : Insts) { |
| 728 if (I->isDeleted()) | 728 if (I.isDeleted()) |
| 729 continue; | 729 continue; |
| 730 if (I->isUnconditionalBranch()) | 730 if (I.isUnconditionalBranch()) |
| 731 Branch = I; | 731 Branch = &I; |
| 732 else if (!I->isRedundantAssign()) | 732 else if (!I.isRedundantAssign()) |
| 733 return; | 733 return; |
| 734 } | 734 } |
| 735 Branch->setDeleted(); | 735 Branch->setDeleted(); |
| 736 assert(OutEdges.size() == 1); | 736 assert(OutEdges.size() == 1); |
| 737 // Repoint all this node's in-edges to this node's successor, unless | 737 // Repoint all this node's in-edges to this node's successor, unless |
| 738 // this node's successor is actually itself (in which case the | 738 // this node's successor is actually itself (in which case the |
| 739 // statement "OutEdges.front()->InEdges.push_back(Pred)" could | 739 // statement "OutEdges.front()->InEdges.push_back(Pred)" could |
| 740 // invalidate the iterator over this->InEdges). | 740 // invalidate the iterator over this->InEdges). |
| 741 if (OutEdges.front() != this) { | 741 if (OutEdges.front() != this) { |
| 742 for (CfgNode *Pred : InEdges) { | 742 for (CfgNode *Pred : InEdges) { |
| 743 for (auto I = Pred->OutEdges.begin(), E = Pred->OutEdges.end(); I != E; | 743 for (auto I = Pred->OutEdges.begin(), E = Pred->OutEdges.end(); I != E; |
| 744 ++I) { | 744 ++I) { |
| 745 if (*I == this) { | 745 if (*I == this) { |
| 746 *I = OutEdges.front(); | 746 *I = OutEdges.front(); |
| 747 OutEdges.front()->InEdges.push_back(Pred); | 747 OutEdges.front()->InEdges.push_back(Pred); |
| 748 } | 748 } |
| 749 } | 749 } |
| 750 for (auto I = Pred->getInsts().begin(), E = Pred->getInsts().end(); | 750 for (Inst &I : Pred->getInsts()) { |
| 751 I != E; ++I) { | 751 if (!I.isDeleted()) |
| 752 if (!I->isDeleted()) | 752 I.repointEdge(this, OutEdges.front()); |
| 753 I->repointEdge(this, OutEdges.front()); | |
| 754 } | 753 } |
| 755 } | 754 } |
| 756 } | 755 } |
| 757 InEdges.clear(); | 756 InEdges.clear(); |
| 758 // Don't bother removing the single out-edge, which would also | 757 // Don't bother removing the single out-edge, which would also |
| 759 // require finding the corresponding in-edge in the successor and | 758 // require finding the corresponding in-edge in the successor and |
| 760 // removing it. | 759 // removing it. |
| 761 } | 760 } |
| 762 | 761 |
| 763 void CfgNode::doBranchOpt(const CfgNode *NextNode) { | 762 void CfgNode::doBranchOpt(const CfgNode *NextNode) { |
| 764 TargetLowering *Target = Func->getTarget(); | 763 TargetLowering *Target = Func->getTarget(); |
| 765 // Check every instruction for a branch optimization opportunity. | 764 // Check every instruction for a branch optimization opportunity. |
| 766 // It may be more efficient to iterate in reverse and stop after the | 765 // It may be more efficient to iterate in reverse and stop after the |
| 767 // first opportunity, unless there is some target lowering where we | 766 // first opportunity, unless there is some target lowering where we |
| 768 // have the possibility of multiple such optimizations per block | 767 // have the possibility of multiple such optimizations per block |
| 769 // (currently not the case for x86 lowering). | 768 // (currently not the case for x86 lowering). |
| 770 for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) { | 769 for (Inst &I : Insts) { |
| 771 if (!I->isDeleted()) { | 770 if (!I.isDeleted()) { |
| 772 Target->doBranchOpt(I, NextNode); | 771 Target->doBranchOpt(&I, NextNode); |
| 773 } | 772 } |
| 774 } | 773 } |
| 775 } | 774 } |
| 776 | 775 |
| 777 // ======================== Dump routines ======================== // | 776 // ======================== Dump routines ======================== // |
| 778 | 777 |
| 779 namespace { | 778 namespace { |
| 780 | 779 |
| 781 // Helper functions for emit(). | 780 // Helper functions for emit(). |
| 782 | 781 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 return; | 864 return; |
| 866 Func->setCurrentNode(this); | 865 Func->setCurrentNode(this); |
| 867 Ostream &Str = Func->getContext()->getStrEmit(); | 866 Ostream &Str = Func->getContext()->getStrEmit(); |
| 868 Liveness *Liveness = Func->getLiveness(); | 867 Liveness *Liveness = Func->getLiveness(); |
| 869 bool DecorateAsm = Liveness && Func->getContext()->getFlags().DecorateAsm; | 868 bool DecorateAsm = Liveness && Func->getContext()->getFlags().DecorateAsm; |
| 870 Str << getAsmName() << ":\n"; | 869 Str << getAsmName() << ":\n"; |
| 871 std::vector<SizeT> LiveRegCount(Func->getTarget()->getNumRegisters()); | 870 std::vector<SizeT> LiveRegCount(Func->getTarget()->getNumRegisters()); |
| 872 if (DecorateAsm) | 871 if (DecorateAsm) |
| 873 emitRegisterUsage(Str, Func, this, true, LiveRegCount); | 872 emitRegisterUsage(Str, Func, this, true, LiveRegCount); |
| 874 | 873 |
| 875 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 874 for (const Inst &I : Phis) { |
| 876 if (I->isDeleted()) | 875 if (I.isDeleted()) |
| 877 continue; | 876 continue; |
| 878 // Emitting a Phi instruction should cause an error. | 877 // Emitting a Phi instruction should cause an error. |
| 879 I->emit(Func); | 878 I.emit(Func); |
| 880 } | 879 } |
| 881 for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) { | 880 for (const Inst &I : Insts) { |
| 882 if (I->isDeleted()) | 881 if (I.isDeleted()) |
| 883 continue; | 882 continue; |
| 884 if (I->isRedundantAssign()) { | 883 if (I.isRedundantAssign()) { |
| 885 Variable *Dest = I->getDest(); | 884 Variable *Dest = I.getDest(); |
| 886 if (DecorateAsm && Dest->hasReg() && !I->isLastUse(I->getSrc(0))) | 885 if (DecorateAsm && Dest->hasReg() && !I.isLastUse(I.getSrc(0))) |
| 887 ++LiveRegCount[Dest->getRegNum()]; | 886 ++LiveRegCount[Dest->getRegNum()]; |
| 888 continue; | 887 continue; |
| 889 } | 888 } |
| 890 I->emit(Func); | 889 I.emit(Func); |
| 891 if (DecorateAsm) | 890 if (DecorateAsm) |
| 892 emitLiveRangesEnded(Str, Func, I, LiveRegCount); | 891 emitLiveRangesEnded(Str, Func, &I, LiveRegCount); |
| 893 Str << "\n"; | 892 Str << "\n"; |
| 894 updateStats(Func, I); | 893 updateStats(Func, &I); |
| 895 } | 894 } |
| 896 if (DecorateAsm) | 895 if (DecorateAsm) |
| 897 emitRegisterUsage(Str, Func, this, false, LiveRegCount); | 896 emitRegisterUsage(Str, Func, this, false, LiveRegCount); |
| 898 } | 897 } |
| 899 | 898 |
| 900 void CfgNode::emitIAS(Cfg *Func) const { | 899 void CfgNode::emitIAS(Cfg *Func) const { |
| 901 Func->setCurrentNode(this); | 900 Func->setCurrentNode(this); |
| 902 Assembler *Asm = Func->getAssembler<Assembler>(); | 901 Assembler *Asm = Func->getAssembler<Assembler>(); |
| 903 Asm->BindCfgNodeLabel(getIndex()); | 902 Asm->BindCfgNodeLabel(getIndex()); |
| 904 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) { | 903 for (const Inst &I : Phis) { |
| 905 if (I->isDeleted()) | 904 if (I.isDeleted()) |
| 906 continue; | 905 continue; |
| 907 // Emitting a Phi instruction should cause an error. | 906 // Emitting a Phi instruction should cause an error. |
| 908 I->emitIAS(Func); | 907 I.emitIAS(Func); |
| 909 } | 908 } |
| 910 for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) { | 909 for (const Inst &I : Insts) { |
| 911 if (I->isDeleted()) | 910 if (I.isDeleted()) |
| 912 continue; | 911 continue; |
| 913 if (I->isRedundantAssign()) | 912 if (I.isRedundantAssign()) |
| 914 continue; | 913 continue; |
| 915 I->emitIAS(Func); | 914 I.emitIAS(Func); |
| 916 updateStats(Func, I); | 915 updateStats(Func, &I); |
| 917 } | 916 } |
| 918 } | 917 } |
| 919 | 918 |
| 920 void CfgNode::dump(Cfg *Func) const { | 919 void CfgNode::dump(Cfg *Func) const { |
| 921 if (!ALLOW_DUMP) | 920 if (!ALLOW_DUMP) |
| 922 return; | 921 return; |
| 923 Func->setCurrentNode(this); | 922 Func->setCurrentNode(this); |
| 924 Ostream &Str = Func->getContext()->getStrDump(); | 923 Ostream &Str = Func->getContext()->getStrDump(); |
| 925 Liveness *Liveness = Func->getLiveness(); | 924 Liveness *Liveness = Func->getLiveness(); |
| 926 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 925 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 951 if (Func->getContext()->isVerbose(IceV_RegOrigins) && Var->hasReg()) { | 950 if (Func->getContext()->isVerbose(IceV_RegOrigins) && Var->hasReg()) { |
| 952 Str << ":" << Func->getTarget()->getRegName(Var->getRegNum(), | 951 Str << ":" << Func->getTarget()->getRegName(Var->getRegNum(), |
| 953 Var->getType()); | 952 Var->getType()); |
| 954 } | 953 } |
| 955 } | 954 } |
| 956 } | 955 } |
| 957 Str << "\n"; | 956 Str << "\n"; |
| 958 } | 957 } |
| 959 // Dump each instruction. | 958 // Dump each instruction. |
| 960 if (Func->getContext()->isVerbose(IceV_Instructions)) { | 959 if (Func->getContext()->isVerbose(IceV_Instructions)) { |
| 961 for (auto I = Phis.begin(), E = Phis.end(); I != E; ++I) | 960 for (const Inst &I : Phis) |
| 962 I->dumpDecorated(Func); | 961 I.dumpDecorated(Func); |
| 963 for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) | 962 for (const Inst &I : Insts) |
| 964 I->dumpDecorated(Func); | 963 I.dumpDecorated(Func); |
| 965 } | 964 } |
| 966 // Dump the live-out variables. | 965 // Dump the live-out variables. |
| 967 LivenessBV LiveOut; | 966 LivenessBV LiveOut; |
| 968 if (Liveness) | 967 if (Liveness) |
| 969 LiveOut = Liveness->getLiveOut(this); | 968 LiveOut = Liveness->getLiveOut(this); |
| 970 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { | 969 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) { |
| 971 Str << " // LiveOut:"; | 970 Str << " // LiveOut:"; |
| 972 for (SizeT i = 0; i < LiveOut.size(); ++i) { | 971 for (SizeT i = 0; i < LiveOut.size(); ++i) { |
| 973 if (LiveOut[i]) { | 972 if (LiveOut[i]) { |
| 974 Variable *Var = Liveness->getVariable(i, this); | 973 Variable *Var = Liveness->getVariable(i, this); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 989 if (!First) | 988 if (!First) |
| 990 Str << ", "; | 989 Str << ", "; |
| 991 First = false; | 990 First = false; |
| 992 Str << "%" << I->getName(); | 991 Str << "%" << I->getName(); |
| 993 } | 992 } |
| 994 Str << "\n"; | 993 Str << "\n"; |
| 995 } | 994 } |
| 996 } | 995 } |
| 997 | 996 |
| 998 } // end of namespace Ice | 997 } // end of namespace Ice |
| OLD | NEW |