[llvm] [SandboxIR] Implement CastInst (PR #101097)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 29 15:47:39 PDT 2024
https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/101097
This patch implements sandboxir::CastInst which mirrors llvm::CastInst.
Just like in llvm::CastInst there are multiple opcodes that correspond to a CastInst, like ZExt, FPToUI etc. These are implemented in follow-up patches.
>From ff9a077e3061a4acc1c8d1e510cf157167b0403c Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 25 Jul 2024 13:05:31 -0700
Subject: [PATCH] [SandboxIR] Implement CastInst.
This patch implements sandboxir::CastInst which mirrors llvm::CastInst.
---
llvm/include/llvm/SandboxIR/SandboxIR.h | 81 ++++++++-
.../llvm/SandboxIR/SandboxIRValues.def | 49 ++++--
llvm/lib/SandboxIR/SandboxIR.cpp | 106 +++++++++++-
llvm/unittests/SandboxIR/SandboxIRTest.cpp | 161 ++++++++++++++++++
4 files changed, 382 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index bca6037bd994b..a56204769fd47 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -94,6 +94,7 @@ class CallInst;
class InvokeInst;
class CallBrInst;
class GetElementPtrInst;
+class CastInst;
/// Iterator for the `Use` edges of a User's operands.
/// \Returns the operand `Use` when dereferenced.
@@ -210,6 +211,7 @@ class Value {
friend class InvokeInst; // For getting `Val`.
friend class CallBrInst; // For getting `Val`.
friend class GetElementPtrInst; // For getting `Val`.
+ friend class CastInst; // For getting `Val`.
/// All values point to the context.
Context &Ctx;
@@ -525,9 +527,8 @@ class BBIterator {
class Instruction : public sandboxir::User {
public:
enum class Opcode {
-#define DEF_VALUE(ID, CLASS)
-#define DEF_USER(ID, CLASS)
#define OP(OPC) OPC,
+#define OPCODES(...) __VA_ARGS__
#define DEF_INSTR(ID, OPC, CLASS) OPC
#include "llvm/SandboxIR/SandboxIRValues.def"
};
@@ -551,6 +552,7 @@ class Instruction : public sandboxir::User {
friend class InvokeInst; // For getTopmostLLVMInstruction().
friend class CallBrInst; // For getTopmostLLVMInstruction().
friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
+ friend class CastInst; // For getTopmostLLVMInstruction().
/// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
/// order.
@@ -1282,6 +1284,79 @@ class GetElementPtrInst final : public Instruction {
#endif
};
+class CastInst : public Instruction {
+ 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)
+ : Instruction(ClassID::Cast, getCastOpcode(CI->getOpcode()), CI, Ctx) {}
+ friend Context; // for SBCastInstruction()
+ 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; }
+ 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 { return cast<llvm::CastInst>(Val)->getSrcTy(); }
+ Type *getDestTy() const { return cast<llvm::CastInst>(Val)->getDestTy(); }
+#ifndef NDEBUG
+ void verify() const final {
+ assert(isa<llvm::CastInst>(Val) && "Expected CastInst!");
+ }
+ void dump(raw_ostream &OS) const override;
+ LLVM_DUMP_METHOD void dump() const override;
+#endif
+};
+
/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
/// an OpaqueInstr.
class OpaqueInst : public sandboxir::Instruction {
@@ -1438,6 +1513,8 @@ class Context {
friend CallBrInst; // For createCallBrInst()
GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I);
friend GetElementPtrInst; // For createGetElementPtrInst()
+ CastInst *createCastInst(llvm::CastInst *I);
+ friend CastInst; // For createCastInst()
public:
Context(LLVMContext &LLVMCtx)
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index 29fb3aa396fdb..243ce6b2c60a9 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -23,18 +23,42 @@ DEF_USER(Constant, Constant)
#ifndef DEF_INSTR
#define DEF_INSTR(ID, OPCODE, CLASS)
#endif
-// ClassID, Opcode(s), Class
-DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
-DEF_INSTR(Select, OP(Select), SelectInst)
-DEF_INSTR(Br, OP(Br), BranchInst)
-DEF_INSTR(Load, OP(Load), LoadInst)
-DEF_INSTR(Store, OP(Store), StoreInst)
-DEF_INSTR(Ret, OP(Ret), ReturnInst)
-DEF_INSTR(Call, OP(Call), CallInst)
-DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
-DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
-DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
+#ifndef OP
+#define OP(OPCODE)
+#endif
+
+#ifndef OPCODES
+#define OPCODES(...)
+#endif
+// clang-format off
+// ClassID, Opcode(s), Class
+DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
+DEF_INSTR(Select, OP(Select), SelectInst)
+DEF_INSTR(Br, OP(Br), BranchInst)
+DEF_INSTR(Load, OP(Load), LoadInst)
+DEF_INSTR(Store, OP(Store), StoreInst)
+DEF_INSTR(Ret, OP(Ret), ReturnInst)
+DEF_INSTR(Call, OP(Call), CallInst)
+DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
+DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
+DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
+DEF_INSTR(Cast, OPCODES(\
+ OP(ZExt) \
+ OP(SExt) \
+ OP(FPToUI) \
+ OP(FPToSI) \
+ OP(FPExt) \
+ OP(PtrToInt) \
+ OP(IntToPtr) \
+ OP(SIToFP) \
+ OP(UIToFP) \
+ OP(Trunc) \
+ OP(FPTrunc) \
+ OP(BitCast) \
+ OP(AddrSpaceCast) \
+ ), CastInst)
+// clang-format on
#ifdef DEF_VALUE
#undef DEF_VALUE
#endif
@@ -47,3 +71,6 @@ DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
#ifdef OP
#undef OP
#endif
+#ifdef OPCODES
+#undef OPCODES
+#endif
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 7ed3e24e247be..3d3fe9d181c12 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -313,11 +313,10 @@ BBIterator &BBIterator::operator--() {
const char *Instruction::getOpcodeName(Opcode Opc) {
switch (Opc) {
-#define DEF_VALUE(ID, CLASS)
-#define DEF_USER(ID, CLASS)
#define OP(OPC) \
case Opcode::OPC: \
return #OPC;
+#define OPCODES(...) __VA_ARGS__
#define DEF_INSTR(ID, OPC, CLASS) OPC
#include "llvm/SandboxIR/SandboxIRValues.def"
}
@@ -1050,6 +1049,87 @@ void GetElementPtrInst::dump() const {
dump(dbgs());
dbgs() << "\n";
}
+#endif // NDEBUG
+
+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!");
+ }
+}
+
+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, 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;
+}
+
+#ifndef NDEBUG
+void CastInst::dump(raw_ostream &OS) const {
+ dumpCommonPrefix(OS);
+ dumpCommonSuffix(OS);
+}
+
+void CastInst::dump() const {
+ dump(dbgs());
+ dbgs() << "\n";
+}
void OpaqueInst::dump(raw_ostream &OS) const {
dumpCommonPrefix(OS);
@@ -1225,6 +1305,23 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
new GetElementPtrInst(LLVMGEP, *this));
return It->second.get();
}
+ case llvm::Instruction::ZExt:
+ case llvm::Instruction::SExt:
+ case llvm::Instruction::FPToUI:
+ case llvm::Instruction::FPToSI:
+ case llvm::Instruction::FPExt:
+ case llvm::Instruction::PtrToInt:
+ case llvm::Instruction::IntToPtr:
+ case llvm::Instruction::SIToFP:
+ case llvm::Instruction::UIToFP:
+ case llvm::Instruction::Trunc:
+ case llvm::Instruction::FPTrunc:
+ case llvm::Instruction::BitCast:
+ case llvm::Instruction::AddrSpaceCast: {
+ auto *LLVMCast = cast<llvm::CastInst>(LLVMV);
+ It->second = std::unique_ptr<CastInst>(new CastInst(LLVMCast, *this));
+ return It->second.get();
+ }
default:
break;
}
@@ -1290,6 +1387,11 @@ Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
return cast<GetElementPtrInst>(registerValue(std::move(NewPtr)));
}
+CastInst *Context::createCastInst(llvm::CastInst *I) {
+ auto NewPtr = std::unique_ptr<CastInst>(new CastInst(I, *this));
+ return cast<CastInst>(registerValue(std::move(NewPtr)));
+}
+
Value *Context::getValue(llvm::Value *V) const {
auto It = LLVMValueToValueMap.find(V);
if (It != LLVMValueToValueMap.end())
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 56e906744a9ca..cd17c1eb8e90a 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1413,3 +1413,164 @@ define void @foo(ptr %ptr, <2 x ptr> %ptrs) {
EXPECT_EQ(NewGEP2->getPrevNode(), Ret);
EXPECT_EQ(NewGEP2->getNextNode(), nullptr);
}
+
+TEST_F(SandboxIRTest, CastInst) {
+ parseIR(C, R"IR(
+define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) {
+ %zext = zext i32 %arg to i64
+ %sext = sext i32 %arg to i64
+ %fptoui = fptoui float %farg to i32
+ %fptosi = fptosi float %farg to i32
+ %fpext = fpext float %farg to double
+ %ptrtoint = ptrtoint ptr %ptr to i32
+ %inttoptr = inttoptr i32 %arg to ptr
+ %sitofp = sitofp i32 %arg to float
+ %uitofp = uitofp i32 %arg to float
+ %trunc = trunc i32 %arg to i16
+ %fptrunc = fptrunc double %darg to float
+ %bitcast = bitcast i32 %arg to float
+ %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1)
+ ret void
+}
+)IR");
+ Function &LLVMF = *M->getFunction("foo");
+ sandboxir::Context Ctx(C);
+ sandboxir::Function *F = Ctx.createFunction(&LLVMF);
+ unsigned ArgIdx = 0;
+ auto *Arg = F->getArg(ArgIdx++);
+ auto *BB = &*F->begin();
+ auto It = BB->begin();
+
+ Type *Ti64 = Type::getInt64Ty(C);
+ Type *Ti32 = Type::getInt32Ty(C);
+ Type *Ti16 = Type::getInt16Ty(C);
+ Type *Tdouble = Type::getDoubleTy(C);
+ Type *Tfloat = Type::getFloatTy(C);
+ Type *Tptr = Tfloat->getPointerTo();
+ Type *Tptr1 = Tfloat->getPointerTo(1);
+
+ // Check classof(), getOpcode(), getSrcTy(), getDstTy()
+ auto *ZExt = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(ZExt->getOpcode(), sandboxir::Instruction::Opcode::ZExt);
+ EXPECT_EQ(ZExt->getSrcTy(), Ti32);
+ EXPECT_EQ(ZExt->getDestTy(), Ti64);
+
+ auto *SExt = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(SExt->getOpcode(), sandboxir::Instruction::Opcode::SExt);
+ EXPECT_EQ(SExt->getSrcTy(), Ti32);
+ EXPECT_EQ(SExt->getDestTy(), Ti64);
+
+ auto *FPToUI = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(FPToUI->getOpcode(), sandboxir::Instruction::Opcode::FPToUI);
+ EXPECT_EQ(FPToUI->getSrcTy(), Tfloat);
+ EXPECT_EQ(FPToUI->getDestTy(), Ti32);
+
+ auto *FPToSI = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(FPToSI->getOpcode(), sandboxir::Instruction::Opcode::FPToSI);
+ EXPECT_EQ(FPToSI->getSrcTy(), Tfloat);
+ EXPECT_EQ(FPToSI->getDestTy(), Ti32);
+
+ auto *FPExt = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(FPExt->getOpcode(), sandboxir::Instruction::Opcode::FPExt);
+ EXPECT_EQ(FPExt->getSrcTy(), Tfloat);
+ EXPECT_EQ(FPExt->getDestTy(), Tdouble);
+
+ auto *PtrToInt = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(PtrToInt->getOpcode(), sandboxir::Instruction::Opcode::PtrToInt);
+ EXPECT_EQ(PtrToInt->getSrcTy(), Tptr);
+ EXPECT_EQ(PtrToInt->getDestTy(), Ti32);
+
+ auto *IntToPtr = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(IntToPtr->getOpcode(), sandboxir::Instruction::Opcode::IntToPtr);
+ EXPECT_EQ(IntToPtr->getSrcTy(), Ti32);
+ EXPECT_EQ(IntToPtr->getDestTy(), Tptr);
+
+ auto *SIToFP = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(SIToFP->getOpcode(), sandboxir::Instruction::Opcode::SIToFP);
+ EXPECT_EQ(SIToFP->getSrcTy(), Ti32);
+ EXPECT_EQ(SIToFP->getDestTy(), Tfloat);
+
+ auto *UIToFP = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(UIToFP->getOpcode(), sandboxir::Instruction::Opcode::UIToFP);
+ EXPECT_EQ(UIToFP->getSrcTy(), Ti32);
+ EXPECT_EQ(UIToFP->getDestTy(), Tfloat);
+
+ auto *Trunc = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(Trunc->getOpcode(), sandboxir::Instruction::Opcode::Trunc);
+ EXPECT_EQ(Trunc->getSrcTy(), Ti32);
+ EXPECT_EQ(Trunc->getDestTy(), Ti16);
+
+ auto *FPTrunc = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(FPTrunc->getOpcode(), sandboxir::Instruction::Opcode::FPTrunc);
+ EXPECT_EQ(FPTrunc->getSrcTy(), Tdouble);
+ EXPECT_EQ(FPTrunc->getDestTy(), Tfloat);
+
+ auto *BitCast = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(BitCast->getOpcode(), sandboxir::Instruction::Opcode::BitCast);
+ EXPECT_EQ(BitCast->getSrcTy(), Ti32);
+ EXPECT_EQ(BitCast->getDestTy(), Tfloat);
+
+ auto *AddrSpaceCast = cast<sandboxir::CastInst>(&*It++);
+ EXPECT_EQ(AddrSpaceCast->getOpcode(),
+ sandboxir::Instruction::Opcode::AddrSpaceCast);
+ EXPECT_EQ(AddrSpaceCast->getSrcTy(), Tptr);
+ EXPECT_EQ(AddrSpaceCast->getDestTy(), Tptr1);
+
+ auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
+
+ {
+ // Check create() WhereIt, WhereBB
+ auto *NewI = cast<sandboxir::CastInst>(sandboxir::CastInst::create(
+ Ti64, sandboxir::Instruction::Opcode::SExt, Arg, /*WhereIt=*/BB->end(),
+ /*WhereBB=*/BB, Ctx, "SExt"));
+ // Check getOpcode().
+ EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::SExt);
+ // Check getSrcTy().
+ EXPECT_EQ(NewI->getSrcTy(), Arg->getType());
+ // Check getDestTy().
+ EXPECT_EQ(NewI->getDestTy(), Ti64);
+ // Check instr position.
+ EXPECT_EQ(NewI->getNextNode(), nullptr);
+ EXPECT_EQ(NewI->getPrevNode(), Ret);
+ }
+
+ {
+ // Check create() InsertBefore.
+ auto *NewI = cast<sandboxir::CastInst>(
+ sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::ZExt,
+ Arg, /*InsertBefore=*/Ret, Ctx, "ZExt"));
+ // Check getOpcode().
+ EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::ZExt);
+ // Check getSrcTy().
+ EXPECT_EQ(NewI->getSrcTy(), Arg->getType());
+ // Check getDestTy().
+ EXPECT_EQ(NewI->getDestTy(), Ti64);
+ // Check instr position.
+ EXPECT_EQ(NewI->getNextNode(), Ret);
+ }
+ {
+ // Check create() InsertAtEnd.
+ auto *NewI = cast<sandboxir::CastInst>(
+ sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::ZExt,
+ Arg, /*InsertAtEnd=*/BB, Ctx, "ZExt"));
+ // Check getOpcode().
+ EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::ZExt);
+ // Check getSrcTy().
+ EXPECT_EQ(NewI->getSrcTy(), Arg->getType());
+ // Check getDestTy().
+ EXPECT_EQ(NewI->getDestTy(), Ti64);
+ // Check instr position.
+ EXPECT_EQ(NewI->getNextNode(), nullptr);
+ EXPECT_EQ(NewI->getParent(), BB);
+ }
+
+ {
+#ifndef NDEBUG
+ // Check that passing a non-cast opcode crashes.
+ EXPECT_DEATH(
+ sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::Store,
+ Arg, /*InsertBefore=*/Ret, Ctx, "Bad"),
+ ".*Opcode.*");
+#endif // NDEBUG
+ }
+}
More information about the llvm-commits
mailing list