[llvm] [CodeGen][ARM] Add regression tests for #202263 (PR #202599)
Aochang Liu via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 29 04:42:28 PDT 2026
https://github.com/HelloWorldU updated https://github.com/llvm/llvm-project/pull/202599
>From 210ed985def673e5386563edfe719d29468d2f3a Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Thu, 23 Jul 2026 22:28:08 +0800
Subject: [PATCH 1/3] [CodeGen][ARM] Add regression tests for #202263
The root cause - RegisterCoalescer eliminating an undef COPY and leaving
a partial subregister redef reading a value that no longer exists - was
fixed by #204039. Add the regression tests originally developed in
#202599 so the pattern stays covered:
- an end-to-end IR test whose assembly output is checked with FileCheck;
- a focused single-pass -run-pass=register-coalescer MIR test using
-verify-coalescing, which hits the "Instruction is reading nonexistent
value" assertion without #204039 and passes with it.
---
.../regcoalesce-undef-copy-subreg-redef.ll | 38 ++++++
.../regcoalesce-undef-copy-subreg-redef.mir | 112 ++++++++++++++++++
2 files changed, 150 insertions(+)
create mode 100644 llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
create mode 100644 llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
diff --git a/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
new file mode 100644
index 0000000000000..74a4101ad5dbf
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
@@ -0,0 +1,38 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=armv8a-unknown-linux < %s | FileCheck %s
+
+; Regression test for issue #202263. Lowering the REG_SEQUENCE that builds the
+; <2 x i64> keeps a COPY of an undefined value which feeds a later partial
+; subregister redef. When RegisterCoalescer eliminates that copy, the redef
+; must be turned into a read-undef def. Otherwise the coalescer asserts with
+; "Instruction is reading nonexistent value" on targets that do not track
+; subregister liveness (armv8a A-profile has no MVE).
+
+target triple = "armv8a-unknown-linux"
+
+define void @init(i64 %x, i1 %c, ptr %p) {
+; CHECK-LABEL: init:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: tst r2, #1
+; CHECK-NEXT: bxne lr
+; CHECK-NEXT: .LBB0_1: @ %body
+; CHECK-NEXT: vmov.32 d17[0], r0
+; CHECK-NEXT: mov r0, #1
+; CHECK-NEXT: vmov.32 d17[1], r1
+; CHECK-NEXT: vmov.32 d16[0], r0
+; CHECK-NEXT: mov r0, #0
+; CHECK-NEXT: vmov.32 d16[1], r0
+; CHECK-NEXT: vst1.64 {d16, d17}, [r3]
+; CHECK-NEXT: bx lr
+entry:
+ %v0 = insertelement <2 x i64> poison, i64 %x, i64 1
+ br i1 %c, label %exit, label %body
+
+body:
+ %v1 = insertelement <2 x i64> %v0, i64 1, i64 0
+ store <2 x i64> %v1, ptr %p, align 8
+ br label %exit
+
+exit:
+ ret void
+}
diff --git a/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
new file mode 100644
index 0000000000000..47060a1398051
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
@@ -0,0 +1,112 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=armv8a-unknown-linux -run-pass=register-coalescer -verify-coalescing -o - %s | FileCheck %s
+
+# Regression test for issue #202263 (and the long-standing #200378). After
+# RegisterCoalescer eliminates the COPY of an undefined value, the partial
+# subregister redef that implicitly read it must become a read-undef def;
+# otherwise the coalescer asserts "Instruction is reading nonexistent value"
+# on targets that do not track subregister liveness.
+#
+# The original failures reach this pattern through REG_SEQUENCE lowering.
+# This focused test starts at the RegisterCoalescer boundary, after that
+# lowering has produced the undef COPY and partial redef sequence.
+
+--- |
+ define void @init(i64 %0, i1 %c, ptr %1) {
+ ret void
+ }
+...
+---
+name: init
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: dpair }
+ - { id: 1, class: gpr }
+ - { id: 2, class: gpr }
+ - { id: 3, class: gpr }
+ - { id: 4, class: gpr }
+ - { id: 5, class: dpr }
+ - { id: 7, class: dpr }
+ - { id: 8, class: qpr }
+ - { id: 9, class: dpr }
+ - { id: 11, class: gpr }
+ - { id: 12, class: dpr }
+ - { id: 13, class: dpr }
+ - { id: 14, class: gpr }
+ - { id: 15, class: qpr }
+ - { id: 16, class: dpr }
+ - { id: 17, class: dpr }
+ - { id: 18, class: qpr }
+liveins:
+ - { reg: '$r0', virtual-reg: '%1' }
+ - { reg: '$r1', virtual-reg: '%2' }
+ - { reg: '$r2', virtual-reg: '%3' }
+ - { reg: '$r3', virtual-reg: '%4' }
+body: |
+ ; CHECK-LABEL: name: init
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: liveins: $r0, $r1, $r2, $r3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $r3
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $r2
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $r1
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $r0
+ ; CHECK-NEXT: TSTri [[COPY1]], 1, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ ; CHECK-NEXT: Bcc %bb.2, 0 /* CC::eq */, killed $cpsr
+ ; CHECK-NEXT: B %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: BX_RET 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: undef [[VSETLNi32_:%[0-9]+]].dsub_1:qpr = VSETLNi32 undef [[VSETLNi32_]].dsub_1, [[COPY3]], 0, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: [[VSETLNi32_:%[0-9]+]].dsub_1:qpr = VSETLNi32 [[VSETLNi32_]].dsub_1, [[COPY2]], 1, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: [[MOVi:%[0-9]+]]:gpr = MOVi 1, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK-NEXT: [[VSETLNi32_:%[0-9]+]].dsub_0:qpr = VSETLNi32 [[VSETLNi32_]].dsub_0, [[MOVi]], 0, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: [[MOVi1:%[0-9]+]]:gpr = MOVi 0, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK-NEXT: [[VSETLNi32_:%[0-9]+]].dsub_0:qpr = VSETLNi32 [[VSETLNi32_]].dsub_0, [[MOVi1]], 1, 14 /* CC::al */, $noreg
+ ; CHECK-NEXT: VST1q64 [[COPY]], 0, [[VSETLNi32_]], 14 /* CC::al */, $noreg :: (store (s128) into %ir.1, align 8)
+ ; CHECK-NEXT: B %bb.1
+ bb.0:
+ successors: %bb.1, %bb.2
+ liveins: $r0, $r1, $r2, $r3
+
+ %4:gpr = COPY killed $r3
+ %3:gpr = COPY killed $r2
+ %2:gpr = COPY killed $r1
+ %1:gpr = COPY killed $r0
+ TSTri killed %3, 1, 14 /* CC::al */, $noreg, implicit-def $cpsr
+ Bcc %bb.2, 0 /* CC::eq */, killed $cpsr
+ B %bb.1
+
+ bb.1:
+ BX_RET 14 /* CC::al */, $noreg
+
+ bb.2:
+ successors: %bb.1
+
+ ; The COPY of an undef value below feeds the dsub_1 partial redef. After the
+ ; copy is eliminated, that redef must become a read-undef def.
+ %5:dpr = VSETLNi32 undef %5, killed %1, 0, 14 /* CC::al */, $noreg
+ %7:dpr = COPY killed %5
+ %7:dpr = VSETLNi32 %7, killed %2, 1, 14 /* CC::al */, $noreg
+ undef %8.dsub_0:qpr = COPY undef %9:dpr
+ %8.dsub_1:qpr = COPY killed %7
+ %11:gpr = MOVi 1, 14 /* CC::al */, $noreg, $noreg
+ %12:dpr = COPY %8.dsub_0
+ %13:dpr = COPY killed %12
+ %13:dpr = VSETLNi32 %13, killed %11, 0, 14 /* CC::al */, $noreg
+ %14:gpr = MOVi 0, 14 /* CC::al */, $noreg, $noreg
+ %15:qpr = COPY killed %8
+ %15.dsub_0:qpr = COPY %13
+ %16:dpr = COPY killed %13
+ %17:dpr = COPY killed %16
+ %17:dpr = VSETLNi32 %17, killed %14, 1, 14 /* CC::al */, $noreg
+ %18:qpr = COPY killed %15
+ %18.dsub_0:qpr = COPY killed %17
+ VST1q64 killed %4, 0, killed %18, 14 /* CC::al */, $noreg :: (store (s128) into %ir.1, align 8)
+ B %bb.1
+...
>From d1472c15072da674ae316ea71f00754517a0b68c Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Wed, 29 Jul 2026 14:31:12 +0800
Subject: [PATCH 2/3] Drop redundant target triple; the RUN line already
specifies it
---
llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll | 2 --
1 file changed, 2 deletions(-)
diff --git a/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
index 74a4101ad5dbf..7cb2a68a18d73 100644
--- a/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
+++ b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
@@ -8,8 +8,6 @@
; "Instruction is reading nonexistent value" on targets that do not track
; subregister liveness (armv8a A-profile has no MVE).
-target triple = "armv8a-unknown-linux"
-
define void @init(i64 %x, i1 %c, ptr %p) {
; CHECK-LABEL: init:
; CHECK: @ %bb.0: @ %entry
>From 053b5171c9c0a86153304bd1c798d2a378999b87 Mon Sep 17 00:00:00 2001
From: HelloWorldU <asd001liu at gmail.com>
Date: Wed, 29 Jul 2026 19:40:02 +0800
Subject: [PATCH 3/3] Minimize the MIR test per review: drop the IR section,
MMO, registers and liveins blocks
---
.../regcoalesce-undef-copy-subreg-redef.mir | 32 ++-----------------
1 file changed, 2 insertions(+), 30 deletions(-)
diff --git a/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
index 47060a1398051..d13b6c6f883ce 100644
--- a/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
+++ b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
@@ -11,37 +11,9 @@
# This focused test starts at the RegisterCoalescer boundary, after that
# lowering has produced the undef COPY and partial redef sequence.
---- |
- define void @init(i64 %0, i1 %c, ptr %1) {
- ret void
- }
-...
---
name: init
tracksRegLiveness: true
-registers:
- - { id: 0, class: dpair }
- - { id: 1, class: gpr }
- - { id: 2, class: gpr }
- - { id: 3, class: gpr }
- - { id: 4, class: gpr }
- - { id: 5, class: dpr }
- - { id: 7, class: dpr }
- - { id: 8, class: qpr }
- - { id: 9, class: dpr }
- - { id: 11, class: gpr }
- - { id: 12, class: dpr }
- - { id: 13, class: dpr }
- - { id: 14, class: gpr }
- - { id: 15, class: qpr }
- - { id: 16, class: dpr }
- - { id: 17, class: dpr }
- - { id: 18, class: qpr }
-liveins:
- - { reg: '$r0', virtual-reg: '%1' }
- - { reg: '$r1', virtual-reg: '%2' }
- - { reg: '$r2', virtual-reg: '%3' }
- - { reg: '$r3', virtual-reg: '%4' }
body: |
; CHECK-LABEL: name: init
; CHECK: bb.0:
@@ -68,7 +40,7 @@ body: |
; CHECK-NEXT: [[VSETLNi32_:%[0-9]+]].dsub_0:qpr = VSETLNi32 [[VSETLNi32_]].dsub_0, [[MOVi]], 0, 14 /* CC::al */, $noreg
; CHECK-NEXT: [[MOVi1:%[0-9]+]]:gpr = MOVi 0, 14 /* CC::al */, $noreg, $noreg
; CHECK-NEXT: [[VSETLNi32_:%[0-9]+]].dsub_0:qpr = VSETLNi32 [[VSETLNi32_]].dsub_0, [[MOVi1]], 1, 14 /* CC::al */, $noreg
- ; CHECK-NEXT: VST1q64 [[COPY]], 0, [[VSETLNi32_]], 14 /* CC::al */, $noreg :: (store (s128) into %ir.1, align 8)
+ ; CHECK-NEXT: VST1q64 [[COPY]], 0, [[VSETLNi32_]], 14 /* CC::al */, $noreg
; CHECK-NEXT: B %bb.1
bb.0:
successors: %bb.1, %bb.2
@@ -107,6 +79,6 @@ body: |
%17:dpr = VSETLNi32 %17, killed %14, 1, 14 /* CC::al */, $noreg
%18:qpr = COPY killed %15
%18.dsub_0:qpr = COPY killed %17
- VST1q64 killed %4, 0, killed %18, 14 /* CC::al */, $noreg :: (store (s128) into %ir.1, align 8)
+ VST1q64 killed %4, 0, killed %18, 14 /* CC::al */, $noreg
B %bb.1
...
More information about the llvm-commits
mailing list