diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -9627,6 +9627,31 @@ } } + // (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(TrueV) && + isa(FalseV) && isNullConstant(RHS) && + (CCVal == ISD::CondCode::SETLT || CCVal == ISD::CondCode::SETGE)) { + if (CCVal == ISD::CondCode::SETGE) + std::swap(TrueV, FalseV); + + int64_t TrueSImm = cast(TrueV)->getSExtValue(); + int64_t FalseSImm = cast(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); + } + std::swap(TrueSImm, FalseSImm); + } + if (combine_CC(LHS, RHS, CC, DL, DAG, Subtarget)) return DAG.getNode(RISCVISD::SELECT_CC, DL, N->getValueType(0), {LHS, RHS, CC, TrueV, FalseV}); diff --git a/llvm/test/CodeGen/RISCV/select-const.ll b/llvm/test/CodeGen/RISCV/select-const.ll --- a/llvm/test/CodeGen/RISCV/select-const.ll +++ b/llvm/test/CodeGen/RISCV/select-const.ll @@ -391,3 +391,41 @@ %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 +}