[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