[llvm] [X86] Keep scalar bf16/f16 selects in vector registers (PR #224218)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 6 04:42:42 PDT 2026


================
@@ -48981,6 +48981,81 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
   bool CondConstantVector = ISD::isBuildVectorOfConstantSDNodes(Cond.getNode());
   unsigned EltBitWidth = VT.getScalarSizeInBits();
 
+  // Soft bf16/f16 scalar selects do a VSELECT in vector registers instead
+  // of a scalar CMOV, to avoid a GPR round-trip. Skip constant operands
+  // (cheaper as immediates) and compare-driven conds (CMOV already reuses
+  // the flags).
+  if (N->getOpcode() == ISD::SELECT && !CondVT.isVector() &&
+      Subtarget.hasSSE2() && !isIntOrFPConstant(LHS) &&
+      !isIntOrFPConstant(RHS)) {
+    // Only worth it if both operands already live in a vector register
+    auto IsBitcastFromGPR = [](SDValue Op) {
+      return Op.getOpcode() == ISD::BITCAST &&
+             Op.getOperand(0).getValueType().isScalarInteger();
+    };
+    SDValue F16LHS, F16RHS;
+    if (!VT.isVector() && isSoftF16(VT, Subtarget)) {
+      if (!IsBitcastFromGPR(LHS) || !IsBitcastFromGPR(RHS)) {
+        F16LHS = DAG.getBitcast(MVT::f16, LHS);
+        F16RHS = DAG.getBitcast(MVT::f16, RHS);
+      }
+    } else if (VT == MVT::i16 && LHS.getOpcode() == ISD::BITCAST &&
+               RHS.getOpcode() == ISD::BITCAST) {
+      MVT SVT = LHS.getOperand(0).getSimpleValueType();
+      if ((SVT == MVT::f16 || SVT == MVT::bf16) &&
+          SVT == RHS.getOperand(0).getSimpleValueType()) {
+        F16LHS = DAG.getBitcast(MVT::f16, LHS.getOperand(0));
+        F16RHS = DAG.getBitcast(MVT::f16, RHS.getOperand(0));
+      }
+    }
+
+    SDValue CondRoot = Cond;
+    while (CondRoot.getOpcode() == ISD::AND ||
----------------
RKSimon wrote:

Maybe tweak this into a IsFromSetCC helper?
```
auto IsFromSetCC = [](SDValue Cond) {
  while (Cond.getOpcode() == ISD::AND ||
         Cond.getOpcode() == ISD::ANY_EXTEND ||
         Cond.getOpcode() == ISD::ZERO_EXTEND ||
         Cond.getOpcode() == ISD::TRUNCATE)
      Cond = Cond.getOperand(0);
  return Cond.getOpcode() == ISD::SETCC || Cond.getOpcode() == X86ISD::SETCC;
}
if (F16LHS && !IsFromSetCC (Cond)) {
```
Maybe I'm just paranoid that CondRoot is going to get used by something....

https://github.com/llvm/llvm-project/pull/224218


More information about the llvm-commits mailing list