blob: a40d2345702f9b45e95fdb9769fcc56b2989b69d [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
Jim Stichnothd72385f2016-04-06 12:21:14 -070025#include "llvm/Support/Format.h"
26
Jim Stichnothf7c9a142014-04-29 10:52:43 -070027namespace Ice {
28
29namespace {
30
31// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070032const struct InstArithmeticAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070033 const char *DisplayString;
34 bool IsCommutative;
35} InstArithmeticAttributes[] = {
36#define X(tag, str, commutative) \
37 { str, commutative } \
38 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080039 ICEINSTARITHMETIC_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070040#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080041};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070042
43// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070044const struct InstCastAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070045 const char *DisplayString;
46} InstCastAttributes[] = {
47#define X(tag, str) \
48 { str } \
49 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080050 ICEINSTCAST_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070051#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080052};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070053
54// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070055const struct InstFcmpAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056 const char *DisplayString;
57} InstFcmpAttributes[] = {
58#define X(tag, str) \
59 { str } \
60 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080061 ICEINSTFCMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070062#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080063};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070064
65// Using non-anonymous struct so that array_lengthof works.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070066const struct InstIcmpAttributes_ {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067 const char *DisplayString;
Manasij Mukherjee0c704172016-07-21 12:40:24 -070068 InstIcmp::ICond Reverse;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070069} InstIcmpAttributes[] = {
Manasij Mukherjee0c704172016-07-21 12:40:24 -070070#define X(tag, reverse, str) \
71 { str, InstIcmp::ICond::reverse } \
Jim Stichnothf7c9a142014-04-29 10:52:43 -070072 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080073 ICEINSTICMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070074#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080075};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070076
77} // end of anonymous namespace
78
79Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
Jim Stichnotheafb56c2015-06-22 10:35:22 -070080 : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
Manasij Mukherjee45f51a22016-06-27 16:12:37 -070081 LiveRangesEnded(0) {
82 Srcs.reserve(MaxSrcs);
83}
Jim Stichnothd97c7df2014-06-04 11:57:08 -070084
Jim Stichnoth467ffe52016-03-29 15:01:06 -070085const char *Inst::getInstName() const {
Eric Holke37076a2016-01-27 14:06:35 -080086 if (!BuildDefs::dump())
87 return "???";
88
89 switch (Kind) {
90#define X(InstrKind, name) \
91 case InstrKind: \
92 return name
93 X(Unreachable, "unreachable");
94 X(Alloca, "alloca");
95 X(Arithmetic, "arithmetic");
96 X(Br, "br");
97 X(Call, "call");
98 X(Cast, "cast");
99 X(ExtractElement, "extractelement");
100 X(Fcmp, "fcmp");
101 X(Icmp, "icmp");
102 X(IntrinsicCall, "intrinsiccall");
103 X(InsertElement, "insertelement");
104 X(Load, "load");
105 X(Phi, "phi");
106 X(Ret, "ret");
107 X(Select, "select");
108 X(Store, "store");
109 X(Switch, "switch");
110 X(Assign, "assign");
Eric Holk67c7c412016-04-15 13:05:37 -0700111 X(Breakpoint, "break");
Eric Holke37076a2016-01-27 14:06:35 -0800112 X(BundleLock, "bundlelock");
113 X(BundleUnlock, "bundleunlock");
114 X(FakeDef, "fakedef");
115 X(FakeUse, "fakeuse");
116 X(FakeKill, "fakekill");
117 X(JumpTable, "jumptable");
John Portoa47c11c2016-04-21 05:53:42 -0700118 X(ShuffleVector, "shufflevector");
Eric Holke37076a2016-01-27 14:06:35 -0800119#undef X
120 default:
121 assert(Kind >= Target);
122 return "target";
123 }
124}
125
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700126// Assign the instruction a new number.
127void Inst::renumber(Cfg *Func) {
128 Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
129}
130
Andrew Scull57e12682015-09-16 11:30:19 -0700131// Delete the instruction if its tentative Dead flag is still set after
132// liveness analysis.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700133void Inst::deleteIfDead() {
134 if (Dead)
135 setDeleted();
136}
137
Andrew Scull57e12682015-09-16 11:30:19 -0700138// If Src is a Variable, it returns true if this instruction ends Src's live
139// range. Otherwise, returns false.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700140bool Inst::isLastUse(const Operand *TestSrc) const {
141 if (LiveRangesEnded == 0)
142 return false; // early-exit optimization
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800143 if (auto *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700144 LREndedBits Mask = LiveRangesEnded;
John Portoec3f5652015-08-31 15:07:09 -0700145 FOREACH_VAR_IN_INST(Var, *this) {
146 if (Var == TestVar) {
147 // We've found where the variable is used in the instruction.
148 return Mask & 1;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700149 }
John Portoec3f5652015-08-31 15:07:09 -0700150 Mask >>= 1;
151 if (Mask == 0)
152 return false; // another early-exit optimization
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700153 }
154 }
155 return false;
156}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700157
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700158// Given an instruction like:
159// a = b + c + [x,y] + e
160// which was created from OrigInst:
161// a = b + c + d + e
162// with SpliceAssn spliced in:
163// d = [x,y]
164//
Andrew Scull57e12682015-09-16 11:30:19 -0700165// Reconstruct the LiveRangesEnded bitmask in this instruction by combining the
166// LiveRangesEnded values of OrigInst and SpliceAssn. If operands d and [x,y]
167// contain a different number of variables, then the bitmask position for e may
168// be different in OrigInst and the current instruction, requiring extra shifts
169// and masks in the computation. In the example above, OrigInst has variable e
170// in bit position 3, whereas the current instruction has e in bit position 4
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700171// because [x,y] consumes 2 bitmask slots while d only consumed 1.
172//
Andrew Scull57e12682015-09-16 11:30:19 -0700173// Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
174// HasSideEffects set.
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700175void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) {
176 HasSideEffects |= OrigInst->HasSideEffects;
177 HasSideEffects |= SpliceAssn->HasSideEffects;
178 // Find the bitmask index of SpliceAssn's dest within OrigInst.
179 Variable *SpliceDest = SpliceAssn->getDest();
180 SizeT Index = 0;
181 for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) {
182 Operand *Src = OrigInst->getSrc(I);
183 if (Src == SpliceDest) {
184 LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1);
185 LREndedBits RightMask = OrigInst->LiveRangesEnded >> (Index + 1);
186 LiveRangesEnded = LeftMask | (SpliceAssn->LiveRangesEnded << Index) |
187 (RightMask << (Index + getSrc(I)->getNumVars()));
188 return;
189 }
190 Index += getSrc(I)->getNumVars();
191 }
192 llvm::report_fatal_error("Failed to find splice operand");
193}
194
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700195bool Inst::isMemoryWrite() const {
196 llvm::report_fatal_error("Attempt to call base Inst::isMemoryWrite() method");
197}
198
Jim Stichnoth47752552014-10-13 17:15:08 -0700199void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700200 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700201 resetLastUses();
Jim Stichnoth47752552014-10-13 17:15:08 -0700202 VariablesMetadata *VMetadata = Func->getVMetadata();
John Portoec3f5652015-08-31 15:07:09 -0700203 FOREACH_VAR_IN_INST(Var, *this) {
204 if (VMetadata->isMultiBlock(Var))
205 continue;
206 SizeT Index = Var->getIndex();
207 if (Live[Index])
208 continue;
209 Live[Index] = true;
210 setLastUse(IndexOfVarInInst(Var));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700211 }
212}
213
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700214bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
Jim Stichnoth47752552014-10-13 17:15:08 -0700215 Liveness *Liveness, LiveBeginEndMap *LiveBegin,
216 LiveBeginEndMap *LiveEnd) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700217 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700218
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700219 Dead = false;
Jim Stichnothcc89c952016-03-31 11:55:23 -0700220 if (Dest && !Dest->isRematerializable()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700221 SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700222 if (Live[VarNum]) {
Jim Stichnoth230d4102015-09-25 17:40:32 -0700223 if (!isDestRedefined()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700224 Live[VarNum] = false;
Jim Stichnoth552490c2015-08-05 16:21:42 -0700225 if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700226 LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
227 }
228 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700229 } else {
230 if (!hasSideEffects())
231 Dead = true;
232 }
233 }
234 if (Dead)
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700235 return false;
Andrew Scull57e12682015-09-16 11:30:19 -0700236 // Phi arguments only get added to Live in the predecessor node, but we still
237 // need to update LiveRangesEnded.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700238 bool IsPhi = llvm::isa<InstPhi>(this);
239 resetLastUses();
John Portoec3f5652015-08-31 15:07:09 -0700240 FOREACH_VAR_IN_INST(Var, *this) {
Jim Stichnothcc89c952016-03-31 11:55:23 -0700241 if (Var->isRematerializable())
242 continue;
John Portoec3f5652015-08-31 15:07:09 -0700243 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
244 if (!Live[VarNum]) {
245 setLastUse(IndexOfVarInInst(Var));
246 if (!IsPhi) {
247 Live[VarNum] = true;
248 // For a variable in SSA form, its live range can end at most once in a
Andrew Scull57e12682015-09-16 11:30:19 -0700249 // basic block. However, after lowering to two-address instructions, we
250 // end up with sequences like "t=b;t+=c;a=t" where t's live range
251 // begins and ends twice. ICE only allows a variable to have a single
252 // liveness interval in a basic block (except for blocks where a
253 // variable is live-in and live-out but there is a gap in the middle).
254 // Therefore, this lowered sequence needs to represent a single
255 // conservative live range for t. Since the instructions are being
256 // traversed backwards, we make sure LiveEnd is only set once by
257 // setting it only when LiveEnd[VarNum]==0 (sentinel value). Note that
258 // it's OK to set LiveBegin multiple times because of the backwards
259 // traversal.
John Portoec3f5652015-08-31 15:07:09 -0700260 if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
261 // Ideally, we would verify that VarNum wasn't already added in this
262 // block, but this can't be done very efficiently with LiveEnd as a
Andrew Scull57e12682015-09-16 11:30:19 -0700263 // vector. Instead, livenessPostprocess() verifies this after the
John Portoec3f5652015-08-31 15:07:09 -0700264 // vector has been sorted.
265 LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700266 }
267 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700268 }
269 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700270 return true;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700271}
272
David Sehr2f3b8ec2015-11-16 16:51:39 -0800273InstAlloca::InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
274 uint32_t AlignInBytes)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700275 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700276 // Verify AlignInBytes is 0 or a power of 2.
277 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
278 addSource(ByteCount);
279}
280
281InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
282 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700283 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700284 addSource(Source1);
285 addSource(Source2);
286}
287
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700288const char *InstArithmetic::getInstName() const {
Eric Holke37076a2016-01-27 14:06:35 -0800289 if (!BuildDefs::dump())
290 return "???";
291
292 return InstArithmeticAttributes[getOp()].DisplayString;
293}
294
Karl Schimpfd6064a12014-08-27 15:34:58 -0700295const char *InstArithmetic::getOpName(OpKind Op) {
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800296 return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
297 : "???";
Karl Schimpfd6064a12014-08-27 15:34:58 -0700298}
299
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700300bool InstArithmetic::isCommutative() const {
301 return InstArithmeticAttributes[getOp()].IsCommutative;
302}
303
304InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700305 : InstHighLevel(Func, Inst::Assign, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700306 addSource(Source);
307}
308
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700309bool InstAssign::isVarAssign() const { return llvm::isa<Variable>(getSrc(0)); }
310
Andrew Scull57e12682015-09-16 11:30:19 -0700311// If TargetTrue==TargetFalse, we turn it into an unconditional branch. This
312// ensures that, along with the 'switch' instruction semantics, there is at
313// most one edge from one node to another.
Karl Schimpfc070d6f2015-06-26 10:25:33 -0700314InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
315 CfgNode *TargetFalse_)
316 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
317 TargetTrue(TargetTrue_) {
David Sehr263ac522016-04-04 10:11:08 -0700318 if (auto *Constant = llvm::dyn_cast<ConstantInteger32>(Source)) {
319 int32_t C32 = Constant->getValue();
320 if (C32 != 0) {
321 TargetFalse = TargetTrue;
322 }
323 TargetTrue = nullptr; // turn into unconditional version
324 } else if (TargetTrue == TargetFalse) {
Jim Stichnothae953202014-12-20 06:17:49 -0800325 TargetTrue = nullptr; // turn into unconditional version
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700326 } else {
327 addSource(Source);
328 }
329}
330
331InstBr::InstBr(Cfg *Func, CfgNode *Target)
Jim Stichnothae953202014-12-20 06:17:49 -0800332 : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
333 TargetTrue(nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700334
335NodeList InstBr::getTerminatorEdges() const {
336 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800337 OutEdges.reserve(TargetTrue ? 2 : 1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700338 OutEdges.push_back(TargetFalse);
339 if (TargetTrue)
340 OutEdges.push_back(TargetTrue);
341 return OutEdges;
342}
343
Andrew Scull87f80c12015-07-20 10:19:16 -0700344bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
345 bool Found = false;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700346 if (TargetFalse == OldNode) {
347 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700348 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700349 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700350 if (TargetTrue == OldNode) {
351 TargetTrue = NewNode;
352 Found = true;
353 }
354 return Found;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700355}
356
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700357InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700358 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700359 addSource(Source);
360}
361
Matt Wala49889232014-07-18 12:45:09 -0700362InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
363 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700364 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700365 addSource(Source1);
366 addSource(Source2);
367}
368
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700369InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
370 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700371 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700372 addSource(Source1);
373 addSource(Source2);
374}
375
376InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
377 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700378 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700379 addSource(Source1);
380 addSource(Source2);
381}
382
Matt Wala49889232014-07-18 12:45:09 -0700383InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
384 Operand *Source1, Operand *Source2,
385 Operand *Source3)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700386 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700387 addSource(Source1);
388 addSource(Source2);
389 addSource(Source3);
390}
391
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700392InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700393 : InstHighLevel(Func, Inst::Load, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700394 addSource(SourceAddr);
395}
396
397InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700398 : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700399 Labels.reserve(MaxSrcs);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700400}
401
Andrew Scull57e12682015-09-16 11:30:19 -0700402// TODO: A Switch instruction (and maybe others) can add duplicate edges. We
403// may want to de-dup Phis and validate consistency (i.e., the source operands
404// are the same for duplicate edges), though it seems the current lowering code
405// is OK with this situation.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700406void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700407 assert(Label);
408 Labels.push_back(Label);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700409 addSource(Source);
410}
411
Andrew Scull57e12682015-09-16 11:30:19 -0700412// Find the source operand corresponding to the incoming edge for the given
David Sehr263ac522016-04-04 10:11:08 -0700413// node.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700414Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
415 for (SizeT I = 0; I < getSrcSize(); ++I) {
416 if (Labels[I] == Target)
417 return getSrc(I);
418 }
419 llvm_unreachable("Phi target not found");
Jim Stichnothae953202014-12-20 06:17:49 -0800420 return nullptr;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700421}
422
David Sehr263ac522016-04-04 10:11:08 -0700423// Replace the source operand corresponding to the incoming edge for the given
424// node by a zero of the appropriate type.
425void InstPhi::clearOperandForTarget(CfgNode *Target) {
426 for (SizeT I = 0; I < getSrcSize(); ++I) {
427 if (getLabel(I) == Target) {
428 Type Ty = Dest->getType();
429 Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
430 return;
431 }
432 }
433 llvm_unreachable("Phi target not found");
434}
435
Andrew Scull57e12682015-09-16 11:30:19 -0700436// Updates liveness for a particular operand based on the given predecessor
437// edge. Doesn't mark the operand as live if the Phi instruction is dead or
438// deleted.
Jim Stichnoth47752552014-10-13 17:15:08 -0700439void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700440 Liveness *Liveness) {
441 if (isDeleted() || Dead)
442 return;
443 for (SizeT I = 0; I < getSrcSize(); ++I) {
444 if (Labels[I] == Target) {
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800445 if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
Jim Stichnothcc89c952016-03-31 11:55:23 -0700446 if (!Var->isRematerializable()) {
447 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
448 if (!Live[SrcIndex]) {
449 setLastUse(I);
450 Live[SrcIndex] = true;
451 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700452 }
453 }
454 return;
455 }
456 }
457 llvm_unreachable("Phi operand not found for specified target node");
458}
459
Andrew Scull57e12682015-09-16 11:30:19 -0700460// Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
461// "a=a_phi".
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700462Inst *InstPhi::lower(Cfg *Func) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700463 Variable *Dest = getDest();
464 assert(Dest);
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800465 Variable *NewSrc = Func->makeVariable(Dest->getType());
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700466 if (BuildDefs::dump())
Jim Stichnotha91c3412016-04-05 15:31:43 -0700467 NewSrc->setName(Func, Dest->getName() + "_phi");
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700468 if (auto *NewSrc64On32 = llvm::dyn_cast<Variable64On32>(NewSrc))
469 NewSrc64On32->initHiLo(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700470 this->Dest = NewSrc;
Jim Stichnothad403532014-09-25 12:44:17 -0700471 return InstAssign::create(Func, Dest, NewSrc);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700472}
473
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700474InstRet::InstRet(Cfg *Func, Operand *RetValue)
Jim Stichnothae953202014-12-20 06:17:49 -0800475 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700476 if (RetValue)
477 addSource(RetValue);
478}
479
480InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
481 Operand *SourceTrue, Operand *SourceFalse)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700482 : InstHighLevel(Func, Inst::Select, 3, Dest) {
Matt Wala9cb61e22014-07-24 09:44:42 -0700483 assert(typeElementType(Condition->getType()) == IceType_i1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700484 addSource(Condition);
485 addSource(SourceTrue);
486 addSource(SourceFalse);
487}
488
489InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700490 : InstHighLevel(Func, Inst::Store, 3, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700491 addSource(Data);
492 addSource(Addr);
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700493 // The 3rd operand is a dummy placeholder for the RMW beacon.
494 addSource(Data);
495}
496
Andrew Scullaa6c1092015-09-03 17:50:30 -0700497Variable *InstStore::getRmwBeacon() const {
498 return llvm::dyn_cast<Variable>(getSrc(2));
499}
500
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700501void InstStore::setRmwBeacon(Variable *Beacon) {
502 Dest = llvm::dyn_cast<Variable>(getData());
503 Srcs[2] = Beacon;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700504}
505
506InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
507 CfgNode *LabelDefault)
Jim Stichnothae953202014-12-20 06:17:49 -0800508 : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700509 NumCases(NumCases) {
510 addSource(Source);
511 Values = Func->allocateArrayOf<uint64_t>(NumCases);
512 Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
513 // Initialize in case buggy code doesn't set all entries
514 for (SizeT I = 0; I < NumCases; ++I) {
515 Values[I] = 0;
Jim Stichnothae953202014-12-20 06:17:49 -0800516 Labels[I] = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700517 }
518}
519
520void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
521 assert(CaseIndex < NumCases);
522 Values[CaseIndex] = Value;
523 Labels[CaseIndex] = Label;
524}
525
526NodeList InstSwitch::getTerminatorEdges() const {
527 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800528 OutEdges.reserve(NumCases + 1);
Eric Holk67c7c412016-04-15 13:05:37 -0700529 assert(LabelDefault);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700530 OutEdges.push_back(LabelDefault);
531 for (SizeT I = 0; I < NumCases; ++I) {
Eric Holk67c7c412016-04-15 13:05:37 -0700532 assert(Labels[I]);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700533 OutEdges.push_back(Labels[I]);
534 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700535 std::sort(OutEdges.begin(), OutEdges.end(),
536 [](const CfgNode *x, const CfgNode *y) {
537 return x->getIndex() < y->getIndex();
538 });
539 auto Last = std::unique(OutEdges.begin(), OutEdges.end());
540 OutEdges.erase(Last, OutEdges.end());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700541 return OutEdges;
542}
543
Andrew Scull87f80c12015-07-20 10:19:16 -0700544bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
545 bool Found = false;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700546 if (LabelDefault == OldNode) {
547 LabelDefault = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700548 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700549 }
550 for (SizeT I = 0; I < NumCases; ++I) {
551 if (Labels[I] == OldNode) {
552 Labels[I] = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700553 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700554 }
555 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700556 return Found;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700557}
558
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700559InstUnreachable::InstUnreachable(Cfg *Func)
Jim Stichnothae953202014-12-20 06:17:49 -0800560 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700561
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800562InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
563 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
564 BundleOption(BundleOption) {}
565
566InstBundleUnlock::InstBundleUnlock(Cfg *Func)
567 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
568
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700569InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700570 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700571 assert(Dest);
572 if (Src)
573 addSource(Src);
574}
575
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800576InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight)
577 : InstHighLevel(Func, Inst::FakeUse, Weight, nullptr) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700578 assert(Src);
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800579 for (uint32_t i = 0; i < Weight; ++i)
580 addSource(Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700581}
582
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800583InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
Jim Stichnothae953202014-12-20 06:17:49 -0800584 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700585
Nicolas Capens579b1b32016-12-09 14:56:03 -0500586InstShuffleVector::InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0,
587 Operand *Src1)
John Portoa47c11c2016-04-21 05:53:42 -0700588 : InstHighLevel(Func, Inst::ShuffleVector, 2, Dest),
589 NumIndexes(typeNumElements(Dest->getType())) {
590 addSource(Src0);
591 addSource(Src1);
592 Indexes = Func->allocateArrayOf<ConstantInteger32 *>(NumIndexes);
593}
594
John Porto03077212016-04-05 06:30:21 -0700595namespace {
596GlobalString makeName(Cfg *Func, const SizeT Id) {
597 const auto FuncName = Func->getFunctionName();
598 auto *Ctx = Func->getContext();
599 if (FuncName.hasStdString())
600 return GlobalString::createWithString(
601 Ctx, ".L" + FuncName.toString() + "$jumptable$__" + std::to_string(Id));
602 return GlobalString::createWithString(
Jim Stichnothe922c232016-04-09 08:54:20 -0700603 Ctx, "$J" + std::to_string(FuncName.getID()) + "_" + std::to_string(Id));
John Porto03077212016-04-05 06:30:21 -0700604}
605} // end of anonymous namespace
606
Andrew Scull87f80c12015-07-20 10:19:16 -0700607InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
608 : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
John Porto03077212016-04-05 06:30:21 -0700609 Id(Func->getTarget()->makeNextJumpTableNumber()), NumTargets(NumTargets),
610 Name(makeName(Func, Id)), FuncName(Func->getFunctionName()) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700611 Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
John Porto03077212016-04-05 06:30:21 -0700612 for (SizeT I = 0; I < NumTargets; ++I) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700613 Targets[I] = Default;
John Porto03077212016-04-05 06:30:21 -0700614 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700615}
616
617bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
618 bool Found = false;
619 for (SizeT I = 0; I < NumTargets; ++I) {
620 if (Targets[I] == OldNode) {
621 Targets[I] = NewNode;
622 Found = true;
623 }
624 }
625 return Found;
626}
627
John Porto03077212016-04-05 06:30:21 -0700628JumpTableData InstJumpTable::toJumpTableData(Assembler *Asm) const {
629 JumpTableData::TargetList TargetList(NumTargets);
630 for (SizeT i = 0; i < NumTargets; ++i) {
631 const SizeT Index = Targets[i]->getIndex();
632 TargetList[i] = Asm->getCfgNodeLabel(Index)->getPosition();
633 }
634 return JumpTableData(Name, FuncName, Id, TargetList);
635}
636
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800637Type InstCall::getReturnType() const {
Jim Stichnothae953202014-12-20 06:17:49 -0800638 if (Dest == nullptr)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800639 return IceType_void;
640 return Dest->getType();
641}
642
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700643// ======================== Dump routines ======================== //
644
645void Inst::dumpDecorated(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700646 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800647 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700648 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800649 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700650 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800651 if (Func->isVerbose(IceV_InstNumbers)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700652 InstNumberT Number = getNumber();
653 if (Number == NumberDeleted)
Jim Stichnothd72385f2016-04-06 12:21:14 -0700654 Str << "[XXX]";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700655 else
Jim Stichnothd72385f2016-04-06 12:21:14 -0700656 Str << llvm::format("[%3d]", Number);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700657 }
658 Str << " ";
659 if (isDeleted())
660 Str << " //";
661 dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700662 dumpExtras(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700663 Str << "\n";
664}
665
666void Inst::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700667 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800668 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700669 Ostream &Str = Func->getContext()->getStrDump();
670 dumpDest(Func);
Eric Holke37076a2016-01-27 14:06:35 -0800671 Str << " =~ " << getInstName() << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700672 dumpSources(Func);
673}
674
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700675void Inst::dumpExtras(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700676 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800677 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700678 Ostream &Str = Func->getContext()->getStrDump();
679 bool First = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700680 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
681 // known to end at this instruction.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800682 if (Func->isVerbose(IceV_Liveness)) {
John Portoec3f5652015-08-31 15:07:09 -0700683 FOREACH_VAR_IN_INST(Var, *this) {
684 if (isLastUse(Var)) {
685 if (First)
686 Str << " // LIVEEND={";
687 else
688 Str << ",";
689 Var->dump(Func);
690 First = false;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700691 }
692 }
693 if (!First)
694 Str << "}";
695 }
696}
697
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700698void Inst::dumpSources(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700699 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800700 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700701 Ostream &Str = Func->getContext()->getStrDump();
702 for (SizeT I = 0; I < getSrcSize(); ++I) {
703 if (I > 0)
704 Str << ", ";
705 getSrc(I)->dump(Func);
706 }
707}
708
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700709void Inst::emitSources(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700710 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800711 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700712 Ostream &Str = Func->getContext()->getStrEmit();
713 for (SizeT I = 0; I < getSrcSize(); ++I) {
714 if (I > 0)
715 Str << ", ";
716 getSrc(I)->emit(Func);
717 }
718}
719
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700720void Inst::dumpDest(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700721 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800722 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700723 if (getDest())
724 getDest()->dump(Func);
725}
726
727void InstAlloca::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700728 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800729 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700730 Ostream &Str = Func->getContext()->getStrDump();
731 dumpDest(Func);
732 Str << " = alloca i8, i32 ";
733 getSizeInBytes()->dump(Func);
Jim Stichnoth72a8f8d2014-09-08 17:56:50 -0700734 if (getAlignInBytes())
735 Str << ", align " << getAlignInBytes();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700736}
737
738void InstArithmetic::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700739 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800740 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700741 Ostream &Str = Func->getContext()->getStrDump();
742 dumpDest(Func);
Eric Holke37076a2016-01-27 14:06:35 -0800743 Str << " = " << getInstName() << " " << getDest()->getType() << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700744 dumpSources(Func);
745}
746
747void InstAssign::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700748 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800749 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700750 Ostream &Str = Func->getContext()->getStrDump();
751 dumpDest(Func);
752 Str << " = " << getDest()->getType() << " ";
753 dumpSources(Func);
754}
755
756void InstBr::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700757 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800758 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700759 Ostream &Str = Func->getContext()->getStrDump();
760 dumpDest(Func);
761 Str << "br ";
762 if (!isUnconditional()) {
763 Str << "i1 ";
764 getCondition()->dump(Func);
765 Str << ", label %" << getTargetTrue()->getName() << ", ";
766 }
767 Str << "label %" << getTargetFalse()->getName();
768}
769
770void InstCall::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700771 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800772 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700773 Ostream &Str = Func->getContext()->getStrDump();
774 if (getDest()) {
775 dumpDest(Func);
776 Str << " = ";
777 }
778 Str << "call ";
779 if (getDest())
780 Str << getDest()->getType();
781 else
782 Str << "void";
783 Str << " ";
784 getCallTarget()->dump(Func);
785 Str << "(";
786 for (SizeT I = 0; I < getNumArgs(); ++I) {
787 if (I > 0)
788 Str << ", ";
789 Str << getArg(I)->getType() << " ";
790 getArg(I)->dump(Func);
791 }
792 Str << ")";
793}
794
Karl Schimpfbf170372014-12-15 10:16:31 -0800795const char *InstCast::getCastName(InstCast::OpKind Kind) {
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800796 if (Kind < InstCast::OpKind::_num)
797 return InstCastAttributes[Kind].DisplayString;
Karl Schimpfbf170372014-12-15 10:16:31 -0800798 llvm_unreachable("Invalid InstCast::OpKind");
799 return "???";
800}
801
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700802void InstCast::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700803 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800804 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700805 Ostream &Str = Func->getContext()->getStrDump();
806 dumpDest(Func);
Karl Schimpfbf170372014-12-15 10:16:31 -0800807 Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
808 << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700809 dumpSources(Func);
810 Str << " to " << getDest()->getType();
811}
812
813void InstIcmp::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700814 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800815 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700816 Ostream &Str = Func->getContext()->getStrDump();
817 dumpDest(Func);
818 Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
819 << getSrc(0)->getType() << " ";
820 dumpSources(Func);
821}
822
Matt Wala49889232014-07-18 12:45:09 -0700823void InstExtractElement::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700824 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800825 return;
Matt Wala49889232014-07-18 12:45:09 -0700826 Ostream &Str = Func->getContext()->getStrDump();
827 dumpDest(Func);
828 Str << " = extractelement ";
829 Str << getSrc(0)->getType() << " ";
830 getSrc(0)->dump(Func);
831 Str << ", ";
832 Str << getSrc(1)->getType() << " ";
833 getSrc(1)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700834}
Matt Wala49889232014-07-18 12:45:09 -0700835
836void InstInsertElement::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700837 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800838 return;
Matt Wala49889232014-07-18 12:45:09 -0700839 Ostream &Str = Func->getContext()->getStrDump();
840 dumpDest(Func);
841 Str << " = insertelement ";
842 Str << getSrc(0)->getType() << " ";
843 getSrc(0)->dump(Func);
844 Str << ", ";
845 Str << getSrc(1)->getType() << " ";
846 getSrc(1)->dump(Func);
847 Str << ", ";
848 Str << getSrc(2)->getType() << " ";
849 getSrc(2)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700850}
Matt Wala49889232014-07-18 12:45:09 -0700851
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700852void InstFcmp::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700853 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800854 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700855 Ostream &Str = Func->getContext()->getStrDump();
856 dumpDest(Func);
857 Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
858 << getSrc(0)->getType() << " ";
859 dumpSources(Func);
860}
861
862void InstLoad::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700863 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800864 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700865 Ostream &Str = Func->getContext()->getStrDump();
866 dumpDest(Func);
867 Type Ty = getDest()->getType();
Jim Stichnothe5b58fb2015-06-01 15:17:20 -0700868 Str << " = load " << Ty << ", " << Ty << "* ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700869 dumpSources(Func);
870 Str << ", align " << typeAlignInBytes(Ty);
871}
872
873void InstStore::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700874 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800875 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700876 Ostream &Str = Func->getContext()->getStrDump();
877 Type Ty = getData()->getType();
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700878 dumpDest(Func);
879 if (Dest)
880 Str << " = ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700881 Str << "store " << Ty << " ";
882 getData()->dump(Func);
883 Str << ", " << Ty << "* ";
884 getAddr()->dump(Func);
885 Str << ", align " << typeAlignInBytes(Ty);
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700886 if (getRmwBeacon()) {
887 Str << ", beacon ";
888 getRmwBeacon()->dump(Func);
889 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700890}
891
892void InstSwitch::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700893 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800894 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700895 Ostream &Str = Func->getContext()->getStrDump();
896 Type Ty = getComparison()->getType();
897 Str << "switch " << Ty << " ";
898 getSrc(0)->dump(Func);
899 Str << ", label %" << getLabelDefault()->getName() << " [\n";
900 for (SizeT I = 0; I < getNumCases(); ++I) {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700901 Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
902 << ", label %" << getLabel(I)->getName() << "\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700903 }
904 Str << " ]";
905}
906
907void InstPhi::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700908 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800909 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700910 Ostream &Str = Func->getContext()->getStrDump();
911 dumpDest(Func);
912 Str << " = phi " << getDest()->getType() << " ";
913 for (SizeT I = 0; I < getSrcSize(); ++I) {
914 if (I > 0)
915 Str << ", ";
916 Str << "[ ";
917 getSrc(I)->dump(Func);
918 Str << ", %" << Labels[I]->getName() << " ]";
919 }
920}
921
922void InstRet::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700923 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800924 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700925 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700926 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700927 Str << "ret " << Ty;
928 if (hasRetValue()) {
929 Str << " ";
930 dumpSources(Func);
931 }
932}
933
934void InstSelect::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700935 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800936 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700937 Ostream &Str = Func->getContext()->getStrDump();
938 dumpDest(Func);
939 Operand *Condition = getCondition();
940 Operand *TrueOp = getTrueOperand();
941 Operand *FalseOp = getFalseOperand();
942 Str << " = select " << Condition->getType() << " ";
943 Condition->dump(Func);
944 Str << ", " << TrueOp->getType() << " ";
945 TrueOp->dump(Func);
946 Str << ", " << FalseOp->getType() << " ";
947 FalseOp->dump(Func);
948}
949
950void InstUnreachable::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700951 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800952 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700953 Ostream &Str = Func->getContext()->getStrDump();
954 Str << "unreachable";
955}
956
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800957void InstBundleLock::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700958 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800959 return;
960 Ostream &Str = Func->getContext()->getStrEmit();
961 Str << "\t.bundle_lock";
962 switch (BundleOption) {
963 case Opt_None:
964 break;
965 case Opt_AlignToEnd:
Jim Stichnoth6106df82015-12-16 06:17:58 -0800966 Str << "\t"
967 "align_to_end";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800968 break;
John Porto56958cb2016-01-14 09:18:18 -0800969 case Opt_PadToEnd:
970 Str << "\t"
971 "align_to_end /* pad_to_end */";
972 break;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800973 }
Jim Stichnoth33436472015-11-27 14:22:02 -0800974 Str << "\n";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800975}
976
977void InstBundleLock::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700978 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800979 return;
980 Ostream &Str = Func->getContext()->getStrDump();
981 Str << "bundle_lock";
982 switch (BundleOption) {
983 case Opt_None:
984 break;
985 case Opt_AlignToEnd:
986 Str << " align_to_end";
987 break;
John Porto56958cb2016-01-14 09:18:18 -0800988 case Opt_PadToEnd:
989 Str << " pad_to_end";
990 break;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800991 }
992}
993
994void InstBundleUnlock::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700995 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800996 return;
997 Ostream &Str = Func->getContext()->getStrEmit();
998 Str << "\t.bundle_unlock";
Jim Stichnoth33436472015-11-27 14:22:02 -0800999 Str << "\n";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -08001000}
1001
1002void InstBundleUnlock::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001003 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -08001004 return;
1005 Ostream &Str = Func->getContext()->getStrDump();
1006 Str << "bundle_unlock";
1007}
1008
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001009void InstFakeDef::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001010 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001011 return;
Andrew Scull57e12682015-09-16 11:30:19 -07001012 // Go ahead and "emit" these for now, since they are relatively rare.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001013 Ostream &Str = Func->getContext()->getStrEmit();
1014 Str << "\t# ";
1015 getDest()->emit(Func);
Jim Stichnothfbdc7e42016-02-09 17:25:02 -08001016 Str << " = def.pseudo";
1017 if (getSrcSize() > 0)
1018 Str << " ";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001019 emitSources(Func);
Jim Stichnoth3e859b72015-11-10 14:39:51 -08001020 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001021}
1022
1023void InstFakeDef::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001024 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001025 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001026 Ostream &Str = Func->getContext()->getStrDump();
1027 dumpDest(Func);
1028 Str << " = def.pseudo ";
1029 dumpSources(Func);
1030}
1031
Jim Stichnothbb8b6242014-11-04 09:10:01 -08001032void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001033
1034void InstFakeUse::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001035 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001036 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001037 Ostream &Str = Func->getContext()->getStrDump();
1038 Str << "use.pseudo ";
1039 dumpSources(Func);
1040}
1041
Jim Stichnothbb8b6242014-11-04 09:10:01 -08001042void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001043
1044void InstFakeKill::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001045 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001046 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001047 Ostream &Str = Func->getContext()->getStrDump();
1048 if (Linked->isDeleted())
1049 Str << "// ";
Jim Stichnoth87ff3a12014-11-14 10:27:29 -08001050 Str << "kill.pseudo scratch_regs";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001051}
1052
John Portoa47c11c2016-04-21 05:53:42 -07001053void InstShuffleVector::dump(const Cfg *Func) const {
1054 if (!BuildDefs::dump())
1055 return;
1056 Ostream &Str = Func->getContext()->getStrDump();
1057 Str << "shufflevector ";
1058 dumpDest(Func);
1059 Str << " = ";
1060 dumpSources(Func);
1061 for (SizeT I = 0; I < NumIndexes; ++I) {
1062 Str << ", ";
1063 Indexes[I]->dump(Func);
1064 }
1065 Str << "\n";
1066}
1067
Andrew Scull87f80c12015-07-20 10:19:16 -07001068void InstJumpTable::dump(const Cfg *Func) const {
1069 if (!BuildDefs::dump())
1070 return;
1071 Ostream &Str = Func->getContext()->getStrDump();
1072 Str << "jump table [";
1073 for (SizeT I = 0; I < NumTargets; ++I)
1074 Str << "\n " << Targets[I]->getName();
1075 Str << "\n ]";
1076}
1077
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001078void InstTarget::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001079 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001080 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001081 Ostream &Str = Func->getContext()->getStrDump();
1082 Str << "[TARGET] ";
1083 Inst::dump(Func);
1084}
1085
Eric Holk67c7c412016-04-15 13:05:37 -07001086InstBreakpoint::InstBreakpoint(Cfg *Func)
1087 : InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
1088
Manasij Mukherjee0c704172016-07-21 12:40:24 -07001089void InstIcmp::reverseConditionAndOperands() {
1090 Condition = InstIcmpAttributes[Condition].Reverse;
1091 std::swap(Srcs[0], Srcs[1]);
1092}
Jim Stichnothb9a84722016-08-01 13:18:36 -07001093
Jan Voungb3401d22015-05-18 09:38:21 -07001094bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
Jim Stichnoth1fb030c2015-10-15 11:10:38 -07001095 const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
Jim Stichnothb9a84722016-08-01 13:18:36 -07001096 if (SrcVar == nullptr)
Jan Voungb3401d22015-05-18 09:38:21 -07001097 return false;
1098 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
Andrew Scull57e12682015-09-16 11:30:19 -07001099 // TODO: On x86-64, instructions like "mov eax, eax" are used to clear the
1100 // upper 32 bits of rax. We need to recognize and preserve these.
Jan Voungb3401d22015-05-18 09:38:21 -07001101 return true;
1102 }
Jim Stichnothfe62f0a2016-07-10 05:13:18 -07001103 if (!Dest->hasReg() && !SrcVar->hasReg()) {
1104 if (!Dest->hasStackOffset() || !SrcVar->hasStackOffset()) {
Jim Stichnothb9a84722016-08-01 13:18:36 -07001105 // If called before stack slots have been assigned (i.e. as part of the
1106 // dump() routine), conservatively return false.
Jim Stichnothfe62f0a2016-07-10 05:13:18 -07001107 return false;
1108 }
1109 if (Dest->getStackOffset() != SrcVar->getStackOffset()) {
1110 return false;
1111 }
Jan Voungb3401d22015-05-18 09:38:21 -07001112 return true;
Jim Stichnothfe62f0a2016-07-10 05:13:18 -07001113 }
Jim Stichnothb9a84722016-08-01 13:18:36 -07001114 // For a "v=t" assignment where t has a register, v has a stack slot, and v
1115 // has a LinkedTo stack root, and v and t share the same LinkedTo root, return
1116 // true. This is because this assignment is effectively reassigning the same
1117 // value to the original LinkedTo stack root.
1118 if (SrcVar->hasReg() && Dest->hasStackOffset() &&
1119 Dest->getLinkedToStackRoot() != nullptr &&
1120 Dest->getLinkedToRoot() == SrcVar->getLinkedToRoot()) {
1121 return true;
1122 }
Jan Voungb3401d22015-05-18 09:38:21 -07001123 return false;
1124}
1125
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001126} // end of namespace Ice