Skip to content

Commit e546430

Browse files
[SandboxIR] Implement UnreachableInst (#101856)
This patch implements the `UnreachableInst` instruction in SandboxIR. Mirroring `llvm::UnreachableInst`.
1 parent 03841e7 commit e546430

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@
8181
// | +- CastInst
8282
// |
8383
// +- UnaryOperator
84+
// |
85+
// +- UnreachableInst
8486
//
8587
// Use
8688
//
@@ -115,6 +117,7 @@ class LoadInst;
115117
class ReturnInst;
116118
class StoreInst;
117119
class User;
120+
class UnreachableInst;
118121
class Value;
119122
class CallBase;
120123
class CallInst;
@@ -244,6 +247,7 @@ class Value {
244247
friend class AllocaInst; // For getting `Val`.
245248
friend class CastInst; // For getting `Val`.
246249
friend class PHINode; // For getting `Val`.
250+
friend class UnreachableInst; // For getting `Val`.
247251

248252
/// All values point to the context.
249253
Context &Ctx;
@@ -638,6 +642,7 @@ class Instruction : public sandboxir::User {
638642
friend class AllocaInst; // For getTopmostLLVMInstruction().
639643
friend class CastInst; // For getTopmostLLVMInstruction().
640644
friend class PHINode; // For getTopmostLLVMInstruction().
645+
friend class UnreachableInst; // For getTopmostLLVMInstruction().
641646

642647
/// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
643648
/// order.
@@ -955,6 +960,36 @@ class StoreInst final : public Instruction {
955960
#endif
956961
};
957962

963+
class UnreachableInst final : public Instruction {
964+
/// Use UnreachableInst::create() instead of calling the constructor.
965+
UnreachableInst(llvm::UnreachableInst *I, Context &Ctx)
966+
: Instruction(ClassID::Unreachable, Opcode::Unreachable, I, Ctx) {}
967+
friend Context;
968+
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
969+
return getOperandUseDefault(OpIdx, Verify);
970+
}
971+
SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
972+
return {cast<llvm::Instruction>(Val)};
973+
}
974+
975+
public:
976+
static UnreachableInst *create(Instruction *InsertBefore, Context &Ctx);
977+
static UnreachableInst *create(BasicBlock *InsertAtEnd, Context &Ctx);
978+
static bool classof(const Value *From);
979+
unsigned getNumSuccessors() const { return 0; }
980+
unsigned getUseOperandNo(const Use &Use) const final {
981+
llvm_unreachable("UnreachableInst has no operands!");
982+
}
983+
unsigned getNumOfIRInstrs() const final { return 1u; }
984+
#ifndef NDEBUG
985+
void verify() const final {
986+
assert(isa<llvm::UnreachableInst>(Val) && "Expected UnreachableInst!");
987+
}
988+
void dump(raw_ostream &OS) const override;
989+
LLVM_DUMP_METHOD void dump() const override;
990+
#endif
991+
};
992+
958993
class ReturnInst final : public Instruction {
959994
/// Use ReturnInst::create() instead of calling the constructor.
960995
ReturnInst(llvm::Instruction *I, Context &Ctx)
@@ -1832,6 +1867,8 @@ class Context {
18321867
friend CastInst; // For createCastInst()
18331868
PHINode *createPHINode(llvm::PHINode *I);
18341869
friend PHINode; // For createPHINode()
1870+
UnreachableInst *createUnreachableInst(llvm::UnreachableInst *UI);
1871+
friend UnreachableInst; // For createUnreachableInst()
18351872

18361873
public:
18371874
Context(LLVMContext &LLVMCtx)

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ DEF_INSTR(Cast, OPCODES(\
6060
OP(AddrSpaceCast) \
6161
), CastInst)
6262
DEF_INSTR(PHI, OP(PHI), PHINode)
63-
63+
DEF_INSTR(Unreachable, OP(Unreachable), UnreachableInst)
64+
6465
// clang-format on
6566
#ifdef DEF_VALUE
6667
#undef DEF_VALUE

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,39 @@ void StoreInst::dump() const {
747747
}
748748
#endif // NDEBUG
749749

750+
UnreachableInst *UnreachableInst::create(Instruction *InsertBefore,
751+
Context &Ctx) {
752+
auto &Builder = Ctx.getLLVMIRBuilder();
753+
llvm::Instruction *LLVMBefore = InsertBefore->getTopmostLLVMInstruction();
754+
Builder.SetInsertPoint(LLVMBefore);
755+
llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
756+
return Ctx.createUnreachableInst(NewUI);
757+
}
758+
759+
UnreachableInst *UnreachableInst::create(BasicBlock *InsertAtEnd,
760+
Context &Ctx) {
761+
auto &Builder = Ctx.getLLVMIRBuilder();
762+
Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
763+
llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
764+
return Ctx.createUnreachableInst(NewUI);
765+
}
766+
767+
bool UnreachableInst::classof(const Value *From) {
768+
return From->getSubclassID() == ClassID::Unreachable;
769+
}
770+
771+
#ifndef NDEBUG
772+
void UnreachableInst::dump(raw_ostream &OS) const {
773+
dumpCommonPrefix(OS);
774+
dumpCommonSuffix(OS);
775+
}
776+
777+
void UnreachableInst::dump() const {
778+
dump(dbgs());
779+
dbgs() << "\n";
780+
}
781+
#endif // NDEBUG
782+
750783
ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder,
751784
Context &Ctx) {
752785
llvm::ReturnInst *NewRI;
@@ -1562,6 +1595,12 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
15621595
It->second = std::unique_ptr<PHINode>(new PHINode(LLVMPhi, *this));
15631596
return It->second.get();
15641597
}
1598+
case llvm::Instruction::Unreachable: {
1599+
auto *LLVMUnreachable = cast<llvm::UnreachableInst>(LLVMV);
1600+
It->second = std::unique_ptr<UnreachableInst>(
1601+
new UnreachableInst(LLVMUnreachable, *this));
1602+
return It->second.get();
1603+
}
15651604
default:
15661605
break;
15671606
}
@@ -1620,6 +1659,12 @@ CallBrInst *Context::createCallBrInst(llvm::CallBrInst *I) {
16201659
return cast<CallBrInst>(registerValue(std::move(NewPtr)));
16211660
}
16221661

1662+
UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
1663+
auto NewPtr =
1664+
std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
1665+
return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
1666+
}
1667+
16231668
GetElementPtrInst *
16241669
Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
16251670
auto NewPtr =

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,3 +2207,29 @@ define void @foo(i32 %arg) {
22072207
}
22082208
EXPECT_EQ(NewPHI->getNumIncomingValues(), PHI->getNumIncomingValues());
22092209
}
2210+
2211+
TEST_F(SandboxIRTest, UnreachableInst) {
2212+
parseIR(C, R"IR(
2213+
define void @foo() {
2214+
unreachable
2215+
}
2216+
)IR");
2217+
llvm::Function *LLVMF = &*M->getFunction("foo");
2218+
sandboxir::Context Ctx(C);
2219+
sandboxir::Function *F = Ctx.createFunction(LLVMF);
2220+
auto *BB = &*F->begin();
2221+
auto It = BB->begin();
2222+
auto *UI = cast<sandboxir::UnreachableInst>(&*It++);
2223+
2224+
EXPECT_EQ(UI->getNumSuccessors(), 0u);
2225+
EXPECT_EQ(UI->getNumOfIRInstrs(), 1u);
2226+
// Check create(InsertBefore)
2227+
sandboxir::UnreachableInst *NewUI =
2228+
sandboxir::UnreachableInst::create(/*InsertBefore=*/UI, Ctx);
2229+
EXPECT_EQ(NewUI->getNextNode(), UI);
2230+
// Check create(InsertAtEnd)
2231+
sandboxir::UnreachableInst *NewUIEnd =
2232+
sandboxir::UnreachableInst::create(/*InsertAtEnd=*/BB, Ctx);
2233+
EXPECT_EQ(NewUIEnd->getParent(), BB);
2234+
EXPECT_EQ(NewUIEnd->getNextNode(), nullptr);
2235+
}

0 commit comments

Comments
 (0)