https://github.com/isanbard updated https://github.com/llvm/llvm-project/pull/236701
>From a32d772433319cb2c43f9ff55b636250af8a059d Mon Sep 17 00:00:00 2001 From: Bill Wendling <[email protected]> Date: Thu, 29 Oct 2026 02:32:09 -0700 Subject: [PATCH 1/2] [Clang][CodeGen] Update the TBAA info for potential aliases The stores of a _Complex number were tagged as "unsigned long", but loads were tagged as "float". TBAA reports no aliases if the store and loads went through different pointers and GVN forwards a stale value. Fix this by giving the "store" the "omnipotent char" tag, so that TBAA treats it as aliasing every access to the destination's members. Using that tag over "Dest.getTBAAInfo()" because it doesn't depend on how CodeGenTBAA happens to tag struct and _Complex types. Assisted-by: Claude for testcases. --- clang/lib/CodeGen/CGStmt.cpp | 6 +++- .../test/CodeGen/X86/inline-asm-output-tbaa.c | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/X86/inline-asm-output-tbaa.c diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 05737ce071647d..dc34bfc0f5e2c6 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -3389,7 +3389,11 @@ void AsmConstraintsInfo::EmitAsmStores( return; } - Dest = CGF.MakeAddrLValue(A, Ty); + // The integer isn't the destination's type, so a TBAA tag for it would + // claim that the store doesn't alias accesses to the destination's + // members. + Dest = CGF.MakeAddrLValue(A, Ty, Dest.getBaseInfo(), + TBAAAccessInfo::getMayAliasInfo()); } CGF.EmitStoreThroughLValue(RValue::get(Tmp), Dest); diff --git a/clang/test/CodeGen/X86/inline-asm-output-tbaa.c b/clang/test/CodeGen/X86/inline-asm-output-tbaa.c new file mode 100644 index 00000000000000..90cb24d0c899e6 --- /dev/null +++ b/clang/test/CodeGen/X86/inline-asm-output-tbaa.c @@ -0,0 +1,28 @@ +// REQUIRES: x86-registered-target +// Clang emits TBAA only when optimizing, so this test needs -O1. +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s + +// A struct or _Complex output with a register constraint is returned as an +// integer and stored to the destination. The store must not have the integer's +// TBAA tag, or it wouldn't alias accesses to the destination's members. + +struct S { + float a, b; +}; + +// CHECK-LABEL: define {{.*}}void @test_struct_output( +// CHECK: [[RES:%.*]] = call i64 asm "", "=r, +// CHECK-NEXT: store i64 [[RES]], ptr %{{.*}}, align 4, !tbaa [[CHAR_TAG:![0-9]+]] +void test_struct_output(struct S *p) { + asm("" : "=r"(*p)); +} + +// CHECK-LABEL: define {{.*}}void @test_complex_output( +// CHECK: [[RES:%.*]] = call i64 asm "", "=r, +// CHECK-NEXT: store i64 [[RES]], ptr %{{.*}}, align 4, !tbaa [[CHAR_TAG]] +void test_complex_output(_Complex float *p) { + asm("" : "=r"(*p)); +} + +// CHECK-DAG: [[CHAR_TAG]] = !{[[CHAR:![0-9]+]], [[CHAR]], i64 0} +// CHECK-DAG: [[CHAR]] = !{!"omnipotent char", >From 903e92e96e60b525401877d499bcbd4810f5057c Mon Sep 17 00:00:00 2001 From: Bill Wendling <[email protected]> Date: Thu, 29 Oct 2026 02:50:48 -0700 Subject: [PATCH 2/2] Remove the _Complex case from the TBAA test _Complex outputs aren't returned by value until #236695. Assisted-by: Claude Opus 5.5 --- clang/test/CodeGen/X86/inline-asm-output-tbaa.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/clang/test/CodeGen/X86/inline-asm-output-tbaa.c b/clang/test/CodeGen/X86/inline-asm-output-tbaa.c index 90cb24d0c899e6..9c6ab17d6818e0 100644 --- a/clang/test/CodeGen/X86/inline-asm-output-tbaa.c +++ b/clang/test/CodeGen/X86/inline-asm-output-tbaa.c @@ -2,9 +2,9 @@ // Clang emits TBAA only when optimizing, so this test needs -O1. // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O1 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -// A struct or _Complex output with a register constraint is returned as an -// integer and stored to the destination. The store must not have the integer's -// TBAA tag, or it wouldn't alias accesses to the destination's members. +// A struct output with a register constraint is returned as an integer and +// stored to the destination. The store must not have the integer's TBAA tag, +// or it wouldn't alias accesses to the destination's members. struct S { float a, b; @@ -17,12 +17,5 @@ void test_struct_output(struct S *p) { asm("" : "=r"(*p)); } -// CHECK-LABEL: define {{.*}}void @test_complex_output( -// CHECK: [[RES:%.*]] = call i64 asm "", "=r, -// CHECK-NEXT: store i64 [[RES]], ptr %{{.*}}, align 4, !tbaa [[CHAR_TAG]] -void test_complex_output(_Complex float *p) { - asm("" : "=r"(*p)); -} - // CHECK-DAG: [[CHAR_TAG]] = !{[[CHAR:![0-9]+]], [[CHAR]], i64 0} // CHECK-DAG: [[CHAR]] = !{!"omnipotent char", _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
