Skip to content

Commit 1ebd4a2

Browse files
committed
[DAGCombiner] widen any_ext of popcount based on target support
This enhances D69127 (rGe6c145e0548e3b3de6eab27e44e1504387cf6b53) to handle the looser "any_extend" cast in addition to zext. This is a prerequisite step for canonicalizing in the other direction (narrow the popcount) in IR - PR43688: https://bugs.llvm.org/show_bug.cgi?id=43688
1 parent 35cb3ee commit 1ebd4a2

File tree

3 files changed

+36
-19
lines changed

3 files changed

+36
-19
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9673,6 +9673,29 @@ static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op,
96739673
return (Known.Zero | 1).isAllOnesValue();
96749674
}
96759675

9676+
/// Given an extending node with a pop-count operand, if the target does not
9677+
/// support a pop-count in the narrow source type but does support it in the
9678+
/// destination type, widen the pop-count to the destination type.
9679+
static SDValue widenCtPop(SDNode *Extend, SelectionDAG &DAG) {
9680+
assert((Extend->getOpcode() == ISD::ZERO_EXTEND ||
9681+
Extend->getOpcode() == ISD::ANY_EXTEND) && "Expected extend op");
9682+
9683+
SDValue CtPop = Extend->getOperand(0);
9684+
if (CtPop.getOpcode() != ISD::CTPOP || !CtPop.hasOneUse())
9685+
return SDValue();
9686+
9687+
EVT VT = Extend->getValueType(0);
9688+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
9689+
if (TLI.isOperationLegalOrCustom(ISD::CTPOP, CtPop.getValueType()) ||
9690+
!TLI.isOperationLegalOrCustom(ISD::CTPOP, VT))
9691+
return SDValue();
9692+
9693+
// zext (ctpop X) --> ctpop (zext X)
9694+
SDLoc DL(Extend);
9695+
SDValue NewZext = DAG.getZExtOrTrunc(CtPop.getOperand(0), DL, VT);
9696+
return DAG.getNode(ISD::CTPOP, DL, VT, NewZext);
9697+
}
9698+
96769699
SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
96779700
SDValue N0 = N->getOperand(0);
96789701
EVT VT = N->getValueType(0);
@@ -9923,17 +9946,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
99239946
if (SDValue NewVSel = matchVSelectOpSizesWithSetCC(N))
99249947
return NewVSel;
99259948

9926-
// If the target does not support a pop-count in the narrow source type but
9927-
// does support it in the destination type, widen the pop-count to this type:
9928-
// zext (ctpop X) --> ctpop (zext X)
9929-
// TODO: Generalize this to handle starting from anyext.
9930-
if (N0.getOpcode() == ISD::CTPOP && N0.hasOneUse() &&
9931-
!TLI.isOperationLegalOrCustom(ISD::CTPOP, N0.getValueType()) &&
9932-
TLI.isOperationLegalOrCustom(ISD::CTPOP, VT)) {
9933-
SDLoc DL(N);
9934-
SDValue NewZext = DAG.getZExtOrTrunc(N0.getOperand(0), DL, VT);
9935-
return DAG.getNode(ISD::CTPOP, DL, VT, NewZext);
9936-
}
9949+
if (SDValue NewCtPop = widenCtPop(N, DAG))
9950+
return NewCtPop;
99379951

99389952
return SDValue();
99399953
}
@@ -10081,6 +10095,9 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
1008110095
return SCC;
1008210096
}
1008310097

10098+
if (SDValue NewCtPop = widenCtPop(N, DAG))
10099+
return NewCtPop;
10100+
1008410101
return SDValue();
1008510102
}
1008610103

llvm/test/CodeGen/PowerPC/popcnt-zext.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
define i16 @zpop_i8_i16(i8 %x) {
66
; FAST-LABEL: zpop_i8_i16:
77
; FAST: # %bb.0:
8-
; FAST-NEXT: rlwinm 3, 3, 0, 24, 31
9-
; FAST-NEXT: popcntw 3, 3
8+
; FAST-NEXT: clrldi 3, 3, 56
9+
; FAST-NEXT: popcntd 3, 3
1010
; FAST-NEXT: blr
1111
;
1212
; SLOW-LABEL: zpop_i8_i16:
@@ -297,8 +297,8 @@ define i64 @popz_i32_i64(i32 %x) {
297297
define i64 @popa_i16_i64(i16 %x) {
298298
; FAST-LABEL: popa_i16_i64:
299299
; FAST: # %bb.0:
300-
; FAST-NEXT: rlwinm 3, 3, 0, 16, 31
301-
; FAST-NEXT: popcntw 3, 3
300+
; FAST-NEXT: clrldi 3, 3, 48
301+
; FAST-NEXT: popcntd 3, 3
302302
; FAST-NEXT: andi. 3, 3, 16
303303
; FAST-NEXT: blr
304304
;

llvm/test/CodeGen/PowerPC/popcnt.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ define i8 @cnt8(i8 %x) nounwind readnone {
88
%cnt = tail call i8 @llvm.ctpop.i8(i8 %x)
99
ret i8 %cnt
1010
; CHECK-LABEL: @cnt8
11-
; CHECK: rlwinm
12-
; CHECK: popcntw
11+
; CHECK: clrldi
12+
; CHECK: popcntd
1313
; CHECK: blr
1414

1515
; SLOWPC-LABEL: @cnt8
@@ -20,8 +20,8 @@ define i16 @cnt16(i16 %x) nounwind readnone {
2020
%cnt = tail call i16 @llvm.ctpop.i16(i16 %x)
2121
ret i16 %cnt
2222
; CHECK-LABEL: @cnt16
23-
; CHECK: rlwinm
24-
; CHECK: popcntw
23+
; CHECK: clrldi
24+
; CHECK: popcntd
2525
; CHECK: blr
2626

2727
; SLOWPC-LABEL: @cnt16

0 commit comments

Comments
 (0)