https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/186667
>From 62f57541b4367881e75fbe440a3905a6d9b514ae 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 | 13 +++++++---- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 5 +--- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 7 ++++++ clang/lib/CIR/CodeGen/CIRGenModule.h | 3 +++ clang/test/CIR/CodeGen/arg-attrs.cpp | 31 +++++++++++++++++++++---- clang/test/CIR/CodeGen/invoke-attrs.cpp | 6 ++--- 6 files changed, 49 insertions(+), 16 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index 1d7f15c569798..aba3ccde28065 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -620,7 +620,7 @@ void CIRGenModule::constructFunctionReturnAttributes( if (pointeeTy->isObjectType()) retAttrs.set(mlir::LLVM::LLVMDialect::getAlignAttrName(), builder.getI64IntegerAttr( - getNaturalTypeAlignment(pointeeTy).getQuantity())); + getNaturalPointeeTypeAlignment(retTy).getQuantity())); } } } @@ -659,7 +659,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 +704,10 @@ 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( + getNaturalPointeeTypeAlignment(argType).getQuantity())); } } } diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 5328bb0a812a5..8c51ac46cea79 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -903,10 +903,7 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) { } } else { // Should we be using the alignment of the constant pointer we emitted? - CharUnits alignment = - cgm.getNaturalTypeAlignment(e->getType(), - /*BaseInfo=*/nullptr, - /*forPointeeType=*/true); + CharUnits alignment = cgm.getNaturalPointeeTypeAlignment(e->getType()); // Classic codegen passes TBAA as null-ptr to the above function, so it // probably needs to deal with that. assert(!cir::MissingFeatures::opTBAA()); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index cb931f969a41d..43f4c48d00828 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -237,6 +237,13 @@ CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t, return alignment; } +CharUnits +CIRGenModule::getNaturalPointeeTypeAlignment(QualType t, + LValueBaseInfo *baseInfo) { + return getNaturalTypeAlignment(t->getPointeeType(), baseInfo, + /*forPointeeType=*/true); +} + const TargetCIRGenInfo &CIRGenModule::getTargetCIRGenInfo() { if (theTargetCIRGenInfo) return *theTargetCIRGenInfo; diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index bef154955b9b6..9d402ffb3bf79 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -398,6 +398,9 @@ class CIRGenModule : public CIRGenTypeCache { clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo = nullptr, bool forPointeeType = false); + clang::CharUnits + getNaturalPointeeTypeAlignment(clang::QualType t, + LValueBaseInfo *baseInfo = nullptr); /// Returns the minimum object size for an object of the given class type /// (or a class derived from it). 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 %{{.*}}) } diff --git a/clang/test/CIR/CodeGen/invoke-attrs.cpp b/clang/test/CIR/CodeGen/invoke-attrs.cpp index bc58d2193c267..aeb2d0cfbc386 100644 --- a/clang/test/CIR/CodeGen/invoke-attrs.cpp +++ b/clang/test/CIR/CodeGen/invoke-attrs.cpp @@ -44,13 +44,13 @@ void test_ref_param_attrs(S &s, int &i) { } // CIR-LABEL: cir.func {{.*}}@_Z20test_ref_param_attrsR1SRi -// CIR: cir.call @_ZN1S9ref_paramERi({{%.*}}, {{%.*}}) : (!cir.ptr<!rec_S> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!s32i> {llvm.align = 8 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, llvm.noundef}) -> () +// CIR: cir.call @_ZN1S9ref_paramERi({{%.*}}, {{%.*}}) : (!cir.ptr<!rec_S> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!s32i> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, llvm.noundef}) -> () // CIR-FLAT-LABEL: cir.func {{.*}}@_Z20test_ref_param_attrsR1SRi -// CIR-FLAT: cir.try_call @_ZN1S9ref_paramERi({{%.*}}, {{%.*}}) ^{{bb[0-9]+}}, ^{{bb[0-9]+}} : (!cir.ptr<!rec_S> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!s32i> {llvm.align = 8 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, llvm.noundef}) -> () +// CIR-FLAT: cir.try_call @_ZN1S9ref_paramERi({{%.*}}, {{%.*}}) ^{{bb[0-9]+}}, ^{{bb[0-9]+}} : (!cir.ptr<!rec_S> {llvm.align = 4 : i64, llvm.dereferenceable = 20 : i64, llvm.nonnull, llvm.noundef}, !cir.ptr<!s32i> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nonnull, llvm.noundef}) -> () // LLVM-LABEL: define {{.*}} void @_Z20test_ref_param_attrsR1SRi -// LLVM: invoke void @_ZN1S9ref_paramERi(ptr noundef nonnull align 4 dereferenceable(20) {{%.*}}, ptr noundef nonnull align 8 dereferenceable(4) {{%.*}}) +// LLVM: invoke void @_ZN1S9ref_paramERi(ptr noundef nonnull align 4 dereferenceable(20) {{%.*}}, ptr noundef nonnull align 4 dereferenceable(4) {{%.*}}) // OGCG-LABEL: define {{.*}} void @_Z20test_ref_param_attrsR1SRi // OGCG: invoke void @_ZN1S9ref_paramERi(ptr noundef nonnull align 4 dereferenceable(20) {{%.*}}, ptr noundef nonnull align 4 dereferenceable(4) {{%.*}}) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
