update_test_checks: match IR basic block labels (#88979)
Labels are matched using a regexp of the form '^(pattern):', which requires the addition of a "suffix" concept to NamelessValue. Aside from that, the key challenge is that block labels are values, and we typically capture values including the prefix '%'. However, when labels appear at the start of a basic block, the prefix '%' is not included, so we must capture block label values *without* the prefix '%'. We don't know ahead of time whether an IR value is a label or not. In most cases, they are prefixed by the word "label" (their type), but this isn't the case in phi nodes. We solve this issue by leveraging the two-phase nature of variable generalization: the first pass finds all occurences of a variable and determines whether the '%' prefix can be included or not. The second pass does the actual substitution. This change also unifies the generalization path for assembly with that for IR and analysis, in the hope that any future changes avoid diverging those cases future. I also considered the alternative of trying to detect the phi node case using more regular expression special cases but ultimately decided against that because it seemed more fragile, and perhaps the approach of keeping a tentative prefix that may later be discarded could also be eventually applied to some metadata and attribute cases. Note that an early version of this change was reviewed as https://reviews.llvm.org/D142452, before version numbers were introduced. This is a substantially updated version of that change.
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
||||
; RUN: opt < %s -S | FileCheck %s
|
||||
|
||||
define i32 @phi_after_label(i1 %cc) {
|
||||
; CHECK-LABEL: define i32 @phi_after_label(
|
||||
; CHECK-SAME: i1 [[CC:%.*]]) {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[CC]], label [[THEN:%.*]], label [[END:%.*]]
|
||||
; CHECK: then:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[THEN]] ]
|
||||
; CHECK-NEXT: [[ENTRY:.*]]:
|
||||
; CHECK-NEXT: br i1 [[CC]], label %[[THEN:.*]], label %[[END:.*]]
|
||||
; CHECK: [[THEN]]:
|
||||
; CHECK-NEXT: br label %[[END]]
|
||||
; CHECK: [[END]]:
|
||||
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[THEN]] ]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
entry:
|
||||
@@ -26,14 +26,14 @@ end:
|
||||
define void @phi_before_label(i32 %bound) {
|
||||
; CHECK-LABEL: define void @phi_before_label(
|
||||
; CHECK-SAME: i32 [[BOUND:%.*]]) {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[CTR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[CTR_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[ENTRY:.*]]:
|
||||
; CHECK-NEXT: br label %[[LOOP:.*]]
|
||||
; CHECK: [[LOOP]]:
|
||||
; CHECK-NEXT: [[CTR:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[CTR_NEXT:%.*]], %[[LOOP]] ]
|
||||
; CHECK-NEXT: [[CTR_NEXT]] = add i32 [[CTR]], 1
|
||||
; CHECK-NEXT: [[CC:%.*]] = icmp ult i32 [[CTR_NEXT]], [[BOUND]]
|
||||
; CHECK-NEXT: br i1 [[CC]], label [[LOOP]], label [[END:%.*]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: br i1 [[CC]], label %[[LOOP]], label %[[END:.*]]
|
||||
; CHECK: [[END]]:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
@@ -52,11 +52,11 @@ end:
|
||||
define i32 @phi_after_label_unnamed(i1 %cc) {
|
||||
; CHECK-LABEL: define i32 @phi_after_label_unnamed(
|
||||
; CHECK-SAME: i1 [[CC:%.*]]) {
|
||||
; CHECK-NEXT: br i1 [[CC]], label [[TMP1:%.*]], label [[TMP2:%.*]]
|
||||
; CHECK: 1:
|
||||
; CHECK-NEXT: br label [[TMP2]]
|
||||
; CHECK: 2:
|
||||
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ 1, [[TMP1]] ]
|
||||
; CHECK-NEXT: br i1 [[CC]], label %[[BB1:.*]], label %[[BB2:.*]]
|
||||
; CHECK: [[BB1]]:
|
||||
; CHECK-NEXT: br label %[[BB2]]
|
||||
; CHECK: [[BB2]]:
|
||||
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ 1, %[[BB1]] ]
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
0:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# RUN: cp -f %S/Inputs/phi-labels.ll %t.ll && %update_test_checks --version 4 %t.ll
|
||||
# RUN: cp -f %S/Inputs/phi-labels.ll %t.ll && %update_test_checks --version 5 %t.ll
|
||||
# RUN: diff -u %t.ll %S/Inputs/phi-labels.ll.expected
|
||||
## Check that running the script again does not change the result:
|
||||
# RUN: %update_test_checks %t.ll
|
||||
|
||||
@@ -605,6 +605,7 @@ def add_checks(
|
||||
prefix_list,
|
||||
func_dict,
|
||||
func_name,
|
||||
ginfo: common.GeneralizerInfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered,
|
||||
):
|
||||
@@ -617,9 +618,7 @@ def add_checks(
|
||||
func_dict,
|
||||
func_name,
|
||||
check_label_format,
|
||||
True,
|
||||
False,
|
||||
1,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=is_filtered,
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,7 @@ def add_checks(
|
||||
prefix_list,
|
||||
func_dict,
|
||||
func_name,
|
||||
ginfo: common.GeneralizerInfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered,
|
||||
):
|
||||
@@ -72,9 +73,7 @@ def add_checks(
|
||||
func_dict,
|
||||
func_name,
|
||||
check_label_format,
|
||||
True,
|
||||
False,
|
||||
1,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=is_filtered,
|
||||
)
|
||||
|
||||
@@ -96,6 +96,7 @@ def main():
|
||||
# now, we just ignore all but the last.
|
||||
prefix_list.append((check_prefixes, tool_cmd_args))
|
||||
|
||||
ginfo = common.make_analyze_generalizer(version=1)
|
||||
builder = common.FunctionTestBuilder(
|
||||
run_list=prefix_list,
|
||||
flags=type(
|
||||
@@ -111,6 +112,7 @@ def main():
|
||||
),
|
||||
scrubber_args=[],
|
||||
path=ti.path,
|
||||
ginfo=ginfo,
|
||||
)
|
||||
|
||||
for prefixes, opt_args in prefix_list:
|
||||
@@ -131,7 +133,6 @@ def main():
|
||||
common.scrub_body,
|
||||
raw_tool_output,
|
||||
prefixes,
|
||||
False,
|
||||
)
|
||||
elif re.search(r"LV: Checking a loop in ", raw_tool_outputs) is not None:
|
||||
# Split analysis outputs by "Printing analysis " declarations.
|
||||
@@ -143,7 +144,6 @@ def main():
|
||||
common.scrub_body,
|
||||
raw_tool_output,
|
||||
prefixes,
|
||||
False,
|
||||
)
|
||||
else:
|
||||
common.warn("Don't know how to deal with this output")
|
||||
@@ -179,6 +179,7 @@ def main():
|
||||
prefix_list,
|
||||
func_dict,
|
||||
func_name,
|
||||
ginfo,
|
||||
is_filtered=builder.is_filtered(),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -270,7 +270,7 @@ def get_function_body(builder, args, filename, clang_args, extra_commands, prefi
|
||||
raw_tool_output = common.invoke_tool(extra_args[0], extra_args[1:], f.name)
|
||||
if "-emit-llvm" in clang_args:
|
||||
builder.process_run_line(
|
||||
common.OPT_FUNCTION_RE, common.scrub_body, raw_tool_output, prefixes, False
|
||||
common.OPT_FUNCTION_RE, common.scrub_body, raw_tool_output, prefixes
|
||||
)
|
||||
builder.processed_prefixes(prefixes)
|
||||
else:
|
||||
@@ -360,8 +360,13 @@ def main():
|
||||
|
||||
# Store only filechecked runlines.
|
||||
filecheck_run_list = [i for i in run_list if i[0]]
|
||||
ginfo = common.make_ir_generalizer(version=ti.args.version)
|
||||
builder = common.FunctionTestBuilder(
|
||||
run_list=filecheck_run_list, flags=ti.args, scrubber_args=[], path=ti.path
|
||||
run_list=filecheck_run_list,
|
||||
flags=ti.args,
|
||||
scrubber_args=[],
|
||||
path=ti.path,
|
||||
ginfo=ginfo,
|
||||
)
|
||||
|
||||
for prefixes, args, extra_commands, triple_in_cmd in run_list:
|
||||
@@ -415,29 +420,18 @@ def main():
|
||||
|
||||
# Now generate all the checks.
|
||||
def check_generator(my_output_lines, prefixes, func):
|
||||
if "-emit-llvm" in clang_args:
|
||||
return common.add_ir_checks(
|
||||
my_output_lines,
|
||||
"//",
|
||||
prefixes,
|
||||
func_dict,
|
||||
func,
|
||||
False,
|
||||
ti.args.function_signature,
|
||||
ti.args.version,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
)
|
||||
else:
|
||||
return asm.add_checks(
|
||||
my_output_lines,
|
||||
"//",
|
||||
prefixes,
|
||||
func_dict,
|
||||
func,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
)
|
||||
return common.add_ir_checks(
|
||||
my_output_lines,
|
||||
"//",
|
||||
prefixes,
|
||||
func_dict,
|
||||
func,
|
||||
False,
|
||||
ti.args.function_signature,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
)
|
||||
|
||||
if ti.args.check_globals != 'none':
|
||||
generated_prefixes.extend(
|
||||
@@ -446,6 +440,7 @@ def main():
|
||||
"//",
|
||||
run_list,
|
||||
output_lines,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
False,
|
||||
True,
|
||||
@@ -506,6 +501,7 @@ def main():
|
||||
"//",
|
||||
run_list,
|
||||
output_lines,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
False,
|
||||
True,
|
||||
@@ -525,7 +521,7 @@ def main():
|
||||
mangled,
|
||||
False,
|
||||
args.function_signature,
|
||||
args.version,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
)
|
||||
@@ -543,6 +539,7 @@ def main():
|
||||
"//",
|
||||
run_list,
|
||||
output_lines,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
False,
|
||||
False,
|
||||
|
||||
@@ -133,6 +133,7 @@ def main():
|
||||
else:
|
||||
check_indent = ""
|
||||
|
||||
ginfo = common.make_asm_generalizer(version=1)
|
||||
builder = common.FunctionTestBuilder(
|
||||
run_list=run_list,
|
||||
flags=type(
|
||||
@@ -148,6 +149,7 @@ def main():
|
||||
),
|
||||
scrubber_args=[ti.args],
|
||||
path=ti.path,
|
||||
ginfo=ginfo,
|
||||
)
|
||||
|
||||
for (
|
||||
@@ -173,9 +175,7 @@ def main():
|
||||
triple = common.get_triple_from_march(march_in_cmd)
|
||||
|
||||
scrubber, function_re = output_type.get_run_handler(triple)
|
||||
builder.process_run_line(
|
||||
function_re, scrubber, raw_tool_output, prefixes, True
|
||||
)
|
||||
builder.process_run_line(function_re, scrubber, raw_tool_output, prefixes)
|
||||
builder.processed_prefixes(prefixes)
|
||||
|
||||
func_dict = builder.finish_and_get_func_dict()
|
||||
@@ -218,6 +218,7 @@ def main():
|
||||
prefixes,
|
||||
func_dict,
|
||||
func,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
),
|
||||
@@ -243,6 +244,7 @@ def main():
|
||||
run_list,
|
||||
func_dict,
|
||||
func_name,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
)
|
||||
|
||||
@@ -147,9 +147,14 @@ def main():
|
||||
# now, we just ignore all but the last.
|
||||
prefix_list.append((check_prefixes, tool_cmd_args, preprocess_cmd))
|
||||
|
||||
ginfo = common.make_ir_generalizer(ti.args.version)
|
||||
global_vars_seen_dict = {}
|
||||
builder = common.FunctionTestBuilder(
|
||||
run_list=prefix_list, flags=ti.args, scrubber_args=[], path=ti.path
|
||||
run_list=prefix_list,
|
||||
flags=ti.args,
|
||||
scrubber_args=[],
|
||||
path=ti.path,
|
||||
ginfo=ginfo,
|
||||
)
|
||||
|
||||
tool_binary = ti.args.tool_binary
|
||||
@@ -172,7 +177,6 @@ def main():
|
||||
common.scrub_body,
|
||||
raw_tool_output,
|
||||
prefixes,
|
||||
False,
|
||||
)
|
||||
builder.processed_prefixes(prefixes)
|
||||
|
||||
@@ -217,6 +221,7 @@ def main():
|
||||
";",
|
||||
prefix_list,
|
||||
output_lines,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
args.preserve_names,
|
||||
True,
|
||||
@@ -239,7 +244,7 @@ def main():
|
||||
func,
|
||||
False,
|
||||
args.function_signature,
|
||||
args.version,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
original_check_lines=original_check_lines.get(func, {}),
|
||||
@@ -271,7 +276,7 @@ def main():
|
||||
func_name,
|
||||
args.preserve_names,
|
||||
args.function_signature,
|
||||
args.version,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
is_filtered=builder.is_filtered(),
|
||||
original_check_lines=original_check_lines.get(
|
||||
@@ -290,6 +295,7 @@ def main():
|
||||
";",
|
||||
prefix_list,
|
||||
output_lines,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
args.preserve_names,
|
||||
True,
|
||||
@@ -337,6 +343,7 @@ def main():
|
||||
";",
|
||||
prefix_list,
|
||||
output_lines,
|
||||
ginfo,
|
||||
global_vars_seen_dict,
|
||||
args.preserve_names,
|
||||
False,
|
||||
|
||||
Reference in New Issue
Block a user