[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