[llvm] [UTC] Record TBAA semantics when autogenerating check lines (PR #147670)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 9 01:29:47 PDT 2025
https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/147670
>From 790a62f2d8dafa49afc22f4e0b77d1d4942cb3e3 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Thu, 26 Jun 2025 15:35:41 +0200
Subject: [PATCH 1/3] [UTC] Introduce test (NFC)
---
.../Inputs/tbaa-semantics-checks.ll | 84 ++++++++++
.../Inputs/tbaa-semantics-checks.ll.expected | 156 ++++++++++++++++++
.../tbaa-semantics-checks.test | 7 +
3 files changed, 247 insertions(+)
create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll
create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected
create mode 100644 llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll
new file mode 100644
index 0000000000000..9d6059602bdb3
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll
@@ -0,0 +1,84 @@
+; RUN: opt < %s -S | FileCheck %s
+
+define void @store_unsignedptr(ptr %ptr) {
+entry:
+ store ptr null, ptr %ptr, align 8, !tbaa !0
+ ret void
+}
+
+define void @store_char(ptr %ptr) {
+entry:
+ store i8 0, ptr %ptr, align 1, !tbaa !5
+ ret void
+}
+
+define float @ptr_to_float(ptr %ptr) {
+entry:
+ store float 0.000000e+00, ptr %ptr, align 4, !tbaa !6
+ call void @opaque(ptr %ptr)
+ %val = load float, ptr %ptr, align 4, !tbaa !6
+ ret float %val
+}
+
+define i64 @ptr_to_longlong(ptr %ptr) {
+entry:
+ %val = load i64, ptr %ptr, align 8, !tbaa !8
+ store i64 0, ptr %ptr, align 8, !tbaa !8
+ ret i64 %val
+}
+
+; struct STRUCT1 {
+; int x;
+; int y;
+; };
+
+define void @store_struct1ptr(ptr %ptr) {
+entry:
+ ; *(struct STRUCT1 **)ptr = 0;
+ store ptr null, ptr %ptr, align 8, !tbaa !10
+ ret void
+}
+
+; struct STRUCT2 {
+; struct STRUCT1 *s;
+; };
+
+define void @store_struct2(ptr %ptr) {
+entry:
+ ; ptr->s = 0;
+ store ptr null, ptr %ptr, align 8, !tbaa !12
+ ret void
+}
+
+define double @access_matrix(ptr %ptr) {
+entry:
+ %alloca.ptr = alloca ptr, align 8
+ store ptr %ptr, ptr %alloca.ptr, align 8, !tbaa !14
+ %ptr.idx = load ptr, ptr %alloca.ptr, align 8, !tbaa !14
+ %add.ptr = getelementptr inbounds ptr, ptr %ptr.idx, i64 4
+ %ptr.idx.1 = load ptr, ptr %add.ptr, align 8, !tbaa !16
+ %add.ptr1 = getelementptr inbounds [6 x double], ptr %ptr.idx.1, i64 6
+ %ptr.idx.2 = load <6 x double>, ptr %add.ptr1, align 8, !tbaa !5
+ %matrixext = extractelement <6 x double> %ptr.idx.2, i64 5
+ ret double %matrixext
+}
+
+declare void @opaque(ptr)
+
+!0 = !{!1, !1, i64 0}
+!1 = !{!"p1 int", !2, i64 0}
+!2 = !{!"any pointer", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!3, !3, i64 0}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"float", !3, i64 0}
+!8 = !{!9, !9, i64 0}
+!9 = !{!"long long", !3, i64 0}
+!10 = !{!11, !11, i64 0}
+!11 = !{!"p1 _ZTS7STRUCT1", !2, i64 0}
+!12 = !{!13, !11, i64 0}
+!13 = !{!"STRUCT2", !11, i64 0}
+!14 = !{!15, !15, i64 0}
+!15 = !{!"any p2 pointer", !2, i64 0}
+!16 = !{!2, !2, i64 0}
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected
new file mode 100644
index 0000000000000..0cd8b9c4817d0
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected
@@ -0,0 +1,156 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -S | FileCheck %s
+
+define void @store_unsignedptr(ptr %ptr) {
+; CHECK-LABEL: define void @store_unsignedptr(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA0:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+entry:
+ store ptr null, ptr %ptr, align 8, !tbaa !0
+ ret void
+}
+
+define void @store_char(ptr %ptr) {
+; CHECK-LABEL: define void @store_char(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: store i8 0, ptr [[PTR]], align 1, !tbaa [[TBAA5:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+entry:
+ store i8 0, ptr %ptr, align 1, !tbaa !5
+ ret void
+}
+
+define float @ptr_to_float(ptr %ptr) {
+; CHECK-LABEL: define float @ptr_to_float(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR]], align 4, !tbaa [[TBAA6:![0-9]+]]
+; CHECK-NEXT: call void @opaque(ptr [[PTR]])
+; CHECK-NEXT: [[VAL:%.*]] = load float, ptr [[PTR]], align 4, !tbaa [[TBAA6]]
+; CHECK-NEXT: ret float [[VAL]]
+;
+entry:
+ store float 0.000000e+00, ptr %ptr, align 4, !tbaa !6
+ call void @opaque(ptr %ptr)
+ %val = load float, ptr %ptr, align 4, !tbaa !6
+ ret float %val
+}
+
+define i64 @ptr_to_longlong(ptr %ptr) {
+; CHECK-LABEL: define i64 @ptr_to_longlong(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR]], align 8, !tbaa [[TBAA8:![0-9]+]]
+; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8, !tbaa [[TBAA8]]
+; CHECK-NEXT: ret i64 [[VAL]]
+;
+entry:
+ %val = load i64, ptr %ptr, align 8, !tbaa !8
+ store i64 0, ptr %ptr, align 8, !tbaa !8
+ ret i64 %val
+}
+
+; struct STRUCT1 {
+; int x;
+; int y;
+; };
+
+define void @store_struct1ptr(ptr %ptr) {
+; CHECK-LABEL: define void @store_struct1ptr(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA10:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+entry:
+ ; *(struct STRUCT1 **)ptr = 0;
+ store ptr null, ptr %ptr, align 8, !tbaa !10
+ ret void
+}
+
+; struct STRUCT2 {
+; struct STRUCT1 *s;
+; };
+
+define void @store_struct2(ptr %ptr) {
+; CHECK-LABEL: define void @store_struct2(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA12:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+entry:
+ ; ptr->s = 0;
+ store ptr null, ptr %ptr, align 8, !tbaa !12
+ ret void
+}
+
+define double @access_matrix(ptr %ptr) {
+; CHECK-LABEL: define double @access_matrix(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ALLOCA_PTR:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: store ptr [[PTR]], ptr [[ALLOCA_PTR]], align 8, !tbaa [[TBAA14:![0-9]+]]
+; CHECK-NEXT: [[PTR_IDX:%.*]] = load ptr, ptr [[ALLOCA_PTR]], align 8, !tbaa [[TBAA14]]
+; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds ptr, ptr [[PTR_IDX]], i64 4
+; CHECK-NEXT: [[PTR_IDX_1:%.*]] = load ptr, ptr [[ADD_PTR]], align 8, !tbaa [[TBAA16:![0-9]+]]
+; CHECK-NEXT: [[ADD_PTR1:%.*]] = getelementptr inbounds [6 x double], ptr [[PTR_IDX_1]], i64 6
+; CHECK-NEXT: [[PTR_IDX_2:%.*]] = load <6 x double>, ptr [[ADD_PTR1]], align 8, !tbaa [[TBAA5]]
+; CHECK-NEXT: [[MATRIXEXT:%.*]] = extractelement <6 x double> [[PTR_IDX_2]], i64 5
+; CHECK-NEXT: ret double [[MATRIXEXT]]
+;
+entry:
+ %alloca.ptr = alloca ptr, align 8
+ store ptr %ptr, ptr %alloca.ptr, align 8, !tbaa !14
+ %ptr.idx = load ptr, ptr %alloca.ptr, align 8, !tbaa !14
+ %add.ptr = getelementptr inbounds ptr, ptr %ptr.idx, i64 4
+ %ptr.idx.1 = load ptr, ptr %add.ptr, align 8, !tbaa !16
+ %add.ptr1 = getelementptr inbounds [6 x double], ptr %ptr.idx.1, i64 6
+ %ptr.idx.2 = load <6 x double>, ptr %add.ptr1, align 8, !tbaa !5
+ %matrixext = extractelement <6 x double> %ptr.idx.2, i64 5
+ ret double %matrixext
+}
+
+declare void @opaque(ptr)
+
+!0 = !{!1, !1, i64 0}
+!1 = !{!"p1 int", !2, i64 0}
+!2 = !{!"any pointer", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!3, !3, i64 0}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"float", !3, i64 0}
+!8 = !{!9, !9, i64 0}
+!9 = !{!"long long", !3, i64 0}
+!10 = !{!11, !11, i64 0}
+!11 = !{!"p1 _ZTS7STRUCT1", !2, i64 0}
+!12 = !{!13, !11, i64 0}
+!13 = !{!"STRUCT2", !11, i64 0}
+!14 = !{!15, !15, i64 0}
+!15 = !{!"any p2 pointer", !2, i64 0}
+!16 = !{!2, !2, i64 0}
+;.
+; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
+; CHECK: [[META1]] = !{!"p1 int", [[META2:![0-9]+]], i64 0}
+; CHECK: [[META2]] = !{!"any pointer", [[META3:![0-9]+]], i64 0}
+; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}
+; CHECK: [[META4]] = !{!"Simple C/C++ TBAA"}
+; CHECK: [[TBAA5]] = !{[[META3]], [[META3]], i64 0}
+; CHECK: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
+; CHECK: [[META7]] = !{!"float", [[META3]], i64 0}
+; CHECK: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
+; CHECK: [[META9]] = !{!"long long", [[META3]], i64 0}
+; CHECK: [[TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0}
+; CHECK: [[META11]] = !{!"p1 _ZTS7STRUCT1", [[META2]], i64 0}
+; CHECK: [[TBAA12]] = !{[[META13:![0-9]+]], [[META11]], i64 0}
+; CHECK: [[META13]] = !{!"STRUCT2", [[META11]], i64 0}
+; CHECK: [[TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
+; CHECK: [[META15]] = !{!"any p2 pointer", [[META2]], i64 0}
+; CHECK: [[TBAA16]] = !{[[META2]], [[META2]], i64 0}
+;.
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test
new file mode 100644
index 0000000000000..e715639394846
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test
@@ -0,0 +1,7 @@
+## Test correct application of TBAA semantics in TBAA check lines.
+# RUN: cp -f %S/Inputs/tbaa-semantics-checks.ll %t.ll && %update_test_checks --version 5 %t.ll
+# RUN: diff -u %t.ll %S/Inputs/tbaa-semantics-checks.ll.expected
+
+## Check that running the script again does not change the result.
+# RUN: %update_test_checks %t.ll
+# RUN: diff -u %t.ll %S/Inputs/tbaa-semantics-checks.ll.expected
>From fd9a4baec4805d0a4ef58858e43b25dd11a0b801 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 2 Jul 2025 14:52:07 +0200
Subject: [PATCH 2/3] [UTC] Record TBAA semantics when autogenerating check
lines
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
UpdateTestChecks have been updated to take into account TBAA
semantics as well, when emitting checks. This is achieved by
parsing TBAA metadata for each tool invocation – whose tool
is identified by their prefixes –, and maintaining a global
dict of prefixes, TBAA nodes.
---
.../Inputs/tbaa-semantics-checks.ll.expected | 42 ++++-----
.../tbaa-semantics-checks.test | 2 +-
llvm/utils/UpdateTestChecks/common.py | 91 ++++++++++++++++++-
llvm/utils/update_cc_test_checks.py | 10 ++
llvm/utils/update_test_checks.py | 10 ++
5 files changed, 130 insertions(+), 25 deletions(-)
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected
index 0cd8b9c4817d0..39d573208e7b6 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected
@@ -1,11 +1,11 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -S | FileCheck %s
define void @store_unsignedptr(ptr %ptr) {
; CHECK-LABEL: define void @store_unsignedptr(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA0:![0-9]+]]
+; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[INTPTR_TBAA0:![0-9]+]]
; CHECK-NEXT: ret void
;
entry:
@@ -17,7 +17,7 @@ define void @store_char(ptr %ptr) {
; CHECK-LABEL: define void @store_char(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: store i8 0, ptr [[PTR]], align 1, !tbaa [[TBAA5:![0-9]+]]
+; CHECK-NEXT: store i8 0, ptr [[PTR]], align 1, !tbaa [[CHAR_TBAA5:![0-9]+]]
; CHECK-NEXT: ret void
;
entry:
@@ -29,9 +29,9 @@ define float @ptr_to_float(ptr %ptr) {
; CHECK-LABEL: define float @ptr_to_float(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR]], align 4, !tbaa [[TBAA6:![0-9]+]]
+; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR]], align 4, !tbaa [[FLOAT_TBAA6:![0-9]+]]
; CHECK-NEXT: call void @opaque(ptr [[PTR]])
-; CHECK-NEXT: [[VAL:%.*]] = load float, ptr [[PTR]], align 4, !tbaa [[TBAA6]]
+; CHECK-NEXT: [[VAL:%.*]] = load float, ptr [[PTR]], align 4, !tbaa [[FLOAT_TBAA6]]
; CHECK-NEXT: ret float [[VAL]]
;
entry:
@@ -45,8 +45,8 @@ define i64 @ptr_to_longlong(ptr %ptr) {
; CHECK-LABEL: define i64 @ptr_to_longlong(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR]], align 8, !tbaa [[TBAA8:![0-9]+]]
-; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8, !tbaa [[TBAA8]]
+; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR]], align 8, !tbaa [[LONG_LONG_TBAA8:![0-9]+]]
+; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8, !tbaa [[LONG_LONG_TBAA8]]
; CHECK-NEXT: ret i64 [[VAL]]
;
entry:
@@ -64,7 +64,7 @@ define void @store_struct1ptr(ptr %ptr) {
; CHECK-LABEL: define void @store_struct1ptr(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA10:![0-9]+]]
+; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[_ZTS7STRUCT1PTR_TBAA10:![0-9]+]]
; CHECK-NEXT: ret void
;
entry:
@@ -81,7 +81,7 @@ define void @store_struct2(ptr %ptr) {
; CHECK-LABEL: define void @store_struct2(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA12:![0-9]+]]
+; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[_ZTS7STRUCT1PTR_TBAA12:![0-9]+]]
; CHECK-NEXT: ret void
;
entry:
@@ -95,12 +95,12 @@ define double @access_matrix(ptr %ptr) {
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ALLOCA_PTR:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: store ptr [[PTR]], ptr [[ALLOCA_PTR]], align 8, !tbaa [[TBAA14:![0-9]+]]
-; CHECK-NEXT: [[PTR_IDX:%.*]] = load ptr, ptr [[ALLOCA_PTR]], align 8, !tbaa [[TBAA14]]
+; CHECK-NEXT: store ptr [[PTR]], ptr [[ALLOCA_PTR]], align 8, !tbaa [[ANYPTR_TBAA14:![0-9]+]]
+; CHECK-NEXT: [[PTR_IDX:%.*]] = load ptr, ptr [[ALLOCA_PTR]], align 8, !tbaa [[ANYPTR_TBAA14]]
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds ptr, ptr [[PTR_IDX]], i64 4
-; CHECK-NEXT: [[PTR_IDX_1:%.*]] = load ptr, ptr [[ADD_PTR]], align 8, !tbaa [[TBAA16:![0-9]+]]
+; CHECK-NEXT: [[PTR_IDX_1:%.*]] = load ptr, ptr [[ADD_PTR]], align 8, !tbaa [[ANYPTR_TBAA16:![0-9]+]]
; CHECK-NEXT: [[ADD_PTR1:%.*]] = getelementptr inbounds [6 x double], ptr [[PTR_IDX_1]], i64 6
-; CHECK-NEXT: [[PTR_IDX_2:%.*]] = load <6 x double>, ptr [[ADD_PTR1]], align 8, !tbaa [[TBAA5]]
+; CHECK-NEXT: [[PTR_IDX_2:%.*]] = load <6 x double>, ptr [[ADD_PTR1]], align 8, !tbaa [[CHAR_TBAA5]]
; CHECK-NEXT: [[MATRIXEXT:%.*]] = extractelement <6 x double> [[PTR_IDX_2]], i64 5
; CHECK-NEXT: ret double [[MATRIXEXT]]
;
@@ -136,21 +136,21 @@ declare void @opaque(ptr)
!15 = !{!"any p2 pointer", !2, i64 0}
!16 = !{!2, !2, i64 0}
;.
-; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
+; CHECK: [[INTPTR_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
; CHECK: [[META1]] = !{!"p1 int", [[META2:![0-9]+]], i64 0}
; CHECK: [[META2]] = !{!"any pointer", [[META3:![0-9]+]], i64 0}
; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}
; CHECK: [[META4]] = !{!"Simple C/C++ TBAA"}
-; CHECK: [[TBAA5]] = !{[[META3]], [[META3]], i64 0}
-; CHECK: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
+; CHECK: [[CHAR_TBAA5]] = !{[[META3]], [[META3]], i64 0}
+; CHECK: [[FLOAT_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
; CHECK: [[META7]] = !{!"float", [[META3]], i64 0}
-; CHECK: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
+; CHECK: [[LONG_LONG_TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
; CHECK: [[META9]] = !{!"long long", [[META3]], i64 0}
-; CHECK: [[TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0}
+; CHECK: [[_ZTS7STRUCT1PTR_TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0}
; CHECK: [[META11]] = !{!"p1 _ZTS7STRUCT1", [[META2]], i64 0}
-; CHECK: [[TBAA12]] = !{[[META13:![0-9]+]], [[META11]], i64 0}
+; CHECK: [[_ZTS7STRUCT1PTR_TBAA12]] = !{[[META13:![0-9]+]], [[META11]], i64 0}
; CHECK: [[META13]] = !{!"STRUCT2", [[META11]], i64 0}
-; CHECK: [[TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
+; CHECK: [[ANYPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
; CHECK: [[META15]] = !{!"any p2 pointer", [[META2]], i64 0}
-; CHECK: [[TBAA16]] = !{[[META2]], [[META2]], i64 0}
+; CHECK: [[ANYPTR_TBAA16]] = !{[[META2]], [[META2]], i64 0}
;.
diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test b/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test
index e715639394846..0849e8940084c 100644
--- a/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test
+++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test
@@ -1,5 +1,5 @@
## Test correct application of TBAA semantics in TBAA check lines.
-# RUN: cp -f %S/Inputs/tbaa-semantics-checks.ll %t.ll && %update_test_checks --version 5 %t.ll
+# RUN: cp -f %S/Inputs/tbaa-semantics-checks.ll %t.ll && %update_test_checks --version 6 %t.ll
# RUN: diff -u %t.ll %S/Inputs/tbaa-semantics-checks.ll.expected
## Check that running the script again does not change the result.
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index 178c623e33e0e..4e662c35dd8ff 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -28,8 +28,9 @@
4: --check-globals now has a third option ('smart'). The others are now called
'none' and 'all'. 'smart' is the default.
5: Basic block labels are matched by FileCheck expressions
+6: The semantics of TBAA checks has been incorporated in the check lines.
"""
-DEFAULT_VERSION = 5
+DEFAULT_VERSION = 6
SUPPORTED_ANALYSES = {
@@ -620,6 +621,9 @@ def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False):
SEPARATOR = "."
+METADATA_NODES_RE = re.compile(r'^\s*!(\d+)\s*=\s*!{(.*)}', re.M)
+TBAA_TAGS_RE = re.compile(r'!tbaa\s*!([0-9]+)')
+
def error(msg, test_file=None):
if test_file:
@@ -685,6 +689,59 @@ def get_globals_name_prefix(raw_tool_output):
return "_" if ch == "o" or ch == "x" else None
+def get_tbaa_records(version, raw_output_tools):
+ if version < 6:
+ return {}
+
+ # Retrieve all unique tbaa tags for the given IR.
+ unique_tbaa_tags = {f'!{n}' for n in TBAA_TAGS_RE.findall(raw_output_tools)}
+ if not unique_tbaa_tags:
+ return {}
+
+ # Small dict of metadata ID and its node content as value.
+ md_nodes = {
+ f'!{m.group(1)}': m.group(2)
+ for m in METADATA_NODES_RE.finditer(raw_output_tools)
+ }
+ assert md_nodes, "Shouldn't have TBAA tags without their type descriptors."
+
+ result = {}
+ for tag in unique_tbaa_tags:
+ type_desc = md_nodes.get(tag)
+ assert type_desc, f"Expected type descriptor for node {tag}."
+
+ # We deal with a tag of kind `(BaseTy, AccessTy, Offset)`.
+ access_ty = type_desc.split(',')[1].strip()
+
+ parent_ty = md_nodes.get(access_ty)
+ assert parent_ty, f"Couldn't find metadata for access type {access_ty}."
+
+ ty_name_field = parent_ty.split(',')[0]
+ assert ty_name_field.startswith('!"') and ty_name_field.endswith('"'), \
+ "First operand should be a MDString."
+ ty_name = ty_name_field[2:-1]
+
+ if ty_name.startswith("p"):
+ # Dealing with a pointer here.
+ pointee_ty_name = ty_name.split(maxsplit=1)[1]
+ if pointee_ty_name.startswith("omnipotent"):
+ pointee_ty_name = "char"
+ # TODO: If pointee_ty_name is a C++ name, should it be demangled?
+ tbaa_prefix = f'{pointee_ty_name.replace(" ", "_")}ptr'
+ elif ty_name.startswith("any"):
+ tbaa_prefix = "anyptr"
+ elif ty_name.startswith("omnipotent"):
+ tbaa_prefix = "char"
+ else:
+ tbaa_prefix = ty_name.replace(" ", "_")
+
+ # Record tag node and its semantics (e.g., INT_TBAA, INTPTR_TBAA).
+ tbaa_sema = f'{tbaa_prefix.upper()}_TBAA'
+ result[tag] = tbaa_sema
+
+ return result
+
+
def apply_filters(line, filters):
has_filter = False
for f in filters:
@@ -1775,6 +1832,7 @@ def generalize_check_lines(
ginfo: GeneralizerInfo,
vars_seen,
global_vars_seen,
+ global_tbaa_records = {},
preserve_names=False,
original_check_lines=None,
*,
@@ -1935,14 +1993,25 @@ def escape_braces(match_obj):
else:
vars_dict = global_vars_seen
+ mapped_name = mapping[value.name]
+
+ # We have computed the name mapping. Now, if possible,
+ # substitute the TBAA value name with its semantics.
+ if ginfo.get_version() >= 6:
+ if value.key == "!" and global_tbaa_records \
+ and mapped_name.startswith("TBAA") and mapped_name[4:].isdigit():
+ tbaa_sema = global_tbaa_records.get(value.text)
+ assert tbaa_sema, f"Shouldn't miss TBAA name for {value.text}?"
+ mapped_name = f"{tbaa_sema}{mapped_name[4:]}"
+
if key in defs:
line += vars_dict[key].get_def(
- mapping[value.name], value.prefix, value.suffix
+ mapped_name, value.prefix, value.suffix
)
defs.remove(key)
else:
line += vars_dict[key].get_use(
- mapping[value.name], value.prefix, value.suffix
+ mapped_name, value.prefix, value.suffix
)
line += line_template
@@ -1968,6 +2037,7 @@ def add_checks(
ginfo,
global_vars_seen_dict,
is_filtered,
+ global_tbaa_records_for_prefixes = {},
preserve_names=False,
original_check_lines: Mapping[str, List[str]] = {},
):
@@ -2018,6 +2088,10 @@ def add_checks(
global_vars_seen_dict[checkprefix] = {}
global_vars_seen_before = [key for key in global_vars_seen.keys()]
+ global_tbaa_records = next(
+ (val for key, val in global_tbaa_records_for_prefixes.items() if checkprefix in key),
+ None
+ )
vars_seen = {}
printed_prefixes.append(checkprefix)
@@ -2041,6 +2115,7 @@ def add_checks(
ginfo,
vars_seen,
global_vars_seen,
+ global_tbaa_records,
preserve_names,
original_check_lines=[],
no_meta_details=ginfo.no_meta_details(),
@@ -2155,6 +2230,7 @@ def add_checks(
ginfo,
vars_seen,
global_vars_seen,
+ global_tbaa_records,
preserve_names,
original_check_lines=original_check_lines.get(checkprefix),
)
@@ -2217,6 +2293,7 @@ def add_ir_checks(
function_sig,
ginfo: GeneralizerInfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
is_filtered,
original_check_lines={},
):
@@ -2241,6 +2318,7 @@ def add_ir_checks(
ginfo,
global_vars_seen_dict,
is_filtered,
+ global_tbaa_records_for_prefixes,
preserve_names,
original_check_lines=original_check_lines,
)
@@ -2627,6 +2705,7 @@ def add_global_checks(
output_lines,
ginfo: GeneralizerInfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
preserve_names,
is_before_functions,
global_check_setting,
@@ -2659,6 +2738,11 @@ def add_global_checks(
check_lines = []
global_vars_seen_before = [key for key in global_vars_seen.keys()]
+ global_tbaa_records = next(
+ (val for key, val in global_tbaa_records_for_prefixes.items() if checkprefix in key),
+ None
+ )
+
lines_w_index = glob_val_dict[checkprefix][nameless_value.check_prefix]
lines_w_index = filter_globals_according_to_preference(
lines_w_index,
@@ -2682,6 +2766,7 @@ def add_global_checks(
ginfo,
{},
global_vars_seen,
+ global_tbaa_records,
preserve_names,
unstable_globals_only=True,
)
diff --git a/llvm/utils/update_cc_test_checks.py b/llvm/utils/update_cc_test_checks.py
index 4102ee4ecbd22..97b446d565973 100755
--- a/llvm/utils/update_cc_test_checks.py
+++ b/llvm/utils/update_cc_test_checks.py
@@ -365,6 +365,7 @@ def update_test(ti: common.TestInfo):
ginfo=ginfo,
)
+ global_tbaa_records_for_prefixes = {}
for prefixes, args, extra_commands, triple_in_cmd in run_list:
# Execute non-filechecked runline.
if not prefixes:
@@ -391,6 +392,10 @@ def update_test(ti: common.TestInfo):
raw_tool_output,
)
+ # Extract TBAA metadata for later usage in check lines.
+ tbaa_map = common.get_tbaa_records(ti.args.version, raw_tool_output)
+ global_tbaa_records_for_prefixes[tuple(prefixes)] = tbaa_map
+
# Invoke clang -Xclang -ast-dump=json to get mapping from start lines to
# mangled names. Forward all clang args for now.
for k, v in get_line2func_list(
@@ -436,6 +441,7 @@ def check_generator(my_output_lines, prefixes, func):
ti.args.function_signature,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
is_filtered=builder.is_filtered(),
)
@@ -448,6 +454,7 @@ def check_generator(my_output_lines, prefixes, func):
output_lines,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
False,
True,
ti.args.check_globals,
@@ -509,6 +516,7 @@ def check_generator(my_output_lines, prefixes, func):
output_lines,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
False,
True,
ti.args.check_globals,
@@ -529,6 +537,7 @@ def check_generator(my_output_lines, prefixes, func):
args.function_signature,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
is_filtered=builder.is_filtered(),
)
)
@@ -547,6 +556,7 @@ def check_generator(my_output_lines, prefixes, func):
output_lines,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
False,
False,
ti.args.check_globals,
diff --git a/llvm/utils/update_test_checks.py b/llvm/utils/update_test_checks.py
index ff5bb7d782346..3b562fbc54f78 100755
--- a/llvm/utils/update_test_checks.py
+++ b/llvm/utils/update_test_checks.py
@@ -93,6 +93,7 @@ def update_test(ti: common.TestInfo):
ginfo = common.make_ir_generalizer(ti.args.version, ti.args.check_globals == "none")
global_vars_seen_dict = {}
+ global_tbaa_records_for_prefixes = {}
builder = common.FunctionTestBuilder(
run_list=prefix_list,
flags=ti.args,
@@ -124,6 +125,10 @@ def update_test(ti: common.TestInfo):
)
builder.processed_prefixes(prefixes)
+ # Extract TBAA metadata for later usage in check lines.
+ tbaa_map = common.get_tbaa_records(ti.args.version, raw_tool_output)
+ global_tbaa_records_for_prefixes[tuple(prefixes)] = tbaa_map
+
prefix_set = set([prefix for prefixes, _, _ in prefix_list for prefix in prefixes])
if not ti.args.reset_variable_names:
@@ -165,6 +170,7 @@ def update_test(ti: common.TestInfo):
output_lines,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
args.preserve_names,
True,
args.check_globals,
@@ -188,6 +194,7 @@ def update_test(ti: common.TestInfo):
args.function_signature,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
is_filtered=builder.is_filtered(),
original_check_lines=original_check_lines.get(func, {}),
),
@@ -220,6 +227,7 @@ def update_test(ti: common.TestInfo):
args.function_signature,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
is_filtered=builder.is_filtered(),
original_check_lines=original_check_lines.get(func_name, {}),
)
@@ -237,6 +245,7 @@ def update_test(ti: common.TestInfo):
output_lines,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
args.preserve_names,
True,
args.check_globals,
@@ -286,6 +295,7 @@ def update_test(ti: common.TestInfo):
output_lines,
ginfo,
global_vars_seen_dict,
+ global_tbaa_records_for_prefixes,
args.preserve_names,
False,
args.check_globals,
>From 00af9aff53d67209537026fe446a358c900ab98c Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 9 Jul 2025 10:29:11 +0200
Subject: [PATCH 3/3] !fixup darker format
---
llvm/utils/UpdateTestChecks/common.py | 47 +++++++++++++++++----------
1 file changed, 30 insertions(+), 17 deletions(-)
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index 4e662c35dd8ff..d4982aa2f4966 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -621,8 +621,8 @@ def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False):
SEPARATOR = "."
-METADATA_NODES_RE = re.compile(r'^\s*!(\d+)\s*=\s*!{(.*)}', re.M)
-TBAA_TAGS_RE = re.compile(r'!tbaa\s*!([0-9]+)')
+METADATA_NODES_RE = re.compile(r"^\s*!(\d+)\s*=\s*!{(.*)}", re.M)
+TBAA_TAGS_RE = re.compile(r"!tbaa\s*!([0-9]+)")
def error(msg, test_file=None):
@@ -694,13 +694,13 @@ def get_tbaa_records(version, raw_output_tools):
return {}
# Retrieve all unique tbaa tags for the given IR.
- unique_tbaa_tags = {f'!{n}' for n in TBAA_TAGS_RE.findall(raw_output_tools)}
+ unique_tbaa_tags = {f"!{n}" for n in TBAA_TAGS_RE.findall(raw_output_tools)}
if not unique_tbaa_tags:
return {}
# Small dict of metadata ID and its node content as value.
md_nodes = {
- f'!{m.group(1)}': m.group(2)
+ f"!{m.group(1)}": m.group(2)
for m in METADATA_NODES_RE.finditer(raw_output_tools)
}
assert md_nodes, "Shouldn't have TBAA tags without their type descriptors."
@@ -711,14 +711,15 @@ def get_tbaa_records(version, raw_output_tools):
assert type_desc, f"Expected type descriptor for node {tag}."
# We deal with a tag of kind `(BaseTy, AccessTy, Offset)`.
- access_ty = type_desc.split(',')[1].strip()
+ access_ty = type_desc.split(",")[1].strip()
parent_ty = md_nodes.get(access_ty)
assert parent_ty, f"Couldn't find metadata for access type {access_ty}."
- ty_name_field = parent_ty.split(',')[0]
- assert ty_name_field.startswith('!"') and ty_name_field.endswith('"'), \
- "First operand should be a MDString."
+ ty_name_field = parent_ty.split(",")[0]
+ assert ty_name_field.startswith('!"') and ty_name_field.endswith(
+ '"'
+ ), "First operand should be a MDString."
ty_name = ty_name_field[2:-1]
if ty_name.startswith("p"):
@@ -736,7 +737,7 @@ def get_tbaa_records(version, raw_output_tools):
tbaa_prefix = ty_name.replace(" ", "_")
# Record tag node and its semantics (e.g., INT_TBAA, INTPTR_TBAA).
- tbaa_sema = f'{tbaa_prefix.upper()}_TBAA'
+ tbaa_sema = f"{tbaa_prefix.upper()}_TBAA"
result[tag] = tbaa_sema
return result
@@ -1832,7 +1833,7 @@ def generalize_check_lines(
ginfo: GeneralizerInfo,
vars_seen,
global_vars_seen,
- global_tbaa_records = {},
+ global_tbaa_records={},
preserve_names=False,
original_check_lines=None,
*,
@@ -1998,8 +1999,12 @@ def escape_braces(match_obj):
# We have computed the name mapping. Now, if possible,
# substitute the TBAA value name with its semantics.
if ginfo.get_version() >= 6:
- if value.key == "!" and global_tbaa_records \
- and mapped_name.startswith("TBAA") and mapped_name[4:].isdigit():
+ if (
+ value.key == "!"
+ and global_tbaa_records
+ and mapped_name.startswith("TBAA")
+ and mapped_name[4:].isdigit()
+ ):
tbaa_sema = global_tbaa_records.get(value.text)
assert tbaa_sema, f"Shouldn't miss TBAA name for {value.text}?"
mapped_name = f"{tbaa_sema}{mapped_name[4:]}"
@@ -2037,7 +2042,7 @@ def add_checks(
ginfo,
global_vars_seen_dict,
is_filtered,
- global_tbaa_records_for_prefixes = {},
+ global_tbaa_records_for_prefixes={},
preserve_names=False,
original_check_lines: Mapping[str, List[str]] = {},
):
@@ -2089,8 +2094,12 @@ def add_checks(
global_vars_seen_before = [key for key in global_vars_seen.keys()]
global_tbaa_records = next(
- (val for key, val in global_tbaa_records_for_prefixes.items() if checkprefix in key),
- None
+ (
+ val
+ for key, val in global_tbaa_records_for_prefixes.items()
+ if checkprefix in key
+ ),
+ None,
)
vars_seen = {}
@@ -2739,8 +2748,12 @@ def add_global_checks(
check_lines = []
global_vars_seen_before = [key for key in global_vars_seen.keys()]
global_tbaa_records = next(
- (val for key, val in global_tbaa_records_for_prefixes.items() if checkprefix in key),
- None
+ (
+ val
+ for key, val in global_tbaa_records_for_prefixes.items()
+ if checkprefix in key
+ ),
+ None,
)
lines_w_index = glob_val_dict[checkprefix][nameless_value.check_prefix]
More information about the llvm-commits
mailing list