Skip to content

[SandboxIR] Implement FenceInst #105920

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
Aug 26, 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
32 changes: 32 additions & 0 deletions llvm/include/llvm/SandboxIR/SandboxIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class ConstantInt;
class Context;
class Function;
class Instruction;
class FenceInst;
class SelectInst;
class ExtractElementInst;
class InsertElementInst;
Expand Down Expand Up @@ -249,6 +250,7 @@ class Value {
friend class Context; // For getting `Val`.
friend class User; // For getting `Val`.
friend class Use; // For getting `Val`.
friend class FenceInst; // For getting `Val`.
friend class SelectInst; // For getting `Val`.
friend class ExtractElementInst; // For getting `Val`.
friend class InsertElementInst; // For getting `Val`.
Expand Down Expand Up @@ -678,6 +680,7 @@ 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 FenceInst; // For getTopmostLLVMInstruction().
friend class SelectInst; // For getTopmostLLVMInstruction().
friend class ExtractElementInst; // For getTopmostLLVMInstruction().
friend class InsertElementInst; // For getTopmostLLVMInstruction().
Expand Down Expand Up @@ -882,6 +885,33 @@ template <typename LLVMT> class SingleLLVMInstructionImpl : public Instruction {
#endif
};

class FenceInst : public SingleLLVMInstructionImpl<llvm::SelectInst> {
FenceInst(llvm::FenceInst *FI, Context &Ctx)
: SingleLLVMInstructionImpl(ClassID::Fence, Opcode::Fence, FI, Ctx) {}
friend Context; // For constructor;

public:
static FenceInst *create(AtomicOrdering Ordering, BBIterator WhereIt,
BasicBlock *WhereBB, Context &Ctx,
SyncScope::ID SSID = SyncScope::System);
/// Returns the ordering constraint of this fence instruction.
AtomicOrdering getOrdering() const {
return cast<llvm::FenceInst>(Val)->getOrdering();
}
/// Sets the ordering constraint of this fence instruction. May only be
/// Acquire, Release, AcquireRelease, or SequentiallyConsistent.
void setOrdering(AtomicOrdering Ordering);
/// Returns the synchronization scope ID of this fence instruction.
SyncScope::ID getSyncScopeID() const {
return cast<llvm::FenceInst>(Val)->getSyncScopeID();
}
/// Sets the synchronization scope ID of this fence instruction.
void setSyncScopeID(SyncScope::ID SSID);
static bool classof(const Value *From) {
return From->getSubclassID() == ClassID::Fence;
}
};

class SelectInst : public SingleLLVMInstructionImpl<llvm::SelectInst> {
/// Use Context::createSelectInst(). Don't call the
/// constructor directly.
Expand Down Expand Up @@ -2854,6 +2884,8 @@ class Context {
IRBuilder<ConstantFolder> LLVMIRBuilder;
auto &getLLVMIRBuilder() { return LLVMIRBuilder; }

FenceInst *createFenceInst(llvm::FenceInst *SI);
friend FenceInst; // For createFenceInst()
SelectInst *createSelectInst(llvm::SelectInst *SI);
friend SelectInst; // For createSelectInst()
InsertElementInst *createInsertElementInst(llvm::InsertElementInst *IEI);
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 @@ -37,6 +37,7 @@ DEF_USER(ConstantInt, ConstantInt)
DEF_INSTR(Opaque, OP(Opaque), OpaqueInst)
DEF_INSTR(ExtractElement, OP(ExtractElement), ExtractElementInst)
DEF_INSTR(InsertElement, OP(InsertElement), InsertElementInst)
DEF_INSTR(Fence, OP(Fence), FenceInst)
DEF_INSTR(ShuffleVector, OP(ShuffleVector), ShuffleVectorInst)
DEF_INSTR(Select, OP(Select), SelectInst)
DEF_INSTR(Br, OP(Br), BranchInst)
Expand Down
37 changes: 37 additions & 0 deletions llvm/lib/SandboxIR/SandboxIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,33 @@ void Instruction::dumpOS(raw_ostream &OS) const {
}
#endif // NDEBUG

FenceInst *FenceInst::create(AtomicOrdering Ordering, BBIterator WhereIt,
BasicBlock *WhereBB, Context &Ctx,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use llvm::InsertPosition to define where to insert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have an InsertPosition class yet. We will refactor all create() functions at some point to use that once it's available.

SyncScope::ID SSID) {
auto &Builder = Ctx.getLLVMIRBuilder();
if (WhereIt != WhereBB->end())
Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
else
Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
llvm::FenceInst *LLVMI = Builder.CreateFence(Ordering, SSID);
return Ctx.createFenceInst(LLVMI);
}

void FenceInst::setOrdering(AtomicOrdering Ordering) {
Ctx.getTracker()
.emplaceIfTracking<
GenericSetter<&FenceInst::getOrdering, &FenceInst::setOrdering>>(
this);
cast<llvm::FenceInst>(Val)->setOrdering(Ordering);
}

void FenceInst::setSyncScopeID(SyncScope::ID SSID) {
Ctx.getTracker()
.emplaceIfTracking<GenericSetter<&FenceInst::getSyncScopeID,
&FenceInst::setSyncScopeID>>(this);
cast<llvm::FenceInst>(Val)->setSyncScopeID(SSID);
}

Value *SelectInst::createCommon(Value *Cond, Value *True, Value *False,
const Twine &Name, IRBuilder<> &Builder,
Context &Ctx) {
Expand Down Expand Up @@ -2157,6 +2184,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
assert(isa<llvm::Instruction>(LLVMV) && "Expected Instruction");

switch (cast<llvm::Instruction>(LLVMV)->getOpcode()) {
case llvm::Instruction::Fence: {
auto *LLVMFence = cast<llvm::FenceInst>(LLVMV);
It->second = std::unique_ptr<FenceInst>(new FenceInst(LLVMFence, *this));
return It->second.get();
}
case llvm::Instruction::Select: {
auto *LLVMSel = cast<llvm::SelectInst>(LLVMV);
It->second = std::unique_ptr<SelectInst>(new SelectInst(LLVMSel, *this));
Expand Down Expand Up @@ -2349,6 +2381,11 @@ BasicBlock *Context::createBasicBlock(llvm::BasicBlock *LLVMBB) {
return BB;
}

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

SelectInst *Context::createSelectInst(llvm::SelectInst *SI) {
auto NewPtr = std::unique_ptr<SelectInst>(new SelectInst(SI, *this));
return cast<SelectInst>(registerValue(std::move(NewPtr)));
Expand Down
46 changes: 46 additions & 0 deletions llvm/unittests/SandboxIR/SandboxIRTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,52 @@ define void @foo(i8 %v1) {
EXPECT_EQ(I0->getNextNode(), Ret);
}

TEST_F(SandboxIRTest, FenceInst) {
parseIR(C, R"IR(
define void @foo() {
fence syncscope("singlethread") seq_cst
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
llvm::BasicBlock *LLVMBB = &*LLVMF->begin();
auto *LLVMFence = cast<llvm::FenceInst>(&*LLVMBB->begin());
sandboxir::Context Ctx(C);
sandboxir::Function *F = Ctx.createFunction(LLVMF);
auto *BB = &*F->begin();
auto It = BB->begin();
auto *Fence = cast<sandboxir::FenceInst>(&*It++);
auto *Ret = cast<sandboxir::ReturnInst>(&*It++);

// Check getOrdering().
EXPECT_EQ(Fence->getOrdering(), LLVMFence->getOrdering());
// Check setOrdering().
auto OrigOrdering = Fence->getOrdering();
auto NewOrdering = AtomicOrdering::Release;
EXPECT_NE(NewOrdering, OrigOrdering);
Fence->setOrdering(NewOrdering);
EXPECT_EQ(Fence->getOrdering(), NewOrdering);
Fence->setOrdering(OrigOrdering);
EXPECT_EQ(Fence->getOrdering(), OrigOrdering);
// Check getSyncScopeID().
EXPECT_EQ(Fence->getSyncScopeID(), LLVMFence->getSyncScopeID());
// Check setSyncScopeID().
auto OrigSSID = Fence->getSyncScopeID();
auto NewSSID = SyncScope::System;
EXPECT_NE(NewSSID, OrigSSID);
Fence->setSyncScopeID(NewSSID);
EXPECT_EQ(Fence->getSyncScopeID(), NewSSID);
Fence->setSyncScopeID(OrigSSID);
EXPECT_EQ(Fence->getSyncScopeID(), OrigSSID);
// Check create().
auto *NewFence =
sandboxir::FenceInst::create(AtomicOrdering::Release, Ret->getIterator(),
BB, Ctx, SyncScope::SingleThread);
EXPECT_EQ(NewFence->getNextNode(), Ret);
EXPECT_EQ(NewFence->getOrdering(), AtomicOrdering::Release);
EXPECT_EQ(NewFence->getSyncScopeID(), SyncScope::SingleThread);
}

TEST_F(SandboxIRTest, SelectInst) {
parseIR(C, R"IR(
define void @foo(i1 %c0, i8 %v0, i8 %v1, i1 %c1) {
Expand Down
34 changes: 34 additions & 0 deletions llvm/unittests/SandboxIR/TrackerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,40 @@ define void @foo(ptr %ptr) {
EXPECT_EQ(It, BB->end());
}

TEST_F(TrackerTest, FenceInstSetters) {
parseIR(C, R"IR(
define void @foo() {
fence syncscope("singlethread") seq_cst
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
sandboxir::Function *F = Ctx.createFunction(LLVMF);
auto *BB = &*F->begin();
auto It = BB->begin();
auto *Fence = cast<sandboxir::FenceInst>(&*It++);

// Check setOrdering().
auto OrigOrdering = Fence->getOrdering();
auto NewOrdering = AtomicOrdering::Release;
EXPECT_NE(NewOrdering, OrigOrdering);
Ctx.save();
Fence->setOrdering(NewOrdering);
EXPECT_EQ(Fence->getOrdering(), NewOrdering);
Ctx.revert();
EXPECT_EQ(Fence->getOrdering(), OrigOrdering);
// Check setSyncScopeID().
auto OrigSSID = Fence->getSyncScopeID();
auto NewSSID = SyncScope::System;
EXPECT_NE(NewSSID, OrigSSID);
Ctx.save();
Fence->setSyncScopeID(NewSSID);
EXPECT_EQ(Fence->getSyncScopeID(), NewSSID);
Ctx.revert();
EXPECT_EQ(Fence->getSyncScopeID(), OrigSSID);
}

TEST_F(TrackerTest, CallBaseSetters) {
parseIR(C, R"IR(
declare void @bar1(i8)
Expand Down
Loading