diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -3137,9 +3137,18 @@ SDValue Sum = DAG.getNode(NoCarryOp, dl, LHS.getValueType(), LHS, RHS); SplitInteger(Sum, Lo, Hi); - // Calculate the overflow: addition overflows iff a + b < a, and subtraction - // overflows iff a - b > a. - Ovf = DAG.getSetCC(dl, N->getValueType(1), Sum, LHS, Cond); + if (N->getOpcode() == ISD::UADDO && isOneConstant(RHS)) { + // Special case: uaddo X, 1 overflowed if X+1 == 0. We can detect this + // with (Lo | Hi) == 0. + SDValue Or = DAG.getNode(ISD::OR, dl, Lo.getValueType(), Lo, Hi); + Ovf = DAG.getSetCC(dl, N->getValueType(1), Or, + DAG.getConstant(0, dl, Lo.getValueType()), + ISD::SETEQ); + } else { + // Calculate the overflow: addition overflows iff a + b < a, and + // subtraction overflows iff a - b > a. + Ovf = DAG.getSetCC(dl, N->getValueType(1), Sum, LHS, Cond); + } } // Legalized the flag result - switch anything that used the old flag to diff --git a/llvm/test/CodeGen/RISCV/overflow-intrinsics.ll b/llvm/test/CodeGen/RISCV/overflow-intrinsics.ll --- a/llvm/test/CodeGen/RISCV/overflow-intrinsics.ll +++ b/llvm/test/CodeGen/RISCV/overflow-intrinsics.ll @@ -519,16 +519,13 @@ define i1 @uaddo_i64_increment(i64 %x, ptr %p) { ; RV32-LABEL: uaddo_i64_increment: ; RV32: # %bb.0: -; RV32-NEXT: mv a3, a0 -; RV32-NEXT: addi a4, a0, 1 -; RV32-NEXT: sltu a0, a4, a0 -; RV32-NEXT: add a5, a1, a0 -; RV32-NEXT: bgeu a4, a3, .LBB12_2 -; RV32-NEXT: # %bb.1: -; RV32-NEXT: sltu a0, a5, a1 -; RV32-NEXT: .LBB12_2: -; RV32-NEXT: sw a4, 0(a2) -; RV32-NEXT: sw a5, 4(a2) +; RV32-NEXT: addi a3, a0, 1 +; RV32-NEXT: sltu a0, a3, a0 +; RV32-NEXT: add a1, a1, a0 +; RV32-NEXT: or a0, a3, a1 +; RV32-NEXT: seqz a0, a0 +; RV32-NEXT: sw a3, 0(a2) +; RV32-NEXT: sw a1, 4(a2) ; RV32-NEXT: ret ; ; RV64-LABEL: uaddo_i64_increment: 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 @@ -499,16 +499,13 @@ define zeroext i1 @uaddo.i64.constant_one(i64 %v1, ptr %res) { ; RV32-LABEL: uaddo.i64.constant_one: ; RV32: # %bb.0: # %entry -; RV32-NEXT: mv a3, a0 -; RV32-NEXT: addi a4, a0, 1 -; RV32-NEXT: sltu a0, a4, a0 -; RV32-NEXT: add a5, a1, a0 -; RV32-NEXT: bgeu a4, a3, .LBB11_2 -; RV32-NEXT: # %bb.1: # %entry -; RV32-NEXT: sltu a0, a5, a1 -; RV32-NEXT: .LBB11_2: # %entry -; RV32-NEXT: sw a4, 0(a2) -; RV32-NEXT: sw a5, 4(a2) +; RV32-NEXT: addi a3, a0, 1 +; RV32-NEXT: sltu a0, a3, a0 +; RV32-NEXT: add a1, a1, a0 +; RV32-NEXT: or a0, a3, a1 +; RV32-NEXT: seqz a0, a0 +; RV32-NEXT: sw a3, 0(a2) +; RV32-NEXT: sw a1, 4(a2) ; RV32-NEXT: ret ; ; RV64-LABEL: uaddo.i64.constant_one: @@ -520,16 +517,13 @@ ; ; RV32ZBA-LABEL: uaddo.i64.constant_one: ; RV32ZBA: # %bb.0: # %entry -; RV32ZBA-NEXT: mv a3, a0 -; RV32ZBA-NEXT: addi a4, a0, 1 -; RV32ZBA-NEXT: sltu a0, a4, a0 -; RV32ZBA-NEXT: add a5, a1, a0 -; RV32ZBA-NEXT: bgeu a4, a3, .LBB11_2 -; RV32ZBA-NEXT: # %bb.1: # %entry -; RV32ZBA-NEXT: sltu a0, a5, a1 -; RV32ZBA-NEXT: .LBB11_2: # %entry -; RV32ZBA-NEXT: sw a4, 0(a2) -; RV32ZBA-NEXT: sw a5, 4(a2) +; RV32ZBA-NEXT: addi a3, a0, 1 +; RV32ZBA-NEXT: sltu a0, a3, a0 +; RV32ZBA-NEXT: add a1, a1, a0 +; RV32ZBA-NEXT: or a0, a3, a1 +; RV32ZBA-NEXT: seqz a0, a0 +; RV32ZBA-NEXT: sw a3, 0(a2) +; RV32ZBA-NEXT: sw a1, 4(a2) ; RV32ZBA-NEXT: ret ; ; RV64ZBA-LABEL: uaddo.i64.constant_one: