@@ -337,6 +337,7 @@ namespace {
337
337
SDValue visitShiftByConstant(SDNode *N, ConstantSDNode *Amt);
338
338
339
339
SDValue foldSelectOfConstants(SDNode *N);
340
+ SDValue foldBinOpIntoSelect(SDNode *BO);
340
341
bool SimplifySelectOps(SDNode *SELECT, SDValue LHS, SDValue RHS);
341
342
SDValue SimplifyBinOpWithSameOpcodeHands(SDNode *N);
342
343
SDValue SimplifySelect(const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2);
@@ -1747,6 +1748,59 @@ static ConstantSDNode *getAsNonOpaqueConstant(SDValue N) {
1747
1748
return Const != nullptr && !Const->isOpaque() ? Const : nullptr;
1748
1749
}
1749
1750
1751
+ SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) {
1752
+ auto BinOpcode = BO->getOpcode();
1753
+ assert((BinOpcode == ISD::ADD || BinOpcode == ISD::SUB ||
1754
+ BinOpcode == ISD::MUL || BinOpcode == ISD::SDIV ||
1755
+ BinOpcode == ISD::UDIV || BinOpcode == ISD::SREM ||
1756
+ BinOpcode == ISD::UREM || BinOpcode == ISD::AND ||
1757
+ BinOpcode == ISD::OR || BinOpcode == ISD::XOR ||
1758
+ BinOpcode == ISD::SHL || BinOpcode == ISD::SRL ||
1759
+ BinOpcode == ISD::SRA || BinOpcode == ISD::FADD ||
1760
+ BinOpcode == ISD::FSUB || BinOpcode == ISD::FMUL ||
1761
+ BinOpcode == ISD::FDIV || BinOpcode == ISD::FREM) &&
1762
+ "Unexpected binary operator");
1763
+
1764
+ SDValue C1 = BO->getOperand(1);
1765
+ if (!isConstantOrConstantVector(C1) &&
1766
+ !isConstantFPBuildVectorOrConstantFP(C1))
1767
+ return SDValue();
1768
+
1769
+ // Don't do this unless the old select is going away. We want to eliminate the
1770
+ // binary operator, not replace a binop with a select.
1771
+ // TODO: Handle ISD::SELECT_CC.
1772
+ SDValue Sel = BO->getOperand(0);
1773
+ if (Sel.getOpcode() != ISD::SELECT || !Sel.hasOneUse())
1774
+ return SDValue();
1775
+
1776
+ SDValue CT = Sel.getOperand(1);
1777
+ if (!isConstantOrConstantVector(CT) &&
1778
+ !isConstantFPBuildVectorOrConstantFP(CT))
1779
+ return SDValue();
1780
+
1781
+ SDValue CF = Sel.getOperand(2);
1782
+ if (!isConstantOrConstantVector(CF) &&
1783
+ !isConstantFPBuildVectorOrConstantFP(CF))
1784
+ return SDValue();
1785
+
1786
+ // We have a select-of-constants followed by a binary operator with a
1787
+ // constant. Eliminate the binop by pulling the constant math into the select.
1788
+ // Example: add (select Cond, CT, CF), C1 --> select Cond, CT + C1, CF + C1
1789
+ EVT VT = Sel.getValueType();
1790
+ SDLoc DL(Sel);
1791
+ SDValue NewCT = DAG.getNode(BinOpcode, DL, VT, CT, C1);
1792
+ assert((isConstantOrConstantVector(NewCT) ||
1793
+ isConstantFPBuildVectorOrConstantFP(NewCT)) &&
1794
+ "Failed to constant fold a binop with constant operands");
1795
+
1796
+ SDValue NewCF = DAG.getNode(BinOpcode, DL, VT, CF, C1);
1797
+ assert((isConstantOrConstantVector(NewCF) ||
1798
+ isConstantFPBuildVectorOrConstantFP(NewCF)) &&
1799
+ "Failed to constant fold a binop with constant operands");
1800
+
1801
+ return DAG.getSelect(DL, VT, Sel.getOperand(0), NewCT, NewCF);
1802
+ }
1803
+
1750
1804
SDValue DAGCombiner::visitADD(SDNode *N) {
1751
1805
SDValue N0 = N->getOperand(0);
1752
1806
SDValue N1 = N->getOperand(1);
@@ -1795,6 +1849,9 @@ SDValue DAGCombiner::visitADD(SDNode *N) {
1795
1849
}
1796
1850
}
1797
1851
1852
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
1853
+ return NewSel;
1854
+
1798
1855
// reassociate add
1799
1856
if (SDValue RADD = ReassociateOps(ISD::ADD, DL, N0, N1))
1800
1857
return RADD;
@@ -1999,6 +2056,9 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
1999
2056
N1.getNode());
2000
2057
}
2001
2058
2059
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
2060
+ return NewSel;
2061
+
2002
2062
ConstantSDNode *N1C = getAsNonOpaqueConstant(N1);
2003
2063
2004
2064
// fold (sub x, c) -> (add x, -c)
@@ -2210,6 +2270,10 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
2210
2270
// fold (mul x, 1) -> x
2211
2271
if (N1IsConst && ConstValue1 == 1 && IsFullSplat)
2212
2272
return N0;
2273
+
2274
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
2275
+ return NewSel;
2276
+
2213
2277
// fold (mul x, -1) -> 0-x
2214
2278
if (N1IsConst && ConstValue1.isAllOnesValue()) {
2215
2279
SDLoc DL(N);
@@ -2401,6 +2465,9 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
2401
2465
return DAG.getNode(ISD::SUB, DL, VT,
2402
2466
DAG.getConstant(0, DL, VT), N0);
2403
2467
2468
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
2469
+ return NewSel;
2470
+
2404
2471
// If we know the sign bits of both operands are zero, strength reduce to a
2405
2472
// udiv instead. Handles (X&15) /s 4 -> X&15 >> 2
2406
2473
if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0))
@@ -2493,6 +2560,9 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) {
2493
2560
N0C, N1C))
2494
2561
return Folded;
2495
2562
2563
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
2564
+ return NewSel;
2565
+
2496
2566
// fold (udiv x, (1 << c)) -> x >>u c
2497
2567
if (isConstantOrConstantVector(N1, /*NoOpaques*/ true) &&
2498
2568
DAG.isKnownToBeAPowerOfTwo(N1)) {
@@ -2561,6 +2631,9 @@ SDValue DAGCombiner::visitREM(SDNode *N) {
2561
2631
if (SDValue Folded = DAG.FoldConstantArithmetic(Opcode, DL, VT, N0C, N1C))
2562
2632
return Folded;
2563
2633
2634
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
2635
+ return NewSel;
2636
+
2564
2637
if (isSigned) {
2565
2638
// If we know the sign bits of both operands are zero, strength reduce to a
2566
2639
// urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15
@@ -3267,6 +3340,10 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
3267
3340
if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0),
3268
3341
APInt::getAllOnesValue(BitWidth)))
3269
3342
return DAG.getConstant(0, SDLoc(N), VT);
3343
+
3344
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
3345
+ return NewSel;
3346
+
3270
3347
// reassociate and
3271
3348
if (SDValue RAND = ReassociateOps(ISD::AND, SDLoc(N), N0, N1))
3272
3349
return RAND;
@@ -4008,6 +4085,10 @@ SDValue DAGCombiner::visitOR(SDNode *N) {
4008
4085
// fold (or x, -1) -> -1
4009
4086
if (isAllOnesConstant(N1))
4010
4087
return N1;
4088
+
4089
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
4090
+ return NewSel;
4091
+
4011
4092
// fold (or x, c) -> c iff (x & ~c) == 0
4012
4093
if (N1C && DAG.MaskedValueIsZero(N0, ~N1C->getAPIntValue()))
4013
4094
return N1;
@@ -4753,6 +4834,10 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
4753
4834
// fold (xor x, 0) -> x
4754
4835
if (isNullConstant(N1))
4755
4836
return N0;
4837
+
4838
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
4839
+ return NewSel;
4840
+
4756
4841
// reassociate xor
4757
4842
if (SDValue RXOR = ReassociateOps(ISD::XOR, SDLoc(N), N0, N1))
4758
4843
return RXOR;
@@ -5040,6 +5125,10 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
5040
5125
// fold (shl undef, x) -> 0
5041
5126
if (N0.isUndef())
5042
5127
return DAG.getConstant(0, SDLoc(N), VT);
5128
+
5129
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
5130
+ return NewSel;
5131
+
5043
5132
// if (shl x, c) is known to be zero, return 0
5044
5133
if (DAG.MaskedValueIsZero(SDValue(N, 0),
5045
5134
APInt::getAllOnesValue(OpSizeInBits)))
@@ -5243,6 +5332,10 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
5243
5332
// fold (sra x, 0) -> x
5244
5333
if (N1C && N1C->isNullValue())
5245
5334
return N0;
5335
+
5336
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
5337
+ return NewSel;
5338
+
5246
5339
// fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target supports
5247
5340
// sext_inreg.
5248
5341
if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) {
@@ -5390,6 +5483,10 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
5390
5483
// fold (srl x, 0) -> x
5391
5484
if (N1C && N1C->isNullValue())
5392
5485
return N0;
5486
+
5487
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
5488
+ return NewSel;
5489
+
5393
5490
// if (srl x, c) is known to be zero, return 0
5394
5491
if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0),
5395
5492
APInt::getAllOnesValue(OpSizeInBits)))
@@ -9064,6 +9161,9 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
9064
9161
if (N0CFP && !N1CFP)
9065
9162
return DAG.getNode(ISD::FADD, DL, VT, N1, N0, Flags);
9066
9163
9164
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
9165
+ return NewSel;
9166
+
9067
9167
// fold (fadd A, (fneg B)) -> (fsub A, B)
9068
9168
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
9069
9169
isNegatibleForFree(N1, LegalOperations, TLI, &Options) == 2)
@@ -9211,6 +9311,9 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
9211
9311
if (N0CFP && N1CFP)
9212
9312
return DAG.getNode(ISD::FSUB, DL, VT, N0, N1, Flags);
9213
9313
9314
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
9315
+ return NewSel;
9316
+
9214
9317
// fold (fsub A, (fneg B)) -> (fadd A, B)
9215
9318
if (isNegatibleForFree(N1, LegalOperations, TLI, &Options))
9216
9319
return DAG.getNode(ISD::FADD, DL, VT, N0,
@@ -9290,6 +9393,9 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
9290
9393
if (N1CFP && N1CFP->isExactlyValue(1.0))
9291
9394
return N0;
9292
9395
9396
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
9397
+ return NewSel;
9398
+
9293
9399
if (Options.UnsafeFPMath) {
9294
9400
// fold (fmul A, 0) -> 0
9295
9401
if (N1CFP && N1CFP->isZero())
@@ -9544,6 +9650,9 @@ SDValue DAGCombiner::visitFDIV(SDNode *N) {
9544
9650
if (N0CFP && N1CFP)
9545
9651
return DAG.getNode(ISD::FDIV, SDLoc(N), VT, N0, N1, Flags);
9546
9652
9653
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
9654
+ return NewSel;
9655
+
9547
9656
if (Options.UnsafeFPMath) {
9548
9657
// fold (fdiv X, c2) -> fmul X, 1/c2 if losing precision is acceptable.
9549
9658
if (N1CFP) {
@@ -9647,6 +9756,9 @@ SDValue DAGCombiner::visitFREM(SDNode *N) {
9647
9756
return DAG.getNode(ISD::FREM, SDLoc(N), VT, N0, N1,
9648
9757
&cast<BinaryWithFlagsSDNode>(N)->Flags);
9649
9758
9759
+ if (SDValue NewSel = foldBinOpIntoSelect(N))
9760
+ return NewSel;
9761
+
9650
9762
return SDValue();
9651
9763
}
9652
9764
0 commit comments