https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/131885
None >From fb1120b5a4abd716f6071ce8c7cfc81e725e9030 Mon Sep 17 00:00:00 2001 From: Florian Hahn <f...@fhahn.com> Date: Fri, 14 Mar 2025 15:40:47 +0000 Subject: [PATCH] [IRGen] Mark pointers as noalias when passing trivial types by value. --- clang/lib/CodeGen/CGCall.cpp | 7 ++++--- clang/test/CodeGen/AArch64/byval-temp.c | 8 ++++---- clang/test/CodeGen/atomic-arm64.c | 2 +- clang/test/CodeGen/attr-noundef.cpp | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7aa77e55dbfcc..434b821ad864a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2797,9 +2797,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); auto *Decl = ParamType->getAsRecordDecl(); - if (CodeGenOpts.PassByValueIsNoAlias && Decl && - Decl->getArgPassingRestrictions() == - RecordArgPassingKind::CanPassInRegs) + if (Decl && ((CodeGenOpts.PassByValueIsNoAlias && + Decl->getArgPassingRestrictions() == + RecordArgPassingKind::CanPassInRegs) || + (!AI.getIndirectByVal() && Context.getTypeDeclType(Decl).isTrivialType(Context)))) // When calling the function, the pointer passed in will be the only // reference to the underlying object. Mark it accordingly. Attrs.addAttribute(llvm::Attribute::NoAlias); diff --git a/clang/test/CodeGen/AArch64/byval-temp.c b/clang/test/CodeGen/AArch64/byval-temp.c index 0ee0312b2362d..05491e8f99542 100644 --- a/clang/test/CodeGen/AArch64/byval-temp.c +++ b/clang/test/CodeGen/AArch64/byval-temp.c @@ -30,10 +30,10 @@ void example(void) { // Then, memcpy `l` to the temporary stack space. // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp]], ptr align 8 %[[l]], i64 64, i1 false) // Finally, call using a pointer to the temporary stack space. -// CHECK-O0-NEXT: call void @pass_large(ptr noundef %[[byvaltemp]]) +// CHECK-O0-NEXT: call void @pass_large(ptr noalias noundef %[[byvaltemp]]) // Now, do the same for the second call, using the second temporary alloca. // CHECK-O0-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp1]], ptr align 8 %[[l]], i64 64, i1 false) -// CHECK-O0-NEXT: call void @pass_large(ptr noundef %[[byvaltemp1]]) +// CHECK-O0-NEXT: call void @pass_large(ptr noalias noundef %[[byvaltemp1]]) // CHECK-O0-NEXT: ret void // // At O3, we should have lifetime markers to help the optimizer re-use the temporary allocas. @@ -58,7 +58,7 @@ void example(void) { // Then, memcpy `l` to the temporary stack space. // CHECK-O3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp]], ptr align 8 %[[l]], i64 64, i1 false) // Finally, call using a pointer to the temporary stack space. -// CHECK-O3-NEXT: call void @pass_large(ptr noundef %[[byvaltemp]]) +// CHECK-O3-NEXT: call void @pass_large(ptr noalias noundef %[[byvaltemp]]) // // The lifetime of the temporary used to pass a pointer to the struct ends here. // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 64, ptr %[[byvaltemp]]) @@ -66,7 +66,7 @@ void example(void) { // Now, do the same for the second call, using the second temporary alloca. // CHECK-O3-NEXT: call void @llvm.lifetime.start.p0(i64 64, ptr %[[byvaltemp1]]) // CHECK-O3-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[byvaltemp1]], ptr align 8 %[[l]], i64 64, i1 false) -// CHECK-O3-NEXT: call void @pass_large(ptr noundef %[[byvaltemp1]]) +// CHECK-O3-NEXT: call void @pass_large(ptr noalias noundef %[[byvaltemp1]]) // CHECK-O3-NEXT: call void @llvm.lifetime.end.p0(i64 64, ptr %[[byvaltemp1]]) // // Mark the end of the lifetime of `l`. diff --git a/clang/test/CodeGen/atomic-arm64.c b/clang/test/CodeGen/atomic-arm64.c index d2a30a3b6e66f..6a3acf899bba6 100644 --- a/clang/test/CodeGen/atomic-arm64.c +++ b/clang/test/CodeGen/atomic-arm64.c @@ -57,7 +57,7 @@ void test3(pointer_pair_t pair) { } // CHECK-LABEL:define{{.*}} void @test4( -// CHECK-SAME: ptr noundef [[QUAD:%.*]]) +// CHECK-SAME: ptr noalias noundef [[QUAD:%.*]]) // CHECK: [[QUAD_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[TEMP:%.*]] = alloca [[QUAD_T:%.*]], align 8 // CHECK-NEXT: store ptr [[QUAD]], ptr [[QUAD_INDIRECT_ADDR]] diff --git a/clang/test/CodeGen/attr-noundef.cpp b/clang/test/CodeGen/attr-noundef.cpp index abdf9496bd396..5431482969fc5 100644 --- a/clang/test/CodeGen/attr-noundef.cpp +++ b/clang/test/CodeGen/attr-noundef.cpp @@ -35,7 +35,7 @@ struct Huge { Huge ret_huge() { return {}; } void pass_huge(Huge h) {} // CHECK: [[DEF]] void @{{.*}}ret_huge{{.*}}(ptr dead_on_unwind noalias writable sret({{[^)]+}}) align 4 % -// CHECK: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr noundef +// CHECK: [[DEF]] void @{{.*}}pass_huge{{.*}}(ptr noalias noundef } // namespace check_structs //************ Passing unions by value _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits