1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceInst.cpp - High-level instruction 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 Inst class, primarily the various subclass
12*03ce13f7SAndroid Build Coastguard Worker /// constructors and dump routines.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker
16*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.h"
17*03ce13f7SAndroid Build Coastguard Worker
18*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceInstVarIter.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceLiveness.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h"
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
26*03ce13f7SAndroid Build Coastguard Worker
27*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
28*03ce13f7SAndroid Build Coastguard Worker
29*03ce13f7SAndroid Build Coastguard Worker namespace {
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker // Using non-anonymous struct so that array_lengthof works.
32*03ce13f7SAndroid Build Coastguard Worker const struct InstArithmeticAttributes_ {
33*03ce13f7SAndroid Build Coastguard Worker const char *DisplayString;
34*03ce13f7SAndroid Build Coastguard Worker bool IsCommutative;
35*03ce13f7SAndroid Build Coastguard Worker } InstArithmeticAttributes[] = {
36*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str, commutative) {str, commutative},
37*03ce13f7SAndroid Build Coastguard Worker ICEINSTARITHMETIC_TABLE
38*03ce13f7SAndroid Build Coastguard Worker #undef X
39*03ce13f7SAndroid Build Coastguard Worker };
40*03ce13f7SAndroid Build Coastguard Worker
41*03ce13f7SAndroid Build Coastguard Worker // Using non-anonymous struct so that array_lengthof works.
42*03ce13f7SAndroid Build Coastguard Worker const struct InstCastAttributes_ {
43*03ce13f7SAndroid Build Coastguard Worker const char *DisplayString;
44*03ce13f7SAndroid Build Coastguard Worker } InstCastAttributes[] = {
45*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) {str},
46*03ce13f7SAndroid Build Coastguard Worker ICEINSTCAST_TABLE
47*03ce13f7SAndroid Build Coastguard Worker #undef X
48*03ce13f7SAndroid Build Coastguard Worker };
49*03ce13f7SAndroid Build Coastguard Worker
50*03ce13f7SAndroid Build Coastguard Worker // Using non-anonymous struct so that array_lengthof works.
51*03ce13f7SAndroid Build Coastguard Worker const struct InstFcmpAttributes_ {
52*03ce13f7SAndroid Build Coastguard Worker const char *DisplayString;
53*03ce13f7SAndroid Build Coastguard Worker } InstFcmpAttributes[] = {
54*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) {str},
55*03ce13f7SAndroid Build Coastguard Worker ICEINSTFCMP_TABLE
56*03ce13f7SAndroid Build Coastguard Worker #undef X
57*03ce13f7SAndroid Build Coastguard Worker };
58*03ce13f7SAndroid Build Coastguard Worker
59*03ce13f7SAndroid Build Coastguard Worker // Using non-anonymous struct so that array_lengthof works.
60*03ce13f7SAndroid Build Coastguard Worker const struct InstIcmpAttributes_ {
61*03ce13f7SAndroid Build Coastguard Worker const char *DisplayString;
62*03ce13f7SAndroid Build Coastguard Worker InstIcmp::ICond Reverse;
63*03ce13f7SAndroid Build Coastguard Worker } InstIcmpAttributes[] = {
64*03ce13f7SAndroid Build Coastguard Worker #define X(tag, reverse, str) {str, InstIcmp::ICond::reverse},
65*03ce13f7SAndroid Build Coastguard Worker ICEINSTICMP_TABLE
66*03ce13f7SAndroid Build Coastguard Worker #undef X
67*03ce13f7SAndroid Build Coastguard Worker };
68*03ce13f7SAndroid Build Coastguard Worker
69*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
70*03ce13f7SAndroid Build Coastguard Worker
Inst(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)71*03ce13f7SAndroid Build Coastguard Worker Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
72*03ce13f7SAndroid Build Coastguard Worker : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
73*03ce13f7SAndroid Build Coastguard Worker LiveRangesEnded(0) {
74*03ce13f7SAndroid Build Coastguard Worker Srcs.reserve(MaxSrcs);
75*03ce13f7SAndroid Build Coastguard Worker }
76*03ce13f7SAndroid Build Coastguard Worker
getInstName() const77*03ce13f7SAndroid Build Coastguard Worker const char *Inst::getInstName() const {
78*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
79*03ce13f7SAndroid Build Coastguard Worker return "???";
80*03ce13f7SAndroid Build Coastguard Worker
81*03ce13f7SAndroid Build Coastguard Worker switch (Kind) {
82*03ce13f7SAndroid Build Coastguard Worker #define X(InstrKind, name) \
83*03ce13f7SAndroid Build Coastguard Worker case InstrKind: \
84*03ce13f7SAndroid Build Coastguard Worker return name
85*03ce13f7SAndroid Build Coastguard Worker X(Unreachable, "unreachable");
86*03ce13f7SAndroid Build Coastguard Worker X(Alloca, "alloca");
87*03ce13f7SAndroid Build Coastguard Worker X(Arithmetic, "arithmetic");
88*03ce13f7SAndroid Build Coastguard Worker X(Br, "br");
89*03ce13f7SAndroid Build Coastguard Worker X(Call, "call");
90*03ce13f7SAndroid Build Coastguard Worker X(Cast, "cast");
91*03ce13f7SAndroid Build Coastguard Worker X(ExtractElement, "extractelement");
92*03ce13f7SAndroid Build Coastguard Worker X(Fcmp, "fcmp");
93*03ce13f7SAndroid Build Coastguard Worker X(Icmp, "icmp");
94*03ce13f7SAndroid Build Coastguard Worker X(Intrinsic, "intrinsic");
95*03ce13f7SAndroid Build Coastguard Worker X(InsertElement, "insertelement");
96*03ce13f7SAndroid Build Coastguard Worker X(Load, "load");
97*03ce13f7SAndroid Build Coastguard Worker X(Phi, "phi");
98*03ce13f7SAndroid Build Coastguard Worker X(Ret, "ret");
99*03ce13f7SAndroid Build Coastguard Worker X(Select, "select");
100*03ce13f7SAndroid Build Coastguard Worker X(Store, "store");
101*03ce13f7SAndroid Build Coastguard Worker X(Switch, "switch");
102*03ce13f7SAndroid Build Coastguard Worker X(Assign, "assign");
103*03ce13f7SAndroid Build Coastguard Worker X(Breakpoint, "break");
104*03ce13f7SAndroid Build Coastguard Worker X(FakeDef, "fakedef");
105*03ce13f7SAndroid Build Coastguard Worker X(FakeUse, "fakeuse");
106*03ce13f7SAndroid Build Coastguard Worker X(FakeKill, "fakekill");
107*03ce13f7SAndroid Build Coastguard Worker X(JumpTable, "jumptable");
108*03ce13f7SAndroid Build Coastguard Worker X(ShuffleVector, "shufflevector");
109*03ce13f7SAndroid Build Coastguard Worker #undef X
110*03ce13f7SAndroid Build Coastguard Worker default:
111*03ce13f7SAndroid Build Coastguard Worker assert(Kind >= Target);
112*03ce13f7SAndroid Build Coastguard Worker return "target";
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker }
115*03ce13f7SAndroid Build Coastguard Worker
116*03ce13f7SAndroid Build Coastguard Worker // Assign the instruction a new number.
renumber(Cfg * Func)117*03ce13f7SAndroid Build Coastguard Worker void Inst::renumber(Cfg *Func) {
118*03ce13f7SAndroid Build Coastguard Worker Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
119*03ce13f7SAndroid Build Coastguard Worker }
120*03ce13f7SAndroid Build Coastguard Worker
121*03ce13f7SAndroid Build Coastguard Worker // Delete the instruction if its tentative Dead flag is still set after
122*03ce13f7SAndroid Build Coastguard Worker // liveness analysis.
deleteIfDead()123*03ce13f7SAndroid Build Coastguard Worker void Inst::deleteIfDead() {
124*03ce13f7SAndroid Build Coastguard Worker if (Dead)
125*03ce13f7SAndroid Build Coastguard Worker setDeleted();
126*03ce13f7SAndroid Build Coastguard Worker }
127*03ce13f7SAndroid Build Coastguard Worker
128*03ce13f7SAndroid Build Coastguard Worker // If Src is a Variable, it returns true if this instruction ends Src's live
129*03ce13f7SAndroid Build Coastguard Worker // range. Otherwise, returns false.
isLastUse(const Operand * TestSrc) const130*03ce13f7SAndroid Build Coastguard Worker bool Inst::isLastUse(const Operand *TestSrc) const {
131*03ce13f7SAndroid Build Coastguard Worker if (LiveRangesEnded == 0)
132*03ce13f7SAndroid Build Coastguard Worker return false; // early-exit optimization
133*03ce13f7SAndroid Build Coastguard Worker if (auto *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
134*03ce13f7SAndroid Build Coastguard Worker LREndedBits Mask = LiveRangesEnded;
135*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *this) {
136*03ce13f7SAndroid Build Coastguard Worker if (Var == TestVar) {
137*03ce13f7SAndroid Build Coastguard Worker // We've found where the variable is used in the instruction.
138*03ce13f7SAndroid Build Coastguard Worker return Mask & 1;
139*03ce13f7SAndroid Build Coastguard Worker }
140*03ce13f7SAndroid Build Coastguard Worker Mask >>= 1;
141*03ce13f7SAndroid Build Coastguard Worker if (Mask == 0)
142*03ce13f7SAndroid Build Coastguard Worker return false; // another early-exit optimization
143*03ce13f7SAndroid Build Coastguard Worker }
144*03ce13f7SAndroid Build Coastguard Worker }
145*03ce13f7SAndroid Build Coastguard Worker return false;
146*03ce13f7SAndroid Build Coastguard Worker }
147*03ce13f7SAndroid Build Coastguard Worker
148*03ce13f7SAndroid Build Coastguard Worker // Given an instruction like:
149*03ce13f7SAndroid Build Coastguard Worker // a = b + c + [x,y] + e
150*03ce13f7SAndroid Build Coastguard Worker // which was created from OrigInst:
151*03ce13f7SAndroid Build Coastguard Worker // a = b + c + d + e
152*03ce13f7SAndroid Build Coastguard Worker // with SpliceAssn spliced in:
153*03ce13f7SAndroid Build Coastguard Worker // d = [x,y]
154*03ce13f7SAndroid Build Coastguard Worker //
155*03ce13f7SAndroid Build Coastguard Worker // Reconstruct the LiveRangesEnded bitmask in this instruction by combining the
156*03ce13f7SAndroid Build Coastguard Worker // LiveRangesEnded values of OrigInst and SpliceAssn. If operands d and [x,y]
157*03ce13f7SAndroid Build Coastguard Worker // contain a different number of variables, then the bitmask position for e may
158*03ce13f7SAndroid Build Coastguard Worker // be different in OrigInst and the current instruction, requiring extra shifts
159*03ce13f7SAndroid Build Coastguard Worker // and masks in the computation. In the example above, OrigInst has variable e
160*03ce13f7SAndroid Build Coastguard Worker // in bit position 3, whereas the current instruction has e in bit position 4
161*03ce13f7SAndroid Build Coastguard Worker // because [x,y] consumes 2 bitmask slots while d only consumed 1.
162*03ce13f7SAndroid Build Coastguard Worker //
163*03ce13f7SAndroid Build Coastguard Worker // Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
164*03ce13f7SAndroid Build Coastguard Worker // HasSideEffects set.
spliceLivenessInfo(Inst * OrigInst,Inst * SpliceAssn)165*03ce13f7SAndroid Build Coastguard Worker void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) {
166*03ce13f7SAndroid Build Coastguard Worker HasSideEffects |= OrigInst->HasSideEffects;
167*03ce13f7SAndroid Build Coastguard Worker HasSideEffects |= SpliceAssn->HasSideEffects;
168*03ce13f7SAndroid Build Coastguard Worker // Find the bitmask index of SpliceAssn's dest within OrigInst.
169*03ce13f7SAndroid Build Coastguard Worker Variable *SpliceDest = SpliceAssn->getDest();
170*03ce13f7SAndroid Build Coastguard Worker SizeT Index = 0;
171*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) {
172*03ce13f7SAndroid Build Coastguard Worker Operand *Src = OrigInst->getSrc(I);
173*03ce13f7SAndroid Build Coastguard Worker if (Src == SpliceDest) {
174*03ce13f7SAndroid Build Coastguard Worker LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1);
175*03ce13f7SAndroid Build Coastguard Worker LREndedBits RightMask = OrigInst->LiveRangesEnded >> (Index + 1);
176*03ce13f7SAndroid Build Coastguard Worker LiveRangesEnded = LeftMask | (SpliceAssn->LiveRangesEnded << Index) |
177*03ce13f7SAndroid Build Coastguard Worker (RightMask << (Index + getSrc(I)->getNumVars()));
178*03ce13f7SAndroid Build Coastguard Worker return;
179*03ce13f7SAndroid Build Coastguard Worker }
180*03ce13f7SAndroid Build Coastguard Worker Index += getSrc(I)->getNumVars();
181*03ce13f7SAndroid Build Coastguard Worker }
182*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Failed to find splice operand");
183*03ce13f7SAndroid Build Coastguard Worker }
184*03ce13f7SAndroid Build Coastguard Worker
isMemoryWrite() const185*03ce13f7SAndroid Build Coastguard Worker bool Inst::isMemoryWrite() const {
186*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Attempt to call base Inst::isMemoryWrite() method");
187*03ce13f7SAndroid Build Coastguard Worker }
188*03ce13f7SAndroid Build Coastguard Worker
livenessLightweight(Cfg * Func,LivenessBV & Live)189*03ce13f7SAndroid Build Coastguard Worker void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
190*03ce13f7SAndroid Build Coastguard Worker assert(!isDeleted());
191*03ce13f7SAndroid Build Coastguard Worker resetLastUses();
192*03ce13f7SAndroid Build Coastguard Worker VariablesMetadata *VMetadata = Func->getVMetadata();
193*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *this) {
194*03ce13f7SAndroid Build Coastguard Worker if (VMetadata->isMultiBlock(Var))
195*03ce13f7SAndroid Build Coastguard Worker continue;
196*03ce13f7SAndroid Build Coastguard Worker SizeT Index = Var->getIndex();
197*03ce13f7SAndroid Build Coastguard Worker if (Live[Index])
198*03ce13f7SAndroid Build Coastguard Worker continue;
199*03ce13f7SAndroid Build Coastguard Worker Live[Index] = true;
200*03ce13f7SAndroid Build Coastguard Worker setLastUse(IndexOfVarInInst(Var));
201*03ce13f7SAndroid Build Coastguard Worker }
202*03ce13f7SAndroid Build Coastguard Worker }
203*03ce13f7SAndroid Build Coastguard Worker
liveness(InstNumberT InstNumber,LivenessBV & Live,Liveness * Liveness,LiveBeginEndMap * LiveBegin,LiveBeginEndMap * LiveEnd)204*03ce13f7SAndroid Build Coastguard Worker bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
205*03ce13f7SAndroid Build Coastguard Worker Liveness *Liveness, LiveBeginEndMap *LiveBegin,
206*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap *LiveEnd) {
207*03ce13f7SAndroid Build Coastguard Worker assert(!isDeleted());
208*03ce13f7SAndroid Build Coastguard Worker
209*03ce13f7SAndroid Build Coastguard Worker Dead = false;
210*03ce13f7SAndroid Build Coastguard Worker if (Dest && !Dest->isRematerializable()) {
211*03ce13f7SAndroid Build Coastguard Worker SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
212*03ce13f7SAndroid Build Coastguard Worker if (Live[VarNum]) {
213*03ce13f7SAndroid Build Coastguard Worker if (!isDestRedefined()) {
214*03ce13f7SAndroid Build Coastguard Worker Live[VarNum] = false;
215*03ce13f7SAndroid Build Coastguard Worker if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
216*03ce13f7SAndroid Build Coastguard Worker LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
217*03ce13f7SAndroid Build Coastguard Worker }
218*03ce13f7SAndroid Build Coastguard Worker }
219*03ce13f7SAndroid Build Coastguard Worker } else {
220*03ce13f7SAndroid Build Coastguard Worker if (!hasSideEffects())
221*03ce13f7SAndroid Build Coastguard Worker Dead = true;
222*03ce13f7SAndroid Build Coastguard Worker }
223*03ce13f7SAndroid Build Coastguard Worker }
224*03ce13f7SAndroid Build Coastguard Worker if (Dead)
225*03ce13f7SAndroid Build Coastguard Worker return false;
226*03ce13f7SAndroid Build Coastguard Worker // Phi arguments only get added to Live in the predecessor node, but we still
227*03ce13f7SAndroid Build Coastguard Worker // need to update LiveRangesEnded.
228*03ce13f7SAndroid Build Coastguard Worker bool IsPhi = llvm::isa<InstPhi>(this);
229*03ce13f7SAndroid Build Coastguard Worker resetLastUses();
230*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *this) {
231*03ce13f7SAndroid Build Coastguard Worker if (Var->isRematerializable())
232*03ce13f7SAndroid Build Coastguard Worker continue;
233*03ce13f7SAndroid Build Coastguard Worker SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
234*03ce13f7SAndroid Build Coastguard Worker if (!Live[VarNum]) {
235*03ce13f7SAndroid Build Coastguard Worker setLastUse(IndexOfVarInInst(Var));
236*03ce13f7SAndroid Build Coastguard Worker if (!IsPhi) {
237*03ce13f7SAndroid Build Coastguard Worker Live[VarNum] = true;
238*03ce13f7SAndroid Build Coastguard Worker // For a variable in SSA form, its live range can end at most once in a
239*03ce13f7SAndroid Build Coastguard Worker // basic block. However, after lowering to two-address instructions, we
240*03ce13f7SAndroid Build Coastguard Worker // end up with sequences like "t=b;t+=c;a=t" where t's live range
241*03ce13f7SAndroid Build Coastguard Worker // begins and ends twice. ICE only allows a variable to have a single
242*03ce13f7SAndroid Build Coastguard Worker // liveness interval in a basic block (except for blocks where a
243*03ce13f7SAndroid Build Coastguard Worker // variable is live-in and live-out but there is a gap in the middle).
244*03ce13f7SAndroid Build Coastguard Worker // Therefore, this lowered sequence needs to represent a single
245*03ce13f7SAndroid Build Coastguard Worker // conservative live range for t. Since the instructions are being
246*03ce13f7SAndroid Build Coastguard Worker // traversed backwards, we make sure LiveEnd is only set once by
247*03ce13f7SAndroid Build Coastguard Worker // setting it only when LiveEnd[VarNum]==0 (sentinel value). Note that
248*03ce13f7SAndroid Build Coastguard Worker // it's OK to set LiveBegin multiple times because of the backwards
249*03ce13f7SAndroid Build Coastguard Worker // traversal.
250*03ce13f7SAndroid Build Coastguard Worker if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
251*03ce13f7SAndroid Build Coastguard Worker // Ideally, we would verify that VarNum wasn't already added in this
252*03ce13f7SAndroid Build Coastguard Worker // block, but this can't be done very efficiently with LiveEnd as a
253*03ce13f7SAndroid Build Coastguard Worker // vector. Instead, livenessPostprocess() verifies this after the
254*03ce13f7SAndroid Build Coastguard Worker // vector has been sorted.
255*03ce13f7SAndroid Build Coastguard Worker LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
256*03ce13f7SAndroid Build Coastguard Worker }
257*03ce13f7SAndroid Build Coastguard Worker }
258*03ce13f7SAndroid Build Coastguard Worker }
259*03ce13f7SAndroid Build Coastguard Worker }
260*03ce13f7SAndroid Build Coastguard Worker return true;
261*03ce13f7SAndroid Build Coastguard Worker }
262*03ce13f7SAndroid Build Coastguard Worker
InstAlloca(Cfg * Func,Variable * Dest,Operand * ByteCount,uint32_t AlignInBytes)263*03ce13f7SAndroid Build Coastguard Worker InstAlloca::InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
264*03ce13f7SAndroid Build Coastguard Worker uint32_t AlignInBytes)
265*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
266*03ce13f7SAndroid Build Coastguard Worker // Verify AlignInBytes is 0 or a power of 2.
267*03ce13f7SAndroid Build Coastguard Worker assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
268*03ce13f7SAndroid Build Coastguard Worker addSource(ByteCount);
269*03ce13f7SAndroid Build Coastguard Worker }
270*03ce13f7SAndroid Build Coastguard Worker
InstArithmetic(Cfg * Func,OpKind Op,Variable * Dest,Operand * Source1,Operand * Source2)271*03ce13f7SAndroid Build Coastguard Worker InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
272*03ce13f7SAndroid Build Coastguard Worker Operand *Source1, Operand *Source2)
273*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
274*03ce13f7SAndroid Build Coastguard Worker addSource(Source1);
275*03ce13f7SAndroid Build Coastguard Worker addSource(Source2);
276*03ce13f7SAndroid Build Coastguard Worker }
277*03ce13f7SAndroid Build Coastguard Worker
getInstName() const278*03ce13f7SAndroid Build Coastguard Worker const char *InstArithmetic::getInstName() const {
279*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
280*03ce13f7SAndroid Build Coastguard Worker return "???";
281*03ce13f7SAndroid Build Coastguard Worker
282*03ce13f7SAndroid Build Coastguard Worker return InstArithmeticAttributes[getOp()].DisplayString;
283*03ce13f7SAndroid Build Coastguard Worker }
284*03ce13f7SAndroid Build Coastguard Worker
getOpName(OpKind Op)285*03ce13f7SAndroid Build Coastguard Worker const char *InstArithmetic::getOpName(OpKind Op) {
286*03ce13f7SAndroid Build Coastguard Worker return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
287*03ce13f7SAndroid Build Coastguard Worker : "???";
288*03ce13f7SAndroid Build Coastguard Worker }
289*03ce13f7SAndroid Build Coastguard Worker
isCommutative() const290*03ce13f7SAndroid Build Coastguard Worker bool InstArithmetic::isCommutative() const {
291*03ce13f7SAndroid Build Coastguard Worker return InstArithmeticAttributes[getOp()].IsCommutative;
292*03ce13f7SAndroid Build Coastguard Worker }
293*03ce13f7SAndroid Build Coastguard Worker
InstAssign(Cfg * Func,Variable * Dest,Operand * Source)294*03ce13f7SAndroid Build Coastguard Worker InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
295*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Assign, 1, Dest) {
296*03ce13f7SAndroid Build Coastguard Worker addSource(Source);
297*03ce13f7SAndroid Build Coastguard Worker }
298*03ce13f7SAndroid Build Coastguard Worker
isVarAssign() const299*03ce13f7SAndroid Build Coastguard Worker bool InstAssign::isVarAssign() const { return llvm::isa<Variable>(getSrc(0)); }
300*03ce13f7SAndroid Build Coastguard Worker
301*03ce13f7SAndroid Build Coastguard Worker // If TargetTrue==TargetFalse, we turn it into an unconditional branch. This
302*03ce13f7SAndroid Build Coastguard Worker // ensures that, along with the 'switch' instruction semantics, there is at
303*03ce13f7SAndroid Build Coastguard Worker // most one edge from one node to another.
InstBr(Cfg * Func,Operand * Source,CfgNode * TargetTrue_,CfgNode * TargetFalse_)304*03ce13f7SAndroid Build Coastguard Worker InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
305*03ce13f7SAndroid Build Coastguard Worker CfgNode *TargetFalse_)
306*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
307*03ce13f7SAndroid Build Coastguard Worker TargetTrue(TargetTrue_) {
308*03ce13f7SAndroid Build Coastguard Worker if (auto *Constant = llvm::dyn_cast<ConstantInteger32>(Source)) {
309*03ce13f7SAndroid Build Coastguard Worker int32_t C32 = Constant->getValue();
310*03ce13f7SAndroid Build Coastguard Worker if (C32 != 0) {
311*03ce13f7SAndroid Build Coastguard Worker TargetFalse = TargetTrue;
312*03ce13f7SAndroid Build Coastguard Worker }
313*03ce13f7SAndroid Build Coastguard Worker TargetTrue = nullptr; // turn into unconditional version
314*03ce13f7SAndroid Build Coastguard Worker } else if (TargetTrue == TargetFalse) {
315*03ce13f7SAndroid Build Coastguard Worker TargetTrue = nullptr; // turn into unconditional version
316*03ce13f7SAndroid Build Coastguard Worker } else {
317*03ce13f7SAndroid Build Coastguard Worker addSource(Source);
318*03ce13f7SAndroid Build Coastguard Worker }
319*03ce13f7SAndroid Build Coastguard Worker }
320*03ce13f7SAndroid Build Coastguard Worker
InstBr(Cfg * Func,CfgNode * Target)321*03ce13f7SAndroid Build Coastguard Worker InstBr::InstBr(Cfg *Func, CfgNode *Target)
322*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
323*03ce13f7SAndroid Build Coastguard Worker TargetTrue(nullptr) {}
324*03ce13f7SAndroid Build Coastguard Worker
getTerminatorEdges() const325*03ce13f7SAndroid Build Coastguard Worker NodeList InstBr::getTerminatorEdges() const {
326*03ce13f7SAndroid Build Coastguard Worker NodeList OutEdges;
327*03ce13f7SAndroid Build Coastguard Worker OutEdges.reserve(TargetTrue ? 2 : 1);
328*03ce13f7SAndroid Build Coastguard Worker OutEdges.push_back(TargetFalse);
329*03ce13f7SAndroid Build Coastguard Worker if (TargetTrue)
330*03ce13f7SAndroid Build Coastguard Worker OutEdges.push_back(TargetTrue);
331*03ce13f7SAndroid Build Coastguard Worker return OutEdges;
332*03ce13f7SAndroid Build Coastguard Worker }
333*03ce13f7SAndroid Build Coastguard Worker
repointEdges(CfgNode * OldNode,CfgNode * NewNode)334*03ce13f7SAndroid Build Coastguard Worker bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
335*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
336*03ce13f7SAndroid Build Coastguard Worker if (TargetFalse == OldNode) {
337*03ce13f7SAndroid Build Coastguard Worker TargetFalse = NewNode;
338*03ce13f7SAndroid Build Coastguard Worker Found = true;
339*03ce13f7SAndroid Build Coastguard Worker }
340*03ce13f7SAndroid Build Coastguard Worker if (TargetTrue == OldNode) {
341*03ce13f7SAndroid Build Coastguard Worker TargetTrue = NewNode;
342*03ce13f7SAndroid Build Coastguard Worker Found = true;
343*03ce13f7SAndroid Build Coastguard Worker }
344*03ce13f7SAndroid Build Coastguard Worker return Found;
345*03ce13f7SAndroid Build Coastguard Worker }
346*03ce13f7SAndroid Build Coastguard Worker
InstCast(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)347*03ce13f7SAndroid Build Coastguard Worker InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
348*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
349*03ce13f7SAndroid Build Coastguard Worker addSource(Source);
350*03ce13f7SAndroid Build Coastguard Worker }
351*03ce13f7SAndroid Build Coastguard Worker
InstExtractElement(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)352*03ce13f7SAndroid Build Coastguard Worker InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
353*03ce13f7SAndroid Build Coastguard Worker Operand *Source1, Operand *Source2)
354*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
355*03ce13f7SAndroid Build Coastguard Worker addSource(Source1);
356*03ce13f7SAndroid Build Coastguard Worker addSource(Source2);
357*03ce13f7SAndroid Build Coastguard Worker }
358*03ce13f7SAndroid Build Coastguard Worker
InstFcmp(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)359*03ce13f7SAndroid Build Coastguard Worker InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
360*03ce13f7SAndroid Build Coastguard Worker Operand *Source2)
361*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
362*03ce13f7SAndroid Build Coastguard Worker addSource(Source1);
363*03ce13f7SAndroid Build Coastguard Worker addSource(Source2);
364*03ce13f7SAndroid Build Coastguard Worker }
365*03ce13f7SAndroid Build Coastguard Worker
InstIcmp(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)366*03ce13f7SAndroid Build Coastguard Worker InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
367*03ce13f7SAndroid Build Coastguard Worker Operand *Source2)
368*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
369*03ce13f7SAndroid Build Coastguard Worker addSource(Source1);
370*03ce13f7SAndroid Build Coastguard Worker addSource(Source2);
371*03ce13f7SAndroid Build Coastguard Worker }
372*03ce13f7SAndroid Build Coastguard Worker
InstInsertElement(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)373*03ce13f7SAndroid Build Coastguard Worker InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
374*03ce13f7SAndroid Build Coastguard Worker Operand *Source1, Operand *Source2,
375*03ce13f7SAndroid Build Coastguard Worker Operand *Source3)
376*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
377*03ce13f7SAndroid Build Coastguard Worker addSource(Source1);
378*03ce13f7SAndroid Build Coastguard Worker addSource(Source2);
379*03ce13f7SAndroid Build Coastguard Worker addSource(Source3);
380*03ce13f7SAndroid Build Coastguard Worker }
381*03ce13f7SAndroid Build Coastguard Worker
InstLoad(Cfg * Func,Variable * Dest,Operand * SourceAddr)382*03ce13f7SAndroid Build Coastguard Worker InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
383*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Load, 1, Dest) {
384*03ce13f7SAndroid Build Coastguard Worker addSource(SourceAddr);
385*03ce13f7SAndroid Build Coastguard Worker }
386*03ce13f7SAndroid Build Coastguard Worker
InstPhi(Cfg * Func,SizeT MaxSrcs,Variable * Dest)387*03ce13f7SAndroid Build Coastguard Worker InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
388*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
389*03ce13f7SAndroid Build Coastguard Worker Labels.reserve(MaxSrcs);
390*03ce13f7SAndroid Build Coastguard Worker }
391*03ce13f7SAndroid Build Coastguard Worker
392*03ce13f7SAndroid Build Coastguard Worker // TODO: A Switch instruction (and maybe others) can add duplicate edges. We
393*03ce13f7SAndroid Build Coastguard Worker // may want to de-dup Phis and validate consistency (i.e., the source operands
394*03ce13f7SAndroid Build Coastguard Worker // are the same for duplicate edges), though it seems the current lowering code
395*03ce13f7SAndroid Build Coastguard Worker // is OK with this situation.
addArgument(Operand * Source,CfgNode * Label)396*03ce13f7SAndroid Build Coastguard Worker void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
397*03ce13f7SAndroid Build Coastguard Worker assert(Label);
398*03ce13f7SAndroid Build Coastguard Worker Labels.push_back(Label);
399*03ce13f7SAndroid Build Coastguard Worker addSource(Source);
400*03ce13f7SAndroid Build Coastguard Worker }
401*03ce13f7SAndroid Build Coastguard Worker
402*03ce13f7SAndroid Build Coastguard Worker // Find the source operand corresponding to the incoming edge for the given
403*03ce13f7SAndroid Build Coastguard Worker // node.
getOperandForTarget(CfgNode * Target) const404*03ce13f7SAndroid Build Coastguard Worker Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
405*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getSrcSize(); ++I) {
406*03ce13f7SAndroid Build Coastguard Worker if (Labels[I] == Target)
407*03ce13f7SAndroid Build Coastguard Worker return getSrc(I);
408*03ce13f7SAndroid Build Coastguard Worker }
409*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("Phi target not found");
410*03ce13f7SAndroid Build Coastguard Worker return nullptr;
411*03ce13f7SAndroid Build Coastguard Worker }
412*03ce13f7SAndroid Build Coastguard Worker
413*03ce13f7SAndroid Build Coastguard Worker // Replace the source operand corresponding to the incoming edge for the given
414*03ce13f7SAndroid Build Coastguard Worker // node by a zero of the appropriate type.
clearOperandForTarget(CfgNode * Target)415*03ce13f7SAndroid Build Coastguard Worker void InstPhi::clearOperandForTarget(CfgNode *Target) {
416*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getSrcSize(); ++I) {
417*03ce13f7SAndroid Build Coastguard Worker if (getLabel(I) == Target) {
418*03ce13f7SAndroid Build Coastguard Worker Type Ty = Dest->getType();
419*03ce13f7SAndroid Build Coastguard Worker Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
420*03ce13f7SAndroid Build Coastguard Worker return;
421*03ce13f7SAndroid Build Coastguard Worker }
422*03ce13f7SAndroid Build Coastguard Worker }
423*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("Phi target not found");
424*03ce13f7SAndroid Build Coastguard Worker }
425*03ce13f7SAndroid Build Coastguard Worker
426*03ce13f7SAndroid Build Coastguard Worker // Updates liveness for a particular operand based on the given predecessor
427*03ce13f7SAndroid Build Coastguard Worker // edge. Doesn't mark the operand as live if the Phi instruction is dead or
428*03ce13f7SAndroid Build Coastguard Worker // deleted.
livenessPhiOperand(LivenessBV & Live,CfgNode * Target,Liveness * Liveness)429*03ce13f7SAndroid Build Coastguard Worker void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
430*03ce13f7SAndroid Build Coastguard Worker Liveness *Liveness) {
431*03ce13f7SAndroid Build Coastguard Worker if (isDeleted() || Dead)
432*03ce13f7SAndroid Build Coastguard Worker return;
433*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getSrcSize(); ++I) {
434*03ce13f7SAndroid Build Coastguard Worker if (Labels[I] == Target) {
435*03ce13f7SAndroid Build Coastguard Worker if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
436*03ce13f7SAndroid Build Coastguard Worker if (!Var->isRematerializable()) {
437*03ce13f7SAndroid Build Coastguard Worker SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
438*03ce13f7SAndroid Build Coastguard Worker if (!Live[SrcIndex]) {
439*03ce13f7SAndroid Build Coastguard Worker setLastUse(I);
440*03ce13f7SAndroid Build Coastguard Worker Live[SrcIndex] = true;
441*03ce13f7SAndroid Build Coastguard Worker }
442*03ce13f7SAndroid Build Coastguard Worker }
443*03ce13f7SAndroid Build Coastguard Worker }
444*03ce13f7SAndroid Build Coastguard Worker return;
445*03ce13f7SAndroid Build Coastguard Worker }
446*03ce13f7SAndroid Build Coastguard Worker }
447*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("Phi operand not found for specified target node");
448*03ce13f7SAndroid Build Coastguard Worker }
449*03ce13f7SAndroid Build Coastguard Worker
450*03ce13f7SAndroid Build Coastguard Worker // Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
451*03ce13f7SAndroid Build Coastguard Worker // "a=a_phi".
lower(Cfg * Func)452*03ce13f7SAndroid Build Coastguard Worker Inst *InstPhi::lower(Cfg *Func) {
453*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = getDest();
454*03ce13f7SAndroid Build Coastguard Worker assert(Dest);
455*03ce13f7SAndroid Build Coastguard Worker Variable *NewSrc = Func->makeVariable(Dest->getType());
456*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump())
457*03ce13f7SAndroid Build Coastguard Worker NewSrc->setName(Func, Dest->getName() + "_phi");
458*03ce13f7SAndroid Build Coastguard Worker if (auto *NewSrc64On32 = llvm::dyn_cast<Variable64On32>(NewSrc))
459*03ce13f7SAndroid Build Coastguard Worker NewSrc64On32->initHiLo(Func);
460*03ce13f7SAndroid Build Coastguard Worker this->Dest = NewSrc;
461*03ce13f7SAndroid Build Coastguard Worker return InstAssign::create(Func, Dest, NewSrc);
462*03ce13f7SAndroid Build Coastguard Worker }
463*03ce13f7SAndroid Build Coastguard Worker
InstRet(Cfg * Func,Operand * RetValue)464*03ce13f7SAndroid Build Coastguard Worker InstRet::InstRet(Cfg *Func, Operand *RetValue)
465*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
466*03ce13f7SAndroid Build Coastguard Worker if (RetValue)
467*03ce13f7SAndroid Build Coastguard Worker addSource(RetValue);
468*03ce13f7SAndroid Build Coastguard Worker }
469*03ce13f7SAndroid Build Coastguard Worker
InstSelect(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)470*03ce13f7SAndroid Build Coastguard Worker InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
471*03ce13f7SAndroid Build Coastguard Worker Operand *SourceTrue, Operand *SourceFalse)
472*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Select, 3, Dest) {
473*03ce13f7SAndroid Build Coastguard Worker assert(typeElementType(Condition->getType()) == IceType_i1);
474*03ce13f7SAndroid Build Coastguard Worker addSource(Condition);
475*03ce13f7SAndroid Build Coastguard Worker addSource(SourceTrue);
476*03ce13f7SAndroid Build Coastguard Worker addSource(SourceFalse);
477*03ce13f7SAndroid Build Coastguard Worker }
478*03ce13f7SAndroid Build Coastguard Worker
InstStore(Cfg * Func,Operand * Data,Operand * Addr)479*03ce13f7SAndroid Build Coastguard Worker InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
480*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Store, 3, nullptr) {
481*03ce13f7SAndroid Build Coastguard Worker addSource(Data);
482*03ce13f7SAndroid Build Coastguard Worker addSource(Addr);
483*03ce13f7SAndroid Build Coastguard Worker // The 3rd operand is a dummy placeholder for the RMW beacon.
484*03ce13f7SAndroid Build Coastguard Worker addSource(Data);
485*03ce13f7SAndroid Build Coastguard Worker }
486*03ce13f7SAndroid Build Coastguard Worker
getRmwBeacon() const487*03ce13f7SAndroid Build Coastguard Worker Variable *InstStore::getRmwBeacon() const {
488*03ce13f7SAndroid Build Coastguard Worker return llvm::dyn_cast<Variable>(getSrc(2));
489*03ce13f7SAndroid Build Coastguard Worker }
490*03ce13f7SAndroid Build Coastguard Worker
setRmwBeacon(Variable * Beacon)491*03ce13f7SAndroid Build Coastguard Worker void InstStore::setRmwBeacon(Variable *Beacon) {
492*03ce13f7SAndroid Build Coastguard Worker Dest = llvm::dyn_cast<Variable>(getData());
493*03ce13f7SAndroid Build Coastguard Worker Srcs[2] = Beacon;
494*03ce13f7SAndroid Build Coastguard Worker }
495*03ce13f7SAndroid Build Coastguard Worker
InstSwitch(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)496*03ce13f7SAndroid Build Coastguard Worker InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
497*03ce13f7SAndroid Build Coastguard Worker CfgNode *LabelDefault)
498*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
499*03ce13f7SAndroid Build Coastguard Worker NumCases(NumCases) {
500*03ce13f7SAndroid Build Coastguard Worker addSource(Source);
501*03ce13f7SAndroid Build Coastguard Worker Values = Func->allocateArrayOf<uint64_t>(NumCases);
502*03ce13f7SAndroid Build Coastguard Worker Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
503*03ce13f7SAndroid Build Coastguard Worker // Initialize in case buggy code doesn't set all entries
504*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumCases; ++I) {
505*03ce13f7SAndroid Build Coastguard Worker Values[I] = 0;
506*03ce13f7SAndroid Build Coastguard Worker Labels[I] = nullptr;
507*03ce13f7SAndroid Build Coastguard Worker }
508*03ce13f7SAndroid Build Coastguard Worker }
509*03ce13f7SAndroid Build Coastguard Worker
addBranch(SizeT CaseIndex,uint64_t Value,CfgNode * Label)510*03ce13f7SAndroid Build Coastguard Worker void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
511*03ce13f7SAndroid Build Coastguard Worker assert(CaseIndex < NumCases);
512*03ce13f7SAndroid Build Coastguard Worker Values[CaseIndex] = Value;
513*03ce13f7SAndroid Build Coastguard Worker Labels[CaseIndex] = Label;
514*03ce13f7SAndroid Build Coastguard Worker }
515*03ce13f7SAndroid Build Coastguard Worker
getTerminatorEdges() const516*03ce13f7SAndroid Build Coastguard Worker NodeList InstSwitch::getTerminatorEdges() const {
517*03ce13f7SAndroid Build Coastguard Worker NodeList OutEdges;
518*03ce13f7SAndroid Build Coastguard Worker OutEdges.reserve(NumCases + 1);
519*03ce13f7SAndroid Build Coastguard Worker assert(LabelDefault);
520*03ce13f7SAndroid Build Coastguard Worker OutEdges.push_back(LabelDefault);
521*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumCases; ++I) {
522*03ce13f7SAndroid Build Coastguard Worker assert(Labels[I]);
523*03ce13f7SAndroid Build Coastguard Worker OutEdges.push_back(Labels[I]);
524*03ce13f7SAndroid Build Coastguard Worker }
525*03ce13f7SAndroid Build Coastguard Worker std::sort(OutEdges.begin(), OutEdges.end(),
526*03ce13f7SAndroid Build Coastguard Worker [](const CfgNode *x, const CfgNode *y) {
527*03ce13f7SAndroid Build Coastguard Worker return x->getIndex() < y->getIndex();
528*03ce13f7SAndroid Build Coastguard Worker });
529*03ce13f7SAndroid Build Coastguard Worker auto Last = std::unique(OutEdges.begin(), OutEdges.end());
530*03ce13f7SAndroid Build Coastguard Worker OutEdges.erase(Last, OutEdges.end());
531*03ce13f7SAndroid Build Coastguard Worker return OutEdges;
532*03ce13f7SAndroid Build Coastguard Worker }
533*03ce13f7SAndroid Build Coastguard Worker
repointEdges(CfgNode * OldNode,CfgNode * NewNode)534*03ce13f7SAndroid Build Coastguard Worker bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
535*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
536*03ce13f7SAndroid Build Coastguard Worker if (LabelDefault == OldNode) {
537*03ce13f7SAndroid Build Coastguard Worker LabelDefault = NewNode;
538*03ce13f7SAndroid Build Coastguard Worker Found = true;
539*03ce13f7SAndroid Build Coastguard Worker }
540*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumCases; ++I) {
541*03ce13f7SAndroid Build Coastguard Worker if (Labels[I] == OldNode) {
542*03ce13f7SAndroid Build Coastguard Worker Labels[I] = NewNode;
543*03ce13f7SAndroid Build Coastguard Worker Found = true;
544*03ce13f7SAndroid Build Coastguard Worker }
545*03ce13f7SAndroid Build Coastguard Worker }
546*03ce13f7SAndroid Build Coastguard Worker return Found;
547*03ce13f7SAndroid Build Coastguard Worker }
548*03ce13f7SAndroid Build Coastguard Worker
InstUnreachable(Cfg * Func)549*03ce13f7SAndroid Build Coastguard Worker InstUnreachable::InstUnreachable(Cfg *Func)
550*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
551*03ce13f7SAndroid Build Coastguard Worker
InstFakeDef(Cfg * Func,Variable * Dest,Variable * Src)552*03ce13f7SAndroid Build Coastguard Worker InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
553*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
554*03ce13f7SAndroid Build Coastguard Worker assert(Dest);
555*03ce13f7SAndroid Build Coastguard Worker if (Src)
556*03ce13f7SAndroid Build Coastguard Worker addSource(Src);
557*03ce13f7SAndroid Build Coastguard Worker }
558*03ce13f7SAndroid Build Coastguard Worker
InstFakeUse(Cfg * Func,Variable * Src,uint32_t Weight)559*03ce13f7SAndroid Build Coastguard Worker InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight)
560*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::FakeUse, Weight, nullptr) {
561*03ce13f7SAndroid Build Coastguard Worker assert(Src);
562*03ce13f7SAndroid Build Coastguard Worker for (uint32_t i = 0; i < Weight; ++i)
563*03ce13f7SAndroid Build Coastguard Worker addSource(Src);
564*03ce13f7SAndroid Build Coastguard Worker }
565*03ce13f7SAndroid Build Coastguard Worker
InstFakeKill(Cfg * Func,const Inst * Linked)566*03ce13f7SAndroid Build Coastguard Worker InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
567*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
568*03ce13f7SAndroid Build Coastguard Worker
InstShuffleVector(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)569*03ce13f7SAndroid Build Coastguard Worker InstShuffleVector::InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0,
570*03ce13f7SAndroid Build Coastguard Worker Operand *Src1)
571*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::ShuffleVector, 2, Dest),
572*03ce13f7SAndroid Build Coastguard Worker NumIndexes(typeNumElements(Dest->getType())) {
573*03ce13f7SAndroid Build Coastguard Worker addSource(Src0);
574*03ce13f7SAndroid Build Coastguard Worker addSource(Src1);
575*03ce13f7SAndroid Build Coastguard Worker Indexes = Func->allocateArrayOf<ConstantInteger32 *>(NumIndexes);
576*03ce13f7SAndroid Build Coastguard Worker }
577*03ce13f7SAndroid Build Coastguard Worker
578*03ce13f7SAndroid Build Coastguard Worker namespace {
makeName(Cfg * Func,const SizeT Id)579*03ce13f7SAndroid Build Coastguard Worker GlobalString makeName(Cfg *Func, const SizeT Id) {
580*03ce13f7SAndroid Build Coastguard Worker const auto FuncName = Func->getFunctionName();
581*03ce13f7SAndroid Build Coastguard Worker auto *Ctx = Func->getContext();
582*03ce13f7SAndroid Build Coastguard Worker if (FuncName.hasStdString())
583*03ce13f7SAndroid Build Coastguard Worker return GlobalString::createWithString(
584*03ce13f7SAndroid Build Coastguard Worker Ctx, ".L" + FuncName.toString() + "$jumptable$__" + std::to_string(Id));
585*03ce13f7SAndroid Build Coastguard Worker return GlobalString::createWithString(
586*03ce13f7SAndroid Build Coastguard Worker Ctx, "$J" + std::to_string(FuncName.getID()) + "_" + std::to_string(Id));
587*03ce13f7SAndroid Build Coastguard Worker }
588*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
589*03ce13f7SAndroid Build Coastguard Worker
InstJumpTable(Cfg * Func,SizeT NumTargets,CfgNode * Default)590*03ce13f7SAndroid Build Coastguard Worker InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
591*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
592*03ce13f7SAndroid Build Coastguard Worker Id(Func->getTarget()->makeNextJumpTableNumber()), NumTargets(NumTargets),
593*03ce13f7SAndroid Build Coastguard Worker Name(makeName(Func, Id)), FuncName(Func->getFunctionName()) {
594*03ce13f7SAndroid Build Coastguard Worker Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
595*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumTargets; ++I) {
596*03ce13f7SAndroid Build Coastguard Worker Targets[I] = Default;
597*03ce13f7SAndroid Build Coastguard Worker }
598*03ce13f7SAndroid Build Coastguard Worker }
599*03ce13f7SAndroid Build Coastguard Worker
repointEdges(CfgNode * OldNode,CfgNode * NewNode)600*03ce13f7SAndroid Build Coastguard Worker bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
601*03ce13f7SAndroid Build Coastguard Worker bool Found = false;
602*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumTargets; ++I) {
603*03ce13f7SAndroid Build Coastguard Worker if (Targets[I] == OldNode) {
604*03ce13f7SAndroid Build Coastguard Worker Targets[I] = NewNode;
605*03ce13f7SAndroid Build Coastguard Worker Found = true;
606*03ce13f7SAndroid Build Coastguard Worker }
607*03ce13f7SAndroid Build Coastguard Worker }
608*03ce13f7SAndroid Build Coastguard Worker return Found;
609*03ce13f7SAndroid Build Coastguard Worker }
610*03ce13f7SAndroid Build Coastguard Worker
toJumpTableData(Assembler * Asm) const611*03ce13f7SAndroid Build Coastguard Worker JumpTableData InstJumpTable::toJumpTableData(Assembler *Asm) const {
612*03ce13f7SAndroid Build Coastguard Worker JumpTableData::TargetList TargetList(NumTargets);
613*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < NumTargets; ++i) {
614*03ce13f7SAndroid Build Coastguard Worker const SizeT Index = Targets[i]->getIndex();
615*03ce13f7SAndroid Build Coastguard Worker TargetList[i] = Asm->getCfgNodeLabel(Index)->getPosition();
616*03ce13f7SAndroid Build Coastguard Worker }
617*03ce13f7SAndroid Build Coastguard Worker return JumpTableData(Name, FuncName, Id, TargetList);
618*03ce13f7SAndroid Build Coastguard Worker }
619*03ce13f7SAndroid Build Coastguard Worker
getReturnType() const620*03ce13f7SAndroid Build Coastguard Worker Type InstCall::getReturnType() const {
621*03ce13f7SAndroid Build Coastguard Worker if (Dest == nullptr)
622*03ce13f7SAndroid Build Coastguard Worker return IceType_void;
623*03ce13f7SAndroid Build Coastguard Worker return Dest->getType();
624*03ce13f7SAndroid Build Coastguard Worker }
625*03ce13f7SAndroid Build Coastguard Worker
626*03ce13f7SAndroid Build Coastguard Worker // ======================== Dump routines ======================== //
627*03ce13f7SAndroid Build Coastguard Worker
dumpDecorated(const Cfg * Func) const628*03ce13f7SAndroid Build Coastguard Worker void Inst::dumpDecorated(const Cfg *Func) const {
629*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
630*03ce13f7SAndroid Build Coastguard Worker return;
631*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
632*03ce13f7SAndroid Build Coastguard Worker if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
633*03ce13f7SAndroid Build Coastguard Worker return;
634*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_InstNumbers)) {
635*03ce13f7SAndroid Build Coastguard Worker InstNumberT Number = getNumber();
636*03ce13f7SAndroid Build Coastguard Worker if (Number == NumberDeleted)
637*03ce13f7SAndroid Build Coastguard Worker Str << "[XXX]";
638*03ce13f7SAndroid Build Coastguard Worker else
639*03ce13f7SAndroid Build Coastguard Worker Str << llvm::format("[%3d]", Number);
640*03ce13f7SAndroid Build Coastguard Worker }
641*03ce13f7SAndroid Build Coastguard Worker Str << " ";
642*03ce13f7SAndroid Build Coastguard Worker if (isDeleted())
643*03ce13f7SAndroid Build Coastguard Worker Str << " //";
644*03ce13f7SAndroid Build Coastguard Worker dump(Func);
645*03ce13f7SAndroid Build Coastguard Worker dumpExtras(Func);
646*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
647*03ce13f7SAndroid Build Coastguard Worker }
648*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const649*03ce13f7SAndroid Build Coastguard Worker void Inst::dump(const Cfg *Func) const {
650*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
651*03ce13f7SAndroid Build Coastguard Worker return;
652*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
653*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
654*03ce13f7SAndroid Build Coastguard Worker Str << " =~ " << getInstName() << " ";
655*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
656*03ce13f7SAndroid Build Coastguard Worker }
657*03ce13f7SAndroid Build Coastguard Worker
dumpExtras(const Cfg * Func) const658*03ce13f7SAndroid Build Coastguard Worker void Inst::dumpExtras(const Cfg *Func) const {
659*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
660*03ce13f7SAndroid Build Coastguard Worker return;
661*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
662*03ce13f7SAndroid Build Coastguard Worker bool First = true;
663*03ce13f7SAndroid Build Coastguard Worker // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
664*03ce13f7SAndroid Build Coastguard Worker // known to end at this instruction.
665*03ce13f7SAndroid Build Coastguard Worker if (Func->isVerbose(IceV_Liveness)) {
666*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *this) {
667*03ce13f7SAndroid Build Coastguard Worker if (isLastUse(Var)) {
668*03ce13f7SAndroid Build Coastguard Worker if (First)
669*03ce13f7SAndroid Build Coastguard Worker Str << " // LIVEEND={";
670*03ce13f7SAndroid Build Coastguard Worker else
671*03ce13f7SAndroid Build Coastguard Worker Str << ",";
672*03ce13f7SAndroid Build Coastguard Worker Var->dump(Func);
673*03ce13f7SAndroid Build Coastguard Worker First = false;
674*03ce13f7SAndroid Build Coastguard Worker }
675*03ce13f7SAndroid Build Coastguard Worker }
676*03ce13f7SAndroid Build Coastguard Worker if (!First)
677*03ce13f7SAndroid Build Coastguard Worker Str << "}";
678*03ce13f7SAndroid Build Coastguard Worker }
679*03ce13f7SAndroid Build Coastguard Worker }
680*03ce13f7SAndroid Build Coastguard Worker
dumpSources(const Cfg * Func) const681*03ce13f7SAndroid Build Coastguard Worker void Inst::dumpSources(const Cfg *Func) const {
682*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
683*03ce13f7SAndroid Build Coastguard Worker return;
684*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
685*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getSrcSize(); ++I) {
686*03ce13f7SAndroid Build Coastguard Worker if (I > 0)
687*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
688*03ce13f7SAndroid Build Coastguard Worker getSrc(I)->dump(Func);
689*03ce13f7SAndroid Build Coastguard Worker }
690*03ce13f7SAndroid Build Coastguard Worker }
691*03ce13f7SAndroid Build Coastguard Worker
emitSources(const Cfg * Func) const692*03ce13f7SAndroid Build Coastguard Worker void Inst::emitSources(const Cfg *Func) const {
693*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
694*03ce13f7SAndroid Build Coastguard Worker return;
695*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrEmit();
696*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getSrcSize(); ++I) {
697*03ce13f7SAndroid Build Coastguard Worker if (I > 0)
698*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
699*03ce13f7SAndroid Build Coastguard Worker getSrc(I)->emit(Func);
700*03ce13f7SAndroid Build Coastguard Worker }
701*03ce13f7SAndroid Build Coastguard Worker }
702*03ce13f7SAndroid Build Coastguard Worker
dumpDest(const Cfg * Func) const703*03ce13f7SAndroid Build Coastguard Worker void Inst::dumpDest(const Cfg *Func) const {
704*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
705*03ce13f7SAndroid Build Coastguard Worker return;
706*03ce13f7SAndroid Build Coastguard Worker if (getDest())
707*03ce13f7SAndroid Build Coastguard Worker getDest()->dump(Func);
708*03ce13f7SAndroid Build Coastguard Worker }
709*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const710*03ce13f7SAndroid Build Coastguard Worker void InstAlloca::dump(const Cfg *Func) const {
711*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
712*03ce13f7SAndroid Build Coastguard Worker return;
713*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
714*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
715*03ce13f7SAndroid Build Coastguard Worker Str << " = alloca i8, i32 ";
716*03ce13f7SAndroid Build Coastguard Worker getSizeInBytes()->dump(Func);
717*03ce13f7SAndroid Build Coastguard Worker if (getAlignInBytes())
718*03ce13f7SAndroid Build Coastguard Worker Str << ", align " << getAlignInBytes();
719*03ce13f7SAndroid Build Coastguard Worker }
720*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const721*03ce13f7SAndroid Build Coastguard Worker void InstArithmetic::dump(const Cfg *Func) const {
722*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
723*03ce13f7SAndroid Build Coastguard Worker return;
724*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
725*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
726*03ce13f7SAndroid Build Coastguard Worker Str << " = " << getInstName() << " " << getDest()->getType() << " ";
727*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
728*03ce13f7SAndroid Build Coastguard Worker }
729*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const730*03ce13f7SAndroid Build Coastguard Worker void InstAssign::dump(const Cfg *Func) const {
731*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
732*03ce13f7SAndroid Build Coastguard Worker return;
733*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
734*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
735*03ce13f7SAndroid Build Coastguard Worker Str << " = " << getDest()->getType() << " ";
736*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
737*03ce13f7SAndroid Build Coastguard Worker }
738*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const739*03ce13f7SAndroid Build Coastguard Worker void InstBr::dump(const Cfg *Func) const {
740*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
741*03ce13f7SAndroid Build Coastguard Worker return;
742*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
743*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
744*03ce13f7SAndroid Build Coastguard Worker Str << "br ";
745*03ce13f7SAndroid Build Coastguard Worker if (!isUnconditional()) {
746*03ce13f7SAndroid Build Coastguard Worker Str << "i1 ";
747*03ce13f7SAndroid Build Coastguard Worker getCondition()->dump(Func);
748*03ce13f7SAndroid Build Coastguard Worker Str << ", label %" << getTargetTrue()->getName() << ", ";
749*03ce13f7SAndroid Build Coastguard Worker }
750*03ce13f7SAndroid Build Coastguard Worker Str << "label %" << getTargetFalse()->getName();
751*03ce13f7SAndroid Build Coastguard Worker }
752*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const753*03ce13f7SAndroid Build Coastguard Worker void InstCall::dump(const Cfg *Func) const {
754*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
755*03ce13f7SAndroid Build Coastguard Worker return;
756*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
757*03ce13f7SAndroid Build Coastguard Worker if (getDest()) {
758*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
759*03ce13f7SAndroid Build Coastguard Worker Str << " = ";
760*03ce13f7SAndroid Build Coastguard Worker }
761*03ce13f7SAndroid Build Coastguard Worker Str << "call ";
762*03ce13f7SAndroid Build Coastguard Worker if (getDest())
763*03ce13f7SAndroid Build Coastguard Worker Str << getDest()->getType();
764*03ce13f7SAndroid Build Coastguard Worker else
765*03ce13f7SAndroid Build Coastguard Worker Str << "void";
766*03ce13f7SAndroid Build Coastguard Worker Str << " ";
767*03ce13f7SAndroid Build Coastguard Worker getCallTarget()->dump(Func);
768*03ce13f7SAndroid Build Coastguard Worker Str << "(";
769*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getNumArgs(); ++I) {
770*03ce13f7SAndroid Build Coastguard Worker if (I > 0)
771*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
772*03ce13f7SAndroid Build Coastguard Worker Str << getArg(I)->getType() << " ";
773*03ce13f7SAndroid Build Coastguard Worker getArg(I)->dump(Func);
774*03ce13f7SAndroid Build Coastguard Worker }
775*03ce13f7SAndroid Build Coastguard Worker Str << ")";
776*03ce13f7SAndroid Build Coastguard Worker }
777*03ce13f7SAndroid Build Coastguard Worker
getCastName(InstCast::OpKind Kind)778*03ce13f7SAndroid Build Coastguard Worker const char *InstCast::getCastName(InstCast::OpKind Kind) {
779*03ce13f7SAndroid Build Coastguard Worker if (Kind < InstCast::OpKind::_num)
780*03ce13f7SAndroid Build Coastguard Worker return InstCastAttributes[Kind].DisplayString;
781*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("Invalid InstCast::OpKind");
782*03ce13f7SAndroid Build Coastguard Worker return "???";
783*03ce13f7SAndroid Build Coastguard Worker }
784*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const785*03ce13f7SAndroid Build Coastguard Worker void InstCast::dump(const Cfg *Func) const {
786*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
787*03ce13f7SAndroid Build Coastguard Worker return;
788*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
789*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
790*03ce13f7SAndroid Build Coastguard Worker Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
791*03ce13f7SAndroid Build Coastguard Worker << " ";
792*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
793*03ce13f7SAndroid Build Coastguard Worker Str << " to " << getDest()->getType();
794*03ce13f7SAndroid Build Coastguard Worker }
795*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const796*03ce13f7SAndroid Build Coastguard Worker void InstIcmp::dump(const Cfg *Func) const {
797*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
798*03ce13f7SAndroid Build Coastguard Worker return;
799*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
800*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
801*03ce13f7SAndroid Build Coastguard Worker Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
802*03ce13f7SAndroid Build Coastguard Worker << getSrc(0)->getType() << " ";
803*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
804*03ce13f7SAndroid Build Coastguard Worker }
805*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const806*03ce13f7SAndroid Build Coastguard Worker void InstExtractElement::dump(const Cfg *Func) const {
807*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
808*03ce13f7SAndroid Build Coastguard Worker return;
809*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
810*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
811*03ce13f7SAndroid Build Coastguard Worker Str << " = extractelement ";
812*03ce13f7SAndroid Build Coastguard Worker Str << getSrc(0)->getType() << " ";
813*03ce13f7SAndroid Build Coastguard Worker getSrc(0)->dump(Func);
814*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
815*03ce13f7SAndroid Build Coastguard Worker Str << getSrc(1)->getType() << " ";
816*03ce13f7SAndroid Build Coastguard Worker getSrc(1)->dump(Func);
817*03ce13f7SAndroid Build Coastguard Worker }
818*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const819*03ce13f7SAndroid Build Coastguard Worker void InstInsertElement::dump(const Cfg *Func) const {
820*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
821*03ce13f7SAndroid Build Coastguard Worker return;
822*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
823*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
824*03ce13f7SAndroid Build Coastguard Worker Str << " = insertelement ";
825*03ce13f7SAndroid Build Coastguard Worker Str << getSrc(0)->getType() << " ";
826*03ce13f7SAndroid Build Coastguard Worker getSrc(0)->dump(Func);
827*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
828*03ce13f7SAndroid Build Coastguard Worker Str << getSrc(1)->getType() << " ";
829*03ce13f7SAndroid Build Coastguard Worker getSrc(1)->dump(Func);
830*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
831*03ce13f7SAndroid Build Coastguard Worker Str << getSrc(2)->getType() << " ";
832*03ce13f7SAndroid Build Coastguard Worker getSrc(2)->dump(Func);
833*03ce13f7SAndroid Build Coastguard Worker }
834*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const835*03ce13f7SAndroid Build Coastguard Worker void InstFcmp::dump(const Cfg *Func) const {
836*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
837*03ce13f7SAndroid Build Coastguard Worker return;
838*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
839*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
840*03ce13f7SAndroid Build Coastguard Worker Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
841*03ce13f7SAndroid Build Coastguard Worker << getSrc(0)->getType() << " ";
842*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
843*03ce13f7SAndroid Build Coastguard Worker }
844*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const845*03ce13f7SAndroid Build Coastguard Worker void InstLoad::dump(const Cfg *Func) const {
846*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
847*03ce13f7SAndroid Build Coastguard Worker return;
848*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
849*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
850*03ce13f7SAndroid Build Coastguard Worker Type Ty = getDest()->getType();
851*03ce13f7SAndroid Build Coastguard Worker Str << " = load " << Ty << ", " << Ty << "* ";
852*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
853*03ce13f7SAndroid Build Coastguard Worker Str << ", align " << typeAlignInBytes(Ty);
854*03ce13f7SAndroid Build Coastguard Worker }
855*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const856*03ce13f7SAndroid Build Coastguard Worker void InstStore::dump(const Cfg *Func) const {
857*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
858*03ce13f7SAndroid Build Coastguard Worker return;
859*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
860*03ce13f7SAndroid Build Coastguard Worker Type Ty = getData()->getType();
861*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
862*03ce13f7SAndroid Build Coastguard Worker if (Dest)
863*03ce13f7SAndroid Build Coastguard Worker Str << " = ";
864*03ce13f7SAndroid Build Coastguard Worker Str << "store " << Ty << " ";
865*03ce13f7SAndroid Build Coastguard Worker getData()->dump(Func);
866*03ce13f7SAndroid Build Coastguard Worker Str << ", " << Ty << "* ";
867*03ce13f7SAndroid Build Coastguard Worker getStoreAddress()->dump(Func);
868*03ce13f7SAndroid Build Coastguard Worker Str << ", align " << typeAlignInBytes(Ty);
869*03ce13f7SAndroid Build Coastguard Worker if (getRmwBeacon()) {
870*03ce13f7SAndroid Build Coastguard Worker Str << ", beacon ";
871*03ce13f7SAndroid Build Coastguard Worker getRmwBeacon()->dump(Func);
872*03ce13f7SAndroid Build Coastguard Worker }
873*03ce13f7SAndroid Build Coastguard Worker }
874*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const875*03ce13f7SAndroid Build Coastguard Worker void InstSwitch::dump(const Cfg *Func) const {
876*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
877*03ce13f7SAndroid Build Coastguard Worker return;
878*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
879*03ce13f7SAndroid Build Coastguard Worker Type Ty = getComparison()->getType();
880*03ce13f7SAndroid Build Coastguard Worker Str << "switch " << Ty << " ";
881*03ce13f7SAndroid Build Coastguard Worker getSrc(0)->dump(Func);
882*03ce13f7SAndroid Build Coastguard Worker Str << ", label %" << getLabelDefault()->getName() << " [\n";
883*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getNumCases(); ++I) {
884*03ce13f7SAndroid Build Coastguard Worker Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
885*03ce13f7SAndroid Build Coastguard Worker << ", label %" << getLabel(I)->getName() << "\n";
886*03ce13f7SAndroid Build Coastguard Worker }
887*03ce13f7SAndroid Build Coastguard Worker Str << " ]";
888*03ce13f7SAndroid Build Coastguard Worker }
889*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const890*03ce13f7SAndroid Build Coastguard Worker void InstPhi::dump(const Cfg *Func) const {
891*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
892*03ce13f7SAndroid Build Coastguard Worker return;
893*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
894*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
895*03ce13f7SAndroid Build Coastguard Worker Str << " = phi " << getDest()->getType() << " ";
896*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < getSrcSize(); ++I) {
897*03ce13f7SAndroid Build Coastguard Worker if (I > 0)
898*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
899*03ce13f7SAndroid Build Coastguard Worker Str << "[ ";
900*03ce13f7SAndroid Build Coastguard Worker getSrc(I)->dump(Func);
901*03ce13f7SAndroid Build Coastguard Worker Str << ", %" << Labels[I]->getName() << " ]";
902*03ce13f7SAndroid Build Coastguard Worker }
903*03ce13f7SAndroid Build Coastguard Worker }
904*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const905*03ce13f7SAndroid Build Coastguard Worker void InstRet::dump(const Cfg *Func) const {
906*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
907*03ce13f7SAndroid Build Coastguard Worker return;
908*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
909*03ce13f7SAndroid Build Coastguard Worker Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
910*03ce13f7SAndroid Build Coastguard Worker Str << "ret " << Ty;
911*03ce13f7SAndroid Build Coastguard Worker if (hasRetValue()) {
912*03ce13f7SAndroid Build Coastguard Worker Str << " ";
913*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
914*03ce13f7SAndroid Build Coastguard Worker }
915*03ce13f7SAndroid Build Coastguard Worker }
916*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const917*03ce13f7SAndroid Build Coastguard Worker void InstSelect::dump(const Cfg *Func) const {
918*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
919*03ce13f7SAndroid Build Coastguard Worker return;
920*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
921*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
922*03ce13f7SAndroid Build Coastguard Worker Operand *Condition = getCondition();
923*03ce13f7SAndroid Build Coastguard Worker Operand *TrueOp = getTrueOperand();
924*03ce13f7SAndroid Build Coastguard Worker Operand *FalseOp = getFalseOperand();
925*03ce13f7SAndroid Build Coastguard Worker Str << " = select " << Condition->getType() << " ";
926*03ce13f7SAndroid Build Coastguard Worker Condition->dump(Func);
927*03ce13f7SAndroid Build Coastguard Worker Str << ", " << TrueOp->getType() << " ";
928*03ce13f7SAndroid Build Coastguard Worker TrueOp->dump(Func);
929*03ce13f7SAndroid Build Coastguard Worker Str << ", " << FalseOp->getType() << " ";
930*03ce13f7SAndroid Build Coastguard Worker FalseOp->dump(Func);
931*03ce13f7SAndroid Build Coastguard Worker }
932*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const933*03ce13f7SAndroid Build Coastguard Worker void InstUnreachable::dump(const Cfg *Func) const {
934*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
935*03ce13f7SAndroid Build Coastguard Worker return;
936*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
937*03ce13f7SAndroid Build Coastguard Worker Str << "unreachable";
938*03ce13f7SAndroid Build Coastguard Worker }
939*03ce13f7SAndroid Build Coastguard Worker
emit(const Cfg * Func) const940*03ce13f7SAndroid Build Coastguard Worker void InstFakeDef::emit(const Cfg *Func) const {
941*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
942*03ce13f7SAndroid Build Coastguard Worker return;
943*03ce13f7SAndroid Build Coastguard Worker // Go ahead and "emit" these for now, since they are relatively rare.
944*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrEmit();
945*03ce13f7SAndroid Build Coastguard Worker Str << "\t# ";
946*03ce13f7SAndroid Build Coastguard Worker getDest()->emit(Func);
947*03ce13f7SAndroid Build Coastguard Worker Str << " = def.pseudo";
948*03ce13f7SAndroid Build Coastguard Worker if (getSrcSize() > 0)
949*03ce13f7SAndroid Build Coastguard Worker Str << " ";
950*03ce13f7SAndroid Build Coastguard Worker emitSources(Func);
951*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
952*03ce13f7SAndroid Build Coastguard Worker }
953*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const954*03ce13f7SAndroid Build Coastguard Worker void InstFakeDef::dump(const Cfg *Func) const {
955*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
956*03ce13f7SAndroid Build Coastguard Worker return;
957*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
958*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
959*03ce13f7SAndroid Build Coastguard Worker Str << " = def.pseudo ";
960*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
961*03ce13f7SAndroid Build Coastguard Worker }
962*03ce13f7SAndroid Build Coastguard Worker
emit(const Cfg * Func) const963*03ce13f7SAndroid Build Coastguard Worker void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
964*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const965*03ce13f7SAndroid Build Coastguard Worker void InstFakeUse::dump(const Cfg *Func) const {
966*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
967*03ce13f7SAndroid Build Coastguard Worker return;
968*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
969*03ce13f7SAndroid Build Coastguard Worker Str << "use.pseudo ";
970*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
971*03ce13f7SAndroid Build Coastguard Worker }
972*03ce13f7SAndroid Build Coastguard Worker
emit(const Cfg * Func) const973*03ce13f7SAndroid Build Coastguard Worker void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
974*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const975*03ce13f7SAndroid Build Coastguard Worker void InstFakeKill::dump(const Cfg *Func) const {
976*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
977*03ce13f7SAndroid Build Coastguard Worker return;
978*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
979*03ce13f7SAndroid Build Coastguard Worker if (Linked->isDeleted())
980*03ce13f7SAndroid Build Coastguard Worker Str << "// ";
981*03ce13f7SAndroid Build Coastguard Worker Str << "kill.pseudo scratch_regs";
982*03ce13f7SAndroid Build Coastguard Worker }
983*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const984*03ce13f7SAndroid Build Coastguard Worker void InstShuffleVector::dump(const Cfg *Func) const {
985*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
986*03ce13f7SAndroid Build Coastguard Worker return;
987*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
988*03ce13f7SAndroid Build Coastguard Worker Str << "shufflevector ";
989*03ce13f7SAndroid Build Coastguard Worker dumpDest(Func);
990*03ce13f7SAndroid Build Coastguard Worker Str << " = ";
991*03ce13f7SAndroid Build Coastguard Worker dumpSources(Func);
992*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumIndexes; ++I) {
993*03ce13f7SAndroid Build Coastguard Worker Str << ", ";
994*03ce13f7SAndroid Build Coastguard Worker Indexes[I]->dump(Func);
995*03ce13f7SAndroid Build Coastguard Worker }
996*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
997*03ce13f7SAndroid Build Coastguard Worker }
998*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const999*03ce13f7SAndroid Build Coastguard Worker void InstJumpTable::dump(const Cfg *Func) const {
1000*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
1001*03ce13f7SAndroid Build Coastguard Worker return;
1002*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
1003*03ce13f7SAndroid Build Coastguard Worker Str << "jump table [";
1004*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumTargets; ++I)
1005*03ce13f7SAndroid Build Coastguard Worker Str << "\n " << Targets[I]->getName();
1006*03ce13f7SAndroid Build Coastguard Worker Str << "\n ]";
1007*03ce13f7SAndroid Build Coastguard Worker }
1008*03ce13f7SAndroid Build Coastguard Worker
dump(const Cfg * Func) const1009*03ce13f7SAndroid Build Coastguard Worker void InstTarget::dump(const Cfg *Func) const {
1010*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
1011*03ce13f7SAndroid Build Coastguard Worker return;
1012*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Func->getContext()->getStrDump();
1013*03ce13f7SAndroid Build Coastguard Worker Str << "[TARGET] ";
1014*03ce13f7SAndroid Build Coastguard Worker Inst::dump(Func);
1015*03ce13f7SAndroid Build Coastguard Worker }
1016*03ce13f7SAndroid Build Coastguard Worker
InstBreakpoint(Cfg * Func)1017*03ce13f7SAndroid Build Coastguard Worker InstBreakpoint::InstBreakpoint(Cfg *Func)
1018*03ce13f7SAndroid Build Coastguard Worker : InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
1019*03ce13f7SAndroid Build Coastguard Worker
reverseConditionAndOperands()1020*03ce13f7SAndroid Build Coastguard Worker void InstIcmp::reverseConditionAndOperands() {
1021*03ce13f7SAndroid Build Coastguard Worker Condition = InstIcmpAttributes[Condition].Reverse;
1022*03ce13f7SAndroid Build Coastguard Worker std::swap(Srcs[0], Srcs[1]);
1023*03ce13f7SAndroid Build Coastguard Worker }
1024*03ce13f7SAndroid Build Coastguard Worker
checkForRedundantAssign(const Variable * Dest,const Operand * Source)1025*03ce13f7SAndroid Build Coastguard Worker bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
1026*03ce13f7SAndroid Build Coastguard Worker const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
1027*03ce13f7SAndroid Build Coastguard Worker if (SrcVar == nullptr)
1028*03ce13f7SAndroid Build Coastguard Worker return false;
1029*03ce13f7SAndroid Build Coastguard Worker if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
1030*03ce13f7SAndroid Build Coastguard Worker // TODO: On x86-64, instructions like "mov eax, eax" are used to clear the
1031*03ce13f7SAndroid Build Coastguard Worker // upper 32 bits of rax. We need to recognize and preserve these.
1032*03ce13f7SAndroid Build Coastguard Worker return true;
1033*03ce13f7SAndroid Build Coastguard Worker }
1034*03ce13f7SAndroid Build Coastguard Worker if (!Dest->hasReg() && !SrcVar->hasReg()) {
1035*03ce13f7SAndroid Build Coastguard Worker if (!Dest->hasStackOffset() || !SrcVar->hasStackOffset()) {
1036*03ce13f7SAndroid Build Coastguard Worker // If called before stack slots have been assigned (i.e. as part of the
1037*03ce13f7SAndroid Build Coastguard Worker // dump() routine), conservatively return false.
1038*03ce13f7SAndroid Build Coastguard Worker return false;
1039*03ce13f7SAndroid Build Coastguard Worker }
1040*03ce13f7SAndroid Build Coastguard Worker if (Dest->getStackOffset() != SrcVar->getStackOffset()) {
1041*03ce13f7SAndroid Build Coastguard Worker return false;
1042*03ce13f7SAndroid Build Coastguard Worker }
1043*03ce13f7SAndroid Build Coastguard Worker return true;
1044*03ce13f7SAndroid Build Coastguard Worker }
1045*03ce13f7SAndroid Build Coastguard Worker // For a "v=t" assignment where t has a register, v has a stack slot, and v
1046*03ce13f7SAndroid Build Coastguard Worker // has a LinkedTo stack root, and v and t share the same LinkedTo root, return
1047*03ce13f7SAndroid Build Coastguard Worker // true. This is because this assignment is effectively reassigning the same
1048*03ce13f7SAndroid Build Coastguard Worker // value to the original LinkedTo stack root.
1049*03ce13f7SAndroid Build Coastguard Worker if (SrcVar->hasReg() && Dest->hasStackOffset() &&
1050*03ce13f7SAndroid Build Coastguard Worker Dest->getLinkedToStackRoot() != nullptr &&
1051*03ce13f7SAndroid Build Coastguard Worker Dest->getLinkedToRoot() == SrcVar->getLinkedToRoot()) {
1052*03ce13f7SAndroid Build Coastguard Worker return true;
1053*03ce13f7SAndroid Build Coastguard Worker }
1054*03ce13f7SAndroid Build Coastguard Worker return false;
1055*03ce13f7SAndroid Build Coastguard Worker }
1056*03ce13f7SAndroid Build Coastguard Worker
1057*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1058