diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4858,6 +4858,15 @@ ISD::MemIndexType getCanonicalIndexType(ISD::MemIndexType IndexType, EVT MemVT, SDValue Offsets) const; + virtual bool isProfitableToExpandUADDOWithConstant(SDValue Val) const { + ConstantSDNode *C = dyn_cast(Val); + // Special case: uaddo X, 1 overflowed if X+1 is 0. This potential reduces + // the live range of X. We assume comparing with 0 is cheap. + if (C && C->getZExtValue() == 1) + return true; + return false; + } + private: SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, const SDLoc &DL, DAGCombinerInfo &DCI) const; diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -8820,13 +8820,10 @@ EVT SetCCType = getSetCCResultType( DAG.getDataLayout(), *DAG.getContext(), Node->getValueType(0)); SDValue SetCC; - if (IsAdd && isOneConstant(RHS)) { - // Special case: uaddo X, 1 overflowed if X+1 is 0. This potential reduces - // the live range of X. We assume comparing with 0 is cheap. - // TODO: This generalizes to (X + C) < C. - SetCC = - DAG.getSetCC(dl, SetCCType, Result, - DAG.getConstant(0, dl, Node->getValueType(0)), ISD::SETEQ); + if (IsAdd && isProfitableToExpandUADDOWithConstant(RHS)) { + // Special case: uaddo X, C overflowed if X+C < C. This potential reduces + // the live range of X. + SetCC = DAG.getSetCC(dl, SetCCType, Result, RHS, ISD::SETULT); } else { ISD::CondCode CC = IsAdd ? ISD::SETULT : ISD::SETUGT; SetCC = DAG.getSetCC(dl, SetCCType, Result, LHS, CC); diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -572,6 +572,8 @@ unsigned uid, MCContext &Ctx) const override; + bool isProfitableToExpandUADDOWithConstant(SDValue Val) const override; + private: /// RISCVCCAssignFn - This target-specific function extends the default /// CCValAssign with additional information used to lower RISC-V calling 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 @@ -6969,11 +6969,10 @@ DAG.getValueType(MVT::i32)); SDValue Overflow; - if (IsAdd && isOneConstant(RHS)) { - // Special case uaddo X, 1 overflowed if the addition result is 0. - // FIXME: We can do this for any constant RHS by using (X + C) < C. - Overflow = DAG.getSetCC(DL, N->getValueType(1), Res, - DAG.getConstant(0, DL, MVT::i64), ISD::SETEQ); + if (IsAdd && isProfitableToExpandUADDOWithConstant(RHS)) { + // Special case uaddo X, C overflowed if the addition result is less than + // C. + Overflow = DAG.getSetCC(DL, N->getValueType(1), Res, RHS, ISD::SETULT); } else { // Sign extend the LHS and perform an unsigned compare with the ADDW // result. Since the inputs are sign extended from i32, this is equivalent @@ -11621,6 +11620,18 @@ return MCSymbolRefExpr::create(MBB->getSymbol(), Ctx); } +bool RISCVTargetLowering::isProfitableToExpandUADDOWithConstant( + SDValue Val) const { + ConstantSDNode *C = dyn_cast(Val); + if (!C) + return false; + + if (C->getAPIntValue().isSignedIntN(12)) + return true; + + return false; +} + bool RISCVTargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT VT) const { VT = VT.getScalarType(); diff --git a/llvm/test/CodeGen/PowerPC/sat-add.ll b/llvm/test/CodeGen/PowerPC/sat-add.ll --- a/llvm/test/CodeGen/PowerPC/sat-add.ll +++ b/llvm/test/CodeGen/PowerPC/sat-add.ll @@ -113,10 +113,10 @@ define i32 @unsigned_sat_constant_i32_using_cmp_sum(i32 %x) { ; CHECK-LABEL: unsigned_sat_constant_i32_using_cmp_sum: ; CHECK: # %bb.0: -; CHECK-NEXT: addi 5, 3, 42 +; CHECK-NEXT: addi 3, 3, 42 ; CHECK-NEXT: li 4, -1 -; CHECK-NEXT: cmplw 5, 3 -; CHECK-NEXT: isellt 3, 4, 5 +; CHECK-NEXT: cmplwi 3, 42 +; CHECK-NEXT: isellt 3, 4, 3 ; CHECK-NEXT: blr %a = add i32 %x, 42 %c = icmp ugt i32 %x, %a @@ -156,10 +156,10 @@ define i64 @unsigned_sat_constant_i64_using_cmp_sum(i64 %x) { ; CHECK-LABEL: unsigned_sat_constant_i64_using_cmp_sum: ; CHECK: # %bb.0: -; CHECK-NEXT: addi 5, 3, 42 +; CHECK-NEXT: addi 3, 3, 42 ; CHECK-NEXT: li 4, -1 -; CHECK-NEXT: cmpld 5, 3 -; CHECK-NEXT: isellt 3, 4, 5 +; CHECK-NEXT: cmpldi 3, 42 +; CHECK-NEXT: isellt 3, 4, 3 ; CHECK-NEXT: blr %a = add i64 %x, 42 %c = icmp ugt i64 %x, %a diff --git a/llvm/test/CodeGen/RISCV/xaluo.ll b/llvm/test/CodeGen/RISCV/xaluo.ll --- a/llvm/test/CodeGen/RISCV/xaluo.ll +++ b/llvm/test/CodeGen/RISCV/xaluo.ll @@ -390,31 +390,29 @@ ; RV32-LABEL: uaddo.i32.constant: ; RV32: # %bb.0: # %entry ; RV32-NEXT: addi a2, a0, -2 -; RV32-NEXT: sltu a0, a2, a0 +; RV32-NEXT: sltiu a0, a2, -2 ; RV32-NEXT: sw a2, 0(a1) ; RV32-NEXT: ret ; ; RV64-LABEL: uaddo.i32.constant: ; RV64: # %bb.0: # %entry -; RV64-NEXT: sext.w a2, a0 -; RV64-NEXT: addiw a3, a0, -2 -; RV64-NEXT: sltu a0, a3, a2 -; RV64-NEXT: sw a3, 0(a1) +; RV64-NEXT: addiw a2, a0, -2 +; RV64-NEXT: sltiu a0, a2, -2 +; RV64-NEXT: sw a2, 0(a1) ; RV64-NEXT: ret ; ; RV32ZBA-LABEL: uaddo.i32.constant: ; RV32ZBA: # %bb.0: # %entry ; RV32ZBA-NEXT: addi a2, a0, -2 -; RV32ZBA-NEXT: sltu a0, a2, a0 +; RV32ZBA-NEXT: sltiu a0, a2, -2 ; RV32ZBA-NEXT: sw a2, 0(a1) ; RV32ZBA-NEXT: ret ; ; RV64ZBA-LABEL: uaddo.i32.constant: ; RV64ZBA: # %bb.0: # %entry -; RV64ZBA-NEXT: sext.w a2, a0 -; RV64ZBA-NEXT: addiw a3, a0, -2 -; RV64ZBA-NEXT: sltu a0, a3, a2 -; RV64ZBA-NEXT: sw a3, 0(a1) +; RV64ZBA-NEXT: addiw a2, a0, -2 +; RV64ZBA-NEXT: sltiu a0, a2, -2 +; RV64ZBA-NEXT: sw a2, 0(a1) ; RV64ZBA-NEXT: ret entry: %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %v1, i32 -2) @@ -4058,7 +4056,7 @@ ; RV64-LABEL: uaddo.i64.constant: ; RV64: # %bb.0: # %entry ; RV64-NEXT: addi a2, a0, 2 -; RV64-NEXT: sltu a0, a2, a0 +; RV64-NEXT: sltiu a0, a2, 2 ; RV64-NEXT: sd a2, 0(a1) ; RV64-NEXT: ret ; @@ -4079,7 +4077,7 @@ ; RV64ZBA-LABEL: uaddo.i64.constant: ; RV64ZBA: # %bb.0: # %entry ; RV64ZBA-NEXT: addi a2, a0, 2 -; RV64ZBA-NEXT: sltu a0, a2, a0 +; RV64ZBA-NEXT: sltiu a0, a2, 2 ; RV64ZBA-NEXT: sd a2, 0(a1) ; RV64ZBA-NEXT: ret entry: @@ -4221,8 +4219,9 @@ ; ; RV64-LABEL: uaddo.i64.constant_setcc_on_overflow_flag: ; RV64: # %bb.0: # %entry -; RV64-NEXT: ld a1, 0(a0) -; RV64-NEXT: addi a0, a1, 2 +; RV64-NEXT: ld a0, 0(a0) +; RV64-NEXT: addi a0, a0, 2 +; RV64-NEXT: li a1, 2 ; RV64-NEXT: bltu a0, a1, .LBB69_2 ; RV64-NEXT: # %bb.1: # %IfOverflow ; RV64-NEXT: li a0, 0 @@ -4251,8 +4250,9 @@ ; ; RV64ZBA-LABEL: uaddo.i64.constant_setcc_on_overflow_flag: ; RV64ZBA: # %bb.0: # %entry -; RV64ZBA-NEXT: ld a1, 0(a0) -; RV64ZBA-NEXT: addi a0, a1, 2 +; RV64ZBA-NEXT: ld a0, 0(a0) +; RV64ZBA-NEXT: addi a0, a0, 2 +; RV64ZBA-NEXT: li a1, 2 ; RV64ZBA-NEXT: bltu a0, a1, .LBB69_2 ; RV64ZBA-NEXT: # %bb.1: # %IfOverflow ; RV64ZBA-NEXT: li a0, 0