Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3392,6 +3392,21 @@ // the wrong spot, so use replaceInstUsesWith(). return replaceInstUsesWith(EV, NL); } + + if (WithOverflowInst *WO = dyn_cast(Agg)) { + Intrinsic::ID OvID = WO->getIntrinsicID(); + const APInt *C; + // Canonicalize: + // extractvalue (u[add|sub]_with_overflow X, Y), 0 -> [add|sub] X, Y + if (*EV.idx_begin() == 0 && + (OvID == Intrinsic::uadd_with_overflow || + OvID == Intrinsic::usub_with_overflow) && + match(WO->getArgOperand(1), m_APInt(C))) { + Instruction::BinaryOps BinOp = WO->getBinaryOp(); + Value *LHS = WO->getLHS(), *RHS = WO->getRHS(); + return BinaryOperator::Create(BinOp, LHS, RHS); + } + } // We could simplify extracts from other values. Note that nested extracts may // already be simplified implicitly by the above: extract (extract (insert) ) // will be translated into extract ( insert ( extract ) ) first and then just Index: llvm/test/Transforms/InstCombine/with_overflow.ll =================================================================== --- llvm/test/Transforms/InstCombine/with_overflow.ll +++ llvm/test/Transforms/InstCombine/with_overflow.ll @@ -432,10 +432,9 @@ define i1 @uadd_res_ult_const(i32 %x, i1* %p) nounwind { ; CHECK-LABEL: @uadd_res_ult_const( -; CHECK-NEXT: [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 42) -; CHECK-NEXT: [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1 +; CHECK-NEXT: [[B:%.*]] = icmp ugt i32 [[X]], -43 ; CHECK-NEXT: store i1 [[B]], i1* [[P:%.*]], align 1 -; CHECK-NEXT: [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1 +; CHECK-NEXT: [[D:%.*]] = icmp ugt i32 [[X]], -43 ; CHECK-NEXT: ret i1 [[D]] ; %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 42) @@ -448,10 +447,9 @@ define i1 @uadd_res_ult_const_one(i32 %x, i1* %p) nounwind { ; CHECK-LABEL: @uadd_res_ult_const_one( -; CHECK-NEXT: [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1) -; CHECK-NEXT: [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1 +; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[X]], -1 ; CHECK-NEXT: store i1 [[B]], i1* [[P:%.*]], align 1 -; CHECK-NEXT: [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1 +; CHECK-NEXT: [[D:%.*]] = icmp eq i32 [[X]], -1 ; CHECK-NEXT: ret i1 [[D]] ; %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1) @@ -464,10 +462,9 @@ define i1 @uadd_res_ult_const_minus_one(i32 %x, i1* %p) nounwind { ; CHECK-LABEL: @uadd_res_ult_const_minus_one( -; CHECK-NEXT: [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 -1) -; CHECK-NEXT: [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1 +; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[X]], 0 ; CHECK-NEXT: store i1 [[B]], i1* [[P:%.*]], align 1 -; CHECK-NEXT: [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1 +; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[X]], 0 ; CHECK-NEXT: ret i1 [[D]] ; %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 -1) @@ -478,6 +475,32 @@ ret i1 %d } +define i1 @uadd_res_ult_const_five_and_ov(i32 %x) nounwind { +; CHECK-LABEL: @uadd_res_ult_const_five_and_ov +; CHECK-NEXT: [[B:%.*]] = add i32 [[X]], 5 +; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[B]], 4 +; CHECK-NEXT: ret i1 [[C]] +; + %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 5) + %c = extractvalue { i32, i1 } %a, 0 + %b = extractvalue { i32, i1 } %a, 1 + %d = icmp ult i32 %c, 4 + %r = and i1 %d, %b + ret i1 %r +} + +define i1 @uadd_res_ugt_smaller_const_or_ov(i32 %x) nounwind { +; CHECK-LABEL: @uadd_res_ugt_smaller_const_or_ov( +; CHECK-NEXT: ret i1 true +; + %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 5) + %c = extractvalue { i32, i1 } %a, 0 + %b = extractvalue { i32, i1 } %a, 1 + %d = icmp ugt i32 %c, 4 + %r = or i1 %d, %b + ret i1 %r +} + define { i32, i1 } @sadd_canonicalize_constant_arg0(i32 %x) nounwind { ; CHECK-LABEL: @sadd_canonicalize_constant_arg0( ; CHECK-NEXT: [[A:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 42)