[llvm-branch-commits] [llvm] 724301d - Fix "Cannot select" crash on bitcast between f64 and int vector types (#201509)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jun 8 11:04:52 PDT 2026


Author: Abinaya Saravanan
Date: 2026-06-04T18:23:46Z
New Revision: 724301d98c6ef981111a077489358de10ec14127

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

LOG: Fix "Cannot select" crash on bitcast between f64 and int vector types (#201509)

All of i64, f64, v2i32, v4i16, v8i8 are assigned to the DoubleRegs
register class (64-bit register pairs). A bitcast between any two of
these types is a machine-level no-op (ie. the same physical register is
reinterpreted with a different type).

HexagonPatterns.td had NopCast_pat entries for all int-to-int bitcasts
within DoubleRegs, and explicit patterns for f64 <-> i64, but was
missing patterns for f64 <-> v2i32, f64 <-> v4i16, and f64 <-> v8i8. The
same gap existed in IntRegs for f32 <-> v2i16 and f32 <-> v4i8.

Without a tableGen pattern for "f64 = bitcast v2i32" node, the
instruction selector crashed with:

  LLVM ERROR: Cannot select: t26: f64 = bitcast t6
    t6: v2i32,ch = CopyFromReg t0, Register:v2i32 %2

Fix by adding the five missing NopCast_pat entries.

Fixes: https://github.com/llvm/llvm-project/issues/195495
(cherry picked from commit c005f737e764fab61a02ca5587cf43a16716b5fc)

Added: 
    llvm/test/CodeGen/Hexagon/bitcast-f64-vector.ll

Modified: 
    llvm/lib/Target/Hexagon/HexagonPatterns.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td
index f6d51acce562e..7d5e3feec6bbe 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatterns.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td
@@ -530,17 +530,22 @@ def: Pat<(i64 (bitconvert F64:$v)), (I64:$v)>;
 def: Pat<(f64 (bitconvert I64:$v)), (F64:$v)>;
 
 // Bit convert 32- and 64-bit types.
-// All of these are bitcastable to one another: i32, v2i16, v4i8.
+// All of these are bitcastable to one another: i32, f32, v2i16, v4i8.
 defm: NopCast_pat<i32,   v2i16, IntRegs>;
 defm: NopCast_pat<i32,    v4i8, IntRegs>;
 defm: NopCast_pat<v2i16,  v4i8, IntRegs>;
-// All of these are bitcastable to one another: i64, v2i32, v4i16, v8i8.
+defm: NopCast_pat<f32,   v2i16, IntRegs>;
+defm: NopCast_pat<f32,    v4i8, IntRegs>;
+// All of these are bitcastable to one another: i64, f64, v2i32, v4i16, v8i8.
 defm: NopCast_pat<i64,   v2i32, DoubleRegs>;
 defm: NopCast_pat<i64,   v4i16, DoubleRegs>;
 defm: NopCast_pat<i64,    v8i8, DoubleRegs>;
 defm: NopCast_pat<v2i32, v4i16, DoubleRegs>;
 defm: NopCast_pat<v2i32,  v8i8, DoubleRegs>;
 defm: NopCast_pat<v4i16,  v8i8, DoubleRegs>;
+defm: NopCast_pat<f64,   v2i32, DoubleRegs>;
+defm: NopCast_pat<f64,   v4i16, DoubleRegs>;
+defm: NopCast_pat<f64,    v8i8, DoubleRegs>;
 
 
 // --(3) Extend/truncate/saturate ----------------------------------------

diff  --git a/llvm/test/CodeGen/Hexagon/bitcast-f64-vector.ll b/llvm/test/CodeGen/Hexagon/bitcast-f64-vector.ll
new file mode 100644
index 0000000000000..172a3ab32e616
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/bitcast-f64-vector.ll
@@ -0,0 +1,63 @@
+; RUN: llc -mtriple=hexagon -mcpu=hexagonv68 -O3 < %s | FileCheck %s
+
+; Verify that bitcasts between f64 and the integer vector types that share the
+; DoubleRegs register class (v2i32, v4i16, v8i8) are treated as no-ops by the
+; instruction selector and do not cause a "Cannot select" crash.
+;
+; All of i64, f64, v2i32, v4i16, v8i8 live in DoubleRegs (64-bit register
+; pairs). A bitcast between any two of them is a pure reinterpretation of the
+; same 64 bits. Therefore no instruction is emitted.
+;
+; Regression test for: llvm.org/PR195495
+;   llc -mtriple=hexagon -mcpu=hexagonv68 -O3 crashed with
+;   "Cannot select: f64 = bitcast v2i32" when compiling Eigen's packetmath.
+
+; CHECK-LABEL: test_v2i32_to_f64:
+; CHECK: dfcmp
+; CHECK: jumpr r31
+define i1 @test_v2i32_to_f64(<2 x i32> %a) {
+  %bc = bitcast <2 x i32> %a to double
+  %cmp = fcmp une double %bc, 0.0
+  ret i1 %cmp
+}
+
+; f64->v2i32 is a no-op: the argument is already in a DoubleReg pair.
+; CHECK-LABEL: test_f64_to_v2i32:
+; CHECK-NOT: combine
+; CHECK: jumpr r31
+define <2 x i32> @test_f64_to_v2i32(double %a) {
+  %bc = bitcast double %a to <2 x i32>
+  ret <2 x i32> %bc
+}
+
+; CHECK-LABEL: test_v4i16_to_f64:
+; CHECK: dfcmp
+; CHECK: jumpr r31
+define i1 @test_v4i16_to_f64(<4 x i16> %a) {
+  %bc = bitcast <4 x i16> %a to double
+  %cmp = fcmp une double %bc, 0.0
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: test_v8i8_to_f64:
+; CHECK: dfcmp
+; CHECK: jumpr r31
+define i1 @test_v8i8_to_f64(<8 x i8> %a) {
+  %bc = bitcast <8 x i8> %a to double
+  %cmp = fcmp une double %bc, 0.0
+  ret i1 %cmp
+}
+
+; Regression test: the original crash.
+; <4 x i32> is passed in two v2i32 DoubleReg pairs; after type-legalizing
+; <2 x f64> setcc into two scalar f64 setcc ops, each f64 operand is produced
+; by a "f64 = bitcast v2i32" node that previously had no matching pattern.
+; CHECK-LABEL: test_packetmath_reduced:
+; CHECK: dfcmp
+; CHECK: jumpr r31
+define <2 x i1> @test_packetmath_reduced(<4 x i32> %arg) {
+entry:
+  %bc = bitcast <4 x i32> %arg to <2 x double>
+  %cmp = fcmp une <2 x double> %bc, zeroinitializer
+  ret <2 x i1> %cmp
+}


        


More information about the llvm-branch-commits mailing list