//===-- Instruction.cpp - Implement the Instruction class -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the Instruction class for the IR library.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Instruction.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;

// FIXME: Flag used for an ablation performance test, Issue #147390. Placing it
// here because referencing IR should be feasible from anywhere. Will be
// removed after the ablation test.
cl::opt<bool> ProfcheckDisableMetadataFixes(
    "profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false),
    cl::desc(
        "Disable metadata propagation fixes discovered through Issue #147390"));

InsertPosition::InsertPosition(Instruction *InsertBefore)
    : InsertAt(InsertBefore ? InsertBefore->getIterator()
                            : InstListType::iterator()) {}
InsertPosition::InsertPosition(BasicBlock *InsertAtEnd)
    : InsertAt(InsertAtEnd ? InsertAtEnd->end() : InstListType::iterator()) {}

Instruction::Instruction(Type *ty, unsigned it, AllocInfo AllocInfo,
                         InsertPosition InsertBefore)
    : User(ty, Value::InstructionVal + it, AllocInfo) {
  // When called with an iterator, there must be a block to insert into.
  if (InstListType::iterator InsertIt = InsertBefore; InsertIt.isValid()) {
    BasicBlock *BB = InsertIt.getNodeParent();
    assert(BB && "Instruction to insert before is not in a basic block!");
    insertInto(BB, InsertBefore);
  }
}

Instruction::~Instruction() {
  assert(!getParent() && "Instruction still linked in the program!");

  // Replace any extant metadata uses of this instruction with poison to
  // preserve debug info accuracy. Some alternatives include:
  // - Treat Instruction like any other Value, and point its extant metadata
  //   uses to an empty ValueAsMetadata node. This makes extant dbg.value uses
  //   trivially dead (i.e. fair game for deletion in many passes), leading to
  //   stale dbg.values being in effect for too long.
  // - Call salvageDebugInfoOrMarkUndef. Not needed to make instruction removal
  //   correct. OTOH results in wasted work in some common cases (e.g. when all
  //   instructions in a BasicBlock are deleted).
  if (isUsedByMetadata())
    ValueAsMetadata::handleRAUW(this, PoisonValue::get(getType()));

  // Explicitly remove DIAssignID metadata to clear up ID -> Instruction(s)
  // mapping in LLVMContext.
  setMetadata(LLVMContext::MD_DIAssignID, nullptr);
}

const Module *Instruction::getModule() const {
  return getParent()->getModule();
}

const Function *Instruction::getFunction() const {
  return getParent()->getParent();
}

const DataLayout &Instruction::getDataLayout() const {
  return getModule()->getDataLayout();
}

void Instruction::removeFromParent() {
  // Perform any debug-info maintenence required.
  handleMarkerRemoval();

  getParent()->getInstList().remove(getIterator());
}

void Instruction::handleMarkerRemoval() {
  if (!DebugMarker)
    return;

  DebugMarker->removeMarker();
}

BasicBlock::iterator Instruction::eraseFromParent() {
  handleMarkerRemoval();
  return getParent()->getInstList().erase(getIterator());
}

void Instruction::insertBefore(Instruction *InsertPos) {
  insertBefore(InsertPos->getIterator());
}

/// Insert an unlinked instruction into a basic block immediately before the
/// specified instruction.
void Instruction::insertBefore(BasicBlock::iterator InsertPos) {
  insertBefore(*InsertPos->getParent(), InsertPos);
}

/// Insert an unlinked instruction into a basic block immediately after the
/// specified instruction.
void Instruction::insertAfter(Instruction *InsertPos) {
  BasicBlock *DestParent = InsertPos->getParent();

  DestParent->getInstList().insertAfter(InsertPos->getIterator(), this);
}

void Instruction::insertAfter(BasicBlock::iterator InsertPos) {
  BasicBlock *DestParent = InsertPos->getParent();

  DestParent->getInstList().insertAfter(InsertPos, this);
}

BasicBlock::iterator Instruction::insertInto(BasicBlock *ParentBB,
                                             BasicBlock::iterator It) {
  assert(getParent() == nullptr && "Expected detached instruction");
  assert((It == ParentBB->end() || It->getParent() == ParentBB) &&
         "It not in ParentBB");
  insertBefore(*ParentBB, It);
  return getIterator();
}

void Instruction::insertBefore(BasicBlock &BB,
                               InstListType::iterator InsertPos) {
  assert(!DebugMarker);

  BB.getInstList().insert(InsertPos, this);

  // We've inserted "this": if InsertAtHead is set then it comes before any
  // DbgVariableRecords attached to InsertPos. But if it's not set, then any
  // DbgRecords should now come before "this".
  bool InsertAtHead = InsertPos.getHeadBit();
  if (!InsertAtHead) {
    DbgMarker *SrcMarker = BB.getMarker(InsertPos);
    if (SrcMarker && !SrcMarker->empty()) {
      // If this assertion fires, the calling code is about to insert a PHI
      // after debug-records, which would form a sequence like:
      //     %0 = PHI
      //     #dbg_value
      //     %1 = PHI
      // Which is de-normalised and undesired -- hence the assertion. To avoid
      // this, you must insert at that position using an iterator, and it must
      // be aquired by calling getFirstNonPHIIt / begin or similar methods on
      // the block. This will signal to this behind-the-scenes debug-info
      // maintenence code that you intend the PHI to be ahead of everything,
      // including any debug-info.
      assert(!isa<PHINode>(this) && "Inserting PHI after debug-records!");
      adoptDbgRecords(&BB, InsertPos, false);
    }
  }

  // If we're inserting a terminator, check if we need to flush out
  // TrailingDbgRecords. Inserting instructions at the end of an incomplete
  // block is handled by the code block above.
  if (isTerminator())
    getParent()->flushTerminatorDbgRecords();
}

/// Unlink this instruction from its current basic block and insert it into the
/// basic block that MovePos lives in, right before MovePos.
void Instruction::moveBefore(Instruction *MovePos) {
  moveBeforeImpl(*MovePos->getParent(), MovePos->getIterator(), false);
}

void Instruction::moveBefore(BasicBlock::iterator MovePos) {
  moveBeforeImpl(*MovePos->getParent(), MovePos, false);
}

void Instruction::moveBeforePreserving(Instruction *MovePos) {
  moveBeforeImpl(*MovePos->getParent(), MovePos->getIterator(), true);
}

void Instruction::moveBeforePreserving(BasicBlock::iterator MovePos) {
  moveBeforeImpl(*MovePos->getParent(), MovePos, true);
}

void Instruction::moveAfter(Instruction *MovePos) {
  auto NextIt = std::next(MovePos->getIterator());
  // We want this instruction to be moved to after NextIt in the instruction
  // list, but before NextIt's debug value range.
  NextIt.setHeadBit(true);
  moveBeforeImpl(*MovePos->getParent(), NextIt, false);
}

void Instruction::moveAfter(InstListType::iterator MovePos) {
  // We want this instruction to be moved to after NextIt in the instruction
  // list, but before NextIt's debug value range.
  MovePos.setHeadBit(true);
  moveBeforeImpl(*MovePos->getParent(), MovePos, false);
}

void Instruction::moveAfterPreserving(Instruction *MovePos) {
  auto NextIt = std::next(MovePos->getIterator());
  // We want this instruction and its debug range to be moved to after NextIt
  // in the instruction list, but before NextIt's debug value range.
  NextIt.setHeadBit(true);
  moveBeforeImpl(*MovePos->getParent(), NextIt, true);
}

void Instruction::moveBefore(BasicBlock &BB, InstListType::iterator I) {
  moveBeforeImpl(BB, I, false);
}

void Instruction::moveBeforePreserving(BasicBlock &BB,
                                       InstListType::iterator I) {
  moveBeforeImpl(BB, I, true);
}

void Instruction::moveBeforeImpl(BasicBlock &BB, InstListType::iterator I,
                              bool Preserve) {
  assert(I == BB.end() || I->getParent() == &BB);
  bool InsertAtHead = I.getHeadBit();

  // If we've been given the "Preserve" flag, then just move the DbgRecords with
  // the instruction, no more special handling needed.
  if (DebugMarker && !Preserve) {
    if (I != this->getIterator() || InsertAtHead) {
      // "this" is definitely moving in the list, or it's moving ahead of its
      // attached DbgVariableRecords. Detach any existing DbgRecords.
      handleMarkerRemoval();
    }
  }

  // Move this single instruction. Use the list splice method directly, not
  // the block splicer, which will do more debug-info things.
  BB.getInstList().splice(I, getParent()->getInstList(), getIterator());

  if (!Preserve) {
    DbgMarker *NextMarker = getParent()->getNextMarker(this);

    // If we're inserting at point I, and not in front of the DbgRecords
    // attached there, then we should absorb the DbgRecords attached to I.
    if (!InsertAtHead && NextMarker && !NextMarker->empty()) {
      adoptDbgRecords(&BB, I, false);
    }
  }

  if (isTerminator())
    getParent()->flushTerminatorDbgRecords();
}

iterator_range<DbgRecord::self_iterator> Instruction::cloneDebugInfoFrom(
    const Instruction *From, std::optional<DbgRecord::self_iterator> FromHere,
    bool InsertAtHead) {
  if (!From->DebugMarker)
    return DbgMarker::getEmptyDbgRecordRange();

  if (!DebugMarker)
    getParent()->createMarker(this);

  return DebugMarker->cloneDebugInfoFrom(From->DebugMarker, FromHere,
                                         InsertAtHead);
}

std::optional<DbgRecord::self_iterator>
Instruction::getDbgReinsertionPosition() {
  // Is there a marker on the next instruction?
  DbgMarker *NextMarker = getParent()->getNextMarker(this);
  if (!NextMarker)
    return std::nullopt;

  // Are there any DbgRecords in the next marker?
  if (NextMarker->StoredDbgRecords.empty())
    return std::nullopt;

  return NextMarker->StoredDbgRecords.begin();
}

bool Instruction::hasDbgRecords() const { return !getDbgRecordRange().empty(); }

void Instruction::adoptDbgRecords(BasicBlock *BB, BasicBlock::iterator It,
                                  bool InsertAtHead) {
  DbgMarker *SrcMarker = BB->getMarker(It);
  auto ReleaseTrailingDbgRecords = [BB, It, SrcMarker]() {
    if (BB->end() == It) {
      SrcMarker->eraseFromParent();
      BB->deleteTrailingDbgRecords();
    }
  };

  if (!SrcMarker || SrcMarker->StoredDbgRecords.empty()) {
    ReleaseTrailingDbgRecords();
    return;
  }

  // If we have DbgMarkers attached to this instruction, we have to honour the
  // ordering of DbgRecords between this and the other marker. Fall back to just
  // absorbing from the source.
  if (DebugMarker || It == BB->end()) {
    // Ensure we _do_ have a marker.
    getParent()->createMarker(this);
    DebugMarker->absorbDebugValues(*SrcMarker, InsertAtHead);

    // Having transferred everything out of SrcMarker, we _could_ clean it up
    // and free the marker now. However, that's a lot of heap-accounting for a
    // small amount of memory with a good chance of re-use. Leave it for the
    // moment. It will be released when the Instruction is freed in the worst
    // case.
    // However: if we transferred from a trailing marker off the end of the
    // block, it's important to not leave the empty marker trailing. It will
    // give a misleading impression that some debug records have been left
    // trailing.
    ReleaseTrailingDbgRecords();
  } else {
    // Optimisation: we're transferring all the DbgRecords from the source
    // marker onto this empty location: just adopt the other instructions
    // marker.
    DebugMarker = SrcMarker;
    DebugMarker->MarkedInstr = this;
    It->DebugMarker = nullptr;
  }
}

void Instruction::dropDbgRecords() {
  if (DebugMarker)
    DebugMarker->dropDbgRecords();
}

void Instruction::dropOneDbgRecord(DbgRecord *DVR) {
  DebugMarker->dropOneDbgRecord(DVR);
}

bool Instruction::comesBefore(const Instruction *Other) const {
  assert(getParent() && Other->getParent() &&
         "instructions without BB parents have no order");
  assert(getParent() == Other->getParent() &&
         "cross-BB instruction order comparison");
  if (!getParent()->isInstrOrderValid())
    const_cast<BasicBlock *>(getParent())->renumberInstructions();
  return Order < Other->Order;
}

std::optional<BasicBlock::iterator> Instruction::getInsertionPointAfterDef() {
  assert(!getType()->isVoidTy() && "Instruction must define result");
  BasicBlock *InsertBB;
  BasicBlock::iterator InsertPt;
  if (auto *PN = dyn_cast<PHINode>(this)) {
    InsertBB = PN->getParent();
    InsertPt = InsertBB->getFirstInsertionPt();
  } else if (auto *II = dyn_cast<InvokeInst>(this)) {
    InsertBB = II->getNormalDest();
    InsertPt = InsertBB->getFirstInsertionPt();
  } else if (isa<CallBrInst>(this)) {
    // Def is available in multiple successors, there's no single dominating
    // insertion point.
    return std::nullopt;
  } else {
    assert(!isTerminator() && "Only invoke/callbr terminators return value");
    InsertBB = getParent();
    InsertPt = std::next(getIterator());
    // Any instruction inserted immediately after "this" will come before any
    // debug-info records take effect -- thus, set the head bit indicating that
    // to debug-info-transfer code.
    InsertPt.setHeadBit(true);
  }

  // catchswitch blocks don't have any legal insertion point (because they
  // are both an exception pad and a terminator).
  if (InsertPt == InsertBB->end())
    return std::nullopt;
  return InsertPt;
}

bool Instruction::isOnlyUserOfAnyOperand() {
  return any_of(operands(), [](const Value *V) { return V->hasOneUser(); });
}

void Instruction::setHasNoUnsignedWrap(bool b) {
  if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this))
    Inst->setHasNoUnsignedWrap(b);
  else
    cast<TruncInst>(this)->setHasNoUnsignedWrap(b);
}

void Instruction::setHasNoSignedWrap(bool b) {
  if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this))
    Inst->setHasNoSignedWrap(b);
  else
    cast<TruncInst>(this)->setHasNoSignedWrap(b);
}

void Instruction::setIsExact(bool b) {
  cast<PossiblyExactOperator>(this)->setIsExact(b);
}

void Instruction::setNonNeg(bool b) {
  assert(isa<PossiblyNonNegInst>(this) && "Must be zext/uitofp");
  SubclassOptionalData = (SubclassOptionalData & ~PossiblyNonNegInst::NonNeg) |
                         (b * PossiblyNonNegInst::NonNeg);
}

bool Instruction::hasNoUnsignedWrap() const {
  if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this))
    return Inst->hasNoUnsignedWrap();

  return cast<TruncInst>(this)->hasNoUnsignedWrap();
}

bool Instruction::hasNoSignedWrap() const {
  if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this))
    return Inst->hasNoSignedWrap();

  return cast<TruncInst>(this)->hasNoSignedWrap();
}

bool Instruction::hasNonNeg() const {
  assert(isa<PossiblyNonNegInst>(this) && "Must be zext/uitofp");
  return (SubclassOptionalData & PossiblyNonNegInst::NonNeg) != 0;
}

bool Instruction::hasPoisonGeneratingFlags() const {
  return cast<Operator>(this)->hasPoisonGeneratingFlags();
}

void Instruction::dropPoisonGeneratingFlags() {
  switch (getOpcode()) {
  case Instruction::Add:
  case Instruction::Sub:
  case Instruction::Mul:
  case Instruction::Shl:
    cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(false);
    cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(false);
    break;

  case Instruction::UDiv:
  case Instruction::SDiv:
  case Instruction::AShr:
  case Instruction::LShr:
    cast<PossiblyExactOperator>(this)->setIsExact(false);
    break;

  case Instruction::Or:
    cast<PossiblyDisjointInst>(this)->setIsDisjoint(false);
    break;

  case Instruction::GetElementPtr:
    cast<GetElementPtrInst>(this)->setNoWrapFlags(GEPNoWrapFlags::none());
    break;

  case Instruction::UIToFP:
  case Instruction::ZExt:
    setNonNeg(false);
    break;

  case Instruction::Trunc:
    cast<TruncInst>(this)->setHasNoUnsignedWrap(false);
    cast<TruncInst>(this)->setHasNoSignedWrap(false);
    break;

  case Instruction::ICmp:
    cast<ICmpInst>(this)->setSameSign(false);
    break;
  }

  if (isa<FPMathOperator>(this)) {
    setHasNoNaNs(false);
    setHasNoInfs(false);
  }

  assert(!hasPoisonGeneratingFlags() && "must be kept in sync");
}

bool Instruction::hasPoisonGeneratingMetadata() const {
  return any_of(Metadata::PoisonGeneratingIDs,
                [this](unsigned ID) { return hasMetadata(ID); });
}

bool Instruction::hasNonDebugLocLoopMetadata() const {
  // If there is no loop metadata at all, we also don't have
  // non-debug loop metadata, obviously.
  if (!hasMetadata(LLVMContext::MD_loop))
    return false;

  // If we do have loop metadata, retrieve it.
  MDNode *LoopMD = getMetadata(LLVMContext::MD_loop);

  // Check if the existing operands are debug locations. This loop
  // should terminate after at most three iterations. Skip
  // the first item because it is a self-reference.
  for (const MDOperand &Op : llvm::drop_begin(LoopMD->operands())) {
    // check for debug location type by attempting a cast.
    if (!isa<DILocation>(Op)) {
      return true;
    }
  }

  // If we get here, then all we have is debug locations in the loop metadata.
  return false;
}

void Instruction::dropPoisonGeneratingMetadata() {
  for (unsigned ID : Metadata::PoisonGeneratingIDs)
    eraseMetadata(ID);
}

bool Instruction::hasPoisonGeneratingReturnAttributes() const {
  if (const auto *CB = dyn_cast<CallBase>(this)) {
    AttributeSet RetAttrs = CB->getAttributes().getRetAttrs();
    return RetAttrs.hasAttribute(Attribute::Range) ||
           RetAttrs.hasAttribute(Attribute::Alignment) ||
           RetAttrs.hasAttribute(Attribute::NonNull);
  }
  return false;
}

void Instruction::dropPoisonGeneratingReturnAttributes() {
  if (auto *CB = dyn_cast<CallBase>(this)) {
    AttributeMask AM;
    AM.addAttribute(Attribute::Range);
    AM.addAttribute(Attribute::Alignment);
    AM.addAttribute(Attribute::NonNull);
    CB->removeRetAttrs(AM);
  }
  assert(!hasPoisonGeneratingReturnAttributes() && "must be kept in sync");
}

void Instruction::dropUBImplyingAttrsAndUnknownMetadata(
    ArrayRef<unsigned> KnownIDs) {
  dropUnknownNonDebugMetadata(KnownIDs);
  auto *CB = dyn_cast<CallBase>(this);
  if (!CB)
    return;
  // For call instructions, we also need to drop parameter and return attributes
  // that can cause UB if the call is moved to a location where the attribute is
  // not valid.
  AttributeList AL = CB->getAttributes();
  if (AL.isEmpty())
    return;
  AttributeMask UBImplyingAttributes =
      AttributeFuncs::getUBImplyingAttributes();
  for (unsigned ArgNo = 0; ArgNo < CB->arg_size(); ArgNo++)
    CB->removeParamAttrs(ArgNo, UBImplyingAttributes);
  CB->removeRetAttrs(UBImplyingAttributes);
}

void Instruction::dropUBImplyingAttrsAndMetadata(ArrayRef<unsigned> Keep) {
  // !annotation and !prof metadata does not impact semantics.
  // !range, !nonnull and !align produce poison, so they are safe to speculate.
  // !noundef and various AA metadata must be dropped, as it generally produces
  // immediate undefined behavior.
  static const unsigned KnownIDs[] = {
      LLVMContext::MD_annotation, LLVMContext::MD_range,
      LLVMContext::MD_nonnull, LLVMContext::MD_align, LLVMContext::MD_prof};
  SmallVector<unsigned> KeepIDs;
  KeepIDs.reserve(Keep.size() + std::size(KnownIDs));
  append_range(KeepIDs, (!ProfcheckDisableMetadataFixes ? KnownIDs
                                                        : drop_end(KnownIDs)));
  append_range(KeepIDs, Keep);
  dropUBImplyingAttrsAndUnknownMetadata(KeepIDs);
}

bool Instruction::hasUBImplyingAttrs() const {
  auto *CB = dyn_cast<CallBase>(this);
  if (!CB)
    return false;
  // For call instructions, we also need to check parameter and return
  // attributes that can cause UB.
  for (unsigned ArgNo = 0; ArgNo < CB->arg_size(); ArgNo++)
    if (CB->isPassingUndefUB(ArgNo))
      return true;
  return CB->hasRetAttr(Attribute::NoUndef) ||
         CB->hasRetAttr(Attribute::Dereferenceable) ||
         CB->hasRetAttr(Attribute::DereferenceableOrNull);
}

bool Instruction::isExact() const {
  return cast<PossiblyExactOperator>(this)->isExact();
}

void Instruction::setFast(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setFast(B);
}

void Instruction::setHasAllowReassoc(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasAllowReassoc(B);
}

void Instruction::setHasNoNaNs(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasNoNaNs(B);
}

void Instruction::setHasNoInfs(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasNoInfs(B);
}

void Instruction::setHasNoSignedZeros(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasNoSignedZeros(B);
}

void Instruction::setHasAllowReciprocal(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasAllowReciprocal(B);
}

void Instruction::setHasAllowContract(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasAllowContract(B);
}

void Instruction::setHasApproxFunc(bool B) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setHasApproxFunc(B);
}

void Instruction::setFastMathFlags(FastMathFlags FMF) {
  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");
  cast<FPMathOperator>(this)->setFastMathFlags(FMF);
}

void Instruction::copyFastMathFlags(FastMathFlags FMF) {
  assert(isa<FPMathOperator>(this) && "copying fast-math flag on invalid op");
  cast<FPMathOperator>(this)->copyFastMathFlags(FMF);
}

bool Instruction::isFast() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->isFast();
}

bool Instruction::hasAllowReassoc() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasAllowReassoc();
}

bool Instruction::hasNoNaNs() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasNoNaNs();
}

bool Instruction::hasNoInfs() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasNoInfs();
}

bool Instruction::hasNoSignedZeros() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasNoSignedZeros();
}

bool Instruction::hasAllowReciprocal() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasAllowReciprocal();
}

bool Instruction::hasAllowContract() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasAllowContract();
}

bool Instruction::hasApproxFunc() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->hasApproxFunc();
}

FastMathFlags Instruction::getFastMathFlags() const {
  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
  return cast<FPMathOperator>(this)->getFastMathFlags();
}

void Instruction::copyFastMathFlags(const Instruction *I) {
  copyFastMathFlags(I->getFastMathFlags());
}

void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) {
  // Copy the wrapping flags.
  if (IncludeWrapFlags && isa<OverflowingBinaryOperator>(this)) {
    if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
      setHasNoSignedWrap(OB->hasNoSignedWrap());
      setHasNoUnsignedWrap(OB->hasNoUnsignedWrap());
    }
  }

  if (auto *TI = dyn_cast<TruncInst>(V)) {
    if (isa<TruncInst>(this)) {
      setHasNoSignedWrap(TI->hasNoSignedWrap());
      setHasNoUnsignedWrap(TI->hasNoUnsignedWrap());
    }
  }

  // Copy the exact flag.
  if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
    if (isa<PossiblyExactOperator>(this))
      setIsExact(PE->isExact());

  if (auto *SrcPD = dyn_cast<PossiblyDisjointInst>(V))
    if (auto *DestPD = dyn_cast<PossiblyDisjointInst>(this))
      DestPD->setIsDisjoint(SrcPD->isDisjoint());

  // Copy the fast-math flags.
  if (auto *FP = dyn_cast<FPMathOperator>(V))
    if (isa<FPMathOperator>(this))
      copyFastMathFlags(FP->getFastMathFlags());

  if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V))
    if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this))
      DestGEP->setNoWrapFlags(SrcGEP->getNoWrapFlags() |
                              DestGEP->getNoWrapFlags());

  if (auto *NNI = dyn_cast<PossiblyNonNegInst>(V))
    if (isa<PossiblyNonNegInst>(this))
      setNonNeg(NNI->hasNonNeg());

  if (auto *SrcICmp = dyn_cast<ICmpInst>(V))
    if (auto *DestICmp = dyn_cast<ICmpInst>(this))
      DestICmp->setSameSign(SrcICmp->hasSameSign());
}

void Instruction::andIRFlags(const Value *V) {
  if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
    if (isa<OverflowingBinaryOperator>(this)) {
      setHasNoSignedWrap(hasNoSignedWrap() && OB->hasNoSignedWrap());
      setHasNoUnsignedWrap(hasNoUnsignedWrap() && OB->hasNoUnsignedWrap());
    }
  }

  if (auto *TI = dyn_cast<TruncInst>(V)) {
    if (isa<TruncInst>(this)) {
      setHasNoSignedWrap(hasNoSignedWrap() && TI->hasNoSignedWrap());
      setHasNoUnsignedWrap(hasNoUnsignedWrap() && TI->hasNoUnsignedWrap());
    }
  }

  if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
    if (isa<PossiblyExactOperator>(this))
      setIsExact(isExact() && PE->isExact());

  if (auto *SrcPD = dyn_cast<PossiblyDisjointInst>(V))
    if (auto *DestPD = dyn_cast<PossiblyDisjointInst>(this))
      DestPD->setIsDisjoint(DestPD->isDisjoint() && SrcPD->isDisjoint());

  if (auto *FP = dyn_cast<FPMathOperator>(V)) {
    if (isa<FPMathOperator>(this)) {
      FastMathFlags FM = getFastMathFlags();
      FM &= FP->getFastMathFlags();
      copyFastMathFlags(FM);
    }
  }

  if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V))
    if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this))
      DestGEP->setNoWrapFlags(SrcGEP->getNoWrapFlags() &
                              DestGEP->getNoWrapFlags());

  if (auto *NNI = dyn_cast<PossiblyNonNegInst>(V))
    if (isa<PossiblyNonNegInst>(this))
      setNonNeg(hasNonNeg() && NNI->hasNonNeg());

  if (auto *SrcICmp = dyn_cast<ICmpInst>(V))
    if (auto *DestICmp = dyn_cast<ICmpInst>(this))
      DestICmp->setSameSign(DestICmp->hasSameSign() && SrcICmp->hasSameSign());
}

const char *Instruction::getOpcodeName(unsigned OpCode) {
  switch (OpCode) {
  // Terminators
  case Ret:    return "ret";
  case Br:     return "br";
  case Switch: return "switch";
  case IndirectBr: return "indirectbr";
  case Invoke: return "invoke";
  case Resume: return "resume";
  case Unreachable: return "unreachable";
  case CleanupRet: return "cleanupret";
  case CatchRet: return "catchret";
  case CatchPad: return "catchpad";
  case CatchSwitch: return "catchswitch";
  case CallBr: return "callbr";

  // Standard unary operators...
  case FNeg: return "fneg";

  // Standard binary operators...
  case Add: return "add";
  case FAdd: return "fadd";
  case Sub: return "sub";
  case FSub: return "fsub";
  case Mul: return "mul";
  case FMul: return "fmul";
  case UDiv: return "udiv";
  case SDiv: return "sdiv";
  case FDiv: return "fdiv";
  case URem: return "urem";
  case SRem: return "srem";
  case FRem: return "frem";

  // Logical operators...
  case And: return "and";
  case Or : return "or";
  case Xor: return "xor";

  // Memory instructions...
  case Alloca:        return "alloca";
  case Load:          return "load";
  case Store:         return "store";
  case AtomicCmpXchg: return "cmpxchg";
  case AtomicRMW:     return "atomicrmw";
  case Fence:         return "fence";
  case GetElementPtr: return "getelementptr";

  // Convert instructions...
  case Trunc:         return "trunc";
  case ZExt:          return "zext";
  case SExt:          return "sext";
  case FPTrunc:       return "fptrunc";
  case FPExt:         return "fpext";
  case FPToUI:        return "fptoui";
  case FPToSI:        return "fptosi";
  case UIToFP:        return "uitofp";
  case SIToFP:        return "sitofp";
  case IntToPtr:      return "inttoptr";
  case PtrToAddr:     return "ptrtoaddr";
  case PtrToInt:      return "ptrtoint";
  case BitCast:       return "bitcast";
  case AddrSpaceCast: return "addrspacecast";

  // Other instructions...
  case ICmp:           return "icmp";
  case FCmp:           return "fcmp";
  case PHI:            return "phi";
  case Select:         return "select";
  case Call:           return "call";
  case Shl:            return "shl";
  case LShr:           return "lshr";
  case AShr:           return "ashr";
  case VAArg:          return "va_arg";
  case ExtractElement: return "extractelement";
  case InsertElement:  return "insertelement";
  case ShuffleVector:  return "shufflevector";
  case ExtractValue:   return "extractvalue";
  case InsertValue:    return "insertvalue";
  case LandingPad:     return "landingpad";
  case CleanupPad:     return "cleanuppad";
  case Freeze:         return "freeze";

  default: return "<Invalid operator> ";
  }
}

/// This must be kept in sync with FunctionComparator::cmpOperations in
/// lib/Transforms/IPO/MergeFunctions.cpp.
bool Instruction::hasSameSpecialState(const Instruction *I2,
                                      bool IgnoreAlignment,
                                      bool IntersectAttrs) const {
  auto I1 = this;
  assert(I1->getOpcode() == I2->getOpcode() &&
         "Can not compare special state of different instructions");

  auto CheckAttrsSame = [IntersectAttrs](const CallBase *CB0,
                                         const CallBase *CB1) {
    return IntersectAttrs
               ? CB0->getAttributes()
                     .intersectWith(CB0->getContext(), CB1->getAttributes())
                     .has_value()
               : CB0->getAttributes() == CB1->getAttributes();
  };

  if (const AllocaInst *AI = dyn_cast<AllocaInst>(I1))
    return AI->getAllocatedType() == cast<AllocaInst>(I2)->getAllocatedType() &&
           (AI->getAlign() == cast<AllocaInst>(I2)->getAlign() ||
            IgnoreAlignment);
  if (const LoadInst *LI = dyn_cast<LoadInst>(I1))
    return LI->isVolatile() == cast<LoadInst>(I2)->isVolatile() &&
           (LI->getAlign() == cast<LoadInst>(I2)->getAlign() ||
            IgnoreAlignment) &&
           LI->getOrdering() == cast<LoadInst>(I2)->getOrdering() &&
           LI->getSyncScopeID() == cast<LoadInst>(I2)->getSyncScopeID();
  if (const StoreInst *SI = dyn_cast<StoreInst>(I1))
    return SI->isVolatile() == cast<StoreInst>(I2)->isVolatile() &&
           (SI->getAlign() == cast<StoreInst>(I2)->getAlign() ||
            IgnoreAlignment) &&
           SI->getOrdering() == cast<StoreInst>(I2)->getOrdering() &&
           SI->getSyncScopeID() == cast<StoreInst>(I2)->getSyncScopeID();
  if (const CmpInst *CI = dyn_cast<CmpInst>(I1))
    return CI->getPredicate() == cast<CmpInst>(I2)->getPredicate();
  if (const CallInst *CI = dyn_cast<CallInst>(I1))
    return CI->isTailCall() == cast<CallInst>(I2)->isTailCall() &&
           CI->getCallingConv() == cast<CallInst>(I2)->getCallingConv() &&
           CheckAttrsSame(CI, cast<CallInst>(I2)) &&
           CI->hasIdenticalOperandBundleSchema(*cast<CallInst>(I2));
  if (const InvokeInst *CI = dyn_cast<InvokeInst>(I1))
    return CI->getCallingConv() == cast<InvokeInst>(I2)->getCallingConv() &&
           CheckAttrsSame(CI, cast<InvokeInst>(I2)) &&
           CI->hasIdenticalOperandBundleSchema(*cast<InvokeInst>(I2));
  if (const CallBrInst *CI = dyn_cast<CallBrInst>(I1))
    return CI->getCallingConv() == cast<CallBrInst>(I2)->getCallingConv() &&
           CheckAttrsSame(CI, cast<CallBrInst>(I2)) &&
           CI->hasIdenticalOperandBundleSchema(*cast<CallBrInst>(I2));
  if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1))
    return IVI->getIndices() == cast<InsertValueInst>(I2)->getIndices();
  if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1))
    return EVI->getIndices() == cast<ExtractValueInst>(I2)->getIndices();
  if (const FenceInst *FI = dyn_cast<FenceInst>(I1))
    return FI->getOrdering() == cast<FenceInst>(I2)->getOrdering() &&
           FI->getSyncScopeID() == cast<FenceInst>(I2)->getSyncScopeID();
  if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I1))
    return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I2)->isVolatile() &&
           CXI->isWeak() == cast<AtomicCmpXchgInst>(I2)->isWeak() &&
           CXI->getSuccessOrdering() ==
               cast<AtomicCmpXchgInst>(I2)->getSuccessOrdering() &&
           CXI->getFailureOrdering() ==
               cast<AtomicCmpXchgInst>(I2)->getFailureOrdering() &&
           CXI->getSyncScopeID() ==
               cast<AtomicCmpXchgInst>(I2)->getSyncScopeID();
  if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I1))
    return RMWI->getOperation() == cast<AtomicRMWInst>(I2)->getOperation() &&
           RMWI->isVolatile() == cast<AtomicRMWInst>(I2)->isVolatile() &&
           RMWI->getOrdering() == cast<AtomicRMWInst>(I2)->getOrdering() &&
           RMWI->getSyncScopeID() == cast<AtomicRMWInst>(I2)->getSyncScopeID();
  if (const ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(I1))
    return SVI->getShuffleMask() ==
           cast<ShuffleVectorInst>(I2)->getShuffleMask();
  if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I1))
    return GEP->getSourceElementType() ==
           cast<GetElementPtrInst>(I2)->getSourceElementType();

  return true;
}

bool Instruction::isIdenticalTo(const Instruction *I) const {
  return isIdenticalToWhenDefined(I) &&
         SubclassOptionalData == I->SubclassOptionalData;
}

bool Instruction::isIdenticalToWhenDefined(const Instruction *I,
                                           bool IntersectAttrs) const {
  if (getOpcode() != I->getOpcode() ||
      getNumOperands() != I->getNumOperands() || getType() != I->getType())
    return false;

  // If both instructions have no operands, they are identical.
  if (getNumOperands() == 0 && I->getNumOperands() == 0)
    return this->hasSameSpecialState(I, /*IgnoreAlignment=*/false,
                                     IntersectAttrs);

  // We have two instructions of identical opcode and #operands.  Check to see
  // if all operands are the same.
  if (!equal(operands(), I->operands()))
    return false;

  // WARNING: this logic must be kept in sync with EliminateDuplicatePHINodes()!
  if (const PHINode *Phi = dyn_cast<PHINode>(this)) {
    const PHINode *OtherPhi = cast<PHINode>(I);
    return equal(Phi->blocks(), OtherPhi->blocks());
  }

  return this->hasSameSpecialState(I, /*IgnoreAlignment=*/false,
                                   IntersectAttrs);
}

// Keep this in sync with FunctionComparator::cmpOperations in
// lib/Transforms/IPO/MergeFunctions.cpp.
bool Instruction::isSameOperationAs(const Instruction *I,
                                    unsigned flags) const {
  bool IgnoreAlignment = flags & CompareIgnoringAlignment;
  bool UseScalarTypes = flags & CompareUsingScalarTypes;
  bool IntersectAttrs = flags & CompareUsingIntersectedAttrs;

  if (getOpcode() != I->getOpcode() ||
      getNumOperands() != I->getNumOperands() ||
      (UseScalarTypes ?
       getType()->getScalarType() != I->getType()->getScalarType() :
       getType() != I->getType()))
    return false;

  // We have two instructions of identical opcode and #operands.  Check to see
  // if all operands are the same type
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
    if (UseScalarTypes ?
        getOperand(i)->getType()->getScalarType() !=
          I->getOperand(i)->getType()->getScalarType() :
        getOperand(i)->getType() != I->getOperand(i)->getType())
      return false;

  return this->hasSameSpecialState(I, IgnoreAlignment, IntersectAttrs);
}

bool Instruction::isUsedOutsideOfBlock(const BasicBlock *BB) const {
  for (const Use &U : uses()) {
    // PHI nodes uses values in the corresponding predecessor block.  For other
    // instructions, just check to see whether the parent of the use matches up.
    const Instruction *I = cast<Instruction>(U.getUser());
    const PHINode *PN = dyn_cast<PHINode>(I);
    if (!PN) {
      if (I->getParent() != BB)
        return true;
      continue;
    }

    if (PN->getIncomingBlock(U) != BB)
      return true;
  }
  return false;
}

bool Instruction::mayReadFromMemory() const {
  switch (getOpcode()) {
  default: return false;
  case Instruction::VAArg:
  case Instruction::Load:
  case Instruction::Fence: // FIXME: refine definition of mayReadFromMemory
  case Instruction::AtomicCmpXchg:
  case Instruction::AtomicRMW:
  case Instruction::CatchPad:
  case Instruction::CatchRet:
    return true;
  case Instruction::Call:
  case Instruction::Invoke:
  case Instruction::CallBr:
    return !cast<CallBase>(this)->onlyWritesMemory();
  case Instruction::Store:
    return !cast<StoreInst>(this)->isUnordered();
  }
}

bool Instruction::mayWriteToMemory() const {
  switch (getOpcode()) {
  default: return false;
  case Instruction::Fence: // FIXME: refine definition of mayWriteToMemory
  case Instruction::Store:
  case Instruction::VAArg:
  case Instruction::AtomicCmpXchg:
  case Instruction::AtomicRMW:
  case Instruction::CatchPad:
  case Instruction::CatchRet:
    return true;
  case Instruction::Call:
  case Instruction::Invoke:
  case Instruction::CallBr:
    return !cast<CallBase>(this)->onlyReadsMemory();
  case Instruction::Load:
    return !cast<LoadInst>(this)->isUnordered();
  }
}

bool Instruction::isAtomic() const {
  switch (getOpcode()) {
  default:
    return false;
  case Instruction::AtomicCmpXchg:
  case Instruction::AtomicRMW:
  case Instruction::Fence:
    return true;
  case Instruction::Load:
    return cast<LoadInst>(this)->getOrdering() != AtomicOrdering::NotAtomic;
  case Instruction::Store:
    return cast<StoreInst>(this)->getOrdering() != AtomicOrdering::NotAtomic;
  }
}

bool Instruction::hasAtomicLoad() const {
  assert(isAtomic());
  switch (getOpcode()) {
  default:
    return false;
  case Instruction::AtomicCmpXchg:
  case Instruction::AtomicRMW:
  case Instruction::Load:
    return true;
  }
}

bool Instruction::hasAtomicStore() const {
  assert(isAtomic());
  switch (getOpcode()) {
  default:
    return false;
  case Instruction::AtomicCmpXchg:
  case Instruction::AtomicRMW:
  case Instruction::Store:
    return true;
  }
}

bool Instruction::isVolatile() const {
  switch (getOpcode()) {
  default:
    return false;
  case Instruction::AtomicRMW:
    return cast<AtomicRMWInst>(this)->isVolatile();
  case Instruction::Store:
    return cast<StoreInst>(this)->isVolatile();
  case Instruction::Load:
    return cast<LoadInst>(this)->isVolatile();
  case Instruction::AtomicCmpXchg:
    return cast<AtomicCmpXchgInst>(this)->isVolatile();
  case Instruction::Call:
  case Instruction::Invoke:
    // There are a very limited number of intrinsics with volatile flags.
    if (auto *II = dyn_cast<IntrinsicInst>(this)) {
      if (auto *MI = dyn_cast<MemIntrinsic>(II))
        return MI->isVolatile();
      switch (II->getIntrinsicID()) {
      default: break;
      case Intrinsic::matrix_column_major_load:
        return cast<ConstantInt>(II->getArgOperand(2))->isOne();
      case Intrinsic::matrix_column_major_store:
        return cast<ConstantInt>(II->getArgOperand(3))->isOne();
      }
    }
    return false;
  }
}

Type *Instruction::getAccessType() const {
  switch (getOpcode()) {
  case Instruction::Store:
    return cast<StoreInst>(this)->getValueOperand()->getType();
  case Instruction::Load:
  case Instruction::AtomicRMW:
    return getType();
  case Instruction::AtomicCmpXchg:
    return cast<AtomicCmpXchgInst>(this)->getNewValOperand()->getType();
  case Instruction::Call:
  case Instruction::Invoke:
    if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(this)) {
      switch (II->getIntrinsicID()) {
      case Intrinsic::masked_load:
      case Intrinsic::masked_gather:
      case Intrinsic::masked_expandload:
      case Intrinsic::vp_load:
      case Intrinsic::vp_gather:
      case Intrinsic::experimental_vp_strided_load:
        return II->getType();
      case Intrinsic::masked_store:
      case Intrinsic::masked_scatter:
      case Intrinsic::masked_compressstore:
      case Intrinsic::vp_store:
      case Intrinsic::vp_scatter:
      case Intrinsic::experimental_vp_strided_store:
        return II->getOperand(0)->getType();
      default:
        break;
      }
    }
  }

  return nullptr;
}

static bool canUnwindPastLandingPad(const LandingPadInst *LP,
                                    bool IncludePhaseOneUnwind) {
  // Because phase one unwinding skips cleanup landingpads, we effectively
  // unwind past this frame, and callers need to have valid unwind info.
  if (LP->isCleanup())
    return IncludePhaseOneUnwind;

  for (unsigned I = 0; I < LP->getNumClauses(); ++I) {
    Constant *Clause = LP->getClause(I);
    // catch ptr null catches all exceptions.
    if (LP->isCatch(I) && isa<ConstantPointerNull>(Clause))
      return false;
    // filter [0 x ptr] catches all exceptions.
    if (LP->isFilter(I) && Clause->getType()->getArrayNumElements() == 0)
      return false;
  }

  // May catch only some subset of exceptions, in which case other exceptions
  // will continue unwinding.
  return true;
}

bool Instruction::mayThrow(bool IncludePhaseOneUnwind) const {
  switch (getOpcode()) {
  case Instruction::Call:
    return !cast<CallInst>(this)->doesNotThrow();
  case Instruction::CleanupRet:
    return cast<CleanupReturnInst>(this)->unwindsToCaller();
  case Instruction::CatchSwitch:
    return cast<CatchSwitchInst>(this)->unwindsToCaller();
  case Instruction::Resume:
    return true;
  case Instruction::Invoke: {
    // Landingpads themselves don't unwind -- however, an invoke of a skipped
    // landingpad may continue unwinding.
    BasicBlock *UnwindDest = cast<InvokeInst>(this)->getUnwindDest();
    BasicBlock::iterator Pad = UnwindDest->getFirstNonPHIIt();
    if (auto *LP = dyn_cast<LandingPadInst>(Pad))
      return canUnwindPastLandingPad(LP, IncludePhaseOneUnwind);
    return false;
  }
  case Instruction::CleanupPad:
    // Treat the same as cleanup landingpad.
    return IncludePhaseOneUnwind;
  default:
    return false;
  }
}

bool Instruction::mayHaveSideEffects() const {
  return mayWriteToMemory() || mayThrow() || !willReturn();
}

bool Instruction::isSafeToRemove() const {
  return (!isa<CallInst>(this) || !this->mayHaveSideEffects()) &&
         !this->isTerminator() && !this->isEHPad();
}

bool Instruction::willReturn() const {
  // Volatile store isn't guaranteed to return; see LangRef.
  if (auto *SI = dyn_cast<StoreInst>(this))
    return !SI->isVolatile();

  if (const auto *CB = dyn_cast<CallBase>(this))
    return CB->hasFnAttr(Attribute::WillReturn);
  return true;
}

bool Instruction::isLifetimeStartOrEnd() const {
  auto *II = dyn_cast<IntrinsicInst>(this);
  if (!II)
    return false;
  Intrinsic::ID ID = II->getIntrinsicID();
  return ID == Intrinsic::lifetime_start || ID == Intrinsic::lifetime_end;
}

bool Instruction::isLaunderOrStripInvariantGroup() const {
  auto *II = dyn_cast<IntrinsicInst>(this);
  if (!II)
    return false;
  Intrinsic::ID ID = II->getIntrinsicID();
  return ID == Intrinsic::launder_invariant_group ||
         ID == Intrinsic::strip_invariant_group;
}

bool Instruction::isDebugOrPseudoInst() const {
  return isa<DbgInfoIntrinsic>(this) || isa<PseudoProbeInst>(this);
}

const DebugLoc &Instruction::getStableDebugLoc() const {
  return getDebugLoc();
}

bool Instruction::isAssociative() const {
  if (auto *II = dyn_cast<IntrinsicInst>(this))
    return II->isAssociative();
  unsigned Opcode = getOpcode();
  if (isAssociative(Opcode))
    return true;

  switch (Opcode) {
  case FMul:
  case FAdd:
    return cast<FPMathOperator>(this)->hasAllowReassoc() &&
           cast<FPMathOperator>(this)->hasNoSignedZeros();
  default:
    return false;
  }
}

bool Instruction::isCommutative() const {
  if (auto *II = dyn_cast<IntrinsicInst>(this))
    return II->isCommutative();
  // TODO: Should allow icmp/fcmp?
  return isCommutative(getOpcode());
}

unsigned Instruction::getNumSuccessors() const {
  switch (getOpcode()) {
#define HANDLE_TERM_INST(N, OPC, CLASS)                                        \
  case Instruction::OPC:                                                       \
    return static_cast<const CLASS *>(this)->getNumSuccessors();
#include "llvm/IR/Instruction.def"
  default:
    break;
  }
  llvm_unreachable("not a terminator");
}

BasicBlock *Instruction::getSuccessor(unsigned idx) const {
  switch (getOpcode()) {
#define HANDLE_TERM_INST(N, OPC, CLASS)                                        \
  case Instruction::OPC:                                                       \
    return static_cast<const CLASS *>(this)->getSuccessor(idx);
#include "llvm/IR/Instruction.def"
  default:
    break;
  }
  llvm_unreachable("not a terminator");
}

void Instruction::setSuccessor(unsigned idx, BasicBlock *B) {
  switch (getOpcode()) {
#define HANDLE_TERM_INST(N, OPC, CLASS)                                        \
  case Instruction::OPC:                                                       \
    return static_cast<CLASS *>(this)->setSuccessor(idx, B);
#include "llvm/IR/Instruction.def"
  default:
    break;
  }
  llvm_unreachable("not a terminator");
}

void Instruction::replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB) {
  for (unsigned Idx = 0, NumSuccessors = Instruction::getNumSuccessors();
       Idx != NumSuccessors; ++Idx)
    if (getSuccessor(Idx) == OldBB)
      setSuccessor(Idx, NewBB);
}

Instruction *Instruction::cloneImpl() const {
  llvm_unreachable("Subclass of Instruction failed to implement cloneImpl");
}

void Instruction::swapProfMetadata() {
  MDNode *ProfileData = getBranchWeightMDNode(*this);
  if (!ProfileData)
    return;
  unsigned FirstIdx = getBranchWeightOffset(ProfileData);
  if (ProfileData->getNumOperands() != 2 + FirstIdx)
    return;

  unsigned SecondIdx = FirstIdx + 1;
  SmallVector<Metadata *, 4> Ops;
  // If there are more weights past the second, we can't swap them
  if (ProfileData->getNumOperands() > SecondIdx + 1)
    return;
  for (unsigned Idx = 0; Idx < FirstIdx; ++Idx) {
    Ops.push_back(ProfileData->getOperand(Idx));
  }
  // Switch the order of the weights
  Ops.push_back(ProfileData->getOperand(SecondIdx));
  Ops.push_back(ProfileData->getOperand(FirstIdx));
  setMetadata(LLVMContext::MD_prof,
              MDNode::get(ProfileData->getContext(), Ops));
}

void Instruction::copyMetadata(const Instruction &SrcInst,
                               ArrayRef<unsigned> WL) {
  if (WL.empty() || is_contained(WL, LLVMContext::MD_dbg))
    setDebugLoc(SrcInst.getDebugLoc().orElse(getDebugLoc()));

  if (!SrcInst.hasMetadata())
    return;

  SmallDenseSet<unsigned, 4> WLS(WL.begin(), WL.end());

  // Otherwise, enumerate and copy over metadata from the old instruction to the
  // new one.
  SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs;
  SrcInst.getAllMetadataOtherThanDebugLoc(TheMDs);
  for (const auto &MD : TheMDs) {
    if (WL.empty() || WLS.count(MD.first))
      setMetadata(MD.first, MD.second);
  }
}

Instruction *Instruction::clone() const {
  Instruction *New = nullptr;
  switch (getOpcode()) {
  default:
    llvm_unreachable("Unhandled Opcode.");
#define HANDLE_INST(num, opc, clas)                                            \
  case Instruction::opc:                                                       \
    New = cast<clas>(this)->cloneImpl();                                       \
    break;
#include "llvm/IR/Instruction.def"
#undef HANDLE_INST
  }

  New->SubclassOptionalData = SubclassOptionalData;
  New->copyMetadata(*this);
  return New;
}
