[llvm] [X86] Fix `"Cannot select"` for `bf16` vector selects on a scalar condition under `AVX10.2` (PR #222854)
Akash Manna via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 23:33:09 PDT 2026
https://github.com/akash-manna-sky created https://github.com/llvm/llvm-project/pull/222854
Fixes #222673
A `select i1 %c, <8 x bfloat> %a, <8 x bfloat> %b` failed instruction selection with `+avx10.2-512` on a `v8bf16 X86ISD::CMOV`. Selects on a scalar condition are lowered to the `CMOV_VR*` pseudos and expanded to a branch, but those pseudos only have patterns for integer and f16 vectors. Before #101603 bf16 vectors were treated as "soft" everywhere, so `LowerSELECT` bitcast them to `v8i16` first and never produced a bf16 CMOV. That PR made bf16 non-soft under AVX10.2 to enable native arithmetic, which silently removed the only bf16-aware path in `LowerSELECT` without adding a replacement. `v16bf16` and `v32bf16` hit the same thing.
`LowerSELECT` now takes the integer-bitcast path for every bf16 vector, using the existing `isBF16orSoftF16` helper, so the select is lowered exactly as it is on every other bf16 target and as `v8f16` is on FP16 targets. Scalar `bf16` is soft-promoted to `f32` before lowering, so it is unaffected. Added `pseudo_cmov_lower-bf16.ll` alongside the f16 sibling, covering the reproducer plus `v8/v16/v32bf16` on both `+avx512bf16,+avx512vl` and `+avx10.2-512`.
>From ab65a53c464e07ddcd4ddbf6c5438d2743bb7e89 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Fri, 11 Sep 2026 12:01:10 +0530
Subject: [PATCH] [X86] Fix "Cannot select" for bf16 vector selects on a scalar
condition under AVX10.2
Since bf16 vectors stopped being "soft" under AVX10.2, LowerSELECT no
longer bitcast them to integer vectors, so a select on a scalar i1 fell
through to an X86ISD::CMOV typed v8bf16, which has no CMOV pseudo
pattern. Route all bf16 vectors through the integer path, matching every
other bf16 target.
Fixes #222673
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 3 +-
.../CodeGen/X86/pseudo_cmov_lower-bf16.ll | 48 +++++++++++++++++++
2 files changed, 50 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/X86/pseudo_cmov_lower-bf16.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index a41cb2914660c..b3cb882898e43 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -25794,7 +25794,8 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
MVT VT = Op1.getSimpleValueType();
SDValue CC;
- if (isSoftF16(VT, Subtarget)) {
+ // Select bf16 vectors as integers; there are no bf16 CMOV pseudos.
+ if (isBF16orSoftF16(VT, Subtarget)) {
MVT NVT = VT.changeTypeToInteger();
return DAG.getBitcast(VT, DAG.getNode(ISD::SELECT, DL, NVT, Cond,
DAG.getBitcast(NVT, Op1),
diff --git a/llvm/test/CodeGen/X86/pseudo_cmov_lower-bf16.ll b/llvm/test/CodeGen/X86/pseudo_cmov_lower-bf16.ll
new file mode 100644
index 0000000000000..77c0c578336c9
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pseudo_cmov_lower-bf16.ll
@@ -0,0 +1,48 @@
+; RUN: llc < %s -mtriple=x86_64 -mattr=+avx512bf16,+avx512vl | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64 -mattr=+avx10.2-512 | FileCheck %s
+
+; https://github.com/llvm/llvm-project/issues/222673
+; CHECK-LABEL: pr222673:
+; CHECK: testb $1, %dil
+; CHECK-NEXT: jne
+; CHECK-NOT: jne
+define <8 x bfloat> @pr222673(i1 %0) {
+ %2 = select i1 %0, <8 x bfloat> splat (bfloat 1.000000e+00), <8 x bfloat> zeroinitializer
+ ret <8 x bfloat> %2
+}
+
+; CHECK-LABEL: select_v8bf16:
+; CHECK: jne
+; CHECK-NOT: jne
+define <8 x bfloat> @select_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b, i1 zeroext %sign) {
+ %sel = select i1 %sign, <8 x bfloat> %a, <8 x bfloat> %b
+ ret <8 x bfloat> %sel
+}
+
+; CHECK-LABEL: select_v16bf16:
+; CHECK: jne
+; CHECK-NOT: jne
+define <16 x bfloat> @select_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b, i1 zeroext %sign) {
+ %sel = select i1 %sign, <16 x bfloat> %a, <16 x bfloat> %b
+ ret <16 x bfloat> %sel
+}
+
+; CHECK-LABEL: select_v32bf16:
+; CHECK: jne
+; CHECK-NOT: jne
+define <32 x bfloat> @select_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b, i1 zeroext %sign) {
+ %sel = select i1 %sign, <32 x bfloat> %a, <32 x bfloat> %b
+ ret <32 x bfloat> %sel
+}
+
+; Both selects share one condition, so only one branch should remain.
+; CHECK-LABEL: select_v8bf16_chain:
+; CHECK: je
+; CHECK-NOT: je
+define <8 x bfloat> @select_v8bf16_chain(i32 %v1, <8 x bfloat> %v2, <8 x bfloat> %v3, <8 x bfloat> %v4) {
+ %cmp = icmp eq i32 %v1, 0
+ %t1 = select i1 %cmp, <8 x bfloat> %v2, <8 x bfloat> %v3
+ %t2 = select i1 %cmp, <8 x bfloat> %v3, <8 x bfloat> %v4
+ %sub = fsub <8 x bfloat> %t1, %t2
+ ret <8 x bfloat> %sub
+}
More information about the llvm-commits
mailing list