blob: 719791a7e42245d3d179bcf80c3054f92a5335b2 [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Implements the Inst class, primarily the various subclass
Andrew Scull57e12682015-09-16 11:30:19 -070012/// constructors and dump routines.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
John Porto67f8de92015-06-25 10:14:17 -070016#include "IceInst.h"
17
Jim Stichnothf7c9a142014-04-29 10:52:43 -070018#include "IceCfg.h"
19#include "IceCfgNode.h"
John Portoec3f5652015-08-31 15:07:09 -070020#include "IceInstVarIter.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070021#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceOperand.h"
Andrew Scull87f80c12015-07-20 10:19:16 -070023#include "IceTargetLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024
25namespace Ice {
26
27namespace {
28
29// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070030const struct InstArithmeticAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070031 const char *DisplayString;
32 bool IsCommutative;
33} InstArithmeticAttributes[] = {
34#define X(tag, str, commutative) \
35 { str, commutative } \
36 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080037 ICEINSTARITHMETIC_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070038#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080039};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070040
41// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070042const struct InstCastAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070043 const char *DisplayString;
44} InstCastAttributes[] = {
45#define X(tag, str) \
46 { str } \
47 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080048 ICEINSTCAST_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070049#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080050};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070051
52// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070053const struct InstFcmpAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070054 const char *DisplayString;
55} InstFcmpAttributes[] = {
56#define X(tag, str) \
57 { str } \
58 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080059 ICEINSTFCMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070060#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080061};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070062
63// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070064const struct InstIcmpAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065 const char *DisplayString;
66} InstIcmpAttributes[] = {
67#define X(tag, str) \
68 { str } \
69 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080070 ICEINSTICMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070071#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080072};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070073
74} // end of anonymous namespace
75
76Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
Jim Stichnotheafb56c2015-06-22 10:35:22 -070077 : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
Jim Stichnothd97c7df2014-06-04 11:57:08 -070078 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)), LiveRangesEnded(0) {}
79
Jim Stichnoth467ffe52016-03-29 15:01:06 -070080const char *Inst::getInstName() const {
Eric Holke37076a2016-01-27 14:06:35 -080081 if (!BuildDefs::dump())
82 return "???";
83
84 switch (Kind) {
85#define X(InstrKind, name) \
86 case InstrKind: \
87 return name
88 X(Unreachable, "unreachable");
89 X(Alloca, "alloca");
90 X(Arithmetic, "arithmetic");
91 X(Br, "br");
92 X(Call, "call");
93 X(Cast, "cast");
94 X(ExtractElement, "extractelement");
95 X(Fcmp, "fcmp");
96 X(Icmp, "icmp");
97 X(IntrinsicCall, "intrinsiccall");
98 X(InsertElement, "insertelement");
99 X(Load, "load");
100 X(Phi, "phi");
101 X(Ret, "ret");
102 X(Select, "select");
103 X(Store, "store");
104 X(Switch, "switch");
105 X(Assign, "assign");
106 X(BundleLock, "bundlelock");
107 X(BundleUnlock, "bundleunlock");
108 X(FakeDef, "fakedef");
109 X(FakeUse, "fakeuse");
110 X(FakeKill, "fakekill");
111 X(JumpTable, "jumptable");
112#undef X
113 default:
114 assert(Kind >= Target);
115 return "target";
116 }
117}
118
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700119// Assign the instruction a new number.
120void Inst::renumber(Cfg *Func) {
121 Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
122}
123
Andrew Scull57e12682015-09-16 11:30:19 -0700124// Delete the instruction if its tentative Dead flag is still set after
125// liveness analysis.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700126void Inst::deleteIfDead() {
127 if (Dead)
128 setDeleted();
129}
130
Andrew Scull57e12682015-09-16 11:30:19 -0700131// If Src is a Variable, it returns true if this instruction ends Src's live
132// range. Otherwise, returns false.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700133bool Inst::isLastUse(const Operand *TestSrc) const {
134 if (LiveRangesEnded == 0)
135 return false; // early-exit optimization
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800136 if (auto *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700137 LREndedBits Mask = LiveRangesEnded;
John Portoec3f5652015-08-31 15:07:09 -0700138 FOREACH_VAR_IN_INST(Var, *this) {
139 if (Var == TestVar) {
140 // We've found where the variable is used in the instruction.
141 return Mask & 1;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700142 }
John Portoec3f5652015-08-31 15:07:09 -0700143 Mask >>= 1;
144 if (Mask == 0)
145 return false; // another early-exit optimization
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700146 }
147 }
148 return false;
149}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700150
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700151// Given an instruction like:
152// a = b + c + [x,y] + e
153// which was created from OrigInst:
154// a = b + c + d + e
155// with SpliceAssn spliced in:
156// d = [x,y]
157//
Andrew Scull57e12682015-09-16 11:30:19 -0700158// Reconstruct the LiveRangesEnded bitmask in this instruction by combining the
159// LiveRangesEnded values of OrigInst and SpliceAssn. If operands d and [x,y]
160// contain a different number of variables, then the bitmask position for e may
161// be different in OrigInst and the current instruction, requiring extra shifts
162// and masks in the computation. In the example above, OrigInst has variable e
163// in bit position 3, whereas the current instruction has e in bit position 4
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700164// because [x,y] consumes 2 bitmask slots while d only consumed 1.
165//
Andrew Scull57e12682015-09-16 11:30:19 -0700166// Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
167// HasSideEffects set.
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700168void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) {
169 HasSideEffects |= OrigInst->HasSideEffects;
170 HasSideEffects |= SpliceAssn->HasSideEffects;
171 // Find the bitmask index of SpliceAssn's dest within OrigInst.
172 Variable *SpliceDest = SpliceAssn->getDest();
173 SizeT Index = 0;
174 for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) {
175 Operand *Src = OrigInst->getSrc(I);
176 if (Src == SpliceDest) {
177 LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1);
178 LREndedBits RightMask = OrigInst->LiveRangesEnded >> (Index + 1);
179 LiveRangesEnded = LeftMask | (SpliceAssn->LiveRangesEnded << Index) |
180 (RightMask << (Index + getSrc(I)->getNumVars()));
181 return;
182 }
183 Index += getSrc(I)->getNumVars();
184 }
185 llvm::report_fatal_error("Failed to find splice operand");
186}
187
Jim Stichnoth47752552014-10-13 17:15:08 -0700188void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700189 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700190 resetLastUses();
Jim Stichnoth47752552014-10-13 17:15:08 -0700191 VariablesMetadata *VMetadata = Func->getVMetadata();
John Portoec3f5652015-08-31 15:07:09 -0700192 FOREACH_VAR_IN_INST(Var, *this) {
193 if (VMetadata->isMultiBlock(Var))
194 continue;
195 SizeT Index = Var->getIndex();
196 if (Live[Index])
197 continue;
198 Live[Index] = true;
199 setLastUse(IndexOfVarInInst(Var));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700200 }
201}
202
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700203bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
Jim Stichnoth47752552014-10-13 17:15:08 -0700204 Liveness *Liveness, LiveBeginEndMap *LiveBegin,
205 LiveBeginEndMap *LiveEnd) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700206 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700207
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700208 Dead = false;
Jim Stichnothcc89c952016-03-31 11:55:23 -0700209 if (Dest && !Dest->isRematerializable()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700210 SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700211 if (Live[VarNum]) {
Jim Stichnoth230d4102015-09-25 17:40:32 -0700212 if (!isDestRedefined()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700213 Live[VarNum] = false;
Jim Stichnoth552490c2015-08-05 16:21:42 -0700214 if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700215 LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
216 }
217 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700218 } else {
219 if (!hasSideEffects())
220 Dead = true;
221 }
222 }
223 if (Dead)
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700224 return false;
Andrew Scull57e12682015-09-16 11:30:19 -0700225 // Phi arguments only get added to Live in the predecessor node, but we still
226 // need to update LiveRangesEnded.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700227 bool IsPhi = llvm::isa<InstPhi>(this);
228 resetLastUses();
John Portoec3f5652015-08-31 15:07:09 -0700229 FOREACH_VAR_IN_INST(Var, *this) {
Jim Stichnothcc89c952016-03-31 11:55:23 -0700230 if (Var->isRematerializable())
231 continue;
John Portoec3f5652015-08-31 15:07:09 -0700232 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
233 if (!Live[VarNum]) {
234 setLastUse(IndexOfVarInInst(Var));
235 if (!IsPhi) {
236 Live[VarNum] = true;
237 // For a variable in SSA form, its live range can end at most once in a
Andrew Scull57e12682015-09-16 11:30:19 -0700238 // basic block. However, after lowering to two-address instructions, we
239 // end up with sequences like "t=b;t+=c;a=t" where t's live range
240 // begins and ends twice. ICE only allows a variable to have a single
241 // liveness interval in a basic block (except for blocks where a
242 // variable is live-in and live-out but there is a gap in the middle).
243 // Therefore, this lowered sequence needs to represent a single
244 // conservative live range for t. Since the instructions are being
245 // traversed backwards, we make sure LiveEnd is only set once by
246 // setting it only when LiveEnd[VarNum]==0 (sentinel value). Note that
247 // it's OK to set LiveBegin multiple times because of the backwards
248 // traversal.
John Portoec3f5652015-08-31 15:07:09 -0700249 if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
250 // Ideally, we would verify that VarNum wasn't already added in this
251 // block, but this can't be done very efficiently with LiveEnd as a
Andrew Scull57e12682015-09-16 11:30:19 -0700252 // vector. Instead, livenessPostprocess() verifies this after the
John Portoec3f5652015-08-31 15:07:09 -0700253 // vector has been sorted.
254 LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700255 }
256 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700257 }
258 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700259 return true;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700260}
261
David Sehr2f3b8ec2015-11-16 16:51:39 -0800262InstAlloca::InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
263 uint32_t AlignInBytes)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700264 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700265 // Verify AlignInBytes is 0 or a power of 2.
266 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
267 addSource(ByteCount);
268}
269
270InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
271 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700272 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700273 addSource(Source1);
274 addSource(Source2);
275}
276
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700277const char *InstArithmetic::getInstName() const {
Eric Holke37076a2016-01-27 14:06:35 -0800278 if (!BuildDefs::dump())
279 return "???";
280
281 return InstArithmeticAttributes[getOp()].DisplayString;
282}
283
Karl Schimpfd6064a12014-08-27 15:34:58 -0700284const char *InstArithmetic::getOpName(OpKind Op) {
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800285 return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
286 : "???";
Karl Schimpfd6064a12014-08-27 15:34:58 -0700287}
288
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700289bool InstArithmetic::isCommutative() const {
290 return InstArithmeticAttributes[getOp()].IsCommutative;
291}
292
293InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700294 : InstHighLevel(Func, Inst::Assign, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700295 addSource(Source);
296}
297
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700298bool InstAssign::isVarAssign() const { return llvm::isa<Variable>(getSrc(0)); }
299
Andrew Scull57e12682015-09-16 11:30:19 -0700300// If TargetTrue==TargetFalse, we turn it into an unconditional branch. This
301// ensures that, along with the 'switch' instruction semantics, there is at
302// most one edge from one node to another.
Karl Schimpfc070d6f2015-06-26 10:25:33 -0700303InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
304 CfgNode *TargetFalse_)
305 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
306 TargetTrue(TargetTrue_) {
David Sehr263ac522016-04-04 10:11:08 -0700307 if (auto *Constant = llvm::dyn_cast<ConstantInteger32>(Source)) {
308 int32_t C32 = Constant->getValue();
309 if (C32 != 0) {
310 TargetFalse = TargetTrue;
311 }
312 TargetTrue = nullptr; // turn into unconditional version
313 } else if (TargetTrue == TargetFalse) {
Jim Stichnothae953202014-12-20 06:17:49 -0800314 TargetTrue = nullptr; // turn into unconditional version
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700315 } else {
316 addSource(Source);
317 }
318}
319
320InstBr::InstBr(Cfg *Func, CfgNode *Target)
Jim Stichnothae953202014-12-20 06:17:49 -0800321 : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
322 TargetTrue(nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700323
324NodeList InstBr::getTerminatorEdges() const {
325 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800326 OutEdges.reserve(TargetTrue ? 2 : 1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700327 OutEdges.push_back(TargetFalse);
328 if (TargetTrue)
329 OutEdges.push_back(TargetTrue);
330 return OutEdges;
331}
332
Andrew Scull87f80c12015-07-20 10:19:16 -0700333bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
334 bool Found = false;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700335 if (TargetFalse == OldNode) {
336 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700337 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700338 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700339 if (TargetTrue == OldNode) {
340 TargetTrue = NewNode;
341 Found = true;
342 }
343 return Found;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700344}
345
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700346InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700347 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700348 addSource(Source);
349}
350
Matt Wala49889232014-07-18 12:45:09 -0700351InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
352 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700353 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700354 addSource(Source1);
355 addSource(Source2);
356}
357
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700358InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
359 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700360 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700361 addSource(Source1);
362 addSource(Source2);
363}
364
365InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
366 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700367 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700368 addSource(Source1);
369 addSource(Source2);
370}
371
Matt Wala49889232014-07-18 12:45:09 -0700372InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
373 Operand *Source1, Operand *Source2,
374 Operand *Source3)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700375 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700376 addSource(Source1);
377 addSource(Source2);
378 addSource(Source3);
379}
380
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700381InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700382 : InstHighLevel(Func, Inst::Load, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700383 addSource(SourceAddr);
384}
385
386InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700387 : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700388 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs);
389}
390
Andrew Scull57e12682015-09-16 11:30:19 -0700391// TODO: A Switch instruction (and maybe others) can add duplicate edges. We
392// may want to de-dup Phis and validate consistency (i.e., the source operands
393// are the same for duplicate edges), though it seems the current lowering code
394// is OK with this situation.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700395void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
396 Labels[getSrcSize()] = Label;
397 addSource(Source);
398}
399
Andrew Scull57e12682015-09-16 11:30:19 -0700400// Find the source operand corresponding to the incoming edge for the given
David Sehr263ac522016-04-04 10:11:08 -0700401// node.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700402Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
403 for (SizeT I = 0; I < getSrcSize(); ++I) {
404 if (Labels[I] == Target)
405 return getSrc(I);
406 }
407 llvm_unreachable("Phi target not found");
Jim Stichnothae953202014-12-20 06:17:49 -0800408 return nullptr;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700409}
410
David Sehr263ac522016-04-04 10:11:08 -0700411// Replace the source operand corresponding to the incoming edge for the given
412// node by a zero of the appropriate type.
413void InstPhi::clearOperandForTarget(CfgNode *Target) {
414 for (SizeT I = 0; I < getSrcSize(); ++I) {
415 if (getLabel(I) == Target) {
416 Type Ty = Dest->getType();
417 Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
418 return;
419 }
420 }
421 llvm_unreachable("Phi target not found");
422}
423
Andrew Scull57e12682015-09-16 11:30:19 -0700424// Updates liveness for a particular operand based on the given predecessor
425// edge. Doesn't mark the operand as live if the Phi instruction is dead or
426// deleted.
Jim Stichnoth47752552014-10-13 17:15:08 -0700427void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700428 Liveness *Liveness) {
429 if (isDeleted() || Dead)
430 return;
431 for (SizeT I = 0; I < getSrcSize(); ++I) {
432 if (Labels[I] == Target) {
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800433 if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
Jim Stichnothcc89c952016-03-31 11:55:23 -0700434 if (!Var->isRematerializable()) {
435 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
436 if (!Live[SrcIndex]) {
437 setLastUse(I);
438 Live[SrcIndex] = true;
439 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700440 }
441 }
442 return;
443 }
444 }
445 llvm_unreachable("Phi operand not found for specified target node");
446}
447
Andrew Scull57e12682015-09-16 11:30:19 -0700448// Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
449// "a=a_phi".
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700450Inst *InstPhi::lower(Cfg *Func) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700451 Variable *Dest = getDest();
452 assert(Dest);
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800453 Variable *NewSrc = Func->makeVariable(Dest->getType());
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700454 if (BuildDefs::dump())
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800455 NewSrc->setName(Func, Dest->getName(Func) + "_phi");
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700456 if (auto *NewSrc64On32 = llvm::dyn_cast<Variable64On32>(NewSrc))
457 NewSrc64On32->initHiLo(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700458 this->Dest = NewSrc;
Jim Stichnothad403532014-09-25 12:44:17 -0700459 return InstAssign::create(Func, Dest, NewSrc);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700460}
461
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700462InstRet::InstRet(Cfg *Func, Operand *RetValue)
Jim Stichnothae953202014-12-20 06:17:49 -0800463 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700464 if (RetValue)
465 addSource(RetValue);
466}
467
468InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
469 Operand *SourceTrue, Operand *SourceFalse)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700470 : InstHighLevel(Func, Inst::Select, 3, Dest) {
Matt Wala9cb61e22014-07-24 09:44:42 -0700471 assert(typeElementType(Condition->getType()) == IceType_i1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700472 addSource(Condition);
473 addSource(SourceTrue);
474 addSource(SourceFalse);
475}
476
477InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700478 : InstHighLevel(Func, Inst::Store, 3, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700479 addSource(Data);
480 addSource(Addr);
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700481 // The 3rd operand is a dummy placeholder for the RMW beacon.
482 addSource(Data);
483}
484
Andrew Scullaa6c1092015-09-03 17:50:30 -0700485Variable *InstStore::getRmwBeacon() const {
486 return llvm::dyn_cast<Variable>(getSrc(2));
487}
488
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700489void InstStore::setRmwBeacon(Variable *Beacon) {
490 Dest = llvm::dyn_cast<Variable>(getData());
491 Srcs[2] = Beacon;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700492}
493
494InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
495 CfgNode *LabelDefault)
Jim Stichnothae953202014-12-20 06:17:49 -0800496 : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700497 NumCases(NumCases) {
498 addSource(Source);
499 Values = Func->allocateArrayOf<uint64_t>(NumCases);
500 Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
501 // Initialize in case buggy code doesn't set all entries
502 for (SizeT I = 0; I < NumCases; ++I) {
503 Values[I] = 0;
Jim Stichnothae953202014-12-20 06:17:49 -0800504 Labels[I] = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700505 }
506}
507
508void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
509 assert(CaseIndex < NumCases);
510 Values[CaseIndex] = Value;
511 Labels[CaseIndex] = Label;
512}
513
514NodeList InstSwitch::getTerminatorEdges() const {
515 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800516 OutEdges.reserve(NumCases + 1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700517 OutEdges.push_back(LabelDefault);
518 for (SizeT I = 0; I < NumCases; ++I) {
519 OutEdges.push_back(Labels[I]);
520 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700521 std::sort(OutEdges.begin(), OutEdges.end(),
522 [](const CfgNode *x, const CfgNode *y) {
523 return x->getIndex() < y->getIndex();
524 });
525 auto Last = std::unique(OutEdges.begin(), OutEdges.end());
526 OutEdges.erase(Last, OutEdges.end());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700527 return OutEdges;
528}
529
Andrew Scull87f80c12015-07-20 10:19:16 -0700530bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
531 bool Found = false;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700532 if (LabelDefault == OldNode) {
533 LabelDefault = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700534 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700535 }
536 for (SizeT I = 0; I < NumCases; ++I) {
537 if (Labels[I] == OldNode) {
538 Labels[I] = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700539 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700540 }
541 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700542 return Found;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700543}
544
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700545InstUnreachable::InstUnreachable(Cfg *Func)
Jim Stichnothae953202014-12-20 06:17:49 -0800546 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700547
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800548InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
549 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
550 BundleOption(BundleOption) {}
551
552InstBundleUnlock::InstBundleUnlock(Cfg *Func)
553 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
554
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700555InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700556 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700557 assert(Dest);
558 if (Src)
559 addSource(Src);
560}
561
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800562InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight)
563 : InstHighLevel(Func, Inst::FakeUse, Weight, nullptr) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700564 assert(Src);
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800565 for (uint32_t i = 0; i < Weight; ++i)
566 addSource(Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700567}
568
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800569InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
Jim Stichnothae953202014-12-20 06:17:49 -0800570 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700571
Andrew Scull87f80c12015-07-20 10:19:16 -0700572InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
573 : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
Andrew Scull86df4e92015-07-30 13:54:44 -0700574 Id(Func->getTarget()->makeNextJumpTableNumber()), NumTargets(NumTargets) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700575 Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
576 for (SizeT I = 0; I < NumTargets; ++I)
577 Targets[I] = Default;
578}
579
580bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
581 bool Found = false;
582 for (SizeT I = 0; I < NumTargets; ++I) {
583 if (Targets[I] == OldNode) {
584 Targets[I] = NewNode;
585 Found = true;
586 }
587 }
588 return Found;
589}
590
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800591Type InstCall::getReturnType() const {
Jim Stichnothae953202014-12-20 06:17:49 -0800592 if (Dest == nullptr)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800593 return IceType_void;
594 return Dest->getType();
595}
596
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700597// ======================== Dump routines ======================== //
598
599void Inst::dumpDecorated(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700600 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800601 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700602 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800603 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700604 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800605 if (Func->isVerbose(IceV_InstNumbers)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700606 char buf[30];
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700607 InstNumberT Number = getNumber();
608 if (Number == NumberDeleted)
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700609 snprintf(buf, llvm::array_lengthof(buf), "[XXX]");
610 else
611 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number);
612 Str << buf;
613 }
614 Str << " ";
615 if (isDeleted())
616 Str << " //";
617 dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700618 dumpExtras(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700619 Str << "\n";
620}
621
622void Inst::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700623 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800624 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700625 Ostream &Str = Func->getContext()->getStrDump();
626 dumpDest(Func);
Eric Holke37076a2016-01-27 14:06:35 -0800627 Str << " =~ " << getInstName() << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700628 dumpSources(Func);
629}
630
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700631void Inst::dumpExtras(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700632 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800633 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700634 Ostream &Str = Func->getContext()->getStrDump();
635 bool First = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700636 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
637 // known to end at this instruction.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800638 if (Func->isVerbose(IceV_Liveness)) {
John Portoec3f5652015-08-31 15:07:09 -0700639 FOREACH_VAR_IN_INST(Var, *this) {
640 if (isLastUse(Var)) {
641 if (First)
642 Str << " // LIVEEND={";
643 else
644 Str << ",";
645 Var->dump(Func);
646 First = false;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700647 }
648 }
649 if (!First)
650 Str << "}";
651 }
652}
653
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700654void Inst::dumpSources(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700655 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800656 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700657 Ostream &Str = Func->getContext()->getStrDump();
658 for (SizeT I = 0; I < getSrcSize(); ++I) {
659 if (I > 0)
660 Str << ", ";
661 getSrc(I)->dump(Func);
662 }
663}
664
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700665void Inst::emitSources(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700666 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800667 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700668 Ostream &Str = Func->getContext()->getStrEmit();
669 for (SizeT I = 0; I < getSrcSize(); ++I) {
670 if (I > 0)
671 Str << ", ";
672 getSrc(I)->emit(Func);
673 }
674}
675
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700676void Inst::dumpDest(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700677 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800678 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700679 if (getDest())
680 getDest()->dump(Func);
681}
682
683void InstAlloca::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700684 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800685 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700686 Ostream &Str = Func->getContext()->getStrDump();
687 dumpDest(Func);
688 Str << " = alloca i8, i32 ";
689 getSizeInBytes()->dump(Func);
Jim Stichnoth72a8f8d2014-09-08 17:56:50 -0700690 if (getAlignInBytes())
691 Str << ", align " << getAlignInBytes();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700692}
693
694void InstArithmetic::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700695 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800696 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700697 Ostream &Str = Func->getContext()->getStrDump();
698 dumpDest(Func);
Eric Holke37076a2016-01-27 14:06:35 -0800699 Str << " = " << getInstName() << " " << getDest()->getType() << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700700 dumpSources(Func);
701}
702
703void InstAssign::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700704 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800705 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700706 Ostream &Str = Func->getContext()->getStrDump();
707 dumpDest(Func);
708 Str << " = " << getDest()->getType() << " ";
709 dumpSources(Func);
710}
711
712void InstBr::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700713 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800714 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700715 Ostream &Str = Func->getContext()->getStrDump();
716 dumpDest(Func);
717 Str << "br ";
718 if (!isUnconditional()) {
719 Str << "i1 ";
720 getCondition()->dump(Func);
721 Str << ", label %" << getTargetTrue()->getName() << ", ";
722 }
723 Str << "label %" << getTargetFalse()->getName();
724}
725
726void InstCall::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700727 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800728 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700729 Ostream &Str = Func->getContext()->getStrDump();
730 if (getDest()) {
731 dumpDest(Func);
732 Str << " = ";
733 }
734 Str << "call ";
735 if (getDest())
736 Str << getDest()->getType();
737 else
738 Str << "void";
739 Str << " ";
740 getCallTarget()->dump(Func);
741 Str << "(";
742 for (SizeT I = 0; I < getNumArgs(); ++I) {
743 if (I > 0)
744 Str << ", ";
745 Str << getArg(I)->getType() << " ";
746 getArg(I)->dump(Func);
747 }
748 Str << ")";
749}
750
Karl Schimpfbf170372014-12-15 10:16:31 -0800751const char *InstCast::getCastName(InstCast::OpKind Kind) {
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800752 if (Kind < InstCast::OpKind::_num)
753 return InstCastAttributes[Kind].DisplayString;
Karl Schimpfbf170372014-12-15 10:16:31 -0800754 llvm_unreachable("Invalid InstCast::OpKind");
755 return "???";
756}
757
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700758void InstCast::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700759 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800760 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700761 Ostream &Str = Func->getContext()->getStrDump();
762 dumpDest(Func);
Karl Schimpfbf170372014-12-15 10:16:31 -0800763 Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
764 << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700765 dumpSources(Func);
766 Str << " to " << getDest()->getType();
767}
768
769void InstIcmp::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700770 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800771 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700772 Ostream &Str = Func->getContext()->getStrDump();
773 dumpDest(Func);
774 Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
775 << getSrc(0)->getType() << " ";
776 dumpSources(Func);
777}
778
Matt Wala49889232014-07-18 12:45:09 -0700779void InstExtractElement::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700780 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800781 return;
Matt Wala49889232014-07-18 12:45:09 -0700782 Ostream &Str = Func->getContext()->getStrDump();
783 dumpDest(Func);
784 Str << " = extractelement ";
785 Str << getSrc(0)->getType() << " ";
786 getSrc(0)->dump(Func);
787 Str << ", ";
788 Str << getSrc(1)->getType() << " ";
789 getSrc(1)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700790}
Matt Wala49889232014-07-18 12:45:09 -0700791
792void InstInsertElement::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700793 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800794 return;
Matt Wala49889232014-07-18 12:45:09 -0700795 Ostream &Str = Func->getContext()->getStrDump();
796 dumpDest(Func);
797 Str << " = insertelement ";
798 Str << getSrc(0)->getType() << " ";
799 getSrc(0)->dump(Func);
800 Str << ", ";
801 Str << getSrc(1)->getType() << " ";
802 getSrc(1)->dump(Func);
803 Str << ", ";
804 Str << getSrc(2)->getType() << " ";
805 getSrc(2)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700806}
Matt Wala49889232014-07-18 12:45:09 -0700807
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700808void InstFcmp::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700809 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800810 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700811 Ostream &Str = Func->getContext()->getStrDump();
812 dumpDest(Func);
813 Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
814 << getSrc(0)->getType() << " ";
815 dumpSources(Func);
816}
817
818void InstLoad::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700819 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800820 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700821 Ostream &Str = Func->getContext()->getStrDump();
822 dumpDest(Func);
823 Type Ty = getDest()->getType();
Jim Stichnothe5b58fb2015-06-01 15:17:20 -0700824 Str << " = load " << Ty << ", " << Ty << "* ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700825 dumpSources(Func);
826 Str << ", align " << typeAlignInBytes(Ty);
827}
828
829void InstStore::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700830 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800831 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700832 Ostream &Str = Func->getContext()->getStrDump();
833 Type Ty = getData()->getType();
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700834 dumpDest(Func);
835 if (Dest)
836 Str << " = ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700837 Str << "store " << Ty << " ";
838 getData()->dump(Func);
839 Str << ", " << Ty << "* ";
840 getAddr()->dump(Func);
841 Str << ", align " << typeAlignInBytes(Ty);
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700842 if (getRmwBeacon()) {
843 Str << ", beacon ";
844 getRmwBeacon()->dump(Func);
845 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700846}
847
848void InstSwitch::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700849 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800850 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700851 Ostream &Str = Func->getContext()->getStrDump();
852 Type Ty = getComparison()->getType();
853 Str << "switch " << Ty << " ";
854 getSrc(0)->dump(Func);
855 Str << ", label %" << getLabelDefault()->getName() << " [\n";
856 for (SizeT I = 0; I < getNumCases(); ++I) {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700857 Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
858 << ", label %" << getLabel(I)->getName() << "\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700859 }
860 Str << " ]";
861}
862
863void InstPhi::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700864 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800865 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700866 Ostream &Str = Func->getContext()->getStrDump();
867 dumpDest(Func);
868 Str << " = phi " << getDest()->getType() << " ";
869 for (SizeT I = 0; I < getSrcSize(); ++I) {
870 if (I > 0)
871 Str << ", ";
872 Str << "[ ";
873 getSrc(I)->dump(Func);
874 Str << ", %" << Labels[I]->getName() << " ]";
875 }
876}
877
878void InstRet::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700879 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800880 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700881 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700882 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700883 Str << "ret " << Ty;
884 if (hasRetValue()) {
885 Str << " ";
886 dumpSources(Func);
887 }
888}
889
890void InstSelect::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700891 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800892 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700893 Ostream &Str = Func->getContext()->getStrDump();
894 dumpDest(Func);
895 Operand *Condition = getCondition();
896 Operand *TrueOp = getTrueOperand();
897 Operand *FalseOp = getFalseOperand();
898 Str << " = select " << Condition->getType() << " ";
899 Condition->dump(Func);
900 Str << ", " << TrueOp->getType() << " ";
901 TrueOp->dump(Func);
902 Str << ", " << FalseOp->getType() << " ";
903 FalseOp->dump(Func);
904}
905
906void InstUnreachable::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700907 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800908 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700909 Ostream &Str = Func->getContext()->getStrDump();
910 Str << "unreachable";
911}
912
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800913void InstBundleLock::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700914 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800915 return;
916 Ostream &Str = Func->getContext()->getStrEmit();
917 Str << "\t.bundle_lock";
918 switch (BundleOption) {
919 case Opt_None:
920 break;
921 case Opt_AlignToEnd:
Jim Stichnoth6106df82015-12-16 06:17:58 -0800922 Str << "\t"
923 "align_to_end";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800924 break;
John Porto56958cb2016-01-14 09:18:18 -0800925 case Opt_PadToEnd:
926 Str << "\t"
927 "align_to_end /* pad_to_end */";
928 break;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800929 }
Jim Stichnoth33436472015-11-27 14:22:02 -0800930 Str << "\n";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800931}
932
933void InstBundleLock::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700934 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800935 return;
936 Ostream &Str = Func->getContext()->getStrDump();
937 Str << "bundle_lock";
938 switch (BundleOption) {
939 case Opt_None:
940 break;
941 case Opt_AlignToEnd:
942 Str << " align_to_end";
943 break;
John Porto56958cb2016-01-14 09:18:18 -0800944 case Opt_PadToEnd:
945 Str << " pad_to_end";
946 break;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800947 }
948}
949
950void InstBundleUnlock::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700951 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800952 return;
953 Ostream &Str = Func->getContext()->getStrEmit();
954 Str << "\t.bundle_unlock";
Jim Stichnoth33436472015-11-27 14:22:02 -0800955 Str << "\n";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800956}
957
958void InstBundleUnlock::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700959 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800960 return;
961 Ostream &Str = Func->getContext()->getStrDump();
962 Str << "bundle_unlock";
963}
964
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700965void InstFakeDef::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700966 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800967 return;
Andrew Scull57e12682015-09-16 11:30:19 -0700968 // Go ahead and "emit" these for now, since they are relatively rare.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700969 Ostream &Str = Func->getContext()->getStrEmit();
970 Str << "\t# ";
971 getDest()->emit(Func);
Jim Stichnothfbdc7e42016-02-09 17:25:02 -0800972 Str << " = def.pseudo";
973 if (getSrcSize() > 0)
974 Str << " ";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700975 emitSources(Func);
Jim Stichnoth3e859b72015-11-10 14:39:51 -0800976 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700977}
978
979void InstFakeDef::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700980 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800981 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700982 Ostream &Str = Func->getContext()->getStrDump();
983 dumpDest(Func);
984 Str << " = def.pseudo ";
985 dumpSources(Func);
986}
987
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800988void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700989
990void InstFakeUse::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700991 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800992 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700993 Ostream &Str = Func->getContext()->getStrDump();
994 Str << "use.pseudo ";
995 dumpSources(Func);
996}
997
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800998void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700999
1000void InstFakeKill::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001001 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001002 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001003 Ostream &Str = Func->getContext()->getStrDump();
1004 if (Linked->isDeleted())
1005 Str << "// ";
Jim Stichnoth87ff3a12014-11-14 10:27:29 -08001006 Str << "kill.pseudo scratch_regs";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001007}
1008
Andrew Scull87f80c12015-07-20 10:19:16 -07001009void InstJumpTable::dump(const Cfg *Func) const {
1010 if (!BuildDefs::dump())
1011 return;
1012 Ostream &Str = Func->getContext()->getStrDump();
1013 Str << "jump table [";
1014 for (SizeT I = 0; I < NumTargets; ++I)
1015 Str << "\n " << Targets[I]->getName();
1016 Str << "\n ]";
1017}
1018
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001019void InstTarget::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001020 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001021 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001022 Ostream &Str = Func->getContext()->getStrDump();
1023 Str << "[TARGET] ";
1024 Inst::dump(Func);
1025}
1026
Jan Voungb3401d22015-05-18 09:38:21 -07001027bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
Jim Stichnoth1fb030c2015-10-15 11:10:38 -07001028 const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
Jan Voungb3401d22015-05-18 09:38:21 -07001029 if (!SrcVar)
1030 return false;
1031 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
Andrew Scull57e12682015-09-16 11:30:19 -07001032 // TODO: On x86-64, instructions like "mov eax, eax" are used to clear the
1033 // upper 32 bits of rax. We need to recognize and preserve these.
Jan Voungb3401d22015-05-18 09:38:21 -07001034 return true;
1035 }
1036 if (!Dest->hasReg() && !SrcVar->hasReg() &&
1037 Dest->getStackOffset() == SrcVar->getStackOffset())
1038 return true;
1039 return false;
1040}
1041
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001042} // end of namespace Ice