• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- subzero/src/IceInst.cpp - High-level instruction implementation ----===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Implements the Inst class, primarily the various subclass
12 /// constructors and dump routines.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "IceInst.h"
17 
18 #include "IceCfg.h"
19 #include "IceCfgNode.h"
20 #include "IceInstVarIter.h"
21 #include "IceLiveness.h"
22 #include "IceOperand.h"
23 #include "IceTargetLowering.h"
24 
25 #include "llvm/Support/Format.h"
26 
27 namespace Ice {
28 
29 namespace {
30 
31 // Using non-anonymous struct so that array_lengthof works.
32 const struct InstArithmeticAttributes_ {
33   const char *DisplayString;
34   bool IsCommutative;
35 } InstArithmeticAttributes[] = {
36 #define X(tag, str, commutative)                                               \
37   { str, commutative }                                                         \
38   ,
39     ICEINSTARITHMETIC_TABLE
40 #undef X
41 };
42 
43 // Using non-anonymous struct so that array_lengthof works.
44 const struct InstCastAttributes_ {
45   const char *DisplayString;
46 } InstCastAttributes[] = {
47 #define X(tag, str)                                                            \
48   { str }                                                                      \
49   ,
50     ICEINSTCAST_TABLE
51 #undef X
52 };
53 
54 // Using non-anonymous struct so that array_lengthof works.
55 const struct InstFcmpAttributes_ {
56   const char *DisplayString;
57 } InstFcmpAttributes[] = {
58 #define X(tag, str)                                                            \
59   { str }                                                                      \
60   ,
61     ICEINSTFCMP_TABLE
62 #undef X
63 };
64 
65 // Using non-anonymous struct so that array_lengthof works.
66 const struct InstIcmpAttributes_ {
67   const char *DisplayString;
68   InstIcmp::ICond Reverse;
69 } InstIcmpAttributes[] = {
70 #define X(tag, reverse, str)                                                   \
71   { str, InstIcmp::ICond::reverse }                                            \
72   ,
73     ICEINSTICMP_TABLE
74 #undef X
75 };
76 
77 } // end of anonymous namespace
78 
Inst(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)79 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
80     : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
81       LiveRangesEnded(0) {
82   Srcs.reserve(MaxSrcs);
83 }
84 
getInstName() const85 const char *Inst::getInstName() const {
86   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");
111     X(Breakpoint, "break");
112     X(BundleLock, "bundlelock");
113     X(BundleUnlock, "bundleunlock");
114     X(FakeDef, "fakedef");
115     X(FakeUse, "fakeuse");
116     X(FakeKill, "fakekill");
117     X(JumpTable, "jumptable");
118     X(ShuffleVector, "shufflevector");
119 #undef X
120   default:
121     assert(Kind >= Target);
122     return "target";
123   }
124 }
125 
126 // Assign the instruction a new number.
renumber(Cfg * Func)127 void Inst::renumber(Cfg *Func) {
128   Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
129 }
130 
131 // Delete the instruction if its tentative Dead flag is still set after
132 // liveness analysis.
deleteIfDead()133 void Inst::deleteIfDead() {
134   if (Dead)
135     setDeleted();
136 }
137 
138 // If Src is a Variable, it returns true if this instruction ends Src's live
139 // range. Otherwise, returns false.
isLastUse(const Operand * TestSrc) const140 bool Inst::isLastUse(const Operand *TestSrc) const {
141   if (LiveRangesEnded == 0)
142     return false; // early-exit optimization
143   if (auto *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
144     LREndedBits Mask = LiveRangesEnded;
145     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;
149       }
150       Mask >>= 1;
151       if (Mask == 0)
152         return false; // another early-exit optimization
153     }
154   }
155   return false;
156 }
157 
158 // 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 //
165 // 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
171 // because [x,y] consumes 2 bitmask slots while d only consumed 1.
172 //
173 // Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
174 // HasSideEffects set.
spliceLivenessInfo(Inst * OrigInst,Inst * SpliceAssn)175 void 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 
isMemoryWrite() const195 bool Inst::isMemoryWrite() const {
196   llvm::report_fatal_error("Attempt to call base Inst::isMemoryWrite() method");
197 }
198 
livenessLightweight(Cfg * Func,LivenessBV & Live)199 void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
200   assert(!isDeleted());
201   resetLastUses();
202   VariablesMetadata *VMetadata = Func->getVMetadata();
203   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));
211   }
212 }
213 
liveness(InstNumberT InstNumber,LivenessBV & Live,Liveness * Liveness,LiveBeginEndMap * LiveBegin,LiveBeginEndMap * LiveEnd)214 bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
215                     Liveness *Liveness, LiveBeginEndMap *LiveBegin,
216                     LiveBeginEndMap *LiveEnd) {
217   assert(!isDeleted());
218 
219   Dead = false;
220   if (Dest && !Dest->isRematerializable()) {
221     SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
222     if (Live[VarNum]) {
223       if (!isDestRedefined()) {
224         Live[VarNum] = false;
225         if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
226           LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
227         }
228       }
229     } else {
230       if (!hasSideEffects())
231         Dead = true;
232     }
233   }
234   if (Dead)
235     return false;
236   // Phi arguments only get added to Live in the predecessor node, but we still
237   // need to update LiveRangesEnded.
238   bool IsPhi = llvm::isa<InstPhi>(this);
239   resetLastUses();
240   FOREACH_VAR_IN_INST(Var, *this) {
241     if (Var->isRematerializable())
242       continue;
243     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
249         // 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.
260         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
263           // vector. Instead, livenessPostprocess() verifies this after the
264           // vector has been sorted.
265           LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
266         }
267       }
268     }
269   }
270   return true;
271 }
272 
InstAlloca(Cfg * Func,Variable * Dest,Operand * ByteCount,uint32_t AlignInBytes)273 InstAlloca::InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
274                        uint32_t AlignInBytes)
275     : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
276   // Verify AlignInBytes is 0 or a power of 2.
277   assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
278   addSource(ByteCount);
279 }
280 
InstArithmetic(Cfg * Func,OpKind Op,Variable * Dest,Operand * Source1,Operand * Source2)281 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
282                                Operand *Source1, Operand *Source2)
283     : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
284   addSource(Source1);
285   addSource(Source2);
286 }
287 
getInstName() const288 const char *InstArithmetic::getInstName() const {
289   if (!BuildDefs::dump())
290     return "???";
291 
292   return InstArithmeticAttributes[getOp()].DisplayString;
293 }
294 
getOpName(OpKind Op)295 const char *InstArithmetic::getOpName(OpKind Op) {
296   return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
297                                    : "???";
298 }
299 
isCommutative() const300 bool InstArithmetic::isCommutative() const {
301   return InstArithmeticAttributes[getOp()].IsCommutative;
302 }
303 
InstAssign(Cfg * Func,Variable * Dest,Operand * Source)304 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
305     : InstHighLevel(Func, Inst::Assign, 1, Dest) {
306   addSource(Source);
307 }
308 
isVarAssign() const309 bool InstAssign::isVarAssign() const { return llvm::isa<Variable>(getSrc(0)); }
310 
311 // 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.
InstBr(Cfg * Func,Operand * Source,CfgNode * TargetTrue_,CfgNode * TargetFalse_)314 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
315                CfgNode *TargetFalse_)
316     : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
317       TargetTrue(TargetTrue_) {
318   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) {
325     TargetTrue = nullptr; // turn into unconditional version
326   } else {
327     addSource(Source);
328   }
329 }
330 
InstBr(Cfg * Func,CfgNode * Target)331 InstBr::InstBr(Cfg *Func, CfgNode *Target)
332     : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
333       TargetTrue(nullptr) {}
334 
getTerminatorEdges() const335 NodeList InstBr::getTerminatorEdges() const {
336   NodeList OutEdges;
337   OutEdges.reserve(TargetTrue ? 2 : 1);
338   OutEdges.push_back(TargetFalse);
339   if (TargetTrue)
340     OutEdges.push_back(TargetTrue);
341   return OutEdges;
342 }
343 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)344 bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
345   bool Found = false;
346   if (TargetFalse == OldNode) {
347     TargetFalse = NewNode;
348     Found = true;
349   }
350   if (TargetTrue == OldNode) {
351     TargetTrue = NewNode;
352     Found = true;
353   }
354   return Found;
355 }
356 
InstCast(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)357 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
358     : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
359   addSource(Source);
360 }
361 
InstExtractElement(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)362 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
363                                        Operand *Source1, Operand *Source2)
364     : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
365   addSource(Source1);
366   addSource(Source2);
367 }
368 
InstFcmp(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)369 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
370                    Operand *Source2)
371     : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
372   addSource(Source1);
373   addSource(Source2);
374 }
375 
InstIcmp(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)376 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
377                    Operand *Source2)
378     : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
379   addSource(Source1);
380   addSource(Source2);
381 }
382 
InstInsertElement(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)383 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
384                                      Operand *Source1, Operand *Source2,
385                                      Operand *Source3)
386     : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
387   addSource(Source1);
388   addSource(Source2);
389   addSource(Source3);
390 }
391 
InstLoad(Cfg * Func,Variable * Dest,Operand * SourceAddr)392 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
393     : InstHighLevel(Func, Inst::Load, 1, Dest) {
394   addSource(SourceAddr);
395 }
396 
InstPhi(Cfg * Func,SizeT MaxSrcs,Variable * Dest)397 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
398     : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
399   Labels.reserve(MaxSrcs);
400 }
401 
402 // 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.
addArgument(Operand * Source,CfgNode * Label)406 void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
407   assert(Label);
408   Labels.push_back(Label);
409   addSource(Source);
410 }
411 
412 // Find the source operand corresponding to the incoming edge for the given
413 // node.
getOperandForTarget(CfgNode * Target) const414 Operand *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");
420   return nullptr;
421 }
422 
423 // Replace the source operand corresponding to the incoming edge for the given
424 // node by a zero of the appropriate type.
clearOperandForTarget(CfgNode * Target)425 void 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 
436 // 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.
livenessPhiOperand(LivenessBV & Live,CfgNode * Target,Liveness * Liveness)439 void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
440                                  Liveness *Liveness) {
441   if (isDeleted() || Dead)
442     return;
443   for (SizeT I = 0; I < getSrcSize(); ++I) {
444     if (Labels[I] == Target) {
445       if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
446         if (!Var->isRematerializable()) {
447           SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
448           if (!Live[SrcIndex]) {
449             setLastUse(I);
450             Live[SrcIndex] = true;
451           }
452         }
453       }
454       return;
455     }
456   }
457   llvm_unreachable("Phi operand not found for specified target node");
458 }
459 
460 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
461 // "a=a_phi".
lower(Cfg * Func)462 Inst *InstPhi::lower(Cfg *Func) {
463   Variable *Dest = getDest();
464   assert(Dest);
465   Variable *NewSrc = Func->makeVariable(Dest->getType());
466   if (BuildDefs::dump())
467     NewSrc->setName(Func, Dest->getName() + "_phi");
468   if (auto *NewSrc64On32 = llvm::dyn_cast<Variable64On32>(NewSrc))
469     NewSrc64On32->initHiLo(Func);
470   this->Dest = NewSrc;
471   return InstAssign::create(Func, Dest, NewSrc);
472 }
473 
InstRet(Cfg * Func,Operand * RetValue)474 InstRet::InstRet(Cfg *Func, Operand *RetValue)
475     : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
476   if (RetValue)
477     addSource(RetValue);
478 }
479 
InstSelect(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)480 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
481                        Operand *SourceTrue, Operand *SourceFalse)
482     : InstHighLevel(Func, Inst::Select, 3, Dest) {
483   assert(typeElementType(Condition->getType()) == IceType_i1);
484   addSource(Condition);
485   addSource(SourceTrue);
486   addSource(SourceFalse);
487 }
488 
InstStore(Cfg * Func,Operand * Data,Operand * Addr)489 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
490     : InstHighLevel(Func, Inst::Store, 3, nullptr) {
491   addSource(Data);
492   addSource(Addr);
493   // The 3rd operand is a dummy placeholder for the RMW beacon.
494   addSource(Data);
495 }
496 
getRmwBeacon() const497 Variable *InstStore::getRmwBeacon() const {
498   return llvm::dyn_cast<Variable>(getSrc(2));
499 }
500 
setRmwBeacon(Variable * Beacon)501 void InstStore::setRmwBeacon(Variable *Beacon) {
502   Dest = llvm::dyn_cast<Variable>(getData());
503   Srcs[2] = Beacon;
504 }
505 
InstSwitch(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)506 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
507                        CfgNode *LabelDefault)
508     : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
509       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;
516     Labels[I] = nullptr;
517   }
518 }
519 
addBranch(SizeT CaseIndex,uint64_t Value,CfgNode * Label)520 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
521   assert(CaseIndex < NumCases);
522   Values[CaseIndex] = Value;
523   Labels[CaseIndex] = Label;
524 }
525 
getTerminatorEdges() const526 NodeList InstSwitch::getTerminatorEdges() const {
527   NodeList OutEdges;
528   OutEdges.reserve(NumCases + 1);
529   assert(LabelDefault);
530   OutEdges.push_back(LabelDefault);
531   for (SizeT I = 0; I < NumCases; ++I) {
532     assert(Labels[I]);
533     OutEdges.push_back(Labels[I]);
534   }
535   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());
541   return OutEdges;
542 }
543 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)544 bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
545   bool Found = false;
546   if (LabelDefault == OldNode) {
547     LabelDefault = NewNode;
548     Found = true;
549   }
550   for (SizeT I = 0; I < NumCases; ++I) {
551     if (Labels[I] == OldNode) {
552       Labels[I] = NewNode;
553       Found = true;
554     }
555   }
556   return Found;
557 }
558 
InstUnreachable(Cfg * Func)559 InstUnreachable::InstUnreachable(Cfg *Func)
560     : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
561 
InstBundleLock(Cfg * Func,InstBundleLock::Option BundleOption)562 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
563     : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
564       BundleOption(BundleOption) {}
565 
InstBundleUnlock(Cfg * Func)566 InstBundleUnlock::InstBundleUnlock(Cfg *Func)
567     : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
568 
InstFakeDef(Cfg * Func,Variable * Dest,Variable * Src)569 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
570     : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
571   assert(Dest);
572   if (Src)
573     addSource(Src);
574 }
575 
InstFakeUse(Cfg * Func,Variable * Src,uint32_t Weight)576 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight)
577     : InstHighLevel(Func, Inst::FakeUse, Weight, nullptr) {
578   assert(Src);
579   for (uint32_t i = 0; i < Weight; ++i)
580     addSource(Src);
581 }
582 
InstFakeKill(Cfg * Func,const Inst * Linked)583 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
584     : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
585 
InstShuffleVector(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)586 InstShuffleVector::InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0,
587                                      Operand *Src1)
588     : 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 
595 namespace {
makeName(Cfg * Func,const SizeT Id)596 GlobalString 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(
603       Ctx, "$J" + std::to_string(FuncName.getID()) + "_" + std::to_string(Id));
604 }
605 } // end of anonymous namespace
606 
InstJumpTable(Cfg * Func,SizeT NumTargets,CfgNode * Default)607 InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
608     : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
609       Id(Func->getTarget()->makeNextJumpTableNumber()), NumTargets(NumTargets),
610       Name(makeName(Func, Id)), FuncName(Func->getFunctionName()) {
611   Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
612   for (SizeT I = 0; I < NumTargets; ++I) {
613     Targets[I] = Default;
614   }
615 }
616 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)617 bool 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 
toJumpTableData(Assembler * Asm) const628 JumpTableData 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 
getReturnType() const637 Type InstCall::getReturnType() const {
638   if (Dest == nullptr)
639     return IceType_void;
640   return Dest->getType();
641 }
642 
643 // ======================== Dump routines ======================== //
644 
dumpDecorated(const Cfg * Func) const645 void Inst::dumpDecorated(const Cfg *Func) const {
646   if (!BuildDefs::dump())
647     return;
648   Ostream &Str = Func->getContext()->getStrDump();
649   if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
650     return;
651   if (Func->isVerbose(IceV_InstNumbers)) {
652     InstNumberT Number = getNumber();
653     if (Number == NumberDeleted)
654       Str << "[XXX]";
655     else
656       Str << llvm::format("[%3d]", Number);
657   }
658   Str << "  ";
659   if (isDeleted())
660     Str << "  //";
661   dump(Func);
662   dumpExtras(Func);
663   Str << "\n";
664 }
665 
dump(const Cfg * Func) const666 void Inst::dump(const Cfg *Func) const {
667   if (!BuildDefs::dump())
668     return;
669   Ostream &Str = Func->getContext()->getStrDump();
670   dumpDest(Func);
671   Str << " =~ " << getInstName() << " ";
672   dumpSources(Func);
673 }
674 
dumpExtras(const Cfg * Func) const675 void Inst::dumpExtras(const Cfg *Func) const {
676   if (!BuildDefs::dump())
677     return;
678   Ostream &Str = Func->getContext()->getStrDump();
679   bool First = true;
680   // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
681   // known to end at this instruction.
682   if (Func->isVerbose(IceV_Liveness)) {
683     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;
691       }
692     }
693     if (!First)
694       Str << "}";
695   }
696 }
697 
dumpSources(const Cfg * Func) const698 void Inst::dumpSources(const Cfg *Func) const {
699   if (!BuildDefs::dump())
700     return;
701   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 
emitSources(const Cfg * Func) const709 void Inst::emitSources(const Cfg *Func) const {
710   if (!BuildDefs::dump())
711     return;
712   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 
dumpDest(const Cfg * Func) const720 void Inst::dumpDest(const Cfg *Func) const {
721   if (!BuildDefs::dump())
722     return;
723   if (getDest())
724     getDest()->dump(Func);
725 }
726 
dump(const Cfg * Func) const727 void InstAlloca::dump(const Cfg *Func) const {
728   if (!BuildDefs::dump())
729     return;
730   Ostream &Str = Func->getContext()->getStrDump();
731   dumpDest(Func);
732   Str << " = alloca i8, i32 ";
733   getSizeInBytes()->dump(Func);
734   if (getAlignInBytes())
735     Str << ", align " << getAlignInBytes();
736 }
737 
dump(const Cfg * Func) const738 void InstArithmetic::dump(const Cfg *Func) const {
739   if (!BuildDefs::dump())
740     return;
741   Ostream &Str = Func->getContext()->getStrDump();
742   dumpDest(Func);
743   Str << " = " << getInstName() << " " << getDest()->getType() << " ";
744   dumpSources(Func);
745 }
746 
dump(const Cfg * Func) const747 void InstAssign::dump(const Cfg *Func) const {
748   if (!BuildDefs::dump())
749     return;
750   Ostream &Str = Func->getContext()->getStrDump();
751   dumpDest(Func);
752   Str << " = " << getDest()->getType() << " ";
753   dumpSources(Func);
754 }
755 
dump(const Cfg * Func) const756 void InstBr::dump(const Cfg *Func) const {
757   if (!BuildDefs::dump())
758     return;
759   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 
dump(const Cfg * Func) const770 void InstCall::dump(const Cfg *Func) const {
771   if (!BuildDefs::dump())
772     return;
773   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 
getCastName(InstCast::OpKind Kind)795 const char *InstCast::getCastName(InstCast::OpKind Kind) {
796   if (Kind < InstCast::OpKind::_num)
797     return InstCastAttributes[Kind].DisplayString;
798   llvm_unreachable("Invalid InstCast::OpKind");
799   return "???";
800 }
801 
dump(const Cfg * Func) const802 void InstCast::dump(const Cfg *Func) const {
803   if (!BuildDefs::dump())
804     return;
805   Ostream &Str = Func->getContext()->getStrDump();
806   dumpDest(Func);
807   Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
808       << " ";
809   dumpSources(Func);
810   Str << " to " << getDest()->getType();
811 }
812 
dump(const Cfg * Func) const813 void InstIcmp::dump(const Cfg *Func) const {
814   if (!BuildDefs::dump())
815     return;
816   Ostream &Str = Func->getContext()->getStrDump();
817   dumpDest(Func);
818   Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
819       << getSrc(0)->getType() << " ";
820   dumpSources(Func);
821 }
822 
dump(const Cfg * Func) const823 void InstExtractElement::dump(const Cfg *Func) const {
824   if (!BuildDefs::dump())
825     return;
826   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);
834 }
835 
dump(const Cfg * Func) const836 void InstInsertElement::dump(const Cfg *Func) const {
837   if (!BuildDefs::dump())
838     return;
839   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);
850 }
851 
dump(const Cfg * Func) const852 void InstFcmp::dump(const Cfg *Func) const {
853   if (!BuildDefs::dump())
854     return;
855   Ostream &Str = Func->getContext()->getStrDump();
856   dumpDest(Func);
857   Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
858       << getSrc(0)->getType() << " ";
859   dumpSources(Func);
860 }
861 
dump(const Cfg * Func) const862 void InstLoad::dump(const Cfg *Func) const {
863   if (!BuildDefs::dump())
864     return;
865   Ostream &Str = Func->getContext()->getStrDump();
866   dumpDest(Func);
867   Type Ty = getDest()->getType();
868   Str << " = load " << Ty << ", " << Ty << "* ";
869   dumpSources(Func);
870   Str << ", align " << typeAlignInBytes(Ty);
871 }
872 
dump(const Cfg * Func) const873 void InstStore::dump(const Cfg *Func) const {
874   if (!BuildDefs::dump())
875     return;
876   Ostream &Str = Func->getContext()->getStrDump();
877   Type Ty = getData()->getType();
878   dumpDest(Func);
879   if (Dest)
880     Str << " = ";
881   Str << "store " << Ty << " ";
882   getData()->dump(Func);
883   Str << ", " << Ty << "* ";
884   getAddr()->dump(Func);
885   Str << ", align " << typeAlignInBytes(Ty);
886   if (getRmwBeacon()) {
887     Str << ", beacon ";
888     getRmwBeacon()->dump(Func);
889   }
890 }
891 
dump(const Cfg * Func) const892 void InstSwitch::dump(const Cfg *Func) const {
893   if (!BuildDefs::dump())
894     return;
895   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) {
901     Str << "    " << Ty << " " << static_cast<int64_t>(getValue(I))
902         << ", label %" << getLabel(I)->getName() << "\n";
903   }
904   Str << "  ]";
905 }
906 
dump(const Cfg * Func) const907 void InstPhi::dump(const Cfg *Func) const {
908   if (!BuildDefs::dump())
909     return;
910   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 
dump(const Cfg * Func) const922 void InstRet::dump(const Cfg *Func) const {
923   if (!BuildDefs::dump())
924     return;
925   Ostream &Str = Func->getContext()->getStrDump();
926   Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
927   Str << "ret " << Ty;
928   if (hasRetValue()) {
929     Str << " ";
930     dumpSources(Func);
931   }
932 }
933 
dump(const Cfg * Func) const934 void InstSelect::dump(const Cfg *Func) const {
935   if (!BuildDefs::dump())
936     return;
937   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 
dump(const Cfg * Func) const950 void InstUnreachable::dump(const Cfg *Func) const {
951   if (!BuildDefs::dump())
952     return;
953   Ostream &Str = Func->getContext()->getStrDump();
954   Str << "unreachable";
955 }
956 
emit(const Cfg * Func) const957 void InstBundleLock::emit(const Cfg *Func) const {
958   if (!BuildDefs::dump())
959     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:
966     Str << "\t"
967            "align_to_end";
968     break;
969   case Opt_PadToEnd:
970     Str << "\t"
971            "align_to_end /* pad_to_end */";
972     break;
973   }
974   Str << "\n";
975 }
976 
dump(const Cfg * Func) const977 void InstBundleLock::dump(const Cfg *Func) const {
978   if (!BuildDefs::dump())
979     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;
988   case Opt_PadToEnd:
989     Str << " pad_to_end";
990     break;
991   }
992 }
993 
emit(const Cfg * Func) const994 void InstBundleUnlock::emit(const Cfg *Func) const {
995   if (!BuildDefs::dump())
996     return;
997   Ostream &Str = Func->getContext()->getStrEmit();
998   Str << "\t.bundle_unlock";
999   Str << "\n";
1000 }
1001 
dump(const Cfg * Func) const1002 void InstBundleUnlock::dump(const Cfg *Func) const {
1003   if (!BuildDefs::dump())
1004     return;
1005   Ostream &Str = Func->getContext()->getStrDump();
1006   Str << "bundle_unlock";
1007 }
1008 
emit(const Cfg * Func) const1009 void InstFakeDef::emit(const Cfg *Func) const {
1010   if (!BuildDefs::dump())
1011     return;
1012   // Go ahead and "emit" these for now, since they are relatively rare.
1013   Ostream &Str = Func->getContext()->getStrEmit();
1014   Str << "\t# ";
1015   getDest()->emit(Func);
1016   Str << " = def.pseudo";
1017   if (getSrcSize() > 0)
1018     Str << " ";
1019   emitSources(Func);
1020   Str << "\n";
1021 }
1022 
dump(const Cfg * Func) const1023 void InstFakeDef::dump(const Cfg *Func) const {
1024   if (!BuildDefs::dump())
1025     return;
1026   Ostream &Str = Func->getContext()->getStrDump();
1027   dumpDest(Func);
1028   Str << " = def.pseudo ";
1029   dumpSources(Func);
1030 }
1031 
emit(const Cfg * Func) const1032 void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
1033 
dump(const Cfg * Func) const1034 void InstFakeUse::dump(const Cfg *Func) const {
1035   if (!BuildDefs::dump())
1036     return;
1037   Ostream &Str = Func->getContext()->getStrDump();
1038   Str << "use.pseudo ";
1039   dumpSources(Func);
1040 }
1041 
emit(const Cfg * Func) const1042 void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
1043 
dump(const Cfg * Func) const1044 void InstFakeKill::dump(const Cfg *Func) const {
1045   if (!BuildDefs::dump())
1046     return;
1047   Ostream &Str = Func->getContext()->getStrDump();
1048   if (Linked->isDeleted())
1049     Str << "// ";
1050   Str << "kill.pseudo scratch_regs";
1051 }
1052 
dump(const Cfg * Func) const1053 void 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 
dump(const Cfg * Func) const1068 void 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 
dump(const Cfg * Func) const1078 void InstTarget::dump(const Cfg *Func) const {
1079   if (!BuildDefs::dump())
1080     return;
1081   Ostream &Str = Func->getContext()->getStrDump();
1082   Str << "[TARGET] ";
1083   Inst::dump(Func);
1084 }
1085 
InstBreakpoint(Cfg * Func)1086 InstBreakpoint::InstBreakpoint(Cfg *Func)
1087     : InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
1088 
reverseConditionAndOperands()1089 void InstIcmp::reverseConditionAndOperands() {
1090   Condition = InstIcmpAttributes[Condition].Reverse;
1091   std::swap(Srcs[0], Srcs[1]);
1092 }
1093 
checkForRedundantAssign(const Variable * Dest,const Operand * Source)1094 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
1095   const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
1096   if (SrcVar == nullptr)
1097     return false;
1098   if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
1099     // 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.
1101     return true;
1102   }
1103   if (!Dest->hasReg() && !SrcVar->hasReg()) {
1104     if (!Dest->hasStackOffset() || !SrcVar->hasStackOffset()) {
1105       // If called before stack slots have been assigned (i.e. as part of the
1106       // dump() routine), conservatively return false.
1107       return false;
1108     }
1109     if (Dest->getStackOffset() != SrcVar->getStackOffset()) {
1110       return false;
1111     }
1112     return true;
1113   }
1114   // 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   }
1123   return false;
1124 }
1125 
1126 } // end of namespace Ice
1127