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
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:
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:
;
; 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: