[llvm] ed389ca - [CodeGen][ARM] Add regression tests for #202263 (#202599)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 29 05:30:02 PDT 2026


Author: Aochang Liu
Date: 2026-07-29T12:29:56Z
New Revision: ed389ca093797baab0bcc95ffd2b6ca41741c40d

URL: https://github.com/llvm/llvm-project/commit/ed389ca093797baab0bcc95ffd2b6ca41741c40d
DIFF: https://github.com/llvm/llvm-project/commit/ed389ca093797baab0bcc95ffd2b6ca41741c40d.diff

LOG: [CodeGen][ARM] Add regression tests for #202263 (#202599)

The underlying issue—RegisterCoalescer eliminating an undef COPY and
leaving a partial subregister redef that reads a value that no longer
exists—was fixed in #204039.

This PR adds the regression coverage originally developed alongside the
fix attempt, so the pattern remains covered:

- an end-to-end IR test that checks the generated assembly with
FileCheck;
- a focused single-pass `-run-pass=register-coalescer` MIR test using
`-verify-coalescing`, which reproduces the "Instruction is reading
nonexistent value" verifier error from #202263 when #204039 is reverted,
and passes with the fix applied.

Fixes #202263

Added: 
    llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
    llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir

Modified: 
    

Removed: 
    


################################################################################
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..7cb2a68a18d73
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.ll
@@ -0,0 +1,36 @@
+; 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).
+
+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..d13b6c6f883ce
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/regcoalesce-undef-copy-subreg-redef.mir
@@ -0,0 +1,84 @@
+# 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.
+
+---
+name:            init
+tracksRegLiveness: true
+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
+  ; 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
+    B %bb.1
+...


        


More information about the llvm-commits mailing list