[llvm] [IR] Add helpers to AllocaInst to avoid getAllocatedType(). (PR #219594)

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 15:54:18 PDT 2026


https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/219594

Add AllocaInst::getAllocationBaseSize() and AllocaInst::isScalable(), which represent common patterns for uses which only need the size of an alloca, but can't use getAllocationSize().

This only replaces uses which are equivalent.  (There are a couple of places in DebugInfo which getTypeSizeInBits(), which is not equivalent, so this patch doesn't touch them for now.)

>From 87deccbabd925942ba0c27f0a4653d23bc4fc7f2 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at qti.qualcomm.com>
Date: Fri, 28 Aug 2026 15:25:13 -0700
Subject: [PATCH] [IR] Add helpers to AllocaInst to avoid getAllocatedType().

Add getAllocationBaseSize() and isScalable(), which represent common
patterns for uses which only need the size of an alloca, but can't use
getAllocationSize().

This only replaces uses which are exactly equivalent.
---
 llvm/include/llvm/IR/Instructions.h                   |  7 +++++++
 llvm/lib/Analysis/InlineCost.cpp                      |  3 +--
 llvm/lib/Analysis/MemoryBuiltins.cpp                  |  7 ++-----
 llvm/lib/Analysis/StackSafetyAnalysis.cpp             |  2 +-
 llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp          |  3 +--
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp |  3 +--
 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp    | 10 ++++------
 llvm/lib/IR/DebugInfo.cpp                             |  2 +-
 llvm/lib/IR/IRBuilder.cpp                             |  2 +-
 llvm/lib/IR/Instructions.cpp                          |  6 +++++-
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp       |  2 +-
 llvm/lib/Transforms/IPO/Instrumentor.cpp              |  2 +-
 .../Transforms/Instrumentation/AddressSanitizer.cpp   | 11 +++--------
 llvm/tools/llubi/lib/Interpreter.cpp                  |  2 +-
 14 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 0475798b9463d..6e34d717f4397 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -118,6 +118,13 @@ class AllocaInst : public UnaryInstruction {
   LLVM_ABI std::optional<TypeSize>
   getAllocationSizeInBits(const DataLayout &DL) const;
 
+  /// Get the size of the allocated type.  (This is the allocation size
+  /// ignoring the array size.)
+  LLVM_ABI TypeSize getAllocationBaseSize(const DataLayout &DL) const;
+
+  // Get whether the allocated type is a scalable type.
+  bool isScalable() const { return AllocatedType->isScalableTy(); }
+
   /// Return the type that is being allocated by the instruction.
   Type *getAllocatedType() const { return AllocatedType; }
   /// for use only in special circumstances that need to generically
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index de6c2456f0d57..d4f4d937aa06a 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -1588,10 +1588,9 @@ bool CallAnalyzer::visitAlloca(AllocaInst &I) {
       // being too pessimistic and prevent inlining non-problematic code. This
       // could result in unintended perf regressions. A better overall strategy
       // is needed to track stack usage during inlining.
-      Type *Ty = I.getAllocatedType();
       AllocatedSize = SaturatingMultiplyAdd(
           AllocSize->getLimitedValue(),
-          DL.getTypeAllocSize(Ty).getKnownMinValue(), AllocatedSize);
+          I.getAllocationBaseSize(DL).getKnownMinValue(), AllocatedSize);
       if (AllocatedSize > InlineConstants::MaxSimplifiedDynamicAllocaToInline)
         HasDynamicAlloca = true;
       return false;
diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
index b7f2ee74721fe..e208b3d9317b6 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -937,7 +937,7 @@ bool ObjectSizeOffsetVisitor::checkedZextOrTrunc(APInt &I) {
 }
 
 OffsetSpan ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
-  TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
+  TypeSize ElemSize = I.getAllocationBaseSize(DL);
   if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
     return ObjectSizeOffsetVisitor::unknown();
   if (!isUIntN(IntTyBits, ElemSize.getKnownMinValue()))
@@ -1324,11 +1324,8 @@ SizeOffsetValue ObjectSizeOffsetEvaluator::compute_(Value *V) {
 }
 
 SizeOffsetValue ObjectSizeOffsetEvaluator::visitAllocaInst(AllocaInst &I) {
-  if (!I.getAllocatedType()->isSized())
-    return ObjectSizeOffsetEvaluator::unknown();
-
   // must be a VLA or vscale.
-  assert(I.isArrayAllocation() || I.getAllocatedType()->isScalableTy());
+  assert(I.isArrayAllocation() || I.isScalable());
 
   // If needed, adjust the alloca's operand size to match the pointer indexing
   // size. Subsequent math operations expect the types to match.
diff --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
index 9c20019677895..5a9832aaf65a7 100644
--- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp
+++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
@@ -152,7 +152,7 @@ raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) {
 // in case of confution.
 ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) {
   const DataLayout &DL = AI.getDataLayout();
-  TypeSize TS = DL.getTypeAllocSize(AI.getAllocatedType());
+  TypeSize TS = AI.getAllocationBaseSize(DL);
   unsigned PointerSize = DL.getPointerTypeSizeInBits(AI.getType());
   // Fallback to empty range for alloca size.
   ConstantRange R = ConstantRange::getEmpty(PointerSize);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 0a9d6926410c2..f498c78528e40 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -4031,8 +4031,7 @@ bool IRTranslatorImpl::translateAlloca(const User &U,
     NumElts = ExtElts;
   }
 
-  Type *Ty = AI.getAllocatedType();
-  TypeSize TySize = DL->getTypeAllocSize(Ty);
+  TypeSize TySize = AI.getAllocationBaseSize(*DL);
 
   Register AllocSize = MRI->createGenericVirtualRegister(IntPtrTy);
   Register TySizeReg;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 4f990e1ff5b9e..c555f0aa0e9c1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4663,10 +4663,9 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) {
     return;   // getValue will auto-populate this.
 
   SDLoc dl = getCurSDLoc();
-  Type *Ty = I.getAllocatedType();
   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
   auto &DL = DAG.getDataLayout();
-  TypeSize TySize = DL.getTypeAllocSize(Ty);
+  TypeSize TySize = I.getAllocationBaseSize(DL);
   MaybeAlign Alignment = I.getAlign();
 
   SDValue AllocSize = getValue(I.getArraySize());
diff --git a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
index 78d1bf1332383..6b936b0edda17 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -979,13 +979,11 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){
 void Interpreter::visitAllocaInst(AllocaInst &I) {
   ExecutionContext &SF = ECStack.back();
 
-  Type *Ty = I.getAllocatedType(); // Type to be allocated
-
   // Get the number of elements being allocated by the array...
   unsigned NumElements =
     getOperandValue(I.getOperand(0), SF).IntVal.getZExtValue();
 
-  unsigned TypeSize = (size_t)getDataLayout().getTypeAllocSize(Ty);
+  unsigned TypeSize = (size_t)I.getAllocationBaseSize(getDataLayout());
 
   // Avoid malloc-ing zero bytes, use max()...
   unsigned MemToAlloc = std::max(1U, NumElements * TypeSize);
@@ -993,9 +991,9 @@ void Interpreter::visitAllocaInst(AllocaInst &I) {
   // Allocate enough memory to hold the type...
   void *Memory = safe_malloc(MemToAlloc);
 
-  LLVM_DEBUG(dbgs() << "Allocated Type: " << *Ty << " (" << TypeSize
-                    << " bytes) x " << NumElements << " (Total: " << MemToAlloc
-                    << ") at " << uintptr_t(Memory) << '\n');
+  LLVM_DEBUG(dbgs() << "Allocation: (" << TypeSize << " bytes) x "
+                    << NumElements << " (Total: " << MemToAlloc << ") at "
+                    << uintptr_t(Memory) << '\n');
 
   GenericValue Result = PTOGV(Memory);
   assert(Result.PointerVal && "Null pointer returned by malloc!");
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 25852faada2b8..bbc06e8d73157 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -2135,7 +2135,7 @@ getAssignmentInfoImpl(const DataLayout &DL, const Value *StoreDest,
   if (OffsetInBytes == UINT64_MAX)
     return std::nullopt;
   if (const auto *Alloca = dyn_cast<AllocaInst>(Base))
-    if (!DL.getTypeSizeInBits(Alloca->getAllocatedType()).isScalable())
+    if (!Alloca->isScalable())
       return AssignmentInfo(DL, Alloca, OffsetInBytes * 8, SizeInBits);
   return std::nullopt;
 }
diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index df738faad7842..45ef8fa1b1835 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -211,7 +211,7 @@ Value *IRBuilderBase::CreateTypeSize(Type *Ty, TypeSize Size) {
 
 Value *IRBuilderBase::CreateAllocationSize(Type *DestTy, AllocaInst *AI) {
   const DataLayout &DL = BB->getDataLayout();
-  TypeSize ElemSize = DL.getTypeAllocSize(AI->getAllocatedType());
+  TypeSize ElemSize = AI->getAllocationBaseSize(DL);
   Value *Size = CreateTypeSize(DestTy, ElemSize);
   if (AI->isArrayAllocation())
     Size = CreateMul(CreateZExtOrTrunc(AI->getArraySize(), DestTy), Size);
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index dd6bbb5fe0e90..325850b0a880d 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -61,9 +61,13 @@ static cl::opt<bool> DisableI2pP2iOpt(
 //                            AllocaInst Class
 //===----------------------------------------------------------------------===//
 
+TypeSize AllocaInst::getAllocationBaseSize(const DataLayout &DL) const {
+  return DL.getTypeAllocSize(getAllocatedType());
+}
+
 std::optional<TypeSize>
 AllocaInst::getAllocationSize(const DataLayout &DL) const {
-  TypeSize Size = DL.getTypeAllocSize(getAllocatedType());
+  TypeSize Size = getAllocationBaseSize(DL);
   // Zero-sized types can return early since 0 * N = 0 for any array size N.
   if (Size.isZero())
     return Size;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index d1935cd87ebee..1d354ea31e744 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -33615,7 +33615,7 @@ bool AArch64TargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
         return true;
 
     if (const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
-      if (AI->getAllocatedType()->isScalableTy())
+      if (AI->isScalable())
         return true;
     }
   }
diff --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp
index 865571cb563d3..c85f64baa21f1 100644
--- a/llvm/lib/Transforms/IPO/Instrumentor.cpp
+++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp
@@ -1174,7 +1174,7 @@ Value *AllocaIO::getSize(Value &V, Type &Ty, InstrumentationConfig &IO,
   auto &AI = cast<AllocaInst>(V);
   const DataLayout &DL = AI.getDataLayout();
   Value *SizeValue = nullptr;
-  TypeSize TypeSize = DL.getTypeAllocSize(AI.getAllocatedType());
+  TypeSize TypeSize = AI.getAllocationBaseSize(DL);
   if (TypeSize.isFixed()) {
     SizeValue = getCI(&Ty, TypeSize.getFixedValue());
   } else {
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 06d60003631d0..c5576f31cfe46 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1228,10 +1228,7 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
   /// Collect Alloca instructions we want (and can) handle.
   void visitAllocaInst(AllocaInst &AI) {
     // FIXME: Handle scalable vectors instead of ignoring them.
-    const Type *AllocaType = AI.getAllocatedType();
-    const auto *STy = dyn_cast<StructType>(AllocaType);
-    if (!ASan.isInterestingAlloca(AI) || isa<ScalableVectorType>(AllocaType) ||
-        (STy && STy->containsHomogeneousScalableVectorTypes())) {
+    if (!ASan.isInterestingAlloca(AI) || AI.isScalable()) {
       if (AI.isStaticAlloca()) {
         // Skip over allocas that are present *before* the first instrumented
         // alloca, we don't want to move those around.
@@ -1473,10 +1470,8 @@ bool AddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
   if (!Inserted)
     return It->getSecond();
 
-  bool IsInteresting =
-      (AI.getAllocatedType()->isSized() &&
-       // alloca() may be called with 0 size, ignore it.
-       ((!AI.isStaticAlloca()) || !getAllocaSizeInBytes(AI).isZero()) &&
+  bool IsInteresting = // alloca() may be called with 0 size, ignore it.
+      (((!AI.isStaticAlloca()) || !getAllocaSizeInBytes(AI).isZero()) &&
        // We are only interested in allocas not promotable to registers.
        // Promotable allocas are common under -O0.
        (!ClSkipPromotableAllocas || !isAllocaPromotable(&AI)) &&
diff --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index 387e6aa062803..00366b0fc14c1 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -2625,7 +2625,7 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
   }
 
   void visitAllocaInst(AllocaInst &AI) {
-    uint64_t AllocSize = Ctx.getEffectiveTypeAllocSize(AI.getAllocatedType());
+    uint64_t AllocSize = Ctx.getEffectiveTypeSize(AI.getAllocationBaseSize(DL));
     if (AI.isArrayAllocation()) {
       auto &Size = getValue(AI.getArraySize());
       if (Size.isPoison()) {



More information about the llvm-commits mailing list