blob: 3327455f21429ee9a374ca5151f83d0a2a224c84 [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceInst.cpp - High-level instruction implementation ----===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Inst class, primarily the various
11// subclass constructors and dump routines.
12//
13//===----------------------------------------------------------------------===//
14
15#include "IceCfg.h"
16#include "IceCfgNode.h"
17#include "IceInst.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070018#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070019#include "IceOperand.h"
20
21namespace Ice {
22
23namespace {
24
25// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070026const struct InstArithmeticAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070027 const char *DisplayString;
28 bool IsCommutative;
29} InstArithmeticAttributes[] = {
30#define X(tag, str, commutative) \
31 { str, commutative } \
32 ,
Jim Stichnothdd842db2015-01-27 12:53:53 -080033 ICEINSTARITHMETIC_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070034#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080035};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070036
37// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070038const struct InstCastAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070039 const char *DisplayString;
40} InstCastAttributes[] = {
41#define X(tag, str) \
42 { str } \
43 ,
Jim Stichnothdd842db2015-01-27 12:53:53 -080044 ICEINSTCAST_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070045#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080046};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070047
48// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070049const struct InstFcmpAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070050 const char *DisplayString;
51} InstFcmpAttributes[] = {
52#define X(tag, str) \
53 { str } \
54 ,
Jim Stichnothdd842db2015-01-27 12:53:53 -080055 ICEINSTFCMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080057};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058
59// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070060const struct InstIcmpAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070061 const char *DisplayString;
62} InstIcmpAttributes[] = {
63#define X(tag, str) \
64 { str } \
65 ,
Jim Stichnothdd842db2015-01-27 12:53:53 -080066 ICEINSTICMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080068};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070069
70} // end of anonymous namespace
71
72Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
Jim Stichnothd97c7df2014-06-04 11:57:08 -070073 : Kind(Kind), Number(Func->newInstNumber()), Deleted(false), Dead(false),
Jim Stichnoth47752552014-10-13 17:15:08 -070074 HasSideEffects(false), IsDestNonKillable(false), Dest(Dest),
75 MaxSrcs(MaxSrcs), NumSrcs(0),
Jim Stichnothd97c7df2014-06-04 11:57:08 -070076 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)), LiveRangesEnded(0) {}
77
78// Assign the instruction a new number.
79void Inst::renumber(Cfg *Func) {
80 Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
81}
82
83// Delete the instruction if its tentative Dead flag is still set
84// after liveness analysis.
85void Inst::deleteIfDead() {
86 if (Dead)
87 setDeleted();
88}
89
90// If Src is a Variable, it returns true if this instruction ends
91// Src's live range. Otherwise, returns false.
92bool Inst::isLastUse(const Operand *TestSrc) const {
93 if (LiveRangesEnded == 0)
94 return false; // early-exit optimization
95 if (const Variable *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
96 LREndedBits Mask = LiveRangesEnded;
97 for (SizeT I = 0; I < getSrcSize(); ++I) {
98 Operand *Src = getSrc(I);
99 SizeT NumVars = Src->getNumVars();
100 for (SizeT J = 0; J < NumVars; ++J) {
101 const Variable *Var = Src->getVar(J);
102 if (Var == TestVar) {
103 // We've found where the variable is used in the instruction.
104 return Mask & 1;
105 }
106 Mask >>= 1;
107 if (Mask == 0)
108 return false; // another early-exit optimization
109 }
110 }
111 }
112 return false;
113}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700114
Jim Stichnoth47752552014-10-13 17:15:08 -0700115void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700116 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700117 resetLastUses();
Jim Stichnoth47752552014-10-13 17:15:08 -0700118 VariablesMetadata *VMetadata = Func->getVMetadata();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700119 SizeT VarIndex = 0;
120 for (SizeT I = 0; I < getSrcSize(); ++I) {
121 Operand *Src = getSrc(I);
122 SizeT NumVars = Src->getNumVars();
123 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700124 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700125 if (VMetadata->isMultiBlock(Var))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700126 continue;
127 SizeT Index = Var->getIndex();
128 if (Live[Index])
129 continue;
130 Live[Index] = true;
131 setLastUse(VarIndex);
132 }
133 }
134}
135
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700136bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
Jim Stichnoth47752552014-10-13 17:15:08 -0700137 Liveness *Liveness, LiveBeginEndMap *LiveBegin,
138 LiveBeginEndMap *LiveEnd) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700139 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700140
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700141 Dead = false;
142 if (Dest) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700143 SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700144 if (Live[VarNum]) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700145 if (!isDestNonKillable()) {
146 Live[VarNum] = false;
147 if (LiveBegin) {
148 LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
149 }
150 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700151 } else {
152 if (!hasSideEffects())
153 Dead = true;
154 }
155 }
156 if (Dead)
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700157 return false;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700158 // Phi arguments only get added to Live in the predecessor node, but
159 // we still need to update LiveRangesEnded.
160 bool IsPhi = llvm::isa<InstPhi>(this);
161 resetLastUses();
162 SizeT VarIndex = 0;
163 for (SizeT I = 0; I < getSrcSize(); ++I) {
164 Operand *Src = getSrc(I);
165 SizeT NumVars = Src->getNumVars();
166 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
167 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700168 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700169 if (!Live[VarNum]) {
170 setLastUse(VarIndex);
171 if (!IsPhi) {
172 Live[VarNum] = true;
173 // For a variable in SSA form, its live range can end at
174 // most once in a basic block. However, after lowering to
175 // two-address instructions, we end up with sequences like
176 // "t=b;t+=c;a=t" where t's live range begins and ends
177 // twice. ICE only allows a variable to have a single
178 // liveness interval in a basic block (except for blocks
179 // where a variable is live-in and live-out but there is a
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800180 // gap in the middle). Therefore, this lowered sequence
181 // needs to represent a single conservative live range for
182 // t. Since the instructions are being traversed backwards,
183 // we make sure LiveEnd is only set once by setting it only
184 // when LiveEnd[VarNum]==0 (sentinel value). Note that it's
185 // OK to set LiveBegin multiple times because of the
186 // backwards traversal.
Jim Stichnoth47752552014-10-13 17:15:08 -0700187 if (LiveEnd) {
188 // Ideally, we would verify that VarNum wasn't already
189 // added in this block, but this can't be done very
190 // efficiently with LiveEnd as a vector. Instead,
191 // livenessPostprocess() verifies this after the vector
192 // has been sorted.
193 LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700194 }
195 }
196 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197 }
198 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700199 return true;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700200}
201
202InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
203 Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700204 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700205 // Verify AlignInBytes is 0 or a power of 2.
206 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
207 addSource(ByteCount);
208}
209
210InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
211 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700212 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700213 addSource(Source1);
214 addSource(Source2);
215}
216
Karl Schimpfd6064a12014-08-27 15:34:58 -0700217const char *InstArithmetic::getOpName(OpKind Op) {
218 size_t OpIndex = static_cast<size_t>(Op);
219 return OpIndex < InstArithmetic::_num
220 ? InstArithmeticAttributes[OpIndex].DisplayString
221 : "???";
222}
223
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700224bool InstArithmetic::isCommutative() const {
225 return InstArithmeticAttributes[getOp()].IsCommutative;
226}
227
228InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700229 : InstHighLevel(Func, Inst::Assign, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700230 addSource(Source);
231}
232
233// If TargetTrue==TargetFalse, we turn it into an unconditional
234// branch. This ensures that, along with the 'switch' instruction
235// semantics, there is at most one edge from one node to another.
236InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
237 CfgNode *TargetFalse)
Jim Stichnothae953202014-12-20 06:17:49 -0800238 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700239 TargetTrue(TargetTrue) {
240 if (TargetTrue == TargetFalse) {
Jim Stichnothae953202014-12-20 06:17:49 -0800241 TargetTrue = nullptr; // turn into unconditional version
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700242 } else {
243 addSource(Source);
244 }
245}
246
247InstBr::InstBr(Cfg *Func, CfgNode *Target)
Jim Stichnothae953202014-12-20 06:17:49 -0800248 : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
249 TargetTrue(nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700250
251NodeList InstBr::getTerminatorEdges() const {
252 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800253 OutEdges.reserve(TargetTrue ? 2 : 1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700254 OutEdges.push_back(TargetFalse);
255 if (TargetTrue)
256 OutEdges.push_back(TargetTrue);
257 return OutEdges;
258}
259
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700260bool InstBr::repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
261 if (TargetFalse == OldNode) {
262 TargetFalse = NewNode;
263 return true;
264 } else if (TargetTrue == OldNode) {
265 TargetTrue = NewNode;
266 return true;
267 }
268 return false;
269}
270
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700271InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700272 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700273 addSource(Source);
274}
275
Matt Wala49889232014-07-18 12:45:09 -0700276InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
277 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700278 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700279 addSource(Source1);
280 addSource(Source2);
281}
282
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700283InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
284 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700285 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700286 addSource(Source1);
287 addSource(Source2);
288}
289
290InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
291 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700292 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700293 addSource(Source1);
294 addSource(Source2);
295}
296
Matt Wala49889232014-07-18 12:45:09 -0700297InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
298 Operand *Source1, Operand *Source2,
299 Operand *Source3)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700300 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700301 addSource(Source1);
302 addSource(Source2);
303 addSource(Source3);
304}
305
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700306InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700307 : InstHighLevel(Func, Inst::Load, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700308 addSource(SourceAddr);
309}
310
311InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700312 : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700313 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs);
314}
315
316// TODO: A Switch instruction (and maybe others) can add duplicate
317// edges. We may want to de-dup Phis and validate consistency (i.e.,
318// the source operands are the same for duplicate edges), though it
319// seems the current lowering code is OK with this situation.
320void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
321 Labels[getSrcSize()] = Label;
322 addSource(Source);
323}
324
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700325// Find the source operand corresponding to the incoming edge for the
326// given node. TODO: This uses a linear-time search, which could be
327// improved if it becomes a problem.
328Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
329 for (SizeT I = 0; I < getSrcSize(); ++I) {
330 if (Labels[I] == Target)
331 return getSrc(I);
332 }
333 llvm_unreachable("Phi target not found");
Jim Stichnothae953202014-12-20 06:17:49 -0800334 return nullptr;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700335}
336
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700337// Updates liveness for a particular operand based on the given
338// predecessor edge. Doesn't mark the operand as live if the Phi
339// instruction is dead or deleted.
Jim Stichnoth47752552014-10-13 17:15:08 -0700340void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700341 Liveness *Liveness) {
342 if (isDeleted() || Dead)
343 return;
344 for (SizeT I = 0; I < getSrcSize(); ++I) {
345 if (Labels[I] == Target) {
346 if (Variable *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700347 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700348 if (!Live[SrcIndex]) {
349 setLastUse(I);
350 Live[SrcIndex] = true;
351 }
352 }
353 return;
354 }
355 }
356 llvm_unreachable("Phi operand not found for specified target node");
357}
358
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700359// Change "a=phi(...)" to "a_phi=phi(...)" and return a new
360// instruction "a=a_phi".
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700361Inst *InstPhi::lower(Cfg *Func) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700362 Variable *Dest = getDest();
363 assert(Dest);
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800364 Variable *NewSrc = Func->makeVariable(Dest->getType());
365 if (ALLOW_DUMP)
366 NewSrc->setName(Func, Dest->getName(Func) + "_phi");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700367 this->Dest = NewSrc;
Jim Stichnothad403532014-09-25 12:44:17 -0700368 return InstAssign::create(Func, Dest, NewSrc);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700369}
370
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700371InstRet::InstRet(Cfg *Func, Operand *RetValue)
Jim Stichnothae953202014-12-20 06:17:49 -0800372 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700373 if (RetValue)
374 addSource(RetValue);
375}
376
377InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
378 Operand *SourceTrue, Operand *SourceFalse)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700379 : InstHighLevel(Func, Inst::Select, 3, Dest) {
Matt Wala9cb61e22014-07-24 09:44:42 -0700380 assert(typeElementType(Condition->getType()) == IceType_i1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700381 addSource(Condition);
382 addSource(SourceTrue);
383 addSource(SourceFalse);
384}
385
386InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
Jim Stichnothae953202014-12-20 06:17:49 -0800387 : InstHighLevel(Func, Inst::Store, 2, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700388 addSource(Data);
389 addSource(Addr);
390}
391
392InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
393 CfgNode *LabelDefault)
Jim Stichnothae953202014-12-20 06:17:49 -0800394 : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700395 NumCases(NumCases) {
396 addSource(Source);
397 Values = Func->allocateArrayOf<uint64_t>(NumCases);
398 Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
399 // Initialize in case buggy code doesn't set all entries
400 for (SizeT I = 0; I < NumCases; ++I) {
401 Values[I] = 0;
Jim Stichnothae953202014-12-20 06:17:49 -0800402 Labels[I] = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700403 }
404}
405
406void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
407 assert(CaseIndex < NumCases);
408 Values[CaseIndex] = Value;
409 Labels[CaseIndex] = Label;
410}
411
412NodeList InstSwitch::getTerminatorEdges() const {
413 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800414 OutEdges.reserve(NumCases + 1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700415 OutEdges.push_back(LabelDefault);
416 for (SizeT I = 0; I < NumCases; ++I) {
417 OutEdges.push_back(Labels[I]);
418 }
419 return OutEdges;
420}
421
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700422bool InstSwitch::repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
423 if (LabelDefault == OldNode) {
424 LabelDefault = NewNode;
425 return true;
426 }
427 for (SizeT I = 0; I < NumCases; ++I) {
428 if (Labels[I] == OldNode) {
429 Labels[I] = NewNode;
430 return true;
431 }
432 }
433 return false;
434}
435
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700436InstUnreachable::InstUnreachable(Cfg *Func)
Jim Stichnothae953202014-12-20 06:17:49 -0800437 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700438
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700439InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700440 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700441 assert(Dest);
442 if (Src)
443 addSource(Src);
444}
445
446InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src)
Jim Stichnothae953202014-12-20 06:17:49 -0800447 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700448 assert(Src);
449 addSource(Src);
450}
451
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800452InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
Jim Stichnothae953202014-12-20 06:17:49 -0800453 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700454
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800455Type InstCall::getReturnType() const {
Jim Stichnothae953202014-12-20 06:17:49 -0800456 if (Dest == nullptr)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800457 return IceType_void;
458 return Dest->getType();
459}
460
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700461// ======================== Dump routines ======================== //
462
463void Inst::dumpDecorated(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800464 if (!ALLOW_DUMP)
465 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700466 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800467 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700468 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800469 if (Func->isVerbose(IceV_InstNumbers)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700470 char buf[30];
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700471 InstNumberT Number = getNumber();
472 if (Number == NumberDeleted)
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700473 snprintf(buf, llvm::array_lengthof(buf), "[XXX]");
474 else
475 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number);
476 Str << buf;
477 }
478 Str << " ";
479 if (isDeleted())
480 Str << " //";
481 dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700482 dumpExtras(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700483 Str << "\n";
484}
485
486void Inst::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800487 if (!ALLOW_DUMP)
488 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700489 Ostream &Str = Func->getContext()->getStrDump();
490 dumpDest(Func);
491 Str << " =~ ";
492 dumpSources(Func);
493}
494
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700495void Inst::dumpExtras(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800496 if (!ALLOW_DUMP)
497 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700498 Ostream &Str = Func->getContext()->getStrDump();
499 bool First = true;
500 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges
501 // are known to end at this instruction.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800502 if (Func->isVerbose(IceV_Liveness)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700503 for (SizeT I = 0; I < getSrcSize(); ++I) {
504 Operand *Src = getSrc(I);
505 SizeT NumVars = Src->getNumVars();
506 for (SizeT J = 0; J < NumVars; ++J) {
507 const Variable *Var = Src->getVar(J);
508 if (isLastUse(Var)) {
509 if (First)
510 Str << " // LIVEEND={";
511 else
512 Str << ",";
513 Var->dump(Func);
514 First = false;
515 }
516 }
517 }
518 if (!First)
519 Str << "}";
520 }
521}
522
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700523void Inst::dumpSources(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800524 if (!ALLOW_DUMP)
525 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700526 Ostream &Str = Func->getContext()->getStrDump();
527 for (SizeT I = 0; I < getSrcSize(); ++I) {
528 if (I > 0)
529 Str << ", ";
530 getSrc(I)->dump(Func);
531 }
532}
533
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700534void Inst::emitSources(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800535 if (!ALLOW_DUMP)
536 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700537 Ostream &Str = Func->getContext()->getStrEmit();
538 for (SizeT I = 0; I < getSrcSize(); ++I) {
539 if (I > 0)
540 Str << ", ";
541 getSrc(I)->emit(Func);
542 }
543}
544
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700545void Inst::dumpDest(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800546 if (!ALLOW_DUMP)
547 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700548 if (getDest())
549 getDest()->dump(Func);
550}
551
552void InstAlloca::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800553 if (!ALLOW_DUMP)
554 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700555 Ostream &Str = Func->getContext()->getStrDump();
556 dumpDest(Func);
557 Str << " = alloca i8, i32 ";
558 getSizeInBytes()->dump(Func);
Jim Stichnoth72a8f8d2014-09-08 17:56:50 -0700559 if (getAlignInBytes())
560 Str << ", align " << getAlignInBytes();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700561}
562
563void InstArithmetic::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800564 if (!ALLOW_DUMP)
565 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700566 Ostream &Str = Func->getContext()->getStrDump();
567 dumpDest(Func);
568 Str << " = " << InstArithmeticAttributes[getOp()].DisplayString << " "
569 << getDest()->getType() << " ";
570 dumpSources(Func);
571}
572
573void InstAssign::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800574 if (!ALLOW_DUMP)
575 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700576 Ostream &Str = Func->getContext()->getStrDump();
577 dumpDest(Func);
578 Str << " = " << getDest()->getType() << " ";
579 dumpSources(Func);
580}
581
582void InstBr::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800583 if (!ALLOW_DUMP)
584 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700585 Ostream &Str = Func->getContext()->getStrDump();
586 dumpDest(Func);
587 Str << "br ";
588 if (!isUnconditional()) {
589 Str << "i1 ";
590 getCondition()->dump(Func);
591 Str << ", label %" << getTargetTrue()->getName() << ", ";
592 }
593 Str << "label %" << getTargetFalse()->getName();
594}
595
596void InstCall::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800597 if (!ALLOW_DUMP)
598 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700599 Ostream &Str = Func->getContext()->getStrDump();
600 if (getDest()) {
601 dumpDest(Func);
602 Str << " = ";
603 }
604 Str << "call ";
605 if (getDest())
606 Str << getDest()->getType();
607 else
608 Str << "void";
609 Str << " ";
610 getCallTarget()->dump(Func);
611 Str << "(";
612 for (SizeT I = 0; I < getNumArgs(); ++I) {
613 if (I > 0)
614 Str << ", ";
615 Str << getArg(I)->getType() << " ";
616 getArg(I)->dump(Func);
617 }
618 Str << ")";
619}
620
Karl Schimpfbf170372014-12-15 10:16:31 -0800621const char *InstCast::getCastName(InstCast::OpKind Kind) {
622 size_t Index = static_cast<size_t>(Kind);
623 if (Index < InstCast::OpKind::_num)
624 return InstCastAttributes[Index].DisplayString;
625 llvm_unreachable("Invalid InstCast::OpKind");
626 return "???";
627}
628
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700629void InstCast::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800630 if (!ALLOW_DUMP)
631 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700632 Ostream &Str = Func->getContext()->getStrDump();
633 dumpDest(Func);
Karl Schimpfbf170372014-12-15 10:16:31 -0800634 Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
635 << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700636 dumpSources(Func);
637 Str << " to " << getDest()->getType();
638}
639
640void InstIcmp::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800641 if (!ALLOW_DUMP)
642 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700643 Ostream &Str = Func->getContext()->getStrDump();
644 dumpDest(Func);
645 Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
646 << getSrc(0)->getType() << " ";
647 dumpSources(Func);
648}
649
Matt Wala49889232014-07-18 12:45:09 -0700650void InstExtractElement::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800651 if (!ALLOW_DUMP)
652 return;
Matt Wala49889232014-07-18 12:45:09 -0700653 Ostream &Str = Func->getContext()->getStrDump();
654 dumpDest(Func);
655 Str << " = extractelement ";
656 Str << getSrc(0)->getType() << " ";
657 getSrc(0)->dump(Func);
658 Str << ", ";
659 Str << getSrc(1)->getType() << " ";
660 getSrc(1)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700661}
Matt Wala49889232014-07-18 12:45:09 -0700662
663void InstInsertElement::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800664 if (!ALLOW_DUMP)
665 return;
Matt Wala49889232014-07-18 12:45:09 -0700666 Ostream &Str = Func->getContext()->getStrDump();
667 dumpDest(Func);
668 Str << " = insertelement ";
669 Str << getSrc(0)->getType() << " ";
670 getSrc(0)->dump(Func);
671 Str << ", ";
672 Str << getSrc(1)->getType() << " ";
673 getSrc(1)->dump(Func);
674 Str << ", ";
675 Str << getSrc(2)->getType() << " ";
676 getSrc(2)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700677}
Matt Wala49889232014-07-18 12:45:09 -0700678
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700679void InstFcmp::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800680 if (!ALLOW_DUMP)
681 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700682 Ostream &Str = Func->getContext()->getStrDump();
683 dumpDest(Func);
684 Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
685 << getSrc(0)->getType() << " ";
686 dumpSources(Func);
687}
688
689void InstLoad::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800690 if (!ALLOW_DUMP)
691 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700692 Ostream &Str = Func->getContext()->getStrDump();
693 dumpDest(Func);
694 Type Ty = getDest()->getType();
695 Str << " = load " << Ty << "* ";
696 dumpSources(Func);
697 Str << ", align " << typeAlignInBytes(Ty);
698}
699
700void InstStore::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800701 if (!ALLOW_DUMP)
702 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700703 Ostream &Str = Func->getContext()->getStrDump();
704 Type Ty = getData()->getType();
705 Str << "store " << Ty << " ";
706 getData()->dump(Func);
707 Str << ", " << Ty << "* ";
708 getAddr()->dump(Func);
709 Str << ", align " << typeAlignInBytes(Ty);
710}
711
712void InstSwitch::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800713 if (!ALLOW_DUMP)
714 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700715 Ostream &Str = Func->getContext()->getStrDump();
716 Type Ty = getComparison()->getType();
717 Str << "switch " << Ty << " ";
718 getSrc(0)->dump(Func);
719 Str << ", label %" << getLabelDefault()->getName() << " [\n";
720 for (SizeT I = 0; I < getNumCases(); ++I) {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700721 Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
722 << ", label %" << getLabel(I)->getName() << "\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700723 }
724 Str << " ]";
725}
726
727void InstPhi::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800728 if (!ALLOW_DUMP)
729 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700730 Ostream &Str = Func->getContext()->getStrDump();
731 dumpDest(Func);
732 Str << " = phi " << getDest()->getType() << " ";
733 for (SizeT I = 0; I < getSrcSize(); ++I) {
734 if (I > 0)
735 Str << ", ";
736 Str << "[ ";
737 getSrc(I)->dump(Func);
738 Str << ", %" << Labels[I]->getName() << " ]";
739 }
740}
741
742void InstRet::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800743 if (!ALLOW_DUMP)
744 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700745 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700746 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700747 Str << "ret " << Ty;
748 if (hasRetValue()) {
749 Str << " ";
750 dumpSources(Func);
751 }
752}
753
754void InstSelect::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800755 if (!ALLOW_DUMP)
756 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700757 Ostream &Str = Func->getContext()->getStrDump();
758 dumpDest(Func);
759 Operand *Condition = getCondition();
760 Operand *TrueOp = getTrueOperand();
761 Operand *FalseOp = getFalseOperand();
762 Str << " = select " << Condition->getType() << " ";
763 Condition->dump(Func);
764 Str << ", " << TrueOp->getType() << " ";
765 TrueOp->dump(Func);
766 Str << ", " << FalseOp->getType() << " ";
767 FalseOp->dump(Func);
768}
769
770void InstUnreachable::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800771 if (!ALLOW_DUMP)
772 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700773 Ostream &Str = Func->getContext()->getStrDump();
774 Str << "unreachable";
775}
776
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700777void InstFakeDef::emit(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800778 if (!ALLOW_DUMP)
779 return;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800780 // Go ahead and "emit" these for now, since they are relatively
781 // rare.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700782 Ostream &Str = Func->getContext()->getStrEmit();
783 Str << "\t# ";
784 getDest()->emit(Func);
785 Str << " = def.pseudo ";
786 emitSources(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700787}
788
789void InstFakeDef::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800790 if (!ALLOW_DUMP)
791 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700792 Ostream &Str = Func->getContext()->getStrDump();
793 dumpDest(Func);
794 Str << " = def.pseudo ";
795 dumpSources(Func);
796}
797
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800798void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700799
800void InstFakeUse::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800801 if (!ALLOW_DUMP)
802 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700803 Ostream &Str = Func->getContext()->getStrDump();
804 Str << "use.pseudo ";
805 dumpSources(Func);
806}
807
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800808void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700809
810void InstFakeKill::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800811 if (!ALLOW_DUMP)
812 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700813 Ostream &Str = Func->getContext()->getStrDump();
814 if (Linked->isDeleted())
815 Str << "// ";
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800816 Str << "kill.pseudo scratch_regs";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700817}
818
819void InstTarget::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800820 if (!ALLOW_DUMP)
821 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700822 Ostream &Str = Func->getContext()->getStrDump();
823 Str << "[TARGET] ";
824 Inst::dump(Func);
825}
826
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700827} // end of namespace Ice