[llvm] [ABI] Thread alloca address space through getNaturalAlignIndirect (PR #225301)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 23:56:45 PDT 2026


https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/225301

>From cc03bc533bd47f5290551a57146739d1e231bc2c Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Tue, 22 Sep 2026 10:41:45 +0530
Subject: [PATCH 1/2] [ABI] Thread alloca address space through
 getNaturalAlignIndirect

---
 llvm/include/llvm/ABI/TargetInfo.h           |  6 +++++-
 llvm/lib/ABI/TargetInfo.cpp                  |  5 +++--
 llvm/lib/ABI/Targets/AArch64.cpp             | 10 ++++++----
 llvm/lib/ABI/Targets/BPF.cpp                 | 10 ++++++----
 llvm/lib/ABI/Targets/X86.cpp                 |  9 +++++----
 llvm/unittests/ABI/AArch64TargetInfoTest.cpp |  2 ++
 llvm/unittests/ABI/X86TargetInfoTest.cpp     |  2 ++
 7 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/ABI/TargetInfo.h b/llvm/include/llvm/ABI/TargetInfo.h
index 956c68ddb7a63..b9dd3087bfaa8 100644
--- a/llvm/include/llvm/ABI/TargetInfo.h
+++ b/llvm/include/llvm/ABI/TargetInfo.h
@@ -80,11 +80,15 @@ class TargetInfo {
   /// store a derived object and return that as an ABICompatInfo reference.
   virtual const ABICompatInfo &getABICompatInfo() const = 0;
 
+  /// Address space in which indirect arguments are allocated (the target's
+  /// alloca/stack space).
+  virtual unsigned getAllocaAddrSpace() const { return 0; }
+
 protected:
   LLVM_ABI RecordArgABI getRecordArgABI(const RecordType *RT) const;
   LLVM_ABI RecordArgABI getRecordArgABI(const Type *Ty) const;
   LLVM_ABI bool isPromotableInteger(const IntegerType *IT) const;
-  LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty,
+  LLVM_ABI ArgInfo getNaturalAlignIndirect(const Type *Ty, unsigned AddrSpace,
                                            bool ByVal = true) const;
   LLVM_ABI bool isAggregateTypeForABI(const Type *Ty) const;
 
diff --git a/llvm/lib/ABI/TargetInfo.cpp b/llvm/lib/ABI/TargetInfo.cpp
index 6fe2b68c001bc..1e03d98880734 100644
--- a/llvm/lib/ABI/TargetInfo.cpp
+++ b/llvm/lib/ABI/TargetInfo.cpp
@@ -41,8 +41,9 @@ bool TargetInfo::isPromotableInteger(const IntegerType *IT) const {
   return BitWidth < 32;
 }
 
-ArgInfo TargetInfo::getNaturalAlignIndirect(const Type *Ty, bool ByVal) const {
-  return ArgInfo::getIndirect(Ty->getAlignment(), ByVal);
+ArgInfo TargetInfo::getNaturalAlignIndirect(const Type *Ty, unsigned AddrSpace,
+                                            bool ByVal) const {
+  return ArgInfo::getIndirect(Ty->getAlignment(), ByVal, AddrSpace);
 }
 
 RecordArgABI TargetInfo::getRecordArgABI(const RecordType *RT) const {
diff --git a/llvm/lib/ABI/Targets/AArch64.cpp b/llvm/lib/ABI/Targets/AArch64.cpp
index 4cdb239f19b41..e529540c8ae11 100644
--- a/llvm/lib/ABI/Targets/AArch64.cpp
+++ b/llvm/lib/ABI/Targets/AArch64.cpp
@@ -88,7 +88,7 @@ ArgInfo AArch64TargetInfo::classifyReturnType(const Type *RetTy,
     if (const auto *IntTy = dyn_cast<IntegerType>(RetTy)) {
       if (IntTy->isBitInt())
         if (RetTy->getSizeInBits().getFixedValue() > 128)
-          return getNaturalAlignIndirect(RetTy);
+          return getNaturalAlignIndirect(RetTy, getAllocaAddrSpace());
 
       if (isPromotableInteger(IntTy) && isDarwinPCS())
         return ArgInfo::getExtend(IntTy);
@@ -128,7 +128,8 @@ ArgInfo AArch64TargetInfo::classifyArgumentType(
     if (const auto *IntTy = dyn_cast<IntegerType>(Ty)) {
       if (IntTy->isBitInt())
         if (Ty->getSizeInBits().getFixedValue() > 128)
-          return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
+          return getNaturalAlignIndirect(Ty, getAllocaAddrSpace(),
+                                         /*ByVal=*/false);
 
       if (isPromotableInteger(IntTy) && isDarwinPCS())
         return ArgInfo::getExtend(IntTy);
@@ -146,8 +147,9 @@ ArgInfo AArch64TargetInfo::classifyArgumentType(
   // Structures with either a non-trivial destructor or a non-trivial
   // copy constructor are always indirect.
   if (auto RecordRAA = getRecordArgABI(Ty)) {
-    return getNaturalAlignIndirect(Ty, RecordRAA ==
-                                           RecordArgABI::RAA_DirectInMemory);
+    return getNaturalAlignIndirect(Ty, getAllocaAddrSpace(),
+                                   /*ByVal=*/RecordRAA ==
+                                       RecordArgABI::RAA_DirectInMemory);
   }
 
   // AAPCS64 does not say that empty C records are ignored as arguments,
diff --git a/llvm/lib/ABI/Targets/BPF.cpp b/llvm/lib/ABI/Targets/BPF.cpp
index ecaf44eed1960..0a525cf28d6f2 100644
--- a/llvm/lib/ABI/Targets/BPF.cpp
+++ b/llvm/lib/ABI/Targets/BPF.cpp
@@ -25,12 +25,14 @@ class BPFTargetInfo : public TargetInfo {
     if (isAggregateTypeForABI(RetTy)) {
       if (RetTy->isZeroSize())
         return ArgInfo::getIgnore();
-      return getNaturalAlignIndirect(RetTy, /*ByVal=*/false);
+      return getNaturalAlignIndirect(RetTy, getAllocaAddrSpace(),
+                                     /*ByVal=*/false);
     }
 
     if (const auto *IntTy = dyn_cast<IntegerType>(RetTy)) {
       if (IntTy->isBitInt() && IntTy->getSizeInBits().getFixedValue() > 128)
-        return getNaturalAlignIndirect(RetTy, /*ByVal=*/false);
+        return getNaturalAlignIndirect(RetTy, getAllocaAddrSpace(),
+                                       /*ByVal=*/false);
     }
 
     return ArgInfo::getDirect();
@@ -57,12 +59,12 @@ class BPFTargetInfo : public TargetInfo {
         return ArgInfo::getDirect(CoerceTy);
       }
 
-      return getNaturalAlignIndirect(ArgTy, /*ByVal=*/true);
+      return getNaturalAlignIndirect(ArgTy, getAllocaAddrSpace());
     }
 
     if (const auto *IntTy = dyn_cast<IntegerType>(ArgTy)) {
       if (IntTy->isBitInt() && IntTy->getSizeInBits().getFixedValue() > 128)
-        return getNaturalAlignIndirect(ArgTy, /*ByVal=*/true);
+        return getNaturalAlignIndirect(ArgTy, getAllocaAddrSpace());
 
       if (isPromotableInteger(IntTy))
         return ArgInfo::getExtend(ArgTy);
diff --git a/llvm/lib/ABI/Targets/X86.cpp b/llvm/lib/ABI/Targets/X86.cpp
index 7f53fff25cb75..b4c4e657939bf 100644
--- a/llvm/lib/ABI/Targets/X86.cpp
+++ b/llvm/lib/ABI/Targets/X86.cpp
@@ -1299,8 +1299,9 @@ ArgInfo X86_64TargetInfo::getIndirectResult(const Type *Ty,
 
   // Check if this is a record type that needs special handling
   if (auto RecordRAA = getRecordArgABI(Ty))
-    return getNaturalAlignIndirect(Ty, RecordRAA ==
-                                           RecordArgABI::RAA_DirectInMemory);
+    return getNaturalAlignIndirect(Ty, getAllocaAddrSpace(),
+                                   /*ByVal=*/RecordRAA ==
+                                       RecordArgABI::RAA_DirectInMemory);
 
   // Compute the byval alignment. We specify the alignment of the byval in all
   // cases so that the mid-level optimizer knows the alignment of the byval.
@@ -1350,14 +1351,14 @@ ArgInfo X86_64TargetInfo::getIndirectReturnResult(const Type *Ty) const {
     // Bit-precise integers are returned indirectly regardless of size.
     if (const auto *IntTy = dyn_cast<IntegerType>(Ty)) {
       if (IntTy->isBitInt())
-        return getNaturalAlignIndirect(IntTy, /*ByVal=*/true);
+        return getNaturalAlignIndirect(IntTy, getAllocaAddrSpace());
       if (isPromotableInteger(IntTy))
         return ArgInfo::getExtend(Ty);
     }
     return ArgInfo::getDirect();
   }
 
-  return getNaturalAlignIndirect(Ty, /*ByVal=*/true);
+  return getNaturalAlignIndirect(Ty, getAllocaAddrSpace());
 }
 
 void X86_64TargetInfo::computeInfo(FunctionInfo &FI) const {
diff --git a/llvm/unittests/ABI/AArch64TargetInfoTest.cpp b/llvm/unittests/ABI/AArch64TargetInfoTest.cpp
index 190477cc636b8..3612865151d18 100644
--- a/llvm/unittests/ABI/AArch64TargetInfoTest.cpp
+++ b/llvm/unittests/ABI/AArch64TargetInfoTest.cpp
@@ -131,6 +131,7 @@ static void expectAlignedIndirect(const ArgInfo &Info, llvm::Align Align,
   EXPECT_TRUE(Info.isIndirect());
   EXPECT_EQ(Info.getIndirectAlign(), Align);
   EXPECT_EQ(Info.getIndirectByVal(), ByVal);
+  EXPECT_EQ(Info.getIndirectAddrSpace(), 0u);
 }
 
 TEST_F(AArch64TargetInfoTest, ClassifyReturnVoidIsIgnore) {
@@ -406,6 +407,7 @@ static void expectNaturalAlignIndirect(const ArgInfo &Info,
   EXPECT_TRUE(Info.isIndirect());
   EXPECT_EQ(Info.getIndirectAlign(), ExpectedAlign);
   EXPECT_EQ(Info.getIndirectByVal(), ByVal);
+  EXPECT_EQ(Info.getIndirectAddrSpace(), 0u);
 }
 
 static void expectHFADirectArg(const ArgInfo &Info, const ABIType *Base,
diff --git a/llvm/unittests/ABI/X86TargetInfoTest.cpp b/llvm/unittests/ABI/X86TargetInfoTest.cpp
index 4cf5bc68cc213..021add1d8ac26 100644
--- a/llvm/unittests/ABI/X86TargetInfoTest.cpp
+++ b/llvm/unittests/ABI/X86TargetInfoTest.cpp
@@ -151,6 +151,7 @@ TEST_F(X86TargetInfoTest, AtomicRecordIsIndirect) {
   ASSERT_TRUE(Info.isIndirect());
   EXPECT_TRUE(Info.getIndirectByVal());
   EXPECT_EQ(Info.getIndirectAlign(), llvm::Align(8));
+  EXPECT_EQ(Info.getIndirectAddrSpace(), 0u);
 }
 
 // Atomic fields classify Memory rather than inheriting the underlying float's
@@ -169,6 +170,7 @@ TEST_F(X86TargetInfoTest, RecordOfAtomicFloatsIsIndirect) {
   ASSERT_TRUE(Info.isIndirect());
   EXPECT_TRUE(Info.getIndirectByVal());
   EXPECT_EQ(Info.getIndirectAlign(), llvm::Align(8));
+  EXPECT_EQ(Info.getIndirectAddrSpace(), 0u);
 }
 
 // Without the atomic wrappers, the same record is passed in an SSE register.

>From 1107a2e774abce3e07d26ed7a45068034d4b68ab Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Wed, 23 Sep 2026 12:25:30 +0530
Subject: [PATCH 2/2] [ABI] Add unit tests for getNaturalAlignIndirect alloca
 address space

---
 llvm/unittests/ABI/TargetInfoTest.cpp | 35 +++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/llvm/unittests/ABI/TargetInfoTest.cpp b/llvm/unittests/ABI/TargetInfoTest.cpp
index c26d2cf6bea9a..e3a03e3b2dfb3 100644
--- a/llvm/unittests/ABI/TargetInfoTest.cpp
+++ b/llvm/unittests/ABI/TargetInfoTest.cpp
@@ -27,6 +27,7 @@ namespace {
 using namespace llvm;
 
 using ABIType = llvm::abi::Type;
+using llvm::abi::ArgInfo;
 using llvm::abi::FieldInfo;
 using llvm::abi::FunctionInfo;
 using llvm::abi::RecordFlags;
@@ -43,12 +44,29 @@ class TestTargetInfo : public TargetInfo {
   const llvm::abi::ABICompatInfo &getABICompatInfo() const override {
     return Compat;
   }
+  using TargetInfo::getNaturalAlignIndirect;
   using TargetInfo::isSingleElementStruct;
 
 private:
   llvm::abi::ABICompatInfo Compat;
 };
 
+// A target whose stack/alloca lives in a non-zero address space, so indirect
+// arguments must be allocated there rather than in AS 0.
+class AllocaAS5TargetInfo : public TargetInfo {
+public:
+  explicit AllocaAS5TargetInfo(TypeBuilder &Builder) : TargetInfo(Builder) {}
+  void computeInfo(FunctionInfo &) const override {}
+  const llvm::abi::ABICompatInfo &getABICompatInfo() const override {
+    return Compat;
+  }
+  unsigned getAllocaAddrSpace() const override { return 5; }
+  using TargetInfo::getNaturalAlignIndirect;
+
+private:
+  llvm::abi::ABICompatInfo Compat;
+};
+
 class TargetInfoTest : public ::testing::Test {
 protected:
   llvm::BumpPtrAllocator Alloc;
@@ -144,4 +162,21 @@ TEST_F(TargetInfoTest, SingleElementStructNonRecordReturnsNull) {
   EXPECT_EQ(singleElement(I32), nullptr);
 }
 
+// Indirect args land in the target's alloca space.
+TEST_F(TargetInfoTest, NaturalAlignIndirectUsesAllocaAddrSpace) {
+  AllocaAS5TargetInfo TI(TB);
+  ArgInfo AI = TI.getNaturalAlignIndirect(I32, TI.getAllocaAddrSpace());
+  EXPECT_TRUE(AI.isIndirect());
+  EXPECT_EQ(AI.getIndirectAddrSpace(), 5u);
+  EXPECT_TRUE(AI.getIndirectByVal());
+}
+
+// The default alloca space is 0, matching classic's DefaultABIInfo.
+TEST_F(TargetInfoTest, NaturalAlignIndirectDefaultsToZeroAddrSpace) {
+  TestTargetInfo TI(TB);
+  ArgInfo AI = TI.getNaturalAlignIndirect(I32, TI.getAllocaAddrSpace());
+  EXPECT_TRUE(AI.isIndirect());
+  EXPECT_EQ(AI.getIndirectAddrSpace(), 0u);
+}
+
 } // namespace



More information about the llvm-commits mailing list