Index: llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/trunk/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1545,6 +1545,18 @@ case TargetOpcode::G_CTTZ: case TargetOpcode::G_CTPOP: return lowerBitCount(MI, TypeIdx, Ty); + case G_UADDO: { + unsigned Res = MI.getOperand(0).getReg(); + unsigned CarryOut = MI.getOperand(1).getReg(); + unsigned LHS = MI.getOperand(2).getReg(); + unsigned RHS = MI.getOperand(3).getReg(); + + MIRBuilder.buildAdd(Res, LHS, RHS); + MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS); + + MI.eraseFromParent(); + return Legalized; + } case G_UADDE: { unsigned Res = MI.getOperand(0).getReg(); unsigned CarryOut = MI.getOperand(1).getReg(); Index: llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -32,7 +32,7 @@ .legalFor({s32}) .minScalar(0, s32); - getActionDefinitionsBuilder({G_UADDE, G_USUBO, G_USUBE}) + getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE}) .lowerFor({{s32, s1}}); getActionDefinitionsBuilder({G_LOAD, G_STORE}) Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/add.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/add.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/add.mir @@ -11,6 +11,7 @@ define void @add_i16_aext() {entry: ret void} define void @add_i64() {entry: ret void} define void @add_i128() {entry: ret void} + define void @uadd_with_overflow(i32 %lhs, i32 %rhs, i32* %padd, i1* %pcarry_flag) { ret void } ... --- @@ -334,3 +335,35 @@ RetRA implicit $v0, implicit $v1, implicit $a0, implicit $a1 ... +--- +name: uadd_with_overflow +alignment: 2 +tracksRegLiveness: true +body: | + bb.1 (%ir-block.0): + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: uadd_with_overflow + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(p0) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(p0) = COPY $a3 + ; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] + ; MIPS32: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY1]] + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ICMP]](s32) + ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; MIPS32: G_STORE [[AND]](s32), [[COPY3]](p0) :: (store 1 into %ir.pcarry_flag) + ; MIPS32: G_STORE [[ADD]](s32), [[COPY2]](p0) :: (store 4 into %ir.padd) + ; MIPS32: RetRA + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(p0) = COPY $a2 + %3:_(p0) = COPY $a3 + %4:_(s32), %5:_(s1) = G_UADDO %0, %1 + G_STORE %5(s1), %3(p0) :: (store 1 into %ir.pcarry_flag) + G_STORE %4(s32), %2(p0) :: (store 4 into %ir.padd) + RetRA + +... Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll @@ -160,3 +160,24 @@ %add = add i128 %b, %a ret i128 %add } + +declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) +define void @uadd_with_overflow(i32 %lhs, i32 %rhs, i32* %padd, i1* %pcarry_flag) { +; MIPS32-LABEL: uadd_with_overflow: +; MIPS32: # %bb.0: +; MIPS32-NEXT: addu $4, $4, $5 +; MIPS32-NEXT: sltu $5, $4, $5 +; MIPS32-NEXT: lui $1, 0 +; MIPS32-NEXT: ori $1, $1, 1 +; MIPS32-NEXT: and $1, $5, $1 +; MIPS32-NEXT: sb $1, 0($7) +; MIPS32-NEXT: sw $4, 0($6) +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop + %res = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %lhs, i32 %rhs) + %carry_flag = extractvalue { i32, i1 } %res, 1 + %add = extractvalue { i32, i1 } %res, 0 + store i1 %carry_flag, i1* %pcarry_flag + store i32 %add, i32* %padd + ret void +}