blob: 4aa6e6947fc030c5c14ba32faa8ee07b21c9b2c0 [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 ,
33 ICEINSTARITHMETIC_TABLE
34#undef X
35 };
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 ,
44 ICEINSTCAST_TABLE
45#undef X
46 };
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 ,
55 ICEINSTFCMP_TABLE
56#undef X
57 };
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 ,
66 ICEINSTICMP_TABLE
67#undef X
68 };
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());
117 if (llvm::isa<InstFakeKill>(this))
118 return;
119 resetLastUses();
Jim Stichnoth47752552014-10-13 17:15:08 -0700120 VariablesMetadata *VMetadata = Func->getVMetadata();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700121 SizeT VarIndex = 0;
122 for (SizeT I = 0; I < getSrcSize(); ++I) {
123 Operand *Src = getSrc(I);
124 SizeT NumVars = Src->getNumVars();
125 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700126 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700127 if (VMetadata->isMultiBlock(Var))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700128 continue;
129 SizeT Index = Var->getIndex();
130 if (Live[Index])
131 continue;
132 Live[Index] = true;
133 setLastUse(VarIndex);
134 }
135 }
136}
137
Jim Stichnoth47752552014-10-13 17:15:08 -0700138void Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
139 Liveness *Liveness, LiveBeginEndMap *LiveBegin,
140 LiveBeginEndMap *LiveEnd) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700141 assert(!isDeleted());
142 if (llvm::isa<InstFakeKill>(this))
143 return;
144
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700145 Dead = false;
146 if (Dest) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700147 SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700148 if (Live[VarNum]) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700149 if (!isDestNonKillable()) {
150 Live[VarNum] = false;
151 if (LiveBegin) {
152 LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
153 }
154 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700155 } else {
156 if (!hasSideEffects())
157 Dead = true;
158 }
159 }
160 if (Dead)
161 return;
162 // Phi arguments only get added to Live in the predecessor node, but
163 // we still need to update LiveRangesEnded.
164 bool IsPhi = llvm::isa<InstPhi>(this);
165 resetLastUses();
166 SizeT VarIndex = 0;
167 for (SizeT I = 0; I < getSrcSize(); ++I) {
168 Operand *Src = getSrc(I);
169 SizeT NumVars = Src->getNumVars();
170 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
171 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700172 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700173 if (!Live[VarNum]) {
174 setLastUse(VarIndex);
175 if (!IsPhi) {
176 Live[VarNum] = true;
177 // For a variable in SSA form, its live range can end at
178 // most once in a basic block. However, after lowering to
179 // two-address instructions, we end up with sequences like
180 // "t=b;t+=c;a=t" where t's live range begins and ends
181 // twice. ICE only allows a variable to have a single
182 // liveness interval in a basic block (except for blocks
183 // where a variable is live-in and live-out but there is a
184 // gap in the middle, and except for the special
185 // InstFakeKill instruction that can appear multiple
186 // times in the same block). Therefore, this lowered
187 // sequence needs to represent a single conservative live
188 // range for t. Since the instructions are being traversed
189 // backwards, we make sure LiveEnd is only set once by
190 // setting it only when LiveEnd[VarNum]==0 (sentinel value).
191 // Note that it's OK to set LiveBegin multiple times because
192 // of the backwards traversal.
Jim Stichnoth47752552014-10-13 17:15:08 -0700193 if (LiveEnd) {
194 // Ideally, we would verify that VarNum wasn't already
195 // added in this block, but this can't be done very
196 // efficiently with LiveEnd as a vector. Instead,
197 // livenessPostprocess() verifies this after the vector
198 // has been sorted.
199 LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700200 }
201 }
202 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700203 }
204 }
205}
206
207InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
208 Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700209 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700210 // Verify AlignInBytes is 0 or a power of 2.
211 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
212 addSource(ByteCount);
213}
214
215InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
216 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700217 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700218 addSource(Source1);
219 addSource(Source2);
220}
221
Karl Schimpfd6064a12014-08-27 15:34:58 -0700222const char *InstArithmetic::getOpName(OpKind Op) {
223 size_t OpIndex = static_cast<size_t>(Op);
224 return OpIndex < InstArithmetic::_num
225 ? InstArithmeticAttributes[OpIndex].DisplayString
226 : "???";
227}
228
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700229bool InstArithmetic::isCommutative() const {
230 return InstArithmeticAttributes[getOp()].IsCommutative;
231}
232
233InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700234 : InstHighLevel(Func, Inst::Assign, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700235 addSource(Source);
236}
237
238// If TargetTrue==TargetFalse, we turn it into an unconditional
239// branch. This ensures that, along with the 'switch' instruction
240// semantics, there is at most one edge from one node to another.
241InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
242 CfgNode *TargetFalse)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700243 : InstHighLevel(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700244 TargetTrue(TargetTrue) {
245 if (TargetTrue == TargetFalse) {
246 TargetTrue = NULL; // turn into unconditional version
247 } else {
248 addSource(Source);
249 }
250}
251
252InstBr::InstBr(Cfg *Func, CfgNode *Target)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700253 : InstHighLevel(Func, Inst::Br, 0, NULL), TargetFalse(Target),
254 TargetTrue(NULL) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700255
256NodeList InstBr::getTerminatorEdges() const {
257 NodeList OutEdges;
258 OutEdges.push_back(TargetFalse);
259 if (TargetTrue)
260 OutEdges.push_back(TargetTrue);
261 return OutEdges;
262}
263
264InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700265 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700266 addSource(Source);
267}
268
Matt Wala49889232014-07-18 12:45:09 -0700269InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
270 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700271 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700272 addSource(Source1);
273 addSource(Source2);
274}
275
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700276InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
277 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700278 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700279 addSource(Source1);
280 addSource(Source2);
281}
282
283InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
284 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700285 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700286 addSource(Source1);
287 addSource(Source2);
288}
289
Matt Wala49889232014-07-18 12:45:09 -0700290InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
291 Operand *Source1, Operand *Source2,
292 Operand *Source3)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700293 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700294 addSource(Source1);
295 addSource(Source2);
296 addSource(Source3);
297}
298
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700299InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700300 : InstHighLevel(Func, Inst::Load, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700301 addSource(SourceAddr);
302}
303
304InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700305 : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700306 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs);
307}
308
309// TODO: A Switch instruction (and maybe others) can add duplicate
310// edges. We may want to de-dup Phis and validate consistency (i.e.,
311// the source operands are the same for duplicate edges), though it
312// seems the current lowering code is OK with this situation.
313void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
314 Labels[getSrcSize()] = Label;
315 addSource(Source);
316}
317
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700318// Find the source operand corresponding to the incoming edge for the
319// given node. TODO: This uses a linear-time search, which could be
320// improved if it becomes a problem.
321Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
322 for (SizeT I = 0; I < getSrcSize(); ++I) {
323 if (Labels[I] == Target)
324 return getSrc(I);
325 }
326 llvm_unreachable("Phi target not found");
327 return NULL;
328}
329
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700330// Updates liveness for a particular operand based on the given
331// predecessor edge. Doesn't mark the operand as live if the Phi
332// instruction is dead or deleted.
Jim Stichnoth47752552014-10-13 17:15:08 -0700333void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700334 Liveness *Liveness) {
335 if (isDeleted() || Dead)
336 return;
337 for (SizeT I = 0; I < getSrcSize(); ++I) {
338 if (Labels[I] == Target) {
339 if (Variable *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700340 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700341 if (!Live[SrcIndex]) {
342 setLastUse(I);
343 Live[SrcIndex] = true;
344 }
345 }
346 return;
347 }
348 }
349 llvm_unreachable("Phi operand not found for specified target node");
350}
351
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700352// Change "a=phi(...)" to "a_phi=phi(...)" and return a new
353// instruction "a=a_phi".
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700354Inst *InstPhi::lower(Cfg *Func) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700355 Variable *Dest = getDest();
356 assert(Dest);
357 IceString PhiName = Dest->getName() + "_phi";
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700358 Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700359 this->Dest = NewSrc;
Jim Stichnothad403532014-09-25 12:44:17 -0700360 return InstAssign::create(Func, Dest, NewSrc);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700361}
362
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700363InstRet::InstRet(Cfg *Func, Operand *RetValue)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700364 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, NULL) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700365 if (RetValue)
366 addSource(RetValue);
367}
368
369InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
370 Operand *SourceTrue, Operand *SourceFalse)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700371 : InstHighLevel(Func, Inst::Select, 3, Dest) {
Matt Wala9cb61e22014-07-24 09:44:42 -0700372 assert(typeElementType(Condition->getType()) == IceType_i1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700373 addSource(Condition);
374 addSource(SourceTrue);
375 addSource(SourceFalse);
376}
377
378InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700379 : InstHighLevel(Func, Inst::Store, 2, NULL) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700380 addSource(Data);
381 addSource(Addr);
382}
383
384InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
385 CfgNode *LabelDefault)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700386 : InstHighLevel(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700387 NumCases(NumCases) {
388 addSource(Source);
389 Values = Func->allocateArrayOf<uint64_t>(NumCases);
390 Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
391 // Initialize in case buggy code doesn't set all entries
392 for (SizeT I = 0; I < NumCases; ++I) {
393 Values[I] = 0;
394 Labels[I] = NULL;
395 }
396}
397
398void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
399 assert(CaseIndex < NumCases);
400 Values[CaseIndex] = Value;
401 Labels[CaseIndex] = Label;
402}
403
404NodeList InstSwitch::getTerminatorEdges() const {
405 NodeList OutEdges;
406 OutEdges.push_back(LabelDefault);
407 for (SizeT I = 0; I < NumCases; ++I) {
408 OutEdges.push_back(Labels[I]);
409 }
410 return OutEdges;
411}
412
413InstUnreachable::InstUnreachable(Cfg *Func)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700414 : InstHighLevel(Func, Inst::Unreachable, 0, NULL) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700415
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700416InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700417 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700418 assert(Dest);
419 if (Src)
420 addSource(Src);
421}
422
423InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700424 : InstHighLevel(Func, Inst::FakeUse, 1, NULL) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700425 assert(Src);
426 addSource(Src);
427}
428
429InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs,
430 const Inst *Linked)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700431 : InstHighLevel(Func, Inst::FakeKill, KilledRegs.size(), NULL),
432 Linked(Linked) {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700433 for (Variable *Var : KilledRegs)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700434 addSource(Var);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700435}
436
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700437// ======================== Dump routines ======================== //
438
439void Inst::dumpDecorated(const Cfg *Func) const {
440 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700441 if (!Func->getContext()->isVerbose(IceV_Deleted) &&
442 (isDeleted() || isRedundantAssign()))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700443 return;
444 if (Func->getContext()->isVerbose(IceV_InstNumbers)) {
445 char buf[30];
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700446 InstNumberT Number = getNumber();
447 if (Number == NumberDeleted)
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700448 snprintf(buf, llvm::array_lengthof(buf), "[XXX]");
449 else
450 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number);
451 Str << buf;
452 }
453 Str << " ";
454 if (isDeleted())
455 Str << " //";
456 dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700457 dumpExtras(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700458 Str << "\n";
459}
460
461void Inst::dump(const Cfg *Func) const {
462 Ostream &Str = Func->getContext()->getStrDump();
463 dumpDest(Func);
464 Str << " =~ ";
465 dumpSources(Func);
466}
467
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700468void Inst::dumpExtras(const Cfg *Func) const {
469 Ostream &Str = Func->getContext()->getStrDump();
470 bool First = true;
471 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges
472 // are known to end at this instruction.
473 if (Func->getContext()->isVerbose(IceV_Liveness)) {
474 for (SizeT I = 0; I < getSrcSize(); ++I) {
475 Operand *Src = getSrc(I);
476 SizeT NumVars = Src->getNumVars();
477 for (SizeT J = 0; J < NumVars; ++J) {
478 const Variable *Var = Src->getVar(J);
479 if (isLastUse(Var)) {
480 if (First)
481 Str << " // LIVEEND={";
482 else
483 Str << ",";
484 Var->dump(Func);
485 First = false;
486 }
487 }
488 }
489 if (!First)
490 Str << "}";
491 }
492}
493
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700494void Inst::dumpSources(const Cfg *Func) const {
495 Ostream &Str = Func->getContext()->getStrDump();
496 for (SizeT I = 0; I < getSrcSize(); ++I) {
497 if (I > 0)
498 Str << ", ";
499 getSrc(I)->dump(Func);
500 }
501}
502
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700503void Inst::emitSources(const Cfg *Func) const {
504 Ostream &Str = Func->getContext()->getStrEmit();
505 for (SizeT I = 0; I < getSrcSize(); ++I) {
506 if (I > 0)
507 Str << ", ";
508 getSrc(I)->emit(Func);
509 }
510}
511
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700512void Inst::dumpDest(const Cfg *Func) const {
513 if (getDest())
514 getDest()->dump(Func);
515}
516
517void InstAlloca::dump(const Cfg *Func) const {
518 Ostream &Str = Func->getContext()->getStrDump();
519 dumpDest(Func);
520 Str << " = alloca i8, i32 ";
521 getSizeInBytes()->dump(Func);
Jim Stichnoth72a8f8d2014-09-08 17:56:50 -0700522 if (getAlignInBytes())
523 Str << ", align " << getAlignInBytes();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700524}
525
526void InstArithmetic::dump(const Cfg *Func) const {
527 Ostream &Str = Func->getContext()->getStrDump();
528 dumpDest(Func);
529 Str << " = " << InstArithmeticAttributes[getOp()].DisplayString << " "
530 << getDest()->getType() << " ";
531 dumpSources(Func);
532}
533
534void InstAssign::dump(const Cfg *Func) const {
535 Ostream &Str = Func->getContext()->getStrDump();
536 dumpDest(Func);
537 Str << " = " << getDest()->getType() << " ";
538 dumpSources(Func);
539}
540
541void InstBr::dump(const Cfg *Func) const {
542 Ostream &Str = Func->getContext()->getStrDump();
543 dumpDest(Func);
544 Str << "br ";
545 if (!isUnconditional()) {
546 Str << "i1 ";
547 getCondition()->dump(Func);
548 Str << ", label %" << getTargetTrue()->getName() << ", ";
549 }
550 Str << "label %" << getTargetFalse()->getName();
551}
552
Karl Schimpf8df26f32014-09-19 09:33:26 -0700553Type InstCall::getReturnType() const {
554 if (Dest == NULL)
555 return IceType_void;
556 return Dest->getType();
557}
558
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700559void InstCall::dump(const Cfg *Func) const {
560 Ostream &Str = Func->getContext()->getStrDump();
561 if (getDest()) {
562 dumpDest(Func);
563 Str << " = ";
564 }
565 Str << "call ";
566 if (getDest())
567 Str << getDest()->getType();
568 else
569 Str << "void";
570 Str << " ";
571 getCallTarget()->dump(Func);
572 Str << "(";
573 for (SizeT I = 0; I < getNumArgs(); ++I) {
574 if (I > 0)
575 Str << ", ";
576 Str << getArg(I)->getType() << " ";
577 getArg(I)->dump(Func);
578 }
579 Str << ")";
580}
581
582void InstCast::dump(const Cfg *Func) const {
583 Ostream &Str = Func->getContext()->getStrDump();
584 dumpDest(Func);
585 Str << " = " << InstCastAttributes[getCastKind()].DisplayString << " "
586 << getSrc(0)->getType() << " ";
587 dumpSources(Func);
588 Str << " to " << getDest()->getType();
589}
590
591void InstIcmp::dump(const Cfg *Func) const {
592 Ostream &Str = Func->getContext()->getStrDump();
593 dumpDest(Func);
594 Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
595 << getSrc(0)->getType() << " ";
596 dumpSources(Func);
597}
598
Matt Wala49889232014-07-18 12:45:09 -0700599void InstExtractElement::dump(const Cfg *Func) const {
600 Ostream &Str = Func->getContext()->getStrDump();
601 dumpDest(Func);
602 Str << " = extractelement ";
603 Str << getSrc(0)->getType() << " ";
604 getSrc(0)->dump(Func);
605 Str << ", ";
606 Str << getSrc(1)->getType() << " ";
607 getSrc(1)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700608}
Matt Wala49889232014-07-18 12:45:09 -0700609
610void InstInsertElement::dump(const Cfg *Func) const {
611 Ostream &Str = Func->getContext()->getStrDump();
612 dumpDest(Func);
613 Str << " = insertelement ";
614 Str << getSrc(0)->getType() << " ";
615 getSrc(0)->dump(Func);
616 Str << ", ";
617 Str << getSrc(1)->getType() << " ";
618 getSrc(1)->dump(Func);
619 Str << ", ";
620 Str << getSrc(2)->getType() << " ";
621 getSrc(2)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700622}
Matt Wala49889232014-07-18 12:45:09 -0700623
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700624void InstFcmp::dump(const Cfg *Func) const {
625 Ostream &Str = Func->getContext()->getStrDump();
626 dumpDest(Func);
627 Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
628 << getSrc(0)->getType() << " ";
629 dumpSources(Func);
630}
631
632void InstLoad::dump(const Cfg *Func) const {
633 Ostream &Str = Func->getContext()->getStrDump();
634 dumpDest(Func);
635 Type Ty = getDest()->getType();
636 Str << " = load " << Ty << "* ";
637 dumpSources(Func);
638 Str << ", align " << typeAlignInBytes(Ty);
639}
640
641void InstStore::dump(const Cfg *Func) const {
642 Ostream &Str = Func->getContext()->getStrDump();
643 Type Ty = getData()->getType();
644 Str << "store " << Ty << " ";
645 getData()->dump(Func);
646 Str << ", " << Ty << "* ";
647 getAddr()->dump(Func);
648 Str << ", align " << typeAlignInBytes(Ty);
649}
650
651void InstSwitch::dump(const Cfg *Func) const {
652 Ostream &Str = Func->getContext()->getStrDump();
653 Type Ty = getComparison()->getType();
654 Str << "switch " << Ty << " ";
655 getSrc(0)->dump(Func);
656 Str << ", label %" << getLabelDefault()->getName() << " [\n";
657 for (SizeT I = 0; I < getNumCases(); ++I) {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700658 Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
659 << ", label %" << getLabel(I)->getName() << "\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700660 }
661 Str << " ]";
662}
663
664void InstPhi::dump(const Cfg *Func) const {
665 Ostream &Str = Func->getContext()->getStrDump();
666 dumpDest(Func);
667 Str << " = phi " << getDest()->getType() << " ";
668 for (SizeT I = 0; I < getSrcSize(); ++I) {
669 if (I > 0)
670 Str << ", ";
671 Str << "[ ";
672 getSrc(I)->dump(Func);
673 Str << ", %" << Labels[I]->getName() << " ]";
674 }
675}
676
677void InstRet::dump(const Cfg *Func) const {
678 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700679 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700680 Str << "ret " << Ty;
681 if (hasRetValue()) {
682 Str << " ";
683 dumpSources(Func);
684 }
685}
686
687void InstSelect::dump(const Cfg *Func) const {
688 Ostream &Str = Func->getContext()->getStrDump();
689 dumpDest(Func);
690 Operand *Condition = getCondition();
691 Operand *TrueOp = getTrueOperand();
692 Operand *FalseOp = getFalseOperand();
693 Str << " = select " << Condition->getType() << " ";
694 Condition->dump(Func);
695 Str << ", " << TrueOp->getType() << " ";
696 TrueOp->dump(Func);
697 Str << ", " << FalseOp->getType() << " ";
698 FalseOp->dump(Func);
699}
700
701void InstUnreachable::dump(const Cfg *Func) const {
702 Ostream &Str = Func->getContext()->getStrDump();
703 Str << "unreachable";
704}
705
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700706void InstFakeDef::emit(const Cfg *Func) const {
707 Ostream &Str = Func->getContext()->getStrEmit();
708 Str << "\t# ";
709 getDest()->emit(Func);
710 Str << " = def.pseudo ";
711 emitSources(Func);
712 Str << "\n";
713}
714
715void InstFakeDef::dump(const Cfg *Func) const {
716 Ostream &Str = Func->getContext()->getStrDump();
717 dumpDest(Func);
718 Str << " = def.pseudo ";
719 dumpSources(Func);
720}
721
722void InstFakeUse::emit(const Cfg *Func) const {
723 Ostream &Str = Func->getContext()->getStrEmit();
724 Str << "\t# ";
725 Str << "use.pseudo ";
726 emitSources(Func);
727 Str << "\n";
728}
729
730void InstFakeUse::dump(const Cfg *Func) const {
731 Ostream &Str = Func->getContext()->getStrDump();
732 Str << "use.pseudo ";
733 dumpSources(Func);
734}
735
736void InstFakeKill::emit(const Cfg *Func) const {
737 Ostream &Str = Func->getContext()->getStrEmit();
738 Str << "\t# ";
739 if (Linked->isDeleted())
740 Str << "// ";
741 Str << "kill.pseudo ";
742 emitSources(Func);
743 Str << "\n";
744}
745
746void InstFakeKill::dump(const Cfg *Func) const {
747 Ostream &Str = Func->getContext()->getStrDump();
748 if (Linked->isDeleted())
749 Str << "// ";
750 Str << "kill.pseudo ";
751 dumpSources(Func);
752}
753
754void InstTarget::dump(const Cfg *Func) const {
755 Ostream &Str = Func->getContext()->getStrDump();
756 Str << "[TARGET] ";
757 Inst::dump(Func);
758}
759
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700760} // end of namespace Ice