https://github.com/matteo-rm updated https://github.com/llvm/llvm-project/pull/234537
From 611cc50afa27814049a7db583125e7066f6d37a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Rizza=20Murgier?= <[email protected]> Date: Thu, 22 Oct 2026 10:43:06 +0200 Subject: [PATCH] [Clang] Add tests checking TBAA emission for complex types (NFC) --- clang/test/CodeGen/tbaa-complex.c | 137 ++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 clang/test/CodeGen/tbaa-complex.c diff --git a/clang/test/CodeGen/tbaa-complex.c b/clang/test/CodeGen/tbaa-complex.c new file mode 100644 index 0000000000000..ac045156c593c --- /dev/null +++ b/clang/test/CodeGen/tbaa-complex.c @@ -0,0 +1,137 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -O1 -triple x86_64-linux \ +// RUN: -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s +// +// Check that we generate correct TBAA information for accesses to complex types. +// FIXME: complex load/stores have no tbaa metadata + +// Verify that complex and scalar accesses to the same element type share the +// same TBAA tag. +// CHECK-LABEL: define dso_local void @load_double_complex_and_scalar( +// CHECK-SAME: ptr noundef [[C:%.*]], ptr noundef [[S:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[LOCAL:%.*]] = alloca { double, double }, align 8 +// CHECK-NEXT: [[D:%.*]] = alloca double, align 8 +// CHECK-NEXT: store ptr [[C]], ptr [[C_ADDR]], align 8, !tbaa [[ANYPTR_TBAA6:![0-9]+]] +// CHECK-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8, !tbaa [[DOUBLEPTR_TBAA8:![0-9]+]] +// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[LOCAL]]) #[[ATTR2:[0-9]+]] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C_ADDR]], align 8, !tbaa [[ANYPTR_TBAA6]] +// CHECK-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[DOTREAL:%.*]] = load double, ptr [[DOTREALP]], align 8 +// CHECK-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[DOTIMAG:%.*]] = load double, ptr [[DOTIMAGP]], align 8 +// CHECK-NEXT: [[LOCAL_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[LOCAL]], i32 0, i32 0 +// CHECK-NEXT: [[LOCAL_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[LOCAL]], i32 0, i32 1 +// CHECK-NEXT: store double [[DOTREAL]], ptr [[LOCAL_REALP]], align 8 +// CHECK-NEXT: store double [[DOTIMAG]], ptr [[LOCAL_IMAGP]], align 8 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[D]]) #[[ATTR2]] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S_ADDR]], align 8, !tbaa [[DOUBLEPTR_TBAA8]] +// CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8, !tbaa [[DOUBLE_TBAA10:![0-9]+]] +// CHECK-NEXT: store double [[TMP2]], ptr [[D]], align 8, !tbaa [[DOUBLE_TBAA10]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[D]]) #[[ATTR2]] +// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[LOCAL]]) #[[ATTR2]] +// CHECK-NEXT: ret void +// +void load_double_complex_and_scalar(_Complex double *c, double *s) { + _Complex double local = *c; + double d = *s; +} + +// CHECK-LABEL: define dso_local void @load_float_complex( +// CHECK-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8, !tbaa [[ANYPTR_TBAA6]] +// CHECK-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8, !tbaa [[ANYPTR_TBAA6]] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8, !tbaa [[ANYPTR_TBAA6]] +// CHECK-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[DOTREAL:%.*]] = load float, ptr [[DOTREALP]], align 4 +// CHECK-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[DOTIMAG:%.*]] = load float, ptr [[DOTIMAGP]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[B_ADDR]], align 8, !tbaa [[ANYPTR_TBAA6]] +// CHECK-NEXT: [[DOTREALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[DOTIMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store float [[DOTREAL]], ptr [[DOTREALP1]], align 4 +// CHECK-NEXT: store float [[DOTIMAG]], ptr [[DOTIMAGP2]], align 4 +// CHECK-NEXT: ret void +// +void load_float_complex(_Complex float *a, _Complex float *b) { + *b = *a; +} + +// Verify that accesses to a complex member of a struct are handled. +struct S { + int i; + _Complex double z; +}; + +// CHECK-LABEL: define dso_local void @load_double_complex_member( +// CHECK-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8, !tbaa [[_ZTS1SPTR_TBAA12:![0-9]+]] +// CHECK-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8, !tbaa [[_ZTS1SPTR_TBAA12]] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8, !tbaa [[_ZTS1SPTR_TBAA12]] +// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[Z_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[Z]], i32 0, i32 0 +// CHECK-NEXT: [[Z_REAL:%.*]] = load double, ptr [[Z_REALP]], align 8 +// CHECK-NEXT: [[Z_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[Z]], i32 0, i32 1 +// CHECK-NEXT: [[Z_IMAG:%.*]] = load double, ptr [[Z_IMAGP]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[B_ADDR]], align 8, !tbaa [[_ZTS1SPTR_TBAA12]] +// CHECK-NEXT: [[Z1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: [[Z1_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[Z1]], i32 0, i32 0 +// CHECK-NEXT: [[Z1_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[Z1]], i32 0, i32 1 +// CHECK-NEXT: store double [[Z_REAL]], ptr [[Z1_REALP]], align 8 +// CHECK-NEXT: store double [[Z_IMAG]], ptr [[Z1_IMAGP]], align 8 +// CHECK-NEXT: ret void +// +void load_double_complex_member(struct S *a, struct S *b) { + b->z = a->z; +} + +// Verify that accesses to a complex member of a union may alias. +union U { + _Complex double z; + long l[2]; +}; + +// CHECK-LABEL: define dso_local void @load_double_complex_union_member( +// CHECK-SAME: ptr noundef [[A:%.*]], ptr noundef [[B:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8, !tbaa [[_ZTS1UPTR_TBAA14:![0-9]+]] +// CHECK-NEXT: store ptr [[B]], ptr [[B_ADDR]], align 8, !tbaa [[_ZTS1UPTR_TBAA14]] +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8, !tbaa [[_ZTS1UPTR_TBAA14]] +// CHECK-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP0]], i32 0, i32 0 +// CHECK-NEXT: [[DOTREAL:%.*]] = load double, ptr [[DOTREALP]], align 8 +// CHECK-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP0]], i32 0, i32 1 +// CHECK-NEXT: [[DOTIMAG:%.*]] = load double, ptr [[DOTIMAGP]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[B_ADDR]], align 8, !tbaa [[_ZTS1UPTR_TBAA14]] +// CHECK-NEXT: [[DOTREALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP1]], i32 0, i32 0 +// CHECK-NEXT: [[DOTIMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store double [[DOTREAL]], ptr [[DOTREALP1]], align 8 +// CHECK-NEXT: store double [[DOTIMAG]], ptr [[DOTIMAGP2]], align 8 +// CHECK-NEXT: ret void +// +void load_double_complex_union_member(union U *a, union U *b) { + b->z = a->z; +} +//. +// CHECK: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0} +// CHECK: [[META5]] = !{!"Simple C/C++ TBAA"} +// CHECK: [[ANYPTR_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0} +// CHECK: [[META7]] = !{!"any pointer", [[META4]], i64 0} +// CHECK: [[DOUBLEPTR_TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0} +// CHECK: [[META9]] = !{!"p1 double", [[META7]], i64 0} +// CHECK: [[DOUBLE_TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0} +// CHECK: [[META11]] = !{!"double", [[META4]], i64 0} +// CHECK: [[_ZTS1SPTR_TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0} +// CHECK: [[META13]] = !{!"p1 _ZTS1S", [[META7]], i64 0} +// CHECK: [[_ZTS1UPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0} +// CHECK: [[META15]] = !{!"p1 _ZTS1U", [[META7]], i64 0} +//. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
