Skip to content

Commit 5641804

Browse files
committed
[DAG] MatchRotate - Add funnel shift by variable support
Followup to D75114, this patch reuses the existing MatchRotate ROTL/ROTR rotation pattern code to also recognize the more general FSHL/FSHR funnel shift patterns when we have variable shift amounts, matched with MatchFunnelPosNeg which acts in an (almost) equivalent manner to MatchRotatePosNeg.
1 parent 650f363 commit 5641804

File tree

5 files changed

+303
-377
lines changed

5 files changed

+303
-377
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,10 @@ namespace {
555555
SDValue InnerPos, SDValue InnerNeg,
556556
unsigned PosOpcode, unsigned NegOpcode,
557557
const SDLoc &DL);
558+
SDValue MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos, SDValue Neg,
559+
SDValue InnerPos, SDValue InnerNeg,
560+
unsigned PosOpcode, unsigned NegOpcode,
561+
const SDLoc &DL);
558562
SDValue MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL);
559563
SDValue MatchLoadCombine(SDNode *N);
560564
SDValue MatchStoreCombine(StoreSDNode *N);
@@ -6319,6 +6323,33 @@ SDValue DAGCombiner::MatchRotatePosNeg(SDValue Shifted, SDValue Pos,
63196323
return SDValue();
63206324
}
63216325

6326+
// A subroutine of MatchRotate used once we have found an OR of two opposite
6327+
// shifts of N0 + N1. If Neg == <operand size> - Pos then the OR reduces
6328+
// to both (PosOpcode N0, N1, Pos) and (NegOpcode N0, N1, Neg), with the
6329+
// former being preferred if supported. InnerPos and InnerNeg are Pos and
6330+
// Neg with outer conversions stripped away.
6331+
// TODO: Merge with MatchRotatePosNeg.
6332+
SDValue DAGCombiner::MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos,
6333+
SDValue Neg, SDValue InnerPos,
6334+
SDValue InnerNeg, unsigned PosOpcode,
6335+
unsigned NegOpcode, const SDLoc &DL) {
6336+
// fold (or (shl x0, (*ext y)),
6337+
// (srl x1, (*ext (sub 32, y)))) ->
6338+
// (fshl x0, x1, y) or (fshr x0, x1, (sub 32, y))
6339+
//
6340+
// fold (or (shl x0, (*ext (sub 32, y))),
6341+
// (srl x1, (*ext y))) ->
6342+
// (fshr x0, x1, y) or (fshl x0, x1, (sub 32, y))
6343+
EVT VT = N0.getValueType();
6344+
if (matchRotateSub(InnerPos, InnerNeg, VT.getScalarSizeInBits(), DAG)) {
6345+
bool HasPos = TLI.isOperationLegalOrCustom(PosOpcode, VT);
6346+
return DAG.getNode(HasPos ? PosOpcode : NegOpcode, DL, VT, N0, N1,
6347+
HasPos ? Pos : Neg);
6348+
}
6349+
6350+
return SDValue();
6351+
}
6352+
63226353
// MatchRotate - Handle an 'or' of two operands. If this is one of the many
63236354
// idioms for rotate, and if the target supports rotation instructions, generate
63246355
// a rot[lr]. This also matches funnel shift patterns, similar to rotation but
@@ -6444,10 +6475,6 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
64446475
return Res;
64456476
}
64466477

6447-
// TODO: Handle variable funnel shifts.
6448-
if (!IsRotate)
6449-
return SDValue();
6450-
64516478
// If there is a mask here, and we have a variable shift, we can't be sure
64526479
// that we're masking out the right stuff.
64536480
if (LHSMask.getNode() || RHSMask.getNode())
@@ -6468,13 +6495,29 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
64686495
RExtOp0 = RHSShiftAmt.getOperand(0);
64696496
}
64706497

6471-
SDValue TryL = MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt,
6472-
LExtOp0, RExtOp0, ISD::ROTL, ISD::ROTR, DL);
6498+
if (IsRotate && (HasROTL || HasROTR)) {
6499+
SDValue TryL =
6500+
MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt, LExtOp0,
6501+
RExtOp0, ISD::ROTL, ISD::ROTR, DL);
6502+
if (TryL)
6503+
return TryL;
6504+
6505+
SDValue TryR =
6506+
MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt, RExtOp0,
6507+
LExtOp0, ISD::ROTR, ISD::ROTL, DL);
6508+
if (TryR)
6509+
return TryR;
6510+
}
6511+
6512+
SDValue TryL =
6513+
MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt, RHSShiftAmt,
6514+
LExtOp0, RExtOp0, ISD::FSHL, ISD::FSHR, DL);
64736515
if (TryL)
64746516
return TryL;
64756517

6476-
SDValue TryR = MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
6477-
RExtOp0, LExtOp0, ISD::ROTR, ISD::ROTL, DL);
6518+
SDValue TryR =
6519+
MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
6520+
RExtOp0, LExtOp0, ISD::FSHR, ISD::FSHL, DL);
64786521
if (TryR)
64796522
return TryR;
64806523

0 commit comments

Comments
 (0)