blob: 0e6be75ffd8b6a3dd34aa2427c5eada0ff106461 [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 Stichnothd9dc82e2015-03-03 17:06:33 -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 Stichnothd9dc82e2015-03-03 17:06:33 -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 Stichnothd9dc82e2015-03-03 17:06:33 -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 Stichnothd9dc82e2015-03-03 17:06:33 -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 Stichnoth9f42d8c2015-02-20 09:20:14 -0800439InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
440 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
441 BundleOption(BundleOption) {}
442
443InstBundleUnlock::InstBundleUnlock(Cfg *Func)
444 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
445
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700446InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700447 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700448 assert(Dest);
449 if (Src)
450 addSource(Src);
451}
452
453InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src)
Jim Stichnothae953202014-12-20 06:17:49 -0800454 : InstHighLevel(Func, Inst::FakeUse, 1, nullptr) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700455 assert(Src);
456 addSource(Src);
457}
458
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800459InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
Jim Stichnothae953202014-12-20 06:17:49 -0800460 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700461
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800462Type InstCall::getReturnType() const {
Jim Stichnothae953202014-12-20 06:17:49 -0800463 if (Dest == nullptr)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800464 return IceType_void;
465 return Dest->getType();
466}
467
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700468// ======================== Dump routines ======================== //
469
470void Inst::dumpDecorated(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800471 if (!ALLOW_DUMP)
472 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700473 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800474 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700475 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800476 if (Func->isVerbose(IceV_InstNumbers)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700477 char buf[30];
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700478 InstNumberT Number = getNumber();
479 if (Number == NumberDeleted)
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700480 snprintf(buf, llvm::array_lengthof(buf), "[XXX]");
481 else
482 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number);
483 Str << buf;
484 }
485 Str << " ";
486 if (isDeleted())
487 Str << " //";
488 dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700489 dumpExtras(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700490 Str << "\n";
491}
492
493void Inst::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800494 if (!ALLOW_DUMP)
495 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700496 Ostream &Str = Func->getContext()->getStrDump();
497 dumpDest(Func);
498 Str << " =~ ";
499 dumpSources(Func);
500}
501
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700502void Inst::dumpExtras(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800503 if (!ALLOW_DUMP)
504 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700505 Ostream &Str = Func->getContext()->getStrDump();
506 bool First = true;
507 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges
508 // are known to end at this instruction.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800509 if (Func->isVerbose(IceV_Liveness)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700510 for (SizeT I = 0; I < getSrcSize(); ++I) {
511 Operand *Src = getSrc(I);
512 SizeT NumVars = Src->getNumVars();
513 for (SizeT J = 0; J < NumVars; ++J) {
514 const Variable *Var = Src->getVar(J);
515 if (isLastUse(Var)) {
516 if (First)
517 Str << " // LIVEEND={";
518 else
519 Str << ",";
520 Var->dump(Func);
521 First = false;
522 }
523 }
524 }
525 if (!First)
526 Str << "}";
527 }
528}
529
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700530void Inst::dumpSources(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800531 if (!ALLOW_DUMP)
532 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700533 Ostream &Str = Func->getContext()->getStrDump();
534 for (SizeT I = 0; I < getSrcSize(); ++I) {
535 if (I > 0)
536 Str << ", ";
537 getSrc(I)->dump(Func);
538 }
539}
540
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700541void Inst::emitSources(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800542 if (!ALLOW_DUMP)
543 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700544 Ostream &Str = Func->getContext()->getStrEmit();
545 for (SizeT I = 0; I < getSrcSize(); ++I) {
546 if (I > 0)
547 Str << ", ";
548 getSrc(I)->emit(Func);
549 }
550}
551
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700552void Inst::dumpDest(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 if (getDest())
556 getDest()->dump(Func);
557}
558
559void InstAlloca::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800560 if (!ALLOW_DUMP)
561 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700562 Ostream &Str = Func->getContext()->getStrDump();
563 dumpDest(Func);
564 Str << " = alloca i8, i32 ";
565 getSizeInBytes()->dump(Func);
Jim Stichnoth72a8f8d2014-09-08 17:56:50 -0700566 if (getAlignInBytes())
567 Str << ", align " << getAlignInBytes();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700568}
569
570void InstArithmetic::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800571 if (!ALLOW_DUMP)
572 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700573 Ostream &Str = Func->getContext()->getStrDump();
574 dumpDest(Func);
575 Str << " = " << InstArithmeticAttributes[getOp()].DisplayString << " "
576 << getDest()->getType() << " ";
577 dumpSources(Func);
578}
579
580void InstAssign::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800581 if (!ALLOW_DUMP)
582 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700583 Ostream &Str = Func->getContext()->getStrDump();
584 dumpDest(Func);
585 Str << " = " << getDest()->getType() << " ";
586 dumpSources(Func);
587}
588
589void InstBr::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800590 if (!ALLOW_DUMP)
591 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700592 Ostream &Str = Func->getContext()->getStrDump();
593 dumpDest(Func);
594 Str << "br ";
595 if (!isUnconditional()) {
596 Str << "i1 ";
597 getCondition()->dump(Func);
598 Str << ", label %" << getTargetTrue()->getName() << ", ";
599 }
600 Str << "label %" << getTargetFalse()->getName();
601}
602
603void InstCall::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800604 if (!ALLOW_DUMP)
605 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700606 Ostream &Str = Func->getContext()->getStrDump();
607 if (getDest()) {
608 dumpDest(Func);
609 Str << " = ";
610 }
611 Str << "call ";
612 if (getDest())
613 Str << getDest()->getType();
614 else
615 Str << "void";
616 Str << " ";
617 getCallTarget()->dump(Func);
618 Str << "(";
619 for (SizeT I = 0; I < getNumArgs(); ++I) {
620 if (I > 0)
621 Str << ", ";
622 Str << getArg(I)->getType() << " ";
623 getArg(I)->dump(Func);
624 }
625 Str << ")";
626}
627
Karl Schimpfbf170372014-12-15 10:16:31 -0800628const char *InstCast::getCastName(InstCast::OpKind Kind) {
629 size_t Index = static_cast<size_t>(Kind);
630 if (Index < InstCast::OpKind::_num)
631 return InstCastAttributes[Index].DisplayString;
632 llvm_unreachable("Invalid InstCast::OpKind");
633 return "???";
634}
635
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700636void InstCast::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800637 if (!ALLOW_DUMP)
638 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700639 Ostream &Str = Func->getContext()->getStrDump();
640 dumpDest(Func);
Karl Schimpfbf170372014-12-15 10:16:31 -0800641 Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
642 << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700643 dumpSources(Func);
644 Str << " to " << getDest()->getType();
645}
646
647void InstIcmp::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800648 if (!ALLOW_DUMP)
649 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700650 Ostream &Str = Func->getContext()->getStrDump();
651 dumpDest(Func);
652 Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
653 << getSrc(0)->getType() << " ";
654 dumpSources(Func);
655}
656
Matt Wala49889232014-07-18 12:45:09 -0700657void InstExtractElement::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800658 if (!ALLOW_DUMP)
659 return;
Matt Wala49889232014-07-18 12:45:09 -0700660 Ostream &Str = Func->getContext()->getStrDump();
661 dumpDest(Func);
662 Str << " = extractelement ";
663 Str << getSrc(0)->getType() << " ";
664 getSrc(0)->dump(Func);
665 Str << ", ";
666 Str << getSrc(1)->getType() << " ";
667 getSrc(1)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700668}
Matt Wala49889232014-07-18 12:45:09 -0700669
670void InstInsertElement::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800671 if (!ALLOW_DUMP)
672 return;
Matt Wala49889232014-07-18 12:45:09 -0700673 Ostream &Str = Func->getContext()->getStrDump();
674 dumpDest(Func);
675 Str << " = insertelement ";
676 Str << getSrc(0)->getType() << " ";
677 getSrc(0)->dump(Func);
678 Str << ", ";
679 Str << getSrc(1)->getType() << " ";
680 getSrc(1)->dump(Func);
681 Str << ", ";
682 Str << getSrc(2)->getType() << " ";
683 getSrc(2)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700684}
Matt Wala49889232014-07-18 12:45:09 -0700685
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700686void InstFcmp::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800687 if (!ALLOW_DUMP)
688 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700689 Ostream &Str = Func->getContext()->getStrDump();
690 dumpDest(Func);
691 Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
692 << getSrc(0)->getType() << " ";
693 dumpSources(Func);
694}
695
696void InstLoad::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800697 if (!ALLOW_DUMP)
698 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700699 Ostream &Str = Func->getContext()->getStrDump();
700 dumpDest(Func);
701 Type Ty = getDest()->getType();
702 Str << " = load " << Ty << "* ";
703 dumpSources(Func);
704 Str << ", align " << typeAlignInBytes(Ty);
705}
706
707void InstStore::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800708 if (!ALLOW_DUMP)
709 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700710 Ostream &Str = Func->getContext()->getStrDump();
711 Type Ty = getData()->getType();
712 Str << "store " << Ty << " ";
713 getData()->dump(Func);
714 Str << ", " << Ty << "* ";
715 getAddr()->dump(Func);
716 Str << ", align " << typeAlignInBytes(Ty);
717}
718
719void InstSwitch::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800720 if (!ALLOW_DUMP)
721 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700722 Ostream &Str = Func->getContext()->getStrDump();
723 Type Ty = getComparison()->getType();
724 Str << "switch " << Ty << " ";
725 getSrc(0)->dump(Func);
726 Str << ", label %" << getLabelDefault()->getName() << " [\n";
727 for (SizeT I = 0; I < getNumCases(); ++I) {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700728 Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
729 << ", label %" << getLabel(I)->getName() << "\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700730 }
731 Str << " ]";
732}
733
734void InstPhi::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800735 if (!ALLOW_DUMP)
736 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700737 Ostream &Str = Func->getContext()->getStrDump();
738 dumpDest(Func);
739 Str << " = phi " << getDest()->getType() << " ";
740 for (SizeT I = 0; I < getSrcSize(); ++I) {
741 if (I > 0)
742 Str << ", ";
743 Str << "[ ";
744 getSrc(I)->dump(Func);
745 Str << ", %" << Labels[I]->getName() << " ]";
746 }
747}
748
749void InstRet::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800750 if (!ALLOW_DUMP)
751 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700752 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700753 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700754 Str << "ret " << Ty;
755 if (hasRetValue()) {
756 Str << " ";
757 dumpSources(Func);
758 }
759}
760
761void InstSelect::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800762 if (!ALLOW_DUMP)
763 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700764 Ostream &Str = Func->getContext()->getStrDump();
765 dumpDest(Func);
766 Operand *Condition = getCondition();
767 Operand *TrueOp = getTrueOperand();
768 Operand *FalseOp = getFalseOperand();
769 Str << " = select " << Condition->getType() << " ";
770 Condition->dump(Func);
771 Str << ", " << TrueOp->getType() << " ";
772 TrueOp->dump(Func);
773 Str << ", " << FalseOp->getType() << " ";
774 FalseOp->dump(Func);
775}
776
777void InstUnreachable::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800778 if (!ALLOW_DUMP)
779 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700780 Ostream &Str = Func->getContext()->getStrDump();
781 Str << "unreachable";
782}
783
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800784void InstBundleLock::emit(const Cfg *Func) const {
785 if (!ALLOW_DUMP)
786 return;
787 Ostream &Str = Func->getContext()->getStrEmit();
788 Str << "\t.bundle_lock";
789 switch (BundleOption) {
790 case Opt_None:
791 break;
792 case Opt_AlignToEnd:
793 Str << "\talign_to_end";
794 break;
795 }
796}
797
798void InstBundleLock::dump(const Cfg *Func) const {
799 if (!ALLOW_DUMP)
800 return;
801 Ostream &Str = Func->getContext()->getStrDump();
802 Str << "bundle_lock";
803 switch (BundleOption) {
804 case Opt_None:
805 break;
806 case Opt_AlignToEnd:
807 Str << " align_to_end";
808 break;
809 }
810}
811
812void InstBundleUnlock::emit(const Cfg *Func) const {
813 if (!ALLOW_DUMP)
814 return;
815 Ostream &Str = Func->getContext()->getStrEmit();
816 Str << "\t.bundle_unlock";
817}
818
819void InstBundleUnlock::dump(const Cfg *Func) const {
820 if (!ALLOW_DUMP)
821 return;
822 Ostream &Str = Func->getContext()->getStrDump();
823 Str << "bundle_unlock";
824}
825
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700826void InstFakeDef::emit(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800827 if (!ALLOW_DUMP)
828 return;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800829 // Go ahead and "emit" these for now, since they are relatively
830 // rare.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700831 Ostream &Str = Func->getContext()->getStrEmit();
832 Str << "\t# ";
833 getDest()->emit(Func);
834 Str << " = def.pseudo ";
835 emitSources(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700836}
837
838void InstFakeDef::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800839 if (!ALLOW_DUMP)
840 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700841 Ostream &Str = Func->getContext()->getStrDump();
842 dumpDest(Func);
843 Str << " = def.pseudo ";
844 dumpSources(Func);
845}
846
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800847void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700848
849void InstFakeUse::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800850 if (!ALLOW_DUMP)
851 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700852 Ostream &Str = Func->getContext()->getStrDump();
853 Str << "use.pseudo ";
854 dumpSources(Func);
855}
856
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800857void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700858
859void InstFakeKill::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800860 if (!ALLOW_DUMP)
861 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700862 Ostream &Str = Func->getContext()->getStrDump();
863 if (Linked->isDeleted())
864 Str << "// ";
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800865 Str << "kill.pseudo scratch_regs";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700866}
867
868void InstTarget::dump(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800869 if (!ALLOW_DUMP)
870 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700871 Ostream &Str = Func->getContext()->getStrDump();
872 Str << "[TARGET] ";
873 Inst::dump(Func);
874}
875
Jan Voungb3401d22015-05-18 09:38:21 -0700876bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
877 const auto SrcVar = llvm::dyn_cast<const Variable>(Source);
878 if (!SrcVar)
879 return false;
880 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
881 // TODO: On x86-64, instructions like "mov eax, eax" are used to
882 // clear the upper 32 bits of rax. We need to recognize and
883 // preserve these.
884 return true;
885 }
886 if (!Dest->hasReg() && !SrcVar->hasReg() &&
887 Dest->getStackOffset() == SrcVar->getStackOffset())
888 return true;
889 return false;
890}
891
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700892} // end of namespace Ice