Skip to content

Commit af41d0d

Browse files
authored
[LoongArch] Perform SELECT_CC combine (#155994)
Fold `((srl (and X, 1<<C), C), 0, eq/ne)` -> `((shl X, GRLen-1-C), 0, ge/lt)`
1 parent 31f0ab0 commit af41d0d

File tree

3 files changed

+86
-17
lines changed

3 files changed

+86
-17
lines changed

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5282,7 +5282,7 @@ static SDValue performBITREV_WCombine(SDNode *N, SelectionDAG &DAG,
52825282
Src.getOperand(0));
52835283
}
52845284

5285-
// Perform combines for BR_CC conditions.
5285+
// Perform common combines for BR_CC and SELECT_CC conditions.
52865286
static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,
52875287
SelectionDAG &DAG, const LoongArchSubtarget &Subtarget) {
52885288
ISD::CondCode CCVal = cast<CondCodeSDNode>(CC)->get();
@@ -5319,6 +5319,29 @@ static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,
53195319
return true;
53205320
}
53215321

5322+
// Fold ((srl (and X, 1<<C), C), 0, eq/ne) -> ((shl X, GRLen-1-C), 0, ge/lt)
5323+
if (isNullConstant(RHS) && LHS.getOpcode() == ISD::SRL && LHS.hasOneUse() &&
5324+
LHS.getOperand(1).getOpcode() == ISD::Constant) {
5325+
SDValue LHS0 = LHS.getOperand(0);
5326+
if (LHS0.getOpcode() == ISD::AND &&
5327+
LHS0.getOperand(1).getOpcode() == ISD::Constant) {
5328+
uint64_t Mask = LHS0.getConstantOperandVal(1);
5329+
uint64_t ShAmt = LHS.getConstantOperandVal(1);
5330+
if (isPowerOf2_64(Mask) && Log2_64(Mask) == ShAmt) {
5331+
CCVal = CCVal == ISD::SETEQ ? ISD::SETGE : ISD::SETLT;
5332+
CC = DAG.getCondCode(CCVal);
5333+
5334+
ShAmt = LHS.getValueSizeInBits() - 1 - ShAmt;
5335+
LHS = LHS0.getOperand(0);
5336+
if (ShAmt != 0)
5337+
LHS =
5338+
DAG.getNode(ISD::SHL, DL, LHS.getValueType(), LHS0.getOperand(0),
5339+
DAG.getConstant(ShAmt, DL, LHS.getValueType()));
5340+
return true;
5341+
}
5342+
}
5343+
}
5344+
53225345
// (X, 1, setne) -> (X, 0, seteq) if we can prove X is 0/1.
53235346
// This can occur when legalizing some floating point comparisons.
53245347
APInt Mask = APInt::getBitsSetFrom(LHS.getValueSizeInBits(), 1);
@@ -5347,6 +5370,57 @@ static SDValue performBR_CCCombine(SDNode *N, SelectionDAG &DAG,
53475370
return SDValue();
53485371
}
53495372

5373+
static SDValue performSELECT_CCCombine(SDNode *N, SelectionDAG &DAG,
5374+
TargetLowering::DAGCombinerInfo &DCI,
5375+
const LoongArchSubtarget &Subtarget) {
5376+
// Transform
5377+
SDValue LHS = N->getOperand(0);
5378+
SDValue RHS = N->getOperand(1);
5379+
SDValue CC = N->getOperand(2);
5380+
ISD::CondCode CCVal = cast<CondCodeSDNode>(CC)->get();
5381+
SDValue TrueV = N->getOperand(3);
5382+
SDValue FalseV = N->getOperand(4);
5383+
SDLoc DL(N);
5384+
EVT VT = N->getValueType(0);
5385+
5386+
// If the True and False values are the same, we don't need a select_cc.
5387+
if (TrueV == FalseV)
5388+
return TrueV;
5389+
5390+
// (select (x < 0), y, z) -> x >> (GRLEN - 1) & (y - z) + z
5391+
// (select (x >= 0), y, z) -> x >> (GRLEN - 1) & (z - y) + y
5392+
if (isa<ConstantSDNode>(TrueV) && isa<ConstantSDNode>(FalseV) &&
5393+
isNullConstant(RHS) &&
5394+
(CCVal == ISD::CondCode::SETLT || CCVal == ISD::CondCode::SETGE)) {
5395+
if (CCVal == ISD::CondCode::SETGE)
5396+
std::swap(TrueV, FalseV);
5397+
5398+
int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
5399+
int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
5400+
// Only handle simm12, if it is not in this range, it can be considered as
5401+
// register.
5402+
if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
5403+
isInt<12>(TrueSImm - FalseSImm)) {
5404+
SDValue SRA =
5405+
DAG.getNode(ISD::SRA, DL, VT, LHS,
5406+
DAG.getConstant(Subtarget.getGRLen() - 1, DL, VT));
5407+
SDValue AND =
5408+
DAG.getNode(ISD::AND, DL, VT, SRA,
5409+
DAG.getSignedConstant(TrueSImm - FalseSImm, DL, VT));
5410+
return DAG.getNode(ISD::ADD, DL, VT, AND, FalseV);
5411+
}
5412+
5413+
if (CCVal == ISD::CondCode::SETGE)
5414+
std::swap(TrueV, FalseV);
5415+
}
5416+
5417+
if (combine_CC(LHS, RHS, CC, DL, DAG, Subtarget))
5418+
return DAG.getNode(LoongArchISD::SELECT_CC, DL, N->getValueType(0),
5419+
{LHS, RHS, CC, TrueV, FalseV});
5420+
5421+
return SDValue();
5422+
}
5423+
53505424
template <unsigned N>
53515425
static SDValue legalizeIntrinsicImmArg(SDNode *Node, unsigned ImmOp,
53525426
SelectionDAG &DAG,
@@ -6041,6 +6115,8 @@ SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
60416115
return performBITREV_WCombine(N, DAG, DCI, Subtarget);
60426116
case LoongArchISD::BR_CC:
60436117
return performBR_CCCombine(N, DAG, DCI, Subtarget);
6118+
case LoongArchISD::SELECT_CC:
6119+
return performSELECT_CCCombine(N, DAG, DCI, Subtarget);
60446120
case ISD::INTRINSIC_WO_CHAIN:
60456121
return performINTRINSIC_WO_CHAINCombine(N, DAG, DCI, Subtarget);
60466122
case LoongArchISD::MOVGR2FR_W_LA64:

llvm/test/CodeGen/LoongArch/bittest.ll

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,9 @@ define signext i32 @bit_10_z_select_i32(i32 signext %a, i32 signext %b, i32 sign
358358
define signext i32 @bit_10_nz_select_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
359359
; LA32-LABEL: bit_10_nz_select_i32:
360360
; LA32: # %bb.0:
361-
; LA32-NEXT: andi $a0, $a0, 1024
362-
; LA32-NEXT: srli.w $a3, $a0, 10
361+
; LA32-NEXT: slli.w $a3, $a0, 21
363362
; LA32-NEXT: move $a0, $a1
364-
; LA32-NEXT: bne $a3, $zero, .LBB16_2
363+
; LA32-NEXT: bltz $a3, .LBB16_2
365364
; LA32-NEXT: # %bb.1:
366365
; LA32-NEXT: move $a0, $a2
367366
; LA32-NEXT: .LBB16_2:
@@ -408,10 +407,9 @@ define signext i32 @bit_11_z_select_i32(i32 signext %a, i32 signext %b, i32 sign
408407
define signext i32 @bit_11_nz_select_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
409408
; LA32-LABEL: bit_11_nz_select_i32:
410409
; LA32: # %bb.0:
411-
; LA32-NEXT: andi $a0, $a0, 2048
412-
; LA32-NEXT: srli.w $a3, $a0, 11
410+
; LA32-NEXT: slli.w $a3, $a0, 20
413411
; LA32-NEXT: move $a0, $a1
414-
; LA32-NEXT: bne $a3, $zero, .LBB18_2
412+
; LA32-NEXT: bltz $a3, .LBB18_2
415413
; LA32-NEXT: # %bb.1:
416414
; LA32-NEXT: move $a0, $a2
417415
; LA32-NEXT: .LBB18_2:
@@ -459,11 +457,9 @@ define signext i32 @bit_20_z_select_i32(i32 signext %a, i32 signext %b, i32 sign
459457
define signext i32 @bit_20_nz_select_i32(i32 signext %a, i32 signext %b, i32 signext %c) {
460458
; LA32-LABEL: bit_20_nz_select_i32:
461459
; LA32: # %bb.0:
462-
; LA32-NEXT: lu12i.w $a3, 256
463-
; LA32-NEXT: and $a0, $a0, $a3
464-
; LA32-NEXT: srli.w $a3, $a0, 20
460+
; LA32-NEXT: slli.w $a3, $a0, 11
465461
; LA32-NEXT: move $a0, $a1
466-
; LA32-NEXT: bne $a3, $zero, .LBB20_2
462+
; LA32-NEXT: bltz $a3, .LBB20_2
467463
; LA32-NEXT: # %bb.1:
468464
; LA32-NEXT: move $a0, $a2
469465
; LA32-NEXT: .LBB20_2:

llvm/test/CodeGen/LoongArch/select-const.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,9 @@ define i32 @select_ne_10001_10002(i32 signext %a, i32 signext %b) {
305305
define i32 @select_slt_zero_constant1_constant2(i32 signext %x) {
306306
; LA32-LABEL: select_slt_zero_constant1_constant2:
307307
; LA32: # %bb.0:
308-
; LA32-NEXT: move $a1, $a0
309-
; LA32-NEXT: ori $a0, $zero, 7
310-
; LA32-NEXT: bltz $a1, .LBB16_2
311-
; LA32-NEXT: # %bb.1:
312-
; LA32-NEXT: addi.w $a0, $zero, -3
313-
; LA32-NEXT: .LBB16_2:
308+
; LA32-NEXT: srai.w $a0, $a0, 31
309+
; LA32-NEXT: andi $a0, $a0, 10
310+
; LA32-NEXT: addi.w $a0, $a0, -3
314311
; LA32-NEXT: ret
315312
;
316313
; LA64-LABEL: select_slt_zero_constant1_constant2:

0 commit comments

Comments
 (0)