Skip to content

Commit 9d48df7

Browse files
authored
[UpdateTestChecks] Don't fail silently when conflicting CHECK lines means no checks are generated for some functions (#159321)
There is a warning that triggers if you (for instance) run `update_llc_test_checks.py` on an input where _all_ functions have conflicting check lines and so no checks are generated. However, there are no warnings emitted at all for the case where some functions have non-conflicting check lines but others don't. This is a source of frustration because running update_llc_test_checks can result in all check lines being removed for certain functions when such a conflict exists with no warning, meaning we have to be extra vigilant inspecting the diff. I've also personally wasted time tracking down the source of the dropped lines assuming that update_test_checks would emit a warning in such cases. This change adds logic to emit warnings on a function-by-function basis for any RUN that has conflicting prefixes meaning no output is generated. This subsumes the previous warning for when _all_ functions conflict.
1 parent b7908e3 commit 9d48df7

File tree

8 files changed

+169
-21
lines changed

8 files changed

+169
-21
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: sed 's/RETVAL/1/g' %s | llc -mtriple=riscv32 \
2+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKA %s
3+
; RUN: sed 's/RETVAL/2/g' %s | llc -mtriple=riscv32 \
4+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKA %s
5+
; RUN: sed 's/RETVAL/3/g' %s | llc -mtriple=riscv32 \
6+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKB %s
7+
; RUN: sed 's/RETVAL/4/g' %s | llc -mtriple=riscv32 \
8+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKB %s
9+
10+
define i32 @foo() {
11+
ret i32 RETVAL
12+
}
13+
14+
define i32 @bar() {
15+
ret i32 100
16+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no-generate-body-for-unused-prefixes
2+
; RUN: sed 's/RETVAL/1/g' %s | llc -mtriple=riscv32 \
3+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKA %s
4+
; RUN: sed 's/RETVAL/2/g' %s | llc -mtriple=riscv32 \
5+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKA %s
6+
; RUN: sed 's/RETVAL/3/g' %s | llc -mtriple=riscv32 \
7+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKB %s
8+
; RUN: sed 's/RETVAL/4/g' %s | llc -mtriple=riscv32 \
9+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKB %s
10+
11+
define i32 @foo() {
12+
ret i32 RETVAL
13+
}
14+
15+
define i32 @bar() {
16+
; CHECK-LABEL: bar:
17+
; CHECK: # %bb.0:
18+
; CHECK-NEXT: li a0, 100
19+
; CHECK-NEXT: ret
20+
ret i32 100
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
; RUN: sed 's/FN/foo/g' %s | llc -mtriple=riscv32 \
2+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKA %s
3+
; RUN: sed 's/FN/foo/g' %s | llc -mtriple=riscv32 \
4+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKB %s
5+
; RUN: sed 's/FN/bar/g' %s | llc -mtriple=riscv32 \
6+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKC %s
7+
8+
define i32 @FN() {
9+
ret i32 1
10+
}
11+
12+
define i32 @common() {
13+
ret i32 100
14+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --include-generated-funcs
2+
; RUN: sed 's/FN/foo/g' %s | llc -mtriple=riscv32 \
3+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKA %s
4+
; RUN: sed 's/FN/foo/g' %s | llc -mtriple=riscv32 \
5+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKB %s
6+
; RUN: sed 's/FN/bar/g' %s | llc -mtriple=riscv32 \
7+
; RUN: | FileCheck -check-prefixes=CHECK,CHECKC %s
8+
9+
define i32 @FN() {
10+
ret i32 1
11+
}
12+
13+
define i32 @common() {
14+
ret i32 100
15+
}
16+
; CHECK-LABEL: foo:
17+
; CHECK: # %bb.0:
18+
; CHECK-NEXT: li a0, 1
19+
; CHECK-NEXT: ret
20+
;
21+
; CHECK-LABEL: common:
22+
; CHECK: # %bb.0:
23+
; CHECK-NEXT: li a0, 100
24+
; CHECK-NEXT: ret
25+
;
26+
; CHECKA-LABEL: foo:
27+
; CHECKA: # %bb.0:
28+
; CHECKA-NEXT: li a0, 1
29+
; CHECKA-NEXT: ret
30+
;
31+
; CHECKA-LABEL: common:
32+
; CHECKA: # %bb.0:
33+
; CHECKA-NEXT: li a0, 100
34+
; CHECKA-NEXT: ret
35+
;
36+
; CHECKB-LABEL: foo:
37+
; CHECKB: # %bb.0:
38+
; CHECKB-NEXT: li a0, 1
39+
; CHECKB-NEXT: ret
40+
;
41+
; CHECKB-LABEL: common:
42+
; CHECKB: # %bb.0:
43+
; CHECKB-NEXT: li a0, 100
44+
; CHECKB-NEXT: ret
45+
;
46+
; CHECKC-LABEL: bar:
47+
; CHECKC: # %bb.0:
48+
; CHECKC-NEXT: li a0, 1
49+
; CHECKC-NEXT: ret
50+
;
51+
; CHECKC-LABEL: common:
52+
; CHECKC: # %bb.0:
53+
; CHECKC-NEXT: li a0, 100
54+
; CHECKC-NEXT: ret
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# REQUIRES: riscv-registered-target
2+
3+
# RUN: cp -f %S/Inputs/conflicting-prefixes.ll %t.ll
4+
# RUN: %update_llc_test_checks --no-generate-body-for-unused-prefixes %t.ll 2>&1 | FileCheck %s
5+
# RUN: diff -u %S/Inputs/conflicting-prefixes.ll.expected %t.ll
6+
7+
# CHECK: WARNING: For function 'foo', the following RUN lines will not generate checks due to conflicting output: RUN #1 (prefixes: CHECK, CHECKA), RUN #2 (prefixes: CHECK, CHECKA), RUN #3 (prefixes: CHECK, CHECKB), RUN #4 (prefixes: CHECK, CHECKB):
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# REQUIRES: riscv-registered-target
2+
3+
# RUN: cp -f %S/Inputs/differing-set-of-functions.ll %t.ll
4+
# RUN: %update_llc_test_checks --include-generated-funcs %t.ll 2>&1 | FileCheck --allow-empty %s
5+
# RUN: diff -u %S/Inputs/differing-set-of-functions.ll.expected %t.ll
6+
7+
# We shouldn't print the warning for clashing CHECK prefixes in the case that
8+
# we're trying to handle a function that is only present for some RUN lines.
9+
# Better warning behaviour than this might be possible.
10+
11+
# CHECK-NOT: WARNING

llvm/test/tools/UpdateTestChecks/update_llc_test_checks/prefix-never-matches.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
# RUN: %update_llc_test_checks --no-generate-body-for-unused-prefixes %t.ll 2>&1 | FileCheck %s
55
# RUN: FileCheck --input-file=%t.ll %s --check-prefix=OUTPUT
66

7-
# CHECK: WARNING: Prefix A had conflicting output
7+
# CHECK: WARNING: For function 'fold_v2i64', the following RUN lines will not generate checks due to conflicting output
88
# OUTPUT-NOT: A:

llvm/utils/UpdateTestChecks/common.py

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ def __str__(self):
882882

883883
class FunctionTestBuilder:
884884
def __init__(self, run_list, flags, scrubber_args, path, ginfo):
885+
self._run_list = run_list
885886
self._verbose = flags.verbose
886887
self._record_args = flags.function_signature
887888
self._check_attributes = flags.check_attributes
@@ -917,15 +918,53 @@ def __init__(self, run_list, flags, scrubber_args, path, ginfo):
917918
self._func_order.update({prefix: []})
918919
self._global_var_dict.update({prefix: dict()})
919920

921+
# Return true if there is conflicting output for different runs for the
922+
# given prefix and function name.
923+
def has_conflicting_output(self, prefix, func):
924+
# There was conflicting output if the func_dict is None for this
925+
# prefix and function.
926+
return self._func_dict[prefix].get(func) is None
927+
920928
def finish_and_get_func_dict(self):
921-
for prefix in self.get_failed_prefixes():
922-
warn(
923-
"Prefix %s had conflicting output from different RUN lines for all functions in test %s"
924-
% (
925-
prefix,
926-
self._path,
929+
all_funcs = set()
930+
for prefix in self._func_dict:
931+
all_funcs.update(self._func_dict[prefix].keys())
932+
933+
warnings_to_print = collections.defaultdict(list)
934+
for func in sorted(list(all_funcs)):
935+
for i, run_info in enumerate(self._run_list):
936+
prefixes = run_info[0]
937+
if not prefixes:
938+
continue
939+
940+
# Check if this RUN line produces this function at all. If
941+
# not, we can skip analysing this function for this RUN.
942+
run_contains_func = all(
943+
func in self._func_dict.get(p, {}) for p in prefixes
927944
)
945+
if not run_contains_func:
946+
continue
947+
948+
# Check if this RUN line can print any checks for this
949+
# function. It can't if all of its prefixes have conflicting
950+
# (None) output.
951+
cannot_print_for_this_run = all(
952+
self.has_conflicting_output(p, func) for p in prefixes
953+
)
954+
if cannot_print_for_this_run:
955+
warnings_to_print[func].append((i, prefixes))
956+
957+
for func, warning_info in warnings_to_print.items():
958+
conflict_strs = []
959+
for run_index, prefixes in warning_info:
960+
conflict_strs.append(
961+
f"RUN #{run_index + 1} (prefixes: {', '.join(prefixes)})"
962+
)
963+
warn(
964+
f"For function '{func}', the following RUN lines will not generate checks due to conflicting output: {', '.join(conflict_strs)}",
965+
test_file=self._path,
928966
)
967+
929968
return self._func_dict
930969

931970
def func_order(self):
@@ -1078,20 +1117,6 @@ def processed_prefixes(self, prefixes):
10781117
"""
10791118
self._processed_prefixes.update(prefixes)
10801119

1081-
def get_failed_prefixes(self):
1082-
# This returns the list of those prefixes that failed to match any function,
1083-
# because there were conflicting bodies produced by different RUN lines, in
1084-
# all instances of the prefix.
1085-
for prefix in self._func_dict:
1086-
if self._func_dict[prefix] and (
1087-
not [
1088-
fct
1089-
for fct in self._func_dict[prefix]
1090-
if self._func_dict[prefix][fct] is not None
1091-
]
1092-
):
1093-
yield prefix
1094-
10951120

10961121
##### Generator of LLVM IR CHECK lines
10971122

0 commit comments

Comments
 (0)