-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[SandboxIR] Implement the InsertElementInst class #102404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
9e5a404
870e1e5
c77e88c
1aa4ad4
e1757cc
fb857ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -235,6 +235,7 @@ class Value { | |
friend class User; // For getting `Val`. | ||
friend class Use; // For getting `Val`. | ||
friend class SelectInst; // For getting `Val`. | ||
friend class InsertElementInst; // For getting `Val`. | ||
friend class BranchInst; // For getting `Val`. | ||
friend class LoadInst; // For getting `Val`. | ||
friend class StoreInst; // For getting `Val`. | ||
|
@@ -631,6 +632,7 @@ class Instruction : public sandboxir::User { | |
/// returns its topmost LLVM IR instruction. | ||
llvm::Instruction *getTopmostLLVMInstruction() const; | ||
friend class SelectInst; // For getTopmostLLVMInstruction(). | ||
friend class InsertElementInst; // For getTopmostLLVMInstruction(). | ||
friend class BranchInst; // For getTopmostLLVMInstruction(). | ||
friend class LoadInst; // For getTopmostLLVMInstruction(). | ||
friend class StoreInst; // For getTopmostLLVMInstruction(). | ||
|
@@ -753,6 +755,48 @@ class SelectInst : public Instruction { | |
#endif | ||
}; | ||
|
||
class InsertElementInst final : public Instruction { | ||
/// Use Context::createInsertElementInst(). Don't call | ||
/// the constructor directly. | ||
InsertElementInst(llvm::Instruction *I, Context &Ctx) | ||
: Instruction(ClassID::InsertElement, Opcode::InsertElement, I, Ctx) {} | ||
InsertElementInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx) | ||
slackito marked this conversation as resolved.
Show resolved
Hide resolved
|
||
: Instruction(SubclassID, Opcode::InsertElement, I, Ctx) {} | ||
friend class Context; // For accessing the constructor in | ||
// create*() | ||
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 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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you also add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, by calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you also add a test for this? Something like:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, following the other comment in the test. |
||
return From->getSubclassID() == ClassID::InsertElement; | ||
} | ||
unsigned getUseOperandNo(const Use &Use) const final { | ||
return getUseOperandNoDefault(Use); | ||
} | ||
unsigned getNumOfIRInstrs() const final { return 1u; } | ||
#ifndef NDEBUG | ||
void verify() const final {} | ||
slackito marked this conversation as resolved.
Show resolved
Hide resolved
|
||
friend raw_ostream &operator<<(raw_ostream &OS, | ||
const InsertElementInst &IEI) { | ||
IEI.dump(OS); | ||
return OS; | ||
} | ||
void dump(raw_ostream &OS) const override; | ||
LLVM_DUMP_METHOD void dump() const override; | ||
#endif | ||
}; | ||
|
||
class BranchInst : public Instruction { | ||
/// Use Context::createBranchInst(). Don't call the constructor directly. | ||
BranchInst(llvm::BranchInst *BI, Context &Ctx) | ||
|
@@ -1845,6 +1889,8 @@ class Context { | |
|
||
SelectInst *createSelectInst(llvm::SelectInst *SI); | ||
friend SelectInst; // For createSelectInst() | ||
InsertElementInst *createInsertElementInst(llvm::InsertElementInst *IEI); | ||
friend InsertElementInst; // For createInsertElementInst() | ||
BranchInst *createBranchInst(llvm::BranchInst *I); | ||
friend BranchInst; // For createBranchInst() | ||
LoadInst *createLoadInst(llvm::LoadInst *LI); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -630,6 +630,44 @@ define void @foo(i1 %c0, i8 %v0, i8 %v1, i1 %c1) { | |
} | ||
} | ||
|
||
TEST_F(SandboxIRTest, InsertElementInst) { | ||
parseIR(C, R"IR( | ||
define void @foo(i8 %v0, i8 %v1) { | ||
%ins0 = insertelement <2 x i8> poison, i8 %v0, i32 0 | ||
%ins1 = insertelement <2 x i8> %ins0, i8 %v1, i32 1 | ||
ret void | ||
} | ||
)IR"); | ||
Function &F = *M->getFunction("foo"); | ||
slackito marked this conversation as resolved.
Show resolved
Hide resolved
|
||
sandboxir::Context Ctx(C); | ||
auto &SBF = *Ctx.createFunction(&F); | ||
slackito marked this conversation as resolved.
Show resolved
Hide resolved
|
||
unsigned ArgIdx = 0; | ||
auto *Arg0 = SBF.getArg(ArgIdx++); | ||
auto *Arg1 = SBF.getArg(ArgIdx++); | ||
auto *SBB = &*SBF.begin(); | ||
auto It = SBB->begin(); | ||
auto *Ins0 = cast<sandboxir::InsertElementInst>(&*It++); | ||
auto *Ins1 = cast<sandboxir::InsertElementInst>(&*It++); | ||
auto *Ret = &*It++; | ||
|
||
EXPECT_EQ(Ins0->getOpcode(), sandboxir::Instruction::Opcode::InsertElement); | ||
EXPECT_EQ(Ins0->getOperand(1), Arg0); | ||
EXPECT_EQ(Ins1->getOperand(1), Arg1); | ||
EXPECT_EQ(Ins1->getOperand(0), Ins0); | ||
auto *Poison = Ins0->getOperand(0); | ||
auto *Idx = Ins0->getOperand(2); | ||
auto *NewI1 = | ||
cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create( | ||
Poison, Arg0, Idx, Ret, Ctx, "NewIns1")); | ||
EXPECT_EQ(NewI1->getOperand(0), Poison); | ||
EXPECT_EQ(NewI1->getNextNode(), Ret); | ||
|
||
auto *NewI2 = | ||
cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create( | ||
Poison, Arg0, Idx, SBB, Ctx, "NewIns2")); | ||
EXPECT_EQ(NewI2->getPrevNode(), Ret); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the Then we would need to get both the sandboxir and the llvm arguments:
Then:
Finally I would add a check like:
To make sure we exercise this even more we can also try swapping the arguments:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, with some slight variation. In particular, I've gotten rid of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's fine with me. The reason I prefer a variable is because as I am modifying the test I may add a new N'th argument. If I am using hard-coded numbers in |
||
|
||
TEST_F(SandboxIRTest, BranchInst) { | ||
parseIR(C, R"IR( | ||
define void @foo(i1 %cond0, i1 %cond2) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.