-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SandboxIR] Add InsertValueInst #106273
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
[SandboxIR] Add InsertValueInst #106273
Changes from all commits
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 |
---|---|---|
|
@@ -74,6 +74,8 @@ | |
// | | ||
// +- ShuffleVectorInst | ||
// | | ||
// +- InsertValueInst | ||
// | | ||
// +- StoreInst | ||
// | | ||
// +- UnaryInstruction -+- LoadInst | ||
|
@@ -117,6 +119,7 @@ class SelectInst; | |
class ExtractElementInst; | ||
class InsertElementInst; | ||
class ShuffleVectorInst; | ||
class InsertValueInst; | ||
class BranchInst; | ||
class UnaryInstruction; | ||
class LoadInst; | ||
|
@@ -260,6 +263,7 @@ class Value { | |
friend class ExtractElementInst; // For getting `Val`. | ||
friend class InsertElementInst; // For getting `Val`. | ||
friend class ShuffleVectorInst; // For getting `Val`. | ||
friend class InsertValueInst; // For getting `Val`. | ||
friend class BranchInst; // For getting `Val`. | ||
friend class LoadInst; // For getting `Val`. | ||
friend class StoreInst; // For getting `Val`. | ||
|
@@ -692,6 +696,7 @@ class Instruction : public sandboxir::User { | |
friend class ExtractElementInst; // For getTopmostLLVMInstruction(). | ||
friend class InsertElementInst; // For getTopmostLLVMInstruction(). | ||
friend class ShuffleVectorInst; // For getTopmostLLVMInstruction(). | ||
friend class InsertValueInst; // For getTopmostLLVMInstruction(). | ||
friend class BranchInst; // For getTopmostLLVMInstruction(). | ||
friend class LoadInst; // For getTopmostLLVMInstruction(). | ||
friend class StoreInst; // For getTopmostLLVMInstruction(). | ||
|
@@ -1451,6 +1456,67 @@ class ShuffleVectorInst final | |
} | ||
}; | ||
|
||
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; | ||
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. No
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. Hmm @slackito does the test pass without 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. 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. I wonder if there is a good way to check that classof has been implemented. Perhaps a test that uses the .def file and does something with 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. I wrote a small test that checks 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. Great! Can you commit that test (and the missing classof) separately from this PR? 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. Yes I will upload a PR in a few minutes. |
||
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) | ||
|
@@ -2999,6 +3065,8 @@ class Context { | |
friend ExtractElementInst; // For createExtractElementInst() | ||
ShuffleVectorInst *createShuffleVectorInst(llvm::ShuffleVectorInst *SVI); | ||
friend ShuffleVectorInst; // For createShuffleVectorInst() | ||
InsertValueInst *createInsertValueInst(llvm::InsertValueInst *IVI); | ||
friend InsertValueInst; // For createInsertValueInst() | ||
BranchInst *createBranchInst(llvm::BranchInst *I); | ||
friend BranchInst; // For createBranchInst() | ||
LoadInst *createLoadInst(llvm::LoadInst *LI); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1228,6 +1228,110 @@ define void @foo(<2 x i8> %v1, <2 x i8> %v2) { | |
} | ||
} | ||
|
||
TEST_F(SandboxIRTest, InsertValueInst) { | ||
parseIR(C, R"IR( | ||
define void @foo({i32, float} %agg, i32 %i) { | ||
%ins_simple = insertvalue {i32, float} %agg, i32 %i, 0 | ||
%ins_nested = insertvalue {float, {i32}} undef, i32 %i, 1, 0 | ||
%const1 = insertvalue {i32, float} {i32 99, float 99.0}, i32 %i, 0 | ||
%const2 = insertvalue {i32, float} {i32 0, float 99.0}, i32 %i, 0 | ||
ret void | ||
} | ||
)IR"); | ||
Function &LLVMF = *M->getFunction("foo"); | ||
sandboxir::Context Ctx(C); | ||
auto &F = *Ctx.createFunction(&LLVMF); | ||
auto *ArgAgg = F.getArg(0); | ||
auto *ArgInt = F.getArg(1); | ||
auto *BB = &*F.begin(); | ||
auto It = BB->begin(); | ||
auto *InsSimple = cast<sandboxir::InsertValueInst>(&*It++); | ||
auto *InsNested = cast<sandboxir::InsertValueInst>(&*It++); | ||
// These "const" instructions are helpers to create constant struct operands. | ||
// TODO: Remove them once sandboxir::ConstantStruct gets added. | ||
auto *Const1 = cast<sandboxir::InsertValueInst>(&*It++); | ||
auto *Const2 = cast<sandboxir::InsertValueInst>(&*It++); | ||
auto *Ret = &*It++; | ||
|
||
EXPECT_EQ(InsSimple->getOperand(0), ArgAgg); | ||
EXPECT_EQ(InsSimple->getOperand(1), ArgInt); | ||
|
||
// create before instruction | ||
auto *NewInsBeforeRet = | ||
cast<sandboxir::InsertValueInst>(sandboxir::InsertValueInst::create( | ||
ArgAgg, ArgInt, ArrayRef<unsigned>({0}), Ret->getIterator(), | ||
Ret->getParent(), Ctx, "NewInsBeforeRet")); | ||
EXPECT_EQ(NewInsBeforeRet->getNextNode(), Ret); | ||
#ifndef NDEBUG | ||
EXPECT_EQ(NewInsBeforeRet->getName(), "NewInsBeforeRet"); | ||
#endif // NDEBUG | ||
|
||
// create at end of BB | ||
auto *NewInsAtEnd = | ||
cast<sandboxir::InsertValueInst>(sandboxir::InsertValueInst::create( | ||
ArgAgg, ArgInt, ArrayRef<unsigned>({0}), BB->end(), BB, Ctx, | ||
"NewInsAtEnd")); | ||
EXPECT_EQ(NewInsAtEnd->getPrevNode(), Ret); | ||
#ifndef NDEBUG | ||
EXPECT_EQ(NewInsAtEnd->getName(), "NewInsAtEnd"); | ||
#endif // NDEBUG | ||
|
||
// Test the path that creates a folded constant. | ||
auto *Zero = sandboxir::ConstantInt::get(Type::getInt32Ty(C), 0, Ctx); | ||
auto *ShouldBeConstant = sandboxir::InsertValueInst::create( | ||
Const1->getOperand(0), Zero, ArrayRef<unsigned>({0}), BB->end(), BB, Ctx); | ||
auto *ExpectedConstant = Const2->getOperand(0); | ||
EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant)); | ||
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. nit: Constants are unique, so we could also do something 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. |
||
EXPECT_EQ(ShouldBeConstant, ExpectedConstant); | ||
|
||
// idx_begin / idx_end | ||
{ | ||
SmallVector<int, 2> IndicesSimple(InsSimple->idx_begin(), | ||
InsSimple->idx_end()); | ||
EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u)); | ||
|
||
SmallVector<int, 2> IndicesNested(InsNested->idx_begin(), | ||
InsNested->idx_end()); | ||
EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u)); | ||
} | ||
|
||
// indices | ||
{ | ||
SmallVector<int, 2> IndicesSimple(InsSimple->indices()); | ||
EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u)); | ||
|
||
SmallVector<int, 2> IndicesNested(InsNested->indices()); | ||
EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u)); | ||
} | ||
|
||
// getAggregateOperand | ||
EXPECT_EQ(InsSimple->getAggregateOperand(), ArgAgg); | ||
const auto *ConstInsSimple = InsSimple; | ||
EXPECT_EQ(ConstInsSimple->getAggregateOperand(), ArgAgg); | ||
|
||
// getAggregateOperandIndex | ||
EXPECT_EQ(sandboxir::InsertValueInst::getAggregateOperandIndex(), | ||
llvm::InsertValueInst::getAggregateOperandIndex()); | ||
|
||
// getInsertedValueOperand | ||
EXPECT_EQ(InsSimple->getInsertedValueOperand(), ArgInt); | ||
EXPECT_EQ(ConstInsSimple->getInsertedValueOperand(), ArgInt); | ||
|
||
// getInsertedValueOperandIndex | ||
EXPECT_EQ(sandboxir::InsertValueInst::getInsertedValueOperandIndex(), | ||
llvm::InsertValueInst::getInsertedValueOperandIndex()); | ||
|
||
// getIndices | ||
EXPECT_EQ(InsSimple->getIndices().size(), 1u); | ||
EXPECT_EQ(InsSimple->getIndices()[0], 0u); | ||
|
||
// getNumIndices | ||
EXPECT_EQ(InsSimple->getNumIndices(), 1u); | ||
|
||
// hasIndices | ||
EXPECT_EQ(InsSimple->hasIndices(), true); | ||
} | ||
|
||
TEST_F(SandboxIRTest, BranchInst) { | ||
parseIR(C, R"IR( | ||
define void @foo(i1 %cond0, i1 %cond2) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing
getInedexedType()
. If it is missing for a reason then we should add a TODO comment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure? I only see
getIndexedType
methods inGetElementPtrInst
andExtractValueInst
, not inInsertValueInst
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops I was looking at the
ExtractValueInst
:)