Skip to content

[SandboxIR] Implement StoreInst #99707

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

Merged
merged 1 commit into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 47 additions & 5 deletions llvm/include/llvm/SandboxIR/SandboxIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Context;
class Function;
class Instruction;
class LoadInst;
class StoreInst;
class User;
class Value;

Expand Down Expand Up @@ -172,10 +173,11 @@ class Value {
/// order.
llvm::Value *Val = nullptr;

friend class Context; // For getting `Val`.
friend class User; // For getting `Val`.
friend class Use; // For getting `Val`.
friend class LoadInst; // For getting `Val`.
friend class Context; // For getting `Val`.
friend class User; // For getting `Val`.
friend class Use; // For getting `Val`.
friend class LoadInst; // For getting `Val`.
friend class StoreInst; // For getting `Val`.

/// All values point to the context.
Context &Ctx;
Expand Down Expand Up @@ -495,7 +497,8 @@ class Instruction : public sandboxir::User {
/// A SandboxIR Instruction may map to multiple LLVM IR Instruction. This
/// returns its topmost LLVM IR instruction.
llvm::Instruction *getTopmostLLVMInstruction() const;
friend class LoadInst; // For getTopmostLLVMInstruction().
friend class LoadInst; // For getTopmostLLVMInstruction().
friend class StoreInst; // For getTopmostLLVMInstruction().

/// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
/// order.
Expand Down Expand Up @@ -599,6 +602,43 @@ class LoadInst final : public Instruction {
#endif
};

class StoreInst final : public Instruction {
/// Use StoreInst::create().
StoreInst(llvm::StoreInst *SI, Context &Ctx)
: Instruction(ClassID::Store, Opcode::Store, SI, Ctx) {}
friend Context; // for StoreInst()
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 StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
Instruction *InsertBefore, Context &Ctx);
static StoreInst *create(Value *V, Value *Ptr, MaybeAlign Align,
BasicBlock *InsertAtEnd, 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(); }
#ifndef NDEBUG
void verify() const final {
assert(isa<llvm::StoreInst>(Val) && "Expected StoreInst!");
}
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 {
Expand Down Expand Up @@ -734,6 +774,8 @@ class Context {

LoadInst *createLoadInst(llvm::LoadInst *LI);
friend LoadInst; // For createLoadInst()
StoreInst *createStoreInst(llvm::StoreInst *SI);
friend StoreInst; // For createStoreInst()

public:
Context(LLVMContext &LLVMCtx)
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/SandboxIRValues.def
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ DEF_USER(Constant, Constant)
// ClassID, Opcode(s), Class
DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
DEF_INSTR(Load, OP(Load), LoadInst)
DEF_INSTR(Store, OP(Store), StoreInst)

#ifdef DEF_VALUE
#undef DEF_VALUE
Expand Down
54 changes: 54 additions & 0 deletions llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,50 @@ void LoadInst::dump() const {
dump(dbgs());
dbgs() << "\n";
}
#endif // NDEBUG
StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
Instruction *InsertBefore, Context &Ctx) {
llvm::Instruction *BeforeIR = InsertBefore->getTopmostLLVMInstruction();
auto &Builder = Ctx.getLLVMIRBuilder();
Builder.SetInsertPoint(BeforeIR);
auto *NewSI =
Builder.CreateAlignedStore(V->Val, Ptr->Val, Align, /*isVolatile=*/false);
auto *NewSBI = Ctx.createStoreInst(NewSI);
return NewSBI;
}
StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align,
BasicBlock *InsertAtEnd, 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=*/false);
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());
}

#ifndef NDEBUG
void StoreInst::dump(raw_ostream &OS) const {
dumpCommonPrefix(OS);
dumpCommonSuffix(OS);
}

void StoreInst::dump() const {
dump(dbgs());
dbgs() << "\n";
}

void OpaqueInst::dump(raw_ostream &OS) const {
dumpCommonPrefix(OS);
Expand Down Expand Up @@ -618,6 +662,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
It->second = std::unique_ptr<LoadInst>(new LoadInst(LLVMLd, *this));
return It->second.get();
}
case llvm::Instruction::Store: {
auto *LLVMSt = cast<llvm::StoreInst>(LLVMV);
It->second = std::unique_ptr<StoreInst>(new StoreInst(LLVMSt, *this));
return It->second.get();
}
default:
break;
}
Expand All @@ -641,6 +690,11 @@ LoadInst *Context::createLoadInst(llvm::LoadInst *LI) {
return cast<LoadInst>(registerValue(std::move(NewPtr)));
}

StoreInst *Context::createStoreInst(llvm::StoreInst *SI) {
auto NewPtr = std::unique_ptr<StoreInst>(new StoreInst(SI, *this));
return cast<StoreInst>(registerValue(std::move(NewPtr)));
}

Value *Context::getValue(llvm::Value *V) const {
auto It = LLVMValueToValueMap.find(V);
if (It != LLVMValueToValueMap.end())
Expand Down
33 changes: 33 additions & 0 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,3 +591,36 @@ define void @foo(ptr %arg0, ptr %arg1) {
EXPECT_EQ(NewLd->getAlign(), 8);
EXPECT_EQ(NewLd->getName(), "NewLd");
}

TEST_F(SandboxIRTest, StoreInst) {
parseIR(C, R"IR(
define void @foo(i8 %val, ptr %ptr) {
store i8 %val, ptr %ptr, align 64
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
sandboxir::Function *F = Ctx.createFunction(LLVMF);
auto *Val = F->getArg(0);
auto *Ptr = F->getArg(1);
auto *BB = &*F->begin();
auto It = BB->begin();
auto *St = cast<sandboxir::StoreInst>(&*It++);
auto *Ret = &*It++;

// Check that the StoreInst has been created correctly.
// Check getPointerOperand()
EXPECT_EQ(St->getValueOperand(), Val);
EXPECT_EQ(St->getPointerOperand(), Ptr);
// Check getAlign()
EXPECT_EQ(St->getAlign(), 64);
// Check create(InsertBefore)
sandboxir::StoreInst *NewSt =
sandboxir::StoreInst::create(Val, Ptr, Align(8),
/*InsertBefore=*/Ret, Ctx);
EXPECT_EQ(NewSt->getType(), St->getType());
EXPECT_EQ(NewSt->getValueOperand(), Val);
EXPECT_EQ(NewSt->getPointerOperand(), Ptr);
EXPECT_EQ(NewSt->getAlign(), 8);
}
Loading