//===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares the Inst class and its target-independent subclasses.
///
/// These represent the high-level Vanilla ICE instructions and map roughly 1:1
/// to LLVM instructions.
///
//===----------------------------------------------------------------------===//

#ifndef SUBZERO_SRC_ICEINST_H
#define SUBZERO_SRC_ICEINST_H

#include "IceCfg.h"
#include "IceDefs.h"
#include "IceInst.def"
#include "IceIntrinsics.h"
#include "IceOperand.h"
#include "IceSwitchLowering.h"
#include "IceTypes.h"

// TODO: The Cfg structure, and instructions in particular, need to be
// validated for things like valid operand types, valid branch targets, proper
// ordering of Phi and non-Phi instructions, etc. Most of the validity checking
// will be done in the bitcode reader. We need a list of everything that should
// be validated, and tests for each.

namespace Ice {

/// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and
/// InstTarget. High-level ICE instructions inherit from InstHighLevel, and
/// low-level (target-specific) ICE instructions inherit from InstTarget.
class Inst : public llvm::ilist_node<Inst> {
  Inst() = delete;
  Inst(const Inst &) = delete;
  Inst &operator=(const Inst &) = delete;

public:
  enum InstKind {
    // Arbitrary (alphabetical) order, except put Unreachable first.
    Unreachable,
    Alloca,
    Arithmetic,
    Br,
    Call,
    Cast,
    ExtractElement,
    Fcmp,
    Icmp,
    Intrinsic,
    InsertElement,
    Load,
    Phi,
    Ret,
    Select,
    Store,
    Switch,
    Assign,        // not part of LLVM/PNaCl bitcode
    Breakpoint,    // not part of LLVM/PNaCl bitcode
    BundleLock,    // not part of LLVM/PNaCl bitcode
    BundleUnlock,  // not part of LLVM/PNaCl bitcode
    FakeDef,       // not part of LLVM/PNaCl bitcode
    FakeUse,       // not part of LLVM/PNaCl bitcode
    FakeKill,      // not part of LLVM/PNaCl bitcode
    JumpTable,     // not part of LLVM/PNaCl bitcode
    ShuffleVector, // not part of LLVM/PNaCl bitcode
    // Anything >= Target is an InstTarget subclass. Note that the value-spaces
    // are shared across targets. To avoid confusion over the definition of
    // shared values, an object specific to one target should never be passed
    // to a different target.
    Target,
    Target_Max = std::numeric_limits<uint8_t>::max(),
  };
  static_assert(Target <= Target_Max, "Must not be above max.");
  InstKind getKind() const { return Kind; }
  virtual const char *getInstName() const;

  InstNumberT getNumber() const { return Number; }
  void renumber(Cfg *Func);
  enum {
    NumberDeleted = -1,
    NumberSentinel = 0,
    NumberInitial = 2,
    NumberExtended = NumberInitial - 1
  };

  bool isDeleted() const { return Deleted; }
  void setDeleted() { Deleted = true; }
  void setDead(bool Value = true) { Dead = Value; }
  void deleteIfDead();

  bool hasSideEffects() const { return HasSideEffects; }

  bool isDestRedefined() const { return IsDestRedefined; }
  void setDestRedefined() { IsDestRedefined = true; }

  Variable *getDest() const { return Dest; }

  SizeT getSrcSize() const { return Srcs.size(); }
  Operand *getSrc(SizeT I) const {
    assert(I < getSrcSize());
    return Srcs[I];
  }
  void replaceSource(SizeT Index, Operand *Replacement) {
    assert(Index < getSrcSize());
    assert(!isDeleted());
    Srcs[Index] = Replacement;
  }

  bool isLastUse(const Operand *Src) const;
  void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn);

  /// Returns a list of out-edges corresponding to a terminator instruction,
  /// which is the last instruction of the block. The list must not contain
  /// duplicates.
  virtual NodeList getTerminatorEdges() const {
    // All valid terminator instructions override this method. For the default
    // implementation, we assert in case some CfgNode is constructed without a
    // terminator instruction at the end.
    llvm_unreachable(
        "getTerminatorEdges() called on a non-terminator instruction");
    return NodeList();
  }
  virtual bool isUnconditionalBranch() const { return false; }
  /// If the instruction is a branch-type instruction with OldNode as a target,
  /// repoint it to NewNode and return true, otherwise return false. Repoint all
  /// instances of OldNode as a target.
  virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
    (void)OldNode;
    (void)NewNode;
    return false;
  }

  /// Returns true if the instruction is equivalent to a simple
  /// "var_dest=var_src" assignment where the dest and src are both variables.
  virtual bool isVarAssign() const { return false; }

  /// Returns true if the instruction has a possible side effect of changing
  /// memory, in which case a memory load should not be reordered with respect
  /// to this instruction.  It should really be pure virtual, but we can't
  /// because of g++ and llvm::ilist<>, so we implement it as
  /// report_fatal_error().
  virtual bool isMemoryWrite() const;

  /// Returns true if the (target-specific) instruction represents an
  /// intra-block label, i.e. branch target.  This is meant primarily for
  /// Cfg::splitLocalVars().
  virtual bool isLabel() const { return false; }
  /// If the (target-specific) instruction represents an intra-block branch to
  /// some Label instruction, return that Label branch target instruction;
  /// otherwise return nullptr.
  virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; }

  void livenessLightweight(Cfg *Func, LivenessBV &Live);
  /// Calculates liveness for this instruction. Returns true if this instruction
  /// is (tentatively) still live and should be retained, and false if this
  /// instruction is (tentatively) dead and should be deleted. The decision is
  /// tentative until the liveness dataflow algorithm has converged, and then a
  /// separate pass permanently deletes dead instructions.
  bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
                LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);

  /// Get the number of native instructions that this instruction ultimately
  /// emits. By default, high-level instructions don't result in any native
  /// instructions, and a target-specific instruction results in a single native
  /// instruction.
  virtual uint32_t getEmitInstCount() const { return 0; }
  // TODO(stichnot): Change Inst back to abstract once the g++ build issue is
  // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the
  // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't
  // allow the abstract class Ice::Inst. The method should be declared
  // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func)
  // const = 0; virtual void emitIAS(const Cfg *Func) const = 0;
  virtual void emit(const Cfg *) const {
    llvm_unreachable("emit on abstract class");
  }
  virtual void emitIAS(const Cfg *Func) const { emit(Func); }
  virtual void dump(const Cfg *Func) const;
  virtual void dumpExtras(const Cfg *Func) const;
  void dumpDecorated(const Cfg *Func) const;
  void emitSources(const Cfg *Func) const;
  void dumpSources(const Cfg *Func) const;
  void dumpDest(const Cfg *Func) const;
  virtual bool isRedundantAssign() const { return false; }

  virtual ~Inst() = default;
  void replaceDest(Variable *Var) { Dest = Var; }

  void operator delete(void *Ptr, std::size_t Size) {
    assert(CfgAllocatorTraits::current() != nullptr);
    CfgAllocatorTraits::current()->Deallocate(Ptr, Size);
    llvm::report_fatal_error("Inst unexpectedly deleted");
  }

  inline void *getExternalData() const { return externalData; }
  inline void setExternalData(void *data) { externalData = data; }

protected:
  Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest);
  void addSource(Operand *Src) {
    assert(Src);
    Srcs.push_back(Src);
  }
  void setLastUse(SizeT VarIndex) {
    if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded))
      LiveRangesEnded |= (((LREndedBits)1u) << VarIndex);
  }
  void resetLastUses() { LiveRangesEnded = 0; }
  /// The destroy() method lets the instruction cleanly release any memory that
  /// was allocated via the Cfg's allocator.
  virtual void destroy(Cfg *) {}

  const InstKind Kind;
  /// Number is the instruction number for describing live ranges.
  InstNumberT Number;
  /// Deleted means irrevocably deleted.
  bool Deleted = false;
  /// Dead means one of two things depending on context: (1) pending deletion
  /// after liveness analysis converges, or (2) marked for deletion during
  /// lowering due to a folded bool operation.
  bool Dead = false;
  /// HasSideEffects means the instruction is something like a function call or
  /// a volatile load that can't be removed even if its Dest variable is not
  /// live.
  bool HasSideEffects = false;
  /// IsDestRedefined indicates that this instruction is not the first
  /// definition of Dest in the basic block.  The effect is that liveness
  /// analysis shouldn't consider this instruction to be the start of Dest's
  /// live range; rather, there is some other instruction earlier in the basic
  /// block with the same Dest.  This is maintained because liveness analysis
  /// has an invariant (primarily for performance reasons) that any Variable's
  /// live range recorded in a basic block has at most one start and at most one
  /// end.
  bool IsDestRedefined = false;
  /// External data can be set by an optimizer to compute and retain any
  /// information related to the current instruction. All the memory used to
  /// store this information must be managed by the optimizer.
  void *externalData = nullptr;

  Variable *Dest;
  const SizeT MaxSrcs; // only used for assert

  CfgVector<Operand *> Srcs;

  /// LiveRangesEnded marks which Variables' live ranges end in this
  /// instruction. An instruction can have an arbitrary number of source
  /// operands (e.g. a call instruction), and each source operand can contain 0
  /// or 1 Variable (and target-specific operands could contain more than 1
  /// Variable). All the variables in an instruction are conceptually flattened
  /// and each variable is mapped to one bit position of the LiveRangesEnded bit
  /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are
  /// tracked this way.
  using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry
  LREndedBits LiveRangesEnded;
};

class InstHighLevel : public Inst {
  InstHighLevel() = delete;
  InstHighLevel(const InstHighLevel &) = delete;
  InstHighLevel &operator=(const InstHighLevel &) = delete;

protected:
  InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
      : Inst(Func, Kind, MaxSrcs, Dest) {}
  void emit(const Cfg * /*Func*/) const override {
    llvm_unreachable("emit() called on a non-lowered instruction");
  }
  void emitIAS(const Cfg * /*Func*/) const override {
    llvm_unreachable("emitIAS() called on a non-lowered instruction");
  }
};

/// Alloca instruction. This captures the size in bytes as getSrc(0), and the
/// required alignment in bytes. The alignment must be either 0 (no alignment
/// required) or a power of 2.
class InstAlloca : public InstHighLevel {
  InstAlloca() = delete;
  InstAlloca(const InstAlloca &) = delete;
  InstAlloca &operator=(const InstAlloca &) = delete;

public:
  static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
                            uint32_t AlignInBytes) {
    return new (Func->allocate<InstAlloca>())
        InstAlloca(Func, Dest, ByteCount, AlignInBytes);
  }
  uint32_t getAlignInBytes() const { return AlignInBytes; }
  Operand *getSizeInBytes() const { return getSrc(0); }
  bool getKnownFrameOffset() const { return KnownFrameOffset; }
  void setKnownFrameOffset() { KnownFrameOffset = true; }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }

private:
  InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
             uint32_t AlignInBytes);

  const uint32_t AlignInBytes;
  bool KnownFrameOffset = false;
};

/// Binary arithmetic instruction. The source operands are captured in getSrc(0)
/// and getSrc(1).
class InstArithmetic : public InstHighLevel {
  InstArithmetic() = delete;
  InstArithmetic(const InstArithmetic &) = delete;
  InstArithmetic &operator=(const InstArithmetic &) = delete;

public:
  enum OpKind {
#define X(tag, str, commutative) tag,
    ICEINSTARITHMETIC_TABLE
#undef X
        _num
  };

  static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest,
                                Operand *Source1, Operand *Source2) {
    return new (Func->allocate<InstArithmetic>())
        InstArithmetic(Func, Op, Dest, Source1, Source2);
  }
  OpKind getOp() const { return Op; }

  virtual const char *getInstName() const override;

  static const char *getOpName(OpKind Op);
  bool isCommutative() const;
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == Arithmetic;
  }

private:
  InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
                 Operand *Source2);

  const OpKind Op;
};

/// Assignment instruction. The source operand is captured in getSrc(0). This is
/// not part of the LLVM bitcode, but is a useful abstraction for some of the
/// lowering. E.g., if Phi instruction lowering happens before target lowering,
/// or for representing an Inttoptr instruction, or as an intermediate step for
/// lowering a Load instruction.
class InstAssign : public InstHighLevel {
  InstAssign() = delete;
  InstAssign(const InstAssign &) = delete;
  InstAssign &operator=(const InstAssign &) = delete;

public:
  static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
    return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
  }
  bool isVarAssign() const override;
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }

private:
  InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
};

/// Branch instruction. This represents both conditional and unconditional
/// branches.
class InstBr : public InstHighLevel {
  InstBr() = delete;
  InstBr(const InstBr &) = delete;
  InstBr &operator=(const InstBr &) = delete;

public:
  /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized
  /// to an unconditional branch.
  static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue,
                        CfgNode *TargetFalse) {
    return new (Func->allocate<InstBr>())
        InstBr(Func, Source, TargetTrue, TargetFalse);
  }
  /// Create an unconditional branch.
  static InstBr *create(Cfg *Func, CfgNode *Target) {
    return new (Func->allocate<InstBr>()) InstBr(Func, Target);
  }
  bool isUnconditional() const { return getTargetTrue() == nullptr; }
  Operand *getCondition() const {
    assert(!isUnconditional());
    return getSrc(0);
  }
  CfgNode *getTargetTrue() const { return TargetTrue; }
  CfgNode *getTargetFalse() const { return TargetFalse; }
  CfgNode *getTargetUnconditional() const {
    assert(isUnconditional());
    return getTargetFalse();
  }
  NodeList getTerminatorEdges() const override;
  bool isUnconditionalBranch() const override { return isUnconditional(); }
  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }

private:
  /// Conditional branch
  InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
  /// Unconditional branch
  InstBr(Cfg *Func, CfgNode *Target);

  CfgNode *TargetFalse; /// Doubles as unconditional branch target
  CfgNode *TargetTrue;  /// nullptr if unconditional branch
};

/// Call instruction. The call target is captured as getSrc(0), and arg I is
/// captured as getSrc(I+1).
class InstCall : public InstHighLevel {
  InstCall() = delete;
  InstCall(const InstCall &) = delete;
  InstCall &operator=(const InstCall &) = delete;

public:
  static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
                          Operand *CallTarget, bool HasTailCall,
                          bool IsTargetHelperCall = false,
                          bool IsVariadic = false) {
    /// Set HasSideEffects to true so that the call instruction can't be
    /// dead-code eliminated.
    constexpr bool HasSideEffects = true;
    constexpr InstKind Kind = Inst::Call;
    return new (Func->allocate<InstCall>())
        InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
                 IsTargetHelperCall, IsVariadic, HasSideEffects, Kind);
  }
  void addArg(Operand *Arg) { addSource(Arg); }
  Operand *getCallTarget() const { return getSrc(0); }
  Operand *getArg(SizeT I) const { return getSrc(I + 1); }
  SizeT getNumArgs() const { return getSrcSize() - 1; }
  bool isTailcall() const { return HasTailCall; }
  bool isTargetHelperCall() const { return IsTargetHelperCall; }
  bool isVariadic() const { return IsVariadic; }
  bool isMemoryWrite() const override { return true; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
  Type getReturnType() const;

protected:
  InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
           bool HasTailCall, bool IsTargetHelperCall, bool IsVariadic,
           bool HasSideEff, InstKind Kind)
      : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
        IsTargetHelperCall(IsTargetHelperCall), IsVariadic(IsVariadic) {
    HasSideEffects = HasSideEff;
    addSource(CallTarget);
  }

private:
  const bool HasTailCall;
  const bool IsTargetHelperCall;
  const bool IsVariadic;
};

/// Cast instruction (a.k.a. conversion operation).
class InstCast : public InstHighLevel {
  InstCast() = delete;
  InstCast(const InstCast &) = delete;
  InstCast &operator=(const InstCast &) = delete;

public:
  enum OpKind {
#define X(tag, str) tag,
    ICEINSTCAST_TABLE
#undef X
        _num
  };

  static const char *getCastName(OpKind Kind);

  static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
                          Operand *Source) {
    return new (Func->allocate<InstCast>())
        InstCast(Func, CastKind, Dest, Source);
  }
  OpKind getCastKind() const { return CastKind; }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }

private:
  InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);

  const OpKind CastKind;
};

/// ExtractElement instruction.
class InstExtractElement : public InstHighLevel {
  InstExtractElement() = delete;
  InstExtractElement(const InstExtractElement &) = delete;
  InstExtractElement &operator=(const InstExtractElement &) = delete;

public:
  static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
                                    Operand *Source2) {
    return new (Func->allocate<InstExtractElement>())
        InstExtractElement(Func, Dest, Source1, Source2);
  }

  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == ExtractElement;
  }

private:
  InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
                     Operand *Source2);
};

/// Floating-point comparison instruction. The source operands are captured in
/// getSrc(0) and getSrc(1).
class InstFcmp : public InstHighLevel {
  InstFcmp() = delete;
  InstFcmp(const InstFcmp &) = delete;
  InstFcmp &operator=(const InstFcmp &) = delete;

public:
  enum FCond {
#define X(tag, str) tag,
    ICEINSTFCMP_TABLE
#undef X
        _num
  };

  static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
                          Operand *Source1, Operand *Source2) {
    return new (Func->allocate<InstFcmp>())
        InstFcmp(Func, Condition, Dest, Source1, Source2);
  }
  FCond getCondition() const { return Condition; }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }

private:
  InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
           Operand *Source2);

  const FCond Condition;
};

/// Integer comparison instruction. The source operands are captured in
/// getSrc(0) and getSrc(1).
class InstIcmp : public InstHighLevel {
  InstIcmp() = delete;
  InstIcmp(const InstIcmp &) = delete;
  InstIcmp &operator=(const InstIcmp &) = delete;

public:
  enum ICond {
#define X(tag, inverse, str) tag,
    ICEINSTICMP_TABLE
#undef X
        _num
  };

  static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
                          Operand *Source1, Operand *Source2) {
    return new (Func->allocate<InstIcmp>())
        InstIcmp(Func, Condition, Dest, Source1, Source2);
  }
  ICond getCondition() const { return Condition; }
  void reverseConditionAndOperands();
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }

private:
  InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
           Operand *Source2);

  ICond Condition;
};

/// InsertElement instruction.
class InstInsertElement : public InstHighLevel {
  InstInsertElement() = delete;
  InstInsertElement(const InstInsertElement &) = delete;
  InstInsertElement &operator=(const InstInsertElement &) = delete;

public:
  static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
                                   Operand *Source2, Operand *Source3) {
    return new (Func->allocate<InstInsertElement>())
        InstInsertElement(Func, Dest, Source1, Source2, Source3);
  }

  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == InsertElement;
  }

private:
  InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
                    Operand *Source2, Operand *Source3);
};

/// An intrinsic operation, representing either a sequence of instructions,
/// or a single instruction. Availability of intrinsics is target-specific.
class InstIntrinsic : public InstHighLevel {
  InstIntrinsic() = delete;
  InstIntrinsic(const InstIntrinsic &) = delete;
  InstIntrinsic &operator=(const InstIntrinsic &) = delete;

public:
  static InstIntrinsic *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
                               const Intrinsics::IntrinsicInfo &Info) {
    return new (Func->allocate<InstIntrinsic>())
        InstIntrinsic(Func, NumArgs, Dest, Info);
  }
  void addArg(Operand *Arg) { addSource(Arg); }
  Operand *getArg(SizeT I) const { return getSrc(I); }
  SizeT getNumArgs() const { return getSrcSize(); }
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == Intrinsic;
  }

  Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
  bool isMemoryWrite() const override {
    return getIntrinsicInfo().IsMemoryWrite;
  }

private:
  InstIntrinsic(Cfg *Func, SizeT NumArgs, Variable *Dest,
                const Intrinsics::IntrinsicInfo &Info)
      : InstHighLevel(Func, Inst::Intrinsic, NumArgs, Dest), Info(Info) {}

  const Intrinsics::IntrinsicInfo Info;
};

/// Load instruction. The source address is captured in getSrc(0).
class InstLoad : public InstHighLevel {
  InstLoad() = delete;
  InstLoad(const InstLoad &) = delete;
  InstLoad &operator=(const InstLoad &) = delete;

public:
  static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
                          uint32_t Align = 1) {
    // TODO(kschimpf) Stop ignoring alignment specification.
    (void)Align;
    return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
  }
  Operand *getSourceAddress() const { return getSrc(0); }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }

private:
  InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
};

/// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
/// source operand is getSrc(I).
class InstPhi : public InstHighLevel {
  InstPhi() = delete;
  InstPhi(const InstPhi &) = delete;
  InstPhi &operator=(const InstPhi &) = delete;

public:
  static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
    return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
  }
  void addArgument(Operand *Source, CfgNode *Label);
  Operand *getOperandForTarget(CfgNode *Target) const;
  void clearOperandForTarget(CfgNode *Target);
  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
  void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
  void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
                          Liveness *Liveness);
  Inst *lower(Cfg *Func);
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }

private:
  InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
  void destroy(Cfg *Func) override { Inst::destroy(Func); }

  /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode,
  /// but the Phi instruction is created before InEdges[] is available, so it's
  /// more complicated to share the list.
  CfgVector<CfgNode *> Labels;
};

/// Ret instruction. The return value is captured in getSrc(0), but if there is
/// no return value (void-type function), then getSrcSize()==0 and
/// hasRetValue()==false.
class InstRet : public InstHighLevel {
  InstRet() = delete;
  InstRet(const InstRet &) = delete;
  InstRet &operator=(const InstRet &) = delete;

public:
  static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
    return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
  }
  bool hasRetValue() const { return getSrcSize(); }
  Operand *getRetValue() const {
    assert(hasRetValue());
    return getSrc(0);
  }
  NodeList getTerminatorEdges() const override { return NodeList(); }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }

private:
  InstRet(Cfg *Func, Operand *RetValue);
};

/// Select instruction.  The condition, true, and false operands are captured.
class InstSelect : public InstHighLevel {
  InstSelect() = delete;
  InstSelect(const InstSelect &) = delete;
  InstSelect &operator=(const InstSelect &) = delete;

public:
  static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
                            Operand *SourceTrue, Operand *SourceFalse) {
    return new (Func->allocate<InstSelect>())
        InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
  }
  Operand *getCondition() const { return getSrc(0); }
  Operand *getTrueOperand() const { return getSrc(1); }
  Operand *getFalseOperand() const { return getSrc(2); }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }

private:
  InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
             Operand *Source2);
};

/// Store instruction. The address operand is captured, along with the data
/// operand to be stored into the address.
class InstStore : public InstHighLevel {
  InstStore() = delete;
  InstStore(const InstStore &) = delete;
  InstStore &operator=(const InstStore &) = delete;

public:
  static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
                           uint32_t Align = 1) {
    // TODO(kschimpf) Stop ignoring alignment specification.
    (void)Align;
    return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
  }
  Operand *getAddr() const { return getSrc(1); }
  Operand *getData() const { return getSrc(0); }
  Variable *getRmwBeacon() const;
  void setRmwBeacon(Variable *Beacon);
  bool isMemoryWrite() const override { return true; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }

private:
  InstStore(Cfg *Func, Operand *Data, Operand *Addr);
};

/// Switch instruction. The single source operand is captured as getSrc(0).
class InstSwitch : public InstHighLevel {
  InstSwitch() = delete;
  InstSwitch(const InstSwitch &) = delete;
  InstSwitch &operator=(const InstSwitch &) = delete;

public:
  static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source,
                            CfgNode *LabelDefault) {
    return new (Func->allocate<InstSwitch>())
        InstSwitch(Func, NumCases, Source, LabelDefault);
  }
  Operand *getComparison() const { return getSrc(0); }
  CfgNode *getLabelDefault() const { return LabelDefault; }
  SizeT getNumCases() const { return NumCases; }
  uint64_t getValue(SizeT I) const {
    assert(I < NumCases);
    return Values[I];
  }
  CfgNode *getLabel(SizeT I) const {
    assert(I < NumCases);
    return Labels[I];
  }
  void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
  NodeList getTerminatorEdges() const override;
  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }

private:
  InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
  void destroy(Cfg *Func) override {
    Func->deallocateArrayOf<uint64_t>(Values);
    Func->deallocateArrayOf<CfgNode *>(Labels);
    Inst::destroy(Func);
  }

  CfgNode *LabelDefault;
  SizeT NumCases;   /// not including the default case
  uint64_t *Values; /// size is NumCases
  CfgNode **Labels; /// size is NumCases
};

/// Unreachable instruction. This is a terminator instruction with no operands.
class InstUnreachable : public InstHighLevel {
  InstUnreachable() = delete;
  InstUnreachable(const InstUnreachable &) = delete;
  InstUnreachable &operator=(const InstUnreachable &) = delete;

public:
  static InstUnreachable *create(Cfg *Func) {
    return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
  }
  NodeList getTerminatorEdges() const override { return NodeList(); }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == Unreachable;
  }

private:
  explicit InstUnreachable(Cfg *Func);
};

/// BundleLock instruction.  There are no operands. Contains an option
/// indicating whether align_to_end is specified.
class InstBundleLock : public InstHighLevel {
  InstBundleLock() = delete;
  InstBundleLock(const InstBundleLock &) = delete;
  InstBundleLock &operator=(const InstBundleLock &) = delete;

public:
  enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
  static InstBundleLock *create(Cfg *Func, Option BundleOption) {
    return new (Func->allocate<InstBundleLock>())
        InstBundleLock(Func, BundleOption);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg * /* Func */) const override {}
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  Option getOption() const { return BundleOption; }
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == BundleLock;
  }

private:
  Option BundleOption;
  InstBundleLock(Cfg *Func, Option BundleOption);
};

/// BundleUnlock instruction. There are no operands.
class InstBundleUnlock : public InstHighLevel {
  InstBundleUnlock() = delete;
  InstBundleUnlock(const InstBundleUnlock &) = delete;
  InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;

public:
  static InstBundleUnlock *create(Cfg *Func) {
    return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg * /* Func */) const override {}
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == BundleUnlock;
  }

private:
  explicit InstBundleUnlock(Cfg *Func);
};

/// FakeDef instruction. This creates a fake definition of a variable, which is
/// how we represent the case when an instruction produces multiple results.
/// This doesn't happen with high-level ICE instructions, but might with lowered
/// instructions. For example, this would be a way to represent condition flags
/// being modified by an instruction.
///
/// It's generally useful to set the optional source operand to be the dest
/// variable of the instruction that actually produces the FakeDef dest.
/// Otherwise, the original instruction could be dead-code eliminated if its
/// dest operand is unused, and therefore the FakeDef dest wouldn't be properly
/// initialized.
class InstFakeDef : public InstHighLevel {
  InstFakeDef() = delete;
  InstFakeDef(const InstFakeDef &) = delete;
  InstFakeDef &operator=(const InstFakeDef &) = delete;

public:
  static InstFakeDef *create(Cfg *Func, Variable *Dest,
                             Variable *Src = nullptr) {
    return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg * /* Func */) const override {}
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }

private:
  InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
};

/// FakeUse instruction. This creates a fake use of a variable, to keep the
/// instruction that produces that variable from being dead-code eliminated.
/// This is useful in a variety of lowering situations. The FakeUse instruction
/// has no dest, so it can itself never be dead-code eliminated.  A weight can
/// be provided to provide extra bias to the register allocator - for simplicity
/// of implementation, weight=N is handled by holding N copies of the variable
/// as source operands.
class InstFakeUse : public InstHighLevel {
  InstFakeUse() = delete;
  InstFakeUse(const InstFakeUse &) = delete;
  InstFakeUse &operator=(const InstFakeUse &) = delete;

public:
  static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
    return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
  }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg * /* Func */) const override {}
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }

private:
  InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
};

/// FakeKill instruction. This "kills" a set of variables by modeling a trivial
/// live range at this instruction for each (implicit) variable. The primary use
/// is to indicate that scratch registers are killed after a call, so that the
/// register allocator won't assign a scratch register to a variable whose live
/// range spans a call.
///
/// The FakeKill instruction also holds a pointer to the instruction that kills
/// the set of variables, so that if that linked instruction gets dead-code
/// eliminated, the FakeKill instruction will as well.
class InstFakeKill : public InstHighLevel {
  InstFakeKill() = delete;
  InstFakeKill(const InstFakeKill &) = delete;
  InstFakeKill &operator=(const InstFakeKill &) = delete;

public:
  static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
    return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
  }
  const Inst *getLinked() const { return Linked; }
  void emit(const Cfg *Func) const override;
  void emitIAS(const Cfg * /* Func */) const override {}
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == FakeKill;
  }

private:
  InstFakeKill(Cfg *Func, const Inst *Linked);

  /// This instruction is ignored if Linked->isDeleted() is true.
  const Inst *Linked;
};

/// ShuffleVector instruction. This represents a shuffle operation on vector
/// types. This instruction is not part of the PNaCl bitcode: it is generated
/// by Subzero when it matches the pattern used by pnacl-clang when compiling
/// to bitcode.
class InstShuffleVector : public InstHighLevel {
  InstShuffleVector() = delete;
  InstShuffleVector(const InstShuffleVector &) = delete;
  InstShuffleVector &operator=(const InstShuffleVector &) = delete;

public:
  static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0,
                                   Operand *Src1) {
    return new (Func->allocate<InstShuffleVector>())
        InstShuffleVector(Func, Dest, Src0, Src1);
  }

  SizeT getNumIndexes() const { return NumIndexes; }

  void addIndex(ConstantInteger32 *Index) {
    assert(CurrentIndex < NumIndexes);
    Indexes[CurrentIndex++] = Index;
  }

  ConstantInteger32 *getIndex(SizeT Pos) const {
    assert(Pos < NumIndexes);
    return Indexes[Pos];
  }

  int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); }

  bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const {
    static constexpr SizeT ExpectedNumElements = 4;
    assert(ExpectedNumElements == getNumIndexes());
    (void)ExpectedNumElements;

    return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
           getIndexValue(2) == i2 && getIndexValue(3) == i3;
  }

  bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
                  int32_t i5, int32_t i6, int32_t i7) const {
    static constexpr SizeT ExpectedNumElements = 8;
    assert(ExpectedNumElements == getNumIndexes());
    (void)ExpectedNumElements;

    return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
           getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
           getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
           getIndexValue(6) == i6 && getIndexValue(7) == i7;
  }

  bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4,
                  int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9,
                  int32_t i10, int32_t i11, int32_t i12, int32_t i13,
                  int32_t i14, int32_t i15) const {
    static constexpr SizeT ExpectedNumElements = 16;
    assert(ExpectedNumElements == getNumIndexes());
    (void)ExpectedNumElements;

    return getIndexValue(0) == i0 && getIndexValue(1) == i1 &&
           getIndexValue(2) == i2 && getIndexValue(3) == i3 &&
           getIndexValue(4) == i4 && getIndexValue(5) == i5 &&
           getIndexValue(6) == i6 && getIndexValue(7) == i7 &&
           getIndexValue(8) == i8 && getIndexValue(9) == i9 &&
           getIndexValue(10) == i10 && getIndexValue(11) == i11 &&
           getIndexValue(12) == i12 && getIndexValue(13) == i13 &&
           getIndexValue(14) == i14 && getIndexValue(15) == i15;
  }

  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == ShuffleVector;
  }

private:
  InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1);

  void destroy(Cfg *Func) override {
    Func->deallocateArrayOf<ConstantInteger32 *>(Indexes);
    Inst::destroy(Func);
  }

  ConstantInteger32 **Indexes;
  SizeT CurrentIndex = 0;
  const SizeT NumIndexes;
};

/// JumpTable instruction. This represents a jump table that will be stored in
/// the .rodata section. This is used to track and repoint the target CfgNodes
/// which may change, for example due to splitting for phi lowering.
class InstJumpTable : public InstHighLevel {
  InstJumpTable() = delete;
  InstJumpTable(const InstJumpTable &) = delete;
  InstJumpTable &operator=(const InstJumpTable &) = delete;

public:
  static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) {
    return new (Func->allocate<InstJumpTable>())
        InstJumpTable(Func, NumTargets, Default);
  }
  void addTarget(SizeT TargetIndex, CfgNode *Target) {
    assert(TargetIndex < NumTargets);
    Targets[TargetIndex] = Target;
  }
  bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
  SizeT getId() const { return Id; }
  SizeT getNumTargets() const { return NumTargets; }
  CfgNode *getTarget(SizeT I) const {
    assert(I < NumTargets);
    return Targets[I];
  }
  bool isMemoryWrite() const override { return false; }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) {
    return Instr->getKind() == JumpTable;
  }
  // Creates a JumpTableData struct (used for ELF emission) that represents this
  // InstJumpTable.
  JumpTableData toJumpTableData(Assembler *Asm) const;

  // InstJumpTable is just a placeholder for the switch targets, and it does not
  // need to emit any code, so we redefine emit and emitIAS to do nothing.
  void emit(const Cfg *) const override {}
  void emitIAS(const Cfg * /* Func */) const override {}

  const std::string getName() const {
    assert(Name.hasStdString());
    return Name.toString();
  }

  std::string getSectionName() const {
    return JumpTableData::createSectionName(FuncName);
  }

private:
  InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default);
  void destroy(Cfg *Func) override {
    Func->deallocateArrayOf<CfgNode *>(Targets);
    Inst::destroy(Func);
  }

  const SizeT Id;
  const SizeT NumTargets;
  CfgNode **Targets;
  GlobalString Name; // This JumpTable's name in the output.
  GlobalString FuncName;
};

/// This instruction inserts an unconditional breakpoint.
///
/// On x86, this assembles into an INT 3 instruction.
///
/// This instruction is primarily meant for debugging the code generator.
class InstBreakpoint : public InstHighLevel {
public:
  InstBreakpoint() = delete;
  InstBreakpoint(const InstBreakpoint &) = delete;
  InstBreakpoint &operator=(const InstBreakpoint &) = delete;

  explicit InstBreakpoint(Cfg *Func);
  bool isMemoryWrite() const override { return false; }

public:
  static InstBreakpoint *create(Cfg *Func) {
    return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
  }

  static bool classof(const Inst *Instr) {
    return Instr->getKind() == Breakpoint;
  }
};

/// The Target instruction is the base class for all target-specific
/// instructions.
class InstTarget : public Inst {
  InstTarget() = delete;
  InstTarget(const InstTarget &) = delete;
  InstTarget &operator=(const InstTarget &) = delete;

public:
  uint32_t getEmitInstCount() const override { return 1; }
  bool isMemoryWrite() const override {
    return true; // conservative answer
  }
  void dump(const Cfg *Func) const override;
  static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }

protected:
  InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
      : Inst(Func, Kind, MaxSrcs, Dest) {
    assert(Kind >= Target);
    assert(Kind <= Target_Max);
  }
};

bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);

} // end of namespace Ice

#ifdef PNACL_LLVM
namespace llvm {

/// Override the default ilist traits so that Inst's private ctor and deleted
/// dtor aren't invoked.
template <>
struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> {
  Ice::Inst *createSentinel() const {
    return static_cast<Ice::Inst *>(&Sentinel);
  }
  static void destroySentinel(Ice::Inst *) {}
  Ice::Inst *provideInitialHead() const { return createSentinel(); }
  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
  static void noteHead(Ice::Inst *, Ice::Inst *) {}
  void deleteNode(Ice::Inst *) {}

private:
  mutable ilist_half_node<Ice::Inst> Sentinel;
};

} // end of namespace llvm
#endif // PNACL_LLVM

namespace Ice {

inline InstList::iterator instToIterator(Inst *Instr) {
#ifdef PNACL_LLVM
  return Instr;
#else  // !PNACL_LLVM
  return Instr->getIterator();
#endif // !PNACL_LLVM
}

inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; }

inline const Inst *iteratorToInst(InstList::const_iterator Iter) {
  return &*Iter;
}

inline InstList::iterator
reverseToForwardIterator(InstList::reverse_iterator RI) {
#ifdef PNACL_LLVM
  return RI.base();
#else  // !PNACL_LLVM
  return ++RI.getReverse();
#endif // !PNACL_LLVM
}

} // end of namespace Ice

#endif // SUBZERO_SRC_ICEINST_H
