[clang] b6de3ba - [Clang] Add tests checking TBAA emission for complex types (NFC) (#234537)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 22 03:11:29 PDT 2026


Author: Mattéo Rizza Murgier
Date: 2026-10-22T10:11:25Z
New Revision: b6de3baf1d1101999ef9577ae75a0bc442791fc3

URL: https://github.com/llvm/llvm-project/commit/b6de3baf1d1101999ef9577ae75a0bc442791fc3
DIFF: https://github.com/llvm/llvm-project/commit/b6de3baf1d1101999ef9577ae75a0bc442791fc3.diff

LOG: [Clang] Add tests checking TBAA emission for complex types (NFC) (#234537)

Added: 
    clang/test/CodeGen/tbaa-complex.c

Modified: 
    

Removed: 
    


################################################################################
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}
+//.


        


More information about the cfe-commits mailing list