[llvm] [X86][AMX] Fix use iteration when reloading tiles in FastPreTileConfig (PR #228724)
Aochang Liu via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 22:11:23 PDT 2026
https://github.com/HelloWorldU updated https://github.com/llvm/llvm-project/pull/228724
>From c1929f3c4f3bad83bf58501a7628aa653c01b79f Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Sat, 3 Oct 2026 23:30:14 +0800
Subject: [PATCH] [X86][AMX] Fix use iteration when reloading tiles in
FastPreTileConfig
reload() rewrites the user's tile operand, which moves it off the use list
being iterated, so only the first use of a tile was reloaded. A DBG_VALUE
was also reloaded as a use; when it came first, the real use kept the
clobbered tile and FastRegAlloc crashed. Iterate the non-debug uses with
make_early_inc_range, as InlineSpiller does.
Fixes #228712
Assisted-by: Claude Opus 5.5
---
llvm/lib/Target/X86/X86FastPreTileConfig.cpp | 4 +-
.../X86/AMX/amx-fastconfig-debug-use.mir | 72 +++++++++++++++++++
.../CodeGen/X86/AMX/amx-fastconfig-spill.mir | 52 ++++++++++++++
3 files changed, 127 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/X86/AMX/amx-fastconfig-debug-use.mir
diff --git a/llvm/lib/Target/X86/X86FastPreTileConfig.cpp b/llvm/lib/Target/X86/X86FastPreTileConfig.cpp
index f461b5e97bd59..42e6fb6098d92 100644
--- a/llvm/lib/Target/X86/X86FastPreTileConfig.cpp
+++ b/llvm/lib/Target/X86/X86FastPreTileConfig.cpp
@@ -653,7 +653,9 @@ bool X86FastPreTileConfigImpl::configBasicBlock(MachineBasicBlock &MBB) {
Register TileReg = MI.getOperand(0).getReg();
if (mayLiveOut(TileReg, LastTileCfg))
spill(++MI.getIterator(), TileReg, false);
- for (MachineInstr &UseMI : MRI->use_instructions(TileReg)) {
+ // reload() rewrites or erases UseMI.
+ for (MachineInstr &UseMI :
+ make_early_inc_range(MRI->use_nodbg_instructions(TileReg))) {
if (UseMI.getParent() == &MBB) {
// check user should not across ldtilecfg
if (!LastTileCfg || !dominates(MBB, LastTileCfg, UseMI))
diff --git a/llvm/test/CodeGen/X86/AMX/amx-fastconfig-debug-use.mir b/llvm/test/CodeGen/X86/AMX/amx-fastconfig-debug-use.mir
new file mode 100644
index 0000000000000..f8759c883329b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/AMX/amx-fastconfig-debug-use.mir
@@ -0,0 +1,72 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=x86_64-- -mattr=+amx-int8,avx512f -run-pass=x86-fast-pre-tile-config -o - %s | FileCheck %s
+# RUN: llc -mtriple=x86_64-- -mattr=+amx-int8,avx512f -passes=x86-fast-pre-tile-config -o - %s | FileCheck %s
+
+# A debug use of a tile must not get a reload, and must not stop the real use
+# from getting one.
+
+--- |
+ define void @debug_use() !dbg !4 {
+ ret void
+ }
+
+ !llvm.dbg.cu = !{!0}
+ !llvm.module.flags = !{!2}
+
+ !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, emissionKind: FullDebug)
+ !1 = !DIFile(filename: "t.c", directory: "/")
+ !2 = !{i32 2, !"Debug Info Version", i32 3}
+ !3 = !DISubroutineType(types: !{})
+ !4 = distinct !DISubprogram(name: "debug_use", scope: !1, file: !1, type: !3, spFlags: DISPFlagDefinition, unit: !0)
+ !5 = !DILocalVariable(name: "t", scope: !4, file: !1, type: !6)
+ !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+ !7 = !DILocation(line: 1, scope: !4)
+...
+---
+name: debug_use
+alignment: 16
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 16
+stack:
+ - { id: 0, size: 1024, alignment: 16 }
+machineFunctionInfo:
+ amxProgModel: ManagedRA
+body: |
+ ; CHECK-LABEL: name: debug_use
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[AVX512_128_SET0_:%[0-9]+]]:vr128x = AVX512_128_SET0
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:vr512 = SUBREG_TO_REG [[AVX512_128_SET0_]], %subreg.sub_xmm
+ ; CHECK-NEXT: VMOVUPSZmr %stack.2, 1, $noreg, 0, $noreg, [[SUBREG_TO_REG]] :: (store (s512) into %stack.2, align 4)
+ ; CHECK-NEXT: MOV8mi %stack.2, 1, $noreg, 0, $noreg, 1 :: (store (s512) into %stack.2, align 4)
+ ; CHECK-NEXT: [[MOV16ri:%[0-9]+]]:gr16 = MOV16ri 32
+ ; CHECK-NEXT: [[MOV16ri1:%[0-9]+]]:gr16 = MOV16ri 8
+ ; CHECK-NEXT: PLDTILECFGV %stack.2, 1, $noreg, 0, $noreg, implicit-def dead $tmm0, implicit-def dead $tmm1, implicit-def dead $tmm2, implicit-def dead $tmm3, implicit-def dead $tmm4, implicit-def dead $tmm5, implicit-def dead $tmm6, implicit-def dead $tmm7 :: (load (s512) from %stack.2, align 4)
+ ; CHECK-NEXT: [[PTILEZEROV:%[0-9]+]]:tile = PTILEZEROV [[MOV16ri1]], [[MOV16ri]]
+ ; CHECK-NEXT: [[MOV64ri:%[0-9]+]]:gr64_nosp = MOV64ri 64
+ ; CHECK-NEXT: TILESTORED %stack.1, 1, killed [[MOV64ri]], 0, $noreg, [[PTILEZEROV]] :: (store (s8192) into %stack.1)
+ ; CHECK-NEXT: [[MOV32ri64_:%[0-9]+]]:gr64_nosp = MOV32ri64 32
+ ; CHECK-NEXT: [[LEA64r:%[0-9]+]]:gr64 = LEA64r %stack.0, 1, $noreg, 0, $noreg
+ ; CHECK-NEXT: JMP_1 %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: PLDTILECFGV %stack.2, 1, $noreg, 0, $noreg, implicit-def dead $tmm0, implicit-def dead $tmm1, implicit-def dead $tmm2, implicit-def dead $tmm3, implicit-def dead $tmm4, implicit-def dead $tmm5, implicit-def dead $tmm6, implicit-def dead $tmm7 :: (load (s512) from %stack.2, align 4)
+ ; CHECK-NEXT: DBG_VALUE [[PTILEZEROV]], $noreg, !6, !DIExpression(), debug-location !DILocation(line: 1, scope: !3)
+ ; CHECK-NEXT: [[MOV64ri1:%[0-9]+]]:gr64_nosp = MOV64ri 64
+ ; CHECK-NEXT: [[PTILELOADDV:%[0-9]+]]:tile = PTILELOADDV [[MOV16ri1]], [[MOV16ri]], %stack.1, 1, killed [[MOV64ri1]], 0, $noreg :: (load (s8192) from %stack.1)
+ ; CHECK-NEXT: PTILESTOREDV killed [[MOV16ri1]], killed [[MOV16ri]], killed [[LEA64r]], 1, killed [[MOV32ri64_]], 0, $noreg, killed [[PTILELOADDV]]
+ ; CHECK-NEXT: RET 0
+ bb.0:
+ %0:gr16 = MOV16ri 32
+ %1:gr16 = MOV16ri 8
+ %2:tile = PTILEZEROV %1, %0
+ %3:gr64_nosp = MOV32ri64 32
+ %4:gr64 = LEA64r %stack.0, 1, $noreg, 0, $noreg
+ JMP_1 %bb.1
+ bb.1:
+ DBG_VALUE %2, $noreg, !5, !DIExpression(), debug-location !7
+ PTILESTOREDV killed %1, killed %0, killed %4, 1, killed %3, 0, $noreg, killed %2
+ RET 0
+...
diff --git a/llvm/test/CodeGen/X86/AMX/amx-fastconfig-spill.mir b/llvm/test/CodeGen/X86/AMX/amx-fastconfig-spill.mir
index d39ba1bdee348..1a8d6630fe7ff 100644
--- a/llvm/test/CodeGen/X86/AMX/amx-fastconfig-spill.mir
+++ b/llvm/test/CodeGen/X86/AMX/amx-fastconfig-spill.mir
@@ -157,3 +157,55 @@ body: |
RET 0, killed $eax
...
+
+# Test that every cross-block use is reloaded.
+---
+name: two_uses
+alignment: 16
+tracksRegLiveness: true
+frameInfo:
+ maxAlignment: 16
+stack:
+ - { id: 0, size: 1024, alignment: 16 }
+machineFunctionInfo:
+ amxProgModel: ManagedRA
+body: |
+ ; CHECK-LABEL: name: two_uses
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[AVX512_128_SET0_:%[0-9]+]]:vr128x = AVX512_128_SET0
+ ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:vr512 = SUBREG_TO_REG [[AVX512_128_SET0_]], %subreg.sub_xmm
+ ; CHECK-NEXT: VMOVUPSZmr %stack.2, 1, $noreg, 0, $noreg, [[SUBREG_TO_REG]] :: (store (s512) into %stack.2, align 4)
+ ; CHECK-NEXT: MOV8mi %stack.2, 1, $noreg, 0, $noreg, 1 :: (store (s512) into %stack.2, align 4)
+ ; CHECK-NEXT: [[MOV16ri:%[0-9]+]]:gr16 = MOV16ri 32
+ ; CHECK-NEXT: [[MOV16ri1:%[0-9]+]]:gr16 = MOV16ri 8
+ ; CHECK-NEXT: PLDTILECFGV %stack.2, 1, $noreg, 0, $noreg, implicit-def dead $tmm0, implicit-def dead $tmm1, implicit-def dead $tmm2, implicit-def dead $tmm3, implicit-def dead $tmm4, implicit-def dead $tmm5, implicit-def dead $tmm6, implicit-def dead $tmm7 :: (load (s512) from %stack.2, align 4)
+ ; CHECK-NEXT: [[PTILEZEROV:%[0-9]+]]:tile = PTILEZEROV [[MOV16ri1]], [[MOV16ri]]
+ ; CHECK-NEXT: [[MOV64ri:%[0-9]+]]:gr64_nosp = MOV64ri 64
+ ; CHECK-NEXT: TILESTORED %stack.1, 1, killed [[MOV64ri]], 0, $noreg, [[PTILEZEROV]] :: (store (s8192) into %stack.1)
+ ; CHECK-NEXT: [[MOV32ri64_:%[0-9]+]]:gr64_nosp = MOV32ri64 32
+ ; CHECK-NEXT: [[LEA64r:%[0-9]+]]:gr64 = LEA64r %stack.0, 1, $noreg, 0, $noreg
+ ; CHECK-NEXT: JMP_1 %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: PLDTILECFGV %stack.2, 1, $noreg, 0, $noreg, implicit-def dead $tmm0, implicit-def dead $tmm1, implicit-def dead $tmm2, implicit-def dead $tmm3, implicit-def dead $tmm4, implicit-def dead $tmm5, implicit-def dead $tmm6, implicit-def dead $tmm7 :: (load (s512) from %stack.2, align 4)
+ ; CHECK-NEXT: [[MOV64ri1:%[0-9]+]]:gr64_nosp = MOV64ri 64
+ ; CHECK-NEXT: [[PTILELOADDV:%[0-9]+]]:tile = PTILELOADDV [[MOV16ri1]], [[MOV16ri]], %stack.1, 1, killed [[MOV64ri1]], 0, $noreg :: (load (s8192) from %stack.1)
+ ; CHECK-NEXT: PTILESTOREDV [[MOV16ri1]], [[MOV16ri]], [[LEA64r]], 1, [[MOV32ri64_]], 0, $noreg, [[PTILELOADDV]]
+ ; CHECK-NEXT: [[MOV64ri2:%[0-9]+]]:gr64_nosp = MOV64ri 64
+ ; CHECK-NEXT: [[PTILELOADDV1:%[0-9]+]]:tile = PTILELOADDV [[MOV16ri1]], [[MOV16ri]], %stack.1, 1, killed [[MOV64ri2]], 0, $noreg :: (load (s8192) from %stack.1)
+ ; CHECK-NEXT: PTILESTOREDV killed [[MOV16ri1]], killed [[MOV16ri]], killed [[LEA64r]], 1, killed [[MOV32ri64_]], 0, $noreg, killed [[PTILELOADDV1]]
+ ; CHECK-NEXT: RET 0
+ bb.0.entry:
+ %0:gr16 = MOV16ri 32
+ %1:gr16 = MOV16ri 8
+ %2:tile = PTILEZEROV %1, %0
+ %3:gr64_nosp = MOV32ri64 32
+ %4:gr64 = LEA64r %stack.0, 1, $noreg, 0, $noreg
+ JMP_1 %bb.1
+ bb.1:
+ PTILESTOREDV %1, %0, %4, 1, %3, 0, $noreg, %2
+ PTILESTOREDV killed %1, killed %0, killed %4, 1, killed %3, 0, $noreg, killed %2
+ RET 0
+...
More information about the llvm-commits
mailing list