[llvm] [SandboxIR] Implement AllocaInst (PR #102027)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 6 10:39:22 PDT 2024


https://github.com/vporpo updated https://github.com/llvm/llvm-project/pull/102027

>From f5b9bb3b7db7bc2f7a83e68f81e4b06bfd3d50da Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 1 Aug 2024 10:37:49 -0700
Subject: [PATCH 1/3] [SandboxIR] Implement AllocaInst

This patch implements sandboxir::AllocaInst which mirrors llvm::AllocaInst.
---
 llvm/include/llvm/SandboxIR/SandboxIR.h       | 107 +++++++++++++
 .../llvm/SandboxIR/SandboxIRValues.def        |   1 +
 llvm/include/llvm/SandboxIR/Tracker.h         |  69 ++++++++
 llvm/lib/SandboxIR/SandboxIR.cpp              |  84 +++++++++-
 llvm/lib/SandboxIR/Tracker.cpp                |  52 ++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp    | 148 ++++++++++++++++++
 llvm/unittests/SandboxIR/TrackerTest.cpp      |  55 +++++++
 7 files changed, 515 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 9e5db20b24877..89741894b95ef 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -124,6 +124,7 @@ class GetElementPtrInst;
 class CastInst;
 class PtrToIntInst;
 class BitCastInst;
+class AllocaInst;
 
 /// Iterator for the `Use` edges of a User's operands.
 /// \Returns the operand `Use` when dereferenced.
@@ -240,6 +241,7 @@ class Value {
   friend class InvokeInst;        // For getting `Val`.
   friend class CallBrInst;        // For getting `Val`.
   friend class GetElementPtrInst; // For getting `Val`.
+  friend class AllocaInst;        // For getting `Val`.
   friend class CastInst;          // For getting `Val`.
   friend class PHINode;           // For getting `Val`.
 
@@ -633,6 +635,7 @@ class Instruction : public sandboxir::User {
   friend class InvokeInst;        // For getTopmostLLVMInstruction().
   friend class CallBrInst;        // For getTopmostLLVMInstruction().
   friend class GetElementPtrInst; // For getTopmostLLVMInstruction().
+  friend class AllocaInst;        // For getTopmostLLVMInstruction().
   friend class CastInst;          // For getTopmostLLVMInstruction().
   friend class PHINode;           // For getTopmostLLVMInstruction().
 
@@ -1393,6 +1396,108 @@ class GetElementPtrInst final : public Instruction {
 #endif
 };
 
+class AllocaInst final : public UnaryInstruction {
+  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:
+  AllocaInst(llvm::AllocaInst *AI, Context &Ctx)
+      : UnaryInstruction(ClassID::Alloca, Instruction::Opcode::Alloca, AI,
+                         Ctx) {}
+
+  static AllocaInst *create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
+                            BasicBlock *WhereBB, Context &Ctx,
+                            Value *ArraySize = nullptr, const Twine &Name = "");
+  static AllocaInst *create(Type *Ty, unsigned AddrSpace,
+                            Instruction *InsertBefore, Context &Ctx,
+                            Value *ArraySize = nullptr, const Twine &Name = "");
+  static AllocaInst *create(Type *Ty, unsigned AddrSpace,
+                            BasicBlock *InsertAtEnd, Context &Ctx,
+                            Value *ArraySize = nullptr, const Twine &Name = "");
+
+  unsigned getUseOperandNo(const Use &Use) const final {
+    return getUseOperandNoDefault(Use);
+  }
+  unsigned getNumOfIRInstrs() const final { return 1u; }
+
+  /// Return true if there is an allocation size parameter to the allocation
+  /// instruction that is not 1.
+  bool isArrayAllocation() const {
+    return cast<llvm::AllocaInst>(Val)->isArrayAllocation();
+  }
+  /// Get the number of elements allocated. For a simple allocation of a single
+  /// element, this will return a constant 1 value.
+  Value *getArraySize();
+  const Value *getArraySize() const {
+    return const_cast<AllocaInst *>(this)->getArraySize();
+  }
+  /// Overload to return most specific pointer type.
+  PointerType *getType() const {
+    return cast<llvm::AllocaInst>(Val)->getType();
+  }
+  /// Return the address space for the allocation.
+  unsigned getAddressSpace() const {
+    return cast<llvm::AllocaInst>(Val)->getAddressSpace();
+  }
+  /// Get allocation size in bytes. Returns std::nullopt if size can't be
+  /// determined, e.g. in case of a VLA.
+  std::optional<TypeSize> getAllocationSize(const DataLayout &DL) const {
+    return cast<llvm::AllocaInst>(Val)->getAllocationSize(DL);
+  }
+  /// Get allocation size in bits. Returns std::nullopt if size can't be
+  /// determined, e.g. in case of a VLA.
+  std::optional<TypeSize> getAllocationSizeInBits(const DataLayout &DL) const {
+    return cast<llvm::AllocaInst>(Val)->getAllocationSizeInBits(DL);
+  }
+  /// Return the type that is being allocated by the instruction.
+  Type *getAllocatedType() const {
+    return cast<llvm::AllocaInst>(Val)->getAllocatedType();
+  }
+  /// for use only in special circumstances that need to generically
+  /// transform a whole instruction (eg: IR linking and vectorization).
+  void setAllocatedType(Type *Ty);
+  /// Return the alignment of the memory that is being allocated by the
+  /// instruction.
+  Align getAlign() const { return cast<llvm::AllocaInst>(Val)->getAlign(); }
+  void setAlignment(Align Align);
+  /// Return true if this alloca is in the entry block of the function and is a
+  /// constant size. If so, the code generator will fold it into the
+  /// prolog/epilog code, so it is basically free.
+  bool isStaticAlloca() const {
+    return cast<llvm::AllocaInst>(Val)->isStaticAlloca();
+  }
+  /// Return true if this alloca is used as an inalloca argument to a call. Such
+  /// allocas are never considered static even if they are in the entry block.
+  bool isUsedWithInAlloca() const {
+    return cast<llvm::AllocaInst>(Val)->isUsedWithInAlloca();
+  }
+  /// Specify whether this alloca is used to represent the arguments to a call.
+  void setUsedWithInAlloca(bool V);
+  /// Return true if this alloca is used as a swifterror argument to a call.
+  bool isSwiftError() const {
+    return cast<llvm::AllocaInst>(Val)->isSwiftError();
+  }
+  /// Specify whether this alloca is used to represent a swifterror.
+  void setSwiftError(bool V);
+
+  static bool classof(const Value *From) {
+    if (auto *I = dyn_cast<Instruction>(From))
+      return I->getSubclassID() == Instruction::ClassID::Alloca;
+    return false;
+  }
+#ifndef NDEBUG
+  void verify() const final {
+    assert(isa<llvm::AllocaInst>(Val) && "Expected AllocaInst!");
+  }
+  void dump(raw_ostream &OS) const override;
+  LLVM_DUMP_METHOD void dump() const override;
+#endif
+};
+
 class CastInst : public UnaryInstruction {
   static Opcode getCastOpcode(llvm::Instruction::CastOps CastOp) {
     switch (CastOp) {
@@ -1727,6 +1832,8 @@ class Context {
   friend CallBrInst; // For createCallBrInst()
   GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I);
   friend GetElementPtrInst; // For createGetElementPtrInst()
+  AllocaInst *createAllocaInst(llvm::AllocaInst *I);
+  friend AllocaInst; // For createAllocaInst()
   CastInst *createCastInst(llvm::CastInst *I);
   friend CastInst; // For createCastInst()
   PHINode *createPHINode(llvm::PHINode *I);
diff --git a/llvm/include/llvm/SandboxIR/SandboxIRValues.def b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
index 4cb601128a507..3b16bdee6d15c 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIRValues.def
+++ b/llvm/include/llvm/SandboxIR/SandboxIRValues.def
@@ -43,6 +43,7 @@ DEF_INSTR(Call,          OP(Call),          CallInst)
 DEF_INSTR(Invoke,        OP(Invoke),        InvokeInst)
 DEF_INSTR(CallBr,        OP(CallBr),        CallBrInst)
 DEF_INSTR(GetElementPtr, OP(GetElementPtr), GetElementPtrInst)
+DEF_INSTR(Alloca,        OP(Alloca),        AllocaInst)
 DEF_INSTR(Cast,  OPCODES(\
                          OP(ZExt)          \
                          OP(SExt)          \
diff --git a/llvm/include/llvm/SandboxIR/Tracker.h b/llvm/include/llvm/SandboxIR/Tracker.h
index 3c491bf0b3f58..3fb52439caef2 100644
--- a/llvm/include/llvm/SandboxIR/Tracker.h
+++ b/llvm/include/llvm/SandboxIR/Tracker.h
@@ -58,6 +58,7 @@ class LoadInst;
 class StoreInst;
 class Instruction;
 class Tracker;
+class AllocaInst;
 
 /// The base class for IR Change classes.
 class IRChangeBase {
@@ -255,6 +256,74 @@ class CallBrInstSetDefaultDest : public IRChangeBase {
 #endif
 };
 
+class AllocaSetAllocatedType final : public IRChangeBase {
+  AllocaInst *Alloca;
+  Type *OrigType;
+
+public:
+  AllocaSetAllocatedType(AllocaInst *Alloca, Tracker &Tracker);
+  void revert() final;
+  void accept() final {}
+#ifndef NDEBUG
+  void dump(raw_ostream &OS) const final {
+    dumpCommon(OS);
+    OS << "AllocaSetAllocatedType";
+  }
+  LLVM_DUMP_METHOD void dump() const final;
+#endif
+};
+
+class AllocaSetAlignment final : public IRChangeBase {
+  AllocaInst *Alloca;
+  Align OrigAlign;
+
+public:
+  AllocaSetAlignment(AllocaInst *Alloca, Tracker &Tracker);
+  void revert() final;
+  void accept() final {}
+#ifndef NDEBUG
+  void dump(raw_ostream &OS) const final {
+    dumpCommon(OS);
+    OS << "AllocaSetAlignment";
+  }
+  LLVM_DUMP_METHOD void dump() const final;
+#endif
+};
+
+class AllocaSetUsedWithInAlloca final : public IRChangeBase {
+  AllocaInst *Alloca;
+  bool Orig;
+
+public:
+  AllocaSetUsedWithInAlloca(AllocaInst *Alloca, Tracker &Tracker);
+  void revert() final;
+  void accept() final {}
+#ifndef NDEBUG
+  void dump(raw_ostream &OS) const final {
+    dumpCommon(OS);
+    OS << "AllocaSetUsedWithInAlloca";
+  }
+  LLVM_DUMP_METHOD void dump() const final;
+#endif
+};
+
+class AllocaSetSwiftError final : public IRChangeBase {
+  AllocaInst *Alloca;
+  bool Orig;
+
+public:
+  AllocaSetSwiftError(AllocaInst *Alloca, Tracker &Tracker);
+  void revert() final;
+  void accept() final {}
+#ifndef NDEBUG
+  void dump(raw_ostream &OS) const final {
+    dumpCommon(OS);
+    OS << "AllocaSetSwiftError";
+  }
+  LLVM_DUMP_METHOD void dump() const final;
+#endif
+};
+
 class CallBrInstSetIndirectDest : public IRChangeBase {
   CallBrInst *CallBr;
   unsigned Idx;
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 235c4574ead13..afd9d1f87e605 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -1212,6 +1212,80 @@ static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) {
   }
 }
 
+AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
+                               BasicBlock *WhereBB, Context &Ctx,
+                               Value *ArraySize, const Twine &Name) {
+  auto &Builder = Ctx.getLLVMIRBuilder();
+  if (WhereIt == WhereBB->end())
+    Builder.SetInsertPoint(cast<llvm::BasicBlock>(WhereBB->Val));
+  else
+    Builder.SetInsertPoint((*WhereIt).getTopmostLLVMInstruction());
+  auto *NewAlloca = Builder.CreateAlloca(Ty, AddrSpace, ArraySize->Val, Name);
+  return Ctx.createAllocaInst(NewAlloca);
+}
+
+AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
+                               Instruction *InsertBefore, Context &Ctx,
+                               Value *ArraySize, const Twine &Name) {
+  return create(Ty, AddrSpace, InsertBefore->getIterator(),
+                InsertBefore->getParent(), Ctx, ArraySize, Name);
+}
+
+AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
+                               BasicBlock *InsertAtEnd, Context &Ctx,
+                               Value *ArraySize, const Twine &Name) {
+  return create(Ty, AddrSpace, InsertAtEnd->end(), InsertAtEnd, Ctx, ArraySize,
+                Name);
+}
+
+void AllocaInst::setAllocatedType(Type *Ty) {
+  auto &Tracker = Ctx.getTracker();
+  if (Tracker.isTracking())
+    Tracker.track(std::make_unique<AllocaSetAllocatedType>(
+        cast<AllocaInst>(this), Tracker));
+  cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty);
+}
+
+void AllocaInst::setAlignment(Align Align) {
+  auto &Tracker = Ctx.getTracker();
+  if (Tracker.isTracking())
+    Tracker.track(
+        std::make_unique<AllocaSetAlignment>(cast<AllocaInst>(this), Tracker));
+  cast<llvm::AllocaInst>(Val)->setAlignment(Align);
+}
+
+void AllocaInst::setUsedWithInAlloca(bool V) {
+  auto &Tracker = Ctx.getTracker();
+  if (Tracker.isTracking())
+    Tracker.track(std::make_unique<AllocaSetUsedWithInAlloca>(
+        cast<AllocaInst>(this), Tracker));
+  cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
+}
+
+void AllocaInst::setSwiftError(bool V) {
+  auto &Tracker = Ctx.getTracker();
+  if (Tracker.isTracking())
+    Tracker.track(
+        std::make_unique<AllocaSetSwiftError>(cast<AllocaInst>(this), Tracker));
+  cast<llvm::AllocaInst>(Val)->setSwiftError(V);
+}
+
+Value *AllocaInst::getArraySize() {
+  return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());
+}
+
+#ifndef NDEBUG
+void AllocaInst::dump(raw_ostream &OS) const {
+  dumpCommonPrefix(OS);
+  dumpCommonSuffix(OS);
+}
+
+void AllocaInst::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
 Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand,
                         BBIterator WhereIt, BasicBlock *WhereBB, Context &Ctx,
                         const Twine &Name) {
@@ -1452,6 +1526,11 @@ Value *Context::getOrCreateValueInternal(llvm::Value *LLVMV, llvm::User *U) {
         new GetElementPtrInst(LLVMGEP, *this));
     return It->second.get();
   }
+  case llvm::Instruction::Alloca: {
+    auto *LLVMAlloca = cast<llvm::AllocaInst>(LLVMV);
+    It->second = std::unique_ptr<AllocaInst>(new AllocaInst(LLVMAlloca, *this));
+    return It->second.get();
+  }
   case llvm::Instruction::ZExt:
   case llvm::Instruction::SExt:
   case llvm::Instruction::FPToUI:
@@ -1538,7 +1617,10 @@ Context::createGetElementPtrInst(llvm::GetElementPtrInst *I) {
       std::unique_ptr<GetElementPtrInst>(new GetElementPtrInst(I, *this));
   return cast<GetElementPtrInst>(registerValue(std::move(NewPtr)));
 }
-
+AllocaInst *Context::createAllocaInst(llvm::AllocaInst *I) {
+  auto NewPtr = std::unique_ptr<AllocaInst>(new AllocaInst(I, *this));
+  return cast<AllocaInst>(registerValue(std::move(NewPtr)));
+}
 CastInst *Context::createCastInst(llvm::CastInst *I) {
   auto NewPtr = std::unique_ptr<CastInst>(new CastInst(I, *this));
   return cast<CastInst>(registerValue(std::move(NewPtr)));
diff --git a/llvm/lib/SandboxIR/Tracker.cpp b/llvm/lib/SandboxIR/Tracker.cpp
index aa18c21cd03d6..90a9df3c96f31 100644
--- a/llvm/lib/SandboxIR/Tracker.cpp
+++ b/llvm/lib/SandboxIR/Tracker.cpp
@@ -204,6 +204,58 @@ void RemoveFromParent::dump() const {
 }
 #endif
 
+AllocaSetAllocatedType::AllocaSetAllocatedType(AllocaInst *Alloca,
+                                               Tracker &Tracker)
+    : IRChangeBase(Tracker), Alloca(Alloca),
+      OrigType(Alloca->getAllocatedType()) {}
+
+void AllocaSetAllocatedType::revert() { Alloca->setAllocatedType(OrigType); }
+
+#ifndef NDEBUG
+void AllocaSetAllocatedType::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
+AllocaSetAlignment::AllocaSetAlignment(AllocaInst *Alloca, Tracker &Tracker)
+    : IRChangeBase(Tracker), Alloca(Alloca), OrigAlign(Alloca->getAlign()) {}
+
+void AllocaSetAlignment::revert() { Alloca->setAlignment(OrigAlign); }
+
+#ifndef NDEBUG
+void AllocaSetAlignment::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
+AllocaSetUsedWithInAlloca::AllocaSetUsedWithInAlloca(AllocaInst *Alloca,
+                                                     Tracker &Tracker)
+    : IRChangeBase(Tracker), Alloca(Alloca),
+      Orig(Alloca->isUsedWithInAlloca()) {}
+
+void AllocaSetUsedWithInAlloca::revert() { Alloca->setUsedWithInAlloca(Orig); }
+
+#ifndef NDEBUG
+void AllocaSetUsedWithInAlloca::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
+AllocaSetSwiftError::AllocaSetSwiftError(AllocaInst *Alloca, Tracker &Tracker)
+    : IRChangeBase(Tracker), Alloca(Alloca), Orig(Alloca->isSwiftError()) {}
+
+void AllocaSetSwiftError::revert() { Alloca->setSwiftError(Orig); }
+
+#ifndef NDEBUG
+void AllocaSetSwiftError::dump() const {
+  dump(dbgs());
+  dbgs() << "\n";
+}
+#endif // NDEBUG
+
 CallBrInstSetDefaultDest::CallBrInstSetDefaultDest(CallBrInst *CallBr,
                                                    Tracker &Tracker)
     : IRChangeBase(Tracker), CallBr(CallBr) {
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index 550c0576e0237..d53e6d872e628 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1475,6 +1475,154 @@ define void @foo(ptr %ptr, <2 x ptr> %ptrs) {
   EXPECT_EQ(NewGEP2->getNextNode(), nullptr);
 }
 
+TEST_F(SandboxIRTest, AllocaInst) {
+  parseIR(C, R"IR(
+define void @foo() {
+  %allocaScalar = alloca i32, align 1024
+  %allocaArray = alloca i32, i32 42
+  ret void
+}
+)IR");
+  DataLayout DL(M.get());
+  llvm::Function &LLVMF = *M->getFunction("foo");
+  llvm::BasicBlock *LLVMBB = &*LLVMF.begin();
+  auto LLVMIt = LLVMBB->begin();
+  auto *LLVMAllocaScalar = cast<llvm::AllocaInst>(&*LLVMIt++);
+  auto *LLVMAllocaArray = cast<llvm::AllocaInst>(&*LLVMIt++);
+
+  sandboxir::Context Ctx(C);
+  sandboxir::Function *F = Ctx.createFunction(&LLVMF);
+  auto *BB = &*F->begin();
+  auto It = BB->begin();
+  auto *AllocaScalar = cast<sandboxir::AllocaInst>(&*It++);
+  auto *AllocaArray = cast<sandboxir::AllocaInst>(&*It++);
+  auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
+
+  // Check isArrayAllocation().
+  EXPECT_EQ(AllocaScalar->isArrayAllocation(),
+            LLVMAllocaScalar->isArrayAllocation());
+  EXPECT_EQ(AllocaArray->isArrayAllocation(),
+            LLVMAllocaArray->isArrayAllocation());
+  // Check getArraySize().
+  EXPECT_EQ(AllocaScalar->getArraySize(),
+            Ctx.getValue(LLVMAllocaScalar->getArraySize()));
+  EXPECT_EQ(AllocaArray->getArraySize(),
+            Ctx.getValue(LLVMAllocaArray->getArraySize()));
+  // Check getType().
+  EXPECT_EQ(AllocaScalar->getType(), LLVMAllocaScalar->getType());
+  EXPECT_EQ(AllocaArray->getType(), LLVMAllocaArray->getType());
+  // Check getAddressSpace().
+  EXPECT_EQ(AllocaScalar->getAddressSpace(),
+            LLVMAllocaScalar->getAddressSpace());
+  EXPECT_EQ(AllocaArray->getAddressSpace(), LLVMAllocaArray->getAddressSpace());
+  // Check getAllocationSize().
+  EXPECT_EQ(AllocaScalar->getAllocationSize(DL),
+            LLVMAllocaScalar->getAllocationSize(DL));
+  EXPECT_EQ(AllocaArray->getAllocationSize(DL),
+            LLVMAllocaArray->getAllocationSize(DL));
+  // Check getAllocationSizeInBits().
+  EXPECT_EQ(AllocaScalar->getAllocationSizeInBits(DL),
+            LLVMAllocaScalar->getAllocationSizeInBits(DL));
+  EXPECT_EQ(AllocaArray->getAllocationSizeInBits(DL),
+            LLVMAllocaArray->getAllocationSizeInBits(DL));
+  // Check getAllocatedType().
+  EXPECT_EQ(AllocaScalar->getAllocatedType(),
+            LLVMAllocaScalar->getAllocatedType());
+  EXPECT_EQ(AllocaArray->getAllocatedType(),
+            LLVMAllocaArray->getAllocatedType());
+  // Check setAllocatedType().
+  auto *OrigType = AllocaScalar->getAllocatedType();
+  auto *NewType = PointerType::get(C, 0);
+  EXPECT_NE(NewType, OrigType);
+  AllocaScalar->setAllocatedType(NewType);
+  EXPECT_EQ(AllocaScalar->getAllocatedType(), NewType);
+  AllocaScalar->setAllocatedType(OrigType);
+  EXPECT_EQ(AllocaScalar->getAllocatedType(), OrigType);
+  // Check getAlign().
+  EXPECT_EQ(AllocaScalar->getAlign(), LLVMAllocaScalar->getAlign());
+  EXPECT_EQ(AllocaArray->getAlign(), LLVMAllocaArray->getAlign());
+  // Check setAlignment().
+  Align OrigAlign = AllocaScalar->getAlign();
+  Align NewAlign(16);
+  EXPECT_NE(NewAlign, OrigAlign);
+  AllocaScalar->setAlignment(NewAlign);
+  EXPECT_EQ(AllocaScalar->getAlign(), NewAlign);
+  AllocaScalar->setAlignment(OrigAlign);
+  EXPECT_EQ(AllocaScalar->getAlign(), OrigAlign);
+  // Check isStaticAlloca().
+  EXPECT_EQ(AllocaScalar->isStaticAlloca(), LLVMAllocaScalar->isStaticAlloca());
+  EXPECT_EQ(AllocaArray->isStaticAlloca(), LLVMAllocaArray->isStaticAlloca());
+  // Check isUsedWithInAlloca(), setUsedWithInAlloca().
+  EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(),
+            LLVMAllocaScalar->isUsedWithInAlloca());
+  bool OrigUsedWithInAlloca = AllocaScalar->isUsedWithInAlloca();
+  bool NewUsedWithInAlloca = true;
+  EXPECT_NE(NewUsedWithInAlloca, OrigUsedWithInAlloca);
+  AllocaScalar->setUsedWithInAlloca(NewUsedWithInAlloca);
+  EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), NewUsedWithInAlloca);
+  AllocaScalar->setUsedWithInAlloca(OrigUsedWithInAlloca);
+  EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), OrigUsedWithInAlloca);
+  // Check isSwiftError(), setSwiftError().
+  EXPECT_EQ(AllocaScalar->isSwiftError(), LLVMAllocaScalar->isSwiftError());
+  bool OrigIsSwiftError = AllocaScalar->isSwiftError();
+  bool NewIsSwiftError = true;
+  EXPECT_NE(NewIsSwiftError, OrigIsSwiftError);
+  AllocaScalar->setSwiftError(NewIsSwiftError);
+  EXPECT_EQ(AllocaScalar->isSwiftError(), NewIsSwiftError);
+
+  auto *Ty = Type::getInt32Ty(C);
+  unsigned AddrSpace = 42;
+  auto *PtrTy = PointerType::get(C, AddrSpace);
+  auto *ArraySize = sandboxir::Constant::createInt(Ty, 43, Ctx);
+  {
+    // Check create() WhereIt, WhereBB.
+    auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create(
+        Ty, AddrSpace, /*WhereIt=*/Ret->getIterator(),
+        /*WhereBB=*/Ret->getParent(), Ctx, ArraySize, "NewAlloca1"));
+    // Check getOpcode().
+    EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca);
+    // Check getType().
+    EXPECT_EQ(NewI->getType(), PtrTy);
+    // Check getArraySize().
+    EXPECT_EQ(NewI->getArraySize(), ArraySize);
+    // Check getAddrSpace().
+    EXPECT_EQ(NewI->getAddressSpace(), AddrSpace);
+    // Check instr position.
+    EXPECT_EQ(NewI->getNextNode(), Ret);
+  }
+  {
+    // Check create() InsertBefore.
+    auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create(
+        Ty, AddrSpace, /*InsertBefore=*/Ret, Ctx, ArraySize, "NewAlloca2"));
+    // Check getOpcode().
+    EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca);
+    // Check getType().
+    EXPECT_EQ(NewI->getType(), PtrTy);
+    // Check getArraySize().
+    EXPECT_EQ(NewI->getArraySize(), ArraySize);
+    // Check getAddrSpace().
+    EXPECT_EQ(NewI->getAddressSpace(), AddrSpace);
+    // Check instr position.
+    EXPECT_EQ(NewI->getNextNode(), Ret);
+  }
+  {
+    // Check create() InsertAtEnd.
+    auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create(
+        Ty, AddrSpace, /*InsertAtEnd=*/BB, Ctx, ArraySize, "NewAlloca3"));
+    // Check getOpcode().
+    EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca);
+    // Check getType().
+    EXPECT_EQ(NewI->getType(), PtrTy);
+    // Check getArraySize().
+    EXPECT_EQ(NewI->getArraySize(), ArraySize);
+    // Check getAddrSpace().
+    EXPECT_EQ(NewI->getAddressSpace(), AddrSpace);
+    // Check instr position.
+    EXPECT_EQ(NewI->getParent(), BB);
+    EXPECT_EQ(NewI->getNextNode(), nullptr);
+  }
+}
+
 TEST_F(SandboxIRTest, CastInst) {
   parseIR(C, R"IR(
 define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) {
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index e61258392a388..12dc6f452504f 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -644,6 +644,61 @@ define void @foo(i8 %arg) {
   EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);
 }
 
+TEST_F(TrackerTest, AllocaInstSetters) {
+  parseIR(C, R"IR(
+define void @foo(i8 %arg) {
+  %alloca = alloca i32, align 64
+  ret void
+}
+)IR");
+  Function &LLVMF = *M->getFunction("foo");
+  sandboxir::Context Ctx(C);
+  auto &F = *Ctx.createFunction(&LLVMF);
+  auto *BB = &*F.begin();
+  auto It = BB->begin();
+  auto *Alloca = cast<sandboxir::AllocaInst>(&*It++);
+
+  // Check setAllocatedType().
+  Ctx.save();
+  auto *OrigTy = Alloca->getAllocatedType();
+  auto *NewTy = Type::getInt64Ty(C);
+  EXPECT_NE(NewTy, OrigTy);
+  Alloca->setAllocatedType(NewTy);
+  EXPECT_EQ(Alloca->getAllocatedType(), NewTy);
+  Ctx.revert();
+  EXPECT_EQ(Alloca->getAllocatedType(), OrigTy);
+
+  // Check setAlignment().
+  Ctx.save();
+  auto OrigAlign = Alloca->getAlign();
+  Align NewAlign(128);
+  EXPECT_NE(NewAlign, OrigAlign);
+  Alloca->setAlignment(NewAlign);
+  EXPECT_EQ(Alloca->getAlign(), NewAlign);
+  Ctx.revert();
+  EXPECT_EQ(Alloca->getAlign(), OrigAlign);
+
+  // Check setUsedWithInAlloca().
+  Ctx.save();
+  auto OrigWIA = Alloca->isUsedWithInAlloca();
+  bool NewWIA = true;
+  EXPECT_NE(NewWIA, OrigWIA);
+  Alloca->setUsedWithInAlloca(NewWIA);
+  EXPECT_EQ(Alloca->isUsedWithInAlloca(), NewWIA);
+  Ctx.revert();
+  EXPECT_EQ(Alloca->isUsedWithInAlloca(), OrigWIA);
+
+  // Check setSwiftError().
+  Ctx.save();
+  auto OrigSE = Alloca->isSwiftError();
+  bool NewSE = true;
+  EXPECT_NE(NewSE, OrigSE);
+  Alloca->setSwiftError(NewSE);
+  EXPECT_EQ(Alloca->isSwiftError(), NewSE);
+  Ctx.revert();
+  EXPECT_EQ(Alloca->isSwiftError(), OrigSE);
+}
+
 TEST_F(TrackerTest, CallBrSetters) {
   parseIR(C, R"IR(
 define void @foo(i8 %arg) {

>From c1da45687a2549d5e238c1a225d39cff38b0d28d Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Mon, 5 Aug 2024 11:20:20 -0700
Subject: [PATCH 2/3] fixup! [SandboxIR] Implement AllocaInst

Remove redundant cast<AllocaInst>(this).
---
 llvm/lib/SandboxIR/SandboxIR.cpp | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index afd9d1f87e605..e3017b15a7205 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -1241,32 +1241,28 @@ AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace,
 void AllocaInst::setAllocatedType(Type *Ty) {
   auto &Tracker = Ctx.getTracker();
   if (Tracker.isTracking())
-    Tracker.track(std::make_unique<AllocaSetAllocatedType>(
-        cast<AllocaInst>(this), Tracker));
+    Tracker.track(std::make_unique<AllocaSetAllocatedType>(this, Tracker));
   cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty);
 }
 
 void AllocaInst::setAlignment(Align Align) {
   auto &Tracker = Ctx.getTracker();
   if (Tracker.isTracking())
-    Tracker.track(
-        std::make_unique<AllocaSetAlignment>(cast<AllocaInst>(this), Tracker));
+    Tracker.track(std::make_unique<AllocaSetAlignment>(this, Tracker));
   cast<llvm::AllocaInst>(Val)->setAlignment(Align);
 }
 
 void AllocaInst::setUsedWithInAlloca(bool V) {
   auto &Tracker = Ctx.getTracker();
   if (Tracker.isTracking())
-    Tracker.track(std::make_unique<AllocaSetUsedWithInAlloca>(
-        cast<AllocaInst>(this), Tracker));
+    Tracker.track(std::make_unique<AllocaSetUsedWithInAlloca>(this, Tracker));
   cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
 }
 
 void AllocaInst::setSwiftError(bool V) {
   auto &Tracker = Ctx.getTracker();
   if (Tracker.isTracking())
-    Tracker.track(
-        std::make_unique<AllocaSetSwiftError>(cast<AllocaInst>(this), Tracker));
+    Tracker.track(std::make_unique<AllocaSetSwiftError>(this, Tracker));
   cast<llvm::AllocaInst>(Val)->setSwiftError(V);
 }
 

>From 784d198649e50aa03d611b28a596e00b9d467828 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Tue, 6 Aug 2024 10:38:42 -0700
Subject: [PATCH 3/3] fixup! fixup! [SandboxIR] Implement AllocaInst

---
 llvm/include/llvm/SandboxIR/SandboxIR.h    |  9 ++-------
 llvm/include/llvm/SandboxIR/Tracker.h      | 17 -----------------
 llvm/lib/SandboxIR/SandboxIR.cpp           |  7 -------
 llvm/lib/SandboxIR/Tracker.cpp             | 12 ------------
 llvm/unittests/SandboxIR/SandboxIRTest.cpp |  7 -------
 llvm/unittests/SandboxIR/TrackerTest.cpp   | 10 ----------
 6 files changed, 2 insertions(+), 60 deletions(-)

diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 89741894b95ef..1f488adbf5021 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -1404,11 +1404,12 @@ class AllocaInst final : public UnaryInstruction {
     return {cast<llvm::Instruction>(Val)};
   }
 
-public:
   AllocaInst(llvm::AllocaInst *AI, Context &Ctx)
       : UnaryInstruction(ClassID::Alloca, Instruction::Opcode::Alloca, AI,
                          Ctx) {}
+  friend class Context; // For constructor.
 
+public:
   static AllocaInst *create(Type *Ty, unsigned AddrSpace, BBIterator WhereIt,
                             BasicBlock *WhereBB, Context &Ctx,
                             Value *ArraySize = nullptr, const Twine &Name = "");
@@ -1477,12 +1478,6 @@ class AllocaInst final : public UnaryInstruction {
   }
   /// Specify whether this alloca is used to represent the arguments to a call.
   void setUsedWithInAlloca(bool V);
-  /// Return true if this alloca is used as a swifterror argument to a call.
-  bool isSwiftError() const {
-    return cast<llvm::AllocaInst>(Val)->isSwiftError();
-  }
-  /// Specify whether this alloca is used to represent a swifterror.
-  void setSwiftError(bool V);
 
   static bool classof(const Value *From) {
     if (auto *I = dyn_cast<Instruction>(From))
diff --git a/llvm/include/llvm/SandboxIR/Tracker.h b/llvm/include/llvm/SandboxIR/Tracker.h
index 3fb52439caef2..af6d015a81518 100644
--- a/llvm/include/llvm/SandboxIR/Tracker.h
+++ b/llvm/include/llvm/SandboxIR/Tracker.h
@@ -307,23 +307,6 @@ class AllocaSetUsedWithInAlloca final : public IRChangeBase {
 #endif
 };
 
-class AllocaSetSwiftError final : public IRChangeBase {
-  AllocaInst *Alloca;
-  bool Orig;
-
-public:
-  AllocaSetSwiftError(AllocaInst *Alloca, Tracker &Tracker);
-  void revert() final;
-  void accept() final {}
-#ifndef NDEBUG
-  void dump(raw_ostream &OS) const final {
-    dumpCommon(OS);
-    OS << "AllocaSetSwiftError";
-  }
-  LLVM_DUMP_METHOD void dump() const final;
-#endif
-};
-
 class CallBrInstSetIndirectDest : public IRChangeBase {
   CallBrInst *CallBr;
   unsigned Idx;
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index e3017b15a7205..ad76698efa709 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -1259,13 +1259,6 @@ void AllocaInst::setUsedWithInAlloca(bool V) {
   cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V);
 }
 
-void AllocaInst::setSwiftError(bool V) {
-  auto &Tracker = Ctx.getTracker();
-  if (Tracker.isTracking())
-    Tracker.track(std::make_unique<AllocaSetSwiftError>(this, Tracker));
-  cast<llvm::AllocaInst>(Val)->setSwiftError(V);
-}
-
 Value *AllocaInst::getArraySize() {
   return Ctx.getValue(cast<llvm::AllocaInst>(Val)->getArraySize());
 }
diff --git a/llvm/lib/SandboxIR/Tracker.cpp b/llvm/lib/SandboxIR/Tracker.cpp
index 90a9df3c96f31..90c48a3683d83 100644
--- a/llvm/lib/SandboxIR/Tracker.cpp
+++ b/llvm/lib/SandboxIR/Tracker.cpp
@@ -244,18 +244,6 @@ void AllocaSetUsedWithInAlloca::dump() const {
 }
 #endif // NDEBUG
 
-AllocaSetSwiftError::AllocaSetSwiftError(AllocaInst *Alloca, Tracker &Tracker)
-    : IRChangeBase(Tracker), Alloca(Alloca), Orig(Alloca->isSwiftError()) {}
-
-void AllocaSetSwiftError::revert() { Alloca->setSwiftError(Orig); }
-
-#ifndef NDEBUG
-void AllocaSetSwiftError::dump() const {
-  dump(dbgs());
-  dbgs() << "\n";
-}
-#endif // NDEBUG
-
 CallBrInstSetDefaultDest::CallBrInstSetDefaultDest(CallBrInst *CallBr,
                                                    Tracker &Tracker)
     : IRChangeBase(Tracker), CallBr(CallBr) {
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index d53e6d872e628..4b3325d9436ef 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1562,13 +1562,6 @@ define void @foo() {
   EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), NewUsedWithInAlloca);
   AllocaScalar->setUsedWithInAlloca(OrigUsedWithInAlloca);
   EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), OrigUsedWithInAlloca);
-  // Check isSwiftError(), setSwiftError().
-  EXPECT_EQ(AllocaScalar->isSwiftError(), LLVMAllocaScalar->isSwiftError());
-  bool OrigIsSwiftError = AllocaScalar->isSwiftError();
-  bool NewIsSwiftError = true;
-  EXPECT_NE(NewIsSwiftError, OrigIsSwiftError);
-  AllocaScalar->setSwiftError(NewIsSwiftError);
-  EXPECT_EQ(AllocaScalar->isSwiftError(), NewIsSwiftError);
 
   auto *Ty = Type::getInt32Ty(C);
   unsigned AddrSpace = 42;
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index 12dc6f452504f..36b7c8be3446b 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -687,16 +687,6 @@ define void @foo(i8 %arg) {
   EXPECT_EQ(Alloca->isUsedWithInAlloca(), NewWIA);
   Ctx.revert();
   EXPECT_EQ(Alloca->isUsedWithInAlloca(), OrigWIA);
-
-  // Check setSwiftError().
-  Ctx.save();
-  auto OrigSE = Alloca->isSwiftError();
-  bool NewSE = true;
-  EXPECT_NE(NewSE, OrigSE);
-  Alloca->setSwiftError(NewSE);
-  EXPECT_EQ(Alloca->isSwiftError(), NewSE);
-  Ctx.revert();
-  EXPECT_EQ(Alloca->isSwiftError(), OrigSE);
 }
 
 TEST_F(TrackerTest, CallBrSetters) {



More information about the llvm-commits mailing list