@@ -662,14 +662,15 @@ namespace {
662
662
bool DemandHighBits = true);
663
663
SDValue MatchBSwapHWord(SDNode *N, SDValue N0, SDValue N1);
664
664
SDValue MatchRotatePosNeg(SDValue Shifted, SDValue Pos, SDValue Neg,
665
- SDValue InnerPos, SDValue InnerNeg, bool HasPos ,
666
- unsigned PosOpcode , unsigned NegOpcode ,
667
- const SDLoc &DL);
665
+ SDValue InnerPos, SDValue InnerNeg, bool FromAdd ,
666
+ bool HasPos , unsigned PosOpcode ,
667
+ unsigned NegOpcode, const SDLoc &DL);
668
668
SDValue MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos, SDValue Neg,
669
- SDValue InnerPos, SDValue InnerNeg, bool HasPos,
670
- unsigned PosOpcode, unsigned NegOpcode,
671
- const SDLoc &DL);
672
- SDValue MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL);
669
+ SDValue InnerPos, SDValue InnerNeg, bool FromAdd,
670
+ bool HasPos, unsigned PosOpcode,
671
+ unsigned NegOpcode, const SDLoc &DL);
672
+ SDValue MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL,
673
+ bool FromAdd);
673
674
SDValue MatchLoadCombine(SDNode *N);
674
675
SDValue mergeTruncStores(StoreSDNode *N);
675
676
SDValue reduceLoadWidth(SDNode *N);
@@ -2992,6 +2993,9 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
2992
2993
if (SDValue V = foldAddSubOfSignBit(N, DL, DAG))
2993
2994
return V;
2994
2995
2996
+ if (SDValue V = MatchRotate(N0, N1, SDLoc(N), /*FromAdd=*/true))
2997
+ return V;
2998
+
2995
2999
// Try to match AVGFLOOR fixedwidth pattern
2996
3000
if (SDValue V = foldAddToAvg(N, DL))
2997
3001
return V;
@@ -8161,7 +8165,7 @@ SDValue DAGCombiner::visitOR(SDNode *N) {
8161
8165
return V;
8162
8166
8163
8167
// See if this is some rotate idiom.
8164
- if (SDValue Rot = MatchRotate(N0, N1, DL))
8168
+ if (SDValue Rot = MatchRotate(N0, N1, DL, /*FromAdd=*/false ))
8165
8169
return Rot;
8166
8170
8167
8171
if (SDValue Load = MatchLoadCombine(N))
@@ -8350,7 +8354,7 @@ static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift,
8350
8354
// The IsRotate flag should be set when the LHS of both shifts is the same.
8351
8355
// Otherwise if matching a general funnel shift, it should be clear.
8352
8356
static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize,
8353
- SelectionDAG &DAG, bool IsRotate) {
8357
+ SelectionDAG &DAG, bool IsRotate, bool FromAdd ) {
8354
8358
const auto &TLI = DAG.getTargetLoweringInfo();
8355
8359
// If EltSize is a power of 2 then:
8356
8360
//
@@ -8389,7 +8393,7 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize,
8389
8393
// NOTE: We can only do this when matching operations which won't modify the
8390
8394
// least Log2(EltSize) significant bits and not a general funnel shift.
8391
8395
unsigned MaskLoBits = 0;
8392
- if (IsRotate && isPowerOf2_64(EltSize)) {
8396
+ if (IsRotate && !FromAdd && isPowerOf2_64(EltSize)) {
8393
8397
unsigned Bits = Log2_64(EltSize);
8394
8398
unsigned NegBits = Neg.getScalarValueSizeInBits();
8395
8399
if (NegBits >= Bits) {
@@ -8472,9 +8476,9 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize,
8472
8476
// Neg with outer conversions stripped away.
8473
8477
SDValue DAGCombiner::MatchRotatePosNeg(SDValue Shifted, SDValue Pos,
8474
8478
SDValue Neg, SDValue InnerPos,
8475
- SDValue InnerNeg, bool HasPos ,
8476
- unsigned PosOpcode , unsigned NegOpcode ,
8477
- const SDLoc &DL) {
8479
+ SDValue InnerNeg, bool FromAdd ,
8480
+ bool HasPos , unsigned PosOpcode ,
8481
+ unsigned NegOpcode, const SDLoc &DL) {
8478
8482
// fold (or (shl x, (*ext y)),
8479
8483
// (srl x, (*ext (sub 32, y)))) ->
8480
8484
// (rotl x, y) or (rotr x, (sub 32, y))
@@ -8484,10 +8488,9 @@ SDValue DAGCombiner::MatchRotatePosNeg(SDValue Shifted, SDValue Pos,
8484
8488
// (rotr x, y) or (rotl x, (sub 32, y))
8485
8489
EVT VT = Shifted.getValueType();
8486
8490
if (matchRotateSub(InnerPos, InnerNeg, VT.getScalarSizeInBits(), DAG,
8487
- /*IsRotate*/ true)) {
8491
+ /*IsRotate*/ true, FromAdd))
8488
8492
return DAG.getNode(HasPos ? PosOpcode : NegOpcode, DL, VT, Shifted,
8489
8493
HasPos ? Pos : Neg);
8490
- }
8491
8494
8492
8495
return SDValue();
8493
8496
}
@@ -8500,9 +8503,9 @@ SDValue DAGCombiner::MatchRotatePosNeg(SDValue Shifted, SDValue Pos,
8500
8503
// TODO: Merge with MatchRotatePosNeg.
8501
8504
SDValue DAGCombiner::MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos,
8502
8505
SDValue Neg, SDValue InnerPos,
8503
- SDValue InnerNeg, bool HasPos ,
8504
- unsigned PosOpcode , unsigned NegOpcode ,
8505
- const SDLoc &DL) {
8506
+ SDValue InnerNeg, bool FromAdd ,
8507
+ bool HasPos , unsigned PosOpcode ,
8508
+ unsigned NegOpcode, const SDLoc &DL) {
8506
8509
EVT VT = N0.getValueType();
8507
8510
unsigned EltBits = VT.getScalarSizeInBits();
8508
8511
@@ -8513,10 +8516,10 @@ SDValue DAGCombiner::MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos,
8513
8516
// fold (or (shl x0, (*ext (sub 32, y))),
8514
8517
// (srl x1, (*ext y))) ->
8515
8518
// (fshr x0, x1, y) or (fshl x0, x1, (sub 32, y))
8516
- if (matchRotateSub(InnerPos, InnerNeg, EltBits, DAG, /*IsRotate*/ N0 == N1)) {
8519
+ if (matchRotateSub(InnerPos, InnerNeg, EltBits, DAG, /*IsRotate*/ N0 == N1,
8520
+ FromAdd))
8517
8521
return DAG.getNode(HasPos ? PosOpcode : NegOpcode, DL, VT, N0, N1,
8518
8522
HasPos ? Pos : Neg);
8519
- }
8520
8523
8521
8524
// Matching the shift+xor cases, we can't easily use the xor'd shift amount
8522
8525
// so for now just use the PosOpcode case if its legal.
@@ -8561,11 +8564,12 @@ SDValue DAGCombiner::MatchFunnelPosNeg(SDValue N0, SDValue N1, SDValue Pos,
8561
8564
return SDValue();
8562
8565
}
8563
8566
8564
- // MatchRotate - Handle an 'or' of two operands. If this is one of the many
8565
- // idioms for rotate, and if the target supports rotation instructions, generate
8566
- // a rot[lr]. This also matches funnel shift patterns, similar to rotation but
8567
- // with different shifted sources.
8568
- SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
8567
+ // MatchRotate - Handle an 'or' or 'add' of two operands. If this is one of the
8568
+ // many idioms for rotate, and if the target supports rotation instructions,
8569
+ // generate a rot[lr]. This also matches funnel shift patterns, similar to
8570
+ // rotation but with different shifted sources.
8571
+ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL,
8572
+ bool FromAdd) {
8569
8573
EVT VT = LHS.getValueType();
8570
8574
8571
8575
// The target must have at least one rotate/funnel flavor.
@@ -8592,9 +8596,9 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
8592
8596
if (LHS.getOpcode() == ISD::TRUNCATE && RHS.getOpcode() == ISD::TRUNCATE &&
8593
8597
LHS.getOperand(0).getValueType() == RHS.getOperand(0).getValueType()) {
8594
8598
assert(LHS.getValueType() == RHS.getValueType());
8595
- if (SDValue Rot = MatchRotate(LHS.getOperand(0), RHS.getOperand(0), DL)) {
8599
+ if (SDValue Rot =
8600
+ MatchRotate(LHS.getOperand(0), RHS.getOperand(0), DL, FromAdd))
8596
8601
return DAG.getNode(ISD::TRUNCATE, SDLoc(LHS), LHS.getValueType(), Rot);
8597
- }
8598
8602
}
8599
8603
8600
8604
// Match "(X shl/srl V1) & V2" where V2 may not be present.
@@ -8774,29 +8778,25 @@ SDValue DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, const SDLoc &DL) {
8774
8778
}
8775
8779
8776
8780
if (IsRotate && (HasROTL || HasROTR)) {
8777
- SDValue TryL =
8778
- MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt, LExtOp0,
8779
- RExtOp0, HasROTL, ISD::ROTL, ISD::ROTR, DL);
8780
- if (TryL)
8781
+ if (SDValue TryL = MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt,
8782
+ LExtOp0, RExtOp0, FromAdd, HasROTL,
8783
+ ISD::ROTL, ISD::ROTR, DL))
8781
8784
return TryL;
8782
8785
8783
- SDValue TryR =
8784
- MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt, RExtOp0,
8785
- LExtOp0, HasROTR, ISD::ROTR, ISD::ROTL, DL);
8786
- if (TryR)
8786
+ if (SDValue TryR = MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
8787
+ RExtOp0, LExtOp0, FromAdd, HasROTR,
8788
+ ISD::ROTR, ISD::ROTL, DL))
8787
8789
return TryR;
8788
8790
}
8789
8791
8790
- SDValue TryL =
8791
- MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt, RHSShiftAmt,
8792
- LExtOp0, RExtOp0, HasFSHL, ISD::FSHL, ISD::FSHR, DL);
8793
- if (TryL)
8792
+ if (SDValue TryL = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt,
8793
+ RHSShiftAmt, LExtOp0, RExtOp0, FromAdd,
8794
+ HasFSHL, ISD::FSHL, ISD::FSHR, DL))
8794
8795
return TryL;
8795
8796
8796
- SDValue TryR =
8797
- MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
8798
- RExtOp0, LExtOp0, HasFSHR, ISD::FSHR, ISD::FSHL, DL);
8799
- if (TryR)
8797
+ if (SDValue TryR = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt,
8798
+ LHSShiftAmt, RExtOp0, LExtOp0, FromAdd,
8799
+ HasFSHR, ISD::FSHR, ISD::FSHL, DL))
8800
8800
return TryR;
8801
8801
8802
8802
return SDValue();
0 commit comments