https://github.com/xlauko created 
https://github.com/llvm/llvm-project/pull/186667

getNaturalTypeAlignment on a reference type returned pointer alignment
instead of pointee alignment. Pass the pointee type with
forPointeeType=true to match traditional codegen's
getNaturalPointeeTypeAlignment behavior. Fix applies to both argument
and return type attribute construction paths.

>From 0277b448c910fc8201776bec11f7b1445c138992 Mon Sep 17 00:00:00 2001
From: xlauko <[email protected]>
Date: Sun, 15 Mar 2026 13:54:42 +0100
Subject: [PATCH] [CIR] Fix reference alignment to use pointee type

getNaturalTypeAlignment on a reference type returned pointer alignment
instead of pointee alignment. Pass the pointee type with
forPointeeType=true to match traditional codegen's
getNaturalPointeeTypeAlignment behavior. Fix applies to both argument
and return type attribute construction paths.
---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp | 18 +++++++++++-----
 clang/test/CIR/CodeGen/arg-attrs.cpp | 31 ++++++++++++++++++++++++----
 2 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 1d7f15c569798..10aa3c4af2d3b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -620,7 +620,10 @@ void CIRGenModule::constructFunctionReturnAttributes(
       if (pointeeTy->isObjectType())
         retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
                      builder.getI64IntegerAttr(
-                         getNaturalTypeAlignment(pointeeTy).getQuantity()));
+                         getNaturalTypeAlignment(pointeeTy,
+                                                 /*baseInfo=*/nullptr,
+                                                 /*forPointeeType=*/true)
+                             .getQuantity()));
     }
   }
 }
@@ -659,7 +662,9 @@ void CIRGenModule::constructFunctionArgumentAttributes(
 
       argAttrs[0].set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
                       builder.getI64IntegerAttr(
-                          getNaturalTypeAlignment(thisTy).getQuantity()));
+                          getNaturalTypeAlignment(thisTy, /*baseInfo=*/nullptr,
+                                                  /*forPointeeType=*/true)
+                              .getQuantity()));
 
       // TODO(cir): the classic codegen has a recently-added bunch of logic for
       // 'dead_on_return' as an attribute. This both doesn't exist in the LLVM
@@ -702,9 +707,12 @@ void CIRGenModule::constructFunctionArgumentAttributes(
         argAttrList.set(mlir::LLVM::LLVMDialect::getNonNullAttrName(),
                         mlir::UnitAttr::get(&getMLIRContext()));
       if (pointeeTy->isObjectType())
-        argAttrList.set(mlir::LLVM::LLVMDialect::getAlignAttrName(),
-                        builder.getI64IntegerAttr(
-                            getNaturalTypeAlignment(argType).getQuantity()));
+        argAttrList.set(
+            mlir::LLVM::LLVMDialect::getAlignAttrName(),
+            builder.getI64IntegerAttr(
+                getNaturalTypeAlignment(pointeeTy, /*baseInfo=*/nullptr,
+                                        /*forPointeeType=*/true)
+                    .getQuantity()));
     }
   }
 }
diff --git a/clang/test/CIR/CodeGen/arg-attrs.cpp 
b/clang/test/CIR/CodeGen/arg-attrs.cpp
index a66cf661dc66c..800b86e602cd0 100644
--- a/clang/test/CIR/CodeGen/arg-attrs.cpp
+++ b/clang/test/CIR/CodeGen/arg-attrs.cpp
@@ -18,18 +18,41 @@ void Struct::this_func(){}
   // CIR: cir.func {{.*}}@_ZN6Struct9this_funcEv(%{{.*}}: 
!cir.ptr<!rec_Struct> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, 
llvm.nonnull, llvm.noundef} {{.*}}) {
   // BOTH: define {{.*}}void @_ZN6Struct9this_funcEv(ptr noundef nonnull align 
4 dereferenceable(20) %{{.*}})
 void Struct::arg_attr(Struct s, int &i, Incomplete &j){}
-  // CIR: cir.func {{.*}}@_ZN6Struct8arg_attrES_RiR10Incomplete(%{{.*}}: 
!cir.ptr<!rec_Struct> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, 
llvm.nonnull, llvm.noundef} {{.*}}, %{{.*}}: !rec_Struct {{.*}}, %{{.*}}: 
!cir.ptr<!s32i> {llvm.align = 8 : i64, llvm.dereferenceable = 4 : i64, 
llvm.nonnull, llvm.noundef} {{.*}}, %arg3: !cir.ptr<!rec_Incomplete> 
{llvm.align = 8 : i64, llvm.nonnull, llvm.noundef} {{.*}}) {
-  // LLVM: define {{.*}}void @_ZN6Struct8arg_attrES_RiR10Incomplete(ptr 
noundef nonnull align 4 dereferenceable(20) %{{.*}}, %struct.Struct %{{.*}}, 
ptr noundef nonnull align 8 dereferenceable(4) %{{.*}}, ptr noundef nonnull 
align 8 %{{.*}})
+  // CIR: cir.func {{.*}}@_ZN6Struct8arg_attrES_RiR10Incomplete(%{{.*}}: 
!cir.ptr<!rec_Struct> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, 
llvm.nonnull, llvm.noundef} {{.*}}, %{{.*}}: !rec_Struct {{.*}}, %{{.*}}: 
!cir.ptr<!s32i> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, 
llvm.nonnull, llvm.noundef} {{.*}}, %arg3: !cir.ptr<!rec_Incomplete> 
{llvm.align = 1 : i64, llvm.nonnull, llvm.noundef} {{.*}}) {
+  // LLVM: define {{.*}}void @_ZN6Struct8arg_attrES_RiR10Incomplete(ptr 
noundef nonnull align 4 dereferenceable(20) %{{.*}}, %struct.Struct %{{.*}}, 
ptr noundef nonnull align 4 dereferenceable(4) %{{.*}}, ptr noundef nonnull 
align 1 %{{.*}})
   // OGCG: define {{.*}}void @_ZN6Struct8arg_attrES_RiR10Incomplete(ptr 
noundef nonnull align 4 dereferenceable(20) %{{.*}}, ptr noundef 
byval(%struct.Struct) align 8 %{{.*}}, ptr noundef nonnull align 4 
dereferenceable(4) %{{.*}}, ptr noundef nonnull align 1 %{{.*}})
 
+struct __attribute__((aligned(32))) Aligned32 {
+  int x;
+  void method();
+};
+
+void Aligned32::method() {}
+  // CIR: cir.func {{.*}}@_ZN9Aligned326methodEv(%{{.*}}: 
!cir.ptr<!rec_Aligned32> {llvm.align = 32 : i64, llvm.dereferenceable = 32 : 
i64, llvm.nonnull, llvm.noundef} {{.*}}) {
+  // BOTH: define {{.*}}void @_ZN9Aligned326methodEv(ptr noundef nonnull align 
32 dereferenceable(32) %{{.*}})
+
+void aligned_ref(Aligned32 &a) {}
+  // CIR: cir.func {{.*}}@_Z11aligned_refR9Aligned32(%{{.*}}: 
!cir.ptr<!rec_Aligned32> {llvm.align = 32 : i64, llvm.dereferenceable = 32 : 
i64, llvm.nonnull, llvm.noundef} {{.*}}) {
+  // BOTH: define {{.*}}void @_Z11aligned_refR9Aligned32(ptr noundef nonnull 
align 32 dereferenceable(32) %{{.*}})
+
+int g;
+int &return_int_ref() { return g; }
+  // CIR: cir.func {{.*}}@_Z14return_int_refv() -> (!cir.ptr<!s32i> 
{llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, 
llvm.noundef}) {
+  // BOTH: define {{.*}}noundef nonnull align 4 dereferenceable(4) ptr 
@_Z14return_int_refv()
+
+Aligned32 ga;
+Aligned32 &return_aligned_ref() { return ga; }
+  // CIR: cir.func {{.*}}@_Z18return_aligned_refv() -> 
(!cir.ptr<!rec_Aligned32> {llvm.align = 32 : i64, llvm.dereferenceable = 32 : 
i64, llvm.nonnull, llvm.noundef}) {
+  // BOTH: define {{.*}}noundef nonnull align 32 dereferenceable(32) ptr 
@_Z18return_aligned_refv()
+
 void caller(Struct s, int i, Incomplete &inc) {
 
   s.this_func();
   // CIR: cir.call @_ZN6Struct9this_funcEv(%{{.*}}) : (!cir.ptr<!rec_Struct> 
{llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, llvm.nonnull, 
llvm.noundef})
   // BOTH: call void @_ZN6Struct9this_funcEv(ptr noundef nonnull align 4 
dereferenceable(20) %{{.*}})
   s.arg_attr(s, i, inc);
-  // CIR: cir.call @_ZN6Struct8arg_attrES_RiR10Incomplete(%{{.*}}, %{{.*}}, 
%{{.*}}, %{{.*}}) : (!cir.ptr<!rec_Struct> {llvm.align = 4 : i64, 
llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}, !rec_Struct, 
!cir.ptr<!s32i> {llvm.align = 8 : i64, llvm.dereferenceable = 4 : i64, 
llvm.nonnull, llvm.noundef}, !cir.ptr<!rec_Incomplete> {llvm.align = 8 : i64, 
llvm.nonnull, llvm.noundef})
-  // LLVM: call void @_ZN6Struct8arg_attrES_RiR10Incomplete(ptr noundef 
nonnull align 4 dereferenceable(20) %{{.*}}, %struct.Struct %{{.*}}, ptr 
noundef nonnull align 8 dereferenceable(4) %{{.*}}, ptr noundef nonnull align 8 
%{{.*}})
+  // CIR: cir.call @_ZN6Struct8arg_attrES_RiR10Incomplete(%{{.*}}, %{{.*}}, 
%{{.*}}, %{{.*}}) : (!cir.ptr<!rec_Struct> {llvm.align = 4 : i64, 
llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}, !rec_Struct, 
!cir.ptr<!s32i> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, 
llvm.nonnull, llvm.noundef}, !cir.ptr<!rec_Incomplete> {llvm.align = 1 : i64, 
llvm.nonnull, llvm.noundef})
+  // LLVM: call void @_ZN6Struct8arg_attrES_RiR10Incomplete(ptr noundef 
nonnull align 4 dereferenceable(20) %{{.*}}, %struct.Struct %{{.*}}, ptr 
noundef nonnull align 4 dereferenceable(4) %{{.*}}, ptr noundef nonnull align 1 
%{{.*}})
   // OGCG: call void @_ZN6Struct8arg_attrES_RiR10Incomplete(ptr noundef 
nonnull align 4 dereferenceable(20) %{{.*}}, ptr noundef byval(%struct.Struct) 
align 8 %{{.*}}, ptr noundef nonnull align 4 dereferenceable(4) %{{.*}}, ptr 
noundef nonnull align 1 %{{.*}})
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to