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
27namespace Ice {
28
29namespace {
30
31// Using non-anonymous struct so that array_lengthof works.
32const 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.
44const 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.
55const 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.
66const 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
79Inst::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
85const 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.
127void 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.
133void 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.
140bool 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.
175void 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
195bool Inst::isMemoryWrite() const {
196  llvm::report_fatal_error("Attempt to call base Inst::isMemoryWrite() method");
197}
198
199void 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
214bool 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
273InstAlloca::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
281InstArithmetic::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
288const char *InstArithmetic::getInstName() const {
289  if (!BuildDefs::dump())
290    return "???";
291
292  return InstArithmeticAttributes[getOp()].DisplayString;
293}
294
295const char *InstArithmetic::getOpName(OpKind Op) {
296  return Op < InstArithmetic::_num ? InstArithmeticAttributes[Op].DisplayString
297                                   : "???";
298}
299
300bool InstArithmetic::isCommutative() const {
301  return InstArithmeticAttributes[getOp()].IsCommutative;
302}
303
304InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source)
305    : InstHighLevel(Func, Inst::Assign, 1, Dest) {
306  addSource(Source);
307}
308
309bool 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.
314InstBr::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
331InstBr::InstBr(Cfg *Func, CfgNode *Target)
332    : InstHighLevel(Func, Inst::Br, 0, nullptr), TargetFalse(Target),
333      TargetTrue(nullptr) {}
334
335NodeList 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
344bool 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
357InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source)
358    : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) {
359  addSource(Source);
360}
361
362InstExtractElement::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
369InstFcmp::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
376InstIcmp::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
383InstInsertElement::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
392InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr)
393    : InstHighLevel(Func, Inst::Load, 1, Dest) {
394  addSource(SourceAddr);
395}
396
397InstPhi::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.
406void 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.
414Operand *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.
425void InstPhi::clearOperandForTarget(CfgNode *Target) {
426  for (SizeT I = 0; I < getSrcSize(); ++I) {
427    if (getLabel(I) == Target) {
428      Type Ty = Dest->getType();
429      Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
430      return;
431    }
432  }
433  llvm_unreachable("Phi target not found");
434}
435
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.
439void 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".
462Inst *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
474InstRet::InstRet(Cfg *Func, Operand *RetValue)
475    : InstHighLevel(Func, Ret, RetValue ? 1 : 0, nullptr) {
476  if (RetValue)
477    addSource(RetValue);
478}
479
480InstSelect::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
489InstStore::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
497Variable *InstStore::getRmwBeacon() const {
498  return llvm::dyn_cast<Variable>(getSrc(2));
499}
500
501void InstStore::setRmwBeacon(Variable *Beacon) {
502  Dest = llvm::dyn_cast<Variable>(getData());
503  Srcs[2] = Beacon;
504}
505
506InstSwitch::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
520void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) {
521  assert(CaseIndex < NumCases);
522  Values[CaseIndex] = Value;
523  Labels[CaseIndex] = Label;
524}
525
526NodeList InstSwitch::getTerminatorEdges() const {
527  NodeList OutEdges;
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
544bool 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
559InstUnreachable::InstUnreachable(Cfg *Func)
560    : InstHighLevel(Func, Inst::Unreachable, 0, nullptr) {}
561
562InstBundleLock::InstBundleLock(Cfg *Func, InstBundleLock::Option BundleOption)
563    : InstHighLevel(Func, Inst::BundleLock, 0, nullptr),
564      BundleOption(BundleOption) {}
565
566InstBundleUnlock::InstBundleUnlock(Cfg *Func)
567    : InstHighLevel(Func, Inst::BundleUnlock, 0, nullptr) {}
568
569InstFakeDef::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
576InstFakeUse::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
583InstFakeKill::InstFakeKill(Cfg *Func, const Inst *Linked)
584    : InstHighLevel(Func, Inst::FakeKill, 0, nullptr), Linked(Linked) {}
585
586InstShuffleVector::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
595namespace {
596GlobalString makeName(Cfg *Func, const SizeT Id) {
597  const auto FuncName = Func->getFunctionName();
598  auto *Ctx = Func->getContext();
599  if (FuncName.hasStdString())
600    return GlobalString::createWithString(
601        Ctx, ".L" + FuncName.toString() + "$jumptable$__" + std::to_string(Id));
602  return GlobalString::createWithString(
603      Ctx, "$J" + std::to_string(FuncName.getID()) + "_" + std::to_string(Id));
604}
605} // end of anonymous namespace
606
607InstJumpTable::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
617bool InstJumpTable::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
618  bool Found = false;
619  for (SizeT I = 0; I < NumTargets; ++I) {
620    if (Targets[I] == OldNode) {
621      Targets[I] = NewNode;
622      Found = true;
623    }
624  }
625  return Found;
626}
627
628JumpTableData 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
637Type InstCall::getReturnType() const {
638  if (Dest == nullptr)
639    return IceType_void;
640  return Dest->getType();
641}
642
643// ======================== Dump routines ======================== //
644
645void 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
666void 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
675void 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
698void 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
709void 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
720void Inst::dumpDest(const Cfg *Func) const {
721  if (!BuildDefs::dump())
722    return;
723  if (getDest())
724    getDest()->dump(Func);
725}
726
727void 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
738void 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
747void 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
756void 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
770void 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
795const 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
802void 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
813void 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
823void 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
836void 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
852void 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
862void 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
873void 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
892void 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
907void 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
922void 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
934void 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
950void InstUnreachable::dump(const Cfg *Func) const {
951  if (!BuildDefs::dump())
952    return;
953  Ostream &Str = Func->getContext()->getStrDump();
954  Str << "unreachable";
955}
956
957void 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
977void 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
994void 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
1002void InstBundleUnlock::dump(const Cfg *Func) const {
1003  if (!BuildDefs::dump())
1004    return;
1005  Ostream &Str = Func->getContext()->getStrDump();
1006  Str << "bundle_unlock";
1007}
1008
1009void 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
1023void 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
1032void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
1033
1034void 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
1042void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
1043
1044void 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
1053void 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
1068void 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
1078void 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
1086InstBreakpoint::InstBreakpoint(Cfg *Func)
1087    : InstHighLevel(Func, Inst::Breakpoint, 0, nullptr) {}
1088
1089void InstIcmp::reverseConditionAndOperands() {
1090  Condition = InstIcmpAttributes[Condition].Reverse;
1091  std::swap(Srcs[0], Srcs[1]);
1092}
1093
1094bool 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