Skip to content

Commit cc8d94a

Browse files
committed
update_test_checks: add new --filter-all-after option
Whilst trying to clean up some loop vectoriser IR tests (see test/Transforms/LoopVectorize/AArch64/partial-reduce-chained.ll for example) a reviewer on PR llvm#129047 suggested it would be nice to have an option to stop generating CHECK lines after a certain point. Typically when performing a transformation with the loop vectoriser we don't usually care about any CHECK lines generated for the scalar tail of the loop, since the scalar loop is kept intact. Previously if you wanted to eliminate such unwanted CHECK lines you had to run the update script, then manually delete all the lines corresponding to the scalar loop. This can be very time consuming if the tests ever need changing. What I've tried to do here is add a new --filter-all-after option alongside the existing --filter* options that provides support for stopping the generation of any CHECK lines beyond the line that matches the filter. With the existing filter options we never generate CHECK-NEXT lines, but we still care about ordering with --filter-all-after so I've amended the code to ensure we treat this filter differently.
1 parent 85cf958 commit cc8d94a

File tree

5 files changed

+158
-12
lines changed

5 files changed

+158
-12
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt < %s -S | FileCheck %s
2+
3+
define i32 @func({i32, i32} %x, i32 %y, i1 %cond) {
4+
entry:
5+
br i1 %cond, label %b1, label %b2
6+
7+
b1:
8+
%x.idx0 = extractvalue {i32, i32} %x, 0
9+
%add1 = add i32 %y, 1
10+
%add2 = add i32 %x.idx0, %add1
11+
%mul = mul i32 %add2, 3
12+
br label %b2
13+
14+
b2:
15+
%res = phi i32 [ -1, %entry ], [ %mul, %b1 ]
16+
ret i32 %res
17+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --filter-all-after "^b2:" --version 5
2+
; RUN: opt < %s -S | FileCheck %s
3+
4+
define i32 @func({i32, i32} %x, i32 %y, i1 %cond) {
5+
; CHECK-LABEL: define i32 @func(
6+
; CHECK-SAME: { i32, i32 } [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: br i1 [[COND]], label %[[B1:.*]], label %[[B2:.*]]
9+
; CHECK: [[B1]]:
10+
; CHECK-NEXT: [[X_IDX0:%.*]] = extractvalue { i32, i32 } [[X]], 0
11+
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[Y]], 1
12+
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[X_IDX0]], [[ADD1]]
13+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ADD2]], 3
14+
; CHECK-NEXT: br label %[[B2]]
15+
; CHECK: [[B2]]:
16+
;
17+
entry:
18+
br i1 %cond, label %b1, label %b2
19+
20+
b1:
21+
%x.idx0 = extractvalue {i32, i32} %x, 0
22+
%add1 = add i32 %y, 1
23+
%add2 = add i32 %x.idx0, %add1
24+
%mul = mul i32 %add2, 3
25+
br label %b2
26+
27+
b2:
28+
%res = phi i32 [ -1, %entry ], [ %mul, %b1 ]
29+
ret i32 %res
30+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --filter-all-after "= mul i32" --filter-all-after "^b2:" --version 5
2+
; RUN: opt < %s -S | FileCheck %s
3+
4+
define i32 @func({i32, i32} %x, i32 %y, i1 %cond) {
5+
; CHECK-LABEL: define i32 @func(
6+
; CHECK-SAME: { i32, i32 } [[X:%.*]], i32 [[Y:%.*]], i1 [[COND:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: br i1 [[COND]], label %[[B1:.*]], [[B2:label %.*]]
9+
; CHECK: [[B1]]:
10+
; CHECK-NEXT: [[X_IDX0:%.*]] = extractvalue { i32, i32 } [[X]], 0
11+
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[Y]], 1
12+
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[X_IDX0]], [[ADD1]]
13+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ADD2]], 3
14+
;
15+
entry:
16+
br i1 %cond, label %b1, label %b2
17+
18+
b1:
19+
%x.idx0 = extractvalue {i32, i32} %x, 0
20+
%add1 = add i32 %y, 1
21+
%add2 = add i32 %x.idx0, %add1
22+
%mul = mul i32 %add2, 3
23+
br label %b2
24+
25+
b2:
26+
%res = phi i32 [ -1, %entry ], [ %mul, %b1 ]
27+
ret i32 %res
28+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Check that --filter-all-after works properly.
2+
# RUN: cp -f %S/Inputs/filter-all-after.ll %t.ll && %update_test_checks --version=5 --filter-all-after="^b2:" %t.ll
3+
# RUN: diff -u %t.ll %S/Inputs/filter-all-after.ll.expected
4+
5+
## Check that running the script again does not change the result:
6+
# RUN: %update_test_checks --version=5 --filter-all-after="^b2:" %t.ll
7+
# RUN: diff -u %t.ll %S/Inputs/filter-all-after.ll.expected
8+
9+
## Check that running the script again, without arguments, does not change the result:
10+
# RUN: %update_test_checks --version=5 %t.ll
11+
# RUN: diff -u %t.ll %S/Inputs/filter-all-after.ll.expected
12+
13+
## Check that multiple --filter-all-after options work properly.
14+
# RUN: cp -f %S/Inputs/filter-all-after.ll %t.ll && %update_test_checks --version=5 --filter-all-after="= mul i32" --filter-all-after="^b2:" %t.ll
15+
# RUN: diff -u %t.ll %S/Inputs/filter-all-after.ll.expected2
16+
17+
## Check that running the script again does not change the result:
18+
# RUN: %update_test_checks --version=5 --filter-all-after="= mul i32" --filter-all-after="^b2:" %t.ll
19+
# RUN: diff -u %t.ll %S/Inputs/filter-all-after.ll.expected2
20+
21+
## Check that running the script again, without arguments, does not change the result:
22+
# RUN: %update_test_checks --version=5 %t.ll
23+
# RUN: diff -u %t.ll %S/Inputs/filter-all-after.ll.expected2

llvm/utils/UpdateTestChecks/common.py

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,17 @@ class Filter(Regex):
7474
7575
"""
7676

77-
def __init__(self, regex, is_filter_out):
77+
def __init__(self, regex, is_filter_out, is_filter_all_after):
7878
super(Filter, self).__init__(regex)
79+
if is_filter_out and is_filter_all_after:
80+
raise ValueError("cannot use both --filter-out and --filter-all-after")
7981
self.is_filter_out = is_filter_out
82+
self.is_filter_all_after = is_filter_all_after
8083

8184
def __deepcopy__(self, memo):
8285
result = copy.deepcopy(super(Filter, self), memo)
8386
result.is_filter_out = copy.deepcopy(self.is_filter_out, memo)
87+
result.is_filter_all_after = copy.deepcopy(self.is_filter_all_after, memo)
8488
return result
8589

8690

@@ -127,7 +131,11 @@ def __call__(self, parser, namespace, values, option_string=None):
127131

128132
is_filter_out = option_string == "--filter-out"
129133

130-
value_list[-1] = Filter(value_list[-1].regex, is_filter_out)
134+
is_filter_all_after = option_string == "--filter-all-after"
135+
136+
value_list[-1] = Filter(
137+
value_list[-1].regex, is_filter_out, is_filter_all_after
138+
)
131139

132140
setattr(namespace, self.dest, value_list)
133141

@@ -151,6 +159,13 @@ def __call__(self, parser, namespace, values, option_string=None):
151159
metavar="REGEX",
152160
help="Exclude lines matching REGEX",
153161
)
162+
filter_group.add_argument(
163+
"--filter-all-after",
164+
action=FilterAction,
165+
dest="filters",
166+
metavar="REGEX",
167+
help="Exclude all lines after line matching REGEX",
168+
)
154169

155170
parser.add_argument(
156171
"--include-generated-funcs",
@@ -671,6 +686,8 @@ def get_globals_name_prefix(raw_tool_output):
671686
def apply_filters(line, filters):
672687
has_filter = False
673688
for f in filters:
689+
if f.is_filter_all_after:
690+
continue
674691
if not f.is_filter_out:
675692
has_filter = True
676693
if f.search(line):
@@ -680,14 +697,34 @@ def apply_filters(line, filters):
680697
return False if has_filter else True
681698

682699

700+
def has_filter_all(filters):
701+
for f in filters:
702+
if f.is_filter_all_after:
703+
return True
704+
return False
705+
706+
707+
def filter_all_after(body, filters):
708+
lines = []
709+
for line in body.splitlines():
710+
lines.append(line)
711+
for f in filters:
712+
if f.is_filter_all_after:
713+
if f.search(line):
714+
return lines
715+
return lines
716+
717+
683718
def do_filter(body, filters):
684-
return (
685-
body
686-
if not filters
687-
else "\n".join(
688-
filter(lambda line: apply_filters(line, filters), body.splitlines())
689-
)
690-
)
719+
if not filters:
720+
return body
721+
has_filter_after = has_filter_all(filters)
722+
lines = []
723+
if has_filter_after:
724+
lines = filter_all_after(body, filters)
725+
else:
726+
lines = body.splitlines()
727+
return "\n".join(filter(lambda line: apply_filters(line, filters), lines))
691728

692729

693730
def scrub_body(body):
@@ -788,7 +825,9 @@ def __init__(self, run_list, flags, scrubber_args, path, ginfo):
788825
list(
789826
map(
790827
lambda f: Filter(
791-
re.compile(f.pattern().strip('"'), f.flags()), f.is_filter_out
828+
re.compile(f.pattern().strip('"'), f.flags()),
829+
f.is_filter_out,
830+
f.is_filter_all_after,
792831
),
793832
flags.filters,
794833
)
@@ -831,7 +870,11 @@ def global_var_dict(self):
831870
return self._global_var_dict
832871

833872
def is_filtered(self):
834-
return bool(self._filters)
873+
total_filters = 0
874+
for f in self._filters:
875+
if not f.is_filter_all_after:
876+
total_filters += 1
877+
return bool(total_filters)
835878

836879
def process_run_line(self, function_re, scrubber, raw_tool_output, prefixes):
837880
build_global_values_dictionary(
@@ -2526,7 +2569,12 @@ def get_autogennote_suffix(parser, args):
25262569
# Create a separate option for each filter element. The value is a list
25272570
# of Filter objects.
25282571
for elem in value:
2529-
opt_name = "filter-out" if elem.is_filter_out else "filter"
2572+
if elem.is_filter_out:
2573+
opt_name = "filter-out"
2574+
elif elem.is_filter_all_after:
2575+
opt_name = "filter-all-after"
2576+
else:
2577+
opt_name = "filter"
25302578
opt_value = elem.pattern()
25312579
new_arg = '--%s "%s" ' % (opt_name, opt_value.strip('"'))
25322580
if new_arg not in autogenerated_note_args:

0 commit comments

Comments
 (0)