[llvm] [SandboxIR] Add InsertValueInst (PR #106273)

Jorge Gorbe Moya via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 27 12:34:19 PDT 2024


https://github.com/slackito updated https://github.com/llvm/llvm-project/pull/106273

>From eb4817c4f5f2d11571f15ab81b1353962afea0b3 Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Tue, 27 Aug 2024 12:18:04 -0700
Subject: [PATCH 1/2] [SandboxIR] Add InsertValueInst

---
 llvm/include/llvm/SandboxIR/SandboxIR.h       | 64 +++++++++++++
 .../llvm/SandboxIR/SandboxIRValues.def        |  1 +
 llvm/lib/SandboxIR/SandboxIR.cpp              | 28 ++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp    | 92 +++++++++++++++++++
 4 files changed, 185 insertions(+)

diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index e4c48e39a40015..058704b4321701 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -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,63 @@ 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 = "");
+
+  using idx_iterator = llvm::InsertValueInst::idx_iterator;
+  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 +3061,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);
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index 8d79523253f233..e35819821cfb5f 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -40,6 +40,7 @@ DEF_INSTR(InsertElement,  OP(InsertElement),  InsertElementInst)
 DEF_INSTR(Freeze,         OP(Freeze),         FreezeInst)
 DEF_INSTR(Fence,          OP(Fence),          FenceInst)
 DEF_INSTR(ShuffleVector,  OP(ShuffleVector),  ShuffleVectorInst)
+DEF_INSTR(InsertValue,    OP(InsertValue),    InsertValueInst)
 DEF_INSTR(Select,         OP(Select),         SelectInst)
 DEF_INSTR(Br,             OP(Br),             BranchInst)
 DEF_INSTR(Load,           OP(Load),           LoadInst)
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 35b642ac7f3a22..58fe15b62496f1 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -2114,6 +2114,21 @@ Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(
       llvm::ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, ResultTy));
 }
 
+Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
+                               BBIterator WhereIt, BasicBlock *WhereBB,
+                               Context &Ctx, const Twine &Name) {
+  auto &Builder = Ctx.getLLVMIRBuilder();
+  if (WhereIt != WhereBB->end())
+    Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+  else
+    Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+  llvm::Value *NewV = Builder.CreateInsertValue(Agg->Val, Val->Val, Idxs, Name);
+  if (auto *NewInsertValueInst = dyn_cast<llvm::InsertValueInst>(NewV))
+    return Ctx.createInsertValueInst(NewInsertValueInst);
+  assert(isa<llvm::Constant>(NewV) && "Expected constant");
+  return Ctx.getOrCreateConstant(cast<llvm::Constant>(NewV));
+}
+
 #ifndef NDEBUG
 void Constant::dumpOS(raw_ostream &OS) const {
   dumpCommonPrefix(OS);
@@ -2269,6 +2284,12 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
         new ShuffleVectorInst(LLVMIns, *this));
     return It->second.get();
   }
+  case llvm::Instruction::InsertValue: {
+    auto *LLVMIns = cast<llvm::InsertValueInst>(LLVMV);
+    It->second = std::unique_ptr<InsertValueInst>(
+        new InsertValueInst(LLVMIns, *this));
+    return It->second.get();
+  }
   case llvm::Instruction::Br: {
     auto *LLVMBr = cast<llvm::BranchInst>(LLVMV);
     It->second = std::unique_ptr<BranchInst>(new BranchInst(LLVMBr, *this));
@@ -2480,6 +2501,13 @@ Context::createShuffleVectorInst(llvm::ShuffleVectorInst *SVI) {
   return cast<ShuffleVectorInst>(registerValue(std::move(NewPtr)));
 }
 
+InsertValueInst *
+Context::createInsertValueInst(llvm::InsertValueInst *IVI) {
+  auto NewPtr =
+      std::unique_ptr<InsertValueInst>(new InsertValueInst(IVI, *this));
+  return cast<InsertValueInst>(registerValue(std::move(NewPtr)));
+}
+
 BranchInst *Context::createBranchInst(llvm::BranchInst *BI) {
   auto NewPtr = std::unique_ptr<BranchInst>(new BranchInst(BI, *this));
   return cast<BranchInst>(registerValue(std::move(NewPtr)));
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 869e752b23913f..039285ff2b3fed 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1228,6 +1228,98 @@ 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) {
+  %ins0 = insertvalue {i32, float} %agg, i32 %i, 0
+  %ins1 = insertvalue {i32, float} {i32 99, 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 *Ins0 = cast<sandboxir::InsertValueInst>(&*It++);
+  auto *Ins1 = cast<sandboxir::InsertValueInst>(&*It++);
+  auto *Ret = &*It++;
+
+  EXPECT_EQ(Ins0->getOperand(0), ArgAgg);
+  EXPECT_EQ(Ins0->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. We're currently using an
+  // insertvalue instruction with a constant struct operand in the textual IR
+  // above to obtain a constant struct to work with.
+  // TODO: Refactor this once sandboxir::ConstantStruct lands.
+  auto *Zero = sandboxir::ConstantInt::get(Type::getInt32Ty(C), 0, Ctx);
+  auto *ShouldBeConstant = sandboxir::InsertValueInst::create(
+      Ins1->getOperand(0), Zero, ArrayRef<unsigned>({0}), BB->end(), BB, Ctx);
+  EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant));
+
+  // idx_begin / idx_end
+  auto IdxIt = Ins0->idx_begin();
+  EXPECT_EQ(*IdxIt++, 0u);
+  EXPECT_EQ(IdxIt, Ins0->idx_end());
+
+  // indices
+  int Count = 0;
+  for (unsigned Idx : Ins0->indices()) {
+    EXPECT_EQ(Idx, 0u);
+    Count++;
+  }
+  EXPECT_EQ(Count, 1);
+
+  // getAggregateOperand
+  EXPECT_EQ(Ins0->getAggregateOperand(), ArgAgg);
+  const auto* ConstIns0 = Ins0;
+  EXPECT_EQ(ConstIns0->getAggregateOperand(), ArgAgg);
+
+  // getAggregateOperandIndex
+  EXPECT_EQ(sandboxir::InsertValueInst::getAggregateOperandIndex(),
+            llvm::InsertValueInst::getAggregateOperandIndex());
+
+  // getInsertedValueOperand
+  EXPECT_EQ(Ins0->getInsertedValueOperand(), ArgInt);
+  EXPECT_EQ(ConstIns0->getInsertedValueOperand(), ArgInt);
+
+  // getInsertedValueOperandIndex
+  EXPECT_EQ(sandboxir::InsertValueInst::getInsertedValueOperandIndex(),
+            llvm::InsertValueInst::getInsertedValueOperandIndex());
+
+  // getIndices
+  EXPECT_EQ(Ins0->getIndices().size(), 1u);
+  EXPECT_EQ(Ins0->getIndices()[0], 0u);
+
+  // getNumIndices
+  EXPECT_EQ(Ins0->getNumIndices(), 1u);
+
+  // hasIndices
+  EXPECT_EQ(Ins0->hasIndices(), true);
+}
+
 TEST_F(SandboxIRTest, BranchInst) {
   parseIR(C, R"IR(
 define void @foo(i1 %cond0, i1 %cond2) {

>From 85c961768248163b9849c4015c47dfc052e00eaa Mon Sep 17 00:00:00 2001
From: Jorge Gorbe Moya <jgorbe at google.com>
Date: Tue, 27 Aug 2024 12:33:39 -0700
Subject: [PATCH 2/2] fix clang-format issues

---
 llvm/lib/SandboxIR/SandboxIR.cpp           | 7 +++----
 llvm/unittests/SandboxIR/SandboxIRTest.cpp | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 58fe15b62496f1..b1a7bb29df581e 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -2286,8 +2286,8 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
   }
   case llvm::Instruction::InsertValue: {
     auto *LLVMIns = cast<llvm::InsertValueInst>(LLVMV);
-    It->second = std::unique_ptr<InsertValueInst>(
-        new InsertValueInst(LLVMIns, *this));
+    It->second =
+        std::unique_ptr<InsertValueInst>(new InsertValueInst(LLVMIns, *this));
     return It->second.get();
   }
   case llvm::Instruction::Br: {
@@ -2501,8 +2501,7 @@ Context::createShuffleVectorInst(llvm::ShuffleVectorInst *SVI) {
   return cast<ShuffleVectorInst>(registerValue(std::move(NewPtr)));
 }
 
-InsertValueInst *
-Context::createInsertValueInst(llvm::InsertValueInst *IVI) {
+InsertValueInst *Context::createInsertValueInst(llvm::InsertValueInst *IVI) {
   auto NewPtr =
       std::unique_ptr<InsertValueInst>(new InsertValueInst(IVI, *this));
   return cast<InsertValueInst>(registerValue(std::move(NewPtr)));
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 039285ff2b3fed..4e44dbc9daa625 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1294,7 +1294,7 @@ define void @foo({i32, float} %agg, i32 %i) {
 
   // getAggregateOperand
   EXPECT_EQ(Ins0->getAggregateOperand(), ArgAgg);
-  const auto* ConstIns0 = Ins0;
+  const auto *ConstIns0 = Ins0;
   EXPECT_EQ(ConstIns0->getAggregateOperand(), ArgAgg);
 
   // getAggregateOperandIndex



More information about the llvm-commits mailing list