[clang] [llvm] [ABI] Add CanBeFlattened to ArgInfo for Direct struct coerces (PR #220579)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 11 03:34:33 PDT 2026
https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/220579
>From bf5e92ded20955b3a50c673e788945ab6aa7449e Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Wed, 2 Sep 2026 17:58:45 +0530
Subject: [PATCH 1/2] [ABI] Add CanBeFlattened to ArgInfo for Direct struct
coerces
---
.../Transforms/CallConvLoweringPass.cpp | 11 +++--
llvm/include/llvm/ABI/FunctionInfo.h | 14 +++++-
llvm/unittests/ABI/CMakeLists.txt | 1 +
llvm/unittests/ABI/FunctionInfoTest.cpp | 43 +++++++++++++++++++
.../gn/secondary/llvm/unittests/ABI/BUILD.gn | 1 +
5 files changed, 64 insertions(+), 6 deletions(-)
create mode 100644 llvm/unittests/ABI/FunctionInfoTest.cpp
diff --git a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
index f59c325a454d0..299adf5fdaf33 100644
--- a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
@@ -515,9 +515,10 @@ static const llvm::abi::Type *mapCIRType(mlir::Type type,
/// unpacked into the register(s) holding it, a scalar too wide for one register
/// split into a tuple of them, a scalar the classifier widens to fill its
/// eightbyte, and a value whose live bytes start partway into its storage
-/// because a leading eightbyte holds no field (getDirectOffset). getDirect
-/// keeps canFlatten set so the rewriter can split a multi-field coerced
-/// struct into individual wire arguments. Any other scalar passes in its
+/// because a leading eightbyte holds no field (getDirectOffset). canFlatten
+/// follows the classifier's CanBeFlattened, so the rewriter splits a
+/// multi-field coerced struct into individual wire arguments unless the
+/// classifier asked to keep it intact. Any other scalar passes in its
/// natural CIR type, which a null coercion denotes. A coercion this bridge
/// cannot represent yields std::nullopt so the caller reports NYI rather than
/// silently passing the value unchanged.
@@ -577,7 +578,9 @@ convertABIArgInfo(const llvm::abi::ArgInfo &info, MLIRContext *ctx,
// trip for nothing.
if (comparesAgainstCoerce && coerced == origTy)
return ArgClassification::getDirect();
- return ArgClassification::getDirect(coerced, offset);
+ ArgClassification classified = ArgClassification::getDirect(coerced, offset);
+ classified.canFlatten = info.getCanBeFlattened();
+ return classified;
}
// An extended value is always read from byte 0 of its own storage, so
// there is no offset to honor here.
diff --git a/llvm/include/llvm/ABI/FunctionInfo.h b/llvm/include/llvm/ABI/FunctionInfo.h
index caedafcbe9d22..f4c20f64677c4 100644
--- a/llvm/include/llvm/ABI/FunctionInfo.h
+++ b/llvm/include/llvm/ABI/FunctionInfo.h
@@ -71,10 +71,11 @@ class ArgInfo {
bool ZeroExt : 1;
bool IndirectByVal : 1;
bool IndirectRealign : 1;
+ bool CanBeFlattened : 1;
ArgInfo(Kind K = Direct)
: TheKind(K), SignExt(false), ZeroExt(false), IndirectByVal(false),
- IndirectRealign(false) {}
+ IndirectRealign(false), CanBeFlattened(true) {}
public:
/// \param T The type to coerce to. If null, the argument's original type is
@@ -85,12 +86,16 @@ class ArgInfo {
/// return value on x86-64).
/// \param Align Override for the argument's alignment. If absent, the
/// default alignment for \p T is used.
+ /// \param CanBeFlattened Whether a multi-field struct coerce type may be
+ /// expanded into one argument per field. False keeps it intact.
static ArgInfo getDirect(const Type *T = nullptr, unsigned Offset = 0,
- MaybeAlign Align = std::nullopt) {
+ MaybeAlign Align = std::nullopt,
+ bool CanBeFlattened = true) {
ArgInfo AI(Direct);
AI.CoercionType = T;
AI.Alignment = Align;
AI.DirectAttr.Offset = Offset;
+ AI.CanBeFlattened = CanBeFlattened;
return AI;
}
@@ -197,6 +202,11 @@ class ArgInfo {
assert((isDirect() || isExtend()) && "Invalid Kind!");
return CoercionType;
}
+
+ bool getCanBeFlattened() const {
+ assert(isDirect() && "Not a direct kind");
+ return CanBeFlattened;
+ }
};
struct ArgEntry {
diff --git a/llvm/unittests/ABI/CMakeLists.txt b/llvm/unittests/ABI/CMakeLists.txt
index 40cdd42ea6c61..83ac07ae2a25d 100644
--- a/llvm/unittests/ABI/CMakeLists.txt
+++ b/llvm/unittests/ABI/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(ABITests
AArch64TargetInfoTest.cpp
+ FunctionInfoTest.cpp
IRTypeMapperTest.cpp
X86TargetInfoTest.cpp
TypesTest.cpp
diff --git a/llvm/unittests/ABI/FunctionInfoTest.cpp b/llvm/unittests/ABI/FunctionInfoTest.cpp
new file mode 100644
index 0000000000000..f43557b32ce1d
--- /dev/null
+++ b/llvm/unittests/ABI/FunctionInfoTest.cpp
@@ -0,0 +1,43 @@
+//===- FunctionInfoTest.cpp - ArgInfo unit tests --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ABI/FunctionInfo.h"
+#include "llvm/ABI/Types.h"
+#include "llvm/Support/Allocator.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using llvm::abi::ArgInfo;
+using llvm::abi::Type;
+using llvm::abi::TypeBuilder;
+
+class ArgInfoTest : public ::testing::Test {
+protected:
+ llvm::BumpPtrAllocator Alloc;
+ TypeBuilder TB;
+ const Type *I32;
+
+ ArgInfoTest()
+ : TB(Alloc), I32(TB.getIntegerType(32, llvm::Align(4), /*Signed=*/true)) {
+ }
+};
+
+TEST_F(ArgInfoTest, DirectCanBeFlattenedDefaultsTrue) {
+ EXPECT_TRUE(ArgInfo::getDirect().getCanBeFlattened());
+ EXPECT_TRUE(ArgInfo::getDirect(I32).getCanBeFlattened());
+}
+
+TEST_F(ArgInfoTest, DirectCanBeFlattenedHonorsFalse) {
+ ArgInfo AI = ArgInfo::getDirect(I32, /*Offset=*/0, /*Align=*/std::nullopt,
+ /*CanBeFlattened=*/false);
+ EXPECT_TRUE(AI.isDirect());
+ EXPECT_FALSE(AI.getCanBeFlattened());
+}
+
+} // namespace
diff --git a/llvm/utils/gn/secondary/llvm/unittests/ABI/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ABI/BUILD.gn
index 43b98bccc447e..6bb38385f861e 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/ABI/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/ABI/BUILD.gn
@@ -8,6 +8,7 @@ unittest("ABITests") {
]
sources = [
"AArch64TargetInfoTest.cpp",
+ "FunctionInfoTest.cpp",
"IRTypeMapperTest.cpp",
"X86TargetInfoTest.cpp",
"TypesTest.cpp",
>From a09b06f638fb9435703825025b44a22b3dc7f259 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Fri, 4 Sep 2026 11:02:21 +0530
Subject: [PATCH 2/2] default CanBeFlattened to false
---
llvm/include/llvm/ABI/FunctionInfo.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/ABI/FunctionInfo.h b/llvm/include/llvm/ABI/FunctionInfo.h
index f4c20f64677c4..d434e0b34a75e 100644
--- a/llvm/include/llvm/ABI/FunctionInfo.h
+++ b/llvm/include/llvm/ABI/FunctionInfo.h
@@ -75,7 +75,7 @@ class ArgInfo {
ArgInfo(Kind K = Direct)
: TheKind(K), SignExt(false), ZeroExt(false), IndirectByVal(false),
- IndirectRealign(false), CanBeFlattened(true) {}
+ IndirectRealign(false), CanBeFlattened(false) {}
public:
/// \param T The type to coerce to. If null, the argument's original type is
More information about the cfe-commits
mailing list