Skip to content

Commit 5f596b6

Browse files
committed
[utils][UpdateLLCTestChecks] Add MIR support to update_llc_test_checks.py
This change enables update_llc_test_checks.py to automatically generate MIR checks for RUN lines that use -stop-before or -stop-after flags. This allows tests to verify intermediate compilation stages (e.g., after instruction selection but before peephole optimizations) alongside the final assembly output.
1 parent 792c65c commit 5f596b6

File tree

5 files changed

+119
-6
lines changed

5 files changed

+119
-6
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: llc -mtriple=x86_64 < %s | FileCheck %s --check-prefix=ASM
2+
; RUN: llc -mtriple=x86_64 -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=MIR
3+
4+
define i64 @test1(i64 %i) nounwind readnone {
5+
%loc = alloca i64
6+
%j = load i64, i64 * %loc
7+
%r = add i64 %i, %j
8+
ret i64 %r
9+
}
10+
11+
define i64 @test2(i32 %i) nounwind readnone {
12+
%loc = alloca i32
13+
%j = load i32, i32 * %loc
14+
%r = add i32 %i, %j
15+
%ext = zext i32 %r to i64
16+
ret i64 %ext
17+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=x86_64 < %s | FileCheck %s --check-prefix=ASM
3+
; RUN: llc -mtriple=x86_64 -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=MIR
4+
5+
define i64 @test1(i64 %i) nounwind readnone {
6+
; ASM-LABEL: test1:
7+
; ASM: # %bb.0:
8+
; ASM-NEXT: movq %rdi, %rax
9+
; ASM-NEXT: addq -{{[0-9]+}}(%rsp), %rax
10+
; ASM-NEXT: retq
11+
; MIR-LABEL: name: test1
12+
; MIR: bb.0 (%ir-block.0):
13+
; MIR-NEXT: liveins: $rdi
14+
; MIR-NEXT: {{ $}}
15+
; MIR-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
16+
; MIR-NEXT: [[ADD64rm:%[0-9]+]]:gr64 = ADD64rm [[COPY]], %stack.0.loc, 1, $noreg, 0, $noreg, implicit-def dead $eflags :: (dereferenceable load (s64) from %ir.loc)
17+
; MIR-NEXT: $rax = COPY [[ADD64rm]]
18+
; MIR-NEXT: RET 0, $rax
19+
%loc = alloca i64
20+
%j = load i64, i64 * %loc
21+
%r = add i64 %i, %j
22+
ret i64 %r
23+
}
24+
25+
define i64 @test2(i32 %i) nounwind readnone {
26+
; ASM-LABEL: test2:
27+
; ASM: # %bb.0:
28+
; ASM-NEXT: movl %edi, %eax
29+
; ASM-NEXT: addl -{{[0-9]+}}(%rsp), %eax
30+
; ASM-NEXT: retq
31+
; MIR-LABEL: name: test2
32+
; MIR: bb.0 (%ir-block.0):
33+
; MIR-NEXT: liveins: $edi
34+
; MIR-NEXT: {{ $}}
35+
; MIR-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi
36+
; MIR-NEXT: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[COPY]], %stack.0.loc, 1, $noreg, 0, $noreg, implicit-def dead $eflags :: (dereferenceable load (s32) from %ir.loc)
37+
; MIR-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[ADD32rm]], %subreg.sub_32bit
38+
; MIR-NEXT: $rax = COPY [[SUBREG_TO_REG]]
39+
; MIR-NEXT: RET 0, $rax
40+
%loc = alloca i32
41+
%j = load i32, i32 * %loc
42+
%r = add i32 %i, %j
43+
%ext = zext i32 %r to i64
44+
ret i64 %ext
45+
}
46+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
47+
; MIR: {{.*}}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# REQUIRES: x86-registered-target
2+
## Test checking that update_llc_test_checks.py can generate both ASM and MIR checks in the same file
3+
4+
# RUN: cp -f %S/Inputs/x86_asm_mir_mixed.ll %t.ll && %update_llc_test_checks %t.ll
5+
# RUN: diff -u %S/Inputs/x86_asm_mir_mixed.ll.expected %t.ll

llvm/utils/UpdateTestChecks/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False):
604604
TRIPLE_ARG_RE = re.compile(r"-m?triple[= ]([^ ]+)")
605605
MARCH_ARG_RE = re.compile(r"-march[= ]([^ ]+)")
606606
DEBUG_ONLY_ARG_RE = re.compile(r"-debug-only[= ]([^ ]+)")
607+
STOP_PASS_RE = re.compile(r"-stop-(before|after)=(\w+)")
607608

608609
IS_DEBUG_RECORD_RE = re.compile(r"^(\s+)#dbg_")
609610

llvm/utils/update_llc_test_checks.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import sys
1717

1818
from UpdateTestChecks import common
19+
import update_mir_test_checks # Reuse MIR parsing code.
1920

2021
# llc is the only llc-like in the LLVM tree but downstream forks can add
2122
# additional ones here if they have them.
@@ -119,6 +120,10 @@ def update_test(ti: common.TestInfo):
119120
ginfo=ginfo,
120121
)
121122

123+
# Dictionary to store MIR function bodies separately
124+
mir_func_dict = {}
125+
mir_run_list = []
126+
122127
for (
123128
prefixes,
124129
llc_tool,
@@ -141,14 +146,37 @@ def update_test(ti: common.TestInfo):
141146
if not triple:
142147
triple = common.get_triple_from_march(march_in_cmd)
143148

144-
scrubber, function_re = output_type.get_run_handler(triple)
145-
if 0 == builder.process_run_line(
146-
function_re, scrubber, raw_tool_output, prefixes
149+
# Check if we are in MIR output mode. If -debug-only is present assume
150+
# the debug output is the main point of interest.
151+
if common.STOP_PASS_RE.search(llc_args) and not common.DEBUG_ONLY_ARG_RE.search(
152+
llc_args
147153
):
148-
common.warn(
149-
"Couldn't match any function. Possibly the wrong target triple has been provided"
154+
common.debug("Detected MIR output mode for prefixes:", str(prefixes))
155+
for prefix in prefixes:
156+
if prefix not in mir_func_dict:
157+
mir_func_dict[prefix] = {}
158+
159+
update_mir_test_checks.build_function_info_dictionary(
160+
ti.path,
161+
raw_tool_output,
162+
triple,
163+
prefixes,
164+
mir_func_dict,
165+
ti.args.verbose,
166+
)
167+
168+
mir_run_list.append(
169+
(prefixes, llc_tool, llc_args, triple_in_cmd, march_in_cmd)
150170
)
151-
builder.processed_prefixes(prefixes)
171+
else:
172+
scrubber, function_re = output_type.get_run_handler(triple)
173+
if 0 == builder.process_run_line(
174+
function_re, scrubber, raw_tool_output, prefixes
175+
):
176+
common.warn(
177+
"Couldn't match any function. Possibly the wrong target triple has been provided"
178+
)
179+
builder.processed_prefixes(prefixes)
152180

153181
func_dict = builder.finish_and_get_func_dict()
154182
global_vars_seen_dict = {}
@@ -221,6 +249,21 @@ def update_test(ti: common.TestInfo):
221249
is_filtered=builder.is_filtered(),
222250
)
223251
)
252+
253+
# Also add MIR checks if we have them for this function
254+
if mir_run_list and func_name:
255+
common.add_mir_checks_for_function(
256+
ti.path,
257+
output_lines,
258+
mir_run_list,
259+
mir_func_dict,
260+
func_name,
261+
single_bb=False, # Don't skip basic block labels.
262+
print_fixed_stack=False, # Don't print fixed stack (ASM tests don't need it).
263+
first_check_is_next=False, # First check is LABEL, not NEXT.
264+
at_the_function_name=False, # Use "name:" not "@name".
265+
)
266+
224267
is_in_function_start = False
225268

226269
if is_in_function:

0 commit comments

Comments
 (0)