[llvm] [AArch64]: Replaced assertion with check (PR #173737)

Kevin Per via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 27 10:27:12 PST 2025


https://github.com/kper created https://github.com/llvm/llvm-project/pull/173737

The crash was triggered because `%38` violates the assertion since `WideTy` is a scalar value and smaller than 128 bits. 

LLC debug from referenced issue:
`Select:  %32:fpr(s16), %33:fpr(s16) = G_UNMERGE_VALUES %38:fpr(s32)`


This PR replaces the assertion with a check that returns `false` which forces a different instruction selection.

Closes https://github.com/llvm/llvm-project/issues/173722

>From 8646bb0543aa2ae73c448360df9f79b37dfd1372 Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Sat, 27 Dec 2025 19:21:06 +0100
Subject: [PATCH] [AArch64]: Replaced assertion with conditional

---
 .../GISel/AArch64InstructionSelector.cpp      |   7 +-
 ...aarch64-avoid-illegal-extract-subvector.ll | 112 +++++++++++++++---
 2 files changed, 99 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index f9db39e5f8622..f9f78c4242568 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -4085,8 +4085,11 @@ bool AArch64InstructionSelector::selectUnmergeValues(MachineInstr &I,
   const LLT NarrowTy = MRI.getType(I.getOperand(0).getReg());
   const LLT WideTy = MRI.getType(SrcReg);
   (void)WideTy;
-  assert((WideTy.isVector() || WideTy.getSizeInBits() == 128) &&
-         "can only unmerge from vector or s128 types!");
+  if (!(WideTy.isVector() || WideTy.getSizeInBits() == 128)) {
+    LLVM_DEBUG(dbgs() << "can only unmerge from vector or s128 types!.\n");
+    return false;
+  }
+
   assert(WideTy.getSizeInBits() > NarrowTy.getSizeInBits() &&
          "source register size too small!");
 
diff --git a/llvm/test/CodeGen/AArch64/aarch64-avoid-illegal-extract-subvector.ll b/llvm/test/CodeGen/AArch64/aarch64-avoid-illegal-extract-subvector.ll
index 925b4c87ec9a5..d19dcbb577aa3 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-avoid-illegal-extract-subvector.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-avoid-illegal-extract-subvector.ll
@@ -1,13 +1,25 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=aarch64-none-linux-gnu < %s -o -| FileCheck %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu < %s -o -| FileCheck %s --check-prefix=O2
+; RUN: llc -O0 -mtriple=aarch64-none-linux-gnu < %s -o -| FileCheck %s --check-prefix=O0
 define <2 x i64> @test1(<4 x i32> %x) #0 {
-; CHECK-LABEL: test1:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, v0.s[1]
-; CHECK-NEXT:    mov w9, v0.s[2]
-; CHECK-NEXT:    fmov d0, x8
-; CHECK-NEXT:    mov v0.d[1], x9
-; CHECK-NEXT:    ret
+; O2-LABEL: test1:
+; O2:       // %bb.0:
+; O2-NEXT:    mov w8, v0.s[1]
+; O2-NEXT:    mov w9, v0.s[2]
+; O2-NEXT:    fmov d0, x8
+; O2-NEXT:    mov v0.d[1], x9
+; O2-NEXT:    ret
+;
+; O0-LABEL: test1:
+; O0:       // %bb.0:
+; O0-NEXT:    mov w8, v0.s[1]
+; O0-NEXT:    mov w9, w8
+; O0-NEXT:    mov w8, v0.s[2]
+; O0-NEXT:    // kill: def $x8 killed $w8
+; O0-NEXT:    // implicit-def: $q0
+; O0-NEXT:    fmov d0, x9
+; O0-NEXT:    mov v0.d[1], x8
+; O0-NEXT:    ret
   %i1 = extractelement <4 x i32> %x, i32 1
   %zi1 = zext i32 %i1 to i64
   %i2 = extractelement <4 x i32> %x, i32 2
@@ -18,16 +30,32 @@ define <2 x i64> @test1(<4 x i32> %x) #0 {
 }
 
 define <4 x i64> @test2(<4 x i32> %0) {
-; CHECK-LABEL: test2:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    adrp x8, .LCPI1_0
-; CHECK-NEXT:    ldr q1, [x8, :lo12:.LCPI1_0]
-; CHECK-NEXT:    add v0.4s, v0.4s, v1.4s
-; CHECK-NEXT:    mov w8, v0.s[1]
-; CHECK-NEXT:    mov w9, v0.s[2]
-; CHECK-NEXT:    fmov d1, x8
-; CHECK-NEXT:    mov v1.d[1], x9
-; CHECK-NEXT:    ret
+; O2-LABEL: test2:
+; O2:       // %bb.0: // %entry
+; O2-NEXT:    adrp x8, .LCPI1_0
+; O2-NEXT:    ldr q1, [x8, :lo12:.LCPI1_0]
+; O2-NEXT:    add v0.4s, v0.4s, v1.4s
+; O2-NEXT:    mov w8, v0.s[1]
+; O2-NEXT:    mov w9, v0.s[2]
+; O2-NEXT:    fmov d1, x8
+; O2-NEXT:    mov v1.d[1], x9
+; O2-NEXT:    ret
+;
+; O0-LABEL: test2:
+; O0:       // %bb.0: // %entry
+; O0-NEXT:    mov v1.16b, v0.16b
+; O0-NEXT:    adrp x8, .LCPI1_0
+; O0-NEXT:    ldr q2, [x8, :lo12:.LCPI1_0]
+; O0-NEXT:    // implicit-def: $q0
+; O0-NEXT:    add v1.4s, v1.4s, v2.4s
+; O0-NEXT:    mov w8, v1.s[1]
+; O0-NEXT:    mov w9, w8
+; O0-NEXT:    mov w8, v1.s[2]
+; O0-NEXT:    // kill: def $x8 killed $w8
+; O0-NEXT:    // implicit-def: $q1
+; O0-NEXT:    fmov d1, x9
+; O0-NEXT:    mov v1.d[1], x8
+; O0-NEXT:    ret
 entry:
   %1 = add <4 x i32> %0, <i32 -4, i32 -8, i32 -12, i32 -16>
   %2 = extractelement <4 x i32> %1, i32 1
@@ -38,3 +66,51 @@ entry:
   %5 = insertelement <4 x i64> %4, i64 %zext2, i32 3
   ret <4 x i64> %5
 }
+
+; This issue was only triggered with -O0
+define i2 @issue_173722(<1 x i16> %call) {
+; O2-LABEL: issue_173722:
+; O2:       // %bb.0: // %entry
+; O2-NEXT:    mov w0, wzr
+; O2-NEXT:    ret
+;
+; O0-LABEL: issue_173722:
+; O0:       // %bb.0: // %entry
+; O0-NEXT:    sub sp, sp, #16
+; O0-NEXT:    .cfi_def_cfa_offset 16
+; O0-NEXT:    str d0, [sp, #8] // 8-byte Spill
+; O0-NEXT:    mov w8, #1 // =0x1
+; O0-NEXT:    cbnz w8, .LBB2_2
+; O0-NEXT:    b .LBB2_1
+; O0-NEXT:  .LBB2_1: // %cond.true
+; O0-NEXT:    ldr d1, [sp, #8] // 8-byte Reload
+; O0-NEXT:    // implicit-def: $q0
+; O0-NEXT:    fmov d0, d1
+; O0-NEXT:    umov w0, v0.h[0]
+; O0-NEXT:    str w0, [sp, #4] // 4-byte Spill
+; O0-NEXT:    b .LBB2_3
+; O0-NEXT:  .LBB2_2: // %cond.false
+; O0-NEXT:    mov w0, wzr
+; O0-NEXT:    str w0, [sp, #4] // 4-byte Spill
+; O0-NEXT:    b .LBB2_3
+; O0-NEXT:  .LBB2_3: // %cond.end
+; O0-NEXT:    ldr w0, [sp, #4] // 4-byte Reload
+; O0-NEXT:    add sp, sp, #16
+; O0-NEXT:    ret
+entry:
+  br i1 false, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %entry
+  %vecext = extractelement <1 x i16> %call, i32 0
+  %conv = trunc i16 %vecext to i2
+  br label %cond.end
+
+cond.false:                                       ; preds = %entry
+  %conv3 = zext i32 0 to i104
+  %conv4 = trunc i104 %conv3 to i2
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i2 [ %conv, %cond.true ], [ %conv4, %cond.false ]
+  ret i2 %cond
+}



More information about the llvm-commits mailing list