1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceCfgNode.cpp - Basic block (node) implementation -----===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Implements the CfgNode class, including the complexities of
12*03ce13f7SAndroid Build Coastguard Worker /// instruction insertion and in-edge calculation.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker
16*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
17*03ce13f7SAndroid Build Coastguard Worker
18*03ce13f7SAndroid Build Coastguard Worker #include "IceAssembler.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalInits.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceInstVarIter.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceLiveness.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h"
26*03ce13f7SAndroid Build Coastguard Worker
27*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
28*03ce13f7SAndroid Build Coastguard Worker
29*03ce13f7SAndroid Build Coastguard Worker // Adds an instruction to either the Phi list or the regular instruction list.
30*03ce13f7SAndroid Build Coastguard Worker // Validates that all Phis are added before all regular instructions.
appendInst(Inst * Instr)31*03ce13f7SAndroid Build Coastguard Worker void CfgNode::appendInst(Inst *Instr) {
32*03ce13f7SAndroid Build Coastguard Worker ++InstCountEstimate;
33*03ce13f7SAndroid Build Coastguard Worker
34*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::wasm()) {
35*03ce13f7SAndroid Build Coastguard Worker if (llvm::isa<InstSwitch>(Instr) || llvm::isa<InstBr>(Instr)) {
36*03ce13f7SAndroid Build Coastguard Worker for (auto *N : Instr->getTerminatorEdges()) {
37*03ce13f7SAndroid Build Coastguard Worker N->addInEdge(this);
38*03ce13f7SAndroid Build Coastguard Worker addOutEdge(N);
39*03ce13f7SAndroid Build Coastguard Worker }
40*03ce13f7SAndroid Build Coastguard Worker }
41*03ce13f7SAndroid Build Coastguard Worker }
42*03ce13f7SAndroid Build Coastguard Worker
43*03ce13f7SAndroid Build Coastguard Worker if (auto *Phi = llvm::dyn_cast<InstPhi>(Instr)) {
44*03ce13f7SAndroid Build Coastguard Worker if (!Insts.empty()) {
45*03ce13f7SAndroid Build Coastguard Worker Func->setError("Phi instruction added to the middle of a block");
46*03ce13f7SAndroid Build Coastguard Worker return;
47*03ce13f7SAndroid Build Coastguard Worker }
48*03ce13f7SAndroid Build Coastguard Worker Phis.push_back(Phi);
49*03ce13f7SAndroid Build Coastguard Worker } else {
50*03ce13f7SAndroid Build Coastguard Worker Insts.push_back(Instr);
51*03ce13f7SAndroid Build Coastguard Worker }
52*03ce13f7SAndroid Build Coastguard Worker }
53*03ce13f7SAndroid Build Coastguard Worker
replaceInEdge(CfgNode * Old,CfgNode * New)54*03ce13f7SAndroid Build Coastguard Worker void CfgNode::replaceInEdge(CfgNode *Old, CfgNode *New) {
55*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < InEdges.size(); ++i) {
56*03ce13f7SAndroid Build Coastguard Worker if (InEdges[i] == Old) {
57*03ce13f7SAndroid Build Coastguard Worker InEdges[i] = New;
58*03ce13f7SAndroid Build Coastguard Worker }
59*03ce13f7SAndroid Build Coastguard Worker }
60*03ce13f7SAndroid Build Coastguard Worker for (auto &Inst : getPhis()) {
61*03ce13f7SAndroid Build Coastguard Worker auto &Phi = llvm::cast<InstPhi>(Inst);
62*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Phi.getSrcSize(); ++i) {
63*03ce13f7SAndroid Build Coastguard Worker if (Phi.getLabel(i) == Old) {
64*03ce13f7SAndroid Build Coastguard Worker Phi.setLabel(i, New);
65*03ce13f7SAndroid Build Coastguard Worker }
66*03ce13f7SAndroid Build Coastguard Worker }
67*03ce13f7SAndroid Build Coastguard Worker }
68*03ce13f7SAndroid Build Coastguard Worker }
69*03ce13f7SAndroid Build Coastguard Worker
70*03ce13f7SAndroid Build Coastguard Worker namespace {
removeDeletedAndRenumber(List * L,Cfg * Func)71*03ce13f7SAndroid Build Coastguard Worker template <typename List> void removeDeletedAndRenumber(List *L, Cfg *Func) {
72*03ce13f7SAndroid Build Coastguard Worker const bool DoDelete =
73*03ce13f7SAndroid Build Coastguard Worker BuildDefs::minimal() || !getFlags().getKeepDeletedInsts();
74*03ce13f7SAndroid Build Coastguard Worker auto I = L->begin(), E = L->end(), Next = I;
75*03ce13f7SAndroid Build Coastguard Worker for (++Next; I != E; I = Next++) {
76*03ce13f7SAndroid Build Coastguard Worker if (DoDelete && I->isDeleted()) {
77*03ce13f7SAndroid Build Coastguard Worker L->remove(I);
78*03ce13f7SAndroid Build Coastguard Worker } else {
79*03ce13f7SAndroid Build Coastguard Worker I->renumber(Func);
80*03ce13f7SAndroid Build Coastguard Worker }
81*03ce13f7SAndroid Build Coastguard Worker }
82*03ce13f7SAndroid Build Coastguard Worker }
83*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
84*03ce13f7SAndroid Build Coastguard Worker
renumberInstructions()85*03ce13f7SAndroid Build Coastguard Worker void CfgNode::renumberInstructions() {
86*03ce13f7SAndroid Build Coastguard Worker InstNumberT FirstNumber = Func->getNextInstNumber();
87*03ce13f7SAndroid Build Coastguard Worker removeDeletedAndRenumber(&Phis, Func);
88*03ce13f7SAndroid Build Coastguard Worker removeDeletedAndRenumber(&Insts, Func);
89*03ce13f7SAndroid Build Coastguard Worker InstCountEstimate = Func->getNextInstNumber() - FirstNumber;
90*03ce13f7SAndroid Build Coastguard Worker }
91*03ce13f7SAndroid Build Coastguard Worker
92*03ce13f7SAndroid Build Coastguard Worker // When a node is created, the OutEdges are immediately known, but the InEdges
93*03ce13f7SAndroid Build Coastguard Worker // have to be built up incrementally. After the CFG has been constructed, the
94*03ce13f7SAndroid Build Coastguard Worker // computePredecessors() pass finalizes it by creating the InEdges list.
computePredecessors()95*03ce13f7SAndroid Build Coastguard Worker void CfgNode::computePredecessors() {
96*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Succ : OutEdges)
97*03ce13f7SAndroid Build Coastguard Worker Succ->InEdges.push_back(this);
98*03ce13f7SAndroid Build Coastguard Worker }
99*03ce13f7SAndroid Build Coastguard Worker
computeSuccessors()100*03ce13f7SAndroid Build Coastguard Worker void CfgNode::computeSuccessors() {
101*03ce13f7SAndroid Build Coastguard Worker OutEdges.clear();
102*03ce13f7SAndroid Build Coastguard Worker InEdges.clear();
103*03ce13f7SAndroid Build Coastguard Worker assert(!Insts.empty());
104*03ce13f7SAndroid Build Coastguard Worker OutEdges = Insts.rbegin()->getTerminatorEdges();
105*03ce13f7SAndroid Build Coastguard Worker }
106*03ce13f7SAndroid Build Coastguard Worker
107*03ce13f7SAndroid Build Coastguard Worker // Ensure each Phi instruction in the node is consistent with respect to control
108*03ce13f7SAndroid Build Coastguard Worker // flow. For each predecessor, there must be a phi argument with that label.
109*03ce13f7SAndroid Build Coastguard Worker // If a phi argument's label doesn't appear in the predecessor list (which can
110*03ce13f7SAndroid Build Coastguard Worker // happen as a result of e.g. unreachable node elimination), its value is
111*03ce13f7SAndroid Build Coastguard Worker // modified to be zero, to maintain consistency in liveness analysis. This
112*03ce13f7SAndroid Build Coastguard Worker // allows us to remove some dead control flow without a major rework of the phi
113*03ce13f7SAndroid Build Coastguard Worker // instructions. We don't check that phi arguments with the same label have the
114*03ce13f7SAndroid Build Coastguard Worker // same value.
enforcePhiConsistency()115*03ce13f7SAndroid Build Coastguard Worker void CfgNode::enforcePhiConsistency() {
116*03ce13f7SAndroid Build Coastguard Worker for (Inst &Instr : Phis) {
117*03ce13f7SAndroid Build Coastguard Worker auto *Phi = llvm::cast<InstPhi>(&Instr);
118*03ce13f7SAndroid Build Coastguard Worker // We do a simple O(N^2) algorithm to check for consistency. Even so, it
119*03ce13f7SAndroid Build Coastguard Worker // shows up as only about 0.2% of the total translation time. But if
120*03ce13f7SAndroid Build Coastguard Worker // necessary, we could improve the complexity by using a hash table to
121*03ce13f7SAndroid Build Coastguard Worker // count how many times each node is referenced in the Phi instruction, and
122*03ce13f7SAndroid Build Coastguard Worker // how many times each node is referenced in the incoming edge list, and
123*03ce13f7SAndroid Build Coastguard Worker // compare the two for equality.
124*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Phi->getSrcSize(); ++i) {
125*03ce13f7SAndroid Build Coastguard Worker CfgNode *Label = Phi->getLabel(i);
126*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
127*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *InNode : getInEdges()) {
128*03ce13f7SAndroid Build Coastguard Worker if (InNode == Label) {
129*03ce13f7SAndroid Build Coastguard Worker Found = true;
130*03ce13f7SAndroid Build Coastguard Worker break;
131*03ce13f7SAndroid Build Coastguard Worker }
132*03ce13f7SAndroid Build Coastguard Worker }
133*03ce13f7SAndroid Build Coastguard Worker if (!Found) {
134*03ce13f7SAndroid Build Coastguard Worker // Predecessor was unreachable, so if (impossibly) the control flow
135*03ce13f7SAndroid Build Coastguard Worker // enters from that predecessor, the value should be zero.
136*03ce13f7SAndroid Build Coastguard Worker Phi->clearOperandForTarget(Label);
137*03ce13f7SAndroid Build Coastguard Worker }
138*03ce13f7SAndroid Build Coastguard Worker }
139*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *InNode : getInEdges()) {
140*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
141*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Phi->getSrcSize(); ++i) {
142*03ce13f7SAndroid Build Coastguard Worker CfgNode *Label = Phi->getLabel(i);
143*03ce13f7SAndroid Build Coastguard Worker if (InNode == Label) {
144*03ce13f7SAndroid Build Coastguard Worker Found = true;
145*03ce13f7SAndroid Build Coastguard Worker break;
146*03ce13f7SAndroid Build Coastguard Worker }
147*03ce13f7SAndroid Build Coastguard Worker }
148*03ce13f7SAndroid Build Coastguard Worker if (!Found)
149*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Phi error: missing label for incoming edge");
150*03ce13f7SAndroid Build Coastguard Worker }
151*03ce13f7SAndroid Build Coastguard Worker }
152*03ce13f7SAndroid Build Coastguard Worker }
153*03ce13f7SAndroid Build Coastguard Worker
154*03ce13f7SAndroid Build Coastguard Worker // This does part 1 of Phi lowering, by creating a new dest variable for each
155*03ce13f7SAndroid Build Coastguard Worker // Phi instruction, replacing the Phi instruction's dest with that variable,
156*03ce13f7SAndroid Build Coastguard Worker // and adding an explicit assignment of the old dest to the new dest. For
157*03ce13f7SAndroid Build Coastguard Worker // example,
158*03ce13f7SAndroid Build Coastguard Worker // a=phi(...)
159*03ce13f7SAndroid Build Coastguard Worker // changes to
160*03ce13f7SAndroid Build Coastguard Worker // "a_phi=phi(...); a=a_phi".
161*03ce13f7SAndroid Build Coastguard Worker //
162*03ce13f7SAndroid Build Coastguard Worker // This is in preparation for part 2 which deletes the Phi instructions and
163*03ce13f7SAndroid Build Coastguard Worker // appends assignment instructions to predecessor blocks. Note that this
164*03ce13f7SAndroid Build Coastguard Worker // transformation preserves SSA form.
placePhiLoads()165*03ce13f7SAndroid Build Coastguard Worker void CfgNode::placePhiLoads() {
166*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Phis) {
167*03ce13f7SAndroid Build Coastguard Worker auto *Phi = llvm::dyn_cast<InstPhi>(&I);
168*03ce13f7SAndroid Build Coastguard Worker Insts.insert(Insts.begin(), Phi->lower(Func));
169*03ce13f7SAndroid Build Coastguard Worker }
170*03ce13f7SAndroid Build Coastguard Worker }
171*03ce13f7SAndroid Build Coastguard Worker
172*03ce13f7SAndroid Build Coastguard Worker // This does part 2 of Phi lowering. For each Phi instruction at each out-edge,
173*03ce13f7SAndroid Build Coastguard Worker // create a corresponding assignment instruction, and add all the assignments
174*03ce13f7SAndroid Build Coastguard Worker // near the end of this block. They need to be added before any branch
175*03ce13f7SAndroid Build Coastguard Worker // instruction, and also if the block ends with a compare instruction followed
176*03ce13f7SAndroid Build Coastguard Worker // by a branch instruction that we may want to fuse, it's better to insert the
177*03ce13f7SAndroid Build Coastguard Worker // new assignments before the compare instruction. The
178*03ce13f7SAndroid Build Coastguard Worker // tryOptimizedCmpxchgCmpBr() method assumes this ordering of instructions.
179*03ce13f7SAndroid Build Coastguard Worker //
180*03ce13f7SAndroid Build Coastguard Worker // Note that this transformation takes the Phi dest variables out of SSA form,
181*03ce13f7SAndroid Build Coastguard Worker // as there may be assignments to the dest variable in multiple blocks.
placePhiStores()182*03ce13f7SAndroid Build Coastguard Worker void CfgNode::placePhiStores() {
183*03ce13f7SAndroid Build Coastguard Worker // Find the insertion point.
184*03ce13f7SAndroid Build Coastguard Worker InstList::iterator InsertionPoint = Insts.end();
185*03ce13f7SAndroid Build Coastguard Worker // Every block must end in a terminator instruction, and therefore must have
186*03ce13f7SAndroid Build Coastguard Worker // at least one instruction, so it's valid to decrement InsertionPoint (but
187*03ce13f7SAndroid Build Coastguard Worker // assert just in case).
188*03ce13f7SAndroid Build Coastguard Worker assert(InsertionPoint != Insts.begin());
189*03ce13f7SAndroid Build Coastguard Worker --InsertionPoint;
190*03ce13f7SAndroid Build Coastguard Worker // Confirm that InsertionPoint is a terminator instruction. Calling
191*03ce13f7SAndroid Build Coastguard Worker // getTerminatorEdges() on a non-terminator instruction will cause an
192*03ce13f7SAndroid Build Coastguard Worker // llvm_unreachable().
193*03ce13f7SAndroid Build Coastguard Worker (void)InsertionPoint->getTerminatorEdges();
194*03ce13f7SAndroid Build Coastguard Worker // SafeInsertionPoint is always immediately before the terminator
195*03ce13f7SAndroid Build Coastguard Worker // instruction. If the block ends in a compare and conditional branch, it's
196*03ce13f7SAndroid Build Coastguard Worker // better to place the Phi store before the compare so as not to interfere
197*03ce13f7SAndroid Build Coastguard Worker // with compare/branch fusing. However, if the compare instruction's dest
198*03ce13f7SAndroid Build Coastguard Worker // operand is the same as the new assignment statement's source operand, this
199*03ce13f7SAndroid Build Coastguard Worker // can't be done due to data dependences, so we need to fall back to the
200*03ce13f7SAndroid Build Coastguard Worker // SafeInsertionPoint. To illustrate:
201*03ce13f7SAndroid Build Coastguard Worker // ; <label>:95
202*03ce13f7SAndroid Build Coastguard Worker // %97 = load i8* %96, align 1
203*03ce13f7SAndroid Build Coastguard Worker // %98 = icmp ne i8 %97, 0
204*03ce13f7SAndroid Build Coastguard Worker // br i1 %98, label %99, label %2132
205*03ce13f7SAndroid Build Coastguard Worker // ; <label>:99
206*03ce13f7SAndroid Build Coastguard Worker // %100 = phi i8 [ %97, %95 ], [ %110, %108 ]
207*03ce13f7SAndroid Build Coastguard Worker // %101 = phi i1 [ %98, %95 ], [ %111, %108 ]
208*03ce13f7SAndroid Build Coastguard Worker // would be Phi-lowered as:
209*03ce13f7SAndroid Build Coastguard Worker // ; <label>:95
210*03ce13f7SAndroid Build Coastguard Worker // %97 = load i8* %96, align 1
211*03ce13f7SAndroid Build Coastguard Worker // %100_phi = %97 ; can be at InsertionPoint
212*03ce13f7SAndroid Build Coastguard Worker // %98 = icmp ne i8 %97, 0
213*03ce13f7SAndroid Build Coastguard Worker // %101_phi = %98 ; must be at SafeInsertionPoint
214*03ce13f7SAndroid Build Coastguard Worker // br i1 %98, label %99, label %2132
215*03ce13f7SAndroid Build Coastguard Worker // ; <label>:99
216*03ce13f7SAndroid Build Coastguard Worker // %100 = %100_phi
217*03ce13f7SAndroid Build Coastguard Worker // %101 = %101_phi
218*03ce13f7SAndroid Build Coastguard Worker //
219*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): It may be possible to bypass this whole SafeInsertionPoint
220*03ce13f7SAndroid Build Coastguard Worker // mechanism. If a source basic block ends in a conditional branch:
221*03ce13f7SAndroid Build Coastguard Worker // labelSource:
222*03ce13f7SAndroid Build Coastguard Worker // ...
223*03ce13f7SAndroid Build Coastguard Worker // br i1 %foo, label %labelTrue, label %labelFalse
224*03ce13f7SAndroid Build Coastguard Worker // and a branch target has a Phi involving the branch operand:
225*03ce13f7SAndroid Build Coastguard Worker // labelTrue:
226*03ce13f7SAndroid Build Coastguard Worker // %bar = phi i1 [ %foo, %labelSource ], ...
227*03ce13f7SAndroid Build Coastguard Worker // then we actually know the constant i1 value of the Phi operand:
228*03ce13f7SAndroid Build Coastguard Worker // labelTrue:
229*03ce13f7SAndroid Build Coastguard Worker // %bar = phi i1 [ true, %labelSource ], ...
230*03ce13f7SAndroid Build Coastguard Worker // It seems that this optimization should be done by clang or opt, but we
231*03ce13f7SAndroid Build Coastguard Worker // could also do it here.
232*03ce13f7SAndroid Build Coastguard Worker InstList::iterator SafeInsertionPoint = InsertionPoint;
233*03ce13f7SAndroid Build Coastguard Worker // Keep track of the dest variable of a compare instruction, so that we
234*03ce13f7SAndroid Build Coastguard Worker // insert the new instruction at the SafeInsertionPoint if the compare's dest
235*03ce13f7SAndroid Build Coastguard Worker // matches the Phi-lowered assignment's source.
236*03ce13f7SAndroid Build Coastguard Worker Variable *CmpInstDest = nullptr;
237*03ce13f7SAndroid Build Coastguard Worker // If the current insertion point is at a conditional branch instruction, and
238*03ce13f7SAndroid Build Coastguard Worker // the previous instruction is a compare instruction, then we move the
239*03ce13f7SAndroid Build Coastguard Worker // insertion point before the compare instruction so as not to interfere with
240*03ce13f7SAndroid Build Coastguard Worker // compare/branch fusing.
241*03ce13f7SAndroid Build Coastguard Worker if (auto *Branch = llvm::dyn_cast<InstBr>(InsertionPoint)) {
242*03ce13f7SAndroid Build Coastguard Worker if (!Branch->isUnconditional()) {
243*03ce13f7SAndroid Build Coastguard Worker if (InsertionPoint != Insts.begin()) {
244*03ce13f7SAndroid Build Coastguard Worker --InsertionPoint;
245*03ce13f7SAndroid Build Coastguard Worker if (llvm::isa<InstIcmp>(InsertionPoint) ||
246*03ce13f7SAndroid Build Coastguard Worker llvm::isa<InstFcmp>(InsertionPoint)) {
247*03ce13f7SAndroid Build Coastguard Worker CmpInstDest = InsertionPoint->getDest();
248*03ce13f7SAndroid Build Coastguard Worker } else {
249*03ce13f7SAndroid Build Coastguard Worker ++InsertionPoint;
250*03ce13f7SAndroid Build Coastguard Worker }
251*03ce13f7SAndroid Build Coastguard Worker }
252*03ce13f7SAndroid Build Coastguard Worker }
253*03ce13f7SAndroid Build Coastguard Worker }
254*03ce13f7SAndroid Build Coastguard Worker
255*03ce13f7SAndroid Build Coastguard Worker // Consider every out-edge.
256*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Succ : OutEdges) {
257*03ce13f7SAndroid Build Coastguard Worker // Consider every Phi instruction at the out-edge.
258*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Succ->Phis) {
259*03ce13f7SAndroid Build Coastguard Worker auto *Phi = llvm::dyn_cast<InstPhi>(&I);
260*03ce13f7SAndroid Build Coastguard Worker Operand *Operand = Phi->getOperandForTarget(this);
261*03ce13f7SAndroid Build Coastguard Worker assert(Operand);
262*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = I.getDest();
263*03ce13f7SAndroid Build Coastguard Worker assert(Dest);
264*03ce13f7SAndroid Build Coastguard Worker auto *NewInst = InstAssign::create(Func, Dest, Operand);
265*03ce13f7SAndroid Build Coastguard Worker if (CmpInstDest == Operand)
266*03ce13f7SAndroid Build Coastguard Worker Insts.insert(SafeInsertionPoint, NewInst);
267*03ce13f7SAndroid Build Coastguard Worker else
268*03ce13f7SAndroid Build Coastguard Worker Insts.insert(InsertionPoint, NewInst);
269*03ce13f7SAndroid Build Coastguard Worker }
270*03ce13f7SAndroid Build Coastguard Worker }
271*03ce13f7SAndroid Build Coastguard Worker }
272*03ce13f7SAndroid Build Coastguard Worker
273*03ce13f7SAndroid Build Coastguard Worker // Deletes the phi instructions after the loads and stores are placed.
deletePhis()274*03ce13f7SAndroid Build Coastguard Worker void CfgNode::deletePhis() {
275*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Phis)
276*03ce13f7SAndroid Build Coastguard Worker I.setDeleted();
277*03ce13f7SAndroid Build Coastguard Worker }
278*03ce13f7SAndroid Build Coastguard Worker
279*03ce13f7SAndroid Build Coastguard Worker // Splits the edge from Pred to this node by creating a new node and hooking up
280*03ce13f7SAndroid Build Coastguard Worker // the in and out edges appropriately. (The EdgeIndex parameter is only used to
281*03ce13f7SAndroid Build Coastguard Worker // make the new node's name unique when there are multiple edges between the
282*03ce13f7SAndroid Build Coastguard Worker // same pair of nodes.) The new node's instruction list is initialized to the
283*03ce13f7SAndroid Build Coastguard Worker // empty list, with no terminator instruction. There must not be multiple edges
284*03ce13f7SAndroid Build Coastguard Worker // from Pred to this node so all Inst::getTerminatorEdges implementations must
285*03ce13f7SAndroid Build Coastguard Worker // not contain duplicates.
splitIncomingEdge(CfgNode * Pred,SizeT EdgeIndex)286*03ce13f7SAndroid Build Coastguard Worker CfgNode *CfgNode::splitIncomingEdge(CfgNode *Pred, SizeT EdgeIndex) {
287*03ce13f7SAndroid Build Coastguard Worker CfgNode *NewNode = Func->makeNode();
288*03ce13f7SAndroid Build Coastguard Worker // Depth is the minimum as it works if both are the same, but if one is
289*03ce13f7SAndroid Build Coastguard Worker // outside the loop and the other is inside, the new node should be placed
290*03ce13f7SAndroid Build Coastguard Worker // outside and not be executed multiple times within the loop.
291*03ce13f7SAndroid Build Coastguard Worker NewNode->setLoopNestDepth(
292*03ce13f7SAndroid Build Coastguard Worker std::min(getLoopNestDepth(), Pred->getLoopNestDepth()));
293*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump())
294*03ce13f7SAndroid Build Coastguard Worker NewNode->setName("split_" + Pred->getName() + "_" + getName() + "_" +
295*03ce13f7SAndroid Build Coastguard Worker std::to_string(EdgeIndex));
296*03ce13f7SAndroid Build Coastguard Worker // The new node is added to the end of the node list, and will later need to
297*03ce13f7SAndroid Build Coastguard Worker // be sorted into a reasonable topological order.
298*03ce13f7SAndroid Build Coastguard Worker NewNode->setNeedsPlacement(true);
299*03ce13f7SAndroid Build Coastguard Worker // Repoint Pred's out-edge.
300*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
301*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *&I : Pred->OutEdges) {
302*03ce13f7SAndroid Build Coastguard Worker if (I == this) {
303*03ce13f7SAndroid Build Coastguard Worker I = NewNode;
304*03ce13f7SAndroid Build Coastguard Worker NewNode->InEdges.push_back(Pred);
305*03ce13f7SAndroid Build Coastguard Worker Found = true;
306*03ce13f7SAndroid Build Coastguard Worker break;
307*03ce13f7SAndroid Build Coastguard Worker }
308*03ce13f7SAndroid Build Coastguard Worker }
309*03ce13f7SAndroid Build Coastguard Worker assert(Found);
310*03ce13f7SAndroid Build Coastguard Worker (void)Found;
311*03ce13f7SAndroid Build Coastguard Worker // Repoint this node's in-edge.
312*03ce13f7SAndroid Build Coastguard Worker Found = false;
313*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *&I : InEdges) {
314*03ce13f7SAndroid Build Coastguard Worker if (I == Pred) {
315*03ce13f7SAndroid Build Coastguard Worker I = NewNode;
316*03ce13f7SAndroid Build Coastguard Worker NewNode->OutEdges.push_back(this);
317*03ce13f7SAndroid Build Coastguard Worker Found = true;
318*03ce13f7SAndroid Build Coastguard Worker break;
319*03ce13f7SAndroid Build Coastguard Worker }
320*03ce13f7SAndroid Build Coastguard Worker }
321*03ce13f7SAndroid Build Coastguard Worker assert(Found);
322*03ce13f7SAndroid Build Coastguard Worker (void)Found;
323*03ce13f7SAndroid Build Coastguard Worker // Repoint all suitable branch instructions' target and return.
324*03ce13f7SAndroid Build Coastguard Worker Found = false;
325*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Pred->getInsts())
326*03ce13f7SAndroid Build Coastguard Worker if (!I.isDeleted() && I.repointEdges(this, NewNode))
327*03ce13f7SAndroid Build Coastguard Worker Found = true;
328*03ce13f7SAndroid Build Coastguard Worker assert(Found);
329*03ce13f7SAndroid Build Coastguard Worker (void)Found;
330*03ce13f7SAndroid Build Coastguard Worker return NewNode;
331*03ce13f7SAndroid Build Coastguard Worker }
332*03ce13f7SAndroid Build Coastguard Worker
333*03ce13f7SAndroid Build Coastguard Worker namespace {
334*03ce13f7SAndroid Build Coastguard Worker
335*03ce13f7SAndroid Build Coastguard Worker // Helpers for advancedPhiLowering().
336*03ce13f7SAndroid Build Coastguard Worker
337*03ce13f7SAndroid Build Coastguard Worker class PhiDesc {
338*03ce13f7SAndroid Build Coastguard Worker PhiDesc() = delete;
339*03ce13f7SAndroid Build Coastguard Worker PhiDesc(const PhiDesc &) = delete;
340*03ce13f7SAndroid Build Coastguard Worker PhiDesc &operator=(const PhiDesc &) = delete;
341*03ce13f7SAndroid Build Coastguard Worker
342*03ce13f7SAndroid Build Coastguard Worker public:
PhiDesc(InstPhi * Phi,Variable * Dest)343*03ce13f7SAndroid Build Coastguard Worker PhiDesc(InstPhi *Phi, Variable *Dest) : Phi(Phi), Dest(Dest) {}
344*03ce13f7SAndroid Build Coastguard Worker PhiDesc(PhiDesc &&) = default;
345*03ce13f7SAndroid Build Coastguard Worker InstPhi *Phi = nullptr;
346*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = nullptr;
347*03ce13f7SAndroid Build Coastguard Worker Operand *Src = nullptr;
348*03ce13f7SAndroid Build Coastguard Worker bool Processed = false;
349*03ce13f7SAndroid Build Coastguard Worker size_t NumPred = 0; // number of entries whose Src is this Dest
350*03ce13f7SAndroid Build Coastguard Worker int32_t Weight = 0; // preference for topological order
351*03ce13f7SAndroid Build Coastguard Worker };
352*03ce13f7SAndroid Build Coastguard Worker using PhiDescList = llvm::SmallVector<PhiDesc, 32>;
353*03ce13f7SAndroid Build Coastguard Worker
354*03ce13f7SAndroid Build Coastguard Worker // Always pick NumPred=0 over NumPred>0.
355*03ce13f7SAndroid Build Coastguard Worker constexpr int32_t WeightNoPreds = 8;
356*03ce13f7SAndroid Build Coastguard Worker // Prefer Src as a register because the register might free up.
357*03ce13f7SAndroid Build Coastguard Worker constexpr int32_t WeightSrcIsReg = 4;
358*03ce13f7SAndroid Build Coastguard Worker // Prefer Dest not as a register because the register stays free longer.
359*03ce13f7SAndroid Build Coastguard Worker constexpr int32_t WeightDestNotReg = 2;
360*03ce13f7SAndroid Build Coastguard Worker // Prefer NumPred=1 over NumPred>1. This is used as a tiebreaker when a
361*03ce13f7SAndroid Build Coastguard Worker // dependency cycle must be broken so that hopefully only one temporary
362*03ce13f7SAndroid Build Coastguard Worker // assignment has to be added to break the cycle.
363*03ce13f7SAndroid Build Coastguard Worker constexpr int32_t WeightOnePred = 1;
364*03ce13f7SAndroid Build Coastguard Worker
sameVarOrReg(TargetLowering * Target,const Variable * Var1,const Operand * Opnd)365*03ce13f7SAndroid Build Coastguard Worker bool sameVarOrReg(TargetLowering *Target, const Variable *Var1,
366*03ce13f7SAndroid Build Coastguard Worker const Operand *Opnd) {
367*03ce13f7SAndroid Build Coastguard Worker if (Var1 == Opnd)
368*03ce13f7SAndroid Build Coastguard Worker return true;
369*03ce13f7SAndroid Build Coastguard Worker const auto *Var2 = llvm::dyn_cast<Variable>(Opnd);
370*03ce13f7SAndroid Build Coastguard Worker if (Var2 == nullptr)
371*03ce13f7SAndroid Build Coastguard Worker return false;
372*03ce13f7SAndroid Build Coastguard Worker
373*03ce13f7SAndroid Build Coastguard Worker // If either operand lacks a register, they cannot be the same.
374*03ce13f7SAndroid Build Coastguard Worker if (!Var1->hasReg())
375*03ce13f7SAndroid Build Coastguard Worker return false;
376*03ce13f7SAndroid Build Coastguard Worker if (!Var2->hasReg())
377*03ce13f7SAndroid Build Coastguard Worker return false;
378*03ce13f7SAndroid Build Coastguard Worker
379*03ce13f7SAndroid Build Coastguard Worker const auto RegNum1 = Var1->getRegNum();
380*03ce13f7SAndroid Build Coastguard Worker const auto RegNum2 = Var2->getRegNum();
381*03ce13f7SAndroid Build Coastguard Worker // Quick common-case check.
382*03ce13f7SAndroid Build Coastguard Worker if (RegNum1 == RegNum2)
383*03ce13f7SAndroid Build Coastguard Worker return true;
384*03ce13f7SAndroid Build Coastguard Worker
385*03ce13f7SAndroid Build Coastguard Worker assert(Target->getAliasesForRegister(RegNum1)[RegNum2] ==
386*03ce13f7SAndroid Build Coastguard Worker Target->getAliasesForRegister(RegNum2)[RegNum1]);
387*03ce13f7SAndroid Build Coastguard Worker return Target->getAliasesForRegister(RegNum1)[RegNum2];
388*03ce13f7SAndroid Build Coastguard Worker }
389*03ce13f7SAndroid Build Coastguard Worker
390*03ce13f7SAndroid Build Coastguard Worker // Update NumPred for all Phi assignments using Var as their Dest variable.
391*03ce13f7SAndroid Build Coastguard Worker // Also update Weight if NumPred dropped from 2 to 1, or 1 to 0.
updatePreds(PhiDescList & Desc,TargetLowering * Target,Variable * Var)392*03ce13f7SAndroid Build Coastguard Worker void updatePreds(PhiDescList &Desc, TargetLowering *Target, Variable *Var) {
393*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
394*03ce13f7SAndroid Build Coastguard Worker if (!Item.Processed && sameVarOrReg(Target, Var, Item.Dest)) {
395*03ce13f7SAndroid Build Coastguard Worker --Item.NumPred;
396*03ce13f7SAndroid Build Coastguard Worker if (Item.NumPred == 1) {
397*03ce13f7SAndroid Build Coastguard Worker // If NumPred changed from 2 to 1, add in WeightOnePred.
398*03ce13f7SAndroid Build Coastguard Worker Item.Weight += WeightOnePred;
399*03ce13f7SAndroid Build Coastguard Worker } else if (Item.NumPred == 0) {
400*03ce13f7SAndroid Build Coastguard Worker // If NumPred changed from 1 to 0, subtract WeightOnePred and add in
401*03ce13f7SAndroid Build Coastguard Worker // WeightNoPreds.
402*03ce13f7SAndroid Build Coastguard Worker Item.Weight += (WeightNoPreds - WeightOnePred);
403*03ce13f7SAndroid Build Coastguard Worker }
404*03ce13f7SAndroid Build Coastguard Worker }
405*03ce13f7SAndroid Build Coastguard Worker }
406*03ce13f7SAndroid Build Coastguard Worker }
407*03ce13f7SAndroid Build Coastguard Worker
408*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
409*03ce13f7SAndroid Build Coastguard Worker
410*03ce13f7SAndroid Build Coastguard Worker // This the "advanced" version of Phi lowering for a basic block, in contrast
411*03ce13f7SAndroid Build Coastguard Worker // to the simple version that lowers through assignments involving temporaries.
412*03ce13f7SAndroid Build Coastguard Worker //
413*03ce13f7SAndroid Build Coastguard Worker // All Phi instructions in a basic block are conceptually executed in parallel.
414*03ce13f7SAndroid Build Coastguard Worker // However, if we lower Phis early and commit to a sequential ordering, we may
415*03ce13f7SAndroid Build Coastguard Worker // end up creating unnecessary interferences which lead to worse register
416*03ce13f7SAndroid Build Coastguard Worker // allocation. Delaying Phi scheduling until after register allocation can help
417*03ce13f7SAndroid Build Coastguard Worker // unless there are no free registers for shuffling registers or stack slots
418*03ce13f7SAndroid Build Coastguard Worker // and spilling becomes necessary.
419*03ce13f7SAndroid Build Coastguard Worker //
420*03ce13f7SAndroid Build Coastguard Worker // The advanced Phi lowering starts by finding a topological sort of the Phi
421*03ce13f7SAndroid Build Coastguard Worker // instructions, where "A=B" comes before "B=C" due to the anti-dependence on
422*03ce13f7SAndroid Build Coastguard Worker // B. Preexisting register assignments are considered in the topological sort.
423*03ce13f7SAndroid Build Coastguard Worker // If a topological sort is not possible due to a cycle, the cycle is broken by
424*03ce13f7SAndroid Build Coastguard Worker // introducing a non-parallel temporary. For example, a cycle arising from a
425*03ce13f7SAndroid Build Coastguard Worker // permutation like "A=B;B=C;C=A" can become "T=A;A=B;B=C;C=T". All else being
426*03ce13f7SAndroid Build Coastguard Worker // equal, prefer to schedule assignments with register-allocated Src operands
427*03ce13f7SAndroid Build Coastguard Worker // earlier, in case that register becomes free afterwards, and prefer to
428*03ce13f7SAndroid Build Coastguard Worker // schedule assignments with register-allocated Dest variables later, to keep
429*03ce13f7SAndroid Build Coastguard Worker // that register free for longer.
430*03ce13f7SAndroid Build Coastguard Worker //
431*03ce13f7SAndroid Build Coastguard Worker // Once the ordering is determined, the Cfg edge is split and the assignment
432*03ce13f7SAndroid Build Coastguard Worker // list is lowered by the target lowering layer. Since the assignment lowering
433*03ce13f7SAndroid Build Coastguard Worker // may create new infinite-weight temporaries, a follow-on register allocation
434*03ce13f7SAndroid Build Coastguard Worker // pass will be needed. To prepare for this, liveness (including live range
435*03ce13f7SAndroid Build Coastguard Worker // calculation) of the split nodes needs to be calculated, and liveness of the
436*03ce13f7SAndroid Build Coastguard Worker // original node need to be updated to "undo" the effects of the phi
437*03ce13f7SAndroid Build Coastguard Worker // assignments.
438*03ce13f7SAndroid Build Coastguard Worker
439*03ce13f7SAndroid Build Coastguard Worker // The specific placement of the new node within the Cfg node list is deferred
440*03ce13f7SAndroid Build Coastguard Worker // until later, including after empty node contraction.
441*03ce13f7SAndroid Build Coastguard Worker //
442*03ce13f7SAndroid Build Coastguard Worker // After phi assignments are lowered across all blocks, another register
443*03ce13f7SAndroid Build Coastguard Worker // allocation pass is run, focusing only on pre-colored and infinite-weight
444*03ce13f7SAndroid Build Coastguard Worker // variables, similar to Om1 register allocation (except without the need to
445*03ce13f7SAndroid Build Coastguard Worker // specially compute these variables' live ranges, since they have already been
446*03ce13f7SAndroid Build Coastguard Worker // precisely calculated). The register allocator in this mode needs the ability
447*03ce13f7SAndroid Build Coastguard Worker // to forcibly spill and reload registers in case none are naturally available.
advancedPhiLowering()448*03ce13f7SAndroid Build Coastguard Worker void CfgNode::advancedPhiLowering() {
449*03ce13f7SAndroid Build Coastguard Worker if (getPhis().empty())
450*03ce13f7SAndroid Build Coastguard Worker return;
451*03ce13f7SAndroid Build Coastguard Worker
452*03ce13f7SAndroid Build Coastguard Worker PhiDescList Desc;
453*03ce13f7SAndroid Build Coastguard Worker
454*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Phis) {
455*03ce13f7SAndroid Build Coastguard Worker auto *Phi = llvm::dyn_cast<InstPhi>(&I);
456*03ce13f7SAndroid Build Coastguard Worker if (!Phi->isDeleted()) {
457*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = Phi->getDest();
458*03ce13f7SAndroid Build Coastguard Worker Desc.emplace_back(Phi, Dest);
459*03ce13f7SAndroid Build Coastguard Worker // Undo the effect of the phi instruction on this node's live-in set by
460*03ce13f7SAndroid Build Coastguard Worker // marking the phi dest variable as live on entry.
461*03ce13f7SAndroid Build Coastguard Worker SizeT VarNum = Func->getLiveness()->getLiveIndex(Dest->getIndex());
462*03ce13f7SAndroid Build Coastguard Worker auto &LiveIn = Func->getLiveness()->getLiveIn(this);
463*03ce13f7SAndroid Build Coastguard Worker if (VarNum < LiveIn.size()) {
464*03ce13f7SAndroid Build Coastguard Worker assert(!LiveIn[VarNum]);
465*03ce13f7SAndroid Build Coastguard Worker LiveIn[VarNum] = true;
466*03ce13f7SAndroid Build Coastguard Worker }
467*03ce13f7SAndroid Build Coastguard Worker Phi->setDeleted();
468*03ce13f7SAndroid Build Coastguard Worker }
469*03ce13f7SAndroid Build Coastguard Worker }
470*03ce13f7SAndroid Build Coastguard Worker if (Desc.empty())
471*03ce13f7SAndroid Build Coastguard Worker return;
472*03ce13f7SAndroid Build Coastguard Worker
473*03ce13f7SAndroid Build Coastguard Worker TargetLowering *Target = Func->getTarget();
474*03ce13f7SAndroid Build Coastguard Worker SizeT InEdgeIndex = 0;
475*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Pred : InEdges) {
476*03ce13f7SAndroid Build Coastguard Worker CfgNode *Split = splitIncomingEdge(Pred, InEdgeIndex++);
477*03ce13f7SAndroid Build Coastguard Worker SizeT Remaining = Desc.size();
478*03ce13f7SAndroid Build Coastguard Worker
479*03ce13f7SAndroid Build Coastguard Worker // First pass computes Src and initializes NumPred.
480*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
481*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = Item.Dest;
482*03ce13f7SAndroid Build Coastguard Worker Operand *Src = Item.Phi->getOperandForTarget(Pred);
483*03ce13f7SAndroid Build Coastguard Worker Item.Src = Src;
484*03ce13f7SAndroid Build Coastguard Worker Item.Processed = false;
485*03ce13f7SAndroid Build Coastguard Worker Item.NumPred = 0;
486*03ce13f7SAndroid Build Coastguard Worker // Cherry-pick any trivial assignments, so that they don't contribute to
487*03ce13f7SAndroid Build Coastguard Worker // the running complexity of the topological sort.
488*03ce13f7SAndroid Build Coastguard Worker if (sameVarOrReg(Target, Dest, Src)) {
489*03ce13f7SAndroid Build Coastguard Worker Item.Processed = true;
490*03ce13f7SAndroid Build Coastguard Worker --Remaining;
491*03ce13f7SAndroid Build Coastguard Worker if (Dest != Src)
492*03ce13f7SAndroid Build Coastguard Worker // If Dest and Src are syntactically the same, don't bother adding
493*03ce13f7SAndroid Build Coastguard Worker // the assignment, because in all respects it would be redundant, and
494*03ce13f7SAndroid Build Coastguard Worker // if Dest/Src are on the stack, the target lowering may naively
495*03ce13f7SAndroid Build Coastguard Worker // decide to lower it using a temporary register.
496*03ce13f7SAndroid Build Coastguard Worker Split->appendInst(InstAssign::create(Func, Dest, Src));
497*03ce13f7SAndroid Build Coastguard Worker }
498*03ce13f7SAndroid Build Coastguard Worker }
499*03ce13f7SAndroid Build Coastguard Worker // Second pass computes NumPred by comparing every pair of Phi instructions.
500*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
501*03ce13f7SAndroid Build Coastguard Worker if (Item.Processed)
502*03ce13f7SAndroid Build Coastguard Worker continue;
503*03ce13f7SAndroid Build Coastguard Worker const Variable *Dest = Item.Dest;
504*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item2 : Desc) {
505*03ce13f7SAndroid Build Coastguard Worker if (Item2.Processed)
506*03ce13f7SAndroid Build Coastguard Worker continue;
507*03ce13f7SAndroid Build Coastguard Worker // There shouldn't be two different Phis with the same Dest variable or
508*03ce13f7SAndroid Build Coastguard Worker // register.
509*03ce13f7SAndroid Build Coastguard Worker assert((&Item == &Item2) || !sameVarOrReg(Target, Dest, Item2.Dest));
510*03ce13f7SAndroid Build Coastguard Worker if (sameVarOrReg(Target, Dest, Item2.Src))
511*03ce13f7SAndroid Build Coastguard Worker ++Item.NumPred;
512*03ce13f7SAndroid Build Coastguard Worker }
513*03ce13f7SAndroid Build Coastguard Worker }
514*03ce13f7SAndroid Build Coastguard Worker
515*03ce13f7SAndroid Build Coastguard Worker // Another pass to compute initial Weight values.
516*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
517*03ce13f7SAndroid Build Coastguard Worker if (Item.Processed)
518*03ce13f7SAndroid Build Coastguard Worker continue;
519*03ce13f7SAndroid Build Coastguard Worker int32_t Weight = 0;
520*03ce13f7SAndroid Build Coastguard Worker if (Item.NumPred == 0)
521*03ce13f7SAndroid Build Coastguard Worker Weight += WeightNoPreds;
522*03ce13f7SAndroid Build Coastguard Worker if (Item.NumPred == 1)
523*03ce13f7SAndroid Build Coastguard Worker Weight += WeightOnePred;
524*03ce13f7SAndroid Build Coastguard Worker if (auto *Var = llvm::dyn_cast<Variable>(Item.Src))
525*03ce13f7SAndroid Build Coastguard Worker if (Var->hasReg())
526*03ce13f7SAndroid Build Coastguard Worker Weight += WeightSrcIsReg;
527*03ce13f7SAndroid Build Coastguard Worker if (!Item.Dest->hasReg())
528*03ce13f7SAndroid Build Coastguard Worker Weight += WeightDestNotReg;
529*03ce13f7SAndroid Build Coastguard Worker Item.Weight = Weight;
530*03ce13f7SAndroid Build Coastguard Worker }
531*03ce13f7SAndroid Build Coastguard Worker
532*03ce13f7SAndroid Build Coastguard Worker // Repeatedly choose and process the best candidate in the topological sort,
533*03ce13f7SAndroid Build Coastguard Worker // until no candidates remain. This implementation is O(N^2) where N is the
534*03ce13f7SAndroid Build Coastguard Worker // number of Phi instructions, but with a small constant factor compared to
535*03ce13f7SAndroid Build Coastguard Worker // a likely implementation of O(N) topological sort.
536*03ce13f7SAndroid Build Coastguard Worker for (; Remaining; --Remaining) {
537*03ce13f7SAndroid Build Coastguard Worker int32_t BestWeight = -1;
538*03ce13f7SAndroid Build Coastguard Worker PhiDesc *BestItem = nullptr;
539*03ce13f7SAndroid Build Coastguard Worker // Find the best candidate.
540*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
541*03ce13f7SAndroid Build Coastguard Worker if (Item.Processed)
542*03ce13f7SAndroid Build Coastguard Worker continue;
543*03ce13f7SAndroid Build Coastguard Worker const int32_t Weight = Item.Weight;
544*03ce13f7SAndroid Build Coastguard Worker if (Weight > BestWeight) {
545*03ce13f7SAndroid Build Coastguard Worker BestItem = &Item;
546*03ce13f7SAndroid Build Coastguard Worker BestWeight = Weight;
547*03ce13f7SAndroid Build Coastguard Worker }
548*03ce13f7SAndroid Build Coastguard Worker }
549*03ce13f7SAndroid Build Coastguard Worker assert(BestWeight >= 0);
550*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = BestItem->Dest;
551*03ce13f7SAndroid Build Coastguard Worker Operand *Src = BestItem->Src;
552*03ce13f7SAndroid Build Coastguard Worker assert(!sameVarOrReg(Target, Dest, Src));
553*03ce13f7SAndroid Build Coastguard Worker // Break a cycle by introducing a temporary.
554*03ce13f7SAndroid Build Coastguard Worker while (BestItem->NumPred > 0) {
555*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
556*03ce13f7SAndroid Build Coastguard Worker // If the target instruction "A=B" is part of a cycle, find the "X=A"
557*03ce13f7SAndroid Build Coastguard Worker // assignment in the cycle because it will have to be rewritten as
558*03ce13f7SAndroid Build Coastguard Worker // "X=tmp".
559*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
560*03ce13f7SAndroid Build Coastguard Worker if (Item.Processed)
561*03ce13f7SAndroid Build Coastguard Worker continue;
562*03ce13f7SAndroid Build Coastguard Worker Operand *OtherSrc = Item.Src;
563*03ce13f7SAndroid Build Coastguard Worker if (Item.NumPred && sameVarOrReg(Target, Dest, OtherSrc)) {
564*03ce13f7SAndroid Build Coastguard Worker SizeT VarNum = Func->getNumVariables();
565*03ce13f7SAndroid Build Coastguard Worker Variable *Tmp = Func->makeVariable(OtherSrc->getType());
566*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump())
567*03ce13f7SAndroid Build Coastguard Worker Tmp->setName(Func, "__split_" + std::to_string(VarNum));
568*03ce13f7SAndroid Build Coastguard Worker Split->appendInst(InstAssign::create(Func, Tmp, OtherSrc));
569*03ce13f7SAndroid Build Coastguard Worker Item.Src = Tmp;
570*03ce13f7SAndroid Build Coastguard Worker updatePreds(Desc, Target, llvm::cast<Variable>(OtherSrc));
571*03ce13f7SAndroid Build Coastguard Worker Found = true;
572*03ce13f7SAndroid Build Coastguard Worker break;
573*03ce13f7SAndroid Build Coastguard Worker }
574*03ce13f7SAndroid Build Coastguard Worker }
575*03ce13f7SAndroid Build Coastguard Worker assert(Found);
576*03ce13f7SAndroid Build Coastguard Worker (void)Found;
577*03ce13f7SAndroid Build Coastguard Worker }
578*03ce13f7SAndroid Build Coastguard Worker // Now that a cycle (if any) has been broken, create the actual
579*03ce13f7SAndroid Build Coastguard Worker // assignment.
580*03ce13f7SAndroid Build Coastguard Worker Split->appendInst(InstAssign::create(Func, Dest, Src));
581*03ce13f7SAndroid Build Coastguard Worker if (auto *Var = llvm::dyn_cast<Variable>(Src))
582*03ce13f7SAndroid Build Coastguard Worker updatePreds(Desc, Target, Var);
583*03ce13f7SAndroid Build Coastguard Worker BestItem->Processed = true;
584*03ce13f7SAndroid Build Coastguard Worker }
585*03ce13f7SAndroid Build Coastguard Worker Split->appendInst(InstBr::create(Func, this));
586*03ce13f7SAndroid Build Coastguard Worker
587*03ce13f7SAndroid Build Coastguard Worker Split->genCode();
588*03ce13f7SAndroid Build Coastguard Worker Func->getVMetadata()->addNode(Split);
589*03ce13f7SAndroid Build Coastguard Worker // Validate to be safe. All items should be marked as processed, and have
590*03ce13f7SAndroid Build Coastguard Worker // no predecessors.
591*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::asserts()) {
592*03ce13f7SAndroid Build Coastguard Worker for (PhiDesc &Item : Desc) {
593*03ce13f7SAndroid Build Coastguard Worker (void)Item;
594*03ce13f7SAndroid Build Coastguard Worker assert(Item.Processed);
595*03ce13f7SAndroid Build Coastguard Worker assert(Item.NumPred == 0);
596*03ce13f7SAndroid Build Coastguard Worker }
597*03ce13f7SAndroid Build Coastguard Worker }
598*03ce13f7SAndroid Build Coastguard Worker }
599*03ce13f7SAndroid Build Coastguard Worker }
600*03ce13f7SAndroid Build Coastguard Worker
601*03ce13f7SAndroid Build Coastguard Worker // Does address mode optimization. Pass each instruction to the TargetLowering
602*03ce13f7SAndroid Build Coastguard Worker // object. If it returns a new instruction (representing the optimized address
603*03ce13f7SAndroid Build Coastguard Worker // mode), then insert the new instruction and delete the old.
doAddressOpt()604*03ce13f7SAndroid Build Coastguard Worker void CfgNode::doAddressOpt() {
605*03ce13f7SAndroid Build Coastguard Worker TargetLowering *Target = Func->getTarget();
606*03ce13f7SAndroid Build Coastguard Worker LoweringContext &Context = Target->getContext();
607*03ce13f7SAndroid Build Coastguard Worker Context.init(this);
608*03ce13f7SAndroid Build Coastguard Worker while (!Context.atEnd()) {
609*03ce13f7SAndroid Build Coastguard Worker Target->doAddressOpt();
610*03ce13f7SAndroid Build Coastguard Worker }
611*03ce13f7SAndroid Build Coastguard Worker }
612*03ce13f7SAndroid Build Coastguard Worker
613*03ce13f7SAndroid Build Coastguard Worker // Drives the target lowering. Passes the current instruction and the next
614*03ce13f7SAndroid Build Coastguard Worker // non-deleted instruction for target lowering.
genCode()615*03ce13f7SAndroid Build Coastguard Worker void CfgNode::genCode() {
616*03ce13f7SAndroid Build Coastguard Worker TargetLowering *Target = Func->getTarget();
617*03ce13f7SAndroid Build Coastguard Worker LoweringContext &Context = Target->getContext();
618*03ce13f7SAndroid Build Coastguard Worker // Lower the regular instructions.
619*03ce13f7SAndroid Build Coastguard Worker Context.init(this);
620*03ce13f7SAndroid Build Coastguard Worker Target->initNodeForLowering(this);
621*03ce13f7SAndroid Build Coastguard Worker while (!Context.atEnd()) {
622*03ce13f7SAndroid Build Coastguard Worker InstList::iterator Orig = Context.getCur();
623*03ce13f7SAndroid Build Coastguard Worker if (llvm::isa<InstRet>(*Orig))
624*03ce13f7SAndroid Build Coastguard Worker setHasReturn();
625*03ce13f7SAndroid Build Coastguard Worker Target->lower();
626*03ce13f7SAndroid Build Coastguard Worker // Ensure target lowering actually moved the cursor.
627*03ce13f7SAndroid Build Coastguard Worker assert(Context.getCur() != Orig);
628*03ce13f7SAndroid Build Coastguard Worker }
629*03ce13f7SAndroid Build Coastguard Worker Context.availabilityReset();
630*03ce13f7SAndroid Build Coastguard Worker // Do preliminary lowering of the Phi instructions.
631*03ce13f7SAndroid Build Coastguard Worker Target->prelowerPhis();
632*03ce13f7SAndroid Build Coastguard Worker }
633*03ce13f7SAndroid Build Coastguard Worker
livenessLightweight()634*03ce13f7SAndroid Build Coastguard Worker void CfgNode::livenessLightweight() {
635*03ce13f7SAndroid Build Coastguard Worker SizeT NumVars = Func->getNumVariables();
636*03ce13f7SAndroid Build Coastguard Worker LivenessBV Live(NumVars);
637*03ce13f7SAndroid Build Coastguard Worker // Process regular instructions in reverse order.
638*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : reverse_range(Insts)) {
639*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
640*03ce13f7SAndroid Build Coastguard Worker continue;
641*03ce13f7SAndroid Build Coastguard Worker I.livenessLightweight(Func, Live);
642*03ce13f7SAndroid Build Coastguard Worker }
643*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Phis) {
644*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
645*03ce13f7SAndroid Build Coastguard Worker continue;
646*03ce13f7SAndroid Build Coastguard Worker I.livenessLightweight(Func, Live);
647*03ce13f7SAndroid Build Coastguard Worker }
648*03ce13f7SAndroid Build Coastguard Worker }
649*03ce13f7SAndroid Build Coastguard Worker
650*03ce13f7SAndroid Build Coastguard Worker // Performs liveness analysis on the block. Returns true if the incoming
651*03ce13f7SAndroid Build Coastguard Worker // liveness changed from before, false if it stayed the same. (If it changes,
652*03ce13f7SAndroid Build Coastguard Worker // the node's predecessors need to be processed again.)
liveness(Liveness * Liveness)653*03ce13f7SAndroid Build Coastguard Worker bool CfgNode::liveness(Liveness *Liveness) {
654*03ce13f7SAndroid Build Coastguard Worker const SizeT NumVars = Liveness->getNumVarsInNode(this);
655*03ce13f7SAndroid Build Coastguard Worker const SizeT NumGlobalVars = Liveness->getNumGlobalVars();
656*03ce13f7SAndroid Build Coastguard Worker LivenessBV &Live = Liveness->getScratchBV();
657*03ce13f7SAndroid Build Coastguard Worker Live.clear();
658*03ce13f7SAndroid Build Coastguard Worker
659*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap *LiveBegin = nullptr;
660*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap *LiveEnd = nullptr;
661*03ce13f7SAndroid Build Coastguard Worker // Mark the beginning and ending of each variable's live range with the
662*03ce13f7SAndroid Build Coastguard Worker // sentinel instruction number 0.
663*03ce13f7SAndroid Build Coastguard Worker if (Liveness->getMode() == Liveness_Intervals) {
664*03ce13f7SAndroid Build Coastguard Worker LiveBegin = Liveness->getLiveBegin(this);
665*03ce13f7SAndroid Build Coastguard Worker LiveEnd = Liveness->getLiveEnd(this);
666*03ce13f7SAndroid Build Coastguard Worker LiveBegin->clear();
667*03ce13f7SAndroid Build Coastguard Worker LiveEnd->clear();
668*03ce13f7SAndroid Build Coastguard Worker // Guess that the number of live ranges beginning is roughly the number of
669*03ce13f7SAndroid Build Coastguard Worker // instructions, and same for live ranges ending.
670*03ce13f7SAndroid Build Coastguard Worker LiveBegin->reserve(getInstCountEstimate());
671*03ce13f7SAndroid Build Coastguard Worker LiveEnd->reserve(getInstCountEstimate());
672*03ce13f7SAndroid Build Coastguard Worker }
673*03ce13f7SAndroid Build Coastguard Worker
674*03ce13f7SAndroid Build Coastguard Worker // Initialize Live to be the union of all successors' LiveIn.
675*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Succ : OutEdges) {
676*03ce13f7SAndroid Build Coastguard Worker const LivenessBV &LiveIn = Liveness->getLiveIn(Succ);
677*03ce13f7SAndroid Build Coastguard Worker assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars);
678*03ce13f7SAndroid Build Coastguard Worker Live |= LiveIn;
679*03ce13f7SAndroid Build Coastguard Worker // Mark corresponding argument of phis in successor as live.
680*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Succ->Phis) {
681*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
682*03ce13f7SAndroid Build Coastguard Worker continue;
683*03ce13f7SAndroid Build Coastguard Worker auto *Phi = llvm::cast<InstPhi>(&I);
684*03ce13f7SAndroid Build Coastguard Worker Phi->livenessPhiOperand(Live, this, Liveness);
685*03ce13f7SAndroid Build Coastguard Worker }
686*03ce13f7SAndroid Build Coastguard Worker }
687*03ce13f7SAndroid Build Coastguard Worker assert(Live.empty() || Live.size() == NumGlobalVars);
688*03ce13f7SAndroid Build Coastguard Worker Liveness->getLiveOut(this) = Live;
689*03ce13f7SAndroid Build Coastguard Worker
690*03ce13f7SAndroid Build Coastguard Worker // Expand Live so it can hold locals in addition to globals.
691*03ce13f7SAndroid Build Coastguard Worker Live.resize(NumVars);
692*03ce13f7SAndroid Build Coastguard Worker // Process regular instructions in reverse order.
693*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : reverse_range(Insts)) {
694*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
695*03ce13f7SAndroid Build Coastguard Worker continue;
696*03ce13f7SAndroid Build Coastguard Worker I.liveness(I.getNumber(), Live, Liveness, LiveBegin, LiveEnd);
697*03ce13f7SAndroid Build Coastguard Worker }
698*03ce13f7SAndroid Build Coastguard Worker // Process phis in forward order so that we can override the instruction
699*03ce13f7SAndroid Build Coastguard Worker // number to be that of the earliest phi instruction in the block.
700*03ce13f7SAndroid Build Coastguard Worker SizeT NumNonDeadPhis = 0;
701*03ce13f7SAndroid Build Coastguard Worker InstNumberT FirstPhiNumber = Inst::NumberSentinel;
702*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Phis) {
703*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
704*03ce13f7SAndroid Build Coastguard Worker continue;
705*03ce13f7SAndroid Build Coastguard Worker if (FirstPhiNumber == Inst::NumberSentinel)
706*03ce13f7SAndroid Build Coastguard Worker FirstPhiNumber = I.getNumber();
707*03ce13f7SAndroid Build Coastguard Worker if (I.liveness(FirstPhiNumber, Live, Liveness, LiveBegin, LiveEnd))
708*03ce13f7SAndroid Build Coastguard Worker ++NumNonDeadPhis;
709*03ce13f7SAndroid Build Coastguard Worker }
710*03ce13f7SAndroid Build Coastguard Worker
711*03ce13f7SAndroid Build Coastguard Worker // When using the sparse representation, after traversing the instructions in
712*03ce13f7SAndroid Build Coastguard Worker // the block, the Live bitvector should only contain set bits for global
713*03ce13f7SAndroid Build Coastguard Worker // variables upon block entry. We validate this by testing the upper bits of
714*03ce13f7SAndroid Build Coastguard Worker // the Live bitvector.
715*03ce13f7SAndroid Build Coastguard Worker if (Live.find_next(NumGlobalVars) != -1) {
716*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump()) {
717*03ce13f7SAndroid Build Coastguard Worker // This is a fatal liveness consistency error. Print some diagnostics and
718*03ce13f7SAndroid Build Coastguard Worker // abort.
719*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
720*03ce13f7SAndroid Build Coastguard Worker Func->resetCurrentNode();
721*03ce13f7SAndroid Build Coastguard Worker Str << "Invalid Live =";
722*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = NumGlobalVars; i < Live.size(); ++i) {
723*03ce13f7SAndroid Build Coastguard Worker if (Live.test(i)) {
724*03ce13f7SAndroid Build Coastguard Worker Str << " ";
725*03ce13f7SAndroid Build Coastguard Worker Liveness->getVariable(i, this)->dump(Func);
726*03ce13f7SAndroid Build Coastguard Worker }
727*03ce13f7SAndroid Build Coastguard Worker }
728*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
729*03ce13f7SAndroid Build Coastguard Worker }
730*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Fatal inconsistency in liveness analysis");
731*03ce13f7SAndroid Build Coastguard Worker }
732*03ce13f7SAndroid Build Coastguard Worker // Now truncate Live to prevent LiveIn from growing.
733*03ce13f7SAndroid Build Coastguard Worker Live.resize(NumGlobalVars);
734*03ce13f7SAndroid Build Coastguard Worker
735*03ce13f7SAndroid Build Coastguard Worker bool Changed = false;
736*03ce13f7SAndroid Build Coastguard Worker LivenessBV &LiveIn = Liveness->getLiveIn(this);
737*03ce13f7SAndroid Build Coastguard Worker assert(LiveIn.empty() || LiveIn.size() == NumGlobalVars);
738*03ce13f7SAndroid Build Coastguard Worker // Add in current LiveIn
739*03ce13f7SAndroid Build Coastguard Worker Live |= LiveIn;
740*03ce13f7SAndroid Build Coastguard Worker // Check result, set LiveIn=Live
741*03ce13f7SAndroid Build Coastguard Worker SizeT &PrevNumNonDeadPhis = Liveness->getNumNonDeadPhis(this);
742*03ce13f7SAndroid Build Coastguard Worker bool LiveInChanged = (Live != LiveIn);
743*03ce13f7SAndroid Build Coastguard Worker Changed = (NumNonDeadPhis != PrevNumNonDeadPhis || LiveInChanged);
744*03ce13f7SAndroid Build Coastguard Worker if (LiveInChanged)
745*03ce13f7SAndroid Build Coastguard Worker LiveIn = Live;
746*03ce13f7SAndroid Build Coastguard Worker PrevNumNonDeadPhis = NumNonDeadPhis;
747*03ce13f7SAndroid Build Coastguard Worker return Changed;
748*03ce13f7SAndroid Build Coastguard Worker }
749*03ce13f7SAndroid Build Coastguard Worker
750*03ce13f7SAndroid Build Coastguard Worker // Validate the integrity of the live ranges in this block. If there are any
751*03ce13f7SAndroid Build Coastguard Worker // errors, it prints details and returns false. On success, it returns true.
livenessValidateIntervals(Liveness * Liveness) const752*03ce13f7SAndroid Build Coastguard Worker bool CfgNode::livenessValidateIntervals(Liveness *Liveness) const {
753*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::asserts())
754*03ce13f7SAndroid Build Coastguard Worker return true;
755*03ce13f7SAndroid Build Coastguard Worker
756*03ce13f7SAndroid Build Coastguard Worker // Verify there are no duplicates.
757*03ce13f7SAndroid Build Coastguard Worker auto ComparePair = [](const LiveBeginEndMapEntry &A,
758*03ce13f7SAndroid Build Coastguard Worker const LiveBeginEndMapEntry &B) {
759*03ce13f7SAndroid Build Coastguard Worker return A.first == B.first;
760*03ce13f7SAndroid Build Coastguard Worker };
761*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this);
762*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this);
763*03ce13f7SAndroid Build Coastguard Worker if (std::adjacent_find(MapBegin.begin(), MapBegin.end(), ComparePair) ==
764*03ce13f7SAndroid Build Coastguard Worker MapBegin.end() &&
765*03ce13f7SAndroid Build Coastguard Worker std::adjacent_find(MapEnd.begin(), MapEnd.end(), ComparePair) ==
766*03ce13f7SAndroid Build Coastguard Worker MapEnd.end())
767*03ce13f7SAndroid Build Coastguard Worker return true;
768*03ce13f7SAndroid Build Coastguard Worker
769*03ce13f7SAndroid Build Coastguard Worker // There is definitely a liveness error. All paths from here return false.
770*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
771*03ce13f7SAndroid Build Coastguard Worker return false;
772*03ce13f7SAndroid Build Coastguard Worker
773*03ce13f7SAndroid Build Coastguard Worker // Print all the errors.
774*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump()) {
775*03ce13f7SAndroid Build Coastguard Worker GlobalContext *Ctx = Func->getContext();
776*03ce13f7SAndroid Build Coastguard Worker OstreamLocker L(Ctx);
777*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrDump();
778*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose()) {
779*03ce13f7SAndroid Build Coastguard Worker Str << "Live range errors in the following block:\n";
780*03ce13f7SAndroid Build Coastguard Worker dump(Func);
781*03ce13f7SAndroid Build Coastguard Worker }
782*03ce13f7SAndroid Build Coastguard Worker for (auto Start = MapBegin.begin();
783*03ce13f7SAndroid Build Coastguard Worker (Start = std::adjacent_find(Start, MapBegin.end(), ComparePair)) !=
784*03ce13f7SAndroid Build Coastguard Worker MapBegin.end();
785*03ce13f7SAndroid Build Coastguard Worker ++Start) {
786*03ce13f7SAndroid Build Coastguard Worker auto Next = Start + 1;
787*03ce13f7SAndroid Build Coastguard Worker Str << "Duplicate LR begin, block " << getName() << ", instructions "
788*03ce13f7SAndroid Build Coastguard Worker << Start->second << " & " << Next->second << ", variable "
789*03ce13f7SAndroid Build Coastguard Worker << Liveness->getVariable(Start->first, this)->getName() << "\n";
790*03ce13f7SAndroid Build Coastguard Worker }
791*03ce13f7SAndroid Build Coastguard Worker for (auto Start = MapEnd.begin();
792*03ce13f7SAndroid Build Coastguard Worker (Start = std::adjacent_find(Start, MapEnd.end(), ComparePair)) !=
793*03ce13f7SAndroid Build Coastguard Worker MapEnd.end();
794*03ce13f7SAndroid Build Coastguard Worker ++Start) {
795*03ce13f7SAndroid Build Coastguard Worker auto Next = Start + 1;
796*03ce13f7SAndroid Build Coastguard Worker Str << "Duplicate LR end, block " << getName() << ", instructions "
797*03ce13f7SAndroid Build Coastguard Worker << Start->second << " & " << Next->second << ", variable "
798*03ce13f7SAndroid Build Coastguard Worker << Liveness->getVariable(Start->first, this)->getName() << "\n";
799*03ce13f7SAndroid Build Coastguard Worker }
800*03ce13f7SAndroid Build Coastguard Worker }
801*03ce13f7SAndroid Build Coastguard Worker
802*03ce13f7SAndroid Build Coastguard Worker return false;
803*03ce13f7SAndroid Build Coastguard Worker }
804*03ce13f7SAndroid Build Coastguard Worker
805*03ce13f7SAndroid Build Coastguard Worker // Once basic liveness is complete, compute actual live ranges. It is assumed
806*03ce13f7SAndroid Build Coastguard Worker // that within a single basic block, a live range begins at most once and ends
807*03ce13f7SAndroid Build Coastguard Worker // at most once. This is certainly true for pure SSA form. It is also true once
808*03ce13f7SAndroid Build Coastguard Worker // phis are lowered, since each assignment to the phi-based temporary is in a
809*03ce13f7SAndroid Build Coastguard Worker // different basic block, and there is a single read that ends the live in the
810*03ce13f7SAndroid Build Coastguard Worker // basic block that contained the actual phi instruction.
livenessAddIntervals(Liveness * Liveness,InstNumberT FirstInstNum,InstNumberT LastInstNum)811*03ce13f7SAndroid Build Coastguard Worker void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
812*03ce13f7SAndroid Build Coastguard Worker InstNumberT LastInstNum) {
813*03ce13f7SAndroid Build Coastguard Worker TimerMarker T1(TimerStack::TT_liveRange, Func);
814*03ce13f7SAndroid Build Coastguard Worker
815*03ce13f7SAndroid Build Coastguard Worker const SizeT NumVars = Liveness->getNumVarsInNode(this);
816*03ce13f7SAndroid Build Coastguard Worker const LivenessBV &LiveIn = Liveness->getLiveIn(this);
817*03ce13f7SAndroid Build Coastguard Worker const LivenessBV &LiveOut = Liveness->getLiveOut(this);
818*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap &MapBegin = *Liveness->getLiveBegin(this);
819*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap &MapEnd = *Liveness->getLiveEnd(this);
820*03ce13f7SAndroid Build Coastguard Worker std::sort(MapBegin.begin(), MapBegin.end());
821*03ce13f7SAndroid Build Coastguard Worker std::sort(MapEnd.begin(), MapEnd.end());
822*03ce13f7SAndroid Build Coastguard Worker
823*03ce13f7SAndroid Build Coastguard Worker if (!livenessValidateIntervals(Liveness)) {
824*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("livenessAddIntervals: Liveness error");
825*03ce13f7SAndroid Build Coastguard Worker return;
826*03ce13f7SAndroid Build Coastguard Worker }
827*03ce13f7SAndroid Build Coastguard Worker
828*03ce13f7SAndroid Build Coastguard Worker LivenessBV &LiveInAndOut = Liveness->getScratchBV();
829*03ce13f7SAndroid Build Coastguard Worker LiveInAndOut = LiveIn;
830*03ce13f7SAndroid Build Coastguard Worker LiveInAndOut &= LiveOut;
831*03ce13f7SAndroid Build Coastguard Worker
832*03ce13f7SAndroid Build Coastguard Worker // Iterate in parallel across the sorted MapBegin[] and MapEnd[].
833*03ce13f7SAndroid Build Coastguard Worker auto IBB = MapBegin.begin(), IEB = MapEnd.begin();
834*03ce13f7SAndroid Build Coastguard Worker auto IBE = MapBegin.end(), IEE = MapEnd.end();
835*03ce13f7SAndroid Build Coastguard Worker while (IBB != IBE || IEB != IEE) {
836*03ce13f7SAndroid Build Coastguard Worker SizeT i1 = IBB == IBE ? NumVars : IBB->first;
837*03ce13f7SAndroid Build Coastguard Worker SizeT i2 = IEB == IEE ? NumVars : IEB->first;
838*03ce13f7SAndroid Build Coastguard Worker SizeT i = std::min(i1, i2);
839*03ce13f7SAndroid Build Coastguard Worker // i1 is the Variable number of the next MapBegin entry, and i2 is the
840*03ce13f7SAndroid Build Coastguard Worker // Variable number of the next MapEnd entry. If i1==i2, then the Variable's
841*03ce13f7SAndroid Build Coastguard Worker // live range begins and ends in this block. If i1<i2, then i1's live range
842*03ce13f7SAndroid Build Coastguard Worker // begins at instruction IBB->second and extends through the end of the
843*03ce13f7SAndroid Build Coastguard Worker // block. If i1>i2, then i2's live range begins at the first instruction of
844*03ce13f7SAndroid Build Coastguard Worker // the block and ends at IEB->second. In any case, we choose the lesser of
845*03ce13f7SAndroid Build Coastguard Worker // i1 and i2 and proceed accordingly.
846*03ce13f7SAndroid Build Coastguard Worker InstNumberT LB = i == i1 ? IBB->second : FirstInstNum;
847*03ce13f7SAndroid Build Coastguard Worker InstNumberT LE = i == i2 ? IEB->second : LastInstNum + 1;
848*03ce13f7SAndroid Build Coastguard Worker
849*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Liveness->getVariable(i, this);
850*03ce13f7SAndroid Build Coastguard Worker if (LB > LE) {
851*03ce13f7SAndroid Build Coastguard Worker Var->addLiveRange(FirstInstNum, LE, this);
852*03ce13f7SAndroid Build Coastguard Worker Var->addLiveRange(LB, LastInstNum + 1, this);
853*03ce13f7SAndroid Build Coastguard Worker // Assert that Var is a global variable by checking that its liveness
854*03ce13f7SAndroid Build Coastguard Worker // index is less than the number of globals. This ensures that the
855*03ce13f7SAndroid Build Coastguard Worker // LiveInAndOut[] access is valid.
856*03ce13f7SAndroid Build Coastguard Worker assert(i < Liveness->getNumGlobalVars());
857*03ce13f7SAndroid Build Coastguard Worker LiveInAndOut[i] = false;
858*03ce13f7SAndroid Build Coastguard Worker } else {
859*03ce13f7SAndroid Build Coastguard Worker Var->addLiveRange(LB, LE, this);
860*03ce13f7SAndroid Build Coastguard Worker }
861*03ce13f7SAndroid Build Coastguard Worker if (i == i1)
862*03ce13f7SAndroid Build Coastguard Worker ++IBB;
863*03ce13f7SAndroid Build Coastguard Worker if (i == i2)
864*03ce13f7SAndroid Build Coastguard Worker ++IEB;
865*03ce13f7SAndroid Build Coastguard Worker }
866*03ce13f7SAndroid Build Coastguard Worker // Process the variables that are live across the entire block.
867*03ce13f7SAndroid Build Coastguard Worker for (int i = LiveInAndOut.find_first(); i != -1;
868*03ce13f7SAndroid Build Coastguard Worker i = LiveInAndOut.find_next(i)) {
869*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Liveness->getVariable(i, this);
870*03ce13f7SAndroid Build Coastguard Worker if (Liveness->getRangeMask(Var->getIndex()))
871*03ce13f7SAndroid Build Coastguard Worker Var->addLiveRange(FirstInstNum, LastInstNum + 1, this);
872*03ce13f7SAndroid Build Coastguard Worker }
873*03ce13f7SAndroid Build Coastguard Worker }
874*03ce13f7SAndroid Build Coastguard Worker
875*03ce13f7SAndroid Build Coastguard Worker // If this node contains only deleted instructions, and ends in an
876*03ce13f7SAndroid Build Coastguard Worker // unconditional branch, contract the node by repointing all its in-edges to
877*03ce13f7SAndroid Build Coastguard Worker // its successor.
contractIfEmpty()878*03ce13f7SAndroid Build Coastguard Worker void CfgNode::contractIfEmpty() {
879*03ce13f7SAndroid Build Coastguard Worker if (InEdges.empty())
880*03ce13f7SAndroid Build Coastguard Worker return;
881*03ce13f7SAndroid Build Coastguard Worker Inst *Branch = nullptr;
882*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Insts) {
883*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
884*03ce13f7SAndroid Build Coastguard Worker continue;
885*03ce13f7SAndroid Build Coastguard Worker if (I.isUnconditionalBranch())
886*03ce13f7SAndroid Build Coastguard Worker Branch = &I;
887*03ce13f7SAndroid Build Coastguard Worker else if (!I.isRedundantAssign())
888*03ce13f7SAndroid Build Coastguard Worker return;
889*03ce13f7SAndroid Build Coastguard Worker }
890*03ce13f7SAndroid Build Coastguard Worker // Make sure there is actually a successor to repoint in-edges to.
891*03ce13f7SAndroid Build Coastguard Worker if (OutEdges.empty())
892*03ce13f7SAndroid Build Coastguard Worker return;
893*03ce13f7SAndroid Build Coastguard Worker assert(hasSingleOutEdge());
894*03ce13f7SAndroid Build Coastguard Worker // Don't try to delete a self-loop.
895*03ce13f7SAndroid Build Coastguard Worker if (OutEdges[0] == this)
896*03ce13f7SAndroid Build Coastguard Worker return;
897*03ce13f7SAndroid Build Coastguard Worker // Make sure the node actually contains (ends with) an unconditional branch.
898*03ce13f7SAndroid Build Coastguard Worker if (Branch == nullptr)
899*03ce13f7SAndroid Build Coastguard Worker return;
900*03ce13f7SAndroid Build Coastguard Worker
901*03ce13f7SAndroid Build Coastguard Worker Branch->setDeleted();
902*03ce13f7SAndroid Build Coastguard Worker CfgNode *Successor = OutEdges.front();
903*03ce13f7SAndroid Build Coastguard Worker // Repoint all this node's in-edges to this node's successor, unless this
904*03ce13f7SAndroid Build Coastguard Worker // node's successor is actually itself (in which case the statement
905*03ce13f7SAndroid Build Coastguard Worker // "OutEdges.front()->InEdges.push_back(Pred)" could invalidate the iterator
906*03ce13f7SAndroid Build Coastguard Worker // over this->InEdges).
907*03ce13f7SAndroid Build Coastguard Worker if (Successor != this) {
908*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Pred : InEdges) {
909*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *&I : Pred->OutEdges) {
910*03ce13f7SAndroid Build Coastguard Worker if (I == this) {
911*03ce13f7SAndroid Build Coastguard Worker I = Successor;
912*03ce13f7SAndroid Build Coastguard Worker Successor->InEdges.push_back(Pred);
913*03ce13f7SAndroid Build Coastguard Worker }
914*03ce13f7SAndroid Build Coastguard Worker }
915*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : Pred->getInsts()) {
916*03ce13f7SAndroid Build Coastguard Worker if (!I.isDeleted())
917*03ce13f7SAndroid Build Coastguard Worker I.repointEdges(this, Successor);
918*03ce13f7SAndroid Build Coastguard Worker }
919*03ce13f7SAndroid Build Coastguard Worker }
920*03ce13f7SAndroid Build Coastguard Worker
921*03ce13f7SAndroid Build Coastguard Worker // Remove the in-edge to the successor to allow node reordering to make
922*03ce13f7SAndroid Build Coastguard Worker // better decisions. For example it's more helpful to place a node after a
923*03ce13f7SAndroid Build Coastguard Worker // reachable predecessor than an unreachable one (like the one we just
924*03ce13f7SAndroid Build Coastguard Worker // contracted).
925*03ce13f7SAndroid Build Coastguard Worker Successor->InEdges.erase(
926*03ce13f7SAndroid Build Coastguard Worker std::find(Successor->InEdges.begin(), Successor->InEdges.end(), this));
927*03ce13f7SAndroid Build Coastguard Worker }
928*03ce13f7SAndroid Build Coastguard Worker InEdges.clear();
929*03ce13f7SAndroid Build Coastguard Worker }
930*03ce13f7SAndroid Build Coastguard Worker
doBranchOpt(const CfgNode * NextNode)931*03ce13f7SAndroid Build Coastguard Worker void CfgNode::doBranchOpt(const CfgNode *NextNode) {
932*03ce13f7SAndroid Build Coastguard Worker TargetLowering *Target = Func->getTarget();
933*03ce13f7SAndroid Build Coastguard Worker // Find the first opportunity for branch optimization (which will be the last
934*03ce13f7SAndroid Build Coastguard Worker // instruction in the block) and stop. This is sufficient unless there is
935*03ce13f7SAndroid Build Coastguard Worker // some target lowering where we have the possibility of multiple
936*03ce13f7SAndroid Build Coastguard Worker // optimizations per block. Take care with switch lowering as there are
937*03ce13f7SAndroid Build Coastguard Worker // multiple unconditional branches and only the last can be deleted.
938*03ce13f7SAndroid Build Coastguard Worker for (Inst &I : reverse_range(Insts)) {
939*03ce13f7SAndroid Build Coastguard Worker if (!I.isDeleted()) {
940*03ce13f7SAndroid Build Coastguard Worker Target->doBranchOpt(&I, NextNode);
941*03ce13f7SAndroid Build Coastguard Worker return;
942*03ce13f7SAndroid Build Coastguard Worker }
943*03ce13f7SAndroid Build Coastguard Worker }
944*03ce13f7SAndroid Build Coastguard Worker }
945*03ce13f7SAndroid Build Coastguard Worker
946*03ce13f7SAndroid Build Coastguard Worker // ======================== Dump routines ======================== //
947*03ce13f7SAndroid Build Coastguard Worker
948*03ce13f7SAndroid Build Coastguard Worker namespace {
949*03ce13f7SAndroid Build Coastguard Worker
950*03ce13f7SAndroid Build Coastguard Worker // Helper functions for emit().
951*03ce13f7SAndroid Build Coastguard Worker
emitRegisterUsage(Ostream & Str,const Cfg * Func,const CfgNode * Node,bool IsLiveIn,CfgVector<SizeT> & LiveRegCount)952*03ce13f7SAndroid Build Coastguard Worker void emitRegisterUsage(Ostream &Str, const Cfg *Func, const CfgNode *Node,
953*03ce13f7SAndroid Build Coastguard Worker bool IsLiveIn, CfgVector<SizeT> &LiveRegCount) {
954*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
955*03ce13f7SAndroid Build Coastguard Worker return;
956*03ce13f7SAndroid Build Coastguard Worker Liveness *Liveness = Func->getLiveness();
957*03ce13f7SAndroid Build Coastguard Worker const LivenessBV *Live;
958*03ce13f7SAndroid Build Coastguard Worker const auto StackReg = Func->getTarget()->getStackReg();
959*03ce13f7SAndroid Build Coastguard Worker const auto FrameOrStackReg = Func->getTarget()->getFrameOrStackReg();
960*03ce13f7SAndroid Build Coastguard Worker if (IsLiveIn) {
961*03ce13f7SAndroid Build Coastguard Worker Live = &Liveness->getLiveIn(Node);
962*03ce13f7SAndroid Build Coastguard Worker Str << "\t\t\t\t/* LiveIn=";
963*03ce13f7SAndroid Build Coastguard Worker } else {
964*03ce13f7SAndroid Build Coastguard Worker Live = &Liveness->getLiveOut(Node);
965*03ce13f7SAndroid Build Coastguard Worker Str << "\t\t\t\t/* LiveOut=";
966*03ce13f7SAndroid Build Coastguard Worker }
967*03ce13f7SAndroid Build Coastguard Worker if (!Live->empty()) {
968*03ce13f7SAndroid Build Coastguard Worker CfgVector<Variable *> LiveRegs;
969*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Live->size(); ++i) {
970*03ce13f7SAndroid Build Coastguard Worker if (!(*Live)[i])
971*03ce13f7SAndroid Build Coastguard Worker continue;
972*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Liveness->getVariable(i, Node);
973*03ce13f7SAndroid Build Coastguard Worker if (!Var->hasReg())
974*03ce13f7SAndroid Build Coastguard Worker continue;
975*03ce13f7SAndroid Build Coastguard Worker const auto RegNum = Var->getRegNum();
976*03ce13f7SAndroid Build Coastguard Worker if (RegNum == StackReg || RegNum == FrameOrStackReg)
977*03ce13f7SAndroid Build Coastguard Worker continue;
978*03ce13f7SAndroid Build Coastguard Worker if (IsLiveIn)
979*03ce13f7SAndroid Build Coastguard Worker ++LiveRegCount[RegNum];
980*03ce13f7SAndroid Build Coastguard Worker LiveRegs.push_back(Var);
981*03ce13f7SAndroid Build Coastguard Worker }
982*03ce13f7SAndroid Build Coastguard Worker // Sort the variables by regnum so they are always printed in a familiar
983*03ce13f7SAndroid Build Coastguard Worker // order.
984*03ce13f7SAndroid Build Coastguard Worker std::sort(LiveRegs.begin(), LiveRegs.end(),
985*03ce13f7SAndroid Build Coastguard Worker [](const Variable *V1, const Variable *V2) {
986*03ce13f7SAndroid Build Coastguard Worker return unsigned(V1->getRegNum()) < unsigned(V2->getRegNum());
987*03ce13f7SAndroid Build Coastguard Worker });
988*03ce13f7SAndroid Build Coastguard Worker bool First = true;
989*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : LiveRegs) {
990*03ce13f7SAndroid Build Coastguard Worker if (!First)
991*03ce13f7SAndroid Build Coastguard Worker Str << ",";
992*03ce13f7SAndroid Build Coastguard Worker First = false;
993*03ce13f7SAndroid Build Coastguard Worker Var->emit(Func);
994*03ce13f7SAndroid Build Coastguard Worker }
995*03ce13f7SAndroid Build Coastguard Worker }
996*03ce13f7SAndroid Build Coastguard Worker Str << " */\n";
997*03ce13f7SAndroid Build Coastguard Worker }
998*03ce13f7SAndroid Build Coastguard Worker
999*03ce13f7SAndroid Build Coastguard Worker /// Returns true if some text was emitted - in which case the caller definitely
1000*03ce13f7SAndroid Build Coastguard Worker /// needs to emit a newline character.
emitLiveRangesEnded(Ostream & Str,const Cfg * Func,const Inst * Instr,CfgVector<SizeT> & LiveRegCount)1001*03ce13f7SAndroid Build Coastguard Worker bool emitLiveRangesEnded(Ostream &Str, const Cfg *Func, const Inst *Instr,
1002*03ce13f7SAndroid Build Coastguard Worker CfgVector<SizeT> &LiveRegCount) {
1003*03ce13f7SAndroid Build Coastguard Worker bool Printed = false;
1004*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
1005*03ce13f7SAndroid Build Coastguard Worker return Printed;
1006*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = Instr->getDest();
1007*03ce13f7SAndroid Build Coastguard Worker // Normally we increment the live count for the dest register. But we
1008*03ce13f7SAndroid Build Coastguard Worker // shouldn't if the instruction's IsDestRedefined flag is set, because this
1009*03ce13f7SAndroid Build Coastguard Worker // means that the target lowering created this instruction as a non-SSA
1010*03ce13f7SAndroid Build Coastguard Worker // assignment; i.e., a different, previous instruction started the dest
1011*03ce13f7SAndroid Build Coastguard Worker // variable's live range.
1012*03ce13f7SAndroid Build Coastguard Worker if (!Instr->isDestRedefined() && Dest && Dest->hasReg())
1013*03ce13f7SAndroid Build Coastguard Worker ++LiveRegCount[Dest->getRegNum()];
1014*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *Instr) {
1015*03ce13f7SAndroid Build Coastguard Worker bool ShouldReport = Instr->isLastUse(Var);
1016*03ce13f7SAndroid Build Coastguard Worker if (ShouldReport && Var->hasReg()) {
1017*03ce13f7SAndroid Build Coastguard Worker // Don't report end of live range until the live count reaches 0.
1018*03ce13f7SAndroid Build Coastguard Worker SizeT NewCount = --LiveRegCount[Var->getRegNum()];
1019*03ce13f7SAndroid Build Coastguard Worker if (NewCount)
1020*03ce13f7SAndroid Build Coastguard Worker ShouldReport = false;
1021*03ce13f7SAndroid Build Coastguard Worker }
1022*03ce13f7SAndroid Build Coastguard Worker if (ShouldReport) {
1023*03ce13f7SAndroid Build Coastguard Worker if (Printed)
1024*03ce13f7SAndroid Build Coastguard Worker Str << ",";
1025*03ce13f7SAndroid Build Coastguard Worker else
1026*03ce13f7SAndroid Build Coastguard Worker Str << " \t/* END=";
1027*03ce13f7SAndroid Build Coastguard Worker Var->emit(Func);
1028*03ce13f7SAndroid Build Coastguard Worker Printed = true;
1029*03ce13f7SAndroid Build Coastguard Worker }
1030*03ce13f7SAndroid Build Coastguard Worker }
1031*03ce13f7SAndroid Build Coastguard Worker if (Printed)
1032*03ce13f7SAndroid Build Coastguard Worker Str << " */";
1033*03ce13f7SAndroid Build Coastguard Worker return Printed;
1034*03ce13f7SAndroid Build Coastguard Worker }
1035*03ce13f7SAndroid Build Coastguard Worker
updateStats(Cfg * Func,const Inst * I)1036*03ce13f7SAndroid Build Coastguard Worker void updateStats(Cfg *Func, const Inst *I) {
1037*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
1038*03ce13f7SAndroid Build Coastguard Worker return;
1039*03ce13f7SAndroid Build Coastguard Worker // Update emitted instruction count, plus fill/spill count for Variable
1040*03ce13f7SAndroid Build Coastguard Worker // operands without a physical register.
1041*03ce13f7SAndroid Build Coastguard Worker if (uint32_t Count = I->getEmitInstCount()) {
1042*03ce13f7SAndroid Build Coastguard Worker Func->getContext()->statsUpdateEmitted(Count);
1043*03ce13f7SAndroid Build Coastguard Worker if (Variable *Dest = I->getDest()) {
1044*03ce13f7SAndroid Build Coastguard Worker if (!Dest->hasReg())
1045*03ce13f7SAndroid Build Coastguard Worker Func->getContext()->statsUpdateFills();
1046*03ce13f7SAndroid Build Coastguard Worker }
1047*03ce13f7SAndroid Build Coastguard Worker for (SizeT S = 0; S < I->getSrcSize(); ++S) {
1048*03ce13f7SAndroid Build Coastguard Worker if (auto *Src = llvm::dyn_cast<Variable>(I->getSrc(S))) {
1049*03ce13f7SAndroid Build Coastguard Worker if (!Src->hasReg())
1050*03ce13f7SAndroid Build Coastguard Worker Func->getContext()->statsUpdateSpills();
1051*03ce13f7SAndroid Build Coastguard Worker }
1052*03ce13f7SAndroid Build Coastguard Worker }
1053*03ce13f7SAndroid Build Coastguard Worker }
1054*03ce13f7SAndroid Build Coastguard Worker }
1055*03ce13f7SAndroid Build Coastguard Worker
1056*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
1057*03ce13f7SAndroid Build Coastguard Worker
emit(Cfg * Func) const1058*03ce13f7SAndroid Build Coastguard Worker void CfgNode::emit(Cfg *Func) const {
1059*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
1060*03ce13f7SAndroid Build Coastguard Worker return;
1061*03ce13f7SAndroid Build Coastguard Worker Func->setCurrentNode(this);
1062*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrEmit();
1063*03ce13f7SAndroid Build Coastguard Worker Liveness *Liveness = Func->getLiveness();
1064*03ce13f7SAndroid Build Coastguard Worker const bool DecorateAsm = Liveness && getFlags().getDecorateAsm();
1065*03ce13f7SAndroid Build Coastguard Worker Str << getAsmName() << ":\n";
1066*03ce13f7SAndroid Build Coastguard Worker // LiveRegCount keeps track of the number of currently live variables that
1067*03ce13f7SAndroid Build Coastguard Worker // each register is assigned to. Normally that would be only 0 or 1, but the
1068*03ce13f7SAndroid Build Coastguard Worker // register allocator's AllowOverlap inference allows it to be greater than 1
1069*03ce13f7SAndroid Build Coastguard Worker // for short periods.
1070*03ce13f7SAndroid Build Coastguard Worker CfgVector<SizeT> LiveRegCount(Func->getTarget()->getNumRegisters());
1071*03ce13f7SAndroid Build Coastguard Worker if (DecorateAsm) {
1072*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLiveIn = true;
1073*03ce13f7SAndroid Build Coastguard Worker emitRegisterUsage(Str, Func, this, IsLiveIn, LiveRegCount);
1074*03ce13f7SAndroid Build Coastguard Worker if (getInEdges().size()) {
1075*03ce13f7SAndroid Build Coastguard Worker Str << "\t\t\t\t/* preds=";
1076*03ce13f7SAndroid Build Coastguard Worker bool First = true;
1077*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *I : getInEdges()) {
1078*03ce13f7SAndroid Build Coastguard Worker if (!First)
1079*03ce13f7SAndroid Build Coastguard Worker Str << ",";
1080*03ce13f7SAndroid Build Coastguard Worker First = false;
1081*03ce13f7SAndroid Build Coastguard Worker Str << "$" << I->getName();
1082*03ce13f7SAndroid Build Coastguard Worker }
1083*03ce13f7SAndroid Build Coastguard Worker Str << " */\n";
1084*03ce13f7SAndroid Build Coastguard Worker }
1085*03ce13f7SAndroid Build Coastguard Worker if (getLoopNestDepth()) {
1086*03ce13f7SAndroid Build Coastguard Worker Str << "\t\t\t\t/* loop depth=" << getLoopNestDepth() << " */\n";
1087*03ce13f7SAndroid Build Coastguard Worker }
1088*03ce13f7SAndroid Build Coastguard Worker }
1089*03ce13f7SAndroid Build Coastguard Worker
1090*03ce13f7SAndroid Build Coastguard Worker for (const Inst &I : Phis) {
1091*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
1092*03ce13f7SAndroid Build Coastguard Worker continue;
1093*03ce13f7SAndroid Build Coastguard Worker // Emitting a Phi instruction should cause an error.
1094*03ce13f7SAndroid Build Coastguard Worker I.emit(Func);
1095*03ce13f7SAndroid Build Coastguard Worker }
1096*03ce13f7SAndroid Build Coastguard Worker for (const Inst &I : Insts) {
1097*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
1098*03ce13f7SAndroid Build Coastguard Worker continue;
1099*03ce13f7SAndroid Build Coastguard Worker if (I.isRedundantAssign()) {
1100*03ce13f7SAndroid Build Coastguard Worker // Usually, redundant assignments end the live range of the src variable
1101*03ce13f7SAndroid Build Coastguard Worker // and begin the live range of the dest variable, with no net effect on
1102*03ce13f7SAndroid Build Coastguard Worker // the liveness of their register. However, if the register allocator
1103*03ce13f7SAndroid Build Coastguard Worker // infers the AllowOverlap condition, then this may be a redundant
1104*03ce13f7SAndroid Build Coastguard Worker // assignment that does not end the src variable's live range, in which
1105*03ce13f7SAndroid Build Coastguard Worker // case the active variable count for that register needs to be bumped.
1106*03ce13f7SAndroid Build Coastguard Worker // That normally would have happened as part of emitLiveRangesEnded(),
1107*03ce13f7SAndroid Build Coastguard Worker // but that isn't called for redundant assignments.
1108*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = I.getDest();
1109*03ce13f7SAndroid Build Coastguard Worker if (DecorateAsm && Dest->hasReg()) {
1110*03ce13f7SAndroid Build Coastguard Worker ++LiveRegCount[Dest->getRegNum()];
1111*03ce13f7SAndroid Build Coastguard Worker if (I.isLastUse(I.getSrc(0)))
1112*03ce13f7SAndroid Build Coastguard Worker --LiveRegCount[llvm::cast<Variable>(I.getSrc(0))->getRegNum()];
1113*03ce13f7SAndroid Build Coastguard Worker }
1114*03ce13f7SAndroid Build Coastguard Worker continue;
1115*03ce13f7SAndroid Build Coastguard Worker }
1116*03ce13f7SAndroid Build Coastguard Worker I.emit(Func);
1117*03ce13f7SAndroid Build Coastguard Worker bool Printed = false;
1118*03ce13f7SAndroid Build Coastguard Worker if (DecorateAsm)
1119*03ce13f7SAndroid Build Coastguard Worker Printed = emitLiveRangesEnded(Str, Func, &I, LiveRegCount);
1120*03ce13f7SAndroid Build Coastguard Worker if (Printed || llvm::isa<InstTarget>(&I))
1121*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
1122*03ce13f7SAndroid Build Coastguard Worker updateStats(Func, &I);
1123*03ce13f7SAndroid Build Coastguard Worker }
1124*03ce13f7SAndroid Build Coastguard Worker if (DecorateAsm) {
1125*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsLiveIn = false;
1126*03ce13f7SAndroid Build Coastguard Worker emitRegisterUsage(Str, Func, this, IsLiveIn, LiveRegCount);
1127*03ce13f7SAndroid Build Coastguard Worker }
1128*03ce13f7SAndroid Build Coastguard Worker }
1129*03ce13f7SAndroid Build Coastguard Worker
emitIAS(Cfg * Func) const1130*03ce13f7SAndroid Build Coastguard Worker void CfgNode::emitIAS(Cfg *Func) const {
1131*03ce13f7SAndroid Build Coastguard Worker Func->setCurrentNode(this);
1132*03ce13f7SAndroid Build Coastguard Worker Assembler *Asm = Func->getAssembler<>();
1133*03ce13f7SAndroid Build Coastguard Worker Asm->bindCfgNodeLabel(this);
1134*03ce13f7SAndroid Build Coastguard Worker for (const Inst &I : Phis) {
1135*03ce13f7SAndroid Build Coastguard Worker if (I.isDeleted())
1136*03ce13f7SAndroid Build Coastguard Worker continue;
1137*03ce13f7SAndroid Build Coastguard Worker // Emitting a Phi instruction should cause an error.
1138*03ce13f7SAndroid Build Coastguard Worker I.emitIAS(Func);
1139*03ce13f7SAndroid Build Coastguard Worker }
1140*03ce13f7SAndroid Build Coastguard Worker
1141*03ce13f7SAndroid Build Coastguard Worker for (const Inst &I : Insts) {
1142*03ce13f7SAndroid Build Coastguard Worker if (!I.isDeleted() && !I.isRedundantAssign()) {
1143*03ce13f7SAndroid Build Coastguard Worker I.emitIAS(Func);
1144*03ce13f7SAndroid Build Coastguard Worker updateStats(Func, &I);
1145*03ce13f7SAndroid Build Coastguard Worker }
1146*03ce13f7SAndroid Build Coastguard Worker }
1147*03ce13f7SAndroid Build Coastguard Worker }
1148*03ce13f7SAndroid Build Coastguard Worker
dump(Cfg * Func) const1149*03ce13f7SAndroid Build Coastguard Worker void CfgNode::dump(Cfg *Func) const {
1150*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
1151*03ce13f7SAndroid Build Coastguard Worker return;
1152*03ce13f7SAndroid Build Coastguard Worker Func->setCurrentNode(this);
1153*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
1154*03ce13f7SAndroid Build Coastguard Worker Liveness *Liveness = Func->getLiveness();
1155*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Instructions) || Func->isVerbose(IceV_Loop))
1156*03ce13f7SAndroid Build Coastguard Worker Str << getName() << ":\n";
1157*03ce13f7SAndroid Build Coastguard Worker // Dump the loop nest depth
1158*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Loop))
1159*03ce13f7SAndroid Build Coastguard Worker Str << " // LoopNestDepth = " << getLoopNestDepth() << "\n";
1160*03ce13f7SAndroid Build Coastguard Worker // Dump list of predecessor nodes.
1161*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Preds) && !InEdges.empty()) {
1162*03ce13f7SAndroid Build Coastguard Worker Str << " // preds = ";
1163*03ce13f7SAndroid Build Coastguard Worker bool First = true;
1164*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *I : InEdges) {
1165*03ce13f7SAndroid Build Coastguard Worker if (!First)
1166*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
1167*03ce13f7SAndroid Build Coastguard Worker First = false;
1168*03ce13f7SAndroid Build Coastguard Worker Str << "%" << I->getName();
1169*03ce13f7SAndroid Build Coastguard Worker }
1170*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
1171*03ce13f7SAndroid Build Coastguard Worker }
1172*03ce13f7SAndroid Build Coastguard Worker // Dump the live-in variables.
1173*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Liveness)) {
1174*03ce13f7SAndroid Build Coastguard Worker if (Liveness != nullptr && !Liveness->getLiveIn(this).empty()) {
1175*03ce13f7SAndroid Build Coastguard Worker const LivenessBV &LiveIn = Liveness->getLiveIn(this);
1176*03ce13f7SAndroid Build Coastguard Worker Str << " // LiveIn:";
1177*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < LiveIn.size(); ++i) {
1178*03ce13f7SAndroid Build Coastguard Worker if (LiveIn[i]) {
1179*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Liveness->getVariable(i, this);
1180*03ce13f7SAndroid Build Coastguard Worker Str << " %" << Var->getName();
1181*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) {
1182*03ce13f7SAndroid Build Coastguard Worker Str << ":"
1183*03ce13f7SAndroid Build Coastguard Worker << Func->getTarget()->getRegName(Var->getRegNum(),
1184*03ce13f7SAndroid Build Coastguard Worker Var->getType());
1185*03ce13f7SAndroid Build Coastguard Worker }
1186*03ce13f7SAndroid Build Coastguard Worker }
1187*03ce13f7SAndroid Build Coastguard Worker }
1188*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
1189*03ce13f7SAndroid Build Coastguard Worker }
1190*03ce13f7SAndroid Build Coastguard Worker }
1191*03ce13f7SAndroid Build Coastguard Worker // Dump each instruction.
1192*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Instructions)) {
1193*03ce13f7SAndroid Build Coastguard Worker for (const Inst &I : Phis)
1194*03ce13f7SAndroid Build Coastguard Worker I.dumpDecorated(Func);
1195*03ce13f7SAndroid Build Coastguard Worker for (const Inst &I : Insts)
1196*03ce13f7SAndroid Build Coastguard Worker I.dumpDecorated(Func);
1197*03ce13f7SAndroid Build Coastguard Worker }
1198*03ce13f7SAndroid Build Coastguard Worker // Dump the live-out variables.
1199*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Liveness)) {
1200*03ce13f7SAndroid Build Coastguard Worker if (Liveness != nullptr && !Liveness->getLiveOut(this).empty()) {
1201*03ce13f7SAndroid Build Coastguard Worker const LivenessBV &LiveOut = Liveness->getLiveOut(this);
1202*03ce13f7SAndroid Build Coastguard Worker Str << " // LiveOut:";
1203*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < LiveOut.size(); ++i) {
1204*03ce13f7SAndroid Build Coastguard Worker if (LiveOut[i]) {
1205*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Liveness->getVariable(i, this);
1206*03ce13f7SAndroid Build Coastguard Worker Str << " %" << Var->getName();
1207*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_RegOrigins) && Var->hasReg()) {
1208*03ce13f7SAndroid Build Coastguard Worker Str << ":"
1209*03ce13f7SAndroid Build Coastguard Worker << Func->getTarget()->getRegName(Var->getRegNum(),
1210*03ce13f7SAndroid Build Coastguard Worker Var->getType());
1211*03ce13f7SAndroid Build Coastguard Worker }
1212*03ce13f7SAndroid Build Coastguard Worker }
1213*03ce13f7SAndroid Build Coastguard Worker }
1214*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
1215*03ce13f7SAndroid Build Coastguard Worker }
1216*03ce13f7SAndroid Build Coastguard Worker }
1217*03ce13f7SAndroid Build Coastguard Worker // Dump list of successor nodes.
1218*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Succs)) {
1219*03ce13f7SAndroid Build Coastguard Worker Str << " // succs = ";
1220*03ce13f7SAndroid Build Coastguard Worker bool First = true;
1221*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *I : OutEdges) {
1222*03ce13f7SAndroid Build Coastguard Worker if (!First)
1223*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
1224*03ce13f7SAndroid Build Coastguard Worker First = false;
1225*03ce13f7SAndroid Build Coastguard Worker Str << "%" << I->getName();
1226*03ce13f7SAndroid Build Coastguard Worker }
1227*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
1228*03ce13f7SAndroid Build Coastguard Worker }
1229*03ce13f7SAndroid Build Coastguard Worker }
1230*03ce13f7SAndroid Build Coastguard Worker
removeInEdge(CfgNode * In)1231*03ce13f7SAndroid Build Coastguard Worker void CfgNode::removeInEdge(CfgNode *In) {
1232*03ce13f7SAndroid Build Coastguard Worker InEdges.erase(std::find(InEdges.begin(), InEdges.end(), In));
1233*03ce13f7SAndroid Build Coastguard Worker }
1234*03ce13f7SAndroid Build Coastguard Worker
shortCircuit()1235*03ce13f7SAndroid Build Coastguard Worker CfgNode *CfgNode::shortCircuit() {
1236*03ce13f7SAndroid Build Coastguard Worker auto *Func = getCfg();
1237*03ce13f7SAndroid Build Coastguard Worker auto *Last = &getInsts().back();
1238*03ce13f7SAndroid Build Coastguard Worker Variable *Condition = nullptr;
1239*03ce13f7SAndroid Build Coastguard Worker InstBr *Br = nullptr;
1240*03ce13f7SAndroid Build Coastguard Worker if ((Br = llvm::dyn_cast<InstBr>(Last))) {
1241*03ce13f7SAndroid Build Coastguard Worker if (!Br->isUnconditional()) {
1242*03ce13f7SAndroid Build Coastguard Worker Condition = llvm::dyn_cast<Variable>(Br->getCondition());
1243*03ce13f7SAndroid Build Coastguard Worker }
1244*03ce13f7SAndroid Build Coastguard Worker }
1245*03ce13f7SAndroid Build Coastguard Worker if (Condition == nullptr)
1246*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1247*03ce13f7SAndroid Build Coastguard Worker
1248*03ce13f7SAndroid Build Coastguard Worker auto *JumpOnTrue = Br->getTargetTrue();
1249*03ce13f7SAndroid Build Coastguard Worker auto *JumpOnFalse = Br->getTargetFalse();
1250*03ce13f7SAndroid Build Coastguard Worker
1251*03ce13f7SAndroid Build Coastguard Worker bool FoundOr = false;
1252*03ce13f7SAndroid Build Coastguard Worker bool FoundAnd = false;
1253*03ce13f7SAndroid Build Coastguard Worker
1254*03ce13f7SAndroid Build Coastguard Worker InstArithmetic *TopLevelBoolOp = nullptr;
1255*03ce13f7SAndroid Build Coastguard Worker
1256*03ce13f7SAndroid Build Coastguard Worker for (auto &Inst : reverse_range(getInsts())) {
1257*03ce13f7SAndroid Build Coastguard Worker if (Inst.isDeleted())
1258*03ce13f7SAndroid Build Coastguard Worker continue;
1259*03ce13f7SAndroid Build Coastguard Worker if (Inst.getDest() == Condition) {
1260*03ce13f7SAndroid Build Coastguard Worker if (auto *Arith = llvm::dyn_cast<InstArithmetic>(&Inst)) {
1261*03ce13f7SAndroid Build Coastguard Worker
1262*03ce13f7SAndroid Build Coastguard Worker FoundOr = (Arith->getOp() == InstArithmetic::OpKind::Or);
1263*03ce13f7SAndroid Build Coastguard Worker FoundAnd = (Arith->getOp() == InstArithmetic::OpKind::And);
1264*03ce13f7SAndroid Build Coastguard Worker
1265*03ce13f7SAndroid Build Coastguard Worker if (FoundOr || FoundAnd) {
1266*03ce13f7SAndroid Build Coastguard Worker TopLevelBoolOp = Arith;
1267*03ce13f7SAndroid Build Coastguard Worker break;
1268*03ce13f7SAndroid Build Coastguard Worker }
1269*03ce13f7SAndroid Build Coastguard Worker }
1270*03ce13f7SAndroid Build Coastguard Worker }
1271*03ce13f7SAndroid Build Coastguard Worker }
1272*03ce13f7SAndroid Build Coastguard Worker
1273*03ce13f7SAndroid Build Coastguard Worker if (!TopLevelBoolOp)
1274*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1275*03ce13f7SAndroid Build Coastguard Worker
1276*03ce13f7SAndroid Build Coastguard Worker auto IsOperand = [](Inst *Instr, Operand *Opr) -> bool {
1277*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Instr->getSrcSize(); ++i) {
1278*03ce13f7SAndroid Build Coastguard Worker if (Instr->getSrc(i) == Opr)
1279*03ce13f7SAndroid Build Coastguard Worker return true;
1280*03ce13f7SAndroid Build Coastguard Worker }
1281*03ce13f7SAndroid Build Coastguard Worker return false;
1282*03ce13f7SAndroid Build Coastguard Worker };
1283*03ce13f7SAndroid Build Coastguard Worker Inst *FirstOperandDef = nullptr;
1284*03ce13f7SAndroid Build Coastguard Worker for (auto &Inst : getInsts()) {
1285*03ce13f7SAndroid Build Coastguard Worker if (IsOperand(TopLevelBoolOp, Inst.getDest())) {
1286*03ce13f7SAndroid Build Coastguard Worker FirstOperandDef = &Inst;
1287*03ce13f7SAndroid Build Coastguard Worker break;
1288*03ce13f7SAndroid Build Coastguard Worker }
1289*03ce13f7SAndroid Build Coastguard Worker }
1290*03ce13f7SAndroid Build Coastguard Worker
1291*03ce13f7SAndroid Build Coastguard Worker if (FirstOperandDef == nullptr) {
1292*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1293*03ce13f7SAndroid Build Coastguard Worker }
1294*03ce13f7SAndroid Build Coastguard Worker
1295*03ce13f7SAndroid Build Coastguard Worker // Check for side effects
1296*03ce13f7SAndroid Build Coastguard Worker auto It = Ice::instToIterator(FirstOperandDef);
1297*03ce13f7SAndroid Build Coastguard Worker while (It != getInsts().end()) {
1298*03ce13f7SAndroid Build Coastguard Worker if (It->isDeleted()) {
1299*03ce13f7SAndroid Build Coastguard Worker ++It;
1300*03ce13f7SAndroid Build Coastguard Worker continue;
1301*03ce13f7SAndroid Build Coastguard Worker }
1302*03ce13f7SAndroid Build Coastguard Worker if (llvm::isa<InstBr>(It) || llvm::isa<InstRet>(It)) {
1303*03ce13f7SAndroid Build Coastguard Worker break;
1304*03ce13f7SAndroid Build Coastguard Worker }
1305*03ce13f7SAndroid Build Coastguard Worker auto *Dest = It->getDest();
1306*03ce13f7SAndroid Build Coastguard Worker if (It->getDest() == nullptr || It->hasSideEffects() ||
1307*03ce13f7SAndroid Build Coastguard Worker !Func->getVMetadata()->isSingleBlock(Dest)) {
1308*03ce13f7SAndroid Build Coastguard Worker // Relying on short cicuit eval here.
1309*03ce13f7SAndroid Build Coastguard Worker // getVMetadata()->isSingleBlock(Dest)
1310*03ce13f7SAndroid Build Coastguard Worker // will segfault if It->getDest() == nullptr
1311*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1312*03ce13f7SAndroid Build Coastguard Worker }
1313*03ce13f7SAndroid Build Coastguard Worker It++;
1314*03ce13f7SAndroid Build Coastguard Worker }
1315*03ce13f7SAndroid Build Coastguard Worker
1316*03ce13f7SAndroid Build Coastguard Worker auto *NewNode = Func->makeNode();
1317*03ce13f7SAndroid Build Coastguard Worker NewNode->setLoopNestDepth(getLoopNestDepth());
1318*03ce13f7SAndroid Build Coastguard Worker It = Ice::instToIterator(FirstOperandDef);
1319*03ce13f7SAndroid Build Coastguard Worker It++; // Have to split after the def
1320*03ce13f7SAndroid Build Coastguard Worker
1321*03ce13f7SAndroid Build Coastguard Worker NewNode->getInsts().splice(NewNode->getInsts().begin(), getInsts(), It,
1322*03ce13f7SAndroid Build Coastguard Worker getInsts().end());
1323*03ce13f7SAndroid Build Coastguard Worker
1324*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump()) {
1325*03ce13f7SAndroid Build Coastguard Worker NewNode->setName(getName().append("_2"));
1326*03ce13f7SAndroid Build Coastguard Worker setName(getName().append("_1"));
1327*03ce13f7SAndroid Build Coastguard Worker }
1328*03ce13f7SAndroid Build Coastguard Worker
1329*03ce13f7SAndroid Build Coastguard Worker // Point edges properly
1330*03ce13f7SAndroid Build Coastguard Worker NewNode->addInEdge(this);
1331*03ce13f7SAndroid Build Coastguard Worker for (auto *Out : getOutEdges()) {
1332*03ce13f7SAndroid Build Coastguard Worker NewNode->addOutEdge(Out);
1333*03ce13f7SAndroid Build Coastguard Worker Out->addInEdge(NewNode);
1334*03ce13f7SAndroid Build Coastguard Worker }
1335*03ce13f7SAndroid Build Coastguard Worker removeAllOutEdges();
1336*03ce13f7SAndroid Build Coastguard Worker addOutEdge(NewNode);
1337*03ce13f7SAndroid Build Coastguard Worker
1338*03ce13f7SAndroid Build Coastguard Worker // Manage Phi instructions of successors
1339*03ce13f7SAndroid Build Coastguard Worker for (auto *Succ : NewNode->getOutEdges()) {
1340*03ce13f7SAndroid Build Coastguard Worker for (auto &Inst : Succ->getPhis()) {
1341*03ce13f7SAndroid Build Coastguard Worker auto *Phi = llvm::cast<InstPhi>(&Inst);
1342*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Phi->getSrcSize(); ++i) {
1343*03ce13f7SAndroid Build Coastguard Worker if (Phi->getLabel(i) == this) {
1344*03ce13f7SAndroid Build Coastguard Worker Phi->addArgument(Phi->getSrc(i), NewNode);
1345*03ce13f7SAndroid Build Coastguard Worker }
1346*03ce13f7SAndroid Build Coastguard Worker }
1347*03ce13f7SAndroid Build Coastguard Worker }
1348*03ce13f7SAndroid Build Coastguard Worker }
1349*03ce13f7SAndroid Build Coastguard Worker
1350*03ce13f7SAndroid Build Coastguard Worker // Create new Br instruction
1351*03ce13f7SAndroid Build Coastguard Worker InstBr *NewInst = nullptr;
1352*03ce13f7SAndroid Build Coastguard Worker if (FoundOr) {
1353*03ce13f7SAndroid Build Coastguard Worker addOutEdge(JumpOnTrue);
1354*03ce13f7SAndroid Build Coastguard Worker JumpOnFalse->removeInEdge(this);
1355*03ce13f7SAndroid Build Coastguard Worker NewInst =
1356*03ce13f7SAndroid Build Coastguard Worker InstBr::create(Func, FirstOperandDef->getDest(), JumpOnTrue, NewNode);
1357*03ce13f7SAndroid Build Coastguard Worker } else if (FoundAnd) {
1358*03ce13f7SAndroid Build Coastguard Worker addOutEdge(JumpOnFalse);
1359*03ce13f7SAndroid Build Coastguard Worker JumpOnTrue->removeInEdge(this);
1360*03ce13f7SAndroid Build Coastguard Worker NewInst =
1361*03ce13f7SAndroid Build Coastguard Worker InstBr::create(Func, FirstOperandDef->getDest(), NewNode, JumpOnFalse);
1362*03ce13f7SAndroid Build Coastguard Worker } else {
1363*03ce13f7SAndroid Build Coastguard Worker return nullptr;
1364*03ce13f7SAndroid Build Coastguard Worker }
1365*03ce13f7SAndroid Build Coastguard Worker
1366*03ce13f7SAndroid Build Coastguard Worker assert(NewInst != nullptr);
1367*03ce13f7SAndroid Build Coastguard Worker appendInst(NewInst);
1368*03ce13f7SAndroid Build Coastguard Worker
1369*03ce13f7SAndroid Build Coastguard Worker Operand *UnusedOperand = nullptr;
1370*03ce13f7SAndroid Build Coastguard Worker assert(TopLevelBoolOp->getSrcSize() == 2);
1371*03ce13f7SAndroid Build Coastguard Worker if (TopLevelBoolOp->getSrc(0) == FirstOperandDef->getDest())
1372*03ce13f7SAndroid Build Coastguard Worker UnusedOperand = TopLevelBoolOp->getSrc(1);
1373*03ce13f7SAndroid Build Coastguard Worker else if (TopLevelBoolOp->getSrc(1) == FirstOperandDef->getDest())
1374*03ce13f7SAndroid Build Coastguard Worker UnusedOperand = TopLevelBoolOp->getSrc(0);
1375*03ce13f7SAndroid Build Coastguard Worker assert(UnusedOperand);
1376*03ce13f7SAndroid Build Coastguard Worker
1377*03ce13f7SAndroid Build Coastguard Worker Br->replaceSource(0, UnusedOperand); // Index 0 has the condition of the Br
1378*03ce13f7SAndroid Build Coastguard Worker
1379*03ce13f7SAndroid Build Coastguard Worker TopLevelBoolOp->setDeleted();
1380*03ce13f7SAndroid Build Coastguard Worker return NewNode;
1381*03ce13f7SAndroid Build Coastguard Worker }
1382*03ce13f7SAndroid Build Coastguard Worker
1383*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1384