[llvm] [GlobalISel] Add SVE support for alloca (PR #178976)
Jameson Nash via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 31 12:48:59 PST 2026
https://github.com/vtjnash updated https://github.com/llvm/llvm-project/pull/178976
>From 7698a351138b40fa459170c16cb5efd4335beacb Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Wed, 28 Jan 2026 19:22:07 +0000
Subject: [PATCH] [GlobalISel] Add SVE support for alloca
Complementary to the same handling in SelectionDAG.
Co-Authored-By: Claude Sonnet 4.5 <noreply at anthropic.com>
---
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 29 +++++++++++++++----
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 5 ----
.../irtranslator-dynamic-alloca-scalable.ll | 14 +++++++++
.../RISCV/GlobalISel/irtranslator/alloca.ll | 15 ++++++++++
.../RISCV/GlobalISel/irtranslator/fallback.ll | 11 -------
5 files changed, 53 insertions(+), 21 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-dynamic-alloca-scalable.ll
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/alloca.ll
delete mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/fallback.ll
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index a0fe900778cca..a4e26628fe6ff 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -258,14 +258,24 @@ int IRTranslator::getOrCreateFrameIndex(const AllocaInst &AI) {
if (!Inserted)
return MapEntry->second;
- uint64_t Size =
- AI.getAllocationSize(*DL).value_or(TypeSize::getZero()).getFixedValue();
+ TypeSize TySize = AI.getAllocationSize(*DL).value_or(TypeSize::getZero());
+ uint64_t Size = TySize.getKnownMinValue();
// Always allocate at least one byte.
Size = std::max<uint64_t>(Size, 1u);
int &FI = MapEntry->second;
FI = MF->getFrameInfo().CreateStackObject(Size, AI.getAlign(), false, &AI);
+
+ // Scalable vectors and structures that contain scalable vectors may
+ // need a special StackID to distinguish them from other (fixed size)
+ // stack objects.
+ if (TySize.isScalable()) {
+ auto StackID =
+ MF->getSubtarget().getFrameLowering()->getStackIDForScalableVectors();
+ MF->getFrameInfo().setStackID(FI, StackID);
+ }
+
return FI;
}
@@ -3197,11 +3207,20 @@ bool IRTranslator::translateAlloca(const User &U,
}
Type *Ty = AI.getAllocatedType();
+ TypeSize TySize = DL->getTypeAllocSize(Ty);
Register AllocSize = MRI->createGenericVirtualRegister(IntPtrTy);
- Register TySize =
- getOrCreateVReg(*ConstantInt::get(IntPtrIRTy, DL->getTypeAllocSize(Ty)));
- MIRBuilder.buildMul(AllocSize, NumElts, TySize);
+ Register TySizeReg;
+ if (TySize.isScalable()) {
+ // For scalable types, use vscale * min_value
+ TySizeReg = MRI->createGenericVirtualRegister(IntPtrTy);
+ MIRBuilder.buildVScale(TySizeReg, TySize.getKnownMinValue());
+ } else {
+ // For fixed types, use a constant
+ TySizeReg =
+ getOrCreateVReg(*ConstantInt::get(IntPtrIRTy, TySize.getFixedValue()));
+ }
+ MIRBuilder.buildMul(AllocSize, NumElts, TySizeReg);
// Round the size of the allocation up to the stack alignment size
// by add SA-1 to the size. This doesn't overflow because we're computing
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 90809828e9653..742c5bc4372b2 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -25934,11 +25934,6 @@ bool RISCVTargetLowering::fallBackToDAGISel(const Instruction &Inst) const {
!isa<ReturnInst>(&Inst))
return true;
- if (const AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
- if (AI->getAllocatedType()->isScalableTy())
- return true;
- }
-
return false;
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-dynamic-alloca-scalable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-dynamic-alloca-scalable.ll
new file mode 100644
index 0000000000000..04bf589a17505
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-dynamic-alloca-scalable.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -mtriple=aarch64 -mattr=+sve -global-isel -aarch64-enable-gisel-sve %s -o - -stop-after=irtranslator | FileCheck %s
+; Tests for scalable vector allocas in GlobalISel
+
+; Test basic scalable vector alloca (single allocation)
+define ptr @test_single_scalable_alloca() {
+ ; CHECK-LABEL: name: test_single_scalable_alloca
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.local0
+ ; CHECK-NEXT: $x0 = COPY [[FRAME_INDEX]](p0)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %local0 = alloca <vscale x 16 x i8>
+ ret ptr %local0
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/alloca.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/alloca.ll
new file mode 100644
index 0000000000000..127ba6b804864
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/alloca.ll
@@ -0,0 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -mtriple=riscv64 -mattr=+v -global-isel %s -o - -stop-after=irtranslator | FileCheck %s
+
+; Test that single scalable vector alloca works and store
+define void @test_single_scalable_alloca() {
+ ; CHECK-LABEL: name: test_single_scalable_alloca
+ ; CHECK: bb.1 (%ir-block.0):
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+ ; CHECK-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.local0
+ ; CHECK-NEXT: G_STORE [[C]](s64), [[FRAME_INDEX]](p0) :: (volatile store (s64) into %ir.local0)
+ ; CHECK-NEXT: PseudoRET
+ %local0 = alloca <vscale x 16 x i8>
+ store volatile i64 1, ptr %local0
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/fallback.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/fallback.ll
deleted file mode 100644
index 8e43e044b7ee5..0000000000000
--- a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/fallback.ll
+++ /dev/null
@@ -1,11 +0,0 @@
-; RUN: llc -mtriple=riscv64 -mattr='+v' -O0 -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' -verify-machineinstrs %s -o %t.out 2> %t.err
-; RUN: FileCheck %s --check-prefix=FALLBACK-WITH-REPORT-OUT < %t.out
-; RUN: FileCheck %s --check-prefix=FALLBACK-WITH-REPORT-ERR < %t.err
-
-; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to translate instruction: alloca:
-; FALLBACK-WITH-REPORT-OUT-LABEL: scalable_alloca
-define void @scalable_alloca() #1 {
- %local0 = alloca <vscale x 16 x i8>
- load volatile <vscale x 16 x i8>, ptr %local0
- ret void
-}
More information about the llvm-commits
mailing list