forked from OSchip/llvm-project
[RISCV] Branchless lowering for (select (x < 0), TrueConstant, FalseConstant) and (select (x >= 0), TrueConstant, FalseConstant)
This patch reduces the number of unpredictable branches (select (x < 0), y, z) -> x >> (XLEN - 1) & (y - z) + z (select (x >= 0), y, z) -> x >> (XLEN - 1) & (z - y) + y Reviewed By: craig.topper, reames Differential Revision: https://reviews.llvm.org/D137949
This commit is contained in:
parent
9d5e82e75c
commit
aa14f002d5
|
@ -9699,6 +9699,33 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
|
|||
}
|
||||
}
|
||||
|
||||
// (select (x < 0), y, z) -> x >> (XLEN - 1) & (y - z) + z
|
||||
// (select (x >= 0), y, z) -> x >> (XLEN - 1) & (z - y) + y
|
||||
if (!Subtarget.hasShortForwardBranchOpt() && isa<ConstantSDNode>(TrueV) &&
|
||||
isa<ConstantSDNode>(FalseV) && isNullConstant(RHS) &&
|
||||
(CCVal == ISD::CondCode::SETLT || CCVal == ISD::CondCode::SETGE)) {
|
||||
if (CCVal == ISD::CondCode::SETGE)
|
||||
std::swap(TrueV, FalseV);
|
||||
|
||||
int64_t TrueSImm = cast<ConstantSDNode>(TrueV)->getSExtValue();
|
||||
int64_t FalseSImm = cast<ConstantSDNode>(FalseV)->getSExtValue();
|
||||
// Only handle simm12, if it is not in this range, it can be considered as
|
||||
// register.
|
||||
if (isInt<12>(TrueSImm) && isInt<12>(FalseSImm) &&
|
||||
isInt<12>(TrueSImm - FalseSImm)) {
|
||||
SDValue SRA =
|
||||
DAG.getNode(ISD::SRA, DL, VT, LHS,
|
||||
DAG.getConstant(Subtarget.getXLen() - 1, DL, VT));
|
||||
SDValue AND =
|
||||
DAG.getNode(ISD::AND, DL, VT, SRA,
|
||||
DAG.getConstant(TrueSImm - FalseSImm, DL, VT));
|
||||
return DAG.getNode(ISD::ADD, DL, VT, AND, FalseV);
|
||||
}
|
||||
|
||||
if (CCVal == ISD::CondCode::SETGE)
|
||||
std::swap(TrueV, FalseV);
|
||||
}
|
||||
|
||||
if (combine_CC(LHS, RHS, CC, DL, DAG, Subtarget))
|
||||
return DAG.getNode(RISCVISD::SELECT_CC, DL, N->getValueType(0),
|
||||
{LHS, RHS, CC, TrueV, FalseV});
|
||||
|
|
|
@ -391,3 +391,41 @@ define i32 @select_ne_10001_10002(i32 signext %a, i32 signext %b) {
|
|||
%2 = select i1 %1, i32 10001, i32 10002
|
||||
ret i32 %2
|
||||
}
|
||||
|
||||
define i32 @select_slt_zero_constant1_constant2(i32 signext %x) {
|
||||
; RV32-LABEL: select_slt_zero_constant1_constant2:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: srai a0, a0, 31
|
||||
; RV32-NEXT: andi a0, a0, 10
|
||||
; RV32-NEXT: addi a0, a0, -3
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: select_slt_zero_constant1_constant2:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: srai a0, a0, 63
|
||||
; RV64-NEXT: andi a0, a0, 10
|
||||
; RV64-NEXT: addi a0, a0, -3
|
||||
; RV64-NEXT: ret
|
||||
%cmp = icmp slt i32 %x, 0
|
||||
%cond = select i1 %cmp, i32 7, i32 -3
|
||||
ret i32 %cond
|
||||
}
|
||||
|
||||
define i32 @select_sgt_negative_one_constant1_constant2(i32 signext %x) {
|
||||
; RV32-LABEL: select_sgt_negative_one_constant1_constant2:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: srai a0, a0, 31
|
||||
; RV32-NEXT: andi a0, a0, -10
|
||||
; RV32-NEXT: addi a0, a0, 7
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: select_sgt_negative_one_constant1_constant2:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: srai a0, a0, 63
|
||||
; RV64-NEXT: andi a0, a0, -10
|
||||
; RV64-NEXT: addi a0, a0, 7
|
||||
; RV64-NEXT: ret
|
||||
%cmp = icmp sgt i32 %x, -1
|
||||
%cond = select i1 %cmp, i32 7, i32 -3
|
||||
ret i32 %cond
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue