Skip to content

Commit 888726d

Browse files
committed
[SDAG] Use shifts if ISD::MUL is illegal when lowering ISD::CTPOP/ISD::VP_CTPOP
We can avoid libcalls. Fixes #86205
1 parent 5b544b5 commit 888726d

File tree

11 files changed

+889
-1289
lines changed

11 files changed

+889
-1289
lines changed

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8710,11 +8710,19 @@ SDValue TargetLowering::expandCTPOP(SDNode *Node, SelectionDAG &DAG) const {
87108710
}
87118711

87128712
// v = (v * 0x01010101...) >> (Len - 8)
8713-
SDValue Mask01 =
8714-
DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
8715-
return DAG.getNode(ISD::SRL, dl, VT,
8716-
DAG.getNode(ISD::MUL, dl, VT, Op, Mask01),
8717-
DAG.getConstant(Len - 8, dl, ShVT));
8713+
SDValue V;
8714+
if (isOperationLegalOrCustomOrPromote(ISD::MUL, VT)) {
8715+
SDValue Mask01 =
8716+
DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
8717+
V = DAG.getNode(ISD::MUL, dl, VT, Op, Mask01);
8718+
} else {
8719+
V = Op;
8720+
for (unsigned Shift = 8; Shift < Len; Shift *= 2)
8721+
V = DAG.getNode(ISD::ADD, dl, VT, V,
8722+
DAG.getNode(ISD::SHL, dl, VT, V,
8723+
DAG.getShiftAmountConstant(Shift, VT, dl)));
8724+
}
8725+
return DAG.getNode(ISD::SRL, dl, VT, V, DAG.getConstant(Len - 8, dl, ShVT));
87188726
}
87198727

87208728
SDValue TargetLowering::expandVPCTPOP(SDNode *Node, SelectionDAG &DAG) const {
@@ -8767,10 +8775,21 @@ SDValue TargetLowering::expandVPCTPOP(SDNode *Node, SelectionDAG &DAG) const {
87678775
return Op;
87688776

87698777
// v = (v * 0x01010101...) >> (Len - 8)
8770-
SDValue Mask01 =
8771-
DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
8772-
return DAG.getNode(ISD::VP_LSHR, dl, VT,
8773-
DAG.getNode(ISD::VP_MUL, dl, VT, Op, Mask01, Mask, VL),
8778+
SDValue V;
8779+
if (isOperationLegalOrCustomOrPromote(ISD::VP_MUL, VT)) {
8780+
SDValue Mask01 =
8781+
DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT);
8782+
V = DAG.getNode(ISD::VP_MUL, dl, VT, Op, Mask01, Mask, VL);
8783+
} else {
8784+
V = Op;
8785+
for (unsigned Shift = 8; Shift < Len; Shift *= 2)
8786+
V = DAG.getNode(ISD::VP_ADD, dl, VT, V,
8787+
DAG.getNode(ISD::VP_SHL, dl, VT, V,
8788+
DAG.getShiftAmountConstant(Shift, VT, dl),
8789+
Mask, VL),
8790+
Mask, VL);
8791+
}
8792+
return DAG.getNode(ISD::VP_LSHR, dl, VT, V,
87748793
DAG.getConstant(Len - 8, dl, ShVT), Mask, VL);
87758794
}
87768795

llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,11 @@ define i32 @test_ctpop_i32(i32 %a) nounwind {
285285
; LA64-NEXT: lu12i.w $a1, 61680
286286
; LA64-NEXT: ori $a1, $a1, 3855
287287
; LA64-NEXT: and $a0, $a0, $a1
288-
; LA64-NEXT: lu12i.w $a1, 4112
289-
; LA64-NEXT: ori $a1, $a1, 257
290-
; LA64-NEXT: mul.d $a0, $a0, $a1
291-
; LA64-NEXT: bstrpick.d $a0, $a0, 31, 24
288+
; LA64-NEXT: slli.d $a1, $a0, 8
289+
; LA64-NEXT: add.d $a0, $a0, $a1
290+
; LA64-NEXT: slli.d $a1, $a0, 16
291+
; LA64-NEXT: add.d $a0, $a0, $a1
292+
; LA64-NEXT: bstrpick.d $a0, $a0, 29, 24
292293
; LA64-NEXT: ret
293294
%1 = call i32 @llvm.ctpop.i32(i32 %a)
294295
ret i32 %1

0 commit comments

Comments
 (0)