[llvm] [SandboxIR][NFC] Move Instruction classes into a separate file (PR #110294)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 27 09:38:15 PDT 2024
https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/110294
None
>From 3dac6c35e5d5465d2fb6ba8332a4ee594de46cc1 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 26 Sep 2024 14:25:38 -0700
Subject: [PATCH] [SandboxIR][NFC] Move Instruction classes into a separate
file
---
llvm/benchmarks/SandboxIRBench.cpp | 3 +-
llvm/include/llvm/SandboxIR/Constant.h | 1 +
llvm/include/llvm/SandboxIR/Context.h | 1 +
llvm/include/llvm/SandboxIR/Instruction.h | 2741 +++++++++++++++++
llvm/include/llvm/SandboxIR/Region.h | 2 +-
llvm/include/llvm/SandboxIR/SandboxIR.h | 2718 ----------------
llvm/include/llvm/SandboxIR/Utils.h | 2 +-
.../SandboxVectorizer/Passes/BottomUpVec.h | 2 +-
llvm/lib/SandboxIR/BasicBlock.cpp | 2 +-
llvm/lib/SandboxIR/CMakeLists.txt | 1 +
llvm/lib/SandboxIR/Context.cpp | 5 +-
llvm/lib/SandboxIR/Instruction.cpp | 1965 ++++++++++++
llvm/lib/SandboxIR/SandboxIR.cpp | 1952 ------------
llvm/lib/SandboxIR/Tracker.cpp | 2 +-
.../SandboxVectorizer/Passes/BottomUpVec.cpp | 1 +
llvm/unittests/SandboxIR/TrackerTest.cpp | 2 +-
.../SandboxVectorizer/LegalityTest.cpp | 2 +-
17 files changed, 4723 insertions(+), 4679 deletions(-)
create mode 100644 llvm/include/llvm/SandboxIR/Instruction.h
create mode 100644 llvm/lib/SandboxIR/Instruction.cpp
diff --git a/llvm/benchmarks/SandboxIRBench.cpp b/llvm/benchmarks/SandboxIRBench.cpp
index d4601d5f53d07a..8f7ab1a3768997 100644
--- a/llvm/benchmarks/SandboxIRBench.cpp
+++ b/llvm/benchmarks/SandboxIRBench.cpp
@@ -18,7 +18,8 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/SandboxIR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include <memory>
#include <sstream>
diff --git a/llvm/include/llvm/SandboxIR/Constant.h b/llvm/include/llvm/SandboxIR/Constant.h
index bc0e3d8849237a..a8cc66ba9d6540 100644
--- a/llvm/include/llvm/SandboxIR/Constant.h
+++ b/llvm/include/llvm/SandboxIR/Constant.h
@@ -17,6 +17,7 @@
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/SandboxIR/Argument.h"
#include "llvm/SandboxIR/Context.h"
#include "llvm/SandboxIR/Type.h"
#include "llvm/SandboxIR/User.h"
diff --git a/llvm/include/llvm/SandboxIR/Context.h b/llvm/include/llvm/SandboxIR/Context.h
index 092b791bc2acb9..37f52d74209cb3 100644
--- a/llvm/include/llvm/SandboxIR/Context.h
+++ b/llvm/include/llvm/SandboxIR/Context.h
@@ -159,6 +159,7 @@ class Context {
public:
Context(LLVMContext &LLVMCtx);
+ ~Context();
Tracker &getTracker() { return IRTracker; }
/// Convenience function for `getTracker().save()`
diff --git a/llvm/include/llvm/SandboxIR/Instruction.h b/llvm/include/llvm/SandboxIR/Instruction.h
new file mode 100644
index 00000000000000..f5f5bb5c4443c2
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/Instruction.h
@@ -0,0 +1,2741 @@
+//===- Instruction.h --------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SANDBOXIR_INSTRUCTION_H
+#define LLVM_SANDBOXIR_INSTRUCTION_H
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/PatternMatch.h"
+#include "llvm/SandboxIR/BasicBlock.h"
+#include "llvm/SandboxIR/Constant.h"
+#include "llvm/SandboxIR/User.h"
+
+namespace llvm::sandboxir {
+
+/// A sandboxir::User with operands, opcode and linked with previous/next
+/// instructions in an instruction list.
+class Instruction : public User {
+public:
+ enum class Opcode {
+#define OP(OPC) OPC,
+#define OPCODES(...) __VA_ARGS__
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ };
+
+protected:
+ Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
+ sandboxir::Context &SBCtx)
+ : User(ID, I, SBCtx), Opc(Opc) {}
+
+ Opcode Opc;
+
+ /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This
+ /// returns its topmost LLVM IR instruction.
+ llvm::Instruction *getTopmostLLVMInstruction() const;
+ friend class VAArgInst; // For getTopmostLLVMInstruction().
+ friend class FreezeInst; // For getTopmostLLVMInstruction().
+ friend class FenceInst; // For getTopmostLLVMInstruction().
+ friend class SelectInst; // For getTopmostLLVMInstruction().
+ friend class ExtractElementInst; // For getTopmostLLVMInstruction().
+ friend class InsertElementInst; // For getTopmostLLVMInstruction().
+ friend class ShuffleVectorInst; // For getTopmostLLVMInstruction().
+ friend class ExtractValueInst; // For getTopmostLLVMInstruction().
+ friend class InsertValueInst; // For getTopmostLLVMInstruction().
+ friend class BranchInst; // For getTopmostLLVMInstruction().
+ friend class LoadInst; // For getTopmostLLVMInstruction().
+ friend class StoreInst; // For getTopmostLLVMInstruction().
+ friend class ReturnInst; // For getTopmostLLVMInstruction().
+ friend class CallInst; // For getTopmostLLVMInstruction().
+ friend class InvokeInst; // For getTopmostLLVMInstruction().
+ friend class CallBrInst; // For getTopmostLLVMInstruction().
+ friend class LandingPadInst; // For getTopmostLLVMInstruction().
+ friend class CatchPadInst; // For getTopmostLLVMInstruction().
+ friend class CleanupPadInst; // For getTopmostLLVMInstruction().
+ friend class CatchReturnInst; // For getTopmostLLVMInstruction().
+ friend class CleanupReturnInst; // For getTopmostLLVMInstruction().
+ friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
+ friend class ResumeInst; // For getTopmostLLVMInstruction().
+ friend class CatchSwitchInst; // For getTopmostLLVMInstruction().
+ friend class SwitchInst; // For getTopmostLLVMInstruction().
+ friend class UnaryOperator; // For getTopmostLLVMInstruction().
+ friend class BinaryOperator; // For getTopmostLLVMInstruction().
+ friend class AtomicRMWInst; // For getTopmostLLVMInstruction().
+ friend class AtomicCmpXchgInst; // For getTopmostLLVMInstruction().
+ friend class AllocaInst; // For getTopmostLLVMInstruction().
+ friend class CastInst; // For getTopmostLLVMInstruction().
+ friend class PHINode; // For getTopmostLLVMInstruction().
+ friend class UnreachableInst; // For getTopmostLLVMInstruction().
+ friend class CmpInst; // For getTopmostLLVMInstruction().
+
+ /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
+ /// order.
+ virtual SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const = 0;
+ friend class EraseFromParent; // For getLLVMInstrs().
+
+public:
+ static const char *getOpcodeName(Opcode Opc);
+ /// This is used by BasicBlock::iterator.
+ virtual unsigned getNumOfIRInstrs() const = 0;
+ /// \Returns a BasicBlock::iterator for this Instruction.
+ BBIterator getIterator() const;
+ /// \Returns the next sandboxir::Instruction in the block, or nullptr if at
+ /// the end of the block.
+ Instruction *getNextNode() const;
+ /// \Returns the previous sandboxir::Instruction in the block, or nullptr if
+ /// at the beginning of the block.
+ Instruction *getPrevNode() const;
+ /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode
+ /// state to allow for new SandboxIR-specific instructions.
+ Opcode getOpcode() const { return Opc; }
+
+ const char *getOpcodeName() const { return getOpcodeName(Opc); }
+
+ // Note that these functions below are calling into llvm::Instruction.
+ // A sandbox IR instruction could introduce a new opcode that could change the
+ // behavior of one of these functions. It is better that these functions are
+ // only added as needed and new sandbox IR instructions must explicitly check
+ // if any of these functions could have a different behavior.
+
+ bool isTerminator() const {
+ return cast<llvm::Instruction>(Val)->isTerminator();
+ }
+ bool isUnaryOp() const { return cast<llvm::Instruction>(Val)->isUnaryOp(); }
+ bool isBinaryOp() const { return cast<llvm::Instruction>(Val)->isBinaryOp(); }
+ bool isIntDivRem() const {
+ return cast<llvm::Instruction>(Val)->isIntDivRem();
+ }
+ bool isShift() const { return cast<llvm::Instruction>(Val)->isShift(); }
+ bool isCast() const { return cast<llvm::Instruction>(Val)->isCast(); }
+ bool isFuncletPad() const {
+ return cast<llvm::Instruction>(Val)->isFuncletPad();
+ }
+ bool isSpecialTerminator() const {
+ return cast<llvm::Instruction>(Val)->isSpecialTerminator();
+ }
+ bool isOnlyUserOfAnyOperand() const {
+ return cast<llvm::Instruction>(Val)->isOnlyUserOfAnyOperand();
+ }
+ bool isLogicalShift() const {
+ return cast<llvm::Instruction>(Val)->isLogicalShift();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Metadata manipulation.
+ //===--------------------------------------------------------------------===//
+
+ /// Return true if the instruction has any metadata attached to it.
+ bool hasMetadata() const {
+ return cast<llvm::Instruction>(Val)->hasMetadata();
+ }
+
+ /// Return true if this instruction has metadata attached to it other than a
+ /// debug location.
+ bool hasMetadataOtherThanDebugLoc() const {
+ return cast<llvm::Instruction>(Val)->hasMetadataOtherThanDebugLoc();
+ }
+
+ /// Return true if this instruction has the given type of metadata attached.
+ bool hasMetadata(unsigned KindID) const {
+ return cast<llvm::Instruction>(Val)->hasMetadata(KindID);
+ }
+
+ // TODO: Implement getMetadata and getAllMetadata after sandboxir::MDNode is
+ // available.
+
+ // TODO: More missing functions
+
+ /// Detach this from its parent BasicBlock without deleting it.
+ void removeFromParent();
+ /// Detach this Value from its parent and delete it.
+ void eraseFromParent();
+ /// Insert this detached instruction before \p BeforeI.
+ void insertBefore(Instruction *BeforeI);
+ /// Insert this detached instruction after \p AfterI.
+ void insertAfter(Instruction *AfterI);
+ /// Insert this detached instruction into \p BB at \p WhereIt.
+ void insertInto(BasicBlock *BB, const BBIterator &WhereIt);
+ /// Move this instruction to \p WhereIt.
+ void moveBefore(BasicBlock &BB, const BBIterator &WhereIt);
+ /// Move this instruction before \p Before.
+ void moveBefore(Instruction *Before) {
+ moveBefore(*Before->getParent(), Before->getIterator());
+ }
+ /// Move this instruction after \p After.
+ void moveAfter(Instruction *After) {
+ moveBefore(*After->getParent(), std::next(After->getIterator()));
+ }
+ // TODO: This currently relies on LLVM IR Instruction::comesBefore which is
+ // can be linear-time.
+ /// Given an instruction Other in the same basic block as this instruction,
+ /// return true if this instruction comes before Other.
+ bool comesBefore(const Instruction *Other) const {
+ return cast<llvm::Instruction>(Val)->comesBefore(
+ cast<llvm::Instruction>(Other->Val));
+ }
+ /// \Returns the BasicBlock containing this Instruction, or null if it is
+ /// detached.
+ BasicBlock *getParent() const;
+ /// For isa/dyn_cast.
+ static bool classof(const sandboxir::Value *From);
+
+ /// Determine whether the no signed wrap flag is set.
+ bool hasNoUnsignedWrap() const {
+ return cast<llvm::Instruction>(Val)->hasNoUnsignedWrap();
+ }
+ /// Set or clear the nuw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setHasNoUnsignedWrap(bool B = true);
+ /// Determine whether the no signed wrap flag is set.
+ bool hasNoSignedWrap() const {
+ return cast<llvm::Instruction>(Val)->hasNoSignedWrap();
+ }
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setHasNoSignedWrap(bool B = true);
+ /// Determine whether all fast-math-flags are set.
+ bool isFast() const { return cast<llvm::Instruction>(Val)->isFast(); }
+ /// Set or clear all fast-math-flags on this instruction, which must be an
+ /// operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setFast(bool B);
+ /// Determine whether the allow-reassociation flag is set.
+ bool hasAllowReassoc() const {
+ return cast<llvm::Instruction>(Val)->hasAllowReassoc();
+ }
+ /// Set or clear the reassociation flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasAllowReassoc(bool B);
+ /// Determine whether the exact flag is set.
+ bool isExact() const { return cast<llvm::Instruction>(Val)->isExact(); }
+ /// Set or clear the exact flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
+ void setIsExact(bool B = true);
+ /// Determine whether the no-NaNs flag is set.
+ bool hasNoNaNs() const { return cast<llvm::Instruction>(Val)->hasNoNaNs(); }
+ /// Set or clear the no-nans flag on this instruction, which must be an
+ /// operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasNoNaNs(bool B);
+ /// Determine whether the no-infs flag is set.
+ bool hasNoInfs() const { return cast<llvm::Instruction>(Val)->hasNoInfs(); }
+ /// Set or clear the no-infs flag on this instruction, which must be an
+ /// operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasNoInfs(bool B);
+ /// Determine whether the no-signed-zeros flag is set.
+ bool hasNoSignedZeros() const {
+ return cast<llvm::Instruction>(Val)->hasNoSignedZeros();
+ }
+ /// Set or clear the no-signed-zeros flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasNoSignedZeros(bool B);
+ /// Determine whether the allow-reciprocal flag is set.
+ bool hasAllowReciprocal() const {
+ return cast<llvm::Instruction>(Val)->hasAllowReciprocal();
+ }
+ /// Set or clear the allow-reciprocal flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasAllowReciprocal(bool B);
+ /// Determine whether the allow-contract flag is set.
+ bool hasAllowContract() const {
+ return cast<llvm::Instruction>(Val)->hasAllowContract();
+ }
+ /// Set or clear the allow-contract flag on this instruction, which must be
+ /// an operator which supports this flag. See LangRef.html for the meaning of
+ /// this flag.
+ void setHasAllowContract(bool B);
+ /// Determine whether the approximate-math-functions flag is set.
+ bool hasApproxFunc() const {
+ return cast<llvm::Instruction>(Val)->hasApproxFunc();
+ }
+ /// Set or clear the approximate-math-functions flag on this instruction,
+ /// which must be an operator which supports this flag. See LangRef.html for
+ /// the meaning of this flag.
+ void setHasApproxFunc(bool B);
+ /// Convenience function for getting all the fast-math flags, which must be an
+ /// operator which supports these flags. See LangRef.html for the meaning of
+ /// these flags.
+ FastMathFlags getFastMathFlags() const {
+ return cast<llvm::Instruction>(Val)->getFastMathFlags();
+ }
+ /// Convenience function for setting multiple fast-math flags on this
+ /// instruction, which must be an operator which supports these flags. See
+ /// LangRef.html for the meaning of these flags.
+ void setFastMathFlags(FastMathFlags FMF);
+ /// Convenience function for transferring all fast-math flag values to this
+ /// instruction, which must be an operator which supports these flags. See
+ /// LangRef.html for the meaning of these flags.
+ void copyFastMathFlags(FastMathFlags FMF);
+
+ bool isAssociative() const {
+ return cast<llvm::Instruction>(Val)->isAssociative();
+ }
+
+ bool isCommutative() const {
+ return cast<llvm::Instruction>(Val)->isCommutative();
+ }
+
+ bool isIdempotent() const {
+ return cast<llvm::Instruction>(Val)->isIdempotent();
+ }
+
+ bool isNilpotent() const {
+ return cast<llvm::Instruction>(Val)->isNilpotent();
+ }
+
+ bool mayWriteToMemory() const {
+ return cast<llvm::Instruction>(Val)->mayWriteToMemory();
+ }
+
+ bool mayReadFromMemory() const {
+ return cast<llvm::Instruction>(Val)->mayReadFromMemory();
+ }
+ bool mayReadOrWriteMemory() const {
+ return cast<llvm::Instruction>(Val)->mayReadOrWriteMemory();
+ }
+
+ bool isAtomic() const { return cast<llvm::Instruction>(Val)->isAtomic(); }
+
+ bool hasAtomicLoad() const {
+ return cast<llvm::Instruction>(Val)->hasAtomicLoad();
+ }
+
+ bool hasAtomicStore() const {
+ return cast<llvm::Instruction>(Val)->hasAtomicStore();
+ }
+
+ bool isVolatile() const { return cast<llvm::Instruction>(Val)->isVolatile(); }
+
+ Type *getAccessType() const;
+
+ bool mayThrow(bool IncludePhaseOneUnwind = false) const {
+ return cast<llvm::Instruction>(Val)->mayThrow(IncludePhaseOneUnwind);
+ }
+
+ bool isFenceLike() const {
+ return cast<llvm::Instruction>(Val)->isFenceLike();
+ }
+
+ bool mayHaveSideEffects() const {
+ return cast<llvm::Instruction>(Val)->mayHaveSideEffects();
+ }
+
+ // TODO: Missing functions.
+
+ bool isStackSaveOrRestoreIntrinsic() const {
+ auto *I = cast<llvm::Instruction>(Val);
+ return match(I,
+ PatternMatch::m_Intrinsic<llvm::Intrinsic::stackrestore>()) ||
+ match(I, PatternMatch::m_Intrinsic<llvm::Intrinsic::stacksave>());
+ }
+
+ /// We consider \p I as a Memory Dependency Candidate instruction if it
+ /// reads/write memory or if it has side-effects. This is used by the
+ /// dependency graph.
+ bool isMemDepCandidate() const {
+ auto *I = cast<llvm::Instruction>(Val);
+ return I->mayReadOrWriteMemory() &&
+ (!isa<llvm::IntrinsicInst>(I) ||
+ (cast<llvm::IntrinsicInst>(I)->getIntrinsicID() !=
+ Intrinsic::sideeffect &&
+ cast<llvm::IntrinsicInst>(I)->getIntrinsicID() !=
+ Intrinsic::pseudoprobe));
+ }
+
+#ifndef NDEBUG
+ void dumpOS(raw_ostream &OS) const override;
+#endif
+};
+
+/// Instructions that contain a single LLVM Instruction can inherit from this.
+template <typename LLVMT> class SingleLLVMInstructionImpl : public Instruction {
+ SingleLLVMInstructionImpl(ClassID ID, Opcode Opc, llvm::Instruction *I,
+ sandboxir::Context &SBCtx)
+ : Instruction(ID, Opc, I, SBCtx) {}
+
+ // All instructions are friends with this so they can call the constructor.
+#define DEF_INSTR(ID, OPC, CLASS) friend class CLASS;
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ friend class UnaryInstruction;
+ friend class CallBase;
+ friend class FuncletPadInst;
+ friend class CmpInst;
+
+ Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
+ return getOperandUseDefault(OpIdx, Verify);
+ }
+ SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
+ return {cast<llvm::Instruction>(Val)};
+ }
+
+public:
+ unsigned getUseOperandNo(const Use &Use) const final {
+ return getUseOperandNoDefault(Use);
+ }
+ unsigned getNumOfIRInstrs() const final { return 1u; }
+#ifndef NDEBUG
+ void verify() const final { assert(isa<LLVMT>(Val) && "Expected LLVMT!"); }
+ void dumpOS(raw_ostream &OS) const override {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+ }
+#endif
+};
+
+class FenceInst : public SingleLLVMInstructionImpl<llvm::FenceInst> {
+ FenceInst(llvm::FenceInst *FI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Fence, Opcode::Fence, FI, Ctx) {}
+ friend Context; // For constructor;
+
+public:
+ static FenceInst *create(AtomicOrdering Ordering, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System);
+ /// Returns the ordering constraint of this fence instruction.
+ AtomicOrdering getOrdering() const {
+ return cast<llvm::FenceInst>(Val)->getOrdering();
+ }
+ /// Sets the ordering constraint of this fence instruction. May only be
+ /// Acquire, Release, AcquireRelease, or SequentiallyConsistent.
+ void setOrdering(AtomicOrdering Ordering);
+ /// Returns the synchronization scope ID of this fence instruction.
+ SyncScope::ID getSyncScopeID() const {
+ return cast<llvm::FenceInst>(Val)->getSyncScopeID();
+ }
+ /// Sets the synchronization scope ID of this fence instruction.
+ void setSyncScopeID(SyncScope::ID SSID);
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Fence;
+ }
+};
+
+class SelectInst : public SingleLLVMInstructionImpl<llvm::SelectInst> {
+ /// Use Context::createSelectInst(). Don't call the
+ /// constructor directly.
+ SelectInst(llvm::SelectInst *CI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Select, Opcode::Select, CI, Ctx) {}
+ friend Context; // for SelectInst()
+ static Value *createCommon(Value *Cond, Value *True, Value *False,
+ const Twine &Name, IRBuilder<> &Builder,
+ Context &Ctx);
+
+public:
+ static Value *create(Value *Cond, Value *True, Value *False,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Value *Cond, Value *True, Value *False,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+
+ const Value *getCondition() const { return getOperand(0); }
+ const Value *getTrueValue() const { return getOperand(1); }
+ const Value *getFalseValue() const { return getOperand(2); }
+ Value *getCondition() { return getOperand(0); }
+ Value *getTrueValue() { return getOperand(1); }
+ Value *getFalseValue() { return getOperand(2); }
+
+ void setCondition(Value *New) { setOperand(0, New); }
+ void setTrueValue(Value *New) { setOperand(1, New); }
+ void setFalseValue(Value *New) { setOperand(2, New); }
+ void swapValues();
+
+ /// Return a string if the specified operands are invalid for a select
+ /// operation, otherwise return null.
+ static const char *areInvalidOperands(Value *Cond, Value *True,
+ Value *False) {
+ return llvm::SelectInst::areInvalidOperands(Cond->Val, True->Val,
+ False->Val);
+ }
+
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From);
+};
+
+class InsertElementInst final
+ : public SingleLLVMInstructionImpl<llvm::InsertElementInst> {
+ /// Use Context::createInsertElementInst() instead.
+ InsertElementInst(llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::InsertElement, Opcode::InsertElement,
+ I, Ctx) {}
+ friend class Context; // For accessing the constructor in create*()
+
+public:
+ static Value *create(Value *Vec, Value *NewElt, Value *Idx,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Value *Vec, Value *NewElt, Value *Idx,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::InsertElement;
+ }
+ static bool isValidOperands(const Value *Vec, const Value *NewElt,
+ const Value *Idx) {
+ return llvm::InsertElementInst::isValidOperands(Vec->Val, NewElt->Val,
+ Idx->Val);
+ }
+};
+
+class ExtractElementInst final
+ : public SingleLLVMInstructionImpl<llvm::ExtractElementInst> {
+ /// Use Context::createExtractElementInst() instead.
+ ExtractElementInst(llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::ExtractElement,
+ Opcode::ExtractElement, I, Ctx) {}
+ friend class Context; // For accessing the constructor in
+ // create*()
+
+public:
+ static Value *create(Value *Vec, Value *Idx, Instruction *InsertBefore,
+ Context &Ctx, const Twine &Name = "");
+ static Value *create(Value *Vec, Value *Idx, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &Name = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::ExtractElement;
+ }
+
+ static bool isValidOperands(const Value *Vec, const Value *Idx) {
+ return llvm::ExtractElementInst::isValidOperands(Vec->Val, Idx->Val);
+ }
+ Value *getVectorOperand() { return getOperand(0); }
+ Value *getIndexOperand() { return getOperand(1); }
+ const Value *getVectorOperand() const { return getOperand(0); }
+ const Value *getIndexOperand() const { return getOperand(1); }
+ VectorType *getVectorOperandType() const;
+};
+
+class ShuffleVectorInst final
+ : public SingleLLVMInstructionImpl<llvm::ShuffleVectorInst> {
+ /// Use Context::createShuffleVectorInst() instead.
+ ShuffleVectorInst(llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::ShuffleVector, Opcode::ShuffleVector,
+ I, Ctx) {}
+ friend class Context; // For accessing the constructor in create*()
+
+public:
+ static Value *create(Value *V1, Value *V2, Value *Mask,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Value *V1, Value *V2, Value *Mask,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Value *V1, Value *V2, ArrayRef<int> Mask,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Value *V1, Value *V2, ArrayRef<int> Mask,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::ShuffleVector;
+ }
+
+ /// Swap the operands and adjust the mask to preserve the semantics of the
+ /// instruction.
+ void commute();
+
+ /// Return true if a shufflevector instruction can be formed with the
+ /// specified operands.
+ static bool isValidOperands(const Value *V1, const Value *V2,
+ const Value *Mask) {
+ return llvm::ShuffleVectorInst::isValidOperands(V1->Val, V2->Val,
+ Mask->Val);
+ }
+ static bool isValidOperands(const Value *V1, const Value *V2,
+ ArrayRef<int> Mask) {
+ return llvm::ShuffleVectorInst::isValidOperands(V1->Val, V2->Val, Mask);
+ }
+
+ /// Overload to return most specific vector type.
+ VectorType *getType() const;
+
+ /// Return the shuffle mask value of this instruction for the given element
+ /// index. Return PoisonMaskElem if the element is undef.
+ int getMaskValue(unsigned Elt) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->getMaskValue(Elt);
+ }
+
+ /// Convert the input shuffle mask operand to a vector of integers. Undefined
+ /// elements of the mask are returned as PoisonMaskElem.
+ static void getShuffleMask(const Constant *Mask,
+ SmallVectorImpl<int> &Result) {
+ llvm::ShuffleVectorInst::getShuffleMask(cast<llvm::Constant>(Mask->Val),
+ Result);
+ }
+
+ /// Return the mask for this instruction as a vector of integers. Undefined
+ /// elements of the mask are returned as PoisonMaskElem.
+ void getShuffleMask(SmallVectorImpl<int> &Result) const {
+ cast<llvm::ShuffleVectorInst>(Val)->getShuffleMask(Result);
+ }
+
+ /// Return the mask for this instruction, for use in bitcode.
+ Constant *getShuffleMaskForBitcode() const;
+
+ static Constant *convertShuffleMaskForBitcode(ArrayRef<int> Mask,
+ Type *ResultTy);
+
+ void setShuffleMask(ArrayRef<int> Mask);
+
+ ArrayRef<int> getShuffleMask() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->getShuffleMask();
+ }
+
+ /// Return true if this shuffle returns a vector with a different number of
+ /// elements than its source vectors.
+ /// Examples: shufflevector <4 x n> A, <4 x n> B, <1,2,3>
+ /// shufflevector <4 x n> A, <4 x n> B, <1,2,3,4,5>
+ bool changesLength() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->changesLength();
+ }
+
+ /// Return true if this shuffle returns a vector with a greater number of
+ /// elements than its source vectors.
+ /// Example: shufflevector <2 x n> A, <2 x n> B, <1,2,3>
+ bool increasesLength() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->increasesLength();
+ }
+
+ /// Return true if this shuffle mask chooses elements from exactly one source
+ /// vector.
+ /// Example: <7,5,undef,7>
+ /// This assumes that vector operands (of length \p NumSrcElts) are the same
+ /// length as the mask.
+ static bool isSingleSourceMask(ArrayRef<int> Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isSingleSourceMask(Mask, NumSrcElts);
+ }
+ static bool isSingleSourceMask(const Constant *Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isSingleSourceMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts);
+ }
+
+ /// Return true if this shuffle chooses elements from exactly one source
+ /// vector without changing the length of that vector.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3>
+ bool isSingleSource() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isSingleSource();
+ }
+
+ /// Return true if this shuffle mask chooses elements from exactly one source
+ /// vector without lane crossings. A shuffle using this mask is not
+ /// necessarily a no-op because it may change the number of elements from its
+ /// input vectors or it may provide demanded bits knowledge via undef lanes.
+ /// Example: <undef,undef,2,3>
+ static bool isIdentityMask(ArrayRef<int> Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isIdentityMask(Mask, NumSrcElts);
+ }
+ static bool isIdentityMask(const Constant *Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isIdentityMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts);
+ }
+
+ /// Return true if this shuffle chooses elements from exactly one source
+ /// vector without lane crossings and does not change the number of elements
+ /// from its input vectors.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef>
+ bool isIdentity() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isIdentity();
+ }
+
+ /// Return true if this shuffle lengthens exactly one source vector with
+ /// undefs in the high elements.
+ bool isIdentityWithPadding() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isIdentityWithPadding();
+ }
+
+ /// Return true if this shuffle extracts the first N elements of exactly one
+ /// source vector.
+ bool isIdentityWithExtract() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isIdentityWithExtract();
+ }
+
+ /// Return true if this shuffle concatenates its 2 source vectors. This
+ /// returns false if either input is undefined. In that case, the shuffle is
+ /// is better classified as an identity with padding operation.
+ bool isConcat() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isConcat();
+ }
+
+ /// Return true if this shuffle mask chooses elements from its source vectors
+ /// without lane crossings. A shuffle using this mask would be
+ /// equivalent to a vector select with a constant condition operand.
+ /// Example: <4,1,6,undef>
+ /// This returns false if the mask does not choose from both input vectors.
+ /// In that case, the shuffle is better classified as an identity shuffle.
+ /// This assumes that vector operands are the same length as the mask
+ /// (a length-changing shuffle can never be equivalent to a vector select).
+ static bool isSelectMask(ArrayRef<int> Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isSelectMask(Mask, NumSrcElts);
+ }
+ static bool isSelectMask(const Constant *Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isSelectMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts);
+ }
+
+ /// Return true if this shuffle chooses elements from its source vectors
+ /// without lane crossings and all operands have the same number of elements.
+ /// In other words, this shuffle is equivalent to a vector select with a
+ /// constant condition operand.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,1,6,3>
+ /// This returns false if the mask does not choose from both input vectors.
+ /// In that case, the shuffle is better classified as an identity shuffle.
+ bool isSelect() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isSelect();
+ }
+
+ /// Return true if this shuffle mask swaps the order of elements from exactly
+ /// one source vector.
+ /// Example: <7,6,undef,4>
+ /// This assumes that vector operands (of length \p NumSrcElts) are the same
+ /// length as the mask.
+ static bool isReverseMask(ArrayRef<int> Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isReverseMask(Mask, NumSrcElts);
+ }
+ static bool isReverseMask(const Constant *Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isReverseMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts);
+ }
+
+ /// Return true if this shuffle swaps the order of elements from exactly
+ /// one source vector.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef>
+ bool isReverse() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isReverse();
+ }
+
+ /// Return true if this shuffle mask chooses all elements with the same value
+ /// as the first element of exactly one source vector.
+ /// Example: <4,undef,undef,4>
+ /// This assumes that vector operands (of length \p NumSrcElts) are the same
+ /// length as the mask.
+ static bool isZeroEltSplatMask(ArrayRef<int> Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isZeroEltSplatMask(Mask, NumSrcElts);
+ }
+ static bool isZeroEltSplatMask(const Constant *Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isZeroEltSplatMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts);
+ }
+
+ /// Return true if all elements of this shuffle are the same value as the
+ /// first element of exactly one source vector without changing the length
+ /// of that vector.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,0,undef,0>
+ bool isZeroEltSplat() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isZeroEltSplat();
+ }
+
+ /// Return true if this shuffle mask is a transpose mask.
+ /// Transpose vector masks transpose a 2xn matrix. They read corresponding
+ /// even- or odd-numbered vector elements from two n-dimensional source
+ /// vectors and write each result into consecutive elements of an
+ /// n-dimensional destination vector. Two shuffles are necessary to complete
+ /// the transpose, one for the even elements and another for the odd elements.
+ /// This description closely follows how the TRN1 and TRN2 AArch64
+ /// instructions operate.
+ ///
+ /// For example, a simple 2x2 matrix can be transposed with:
+ ///
+ /// ; Original matrix
+ /// m0 = < a, b >
+ /// m1 = < c, d >
+ ///
+ /// ; Transposed matrix
+ /// t0 = < a, c > = shufflevector m0, m1, < 0, 2 >
+ /// t1 = < b, d > = shufflevector m0, m1, < 1, 3 >
+ ///
+ /// For matrices having greater than n columns, the resulting nx2 transposed
+ /// matrix is stored in two result vectors such that one vector contains
+ /// interleaved elements from all the even-numbered rows and the other vector
+ /// contains interleaved elements from all the odd-numbered rows. For example,
+ /// a 2x4 matrix can be transposed with:
+ ///
+ /// ; Original matrix
+ /// m0 = < a, b, c, d >
+ /// m1 = < e, f, g, h >
+ ///
+ /// ; Transposed matrix
+ /// t0 = < a, e, c, g > = shufflevector m0, m1 < 0, 4, 2, 6 >
+ /// t1 = < b, f, d, h > = shufflevector m0, m1 < 1, 5, 3, 7 >
+ static bool isTransposeMask(ArrayRef<int> Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isTransposeMask(Mask, NumSrcElts);
+ }
+ static bool isTransposeMask(const Constant *Mask, int NumSrcElts) {
+ return llvm::ShuffleVectorInst::isTransposeMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts);
+ }
+
+ /// Return true if this shuffle transposes the elements of its inputs without
+ /// changing the length of the vectors. This operation may also be known as a
+ /// merge or interleave. See the description for isTransposeMask() for the
+ /// exact specification.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6>
+ bool isTranspose() const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isTranspose();
+ }
+
+ /// Return true if this shuffle mask is a splice mask, concatenating the two
+ /// inputs together and then extracts an original width vector starting from
+ /// the splice index.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4>
+ /// This assumes that vector operands (of length \p NumSrcElts) are the same
+ /// length as the mask.
+ static bool isSpliceMask(ArrayRef<int> Mask, int NumSrcElts, int &Index) {
+ return llvm::ShuffleVectorInst::isSpliceMask(Mask, NumSrcElts, Index);
+ }
+ static bool isSpliceMask(const Constant *Mask, int NumSrcElts, int &Index) {
+ return llvm::ShuffleVectorInst::isSpliceMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts, Index);
+ }
+
+ /// Return true if this shuffle splices two inputs without changing the length
+ /// of the vectors. This operation concatenates the two inputs together and
+ /// then extracts an original width vector starting from the splice index.
+ /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4>
+ bool isSplice(int &Index) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isSplice(Index);
+ }
+
+ /// Return true if this shuffle mask is an extract subvector mask.
+ /// A valid extract subvector mask returns a smaller vector from a single
+ /// source operand. The base extraction index is returned as well.
+ static bool isExtractSubvectorMask(ArrayRef<int> Mask, int NumSrcElts,
+ int &Index) {
+ return llvm::ShuffleVectorInst::isExtractSubvectorMask(Mask, NumSrcElts,
+ Index);
+ }
+ static bool isExtractSubvectorMask(const Constant *Mask, int NumSrcElts,
+ int &Index) {
+ return llvm::ShuffleVectorInst::isExtractSubvectorMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts, Index);
+ }
+
+ /// Return true if this shuffle mask is an extract subvector mask.
+ bool isExtractSubvectorMask(int &Index) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isExtractSubvectorMask(Index);
+ }
+
+ /// Return true if this shuffle mask is an insert subvector mask.
+ /// A valid insert subvector mask inserts the lowest elements of a second
+ /// source operand into an in-place first source operand.
+ /// Both the sub vector width and the insertion index is returned.
+ static bool isInsertSubvectorMask(ArrayRef<int> Mask, int NumSrcElts,
+ int &NumSubElts, int &Index) {
+ return llvm::ShuffleVectorInst::isInsertSubvectorMask(Mask, NumSrcElts,
+ NumSubElts, Index);
+ }
+ static bool isInsertSubvectorMask(const Constant *Mask, int NumSrcElts,
+ int &NumSubElts, int &Index) {
+ return llvm::ShuffleVectorInst::isInsertSubvectorMask(
+ cast<llvm::Constant>(Mask->Val), NumSrcElts, NumSubElts, Index);
+ }
+
+ /// Return true if this shuffle mask is an insert subvector mask.
+ bool isInsertSubvectorMask(int &NumSubElts, int &Index) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isInsertSubvectorMask(NumSubElts,
+ Index);
+ }
+
+ /// Return true if this shuffle mask replicates each of the \p VF elements
+ /// in a vector \p ReplicationFactor times.
+ /// For example, the mask for \p ReplicationFactor=3 and \p VF=4 is:
+ /// <0,0,0,1,1,1,2,2,2,3,3,3>
+ static bool isReplicationMask(ArrayRef<int> Mask, int &ReplicationFactor,
+ int &VF) {
+ return llvm::ShuffleVectorInst::isReplicationMask(Mask, ReplicationFactor,
+ VF);
+ }
+ static bool isReplicationMask(const Constant *Mask, int &ReplicationFactor,
+ int &VF) {
+ return llvm::ShuffleVectorInst::isReplicationMask(
+ cast<llvm::Constant>(Mask->Val), ReplicationFactor, VF);
+ }
+
+ /// Return true if this shuffle mask is a replication mask.
+ bool isReplicationMask(int &ReplicationFactor, int &VF) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isReplicationMask(
+ ReplicationFactor, VF);
+ }
+
+ /// Return true if this shuffle mask represents "clustered" mask of size VF,
+ /// i.e. each index between [0..VF) is used exactly once in each submask of
+ /// size VF.
+ /// For example, the mask for \p VF=4 is:
+ /// 0, 1, 2, 3, 3, 2, 0, 1 - "clustered", because each submask of size 4
+ /// (0,1,2,3 and 3,2,0,1) uses indices [0..VF) exactly one time.
+ /// 0, 1, 2, 3, 3, 3, 1, 0 - not "clustered", because
+ /// element 3 is used twice in the second submask
+ /// (3,3,1,0) and index 2 is not used at all.
+ static bool isOneUseSingleSourceMask(ArrayRef<int> Mask, int VF) {
+ return llvm::ShuffleVectorInst::isOneUseSingleSourceMask(Mask, VF);
+ }
+
+ /// Return true if this shuffle mask is a one-use-single-source("clustered")
+ /// mask.
+ bool isOneUseSingleSourceMask(int VF) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isOneUseSingleSourceMask(VF);
+ }
+
+ /// Change values in a shuffle permute mask assuming the two vector operands
+ /// of length InVecNumElts have swapped position.
+ static void commuteShuffleMask(MutableArrayRef<int> Mask,
+ unsigned InVecNumElts) {
+ llvm::ShuffleVectorInst::commuteShuffleMask(Mask, InVecNumElts);
+ }
+
+ /// Return if this shuffle interleaves its two input vectors together.
+ bool isInterleave(unsigned Factor) const {
+ return cast<llvm::ShuffleVectorInst>(Val)->isInterleave(Factor);
+ }
+
+ /// Return true if the mask interleaves one or more input vectors together.
+ ///
+ /// I.e. <0, LaneLen, ... , LaneLen*(Factor - 1), 1, LaneLen + 1, ...>
+ /// E.g. For a Factor of 2 (LaneLen=4):
+ /// <0, 4, 1, 5, 2, 6, 3, 7>
+ /// E.g. For a Factor of 3 (LaneLen=4):
+ /// <4, 0, 9, 5, 1, 10, 6, 2, 11, 7, 3, 12>
+ /// E.g. For a Factor of 4 (LaneLen=2):
+ /// <0, 2, 6, 4, 1, 3, 7, 5>
+ ///
+ /// NumInputElts is the total number of elements in the input vectors.
+ ///
+ /// StartIndexes are the first indexes of each vector being interleaved,
+ /// substituting any indexes that were undef
+ /// E.g. <4, -1, 2, 5, 1, 3> (Factor=3): StartIndexes=<4, 0, 2>
+ ///
+ /// Note that this does not check if the input vectors are consecutive:
+ /// It will return true for masks such as
+ /// <0, 4, 6, 1, 5, 7> (Factor=3, LaneLen=2)
+ static bool isInterleaveMask(ArrayRef<int> Mask, unsigned Factor,
+ unsigned NumInputElts,
+ SmallVectorImpl<unsigned> &StartIndexes) {
+ return llvm::ShuffleVectorInst::isInterleaveMask(Mask, Factor, NumInputElts,
+ StartIndexes);
+ }
+ static bool isInterleaveMask(ArrayRef<int> Mask, unsigned Factor,
+ unsigned NumInputElts) {
+ return llvm::ShuffleVectorInst::isInterleaveMask(Mask, Factor,
+ NumInputElts);
+ }
+
+ /// Check if the mask is a DE-interleave mask of the given factor
+ /// \p Factor like:
+ /// <Index, Index+Factor, ..., Index+(NumElts-1)*Factor>
+ static bool isDeInterleaveMaskOfFactor(ArrayRef<int> Mask, unsigned Factor,
+ unsigned &Index) {
+ return llvm::ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor,
+ Index);
+ }
+ static bool isDeInterleaveMaskOfFactor(ArrayRef<int> Mask, unsigned Factor) {
+ return llvm::ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor);
+ }
+
+ /// Checks if the shuffle is a bit rotation of the first operand across
+ /// multiple subelements, e.g:
+ ///
+ /// shuffle <8 x i8> %a, <8 x i8> poison, <8 x i32> <1, 0, 3, 2, 5, 4, 7, 6>
+ ///
+ /// could be expressed as
+ ///
+ /// rotl <4 x i16> %a, 8
+ ///
+ /// If it can be expressed as a rotation, returns the number of subelements to
+ /// group by in NumSubElts and the number of bits to rotate left in RotateAmt.
+ static bool isBitRotateMask(ArrayRef<int> Mask, unsigned EltSizeInBits,
+ unsigned MinSubElts, unsigned MaxSubElts,
+ unsigned &NumSubElts, unsigned &RotateAmt) {
+ return llvm::ShuffleVectorInst::isBitRotateMask(
+ Mask, EltSizeInBits, MinSubElts, MaxSubElts, NumSubElts, RotateAmt);
+ }
+};
+
+class InsertValueInst
+ : public SingleLLVMInstructionImpl<llvm::InsertValueInst> {
+ /// Use Context::createInsertValueInst(). Don't call the constructor directly.
+ InsertValueInst(llvm::InsertValueInst *IVI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::InsertValue, Opcode::InsertValue,
+ IVI, Ctx) {}
+ friend Context; // for InsertValueInst()
+
+public:
+ static Value *create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
+ BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::InsertValue;
+ }
+
+ using idx_iterator = llvm::InsertValueInst::idx_iterator;
+ inline idx_iterator idx_begin() const {
+ return cast<llvm::InsertValueInst>(Val)->idx_begin();
+ }
+ inline idx_iterator idx_end() const {
+ return cast<llvm::InsertValueInst>(Val)->idx_end();
+ }
+ inline iterator_range<idx_iterator> indices() const {
+ return cast<llvm::InsertValueInst>(Val)->indices();
+ }
+
+ Value *getAggregateOperand() {
+ return getOperand(getAggregateOperandIndex());
+ }
+ const Value *getAggregateOperand() const {
+ return getOperand(getAggregateOperandIndex());
+ }
+ static unsigned getAggregateOperandIndex() {
+ return llvm::InsertValueInst::getAggregateOperandIndex();
+ }
+
+ Value *getInsertedValueOperand() {
+ return getOperand(getInsertedValueOperandIndex());
+ }
+ const Value *getInsertedValueOperand() const {
+ return getOperand(getInsertedValueOperandIndex());
+ }
+ static unsigned getInsertedValueOperandIndex() {
+ return llvm::InsertValueInst::getInsertedValueOperandIndex();
+ }
+
+ ArrayRef<unsigned> getIndices() const {
+ return cast<llvm::InsertValueInst>(Val)->getIndices();
+ }
+
+ unsigned getNumIndices() const {
+ return cast<llvm::InsertValueInst>(Val)->getNumIndices();
+ }
+
+ unsigned hasIndices() const {
+ return cast<llvm::InsertValueInst>(Val)->hasIndices();
+ }
+};
+
+class BranchInst : public SingleLLVMInstructionImpl<llvm::BranchInst> {
+ /// Use Context::createBranchInst(). Don't call the constructor directly.
+ BranchInst(llvm::BranchInst *BI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Br, Opcode::Br, BI, Ctx) {}
+ friend Context; // for BranchInst()
+
+public:
+ static BranchInst *create(BasicBlock *IfTrue, Instruction *InsertBefore,
+ Context &Ctx);
+ static BranchInst *create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd,
+ Context &Ctx);
+ static BranchInst *create(BasicBlock *IfTrue, BasicBlock *IfFalse,
+ Value *Cond, Instruction *InsertBefore,
+ Context &Ctx);
+ static BranchInst *create(BasicBlock *IfTrue, BasicBlock *IfFalse,
+ Value *Cond, BasicBlock *InsertAtEnd, Context &Ctx);
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From);
+ bool isUnconditional() const {
+ return cast<llvm::BranchInst>(Val)->isUnconditional();
+ }
+ bool isConditional() const {
+ return cast<llvm::BranchInst>(Val)->isConditional();
+ }
+ Value *getCondition() const;
+ void setCondition(Value *V) { setOperand(0, V); }
+ unsigned getNumSuccessors() const { return 1 + isConditional(); }
+ BasicBlock *getSuccessor(unsigned SuccIdx) const;
+ void setSuccessor(unsigned Idx, BasicBlock *NewSucc);
+ void swapSuccessors() { swapOperandsInternal(1, 2); }
+
+private:
+ struct LLVMBBToSBBB {
+ Context &Ctx;
+ LLVMBBToSBBB(Context &Ctx) : Ctx(Ctx) {}
+ BasicBlock *operator()(llvm::BasicBlock *BB) const;
+ };
+
+ struct ConstLLVMBBToSBBB {
+ Context &Ctx;
+ ConstLLVMBBToSBBB(Context &Ctx) : Ctx(Ctx) {}
+ const BasicBlock *operator()(const llvm::BasicBlock *BB) const;
+ };
+
+public:
+ using sb_succ_op_iterator =
+ mapped_iterator<llvm::BranchInst::succ_op_iterator, LLVMBBToSBBB>;
+ iterator_range<sb_succ_op_iterator> successors() {
+ iterator_range<llvm::BranchInst::succ_op_iterator> LLVMRange =
+ cast<llvm::BranchInst>(Val)->successors();
+ LLVMBBToSBBB BBMap(Ctx);
+ sb_succ_op_iterator MappedBegin = map_iterator(LLVMRange.begin(), BBMap);
+ sb_succ_op_iterator MappedEnd = map_iterator(LLVMRange.end(), BBMap);
+ return make_range(MappedBegin, MappedEnd);
+ }
+
+ using const_sb_succ_op_iterator =
+ mapped_iterator<llvm::BranchInst::const_succ_op_iterator,
+ ConstLLVMBBToSBBB>;
+ iterator_range<const_sb_succ_op_iterator> successors() const {
+ iterator_range<llvm::BranchInst::const_succ_op_iterator> ConstLLVMRange =
+ static_cast<const llvm::BranchInst *>(cast<llvm::BranchInst>(Val))
+ ->successors();
+ ConstLLVMBBToSBBB ConstBBMap(Ctx);
+ const_sb_succ_op_iterator ConstMappedBegin =
+ map_iterator(ConstLLVMRange.begin(), ConstBBMap);
+ const_sb_succ_op_iterator ConstMappedEnd =
+ map_iterator(ConstLLVMRange.end(), ConstBBMap);
+ return make_range(ConstMappedBegin, ConstMappedEnd);
+ }
+};
+
+/// An abstract class, parent of unary instructions.
+class UnaryInstruction
+ : public SingleLLVMInstructionImpl<llvm::UnaryInstruction> {
+protected:
+ UnaryInstruction(ClassID ID, Opcode Opc, llvm::Instruction *LLVMI,
+ Context &Ctx)
+ : SingleLLVMInstructionImpl(ID, Opc, LLVMI, Ctx) {}
+
+public:
+ static bool classof(const Instruction *I) {
+ return isa<LoadInst>(I) || isa<CastInst>(I) || isa<FreezeInst>(I);
+ }
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
+class ExtractValueInst : public UnaryInstruction {
+ /// Use Context::createExtractValueInst() instead.
+ ExtractValueInst(llvm::ExtractValueInst *EVI, Context &Ctx)
+ : UnaryInstruction(ClassID::ExtractValue, Opcode::ExtractValue, EVI,
+ Ctx) {}
+ friend Context; // for ExtractValueInst()
+
+public:
+ static Value *create(Value *Agg, ArrayRef<unsigned> Idxs, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::ExtractValue;
+ }
+
+ /// Returns the type of the element that would be extracted
+ /// with an extractvalue instruction with the specified parameters.
+ ///
+ /// Null is returned if the indices are invalid for the specified type.
+ static Type *getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs);
+
+ using idx_iterator = llvm::ExtractValueInst::idx_iterator;
+
+ inline idx_iterator idx_begin() const {
+ return cast<llvm::ExtractValueInst>(Val)->idx_begin();
+ }
+ inline idx_iterator idx_end() const {
+ return cast<llvm::ExtractValueInst>(Val)->idx_end();
+ }
+ inline iterator_range<idx_iterator> indices() const {
+ return cast<llvm::ExtractValueInst>(Val)->indices();
+ }
+
+ Value *getAggregateOperand() {
+ return getOperand(getAggregateOperandIndex());
+ }
+ const Value *getAggregateOperand() const {
+ return getOperand(getAggregateOperandIndex());
+ }
+ static unsigned getAggregateOperandIndex() {
+ return llvm::ExtractValueInst::getAggregateOperandIndex();
+ }
+
+ ArrayRef<unsigned> getIndices() const {
+ return cast<llvm::ExtractValueInst>(Val)->getIndices();
+ }
+
+ unsigned getNumIndices() const {
+ return cast<llvm::ExtractValueInst>(Val)->getNumIndices();
+ }
+
+ unsigned hasIndices() const {
+ return cast<llvm::ExtractValueInst>(Val)->hasIndices();
+ }
+};
+
+class VAArgInst : public UnaryInstruction {
+ VAArgInst(llvm::VAArgInst *FI, Context &Ctx)
+ : UnaryInstruction(ClassID::VAArg, Opcode::VAArg, FI, Ctx) {}
+ friend Context; // For constructor;
+
+public:
+ static VAArgInst *create(Value *List, Type *Ty, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+ Value *getPointerOperand();
+ const Value *getPointerOperand() const {
+ return const_cast<VAArgInst *>(this)->getPointerOperand();
+ }
+ static unsigned getPointerOperandIndex() {
+ return llvm::VAArgInst::getPointerOperandIndex();
+ }
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::VAArg;
+ }
+};
+
+class FreezeInst : public UnaryInstruction {
+ FreezeInst(llvm::FreezeInst *FI, Context &Ctx)
+ : UnaryInstruction(ClassID::Freeze, Opcode::Freeze, FI, Ctx) {}
+ friend Context; // For constructor;
+
+public:
+ static FreezeInst *create(Value *V, BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Freeze;
+ }
+};
+
+class LoadInst final : public UnaryInstruction {
+ /// Use LoadInst::create() instead of calling the constructor.
+ LoadInst(llvm::LoadInst *LI, Context &Ctx)
+ : UnaryInstruction(ClassID::Load, Opcode::Load, LI, Ctx) {}
+ friend Context; // for LoadInst()
+
+public:
+ /// Return true if this is a load from a volatile memory location.
+ bool isVolatile() const { return cast<llvm::LoadInst>(Val)->isVolatile(); }
+ /// Specify whether this is a volatile load or not.
+ void setVolatile(bool V);
+
+ static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, bool IsVolatile,
+ Context &Ctx, const Twine &Name = "");
+ static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, bool IsVolatile,
+ Context &Ctx, const Twine &Name = "");
+
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From);
+ Value *getPointerOperand() const;
+ Align getAlign() const { return cast<llvm::LoadInst>(Val)->getAlign(); }
+ bool isUnordered() const { return cast<llvm::LoadInst>(Val)->isUnordered(); }
+ bool isSimple() const { return cast<llvm::LoadInst>(Val)->isSimple(); }
+};
+
+class StoreInst final : public SingleLLVMInstructionImpl<llvm::StoreInst> {
+ /// Use StoreInst::create().
+ StoreInst(llvm::StoreInst *SI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Store, Opcode::Store, SI, Ctx) {}
+ friend Context; // for StoreInst()
+
+public:
+ /// Return true if this is a store from a volatile memory location.
+ bool isVolatile() const { return cast<llvm::StoreInst>(Val)->isVolatile(); }
+ /// Specify whether this is a volatile store or not.
+ void setVolatile(bool V);
+
+ static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, Context &Ctx);
+ static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, bool IsVolatile,
+ Context &Ctx);
+ static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, Context &Ctx);
+ static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, bool IsVolatile,
+ Context &Ctx);
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From);
+ Value *getValueOperand() const;
+ Value *getPointerOperand() const;
+ Align getAlign() const { return cast<llvm::StoreInst>(Val)->getAlign(); }
+ bool isSimple() const { return cast<llvm::StoreInst>(Val)->isSimple(); }
+ bool isUnordered() const { return cast<llvm::StoreInst>(Val)->isUnordered(); }
+};
+
+class UnreachableInst final : public Instruction {
+ /// Use UnreachableInst::create() instead of calling the constructor.
+ UnreachableInst(llvm::UnreachableInst *I, Context &Ctx)
+ : Instruction(ClassID::Unreachable, Opcode::Unreachable, I, Ctx) {}
+ friend Context;
+ Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
+ return getOperandUseDefault(OpIdx, Verify);
+ }
+ SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
+ return {cast<llvm::Instruction>(Val)};
+ }
+
+public:
+ static UnreachableInst *create(Instruction *InsertBefore, Context &Ctx);
+ static UnreachableInst *create(BasicBlock *InsertAtEnd, Context &Ctx);
+ static bool classof(const Value *From);
+ unsigned getNumSuccessors() const { return 0; }
+ unsigned getUseOperandNo(const Use &Use) const final {
+ llvm_unreachable("UnreachableInst has no operands!");
+ }
+ unsigned getNumOfIRInstrs() const final { return 1u; }
+};
+
+class ReturnInst final : public SingleLLVMInstructionImpl<llvm::ReturnInst> {
+ /// Use ReturnInst::create() instead of calling the constructor.
+ ReturnInst(llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Ret, Opcode::Ret, I, Ctx) {}
+ ReturnInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(SubclassID, Opcode::Ret, I, Ctx) {}
+ friend class Context; // For accessing the constructor in create*()
+ static ReturnInst *createCommon(Value *RetVal, IRBuilder<> &Builder,
+ Context &Ctx);
+
+public:
+ static ReturnInst *create(Value *RetVal, Instruction *InsertBefore,
+ Context &Ctx);
+ static ReturnInst *create(Value *RetVal, BasicBlock *InsertAtEnd,
+ Context &Ctx);
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Ret;
+ }
+ /// \Returns null if there is no return value.
+ Value *getReturnValue() const;
+};
+
+class CallBase : public SingleLLVMInstructionImpl<llvm::CallBase> {
+ CallBase(ClassID ID, Opcode Opc, llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(ID, Opc, I, Ctx) {}
+ friend class CallInst; // For constructor.
+ friend class InvokeInst; // For constructor.
+ friend class CallBrInst; // For constructor.
+
+public:
+ static bool classof(const Value *From) {
+ auto Opc = From->getSubclassID();
+ return Opc == Instruction::ClassID::Call ||
+ Opc == Instruction::ClassID::Invoke ||
+ Opc == Instruction::ClassID::CallBr;
+ }
+
+ FunctionType *getFunctionType() const;
+
+ op_iterator data_operands_begin() { return op_begin(); }
+ const_op_iterator data_operands_begin() const {
+ return const_cast<CallBase *>(this)->data_operands_begin();
+ }
+ op_iterator data_operands_end() {
+ auto *LLVMCB = cast<llvm::CallBase>(Val);
+ auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin();
+ return op_begin() + Dist;
+ }
+ const_op_iterator data_operands_end() const {
+ auto *LLVMCB = cast<llvm::CallBase>(Val);
+ auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin();
+ return op_begin() + Dist;
+ }
+ iterator_range<op_iterator> data_ops() {
+ return make_range(data_operands_begin(), data_operands_end());
+ }
+ iterator_range<const_op_iterator> data_ops() const {
+ return make_range(data_operands_begin(), data_operands_end());
+ }
+ bool data_operands_empty() const {
+ return data_operands_end() == data_operands_begin();
+ }
+ unsigned data_operands_size() const {
+ return std::distance(data_operands_begin(), data_operands_end());
+ }
+ bool isDataOperand(Use U) const {
+ assert(this == U.getUser() &&
+ "Only valid to query with a use of this instruction!");
+ return cast<llvm::CallBase>(Val)->isDataOperand(U.LLVMUse);
+ }
+ unsigned getDataOperandNo(Use U) const {
+ assert(isDataOperand(U) && "Data operand # out of range!");
+ return cast<llvm::CallBase>(Val)->getDataOperandNo(U.LLVMUse);
+ }
+
+ /// Return the total number operands (not operand bundles) used by
+ /// every operand bundle in this OperandBundleUser.
+ unsigned getNumTotalBundleOperands() const {
+ return cast<llvm::CallBase>(Val)->getNumTotalBundleOperands();
+ }
+
+ op_iterator arg_begin() { return op_begin(); }
+ const_op_iterator arg_begin() const { return op_begin(); }
+ op_iterator arg_end() {
+ return data_operands_end() - getNumTotalBundleOperands();
+ }
+ const_op_iterator arg_end() const {
+ return const_cast<CallBase *>(this)->arg_end();
+ }
+ iterator_range<op_iterator> args() {
+ return make_range(arg_begin(), arg_end());
+ }
+ iterator_range<const_op_iterator> args() const {
+ return make_range(arg_begin(), arg_end());
+ }
+ bool arg_empty() const { return arg_end() == arg_begin(); }
+ unsigned arg_size() const { return arg_end() - arg_begin(); }
+
+ Value *getArgOperand(unsigned OpIdx) const {
+ assert(OpIdx < arg_size() && "Out of bounds!");
+ return getOperand(OpIdx);
+ }
+ void setArgOperand(unsigned OpIdx, Value *NewOp) {
+ assert(OpIdx < arg_size() && "Out of bounds!");
+ setOperand(OpIdx, NewOp);
+ }
+
+ Use getArgOperandUse(unsigned Idx) const {
+ assert(Idx < arg_size() && "Out of bounds!");
+ return getOperandUse(Idx);
+ }
+ Use getArgOperandUse(unsigned Idx) {
+ assert(Idx < arg_size() && "Out of bounds!");
+ return getOperandUse(Idx);
+ }
+
+ bool isArgOperand(Use U) const {
+ return cast<llvm::CallBase>(Val)->isArgOperand(U.LLVMUse);
+ }
+ unsigned getArgOperandNo(Use U) const {
+ return cast<llvm::CallBase>(Val)->getArgOperandNo(U.LLVMUse);
+ }
+ bool hasArgument(const Value *V) const { return is_contained(args(), V); }
+
+ Value *getCalledOperand() const;
+ Use getCalledOperandUse() const;
+
+ Function *getCalledFunction() const;
+ bool isIndirectCall() const {
+ return cast<llvm::CallBase>(Val)->isIndirectCall();
+ }
+ bool isCallee(Use U) const {
+ return cast<llvm::CallBase>(Val)->isCallee(U.LLVMUse);
+ }
+ Function *getCaller();
+ const Function *getCaller() const {
+ return const_cast<CallBase *>(this)->getCaller();
+ }
+ bool isMustTailCall() const {
+ return cast<llvm::CallBase>(Val)->isMustTailCall();
+ }
+ bool isTailCall() const { return cast<llvm::CallBase>(Val)->isTailCall(); }
+ Intrinsic::ID getIntrinsicID() const {
+ return cast<llvm::CallBase>(Val)->getIntrinsicID();
+ }
+ void setCalledOperand(Value *V) { getCalledOperandUse().set(V); }
+ void setCalledFunction(Function *F);
+ CallingConv::ID getCallingConv() const {
+ return cast<llvm::CallBase>(Val)->getCallingConv();
+ }
+ bool isInlineAsm() const { return cast<llvm::CallBase>(Val)->isInlineAsm(); }
+};
+
+class CallInst final : public CallBase {
+ /// Use Context::createCallInst(). Don't call the
+ /// constructor directly.
+ CallInst(llvm::Instruction *I, Context &Ctx)
+ : CallBase(ClassID::Call, Opcode::Call, I, Ctx) {}
+ friend class Context; // For accessing the constructor in
+ // create*()
+
+public:
+ static CallInst *create(FunctionType *FTy, Value *Func,
+ ArrayRef<Value *> Args, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr = "");
+ static CallInst *create(FunctionType *FTy, Value *Func,
+ ArrayRef<Value *> Args, Instruction *InsertBefore,
+ Context &Ctx, const Twine &NameStr = "");
+ static CallInst *create(FunctionType *FTy, Value *Func,
+ ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &NameStr = "");
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Call;
+ }
+};
+
+class InvokeInst final : public CallBase {
+ /// Use Context::createInvokeInst(). Don't call the
+ /// constructor directly.
+ InvokeInst(llvm::Instruction *I, Context &Ctx)
+ : CallBase(ClassID::Invoke, Opcode::Invoke, I, Ctx) {}
+ friend class Context; // For accessing the constructor in
+ // create*()
+
+public:
+ static InvokeInst *create(FunctionType *FTy, Value *Func,
+ BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr = "");
+ static InvokeInst *create(FunctionType *FTy, Value *Func,
+ BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, Instruction *InsertBefore,
+ Context &Ctx, const Twine &NameStr = "");
+ static InvokeInst *create(FunctionType *FTy, Value *Func,
+ BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &NameStr = "");
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Invoke;
+ }
+ BasicBlock *getNormalDest() const;
+ BasicBlock *getUnwindDest() const;
+ void setNormalDest(BasicBlock *BB);
+ void setUnwindDest(BasicBlock *BB);
+ LandingPadInst *getLandingPadInst() const;
+ BasicBlock *getSuccessor(unsigned SuccIdx) const;
+ void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) {
+ assert(SuccIdx < 2 && "Successor # out of range for invoke!");
+ if (SuccIdx == 0)
+ setNormalDest(NewSucc);
+ else
+ setUnwindDest(NewSucc);
+ }
+ unsigned getNumSuccessors() const {
+ return cast<llvm::InvokeInst>(Val)->getNumSuccessors();
+ }
+};
+
+class CallBrInst final : public CallBase {
+ /// Use Context::createCallBrInst(). Don't call the
+ /// constructor directly.
+ CallBrInst(llvm::Instruction *I, Context &Ctx)
+ : CallBase(ClassID::CallBr, Opcode::CallBr, I, Ctx) {}
+ friend class Context; // For accessing the constructor in
+ // create*()
+
+public:
+ static CallBrInst *create(FunctionType *FTy, Value *Func,
+ BasicBlock *DefaultDest,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr = "");
+ static CallBrInst *create(FunctionType *FTy, Value *Func,
+ BasicBlock *DefaultDest,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args, Instruction *InsertBefore,
+ Context &Ctx, const Twine &NameStr = "");
+ static CallBrInst *create(FunctionType *FTy, Value *Func,
+ BasicBlock *DefaultDest,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &NameStr = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CallBr;
+ }
+ unsigned getNumIndirectDests() const {
+ return cast<llvm::CallBrInst>(Val)->getNumIndirectDests();
+ }
+ Value *getIndirectDestLabel(unsigned Idx) const;
+ Value *getIndirectDestLabelUse(unsigned Idx) const;
+ BasicBlock *getDefaultDest() const;
+ BasicBlock *getIndirectDest(unsigned Idx) const;
+ SmallVector<BasicBlock *, 16> getIndirectDests() const;
+ void setDefaultDest(BasicBlock *BB);
+ void setIndirectDest(unsigned Idx, BasicBlock *BB);
+ BasicBlock *getSuccessor(unsigned Idx) const;
+ unsigned getNumSuccessors() const {
+ return cast<llvm::CallBrInst>(Val)->getNumSuccessors();
+ }
+};
+
+class LandingPadInst : public SingleLLVMInstructionImpl<llvm::LandingPadInst> {
+ LandingPadInst(llvm::LandingPadInst *LP, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::LandingPad, Opcode::LandingPad, LP,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static LandingPadInst *create(Type *RetTy, unsigned NumReservedClauses,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+ /// Return 'true' if this landingpad instruction is a
+ /// cleanup. I.e., it should be run when unwinding even if its landing pad
+ /// doesn't catch the exception.
+ bool isCleanup() const {
+ return cast<llvm::LandingPadInst>(Val)->isCleanup();
+ }
+ /// Indicate that this landingpad instruction is a cleanup.
+ void setCleanup(bool V);
+
+ // TODO: We are not implementing addClause() because we have no way to revert
+ // it for now.
+
+ /// Get the value of the clause at index Idx. Use isCatch/isFilter to
+ /// determine what type of clause this is.
+ Constant *getClause(unsigned Idx) const;
+
+ /// Return 'true' if the clause and index Idx is a catch clause.
+ bool isCatch(unsigned Idx) const {
+ return cast<llvm::LandingPadInst>(Val)->isCatch(Idx);
+ }
+ /// Return 'true' if the clause and index Idx is a filter clause.
+ bool isFilter(unsigned Idx) const {
+ return cast<llvm::LandingPadInst>(Val)->isFilter(Idx);
+ }
+ /// Get the number of clauses for this landing pad.
+ unsigned getNumClauses() const {
+ return cast<llvm::LandingPadInst>(Val)->getNumOperands();
+ }
+ // TODO: We are not implementing reserveClauses() because we can't revert it.
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::LandingPad;
+ }
+};
+
+class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
+ FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
+ Context &Ctx)
+ : SingleLLVMInstructionImpl(SubclassID, Opc, I, Ctx) {}
+ friend class CatchPadInst; // For constructor.
+ friend class CleanupPadInst; // For constructor.
+
+public:
+ /// Return the number of funcletpad arguments.
+ unsigned arg_size() const {
+ return cast<llvm::FuncletPadInst>(Val)->arg_size();
+ }
+ /// Return the outer EH-pad this funclet is nested within.
+ ///
+ /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
+ /// is a CatchPadInst.
+ Value *getParentPad() const;
+ void setParentPad(Value *ParentPad);
+ /// Return the Idx-th funcletpad argument.
+ Value *getArgOperand(unsigned Idx) const;
+ /// Set the Idx-th funcletpad argument.
+ void setArgOperand(unsigned Idx, Value *V);
+
+ // TODO: Implement missing functions: arg_operands().
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CatchPad ||
+ From->getSubclassID() == ClassID::CleanupPad;
+ }
+};
+
+class CatchPadInst : public FuncletPadInst {
+ CatchPadInst(llvm::CatchPadInst *CPI, Context &Ctx)
+ : FuncletPadInst(ClassID::CatchPad, Opcode::CatchPad, CPI, Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ CatchSwitchInst *getCatchSwitch() const;
+ // TODO: We have not implemented setCatchSwitch() because we can't revert it
+ // for now, as there is no CatchPadInst member function that can undo it.
+
+ static CatchPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CatchPad;
+ }
+};
+
+class CleanupPadInst : public FuncletPadInst {
+ CleanupPadInst(llvm::CleanupPadInst *CPI, Context &Ctx)
+ : FuncletPadInst(ClassID::CleanupPad, Opcode::CleanupPad, CPI, Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static CleanupPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CleanupPad;
+ }
+};
+
+class CatchReturnInst
+ : public SingleLLVMInstructionImpl<llvm::CatchReturnInst> {
+ CatchReturnInst(llvm::CatchReturnInst *CRI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::CatchRet, Opcode::CatchRet, CRI,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static CatchReturnInst *create(CatchPadInst *CatchPad, BasicBlock *BB,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx);
+ CatchPadInst *getCatchPad() const;
+ void setCatchPad(CatchPadInst *CatchPad);
+ BasicBlock *getSuccessor() const;
+ void setSuccessor(BasicBlock *NewSucc);
+ unsigned getNumSuccessors() {
+ return cast<llvm::CatchReturnInst>(Val)->getNumSuccessors();
+ }
+ Value *getCatchSwitchParentPad() const;
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CatchRet;
+ }
+};
+
+class CleanupReturnInst
+ : public SingleLLVMInstructionImpl<llvm::CleanupReturnInst> {
+ CleanupReturnInst(llvm::CleanupReturnInst *CRI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::CleanupRet, Opcode::CleanupRet, CRI,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static CleanupReturnInst *create(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx);
+ bool hasUnwindDest() const {
+ return cast<llvm::CleanupReturnInst>(Val)->hasUnwindDest();
+ }
+ bool unwindsToCaller() const {
+ return cast<llvm::CleanupReturnInst>(Val)->unwindsToCaller();
+ }
+ CleanupPadInst *getCleanupPad() const;
+ void setCleanupPad(CleanupPadInst *CleanupPad);
+ unsigned getNumSuccessors() const {
+ return cast<llvm::CleanupReturnInst>(Val)->getNumSuccessors();
+ }
+ BasicBlock *getUnwindDest() const;
+ void setUnwindDest(BasicBlock *NewDest);
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CleanupRet;
+ }
+};
+
+class GetElementPtrInst final
+ : public SingleLLVMInstructionImpl<llvm::GetElementPtrInst> {
+ /// Use Context::createGetElementPtrInst(). Don't call
+ /// the constructor directly.
+ GetElementPtrInst(llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::GetElementPtr, Opcode::GetElementPtr,
+ I, Ctx) {}
+ GetElementPtrInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
+ : SingleLLVMInstructionImpl(SubclassID, Opcode::GetElementPtr, I, Ctx) {}
+ friend class Context; // For accessing the constructor in
+ // create*()
+
+public:
+ static Value *create(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
+ BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr = "");
+ static Value *create(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &NameStr = "");
+ static Value *create(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &NameStr = "");
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::GetElementPtr;
+ }
+
+ Type *getSourceElementType() const;
+ Type *getResultElementType() const;
+ unsigned getAddressSpace() const {
+ return cast<llvm::GetElementPtrInst>(Val)->getAddressSpace();
+ }
+
+ inline op_iterator idx_begin() { return op_begin() + 1; }
+ inline const_op_iterator idx_begin() const {
+ return const_cast<GetElementPtrInst *>(this)->idx_begin();
+ }
+ inline op_iterator idx_end() { return op_end(); }
+ inline const_op_iterator idx_end() const {
+ return const_cast<GetElementPtrInst *>(this)->idx_end();
+ }
+ inline iterator_range<op_iterator> indices() {
+ return make_range(idx_begin(), idx_end());
+ }
+ inline iterator_range<const_op_iterator> indices() const {
+ return const_cast<GetElementPtrInst *>(this)->indices();
+ }
+
+ Value *getPointerOperand() const;
+ static unsigned getPointerOperandIndex() {
+ return llvm::GetElementPtrInst::getPointerOperandIndex();
+ }
+ Type *getPointerOperandType() const;
+ unsigned getPointerAddressSpace() const {
+ return cast<llvm::GetElementPtrInst>(Val)->getPointerAddressSpace();
+ }
+ unsigned getNumIndices() const {
+ return cast<llvm::GetElementPtrInst>(Val)->getNumIndices();
+ }
+ bool hasIndices() const {
+ return cast<llvm::GetElementPtrInst>(Val)->hasIndices();
+ }
+ bool hasAllConstantIndices() const {
+ return cast<llvm::GetElementPtrInst>(Val)->hasAllConstantIndices();
+ }
+ GEPNoWrapFlags getNoWrapFlags() const {
+ return cast<llvm::GetElementPtrInst>(Val)->getNoWrapFlags();
+ }
+ bool isInBounds() const {
+ return cast<llvm::GetElementPtrInst>(Val)->isInBounds();
+ }
+ bool hasNoUnsignedSignedWrap() const {
+ return cast<llvm::GetElementPtrInst>(Val)->hasNoUnsignedSignedWrap();
+ }
+ bool hasNoUnsignedWrap() const {
+ return cast<llvm::GetElementPtrInst>(Val)->hasNoUnsignedWrap();
+ }
+ bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const {
+ return cast<llvm::GetElementPtrInst>(Val)->accumulateConstantOffset(DL,
+ Offset);
+ }
+ // TODO: Add missing member functions.
+};
+
+class CatchSwitchInst
+ : public SingleLLVMInstructionImpl<llvm::CatchSwitchInst> {
+public:
+ CatchSwitchInst(llvm::CatchSwitchInst *CSI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::CatchSwitch, Opcode::CatchSwitch,
+ CSI, Ctx) {}
+
+ static CatchSwitchInst *create(Value *ParentPad, BasicBlock *UnwindBB,
+ unsigned NumHandlers, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+
+ Value *getParentPad() const;
+ void setParentPad(Value *ParentPad);
+
+ bool hasUnwindDest() const {
+ return cast<llvm::CatchSwitchInst>(Val)->hasUnwindDest();
+ }
+ bool unwindsToCaller() const {
+ return cast<llvm::CatchSwitchInst>(Val)->unwindsToCaller();
+ }
+ BasicBlock *getUnwindDest() const;
+ void setUnwindDest(BasicBlock *UnwindDest);
+
+ unsigned getNumHandlers() const {
+ return cast<llvm::CatchSwitchInst>(Val)->getNumHandlers();
+ }
+
+private:
+ static BasicBlock *handler_helper(Value *V) { return cast<BasicBlock>(V); }
+ static const BasicBlock *handler_helper(const Value *V) {
+ return cast<BasicBlock>(V);
+ }
+
+public:
+ using DerefFnTy = BasicBlock *(*)(Value *);
+ using handler_iterator = mapped_iterator<op_iterator, DerefFnTy>;
+ using handler_range = iterator_range<handler_iterator>;
+ using ConstDerefFnTy = const BasicBlock *(*)(const Value *);
+ using const_handler_iterator =
+ mapped_iterator<const_op_iterator, ConstDerefFnTy>;
+ using const_handler_range = iterator_range<const_handler_iterator>;
+
+ handler_iterator handler_begin() {
+ op_iterator It = op_begin() + 1;
+ if (hasUnwindDest())
+ ++It;
+ return handler_iterator(It, DerefFnTy(handler_helper));
+ }
+ const_handler_iterator handler_begin() const {
+ const_op_iterator It = op_begin() + 1;
+ if (hasUnwindDest())
+ ++It;
+ return const_handler_iterator(It, ConstDerefFnTy(handler_helper));
+ }
+ handler_iterator handler_end() {
+ return handler_iterator(op_end(), DerefFnTy(handler_helper));
+ }
+ const_handler_iterator handler_end() const {
+ return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper));
+ }
+ handler_range handlers() {
+ return make_range(handler_begin(), handler_end());
+ }
+ const_handler_range handlers() const {
+ return make_range(handler_begin(), handler_end());
+ }
+
+ void addHandler(BasicBlock *Dest);
+
+ // TODO: removeHandler() cannot be reverted because there is no equivalent
+ // addHandler() with a handler_iterator to specify the position. So we can't
+ // implement it for now.
+
+ unsigned getNumSuccessors() const { return getNumOperands() - 1; }
+ BasicBlock *getSuccessor(unsigned Idx) const {
+ assert(Idx < getNumSuccessors() &&
+ "Successor # out of range for catchswitch!");
+ return cast<BasicBlock>(getOperand(Idx + 1));
+ }
+ void setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
+ assert(Idx < getNumSuccessors() &&
+ "Successor # out of range for catchswitch!");
+ setOperand(Idx + 1, NewSucc);
+ }
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::CatchSwitch;
+ }
+};
+
+class ResumeInst : public SingleLLVMInstructionImpl<llvm::ResumeInst> {
+public:
+ ResumeInst(llvm::ResumeInst *CSI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Resume, Opcode::Resume, CSI, Ctx) {}
+
+ static ResumeInst *create(Value *Exn, BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx);
+ Value *getValue() const;
+ unsigned getNumSuccessors() const {
+ return cast<llvm::ResumeInst>(Val)->getNumSuccessors();
+ }
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Resume;
+ }
+};
+
+class SwitchInst : public SingleLLVMInstructionImpl<llvm::SwitchInst> {
+public:
+ SwitchInst(llvm::SwitchInst *SI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Switch, Opcode::Switch, SI, Ctx) {}
+
+ static constexpr const unsigned DefaultPseudoIndex =
+ llvm::SwitchInst::DefaultPseudoIndex;
+
+ static SwitchInst *create(Value *V, BasicBlock *Dest, unsigned NumCases,
+ BasicBlock::iterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+
+ Value *getCondition() const;
+ void setCondition(Value *V);
+ BasicBlock *getDefaultDest() const;
+ bool defaultDestUndefined() const {
+ return cast<llvm::SwitchInst>(Val)->defaultDestUndefined();
+ }
+ void setDefaultDest(BasicBlock *DefaultCase);
+ unsigned getNumCases() const {
+ return cast<llvm::SwitchInst>(Val)->getNumCases();
+ }
+
+ using CaseHandle =
+ llvm::SwitchInst::CaseHandleImpl<SwitchInst, ConstantInt, BasicBlock>;
+ using ConstCaseHandle =
+ llvm::SwitchInst::CaseHandleImpl<const SwitchInst, const ConstantInt,
+ const BasicBlock>;
+ using CaseIt = llvm::SwitchInst::CaseIteratorImpl<CaseHandle>;
+ using ConstCaseIt = llvm::SwitchInst::CaseIteratorImpl<ConstCaseHandle>;
+
+ /// Returns a read/write iterator that points to the first case in the
+ /// SwitchInst.
+ CaseIt case_begin() { return CaseIt(this, 0); }
+ ConstCaseIt case_begin() const { return ConstCaseIt(this, 0); }
+ /// Returns a read/write iterator that points one past the last in the
+ /// SwitchInst.
+ CaseIt case_end() { return CaseIt(this, getNumCases()); }
+ ConstCaseIt case_end() const { return ConstCaseIt(this, getNumCases()); }
+ /// Iteration adapter for range-for loops.
+ iterator_range<CaseIt> cases() {
+ return make_range(case_begin(), case_end());
+ }
+ iterator_range<ConstCaseIt> cases() const {
+ return make_range(case_begin(), case_end());
+ }
+ CaseIt case_default() { return CaseIt(this, DefaultPseudoIndex); }
+ ConstCaseIt case_default() const {
+ return ConstCaseIt(this, DefaultPseudoIndex);
+ }
+ CaseIt findCaseValue(const ConstantInt *C) {
+ return CaseIt(
+ this,
+ const_cast<const SwitchInst *>(this)->findCaseValue(C)->getCaseIndex());
+ }
+ ConstCaseIt findCaseValue(const ConstantInt *C) const {
+ ConstCaseIt I = llvm::find_if(cases(), [C](const ConstCaseHandle &Case) {
+ return Case.getCaseValue() == C;
+ });
+ if (I != case_end())
+ return I;
+ return case_default();
+ }
+ ConstantInt *findCaseDest(BasicBlock *BB);
+
+ void addCase(ConstantInt *OnVal, BasicBlock *Dest);
+ /// This method removes the specified case and its successor from the switch
+ /// instruction. Note that this operation may reorder the remaining cases at
+ /// index idx and above.
+ /// Note:
+ /// This action invalidates iterators for all cases following the one removed,
+ /// including the case_end() iterator. It returns an iterator for the next
+ /// case.
+ CaseIt removeCase(CaseIt It);
+
+ unsigned getNumSuccessors() const {
+ return cast<llvm::SwitchInst>(Val)->getNumSuccessors();
+ }
+ BasicBlock *getSuccessor(unsigned Idx) const;
+ void setSuccessor(unsigned Idx, BasicBlock *NewSucc);
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Switch;
+ }
+};
+
+class UnaryOperator : public UnaryInstruction {
+ static Opcode getUnaryOpcode(llvm::Instruction::UnaryOps UnOp) {
+ switch (UnOp) {
+ case llvm::Instruction::FNeg:
+ return Opcode::FNeg;
+ case llvm::Instruction::UnaryOpsEnd:
+ llvm_unreachable("Bad UnOp!");
+ }
+ llvm_unreachable("Unhandled UnOp!");
+ }
+ UnaryOperator(llvm::UnaryOperator *UO, Context &Ctx)
+ : UnaryInstruction(ClassID::UnOp, getUnaryOpcode(UO->getOpcode()), UO,
+ Ctx) {}
+ friend Context; // for constructor.
+public:
+ static Value *create(Instruction::Opcode Op, Value *OpV, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Instruction::Opcode Op, Value *OpV,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Instruction::Opcode Op, Value *OpV,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
+ Value *CopyFrom, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+ static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
+ Value *CopyFrom,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
+ Value *CopyFrom, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &Name = "");
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::UnOp;
+ }
+};
+
+class BinaryOperator : public SingleLLVMInstructionImpl<llvm::BinaryOperator> {
+protected:
+ static Opcode getBinOpOpcode(llvm::Instruction::BinaryOps BinOp) {
+ switch (BinOp) {
+ case llvm::Instruction::Add:
+ return Opcode::Add;
+ case llvm::Instruction::FAdd:
+ return Opcode::FAdd;
+ case llvm::Instruction::Sub:
+ return Opcode::Sub;
+ case llvm::Instruction::FSub:
+ return Opcode::FSub;
+ case llvm::Instruction::Mul:
+ return Opcode::Mul;
+ case llvm::Instruction::FMul:
+ return Opcode::FMul;
+ case llvm::Instruction::UDiv:
+ return Opcode::UDiv;
+ case llvm::Instruction::SDiv:
+ return Opcode::SDiv;
+ case llvm::Instruction::FDiv:
+ return Opcode::FDiv;
+ case llvm::Instruction::URem:
+ return Opcode::URem;
+ case llvm::Instruction::SRem:
+ return Opcode::SRem;
+ case llvm::Instruction::FRem:
+ return Opcode::FRem;
+ case llvm::Instruction::Shl:
+ return Opcode::Shl;
+ case llvm::Instruction::LShr:
+ return Opcode::LShr;
+ case llvm::Instruction::AShr:
+ return Opcode::AShr;
+ case llvm::Instruction::And:
+ return Opcode::And;
+ case llvm::Instruction::Or:
+ return Opcode::Or;
+ case llvm::Instruction::Xor:
+ return Opcode::Xor;
+ case llvm::Instruction::BinaryOpsEnd:
+ llvm_unreachable("Bad BinOp!");
+ }
+ llvm_unreachable("Unhandled BinOp!");
+ }
+ BinaryOperator(llvm::BinaryOperator *BinOp, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::BinaryOperator,
+ getBinOpOpcode(BinOp->getOpcode()), BinOp,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS,
+ BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+
+ static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
+ Value *RHS, Value *CopyFrom,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name = "");
+ static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
+ Value *RHS, Value *CopyFrom,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
+ Value *RHS, Value *CopyFrom,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::BinaryOperator;
+ }
+ void swapOperands() { swapOperandsInternal(0, 1); }
+};
+
+/// An or instruction, which can be marked as "disjoint", indicating that the
+/// inputs don't have a 1 in the same bit position. Meaning this instruction
+/// can also be treated as an add.
+class PossiblyDisjointInst : public BinaryOperator {
+public:
+ void setIsDisjoint(bool B);
+ bool isDisjoint() const {
+ return cast<llvm::PossiblyDisjointInst>(Val)->isDisjoint();
+ }
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From) {
+ return isa<Instruction>(From) &&
+ cast<Instruction>(From)->getOpcode() == Opcode::Or;
+ }
+};
+
+class AtomicRMWInst : public SingleLLVMInstructionImpl<llvm::AtomicRMWInst> {
+ AtomicRMWInst(llvm::AtomicRMWInst *Atomic, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::AtomicRMW,
+ Instruction::Opcode::AtomicRMW, Atomic, Ctx) {
+ }
+ friend class Context; // For constructor.
+
+public:
+ using BinOp = llvm::AtomicRMWInst::BinOp;
+ BinOp getOperation() const {
+ return cast<llvm::AtomicRMWInst>(Val)->getOperation();
+ }
+ static StringRef getOperationName(BinOp Op) {
+ return llvm::AtomicRMWInst::getOperationName(Op);
+ }
+ static bool isFPOperation(BinOp Op) {
+ return llvm::AtomicRMWInst::isFPOperation(Op);
+ }
+ void setOperation(BinOp Op) {
+ cast<llvm::AtomicRMWInst>(Val)->setOperation(Op);
+ }
+ Align getAlign() const { return cast<llvm::AtomicRMWInst>(Val)->getAlign(); }
+ void setAlignment(Align Align);
+ bool isVolatile() const {
+ return cast<llvm::AtomicRMWInst>(Val)->isVolatile();
+ }
+ void setVolatile(bool V);
+ AtomicOrdering getOrdering() const {
+ return cast<llvm::AtomicRMWInst>(Val)->getOrdering();
+ }
+ void setOrdering(AtomicOrdering Ordering);
+ SyncScope::ID getSyncScopeID() const {
+ return cast<llvm::AtomicRMWInst>(Val)->getSyncScopeID();
+ }
+ void setSyncScopeID(SyncScope::ID SSID);
+ Value *getPointerOperand();
+ const Value *getPointerOperand() const {
+ return const_cast<AtomicRMWInst *>(this)->getPointerOperand();
+ }
+ Value *getValOperand();
+ const Value *getValOperand() const {
+ return const_cast<AtomicRMWInst *>(this)->getValOperand();
+ }
+ unsigned getPointerAddressSpace() const {
+ return cast<llvm::AtomicRMWInst>(Val)->getPointerAddressSpace();
+ }
+ bool isFloatingPointOperation() const {
+ return cast<llvm::AtomicRMWInst>(Val)->isFloatingPointOperation();
+ }
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::AtomicRMW;
+ }
+
+ static AtomicRMWInst *create(BinOp Op, Value *Ptr, Value *Val,
+ MaybeAlign Align, AtomicOrdering Ordering,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System,
+ const Twine &Name = "");
+ static AtomicRMWInst *create(BinOp Op, Value *Ptr, Value *Val,
+ MaybeAlign Align, AtomicOrdering Ordering,
+ Instruction *InsertBefore, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System,
+ const Twine &Name = "");
+ static AtomicRMWInst *create(BinOp Op, Value *Ptr, Value *Val,
+ MaybeAlign Align, AtomicOrdering Ordering,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System,
+ const Twine &Name = "");
+};
+
+class AtomicCmpXchgInst
+ : public SingleLLVMInstructionImpl<llvm::AtomicCmpXchgInst> {
+ AtomicCmpXchgInst(llvm::AtomicCmpXchgInst *Atomic, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::AtomicCmpXchg,
+ Instruction::Opcode::AtomicCmpXchg, Atomic,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ /// Return the alignment of the memory that is being allocated by the
+ /// instruction.
+ Align getAlign() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->getAlign();
+ }
+
+ void setAlignment(Align Align);
+ /// Return true if this is a cmpxchg from a volatile memory
+ /// location.
+ bool isVolatile() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->isVolatile();
+ }
+ /// Specify whether this is a volatile cmpxchg.
+ void setVolatile(bool V);
+ /// Return true if this cmpxchg may spuriously fail.
+ bool isWeak() const { return cast<llvm::AtomicCmpXchgInst>(Val)->isWeak(); }
+ void setWeak(bool IsWeak);
+ static bool isValidSuccessOrdering(AtomicOrdering Ordering) {
+ return llvm::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering);
+ }
+ static bool isValidFailureOrdering(AtomicOrdering Ordering) {
+ return llvm::AtomicCmpXchgInst::isValidFailureOrdering(Ordering);
+ }
+ AtomicOrdering getSuccessOrdering() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->getSuccessOrdering();
+ }
+ void setSuccessOrdering(AtomicOrdering Ordering);
+
+ AtomicOrdering getFailureOrdering() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->getFailureOrdering();
+ }
+ void setFailureOrdering(AtomicOrdering Ordering);
+ AtomicOrdering getMergedOrdering() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->getMergedOrdering();
+ }
+ SyncScope::ID getSyncScopeID() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->getSyncScopeID();
+ }
+ void setSyncScopeID(SyncScope::ID SSID);
+ Value *getPointerOperand();
+ const Value *getPointerOperand() const {
+ return const_cast<AtomicCmpXchgInst *>(this)->getPointerOperand();
+ }
+
+ Value *getCompareOperand();
+ const Value *getCompareOperand() const {
+ return const_cast<AtomicCmpXchgInst *>(this)->getCompareOperand();
+ }
+
+ Value *getNewValOperand();
+ const Value *getNewValOperand() const {
+ return const_cast<AtomicCmpXchgInst *>(this)->getNewValOperand();
+ }
+
+ /// Returns the address space of the pointer operand.
+ unsigned getPointerAddressSpace() const {
+ return cast<llvm::AtomicCmpXchgInst>(Val)->getPointerAddressSpace();
+ }
+
+ static AtomicCmpXchgInst *
+ create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
+ AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
+ BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System, const Twine &Name = "");
+ static AtomicCmpXchgInst *
+ create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
+ AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
+ Instruction *InsertBefore, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System, const Twine &Name = "");
+ static AtomicCmpXchgInst *
+ create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
+ AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ SyncScope::ID SSID = SyncScope::System, const Twine &Name = "");
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::AtomicCmpXchg;
+ }
+};
+
+class AllocaInst final : public UnaryInstruction {
+ AllocaInst(llvm::AllocaInst *AI, Context &Ctx)
+ : UnaryInstruction(ClassID::Alloca, Instruction::Opcode::Alloca, AI,
+ Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static AllocaInst *create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ Value *ArraySize = nullptr, const Twine &Name = "");
+ static AllocaInst *create(Type *Ty, unsigned AddrSpace,
+ Instruction *InsertBefore, Context &Ctx,
+ Value *ArraySize = nullptr, const Twine &Name = "");
+ static AllocaInst *create(Type *Ty, unsigned AddrSpace,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ Value *ArraySize = nullptr, const Twine &Name = "");
+
+ /// Return true if there is an allocation size parameter to the allocation
+ /// instruction that is not 1.
+ bool isArrayAllocation() const {
+ return cast<llvm::AllocaInst>(Val)->isArrayAllocation();
+ }
+ /// Get the number of elements allocated. For a simple allocation of a single
+ /// element, this will return a constant 1 value.
+ Value *getArraySize();
+ const Value *getArraySize() const {
+ return const_cast<AllocaInst *>(this)->getArraySize();
+ }
+ /// Overload to return most specific pointer type.
+ PointerType *getType() const;
+ /// Return the address space for the allocation.
+ unsigned getAddressSpace() const {
+ return cast<llvm::AllocaInst>(Val)->getAddressSpace();
+ }
+ /// Get allocation size in bytes. Returns std::nullopt if size can't be
+ /// determined, e.g. in case of a VLA.
+ std::optional<TypeSize> getAllocationSize(const DataLayout &DL) const {
+ return cast<llvm::AllocaInst>(Val)->getAllocationSize(DL);
+ }
+ /// Get allocation size in bits. Returns std::nullopt if size can't be
+ /// determined, e.g. in case of a VLA.
+ std::optional<TypeSize> getAllocationSizeInBits(const DataLayout &DL) const {
+ return cast<llvm::AllocaInst>(Val)->getAllocationSizeInBits(DL);
+ }
+ /// Return the type that is being allocated by the instruction.
+ Type *getAllocatedType() const;
+ /// for use only in special circumstances that need to generically
+ /// transform a whole instruction (eg: IR linking and vectorization).
+ void setAllocatedType(Type *Ty);
+ /// Return the alignment of the memory that is being allocated by the
+ /// instruction.
+ Align getAlign() const { return cast<llvm::AllocaInst>(Val)->getAlign(); }
+ void setAlignment(Align Align);
+ /// Return true if this alloca is in the entry block of the function and is a
+ /// constant size. If so, the code generator will fold it into the
+ /// prolog/epilog code, so it is basically free.
+ bool isStaticAlloca() const {
+ return cast<llvm::AllocaInst>(Val)->isStaticAlloca();
+ }
+ /// Return true if this alloca is used as an inalloca argument to a call. Such
+ /// allocas are never considered static even if they are in the entry block.
+ bool isUsedWithInAlloca() const {
+ return cast<llvm::AllocaInst>(Val)->isUsedWithInAlloca();
+ }
+ /// Specify whether this alloca is used to represent the arguments to a call.
+ void setUsedWithInAlloca(bool V);
+
+ static bool classof(const Value *From) {
+ if (auto *I = dyn_cast<Instruction>(From))
+ return I->getSubclassID() == Instruction::ClassID::Alloca;
+ return false;
+ }
+};
+
+class CastInst : public UnaryInstruction {
+ static Opcode getCastOpcode(llvm::Instruction::CastOps CastOp) {
+ switch (CastOp) {
+ case llvm::Instruction::ZExt:
+ return Opcode::ZExt;
+ case llvm::Instruction::SExt:
+ return Opcode::SExt;
+ case llvm::Instruction::FPToUI:
+ return Opcode::FPToUI;
+ case llvm::Instruction::FPToSI:
+ return Opcode::FPToSI;
+ case llvm::Instruction::FPExt:
+ return Opcode::FPExt;
+ case llvm::Instruction::PtrToInt:
+ return Opcode::PtrToInt;
+ case llvm::Instruction::IntToPtr:
+ return Opcode::IntToPtr;
+ case llvm::Instruction::SIToFP:
+ return Opcode::SIToFP;
+ case llvm::Instruction::UIToFP:
+ return Opcode::UIToFP;
+ case llvm::Instruction::Trunc:
+ return Opcode::Trunc;
+ case llvm::Instruction::FPTrunc:
+ return Opcode::FPTrunc;
+ case llvm::Instruction::BitCast:
+ return Opcode::BitCast;
+ case llvm::Instruction::AddrSpaceCast:
+ return Opcode::AddrSpaceCast;
+ case llvm::Instruction::CastOpsEnd:
+ llvm_unreachable("Bad CastOp!");
+ }
+ llvm_unreachable("Unhandled CastOp!");
+ }
+ /// Use Context::createCastInst(). Don't call the
+ /// constructor directly.
+ CastInst(llvm::CastInst *CI, Context &Ctx)
+ : UnaryInstruction(ClassID::Cast, getCastOpcode(CI->getOpcode()), CI,
+ Ctx) {}
+ friend Context; // for SBCastInstruction()
+
+public:
+ static Value *create(Type *DestTy, Opcode Op, Value *Operand,
+ BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Type *DestTy, Opcode Op, Value *Operand,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static Value *create(Type *DestTy, Opcode Op, Value *Operand,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name = "");
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From);
+ Type *getSrcTy() const;
+ Type *getDestTy() const;
+};
+
+/// Instruction that can have a nneg flag (zext/uitofp).
+class PossiblyNonNegInst : public CastInst {
+public:
+ bool hasNonNeg() const {
+ return cast<llvm::PossiblyNonNegInst>(Val)->hasNonNeg();
+ }
+ void setNonNeg(bool B);
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From) {
+ if (auto *I = dyn_cast<Instruction>(From)) {
+ switch (I->getOpcode()) {
+ case Opcode::ZExt:
+ case Opcode::UIToFP:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+};
+
+// Helper class to simplify stamping out CastInst subclasses.
+template <Instruction::Opcode Op> class CastInstImpl : public CastInst {
+public:
+ static Value *create(Value *Src, Type *DestTy, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name = "") {
+ return CastInst::create(DestTy, Op, Src, WhereIt, WhereBB, Ctx, Name);
+ }
+ static Value *create(Value *Src, Type *DestTy, Instruction *InsertBefore,
+ Context &Ctx, const Twine &Name = "") {
+ return create(Src, DestTy, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, Name);
+ }
+ static Value *create(Value *Src, Type *DestTy, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &Name = "") {
+ return create(Src, DestTy, InsertAtEnd->end(), InsertAtEnd, Ctx, Name);
+ }
+
+ static bool classof(const Value *From) {
+ if (auto *I = dyn_cast<Instruction>(From))
+ return I->getOpcode() == Op;
+ return false;
+ }
+};
+
+class TruncInst final : public CastInstImpl<Instruction::Opcode::Trunc> {};
+class ZExtInst final : public CastInstImpl<Instruction::Opcode::ZExt> {};
+class SExtInst final : public CastInstImpl<Instruction::Opcode::SExt> {};
+class FPTruncInst final : public CastInstImpl<Instruction::Opcode::FPTrunc> {};
+class FPExtInst final : public CastInstImpl<Instruction::Opcode::FPExt> {};
+class UIToFPInst final : public CastInstImpl<Instruction::Opcode::UIToFP> {};
+class SIToFPInst final : public CastInstImpl<Instruction::Opcode::SIToFP> {};
+class FPToUIInst final : public CastInstImpl<Instruction::Opcode::FPToUI> {};
+class FPToSIInst final : public CastInstImpl<Instruction::Opcode::FPToSI> {};
+class IntToPtrInst final : public CastInstImpl<Instruction::Opcode::IntToPtr> {
+};
+class PtrToIntInst final : public CastInstImpl<Instruction::Opcode::PtrToInt> {
+};
+class BitCastInst final : public CastInstImpl<Instruction::Opcode::BitCast> {};
+class AddrSpaceCastInst final
+ : public CastInstImpl<Instruction::Opcode::AddrSpaceCast> {
+public:
+ /// \Returns the pointer operand.
+ Value *getPointerOperand() { return getOperand(0); }
+ /// \Returns the pointer operand.
+ const Value *getPointerOperand() const {
+ return const_cast<AddrSpaceCastInst *>(this)->getPointerOperand();
+ }
+ /// \Returns the operand index of the pointer operand.
+ static unsigned getPointerOperandIndex() { return 0u; }
+ /// \Returns the address space of the pointer operand.
+ unsigned getSrcAddressSpace() const {
+ return getPointerOperand()->getType()->getPointerAddressSpace();
+ }
+ /// \Returns the address space of the result.
+ unsigned getDestAddressSpace() const {
+ return getType()->getPointerAddressSpace();
+ }
+};
+
+class PHINode final : public SingleLLVMInstructionImpl<llvm::PHINode> {
+ /// Use Context::createPHINode(). Don't call the constructor directly.
+ PHINode(llvm::PHINode *PHI, Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::PHI, Opcode::PHI, PHI, Ctx) {}
+ friend Context; // for PHINode()
+ /// Helper for mapped_iterator.
+ struct LLVMBBToBB {
+ Context &Ctx;
+ LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
+ BasicBlock *operator()(llvm::BasicBlock *LLVMBB) const;
+ };
+
+public:
+ static PHINode *create(Type *Ty, unsigned NumReservedValues,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ /// For isa/dyn_cast.
+ static bool classof(const Value *From);
+
+ using const_block_iterator =
+ mapped_iterator<llvm::PHINode::const_block_iterator, LLVMBBToBB>;
+
+ const_block_iterator block_begin() const {
+ LLVMBBToBB BBGetter(Ctx);
+ return const_block_iterator(cast<llvm::PHINode>(Val)->block_begin(),
+ BBGetter);
+ }
+ const_block_iterator block_end() const {
+ LLVMBBToBB BBGetter(Ctx);
+ return const_block_iterator(cast<llvm::PHINode>(Val)->block_end(),
+ BBGetter);
+ }
+ iterator_range<const_block_iterator> blocks() const {
+ return make_range(block_begin(), block_end());
+ }
+
+ op_range incoming_values() { return operands(); }
+
+ const_op_range incoming_values() const { return operands(); }
+
+ unsigned getNumIncomingValues() const {
+ return cast<llvm::PHINode>(Val)->getNumIncomingValues();
+ }
+ Value *getIncomingValue(unsigned Idx) const;
+ void setIncomingValue(unsigned Idx, Value *V);
+ static unsigned getOperandNumForIncomingValue(unsigned Idx) {
+ return llvm::PHINode::getOperandNumForIncomingValue(Idx);
+ }
+ static unsigned getIncomingValueNumForOperand(unsigned Idx) {
+ return llvm::PHINode::getIncomingValueNumForOperand(Idx);
+ }
+ BasicBlock *getIncomingBlock(unsigned Idx) const;
+ BasicBlock *getIncomingBlock(const Use &U) const;
+
+ void setIncomingBlock(unsigned Idx, BasicBlock *BB);
+
+ void addIncoming(Value *V, BasicBlock *BB);
+
+ Value *removeIncomingValue(unsigned Idx);
+ Value *removeIncomingValue(BasicBlock *BB);
+
+ int getBasicBlockIndex(const BasicBlock *BB) const;
+ Value *getIncomingValueForBlock(const BasicBlock *BB) const;
+
+ Value *hasConstantValue() const;
+
+ bool hasConstantOrUndefValue() const {
+ return cast<llvm::PHINode>(Val)->hasConstantOrUndefValue();
+ }
+ bool isComplete() const { return cast<llvm::PHINode>(Val)->isComplete(); }
+ void replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New);
+ void removeIncomingValueIf(function_ref<bool(unsigned)> Predicate);
+ // TODO: Implement
+ // void copyIncomingBlocks(iterator_range<const_block_iterator> BBRange,
+ // uint32_t ToIdx = 0)
+};
+
+// Wraps a static function that takes a single Predicate parameter
+// LLVMValType should be the type of the wrapped class
+#define WRAP_STATIC_PREDICATE(FunctionName) \
+ static auto FunctionName(Predicate P) { return LLVMValType::FunctionName(P); }
+// Wraps a member function that takes no parameters
+// LLVMValType should be the type of the wrapped class
+#define WRAP_MEMBER(FunctionName) \
+ auto FunctionName() const { return cast<LLVMValType>(Val)->FunctionName(); }
+// Wraps both--a common idiom in the CmpInst classes
+#define WRAP_BOTH(FunctionName) \
+ WRAP_STATIC_PREDICATE(FunctionName) \
+ WRAP_MEMBER(FunctionName)
+
+class CmpInst : public SingleLLVMInstructionImpl<llvm::CmpInst> {
+protected:
+ using LLVMValType = llvm::CmpInst;
+ /// Use Context::createCmpInst(). Don't call the constructor directly.
+ CmpInst(llvm::CmpInst *CI, Context &Ctx, ClassID Id, Opcode Opc)
+ : SingleLLVMInstructionImpl(Id, Opc, CI, Ctx) {}
+ friend Context; // for CmpInst()
+ static Value *createCommon(Value *Cond, Value *True, Value *False,
+ const Twine &Name, IRBuilder<> &Builder,
+ Context &Ctx);
+
+public:
+ using Predicate = llvm::CmpInst::Predicate;
+
+ static CmpInst *create(Predicate Pred, Value *S1, Value *S2,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ static CmpInst *createWithCopiedFlags(Predicate Pred, Value *S1, Value *S2,
+ const Instruction *FlagsSource,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name = "");
+ void setPredicate(Predicate P);
+ void swapOperands();
+
+ WRAP_MEMBER(getPredicate);
+ WRAP_BOTH(isFPPredicate);
+ WRAP_BOTH(isIntPredicate);
+ WRAP_STATIC_PREDICATE(getPredicateName);
+ WRAP_BOTH(getInversePredicate);
+ WRAP_BOTH(getOrderedPredicate);
+ WRAP_BOTH(getUnorderedPredicate);
+ WRAP_BOTH(getSwappedPredicate);
+ WRAP_BOTH(isStrictPredicate);
+ WRAP_BOTH(isNonStrictPredicate);
+ WRAP_BOTH(getStrictPredicate);
+ WRAP_BOTH(getNonStrictPredicate);
+ WRAP_BOTH(getFlippedStrictnessPredicate);
+ WRAP_MEMBER(isCommutative);
+ WRAP_BOTH(isEquality);
+ WRAP_BOTH(isRelational);
+ WRAP_BOTH(isSigned);
+ WRAP_BOTH(getSignedPredicate);
+ WRAP_BOTH(getUnsignedPredicate);
+ WRAP_BOTH(getFlippedSignednessPredicate);
+ WRAP_BOTH(isTrueWhenEqual);
+ WRAP_BOTH(isFalseWhenEqual);
+ WRAP_BOTH(isUnsigned);
+ WRAP_STATIC_PREDICATE(isOrdered);
+ WRAP_STATIC_PREDICATE(isUnordered);
+
+ static bool isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
+ return llvm::CmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
+ }
+ static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2) {
+ return llvm::CmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
+ }
+
+ /// Method for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::ICmp ||
+ From->getSubclassID() == ClassID::FCmp;
+ }
+
+ /// Create a result type for fcmp/icmp
+ static Type *makeCmpResultType(Type *OpndType);
+
+#ifndef NDEBUG
+ void dumpOS(raw_ostream &OS) const override;
+ LLVM_DUMP_METHOD void dump() const;
+#endif
+};
+
+class ICmpInst : public CmpInst {
+ /// Use Context::createICmpInst(). Don't call the constructor directly.
+ ICmpInst(llvm::ICmpInst *CI, Context &Ctx)
+ : CmpInst(CI, Ctx, ClassID::ICmp, Opcode::ICmp) {}
+ friend class Context; // For constructor.
+ using LLVMValType = llvm::ICmpInst;
+
+public:
+ void swapOperands();
+
+ WRAP_BOTH(getSignedPredicate);
+ WRAP_BOTH(getUnsignedPredicate);
+ WRAP_BOTH(isEquality);
+ WRAP_MEMBER(isCommutative);
+ WRAP_MEMBER(isRelational);
+ WRAP_STATIC_PREDICATE(isGT);
+ WRAP_STATIC_PREDICATE(isLT);
+ WRAP_STATIC_PREDICATE(isGE);
+ WRAP_STATIC_PREDICATE(isLE);
+
+ static auto predicates() { return llvm::ICmpInst::predicates(); }
+ static bool compare(const APInt &LHS, const APInt &RHS,
+ ICmpInst::Predicate Pred) {
+ return llvm::ICmpInst::compare(LHS, RHS, Pred);
+ }
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::ICmp;
+ }
+};
+
+class FCmpInst : public CmpInst {
+ /// Use Context::createFCmpInst(). Don't call the constructor directly.
+ FCmpInst(llvm::FCmpInst *CI, Context &Ctx)
+ : CmpInst(CI, Ctx, ClassID::FCmp, Opcode::FCmp) {}
+ friend class Context; // For constructor.
+ using LLVMValType = llvm::FCmpInst;
+
+public:
+ void swapOperands();
+
+ WRAP_BOTH(isEquality);
+ WRAP_MEMBER(isCommutative);
+ WRAP_MEMBER(isRelational);
+
+ static auto predicates() { return llvm::FCmpInst::predicates(); }
+ static bool compare(const APFloat &LHS, const APFloat &RHS,
+ FCmpInst::Predicate Pred) {
+ return llvm::FCmpInst::compare(LHS, RHS, Pred);
+ }
+
+ static bool classof(const Value *From) {
+ return From->getSubclassID() == ClassID::FCmp;
+ }
+};
+
+#undef WRAP_STATIC_PREDICATE
+#undef WRAP_MEMBER
+#undef WRAP_BOTH
+
+/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
+/// an OpaqueInstr.
+class OpaqueInst : public SingleLLVMInstructionImpl<llvm::Instruction> {
+ OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx)
+ : SingleLLVMInstructionImpl(ClassID::Opaque, Opcode::Opaque, I, Ctx) {}
+ OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
+ : SingleLLVMInstructionImpl(SubclassID, Opcode::Opaque, I, Ctx) {}
+ friend class Context; // For constructor.
+
+public:
+ static bool classof(const sandboxir::Value *From) {
+ return From->getSubclassID() == ClassID::Opaque;
+ }
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_SANDBOXIR_INSTRUCTION_H
diff --git a/llvm/include/llvm/SandboxIR/Region.h b/llvm/include/llvm/SandboxIR/Region.h
index 884f1324df7829..67411f3fb741da 100644
--- a/llvm/include/llvm/SandboxIR/Region.h
+++ b/llvm/include/llvm/SandboxIR/Region.h
@@ -13,7 +13,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm::sandboxir {
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 2376450d190115..85fa7ad8e40640 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -192,2724 +192,6 @@ class CmpInst;
class ICmpInst;
class FCmpInst;
-/// A sandboxir::User with operands, opcode and linked with previous/next
-/// instructions in an instruction list.
-class Instruction : public sandboxir::User {
-public:
- enum class Opcode {
-#define OP(OPC) OPC,
-#define OPCODES(...) __VA_ARGS__
-#define DEF_INSTR(ID, OPC, CLASS) OPC
-#include "llvm/SandboxIR/SandboxIRValues.def"
- };
-
-protected:
- Instruction(ClassID ID, Opcode Opc, llvm::Instruction *I,
- sandboxir::Context &SBCtx)
- : sandboxir::User(ID, I, SBCtx), Opc(Opc) {}
-
- Opcode Opc;
-
- /// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This
- /// returns its topmost LLVM IR instruction.
- llvm::Instruction *getTopmostLLVMInstruction() const;
- friend class VAArgInst; // For getTopmostLLVMInstruction().
- friend class FreezeInst; // For getTopmostLLVMInstruction().
- friend class FenceInst; // For getTopmostLLVMInstruction().
- friend class SelectInst; // For getTopmostLLVMInstruction().
- friend class ExtractElementInst; // For getTopmostLLVMInstruction().
- friend class InsertElementInst; // For getTopmostLLVMInstruction().
- friend class ShuffleVectorInst; // For getTopmostLLVMInstruction().
- friend class ExtractValueInst; // For getTopmostLLVMInstruction().
- friend class InsertValueInst; // For getTopmostLLVMInstruction().
- friend class BranchInst; // For getTopmostLLVMInstruction().
- friend class LoadInst; // For getTopmostLLVMInstruction().
- friend class StoreInst; // For getTopmostLLVMInstruction().
- friend class ReturnInst; // For getTopmostLLVMInstruction().
- friend class CallInst; // For getTopmostLLVMInstruction().
- friend class InvokeInst; // For getTopmostLLVMInstruction().
- friend class CallBrInst; // For getTopmostLLVMInstruction().
- friend class LandingPadInst; // For getTopmostLLVMInstruction().
- friend class CatchPadInst; // For getTopmostLLVMInstruction().
- friend class CleanupPadInst; // For getTopmostLLVMInstruction().
- friend class CatchReturnInst; // For getTopmostLLVMInstruction().
- friend class CleanupReturnInst; // For getTopmostLLVMInstruction().
- friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
- friend class ResumeInst; // For getTopmostLLVMInstruction().
- friend class CatchSwitchInst; // For getTopmostLLVMInstruction().
- friend class SwitchInst; // For getTopmostLLVMInstruction().
- friend class UnaryOperator; // For getTopmostLLVMInstruction().
- friend class BinaryOperator; // For getTopmostLLVMInstruction().
- friend class AtomicRMWInst; // For getTopmostLLVMInstruction().
- friend class AtomicCmpXchgInst; // For getTopmostLLVMInstruction().
- friend class AllocaInst; // For getTopmostLLVMInstruction().
- friend class CastInst; // For getTopmostLLVMInstruction().
- friend class PHINode; // For getTopmostLLVMInstruction().
- friend class UnreachableInst; // For getTopmostLLVMInstruction().
- friend class CmpInst; // For getTopmostLLVMInstruction().
-
- /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
- /// order.
- virtual SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const = 0;
- friend class EraseFromParent; // For getLLVMInstrs().
-
-public:
- static const char *getOpcodeName(Opcode Opc);
- /// This is used by BasicBlock::iterator.
- virtual unsigned getNumOfIRInstrs() const = 0;
- /// \Returns a BasicBlock::iterator for this Instruction.
- BBIterator getIterator() const;
- /// \Returns the next sandboxir::Instruction in the block, or nullptr if at
- /// the end of the block.
- Instruction *getNextNode() const;
- /// \Returns the previous sandboxir::Instruction in the block, or nullptr if
- /// at the beginning of the block.
- Instruction *getPrevNode() const;
- /// \Returns this Instruction's opcode. Note that SandboxIR has its own opcode
- /// state to allow for new SandboxIR-specific instructions.
- Opcode getOpcode() const { return Opc; }
-
- const char *getOpcodeName() const { return getOpcodeName(Opc); }
-
- // Note that these functions below are calling into llvm::Instruction.
- // A sandbox IR instruction could introduce a new opcode that could change the
- // behavior of one of these functions. It is better that these functions are
- // only added as needed and new sandbox IR instructions must explicitly check
- // if any of these functions could have a different behavior.
-
- bool isTerminator() const {
- return cast<llvm::Instruction>(Val)->isTerminator();
- }
- bool isUnaryOp() const { return cast<llvm::Instruction>(Val)->isUnaryOp(); }
- bool isBinaryOp() const { return cast<llvm::Instruction>(Val)->isBinaryOp(); }
- bool isIntDivRem() const {
- return cast<llvm::Instruction>(Val)->isIntDivRem();
- }
- bool isShift() const { return cast<llvm::Instruction>(Val)->isShift(); }
- bool isCast() const { return cast<llvm::Instruction>(Val)->isCast(); }
- bool isFuncletPad() const {
- return cast<llvm::Instruction>(Val)->isFuncletPad();
- }
- bool isSpecialTerminator() const {
- return cast<llvm::Instruction>(Val)->isSpecialTerminator();
- }
- bool isOnlyUserOfAnyOperand() const {
- return cast<llvm::Instruction>(Val)->isOnlyUserOfAnyOperand();
- }
- bool isLogicalShift() const {
- return cast<llvm::Instruction>(Val)->isLogicalShift();
- }
-
- //===--------------------------------------------------------------------===//
- // Metadata manipulation.
- //===--------------------------------------------------------------------===//
-
- /// Return true if the instruction has any metadata attached to it.
- bool hasMetadata() const {
- return cast<llvm::Instruction>(Val)->hasMetadata();
- }
-
- /// Return true if this instruction has metadata attached to it other than a
- /// debug location.
- bool hasMetadataOtherThanDebugLoc() const {
- return cast<llvm::Instruction>(Val)->hasMetadataOtherThanDebugLoc();
- }
-
- /// Return true if this instruction has the given type of metadata attached.
- bool hasMetadata(unsigned KindID) const {
- return cast<llvm::Instruction>(Val)->hasMetadata(KindID);
- }
-
- // TODO: Implement getMetadata and getAllMetadata after sandboxir::MDNode is
- // available.
-
- // TODO: More missing functions
-
- /// Detach this from its parent BasicBlock without deleting it.
- void removeFromParent();
- /// Detach this Value from its parent and delete it.
- void eraseFromParent();
- /// Insert this detached instruction before \p BeforeI.
- void insertBefore(Instruction *BeforeI);
- /// Insert this detached instruction after \p AfterI.
- void insertAfter(Instruction *AfterI);
- /// Insert this detached instruction into \p BB at \p WhereIt.
- void insertInto(BasicBlock *BB, const BBIterator &WhereIt);
- /// Move this instruction to \p WhereIt.
- void moveBefore(BasicBlock &BB, const BBIterator &WhereIt);
- /// Move this instruction before \p Before.
- void moveBefore(Instruction *Before) {
- moveBefore(*Before->getParent(), Before->getIterator());
- }
- /// Move this instruction after \p After.
- void moveAfter(Instruction *After) {
- moveBefore(*After->getParent(), std::next(After->getIterator()));
- }
- // TODO: This currently relies on LLVM IR Instruction::comesBefore which is
- // can be linear-time.
- /// Given an instruction Other in the same basic block as this instruction,
- /// return true if this instruction comes before Other.
- bool comesBefore(const Instruction *Other) const {
- return cast<llvm::Instruction>(Val)->comesBefore(
- cast<llvm::Instruction>(Other->Val));
- }
- /// \Returns the BasicBlock containing this Instruction, or null if it is
- /// detached.
- BasicBlock *getParent() const;
- /// For isa/dyn_cast.
- static bool classof(const sandboxir::Value *From);
-
- /// Determine whether the no signed wrap flag is set.
- bool hasNoUnsignedWrap() const {
- return cast<llvm::Instruction>(Val)->hasNoUnsignedWrap();
- }
- /// Set or clear the nuw flag on this instruction, which must be an operator
- /// which supports this flag. See LangRef.html for the meaning of this flag.
- void setHasNoUnsignedWrap(bool B = true);
- /// Determine whether the no signed wrap flag is set.
- bool hasNoSignedWrap() const {
- return cast<llvm::Instruction>(Val)->hasNoSignedWrap();
- }
- /// Set or clear the nsw flag on this instruction, which must be an operator
- /// which supports this flag. See LangRef.html for the meaning of this flag.
- void setHasNoSignedWrap(bool B = true);
- /// Determine whether all fast-math-flags are set.
- bool isFast() const { return cast<llvm::Instruction>(Val)->isFast(); }
- /// Set or clear all fast-math-flags on this instruction, which must be an
- /// operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setFast(bool B);
- /// Determine whether the allow-reassociation flag is set.
- bool hasAllowReassoc() const {
- return cast<llvm::Instruction>(Val)->hasAllowReassoc();
- }
- /// Set or clear the reassociation flag on this instruction, which must be
- /// an operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setHasAllowReassoc(bool B);
- /// Determine whether the exact flag is set.
- bool isExact() const { return cast<llvm::Instruction>(Val)->isExact(); }
- /// Set or clear the exact flag on this instruction, which must be an operator
- /// which supports this flag. See LangRef.html for the meaning of this flag.
- void setIsExact(bool B = true);
- /// Determine whether the no-NaNs flag is set.
- bool hasNoNaNs() const { return cast<llvm::Instruction>(Val)->hasNoNaNs(); }
- /// Set or clear the no-nans flag on this instruction, which must be an
- /// operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setHasNoNaNs(bool B);
- /// Determine whether the no-infs flag is set.
- bool hasNoInfs() const { return cast<llvm::Instruction>(Val)->hasNoInfs(); }
- /// Set or clear the no-infs flag on this instruction, which must be an
- /// operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setHasNoInfs(bool B);
- /// Determine whether the no-signed-zeros flag is set.
- bool hasNoSignedZeros() const {
- return cast<llvm::Instruction>(Val)->hasNoSignedZeros();
- }
- /// Set or clear the no-signed-zeros flag on this instruction, which must be
- /// an operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setHasNoSignedZeros(bool B);
- /// Determine whether the allow-reciprocal flag is set.
- bool hasAllowReciprocal() const {
- return cast<llvm::Instruction>(Val)->hasAllowReciprocal();
- }
- /// Set or clear the allow-reciprocal flag on this instruction, which must be
- /// an operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setHasAllowReciprocal(bool B);
- /// Determine whether the allow-contract flag is set.
- bool hasAllowContract() const {
- return cast<llvm::Instruction>(Val)->hasAllowContract();
- }
- /// Set or clear the allow-contract flag on this instruction, which must be
- /// an operator which supports this flag. See LangRef.html for the meaning of
- /// this flag.
- void setHasAllowContract(bool B);
- /// Determine whether the approximate-math-functions flag is set.
- bool hasApproxFunc() const {
- return cast<llvm::Instruction>(Val)->hasApproxFunc();
- }
- /// Set or clear the approximate-math-functions flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html for
- /// the meaning of this flag.
- void setHasApproxFunc(bool B);
- /// Convenience function for getting all the fast-math flags, which must be an
- /// operator which supports these flags. See LangRef.html for the meaning of
- /// these flags.
- FastMathFlags getFastMathFlags() const {
- return cast<llvm::Instruction>(Val)->getFastMathFlags();
- }
- /// Convenience function for setting multiple fast-math flags on this
- /// instruction, which must be an operator which supports these flags. See
- /// LangRef.html for the meaning of these flags.
- void setFastMathFlags(FastMathFlags FMF);
- /// Convenience function for transferring all fast-math flag values to this
- /// instruction, which must be an operator which supports these flags. See
- /// LangRef.html for the meaning of these flags.
- void copyFastMathFlags(FastMathFlags FMF);
-
- bool isAssociative() const {
- return cast<llvm::Instruction>(Val)->isAssociative();
- }
-
- bool isCommutative() const {
- return cast<llvm::Instruction>(Val)->isCommutative();
- }
-
- bool isIdempotent() const {
- return cast<llvm::Instruction>(Val)->isIdempotent();
- }
-
- bool isNilpotent() const {
- return cast<llvm::Instruction>(Val)->isNilpotent();
- }
-
- bool mayWriteToMemory() const {
- return cast<llvm::Instruction>(Val)->mayWriteToMemory();
- }
-
- bool mayReadFromMemory() const {
- return cast<llvm::Instruction>(Val)->mayReadFromMemory();
- }
- bool mayReadOrWriteMemory() const {
- return cast<llvm::Instruction>(Val)->mayReadOrWriteMemory();
- }
-
- bool isAtomic() const { return cast<llvm::Instruction>(Val)->isAtomic(); }
-
- bool hasAtomicLoad() const {
- return cast<llvm::Instruction>(Val)->hasAtomicLoad();
- }
-
- bool hasAtomicStore() const {
- return cast<llvm::Instruction>(Val)->hasAtomicStore();
- }
-
- bool isVolatile() const { return cast<llvm::Instruction>(Val)->isVolatile(); }
-
- Type *getAccessType() const;
-
- bool mayThrow(bool IncludePhaseOneUnwind = false) const {
- return cast<llvm::Instruction>(Val)->mayThrow(IncludePhaseOneUnwind);
- }
-
- bool isFenceLike() const {
- return cast<llvm::Instruction>(Val)->isFenceLike();
- }
-
- bool mayHaveSideEffects() const {
- return cast<llvm::Instruction>(Val)->mayHaveSideEffects();
- }
-
- // TODO: Missing functions.
-
- bool isStackSaveOrRestoreIntrinsic() const {
- auto *I = cast<llvm::Instruction>(Val);
- return match(I,
- PatternMatch::m_Intrinsic<llvm::Intrinsic::stackrestore>()) ||
- match(I, PatternMatch::m_Intrinsic<llvm::Intrinsic::stacksave>());
- }
-
- /// We consider \p I as a Memory Dependency Candidate instruction if it
- /// reads/write memory or if it has side-effects. This is used by the
- /// dependency graph.
- bool isMemDepCandidate() const {
- auto *I = cast<llvm::Instruction>(Val);
- return I->mayReadOrWriteMemory() &&
- (!isa<llvm::IntrinsicInst>(I) ||
- (cast<llvm::IntrinsicInst>(I)->getIntrinsicID() !=
- Intrinsic::sideeffect &&
- cast<llvm::IntrinsicInst>(I)->getIntrinsicID() !=
- Intrinsic::pseudoprobe));
- }
-
-#ifndef NDEBUG
- void dumpOS(raw_ostream &OS) const override;
-#endif
-};
-
-/// Instructions that contain a single LLVM Instruction can inherit from this.
-template <typename LLVMT> class SingleLLVMInstructionImpl : public Instruction {
- SingleLLVMInstructionImpl(ClassID ID, Opcode Opc, llvm::Instruction *I,
- sandboxir::Context &SBCtx)
- : Instruction(ID, Opc, I, SBCtx) {}
-
- // All instructions are friends with this so they can call the constructor.
-#define DEF_INSTR(ID, OPC, CLASS) friend class CLASS;
-#include "llvm/SandboxIR/SandboxIRValues.def"
- friend class UnaryInstruction;
- friend class CallBase;
- friend class FuncletPadInst;
- friend class CmpInst;
-
- Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
- return getOperandUseDefault(OpIdx, Verify);
- }
- SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
- return {cast<llvm::Instruction>(Val)};
- }
-
-public:
- unsigned getUseOperandNo(const Use &Use) const final {
- return getUseOperandNoDefault(Use);
- }
- unsigned getNumOfIRInstrs() const final { return 1u; }
-#ifndef NDEBUG
- void verify() const final { assert(isa<LLVMT>(Val) && "Expected LLVMT!"); }
- void dumpOS(raw_ostream &OS) const override {
- dumpCommonPrefix(OS);
- dumpCommonSuffix(OS);
- }
-#endif
-};
-
-class FenceInst : public SingleLLVMInstructionImpl<llvm::FenceInst> {
- FenceInst(llvm::FenceInst *FI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Fence, Opcode::Fence, FI, Ctx) {}
- friend Context; // For constructor;
-
-public:
- static FenceInst *create(AtomicOrdering Ordering, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- SyncScope::ID SSID = SyncScope::System);
- /// Returns the ordering constraint of this fence instruction.
- AtomicOrdering getOrdering() const {
- return cast<llvm::FenceInst>(Val)->getOrdering();
- }
- /// Sets the ordering constraint of this fence instruction. May only be
- /// Acquire, Release, AcquireRelease, or SequentiallyConsistent.
- void setOrdering(AtomicOrdering Ordering);
- /// Returns the synchronization scope ID of this fence instruction.
- SyncScope::ID getSyncScopeID() const {
- return cast<llvm::FenceInst>(Val)->getSyncScopeID();
- }
- /// Sets the synchronization scope ID of this fence instruction.
- void setSyncScopeID(SyncScope::ID SSID);
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Fence;
- }
-};
-
-class SelectInst : public SingleLLVMInstructionImpl<llvm::SelectInst> {
- /// Use Context::createSelectInst(). Don't call the
- /// constructor directly.
- SelectInst(llvm::SelectInst *CI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Select, Opcode::Select, CI, Ctx) {}
- friend Context; // for SelectInst()
- static Value *createCommon(Value *Cond, Value *True, Value *False,
- const Twine &Name, IRBuilder<> &Builder,
- Context &Ctx);
-
-public:
- static Value *create(Value *Cond, Value *True, Value *False,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Value *Cond, Value *True, Value *False,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
-
- const Value *getCondition() const { return getOperand(0); }
- const Value *getTrueValue() const { return getOperand(1); }
- const Value *getFalseValue() const { return getOperand(2); }
- Value *getCondition() { return getOperand(0); }
- Value *getTrueValue() { return getOperand(1); }
- Value *getFalseValue() { return getOperand(2); }
-
- void setCondition(Value *New) { setOperand(0, New); }
- void setTrueValue(Value *New) { setOperand(1, New); }
- void setFalseValue(Value *New) { setOperand(2, New); }
- void swapValues();
-
- /// Return a string if the specified operands are invalid for a select
- /// operation, otherwise return null.
- static const char *areInvalidOperands(Value *Cond, Value *True,
- Value *False) {
- return llvm::SelectInst::areInvalidOperands(Cond->Val, True->Val,
- False->Val);
- }
-
- /// For isa/dyn_cast.
- static bool classof(const Value *From);
-};
-
-class InsertElementInst final
- : public SingleLLVMInstructionImpl<llvm::InsertElementInst> {
- /// Use Context::createInsertElementInst() instead.
- InsertElementInst(llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::InsertElement, Opcode::InsertElement,
- I, Ctx) {}
- friend class Context; // For accessing the constructor in create*()
-
-public:
- static Value *create(Value *Vec, Value *NewElt, Value *Idx,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Value *Vec, Value *NewElt, Value *Idx,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::InsertElement;
- }
- static bool isValidOperands(const Value *Vec, const Value *NewElt,
- const Value *Idx) {
- return llvm::InsertElementInst::isValidOperands(Vec->Val, NewElt->Val,
- Idx->Val);
- }
-};
-
-class ExtractElementInst final
- : public SingleLLVMInstructionImpl<llvm::ExtractElementInst> {
- /// Use Context::createExtractElementInst() instead.
- ExtractElementInst(llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::ExtractElement,
- Opcode::ExtractElement, I, Ctx) {}
- friend class Context; // For accessing the constructor in
- // create*()
-
-public:
- static Value *create(Value *Vec, Value *Idx, Instruction *InsertBefore,
- Context &Ctx, const Twine &Name = "");
- static Value *create(Value *Vec, Value *Idx, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &Name = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::ExtractElement;
- }
-
- static bool isValidOperands(const Value *Vec, const Value *Idx) {
- return llvm::ExtractElementInst::isValidOperands(Vec->Val, Idx->Val);
- }
- Value *getVectorOperand() { return getOperand(0); }
- Value *getIndexOperand() { return getOperand(1); }
- const Value *getVectorOperand() const { return getOperand(0); }
- const Value *getIndexOperand() const { return getOperand(1); }
- VectorType *getVectorOperandType() const;
-};
-
-class ShuffleVectorInst final
- : public SingleLLVMInstructionImpl<llvm::ShuffleVectorInst> {
- /// Use Context::createShuffleVectorInst() instead.
- ShuffleVectorInst(llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::ShuffleVector, Opcode::ShuffleVector,
- I, Ctx) {}
- friend class Context; // For accessing the constructor in create*()
-
-public:
- static Value *create(Value *V1, Value *V2, Value *Mask,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Value *V1, Value *V2, Value *Mask,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Value *V1, Value *V2, ArrayRef<int> Mask,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Value *V1, Value *V2, ArrayRef<int> Mask,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::ShuffleVector;
- }
-
- /// Swap the operands and adjust the mask to preserve the semantics of the
- /// instruction.
- void commute();
-
- /// Return true if a shufflevector instruction can be formed with the
- /// specified operands.
- static bool isValidOperands(const Value *V1, const Value *V2,
- const Value *Mask) {
- return llvm::ShuffleVectorInst::isValidOperands(V1->Val, V2->Val,
- Mask->Val);
- }
- static bool isValidOperands(const Value *V1, const Value *V2,
- ArrayRef<int> Mask) {
- return llvm::ShuffleVectorInst::isValidOperands(V1->Val, V2->Val, Mask);
- }
-
- /// Overload to return most specific vector type.
- VectorType *getType() const;
-
- /// Return the shuffle mask value of this instruction for the given element
- /// index. Return PoisonMaskElem if the element is undef.
- int getMaskValue(unsigned Elt) const {
- return cast<llvm::ShuffleVectorInst>(Val)->getMaskValue(Elt);
- }
-
- /// Convert the input shuffle mask operand to a vector of integers. Undefined
- /// elements of the mask are returned as PoisonMaskElem.
- static void getShuffleMask(const Constant *Mask,
- SmallVectorImpl<int> &Result) {
- llvm::ShuffleVectorInst::getShuffleMask(cast<llvm::Constant>(Mask->Val),
- Result);
- }
-
- /// Return the mask for this instruction as a vector of integers. Undefined
- /// elements of the mask are returned as PoisonMaskElem.
- void getShuffleMask(SmallVectorImpl<int> &Result) const {
- cast<llvm::ShuffleVectorInst>(Val)->getShuffleMask(Result);
- }
-
- /// Return the mask for this instruction, for use in bitcode.
- Constant *getShuffleMaskForBitcode() const;
-
- static Constant *convertShuffleMaskForBitcode(ArrayRef<int> Mask,
- Type *ResultTy);
-
- void setShuffleMask(ArrayRef<int> Mask);
-
- ArrayRef<int> getShuffleMask() const {
- return cast<llvm::ShuffleVectorInst>(Val)->getShuffleMask();
- }
-
- /// Return true if this shuffle returns a vector with a different number of
- /// elements than its source vectors.
- /// Examples: shufflevector <4 x n> A, <4 x n> B, <1,2,3>
- /// shufflevector <4 x n> A, <4 x n> B, <1,2,3,4,5>
- bool changesLength() const {
- return cast<llvm::ShuffleVectorInst>(Val)->changesLength();
- }
-
- /// Return true if this shuffle returns a vector with a greater number of
- /// elements than its source vectors.
- /// Example: shufflevector <2 x n> A, <2 x n> B, <1,2,3>
- bool increasesLength() const {
- return cast<llvm::ShuffleVectorInst>(Val)->increasesLength();
- }
-
- /// Return true if this shuffle mask chooses elements from exactly one source
- /// vector.
- /// Example: <7,5,undef,7>
- /// This assumes that vector operands (of length \p NumSrcElts) are the same
- /// length as the mask.
- static bool isSingleSourceMask(ArrayRef<int> Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isSingleSourceMask(Mask, NumSrcElts);
- }
- static bool isSingleSourceMask(const Constant *Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isSingleSourceMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts);
- }
-
- /// Return true if this shuffle chooses elements from exactly one source
- /// vector without changing the length of that vector.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3>
- bool isSingleSource() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isSingleSource();
- }
-
- /// Return true if this shuffle mask chooses elements from exactly one source
- /// vector without lane crossings. A shuffle using this mask is not
- /// necessarily a no-op because it may change the number of elements from its
- /// input vectors or it may provide demanded bits knowledge via undef lanes.
- /// Example: <undef,undef,2,3>
- static bool isIdentityMask(ArrayRef<int> Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isIdentityMask(Mask, NumSrcElts);
- }
- static bool isIdentityMask(const Constant *Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isIdentityMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts);
- }
-
- /// Return true if this shuffle chooses elements from exactly one source
- /// vector without lane crossings and does not change the number of elements
- /// from its input vectors.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef>
- bool isIdentity() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isIdentity();
- }
-
- /// Return true if this shuffle lengthens exactly one source vector with
- /// undefs in the high elements.
- bool isIdentityWithPadding() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isIdentityWithPadding();
- }
-
- /// Return true if this shuffle extracts the first N elements of exactly one
- /// source vector.
- bool isIdentityWithExtract() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isIdentityWithExtract();
- }
-
- /// Return true if this shuffle concatenates its 2 source vectors. This
- /// returns false if either input is undefined. In that case, the shuffle is
- /// is better classified as an identity with padding operation.
- bool isConcat() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isConcat();
- }
-
- /// Return true if this shuffle mask chooses elements from its source vectors
- /// without lane crossings. A shuffle using this mask would be
- /// equivalent to a vector select with a constant condition operand.
- /// Example: <4,1,6,undef>
- /// This returns false if the mask does not choose from both input vectors.
- /// In that case, the shuffle is better classified as an identity shuffle.
- /// This assumes that vector operands are the same length as the mask
- /// (a length-changing shuffle can never be equivalent to a vector select).
- static bool isSelectMask(ArrayRef<int> Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isSelectMask(Mask, NumSrcElts);
- }
- static bool isSelectMask(const Constant *Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isSelectMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts);
- }
-
- /// Return true if this shuffle chooses elements from its source vectors
- /// without lane crossings and all operands have the same number of elements.
- /// In other words, this shuffle is equivalent to a vector select with a
- /// constant condition operand.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,1,6,3>
- /// This returns false if the mask does not choose from both input vectors.
- /// In that case, the shuffle is better classified as an identity shuffle.
- bool isSelect() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isSelect();
- }
-
- /// Return true if this shuffle mask swaps the order of elements from exactly
- /// one source vector.
- /// Example: <7,6,undef,4>
- /// This assumes that vector operands (of length \p NumSrcElts) are the same
- /// length as the mask.
- static bool isReverseMask(ArrayRef<int> Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isReverseMask(Mask, NumSrcElts);
- }
- static bool isReverseMask(const Constant *Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isReverseMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts);
- }
-
- /// Return true if this shuffle swaps the order of elements from exactly
- /// one source vector.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef>
- bool isReverse() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isReverse();
- }
-
- /// Return true if this shuffle mask chooses all elements with the same value
- /// as the first element of exactly one source vector.
- /// Example: <4,undef,undef,4>
- /// This assumes that vector operands (of length \p NumSrcElts) are the same
- /// length as the mask.
- static bool isZeroEltSplatMask(ArrayRef<int> Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isZeroEltSplatMask(Mask, NumSrcElts);
- }
- static bool isZeroEltSplatMask(const Constant *Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isZeroEltSplatMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts);
- }
-
- /// Return true if all elements of this shuffle are the same value as the
- /// first element of exactly one source vector without changing the length
- /// of that vector.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,0,undef,0>
- bool isZeroEltSplat() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isZeroEltSplat();
- }
-
- /// Return true if this shuffle mask is a transpose mask.
- /// Transpose vector masks transpose a 2xn matrix. They read corresponding
- /// even- or odd-numbered vector elements from two n-dimensional source
- /// vectors and write each result into consecutive elements of an
- /// n-dimensional destination vector. Two shuffles are necessary to complete
- /// the transpose, one for the even elements and another for the odd elements.
- /// This description closely follows how the TRN1 and TRN2 AArch64
- /// instructions operate.
- ///
- /// For example, a simple 2x2 matrix can be transposed with:
- ///
- /// ; Original matrix
- /// m0 = < a, b >
- /// m1 = < c, d >
- ///
- /// ; Transposed matrix
- /// t0 = < a, c > = shufflevector m0, m1, < 0, 2 >
- /// t1 = < b, d > = shufflevector m0, m1, < 1, 3 >
- ///
- /// For matrices having greater than n columns, the resulting nx2 transposed
- /// matrix is stored in two result vectors such that one vector contains
- /// interleaved elements from all the even-numbered rows and the other vector
- /// contains interleaved elements from all the odd-numbered rows. For example,
- /// a 2x4 matrix can be transposed with:
- ///
- /// ; Original matrix
- /// m0 = < a, b, c, d >
- /// m1 = < e, f, g, h >
- ///
- /// ; Transposed matrix
- /// t0 = < a, e, c, g > = shufflevector m0, m1 < 0, 4, 2, 6 >
- /// t1 = < b, f, d, h > = shufflevector m0, m1 < 1, 5, 3, 7 >
- static bool isTransposeMask(ArrayRef<int> Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isTransposeMask(Mask, NumSrcElts);
- }
- static bool isTransposeMask(const Constant *Mask, int NumSrcElts) {
- return llvm::ShuffleVectorInst::isTransposeMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts);
- }
-
- /// Return true if this shuffle transposes the elements of its inputs without
- /// changing the length of the vectors. This operation may also be known as a
- /// merge or interleave. See the description for isTransposeMask() for the
- /// exact specification.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6>
- bool isTranspose() const {
- return cast<llvm::ShuffleVectorInst>(Val)->isTranspose();
- }
-
- /// Return true if this shuffle mask is a splice mask, concatenating the two
- /// inputs together and then extracts an original width vector starting from
- /// the splice index.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4>
- /// This assumes that vector operands (of length \p NumSrcElts) are the same
- /// length as the mask.
- static bool isSpliceMask(ArrayRef<int> Mask, int NumSrcElts, int &Index) {
- return llvm::ShuffleVectorInst::isSpliceMask(Mask, NumSrcElts, Index);
- }
- static bool isSpliceMask(const Constant *Mask, int NumSrcElts, int &Index) {
- return llvm::ShuffleVectorInst::isSpliceMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts, Index);
- }
-
- /// Return true if this shuffle splices two inputs without changing the length
- /// of the vectors. This operation concatenates the two inputs together and
- /// then extracts an original width vector starting from the splice index.
- /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2,3,4>
- bool isSplice(int &Index) const {
- return cast<llvm::ShuffleVectorInst>(Val)->isSplice(Index);
- }
-
- /// Return true if this shuffle mask is an extract subvector mask.
- /// A valid extract subvector mask returns a smaller vector from a single
- /// source operand. The base extraction index is returned as well.
- static bool isExtractSubvectorMask(ArrayRef<int> Mask, int NumSrcElts,
- int &Index) {
- return llvm::ShuffleVectorInst::isExtractSubvectorMask(Mask, NumSrcElts,
- Index);
- }
- static bool isExtractSubvectorMask(const Constant *Mask, int NumSrcElts,
- int &Index) {
- return llvm::ShuffleVectorInst::isExtractSubvectorMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts, Index);
- }
-
- /// Return true if this shuffle mask is an extract subvector mask.
- bool isExtractSubvectorMask(int &Index) const {
- return cast<llvm::ShuffleVectorInst>(Val)->isExtractSubvectorMask(Index);
- }
-
- /// Return true if this shuffle mask is an insert subvector mask.
- /// A valid insert subvector mask inserts the lowest elements of a second
- /// source operand into an in-place first source operand.
- /// Both the sub vector width and the insertion index is returned.
- static bool isInsertSubvectorMask(ArrayRef<int> Mask, int NumSrcElts,
- int &NumSubElts, int &Index) {
- return llvm::ShuffleVectorInst::isInsertSubvectorMask(Mask, NumSrcElts,
- NumSubElts, Index);
- }
- static bool isInsertSubvectorMask(const Constant *Mask, int NumSrcElts,
- int &NumSubElts, int &Index) {
- return llvm::ShuffleVectorInst::isInsertSubvectorMask(
- cast<llvm::Constant>(Mask->Val), NumSrcElts, NumSubElts, Index);
- }
-
- /// Return true if this shuffle mask is an insert subvector mask.
- bool isInsertSubvectorMask(int &NumSubElts, int &Index) const {
- return cast<llvm::ShuffleVectorInst>(Val)->isInsertSubvectorMask(NumSubElts,
- Index);
- }
-
- /// Return true if this shuffle mask replicates each of the \p VF elements
- /// in a vector \p ReplicationFactor times.
- /// For example, the mask for \p ReplicationFactor=3 and \p VF=4 is:
- /// <0,0,0,1,1,1,2,2,2,3,3,3>
- static bool isReplicationMask(ArrayRef<int> Mask, int &ReplicationFactor,
- int &VF) {
- return llvm::ShuffleVectorInst::isReplicationMask(Mask, ReplicationFactor,
- VF);
- }
- static bool isReplicationMask(const Constant *Mask, int &ReplicationFactor,
- int &VF) {
- return llvm::ShuffleVectorInst::isReplicationMask(
- cast<llvm::Constant>(Mask->Val), ReplicationFactor, VF);
- }
-
- /// Return true if this shuffle mask is a replication mask.
- bool isReplicationMask(int &ReplicationFactor, int &VF) const {
- return cast<llvm::ShuffleVectorInst>(Val)->isReplicationMask(
- ReplicationFactor, VF);
- }
-
- /// Return true if this shuffle mask represents "clustered" mask of size VF,
- /// i.e. each index between [0..VF) is used exactly once in each submask of
- /// size VF.
- /// For example, the mask for \p VF=4 is:
- /// 0, 1, 2, 3, 3, 2, 0, 1 - "clustered", because each submask of size 4
- /// (0,1,2,3 and 3,2,0,1) uses indices [0..VF) exactly one time.
- /// 0, 1, 2, 3, 3, 3, 1, 0 - not "clustered", because
- /// element 3 is used twice in the second submask
- /// (3,3,1,0) and index 2 is not used at all.
- static bool isOneUseSingleSourceMask(ArrayRef<int> Mask, int VF) {
- return llvm::ShuffleVectorInst::isOneUseSingleSourceMask(Mask, VF);
- }
-
- /// Return true if this shuffle mask is a one-use-single-source("clustered")
- /// mask.
- bool isOneUseSingleSourceMask(int VF) const {
- return cast<llvm::ShuffleVectorInst>(Val)->isOneUseSingleSourceMask(VF);
- }
-
- /// Change values in a shuffle permute mask assuming the two vector operands
- /// of length InVecNumElts have swapped position.
- static void commuteShuffleMask(MutableArrayRef<int> Mask,
- unsigned InVecNumElts) {
- llvm::ShuffleVectorInst::commuteShuffleMask(Mask, InVecNumElts);
- }
-
- /// Return if this shuffle interleaves its two input vectors together.
- bool isInterleave(unsigned Factor) const {
- return cast<llvm::ShuffleVectorInst>(Val)->isInterleave(Factor);
- }
-
- /// Return true if the mask interleaves one or more input vectors together.
- ///
- /// I.e. <0, LaneLen, ... , LaneLen*(Factor - 1), 1, LaneLen + 1, ...>
- /// E.g. For a Factor of 2 (LaneLen=4):
- /// <0, 4, 1, 5, 2, 6, 3, 7>
- /// E.g. For a Factor of 3 (LaneLen=4):
- /// <4, 0, 9, 5, 1, 10, 6, 2, 11, 7, 3, 12>
- /// E.g. For a Factor of 4 (LaneLen=2):
- /// <0, 2, 6, 4, 1, 3, 7, 5>
- ///
- /// NumInputElts is the total number of elements in the input vectors.
- ///
- /// StartIndexes are the first indexes of each vector being interleaved,
- /// substituting any indexes that were undef
- /// E.g. <4, -1, 2, 5, 1, 3> (Factor=3): StartIndexes=<4, 0, 2>
- ///
- /// Note that this does not check if the input vectors are consecutive:
- /// It will return true for masks such as
- /// <0, 4, 6, 1, 5, 7> (Factor=3, LaneLen=2)
- static bool isInterleaveMask(ArrayRef<int> Mask, unsigned Factor,
- unsigned NumInputElts,
- SmallVectorImpl<unsigned> &StartIndexes) {
- return llvm::ShuffleVectorInst::isInterleaveMask(Mask, Factor, NumInputElts,
- StartIndexes);
- }
- static bool isInterleaveMask(ArrayRef<int> Mask, unsigned Factor,
- unsigned NumInputElts) {
- return llvm::ShuffleVectorInst::isInterleaveMask(Mask, Factor,
- NumInputElts);
- }
-
- /// Check if the mask is a DE-interleave mask of the given factor
- /// \p Factor like:
- /// <Index, Index+Factor, ..., Index+(NumElts-1)*Factor>
- static bool isDeInterleaveMaskOfFactor(ArrayRef<int> Mask, unsigned Factor,
- unsigned &Index) {
- return llvm::ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor,
- Index);
- }
- static bool isDeInterleaveMaskOfFactor(ArrayRef<int> Mask, unsigned Factor) {
- return llvm::ShuffleVectorInst::isDeInterleaveMaskOfFactor(Mask, Factor);
- }
-
- /// Checks if the shuffle is a bit rotation of the first operand across
- /// multiple subelements, e.g:
- ///
- /// shuffle <8 x i8> %a, <8 x i8> poison, <8 x i32> <1, 0, 3, 2, 5, 4, 7, 6>
- ///
- /// could be expressed as
- ///
- /// rotl <4 x i16> %a, 8
- ///
- /// If it can be expressed as a rotation, returns the number of subelements to
- /// group by in NumSubElts and the number of bits to rotate left in RotateAmt.
- static bool isBitRotateMask(ArrayRef<int> Mask, unsigned EltSizeInBits,
- unsigned MinSubElts, unsigned MaxSubElts,
- unsigned &NumSubElts, unsigned &RotateAmt) {
- return llvm::ShuffleVectorInst::isBitRotateMask(
- Mask, EltSizeInBits, MinSubElts, MaxSubElts, NumSubElts, RotateAmt);
- }
-};
-
-class InsertValueInst
- : public SingleLLVMInstructionImpl<llvm::InsertValueInst> {
- /// Use Context::createInsertValueInst(). Don't call the constructor directly.
- InsertValueInst(llvm::InsertValueInst *IVI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::InsertValue, Opcode::InsertValue,
- IVI, Ctx) {}
- friend Context; // for InsertValueInst()
-
-public:
- static Value *create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
- BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::InsertValue;
- }
-
- using idx_iterator = llvm::InsertValueInst::idx_iterator;
- inline idx_iterator idx_begin() const {
- return cast<llvm::InsertValueInst>(Val)->idx_begin();
- }
- inline idx_iterator idx_end() const {
- return cast<llvm::InsertValueInst>(Val)->idx_end();
- }
- inline iterator_range<idx_iterator> indices() const {
- return cast<llvm::InsertValueInst>(Val)->indices();
- }
-
- Value *getAggregateOperand() {
- return getOperand(getAggregateOperandIndex());
- }
- const Value *getAggregateOperand() const {
- return getOperand(getAggregateOperandIndex());
- }
- static unsigned getAggregateOperandIndex() {
- return llvm::InsertValueInst::getAggregateOperandIndex();
- }
-
- Value *getInsertedValueOperand() {
- return getOperand(getInsertedValueOperandIndex());
- }
- const Value *getInsertedValueOperand() const {
- return getOperand(getInsertedValueOperandIndex());
- }
- static unsigned getInsertedValueOperandIndex() {
- return llvm::InsertValueInst::getInsertedValueOperandIndex();
- }
-
- ArrayRef<unsigned> getIndices() const {
- return cast<llvm::InsertValueInst>(Val)->getIndices();
- }
-
- unsigned getNumIndices() const {
- return cast<llvm::InsertValueInst>(Val)->getNumIndices();
- }
-
- unsigned hasIndices() const {
- return cast<llvm::InsertValueInst>(Val)->hasIndices();
- }
-};
-
-class BranchInst : public SingleLLVMInstructionImpl<llvm::BranchInst> {
- /// Use Context::createBranchInst(). Don't call the constructor directly.
- BranchInst(llvm::BranchInst *BI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Br, Opcode::Br, BI, Ctx) {}
- friend Context; // for BranchInst()
-
-public:
- static BranchInst *create(BasicBlock *IfTrue, Instruction *InsertBefore,
- Context &Ctx);
- static BranchInst *create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd,
- Context &Ctx);
- static BranchInst *create(BasicBlock *IfTrue, BasicBlock *IfFalse,
- Value *Cond, Instruction *InsertBefore,
- Context &Ctx);
- static BranchInst *create(BasicBlock *IfTrue, BasicBlock *IfFalse,
- Value *Cond, BasicBlock *InsertAtEnd, Context &Ctx);
- /// For isa/dyn_cast.
- static bool classof(const Value *From);
- bool isUnconditional() const {
- return cast<llvm::BranchInst>(Val)->isUnconditional();
- }
- bool isConditional() const {
- return cast<llvm::BranchInst>(Val)->isConditional();
- }
- Value *getCondition() const;
- void setCondition(Value *V) { setOperand(0, V); }
- unsigned getNumSuccessors() const { return 1 + isConditional(); }
- BasicBlock *getSuccessor(unsigned SuccIdx) const;
- void setSuccessor(unsigned Idx, BasicBlock *NewSucc);
- void swapSuccessors() { swapOperandsInternal(1, 2); }
-
-private:
- struct LLVMBBToSBBB {
- Context &Ctx;
- LLVMBBToSBBB(Context &Ctx) : Ctx(Ctx) {}
- BasicBlock *operator()(llvm::BasicBlock *BB) const;
- };
-
- struct ConstLLVMBBToSBBB {
- Context &Ctx;
- ConstLLVMBBToSBBB(Context &Ctx) : Ctx(Ctx) {}
- const BasicBlock *operator()(const llvm::BasicBlock *BB) const;
- };
-
-public:
- using sb_succ_op_iterator =
- mapped_iterator<llvm::BranchInst::succ_op_iterator, LLVMBBToSBBB>;
- iterator_range<sb_succ_op_iterator> successors() {
- iterator_range<llvm::BranchInst::succ_op_iterator> LLVMRange =
- cast<llvm::BranchInst>(Val)->successors();
- LLVMBBToSBBB BBMap(Ctx);
- sb_succ_op_iterator MappedBegin = map_iterator(LLVMRange.begin(), BBMap);
- sb_succ_op_iterator MappedEnd = map_iterator(LLVMRange.end(), BBMap);
- return make_range(MappedBegin, MappedEnd);
- }
-
- using const_sb_succ_op_iterator =
- mapped_iterator<llvm::BranchInst::const_succ_op_iterator,
- ConstLLVMBBToSBBB>;
- iterator_range<const_sb_succ_op_iterator> successors() const {
- iterator_range<llvm::BranchInst::const_succ_op_iterator> ConstLLVMRange =
- static_cast<const llvm::BranchInst *>(cast<llvm::BranchInst>(Val))
- ->successors();
- ConstLLVMBBToSBBB ConstBBMap(Ctx);
- const_sb_succ_op_iterator ConstMappedBegin =
- map_iterator(ConstLLVMRange.begin(), ConstBBMap);
- const_sb_succ_op_iterator ConstMappedEnd =
- map_iterator(ConstLLVMRange.end(), ConstBBMap);
- return make_range(ConstMappedBegin, ConstMappedEnd);
- }
-};
-
-/// An abstract class, parent of unary instructions.
-class UnaryInstruction
- : public SingleLLVMInstructionImpl<llvm::UnaryInstruction> {
-protected:
- UnaryInstruction(ClassID ID, Opcode Opc, llvm::Instruction *LLVMI,
- Context &Ctx)
- : SingleLLVMInstructionImpl(ID, Opc, LLVMI, Ctx) {}
-
-public:
- static bool classof(const Instruction *I) {
- return isa<LoadInst>(I) || isa<CastInst>(I) || isa<FreezeInst>(I);
- }
- static bool classof(const Value *V) {
- return isa<Instruction>(V) && classof(cast<Instruction>(V));
- }
-};
-
-class ExtractValueInst : public UnaryInstruction {
- /// Use Context::createExtractValueInst() instead.
- ExtractValueInst(llvm::ExtractValueInst *EVI, Context &Ctx)
- : UnaryInstruction(ClassID::ExtractValue, Opcode::ExtractValue, EVI,
- Ctx) {}
- friend Context; // for ExtractValueInst()
-
-public:
- static Value *create(Value *Agg, ArrayRef<unsigned> Idxs, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::ExtractValue;
- }
-
- /// Returns the type of the element that would be extracted
- /// with an extractvalue instruction with the specified parameters.
- ///
- /// Null is returned if the indices are invalid for the specified type.
- static Type *getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs);
-
- using idx_iterator = llvm::ExtractValueInst::idx_iterator;
-
- inline idx_iterator idx_begin() const {
- return cast<llvm::ExtractValueInst>(Val)->idx_begin();
- }
- inline idx_iterator idx_end() const {
- return cast<llvm::ExtractValueInst>(Val)->idx_end();
- }
- inline iterator_range<idx_iterator> indices() const {
- return cast<llvm::ExtractValueInst>(Val)->indices();
- }
-
- Value *getAggregateOperand() {
- return getOperand(getAggregateOperandIndex());
- }
- const Value *getAggregateOperand() const {
- return getOperand(getAggregateOperandIndex());
- }
- static unsigned getAggregateOperandIndex() {
- return llvm::ExtractValueInst::getAggregateOperandIndex();
- }
-
- ArrayRef<unsigned> getIndices() const {
- return cast<llvm::ExtractValueInst>(Val)->getIndices();
- }
-
- unsigned getNumIndices() const {
- return cast<llvm::ExtractValueInst>(Val)->getNumIndices();
- }
-
- unsigned hasIndices() const {
- return cast<llvm::ExtractValueInst>(Val)->hasIndices();
- }
-};
-
-class VAArgInst : public UnaryInstruction {
- VAArgInst(llvm::VAArgInst *FI, Context &Ctx)
- : UnaryInstruction(ClassID::VAArg, Opcode::VAArg, FI, Ctx) {}
- friend Context; // For constructor;
-
-public:
- static VAArgInst *create(Value *List, Type *Ty, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
- Value *getPointerOperand();
- const Value *getPointerOperand() const {
- return const_cast<VAArgInst *>(this)->getPointerOperand();
- }
- static unsigned getPointerOperandIndex() {
- return llvm::VAArgInst::getPointerOperandIndex();
- }
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::VAArg;
- }
-};
-
-class FreezeInst : public UnaryInstruction {
- FreezeInst(llvm::FreezeInst *FI, Context &Ctx)
- : UnaryInstruction(ClassID::Freeze, Opcode::Freeze, FI, Ctx) {}
- friend Context; // For constructor;
-
-public:
- static FreezeInst *create(Value *V, BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Freeze;
- }
-};
-
-class LoadInst final : public UnaryInstruction {
- /// Use LoadInst::create() instead of calling the constructor.
- LoadInst(llvm::LoadInst *LI, Context &Ctx)
- : UnaryInstruction(ClassID::Load, Opcode::Load, LI, Ctx) {}
- friend Context; // for LoadInst()
-
-public:
- /// Return true if this is a load from a volatile memory location.
- bool isVolatile() const { return cast<llvm::LoadInst>(Val)->isVolatile(); }
- /// Specify whether this is a volatile load or not.
- void setVolatile(bool V);
-
- static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, bool IsVolatile,
- Context &Ctx, const Twine &Name = "");
- static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- static LoadInst *create(Type *Ty, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, bool IsVolatile,
- Context &Ctx, const Twine &Name = "");
-
- /// For isa/dyn_cast.
- static bool classof(const Value *From);
- Value *getPointerOperand() const;
- Align getAlign() const { return cast<llvm::LoadInst>(Val)->getAlign(); }
- bool isUnordered() const { return cast<llvm::LoadInst>(Val)->isUnordered(); }
- bool isSimple() const { return cast<llvm::LoadInst>(Val)->isSimple(); }
-};
-
-class StoreInst final : public SingleLLVMInstructionImpl<llvm::StoreInst> {
- /// Use StoreInst::create().
- StoreInst(llvm::StoreInst *SI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Store, Opcode::Store, SI, Ctx) {}
- friend Context; // for StoreInst()
-
-public:
- /// Return true if this is a store from a volatile memory location.
- bool isVolatile() const { return cast<llvm::StoreInst>(Val)->isVolatile(); }
- /// Specify whether this is a volatile store or not.
- void setVolatile(bool V);
-
- static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, Context &Ctx);
- static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, bool IsVolatile,
- Context &Ctx);
- static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, Context &Ctx);
- static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, bool IsVolatile,
- Context &Ctx);
- /// For isa/dyn_cast.
- static bool classof(const Value *From);
- Value *getValueOperand() const;
- Value *getPointerOperand() const;
- Align getAlign() const { return cast<llvm::StoreInst>(Val)->getAlign(); }
- bool isSimple() const { return cast<llvm::StoreInst>(Val)->isSimple(); }
- bool isUnordered() const { return cast<llvm::StoreInst>(Val)->isUnordered(); }
-};
-
-class UnreachableInst final : public Instruction {
- /// Use UnreachableInst::create() instead of calling the constructor.
- UnreachableInst(llvm::UnreachableInst *I, Context &Ctx)
- : Instruction(ClassID::Unreachable, Opcode::Unreachable, I, Ctx) {}
- friend Context;
- Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
- return getOperandUseDefault(OpIdx, Verify);
- }
- SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
- return {cast<llvm::Instruction>(Val)};
- }
-
-public:
- static UnreachableInst *create(Instruction *InsertBefore, Context &Ctx);
- static UnreachableInst *create(BasicBlock *InsertAtEnd, Context &Ctx);
- static bool classof(const Value *From);
- unsigned getNumSuccessors() const { return 0; }
- unsigned getUseOperandNo(const Use &Use) const final {
- llvm_unreachable("UnreachableInst has no operands!");
- }
- unsigned getNumOfIRInstrs() const final { return 1u; }
-};
-
-class ReturnInst final : public SingleLLVMInstructionImpl<llvm::ReturnInst> {
- /// Use ReturnInst::create() instead of calling the constructor.
- ReturnInst(llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Ret, Opcode::Ret, I, Ctx) {}
- ReturnInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(SubclassID, Opcode::Ret, I, Ctx) {}
- friend class Context; // For accessing the constructor in create*()
- static ReturnInst *createCommon(Value *RetVal, IRBuilder<> &Builder,
- Context &Ctx);
-
-public:
- static ReturnInst *create(Value *RetVal, Instruction *InsertBefore,
- Context &Ctx);
- static ReturnInst *create(Value *RetVal, BasicBlock *InsertAtEnd,
- Context &Ctx);
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Ret;
- }
- /// \Returns null if there is no return value.
- Value *getReturnValue() const;
-};
-
-class CallBase : public SingleLLVMInstructionImpl<llvm::CallBase> {
- CallBase(ClassID ID, Opcode Opc, llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(ID, Opc, I, Ctx) {}
- friend class CallInst; // For constructor.
- friend class InvokeInst; // For constructor.
- friend class CallBrInst; // For constructor.
-
-public:
- static bool classof(const Value *From) {
- auto Opc = From->getSubclassID();
- return Opc == Instruction::ClassID::Call ||
- Opc == Instruction::ClassID::Invoke ||
- Opc == Instruction::ClassID::CallBr;
- }
-
- FunctionType *getFunctionType() const;
-
- op_iterator data_operands_begin() { return op_begin(); }
- const_op_iterator data_operands_begin() const {
- return const_cast<CallBase *>(this)->data_operands_begin();
- }
- op_iterator data_operands_end() {
- auto *LLVMCB = cast<llvm::CallBase>(Val);
- auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin();
- return op_begin() + Dist;
- }
- const_op_iterator data_operands_end() const {
- auto *LLVMCB = cast<llvm::CallBase>(Val);
- auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin();
- return op_begin() + Dist;
- }
- iterator_range<op_iterator> data_ops() {
- return make_range(data_operands_begin(), data_operands_end());
- }
- iterator_range<const_op_iterator> data_ops() const {
- return make_range(data_operands_begin(), data_operands_end());
- }
- bool data_operands_empty() const {
- return data_operands_end() == data_operands_begin();
- }
- unsigned data_operands_size() const {
- return std::distance(data_operands_begin(), data_operands_end());
- }
- bool isDataOperand(Use U) const {
- assert(this == U.getUser() &&
- "Only valid to query with a use of this instruction!");
- return cast<llvm::CallBase>(Val)->isDataOperand(U.LLVMUse);
- }
- unsigned getDataOperandNo(Use U) const {
- assert(isDataOperand(U) && "Data operand # out of range!");
- return cast<llvm::CallBase>(Val)->getDataOperandNo(U.LLVMUse);
- }
-
- /// Return the total number operands (not operand bundles) used by
- /// every operand bundle in this OperandBundleUser.
- unsigned getNumTotalBundleOperands() const {
- return cast<llvm::CallBase>(Val)->getNumTotalBundleOperands();
- }
-
- op_iterator arg_begin() { return op_begin(); }
- const_op_iterator arg_begin() const { return op_begin(); }
- op_iterator arg_end() {
- return data_operands_end() - getNumTotalBundleOperands();
- }
- const_op_iterator arg_end() const {
- return const_cast<CallBase *>(this)->arg_end();
- }
- iterator_range<op_iterator> args() {
- return make_range(arg_begin(), arg_end());
- }
- iterator_range<const_op_iterator> args() const {
- return make_range(arg_begin(), arg_end());
- }
- bool arg_empty() const { return arg_end() == arg_begin(); }
- unsigned arg_size() const { return arg_end() - arg_begin(); }
-
- Value *getArgOperand(unsigned OpIdx) const {
- assert(OpIdx < arg_size() && "Out of bounds!");
- return getOperand(OpIdx);
- }
- void setArgOperand(unsigned OpIdx, Value *NewOp) {
- assert(OpIdx < arg_size() && "Out of bounds!");
- setOperand(OpIdx, NewOp);
- }
-
- Use getArgOperandUse(unsigned Idx) const {
- assert(Idx < arg_size() && "Out of bounds!");
- return getOperandUse(Idx);
- }
- Use getArgOperandUse(unsigned Idx) {
- assert(Idx < arg_size() && "Out of bounds!");
- return getOperandUse(Idx);
- }
-
- bool isArgOperand(Use U) const {
- return cast<llvm::CallBase>(Val)->isArgOperand(U.LLVMUse);
- }
- unsigned getArgOperandNo(Use U) const {
- return cast<llvm::CallBase>(Val)->getArgOperandNo(U.LLVMUse);
- }
- bool hasArgument(const Value *V) const { return is_contained(args(), V); }
-
- Value *getCalledOperand() const;
- Use getCalledOperandUse() const;
-
- Function *getCalledFunction() const;
- bool isIndirectCall() const {
- return cast<llvm::CallBase>(Val)->isIndirectCall();
- }
- bool isCallee(Use U) const {
- return cast<llvm::CallBase>(Val)->isCallee(U.LLVMUse);
- }
- Function *getCaller();
- const Function *getCaller() const {
- return const_cast<CallBase *>(this)->getCaller();
- }
- bool isMustTailCall() const {
- return cast<llvm::CallBase>(Val)->isMustTailCall();
- }
- bool isTailCall() const { return cast<llvm::CallBase>(Val)->isTailCall(); }
- Intrinsic::ID getIntrinsicID() const {
- return cast<llvm::CallBase>(Val)->getIntrinsicID();
- }
- void setCalledOperand(Value *V) { getCalledOperandUse().set(V); }
- void setCalledFunction(Function *F);
- CallingConv::ID getCallingConv() const {
- return cast<llvm::CallBase>(Val)->getCallingConv();
- }
- bool isInlineAsm() const { return cast<llvm::CallBase>(Val)->isInlineAsm(); }
-};
-
-class CallInst final : public CallBase {
- /// Use Context::createCallInst(). Don't call the
- /// constructor directly.
- CallInst(llvm::Instruction *I, Context &Ctx)
- : CallBase(ClassID::Call, Opcode::Call, I, Ctx) {}
- friend class Context; // For accessing the constructor in
- // create*()
-
-public:
- static CallInst *create(FunctionType *FTy, Value *Func,
- ArrayRef<Value *> Args, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr = "");
- static CallInst *create(FunctionType *FTy, Value *Func,
- ArrayRef<Value *> Args, Instruction *InsertBefore,
- Context &Ctx, const Twine &NameStr = "");
- static CallInst *create(FunctionType *FTy, Value *Func,
- ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &NameStr = "");
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Call;
- }
-};
-
-class InvokeInst final : public CallBase {
- /// Use Context::createInvokeInst(). Don't call the
- /// constructor directly.
- InvokeInst(llvm::Instruction *I, Context &Ctx)
- : CallBase(ClassID::Invoke, Opcode::Invoke, I, Ctx) {}
- friend class Context; // For accessing the constructor in
- // create*()
-
-public:
- static InvokeInst *create(FunctionType *FTy, Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr = "");
- static InvokeInst *create(FunctionType *FTy, Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, Instruction *InsertBefore,
- Context &Ctx, const Twine &NameStr = "");
- static InvokeInst *create(FunctionType *FTy, Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &NameStr = "");
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Invoke;
- }
- BasicBlock *getNormalDest() const;
- BasicBlock *getUnwindDest() const;
- void setNormalDest(BasicBlock *BB);
- void setUnwindDest(BasicBlock *BB);
- LandingPadInst *getLandingPadInst() const;
- BasicBlock *getSuccessor(unsigned SuccIdx) const;
- void setSuccessor(unsigned SuccIdx, BasicBlock *NewSucc) {
- assert(SuccIdx < 2 && "Successor # out of range for invoke!");
- if (SuccIdx == 0)
- setNormalDest(NewSucc);
- else
- setUnwindDest(NewSucc);
- }
- unsigned getNumSuccessors() const {
- return cast<llvm::InvokeInst>(Val)->getNumSuccessors();
- }
-};
-
-class CallBrInst final : public CallBase {
- /// Use Context::createCallBrInst(). Don't call the
- /// constructor directly.
- CallBrInst(llvm::Instruction *I, Context &Ctx)
- : CallBase(ClassID::CallBr, Opcode::CallBr, I, Ctx) {}
- friend class Context; // For accessing the constructor in
- // create*()
-
-public:
- static CallBrInst *create(FunctionType *FTy, Value *Func,
- BasicBlock *DefaultDest,
- ArrayRef<BasicBlock *> IndirectDests,
- ArrayRef<Value *> Args, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr = "");
- static CallBrInst *create(FunctionType *FTy, Value *Func,
- BasicBlock *DefaultDest,
- ArrayRef<BasicBlock *> IndirectDests,
- ArrayRef<Value *> Args, Instruction *InsertBefore,
- Context &Ctx, const Twine &NameStr = "");
- static CallBrInst *create(FunctionType *FTy, Value *Func,
- BasicBlock *DefaultDest,
- ArrayRef<BasicBlock *> IndirectDests,
- ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &NameStr = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CallBr;
- }
- unsigned getNumIndirectDests() const {
- return cast<llvm::CallBrInst>(Val)->getNumIndirectDests();
- }
- Value *getIndirectDestLabel(unsigned Idx) const;
- Value *getIndirectDestLabelUse(unsigned Idx) const;
- BasicBlock *getDefaultDest() const;
- BasicBlock *getIndirectDest(unsigned Idx) const;
- SmallVector<BasicBlock *, 16> getIndirectDests() const;
- void setDefaultDest(BasicBlock *BB);
- void setIndirectDest(unsigned Idx, BasicBlock *BB);
- BasicBlock *getSuccessor(unsigned Idx) const;
- unsigned getNumSuccessors() const {
- return cast<llvm::CallBrInst>(Val)->getNumSuccessors();
- }
-};
-
-class LandingPadInst : public SingleLLVMInstructionImpl<llvm::LandingPadInst> {
- LandingPadInst(llvm::LandingPadInst *LP, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::LandingPad, Opcode::LandingPad, LP,
- Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static LandingPadInst *create(Type *RetTy, unsigned NumReservedClauses,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name = "");
- /// Return 'true' if this landingpad instruction is a
- /// cleanup. I.e., it should be run when unwinding even if its landing pad
- /// doesn't catch the exception.
- bool isCleanup() const {
- return cast<llvm::LandingPadInst>(Val)->isCleanup();
- }
- /// Indicate that this landingpad instruction is a cleanup.
- void setCleanup(bool V);
-
- // TODO: We are not implementing addClause() because we have no way to revert
- // it for now.
-
- /// Get the value of the clause at index Idx. Use isCatch/isFilter to
- /// determine what type of clause this is.
- Constant *getClause(unsigned Idx) const;
-
- /// Return 'true' if the clause and index Idx is a catch clause.
- bool isCatch(unsigned Idx) const {
- return cast<llvm::LandingPadInst>(Val)->isCatch(Idx);
- }
- /// Return 'true' if the clause and index Idx is a filter clause.
- bool isFilter(unsigned Idx) const {
- return cast<llvm::LandingPadInst>(Val)->isFilter(Idx);
- }
- /// Get the number of clauses for this landing pad.
- unsigned getNumClauses() const {
- return cast<llvm::LandingPadInst>(Val)->getNumOperands();
- }
- // TODO: We are not implementing reserveClauses() because we can't revert it.
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::LandingPad;
- }
-};
-
-class FuncletPadInst : public SingleLLVMInstructionImpl<llvm::FuncletPadInst> {
- FuncletPadInst(ClassID SubclassID, Opcode Opc, llvm::Instruction *I,
- Context &Ctx)
- : SingleLLVMInstructionImpl(SubclassID, Opc, I, Ctx) {}
- friend class CatchPadInst; // For constructor.
- friend class CleanupPadInst; // For constructor.
-
-public:
- /// Return the number of funcletpad arguments.
- unsigned arg_size() const {
- return cast<llvm::FuncletPadInst>(Val)->arg_size();
- }
- /// Return the outer EH-pad this funclet is nested within.
- ///
- /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
- /// is a CatchPadInst.
- Value *getParentPad() const;
- void setParentPad(Value *ParentPad);
- /// Return the Idx-th funcletpad argument.
- Value *getArgOperand(unsigned Idx) const;
- /// Set the Idx-th funcletpad argument.
- void setArgOperand(unsigned Idx, Value *V);
-
- // TODO: Implement missing functions: arg_operands().
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CatchPad ||
- From->getSubclassID() == ClassID::CleanupPad;
- }
-};
-
-class CatchPadInst : public FuncletPadInst {
- CatchPadInst(llvm::CatchPadInst *CPI, Context &Ctx)
- : FuncletPadInst(ClassID::CatchPad, Opcode::CatchPad, CPI, Ctx) {}
- friend class Context; // For constructor.
-
-public:
- CatchSwitchInst *getCatchSwitch() const;
- // TODO: We have not implemented setCatchSwitch() because we can't revert it
- // for now, as there is no CatchPadInst member function that can undo it.
-
- static CatchPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CatchPad;
- }
-};
-
-class CleanupPadInst : public FuncletPadInst {
- CleanupPadInst(llvm::CleanupPadInst *CPI, Context &Ctx)
- : FuncletPadInst(ClassID::CleanupPad, Opcode::CleanupPad, CPI, Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static CleanupPadInst *create(Value *ParentPad, ArrayRef<Value *> Args,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name = "");
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CleanupPad;
- }
-};
-
-class CatchReturnInst
- : public SingleLLVMInstructionImpl<llvm::CatchReturnInst> {
- CatchReturnInst(llvm::CatchReturnInst *CRI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::CatchRet, Opcode::CatchRet, CRI,
- Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static CatchReturnInst *create(CatchPadInst *CatchPad, BasicBlock *BB,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx);
- CatchPadInst *getCatchPad() const;
- void setCatchPad(CatchPadInst *CatchPad);
- BasicBlock *getSuccessor() const;
- void setSuccessor(BasicBlock *NewSucc);
- unsigned getNumSuccessors() {
- return cast<llvm::CatchReturnInst>(Val)->getNumSuccessors();
- }
- Value *getCatchSwitchParentPad() const;
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CatchRet;
- }
-};
-
-class CleanupReturnInst
- : public SingleLLVMInstructionImpl<llvm::CleanupReturnInst> {
- CleanupReturnInst(llvm::CleanupReturnInst *CRI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::CleanupRet, Opcode::CleanupRet, CRI,
- Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static CleanupReturnInst *create(CleanupPadInst *CleanupPad,
- BasicBlock *UnwindBB, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx);
- bool hasUnwindDest() const {
- return cast<llvm::CleanupReturnInst>(Val)->hasUnwindDest();
- }
- bool unwindsToCaller() const {
- return cast<llvm::CleanupReturnInst>(Val)->unwindsToCaller();
- }
- CleanupPadInst *getCleanupPad() const;
- void setCleanupPad(CleanupPadInst *CleanupPad);
- unsigned getNumSuccessors() const {
- return cast<llvm::CleanupReturnInst>(Val)->getNumSuccessors();
- }
- BasicBlock *getUnwindDest() const;
- void setUnwindDest(BasicBlock *NewDest);
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CleanupRet;
- }
-};
-
-class GetElementPtrInst final
- : public SingleLLVMInstructionImpl<llvm::GetElementPtrInst> {
- /// Use Context::createGetElementPtrInst(). Don't call
- /// the constructor directly.
- GetElementPtrInst(llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::GetElementPtr, Opcode::GetElementPtr,
- I, Ctx) {}
- GetElementPtrInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
- : SingleLLVMInstructionImpl(SubclassID, Opcode::GetElementPtr, I, Ctx) {}
- friend class Context; // For accessing the constructor in
- // create*()
-
-public:
- static Value *create(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
- BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr = "");
- static Value *create(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &NameStr = "");
- static Value *create(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &NameStr = "");
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::GetElementPtr;
- }
-
- Type *getSourceElementType() const;
- Type *getResultElementType() const;
- unsigned getAddressSpace() const {
- return cast<llvm::GetElementPtrInst>(Val)->getAddressSpace();
- }
-
- inline op_iterator idx_begin() { return op_begin() + 1; }
- inline const_op_iterator idx_begin() const {
- return const_cast<GetElementPtrInst *>(this)->idx_begin();
- }
- inline op_iterator idx_end() { return op_end(); }
- inline const_op_iterator idx_end() const {
- return const_cast<GetElementPtrInst *>(this)->idx_end();
- }
- inline iterator_range<op_iterator> indices() {
- return make_range(idx_begin(), idx_end());
- }
- inline iterator_range<const_op_iterator> indices() const {
- return const_cast<GetElementPtrInst *>(this)->indices();
- }
-
- Value *getPointerOperand() const;
- static unsigned getPointerOperandIndex() {
- return llvm::GetElementPtrInst::getPointerOperandIndex();
- }
- Type *getPointerOperandType() const;
- unsigned getPointerAddressSpace() const {
- return cast<llvm::GetElementPtrInst>(Val)->getPointerAddressSpace();
- }
- unsigned getNumIndices() const {
- return cast<llvm::GetElementPtrInst>(Val)->getNumIndices();
- }
- bool hasIndices() const {
- return cast<llvm::GetElementPtrInst>(Val)->hasIndices();
- }
- bool hasAllConstantIndices() const {
- return cast<llvm::GetElementPtrInst>(Val)->hasAllConstantIndices();
- }
- GEPNoWrapFlags getNoWrapFlags() const {
- return cast<llvm::GetElementPtrInst>(Val)->getNoWrapFlags();
- }
- bool isInBounds() const {
- return cast<llvm::GetElementPtrInst>(Val)->isInBounds();
- }
- bool hasNoUnsignedSignedWrap() const {
- return cast<llvm::GetElementPtrInst>(Val)->hasNoUnsignedSignedWrap();
- }
- bool hasNoUnsignedWrap() const {
- return cast<llvm::GetElementPtrInst>(Val)->hasNoUnsignedWrap();
- }
- bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const {
- return cast<llvm::GetElementPtrInst>(Val)->accumulateConstantOffset(DL,
- Offset);
- }
- // TODO: Add missing member functions.
-};
-
-class CatchSwitchInst
- : public SingleLLVMInstructionImpl<llvm::CatchSwitchInst> {
-public:
- CatchSwitchInst(llvm::CatchSwitchInst *CSI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::CatchSwitch, Opcode::CatchSwitch,
- CSI, Ctx) {}
-
- static CatchSwitchInst *create(Value *ParentPad, BasicBlock *UnwindBB,
- unsigned NumHandlers, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
-
- Value *getParentPad() const;
- void setParentPad(Value *ParentPad);
-
- bool hasUnwindDest() const {
- return cast<llvm::CatchSwitchInst>(Val)->hasUnwindDest();
- }
- bool unwindsToCaller() const {
- return cast<llvm::CatchSwitchInst>(Val)->unwindsToCaller();
- }
- BasicBlock *getUnwindDest() const;
- void setUnwindDest(BasicBlock *UnwindDest);
-
- unsigned getNumHandlers() const {
- return cast<llvm::CatchSwitchInst>(Val)->getNumHandlers();
- }
-
-private:
- static BasicBlock *handler_helper(Value *V) { return cast<BasicBlock>(V); }
- static const BasicBlock *handler_helper(const Value *V) {
- return cast<BasicBlock>(V);
- }
-
-public:
- using DerefFnTy = BasicBlock *(*)(Value *);
- using handler_iterator = mapped_iterator<op_iterator, DerefFnTy>;
- using handler_range = iterator_range<handler_iterator>;
- using ConstDerefFnTy = const BasicBlock *(*)(const Value *);
- using const_handler_iterator =
- mapped_iterator<const_op_iterator, ConstDerefFnTy>;
- using const_handler_range = iterator_range<const_handler_iterator>;
-
- handler_iterator handler_begin() {
- op_iterator It = op_begin() + 1;
- if (hasUnwindDest())
- ++It;
- return handler_iterator(It, DerefFnTy(handler_helper));
- }
- const_handler_iterator handler_begin() const {
- const_op_iterator It = op_begin() + 1;
- if (hasUnwindDest())
- ++It;
- return const_handler_iterator(It, ConstDerefFnTy(handler_helper));
- }
- handler_iterator handler_end() {
- return handler_iterator(op_end(), DerefFnTy(handler_helper));
- }
- const_handler_iterator handler_end() const {
- return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper));
- }
- handler_range handlers() {
- return make_range(handler_begin(), handler_end());
- }
- const_handler_range handlers() const {
- return make_range(handler_begin(), handler_end());
- }
-
- void addHandler(BasicBlock *Dest);
-
- // TODO: removeHandler() cannot be reverted because there is no equivalent
- // addHandler() with a handler_iterator to specify the position. So we can't
- // implement it for now.
-
- unsigned getNumSuccessors() const { return getNumOperands() - 1; }
- BasicBlock *getSuccessor(unsigned Idx) const {
- assert(Idx < getNumSuccessors() &&
- "Successor # out of range for catchswitch!");
- return cast<BasicBlock>(getOperand(Idx + 1));
- }
- void setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
- assert(Idx < getNumSuccessors() &&
- "Successor # out of range for catchswitch!");
- setOperand(Idx + 1, NewSucc);
- }
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::CatchSwitch;
- }
-};
-
-class ResumeInst : public SingleLLVMInstructionImpl<llvm::ResumeInst> {
-public:
- ResumeInst(llvm::ResumeInst *CSI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Resume, Opcode::Resume, CSI, Ctx) {}
-
- static ResumeInst *create(Value *Exn, BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx);
- Value *getValue() const;
- unsigned getNumSuccessors() const {
- return cast<llvm::ResumeInst>(Val)->getNumSuccessors();
- }
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Resume;
- }
-};
-
-class SwitchInst : public SingleLLVMInstructionImpl<llvm::SwitchInst> {
-public:
- SwitchInst(llvm::SwitchInst *SI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Switch, Opcode::Switch, SI, Ctx) {}
-
- static constexpr const unsigned DefaultPseudoIndex =
- llvm::SwitchInst::DefaultPseudoIndex;
-
- static SwitchInst *create(Value *V, BasicBlock *Dest, unsigned NumCases,
- BasicBlock::iterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name = "");
-
- Value *getCondition() const;
- void setCondition(Value *V);
- BasicBlock *getDefaultDest() const;
- bool defaultDestUndefined() const {
- return cast<llvm::SwitchInst>(Val)->defaultDestUndefined();
- }
- void setDefaultDest(BasicBlock *DefaultCase);
- unsigned getNumCases() const {
- return cast<llvm::SwitchInst>(Val)->getNumCases();
- }
-
- using CaseHandle =
- llvm::SwitchInst::CaseHandleImpl<SwitchInst, ConstantInt, BasicBlock>;
- using ConstCaseHandle =
- llvm::SwitchInst::CaseHandleImpl<const SwitchInst, const ConstantInt,
- const BasicBlock>;
- using CaseIt = llvm::SwitchInst::CaseIteratorImpl<CaseHandle>;
- using ConstCaseIt = llvm::SwitchInst::CaseIteratorImpl<ConstCaseHandle>;
-
- /// Returns a read/write iterator that points to the first case in the
- /// SwitchInst.
- CaseIt case_begin() { return CaseIt(this, 0); }
- ConstCaseIt case_begin() const { return ConstCaseIt(this, 0); }
- /// Returns a read/write iterator that points one past the last in the
- /// SwitchInst.
- CaseIt case_end() { return CaseIt(this, getNumCases()); }
- ConstCaseIt case_end() const { return ConstCaseIt(this, getNumCases()); }
- /// Iteration adapter for range-for loops.
- iterator_range<CaseIt> cases() {
- return make_range(case_begin(), case_end());
- }
- iterator_range<ConstCaseIt> cases() const {
- return make_range(case_begin(), case_end());
- }
- CaseIt case_default() { return CaseIt(this, DefaultPseudoIndex); }
- ConstCaseIt case_default() const {
- return ConstCaseIt(this, DefaultPseudoIndex);
- }
- CaseIt findCaseValue(const ConstantInt *C) {
- return CaseIt(
- this,
- const_cast<const SwitchInst *>(this)->findCaseValue(C)->getCaseIndex());
- }
- ConstCaseIt findCaseValue(const ConstantInt *C) const {
- ConstCaseIt I = llvm::find_if(cases(), [C](const ConstCaseHandle &Case) {
- return Case.getCaseValue() == C;
- });
- if (I != case_end())
- return I;
- return case_default();
- }
- ConstantInt *findCaseDest(BasicBlock *BB);
-
- void addCase(ConstantInt *OnVal, BasicBlock *Dest);
- /// This method removes the specified case and its successor from the switch
- /// instruction. Note that this operation may reorder the remaining cases at
- /// index idx and above.
- /// Note:
- /// This action invalidates iterators for all cases following the one removed,
- /// including the case_end() iterator. It returns an iterator for the next
- /// case.
- CaseIt removeCase(CaseIt It);
-
- unsigned getNumSuccessors() const {
- return cast<llvm::SwitchInst>(Val)->getNumSuccessors();
- }
- BasicBlock *getSuccessor(unsigned Idx) const;
- void setSuccessor(unsigned Idx, BasicBlock *NewSucc);
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::Switch;
- }
-};
-
-class UnaryOperator : public UnaryInstruction {
- static Opcode getUnaryOpcode(llvm::Instruction::UnaryOps UnOp) {
- switch (UnOp) {
- case llvm::Instruction::FNeg:
- return Opcode::FNeg;
- case llvm::Instruction::UnaryOpsEnd:
- llvm_unreachable("Bad UnOp!");
- }
- llvm_unreachable("Unhandled UnOp!");
- }
- UnaryOperator(llvm::UnaryOperator *UO, Context &Ctx)
- : UnaryInstruction(ClassID::UnOp, getUnaryOpcode(UO->getOpcode()), UO,
- Ctx) {}
- friend Context; // for constructor.
-public:
- static Value *create(Instruction::Opcode Op, Value *OpV, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Instruction::Opcode Op, Value *OpV,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Instruction::Opcode Op, Value *OpV,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
- Value *CopyFrom, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
- static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
- Value *CopyFrom,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
- Value *CopyFrom, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &Name = "");
- /// For isa/dyn_cast.
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::UnOp;
- }
-};
-
-class BinaryOperator : public SingleLLVMInstructionImpl<llvm::BinaryOperator> {
-protected:
- static Opcode getBinOpOpcode(llvm::Instruction::BinaryOps BinOp) {
- switch (BinOp) {
- case llvm::Instruction::Add:
- return Opcode::Add;
- case llvm::Instruction::FAdd:
- return Opcode::FAdd;
- case llvm::Instruction::Sub:
- return Opcode::Sub;
- case llvm::Instruction::FSub:
- return Opcode::FSub;
- case llvm::Instruction::Mul:
- return Opcode::Mul;
- case llvm::Instruction::FMul:
- return Opcode::FMul;
- case llvm::Instruction::UDiv:
- return Opcode::UDiv;
- case llvm::Instruction::SDiv:
- return Opcode::SDiv;
- case llvm::Instruction::FDiv:
- return Opcode::FDiv;
- case llvm::Instruction::URem:
- return Opcode::URem;
- case llvm::Instruction::SRem:
- return Opcode::SRem;
- case llvm::Instruction::FRem:
- return Opcode::FRem;
- case llvm::Instruction::Shl:
- return Opcode::Shl;
- case llvm::Instruction::LShr:
- return Opcode::LShr;
- case llvm::Instruction::AShr:
- return Opcode::AShr;
- case llvm::Instruction::And:
- return Opcode::And;
- case llvm::Instruction::Or:
- return Opcode::Or;
- case llvm::Instruction::Xor:
- return Opcode::Xor;
- case llvm::Instruction::BinaryOpsEnd:
- llvm_unreachable("Bad BinOp!");
- }
- llvm_unreachable("Unhandled BinOp!");
- }
- BinaryOperator(llvm::BinaryOperator *BinOp, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::BinaryOperator,
- getBinOpOpcode(BinOp->getOpcode()), BinOp,
- Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS,
- BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Instruction::Opcode Op, Value *LHS, Value *RHS,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
-
- static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
- Value *RHS, Value *CopyFrom,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name = "");
- static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
- Value *RHS, Value *CopyFrom,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
- Value *RHS, Value *CopyFrom,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- /// For isa/dyn_cast.
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::BinaryOperator;
- }
- void swapOperands() { swapOperandsInternal(0, 1); }
-};
-
-/// An or instruction, which can be marked as "disjoint", indicating that the
-/// inputs don't have a 1 in the same bit position. Meaning this instruction
-/// can also be treated as an add.
-class PossiblyDisjointInst : public BinaryOperator {
-public:
- void setIsDisjoint(bool B);
- bool isDisjoint() const {
- return cast<llvm::PossiblyDisjointInst>(Val)->isDisjoint();
- }
- /// For isa/dyn_cast.
- static bool classof(const Value *From) {
- return isa<Instruction>(From) &&
- cast<Instruction>(From)->getOpcode() == Opcode::Or;
- }
-};
-
-class AtomicRMWInst : public SingleLLVMInstructionImpl<llvm::AtomicRMWInst> {
- AtomicRMWInst(llvm::AtomicRMWInst *Atomic, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::AtomicRMW,
- Instruction::Opcode::AtomicRMW, Atomic, Ctx) {
- }
- friend class Context; // For constructor.
-
-public:
- using BinOp = llvm::AtomicRMWInst::BinOp;
- BinOp getOperation() const {
- return cast<llvm::AtomicRMWInst>(Val)->getOperation();
- }
- static StringRef getOperationName(BinOp Op) {
- return llvm::AtomicRMWInst::getOperationName(Op);
- }
- static bool isFPOperation(BinOp Op) {
- return llvm::AtomicRMWInst::isFPOperation(Op);
- }
- void setOperation(BinOp Op) {
- cast<llvm::AtomicRMWInst>(Val)->setOperation(Op);
- }
- Align getAlign() const { return cast<llvm::AtomicRMWInst>(Val)->getAlign(); }
- void setAlignment(Align Align);
- bool isVolatile() const {
- return cast<llvm::AtomicRMWInst>(Val)->isVolatile();
- }
- void setVolatile(bool V);
- AtomicOrdering getOrdering() const {
- return cast<llvm::AtomicRMWInst>(Val)->getOrdering();
- }
- void setOrdering(AtomicOrdering Ordering);
- SyncScope::ID getSyncScopeID() const {
- return cast<llvm::AtomicRMWInst>(Val)->getSyncScopeID();
- }
- void setSyncScopeID(SyncScope::ID SSID);
- Value *getPointerOperand();
- const Value *getPointerOperand() const {
- return const_cast<AtomicRMWInst *>(this)->getPointerOperand();
- }
- Value *getValOperand();
- const Value *getValOperand() const {
- return const_cast<AtomicRMWInst *>(this)->getValOperand();
- }
- unsigned getPointerAddressSpace() const {
- return cast<llvm::AtomicRMWInst>(Val)->getPointerAddressSpace();
- }
- bool isFloatingPointOperation() const {
- return cast<llvm::AtomicRMWInst>(Val)->isFloatingPointOperation();
- }
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::AtomicRMW;
- }
-
- static AtomicRMWInst *create(BinOp Op, Value *Ptr, Value *Val,
- MaybeAlign Align, AtomicOrdering Ordering,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx,
- SyncScope::ID SSID = SyncScope::System,
- const Twine &Name = "");
- static AtomicRMWInst *create(BinOp Op, Value *Ptr, Value *Val,
- MaybeAlign Align, AtomicOrdering Ordering,
- Instruction *InsertBefore, Context &Ctx,
- SyncScope::ID SSID = SyncScope::System,
- const Twine &Name = "");
- static AtomicRMWInst *create(BinOp Op, Value *Ptr, Value *Val,
- MaybeAlign Align, AtomicOrdering Ordering,
- BasicBlock *InsertAtEnd, Context &Ctx,
- SyncScope::ID SSID = SyncScope::System,
- const Twine &Name = "");
-};
-
-class AtomicCmpXchgInst
- : public SingleLLVMInstructionImpl<llvm::AtomicCmpXchgInst> {
- AtomicCmpXchgInst(llvm::AtomicCmpXchgInst *Atomic, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::AtomicCmpXchg,
- Instruction::Opcode::AtomicCmpXchg, Atomic,
- Ctx) {}
- friend class Context; // For constructor.
-
-public:
- /// Return the alignment of the memory that is being allocated by the
- /// instruction.
- Align getAlign() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->getAlign();
- }
-
- void setAlignment(Align Align);
- /// Return true if this is a cmpxchg from a volatile memory
- /// location.
- bool isVolatile() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->isVolatile();
- }
- /// Specify whether this is a volatile cmpxchg.
- void setVolatile(bool V);
- /// Return true if this cmpxchg may spuriously fail.
- bool isWeak() const { return cast<llvm::AtomicCmpXchgInst>(Val)->isWeak(); }
- void setWeak(bool IsWeak);
- static bool isValidSuccessOrdering(AtomicOrdering Ordering) {
- return llvm::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering);
- }
- static bool isValidFailureOrdering(AtomicOrdering Ordering) {
- return llvm::AtomicCmpXchgInst::isValidFailureOrdering(Ordering);
- }
- AtomicOrdering getSuccessOrdering() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->getSuccessOrdering();
- }
- void setSuccessOrdering(AtomicOrdering Ordering);
-
- AtomicOrdering getFailureOrdering() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->getFailureOrdering();
- }
- void setFailureOrdering(AtomicOrdering Ordering);
- AtomicOrdering getMergedOrdering() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->getMergedOrdering();
- }
- SyncScope::ID getSyncScopeID() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->getSyncScopeID();
- }
- void setSyncScopeID(SyncScope::ID SSID);
- Value *getPointerOperand();
- const Value *getPointerOperand() const {
- return const_cast<AtomicCmpXchgInst *>(this)->getPointerOperand();
- }
-
- Value *getCompareOperand();
- const Value *getCompareOperand() const {
- return const_cast<AtomicCmpXchgInst *>(this)->getCompareOperand();
- }
-
- Value *getNewValOperand();
- const Value *getNewValOperand() const {
- return const_cast<AtomicCmpXchgInst *>(this)->getNewValOperand();
- }
-
- /// Returns the address space of the pointer operand.
- unsigned getPointerAddressSpace() const {
- return cast<llvm::AtomicCmpXchgInst>(Val)->getPointerAddressSpace();
- }
-
- static AtomicCmpXchgInst *
- create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
- AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
- BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
- SyncScope::ID SSID = SyncScope::System, const Twine &Name = "");
- static AtomicCmpXchgInst *
- create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
- AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
- Instruction *InsertBefore, Context &Ctx,
- SyncScope::ID SSID = SyncScope::System, const Twine &Name = "");
- static AtomicCmpXchgInst *
- create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
- AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
- BasicBlock *InsertAtEnd, Context &Ctx,
- SyncScope::ID SSID = SyncScope::System, const Twine &Name = "");
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::AtomicCmpXchg;
- }
-};
-
-class AllocaInst final : public UnaryInstruction {
- AllocaInst(llvm::AllocaInst *AI, Context &Ctx)
- : UnaryInstruction(ClassID::Alloca, Instruction::Opcode::Alloca, AI,
- Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static AllocaInst *create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- Value *ArraySize = nullptr, const Twine &Name = "");
- static AllocaInst *create(Type *Ty, unsigned AddrSpace,
- Instruction *InsertBefore, Context &Ctx,
- Value *ArraySize = nullptr, const Twine &Name = "");
- static AllocaInst *create(Type *Ty, unsigned AddrSpace,
- BasicBlock *InsertAtEnd, Context &Ctx,
- Value *ArraySize = nullptr, const Twine &Name = "");
-
- /// Return true if there is an allocation size parameter to the allocation
- /// instruction that is not 1.
- bool isArrayAllocation() const {
- return cast<llvm::AllocaInst>(Val)->isArrayAllocation();
- }
- /// Get the number of elements allocated. For a simple allocation of a single
- /// element, this will return a constant 1 value.
- Value *getArraySize();
- const Value *getArraySize() const {
- return const_cast<AllocaInst *>(this)->getArraySize();
- }
- /// Overload to return most specific pointer type.
- PointerType *getType() const;
- /// Return the address space for the allocation.
- unsigned getAddressSpace() const {
- return cast<llvm::AllocaInst>(Val)->getAddressSpace();
- }
- /// Get allocation size in bytes. Returns std::nullopt if size can't be
- /// determined, e.g. in case of a VLA.
- std::optional<TypeSize> getAllocationSize(const DataLayout &DL) const {
- return cast<llvm::AllocaInst>(Val)->getAllocationSize(DL);
- }
- /// Get allocation size in bits. Returns std::nullopt if size can't be
- /// determined, e.g. in case of a VLA.
- std::optional<TypeSize> getAllocationSizeInBits(const DataLayout &DL) const {
- return cast<llvm::AllocaInst>(Val)->getAllocationSizeInBits(DL);
- }
- /// Return the type that is being allocated by the instruction.
- Type *getAllocatedType() const;
- /// for use only in special circumstances that need to generically
- /// transform a whole instruction (eg: IR linking and vectorization).
- void setAllocatedType(Type *Ty);
- /// Return the alignment of the memory that is being allocated by the
- /// instruction.
- Align getAlign() const { return cast<llvm::AllocaInst>(Val)->getAlign(); }
- void setAlignment(Align Align);
- /// Return true if this alloca is in the entry block of the function and is a
- /// constant size. If so, the code generator will fold it into the
- /// prolog/epilog code, so it is basically free.
- bool isStaticAlloca() const {
- return cast<llvm::AllocaInst>(Val)->isStaticAlloca();
- }
- /// Return true if this alloca is used as an inalloca argument to a call. Such
- /// allocas are never considered static even if they are in the entry block.
- bool isUsedWithInAlloca() const {
- return cast<llvm::AllocaInst>(Val)->isUsedWithInAlloca();
- }
- /// Specify whether this alloca is used to represent the arguments to a call.
- void setUsedWithInAlloca(bool V);
-
- static bool classof(const Value *From) {
- if (auto *I = dyn_cast<Instruction>(From))
- return I->getSubclassID() == Instruction::ClassID::Alloca;
- return false;
- }
-};
-
-class CastInst : public UnaryInstruction {
- static Opcode getCastOpcode(llvm::Instruction::CastOps CastOp) {
- switch (CastOp) {
- case llvm::Instruction::ZExt:
- return Opcode::ZExt;
- case llvm::Instruction::SExt:
- return Opcode::SExt;
- case llvm::Instruction::FPToUI:
- return Opcode::FPToUI;
- case llvm::Instruction::FPToSI:
- return Opcode::FPToSI;
- case llvm::Instruction::FPExt:
- return Opcode::FPExt;
- case llvm::Instruction::PtrToInt:
- return Opcode::PtrToInt;
- case llvm::Instruction::IntToPtr:
- return Opcode::IntToPtr;
- case llvm::Instruction::SIToFP:
- return Opcode::SIToFP;
- case llvm::Instruction::UIToFP:
- return Opcode::UIToFP;
- case llvm::Instruction::Trunc:
- return Opcode::Trunc;
- case llvm::Instruction::FPTrunc:
- return Opcode::FPTrunc;
- case llvm::Instruction::BitCast:
- return Opcode::BitCast;
- case llvm::Instruction::AddrSpaceCast:
- return Opcode::AddrSpaceCast;
- case llvm::Instruction::CastOpsEnd:
- llvm_unreachable("Bad CastOp!");
- }
- llvm_unreachable("Unhandled CastOp!");
- }
- /// Use Context::createCastInst(). Don't call the
- /// constructor directly.
- CastInst(llvm::CastInst *CI, Context &Ctx)
- : UnaryInstruction(ClassID::Cast, getCastOpcode(CI->getOpcode()), CI,
- Ctx) {}
- friend Context; // for SBCastInstruction()
-
-public:
- static Value *create(Type *DestTy, Opcode Op, Value *Operand,
- BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Type *DestTy, Opcode Op, Value *Operand,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static Value *create(Type *DestTy, Opcode Op, Value *Operand,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name = "");
- /// For isa/dyn_cast.
- static bool classof(const Value *From);
- Type *getSrcTy() const;
- Type *getDestTy() const;
-};
-
-/// Instruction that can have a nneg flag (zext/uitofp).
-class PossiblyNonNegInst : public CastInst {
-public:
- bool hasNonNeg() const {
- return cast<llvm::PossiblyNonNegInst>(Val)->hasNonNeg();
- }
- void setNonNeg(bool B);
- /// For isa/dyn_cast.
- static bool classof(const Value *From) {
- if (auto *I = dyn_cast<Instruction>(From)) {
- switch (I->getOpcode()) {
- case Opcode::ZExt:
- case Opcode::UIToFP:
- return true;
- default:
- return false;
- }
- }
- return false;
- }
-};
-
-// Helper class to simplify stamping out CastInst subclasses.
-template <Instruction::Opcode Op> class CastInstImpl : public CastInst {
-public:
- static Value *create(Value *Src, Type *DestTy, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name = "") {
- return CastInst::create(DestTy, Op, Src, WhereIt, WhereBB, Ctx, Name);
- }
- static Value *create(Value *Src, Type *DestTy, Instruction *InsertBefore,
- Context &Ctx, const Twine &Name = "") {
- return create(Src, DestTy, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, Name);
- }
- static Value *create(Value *Src, Type *DestTy, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &Name = "") {
- return create(Src, DestTy, InsertAtEnd->end(), InsertAtEnd, Ctx, Name);
- }
-
- static bool classof(const Value *From) {
- if (auto *I = dyn_cast<Instruction>(From))
- return I->getOpcode() == Op;
- return false;
- }
-};
-
-class TruncInst final : public CastInstImpl<Instruction::Opcode::Trunc> {};
-class ZExtInst final : public CastInstImpl<Instruction::Opcode::ZExt> {};
-class SExtInst final : public CastInstImpl<Instruction::Opcode::SExt> {};
-class FPTruncInst final : public CastInstImpl<Instruction::Opcode::FPTrunc> {};
-class FPExtInst final : public CastInstImpl<Instruction::Opcode::FPExt> {};
-class UIToFPInst final : public CastInstImpl<Instruction::Opcode::UIToFP> {};
-class SIToFPInst final : public CastInstImpl<Instruction::Opcode::SIToFP> {};
-class FPToUIInst final : public CastInstImpl<Instruction::Opcode::FPToUI> {};
-class FPToSIInst final : public CastInstImpl<Instruction::Opcode::FPToSI> {};
-class IntToPtrInst final : public CastInstImpl<Instruction::Opcode::IntToPtr> {
-};
-class PtrToIntInst final : public CastInstImpl<Instruction::Opcode::PtrToInt> {
-};
-class BitCastInst final : public CastInstImpl<Instruction::Opcode::BitCast> {};
-class AddrSpaceCastInst final
- : public CastInstImpl<Instruction::Opcode::AddrSpaceCast> {
-public:
- /// \Returns the pointer operand.
- Value *getPointerOperand() { return getOperand(0); }
- /// \Returns the pointer operand.
- const Value *getPointerOperand() const {
- return const_cast<AddrSpaceCastInst *>(this)->getPointerOperand();
- }
- /// \Returns the operand index of the pointer operand.
- static unsigned getPointerOperandIndex() { return 0u; }
- /// \Returns the address space of the pointer operand.
- unsigned getSrcAddressSpace() const {
- return getPointerOperand()->getType()->getPointerAddressSpace();
- }
- /// \Returns the address space of the result.
- unsigned getDestAddressSpace() const {
- return getType()->getPointerAddressSpace();
- }
-};
-
-class PHINode final : public SingleLLVMInstructionImpl<llvm::PHINode> {
- /// Use Context::createPHINode(). Don't call the constructor directly.
- PHINode(llvm::PHINode *PHI, Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::PHI, Opcode::PHI, PHI, Ctx) {}
- friend Context; // for PHINode()
- /// Helper for mapped_iterator.
- struct LLVMBBToBB {
- Context &Ctx;
- LLVMBBToBB(Context &Ctx) : Ctx(Ctx) {}
- BasicBlock *operator()(llvm::BasicBlock *LLVMBB) const;
- };
-
-public:
- static PHINode *create(Type *Ty, unsigned NumReservedValues,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- /// For isa/dyn_cast.
- static bool classof(const Value *From);
-
- using const_block_iterator =
- mapped_iterator<llvm::PHINode::const_block_iterator, LLVMBBToBB>;
-
- const_block_iterator block_begin() const {
- LLVMBBToBB BBGetter(Ctx);
- return const_block_iterator(cast<llvm::PHINode>(Val)->block_begin(),
- BBGetter);
- }
- const_block_iterator block_end() const {
- LLVMBBToBB BBGetter(Ctx);
- return const_block_iterator(cast<llvm::PHINode>(Val)->block_end(),
- BBGetter);
- }
- iterator_range<const_block_iterator> blocks() const {
- return make_range(block_begin(), block_end());
- }
-
- op_range incoming_values() { return operands(); }
-
- const_op_range incoming_values() const { return operands(); }
-
- unsigned getNumIncomingValues() const {
- return cast<llvm::PHINode>(Val)->getNumIncomingValues();
- }
- Value *getIncomingValue(unsigned Idx) const;
- void setIncomingValue(unsigned Idx, Value *V);
- static unsigned getOperandNumForIncomingValue(unsigned Idx) {
- return llvm::PHINode::getOperandNumForIncomingValue(Idx);
- }
- static unsigned getIncomingValueNumForOperand(unsigned Idx) {
- return llvm::PHINode::getIncomingValueNumForOperand(Idx);
- }
- BasicBlock *getIncomingBlock(unsigned Idx) const;
- BasicBlock *getIncomingBlock(const Use &U) const;
-
- void setIncomingBlock(unsigned Idx, BasicBlock *BB);
-
- void addIncoming(Value *V, BasicBlock *BB);
-
- Value *removeIncomingValue(unsigned Idx);
- Value *removeIncomingValue(BasicBlock *BB);
-
- int getBasicBlockIndex(const BasicBlock *BB) const;
- Value *getIncomingValueForBlock(const BasicBlock *BB) const;
-
- Value *hasConstantValue() const;
-
- bool hasConstantOrUndefValue() const {
- return cast<llvm::PHINode>(Val)->hasConstantOrUndefValue();
- }
- bool isComplete() const { return cast<llvm::PHINode>(Val)->isComplete(); }
- void replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New);
- void removeIncomingValueIf(function_ref<bool(unsigned)> Predicate);
- // TODO: Implement
- // void copyIncomingBlocks(iterator_range<const_block_iterator> BBRange,
- // uint32_t ToIdx = 0)
-};
-
-// Wraps a static function that takes a single Predicate parameter
-// LLVMValType should be the type of the wrapped class
-#define WRAP_STATIC_PREDICATE(FunctionName) \
- static auto FunctionName(Predicate P) { return LLVMValType::FunctionName(P); }
-// Wraps a member function that takes no parameters
-// LLVMValType should be the type of the wrapped class
-#define WRAP_MEMBER(FunctionName) \
- auto FunctionName() const { return cast<LLVMValType>(Val)->FunctionName(); }
-// Wraps both--a common idiom in the CmpInst classes
-#define WRAP_BOTH(FunctionName) \
- WRAP_STATIC_PREDICATE(FunctionName) \
- WRAP_MEMBER(FunctionName)
-
-class CmpInst : public SingleLLVMInstructionImpl<llvm::CmpInst> {
-protected:
- using LLVMValType = llvm::CmpInst;
- /// Use Context::createCmpInst(). Don't call the constructor directly.
- CmpInst(llvm::CmpInst *CI, Context &Ctx, ClassID Id, Opcode Opc)
- : SingleLLVMInstructionImpl(Id, Opc, CI, Ctx) {}
- friend Context; // for CmpInst()
- static Value *createCommon(Value *Cond, Value *True, Value *False,
- const Twine &Name, IRBuilder<> &Builder,
- Context &Ctx);
-
-public:
- using Predicate = llvm::CmpInst::Predicate;
-
- static CmpInst *create(Predicate Pred, Value *S1, Value *S2,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- static CmpInst *createWithCopiedFlags(Predicate Pred, Value *S1, Value *S2,
- const Instruction *FlagsSource,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name = "");
- void setPredicate(Predicate P);
- void swapOperands();
-
- WRAP_MEMBER(getPredicate);
- WRAP_BOTH(isFPPredicate);
- WRAP_BOTH(isIntPredicate);
- WRAP_STATIC_PREDICATE(getPredicateName);
- WRAP_BOTH(getInversePredicate);
- WRAP_BOTH(getOrderedPredicate);
- WRAP_BOTH(getUnorderedPredicate);
- WRAP_BOTH(getSwappedPredicate);
- WRAP_BOTH(isStrictPredicate);
- WRAP_BOTH(isNonStrictPredicate);
- WRAP_BOTH(getStrictPredicate);
- WRAP_BOTH(getNonStrictPredicate);
- WRAP_BOTH(getFlippedStrictnessPredicate);
- WRAP_MEMBER(isCommutative);
- WRAP_BOTH(isEquality);
- WRAP_BOTH(isRelational);
- WRAP_BOTH(isSigned);
- WRAP_BOTH(getSignedPredicate);
- WRAP_BOTH(getUnsignedPredicate);
- WRAP_BOTH(getFlippedSignednessPredicate);
- WRAP_BOTH(isTrueWhenEqual);
- WRAP_BOTH(isFalseWhenEqual);
- WRAP_BOTH(isUnsigned);
- WRAP_STATIC_PREDICATE(isOrdered);
- WRAP_STATIC_PREDICATE(isUnordered);
-
- static bool isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
- return llvm::CmpInst::isImpliedTrueByMatchingCmp(Pred1, Pred2);
- }
- static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2) {
- return llvm::CmpInst::isImpliedFalseByMatchingCmp(Pred1, Pred2);
- }
-
- /// Method for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::ICmp ||
- From->getSubclassID() == ClassID::FCmp;
- }
-
- /// Create a result type for fcmp/icmp
- static Type *makeCmpResultType(Type *OpndType);
-
-#ifndef NDEBUG
- void dumpOS(raw_ostream &OS) const override;
- LLVM_DUMP_METHOD void dump() const;
-#endif
-};
-
-class ICmpInst : public CmpInst {
- /// Use Context::createICmpInst(). Don't call the constructor directly.
- ICmpInst(llvm::ICmpInst *CI, Context &Ctx)
- : CmpInst(CI, Ctx, ClassID::ICmp, Opcode::ICmp) {}
- friend class Context; // For constructor.
- using LLVMValType = llvm::ICmpInst;
-
-public:
- void swapOperands();
-
- WRAP_BOTH(getSignedPredicate);
- WRAP_BOTH(getUnsignedPredicate);
- WRAP_BOTH(isEquality);
- WRAP_MEMBER(isCommutative);
- WRAP_MEMBER(isRelational);
- WRAP_STATIC_PREDICATE(isGT);
- WRAP_STATIC_PREDICATE(isLT);
- WRAP_STATIC_PREDICATE(isGE);
- WRAP_STATIC_PREDICATE(isLE);
-
- static auto predicates() { return llvm::ICmpInst::predicates(); }
- static bool compare(const APInt &LHS, const APInt &RHS,
- ICmpInst::Predicate Pred) {
- return llvm::ICmpInst::compare(LHS, RHS, Pred);
- }
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::ICmp;
- }
-};
-
-class FCmpInst : public CmpInst {
- /// Use Context::createFCmpInst(). Don't call the constructor directly.
- FCmpInst(llvm::FCmpInst *CI, Context &Ctx)
- : CmpInst(CI, Ctx, ClassID::FCmp, Opcode::FCmp) {}
- friend class Context; // For constructor.
- using LLVMValType = llvm::FCmpInst;
-
-public:
- void swapOperands();
-
- WRAP_BOTH(isEquality);
- WRAP_MEMBER(isCommutative);
- WRAP_MEMBER(isRelational);
-
- static auto predicates() { return llvm::FCmpInst::predicates(); }
- static bool compare(const APFloat &LHS, const APFloat &RHS,
- FCmpInst::Predicate Pred) {
- return llvm::FCmpInst::compare(LHS, RHS, Pred);
- }
-
- static bool classof(const Value *From) {
- return From->getSubclassID() == ClassID::FCmp;
- }
-};
-
-#undef WRAP_STATIC_PREDICATE
-#undef WRAP_MEMBER
-#undef WRAP_BOTH
-
-/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
-/// an OpaqueInstr.
-class OpaqueInst : public SingleLLVMInstructionImpl<llvm::Instruction> {
- OpaqueInst(llvm::Instruction *I, sandboxir::Context &Ctx)
- : SingleLLVMInstructionImpl(ClassID::Opaque, Opcode::Opaque, I, Ctx) {}
- OpaqueInst(ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
- : SingleLLVMInstructionImpl(SubclassID, Opcode::Opaque, I, Ctx) {}
- friend class Context; // For constructor.
-
-public:
- static bool classof(const sandboxir::Value *From) {
- return From->getSubclassID() == ClassID::Opaque;
- }
-};
-
} // namespace sandboxir
} // namespace llvm
diff --git a/llvm/include/llvm/SandboxIR/Utils.h b/llvm/include/llvm/SandboxIR/Utils.h
index 4e8a175f547059..690848932229e4 100644
--- a/llvm/include/llvm/SandboxIR/Utils.h
+++ b/llvm/include/llvm/SandboxIR/Utils.h
@@ -13,7 +13,7 @@
#define LLVM_SANDBOXIR_UTILS_H
#include "llvm/Analysis/MemoryLocation.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
namespace llvm::sandboxir {
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
index 99582e3e0e0233..a2108f07c28e50 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
@@ -13,8 +13,8 @@
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_BOTTOMUPVEC_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/SandboxIR/Constant.h"
#include "llvm/SandboxIR/Pass.h"
-#include "llvm/SandboxIR/SandboxIR.h"
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
namespace llvm::sandboxir {
diff --git a/llvm/lib/SandboxIR/BasicBlock.cpp b/llvm/lib/SandboxIR/BasicBlock.cpp
index 7eba53ffb5ec4a..ebca41aa39da82 100644
--- a/llvm/lib/SandboxIR/BasicBlock.cpp
+++ b/llvm/lib/SandboxIR/BasicBlock.cpp
@@ -8,7 +8,7 @@
#include "llvm/SandboxIR/BasicBlock.h"
#include "llvm/SandboxIR/Context.h"
-#include "llvm/SandboxIR/SandboxIR.h" // TODO: remove this
+#include "llvm/SandboxIR/Instruction.h"
namespace llvm::sandboxir {
diff --git a/llvm/lib/SandboxIR/CMakeLists.txt b/llvm/lib/SandboxIR/CMakeLists.txt
index deea86d442d395..7c817ed133ed8e 100644
--- a/llvm/lib/SandboxIR/CMakeLists.txt
+++ b/llvm/lib/SandboxIR/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMSandboxIR
BasicBlock.cpp
Constant.cpp
Context.cpp
+ Instruction.cpp
Module.cpp
Pass.cpp
PassManager.cpp
diff --git a/llvm/lib/SandboxIR/Context.cpp b/llvm/lib/SandboxIR/Context.cpp
index d10cb18e6d3684..0a61e329b78c51 100644
--- a/llvm/lib/SandboxIR/Context.cpp
+++ b/llvm/lib/SandboxIR/Context.cpp
@@ -7,7 +7,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/SandboxIR/Context.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/SandboxIR/Module.h"
namespace llvm::sandboxir {
@@ -670,6 +671,8 @@ Context::Context(LLVMContext &LLVMCtx)
: LLVMCtx(LLVMCtx), IRTracker(*this),
LLVMIRBuilder(LLVMCtx, ConstantFolder()) {}
+Context::~Context() {}
+
Module *Context::getModule(llvm::Module *LLVMM) const {
auto It = LLVMModuleToModuleMap.find(LLVMM);
if (It != LLVMModuleToModuleMap.end())
diff --git a/llvm/lib/SandboxIR/Instruction.cpp b/llvm/lib/SandboxIR/Instruction.cpp
new file mode 100644
index 00000000000000..919a44fca8b041
--- /dev/null
+++ b/llvm/lib/SandboxIR/Instruction.cpp
@@ -0,0 +1,1965 @@
+//===- Instruction.cpp - The Instructions of Sandbox IR -------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/SandboxIR/Instruction.h"
+
+namespace llvm::sandboxir {
+
+const char *Instruction::getOpcodeName(Opcode Opc) {
+ switch (Opc) {
+#define OP(OPC) \
+ case Opcode::OPC: \
+ return #OPC;
+#define OPCODES(...) __VA_ARGS__
+#define DEF_INSTR(ID, OPC, CLASS) OPC
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ }
+ llvm_unreachable("Unknown Opcode");
+}
+
+llvm::Instruction *Instruction::getTopmostLLVMInstruction() const {
+ Instruction *Prev = getPrevNode();
+ if (Prev == nullptr) {
+ // If at top of the BB, return the first BB instruction.
+ return &*cast<llvm::BasicBlock>(getParent()->Val)->begin();
+ }
+ // Else get the Previous sandbox IR instruction's bottom IR instruction and
+ // return its successor.
+ llvm::Instruction *PrevBotI = cast<llvm::Instruction>(Prev->Val);
+ return PrevBotI->getNextNode();
+}
+
+BBIterator Instruction::getIterator() const {
+ auto *I = cast<llvm::Instruction>(Val);
+ return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx);
+}
+
+Instruction *Instruction::getNextNode() const {
+ assert(getParent() != nullptr && "Detached!");
+ assert(getIterator() != getParent()->end() && "Already at end!");
+ // `Val` is the bottom-most LLVM IR instruction. Get the next in the chain,
+ // and get the corresponding sandboxir Instruction that maps to it. This works
+ // even for SandboxIR Instructions that map to more than one LLVM Instruction.
+ auto *LLVMI = cast<llvm::Instruction>(Val);
+ assert(LLVMI->getParent() != nullptr && "LLVM IR instr is detached!");
+ auto *NextLLVMI = LLVMI->getNextNode();
+ auto *NextI = cast_or_null<Instruction>(Ctx.getValue(NextLLVMI));
+ if (NextI == nullptr)
+ return nullptr;
+ return NextI;
+}
+
+Instruction *Instruction::getPrevNode() const {
+ assert(getParent() != nullptr && "Detached!");
+ auto It = getIterator();
+ if (It != getParent()->begin())
+ return std::prev(getIterator()).get();
+ return nullptr;
+}
+
+void Instruction::removeFromParent() {
+ Ctx.getTracker().emplaceIfTracking<RemoveFromParent>(this);
+
+ // Detach all the LLVM IR instructions from their parent BB.
+ for (llvm::Instruction *I : getLLVMInstrs())
+ I->removeFromParent();
+}
+
+void Instruction::eraseFromParent() {
+ assert(users().empty() && "Still connected to users, can't erase!");
+ std::unique_ptr<Value> Detached = Ctx.detach(this);
+ auto LLVMInstrs = getLLVMInstrs();
+
+ auto &Tracker = Ctx.getTracker();
+ if (Tracker.isTracking()) {
+ Tracker.track(std::make_unique<EraseFromParent>(std::move(Detached)));
+ // We don't actually delete the IR instruction, because then it would be
+ // impossible to bring it back from the dead at the same memory location.
+ // Instead we remove it from its BB and track its current location.
+ for (llvm::Instruction *I : LLVMInstrs)
+ I->removeFromParent();
+ // TODO: Multi-instructions need special treatment because some of the
+ // references are internal to the instruction.
+ for (llvm::Instruction *I : LLVMInstrs)
+ I->dropAllReferences();
+ } else {
+ // Erase in reverse to avoid erasing nstructions with attached uses.
+ for (llvm::Instruction *I : reverse(LLVMInstrs))
+ I->eraseFromParent();
+ }
+}
+
+void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) {
+ if (std::next(getIterator()) == WhereIt)
+ // Destination is same as origin, nothing to do.
+ return;
+
+ Ctx.getTracker().emplaceIfTracking<MoveInstr>(this);
+
+ auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val);
+ llvm::BasicBlock::iterator It;
+ if (WhereIt == BB.end()) {
+ It = LLVMBB->end();
+ } else {
+ Instruction *WhereI = &*WhereIt;
+ It = WhereI->getTopmostLLVMInstruction()->getIterator();
+ }
+ // TODO: Move this to the verifier of sandboxir::Instruction.
+ assert(is_sorted(getLLVMInstrs(),
+ [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
+ "Expected program order!");
+ // Do the actual move in LLVM IR.
+ for (auto *I : getLLVMInstrs())
+ I->moveBefore(*LLVMBB, It);
+}
+
+void Instruction::insertBefore(Instruction *BeforeI) {
+ llvm::Instruction *BeforeTopI = BeforeI->getTopmostLLVMInstruction();
+ // TODO: Move this to the verifier of sandboxir::Instruction.
+ assert(is_sorted(getLLVMInstrs(),
+ [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
+ "Expected program order!");
+
+ Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);
+
+ // Insert the LLVM IR Instructions in program order.
+ for (llvm::Instruction *I : getLLVMInstrs())
+ I->insertBefore(BeforeTopI);
+}
+
+void Instruction::insertAfter(Instruction *AfterI) {
+ insertInto(AfterI->getParent(), std::next(AfterI->getIterator()));
+}
+
+void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) {
+ llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
+ llvm::Instruction *LLVMBeforeI;
+ llvm::BasicBlock::iterator LLVMBeforeIt;
+ Instruction *BeforeI;
+ if (WhereIt != BB->end()) {
+ BeforeI = &*WhereIt;
+ LLVMBeforeI = BeforeI->getTopmostLLVMInstruction();
+ LLVMBeforeIt = LLVMBeforeI->getIterator();
+ } else {
+ BeforeI = nullptr;
+ LLVMBeforeI = nullptr;
+ LLVMBeforeIt = LLVMBB->end();
+ }
+
+ Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);
+
+ // Insert the LLVM IR Instructions in program order.
+ for (llvm::Instruction *I : getLLVMInstrs())
+ I->insertInto(LLVMBB, LLVMBeforeIt);
+}
+
+BasicBlock *Instruction::getParent() const {
+ // Get the LLVM IR Instruction that this maps to, get its parent, and get the
+ // corresponding sandboxir::BasicBlock by looking it up in sandboxir::Context.
+ auto *BB = cast<llvm::Instruction>(Val)->getParent();
+ if (BB == nullptr)
+ return nullptr;
+ return cast<BasicBlock>(Ctx.getValue(BB));
+}
+
+bool Instruction::classof(const sandboxir::Value *From) {
+ switch (From->getSubclassID()) {
+#define DEF_INSTR(ID, OPC, CLASS) \
+ case ClassID::ID: \
+ return true;
+#include "llvm/SandboxIR/SandboxIRValues.def"
+ default:
+ return false;
+ }
+}
+
+void Instruction::setHasNoUnsignedWrap(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap,
+ &Instruction::setHasNoUnsignedWrap>>(
+ this);
+ cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B);
+}
+
+void Instruction::setHasNoSignedWrap(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap,
+ &Instruction::setHasNoSignedWrap>>(this);
+ cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B);
+}
+
+void Instruction::setFast(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&Instruction::isFast, &Instruction::setFast>>(this);
+ cast<llvm::Instruction>(Val)->setFast(B);
+}
+
+void Instruction::setIsExact(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(this);
+ cast<llvm::Instruction>(Val)->setIsExact(B);
+}
+
+void Instruction::setHasAllowReassoc(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc,
+ &Instruction::setHasAllowReassoc>>(this);
+ cast<llvm::Instruction>(Val)->setHasAllowReassoc(B);
+}
+
+void Instruction::setHasNoNaNs(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>(
+ this);
+ cast<llvm::Instruction>(Val)->setHasNoNaNs(B);
+}
+
+void Instruction::setHasNoInfs(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>(
+ this);
+ cast<llvm::Instruction>(Val)->setHasNoInfs(B);
+}
+
+void Instruction::setHasNoSignedZeros(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros,
+ &Instruction::setHasNoSignedZeros>>(
+ this);
+ cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B);
+}
+
+void Instruction::setHasAllowReciprocal(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal,
+ &Instruction::setHasAllowReciprocal>>(
+ this);
+ cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B);
+}
+
+void Instruction::setHasAllowContract(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract,
+ &Instruction::setHasAllowContract>>(
+ this);
+ cast<llvm::Instruction>(Val)->setHasAllowContract(B);
+}
+
+void Instruction::setFastMathFlags(FastMathFlags FMF) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
+ &Instruction::copyFastMathFlags>>(this);
+ cast<llvm::Instruction>(Val)->setFastMathFlags(FMF);
+}
+
+void Instruction::copyFastMathFlags(FastMathFlags FMF) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
+ &Instruction::copyFastMathFlags>>(this);
+ cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF);
+}
+
+Type *Instruction::getAccessType() const {
+ return Ctx.getType(cast<llvm::Instruction>(Val)->getAccessType());
+}
+
+void Instruction::setHasApproxFunc(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc,
+ &Instruction::setHasApproxFunc>>(this);
+ cast<llvm::Instruction>(Val)->setHasApproxFunc(B);
+}
+
+#ifndef NDEBUG
+void Instruction::dumpOS(raw_ostream &OS) const {
+ OS << "Unimplemented! Please override dump().";
+}
+#endif // NDEBUG
+
+VAArgInst *VAArgInst::create(Value *List, Type *Ty, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ auto *LLVMI =
+ cast<llvm::VAArgInst>(Builder.CreateVAArg(List->Val, Ty->LLVMTy, Name));
+ return Ctx.createVAArgInst(LLVMI);
+}
+
+Value *VAArgInst::getPointerOperand() {
+ return Ctx.getValue(cast<llvm::VAArgInst>(Val)->getPointerOperand());
+}
+
+FreezeInst *FreezeInst::create(Value *V, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ auto *LLVMI = cast<llvm::FreezeInst>(Builder.CreateFreeze(V->Val, Name));
+ return Ctx.createFreezeInst(LLVMI);
+}
+
+FenceInst *FenceInst::create(AtomicOrdering Ordering, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ SyncScope::ID SSID) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::FenceInst *LLVMI = Builder.CreateFence(Ordering, SSID);
+ return Ctx.createFenceInst(LLVMI);
+}
+
+void FenceInst::setOrdering(AtomicOrdering Ordering) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&FenceInst::getOrdering, &FenceInst::setOrdering>>(
+ this);
+ cast<llvm::FenceInst>(Val)->setOrdering(Ordering);
+}
+
+void FenceInst::setSyncScopeID(SyncScope::ID SSID) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&FenceInst::getSyncScopeID,
+ &FenceInst::setSyncScopeID>>(this);
+ cast<llvm::FenceInst>(Val)->setSyncScopeID(SSID);
+}
+
+Value *SelectInst::createCommon(Value *Cond, Value *True, Value *False,
+ const Twine &Name, IRBuilder<> &Builder,
+ Context &Ctx) {
+ llvm::Value *NewV =
+ Builder.CreateSelect(Cond->Val, True->Val, False->Val, Name);
+ if (auto *NewSI = dyn_cast<llvm::SelectInst>(NewV))
+ return Ctx.createSelectInst(NewSI);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *SelectInst::create(Value *Cond, Value *True, Value *False,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(BeforeIR);
+ return createCommon(Cond, True, False, Name, Builder, Ctx);
+}
+
+Value *SelectInst::create(Value *Cond, Value *True, Value *False,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ auto *IRInsertAtEnd = cast<llvm::BasicBlock>(InsertAtEnd->Val);
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(IRInsertAtEnd);
+ return createCommon(Cond, True, False, Name, Builder, Ctx);
+}
+
+void SelectInst::swapValues() {
+ Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(1),
+ getOperandUse(2));
+ cast<llvm::SelectInst>(Val)->swapValues();
+}
+
+bool SelectInst::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Select;
+}
+
+BranchInst *BranchInst::create(BasicBlock *IfTrue, Instruction *InsertBefore,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
+ Builder.SetInsertPoint(cast<llvm::Instruction>(LLVMBefore));
+ llvm::BranchInst *NewBr =
+ Builder.CreateBr(cast<llvm::BasicBlock>(IfTrue->Val));
+ return Ctx.createBranchInst(NewBr);
+}
+
+BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::BranchInst *NewBr =
+ Builder.CreateBr(cast<llvm::BasicBlock>(IfTrue->Val));
+ return Ctx.createBranchInst(NewBr);
+}
+
+BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse,
+ Value *Cond, Instruction *InsertBefore,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
+ Builder.SetInsertPoint(LLVMBefore);
+ llvm::BranchInst *NewBr =
+ Builder.CreateCondBr(Cond->Val, cast<llvm::BasicBlock>(IfTrue->Val),
+ cast<llvm::BasicBlock>(IfFalse->Val));
+ return Ctx.createBranchInst(NewBr);
+}
+
+BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse,
+ Value *Cond, BasicBlock *InsertAtEnd,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::BranchInst *NewBr =
+ Builder.CreateCondBr(Cond->Val, cast<llvm::BasicBlock>(IfTrue->Val),
+ cast<llvm::BasicBlock>(IfFalse->Val));
+ return Ctx.createBranchInst(NewBr);
+}
+
+bool BranchInst::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Br;
+}
+
+Value *BranchInst::getCondition() const {
+ assert(isConditional() && "Cannot get condition of an uncond branch!");
+ return Ctx.getValue(cast<llvm::BranchInst>(Val)->getCondition());
+}
+
+BasicBlock *BranchInst::getSuccessor(unsigned SuccIdx) const {
+ assert(SuccIdx < getNumSuccessors() &&
+ "Successor # out of range for Branch!");
+ return cast_or_null<BasicBlock>(
+ Ctx.getValue(cast<llvm::BranchInst>(Val)->getSuccessor(SuccIdx)));
+}
+
+void BranchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
+ assert((Idx == 0 || Idx == 1) && "Out of bounds!");
+ setOperand(2u - Idx, NewSucc);
+}
+
+BasicBlock *BranchInst::LLVMBBToSBBB::operator()(llvm::BasicBlock *BB) const {
+ return cast<BasicBlock>(Ctx.getValue(BB));
+}
+const BasicBlock *
+BranchInst::ConstLLVMBBToSBBB::operator()(const llvm::BasicBlock *BB) const {
+ return cast<BasicBlock>(Ctx.getValue(BB));
+}
+
+void LoadInst::setVolatile(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&LoadInst::isVolatile, &LoadInst::setVolatile>>(this);
+ cast<llvm::LoadInst>(Val)->setVolatile(V);
+}
+
+LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ return create(Ty, Ptr, Align, InsertBefore, /*IsVolatile=*/false, Ctx, Name);
+}
+
+LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, bool IsVolatile,
+ Context &Ctx, const Twine &Name) {
+ llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(BeforeIR);
+ auto *NewLI =
+ Builder.CreateAlignedLoad(Ty->LLVMTy, Ptr->Val, Align, IsVolatile, Name);
+ auto *NewSBI = Ctx.createLoadInst(NewLI);
+ return NewSBI;
+}
+
+LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ return create(Ty, Ptr, Align, InsertAtEnd, /*IsVolatile=*/false, Ctx, Name);
+}
+
+LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, bool IsVolatile,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ auto *NewLI =
+ Builder.CreateAlignedLoad(Ty->LLVMTy, Ptr->Val, Align, IsVolatile, Name);
+ auto *NewSBI = Ctx.createLoadInst(NewLI);
+ return NewSBI;
+}
+
+bool LoadInst::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Load;
+}
+
+Value *LoadInst::getPointerOperand() const {
+ return Ctx.getValue(cast<llvm::LoadInst>(Val)->getPointerOperand());
+}
+
+void StoreInst::setVolatile(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&StoreInst::isVolatile, &StoreInst::setVolatile>>(this);
+ cast<llvm::StoreInst>(Val)->setVolatile(V);
+}
+
+StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, Context &Ctx) {
+ return create(V, Ptr, Align, InsertBefore, /*IsVolatile=*/false, Ctx);
+}
+
+StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
+ Instruction *InsertBefore, bool IsVolatile,
+ Context &Ctx) {
+ llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(BeforeIR);
+ auto *NewSI = Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, IsVolatile);
+ auto *NewSBI = Ctx.createStoreInst(NewSI);
+ return NewSBI;
+}
+
+StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, Context &Ctx) {
+ return create(V, Ptr, Align, InsertAtEnd, /*IsVolatile=*/false, Ctx);
+}
+
+StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
+ BasicBlock *InsertAtEnd, bool IsVolatile,
+ Context &Ctx) {
+ auto *InsertAtEndIR = cast<llvm::BasicBlock>(InsertAtEnd->Val);
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(InsertAtEndIR);
+ auto *NewSI = Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, IsVolatile);
+ auto *NewSBI = Ctx.createStoreInst(NewSI);
+ return NewSBI;
+}
+
+bool StoreInst::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Store;
+}
+
+Value *StoreInst::getValueOperand() const {
+ return Ctx.getValue(cast<llvm::StoreInst>(Val)->getValueOperand());
+}
+
+Value *StoreInst::getPointerOperand() const {
+ return Ctx.getValue(cast<llvm::StoreInst>(Val)->getPointerOperand());
+}
+
+UnreachableInst *UnreachableInst::create(Instruction *InsertBefore,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
+ Builder.SetInsertPoint(LLVMBefore);
+ llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
+ return Ctx.createUnreachableInst(NewUI);
+}
+
+UnreachableInst *UnreachableInst::create(BasicBlock *InsertAtEnd,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
+ return Ctx.createUnreachableInst(NewUI);
+}
+
+bool UnreachableInst::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Unreachable;
+}
+
+ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder,
+ Context &Ctx) {
+ llvm::ReturnInst *NewRI;
+ if (RetVal != nullptr)
+ NewRI = Builder.CreateRet(RetVal->Val);
+ else
+ NewRI = Builder.CreateRetVoid();
+ return Ctx.createReturnInst(NewRI);
+}
+
+ReturnInst *ReturnInst::create(Value *RetVal, Instruction *InsertBefore,
+ Context &Ctx) {
+ llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(BeforeIR);
+ return createCommon(RetVal, Builder, Ctx);
+}
+
+ReturnInst *ReturnInst::create(Value *RetVal, BasicBlock *InsertAtEnd,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ return createCommon(RetVal, Builder, Ctx);
+}
+
+Value *ReturnInst::getReturnValue() const {
+ auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue();
+ return LLVMRetVal != nullptr ? Ctx.getValue(LLVMRetVal) : nullptr;
+}
+
+FunctionType *CallBase::getFunctionType() const {
+ return cast<FunctionType>(
+ Ctx.getType(cast<llvm::CallBase>(Val)->getFunctionType()));
+}
+
+Value *CallBase::getCalledOperand() const {
+ return Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledOperand());
+}
+
+Use CallBase::getCalledOperandUse() const {
+ llvm::Use *LLVMUse = &cast<llvm::CallBase>(Val)->getCalledOperandUse();
+ return Use(LLVMUse, cast<User>(Ctx.getValue(LLVMUse->getUser())), Ctx);
+}
+
+Function *CallBase::getCalledFunction() const {
+ return cast_or_null<Function>(
+ Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledFunction()));
+}
+Function *CallBase::getCaller() {
+ return cast<Function>(Ctx.getValue(cast<llvm::CallBase>(Val)->getCaller()));
+}
+
+void CallBase::setCalledFunction(Function *F) {
+ // F's function type is private, so we rely on `setCalledFunction()` to update
+ // it. But even though we are calling `setCalledFunction()` we also need to
+ // track this change at the SandboxIR level, which is why we call
+ // `setCalledOperand()` here.
+ // Note: This may break if `setCalledFunction()` early returns if `F`
+ // is already set, but we do have a unit test for it.
+ setCalledOperand(F);
+ cast<llvm::CallBase>(Val)->setCalledFunction(
+ cast<llvm::FunctionType>(F->getFunctionType()->LLVMTy),
+ cast<llvm::Function>(F->Val));
+}
+
+CallInst *CallInst::create(FunctionType *FTy, Value *Func,
+ ArrayRef<Value *> Args, BasicBlock::iterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ SmallVector<llvm::Value *> LLVMArgs;
+ LLVMArgs.reserve(Args.size());
+ for (Value *Arg : Args)
+ LLVMArgs.push_back(Arg->Val);
+ llvm::CallInst *NewCI = Builder.CreateCall(
+ cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val, LLVMArgs, NameStr);
+ return Ctx.createCallInst(NewCI);
+}
+
+CallInst *CallInst::create(FunctionType *FTy, Value *Func,
+ ArrayRef<Value *> Args, Instruction *InsertBefore,
+ Context &Ctx, const Twine &NameStr) {
+ return CallInst::create(FTy, Func, Args, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, NameStr);
+}
+
+CallInst *CallInst::create(FunctionType *FTy, Value *Func,
+ ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &NameStr) {
+ return CallInst::create(FTy, Func, Args, InsertAtEnd->end(), InsertAtEnd, Ctx,
+ NameStr);
+}
+
+InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
+ BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ SmallVector<llvm::Value *> LLVMArgs;
+ LLVMArgs.reserve(Args.size());
+ for (Value *Arg : Args)
+ LLVMArgs.push_back(Arg->Val);
+ llvm::InvokeInst *Invoke = Builder.CreateInvoke(
+ cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,
+ cast<llvm::BasicBlock>(IfNormal->Val),
+ cast<llvm::BasicBlock>(IfException->Val), LLVMArgs, NameStr);
+ return Ctx.createInvokeInst(Invoke);
+}
+
+InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
+ BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &NameStr) {
+ return create(FTy, Func, IfNormal, IfException, Args,
+ InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
+ NameStr);
+}
+
+InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
+ BasicBlock *IfNormal, BasicBlock *IfException,
+ ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &NameStr) {
+ return create(FTy, Func, IfNormal, IfException, Args, InsertAtEnd->end(),
+ InsertAtEnd, Ctx, NameStr);
+}
+
+BasicBlock *InvokeInst::getNormalDest() const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::InvokeInst>(Val)->getNormalDest()));
+}
+BasicBlock *InvokeInst::getUnwindDest() const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::InvokeInst>(Val)->getUnwindDest()));
+}
+void InvokeInst::setNormalDest(BasicBlock *BB) {
+ setOperand(1, BB);
+ assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");
+}
+void InvokeInst::setUnwindDest(BasicBlock *BB) {
+ setOperand(2, BB);
+ assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
+}
+LandingPadInst *InvokeInst::getLandingPadInst() const {
+ return cast<LandingPadInst>(
+ Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
+ ;
+}
+BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::InvokeInst>(Val)->getSuccessor(SuccIdx)));
+}
+
+CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
+ BasicBlock *DefaultDest,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+
+ SmallVector<llvm::BasicBlock *> LLVMIndirectDests;
+ LLVMIndirectDests.reserve(IndirectDests.size());
+ for (BasicBlock *IndDest : IndirectDests)
+ LLVMIndirectDests.push_back(cast<llvm::BasicBlock>(IndDest->Val));
+
+ SmallVector<llvm::Value *> LLVMArgs;
+ LLVMArgs.reserve(Args.size());
+ for (Value *Arg : Args)
+ LLVMArgs.push_back(Arg->Val);
+
+ llvm::CallBrInst *CallBr =
+ Builder.CreateCallBr(cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,
+ cast<llvm::BasicBlock>(DefaultDest->Val),
+ LLVMIndirectDests, LLVMArgs, NameStr);
+ return Ctx.createCallBrInst(CallBr);
+}
+
+CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
+ BasicBlock *DefaultDest,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &NameStr) {
+ return create(FTy, Func, DefaultDest, IndirectDests, Args,
+ InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
+ NameStr);
+}
+CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
+ BasicBlock *DefaultDest,
+ ArrayRef<BasicBlock *> IndirectDests,
+ ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &NameStr) {
+ return create(FTy, Func, DefaultDest, IndirectDests, Args, InsertAtEnd->end(),
+ InsertAtEnd, Ctx, NameStr);
+}
+
+Value *CallBrInst::getIndirectDestLabel(unsigned Idx) const {
+ return Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDestLabel(Idx));
+}
+Value *CallBrInst::getIndirectDestLabelUse(unsigned Idx) const {
+ return Ctx.getValue(
+ cast<llvm::CallBrInst>(Val)->getIndirectDestLabelUse(Idx));
+}
+BasicBlock *CallBrInst::getDefaultDest() const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::CallBrInst>(Val)->getDefaultDest()));
+}
+BasicBlock *CallBrInst::getIndirectDest(unsigned Idx) const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDest(Idx)));
+}
+llvm::SmallVector<BasicBlock *, 16> CallBrInst::getIndirectDests() const {
+ SmallVector<BasicBlock *, 16> BBs;
+ for (llvm::BasicBlock *LLVMBB :
+ cast<llvm::CallBrInst>(Val)->getIndirectDests())
+ BBs.push_back(cast<BasicBlock>(Ctx.getValue(LLVMBB)));
+ return BBs;
+}
+void CallBrInst::setDefaultDest(BasicBlock *BB) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CallBrInst::getDefaultDest,
+ &CallBrInst::setDefaultDest>>(this);
+ cast<llvm::CallBrInst>(Val)->setDefaultDest(cast<llvm::BasicBlock>(BB->Val));
+}
+void CallBrInst::setIndirectDest(unsigned Idx, BasicBlock *BB) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetterWithIdx<&CallBrInst::getIndirectDest,
+ &CallBrInst::setIndirectDest>>(
+ this, Idx);
+ cast<llvm::CallBrInst>(Val)->setIndirectDest(Idx,
+ cast<llvm::BasicBlock>(BB->Val));
+}
+BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));
+}
+
+LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::LandingPadInst *LLVMI =
+ Builder.CreateLandingPad(RetTy->LLVMTy, NumReservedClauses, Name);
+ return Ctx.createLandingPadInst(LLVMI);
+}
+
+void LandingPadInst::setCleanup(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup,
+ &LandingPadInst::setCleanup>>(this);
+ cast<llvm::LandingPadInst>(Val)->setCleanup(V);
+}
+
+Constant *LandingPadInst::getClause(unsigned Idx) const {
+ return cast<Constant>(
+ Ctx.getValue(cast<llvm::LandingPadInst>(Val)->getClause(Idx)));
+}
+
+Value *FuncletPadInst::getParentPad() const {
+ return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());
+}
+
+void FuncletPadInst::setParentPad(Value *ParentPad) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&FuncletPadInst::getParentPad,
+ &FuncletPadInst::setParentPad>>(this);
+ cast<llvm::FuncletPadInst>(Val)->setParentPad(ParentPad->Val);
+}
+
+Value *FuncletPadInst::getArgOperand(unsigned Idx) const {
+ return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getArgOperand(Idx));
+}
+
+void FuncletPadInst::setArgOperand(unsigned Idx, Value *V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetterWithIdx<&FuncletPadInst::getArgOperand,
+ &FuncletPadInst::setArgOperand>>(
+ this, Idx);
+ cast<llvm::FuncletPadInst>(Val)->setArgOperand(Idx, V->Val);
+}
+
+CatchSwitchInst *CatchPadInst::getCatchSwitch() const {
+ return cast<CatchSwitchInst>(
+ Ctx.getValue(cast<llvm::CatchPadInst>(Val)->getCatchSwitch()));
+}
+
+CatchPadInst *CatchPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ SmallVector<llvm::Value *> LLVMArgs;
+ LLVMArgs.reserve(Args.size());
+ for (auto *Arg : Args)
+ LLVMArgs.push_back(Arg->Val);
+ llvm::CatchPadInst *LLVMI =
+ Builder.CreateCatchPad(ParentPad->Val, LLVMArgs, Name);
+ return Ctx.createCatchPadInst(LLVMI);
+}
+
+CleanupPadInst *CleanupPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ SmallVector<llvm::Value *> LLVMArgs;
+ LLVMArgs.reserve(Args.size());
+ for (auto *Arg : Args)
+ LLVMArgs.push_back(Arg->Val);
+ llvm::CleanupPadInst *LLVMI =
+ Builder.CreateCleanupPad(ParentPad->Val, LLVMArgs, Name);
+ return Ctx.createCleanupPadInst(LLVMI);
+}
+
+CatchReturnInst *CatchReturnInst::create(CatchPadInst *CatchPad, BasicBlock *BB,
+ BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::CatchReturnInst *LLVMI = Builder.CreateCatchRet(
+ cast<llvm::CatchPadInst>(CatchPad->Val), cast<llvm::BasicBlock>(BB->Val));
+ return Ctx.createCatchReturnInst(LLVMI);
+}
+
+CatchPadInst *CatchReturnInst::getCatchPad() const {
+ return cast<CatchPadInst>(
+ Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getCatchPad()));
+}
+
+void CatchReturnInst::setCatchPad(CatchPadInst *CatchPad) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CatchReturnInst::getCatchPad,
+ &CatchReturnInst::setCatchPad>>(this);
+ cast<llvm::CatchReturnInst>(Val)->setCatchPad(
+ cast<llvm::CatchPadInst>(CatchPad->Val));
+}
+
+BasicBlock *CatchReturnInst::getSuccessor() const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getSuccessor()));
+}
+
+void CatchReturnInst::setSuccessor(BasicBlock *NewSucc) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CatchReturnInst::getSuccessor,
+ &CatchReturnInst::setSuccessor>>(this);
+ cast<llvm::CatchReturnInst>(Val)->setSuccessor(
+ cast<llvm::BasicBlock>(NewSucc->Val));
+}
+
+Value *CatchReturnInst::getCatchSwitchParentPad() const {
+ return Ctx.getValue(
+ cast<llvm::CatchReturnInst>(Val)->getCatchSwitchParentPad());
+}
+
+CleanupReturnInst *CleanupReturnInst::create(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB,
+ BBIterator WhereIt,
+ BasicBlock *WhereBB,
+ Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ auto *LLVMUnwindBB =
+ UnwindBB != nullptr ? cast<llvm::BasicBlock>(UnwindBB->Val) : nullptr;
+ llvm::CleanupReturnInst *LLVMI = Builder.CreateCleanupRet(
+ cast<llvm::CleanupPadInst>(CleanupPad->Val), LLVMUnwindBB);
+ return Ctx.createCleanupReturnInst(LLVMI);
+}
+
+CleanupPadInst *CleanupReturnInst::getCleanupPad() const {
+ return cast<CleanupPadInst>(
+ Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getCleanupPad()));
+}
+
+void CleanupReturnInst::setCleanupPad(CleanupPadInst *CleanupPad) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CleanupReturnInst::getCleanupPad,
+ &CleanupReturnInst::setCleanupPad>>(
+ this);
+ cast<llvm::CleanupReturnInst>(Val)->setCleanupPad(
+ cast<llvm::CleanupPadInst>(CleanupPad->Val));
+}
+
+BasicBlock *CleanupReturnInst::getUnwindDest() const {
+ return cast_or_null<BasicBlock>(
+ Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getUnwindDest()));
+}
+
+void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CleanupReturnInst::getUnwindDest,
+ &CleanupReturnInst::setUnwindDest>>(
+ this);
+ cast<llvm::CleanupReturnInst>(Val)->setUnwindDest(
+ cast<llvm::BasicBlock>(NewDest->Val));
+}
+
+Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
+ ArrayRef<Value *> IdxList,
+ BasicBlock::iterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &NameStr) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ SmallVector<llvm::Value *> LLVMIdxList;
+ LLVMIdxList.reserve(IdxList.size());
+ for (Value *Idx : IdxList)
+ LLVMIdxList.push_back(Idx->Val);
+ llvm::Value *NewV =
+ Builder.CreateGEP(Ty->LLVMTy, Ptr->Val, LLVMIdxList, NameStr);
+ if (auto *NewGEP = dyn_cast<llvm::GetElementPtrInst>(NewV))
+ return Ctx.createGetElementPtrInst(NewGEP);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
+ ArrayRef<Value *> IdxList,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &NameStr) {
+ return GetElementPtrInst::create(Ty, Ptr, IdxList,
+ InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, NameStr);
+}
+
+Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
+ ArrayRef<Value *> IdxList,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &NameStr) {
+ return GetElementPtrInst::create(Ty, Ptr, IdxList, InsertAtEnd->end(),
+ InsertAtEnd, Ctx, NameStr);
+}
+
+Type *GetElementPtrInst::getSourceElementType() const {
+ return Ctx.getType(
+ cast<llvm::GetElementPtrInst>(Val)->getSourceElementType());
+}
+
+Type *GetElementPtrInst::getResultElementType() const {
+ return Ctx.getType(
+ cast<llvm::GetElementPtrInst>(Val)->getResultElementType());
+}
+
+Value *GetElementPtrInst::getPointerOperand() const {
+ return Ctx.getValue(cast<llvm::GetElementPtrInst>(Val)->getPointerOperand());
+}
+
+Type *GetElementPtrInst::getPointerOperandType() const {
+ return Ctx.getType(
+ cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType());
+}
+
+BasicBlock *PHINode::LLVMBBToBB::operator()(llvm::BasicBlock *LLVMBB) const {
+ return cast<BasicBlock>(Ctx.getValue(LLVMBB));
+}
+
+PHINode *PHINode::create(Type *Ty, unsigned NumReservedValues,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ llvm::PHINode *NewPHI = llvm::PHINode::Create(
+ Ty->LLVMTy, NumReservedValues, Name,
+ InsertBefore->getTopmostLLVMInstruction()->getIterator());
+ return Ctx.createPHINode(NewPHI);
+}
+
+bool PHINode::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::PHI;
+}
+
+Value *PHINode::getIncomingValue(unsigned Idx) const {
+ return Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingValue(Idx));
+}
+void PHINode::setIncomingValue(unsigned Idx, Value *V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetterWithIdx<&PHINode::getIncomingValue,
+ &PHINode::setIncomingValue>>(this,
+ Idx);
+ cast<llvm::PHINode>(Val)->setIncomingValue(Idx, V->Val);
+}
+BasicBlock *PHINode::getIncomingBlock(unsigned Idx) const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingBlock(Idx)));
+}
+BasicBlock *PHINode::getIncomingBlock(const Use &U) const {
+ llvm::Use *LLVMUse = U.LLVMUse;
+ llvm::BasicBlock *BB = cast<llvm::PHINode>(Val)->getIncomingBlock(*LLVMUse);
+ return cast<BasicBlock>(Ctx.getValue(BB));
+}
+void PHINode::setIncomingBlock(unsigned Idx, BasicBlock *BB) {
+ // Helper to disambiguate PHINode::getIncomingBlock(unsigned).
+ constexpr BasicBlock *(PHINode::*GetIncomingBlockFn)(unsigned) const =
+ &PHINode::getIncomingBlock;
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetterWithIdx<GetIncomingBlockFn, &PHINode::setIncomingBlock>>(
+ this, Idx);
+ cast<llvm::PHINode>(Val)->setIncomingBlock(Idx,
+ cast<llvm::BasicBlock>(BB->Val));
+}
+void PHINode::addIncoming(Value *V, BasicBlock *BB) {
+ auto &Tracker = Ctx.getTracker();
+ Tracker.emplaceIfTracking<PHIAddIncoming>(this);
+
+ cast<llvm::PHINode>(Val)->addIncoming(V->Val,
+ cast<llvm::BasicBlock>(BB->Val));
+}
+Value *PHINode::removeIncomingValue(unsigned Idx) {
+ auto &Tracker = Ctx.getTracker();
+ Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, Idx);
+ llvm::Value *LLVMV =
+ cast<llvm::PHINode>(Val)->removeIncomingValue(Idx,
+ /*DeletePHIIfEmpty=*/false);
+ return Ctx.getValue(LLVMV);
+}
+Value *PHINode::removeIncomingValue(BasicBlock *BB) {
+ auto &Tracker = Ctx.getTracker();
+ Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, getBasicBlockIndex(BB));
+
+ auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
+ llvm::Value *LLVMV =
+ cast<llvm::PHINode>(Val)->removeIncomingValue(LLVMBB,
+ /*DeletePHIIfEmpty=*/false);
+ return Ctx.getValue(LLVMV);
+}
+int PHINode::getBasicBlockIndex(const BasicBlock *BB) const {
+ auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
+ return cast<llvm::PHINode>(Val)->getBasicBlockIndex(LLVMBB);
+}
+Value *PHINode::getIncomingValueForBlock(const BasicBlock *BB) const {
+ auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
+ llvm::Value *LLVMV =
+ cast<llvm::PHINode>(Val)->getIncomingValueForBlock(LLVMBB);
+ return Ctx.getValue(LLVMV);
+}
+Value *PHINode::hasConstantValue() const {
+ llvm::Value *LLVMV = cast<llvm::PHINode>(Val)->hasConstantValue();
+ return LLVMV != nullptr ? Ctx.getValue(LLVMV) : nullptr;
+}
+void PHINode::replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) {
+ assert(New && Old && "Sandbox IR PHI node got a null basic block!");
+ for (unsigned Idx = 0, NumOps = cast<llvm::PHINode>(Val)->getNumOperands();
+ Idx != NumOps; ++Idx)
+ if (getIncomingBlock(Idx) == Old)
+ setIncomingBlock(Idx, New);
+}
+void PHINode::removeIncomingValueIf(function_ref<bool(unsigned)> Predicate) {
+ // Avoid duplicate tracking by going through this->removeIncomingValue here at
+ // the expense of some performance. Copy PHI::removeIncomingValueIf more
+ // directly if performance becomes an issue.
+
+ // Removing the element at index X, moves the element previously at X + 1
+ // to X. Working from the end avoids complications from that.
+ unsigned Idx = getNumIncomingValues();
+ while (Idx > 0) {
+ if (Predicate(Idx - 1))
+ removeIncomingValue(Idx - 1);
+ --Idx;
+ }
+}
+
+static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {
+ switch (Opc) {
+ case Instruction::Opcode::ZExt:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::ZExt);
+ case Instruction::Opcode::SExt:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SExt);
+ case Instruction::Opcode::FPToUI:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToUI);
+ case Instruction::Opcode::FPToSI:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToSI);
+ case Instruction::Opcode::FPExt:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPExt);
+ case Instruction::Opcode::PtrToInt:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::PtrToInt);
+ case Instruction::Opcode::IntToPtr:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::IntToPtr);
+ case Instruction::Opcode::SIToFP:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SIToFP);
+ case Instruction::Opcode::UIToFP:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::UIToFP);
+ case Instruction::Opcode::Trunc:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::Trunc);
+ case Instruction::Opcode::FPTrunc:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPTrunc);
+ case Instruction::Opcode::BitCast:
+ return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::BitCast);
+ case Instruction::Opcode::AddrSpaceCast:
+ return static_cast<llvm::Instruction::CastOps>(
+ llvm::Instruction::AddrSpaceCast);
+ default:
+ llvm_unreachable("Opcode not suitable for CastInst!");
+ }
+}
+
+/// \Returns the LLVM opcode that corresponds to \p Opc.
+static llvm::Instruction::UnaryOps getLLVMUnaryOp(Instruction::Opcode Opc) {
+ switch (Opc) {
+ case Instruction::Opcode::FNeg:
+ return static_cast<llvm::Instruction::UnaryOps>(llvm::Instruction::FNeg);
+ default:
+ llvm_unreachable("Not a unary op!");
+ }
+}
+
+CatchSwitchInst *CatchSwitchInst::create(Value *ParentPad, BasicBlock *UnwindBB,
+ unsigned NumHandlers,
+ BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::CatchSwitchInst *LLVMCSI = Builder.CreateCatchSwitch(
+ ParentPad->Val, cast<llvm::BasicBlock>(UnwindBB->Val), NumHandlers, Name);
+ return Ctx.createCatchSwitchInst(LLVMCSI);
+}
+
+Value *CatchSwitchInst::getParentPad() const {
+ return Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getParentPad());
+}
+
+void CatchSwitchInst::setParentPad(Value *ParentPad) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CatchSwitchInst::getParentPad,
+ &CatchSwitchInst::setParentPad>>(this);
+ cast<llvm::CatchSwitchInst>(Val)->setParentPad(ParentPad->Val);
+}
+
+BasicBlock *CatchSwitchInst::getUnwindDest() const {
+ return cast_or_null<BasicBlock>(
+ Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getUnwindDest()));
+}
+
+void CatchSwitchInst::setUnwindDest(BasicBlock *UnwindDest) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&CatchSwitchInst::getUnwindDest,
+ &CatchSwitchInst::setUnwindDest>>(this);
+ cast<llvm::CatchSwitchInst>(Val)->setUnwindDest(
+ cast<llvm::BasicBlock>(UnwindDest->Val));
+}
+
+void CatchSwitchInst::addHandler(BasicBlock *Dest) {
+ Ctx.getTracker().emplaceIfTracking<CatchSwitchAddHandler>(this);
+ cast<llvm::CatchSwitchInst>(Val)->addHandler(
+ cast<llvm::BasicBlock>(Dest->Val));
+}
+
+ResumeInst *ResumeInst::create(Value *Exn, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ auto *LLVMI = cast<llvm::ResumeInst>(Builder.CreateResume(Exn->Val));
+ return Ctx.createResumeInst(LLVMI);
+}
+
+Value *ResumeInst::getValue() const {
+ return Ctx.getValue(cast<llvm::ResumeInst>(Val)->getValue());
+}
+
+SwitchInst *SwitchInst::create(Value *V, BasicBlock *Dest, unsigned NumCases,
+ BasicBlock::iterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::SwitchInst *LLVMSwitch =
+ Builder.CreateSwitch(V->Val, cast<llvm::BasicBlock>(Dest->Val), NumCases);
+ return Ctx.createSwitchInst(LLVMSwitch);
+}
+
+Value *SwitchInst::getCondition() const {
+ return Ctx.getValue(cast<llvm::SwitchInst>(Val)->getCondition());
+}
+
+void SwitchInst::setCondition(Value *V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&SwitchInst::getCondition, &SwitchInst::setCondition>>(
+ this);
+ cast<llvm::SwitchInst>(Val)->setCondition(V->Val);
+}
+
+BasicBlock *SwitchInst::getDefaultDest() const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::SwitchInst>(Val)->getDefaultDest()));
+}
+
+void SwitchInst::setDefaultDest(BasicBlock *DefaultCase) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&SwitchInst::getDefaultDest,
+ &SwitchInst::setDefaultDest>>(this);
+ cast<llvm::SwitchInst>(Val)->setDefaultDest(
+ cast<llvm::BasicBlock>(DefaultCase->Val));
+}
+ConstantInt *SwitchInst::findCaseDest(BasicBlock *BB) {
+ auto *LLVMC = cast<llvm::SwitchInst>(Val)->findCaseDest(
+ cast<llvm::BasicBlock>(BB->Val));
+ return LLVMC != nullptr ? cast<ConstantInt>(Ctx.getValue(LLVMC)) : nullptr;
+}
+
+void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
+ Ctx.getTracker().emplaceIfTracking<SwitchAddCase>(this, OnVal);
+ // TODO: Track this!
+ cast<llvm::SwitchInst>(Val)->addCase(cast<llvm::ConstantInt>(OnVal->Val),
+ cast<llvm::BasicBlock>(Dest->Val));
+}
+
+SwitchInst::CaseIt SwitchInst::removeCase(CaseIt It) {
+ auto &Case = *It;
+ Ctx.getTracker().emplaceIfTracking<SwitchRemoveCase>(
+ this, Case.getCaseValue(), Case.getCaseSuccessor());
+
+ auto *LLVMSwitch = cast<llvm::SwitchInst>(Val);
+ unsigned CaseNum = It - case_begin();
+ llvm::SwitchInst::CaseIt LLVMIt(LLVMSwitch, CaseNum);
+ auto LLVMCaseIt = LLVMSwitch->removeCase(LLVMIt);
+ unsigned Num = LLVMCaseIt - LLVMSwitch->case_begin();
+ return CaseIt(this, Num);
+}
+
+BasicBlock *SwitchInst::getSuccessor(unsigned Idx) const {
+ return cast<BasicBlock>(
+ Ctx.getValue(cast<llvm::SwitchInst>(Val)->getSuccessor(Idx)));
+}
+
+void SwitchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetterWithIdx<&SwitchInst::getSuccessor,
+ &SwitchInst::setSuccessor>>(this,
+ Idx);
+ cast<llvm::SwitchInst>(Val)->setSuccessor(
+ Idx, cast<llvm::BasicBlock>(NewSucc->Val));
+}
+
+Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt == WhereBB->end())
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ else
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ auto *NewLLVMV = Builder.CreateUnOp(getLLVMUnaryOp(Op), OpV->Val, Name);
+ if (auto *NewUnOpV = dyn_cast<llvm::UnaryOperator>(NewLLVMV)) {
+ return Ctx.createUnaryOperator(NewUnOpV);
+ }
+ assert(isa<llvm::Constant>(NewLLVMV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewLLVMV));
+}
+
+Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ return create(Op, OpV, InsertBefore->getIterator(), InsertBefore->getParent(),
+ Ctx, Name);
+}
+
+Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
+ BasicBlock *InsertAfter, Context &Ctx,
+ const Twine &Name) {
+ return create(Op, OpV, InsertAfter->end(), InsertAfter, Ctx, Name);
+}
+
+Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
+ Value *CopyFrom, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+ auto *NewV = create(Op, OpV, WhereIt, WhereBB, Ctx, Name);
+ if (auto *UnI = dyn_cast<llvm::UnaryOperator>(NewV->Val))
+ UnI->copyIRFlags(CopyFrom->Val);
+ return NewV;
+}
+
+Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
+ Value *CopyFrom,
+ Instruction *InsertBefore,
+ Context &Ctx, const Twine &Name) {
+ return createWithCopiedFlags(Op, OpV, CopyFrom, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, Name);
+}
+
+Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
+ Value *CopyFrom,
+ BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &Name) {
+ return createWithCopiedFlags(Op, OpV, CopyFrom, InsertAtEnd->end(),
+ InsertAtEnd, Ctx, Name);
+}
+
+/// \Returns the LLVM opcode that corresponds to \p Opc.
+static llvm::Instruction::BinaryOps getLLVMBinaryOp(Instruction::Opcode Opc) {
+ switch (Opc) {
+ case Instruction::Opcode::Add:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Add);
+ case Instruction::Opcode::FAdd:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FAdd);
+ case Instruction::Opcode::Sub:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Sub);
+ case Instruction::Opcode::FSub:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FSub);
+ case Instruction::Opcode::Mul:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Mul);
+ case Instruction::Opcode::FMul:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FMul);
+ case Instruction::Opcode::UDiv:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::UDiv);
+ case Instruction::Opcode::SDiv:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SDiv);
+ case Instruction::Opcode::FDiv:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FDiv);
+ case Instruction::Opcode::URem:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::URem);
+ case Instruction::Opcode::SRem:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SRem);
+ case Instruction::Opcode::FRem:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FRem);
+ case Instruction::Opcode::Shl:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Shl);
+ case Instruction::Opcode::LShr:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::LShr);
+ case Instruction::Opcode::AShr:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::AShr);
+ case Instruction::Opcode::And:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::And);
+ case Instruction::Opcode::Or:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Or);
+ case Instruction::Opcode::Xor:
+ return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Xor);
+ default:
+ llvm_unreachable("Not a binary op!");
+ }
+}
+Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt == WhereBB->end())
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ else
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ llvm::Value *NewV =
+ Builder.CreateBinOp(getLLVMBinaryOp(Op), LHS->Val, RHS->Val, Name);
+ if (auto *NewBinOp = dyn_cast<llvm::BinaryOperator>(NewV))
+ return Ctx.createBinaryOperator(NewBinOp);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ return create(Op, LHS, RHS, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, Name);
+}
+
+Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ return create(Op, LHS, RHS, InsertAtEnd->end(), InsertAtEnd, Ctx, Name);
+}
+
+Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
+ Value *RHS, Value *CopyFrom,
+ BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+
+ Value *NewV = create(Op, LHS, RHS, WhereIt, WhereBB, Ctx, Name);
+ if (auto *NewBO = dyn_cast<BinaryOperator>(NewV))
+ cast<llvm::BinaryOperator>(NewBO->Val)->copyIRFlags(CopyFrom->Val);
+ return NewV;
+}
+
+Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
+ Value *RHS, Value *CopyFrom,
+ Instruction *InsertBefore,
+ Context &Ctx, const Twine &Name) {
+ return createWithCopiedFlags(Op, LHS, RHS, CopyFrom,
+ InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, Name);
+}
+
+Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
+ Value *RHS, Value *CopyFrom,
+ BasicBlock *InsertAtEnd,
+ Context &Ctx, const Twine &Name) {
+ return createWithCopiedFlags(Op, LHS, RHS, CopyFrom, InsertAtEnd->end(),
+ InsertAtEnd, Ctx, Name);
+}
+
+void PossiblyDisjointInst::setIsDisjoint(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&PossiblyDisjointInst::isDisjoint,
+ &PossiblyDisjointInst::setIsDisjoint>>(
+ this);
+ cast<llvm::PossiblyDisjointInst>(Val)->setIsDisjoint(B);
+}
+
+void AtomicRMWInst::setAlignment(Align Align) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getAlign,
+ &AtomicRMWInst::setAlignment>>(this);
+ cast<llvm::AtomicRMWInst>(Val)->setAlignment(Align);
+}
+
+void AtomicRMWInst::setVolatile(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicRMWInst::isVolatile,
+ &AtomicRMWInst::setVolatile>>(this);
+ cast<llvm::AtomicRMWInst>(Val)->setVolatile(V);
+}
+
+void AtomicRMWInst::setOrdering(AtomicOrdering Ordering) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getOrdering,
+ &AtomicRMWInst::setOrdering>>(this);
+ cast<llvm::AtomicRMWInst>(Val)->setOrdering(Ordering);
+}
+
+void AtomicRMWInst::setSyncScopeID(SyncScope::ID SSID) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getSyncScopeID,
+ &AtomicRMWInst::setSyncScopeID>>(this);
+ cast<llvm::AtomicRMWInst>(Val)->setSyncScopeID(SSID);
+}
+
+Value *AtomicRMWInst::getPointerOperand() {
+ return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getPointerOperand());
+}
+
+Value *AtomicRMWInst::getValOperand() {
+ return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getValOperand());
+}
+
+AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
+ MaybeAlign Align, AtomicOrdering Ordering,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, SyncScope::ID SSID,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt == WhereBB->end())
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ else
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ auto *LLVMAtomicRMW =
+ Builder.CreateAtomicRMW(Op, Ptr->Val, Val->Val, Align, Ordering, SSID);
+ LLVMAtomicRMW->setName(Name);
+ return Ctx.createAtomicRMWInst(LLVMAtomicRMW);
+}
+
+AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
+ MaybeAlign Align, AtomicOrdering Ordering,
+ Instruction *InsertBefore, Context &Ctx,
+ SyncScope::ID SSID, const Twine &Name) {
+ return create(Op, Ptr, Val, Align, Ordering, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, SSID, Name);
+}
+
+AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
+ MaybeAlign Align, AtomicOrdering Ordering,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ SyncScope::ID SSID, const Twine &Name) {
+ return create(Op, Ptr, Val, Align, Ordering, InsertAtEnd->end(), InsertAtEnd,
+ Ctx, SSID, Name);
+}
+
+void AtomicCmpXchgInst::setSyncScopeID(SyncScope::ID SSID) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSyncScopeID,
+ &AtomicCmpXchgInst::setSyncScopeID>>(
+ this);
+ cast<llvm::AtomicCmpXchgInst>(Val)->setSyncScopeID(SSID);
+}
+
+Value *AtomicCmpXchgInst::getPointerOperand() {
+ return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getPointerOperand());
+}
+
+Value *AtomicCmpXchgInst::getCompareOperand() {
+ return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getCompareOperand());
+}
+
+Value *AtomicCmpXchgInst::getNewValOperand() {
+ return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getNewValOperand());
+}
+
+AtomicCmpXchgInst *
+AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx, SyncScope::ID SSID,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt == WhereBB->end())
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ else
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ auto *LLVMAtomicCmpXchg =
+ Builder.CreateAtomicCmpXchg(Ptr->Val, Cmp->Val, New->Val, Align,
+ SuccessOrdering, FailureOrdering, SSID);
+ LLVMAtomicCmpXchg->setName(Name);
+ return Ctx.createAtomicCmpXchgInst(LLVMAtomicCmpXchg);
+}
+
+AtomicCmpXchgInst *AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New,
+ MaybeAlign Align,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
+ Instruction *InsertBefore,
+ Context &Ctx, SyncScope::ID SSID,
+ const Twine &Name) {
+ return create(Ptr, Cmp, New, Align, SuccessOrdering, FailureOrdering,
+ InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
+ SSID, Name);
+}
+
+AtomicCmpXchgInst *AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New,
+ MaybeAlign Align,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
+ BasicBlock *InsertAtEnd,
+ Context &Ctx, SyncScope::ID SSID,
+ const Twine &Name) {
+ return create(Ptr, Cmp, New, Align, SuccessOrdering, FailureOrdering,
+ InsertAtEnd->end(), InsertAtEnd, Ctx, SSID, Name);
+}
+
+void AtomicCmpXchgInst::setAlignment(Align Align) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getAlign,
+ &AtomicCmpXchgInst::setAlignment>>(this);
+ cast<llvm::AtomicCmpXchgInst>(Val)->setAlignment(Align);
+}
+
+void AtomicCmpXchgInst::setVolatile(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isVolatile,
+ &AtomicCmpXchgInst::setVolatile>>(this);
+ cast<llvm::AtomicCmpXchgInst>(Val)->setVolatile(V);
+}
+
+void AtomicCmpXchgInst::setWeak(bool IsWeak) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isWeak,
+ &AtomicCmpXchgInst::setWeak>>(this);
+ cast<llvm::AtomicCmpXchgInst>(Val)->setWeak(IsWeak);
+}
+
+void AtomicCmpXchgInst::setSuccessOrdering(AtomicOrdering Ordering) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSuccessOrdering,
+ &AtomicCmpXchgInst::setSuccessOrdering>>(
+ this);
+ cast<llvm::AtomicCmpXchgInst>(Val)->setSuccessOrdering(Ordering);
+}
+
+void AtomicCmpXchgInst::setFailureOrdering(AtomicOrdering Ordering) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getFailureOrdering,
+ &AtomicCmpXchgInst::setFailureOrdering>>(
+ this);
+ cast<llvm::AtomicCmpXchgInst>(Val)->setFailureOrdering(Ordering);
+}
+
+AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
+ BasicBlock *WhereBB, Context &Ctx,
+ Value *ArraySize, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt == WhereBB->end())
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ else
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ auto *NewAlloca =
+ Builder.CreateAlloca(Ty->LLVMTy, AddrSpace, ArraySize->Val, Name);
+ return Ctx.createAllocaInst(NewAlloca);
+}
+
+AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
+ Instruction *InsertBefore, Context &Ctx,
+ Value *ArraySize, const Twine &Name) {
+ return create(Ty, AddrSpace, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, ArraySize, Name);
+}
+
+AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ Value *ArraySize, const Twine &Name) {
+ return create(Ty, AddrSpace, InsertAtEnd->end(), InsertAtEnd, Ctx, ArraySize,
+ Name);
+}
+
+Type *AllocaInst::getAllocatedType() const {
+ return Ctx.getType(cast<llvm::AllocaInst>(Val)->getAllocatedType());
+}
+
+void AllocaInst::setAllocatedType(Type *Ty) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AllocaInst::getAllocatedType,
+ &AllocaInst::setAllocatedType>>(this);
+ cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty->LLVMTy);
+}
+
+void AllocaInst::setAlignment(Align Align) {
+ Ctx.getTracker()
+ .emplaceIfTracking<
+ GenericSetter<&AllocaInst::getAlign, &AllocaInst::setAlignment>>(
+ this);
+ cast<llvm::AllocaInst>(Val)->setAlignment(Align);
+}
+
+void AllocaInst::setUsedWithInAlloca(bool V) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&AllocaInst::isUsedWithInAlloca,
+ &AllocaInst::setUsedWithInAlloca>>(this);
+ cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
+}
+
+Value *AllocaInst::getArraySize() {
+ return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());
+}
+
+PointerType *AllocaInst::getType() const {
+ return cast<PointerType>(Ctx.getType(cast<llvm::AllocaInst>(Val)->getType()));
+}
+
+Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
+ BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
+ const Twine &Name) {
+ assert(getLLVMCastOp(Op) && "Opcode not suitable for CastInst!");
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt == WhereBB->end())
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ else
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ auto *NewV =
+ Builder.CreateCast(getLLVMCastOp(Op), Operand->Val, DestTy->LLVMTy, Name);
+ if (auto *NewCI = dyn_cast<llvm::CastInst>(NewV))
+ return Ctx.createCastInst(NewCI);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ return create(DestTy, Op, Operand, InsertBefore->getIterator(),
+ InsertBefore->getParent(), Ctx, Name);
+}
+
+Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ return create(DestTy, Op, Operand, InsertAtEnd->end(), InsertAtEnd, Ctx,
+ Name);
+}
+
+bool CastInst::classof(const Value *From) {
+ return From->getSubclassID() == ClassID::Cast;
+}
+
+Type *CastInst::getSrcTy() const {
+ return Ctx.getType(cast<llvm::CastInst>(Val)->getSrcTy());
+}
+
+Type *CastInst::getDestTy() const {
+ return Ctx.getType(cast<llvm::CastInst>(Val)->getDestTy());
+}
+
+void PossiblyNonNegInst::setNonNeg(bool B) {
+ Ctx.getTracker()
+ .emplaceIfTracking<GenericSetter<&PossiblyNonNegInst::hasNonNeg,
+ &PossiblyNonNegInst::setNonNeg>>(this);
+ cast<llvm::PossiblyNonNegInst>(Val)->setNonNeg(B);
+}
+
+Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
+ llvm::Value *NewV =
+ Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
+ if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
+ return Ctx.createInsertElementInst(NewInsert);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::Value *NewV =
+ Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
+ if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
+ return Ctx.createInsertElementInst(NewInsert);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *ExtractElementInst::create(Value *Vec, Value *Idx,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
+ llvm::Value *NewV = Builder.CreateExtractElement(Vec->Val, Idx->Val, Name);
+ if (auto *NewExtract = dyn_cast<llvm::ExtractElementInst>(NewV))
+ return Ctx.createExtractElementInst(NewExtract);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *ExtractElementInst::create(Value *Vec, Value *Idx,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::Value *NewV = Builder.CreateExtractElement(Vec->Val, Idx->Val, Name);
+ if (auto *NewExtract = dyn_cast<llvm::ExtractElementInst>(NewV))
+ return Ctx.createExtractElementInst(NewExtract);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
+ llvm::Value *NewV =
+ Builder.CreateShuffleVector(V1->Val, V2->Val, Mask->Val, Name);
+ if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
+ return Ctx.createShuffleVectorInst(NewShuffle);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::Value *NewV =
+ Builder.CreateShuffleVector(V1->Val, V2->Val, Mask->Val, Name);
+ if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
+ return Ctx.createShuffleVectorInst(NewShuffle);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask,
+ Instruction *InsertBefore, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
+ llvm::Value *NewV = Builder.CreateShuffleVector(V1->Val, V2->Val, Mask, Name);
+ if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
+ return Ctx.createShuffleVectorInst(NewShuffle);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask,
+ BasicBlock *InsertAtEnd, Context &Ctx,
+ const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+ llvm::Value *NewV = Builder.CreateShuffleVector(V1->Val, V2->Val, Mask, Name);
+ if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
+ return Ctx.createShuffleVectorInst(NewShuffle);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+void ShuffleVectorInst::setShuffleMask(ArrayRef<int> Mask) {
+ Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);
+ cast<llvm::ShuffleVectorInst>(Val)->setShuffleMask(Mask);
+}
+
+VectorType *ShuffleVectorInst::getType() const {
+ return cast<VectorType>(
+ Ctx.getType(cast<llvm::ShuffleVectorInst>(Val)->getType()));
+}
+
+void ShuffleVectorInst::commute() {
+ Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);
+ Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(0),
+ getOperandUse(1));
+ cast<llvm::ShuffleVectorInst>(Val)->commute();
+}
+
+Constant *ShuffleVectorInst::getShuffleMaskForBitcode() const {
+ return Ctx.getOrCreateConstant(
+ cast<llvm::ShuffleVectorInst>(Val)->getShuffleMaskForBitcode());
+}
+
+Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(ArrayRef<int> Mask,
+ Type *ResultTy) {
+ return ResultTy->getContext().getOrCreateConstant(
+ llvm::ShuffleVectorInst::convertShuffleMaskForBitcode(Mask,
+ ResultTy->LLVMTy));
+}
+
+VectorType *ExtractElementInst::getVectorOperandType() const {
+ return cast<VectorType>(Ctx.getType(getVectorOperand()->getType()->LLVMTy));
+}
+
+Value *ExtractValueInst::create(Value *Agg, ArrayRef<unsigned> Idxs,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::Value *NewV = Builder.CreateExtractValue(Agg->Val, Idxs, Name);
+ if (auto *NewExtractValueInst = dyn_cast<llvm::ExtractValueInst>(NewV))
+ return Ctx.createExtractValueInst(NewExtractValueInst);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+Type *ExtractValueInst::getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs) {
+ auto *LLVMTy = llvm::ExtractValueInst::getIndexedType(Agg->LLVMTy, Idxs);
+ return Agg->getContext().getType(LLVMTy);
+}
+
+Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
+ BBIterator WhereIt, BasicBlock *WhereBB,
+ Context &Ctx, const Twine &Name) {
+ auto &Builder = Ctx.getLLVMIRBuilder();
+ if (WhereIt != WhereBB->end())
+ Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+ else
+ Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+ llvm::Value *NewV = Builder.CreateInsertValue(Agg->Val, Val->Val, Idxs, Name);
+ if (auto *NewInsertValueInst = dyn_cast<llvm::InsertValueInst>(NewV))
+ return Ctx.createInsertValueInst(NewInsertValueInst);
+ assert(isa<llvm::Constant>(NewV) && "Expected constant");
+ return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
+ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) {
+ auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx);
+ return cast<ConstantTokenNone>(Ctx.getOrCreateConstant(LLVMC));
+}
+
+} // namespace llvm::sandboxir
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 5baeffef32e5e5..63f65bfc88544b 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -106,1955 +106,3 @@ int OperandUseIterator::operator-(const OperandUseIterator &Other) const {
int OtherOpNo = Other.Use.getOperandNo();
return ThisOpNo - OtherOpNo;
}
-
-const char *Instruction::getOpcodeName(Opcode Opc) {
- switch (Opc) {
-#define OP(OPC) \
- case Opcode::OPC: \
- return #OPC;
-#define OPCODES(...) __VA_ARGS__
-#define DEF_INSTR(ID, OPC, CLASS) OPC
-#include "llvm/SandboxIR/SandboxIRValues.def"
- }
- llvm_unreachable("Unknown Opcode");
-}
-
-llvm::Instruction *Instruction::getTopmostLLVMInstruction() const {
- Instruction *Prev = getPrevNode();
- if (Prev == nullptr) {
- // If at top of the BB, return the first BB instruction.
- return &*cast<llvm::BasicBlock>(getParent()->Val)->begin();
- }
- // Else get the Previous sandbox IR instruction's bottom IR instruction and
- // return its successor.
- llvm::Instruction *PrevBotI = cast<llvm::Instruction>(Prev->Val);
- return PrevBotI->getNextNode();
-}
-
-BBIterator Instruction::getIterator() const {
- auto *I = cast<llvm::Instruction>(Val);
- return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx);
-}
-
-Instruction *Instruction::getNextNode() const {
- assert(getParent() != nullptr && "Detached!");
- assert(getIterator() != getParent()->end() && "Already at end!");
- // `Val` is the bottom-most LLVM IR instruction. Get the next in the chain,
- // and get the corresponding sandboxir Instruction that maps to it. This works
- // even for SandboxIR Instructions that map to more than one LLVM Instruction.
- auto *LLVMI = cast<llvm::Instruction>(Val);
- assert(LLVMI->getParent() != nullptr && "LLVM IR instr is detached!");
- auto *NextLLVMI = LLVMI->getNextNode();
- auto *NextI = cast_or_null<Instruction>(Ctx.getValue(NextLLVMI));
- if (NextI == nullptr)
- return nullptr;
- return NextI;
-}
-
-Instruction *Instruction::getPrevNode() const {
- assert(getParent() != nullptr && "Detached!");
- auto It = getIterator();
- if (It != getParent()->begin())
- return std::prev(getIterator()).get();
- return nullptr;
-}
-
-void Instruction::removeFromParent() {
- Ctx.getTracker().emplaceIfTracking<RemoveFromParent>(this);
-
- // Detach all the LLVM IR instructions from their parent BB.
- for (llvm::Instruction *I : getLLVMInstrs())
- I->removeFromParent();
-}
-
-void Instruction::eraseFromParent() {
- assert(users().empty() && "Still connected to users, can't erase!");
- std::unique_ptr<Value> Detached = Ctx.detach(this);
- auto LLVMInstrs = getLLVMInstrs();
-
- auto &Tracker = Ctx.getTracker();
- if (Tracker.isTracking()) {
- Tracker.track(std::make_unique<EraseFromParent>(std::move(Detached)));
- // We don't actually delete the IR instruction, because then it would be
- // impossible to bring it back from the dead at the same memory location.
- // Instead we remove it from its BB and track its current location.
- for (llvm::Instruction *I : LLVMInstrs)
- I->removeFromParent();
- // TODO: Multi-instructions need special treatment because some of the
- // references are internal to the instruction.
- for (llvm::Instruction *I : LLVMInstrs)
- I->dropAllReferences();
- } else {
- // Erase in reverse to avoid erasing nstructions with attached uses.
- for (llvm::Instruction *I : reverse(LLVMInstrs))
- I->eraseFromParent();
- }
-}
-
-void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) {
- if (std::next(getIterator()) == WhereIt)
- // Destination is same as origin, nothing to do.
- return;
-
- Ctx.getTracker().emplaceIfTracking<MoveInstr>(this);
-
- auto *LLVMBB = cast<llvm::BasicBlock>(BB.Val);
- llvm::BasicBlock::iterator It;
- if (WhereIt == BB.end()) {
- It = LLVMBB->end();
- } else {
- Instruction *WhereI = &*WhereIt;
- It = WhereI->getTopmostLLVMInstruction()->getIterator();
- }
- // TODO: Move this to the verifier of sandboxir::Instruction.
- assert(is_sorted(getLLVMInstrs(),
- [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
- "Expected program order!");
- // Do the actual move in LLVM IR.
- for (auto *I : getLLVMInstrs())
- I->moveBefore(*LLVMBB, It);
-}
-
-void Instruction::insertBefore(Instruction *BeforeI) {
- llvm::Instruction *BeforeTopI = BeforeI->getTopmostLLVMInstruction();
- // TODO: Move this to the verifier of sandboxir::Instruction.
- assert(is_sorted(getLLVMInstrs(),
- [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) &&
- "Expected program order!");
-
- Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);
-
- // Insert the LLVM IR Instructions in program order.
- for (llvm::Instruction *I : getLLVMInstrs())
- I->insertBefore(BeforeTopI);
-}
-
-void Instruction::insertAfter(Instruction *AfterI) {
- insertInto(AfterI->getParent(), std::next(AfterI->getIterator()));
-}
-
-void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) {
- llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
- llvm::Instruction *LLVMBeforeI;
- llvm::BasicBlock::iterator LLVMBeforeIt;
- Instruction *BeforeI;
- if (WhereIt != BB->end()) {
- BeforeI = &*WhereIt;
- LLVMBeforeI = BeforeI->getTopmostLLVMInstruction();
- LLVMBeforeIt = LLVMBeforeI->getIterator();
- } else {
- BeforeI = nullptr;
- LLVMBeforeI = nullptr;
- LLVMBeforeIt = LLVMBB->end();
- }
-
- Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(this);
-
- // Insert the LLVM IR Instructions in program order.
- for (llvm::Instruction *I : getLLVMInstrs())
- I->insertInto(LLVMBB, LLVMBeforeIt);
-}
-
-BasicBlock *Instruction::getParent() const {
- // Get the LLVM IR Instruction that this maps to, get its parent, and get the
- // corresponding sandboxir::BasicBlock by looking it up in sandboxir::Context.
- auto *BB = cast<llvm::Instruction>(Val)->getParent();
- if (BB == nullptr)
- return nullptr;
- return cast<BasicBlock>(Ctx.getValue(BB));
-}
-
-bool Instruction::classof(const sandboxir::Value *From) {
- switch (From->getSubclassID()) {
-#define DEF_INSTR(ID, OPC, CLASS) \
- case ClassID::ID: \
- return true;
-#include "llvm/SandboxIR/SandboxIRValues.def"
- default:
- return false;
- }
-}
-
-void Instruction::setHasNoUnsignedWrap(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap,
- &Instruction::setHasNoUnsignedWrap>>(
- this);
- cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B);
-}
-
-void Instruction::setHasNoSignedWrap(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap,
- &Instruction::setHasNoSignedWrap>>(this);
- cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B);
-}
-
-void Instruction::setFast(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&Instruction::isFast, &Instruction::setFast>>(this);
- cast<llvm::Instruction>(Val)->setFast(B);
-}
-
-void Instruction::setIsExact(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(this);
- cast<llvm::Instruction>(Val)->setIsExact(B);
-}
-
-void Instruction::setHasAllowReassoc(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc,
- &Instruction::setHasAllowReassoc>>(this);
- cast<llvm::Instruction>(Val)->setHasAllowReassoc(B);
-}
-
-void Instruction::setHasNoNaNs(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>(
- this);
- cast<llvm::Instruction>(Val)->setHasNoNaNs(B);
-}
-
-void Instruction::setHasNoInfs(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>(
- this);
- cast<llvm::Instruction>(Val)->setHasNoInfs(B);
-}
-
-void Instruction::setHasNoSignedZeros(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros,
- &Instruction::setHasNoSignedZeros>>(
- this);
- cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B);
-}
-
-void Instruction::setHasAllowReciprocal(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal,
- &Instruction::setHasAllowReciprocal>>(
- this);
- cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B);
-}
-
-void Instruction::setHasAllowContract(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract,
- &Instruction::setHasAllowContract>>(
- this);
- cast<llvm::Instruction>(Val)->setHasAllowContract(B);
-}
-
-void Instruction::setFastMathFlags(FastMathFlags FMF) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
- &Instruction::copyFastMathFlags>>(this);
- cast<llvm::Instruction>(Val)->setFastMathFlags(FMF);
-}
-
-void Instruction::copyFastMathFlags(FastMathFlags FMF) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
- &Instruction::copyFastMathFlags>>(this);
- cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF);
-}
-
-Type *Instruction::getAccessType() const {
- return Ctx.getType(cast<llvm::Instruction>(Val)->getAccessType());
-}
-
-void Instruction::setHasApproxFunc(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc,
- &Instruction::setHasApproxFunc>>(this);
- cast<llvm::Instruction>(Val)->setHasApproxFunc(B);
-}
-
-#ifndef NDEBUG
-void Instruction::dumpOS(raw_ostream &OS) const {
- OS << "Unimplemented! Please override dump().";
-}
-#endif // NDEBUG
-
-VAArgInst *VAArgInst::create(Value *List, Type *Ty, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- auto *LLVMI =
- cast<llvm::VAArgInst>(Builder.CreateVAArg(List->Val, Ty->LLVMTy, Name));
- return Ctx.createVAArgInst(LLVMI);
-}
-
-Value *VAArgInst::getPointerOperand() {
- return Ctx.getValue(cast<llvm::VAArgInst>(Val)->getPointerOperand());
-}
-
-FreezeInst *FreezeInst::create(Value *V, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- auto *LLVMI = cast<llvm::FreezeInst>(Builder.CreateFreeze(V->Val, Name));
- return Ctx.createFreezeInst(LLVMI);
-}
-
-FenceInst *FenceInst::create(AtomicOrdering Ordering, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- SyncScope::ID SSID) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::FenceInst *LLVMI = Builder.CreateFence(Ordering, SSID);
- return Ctx.createFenceInst(LLVMI);
-}
-
-void FenceInst::setOrdering(AtomicOrdering Ordering) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&FenceInst::getOrdering, &FenceInst::setOrdering>>(
- this);
- cast<llvm::FenceInst>(Val)->setOrdering(Ordering);
-}
-
-void FenceInst::setSyncScopeID(SyncScope::ID SSID) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&FenceInst::getSyncScopeID,
- &FenceInst::setSyncScopeID>>(this);
- cast<llvm::FenceInst>(Val)->setSyncScopeID(SSID);
-}
-
-Value *SelectInst::createCommon(Value *Cond, Value *True, Value *False,
- const Twine &Name, IRBuilder<> &Builder,
- Context &Ctx) {
- llvm::Value *NewV =
- Builder.CreateSelect(Cond->Val, True->Val, False->Val, Name);
- if (auto *NewSI = dyn_cast<llvm::SelectInst>(NewV))
- return Ctx.createSelectInst(NewSI);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *SelectInst::create(Value *Cond, Value *True, Value *False,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(BeforeIR);
- return createCommon(Cond, True, False, Name, Builder, Ctx);
-}
-
-Value *SelectInst::create(Value *Cond, Value *True, Value *False,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- auto *IRInsertAtEnd = cast<llvm::BasicBlock>(InsertAtEnd->Val);
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(IRInsertAtEnd);
- return createCommon(Cond, True, False, Name, Builder, Ctx);
-}
-
-void SelectInst::swapValues() {
- Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(1),
- getOperandUse(2));
- cast<llvm::SelectInst>(Val)->swapValues();
-}
-
-bool SelectInst::classof(const Value *From) {
- return From->getSubclassID() == ClassID::Select;
-}
-
-BranchInst *BranchInst::create(BasicBlock *IfTrue, Instruction *InsertBefore,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
- Builder.SetInsertPoint(cast<llvm::Instruction>(LLVMBefore));
- llvm::BranchInst *NewBr =
- Builder.CreateBr(cast<llvm::BasicBlock>(IfTrue->Val));
- return Ctx.createBranchInst(NewBr);
-}
-
-BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::BranchInst *NewBr =
- Builder.CreateBr(cast<llvm::BasicBlock>(IfTrue->Val));
- return Ctx.createBranchInst(NewBr);
-}
-
-BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse,
- Value *Cond, Instruction *InsertBefore,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
- Builder.SetInsertPoint(LLVMBefore);
- llvm::BranchInst *NewBr =
- Builder.CreateCondBr(Cond->Val, cast<llvm::BasicBlock>(IfTrue->Val),
- cast<llvm::BasicBlock>(IfFalse->Val));
- return Ctx.createBranchInst(NewBr);
-}
-
-BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse,
- Value *Cond, BasicBlock *InsertAtEnd,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::BranchInst *NewBr =
- Builder.CreateCondBr(Cond->Val, cast<llvm::BasicBlock>(IfTrue->Val),
- cast<llvm::BasicBlock>(IfFalse->Val));
- return Ctx.createBranchInst(NewBr);
-}
-
-bool BranchInst::classof(const Value *From) {
- return From->getSubclassID() == ClassID::Br;
-}
-
-Value *BranchInst::getCondition() const {
- assert(isConditional() && "Cannot get condition of an uncond branch!");
- return Ctx.getValue(cast<llvm::BranchInst>(Val)->getCondition());
-}
-
-BasicBlock *BranchInst::getSuccessor(unsigned SuccIdx) const {
- assert(SuccIdx < getNumSuccessors() &&
- "Successor # out of range for Branch!");
- return cast_or_null<BasicBlock>(
- Ctx.getValue(cast<llvm::BranchInst>(Val)->getSuccessor(SuccIdx)));
-}
-
-void BranchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
- assert((Idx == 0 || Idx == 1) && "Out of bounds!");
- setOperand(2u - Idx, NewSucc);
-}
-
-BasicBlock *BranchInst::LLVMBBToSBBB::operator()(llvm::BasicBlock *BB) const {
- return cast<BasicBlock>(Ctx.getValue(BB));
-}
-const BasicBlock *
-BranchInst::ConstLLVMBBToSBBB::operator()(const llvm::BasicBlock *BB) const {
- return cast<BasicBlock>(Ctx.getValue(BB));
-}
-
-void LoadInst::setVolatile(bool V) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&LoadInst::isVolatile, &LoadInst::setVolatile>>(this);
- cast<llvm::LoadInst>(Val)->setVolatile(V);
-}
-
-LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- return create(Ty, Ptr, Align, InsertBefore, /*IsVolatile=*/false, Ctx, Name);
-}
-
-LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, bool IsVolatile,
- Context &Ctx, const Twine &Name) {
- llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(BeforeIR);
- auto *NewLI =
- Builder.CreateAlignedLoad(Ty->LLVMTy, Ptr->Val, Align, IsVolatile, Name);
- auto *NewSBI = Ctx.createLoadInst(NewLI);
- return NewSBI;
-}
-
-LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- return create(Ty, Ptr, Align, InsertAtEnd, /*IsVolatile=*/false, Ctx, Name);
-}
-
-LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, bool IsVolatile,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- auto *NewLI =
- Builder.CreateAlignedLoad(Ty->LLVMTy, Ptr->Val, Align, IsVolatile, Name);
- auto *NewSBI = Ctx.createLoadInst(NewLI);
- return NewSBI;
-}
-
-bool LoadInst::classof(const Value *From) {
- return From->getSubclassID() == ClassID::Load;
-}
-
-Value *LoadInst::getPointerOperand() const {
- return Ctx.getValue(cast<llvm::LoadInst>(Val)->getPointerOperand());
-}
-
-void StoreInst::setVolatile(bool V) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&StoreInst::isVolatile, &StoreInst::setVolatile>>(this);
- cast<llvm::StoreInst>(Val)->setVolatile(V);
-}
-
-StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, Context &Ctx) {
- return create(V, Ptr, Align, InsertBefore, /*IsVolatile=*/false, Ctx);
-}
-
-StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
- Instruction *InsertBefore, bool IsVolatile,
- Context &Ctx) {
- llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(BeforeIR);
- auto *NewSI = Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, IsVolatile);
- auto *NewSBI = Ctx.createStoreInst(NewSI);
- return NewSBI;
-}
-
-StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, Context &Ctx) {
- return create(V, Ptr, Align, InsertAtEnd, /*IsVolatile=*/false, Ctx);
-}
-
-StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
- BasicBlock *InsertAtEnd, bool IsVolatile,
- Context &Ctx) {
- auto *InsertAtEndIR = cast<llvm::BasicBlock>(InsertAtEnd->Val);
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(InsertAtEndIR);
- auto *NewSI = Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, IsVolatile);
- auto *NewSBI = Ctx.createStoreInst(NewSI);
- return NewSBI;
-}
-
-bool StoreInst::classof(const Value *From) {
- return From->getSubclassID() == ClassID::Store;
-}
-
-Value *StoreInst::getValueOperand() const {
- return Ctx.getValue(cast<llvm::StoreInst>(Val)->getValueOperand());
-}
-
-Value *StoreInst::getPointerOperand() const {
- return Ctx.getValue(cast<llvm::StoreInst>(Val)->getPointerOperand());
-}
-
-UnreachableInst *UnreachableInst::create(Instruction *InsertBefore,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
- Builder.SetInsertPoint(LLVMBefore);
- llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
- return Ctx.createUnreachableInst(NewUI);
-}
-
-UnreachableInst *UnreachableInst::create(BasicBlock *InsertAtEnd,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
- return Ctx.createUnreachableInst(NewUI);
-}
-
-bool UnreachableInst::classof(const Value *From) {
- return From->getSubclassID() == ClassID::Unreachable;
-}
-
-ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder,
- Context &Ctx) {
- llvm::ReturnInst *NewRI;
- if (RetVal != nullptr)
- NewRI = Builder.CreateRet(RetVal->Val);
- else
- NewRI = Builder.CreateRetVoid();
- return Ctx.createReturnInst(NewRI);
-}
-
-ReturnInst *ReturnInst::create(Value *RetVal, Instruction *InsertBefore,
- Context &Ctx) {
- llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(BeforeIR);
- return createCommon(RetVal, Builder, Ctx);
-}
-
-ReturnInst *ReturnInst::create(Value *RetVal, BasicBlock *InsertAtEnd,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- return createCommon(RetVal, Builder, Ctx);
-}
-
-Value *ReturnInst::getReturnValue() const {
- auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue();
- return LLVMRetVal != nullptr ? Ctx.getValue(LLVMRetVal) : nullptr;
-}
-
-FunctionType *CallBase::getFunctionType() const {
- return cast<FunctionType>(
- Ctx.getType(cast<llvm::CallBase>(Val)->getFunctionType()));
-}
-
-Value *CallBase::getCalledOperand() const {
- return Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledOperand());
-}
-
-Use CallBase::getCalledOperandUse() const {
- llvm::Use *LLVMUse = &cast<llvm::CallBase>(Val)->getCalledOperandUse();
- return Use(LLVMUse, cast<User>(Ctx.getValue(LLVMUse->getUser())), Ctx);
-}
-
-Function *CallBase::getCalledFunction() const {
- return cast_or_null<Function>(
- Ctx.getValue(cast<llvm::CallBase>(Val)->getCalledFunction()));
-}
-Function *CallBase::getCaller() {
- return cast<Function>(Ctx.getValue(cast<llvm::CallBase>(Val)->getCaller()));
-}
-
-void CallBase::setCalledFunction(Function *F) {
- // F's function type is private, so we rely on `setCalledFunction()` to update
- // it. But even though we are calling `setCalledFunction()` we also need to
- // track this change at the SandboxIR level, which is why we call
- // `setCalledOperand()` here.
- // Note: This may break if `setCalledFunction()` early returns if `F`
- // is already set, but we do have a unit test for it.
- setCalledOperand(F);
- cast<llvm::CallBase>(Val)->setCalledFunction(
- cast<llvm::FunctionType>(F->getFunctionType()->LLVMTy),
- cast<llvm::Function>(F->Val));
-}
-
-CallInst *CallInst::create(FunctionType *FTy, Value *Func,
- ArrayRef<Value *> Args, BasicBlock::iterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- SmallVector<llvm::Value *> LLVMArgs;
- LLVMArgs.reserve(Args.size());
- for (Value *Arg : Args)
- LLVMArgs.push_back(Arg->Val);
- llvm::CallInst *NewCI = Builder.CreateCall(
- cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val, LLVMArgs, NameStr);
- return Ctx.createCallInst(NewCI);
-}
-
-CallInst *CallInst::create(FunctionType *FTy, Value *Func,
- ArrayRef<Value *> Args, Instruction *InsertBefore,
- Context &Ctx, const Twine &NameStr) {
- return CallInst::create(FTy, Func, Args, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, NameStr);
-}
-
-CallInst *CallInst::create(FunctionType *FTy, Value *Func,
- ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &NameStr) {
- return CallInst::create(FTy, Func, Args, InsertAtEnd->end(), InsertAtEnd, Ctx,
- NameStr);
-}
-
-InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- SmallVector<llvm::Value *> LLVMArgs;
- LLVMArgs.reserve(Args.size());
- for (Value *Arg : Args)
- LLVMArgs.push_back(Arg->Val);
- llvm::InvokeInst *Invoke = Builder.CreateInvoke(
- cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,
- cast<llvm::BasicBlock>(IfNormal->Val),
- cast<llvm::BasicBlock>(IfException->Val), LLVMArgs, NameStr);
- return Ctx.createInvokeInst(Invoke);
-}
-
-InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &NameStr) {
- return create(FTy, Func, IfNormal, IfException, Args,
- InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
- NameStr);
-}
-
-InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func,
- BasicBlock *IfNormal, BasicBlock *IfException,
- ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &NameStr) {
- return create(FTy, Func, IfNormal, IfException, Args, InsertAtEnd->end(),
- InsertAtEnd, Ctx, NameStr);
-}
-
-BasicBlock *InvokeInst::getNormalDest() const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::InvokeInst>(Val)->getNormalDest()));
-}
-BasicBlock *InvokeInst::getUnwindDest() const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::InvokeInst>(Val)->getUnwindDest()));
-}
-void InvokeInst::setNormalDest(BasicBlock *BB) {
- setOperand(1, BB);
- assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");
-}
-void InvokeInst::setUnwindDest(BasicBlock *BB) {
- setOperand(2, BB);
- assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
-}
-LandingPadInst *InvokeInst::getLandingPadInst() const {
- return cast<LandingPadInst>(
- Ctx.getValue(cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
- ;
-}
-BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::InvokeInst>(Val)->getSuccessor(SuccIdx)));
-}
-
-CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
- BasicBlock *DefaultDest,
- ArrayRef<BasicBlock *> IndirectDests,
- ArrayRef<Value *> Args, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
-
- SmallVector<llvm::BasicBlock *> LLVMIndirectDests;
- LLVMIndirectDests.reserve(IndirectDests.size());
- for (BasicBlock *IndDest : IndirectDests)
- LLVMIndirectDests.push_back(cast<llvm::BasicBlock>(IndDest->Val));
-
- SmallVector<llvm::Value *> LLVMArgs;
- LLVMArgs.reserve(Args.size());
- for (Value *Arg : Args)
- LLVMArgs.push_back(Arg->Val);
-
- llvm::CallBrInst *CallBr =
- Builder.CreateCallBr(cast<llvm::FunctionType>(FTy->LLVMTy), Func->Val,
- cast<llvm::BasicBlock>(DefaultDest->Val),
- LLVMIndirectDests, LLVMArgs, NameStr);
- return Ctx.createCallBrInst(CallBr);
-}
-
-CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
- BasicBlock *DefaultDest,
- ArrayRef<BasicBlock *> IndirectDests,
- ArrayRef<Value *> Args,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &NameStr) {
- return create(FTy, Func, DefaultDest, IndirectDests, Args,
- InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
- NameStr);
-}
-CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func,
- BasicBlock *DefaultDest,
- ArrayRef<BasicBlock *> IndirectDests,
- ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &NameStr) {
- return create(FTy, Func, DefaultDest, IndirectDests, Args, InsertAtEnd->end(),
- InsertAtEnd, Ctx, NameStr);
-}
-
-Value *CallBrInst::getIndirectDestLabel(unsigned Idx) const {
- return Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDestLabel(Idx));
-}
-Value *CallBrInst::getIndirectDestLabelUse(unsigned Idx) const {
- return Ctx.getValue(
- cast<llvm::CallBrInst>(Val)->getIndirectDestLabelUse(Idx));
-}
-BasicBlock *CallBrInst::getDefaultDest() const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::CallBrInst>(Val)->getDefaultDest()));
-}
-BasicBlock *CallBrInst::getIndirectDest(unsigned Idx) const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::CallBrInst>(Val)->getIndirectDest(Idx)));
-}
-llvm::SmallVector<BasicBlock *, 16> CallBrInst::getIndirectDests() const {
- SmallVector<BasicBlock *, 16> BBs;
- for (llvm::BasicBlock *LLVMBB :
- cast<llvm::CallBrInst>(Val)->getIndirectDests())
- BBs.push_back(cast<BasicBlock>(Ctx.getValue(LLVMBB)));
- return BBs;
-}
-void CallBrInst::setDefaultDest(BasicBlock *BB) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CallBrInst::getDefaultDest,
- &CallBrInst::setDefaultDest>>(this);
- cast<llvm::CallBrInst>(Val)->setDefaultDest(cast<llvm::BasicBlock>(BB->Val));
-}
-void CallBrInst::setIndirectDest(unsigned Idx, BasicBlock *BB) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetterWithIdx<&CallBrInst::getIndirectDest,
- &CallBrInst::setIndirectDest>>(
- this, Idx);
- cast<llvm::CallBrInst>(Val)->setIndirectDest(Idx,
- cast<llvm::BasicBlock>(BB->Val));
-}
-BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::CallBrInst>(Val)->getSuccessor(Idx)));
-}
-
-LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::LandingPadInst *LLVMI =
- Builder.CreateLandingPad(RetTy->LLVMTy, NumReservedClauses, Name);
- return Ctx.createLandingPadInst(LLVMI);
-}
-
-void LandingPadInst::setCleanup(bool V) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup,
- &LandingPadInst::setCleanup>>(this);
- cast<llvm::LandingPadInst>(Val)->setCleanup(V);
-}
-
-Constant *LandingPadInst::getClause(unsigned Idx) const {
- return cast<Constant>(
- Ctx.getValue(cast<llvm::LandingPadInst>(Val)->getClause(Idx)));
-}
-
-Value *FuncletPadInst::getParentPad() const {
- return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getParentPad());
-}
-
-void FuncletPadInst::setParentPad(Value *ParentPad) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&FuncletPadInst::getParentPad,
- &FuncletPadInst::setParentPad>>(this);
- cast<llvm::FuncletPadInst>(Val)->setParentPad(ParentPad->Val);
-}
-
-Value *FuncletPadInst::getArgOperand(unsigned Idx) const {
- return Ctx.getValue(cast<llvm::FuncletPadInst>(Val)->getArgOperand(Idx));
-}
-
-void FuncletPadInst::setArgOperand(unsigned Idx, Value *V) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetterWithIdx<&FuncletPadInst::getArgOperand,
- &FuncletPadInst::setArgOperand>>(
- this, Idx);
- cast<llvm::FuncletPadInst>(Val)->setArgOperand(Idx, V->Val);
-}
-
-CatchSwitchInst *CatchPadInst::getCatchSwitch() const {
- return cast<CatchSwitchInst>(
- Ctx.getValue(cast<llvm::CatchPadInst>(Val)->getCatchSwitch()));
-}
-
-CatchPadInst *CatchPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- SmallVector<llvm::Value *> LLVMArgs;
- LLVMArgs.reserve(Args.size());
- for (auto *Arg : Args)
- LLVMArgs.push_back(Arg->Val);
- llvm::CatchPadInst *LLVMI =
- Builder.CreateCatchPad(ParentPad->Val, LLVMArgs, Name);
- return Ctx.createCatchPadInst(LLVMI);
-}
-
-CleanupPadInst *CleanupPadInst::create(Value *ParentPad, ArrayRef<Value *> Args,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- SmallVector<llvm::Value *> LLVMArgs;
- LLVMArgs.reserve(Args.size());
- for (auto *Arg : Args)
- LLVMArgs.push_back(Arg->Val);
- llvm::CleanupPadInst *LLVMI =
- Builder.CreateCleanupPad(ParentPad->Val, LLVMArgs, Name);
- return Ctx.createCleanupPadInst(LLVMI);
-}
-
-CatchReturnInst *CatchReturnInst::create(CatchPadInst *CatchPad, BasicBlock *BB,
- BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::CatchReturnInst *LLVMI = Builder.CreateCatchRet(
- cast<llvm::CatchPadInst>(CatchPad->Val), cast<llvm::BasicBlock>(BB->Val));
- return Ctx.createCatchReturnInst(LLVMI);
-}
-
-CatchPadInst *CatchReturnInst::getCatchPad() const {
- return cast<CatchPadInst>(
- Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getCatchPad()));
-}
-
-void CatchReturnInst::setCatchPad(CatchPadInst *CatchPad) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CatchReturnInst::getCatchPad,
- &CatchReturnInst::setCatchPad>>(this);
- cast<llvm::CatchReturnInst>(Val)->setCatchPad(
- cast<llvm::CatchPadInst>(CatchPad->Val));
-}
-
-BasicBlock *CatchReturnInst::getSuccessor() const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::CatchReturnInst>(Val)->getSuccessor()));
-}
-
-void CatchReturnInst::setSuccessor(BasicBlock *NewSucc) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CatchReturnInst::getSuccessor,
- &CatchReturnInst::setSuccessor>>(this);
- cast<llvm::CatchReturnInst>(Val)->setSuccessor(
- cast<llvm::BasicBlock>(NewSucc->Val));
-}
-
-Value *CatchReturnInst::getCatchSwitchParentPad() const {
- return Ctx.getValue(
- cast<llvm::CatchReturnInst>(Val)->getCatchSwitchParentPad());
-}
-
-CleanupReturnInst *CleanupReturnInst::create(CleanupPadInst *CleanupPad,
- BasicBlock *UnwindBB,
- BBIterator WhereIt,
- BasicBlock *WhereBB,
- Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- auto *LLVMUnwindBB =
- UnwindBB != nullptr ? cast<llvm::BasicBlock>(UnwindBB->Val) : nullptr;
- llvm::CleanupReturnInst *LLVMI = Builder.CreateCleanupRet(
- cast<llvm::CleanupPadInst>(CleanupPad->Val), LLVMUnwindBB);
- return Ctx.createCleanupReturnInst(LLVMI);
-}
-
-CleanupPadInst *CleanupReturnInst::getCleanupPad() const {
- return cast<CleanupPadInst>(
- Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getCleanupPad()));
-}
-
-void CleanupReturnInst::setCleanupPad(CleanupPadInst *CleanupPad) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CleanupReturnInst::getCleanupPad,
- &CleanupReturnInst::setCleanupPad>>(
- this);
- cast<llvm::CleanupReturnInst>(Val)->setCleanupPad(
- cast<llvm::CleanupPadInst>(CleanupPad->Val));
-}
-
-BasicBlock *CleanupReturnInst::getUnwindDest() const {
- return cast_or_null<BasicBlock>(
- Ctx.getValue(cast<llvm::CleanupReturnInst>(Val)->getUnwindDest()));
-}
-
-void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CleanupReturnInst::getUnwindDest,
- &CleanupReturnInst::setUnwindDest>>(
- this);
- cast<llvm::CleanupReturnInst>(Val)->setUnwindDest(
- cast<llvm::BasicBlock>(NewDest->Val));
-}
-
-Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
- ArrayRef<Value *> IdxList,
- BasicBlock::iterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &NameStr) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- SmallVector<llvm::Value *> LLVMIdxList;
- LLVMIdxList.reserve(IdxList.size());
- for (Value *Idx : IdxList)
- LLVMIdxList.push_back(Idx->Val);
- llvm::Value *NewV =
- Builder.CreateGEP(Ty->LLVMTy, Ptr->Val, LLVMIdxList, NameStr);
- if (auto *NewGEP = dyn_cast<llvm::GetElementPtrInst>(NewV))
- return Ctx.createGetElementPtrInst(NewGEP);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
- ArrayRef<Value *> IdxList,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &NameStr) {
- return GetElementPtrInst::create(Ty, Ptr, IdxList,
- InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, NameStr);
-}
-
-Value *GetElementPtrInst::create(Type *Ty, Value *Ptr,
- ArrayRef<Value *> IdxList,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &NameStr) {
- return GetElementPtrInst::create(Ty, Ptr, IdxList, InsertAtEnd->end(),
- InsertAtEnd, Ctx, NameStr);
-}
-
-Type *GetElementPtrInst::getSourceElementType() const {
- return Ctx.getType(
- cast<llvm::GetElementPtrInst>(Val)->getSourceElementType());
-}
-
-Type *GetElementPtrInst::getResultElementType() const {
- return Ctx.getType(
- cast<llvm::GetElementPtrInst>(Val)->getResultElementType());
-}
-
-Value *GetElementPtrInst::getPointerOperand() const {
- return Ctx.getValue(cast<llvm::GetElementPtrInst>(Val)->getPointerOperand());
-}
-
-Type *GetElementPtrInst::getPointerOperandType() const {
- return Ctx.getType(
- cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType());
-}
-
-BasicBlock *PHINode::LLVMBBToBB::operator()(llvm::BasicBlock *LLVMBB) const {
- return cast<BasicBlock>(Ctx.getValue(LLVMBB));
-}
-
-PHINode *PHINode::create(Type *Ty, unsigned NumReservedValues,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- llvm::PHINode *NewPHI = llvm::PHINode::Create(
- Ty->LLVMTy, NumReservedValues, Name,
- InsertBefore->getTopmostLLVMInstruction()->getIterator());
- return Ctx.createPHINode(NewPHI);
-}
-
-bool PHINode::classof(const Value *From) {
- return From->getSubclassID() == ClassID::PHI;
-}
-
-Value *PHINode::getIncomingValue(unsigned Idx) const {
- return Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingValue(Idx));
-}
-void PHINode::setIncomingValue(unsigned Idx, Value *V) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetterWithIdx<&PHINode::getIncomingValue,
- &PHINode::setIncomingValue>>(this,
- Idx);
- cast<llvm::PHINode>(Val)->setIncomingValue(Idx, V->Val);
-}
-BasicBlock *PHINode::getIncomingBlock(unsigned Idx) const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::PHINode>(Val)->getIncomingBlock(Idx)));
-}
-BasicBlock *PHINode::getIncomingBlock(const Use &U) const {
- llvm::Use *LLVMUse = U.LLVMUse;
- llvm::BasicBlock *BB = cast<llvm::PHINode>(Val)->getIncomingBlock(*LLVMUse);
- return cast<BasicBlock>(Ctx.getValue(BB));
-}
-void PHINode::setIncomingBlock(unsigned Idx, BasicBlock *BB) {
- // Helper to disambiguate PHINode::getIncomingBlock(unsigned).
- constexpr BasicBlock *(PHINode::*GetIncomingBlockFn)(unsigned) const =
- &PHINode::getIncomingBlock;
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetterWithIdx<GetIncomingBlockFn, &PHINode::setIncomingBlock>>(
- this, Idx);
- cast<llvm::PHINode>(Val)->setIncomingBlock(Idx,
- cast<llvm::BasicBlock>(BB->Val));
-}
-void PHINode::addIncoming(Value *V, BasicBlock *BB) {
- auto &Tracker = Ctx.getTracker();
- Tracker.emplaceIfTracking<PHIAddIncoming>(this);
-
- cast<llvm::PHINode>(Val)->addIncoming(V->Val,
- cast<llvm::BasicBlock>(BB->Val));
-}
-Value *PHINode::removeIncomingValue(unsigned Idx) {
- auto &Tracker = Ctx.getTracker();
- Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, Idx);
- llvm::Value *LLVMV =
- cast<llvm::PHINode>(Val)->removeIncomingValue(Idx,
- /*DeletePHIIfEmpty=*/false);
- return Ctx.getValue(LLVMV);
-}
-Value *PHINode::removeIncomingValue(BasicBlock *BB) {
- auto &Tracker = Ctx.getTracker();
- Tracker.emplaceIfTracking<PHIRemoveIncoming>(this, getBasicBlockIndex(BB));
-
- auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
- llvm::Value *LLVMV =
- cast<llvm::PHINode>(Val)->removeIncomingValue(LLVMBB,
- /*DeletePHIIfEmpty=*/false);
- return Ctx.getValue(LLVMV);
-}
-int PHINode::getBasicBlockIndex(const BasicBlock *BB) const {
- auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
- return cast<llvm::PHINode>(Val)->getBasicBlockIndex(LLVMBB);
-}
-Value *PHINode::getIncomingValueForBlock(const BasicBlock *BB) const {
- auto *LLVMBB = cast<llvm::BasicBlock>(BB->Val);
- llvm::Value *LLVMV =
- cast<llvm::PHINode>(Val)->getIncomingValueForBlock(LLVMBB);
- return Ctx.getValue(LLVMV);
-}
-Value *PHINode::hasConstantValue() const {
- llvm::Value *LLVMV = cast<llvm::PHINode>(Val)->hasConstantValue();
- return LLVMV != nullptr ? Ctx.getValue(LLVMV) : nullptr;
-}
-void PHINode::replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) {
- assert(New && Old && "Sandbox IR PHI node got a null basic block!");
- for (unsigned Idx = 0, NumOps = cast<llvm::PHINode>(Val)->getNumOperands();
- Idx != NumOps; ++Idx)
- if (getIncomingBlock(Idx) == Old)
- setIncomingBlock(Idx, New);
-}
-void PHINode::removeIncomingValueIf(function_ref<bool(unsigned)> Predicate) {
- // Avoid duplicate tracking by going through this->removeIncomingValue here at
- // the expense of some performance. Copy PHI::removeIncomingValueIf more
- // directly if performance becomes an issue.
-
- // Removing the element at index X, moves the element previously at X + 1
- // to X. Working from the end avoids complications from that.
- unsigned Idx = getNumIncomingValues();
- while (Idx > 0) {
- if (Predicate(Idx - 1))
- removeIncomingValue(Idx - 1);
- --Idx;
- }
-}
-
-static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {
- switch (Opc) {
- case Instruction::Opcode::ZExt:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::ZExt);
- case Instruction::Opcode::SExt:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SExt);
- case Instruction::Opcode::FPToUI:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToUI);
- case Instruction::Opcode::FPToSI:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToSI);
- case Instruction::Opcode::FPExt:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPExt);
- case Instruction::Opcode::PtrToInt:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::PtrToInt);
- case Instruction::Opcode::IntToPtr:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::IntToPtr);
- case Instruction::Opcode::SIToFP:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SIToFP);
- case Instruction::Opcode::UIToFP:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::UIToFP);
- case Instruction::Opcode::Trunc:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::Trunc);
- case Instruction::Opcode::FPTrunc:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPTrunc);
- case Instruction::Opcode::BitCast:
- return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::BitCast);
- case Instruction::Opcode::AddrSpaceCast:
- return static_cast<llvm::Instruction::CastOps>(
- llvm::Instruction::AddrSpaceCast);
- default:
- llvm_unreachable("Opcode not suitable for CastInst!");
- }
-}
-
-/// \Returns the LLVM opcode that corresponds to \p Opc.
-static llvm::Instruction::UnaryOps getLLVMUnaryOp(Instruction::Opcode Opc) {
- switch (Opc) {
- case Instruction::Opcode::FNeg:
- return static_cast<llvm::Instruction::UnaryOps>(llvm::Instruction::FNeg);
- default:
- llvm_unreachable("Not a unary op!");
- }
-}
-
-CatchSwitchInst *CatchSwitchInst::create(Value *ParentPad, BasicBlock *UnwindBB,
- unsigned NumHandlers,
- BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::CatchSwitchInst *LLVMCSI = Builder.CreateCatchSwitch(
- ParentPad->Val, cast<llvm::BasicBlock>(UnwindBB->Val), NumHandlers, Name);
- return Ctx.createCatchSwitchInst(LLVMCSI);
-}
-
-Value *CatchSwitchInst::getParentPad() const {
- return Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getParentPad());
-}
-
-void CatchSwitchInst::setParentPad(Value *ParentPad) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CatchSwitchInst::getParentPad,
- &CatchSwitchInst::setParentPad>>(this);
- cast<llvm::CatchSwitchInst>(Val)->setParentPad(ParentPad->Val);
-}
-
-BasicBlock *CatchSwitchInst::getUnwindDest() const {
- return cast_or_null<BasicBlock>(
- Ctx.getValue(cast<llvm::CatchSwitchInst>(Val)->getUnwindDest()));
-}
-
-void CatchSwitchInst::setUnwindDest(BasicBlock *UnwindDest) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&CatchSwitchInst::getUnwindDest,
- &CatchSwitchInst::setUnwindDest>>(this);
- cast<llvm::CatchSwitchInst>(Val)->setUnwindDest(
- cast<llvm::BasicBlock>(UnwindDest->Val));
-}
-
-void CatchSwitchInst::addHandler(BasicBlock *Dest) {
- Ctx.getTracker().emplaceIfTracking<CatchSwitchAddHandler>(this);
- cast<llvm::CatchSwitchInst>(Val)->addHandler(
- cast<llvm::BasicBlock>(Dest->Val));
-}
-
-ResumeInst *ResumeInst::create(Value *Exn, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- auto *LLVMI = cast<llvm::ResumeInst>(Builder.CreateResume(Exn->Val));
- return Ctx.createResumeInst(LLVMI);
-}
-
-Value *ResumeInst::getValue() const {
- return Ctx.getValue(cast<llvm::ResumeInst>(Val)->getValue());
-}
-
-SwitchInst *SwitchInst::create(Value *V, BasicBlock *Dest, unsigned NumCases,
- BasicBlock::iterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::SwitchInst *LLVMSwitch =
- Builder.CreateSwitch(V->Val, cast<llvm::BasicBlock>(Dest->Val), NumCases);
- return Ctx.createSwitchInst(LLVMSwitch);
-}
-
-Value *SwitchInst::getCondition() const {
- return Ctx.getValue(cast<llvm::SwitchInst>(Val)->getCondition());
-}
-
-void SwitchInst::setCondition(Value *V) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&SwitchInst::getCondition, &SwitchInst::setCondition>>(
- this);
- cast<llvm::SwitchInst>(Val)->setCondition(V->Val);
-}
-
-BasicBlock *SwitchInst::getDefaultDest() const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::SwitchInst>(Val)->getDefaultDest()));
-}
-
-void SwitchInst::setDefaultDest(BasicBlock *DefaultCase) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&SwitchInst::getDefaultDest,
- &SwitchInst::setDefaultDest>>(this);
- cast<llvm::SwitchInst>(Val)->setDefaultDest(
- cast<llvm::BasicBlock>(DefaultCase->Val));
-}
-ConstantInt *SwitchInst::findCaseDest(BasicBlock *BB) {
- auto *LLVMC = cast<llvm::SwitchInst>(Val)->findCaseDest(
- cast<llvm::BasicBlock>(BB->Val));
- return LLVMC != nullptr ? cast<ConstantInt>(Ctx.getValue(LLVMC)) : nullptr;
-}
-
-void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
- Ctx.getTracker().emplaceIfTracking<SwitchAddCase>(this, OnVal);
- // TODO: Track this!
- cast<llvm::SwitchInst>(Val)->addCase(cast<llvm::ConstantInt>(OnVal->Val),
- cast<llvm::BasicBlock>(Dest->Val));
-}
-
-SwitchInst::CaseIt SwitchInst::removeCase(CaseIt It) {
- auto &Case = *It;
- Ctx.getTracker().emplaceIfTracking<SwitchRemoveCase>(
- this, Case.getCaseValue(), Case.getCaseSuccessor());
-
- auto *LLVMSwitch = cast<llvm::SwitchInst>(Val);
- unsigned CaseNum = It - case_begin();
- llvm::SwitchInst::CaseIt LLVMIt(LLVMSwitch, CaseNum);
- auto LLVMCaseIt = LLVMSwitch->removeCase(LLVMIt);
- unsigned Num = LLVMCaseIt - LLVMSwitch->case_begin();
- return CaseIt(this, Num);
-}
-
-BasicBlock *SwitchInst::getSuccessor(unsigned Idx) const {
- return cast<BasicBlock>(
- Ctx.getValue(cast<llvm::SwitchInst>(Val)->getSuccessor(Idx)));
-}
-
-void SwitchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetterWithIdx<&SwitchInst::getSuccessor,
- &SwitchInst::setSuccessor>>(this,
- Idx);
- cast<llvm::SwitchInst>(Val)->setSuccessor(
- Idx, cast<llvm::BasicBlock>(NewSucc->Val));
-}
-
-Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt == WhereBB->end())
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- else
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- auto *NewLLVMV = Builder.CreateUnOp(getLLVMUnaryOp(Op), OpV->Val, Name);
- if (auto *NewUnOpV = dyn_cast<llvm::UnaryOperator>(NewLLVMV)) {
- return Ctx.createUnaryOperator(NewUnOpV);
- }
- assert(isa<llvm::Constant>(NewLLVMV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewLLVMV));
-}
-
-Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- return create(Op, OpV, InsertBefore->getIterator(), InsertBefore->getParent(),
- Ctx, Name);
-}
-
-Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV,
- BasicBlock *InsertAfter, Context &Ctx,
- const Twine &Name) {
- return create(Op, OpV, InsertAfter->end(), InsertAfter, Ctx, Name);
-}
-
-Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
- Value *CopyFrom, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
- auto *NewV = create(Op, OpV, WhereIt, WhereBB, Ctx, Name);
- if (auto *UnI = dyn_cast<llvm::UnaryOperator>(NewV->Val))
- UnI->copyIRFlags(CopyFrom->Val);
- return NewV;
-}
-
-Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
- Value *CopyFrom,
- Instruction *InsertBefore,
- Context &Ctx, const Twine &Name) {
- return createWithCopiedFlags(Op, OpV, CopyFrom, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, Name);
-}
-
-Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV,
- Value *CopyFrom,
- BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &Name) {
- return createWithCopiedFlags(Op, OpV, CopyFrom, InsertAtEnd->end(),
- InsertAtEnd, Ctx, Name);
-}
-
-/// \Returns the LLVM opcode that corresponds to \p Opc.
-static llvm::Instruction::BinaryOps getLLVMBinaryOp(Instruction::Opcode Opc) {
- switch (Opc) {
- case Instruction::Opcode::Add:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Add);
- case Instruction::Opcode::FAdd:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FAdd);
- case Instruction::Opcode::Sub:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Sub);
- case Instruction::Opcode::FSub:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FSub);
- case Instruction::Opcode::Mul:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Mul);
- case Instruction::Opcode::FMul:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FMul);
- case Instruction::Opcode::UDiv:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::UDiv);
- case Instruction::Opcode::SDiv:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SDiv);
- case Instruction::Opcode::FDiv:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FDiv);
- case Instruction::Opcode::URem:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::URem);
- case Instruction::Opcode::SRem:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SRem);
- case Instruction::Opcode::FRem:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FRem);
- case Instruction::Opcode::Shl:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Shl);
- case Instruction::Opcode::LShr:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::LShr);
- case Instruction::Opcode::AShr:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::AShr);
- case Instruction::Opcode::And:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::And);
- case Instruction::Opcode::Or:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Or);
- case Instruction::Opcode::Xor:
- return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Xor);
- default:
- llvm_unreachable("Not a binary op!");
- }
-}
-Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt == WhereBB->end())
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- else
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- llvm::Value *NewV =
- Builder.CreateBinOp(getLLVMBinaryOp(Op), LHS->Val, RHS->Val, Name);
- if (auto *NewBinOp = dyn_cast<llvm::BinaryOperator>(NewV))
- return Ctx.createBinaryOperator(NewBinOp);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- return create(Op, LHS, RHS, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, Name);
-}
-
-Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- return create(Op, LHS, RHS, InsertAtEnd->end(), InsertAtEnd, Ctx, Name);
-}
-
-Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
- Value *RHS, Value *CopyFrom,
- BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
-
- Value *NewV = create(Op, LHS, RHS, WhereIt, WhereBB, Ctx, Name);
- if (auto *NewBO = dyn_cast<BinaryOperator>(NewV))
- cast<llvm::BinaryOperator>(NewBO->Val)->copyIRFlags(CopyFrom->Val);
- return NewV;
-}
-
-Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
- Value *RHS, Value *CopyFrom,
- Instruction *InsertBefore,
- Context &Ctx, const Twine &Name) {
- return createWithCopiedFlags(Op, LHS, RHS, CopyFrom,
- InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, Name);
-}
-
-Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS,
- Value *RHS, Value *CopyFrom,
- BasicBlock *InsertAtEnd,
- Context &Ctx, const Twine &Name) {
- return createWithCopiedFlags(Op, LHS, RHS, CopyFrom, InsertAtEnd->end(),
- InsertAtEnd, Ctx, Name);
-}
-
-void PossiblyDisjointInst::setIsDisjoint(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&PossiblyDisjointInst::isDisjoint,
- &PossiblyDisjointInst::setIsDisjoint>>(
- this);
- cast<llvm::PossiblyDisjointInst>(Val)->setIsDisjoint(B);
-}
-
-void AtomicRMWInst::setAlignment(Align Align) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getAlign,
- &AtomicRMWInst::setAlignment>>(this);
- cast<llvm::AtomicRMWInst>(Val)->setAlignment(Align);
-}
-
-void AtomicRMWInst::setVolatile(bool V) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicRMWInst::isVolatile,
- &AtomicRMWInst::setVolatile>>(this);
- cast<llvm::AtomicRMWInst>(Val)->setVolatile(V);
-}
-
-void AtomicRMWInst::setOrdering(AtomicOrdering Ordering) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getOrdering,
- &AtomicRMWInst::setOrdering>>(this);
- cast<llvm::AtomicRMWInst>(Val)->setOrdering(Ordering);
-}
-
-void AtomicRMWInst::setSyncScopeID(SyncScope::ID SSID) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getSyncScopeID,
- &AtomicRMWInst::setSyncScopeID>>(this);
- cast<llvm::AtomicRMWInst>(Val)->setSyncScopeID(SSID);
-}
-
-Value *AtomicRMWInst::getPointerOperand() {
- return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getPointerOperand());
-}
-
-Value *AtomicRMWInst::getValOperand() {
- return Ctx.getValue(cast<llvm::AtomicRMWInst>(Val)->getValOperand());
-}
-
-AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
- MaybeAlign Align, AtomicOrdering Ordering,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, SyncScope::ID SSID,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt == WhereBB->end())
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- else
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- auto *LLVMAtomicRMW =
- Builder.CreateAtomicRMW(Op, Ptr->Val, Val->Val, Align, Ordering, SSID);
- LLVMAtomicRMW->setName(Name);
- return Ctx.createAtomicRMWInst(LLVMAtomicRMW);
-}
-
-AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
- MaybeAlign Align, AtomicOrdering Ordering,
- Instruction *InsertBefore, Context &Ctx,
- SyncScope::ID SSID, const Twine &Name) {
- return create(Op, Ptr, Val, Align, Ordering, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, SSID, Name);
-}
-
-AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val,
- MaybeAlign Align, AtomicOrdering Ordering,
- BasicBlock *InsertAtEnd, Context &Ctx,
- SyncScope::ID SSID, const Twine &Name) {
- return create(Op, Ptr, Val, Align, Ordering, InsertAtEnd->end(), InsertAtEnd,
- Ctx, SSID, Name);
-}
-
-void AtomicCmpXchgInst::setSyncScopeID(SyncScope::ID SSID) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSyncScopeID,
- &AtomicCmpXchgInst::setSyncScopeID>>(
- this);
- cast<llvm::AtomicCmpXchgInst>(Val)->setSyncScopeID(SSID);
-}
-
-Value *AtomicCmpXchgInst::getPointerOperand() {
- return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getPointerOperand());
-}
-
-Value *AtomicCmpXchgInst::getCompareOperand() {
- return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getCompareOperand());
-}
-
-Value *AtomicCmpXchgInst::getNewValOperand() {
- return Ctx.getValue(cast<llvm::AtomicCmpXchgInst>(Val)->getNewValOperand());
-}
-
-AtomicCmpXchgInst *
-AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align,
- AtomicOrdering SuccessOrdering,
- AtomicOrdering FailureOrdering, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx, SyncScope::ID SSID,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt == WhereBB->end())
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- else
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- auto *LLVMAtomicCmpXchg =
- Builder.CreateAtomicCmpXchg(Ptr->Val, Cmp->Val, New->Val, Align,
- SuccessOrdering, FailureOrdering, SSID);
- LLVMAtomicCmpXchg->setName(Name);
- return Ctx.createAtomicCmpXchgInst(LLVMAtomicCmpXchg);
-}
-
-AtomicCmpXchgInst *AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New,
- MaybeAlign Align,
- AtomicOrdering SuccessOrdering,
- AtomicOrdering FailureOrdering,
- Instruction *InsertBefore,
- Context &Ctx, SyncScope::ID SSID,
- const Twine &Name) {
- return create(Ptr, Cmp, New, Align, SuccessOrdering, FailureOrdering,
- InsertBefore->getIterator(), InsertBefore->getParent(), Ctx,
- SSID, Name);
-}
-
-AtomicCmpXchgInst *AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New,
- MaybeAlign Align,
- AtomicOrdering SuccessOrdering,
- AtomicOrdering FailureOrdering,
- BasicBlock *InsertAtEnd,
- Context &Ctx, SyncScope::ID SSID,
- const Twine &Name) {
- return create(Ptr, Cmp, New, Align, SuccessOrdering, FailureOrdering,
- InsertAtEnd->end(), InsertAtEnd, Ctx, SSID, Name);
-}
-
-void AtomicCmpXchgInst::setAlignment(Align Align) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getAlign,
- &AtomicCmpXchgInst::setAlignment>>(this);
- cast<llvm::AtomicCmpXchgInst>(Val)->setAlignment(Align);
-}
-
-void AtomicCmpXchgInst::setVolatile(bool V) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isVolatile,
- &AtomicCmpXchgInst::setVolatile>>(this);
- cast<llvm::AtomicCmpXchgInst>(Val)->setVolatile(V);
-}
-
-void AtomicCmpXchgInst::setWeak(bool IsWeak) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isWeak,
- &AtomicCmpXchgInst::setWeak>>(this);
- cast<llvm::AtomicCmpXchgInst>(Val)->setWeak(IsWeak);
-}
-
-void AtomicCmpXchgInst::setSuccessOrdering(AtomicOrdering Ordering) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSuccessOrdering,
- &AtomicCmpXchgInst::setSuccessOrdering>>(
- this);
- cast<llvm::AtomicCmpXchgInst>(Val)->setSuccessOrdering(Ordering);
-}
-
-void AtomicCmpXchgInst::setFailureOrdering(AtomicOrdering Ordering) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getFailureOrdering,
- &AtomicCmpXchgInst::setFailureOrdering>>(
- this);
- cast<llvm::AtomicCmpXchgInst>(Val)->setFailureOrdering(Ordering);
-}
-
-AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
- BasicBlock *WhereBB, Context &Ctx,
- Value *ArraySize, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt == WhereBB->end())
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- else
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- auto *NewAlloca =
- Builder.CreateAlloca(Ty->LLVMTy, AddrSpace, ArraySize->Val, Name);
- return Ctx.createAllocaInst(NewAlloca);
-}
-
-AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
- Instruction *InsertBefore, Context &Ctx,
- Value *ArraySize, const Twine &Name) {
- return create(Ty, AddrSpace, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, ArraySize, Name);
-}
-
-AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
- BasicBlock *InsertAtEnd, Context &Ctx,
- Value *ArraySize, const Twine &Name) {
- return create(Ty, AddrSpace, InsertAtEnd->end(), InsertAtEnd, Ctx, ArraySize,
- Name);
-}
-
-Type *AllocaInst::getAllocatedType() const {
- return Ctx.getType(cast<llvm::AllocaInst>(Val)->getAllocatedType());
-}
-
-void AllocaInst::setAllocatedType(Type *Ty) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AllocaInst::getAllocatedType,
- &AllocaInst::setAllocatedType>>(this);
- cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty->LLVMTy);
-}
-
-void AllocaInst::setAlignment(Align Align) {
- Ctx.getTracker()
- .emplaceIfTracking<
- GenericSetter<&AllocaInst::getAlign, &AllocaInst::setAlignment>>(
- this);
- cast<llvm::AllocaInst>(Val)->setAlignment(Align);
-}
-
-void AllocaInst::setUsedWithInAlloca(bool V) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&AllocaInst::isUsedWithInAlloca,
- &AllocaInst::setUsedWithInAlloca>>(this);
- cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
-}
-
-Value *AllocaInst::getArraySize() {
- return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());
-}
-
-PointerType *AllocaInst::getType() const {
- return cast<PointerType>(Ctx.getType(cast<llvm::AllocaInst>(Val)->getType()));
-}
-
-Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
- BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
- const Twine &Name) {
- assert(getLLVMCastOp(Op) && "Opcode not suitable for CastInst!");
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt == WhereBB->end())
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- else
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- auto *NewV =
- Builder.CreateCast(getLLVMCastOp(Op), Operand->Val, DestTy->LLVMTy, Name);
- if (auto *NewCI = dyn_cast<llvm::CastInst>(NewV))
- return Ctx.createCastInst(NewCI);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- return create(DestTy, Op, Operand, InsertBefore->getIterator(),
- InsertBefore->getParent(), Ctx, Name);
-}
-
-Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- return create(DestTy, Op, Operand, InsertAtEnd->end(), InsertAtEnd, Ctx,
- Name);
-}
-
-bool CastInst::classof(const Value *From) {
- return From->getSubclassID() == ClassID::Cast;
-}
-
-Type *CastInst::getSrcTy() const {
- return Ctx.getType(cast<llvm::CastInst>(Val)->getSrcTy());
-}
-
-Type *CastInst::getDestTy() const {
- return Ctx.getType(cast<llvm::CastInst>(Val)->getDestTy());
-}
-
-void PossiblyNonNegInst::setNonNeg(bool B) {
- Ctx.getTracker()
- .emplaceIfTracking<GenericSetter<&PossiblyNonNegInst::hasNonNeg,
- &PossiblyNonNegInst::setNonNeg>>(this);
- cast<llvm::PossiblyNonNegInst>(Val)->setNonNeg(B);
-}
-
-Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
- llvm::Value *NewV =
- Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
- if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
- return Ctx.createInsertElementInst(NewInsert);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::Value *NewV =
- Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
- if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
- return Ctx.createInsertElementInst(NewInsert);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *ExtractElementInst::create(Value *Vec, Value *Idx,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
- llvm::Value *NewV = Builder.CreateExtractElement(Vec->Val, Idx->Val, Name);
- if (auto *NewExtract = dyn_cast<llvm::ExtractElementInst>(NewV))
- return Ctx.createExtractElementInst(NewExtract);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *ExtractElementInst::create(Value *Vec, Value *Idx,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::Value *NewV = Builder.CreateExtractElement(Vec->Val, Idx->Val, Name);
- if (auto *NewExtract = dyn_cast<llvm::ExtractElementInst>(NewV))
- return Ctx.createExtractElementInst(NewExtract);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
- llvm::Value *NewV =
- Builder.CreateShuffleVector(V1->Val, V2->Val, Mask->Val, Name);
- if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
- return Ctx.createShuffleVectorInst(NewShuffle);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::Value *NewV =
- Builder.CreateShuffleVector(V1->Val, V2->Val, Mask->Val, Name);
- if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
- return Ctx.createShuffleVectorInst(NewShuffle);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask,
- Instruction *InsertBefore, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
- llvm::Value *NewV = Builder.CreateShuffleVector(V1->Val, V2->Val, Mask, Name);
- if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
- return Ctx.createShuffleVectorInst(NewShuffle);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask,
- BasicBlock *InsertAtEnd, Context &Ctx,
- const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
- llvm::Value *NewV = Builder.CreateShuffleVector(V1->Val, V2->Val, Mask, Name);
- if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(NewV))
- return Ctx.createShuffleVectorInst(NewShuffle);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-void ShuffleVectorInst::setShuffleMask(ArrayRef<int> Mask) {
- Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);
- cast<llvm::ShuffleVectorInst>(Val)->setShuffleMask(Mask);
-}
-
-VectorType *ShuffleVectorInst::getType() const {
- return cast<VectorType>(
- Ctx.getType(cast<llvm::ShuffleVectorInst>(Val)->getType()));
-}
-
-void ShuffleVectorInst::commute() {
- Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(this);
- Ctx.getTracker().emplaceIfTracking<UseSwap>(getOperandUse(0),
- getOperandUse(1));
- cast<llvm::ShuffleVectorInst>(Val)->commute();
-}
-
-Constant *ShuffleVectorInst::getShuffleMaskForBitcode() const {
- return Ctx.getOrCreateConstant(
- cast<llvm::ShuffleVectorInst>(Val)->getShuffleMaskForBitcode());
-}
-
-Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(ArrayRef<int> Mask,
- Type *ResultTy) {
- return ResultTy->getContext().getOrCreateConstant(
- llvm::ShuffleVectorInst::convertShuffleMaskForBitcode(Mask,
- ResultTy->LLVMTy));
-}
-
-VectorType *ExtractElementInst::getVectorOperandType() const {
- return cast<VectorType>(Ctx.getType(getVectorOperand()->getType()->LLVMTy));
-}
-
-Value *ExtractValueInst::create(Value *Agg, ArrayRef<unsigned> Idxs,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::Value *NewV = Builder.CreateExtractValue(Agg->Val, Idxs, Name);
- if (auto *NewExtractValueInst = dyn_cast<llvm::ExtractValueInst>(NewV))
- return Ctx.createExtractValueInst(NewExtractValueInst);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-Type *ExtractValueInst::getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs) {
- auto *LLVMTy = llvm::ExtractValueInst::getIndexedType(Agg->LLVMTy, Idxs);
- return Agg->getContext().getType(LLVMTy);
-}
-
-Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
- BBIterator WhereIt, BasicBlock *WhereBB,
- Context &Ctx, const Twine &Name) {
- auto &Builder = Ctx.getLLVMIRBuilder();
- if (WhereIt != WhereBB->end())
- Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
- else
- Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
- llvm::Value *NewV = Builder.CreateInsertValue(Agg->Val, Val->Val, Idxs, Name);
- if (auto *NewInsertValueInst = dyn_cast<llvm::InsertValueInst>(NewV))
- return Ctx.createInsertValueInst(NewInsertValueInst);
- assert(isa<llvm::Constant>(NewV) && "Expected constant");
- return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
-}
-
-ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) {
- auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx);
- return cast<ConstantTokenNone>(Ctx.getOrCreateConstant(LLVMC));
-}
diff --git a/llvm/lib/SandboxIR/Tracker.cpp b/llvm/lib/SandboxIR/Tracker.cpp
index b1f472d7928f4a..abcad39330094d 100644
--- a/llvm/lib/SandboxIR/Tracker.cpp
+++ b/llvm/lib/SandboxIR/Tracker.cpp
@@ -10,7 +10,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instruction.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
#include <sstream>
using namespace llvm::sandboxir;
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
index 0c44d05f0474d5..7ebbcabb004df7 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
@@ -8,6 +8,7 @@
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/SandboxIR/Instruction.h"
using namespace llvm::sandboxir;
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index da5416395ec42f..5823f4e14a8542 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -11,7 +11,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
#include "llvm/Support/SourceMgr.h"
#include "gmock/gmock-matchers.h"
#include "gtest/gtest.h"
diff --git a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp
index a136be41ae363b..89255a108ed6cb 100644
--- a/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp
@@ -8,7 +8,7 @@
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
#include "llvm/AsmParser/Parser.h"
-#include "llvm/SandboxIR/SandboxIR.h"
+#include "llvm/SandboxIR/Instruction.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
More information about the llvm-commits
mailing list