Skip to content

Commit 6bdef82

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 a2f3811 commit 6bdef82

File tree

5 files changed

+117
-7
lines changed

5 files changed

+117
-7
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: 47 additions & 7 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,34 @@ 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
147-
):
148-
common.warn(
149-
"Couldn't match any function. Possibly the wrong target triple has been provided"
149+
if common.STOP_PASS_RE.search(llc_args) and \
150+
not common.DEBUG_ONLY_ARG_RE.search(llc_args):
151+
common.debug("Detected MIR output mode for prefixes:", str(prefixes))
152+
for prefix in prefixes:
153+
if prefix not in mir_func_dict:
154+
mir_func_dict[prefix] = {}
155+
156+
update_mir_test_checks.build_function_info_dictionary(
157+
ti.path,
158+
raw_tool_output,
159+
triple,
160+
prefixes,
161+
mir_func_dict,
162+
ti.args.verbose,
163+
)
164+
165+
mir_run_list.append(
166+
(prefixes, llc_tool, llc_args, triple_in_cmd, march_in_cmd)
150167
)
151-
builder.processed_prefixes(prefixes)
168+
else:
169+
scrubber, function_re = output_type.get_run_handler(triple)
170+
if 0 == builder.process_run_line(
171+
function_re, scrubber, raw_tool_output, prefixes
172+
):
173+
common.warn(
174+
"Couldn't match any function. Possibly the wrong target triple has been provided"
175+
)
176+
builder.processed_prefixes(prefixes)
152177

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

226266
if is_in_function:

0 commit comments

Comments
 (0)