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) {str, commutative},
37     ICEINSTARITHMETIC_TABLE
38 #undef X
39 };
40 
41 // Using non-anonymous struct so that array_lengthof works.
42 const struct InstCastAttributes_ {
43   const char *DisplayString;
44 } InstCastAttributes[] = {
45 #define X(tag, str) {str},
46     ICEINSTCAST_TABLE
47 #undef X
48 };
49 
50 // Using non-anonymous struct so that array_lengthof works.
51 const struct InstFcmpAttributes_ {
52   const char *DisplayString;
53 } InstFcmpAttributes[] = {
54 #define X(tag, str) {str},
55     ICEINSTFCMP_TABLE
56 #undef X
57 };
58 
59 // Using non-anonymous struct so that array_lengthof works.
60 const struct InstIcmpAttributes_ {
61   const char *DisplayString;
62   InstIcmp::ICond Reverse;
63 } InstIcmpAttributes[] = {
64 #define X(tag, reverse, str) {str, InstIcmp::ICond::reverse},
65     ICEINSTICMP_TABLE
66 #undef X
67 };
68 
69 } // end of anonymous namespace
70 
Inst(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)71 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
72     : Kind(Kind), Number(Func->newInstNumber()), Dest(Dest), MaxSrcs(MaxSrcs),
73       LiveRangesEnded(0) {
74   Srcs.reserve(MaxSrcs);
75 }
76 
getInstName() const77 const char *Inst::getInstName() const {
78   if (!BuildDefs::dump())
79     return "???";
80 
81   switch (Kind) {
82 #define X(InstrKind, name)                                                     \
83   case InstrKind:                                                              \
84     return name
85     X(Unreachable, "unreachable");
86     X(Alloca, "alloca");
87     X(Arithmetic, "arithmetic");
88     X(Br, "br");
89     X(Call, "call");
90     X(Cast, "cast");
91     X(ExtractElement, "extractelement");
92     X(Fcmp, "fcmp");
93     X(Icmp, "icmp");
94     X(IntrinsicCall, "intrinsiccall");
95     X(InsertElement, "insertelement");
96     X(Load, "load");
97     X(Phi, "phi");
98     X(Ret, "ret");
99     X(Select, "select");
100     X(Store, "store");
101     X(Switch, "switch");
102     X(Assign, "assign");
103     X(Breakpoint, "break");
104     X(BundleLock, "bundlelock");
105     X(BundleUnlock, "bundleunlock");
106     X(FakeDef, "fakedef");
107     X(FakeUse, "fakeuse");
108     X(FakeKill, "fakekill");
109     X(JumpTable, "jumptable");
110     X(ShuffleVector, "shufflevector");
111 #undef X
112   default:
113     assert(Kind >= Target);
114     return "target";
115   }
116 }
117 
118 // Assign the instruction a new number.
renumber(Cfg * Func)119 void Inst::renumber(Cfg *Func) {
120   Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
121 }
122 
123 // Delete the instruction if its tentative Dead flag is still set after
124 // liveness analysis.
deleteIfDead()125 void Inst::deleteIfDead() {
126   if (Dead)
127     setDeleted();
128 }
129 
130 // If Src is a Variable, it returns true if this instruction ends Src's live
131 // range. Otherwise, returns false.
isLastUse(const Operand * TestSrc) const132 bool Inst::isLastUse(const Operand *TestSrc) const {
133   if (LiveRangesEnded == 0)
134     return false; // early-exit optimization
135   if (auto *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
136     LREndedBits Mask = LiveRangesEnded;
137     FOREACH_VAR_IN_INST(Var, *this) {
138       if (Var == TestVar) {
139         // We've found where the variable is used in the instruction.
140         return Mask & 1;
141       }
142       Mask >>= 1;
143       if (Mask == 0)
144         return false; // another early-exit optimization
145     }
146   }
147   return false;
148 }
149 
150 // Given an instruction like:
151 //   a = b + c + [x,y] + e
152 // which was created from OrigInst:
153 //   a = b + c + d + e
154 // with SpliceAssn spliced in:
155 //   d = [x,y]
156 //
157 // Reconstruct the LiveRangesEnded bitmask in this instruction by combining the
158 // LiveRangesEnded values of OrigInst and SpliceAssn. If operands d and [x,y]
159 // contain a different number of variables, then the bitmask position for e may
160 // be different in OrigInst and the current instruction, requiring extra shifts
161 // and masks in the computation. In the example above, OrigInst has variable e
162 // in bit position 3, whereas the current instruction has e in bit position 4
163 // because [x,y] consumes 2 bitmask slots while d only consumed 1.
164 //
165 // Additionally, set HasSideEffects if either OrigInst or SpliceAssn have
166 // HasSideEffects set.
spliceLivenessInfo(Inst * OrigInst,Inst * SpliceAssn)167 void Inst::spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn) {
168   HasSideEffects |= OrigInst->HasSideEffects;
169   HasSideEffects |= SpliceAssn->HasSideEffects;
170   // Find the bitmask index of SpliceAssn's dest within OrigInst.
171   Variable *SpliceDest = SpliceAssn->getDest();
172   SizeT Index = 0;
173   for (SizeT I = 0; I < OrigInst->getSrcSize(); ++I) {
174     Operand *Src = OrigInst->getSrc(I);
175     if (Src == SpliceDest) {
176       LREndedBits LeftMask = OrigInst->LiveRangesEnded & ((1 << Index) - 1);
177       LREndedBits RightMask = OrigInst->LiveRangesEnded >> (Index + 1);
178       LiveRangesEnded = LeftMask | (SpliceAssn->LiveRangesEnded << Index) |
179                         (RightMask << (Index + getSrc(I)->getNumVars()));
180       return;
181     }
182     Index += getSrc(I)->getNumVars();
183   }
184   llvm::report_fatal_error("Failed to find splice operand");
185 }
186 
isMemoryWrite() const187 bool Inst::isMemoryWrite() const {
188   llvm::report_fatal_error("Attempt to call base Inst::isMemoryWrite() method");
189 }
190 
livenessLightweight(Cfg * Func,LivenessBV & Live)191 void Inst::livenessLightweight(Cfg *Func, LivenessBV &Live) {
192   assert(!isDeleted());
193   resetLastUses();
194   VariablesMetadata *VMetadata = Func->getVMetadata();
195   FOREACH_VAR_IN_INST(Var, *this) {
196     if (VMetadata->isMultiBlock(Var))
197       continue;
198     SizeT Index = Var->getIndex();
199     if (Live[Index])
200       continue;
201     Live[Index] = true;
202     setLastUse(IndexOfVarInInst(Var));
203   }
204 }
205 
liveness(InstNumberT InstNumber,LivenessBV & Live,Liveness * Liveness,LiveBeginEndMap * LiveBegin,LiveBeginEndMap * LiveEnd)206 bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
207                     Liveness *Liveness, LiveBeginEndMap *LiveBegin,
208                     LiveBeginEndMap *LiveEnd) {
209   assert(!isDeleted());
210 
211   Dead = false;
212   if (Dest && !Dest->isRematerializable()) {
213     SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
214     if (Live[VarNum]) {
215       if (!isDestRedefined()) {
216         Live[VarNum] = false;
217         if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
218           LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
219         }
220       }
221     } else {
222       if (!hasSideEffects())
223         Dead = true;
224     }
225   }
226   if (Dead)
227     return false;
228   // Phi arguments only get added to Live in the predecessor node, but we still
229   // need to update LiveRangesEnded.
230   bool IsPhi = llvm::isa<InstPhi>(this);
231   resetLastUses();
232   FOREACH_VAR_IN_INST(Var, *this) {
233     if (Var->isRematerializable())
234       continue;
235     SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
236     if (!Live[VarNum]) {
237       setLastUse(IndexOfVarInInst(Var));
238       if (!IsPhi) {
239         Live[VarNum] = true;
240         // For a variable in SSA form, its live range can end at most once in a
241         // basic block. However, after lowering to two-address instructions, we
242         // end up with sequences like "t=b;t+=c;a=t" where t's live range
243         // begins and ends twice. ICE only allows a variable to have a single
244         // liveness interval in a basic block (except for blocks where a
245         // variable is live-in and live-out but there is a gap in the middle).
246         // Therefore, this lowered sequence needs to represent a single
247         // conservative live range for t. Since the instructions are being
248         // traversed backwards, we make sure LiveEnd is only set once by
249         // setting it only when LiveEnd[VarNum]==0 (sentinel value). Note that
250         // it's OK to set LiveBegin multiple times because of the backwards
251         // traversal.
252         if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
253           // Ideally, we would verify that VarNum wasn't already added in this
254           // block, but this can't be done very efficiently with LiveEnd as a
255           // vector. Instead, livenessPostprocess() verifies this after the
256           // vector has been sorted.
257           LiveEnd->push_back(std::make_pair(VarNum, InstNumber));
258         }
259       }
260     }
261   }
262   return true;
263 }
264 
InstAlloca(Cfg * Func,Variable * Dest,Operand * ByteCount,uint32_t AlignInBytes)265 InstAlloca::InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
266                        uint32_t AlignInBytes)
267     : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
268   // Verify AlignInBytes is 0 or a power of 2.
269   assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
270   addSource(ByteCount);
271 }
272 
InstArithmetic(Cfg * Func,OpKind Op,Variable * Dest,Operand * Source1,Operand * Source2)273 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest,
274                                Operand *Source1, Operand *Source2)
275     : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) {
276   addSource(Source1);
277   addSource(Source2);
278 }
279 
getInstName() const280 const char *InstArithmetic::getInstName() const {
281   if (!BuildDefs::dump())
282     return "???";
283 
284   return InstArithmeticAttributes[getOp()].DisplayString;
285 }
286 
getOpName(OpKind Op)287 const char *InstArithmetic::getOpName(OpKind Op) {
288   return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
289                                    : "???";
290 }
291 
isCommutative() const292 bool InstArithmetic::isCommutative() const {
293   return InstArithmeticAttributes[getOp()].IsCommutative;
294 }
295 
InstAssign(Cfg * Func,Variable * Dest,Operand * Source)296 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
297     : InstHighLevel(Func, Inst::Assign, 1, Dest) {
298   addSource(Source);
299 }
300 
isVarAssign() const301 bool InstAssign::isVarAssign() const { return llvm::isa<Variable>(getSrc(0)); }
302 
303 // If TargetTrue==TargetFalse, we turn it into an unconditional branch. This
304 // ensures that, along with the 'switch' instruction semantics, there is at
305 // most one edge from one node to another.
InstBr(Cfg * Func,Operand * Source,CfgNode * TargetTrue_,CfgNode * TargetFalse_)306 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
307                CfgNode *TargetFalse_)
308     : InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
309       TargetTrue(TargetTrue_) {
310   if (auto *Constant = llvm::dyn_cast<ConstantInteger32>(Source)) {
311     int32_t C32 = Constant->getValue();
312     if (C32 != 0) {
313       TargetFalse = TargetTrue;
314     }
315     TargetTrue = nullptr; // turn into unconditional version
316   } else if (TargetTrue == TargetFalse) {
317     TargetTrue = nullptr; // turn into unconditional version
318   } else {
319     addSource(Source);
320   }
321 }
322 
InstBr(Cfg * Func,CfgNode * Target)323 InstBr::InstBr(Cfg *Func, CfgNode *Target)
324     : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
325       TargetTrue(nullptr) {}
326 
getTerminatorEdges() const327 NodeList InstBr::getTerminatorEdges() const {
328   NodeList OutEdges;
329   OutEdges.reserve(TargetTrue ? 2 : 1);
330   OutEdges.push_back(TargetFalse);
331   if (TargetTrue)
332     OutEdges.push_back(TargetTrue);
333   return OutEdges;
334 }
335 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)336 bool InstBr::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
337   bool Found = false;
338   if (TargetFalse == OldNode) {
339     TargetFalse = NewNode;
340     Found = true;
341   }
342   if (TargetTrue == OldNode) {
343     TargetTrue = NewNode;
344     Found = true;
345   }
346   return Found;
347 }
348 
InstCast(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)349 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
350     : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
351   addSource(Source);
352 }
353 
InstExtractElement(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)354 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest,
355                                        Operand *Source1, Operand *Source2)
356     : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) {
357   addSource(Source1);
358   addSource(Source2);
359 }
360 
InstFcmp(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)361 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
362                    Operand *Source2)
363     : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) {
364   addSource(Source1);
365   addSource(Source2);
366 }
367 
InstIcmp(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)368 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
369                    Operand *Source2)
370     : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) {
371   addSource(Source1);
372   addSource(Source2);
373 }
374 
InstInsertElement(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)375 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest,
376                                      Operand *Source1, Operand *Source2,
377                                      Operand *Source3)
378     : InstHighLevel(Func, Inst::InsertElement, 3, Dest) {
379   addSource(Source1);
380   addSource(Source2);
381   addSource(Source3);
382 }
383 
InstLoad(Cfg * Func,Variable * Dest,Operand * SourceAddr)384 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
385     : InstHighLevel(Func, Inst::Load, 1, Dest) {
386   addSource(SourceAddr);
387 }
388 
InstPhi(Cfg * Func,SizeT MaxSrcs,Variable * Dest)389 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest)
390     : InstHighLevel(Func, Phi, MaxSrcs, Dest) {
391   Labels.reserve(MaxSrcs);
392 }
393 
394 // TODO: A Switch instruction (and maybe others) can add duplicate edges. We
395 // may want to de-dup Phis and validate consistency (i.e., the source operands
396 // are the same for duplicate edges), though it seems the current lowering code
397 // is OK with this situation.
addArgument(Operand * Source,CfgNode * Label)398 void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
399   assert(Label);
400   Labels.push_back(Label);
401   addSource(Source);
402 }
403 
404 // Find the source operand corresponding to the incoming edge for the given
405 // node.
getOperandForTarget(CfgNode * Target) const406 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
407   for (SizeT I = 0; I < getSrcSize(); ++I) {
408     if (Labels[I] == Target)
409       return getSrc(I);
410   }
411   llvm_unreachable("Phi target not found");
412   return nullptr;
413 }
414 
415 // Replace the source operand corresponding to the incoming edge for the given
416 // node by a zero of the appropriate type.
clearOperandForTarget(CfgNode * Target)417 void InstPhi::clearOperandForTarget(CfgNode *Target) {
418   for (SizeT I = 0; I < getSrcSize(); ++I) {
419     if (getLabel(I) == Target) {
420       Type Ty = Dest->getType();
421       Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
422       return;
423     }
424   }
425   llvm_unreachable("Phi target not found");
426 }
427 
428 // Updates liveness for a particular operand based on the given predecessor
429 // edge. Doesn't mark the operand as live if the Phi instruction is dead or
430 // deleted.
livenessPhiOperand(LivenessBV & Live,CfgNode * Target,Liveness * Liveness)431 void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
432                                  Liveness *Liveness) {
433   if (isDeleted() || Dead)
434     return;
435   for (SizeT I = 0; I < getSrcSize(); ++I) {
436     if (Labels[I] == Target) {
437       if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
438         if (!Var->isRematerializable()) {
439           SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
440           if (!Live[SrcIndex]) {
441             setLastUse(I);
442             Live[SrcIndex] = true;
443           }
444         }
445       }
446       return;
447     }
448   }
449   llvm_unreachable("Phi operand not found for specified target node");
450 }
451 
452 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new instruction
453 // "a=a_phi".
lower(Cfg * Func)454 Inst *InstPhi::lower(Cfg *Func) {
455   Variable *Dest = getDest();
456   assert(Dest);
457   Variable *NewSrc = Func->makeVariable(Dest->getType());
458   if (BuildDefs::dump())
459     NewSrc->setName(Func, Dest->getName() + "_phi");
460   if (auto *NewSrc64On32 = llvm::dyn_cast<Variable64On32>(NewSrc))
461     NewSrc64On32->initHiLo(Func);
462   this->Dest = NewSrc;
463   return InstAssign::create(Func, Dest, NewSrc);
464 }
465 
InstRet(Cfg * Func,Operand * RetValue)466 InstRet::InstRet(Cfg *Func, Operand *RetValue)
467     : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
468   if (RetValue)
469     addSource(RetValue);
470 }
471 
InstSelect(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)472 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition,
473                        Operand *SourceTrue, Operand *SourceFalse)
474     : InstHighLevel(Func, Inst::Select, 3, Dest) {
475   assert(typeElementType(Condition->getType()) == IceType_i1);
476   addSource(Condition);
477   addSource(SourceTrue);
478   addSource(SourceFalse);
479 }
480 
InstStore(Cfg * Func,Operand * Data,Operand * Addr)481 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr)
482     : InstHighLevel(Func, Inst::Store, 3, nullptr) {
483   addSource(Data);
484   addSource(Addr);
485   // The 3rd operand is a dummy placeholder for the RMW beacon.
486   addSource(Data);
487 }
488 
getRmwBeacon() const489 Variable *InstStore::getRmwBeacon() const {
490   return llvm::dyn_cast<Variable>(getSrc(2));
491 }
492 
setRmwBeacon(Variable * Beacon)493 void InstStore::setRmwBeacon(Variable *Beacon) {
494   Dest = llvm::dyn_cast<Variable>(getData());
495   Srcs[2] = Beacon;
496 }
497 
InstSwitch(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)498 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source,
499                        CfgNode *LabelDefault)
500     : InstHighLevel(Func, Inst::Switch, 1, nullptr), LabelDefault(LabelDefault),
501       NumCases(NumCases) {
502   addSource(Source);
503   Values = Func->allocateArrayOf<uint64_t>(NumCases);
504   Labels = Func->allocateArrayOf<CfgNode *>(NumCases);
505   // Initialize in case buggy code doesn't set all entries
506   for (SizeT I = 0; I < NumCases; ++I) {
507     Values[I] = 0;
508     Labels[I] = nullptr;
509   }
510 }
511 
addBranch(SizeT CaseIndex,uint64_t Value,CfgNode * Label)512 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
513   assert(CaseIndex < NumCases);
514   Values[CaseIndex] = Value;
515   Labels[CaseIndex] = Label;
516 }
517 
getTerminatorEdges() const518 NodeList InstSwitch::getTerminatorEdges() const {
519   NodeList OutEdges;
520   OutEdges.reserve(NumCases + 1);
521   assert(LabelDefault);
522   OutEdges.push_back(LabelDefault);
523   for (SizeT I = 0; I < NumCases; ++I) {
524     assert(Labels[I]);
525     OutEdges.push_back(Labels[I]);
526   }
527   std::sort(OutEdges.begin(), OutEdges.end(),
528             [](const CfgNode *x, const CfgNode *y) {
529               return x->getIndex() < y->getIndex();
530             });
531   auto Last = std::unique(OutEdges.begin(), OutEdges.end());
532   OutEdges.erase(Last, OutEdges.end());
533   return OutEdges;
534 }
535 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)536 bool InstSwitch::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
537   bool Found = false;
538   if (LabelDefault == OldNode) {
539     LabelDefault = NewNode;
540     Found = true;
541   }
542   for (SizeT I = 0; I < NumCases; ++I) {
543     if (Labels[I] == OldNode) {
544       Labels[I] = NewNode;
545       Found = true;
546     }
547   }
548   return Found;
549 }
550 
InstUnreachable(Cfg * Func)551 InstUnreachable::InstUnreachable(Cfg *Func)
552     : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
553 
InstBundleLock(Cfg * Func,InstBundleLock::Option BundleOption)554 InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
555     : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
556       BundleOption(BundleOption) {}
557 
InstBundleUnlock(Cfg * Func)558 InstBundleUnlock::InstBundleUnlock(Cfg *Func)
559     : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
560 
InstFakeDef(Cfg * Func,Variable * Dest,Variable * Src)561 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src)
562     : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) {
563   assert(Dest);
564   if (Src)
565     addSource(Src);
566 }
567 
InstFakeUse(Cfg * Func,Variable * Src,uint32_t Weight)568 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight)
569     : InstHighLevel(Func, Inst::FakeUse, Weight, nullptr) {
570   assert(Src);
571   for (uint32_t i = 0; i < Weight; ++i)
572     addSource(Src);
573 }
574 
InstFakeKill(Cfg * Func,const Inst * Linked)575 InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
576     : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
577 
InstShuffleVector(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)578 InstShuffleVector::InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0,
579                                      Operand *Src1)
580     : InstHighLevel(Func, Inst::ShuffleVector, 2, Dest),
581       NumIndexes(typeNumElements(Dest->getType())) {
582   addSource(Src0);
583   addSource(Src1);
584   Indexes = Func->allocateArrayOf<ConstantInteger32 *>(NumIndexes);
585 }
586 
587 namespace {
makeName(Cfg * Func,const SizeT Id)588 GlobalString makeName(Cfg *Func, const SizeT Id) {
589   const auto FuncName = Func->getFunctionName();
590   auto *Ctx = Func->getContext();
591   if (FuncName.hasStdString())
592     return GlobalString::createWithString(
593         Ctx, ".L" + FuncName.toString() + "$jumptable$__" + std::to_string(Id));
594   return GlobalString::createWithString(
595       Ctx, "$J" + std::to_string(FuncName.getID()) + "_" + std::to_string(Id));
596 }
597 } // end of anonymous namespace
598 
InstJumpTable(Cfg * Func,SizeT NumTargets,CfgNode * Default)599 InstJumpTable::InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default)
600     : InstHighLevel(Func, Inst::JumpTable, 1, nullptr),
601       Id(Func->getTarget()->makeNextJumpTableNumber()), NumTargets(NumTargets),
602       Name(makeName(Func, Id)), FuncName(Func->getFunctionName()) {
603   Targets = Func->allocateArrayOf<CfgNode *>(NumTargets);
604   for (SizeT I = 0; I < NumTargets; ++I) {
605     Targets[I] = Default;
606   }
607 }
608 
repointEdges(CfgNode * OldNode,CfgNode * NewNode)609 bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
610   bool Found = false;
611   for (SizeT I = 0; I < NumTargets; ++I) {
612     if (Targets[I] == OldNode) {
613       Targets[I] = NewNode;
614       Found = true;
615     }
616   }
617   return Found;
618 }
619 
toJumpTableData(Assembler * Asm) const620 JumpTableData InstJumpTable::toJumpTableData(Assembler *Asm) const {
621   JumpTableData::TargetList TargetList(NumTargets);
622   for (SizeT i = 0; i < NumTargets; ++i) {
623     const SizeT Index = Targets[i]->getIndex();
624     TargetList[i] = Asm->getCfgNodeLabel(Index)->getPosition();
625   }
626   return JumpTableData(Name, FuncName, Id, TargetList);
627 }
628 
getReturnType() const629 Type InstCall::getReturnType() const {
630   if (Dest == nullptr)
631     return IceType_void;
632   return Dest->getType();
633 }
634 
635 // ======================== Dump routines ======================== //
636 
dumpDecorated(const Cfg * Func) const637 void Inst::dumpDecorated(const Cfg *Func) const {
638   if (!BuildDefs::dump())
639     return;
640   Ostream &Str = Func->getContext()->getStrDump();
641   if (!Func->isVerbose(IceV_Deleted) && (isDeleted() || isRedundantAssign()))
642     return;
643   if (Func->isVerbose(IceV_InstNumbers)) {
644     InstNumberT Number = getNumber();
645     if (Number == NumberDeleted)
646       Str << "[XXX]";
647     else
648       Str << llvm::format("[%3d]", Number);
649   }
650   Str << "  ";
651   if (isDeleted())
652     Str << "  //";
653   dump(Func);
654   dumpExtras(Func);
655   Str << "\n";
656 }
657 
dump(const Cfg * Func) const658 void Inst::dump(const Cfg *Func) const {
659   if (!BuildDefs::dump())
660     return;
661   Ostream &Str = Func->getContext()->getStrDump();
662   dumpDest(Func);
663   Str << " =~ " << getInstName() << " ";
664   dumpSources(Func);
665 }
666 
dumpExtras(const Cfg * Func) const667 void Inst::dumpExtras(const Cfg *Func) const {
668   if (!BuildDefs::dump())
669     return;
670   Ostream &Str = Func->getContext()->getStrDump();
671   bool First = true;
672   // Print "LIVEEND={a,b,c}" for all source operands whose live ranges are
673   // known to end at this instruction.
674   if (Func->isVerbose(IceV_Liveness)) {
675     FOREACH_VAR_IN_INST(Var, *this) {
676       if (isLastUse(Var)) {
677         if (First)
678           Str << " // LIVEEND={";
679         else
680           Str << ",";
681         Var->dump(Func);
682         First = false;
683       }
684     }
685     if (!First)
686       Str << "}";
687   }
688 }
689 
dumpSources(const Cfg * Func) const690 void Inst::dumpSources(const Cfg *Func) const {
691   if (!BuildDefs::dump())
692     return;
693   Ostream &Str = Func->getContext()->getStrDump();
694   for (SizeT I = 0; I < getSrcSize(); ++I) {
695     if (I > 0)
696       Str << ", ";
697     getSrc(I)->dump(Func);
698   }
699 }
700 
emitSources(const Cfg * Func) const701 void Inst::emitSources(const Cfg *Func) const {
702   if (!BuildDefs::dump())
703     return;
704   Ostream &Str = Func->getContext()->getStrEmit();
705   for (SizeT I = 0; I < getSrcSize(); ++I) {
706     if (I > 0)
707       Str << ", ";
708     getSrc(I)->emit(Func);
709   }
710 }
711 
dumpDest(const Cfg * Func) const712 void Inst::dumpDest(const Cfg *Func) const {
713   if (!BuildDefs::dump())
714     return;
715   if (getDest())
716     getDest()->dump(Func);
717 }
718 
dump(const Cfg * Func) const719 void InstAlloca::dump(const Cfg *Func) const {
720   if (!BuildDefs::dump())
721     return;
722   Ostream &Str = Func->getContext()->getStrDump();
723   dumpDest(Func);
724   Str << " = alloca i8, i32 ";
725   getSizeInBytes()->dump(Func);
726   if (getAlignInBytes())
727     Str << ", align " << getAlignInBytes();
728 }
729 
dump(const Cfg * Func) const730 void InstArithmetic::dump(const Cfg *Func) const {
731   if (!BuildDefs::dump())
732     return;
733   Ostream &Str = Func->getContext()->getStrDump();
734   dumpDest(Func);
735   Str << " = " << getInstName() << " " << getDest()->getType() << " ";
736   dumpSources(Func);
737 }
738 
dump(const Cfg * Func) const739 void InstAssign::dump(const Cfg *Func) const {
740   if (!BuildDefs::dump())
741     return;
742   Ostream &Str = Func->getContext()->getStrDump();
743   dumpDest(Func);
744   Str << " = " << getDest()->getType() << " ";
745   dumpSources(Func);
746 }
747 
dump(const Cfg * Func) const748 void InstBr::dump(const Cfg *Func) const {
749   if (!BuildDefs::dump())
750     return;
751   Ostream &Str = Func->getContext()->getStrDump();
752   dumpDest(Func);
753   Str << "br ";
754   if (!isUnconditional()) {
755     Str << "i1 ";
756     getCondition()->dump(Func);
757     Str << ", label %" << getTargetTrue()->getName() << ", ";
758   }
759   Str << "label %" << getTargetFalse()->getName();
760 }
761 
dump(const Cfg * Func) const762 void InstCall::dump(const Cfg *Func) const {
763   if (!BuildDefs::dump())
764     return;
765   Ostream &Str = Func->getContext()->getStrDump();
766   if (getDest()) {
767     dumpDest(Func);
768     Str << " = ";
769   }
770   Str << "call ";
771   if (getDest())
772     Str << getDest()->getType();
773   else
774     Str << "void";
775   Str << " ";
776   getCallTarget()->dump(Func);
777   Str << "(";
778   for (SizeT I = 0; I < getNumArgs(); ++I) {
779     if (I > 0)
780       Str << ", ";
781     Str << getArg(I)->getType() << " ";
782     getArg(I)->dump(Func);
783   }
784   Str << ")";
785 }
786 
getCastName(InstCast::OpKind Kind)787 const char *InstCast::getCastName(InstCast::OpKind Kind) {
788   if (Kind < InstCast::OpKind::_num)
789     return InstCastAttributes[Kind].DisplayString;
790   llvm_unreachable("Invalid InstCast::OpKind");
791   return "???";
792 }
793 
dump(const Cfg * Func) const794 void InstCast::dump(const Cfg *Func) const {
795   if (!BuildDefs::dump())
796     return;
797   Ostream &Str = Func->getContext()->getStrDump();
798   dumpDest(Func);
799   Str << " = " << getCastName(getCastKind()) << " " << getSrc(0)->getType()
800       << " ";
801   dumpSources(Func);
802   Str << " to " << getDest()->getType();
803 }
804 
dump(const Cfg * Func) const805 void InstIcmp::dump(const Cfg *Func) const {
806   if (!BuildDefs::dump())
807     return;
808   Ostream &Str = Func->getContext()->getStrDump();
809   dumpDest(Func);
810   Str << " = icmp " << InstIcmpAttributes[getCondition()].DisplayString << " "
811       << getSrc(0)->getType() << " ";
812   dumpSources(Func);
813 }
814 
dump(const Cfg * Func) const815 void InstExtractElement::dump(const Cfg *Func) const {
816   if (!BuildDefs::dump())
817     return;
818   Ostream &Str = Func->getContext()->getStrDump();
819   dumpDest(Func);
820   Str << " = extractelement ";
821   Str << getSrc(0)->getType() << " ";
822   getSrc(0)->dump(Func);
823   Str << ", ";
824   Str << getSrc(1)->getType() << " ";
825   getSrc(1)->dump(Func);
826 }
827 
dump(const Cfg * Func) const828 void InstInsertElement::dump(const Cfg *Func) const {
829   if (!BuildDefs::dump())
830     return;
831   Ostream &Str = Func->getContext()->getStrDump();
832   dumpDest(Func);
833   Str << " = insertelement ";
834   Str << getSrc(0)->getType() << " ";
835   getSrc(0)->dump(Func);
836   Str << ", ";
837   Str << getSrc(1)->getType() << " ";
838   getSrc(1)->dump(Func);
839   Str << ", ";
840   Str << getSrc(2)->getType() << " ";
841   getSrc(2)->dump(Func);
842 }
843 
dump(const Cfg * Func) const844 void InstFcmp::dump(const Cfg *Func) const {
845   if (!BuildDefs::dump())
846     return;
847   Ostream &Str = Func->getContext()->getStrDump();
848   dumpDest(Func);
849   Str << " = fcmp " << InstFcmpAttributes[getCondition()].DisplayString << " "
850       << getSrc(0)->getType() << " ";
851   dumpSources(Func);
852 }
853 
dump(const Cfg * Func) const854 void InstLoad::dump(const Cfg *Func) const {
855   if (!BuildDefs::dump())
856     return;
857   Ostream &Str = Func->getContext()->getStrDump();
858   dumpDest(Func);
859   Type Ty = getDest()->getType();
860   Str << " = load " << Ty << ", " << Ty << "* ";
861   dumpSources(Func);
862   Str << ", align " << typeAlignInBytes(Ty);
863 }
864 
dump(const Cfg * Func) const865 void InstStore::dump(const Cfg *Func) const {
866   if (!BuildDefs::dump())
867     return;
868   Ostream &Str = Func->getContext()->getStrDump();
869   Type Ty = getData()->getType();
870   dumpDest(Func);
871   if (Dest)
872     Str << " = ";
873   Str << "store " << Ty << " ";
874   getData()->dump(Func);
875   Str << ", " << Ty << "* ";
876   getAddr()->dump(Func);
877   Str << ", align " << typeAlignInBytes(Ty);
878   if (getRmwBeacon()) {
879     Str << ", beacon ";
880     getRmwBeacon()->dump(Func);
881   }
882 }
883 
dump(const Cfg * Func) const884 void InstSwitch::dump(const Cfg *Func) const {
885   if (!BuildDefs::dump())
886     return;
887   Ostream &Str = Func->getContext()->getStrDump();
888   Type Ty = getComparison()->getType();
889   Str << "switch " << Ty << " ";
890   getSrc(0)->dump(Func);
891   Str << ", label %" << getLabelDefault()->getName() << " [\n";
892   for (SizeT I = 0; I < getNumCases(); ++I) {
893     Str << "    " << Ty << " " << static_cast<int64_t>(getValue(I))
894         << ", label %" << getLabel(I)->getName() << "\n";
895   }
896   Str << "  ]";
897 }
898 
dump(const Cfg * Func) const899 void InstPhi::dump(const Cfg *Func) const {
900   if (!BuildDefs::dump())
901     return;
902   Ostream &Str = Func->getContext()->getStrDump();
903   dumpDest(Func);
904   Str << " = phi " << getDest()->getType() << " ";
905   for (SizeT I = 0; I < getSrcSize(); ++I) {
906     if (I > 0)
907       Str << ", ";
908     Str << "[ ";
909     getSrc(I)->dump(Func);
910     Str << ", %" << Labels[I]->getName() << " ]";
911   }
912 }
913 
dump(const Cfg * Func) const914 void InstRet::dump(const Cfg *Func) const {
915   if (!BuildDefs::dump())
916     return;
917   Ostream &Str = Func->getContext()->getStrDump();
918   Type Ty = hasRetValue() ? getRetValue()->getType() : IceType_void;
919   Str << "ret " << Ty;
920   if (hasRetValue()) {
921     Str << " ";
922     dumpSources(Func);
923   }
924 }
925 
dump(const Cfg * Func) const926 void InstSelect::dump(const Cfg *Func) const {
927   if (!BuildDefs::dump())
928     return;
929   Ostream &Str = Func->getContext()->getStrDump();
930   dumpDest(Func);
931   Operand *Condition = getCondition();
932   Operand *TrueOp = getTrueOperand();
933   Operand *FalseOp = getFalseOperand();
934   Str << " = select " << Condition->getType() << " ";
935   Condition->dump(Func);
936   Str << ", " << TrueOp->getType() << " ";
937   TrueOp->dump(Func);
938   Str << ", " << FalseOp->getType() << " ";
939   FalseOp->dump(Func);
940 }
941 
dump(const Cfg * Func) const942 void InstUnreachable::dump(const Cfg *Func) const {
943   if (!BuildDefs::dump())
944     return;
945   Ostream &Str = Func->getContext()->getStrDump();
946   Str << "unreachable";
947 }
948 
emit(const Cfg * Func) const949 void InstBundleLock::emit(const Cfg *Func) const {
950   if (!BuildDefs::dump())
951     return;
952   Ostream &Str = Func->getContext()->getStrEmit();
953   Str << "\t.bundle_lock";
954   switch (BundleOption) {
955   case Opt_None:
956     break;
957   case Opt_AlignToEnd:
958     Str << "\t"
959            "align_to_end";
960     break;
961   case Opt_PadToEnd:
962     Str << "\t"
963            "align_to_end /* pad_to_end */";
964     break;
965   }
966   Str << "\n";
967 }
968 
dump(const Cfg * Func) const969 void InstBundleLock::dump(const Cfg *Func) const {
970   if (!BuildDefs::dump())
971     return;
972   Ostream &Str = Func->getContext()->getStrDump();
973   Str << "bundle_lock";
974   switch (BundleOption) {
975   case Opt_None:
976     break;
977   case Opt_AlignToEnd:
978     Str << " align_to_end";
979     break;
980   case Opt_PadToEnd:
981     Str << " pad_to_end";
982     break;
983   }
984 }
985 
emit(const Cfg * Func) const986 void InstBundleUnlock::emit(const Cfg *Func) const {
987   if (!BuildDefs::dump())
988     return;
989   Ostream &Str = Func->getContext()->getStrEmit();
990   Str << "\t.bundle_unlock";
991   Str << "\n";
992 }
993 
dump(const Cfg * Func) const994 void InstBundleUnlock::dump(const Cfg *Func) const {
995   if (!BuildDefs::dump())
996     return;
997   Ostream &Str = Func->getContext()->getStrDump();
998   Str << "bundle_unlock";
999 }
1000 
emit(const Cfg * Func) const1001 void InstFakeDef::emit(const Cfg *Func) const {
1002   if (!BuildDefs::dump())
1003     return;
1004   // Go ahead and "emit" these for now, since they are relatively rare.
1005   Ostream &Str = Func->getContext()->getStrEmit();
1006   Str << "\t# ";
1007   getDest()->emit(Func);
1008   Str << " = def.pseudo";
1009   if (getSrcSize() > 0)
1010     Str << " ";
1011   emitSources(Func);
1012   Str << "\n";
1013 }
1014 
dump(const Cfg * Func) const1015 void InstFakeDef::dump(const Cfg *Func) const {
1016   if (!BuildDefs::dump())
1017     return;
1018   Ostream &Str = Func->getContext()->getStrDump();
1019   dumpDest(Func);
1020   Str << " = def.pseudo ";
1021   dumpSources(Func);
1022 }
1023 
emit(const Cfg * Func) const1024 void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
1025 
dump(const Cfg * Func) const1026 void InstFakeUse::dump(const Cfg *Func) const {
1027   if (!BuildDefs::dump())
1028     return;
1029   Ostream &Str = Func->getContext()->getStrDump();
1030   Str << "use.pseudo ";
1031   dumpSources(Func);
1032 }
1033 
emit(const Cfg * Func) const1034 void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
1035 
dump(const Cfg * Func) const1036 void InstFakeKill::dump(const Cfg *Func) const {
1037   if (!BuildDefs::dump())
1038     return;
1039   Ostream &Str = Func->getContext()->getStrDump();
1040   if (Linked->isDeleted())
1041     Str << "// ";
1042   Str << "kill.pseudo scratch_regs";
1043 }
1044 
dump(const Cfg * Func) const1045 void InstShuffleVector::dump(const Cfg *Func) const {
1046   if (!BuildDefs::dump())
1047     return;
1048   Ostream &Str = Func->getContext()->getStrDump();
1049   Str << "shufflevector ";
1050   dumpDest(Func);
1051   Str << " = ";
1052   dumpSources(Func);
1053   for (SizeT I = 0; I < NumIndexes; ++I) {
1054     Str << ", ";
1055     Indexes[I]->dump(Func);
1056   }
1057   Str << "\n";
1058 }
1059 
dump(const Cfg * Func) const1060 void InstJumpTable::dump(const Cfg *Func) const {
1061   if (!BuildDefs::dump())
1062     return;
1063   Ostream &Str = Func->getContext()->getStrDump();
1064   Str << "jump table [";
1065   for (SizeT I = 0; I < NumTargets; ++I)
1066     Str << "\n    " << Targets[I]->getName();
1067   Str << "\n  ]";
1068 }
1069 
dump(const Cfg * Func) const1070 void InstTarget::dump(const Cfg *Func) const {
1071   if (!BuildDefs::dump())
1072     return;
1073   Ostream &Str = Func->getContext()->getStrDump();
1074   Str << "[TARGET] ";
1075   Inst::dump(Func);
1076 }
1077 
InstBreakpoint(Cfg * Func)1078 InstBreakpoint::InstBreakpoint(Cfg *Func)
1079     : InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
1080 
reverseConditionAndOperands()1081 void InstIcmp::reverseConditionAndOperands() {
1082   Condition = InstIcmpAttributes[Condition].Reverse;
1083   std::swap(Srcs[0], Srcs[1]);
1084 }
1085 
checkForRedundantAssign(const Variable * Dest,const Operand * Source)1086 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
1087   const auto *SrcVar = llvm::dyn_cast<const Variable>(Source);
1088   if (SrcVar == nullptr)
1089     return false;
1090   if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) {
1091     // TODO: On x86-64, instructions like "mov eax, eax" are used to clear the
1092     // upper 32 bits of rax. We need to recognize and preserve these.
1093     return true;
1094   }
1095   if (!Dest->hasReg() && !SrcVar->hasReg()) {
1096     if (!Dest->hasStackOffset() || !SrcVar->hasStackOffset()) {
1097       // If called before stack slots have been assigned (i.e. as part of the
1098       // dump() routine), conservatively return false.
1099       return false;
1100     }
1101     if (Dest->getStackOffset() != SrcVar->getStackOffset()) {
1102       return false;
1103     }
1104     return true;
1105   }
1106   // For a "v=t" assignment where t has a register, v has a stack slot, and v
1107   // has a LinkedTo stack root, and v and t share the same LinkedTo root, return
1108   // true.  This is because this assignment is effectively reassigning the same
1109   // value to the original LinkedTo stack root.
1110   if (SrcVar->hasReg() && Dest->hasStackOffset() &&
1111       Dest->getLinkedToStackRoot() != nullptr &&
1112       Dest->getLinkedToRoot() == SrcVar->getLinkedToRoot()) {
1113     return true;
1114   }
1115   return false;
1116 }
1117 
1118 } // end of namespace Ice
1119