[llvm] [X86] Compute `CTLZ` using fp math for `v4i32` on SSE2 targets (PR #190930)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 26 05:18:40 PDT 2026


================
@@ -10870,6 +10870,49 @@ SDValue TargetLowering::expandCTLZ(SDNode *Node, SelectionDAG &DAG) const {
   return DAG.getNode(ISD::CTPOP, dl, VT, Op);
 }
 
+SDValue TargetLowering::expandCTLZWithFP(SDNode *Node,
+                                         SelectionDAG &DAG) const {
+  // pseudocode :
+  // v = v & ~(v >> 8)
+  // v = (f32)v
+  // v = bitcast<i32>(v)
+  // v = v >> 23
+  // v = 158 - v
+  // v = min(v, 32)
+
+  SDLoc dl(Node);
+  EVT VT = Node->getValueType(0);
+  SDValue Op = Node->getOperand(0);
+
+  EVT EltVT = VT.getVectorElementType();
+  if (EltVT != MVT::i32)
+    return SDValue();
+
+  EVT FloatVT = VT.changeVectorElementType(*DAG.getContext(), MVT::f32);
+  const fltSemantics &Sem = FloatVT.getVectorElementType().getFltSemantics();
+  unsigned BitWidth = EltVT.getSizeInBits();
+  unsigned MantissaBits = APFloat::semanticsPrecision(Sem);
+  unsigned ExponentBias = APFloat::semanticsMaxExponent(Sem);
+
+  // v = v & ~(v >> 8)
+  SDValue ShiftOp =
+      DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getShiftAmountConstant(8, VT, dl));
+  SDValue Tmp = DAG.getNode(ISD::AND, dl, VT, Op, DAG.getNOT(dl, ShiftOp, VT));
+
+  SDValue Float = DAG.getNode(ISD::SINT_TO_FP, dl, FloatVT, Tmp);
+  SDValue Int = DAG.getNode(ISD::BITCAST, dl, VT, Float);
+
+  SDValue ShiftExp =
+      DAG.getNode(ISD::SRL, dl, VT, Int,
+                  DAG.getShiftAmountConstant(MantissaBits - 1, VT, dl));
+  SDValue UndoBias = DAG.getNode(
+      ISD::USUBSAT, dl, VT,
----------------
def3r wrote:

Yes, the suggested impl https://stackoverflow.com/a/58827596 used `_mm256_subs_epu16` to undo the bias

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


More information about the llvm-commits mailing list