Skip to content

Commit 6f5edc3

Browse files
committed
[RISCV] Fold (add (select lhs, rhs, cc, 0, y), x) -> (select lhs, rhs, cc, x, (add x, y))
Similar for sub except sub isn't commutative. Modify the existing and/or/xor folds to also work on ISD::SELECT and not just RISCVISD::SELECT_CC. This is needed to make sure we do this transform before type legalization turns i32 add/sub into add/sub+sign_extend_inreg on RV64. If we don't do this before that, the sign_extend_inreg will still be after the select. Reviewed By: frasercrmck Differential Revision: https://reviews.llvm.org/D107603
1 parent ce96d81 commit 6f5edc3

File tree

3 files changed

+104
-83
lines changed

3 files changed

+104
-83
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+67-41
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
858858
// We can use any register for comparisons
859859
setHasMultipleConditionRegisters();
860860

861+
setTargetDAGCombine(ISD::ADD);
862+
setTargetDAGCombine(ISD::SUB);
861863
setTargetDAGCombine(ISD::AND);
862864
setTargetDAGCombine(ISD::OR);
863865
setTargetDAGCombine(ISD::XOR);
@@ -5769,26 +5771,37 @@ static SDValue combineGREVI_GORCI(SDNode *N, SelectionDAG &DAG) {
57695771

57705772
// Combine a constant select operand into its use:
57715773
//
5772-
// (and (select_cc lhs, rhs, cc, -1, c), x)
5773-
// -> (select_cc lhs, rhs, cc, x, (and, x, c)) [AllOnes=1]
5774-
// (or (select_cc lhs, rhs, cc, 0, c), x)
5775-
// -> (select_cc lhs, rhs, cc, x, (or, x, c)) [AllOnes=0]
5776-
// (xor (select_cc lhs, rhs, cc, 0, c), x)
5777-
// -> (select_cc lhs, rhs, cc, x, (xor, x, c)) [AllOnes=0]
5778-
static SDValue combineSelectCCAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
5779-
SelectionDAG &DAG, bool AllOnes) {
5774+
// (and (select cond, -1, c), x)
5775+
// -> (select cond, x, (and x, c)) [AllOnes=1]
5776+
// (or (select cond, 0, c), x)
5777+
// -> (select cond, x, (or x, c)) [AllOnes=0]
5778+
// (xor (select cond, 0, c), x)
5779+
// -> (select cond, x, (xor x, c)) [AllOnes=0]
5780+
// (add (select cond, 0, c), x)
5781+
// -> (select cond, x, (add x, c)) [AllOnes=0]
5782+
// (sub x, (select cond, 0, c))
5783+
// -> (select cond, x, (sub x, c)) [AllOnes=0]
5784+
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
5785+
SelectionDAG &DAG, bool AllOnes) {
57805786
EVT VT = N->getValueType(0);
57815787

5782-
if (Slct.getOpcode() != RISCVISD::SELECT_CC || !Slct.hasOneUse())
5788+
// Skip vectors.
5789+
if (VT.isVector())
5790+
return SDValue();
5791+
5792+
if ((Slct.getOpcode() != ISD::SELECT &&
5793+
Slct.getOpcode() != RISCVISD::SELECT_CC) ||
5794+
!Slct.hasOneUse())
57835795
return SDValue();
57845796

57855797
auto isZeroOrAllOnes = [](SDValue N, bool AllOnes) {
57865798
return AllOnes ? isAllOnesConstant(N) : isNullConstant(N);
57875799
};
57885800

57895801
bool SwapSelectOps;
5790-
SDValue TrueVal = Slct.getOperand(3);
5791-
SDValue FalseVal = Slct.getOperand(4);
5802+
unsigned OpOffset = Slct.getOpcode() == RISCVISD::SELECT_CC ? 2 : 0;
5803+
SDValue TrueVal = Slct.getOperand(1 + OpOffset);
5804+
SDValue FalseVal = Slct.getOperand(2 + OpOffset);
57925805
SDValue NonConstantVal;
57935806
if (isZeroOrAllOnes(TrueVal, AllOnes)) {
57945807
SwapSelectOps = false;
@@ -5802,40 +5815,53 @@ static SDValue combineSelectCCAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
58025815
// Slct is now know to be the desired identity constant when CC is true.
58035816
TrueVal = OtherOp;
58045817
FalseVal = DAG.getNode(N->getOpcode(), SDLoc(N), VT, OtherOp, NonConstantVal);
5805-
// Unless SwapSelectOps says CC should be false.
5818+
// Unless SwapSelectOps says the condition should be false.
58065819
if (SwapSelectOps)
58075820
std::swap(TrueVal, FalseVal);
58085821

5809-
return DAG.getNode(RISCVISD::SELECT_CC, SDLoc(N), VT,
5810-
{Slct.getOperand(0), Slct.getOperand(1),
5811-
Slct.getOperand(2), TrueVal, FalseVal});
5822+
if (Slct.getOpcode() == RISCVISD::SELECT_CC)
5823+
return DAG.getNode(RISCVISD::SELECT_CC, SDLoc(N), VT,
5824+
{Slct.getOperand(0), Slct.getOperand(1),
5825+
Slct.getOperand(2), TrueVal, FalseVal});
5826+
5827+
return DAG.getNode(ISD::SELECT, SDLoc(N), VT,
5828+
{Slct.getOperand(0), TrueVal, FalseVal});
58125829
}
58135830

58145831
// Attempt combineSelectAndUse on each operand of a commutative operator N.
5815-
static SDValue combineSelectCCAndUseCommutative(SDNode *N, SelectionDAG &DAG,
5816-
bool AllOnes) {
5832+
static SDValue combineSelectAndUseCommutative(SDNode *N, SelectionDAG &DAG,
5833+
bool AllOnes) {
58175834
SDValue N0 = N->getOperand(0);
58185835
SDValue N1 = N->getOperand(1);
5819-
if (SDValue Result = combineSelectCCAndUse(N, N0, N1, DAG, AllOnes))
5836+
if (SDValue Result = combineSelectAndUse(N, N0, N1, DAG, AllOnes))
58205837
return Result;
5821-
if (SDValue Result = combineSelectCCAndUse(N, N1, N0, DAG, AllOnes))
5838+
if (SDValue Result = combineSelectAndUse(N, N1, N0, DAG, AllOnes))
58225839
return Result;
58235840
return SDValue();
58245841
}
58255842

5826-
static SDValue performANDCombine(SDNode *N,
5827-
TargetLowering::DAGCombinerInfo &DCI,
5828-
const RISCVSubtarget &Subtarget) {
5829-
SelectionDAG &DAG = DCI.DAG;
5843+
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG) {
5844+
// fold (add (select lhs, rhs, cc, 0, y), x) ->
5845+
// (select lhs, rhs, cc, x, (add x, y))
5846+
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false);
5847+
}
58305848

5831-
// fold (and (select_cc lhs, rhs, cc, -1, y), x) ->
5849+
static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG) {
5850+
// fold (sub x, (select lhs, rhs, cc, 0, y)) ->
5851+
// (select lhs, rhs, cc, x, (sub x, y))
5852+
SDValue N0 = N->getOperand(0);
5853+
SDValue N1 = N->getOperand(1);
5854+
return combineSelectAndUse(N, N1, N0, DAG, /*AllOnes*/ false);
5855+
}
5856+
5857+
static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG) {
5858+
// fold (and (select lhs, rhs, cc, -1, y), x) ->
58325859
// (select lhs, rhs, cc, x, (and x, y))
5833-
return combineSelectCCAndUseCommutative(N, DAG, true);
5860+
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ true);
58345861
}
58355862

5836-
static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
5863+
static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
58375864
const RISCVSubtarget &Subtarget) {
5838-
SelectionDAG &DAG = DCI.DAG;
58395865
if (Subtarget.hasStdExtZbp()) {
58405866
if (auto GREV = combineORToGREV(SDValue(N, 0), DAG, Subtarget))
58415867
return GREV;
@@ -5845,19 +5871,15 @@ static SDValue performORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
58455871
return SHFL;
58465872
}
58475873

5848-
// fold (or (select_cc lhs, rhs, cc, 0, y), x) ->
5849-
// (select lhs, rhs, cc, x, (or x, y))
5850-
return combineSelectCCAndUseCommutative(N, DAG, false);
5874+
// fold (or (select cond, 0, y), x) ->
5875+
// (select cond, x, (or x, y))
5876+
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false);
58515877
}
58525878

5853-
static SDValue performXORCombine(SDNode *N,
5854-
TargetLowering::DAGCombinerInfo &DCI,
5855-
const RISCVSubtarget &Subtarget) {
5856-
SelectionDAG &DAG = DCI.DAG;
5857-
5858-
// fold (xor (select_cc lhs, rhs, cc, 0, y), x) ->
5859-
// (select lhs, rhs, cc, x, (xor x, y))
5860-
return combineSelectCCAndUseCommutative(N, DAG, false);
5879+
static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG) {
5880+
// fold (xor (select cond, 0, y), x) ->
5881+
// (select cond, x, (xor x, y))
5882+
return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false);
58615883
}
58625884

58635885
// Attempt to turn ANY_EXTEND into SIGN_EXTEND if the input to the ANY_EXTEND
@@ -6167,12 +6189,16 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
61676189
return DAG.getNode(ISD::AND, DL, VT, NewFMV,
61686190
DAG.getConstant(~SignBit, DL, VT));
61696191
}
6192+
case ISD::ADD:
6193+
return performADDCombine(N, DAG);
6194+
case ISD::SUB:
6195+
return performSUBCombine(N, DAG);
61706196
case ISD::AND:
6171-
return performANDCombine(N, DCI, Subtarget);
6197+
return performANDCombine(N, DAG);
61726198
case ISD::OR:
6173-
return performORCombine(N, DCI, Subtarget);
6199+
return performORCombine(N, DAG, Subtarget);
61746200
case ISD::XOR:
6175-
return performXORCombine(N, DCI, Subtarget);
6201+
return performXORCombine(N, DAG);
61766202
case ISD::ANY_EXTEND:
61776203
return performANY_EXTENDCombine(N, DCI, Subtarget);
61786204
case ISD::ZERO_EXTEND:

llvm/test/CodeGen/RISCV/rv32zbs.ll

+9-10
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,15 @@ define i64 @sbclr_i64(i64 %a, i64 %b) nounwind {
7575
;
7676
; RV32IB-LABEL: sbclr_i64:
7777
; RV32IB: # %bb.0:
78-
; RV32IB-NEXT: andi a3, a2, 63
79-
; RV32IB-NEXT: addi a3, a3, -32
80-
; RV32IB-NEXT: bset a4, zero, a3
81-
; RV32IB-NEXT: slti a5, a3, 0
82-
; RV32IB-NEXT: cmov a4, a5, zero, a4
83-
; RV32IB-NEXT: bset a2, zero, a2
84-
; RV32IB-NEXT: srai a3, a3, 31
85-
; RV32IB-NEXT: and a2, a3, a2
86-
; RV32IB-NEXT: andn a1, a1, a4
87-
; RV32IB-NEXT: andn a0, a0, a2
78+
; RV32IB-NEXT: bset a3, zero, a2
79+
; RV32IB-NEXT: andi a2, a2, 63
80+
; RV32IB-NEXT: addi a2, a2, -32
81+
; RV32IB-NEXT: srai a4, a2, 31
82+
; RV32IB-NEXT: and a3, a4, a3
83+
; RV32IB-NEXT: slti a4, a2, 0
84+
; RV32IB-NEXT: bclr a2, a1, a2
85+
; RV32IB-NEXT: cmov a1, a4, a1, a2
86+
; RV32IB-NEXT: andn a0, a0, a3
8887
; RV32IB-NEXT: ret
8988
;
9089
; RV32IBS-LABEL: sbclr_i64:

llvm/test/CodeGen/RISCV/select-binop-identity.ll

+28-32
Original file line numberDiff line numberDiff line change
@@ -157,22 +157,20 @@ define i64 @xor_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) {
157157
define signext i32 @add_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32 signext %y) {
158158
; RV32I-LABEL: add_select_all_zeros_i32:
159159
; RV32I: # %bb.0:
160-
; RV32I-NEXT: mv a3, zero
161160
; RV32I-NEXT: bnez a0, .LBB6_2
162161
; RV32I-NEXT: # %bb.1:
163-
; RV32I-NEXT: mv a3, a1
162+
; RV32I-NEXT: add a2, a2, a1
164163
; RV32I-NEXT: .LBB6_2:
165-
; RV32I-NEXT: add a0, a2, a3
164+
; RV32I-NEXT: mv a0, a2
166165
; RV32I-NEXT: ret
167166
;
168167
; RV64I-LABEL: add_select_all_zeros_i32:
169168
; RV64I: # %bb.0:
170-
; RV64I-NEXT: mv a3, zero
171169
; RV64I-NEXT: bnez a0, .LBB6_2
172170
; RV64I-NEXT: # %bb.1:
173-
; RV64I-NEXT: mv a3, a1
171+
; RV64I-NEXT: addw a2, a2, a1
174172
; RV64I-NEXT: .LBB6_2:
175-
; RV64I-NEXT: addw a0, a2, a3
173+
; RV64I-NEXT: mv a0, a2
176174
; RV64I-NEXT: ret
177175
%a = select i1 %c, i32 0, i32 %x
178176
%b = add i32 %y, %a
@@ -182,24 +180,25 @@ define signext i32 @add_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32
182180
define i64 @add_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) {
183181
; RV32I-LABEL: add_select_all_zeros_i64:
184182
; RV32I: # %bb.0:
185-
; RV32I-NEXT: bnez a0, .LBB7_2
183+
; RV32I-NEXT: beqz a0, .LBB7_2
186184
; RV32I-NEXT: # %bb.1:
187-
; RV32I-NEXT: mv a2, zero
188-
; RV32I-NEXT: mv a1, zero
185+
; RV32I-NEXT: add a0, a4, a2
186+
; RV32I-NEXT: add a1, a3, a1
187+
; RV32I-NEXT: sltu a2, a1, a3
188+
; RV32I-NEXT: add a4, a0, a2
189+
; RV32I-NEXT: mv a3, a1
189190
; RV32I-NEXT: .LBB7_2:
190-
; RV32I-NEXT: add a0, a1, a3
191-
; RV32I-NEXT: sltu a1, a0, a1
192-
; RV32I-NEXT: add a2, a2, a4
193-
; RV32I-NEXT: add a1, a2, a1
191+
; RV32I-NEXT: mv a0, a3
192+
; RV32I-NEXT: mv a1, a4
194193
; RV32I-NEXT: ret
195194
;
196195
; RV64I-LABEL: add_select_all_zeros_i64:
197196
; RV64I: # %bb.0:
198-
; RV64I-NEXT: bnez a0, .LBB7_2
197+
; RV64I-NEXT: beqz a0, .LBB7_2
199198
; RV64I-NEXT: # %bb.1:
200-
; RV64I-NEXT: mv a1, zero
199+
; RV64I-NEXT: add a2, a2, a1
201200
; RV64I-NEXT: .LBB7_2:
202-
; RV64I-NEXT: add a0, a1, a2
201+
; RV64I-NEXT: mv a0, a2
203202
; RV64I-NEXT: ret
204203
%a = select i1 %c, i64 %x, i64 0
205204
%b = add i64 %a, %y
@@ -209,22 +208,20 @@ define i64 @add_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) {
209208
define signext i32 @sub_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32 signext %y) {
210209
; RV32I-LABEL: sub_select_all_zeros_i32:
211210
; RV32I: # %bb.0:
212-
; RV32I-NEXT: mv a3, zero
213211
; RV32I-NEXT: bnez a0, .LBB8_2
214212
; RV32I-NEXT: # %bb.1:
215-
; RV32I-NEXT: mv a3, a1
213+
; RV32I-NEXT: sub a2, a2, a1
216214
; RV32I-NEXT: .LBB8_2:
217-
; RV32I-NEXT: sub a0, a2, a3
215+
; RV32I-NEXT: mv a0, a2
218216
; RV32I-NEXT: ret
219217
;
220218
; RV64I-LABEL: sub_select_all_zeros_i32:
221219
; RV64I: # %bb.0:
222-
; RV64I-NEXT: mv a3, zero
223220
; RV64I-NEXT: bnez a0, .LBB8_2
224221
; RV64I-NEXT: # %bb.1:
225-
; RV64I-NEXT: mv a3, a1
222+
; RV64I-NEXT: subw a2, a2, a1
226223
; RV64I-NEXT: .LBB8_2:
227-
; RV64I-NEXT: subw a0, a2, a3
224+
; RV64I-NEXT: mv a0, a2
228225
; RV64I-NEXT: ret
229226
%a = select i1 %c, i32 0, i32 %x
230227
%b = sub i32 %y, %a
@@ -234,25 +231,24 @@ define signext i32 @sub_select_all_zeros_i32(i1 zeroext %c, i32 signext %x, i32
234231
define i64 @sub_select_all_zeros_i64(i1 zeroext %c, i64 %x, i64 %y) {
235232
; RV32I-LABEL: sub_select_all_zeros_i64:
236233
; RV32I: # %bb.0:
237-
; RV32I-NEXT: bnez a0, .LBB9_2
234+
; RV32I-NEXT: beqz a0, .LBB9_2
238235
; RV32I-NEXT: # %bb.1:
239-
; RV32I-NEXT: mv a2, zero
240-
; RV32I-NEXT: mv a1, zero
241-
; RV32I-NEXT: .LBB9_2:
242236
; RV32I-NEXT: sltu a0, a3, a1
243237
; RV32I-NEXT: sub a2, a4, a2
244-
; RV32I-NEXT: sub a2, a2, a0
245-
; RV32I-NEXT: sub a0, a3, a1
246-
; RV32I-NEXT: mv a1, a2
238+
; RV32I-NEXT: sub a4, a2, a0
239+
; RV32I-NEXT: sub a3, a3, a1
240+
; RV32I-NEXT: .LBB9_2:
241+
; RV32I-NEXT: mv a0, a3
242+
; RV32I-NEXT: mv a1, a4
247243
; RV32I-NEXT: ret
248244
;
249245
; RV64I-LABEL: sub_select_all_zeros_i64:
250246
; RV64I: # %bb.0:
251-
; RV64I-NEXT: bnez a0, .LBB9_2
247+
; RV64I-NEXT: beqz a0, .LBB9_2
252248
; RV64I-NEXT: # %bb.1:
253-
; RV64I-NEXT: mv a1, zero
249+
; RV64I-NEXT: sub a2, a2, a1
254250
; RV64I-NEXT: .LBB9_2:
255-
; RV64I-NEXT: sub a0, a2, a1
251+
; RV64I-NEXT: mv a0, a2
256252
; RV64I-NEXT: ret
257253
%a = select i1 %c, i64 %x, i64 0
258254
%b = sub i64 %y, %a

0 commit comments

Comments
 (0)