Skip to content

Commit 1cacc73

Browse files
[UTC] Record TBAA semantics when autogenerating check lines
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.
1 parent cb9cb4e commit 1cacc73

File tree

5 files changed

+146
-25
lines changed

5 files changed

+146
-25
lines changed

llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/tbaa-semantics-checks.ll.expected

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
22
; RUN: opt < %s -S | FileCheck %s
33

44
define void @store_unsignedptr(ptr %ptr) {
55
; CHECK-LABEL: define void @store_unsignedptr(
66
; CHECK-SAME: ptr [[PTR:%.*]]) {
77
; CHECK-NEXT: [[ENTRY:.*:]]
8-
; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA0:![0-9]+]]
8+
; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[INTPTR_TBAA0:![0-9]+]]
99
; CHECK-NEXT: ret void
1010
;
1111
entry:
@@ -17,7 +17,7 @@ define void @store_char(ptr %ptr) {
1717
; CHECK-LABEL: define void @store_char(
1818
; CHECK-SAME: ptr [[PTR:%.*]]) {
1919
; CHECK-NEXT: [[ENTRY:.*:]]
20-
; CHECK-NEXT: store i8 0, ptr [[PTR]], align 1, !tbaa [[TBAA5:![0-9]+]]
20+
; CHECK-NEXT: store i8 0, ptr [[PTR]], align 1, !tbaa [[CHAR_TBAA5:![0-9]+]]
2121
; CHECK-NEXT: ret void
2222
;
2323
entry:
@@ -29,9 +29,9 @@ define float @ptr_to_float(ptr %ptr) {
2929
; CHECK-LABEL: define float @ptr_to_float(
3030
; CHECK-SAME: ptr [[PTR:%.*]]) {
3131
; CHECK-NEXT: [[ENTRY:.*:]]
32-
; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR]], align 4, !tbaa [[TBAA6:![0-9]+]]
32+
; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR]], align 4, !tbaa [[FLOAT_TBAA6:![0-9]+]]
3333
; CHECK-NEXT: call void @opaque(ptr [[PTR]])
34-
; CHECK-NEXT: [[VAL:%.*]] = load float, ptr [[PTR]], align 4, !tbaa [[TBAA6]]
34+
; CHECK-NEXT: [[VAL:%.*]] = load float, ptr [[PTR]], align 4, !tbaa [[FLOAT_TBAA6]]
3535
; CHECK-NEXT: ret float [[VAL]]
3636
;
3737
entry:
@@ -45,8 +45,8 @@ define i64 @ptr_to_longlong(ptr %ptr) {
4545
; CHECK-LABEL: define i64 @ptr_to_longlong(
4646
; CHECK-SAME: ptr [[PTR:%.*]]) {
4747
; CHECK-NEXT: [[ENTRY:.*:]]
48-
; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR]], align 8, !tbaa [[TBAA8:![0-9]+]]
49-
; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8, !tbaa [[TBAA8]]
48+
; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR]], align 8, !tbaa [[LONG_LONG_TBAA8:![0-9]+]]
49+
; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8, !tbaa [[LONG_LONG_TBAA8]]
5050
; CHECK-NEXT: ret i64 [[VAL]]
5151
;
5252
entry:
@@ -64,7 +64,7 @@ define void @store_struct1ptr(ptr %ptr) {
6464
; CHECK-LABEL: define void @store_struct1ptr(
6565
; CHECK-SAME: ptr [[PTR:%.*]]) {
6666
; CHECK-NEXT: [[ENTRY:.*:]]
67-
; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA10:![0-9]+]]
67+
; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[_ZTS7STRUCT1PTR_TBAA10:![0-9]+]]
6868
; CHECK-NEXT: ret void
6969
;
7070
entry:
@@ -81,7 +81,7 @@ define void @store_struct2(ptr %ptr) {
8181
; CHECK-LABEL: define void @store_struct2(
8282
; CHECK-SAME: ptr [[PTR:%.*]]) {
8383
; CHECK-NEXT: [[ENTRY:.*:]]
84-
; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[TBAA12:![0-9]+]]
84+
; CHECK-NEXT: store ptr null, ptr [[PTR]], align 8, !tbaa [[_ZTS7STRUCT1PTR_TBAA12:![0-9]+]]
8585
; CHECK-NEXT: ret void
8686
;
8787
entry:
@@ -95,12 +95,12 @@ define double @access_matrix(ptr %ptr) {
9595
; CHECK-SAME: ptr [[PTR:%.*]]) {
9696
; CHECK-NEXT: [[ENTRY:.*:]]
9797
; CHECK-NEXT: [[ALLOCA_PTR:%.*]] = alloca ptr, align 8
98-
; CHECK-NEXT: store ptr [[PTR]], ptr [[ALLOCA_PTR]], align 8, !tbaa [[TBAA14:![0-9]+]]
99-
; CHECK-NEXT: [[PTR_IDX:%.*]] = load ptr, ptr [[ALLOCA_PTR]], align 8, !tbaa [[TBAA14]]
98+
; CHECK-NEXT: store ptr [[PTR]], ptr [[ALLOCA_PTR]], align 8, !tbaa [[ANYPTR_TBAA14:![0-9]+]]
99+
; CHECK-NEXT: [[PTR_IDX:%.*]] = load ptr, ptr [[ALLOCA_PTR]], align 8, !tbaa [[ANYPTR_TBAA14]]
100100
; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds ptr, ptr [[PTR_IDX]], i64 4
101-
; CHECK-NEXT: [[PTR_IDX_1:%.*]] = load ptr, ptr [[ADD_PTR]], align 8, !tbaa [[TBAA16:![0-9]+]]
101+
; CHECK-NEXT: [[PTR_IDX_1:%.*]] = load ptr, ptr [[ADD_PTR]], align 8, !tbaa [[ANYPTR_TBAA16:![0-9]+]]
102102
; CHECK-NEXT: [[ADD_PTR1:%.*]] = getelementptr inbounds [6 x double], ptr [[PTR_IDX_1]], i64 6
103-
; CHECK-NEXT: [[PTR_IDX_2:%.*]] = load <6 x double>, ptr [[ADD_PTR1]], align 8, !tbaa [[TBAA5]]
103+
; CHECK-NEXT: [[PTR_IDX_2:%.*]] = load <6 x double>, ptr [[ADD_PTR1]], align 8, !tbaa [[CHAR_TBAA5]]
104104
; CHECK-NEXT: [[MATRIXEXT:%.*]] = extractelement <6 x double> [[PTR_IDX_2]], i64 5
105105
; CHECK-NEXT: ret double [[MATRIXEXT]]
106106
;
@@ -136,21 +136,21 @@ declare void @opaque(ptr)
136136
!15 = !{!"any p2 pointer", !2, i64 0}
137137
!16 = !{!2, !2, i64 0}
138138
;.
139-
; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
139+
; CHECK: [[INTPTR_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
140140
; CHECK: [[META1]] = !{!"p1 int", [[META2:![0-9]+]], i64 0}
141141
; CHECK: [[META2]] = !{!"any pointer", [[META3:![0-9]+]], i64 0}
142142
; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}
143143
; CHECK: [[META4]] = !{!"Simple C/C++ TBAA"}
144-
; CHECK: [[TBAA5]] = !{[[META3]], [[META3]], i64 0}
145-
; CHECK: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
144+
; CHECK: [[CHAR_TBAA5]] = !{[[META3]], [[META3]], i64 0}
145+
; CHECK: [[FLOAT_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
146146
; CHECK: [[META7]] = !{!"float", [[META3]], i64 0}
147-
; CHECK: [[TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
147+
; CHECK: [[LONG_LONG_TBAA8]] = !{[[META9:![0-9]+]], [[META9]], i64 0}
148148
; CHECK: [[META9]] = !{!"long long", [[META3]], i64 0}
149-
; CHECK: [[TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0}
149+
; CHECK: [[_ZTS7STRUCT1PTR_TBAA10]] = !{[[META11:![0-9]+]], [[META11]], i64 0}
150150
; CHECK: [[META11]] = !{!"p1 _ZTS7STRUCT1", [[META2]], i64 0}
151-
; CHECK: [[TBAA12]] = !{[[META13:![0-9]+]], [[META11]], i64 0}
151+
; CHECK: [[_ZTS7STRUCT1PTR_TBAA12]] = !{[[META13:![0-9]+]], [[META11]], i64 0}
152152
; CHECK: [[META13]] = !{!"STRUCT2", [[META11]], i64 0}
153-
; CHECK: [[TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
153+
; CHECK: [[ANYPTR_TBAA14]] = !{[[META15:![0-9]+]], [[META15]], i64 0}
154154
; CHECK: [[META15]] = !{!"any p2 pointer", [[META2]], i64 0}
155-
; CHECK: [[TBAA16]] = !{[[META2]], [[META2]], i64 0}
155+
; CHECK: [[ANYPTR_TBAA16]] = !{[[META2]], [[META2]], i64 0}
156156
;.

llvm/test/tools/UpdateTestChecks/update_test_checks/tbaa-semantics-checks.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## Test correct application of TBAA semantics in TBAA check lines.
2-
# RUN: cp -f %S/Inputs/tbaa-semantics-checks.ll %t.ll && %update_test_checks --version 5 %t.ll
2+
# RUN: cp -f %S/Inputs/tbaa-semantics-checks.ll %t.ll && %update_test_checks --version 6 %t.ll
33
# RUN: diff -u %t.ll %S/Inputs/tbaa-semantics-checks.ll.expected
44

55
## Check that running the script again does not change the result.

llvm/utils/UpdateTestChecks/common.py

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
4: --check-globals now has a third option ('smart'). The others are now called
2929
'none' and 'all'. 'smart' is the default.
3030
5: Basic block labels are matched by FileCheck expressions
31+
6: The semantics of TBAA checks has been incorporated in the check lines.
3132
"""
32-
DEFAULT_VERSION = 5
33+
DEFAULT_VERSION = 6
3334

3435

3536
SUPPORTED_ANALYSES = {
@@ -622,6 +623,9 @@ def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False):
622623

623624
SEPARATOR = "."
624625

626+
METADATA_NODES_RE = re.compile(r"^\s*!(\d+)\s*=\s*!\{(.*)\}", re.M)
627+
TBAA_TAGS_RE = re.compile(r"!tbaa\s*!([0-9]+)")
628+
625629

626630
def error(msg, test_file=None):
627631
if test_file:
@@ -687,6 +691,63 @@ def get_globals_name_prefix(raw_tool_output):
687691
return "_" if ch == "o" or ch == "x" else None
688692

689693

694+
def get_tbaa_records(version, raw_output_tools):
695+
if version < 6:
696+
return {}
697+
698+
# Retrieve all unique tbaa tags for the given IR.
699+
unique_tbaa_tags = {f"!{n}" for n in TBAA_TAGS_RE.findall(raw_output_tools)}
700+
if not unique_tbaa_tags:
701+
return {}
702+
703+
# Small dict of metadata ID and its node content as value.
704+
md_nodes = {
705+
f"!{m.group(1)}": m.group(2)
706+
for m in METADATA_NODES_RE.finditer(raw_output_tools)
707+
}
708+
assert md_nodes, "Shouldn't have TBAA tags without their type descriptors."
709+
710+
result = {}
711+
for tag in unique_tbaa_tags:
712+
type_desc = md_nodes.get(tag)
713+
assert type_desc, f"Expected type descriptor for node {tag}."
714+
715+
# We deal with a tag of kind `(BaseTy, AccessTy, Offset)`.
716+
access_ty = type_desc.split(",")[1].strip()
717+
718+
parent_ty = md_nodes.get(access_ty)
719+
assert parent_ty, f"Couldn't find metadata for access type {access_ty}."
720+
721+
# First operand should be a MDString. If not, likely dealing with
722+
# `new-struct-path-tbaa`.
723+
# TODO: Support `new-struct-path-tbaa` TBAA format.
724+
ty_name_field = parent_ty.split(",")[0]
725+
if not (ty_name_field.startswith('!"') and ty_name_field.endswith('"')):
726+
return {}
727+
ty_name = ty_name_field[2:-1]
728+
729+
if ty_name.startswith("p"):
730+
# Dealing with a pointer here.
731+
pointee_ty_name = ty_name.split(maxsplit=1)[1]
732+
if pointee_ty_name.startswith("omnipotent"):
733+
pointee_ty_name = "char"
734+
# TODO: If pointee_ty_name is a C++ name, should it be demangled?
735+
pointee_ty_name = pointee_ty_name.replace(" ", "_")
736+
tbaa_prefix = f"{pointee_ty_name}ptr"
737+
elif ty_name.startswith("any"):
738+
tbaa_prefix = "anyptr"
739+
elif ty_name.startswith("omnipotent"):
740+
tbaa_prefix = "char"
741+
else:
742+
tbaa_prefix = ty_name.replace(" ", "_")
743+
744+
# Record tag node and its semantics (e.g., INT_TBAA, INTPTR_TBAA).
745+
tbaa_sema = f"{tbaa_prefix.upper()}_TBAA"
746+
result[tag] = tbaa_sema
747+
748+
return result
749+
750+
690751
def apply_filters(line, filters):
691752
has_filter = False
692753
for f in filters:
@@ -1783,6 +1844,7 @@ def generalize_check_lines(
17831844
ginfo: GeneralizerInfo,
17841845
vars_seen,
17851846
global_vars_seen,
1847+
global_tbaa_records={},
17861848
preserve_names=False,
17871849
original_check_lines=None,
17881850
*,
@@ -1943,14 +2005,29 @@ def escape_braces(match_obj):
19432005
else:
19442006
vars_dict = global_vars_seen
19452007

2008+
mapped_name = mapping[value.name]
2009+
2010+
# We have computed the name mapping. Now, if possible,
2011+
# substitute the TBAA value name with its semantics.
2012+
if ginfo.get_version() >= 6:
2013+
if (
2014+
value.key == "!"
2015+
and global_tbaa_records
2016+
and mapped_name.startswith("TBAA")
2017+
and mapped_name[4:].isdigit()
2018+
):
2019+
tbaa_sema = global_tbaa_records.get(value.text)
2020+
assert tbaa_sema, f"Shouldn't miss TBAA name for {value.text}?"
2021+
mapped_name = f"{tbaa_sema}{mapped_name[4:]}"
2022+
19462023
if key in defs:
19472024
line += vars_dict[key].get_def(
1948-
mapping[value.name], value.prefix, value.suffix
2025+
mapped_name, value.prefix, value.suffix
19492026
)
19502027
defs.remove(key)
19512028
else:
19522029
line += vars_dict[key].get_use(
1953-
mapping[value.name], value.prefix, value.suffix
2030+
mapped_name, value.prefix, value.suffix
19542031
)
19552032

19562033
line += line_template
@@ -1976,6 +2053,7 @@ def add_checks(
19762053
ginfo,
19772054
global_vars_seen_dict,
19782055
is_filtered,
2056+
global_tbaa_records_for_prefixes={},
19792057
preserve_names=False,
19802058
original_check_lines: Mapping[str, List[str]] = {},
19812059
):
@@ -2026,6 +2104,14 @@ def add_checks(
20262104
global_vars_seen_dict[checkprefix] = {}
20272105

20282106
global_vars_seen_before = [key for key in global_vars_seen.keys()]
2107+
global_tbaa_records = next(
2108+
(
2109+
val
2110+
for key, val in global_tbaa_records_for_prefixes.items()
2111+
if checkprefix in key
2112+
),
2113+
None,
2114+
)
20292115

20302116
vars_seen = {}
20312117
printed_prefixes.append(checkprefix)
@@ -2049,6 +2135,7 @@ def add_checks(
20492135
ginfo,
20502136
vars_seen,
20512137
global_vars_seen,
2138+
global_tbaa_records,
20522139
preserve_names,
20532140
original_check_lines=[],
20542141
no_meta_details=ginfo.no_meta_details(),
@@ -2163,6 +2250,7 @@ def add_checks(
21632250
ginfo,
21642251
vars_seen,
21652252
global_vars_seen,
2253+
global_tbaa_records,
21662254
preserve_names,
21672255
original_check_lines=original_check_lines.get(checkprefix),
21682256
)
@@ -2225,6 +2313,7 @@ def add_ir_checks(
22252313
function_sig,
22262314
ginfo: GeneralizerInfo,
22272315
global_vars_seen_dict,
2316+
global_tbaa_records_for_prefixes,
22282317
is_filtered,
22292318
original_check_lines={},
22302319
):
@@ -2249,6 +2338,7 @@ def add_ir_checks(
22492338
ginfo,
22502339
global_vars_seen_dict,
22512340
is_filtered,
2341+
global_tbaa_records_for_prefixes,
22522342
preserve_names,
22532343
original_check_lines=original_check_lines,
22542344
)
@@ -2635,6 +2725,7 @@ def add_global_checks(
26352725
output_lines,
26362726
ginfo: GeneralizerInfo,
26372727
global_vars_seen_dict,
2728+
global_tbaa_records_for_prefixes,
26382729
preserve_names,
26392730
is_before_functions,
26402731
global_check_setting,
@@ -2667,6 +2758,15 @@ def add_global_checks(
26672758

26682759
check_lines = []
26692760
global_vars_seen_before = [key for key in global_vars_seen.keys()]
2761+
global_tbaa_records = next(
2762+
(
2763+
val
2764+
for key, val in global_tbaa_records_for_prefixes.items()
2765+
if checkprefix in key
2766+
),
2767+
None,
2768+
)
2769+
26702770
lines_w_index = glob_val_dict[checkprefix][nameless_value.check_prefix]
26712771
lines_w_index = filter_globals_according_to_preference(
26722772
lines_w_index,
@@ -2690,6 +2790,7 @@ def add_global_checks(
26902790
ginfo,
26912791
{},
26922792
global_vars_seen,
2793+
global_tbaa_records,
26932794
preserve_names,
26942795
unstable_globals_only=True,
26952796
)

llvm/utils/update_cc_test_checks.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ def update_test(ti: common.TestInfo):
365365
ginfo=ginfo,
366366
)
367367

368+
global_tbaa_records_for_prefixes = {}
368369
for prefixes, args, extra_commands, triple_in_cmd in run_list:
369370
# Execute non-filechecked runline.
370371
if not prefixes:
@@ -391,6 +392,10 @@ def update_test(ti: common.TestInfo):
391392
raw_tool_output,
392393
)
393394

395+
# Extract TBAA metadata for later usage in check lines.
396+
tbaa_map = common.get_tbaa_records(ti.args.version, raw_tool_output)
397+
global_tbaa_records_for_prefixes[tuple(prefixes)] = tbaa_map
398+
394399
# Invoke clang -Xclang -ast-dump=json to get mapping from start lines to
395400
# mangled names. Forward all clang args for now.
396401
for k, v in get_line2func_list(
@@ -436,6 +441,7 @@ def check_generator(my_output_lines, prefixes, func):
436441
ti.args.function_signature,
437442
ginfo,
438443
global_vars_seen_dict,
444+
global_tbaa_records_for_prefixes,
439445
is_filtered=builder.is_filtered(),
440446
)
441447

@@ -448,6 +454,7 @@ def check_generator(my_output_lines, prefixes, func):
448454
output_lines,
449455
ginfo,
450456
global_vars_seen_dict,
457+
global_tbaa_records_for_prefixes,
451458
False,
452459
True,
453460
ti.args.check_globals,
@@ -509,6 +516,7 @@ def check_generator(my_output_lines, prefixes, func):
509516
output_lines,
510517
ginfo,
511518
global_vars_seen_dict,
519+
global_tbaa_records_for_prefixes,
512520
False,
513521
True,
514522
ti.args.check_globals,
@@ -529,6 +537,7 @@ def check_generator(my_output_lines, prefixes, func):
529537
args.function_signature,
530538
ginfo,
531539
global_vars_seen_dict,
540+
global_tbaa_records_for_prefixes,
532541
is_filtered=builder.is_filtered(),
533542
)
534543
)
@@ -547,6 +556,7 @@ def check_generator(my_output_lines, prefixes, func):
547556
output_lines,
548557
ginfo,
549558
global_vars_seen_dict,
559+
global_tbaa_records_for_prefixes,
550560
False,
551561
False,
552562
ti.args.check_globals,

0 commit comments

Comments
 (0)