[llvm] [SandboxIR] Implement UnreachableInst (PR #101856)

Julius Alexandre via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 3 17:25:06 PDT 2024


https://github.com/medievalghoul created https://github.com/llvm/llvm-project/pull/101856

This patch implements the `UnreachableInst` instruction in SandboxIR. Mirroring `llvm::UnreachableInst`.

cc: @vporpo 

>From f0a3cb13c0ded19be5f364f19bd3f242ffde3b4d Mon Sep 17 00:00:00 2001
From: medievalghoul <61852278+medievalghoul at users.noreply.github.com>
Date: Sat, 3 Aug 2024 20:22:41 -0400
Subject: [PATCH] [SandboxIR] Implement UnreachableInst

---
 llvm/include/llvm/SandboxIR/SandboxIR.h       | 45 +++++++++++++++++++
 .../llvm/SandboxIR/SandboxIRValues.def        |  4 +-
 llvm/lib/SandboxIR/SandboxIR.cpp              | 38 ++++++++++++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp    | 29 ++++++++++++
 4 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index ed0aaeb4f9a8e..bbe4ea5dd8d24 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -81,6 +81,8 @@
 //                                      |                    +- CastInst
 //                                      |
 //                                      +- UnaryOperator
+//                                      |
+//                                      +- UnreachableInst
 //
 // Use
 //
@@ -115,6 +117,7 @@ class LoadInst;
 class ReturnInst;
 class StoreInst;
 class User;
+class UnreachableInst;
 class Value;
 class CallBase;
 class CallInst;
@@ -242,6 +245,7 @@ class Value {
   friend class GetElementPtrInst; // For getting `Val`.
   friend class CastInst;          // For getting `Val`.
   friend class PHINode;           // For getting `Val`.
+  friend class UnreachableInst;   // For getting `Val`.
 
   /// All values point to the context.
   Context &Ctx;
@@ -635,6 +639,7 @@ class Instruction : public sandboxir::User {
   friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
   friend class CastInst;          // For getTopmostLLVMInstruction().
   friend class PHINode;           // For getTopmostLLVMInstruction().
+  friend class UnreachableInst;   // For getTopmostLLVMInstruction().
 
   /// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
   /// order.
@@ -952,6 +957,44 @@ class StoreInst final : public Instruction {
 #endif
 };
 
+class UnreachableInst final : public Instruction {
+  /// Use UnreachableInst::create() instead of calling the constructor.
+  UnreachableInst(llvm::Instruction *I, Context &Ctx)
+      : Instruction(ClassID::Unreachable, Opcode::Unreachable, I, Ctx) {}
+  UnreachableInst(ClassID SubclassID, llvm::Instruction *I, Context &Ctx)
+      : Instruction(SubclassID, Opcode::Unreachable, I, Ctx) {}
+  friend Context;
+  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 UnreachableInst *create(Instruction *InsertBefore, Context &Ctx);
+  static UnreachableInst *create(BasicBlock *InsertAtEnd, Context &Ctx);
+  static bool classof(const Value *From);
+  unsigned getNumSuccessors() const { return 0; }
+  BasicBlock *getSuccessor(unsigned idx) const {
+    llvm_unreachable("UnreachableInst has no successors!");
+  }
+  void setSuccessor(unsigned idx, BasicBlock *B) {
+    llvm_unreachable("UnreachableInst has no successors!");
+  }
+  unsigned getUseOperandNo(const Use &Use) const final {
+    return getUseOperandNoDefault(Use);
+  }
+  unsigned getNumOfIRInstrs() const final { return 1u; }
+#ifndef NDEBUG
+  void verify() const final {
+    assert(isa<llvm::UnreachableInst>(Val) && "Expected UnreachableInst!");
+  }
+  void dump(raw_ostream &OS) const override;
+  LLVM_DUMP_METHOD void dump() const override;
+#endif
+};
+
 class ReturnInst final : public Instruction {
   /// Use ReturnInst::create() instead of calling the constructor.
   ReturnInst(llvm::Instruction *I, Context &Ctx)
@@ -1732,6 +1775,8 @@ class Context {
   friend CastInst; // For createCastInst()
   PHINode *createPHINode(llvm::PHINode *I);
   friend PHINode; // For createPHINode()
+  UnreachableInst *createUnreachableInst(llvm::UnreachableInst *UI);
+  friend UnreachableInst; // For createUnreachableInst()
 
 public:
   Context(LLVMContext &LLVMCtx)
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index 4cb601128a507..61c5f7d79412d 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -59,7 +59,9 @@ DEF_INSTR(Cast,  OPCODES(\
                          OP(AddrSpaceCast) \
                          ),                 CastInst)
 DEF_INSTR(PHI,           OP(PHI),           PHINode)
-  
+DEF_INSTR(Unreachable,   OP(Unreachable),   UnreachableInst)
+
+
 // clang-format on
 #ifdef DEF_VALUE
 #undef DEF_VALUE
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 00abee48821ff..8438cb84a35bb 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -747,6 +747,38 @@ void StoreInst::dump() const {
 }
 #endif // NDEBUG
 
+UnreachableInst *UnreachableInst::create(Instruction *InsertBefore,
+                                         Context &Ctx) {
+  auto &Builder = Ctx.getLLVMIRBuilder();
+  Builder.SetInsertPoint(cast<llvm::Instruction>(InsertBefore->Val));
+  llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
+  return Ctx.createUnreachableInst(NewUI);
+}
+
+UnreachableInst *UnreachableInst::create(BasicBlock *InsertAtEnd,
+                                         Context &Ctx) {
+  auto &Builder = Ctx.getLLVMIRBuilder();
+  Builder.SetInsertPoint(cast<llvm::BasicBlock>(InsertAtEnd->Val));
+  llvm::UnreachableInst *NewUI = Builder.CreateUnreachable();
+  return Ctx.createUnreachableInst(NewUI);
+}
+
+bool UnreachableInst::classof(const Value *From) {
+  return From->getSubclassID() == ClassID::Unreachable;
+}
+
+#ifndef NDEBUG
+void UnreachableInst::dump(raw_ostream &OS) const {
+  dumpCommonPrefix(OS);
+  dumpCommonSuffix(OS);
+}
+
+void UnreachableInst::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
 ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder,
                                      Context &Ctx) {
   llvm::ReturnInst *NewRI;
@@ -1522,6 +1554,12 @@ CallBrInst *Context::createCallBrInst(llvm::CallBrInst *I) {
   return cast<CallBrInst>(registerValue(std::move(NewPtr)));
 }
 
+UnreachableInst *Context::createUnreachableInst(llvm::UnreachableInst *UI) {
+  auto NewPtr =
+      std::unique_ptr<UnreachableInst>(new UnreachableInst(UI, *this));
+  return cast<UnreachableInst>(registerValue(std::move(NewPtr)));
+}
+
 GetElementPtrInst *
 Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
   auto NewPtr =
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 550c0576e0237..a14992c530309 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -2037,3 +2037,32 @@ define void @foo(i32 %arg) {
   }
   EXPECT_EQ(NewPHI->getNumIncomingValues(), PHI->getNumIncomingValues());
 }
+
+TEST_F(SandboxIRTest, UnreachableInst) {
+  parseIR(C, R"IR(
+define void @foo() {
+  ret void
+  unreachable
+}
+)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 *Ret = &*It++;
+  auto *UI = cast<sandboxir::UnreachableInst>(&*It++);
+
+  EXPECT_TRUE(llvm::isa<sandboxir::UnreachableInst>(UI));
+
+  // Check create(InsertBefore)
+  sandboxir::UnreachableInst *NewUI =
+      sandboxir::UnreachableInst::create(/*InsertBefore=*/Ret, Ctx);
+  EXPECT_NE(NewUI, nullptr);
+  EXPECT_EQ(NewUI->getParent(), BB);
+  // Check create(InsertAtEnd)
+  sandboxir::UnreachableInst *NewUIEnd =
+      sandboxir::UnreachableInst::create(/*InsertAtEnd=*/BB, Ctx);
+  EXPECT_NE(NewUIEnd, nullptr);
+  EXPECT_EQ(NewUIEnd->getParent(), BB);
+}



More information about the llvm-commits mailing list