Skip to content

Commit bfe2cf4

Browse files
committed
[GlobalISel] Add a update_givaluetracking_test_checks.py script
As with the other update scripts this takes the output of -passes=print<gisel-value-tracking> and inserts the results into an existing mir file. This means that the input is a lot like update_analysis_test_checks.py, and the output needs to insert into a mir file similarly to update_mir_test_checks.py. The code used to do the inserting has been moved to common, to allow it to be reused.
1 parent b565933 commit bfe2cf4

File tree

9 files changed

+460
-239
lines changed

9 files changed

+460
-239
lines changed
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2-
# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
1+
# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
33

44
---
55
name: Cst
66
tracksRegLiveness: true
77
body: |
88
bb.1:
9-
; CHECK-LABEL: name: @Cst
10-
; CHECK-NEXT: %0:_ KnownBits:00000001 SignBits:7
11-
; CHECK-NEXT: %1:_ KnownBits:00000001 SignBits:7
9+
; CHECK-LABEL: name: @Cst
10+
; CHECK-NEXT: %0:_ KnownBits:00000001 SignBits:7
11+
; CHECK-NEXT: %1:_ KnownBits:00000001 SignBits:7
1212
%0:_(s8) = G_CONSTANT i8 1
1313
%1:_(s8) = COPY %0
1414
...
1515
---
1616
name: CstWithClass
17-
# We can't analyze %0 due to the lack of an LLT. We will get a default
18-
# constructed KnownBits back. %0 will have the correct size but we will
19-
# not know any further info.
2017
tracksRegLiveness: true
2118
body: |
2219
bb.1:
23-
; CHECK-LABEL: name: @CstWithClass
24-
; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
20+
; We can't analyze %0 due to the lack of an LLT. We will get a default
21+
; constructed KnownBits back. %0 will have the correct size but we will
22+
; not know any further info.
23+
; CHECK-LABEL: name: @CstWithClass
24+
; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
2525
%0:gpr32 = MOVi32imm 1
2626
%1:_(s32) = COPY %0
2727
...

llvm/test/tools/UpdateTestChecks/lit.local.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ if os.path.isfile(llc_path):
3535
llc_arg = "--llc-binary " + shell_quote(llc_path)
3636
add_update_script_substitution("%update_llc_test_checks", extra_args=llc_arg)
3737
add_update_script_substitution("%update_mir_test_checks", extra_args=llc_arg)
38+
add_update_script_substitution("%update_givaluetracking_test_checks", extra_args=llc_arg)
3839

3940
opt_path = os.path.join(config.llvm_tools_dir, "opt")
4041
if os.path.isfile(opt_path):
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
3+
4+
---
5+
name: Cst
6+
body: |
7+
bb.1:
8+
%0:_(s8) = G_CONSTANT i8 1
9+
%1:_(s8) = COPY %0
10+
...
11+
---
12+
name: CstWithClass
13+
body: |
14+
bb.1:
15+
; Note: This comment should not be removed, the check lines below should be updated
16+
; CHECK-LABEL: name: @CstWithClass
17+
; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
18+
%0:gpr32 = MOVi32imm 1
19+
%1:_(s32) = COPY %0
20+
...
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple aarch64 -passes="print<gisel-value-tracking>" %s -filetype=null 2>&1 | FileCheck %s
3+
4+
---
5+
name: Cst
6+
body: |
7+
bb.1:
8+
; CHECK-LABEL: name: @Cst
9+
; CHECK-NEXT: %0:_ KnownBits:00000001 SignBits:7
10+
; CHECK-NEXT: %1:_ KnownBits:00000001 SignBits:7
11+
%0:_(s8) = G_CONSTANT i8 1
12+
%1:_(s8) = COPY %0
13+
...
14+
---
15+
name: CstWithClass
16+
body: |
17+
bb.1:
18+
; Note: This comment should not be removed, the check lines below should be updated
19+
; CHECK-LABEL: name: @CstWithClass
20+
; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1
21+
%0:gpr32 = MOVi32imm 1
22+
%1:_(s32) = COPY %0
23+
...
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# REQUIRES: aarch64-registered-target
2+
# RUN: cp -f %S/Inputs/const.mir %t.mir && %update_givaluetracking_test_checks %t.mir
3+
# RUN: diff -u %S/Inputs/const.mir.expected %t.mir
4+
# RUN: FileCheck %t.mir < %t.mir
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# These tests require llc.
2+
if "llc-binary" not in config.available_features:
3+
config.unsupported = True

llvm/utils/UpdateTestChecks/common.py

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,244 @@ def add_analyze_checks(
22702270
)
22712271

22722272

2273+
IR_FUNC_NAME_RE = re.compile(
2274+
r"^\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[A-Za-z0-9_.]+)\s*\("
2275+
)
2276+
IR_PREFIX_DATA_RE = re.compile(r"^ *(;|$)")
2277+
MIR_FUNC_NAME_RE = re.compile(r" *name: *(?P<func>[A-Za-z0-9_.-]+)")
2278+
MIR_BODY_BEGIN_RE = re.compile(r" *body: *\|")
2279+
MIR_BASIC_BLOCK_RE = re.compile(r" *bb\.[0-9]+.*:$")
2280+
MIR_PREFIX_DATA_RE = re.compile(r"^ *(;|bb.[0-9].*: *$|[a-z]+:( |$)|$)")
2281+
2282+
2283+
def find_mir_functions_with_one_bb(lines, verbose=False):
2284+
result = []
2285+
cur_func = None
2286+
bbs = 0
2287+
for line in lines:
2288+
m = MIR_FUNC_NAME_RE.match(line)
2289+
if m:
2290+
if bbs == 1:
2291+
result.append(cur_func)
2292+
cur_func = m.group("func")
2293+
bbs = 0
2294+
m = MIR_BASIC_BLOCK_RE.match(line)
2295+
if m:
2296+
bbs += 1
2297+
if bbs == 1:
2298+
result.append(cur_func)
2299+
return result
2300+
2301+
2302+
def add_mir_checks_for_function(
2303+
test,
2304+
output_lines,
2305+
run_list,
2306+
func_dict,
2307+
func_name,
2308+
single_bb,
2309+
print_fixed_stack,
2310+
first_check_is_next,
2311+
at_the_function_name,
2312+
):
2313+
printed_prefixes = set()
2314+
for run in run_list:
2315+
for prefix in run[0]:
2316+
if prefix in printed_prefixes:
2317+
break
2318+
if not func_dict[prefix][func_name]:
2319+
continue
2320+
if printed_prefixes:
2321+
# Add some space between different check prefixes.
2322+
indent = len(output_lines[-1]) - len(output_lines[-1].lstrip(" "))
2323+
output_lines.append(" " * indent + ";")
2324+
printed_prefixes.add(prefix)
2325+
add_mir_check_lines(
2326+
test,
2327+
output_lines,
2328+
prefix,
2329+
("@" if at_the_function_name else "") + func_name,
2330+
single_bb,
2331+
func_dict[prefix][func_name],
2332+
print_fixed_stack,
2333+
first_check_is_next,
2334+
)
2335+
break
2336+
else:
2337+
warn(
2338+
"Found conflicting asm for function: {}".format(func_name),
2339+
test_file=test,
2340+
)
2341+
return output_lines
2342+
2343+
2344+
def add_mir_check_lines(
2345+
test,
2346+
output_lines,
2347+
prefix,
2348+
func_name,
2349+
single_bb,
2350+
func_info,
2351+
print_fixed_stack,
2352+
first_check_is_next,
2353+
):
2354+
func_body = str(func_info).splitlines()
2355+
if single_bb:
2356+
# Don't bother checking the basic block label for a single BB
2357+
func_body.pop(0)
2358+
2359+
if not func_body:
2360+
warn(
2361+
"Function has no instructions to check: {}".format(func_name),
2362+
test_file=test,
2363+
)
2364+
return
2365+
2366+
first_line = func_body[0]
2367+
indent = len(first_line) - len(first_line.lstrip(" "))
2368+
# A check comment, indented the appropriate amount
2369+
check = "{:>{}}; {}".format("", indent, prefix)
2370+
2371+
output_lines.append("{}-LABEL: name: {}".format(check, func_name))
2372+
2373+
if print_fixed_stack:
2374+
output_lines.append("{}: fixedStack:".format(check))
2375+
for stack_line in func_info.extrascrub.splitlines():
2376+
filecheck_directive = check + "-NEXT"
2377+
output_lines.append("{}: {}".format(filecheck_directive, stack_line))
2378+
2379+
first_check = not first_check_is_next
2380+
for func_line in func_body:
2381+
if not func_line.strip():
2382+
# The mir printer prints leading whitespace so we can't use CHECK-EMPTY:
2383+
output_lines.append(check + "-NEXT: {{" + func_line + "$}}")
2384+
continue
2385+
filecheck_directive = check if first_check else check + "-NEXT"
2386+
first_check = False
2387+
check_line = "{}: {}".format(filecheck_directive, func_line[indent:]).rstrip()
2388+
output_lines.append(check_line)
2389+
2390+
2391+
def should_add_mir_line_to_output(input_line, prefix_set):
2392+
# Skip any check lines that we're handling as well as comments
2393+
m = CHECK_RE.match(input_line)
2394+
if (m and m.group(1) in prefix_set) or input_line.strip() == ";":
2395+
return False
2396+
return True
2397+
2398+
2399+
def add_mir_checks(
2400+
input_lines,
2401+
prefix_set,
2402+
autogenerated_note,
2403+
test,
2404+
run_list,
2405+
func_dict,
2406+
print_fixed_stack,
2407+
first_check_is_next,
2408+
at_the_function_name,
2409+
):
2410+
simple_functions = find_mir_functions_with_one_bb(input_lines)
2411+
2412+
output_lines = []
2413+
output_lines.append(autogenerated_note)
2414+
2415+
func_name = None
2416+
state = "toplevel"
2417+
for input_line in input_lines:
2418+
if input_line == autogenerated_note:
2419+
continue
2420+
2421+
if state == "toplevel":
2422+
m = IR_FUNC_NAME_RE.match(input_line)
2423+
if m:
2424+
state = "ir function prefix"
2425+
func_name = m.group("func")
2426+
if input_line.rstrip("| \r\n") == "---":
2427+
state = "document"
2428+
output_lines.append(input_line)
2429+
elif state == "document":
2430+
m = MIR_FUNC_NAME_RE.match(input_line)
2431+
if m:
2432+
state = "mir function metadata"
2433+
func_name = m.group("func")
2434+
if input_line.strip() == "...":
2435+
state = "toplevel"
2436+
func_name = None
2437+
if should_add_mir_line_to_output(input_line, prefix_set):
2438+
output_lines.append(input_line)
2439+
elif state == "mir function metadata":
2440+
if should_add_mir_line_to_output(input_line, prefix_set):
2441+
output_lines.append(input_line)
2442+
m = MIR_BODY_BEGIN_RE.match(input_line)
2443+
if m:
2444+
if func_name in simple_functions:
2445+
# If there's only one block, put the checks inside it
2446+
state = "mir function prefix"
2447+
continue
2448+
state = "mir function body"
2449+
add_mir_checks_for_function(
2450+
test,
2451+
output_lines,
2452+
run_list,
2453+
func_dict,
2454+
func_name,
2455+
single_bb=False,
2456+
print_fixed_stack=print_fixed_stack,
2457+
first_check_is_next=first_check_is_next,
2458+
at_the_function_name=at_the_function_name,
2459+
)
2460+
elif state == "mir function prefix":
2461+
m = MIR_PREFIX_DATA_RE.match(input_line)
2462+
if not m:
2463+
state = "mir function body"
2464+
add_mir_checks_for_function(
2465+
test,
2466+
output_lines,
2467+
run_list,
2468+
func_dict,
2469+
func_name,
2470+
single_bb=True,
2471+
print_fixed_stack=print_fixed_stack,
2472+
first_check_is_next=first_check_is_next,
2473+
at_the_function_name=at_the_function_name,
2474+
)
2475+
2476+
if should_add_mir_line_to_output(input_line, prefix_set):
2477+
output_lines.append(input_line)
2478+
elif state == "mir function body":
2479+
if input_line.strip() == "...":
2480+
state = "toplevel"
2481+
func_name = None
2482+
if should_add_mir_line_to_output(input_line, prefix_set):
2483+
output_lines.append(input_line)
2484+
elif state == "ir function prefix":
2485+
m = IR_PREFIX_DATA_RE.match(input_line)
2486+
if not m:
2487+
state = "ir function body"
2488+
add_mir_checks_for_function(
2489+
test,
2490+
output_lines,
2491+
run_list,
2492+
func_dict,
2493+
func_name,
2494+
single_bb=False,
2495+
print_fixed_stack=print_fixed_stack,
2496+
first_check_is_next=first_check_is_next,
2497+
at_the_function_name=at_the_function_name,
2498+
)
2499+
2500+
if should_add_mir_line_to_output(input_line, prefix_set):
2501+
output_lines.append(input_line)
2502+
elif state == "ir function body":
2503+
if input_line.strip() == "}":
2504+
state = "toplevel"
2505+
func_name = None
2506+
if should_add_mir_line_to_output(input_line, prefix_set):
2507+
output_lines.append(input_line)
2508+
return output_lines
2509+
2510+
22732511
def build_global_values_dictionary(glob_val_dict, raw_tool_output, prefixes, ginfo):
22742512
for nameless_value in ginfo.get_nameless_values():
22752513
if nameless_value.global_ir_rhs_regexp is None:

0 commit comments

Comments
 (0)