blob: f9cfdddf60c13b41771fd4a9fa80dd6d46edd2db [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;
68} InstIcmpAttributes[] = {
69#define X(tag, str) \
70 { str } \
71 ,
Jim Stichnothd9dc82e2015-03-03 17:06:33 -080072 ICEINSTICMP_TABLE
Jim Stichnothf7c9a142014-04-29 10:52:43 -070073#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -080074};
Jim Stichnothf7c9a142014-04-29 10:52:43 -070075
76} // end of anonymous namespace
77
78Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
Jim Stichnotheafb56c2015-06-22 10:35:22 -070079 : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
Manasij Mukherjee45f51a22016-06-27 16:12:37 -070080 LiveRangesEnded(0) {
81 Srcs.reserve(MaxSrcs);
82}
Jim Stichnothd97c7df2014-06-04 11:57:08 -070083
Jim Stichnoth467ffe52016-03-29 15:01:06 -070084const char *Inst::getInstName() const {
Eric Holke37076a2016-01-27 14:06:35 -080085 if (!BuildDefs::dump())
86 return "???";
87
88 switch (Kind) {
89#define X(InstrKind, name) \
90 case InstrKind: \
91 return name
92 X(Unreachable, "unreachable");
93 X(Alloca, "alloca");
94 X(Arithmetic, "arithmetic");
95 X(Br, "br");
96 X(Call, "call");
97 X(Cast, "cast");
98 X(ExtractElement, "extractelement");
99 X(Fcmp, "fcmp");
100 X(Icmp, "icmp");
101 X(IntrinsicCall, "intrinsiccall");
102 X(InsertElement, "insertelement");
103 X(Load, "load");
104 X(Phi, "phi");
105 X(Ret, "ret");
106 X(Select, "select");
107 X(Store, "store");
108 X(Switch, "switch");
109 X(Assign, "assign");
Eric Holk67c7c412016-04-15 13:05:37 -0700110 X(Breakpoint, "break");
Eric Holke37076a2016-01-27 14:06:35 -0800111 X(BundleLock, "bundlelock");
112 X(BundleUnlock, "bundleunlock");
113 X(FakeDef, "fakedef");
114 X(FakeUse, "fakeuse");
115 X(FakeKill, "fakekill");
116 X(JumpTable, "jumptable");
John Portoa47c11c2016-04-21 05:53:42 -0700117 X(ShuffleVector, "shufflevector");
Eric Holke37076a2016-01-27 14:06:35 -0800118#undef X
119 default:
120 assert(Kind >= Target);
121 return "target";
122 }
123}
124
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700125// Assign the instruction a new number.
126void Inst::renumber(Cfg *Func) {
127 Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
128}
129
Andrew Scull57e12682015-09-16 11:30:19 -0700130// Delete the instruction if its tentative Dead flag is still set after
131// liveness analysis.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700132void Inst::deleteIfDead() {
133 if (Dead)
134 setDeleted();
135}
136
Andrew Scull57e12682015-09-16 11:30:19 -0700137// If Src is a Variable, it returns true if this instruction ends Src's live
138// range. Otherwise, returns false.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700139bool Inst::isLastUse(const Operand *TestSrc) const {
140 if (LiveRangesEnded == 0)
141 return false; // early-exit optimization
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800142 if (auto *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700143 LREndedBits Mask = LiveRangesEnded;
John Portoec3f5652015-08-31 15:07:09 -0700144 FOREACH_VAR_IN_INST(Var, *this) {
145 if (Var == TestVar) {
146 // We've found where the variable is used in the instruction.
147 return Mask & 1;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700148 }
John Portoec3f5652015-08-31 15:07:09 -0700149 Mask >>= 1;
150 if (Mask == 0)
151 return false; // another early-exit optimization
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700152 }
153 }
154 return false;
155}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700156
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700157// Given an instruction like:
158// a = b + c + [x,y] + e
159// which was created from OrigInst:
160// a = b + c + d + e
161// with SpliceAssn spliced in:
162// d = [x,y]
163//
Andrew Scull57e12682015-09-16 11:30:19 -0700164// Reconstruct the LiveRangesEnded bitmask in this instruction by combining the
165// LiveRangesEnded values of OrigInst and SpliceAssn. If operands d and [x,y]
166// contain a different number of variables, then the bitmask position for e may
167// be different in OrigInst and the current instruction, requiring extra shifts
168// and masks in the computation. In the example above, OrigInst has variable e
169// in bit position 3, whereas the current instruction has e in bit position 4
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700170// because [x,y] consumes 2 bitmask slots while d only consumed 1.
171//
Andrew Scull57e12682015-09-16 11:30:19 -0700172// Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
173// HasSideEffects set.
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700174void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) {
175 HasSideEffects |= OrigInst->HasSideEffects;
176 HasSideEffects |= SpliceAssn->HasSideEffects;
177 // Find the bitmask index of SpliceAssn's dest within OrigInst.
178 Variable *SpliceDest = SpliceAssn->getDest();
179 SizeT Index = 0;
180 for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) {
181 Operand *Src = OrigInst->getSrc(I);
182 if (Src == SpliceDest) {
183 LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1);
184 LREndedBits RightMask = OrigInst->LiveRangesEnded >> (Index + 1);
185 LiveRangesEnded = LeftMask | (SpliceAssn->LiveRangesEnded << Index) |
186 (RightMask << (Index + getSrc(I)->getNumVars()));
187 return;
188 }
189 Index += getSrc(I)->getNumVars();
190 }
191 llvm::report_fatal_error("Failed to find splice operand");
192}
193
Jim Stichnothf1f773d2016-04-21 16:54:33 -0700194bool Inst::isMemoryWrite() const {
195 llvm::report_fatal_error("Attempt to call base Inst::isMemoryWrite() method");
196}
197
Jim Stichnoth47752552014-10-13 17:15:08 -0700198void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700199 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700200 resetLastUses();
Jim Stichnoth47752552014-10-13 17:15:08 -0700201 VariablesMetadata *VMetadata = Func->getVMetadata();
John Portoec3f5652015-08-31 15:07:09 -0700202 FOREACH_VAR_IN_INST(Var, *this) {
203 if (VMetadata->isMultiBlock(Var))
204 continue;
205 SizeT Index = Var->getIndex();
206 if (Live[Index])
207 continue;
208 Live[Index] = true;
209 setLastUse(IndexOfVarInInst(Var));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700210 }
211}
212
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700213bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
Jim Stichnoth47752552014-10-13 17:15:08 -0700214 Liveness *Liveness, LiveBeginEndMap *LiveBegin,
215 LiveBeginEndMap *LiveEnd) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700216 assert(!isDeleted());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700217
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700218 Dead = false;
Jim Stichnothcc89c952016-03-31 11:55:23 -0700219 if (Dest && !Dest->isRematerializable()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700220 SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700221 if (Live[VarNum]) {
Jim Stichnoth230d4102015-09-25 17:40:32 -0700222 if (!isDestRedefined()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700223 Live[VarNum] = false;
Jim Stichnoth552490c2015-08-05 16:21:42 -0700224 if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700225 LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
226 }
227 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700228 } else {
229 if (!hasSideEffects())
230 Dead = true;
231 }
232 }
233 if (Dead)
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700234 return false;
Andrew Scull57e12682015-09-16 11:30:19 -0700235 // Phi arguments only get added to Live in the predecessor node, but we still
236 // need to update LiveRangesEnded.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700237 bool IsPhi = llvm::isa<InstPhi>(this);
238 resetLastUses();
John Portoec3f5652015-08-31 15:07:09 -0700239 FOREACH_VAR_IN_INST(Var, *this) {
Jim Stichnothcc89c952016-03-31 11:55:23 -0700240 if (Var->isRematerializable())
241 continue;
John Portoec3f5652015-08-31 15:07:09 -0700242 SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
243 if (!Live[VarNum]) {
244 setLastUse(IndexOfVarInInst(Var));
245 if (!IsPhi) {
246 Live[VarNum] = true;
247 // For a variable in SSA form, its live range can end at most once in a
Andrew Scull57e12682015-09-16 11:30:19 -0700248 // basic block. However, after lowering to two-address instructions, we
249 // end up with sequences like "t=b;t+=c;a=t" where t's live range
250 // begins and ends twice. ICE only allows a variable to have a single
251 // liveness interval in a basic block (except for blocks where a
252 // variable is live-in and live-out but there is a gap in the middle).
253 // Therefore, this lowered sequence needs to represent a single
254 // conservative live range for t. Since the instructions are being
255 // traversed backwards, we make sure LiveEnd is only set once by
256 // setting it only when LiveEnd[VarNum]==0 (sentinel value). Note that
257 // it's OK to set LiveBegin multiple times because of the backwards
258 // traversal.
John Portoec3f5652015-08-31 15:07:09 -0700259 if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
260 // Ideally, we would verify that VarNum wasn't already added in this
261 // block, but this can't be done very efficiently with LiveEnd as a
Andrew Scull57e12682015-09-16 11:30:19 -0700262 // vector. Instead, livenessPostprocess() verifies this after the
John Portoec3f5652015-08-31 15:07:09 -0700263 // vector has been sorted.
264 LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700265 }
266 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700267 }
268 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700269 return true;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700270}
271
David Sehr2f3b8ec2015-11-16 16:51:39 -0800272InstAlloca::InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
273 uint32_t AlignInBytes)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700274 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700275 // Verify AlignInBytes is 0 or a power of 2.
276 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
277 addSource(ByteCount);
278}
279
280InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
281 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700282 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700283 addSource(Source1);
284 addSource(Source2);
285}
286
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700287const char *InstArithmetic::getInstName() const {
Eric Holke37076a2016-01-27 14:06:35 -0800288 if (!BuildDefs::dump())
289 return "???";
290
291 return InstArithmeticAttributes[getOp()].DisplayString;
292}
293
Karl Schimpfd6064a12014-08-27 15:34:58 -0700294const char *InstArithmetic::getOpName(OpKind Op) {
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800295 return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
296 : "???";
Karl Schimpfd6064a12014-08-27 15:34:58 -0700297}
298
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700299bool InstArithmetic::isCommutative() const {
300 return InstArithmeticAttributes[getOp()].IsCommutative;
301}
302
303InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700304 : InstHighLevel(Func, Inst::Assign, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700305 addSource(Source);
306}
307
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700308bool InstAssign::isVarAssign() const { return llvm::isa<Variable>(getSrc(0)); }
309
Andrew Scull57e12682015-09-16 11:30:19 -0700310// If TargetTrue==TargetFalse, we turn it into an unconditional branch. This
311// ensures that, along with the 'switch' instruction semantics, there is at
312// most one edge from one node to another.
Karl Schimpfc070d6f2015-06-26 10:25:33 -0700313InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
314 CfgNode *TargetFalse_)
315 : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
316 TargetTrue(TargetTrue_) {
David Sehr263ac522016-04-04 10:11:08 -0700317 if (auto *Constant = llvm::dyn_cast<ConstantInteger32>(Source)) {
318 int32_t C32 = Constant->getValue();
319 if (C32 != 0) {
320 TargetFalse = TargetTrue;
321 }
322 TargetTrue = nullptr; // turn into unconditional version
323 } else if (TargetTrue == TargetFalse) {
Jim Stichnothae953202014-12-20 06:17:49 -0800324 TargetTrue = nullptr; // turn into unconditional version
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700325 } else {
326 addSource(Source);
327 }
328}
329
330InstBr::InstBr(Cfg *Func, CfgNode *Target)
Jim Stichnothae953202014-12-20 06:17:49 -0800331 : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
332 TargetTrue(nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700333
334NodeList InstBr::getTerminatorEdges() const {
335 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800336 OutEdges.reserve(TargetTrue ? 2 : 1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700337 OutEdges.push_back(TargetFalse);
338 if (TargetTrue)
339 OutEdges.push_back(TargetTrue);
340 return OutEdges;
341}
342
Andrew Scull87f80c12015-07-20 10:19:16 -0700343bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
344 bool Found = false;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700345 if (TargetFalse == OldNode) {
346 TargetFalse = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700347 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700348 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700349 if (TargetTrue == OldNode) {
350 TargetTrue = NewNode;
351 Found = true;
352 }
353 return Found;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700354}
355
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700356InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700357 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700358 addSource(Source);
359}
360
Matt Wala49889232014-07-18 12:45:09 -0700361InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
362 Operand *Source1, Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700363 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700364 addSource(Source1);
365 addSource(Source2);
366}
367
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700368InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
369 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700370 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700371 addSource(Source1);
372 addSource(Source2);
373}
374
375InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
376 Operand *Source2)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700377 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700378 addSource(Source1);
379 addSource(Source2);
380}
381
Matt Wala49889232014-07-18 12:45:09 -0700382InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
383 Operand *Source1, Operand *Source2,
384 Operand *Source3)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700385 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
Matt Wala49889232014-07-18 12:45:09 -0700386 addSource(Source1);
387 addSource(Source2);
388 addSource(Source3);
389}
390
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700391InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700392 : InstHighLevel(Func, Inst::Load, 1, Dest) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700393 addSource(SourceAddr);
394}
395
396InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700397 : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700398 Labels.reserve(MaxSrcs);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700399}
400
Andrew Scull57e12682015-09-16 11:30:19 -0700401// TODO: A Switch instruction (and maybe others) can add duplicate edges. We
402// may want to de-dup Phis and validate consistency (i.e., the source operands
403// are the same for duplicate edges), though it seems the current lowering code
404// is OK with this situation.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700405void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
Manasij Mukherjee45f51a22016-06-27 16:12:37 -0700406 assert(Label);
407 Labels.push_back(Label);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700408 addSource(Source);
409}
410
Andrew Scull57e12682015-09-16 11:30:19 -0700411// Find the source operand corresponding to the incoming edge for the given
David Sehr263ac522016-04-04 10:11:08 -0700412// node.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700413Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
414 for (SizeT I = 0; I < getSrcSize(); ++I) {
415 if (Labels[I] == Target)
416 return getSrc(I);
417 }
418 llvm_unreachable("Phi target not found");
Jim Stichnothae953202014-12-20 06:17:49 -0800419 return nullptr;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700420}
421
David Sehr263ac522016-04-04 10:11:08 -0700422// Replace the source operand corresponding to the incoming edge for the given
423// node by a zero of the appropriate type.
424void InstPhi::clearOperandForTarget(CfgNode *Target) {
425 for (SizeT I = 0; I < getSrcSize(); ++I) {
426 if (getLabel(I) == Target) {
427 Type Ty = Dest->getType();
428 Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
429 return;
430 }
431 }
432 llvm_unreachable("Phi target not found");
433}
434
Andrew Scull57e12682015-09-16 11:30:19 -0700435// Updates liveness for a particular operand based on the given predecessor
436// edge. Doesn't mark the operand as live if the Phi instruction is dead or
437// deleted.
Jim Stichnoth47752552014-10-13 17:15:08 -0700438void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700439 Liveness *Liveness) {
440 if (isDeleted() || Dead)
441 return;
442 for (SizeT I = 0; I < getSrcSize(); ++I) {
443 if (Labels[I] == Target) {
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800444 if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
Jim Stichnothcc89c952016-03-31 11:55:23 -0700445 if (!Var->isRematerializable()) {
446 SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
447 if (!Live[SrcIndex]) {
448 setLastUse(I);
449 Live[SrcIndex] = true;
450 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700451 }
452 }
453 return;
454 }
455 }
456 llvm_unreachable("Phi operand not found for specified target node");
457}
458
Andrew Scull57e12682015-09-16 11:30:19 -0700459// Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
460// "a=a_phi".
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700461Inst *InstPhi::lower(Cfg *Func) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700462 Variable *Dest = getDest();
463 assert(Dest);
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800464 Variable *NewSrc = Func->makeVariable(Dest->getType());
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700465 if (BuildDefs::dump())
Jim Stichnotha91c3412016-04-05 15:31:43 -0700466 NewSrc->setName(Func, Dest->getName() + "_phi");
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700467 if (auto *NewSrc64On32 = llvm::dyn_cast<Variable64On32>(NewSrc))
468 NewSrc64On32->initHiLo(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700469 this->Dest = NewSrc;
Jim Stichnothad403532014-09-25 12:44:17 -0700470 return InstAssign::create(Func, Dest, NewSrc);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700471}
472
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700473InstRet::InstRet(Cfg *Func, Operand *RetValue)
Jim Stichnothae953202014-12-20 06:17:49 -0800474 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700475 if (RetValue)
476 addSource(RetValue);
477}
478
479InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
480 Operand *SourceTrue, Operand *SourceFalse)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700481 : InstHighLevel(Func, Inst::Select, 3, Dest) {
Matt Wala9cb61e22014-07-24 09:44:42 -0700482 assert(typeElementType(Condition->getType()) == IceType_i1);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700483 addSource(Condition);
484 addSource(SourceTrue);
485 addSource(SourceFalse);
486}
487
488InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700489 : InstHighLevel(Func, Inst::Store, 3, nullptr) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700490 addSource(Data);
491 addSource(Addr);
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700492 // The 3rd operand is a dummy placeholder for the RMW beacon.
493 addSource(Data);
494}
495
Andrew Scullaa6c1092015-09-03 17:50:30 -0700496Variable *InstStore::getRmwBeacon() const {
497 return llvm::dyn_cast<Variable>(getSrc(2));
498}
499
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700500void InstStore::setRmwBeacon(Variable *Beacon) {
501 Dest = llvm::dyn_cast<Variable>(getData());
502 Srcs[2] = Beacon;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700503}
504
505InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
506 CfgNode *LabelDefault)
Jim Stichnothae953202014-12-20 06:17:49 -0800507 : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700508 NumCases(NumCases) {
509 addSource(Source);
510 Values = Func->allocateArrayOf<uint64_t>(NumCases);
511 Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
512 // Initialize in case buggy code doesn't set all entries
513 for (SizeT I = 0; I < NumCases; ++I) {
514 Values[I] = 0;
Jim Stichnothae953202014-12-20 06:17:49 -0800515 Labels[I] = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700516 }
517}
518
519void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
520 assert(CaseIndex < NumCases);
521 Values[CaseIndex] = Value;
522 Labels[CaseIndex] = Label;
523}
524
525NodeList InstSwitch::getTerminatorEdges() const {
526 NodeList OutEdges;
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800527 OutEdges.reserve(NumCases + 1);
Eric Holk67c7c412016-04-15 13:05:37 -0700528 assert(LabelDefault);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700529 OutEdges.push_back(LabelDefault);
530 for (SizeT I = 0; I < NumCases; ++I) {
Eric Holk67c7c412016-04-15 13:05:37 -0700531 assert(Labels[I]);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700532 OutEdges.push_back(Labels[I]);
533 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700534 std::sort(OutEdges.begin(), OutEdges.end(),
535 [](const CfgNode *x, const CfgNode *y) {
536 return x->getIndex() < y->getIndex();
537 });
538 auto Last = std::unique(OutEdges.begin(), OutEdges.end());
539 OutEdges.erase(Last, OutEdges.end());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700540 return OutEdges;
541}
542
Andrew Scull87f80c12015-07-20 10:19:16 -0700543bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
544 bool Found = false;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700545 if (LabelDefault == OldNode) {
546 LabelDefault = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700547 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700548 }
549 for (SizeT I = 0; I < NumCases; ++I) {
550 if (Labels[I] == OldNode) {
551 Labels[I] = NewNode;
Andrew Scull87f80c12015-07-20 10:19:16 -0700552 Found = true;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700553 }
554 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700555 return Found;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700556}
557
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700558InstUnreachable::InstUnreachable(Cfg *Func)
Jim Stichnothae953202014-12-20 06:17:49 -0800559 : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700560
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800561InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
562 : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
563 BundleOption(BundleOption) {}
564
565InstBundleUnlock::InstBundleUnlock(Cfg *Func)
566 : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
567
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700568InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700569 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700570 assert(Dest);
571 if (Src)
572 addSource(Src);
573}
574
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800575InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight)
576 : InstHighLevel(Func, Inst::FakeUse, Weight, nullptr) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700577 assert(Src);
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800578 for (uint32_t i = 0; i < Weight; ++i)
579 addSource(Src);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700580}
581
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800582InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
Jim Stichnothae953202014-12-20 06:17:49 -0800583 : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700584
John Portoa47c11c2016-04-21 05:53:42 -0700585InstShuffleVector::InstShuffleVector(Cfg *Func, Variable *Dest, Variable *Src0,
586 Variable *Src1)
587 : InstHighLevel(Func, Inst::ShuffleVector, 2, Dest),
588 NumIndexes(typeNumElements(Dest->getType())) {
589 addSource(Src0);
590 addSource(Src1);
591 Indexes = Func->allocateArrayOf<ConstantInteger32 *>(NumIndexes);
592}
593
John Porto03077212016-04-05 06:30:21 -0700594namespace {
595GlobalString makeName(Cfg *Func, const SizeT Id) {
596 const auto FuncName = Func->getFunctionName();
597 auto *Ctx = Func->getContext();
598 if (FuncName.hasStdString())
599 return GlobalString::createWithString(
600 Ctx, ".L" + FuncName.toString() + "$jumptable$__" + std::to_string(Id));
601 return GlobalString::createWithString(
Jim Stichnothe922c232016-04-09 08:54:20 -0700602 Ctx, "$J" + std::to_string(FuncName.getID()) + "_" + std::to_string(Id));
John Porto03077212016-04-05 06:30:21 -0700603}
604} // end of anonymous namespace
605
Andrew Scull87f80c12015-07-20 10:19:16 -0700606InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
607 : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
John Porto03077212016-04-05 06:30:21 -0700608 Id(Func->getTarget()->makeNextJumpTableNumber()), NumTargets(NumTargets),
609 Name(makeName(Func, Id)), FuncName(Func->getFunctionName()) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700610 Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
John Porto03077212016-04-05 06:30:21 -0700611 for (SizeT I = 0; I < NumTargets; ++I) {
Andrew Scull87f80c12015-07-20 10:19:16 -0700612 Targets[I] = Default;
John Porto03077212016-04-05 06:30:21 -0700613 }
Andrew Scull87f80c12015-07-20 10:19:16 -0700614}
615
616bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
617 bool Found = false;
618 for (SizeT I = 0; I < NumTargets; ++I) {
619 if (Targets[I] == OldNode) {
620 Targets[I] = NewNode;
621 Found = true;
622 }
623 }
624 return Found;
625}
626
John Porto03077212016-04-05 06:30:21 -0700627JumpTableData InstJumpTable::toJumpTableData(Assembler *Asm) const {
628 JumpTableData::TargetList TargetList(NumTargets);
629 for (SizeT i = 0; i < NumTargets; ++i) {
630 const SizeT Index = Targets[i]->getIndex();
631 TargetList[i] = Asm->getCfgNodeLabel(Index)->getPosition();
632 }
633 return JumpTableData(Name, FuncName, Id, TargetList);
634}
635
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800636Type InstCall::getReturnType() const {
Jim Stichnothae953202014-12-20 06:17:49 -0800637 if (Dest == nullptr)
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800638 return IceType_void;
639 return Dest->getType();
640}
641
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700642// ======================== Dump routines ======================== //
643
644void Inst::dumpDecorated(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700645 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800646 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700647 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800648 if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700649 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800650 if (Func->isVerbose(IceV_InstNumbers)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700651 InstNumberT Number = getNumber();
652 if (Number == NumberDeleted)
Jim Stichnothd72385f2016-04-06 12:21:14 -0700653 Str << "[XXX]";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700654 else
Jim Stichnothd72385f2016-04-06 12:21:14 -0700655 Str << llvm::format("[%3d]", Number);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700656 }
657 Str << " ";
658 if (isDeleted())
659 Str << " //";
660 dump(Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700661 dumpExtras(Func);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700662 Str << "\n";
663}
664
665void Inst::dump(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 Stichnothf7c9a142014-04-29 10:52:43 -0700668 Ostream &Str = Func->getContext()->getStrDump();
669 dumpDest(Func);
Eric Holke37076a2016-01-27 14:06:35 -0800670 Str << " =~ " << getInstName() << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700671 dumpSources(Func);
672}
673
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700674void Inst::dumpExtras(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700675 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800676 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700677 Ostream &Str = Func->getContext()->getStrDump();
678 bool First = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700679 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
680 // known to end at this instruction.
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800681 if (Func->isVerbose(IceV_Liveness)) {
John Portoec3f5652015-08-31 15:07:09 -0700682 FOREACH_VAR_IN_INST(Var, *this) {
683 if (isLastUse(Var)) {
684 if (First)
685 Str << " // LIVEEND={";
686 else
687 Str << ",";
688 Var->dump(Func);
689 First = false;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700690 }
691 }
692 if (!First)
693 Str << "}";
694 }
695}
696
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700697void Inst::dumpSources(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700698 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800699 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700700 Ostream &Str = Func->getContext()->getStrDump();
701 for (SizeT I = 0; I < getSrcSize(); ++I) {
702 if (I > 0)
703 Str << ", ";
704 getSrc(I)->dump(Func);
705 }
706}
707
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700708void Inst::emitSources(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700709 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800710 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700711 Ostream &Str = Func->getContext()->getStrEmit();
712 for (SizeT I = 0; I < getSrcSize(); ++I) {
713 if (I > 0)
714 Str << ", ";
715 getSrc(I)->emit(Func);
716 }
717}
718
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700719void Inst::dumpDest(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700720 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800721 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700722 if (getDest())
723 getDest()->dump(Func);
724}
725
726void InstAlloca::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 dumpDest(Func);
731 Str << " = alloca i8, i32 ";
732 getSizeInBytes()->dump(Func);
Jim Stichnoth72a8f8d2014-09-08 17:56:50 -0700733 if (getAlignInBytes())
734 Str << ", align " << getAlignInBytes();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700735}
736
737void InstArithmetic::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700738 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800739 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700740 Ostream &Str = Func->getContext()->getStrDump();
741 dumpDest(Func);
Eric Holke37076a2016-01-27 14:06:35 -0800742 Str << " = " << getInstName() << " " << getDest()->getType() << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700743 dumpSources(Func);
744}
745
746void InstAssign::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700747 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800748 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700749 Ostream &Str = Func->getContext()->getStrDump();
750 dumpDest(Func);
751 Str << " = " << getDest()->getType() << " ";
752 dumpSources(Func);
753}
754
755void InstBr::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700756 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800757 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700758 Ostream &Str = Func->getContext()->getStrDump();
759 dumpDest(Func);
760 Str << "br ";
761 if (!isUnconditional()) {
762 Str << "i1 ";
763 getCondition()->dump(Func);
764 Str << ", label %" << getTargetTrue()->getName() << ", ";
765 }
766 Str << "label %" << getTargetFalse()->getName();
767}
768
769void InstCall::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 if (getDest()) {
774 dumpDest(Func);
775 Str << " = ";
776 }
777 Str << "call ";
778 if (getDest())
779 Str << getDest()->getType();
780 else
781 Str << "void";
782 Str << " ";
783 getCallTarget()->dump(Func);
784 Str << "(";
785 for (SizeT I = 0; I < getNumArgs(); ++I) {
786 if (I > 0)
787 Str << ", ";
788 Str << getArg(I)->getType() << " ";
789 getArg(I)->dump(Func);
790 }
791 Str << ")";
792}
793
Karl Schimpfbf170372014-12-15 10:16:31 -0800794const char *InstCast::getCastName(InstCast::OpKind Kind) {
Jim Stichnoth2d6c8262016-02-07 09:50:27 -0800795 if (Kind < InstCast::OpKind::_num)
796 return InstCastAttributes[Kind].DisplayString;
Karl Schimpfbf170372014-12-15 10:16:31 -0800797 llvm_unreachable("Invalid InstCast::OpKind");
798 return "???";
799}
800
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700801void InstCast::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700802 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800803 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700804 Ostream &Str = Func->getContext()->getStrDump();
805 dumpDest(Func);
Karl Schimpfbf170372014-12-15 10:16:31 -0800806 Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
807 << " ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700808 dumpSources(Func);
809 Str << " to " << getDest()->getType();
810}
811
812void InstIcmp::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700813 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800814 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700815 Ostream &Str = Func->getContext()->getStrDump();
816 dumpDest(Func);
817 Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
818 << getSrc(0)->getType() << " ";
819 dumpSources(Func);
820}
821
Matt Wala49889232014-07-18 12:45:09 -0700822void InstExtractElement::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700823 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800824 return;
Matt Wala49889232014-07-18 12:45:09 -0700825 Ostream &Str = Func->getContext()->getStrDump();
826 dumpDest(Func);
827 Str << " = extractelement ";
828 Str << getSrc(0)->getType() << " ";
829 getSrc(0)->dump(Func);
830 Str << ", ";
831 Str << getSrc(1)->getType() << " ";
832 getSrc(1)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700833}
Matt Wala49889232014-07-18 12:45:09 -0700834
835void InstInsertElement::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700836 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800837 return;
Matt Wala49889232014-07-18 12:45:09 -0700838 Ostream &Str = Func->getContext()->getStrDump();
839 dumpDest(Func);
840 Str << " = insertelement ";
841 Str << getSrc(0)->getType() << " ";
842 getSrc(0)->dump(Func);
843 Str << ", ";
844 Str << getSrc(1)->getType() << " ";
845 getSrc(1)->dump(Func);
846 Str << ", ";
847 Str << getSrc(2)->getType() << " ";
848 getSrc(2)->dump(Func);
Derek Schuffd7ee9722014-07-30 09:39:36 -0700849}
Matt Wala49889232014-07-18 12:45:09 -0700850
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700851void InstFcmp::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700852 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800853 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700854 Ostream &Str = Func->getContext()->getStrDump();
855 dumpDest(Func);
856 Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
857 << getSrc(0)->getType() << " ";
858 dumpSources(Func);
859}
860
861void InstLoad::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700862 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800863 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700864 Ostream &Str = Func->getContext()->getStrDump();
865 dumpDest(Func);
866 Type Ty = getDest()->getType();
Jim Stichnothe5b58fb2015-06-01 15:17:20 -0700867 Str << " = load " << Ty << ", " << Ty << "* ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700868 dumpSources(Func);
869 Str << ", align " << typeAlignInBytes(Ty);
870}
871
872void InstStore::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700873 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800874 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700875 Ostream &Str = Func->getContext()->getStrDump();
876 Type Ty = getData()->getType();
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700877 dumpDest(Func);
878 if (Dest)
879 Str << " = ";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700880 Str << "store " << Ty << " ";
881 getData()->dump(Func);
882 Str << ", " << Ty << "* ";
883 getAddr()->dump(Func);
884 Str << ", align " << typeAlignInBytes(Ty);
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700885 if (getRmwBeacon()) {
886 Str << ", beacon ";
887 getRmwBeacon()->dump(Func);
888 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700889}
890
891void InstSwitch::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700892 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800893 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700894 Ostream &Str = Func->getContext()->getStrDump();
895 Type Ty = getComparison()->getType();
896 Str << "switch " << Ty << " ";
897 getSrc(0)->dump(Func);
898 Str << ", label %" << getLabelDefault()->getName() << " [\n";
899 for (SizeT I = 0; I < getNumCases(); ++I) {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700900 Str << " " << Ty << " " << static_cast<int64_t>(getValue(I))
901 << ", label %" << getLabel(I)->getName() << "\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700902 }
903 Str << " ]";
904}
905
906void InstPhi::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 dumpDest(Func);
911 Str << " = phi " << getDest()->getType() << " ";
912 for (SizeT I = 0; I < getSrcSize(); ++I) {
913 if (I > 0)
914 Str << ", ";
915 Str << "[ ";
916 getSrc(I)->dump(Func);
917 Str << ", %" << Labels[I]->getName() << " ]";
918 }
919}
920
921void InstRet::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700922 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800923 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700924 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700925 Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700926 Str << "ret " << Ty;
927 if (hasRetValue()) {
928 Str << " ";
929 dumpSources(Func);
930 }
931}
932
933void InstSelect::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700934 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800935 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700936 Ostream &Str = Func->getContext()->getStrDump();
937 dumpDest(Func);
938 Operand *Condition = getCondition();
939 Operand *TrueOp = getTrueOperand();
940 Operand *FalseOp = getFalseOperand();
941 Str << " = select " << Condition->getType() << " ";
942 Condition->dump(Func);
943 Str << ", " << TrueOp->getType() << " ";
944 TrueOp->dump(Func);
945 Str << ", " << FalseOp->getType() << " ";
946 FalseOp->dump(Func);
947}
948
949void InstUnreachable::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700950 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800951 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700952 Ostream &Str = Func->getContext()->getStrDump();
953 Str << "unreachable";
954}
955
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800956void InstBundleLock::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700957 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800958 return;
959 Ostream &Str = Func->getContext()->getStrEmit();
960 Str << "\t.bundle_lock";
961 switch (BundleOption) {
962 case Opt_None:
963 break;
964 case Opt_AlignToEnd:
Jim Stichnoth6106df82015-12-16 06:17:58 -0800965 Str << "\t"
966 "align_to_end";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800967 break;
John Porto56958cb2016-01-14 09:18:18 -0800968 case Opt_PadToEnd:
969 Str << "\t"
970 "align_to_end /* pad_to_end */";
971 break;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800972 }
Jim Stichnoth33436472015-11-27 14:22:02 -0800973 Str << "\n";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800974}
975
976void InstBundleLock::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700977 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800978 return;
979 Ostream &Str = Func->getContext()->getStrDump();
980 Str << "bundle_lock";
981 switch (BundleOption) {
982 case Opt_None:
983 break;
984 case Opt_AlignToEnd:
985 Str << " align_to_end";
986 break;
John Porto56958cb2016-01-14 09:18:18 -0800987 case Opt_PadToEnd:
988 Str << " pad_to_end";
989 break;
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800990 }
991}
992
993void InstBundleUnlock::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700994 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800995 return;
996 Ostream &Str = Func->getContext()->getStrEmit();
997 Str << "\t.bundle_unlock";
Jim Stichnoth33436472015-11-27 14:22:02 -0800998 Str << "\n";
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800999}
1000
1001void InstBundleUnlock::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001002 if (!BuildDefs::dump())
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -08001003 return;
1004 Ostream &Str = Func->getContext()->getStrDump();
1005 Str << "bundle_unlock";
1006}
1007
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001008void InstFakeDef::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001009 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001010 return;
Andrew Scull57e12682015-09-16 11:30:19 -07001011 // Go ahead and "emit" these for now, since they are relatively rare.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001012 Ostream &Str = Func->getContext()->getStrEmit();
1013 Str << "\t# ";
1014 getDest()->emit(Func);
Jim Stichnothfbdc7e42016-02-09 17:25:02 -08001015 Str << " = def.pseudo";
1016 if (getSrcSize() > 0)
1017 Str << " ";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001018 emitSources(Func);
Jim Stichnoth3e859b72015-11-10 14:39:51 -08001019 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001020}
1021
1022void InstFakeDef::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001023 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001024 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001025 Ostream &Str = Func->getContext()->getStrDump();
1026 dumpDest(Func);
1027 Str << " = def.pseudo ";
1028 dumpSources(Func);
1029}
1030
Jim Stichnothbb8b6242014-11-04 09:10:01 -08001031void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001032
1033void InstFakeUse::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001034 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001035 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001036 Ostream &Str = Func->getContext()->getStrDump();
1037 Str << "use.pseudo ";
1038 dumpSources(Func);
1039}
1040
Jim Stichnothbb8b6242014-11-04 09:10:01 -08001041void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001042
1043void InstFakeKill::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001044 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001045 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001046 Ostream &Str = Func->getContext()->getStrDump();
1047 if (Linked->isDeleted())
1048 Str << "// ";
Jim Stichnoth87ff3a12014-11-14 10:27:29 -08001049 Str << "kill.pseudo scratch_regs";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001050}
1051
John Portoa47c11c2016-04-21 05:53:42 -07001052void InstShuffleVector::dump(const Cfg *Func) const {
1053 if (!BuildDefs::dump())
1054 return;
1055 Ostream &Str = Func->getContext()->getStrDump();
1056 Str << "shufflevector ";
1057 dumpDest(Func);
1058 Str << " = ";
1059 dumpSources(Func);
1060 for (SizeT I = 0; I < NumIndexes; ++I) {
1061 Str << ", ";
1062 Indexes[I]->dump(Func);
1063 }
1064 Str << "\n";
1065}
1066
Andrew Scull87f80c12015-07-20 10:19:16 -07001067void InstJumpTable::dump(const Cfg *Func) const {
1068 if (!BuildDefs::dump())
1069 return;
1070 Ostream &Str = Func->getContext()->getStrDump();
1071 Str << "jump table [";
1072 for (SizeT I = 0; I < NumTargets; ++I)
1073 Str << "\n " << Targets[I]->getName();
1074 Str << "\n ]";
1075}
1076
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001077void InstTarget::dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001078 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -08001079 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001080 Ostream &Str = Func->getContext()->getStrDump();
1081 Str << "[TARGET] ";
1082 Inst::dump(Func);
1083}
1084
Eric Holk67c7c412016-04-15 13:05:37 -07001085InstBreakpoint::InstBreakpoint(Cfg *Func)
1086 : InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
1087
Jan Voungb3401d22015-05-18 09:38:21 -07001088bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
Jim Stichnoth1fb030c2015-10-15 11:10:38 -07001089 const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
Jan Voungb3401d22015-05-18 09:38:21 -07001090 if (!SrcVar)
1091 return false;
1092 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
Andrew Scull57e12682015-09-16 11:30:19 -07001093 // TODO: On x86-64, instructions like "mov eax, eax" are used to clear the
1094 // upper 32 bits of rax. We need to recognize and preserve these.
Jan Voungb3401d22015-05-18 09:38:21 -07001095 return true;
1096 }
1097 if (!Dest->hasReg() && !SrcVar->hasReg() &&
1098 Dest->getStackOffset() == SrcVar->getStackOffset())
1099 return true;
1100 return false;
1101}
1102
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001103} // end of namespace Ice