[llvm] [utils][UpdateLLCTestChecks] Add MIR support to update_llc_test_checks.py. (PR #164965)
Valery Pykhtin via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 28 00:32:16 PDT 2025
https://github.com/vpykhtin updated https://github.com/llvm/llvm-project/pull/164965
>From 5f596b62cc77bde17360b4834d279d94db09f0f5 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Fri, 24 Oct 2025 11:41:06 +0000
Subject: [PATCH 1/4] [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.
---
.../Inputs/x86_asm_mir_mixed.ll | 17 ++++++
.../Inputs/x86_asm_mir_mixed.ll.expected | 47 ++++++++++++++++
.../x86-asm-mir-mixed.test | 5 ++
llvm/utils/UpdateTestChecks/common.py | 1 +
llvm/utils/update_llc_test_checks.py | 55 +++++++++++++++++--
5 files changed, 119 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll
create mode 100644 llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected
create mode 100644 llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-asm-mir-mixed.test
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll
new file mode 100644
index 0000000000000..3c3dd01e4239d
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll
@@ -0,0 +1,17 @@
+; RUN: llc -mtriple=x86_64 < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc -mtriple=x86_64 -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=MIR
+
+define i64 @test1(i64 %i) nounwind readnone {
+ %loc = alloca i64
+ %j = load i64, i64 * %loc
+ %r = add i64 %i, %j
+ ret i64 %r
+}
+
+define i64 @test2(i32 %i) nounwind readnone {
+ %loc = alloca i32
+ %j = load i32, i32 * %loc
+ %r = add i32 %i, %j
+ %ext = zext i32 %r to i64
+ ret i64 %ext
+}
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected
new file mode 100644
index 0000000000000..03a79408c7e47
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64 < %s | FileCheck %s --check-prefix=ASM
+; RUN: llc -mtriple=x86_64 -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=MIR
+
+define i64 @test1(i64 %i) nounwind readnone {
+; ASM-LABEL: test1:
+; ASM: # %bb.0:
+; ASM-NEXT: movq %rdi, %rax
+; ASM-NEXT: addq -{{[0-9]+}}(%rsp), %rax
+; ASM-NEXT: retq
+ ; MIR-LABEL: name: test1
+ ; MIR: bb.0 (%ir-block.0):
+ ; MIR-NEXT: liveins: $rdi
+ ; MIR-NEXT: {{ $}}
+ ; MIR-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
+ ; 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)
+ ; MIR-NEXT: $rax = COPY [[ADD64rm]]
+ ; MIR-NEXT: RET 0, $rax
+ %loc = alloca i64
+ %j = load i64, i64 * %loc
+ %r = add i64 %i, %j
+ ret i64 %r
+}
+
+define i64 @test2(i32 %i) nounwind readnone {
+; ASM-LABEL: test2:
+; ASM: # %bb.0:
+; ASM-NEXT: movl %edi, %eax
+; ASM-NEXT: addl -{{[0-9]+}}(%rsp), %eax
+; ASM-NEXT: retq
+ ; MIR-LABEL: name: test2
+ ; MIR: bb.0 (%ir-block.0):
+ ; MIR-NEXT: liveins: $edi
+ ; MIR-NEXT: {{ $}}
+ ; MIR-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+ ; 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)
+ ; MIR-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[ADD32rm]], %subreg.sub_32bit
+ ; MIR-NEXT: $rax = COPY [[SUBREG_TO_REG]]
+ ; MIR-NEXT: RET 0, $rax
+ %loc = alloca i32
+ %j = load i32, i32 * %loc
+ %r = add i32 %i, %j
+ %ext = zext i32 %r to i64
+ ret i64 %ext
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; MIR: {{.*}}
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-asm-mir-mixed.test b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-asm-mir-mixed.test
new file mode 100644
index 0000000000000..57b6d48147949
--- /dev/null
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-asm-mir-mixed.test
@@ -0,0 +1,5 @@
+# REQUIRES: x86-registered-target
+## Test checking that update_llc_test_checks.py can generate both ASM and MIR checks in the same file
+
+# RUN: cp -f %S/Inputs/x86_asm_mir_mixed.ll %t.ll && %update_llc_test_checks %t.ll
+# RUN: diff -u %S/Inputs/x86_asm_mir_mixed.ll.expected %t.ll
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index a5e3c39bfdecd..eab0977ed7200 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -604,6 +604,7 @@ def invoke_tool(exe, cmd_args, ir, preprocess_cmd=None, verbose=False):
TRIPLE_ARG_RE = re.compile(r"-m?triple[= ]([^ ]+)")
MARCH_ARG_RE = re.compile(r"-march[= ]([^ ]+)")
DEBUG_ONLY_ARG_RE = re.compile(r"-debug-only[= ]([^ ]+)")
+STOP_PASS_RE = re.compile(r"-stop-(before|after)=(\w+)")
IS_DEBUG_RECORD_RE = re.compile(r"^(\s+)#dbg_")
diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py
index 8c57e75f34f75..2a160cb82a273 100755
--- a/llvm/utils/update_llc_test_checks.py
+++ b/llvm/utils/update_llc_test_checks.py
@@ -16,6 +16,7 @@
import sys
from UpdateTestChecks import common
+import update_mir_test_checks # Reuse MIR parsing code.
# llc is the only llc-like in the LLVM tree but downstream forks can add
# additional ones here if they have them.
@@ -119,6 +120,10 @@ def update_test(ti: common.TestInfo):
ginfo=ginfo,
)
+ # Dictionary to store MIR function bodies separately
+ mir_func_dict = {}
+ mir_run_list = []
+
for (
prefixes,
llc_tool,
@@ -141,14 +146,37 @@ def update_test(ti: common.TestInfo):
if not triple:
triple = common.get_triple_from_march(march_in_cmd)
- scrubber, function_re = output_type.get_run_handler(triple)
- if 0 == builder.process_run_line(
- function_re, scrubber, raw_tool_output, prefixes
+ # Check if we are in MIR output mode. If -debug-only is present assume
+ # the debug output is the main point of interest.
+ if common.STOP_PASS_RE.search(llc_args) and not common.DEBUG_ONLY_ARG_RE.search(
+ llc_args
):
- common.warn(
- "Couldn't match any function. Possibly the wrong target triple has been provided"
+ common.debug("Detected MIR output mode for prefixes:", str(prefixes))
+ for prefix in prefixes:
+ if prefix not in mir_func_dict:
+ mir_func_dict[prefix] = {}
+
+ update_mir_test_checks.build_function_info_dictionary(
+ ti.path,
+ raw_tool_output,
+ triple,
+ prefixes,
+ mir_func_dict,
+ ti.args.verbose,
+ )
+
+ mir_run_list.append(
+ (prefixes, llc_tool, llc_args, triple_in_cmd, march_in_cmd)
)
- builder.processed_prefixes(prefixes)
+ else:
+ scrubber, function_re = output_type.get_run_handler(triple)
+ if 0 == builder.process_run_line(
+ function_re, scrubber, raw_tool_output, prefixes
+ ):
+ common.warn(
+ "Couldn't match any function. Possibly the wrong target triple has been provided"
+ )
+ builder.processed_prefixes(prefixes)
func_dict = builder.finish_and_get_func_dict()
global_vars_seen_dict = {}
@@ -221,6 +249,21 @@ def update_test(ti: common.TestInfo):
is_filtered=builder.is_filtered(),
)
)
+
+ # Also add MIR checks if we have them for this function
+ if mir_run_list and func_name:
+ common.add_mir_checks_for_function(
+ ti.path,
+ output_lines,
+ mir_run_list,
+ mir_func_dict,
+ func_name,
+ single_bb=False, # Don't skip basic block labels.
+ print_fixed_stack=False, # Don't print fixed stack (ASM tests don't need it).
+ first_check_is_next=False, # First check is LABEL, not NEXT.
+ at_the_function_name=False, # Use "name:" not "@name".
+ )
+
is_in_function_start = False
if is_in_function:
>From d9e9519adbfdb7a53679e64c9a7220c695b7aff4 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Sun, 26 Oct 2025 14:01:41 +0000
Subject: [PATCH 2/4] move MIR parsing code to the common
---
llvm/utils/UpdateTestChecks/common.py | 115 +++++++++++++++++++++++++
llvm/utils/update_llc_test_checks.py | 3 +-
llvm/utils/update_mir_test_checks.py | 118 +-------------------------
3 files changed, 117 insertions(+), 119 deletions(-)
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index eab0977ed7200..11449a2693018 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -2404,6 +2404,121 @@ def add_analyze_checks(
MIR_BASIC_BLOCK_RE = re.compile(r" *bb\.[0-9]+.*:$")
MIR_PREFIX_DATA_RE = re.compile(r"^ *(;|bb.[0-9].*: *$|[a-z]+:( |$)|$)")
+# Patterns for MIR function parsing
+VREG_RE = re.compile(r"(%[0-9]+)(?:\.[a-z0-9_]+)?(?::[a-z0-9_]+)?(?:\([<>a-z0-9 ]+\))?")
+MI_FLAGS_STR = (
+ r"(frame-setup |frame-destroy |nnan |ninf |nsz |arcp |contract |afn "
+ r"|reassoc |nuw |nsw |exact |nofpexcept |nomerge |unpredictable "
+ r"|noconvergent |nneg |disjoint |nusw |samesign |inbounds )*"
+)
+VREG_DEF_FLAGS_STR = r"(?:dead |undef )*"
+
+# Pattern to match the defined vregs and the opcode of an instruction that
+# defines vregs. Opcodes starting with a lower-case 't' are allowed to match
+# ARM's thumb instructions, like tADDi8 and t2ADDri.
+VREG_DEF_RE = re.compile(
+ r"^ *(?P<vregs>{2}{0}(?:, {2}{0})*) = "
+ r"{1}(?P<opcode>[A-Zt][A-Za-z0-9_]+)".format(
+ VREG_RE.pattern, MI_FLAGS_STR, VREG_DEF_FLAGS_STR
+ )
+)
+
+MIR_FUNC_RE = re.compile(
+ r"^---$"
+ r"\n"
+ r"^ *name: *(?P<func>[A-Za-z0-9_.-]+)$"
+ r".*?"
+ r"(?:^ *fixedStack: *(\[\])? *\n"
+ r"(?P<fixedStack>.*?)\n?"
+ r"^ *stack:"
+ r".*?)?"
+ r"^ *body: *\|\n"
+ r"(?P<body>.*?)\n"
+ r"^\.\.\.$",
+ flags=(re.M | re.S),
+)
+
+
+def mangle_vreg(opcode, current_names):
+ base = opcode
+ # Simplify some common prefixes and suffixes
+ if opcode.startswith("G_"):
+ base = base[len("G_") :]
+ if opcode.endswith("_PSEUDO"):
+ base = base[: -len("_PSEUDO")]
+ # Shorten some common opcodes with long-ish names
+ base = dict(
+ IMPLICIT_DEF="DEF",
+ GLOBAL_VALUE="GV",
+ CONSTANT="C",
+ FCONSTANT="C",
+ MERGE_VALUES="MV",
+ UNMERGE_VALUES="UV",
+ INTRINSIC="INT",
+ INTRINSIC_W_SIDE_EFFECTS="INT",
+ INSERT_VECTOR_ELT="IVEC",
+ EXTRACT_VECTOR_ELT="EVEC",
+ SHUFFLE_VECTOR="SHUF",
+ ).get(base, base)
+ # Avoid ambiguity when opcodes end in numbers
+ if len(base.rstrip("0123456789")) < len(base):
+ base += "_"
+
+ i = 0
+ for name in current_names:
+ if name.rstrip("0123456789") == base:
+ i += 1
+ if i:
+ return "{}{}".format(base, i)
+ return base
+
+
+def build_function_info_dictionary(
+ test, raw_tool_output, triple, prefixes, func_dict, verbose
+):
+ for m in MIR_FUNC_RE.finditer(raw_tool_output):
+ func = m.group("func")
+ fixedStack = m.group("fixedStack")
+ body = m.group("body")
+ if verbose:
+ debug("Processing function: {}".format(func))
+ for l in body.splitlines():
+ debug(" {}".format(l))
+
+ # Vreg mangling
+ mangled = []
+ vreg_map = {}
+ for func_line in body.splitlines(keepends=True):
+ m = VREG_DEF_RE.match(func_line)
+ if m:
+ for vreg in VREG_RE.finditer(m.group("vregs")):
+ if vreg.group(1) in vreg_map:
+ name = vreg_map[vreg.group(1)]
+ else:
+ name = mangle_vreg(m.group("opcode"), vreg_map.values())
+ vreg_map[vreg.group(1)] = name
+ func_line = func_line.replace(
+ vreg.group(1), "[[{}:%[0-9]+]]".format(name), 1
+ )
+ for number, name in vreg_map.items():
+ func_line = re.sub(
+ r"{}\b".format(number), "[[{}]]".format(name), func_line
+ )
+ mangled.append(func_line)
+ body = "".join(mangled)
+
+ for prefix in prefixes:
+ info = function_body(body, fixedStack, None, None, None, None, ginfo=None)
+ if func in func_dict[prefix]:
+ if (
+ not func_dict[prefix][func]
+ or func_dict[prefix][func].scrub != info.scrub
+ or func_dict[prefix][func].extrascrub != info.extrascrub
+ ):
+ func_dict[prefix][func] = None
+ else:
+ func_dict[prefix][func] = info
+
def find_mir_functions_with_one_bb(lines, verbose=False):
result = []
diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py
index 2a160cb82a273..079d05352238b 100755
--- a/llvm/utils/update_llc_test_checks.py
+++ b/llvm/utils/update_llc_test_checks.py
@@ -16,7 +16,6 @@
import sys
from UpdateTestChecks import common
-import update_mir_test_checks # Reuse MIR parsing code.
# llc is the only llc-like in the LLVM tree but downstream forks can add
# additional ones here if they have them.
@@ -156,7 +155,7 @@ def update_test(ti: common.TestInfo):
if prefix not in mir_func_dict:
mir_func_dict[prefix] = {}
- update_mir_test_checks.build_function_info_dictionary(
+ common.build_function_info_dictionary(
ti.path,
raw_tool_output,
triple,
diff --git a/llvm/utils/update_mir_test_checks.py b/llvm/utils/update_mir_test_checks.py
index c4ee0523a6469..dd2763917efa6 100755
--- a/llvm/utils/update_mir_test_checks.py
+++ b/llvm/utils/update_mir_test_checks.py
@@ -32,39 +32,6 @@
from UpdateTestChecks import common
-VREG_RE = re.compile(r"(%[0-9]+)(?:\.[a-z0-9_]+)?(?::[a-z0-9_]+)?(?:\([<>a-z0-9 ]+\))?")
-MI_FLAGS_STR = (
- r"(frame-setup |frame-destroy |nnan |ninf |nsz |arcp |contract |afn "
- r"|reassoc |nuw |nsw |exact |nofpexcept |nomerge |unpredictable "
- r"|noconvergent |nneg |disjoint |nusw |samesign |inbounds )*"
-)
-VREG_DEF_FLAGS_STR = r"(?:dead |undef )*"
-
-# Pattern to match the defined vregs and the opcode of an instruction that
-# defines vregs. Opcodes starting with a lower-case 't' are allowed to match
-# ARM's thumb instructions, like tADDi8 and t2ADDri.
-VREG_DEF_RE = re.compile(
- r"^ *(?P<vregs>{2}{0}(?:, {2}{0})*) = "
- r"{1}(?P<opcode>[A-Zt][A-Za-z0-9_]+)".format(
- VREG_RE.pattern, MI_FLAGS_STR, VREG_DEF_FLAGS_STR
- )
-)
-
-MIR_FUNC_RE = re.compile(
- r"^---$"
- r"\n"
- r"^ *name: *(?P<func>[A-Za-z0-9_.-]+)$"
- r".*?"
- r"(?:^ *fixedStack: *(\[\])? *\n"
- r"(?P<fixedStack>.*?)\n?"
- r"^ *stack:"
- r".*?)?"
- r"^ *body: *\|\n"
- r"(?P<body>.*?)\n"
- r"^\.\.\.$",
- flags=(re.M | re.S),
-)
-
class LLC:
def __init__(self, bin):
@@ -143,89 +110,6 @@ def build_run_list(test, run_lines, verbose=False):
return run_list
-def build_function_info_dictionary(
- test, raw_tool_output, triple, prefixes, func_dict, verbose
-):
- for m in MIR_FUNC_RE.finditer(raw_tool_output):
- func = m.group("func")
- fixedStack = m.group("fixedStack")
- body = m.group("body")
- if verbose:
- log("Processing function: {}".format(func))
- for l in body.splitlines():
- log(" {}".format(l))
-
- # Vreg mangling
- mangled = []
- vreg_map = {}
- for func_line in body.splitlines(keepends=True):
- m = VREG_DEF_RE.match(func_line)
- if m:
- for vreg in VREG_RE.finditer(m.group("vregs")):
- if vreg.group(1) in vreg_map:
- name = vreg_map[vreg.group(1)]
- else:
- name = mangle_vreg(m.group("opcode"), vreg_map.values())
- vreg_map[vreg.group(1)] = name
- func_line = func_line.replace(
- vreg.group(1), "[[{}:%[0-9]+]]".format(name), 1
- )
- for number, name in vreg_map.items():
- func_line = re.sub(
- r"{}\b".format(number), "[[{}]]".format(name), func_line
- )
- mangled.append(func_line)
- body = "".join(mangled)
-
- for prefix in prefixes:
- info = common.function_body(
- body, fixedStack, None, None, None, None, ginfo=None
- )
- if func in func_dict[prefix]:
- if (
- not func_dict[prefix][func]
- or func_dict[prefix][func].scrub != info.scrub
- or func_dict[prefix][func].extrascrub != info.extrascrub
- ):
- func_dict[prefix][func] = None
- else:
- func_dict[prefix][func] = info
-
-
-def mangle_vreg(opcode, current_names):
- base = opcode
- # Simplify some common prefixes and suffixes
- if opcode.startswith("G_"):
- base = base[len("G_") :]
- if opcode.endswith("_PSEUDO"):
- base = base[: len("_PSEUDO")]
- # Shorten some common opcodes with long-ish names
- base = dict(
- IMPLICIT_DEF="DEF",
- GLOBAL_VALUE="GV",
- CONSTANT="C",
- FCONSTANT="C",
- MERGE_VALUES="MV",
- UNMERGE_VALUES="UV",
- INTRINSIC="INT",
- INTRINSIC_W_SIDE_EFFECTS="INT",
- INSERT_VECTOR_ELT="IVEC",
- EXTRACT_VECTOR_ELT="EVEC",
- SHUFFLE_VECTOR="SHUF",
- ).get(base, base)
- # Avoid ambiguity when opcodes end in numbers
- if len(base.rstrip("0123456789")) < len(base):
- base += "_"
-
- i = 0
- for name in current_names:
- if name.rstrip("0123456789") == base:
- i += 1
- if i:
- return "{}{}".format(base, i)
- return base
-
-
def update_test_file(args, test, autogenerated_note):
with open(test) as fd:
input_lines = [l.rstrip() for l in fd]
@@ -247,7 +131,7 @@ def update_test_file(args, test, autogenerated_note):
common.warn("No triple found: skipping file", test_file=test)
return
- build_function_info_dictionary(
+ common.build_function_info_dictionary(
test,
raw_tool_output,
triple_in_cmd or triple_in_ir,
>From 1e97c19eee43f9bacb82e69ffae060a0d81ce517 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Tue, 28 Oct 2025 07:20:20 +0000
Subject: [PATCH 3/4] Rename build_function_info_dictionary to
build_mir_function_info_dictionary.
---
llvm/utils/UpdateTestChecks/common.py | 2 +-
llvm/utils/update_llc_test_checks.py | 2 +-
llvm/utils/update_mir_test_checks.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index 11449a2693018..dc8f4eb493055 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -2473,7 +2473,7 @@ def mangle_vreg(opcode, current_names):
return base
-def build_function_info_dictionary(
+def build_mir_function_info_dictionary(
test, raw_tool_output, triple, prefixes, func_dict, verbose
):
for m in MIR_FUNC_RE.finditer(raw_tool_output):
diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py
index 079d05352238b..63ec03a3d3076 100755
--- a/llvm/utils/update_llc_test_checks.py
+++ b/llvm/utils/update_llc_test_checks.py
@@ -155,7 +155,7 @@ def update_test(ti: common.TestInfo):
if prefix not in mir_func_dict:
mir_func_dict[prefix] = {}
- common.build_function_info_dictionary(
+ common.build_mir_function_info_dictionary(
ti.path,
raw_tool_output,
triple,
diff --git a/llvm/utils/update_mir_test_checks.py b/llvm/utils/update_mir_test_checks.py
index dd2763917efa6..866694e13f522 100755
--- a/llvm/utils/update_mir_test_checks.py
+++ b/llvm/utils/update_mir_test_checks.py
@@ -131,7 +131,7 @@ def update_test_file(args, test, autogenerated_note):
common.warn("No triple found: skipping file", test_file=test)
return
- common.build_function_info_dictionary(
+ common.build_mir_function_info_dictionary(
test,
raw_tool_output,
triple_in_cmd or triple_in_ir,
>From 2d34e0477dca23da6bf74fa2bcee6279bd70e6e7 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Tue, 28 Oct 2025 07:30:35 +0000
Subject: [PATCH 4/4] Remove extra indentation from MIR check lines
---
.../Inputs/x86_asm_mir_mixed.ll.expected | 34 +++++++++----------
llvm/utils/UpdateTestChecks/common.py | 9 ++++-
llvm/utils/update_llc_test_checks.py | 1 +
3 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected
index 03a79408c7e47..e7acd2e36a4d6 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86_asm_mir_mixed.ll.expected
@@ -8,14 +8,14 @@ define i64 @test1(i64 %i) nounwind readnone {
; ASM-NEXT: movq %rdi, %rax
; ASM-NEXT: addq -{{[0-9]+}}(%rsp), %rax
; ASM-NEXT: retq
- ; MIR-LABEL: name: test1
- ; MIR: bb.0 (%ir-block.0):
- ; MIR-NEXT: liveins: $rdi
- ; MIR-NEXT: {{ $}}
- ; MIR-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
- ; 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)
- ; MIR-NEXT: $rax = COPY [[ADD64rm]]
- ; MIR-NEXT: RET 0, $rax
+; MIR-LABEL: name: test1
+; MIR: bb.0 (%ir-block.0):
+; MIR-NEXT: liveins: $rdi
+; MIR-NEXT: {{ $}}
+; MIR-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
+; 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)
+; MIR-NEXT: $rax = COPY [[ADD64rm]]
+; MIR-NEXT: RET 0, $rax
%loc = alloca i64
%j = load i64, i64 * %loc
%r = add i64 %i, %j
@@ -28,15 +28,15 @@ define i64 @test2(i32 %i) nounwind readnone {
; ASM-NEXT: movl %edi, %eax
; ASM-NEXT: addl -{{[0-9]+}}(%rsp), %eax
; ASM-NEXT: retq
- ; MIR-LABEL: name: test2
- ; MIR: bb.0 (%ir-block.0):
- ; MIR-NEXT: liveins: $edi
- ; MIR-NEXT: {{ $}}
- ; MIR-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi
- ; 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)
- ; MIR-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[ADD32rm]], %subreg.sub_32bit
- ; MIR-NEXT: $rax = COPY [[SUBREG_TO_REG]]
- ; MIR-NEXT: RET 0, $rax
+; MIR-LABEL: name: test2
+; MIR: bb.0 (%ir-block.0):
+; MIR-NEXT: liveins: $edi
+; MIR-NEXT: {{ $}}
+; MIR-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi
+; 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)
+; MIR-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[ADD32rm]], %subreg.sub_32bit
+; MIR-NEXT: $rax = COPY [[SUBREG_TO_REG]]
+; MIR-NEXT: RET 0, $rax
%loc = alloca i32
%j = load i32, i32 * %loc
%r = add i32 %i, %j
diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py
index dc8f4eb493055..202ec22ecb62c 100644
--- a/llvm/utils/UpdateTestChecks/common.py
+++ b/llvm/utils/UpdateTestChecks/common.py
@@ -2549,6 +2549,7 @@ def add_mir_checks_for_function(
print_fixed_stack,
first_check_is_next,
at_the_function_name,
+ check_indent=None,
):
printed_prefixes = set()
for run in run_list:
@@ -2571,6 +2572,7 @@ def add_mir_checks_for_function(
func_dict[prefix][func_name],
print_fixed_stack,
first_check_is_next,
+ check_indent,
)
break
else:
@@ -2590,6 +2592,7 @@ def add_mir_check_lines(
func_info,
print_fixed_stack,
first_check_is_next,
+ check_indent=None,
):
func_body = str(func_info).splitlines()
if single_bb:
@@ -2606,7 +2609,11 @@ def add_mir_check_lines(
first_line = func_body[0]
indent = len(first_line) - len(first_line.lstrip(" "))
# A check comment, indented the appropriate amount
- check = "{:>{}}; {}".format("", indent, prefix)
+ # If check_indent is provided, use it; otherwise, auto-detect from MIR body
+ if check_indent is not None:
+ check = "{}; {}".format(check_indent, prefix)
+ else:
+ check = "{:>{}}; {}".format("", indent, prefix)
output_lines.append("{}-LABEL: name: {}".format(check, func_name))
diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py
index 63ec03a3d3076..56b7860c8618d 100755
--- a/llvm/utils/update_llc_test_checks.py
+++ b/llvm/utils/update_llc_test_checks.py
@@ -261,6 +261,7 @@ def update_test(ti: common.TestInfo):
print_fixed_stack=False, # Don't print fixed stack (ASM tests don't need it).
first_check_is_next=False, # First check is LABEL, not NEXT.
at_the_function_name=False, # Use "name:" not "@name".
+ check_indent="", # No indentation for IR files (not MIR files).
)
is_in_function_start = False
More information about the llvm-commits
mailing list