Skip to content

Commit 66d8735

Browse files
authored
[SandboxIR] Implement the InsertElementInst class (#102404)
Heavily based on work by @vporpo.
1 parent a21cf56 commit 66d8735

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class Context;
111111
class Function;
112112
class Instruction;
113113
class SelectInst;
114+
class InsertElementInst;
114115
class BranchInst;
115116
class UnaryInstruction;
116117
class LoadInst;
@@ -235,6 +236,7 @@ class Value {
235236
friend class User; // For getting `Val`.
236237
friend class Use; // For getting `Val`.
237238
friend class SelectInst; // For getting `Val`.
239+
friend class InsertElementInst; // For getting `Val`.
238240
friend class BranchInst; // For getting `Val`.
239241
friend class LoadInst; // For getting `Val`.
240242
friend class StoreInst; // For getting `Val`.
@@ -631,6 +633,7 @@ class Instruction : public sandboxir::User {
631633
/// returns its topmost LLVM IR instruction.
632634
llvm::Instruction *getTopmostLLVMInstruction() const;
633635
friend class SelectInst; // For getTopmostLLVMInstruction().
636+
friend class InsertElementInst; // For getTopmostLLVMInstruction().
634637
friend class BranchInst; // For getTopmostLLVMInstruction().
635638
friend class LoadInst; // For getTopmostLLVMInstruction().
636639
friend class StoreInst; // For getTopmostLLVMInstruction().
@@ -753,6 +756,52 @@ class SelectInst : public Instruction {
753756
#endif
754757
};
755758

759+
class InsertElementInst final : public Instruction {
760+
/// Use Context::createInsertElementInst() instead.
761+
InsertElementInst(llvm::Instruction *I, Context &Ctx)
762+
: Instruction(ClassID::InsertElement, Opcode::InsertElement, I, Ctx) {}
763+
friend class Context; // For accessing the constructor in
764+
// create*()
765+
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
766+
return getOperandUseDefault(OpIdx, Verify);
767+
}
768+
SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
769+
return {cast<llvm::Instruction>(Val)};
770+
}
771+
772+
public:
773+
static Value *create(Value *Vec, Value *NewElt, Value *Idx,
774+
Instruction *InsertBefore, Context &Ctx,
775+
const Twine &Name = "");
776+
static Value *create(Value *Vec, Value *NewElt, Value *Idx,
777+
BasicBlock *InsertAtEnd, Context &Ctx,
778+
const Twine &Name = "");
779+
static bool classof(const Value *From) {
780+
return From->getSubclassID() == ClassID::InsertElement;
781+
}
782+
static bool isValidOperands(const Value *Vec, const Value *NewElt,
783+
const Value *Idx) {
784+
return llvm::InsertElementInst::isValidOperands(Vec->Val, NewElt->Val,
785+
Idx->Val);
786+
}
787+
unsigned getUseOperandNo(const Use &Use) const final {
788+
return getUseOperandNoDefault(Use);
789+
}
790+
unsigned getNumOfIRInstrs() const final { return 1u; }
791+
#ifndef NDEBUG
792+
void verify() const final {
793+
assert(isa<llvm::InsertElementInst>(Val) && "Expected InsertElementInst");
794+
}
795+
friend raw_ostream &operator<<(raw_ostream &OS,
796+
const InsertElementInst &IEI) {
797+
IEI.dump(OS);
798+
return OS;
799+
}
800+
void dump(raw_ostream &OS) const override;
801+
LLVM_DUMP_METHOD void dump() const override;
802+
#endif
803+
};
804+
756805
class BranchInst : public Instruction {
757806
/// Use Context::createBranchInst(). Don't call the constructor directly.
758807
BranchInst(llvm::BranchInst *BI, Context &Ctx)
@@ -1845,6 +1894,8 @@ class Context {
18451894

18461895
SelectInst *createSelectInst(llvm::SelectInst *SI);
18471896
friend SelectInst; // For createSelectInst()
1897+
InsertElementInst *createInsertElementInst(llvm::InsertElementInst *IEI);
1898+
friend InsertElementInst; // For createInsertElementInst()
18481899
BranchInst *createBranchInst(llvm::BranchInst *I);
18491900
friend BranchInst; // For createBranchInst()
18501901
LoadInst *createLoadInst(llvm::LoadInst *LI);

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ DEF_USER(Constant, Constant)
3434
// clang-format off
3535
// ClassID, Opcode(s), Class
3636
DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
37+
DEF_INSTR(InsertElement, OP(InsertElement), InsertElementInst)
3738
DEF_INSTR(Select, OP(Select), SelectInst)
3839
DEF_INSTR(Br, OP(Br), BranchInst)
3940
DEF_INSTR(Load, OP(Load), LoadInst)

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,44 @@ void OpaqueInst::dump() const {
14191419
}
14201420
#endif // NDEBUG
14211421

1422+
Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
1423+
Instruction *InsertBefore, Context &Ctx,
1424+
const Twine &Name) {
1425+
auto &Builder = Ctx.getLLVMIRBuilder();
1426+
Builder.SetInsertPoint(InsertBefore->getTopmostLLVMInstruction());
1427+
llvm::Value *NewV =
1428+
Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
1429+
if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
1430+
return Ctx.createInsertElementInst(NewInsert);
1431+
assert(isa<llvm::Constant>(NewV) && "Expected constant");
1432+
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
1433+
}
1434+
1435+
Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx,
1436+
BasicBlock *InsertAtEnd, Context &Ctx,
1437+
const Twine &Name) {
1438+
auto &Builder = Ctx.getLLVMIRBuilder();
1439+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
1440+
llvm::Value *NewV =
1441+
Builder.CreateInsertElement(Vec->Val, NewElt->Val, Idx->Val, Name);
1442+
if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(NewV))
1443+
return Ctx.createInsertElementInst(NewInsert);
1444+
assert(isa<llvm::Constant>(NewV) && "Expected constant");
1445+
return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
1446+
}
1447+
1448+
#ifndef NDEBUG
1449+
void InsertElementInst::dump(raw_ostream &OS) const {
1450+
dumpCommonPrefix(OS);
1451+
dumpCommonSuffix(OS);
1452+
}
1453+
1454+
void InsertElementInst::dump() const {
1455+
dump(dbgs());
1456+
dbgs() << "\n";
1457+
}
1458+
#endif // NDEBUG
1459+
14221460
Constant *Constant::createInt(Type *Ty, uint64_t V, Context &Ctx,
14231461
bool IsSigned) {
14241462
llvm::Constant *LLVMC = llvm::ConstantInt::get(Ty, V, IsSigned);
@@ -1551,6 +1589,12 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
15511589
It->second = std::unique_ptr<SelectInst>(new SelectInst(LLVMSel, *this));
15521590
return It->second.get();
15531591
}
1592+
case llvm::Instruction::InsertElement: {
1593+
auto *LLVMIns = cast<llvm::InsertElementInst>(LLVMV);
1594+
It->second = std::unique_ptr<InsertElementInst>(
1595+
new InsertElementInst(LLVMIns, *this));
1596+
return It->second.get();
1597+
}
15541598
case llvm::Instruction::Br: {
15551599
auto *LLVMBr = cast<llvm::BranchInst>(LLVMV);
15561600
It->second = std::unique_ptr<BranchInst>(new BranchInst(LLVMBr, *this));
@@ -1648,6 +1692,13 @@ SelectInst *Context::createSelectInst(llvm::SelectInst *SI) {
16481692
return cast<SelectInst>(registerValue(std::move(NewPtr)));
16491693
}
16501694

1695+
InsertElementInst *
1696+
Context::createInsertElementInst(llvm::InsertElementInst *IEI) {
1697+
auto NewPtr =
1698+
std::unique_ptr<InsertElementInst>(new InsertElementInst(IEI, *this));
1699+
return cast<InsertElementInst>(registerValue(std::move(NewPtr)));
1700+
}
1701+
16511702
BranchInst *Context::createBranchInst(llvm::BranchInst *BI) {
16521703
auto NewPtr = std::unique_ptr<BranchInst>(new BranchInst(BI, *this));
16531704
return cast<BranchInst>(registerValue(std::move(NewPtr)));

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/SandboxIR/SandboxIR.h"
1010
#include "llvm/AsmParser/Parser.h"
1111
#include "llvm/IR/BasicBlock.h"
12+
#include "llvm/IR/Constants.h"
1213
#include "llvm/IR/DataLayout.h"
1314
#include "llvm/IR/Function.h"
1415
#include "llvm/IR/Instruction.h"
@@ -630,6 +631,55 @@ define void @foo(i1 %c0, i8 %v0, i8 %v1, i1 %c1) {
630631
}
631632
}
632633

634+
TEST_F(SandboxIRTest, InsertElementInst) {
635+
parseIR(C, R"IR(
636+
define void @foo(i8 %v0, i8 %v1, <2 x i8> %vec) {
637+
%ins0 = insertelement <2 x i8> poison, i8 %v0, i32 0
638+
%ins1 = insertelement <2 x i8> %ins0, i8 %v1, i32 1
639+
ret void
640+
}
641+
)IR");
642+
Function &LLVMF = *M->getFunction("foo");
643+
sandboxir::Context Ctx(C);
644+
auto &F = *Ctx.createFunction(&LLVMF);
645+
auto *Arg0 = F.getArg(0);
646+
auto *Arg1 = F.getArg(1);
647+
auto *ArgVec = F.getArg(2);
648+
auto *BB = &*F.begin();
649+
auto It = BB->begin();
650+
auto *Ins0 = cast<sandboxir::InsertElementInst>(&*It++);
651+
auto *Ins1 = cast<sandboxir::InsertElementInst>(&*It++);
652+
auto *Ret = &*It++;
653+
654+
EXPECT_EQ(Ins0->getOpcode(), sandboxir::Instruction::Opcode::InsertElement);
655+
EXPECT_EQ(Ins0->getOperand(1), Arg0);
656+
EXPECT_EQ(Ins1->getOperand(1), Arg1);
657+
EXPECT_EQ(Ins1->getOperand(0), Ins0);
658+
auto *Poison = Ins0->getOperand(0);
659+
auto *Idx = Ins0->getOperand(2);
660+
auto *NewI1 =
661+
cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create(
662+
Poison, Arg0, Idx, Ret, Ctx, "NewIns1"));
663+
EXPECT_EQ(NewI1->getOperand(0), Poison);
664+
EXPECT_EQ(NewI1->getNextNode(), Ret);
665+
666+
auto *NewI2 =
667+
cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create(
668+
Poison, Arg0, Idx, BB, Ctx, "NewIns2"));
669+
EXPECT_EQ(NewI2->getPrevNode(), Ret);
670+
671+
auto *LLVMArg0 = LLVMF.getArg(0);
672+
auto *LLVMArgVec = LLVMF.getArg(2);
673+
auto *Zero = sandboxir::Constant::createInt(Type::getInt8Ty(C), 0, Ctx);
674+
auto *LLVMZero = llvm::ConstantInt::get(Type::getInt8Ty(C), 0);
675+
EXPECT_EQ(
676+
sandboxir::InsertElementInst::isValidOperands(ArgVec, Arg0, Zero),
677+
llvm::InsertElementInst::isValidOperands(LLVMArgVec, LLVMArg0, LLVMZero));
678+
EXPECT_EQ(
679+
sandboxir::InsertElementInst::isValidOperands(Arg0, ArgVec, Zero),
680+
llvm::InsertElementInst::isValidOperands(LLVMArg0, LLVMArgVec, LLVMZero));
681+
}
682+
633683
TEST_F(SandboxIRTest, BranchInst) {
634684
parseIR(C, R"IR(
635685
define void @foo(i1 %cond0, i1 %cond2) {

0 commit comments

Comments
 (0)