[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