[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