diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2771,6 +2771,11 @@ Type *Ty = Add->getType(); const CmpInst::Predicate Pred = Cmp.getPredicate(); + // If add has multiple uses then no need to combine because a comparison with + // zero is cheaper than with non zero. + if (!Add->hasOneUse() && C.isZero()) + return nullptr; + // If the add does not wrap, we can always adjust the compare by subtracting // the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE // are canonicalized to SGT/SLT/UGT/ULT. diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -93,6 +93,24 @@ ret { i32, i1 } %res } +define { i32, i1 } @test4multiuse_with_zero(i32 %a) { +; CHECK-LABEL: @test4multiuse_with_zero( +; CHECK-NEXT: [[B:%.*]] = add nsw i32 [[A:%.*]], -2147483644 +; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[B]], 0 +; CHECK-NEXT: [[TMP:%.*]] = insertvalue { i32, i1 } undef, i32 [[B]], 0 +; CHECK-NEXT: [[RES:%.*]] = insertvalue { i32, i1 } [[TMP]], i1 [[C]], 1 +; CHECK-NEXT: ret { i32, i1 } [[RES]] +; + + %b = add nsw i32 %a, -2147483644 + %c = icmp slt i32 %b, 0 + + %tmp = insertvalue { i32, i1 } undef, i32 %b, 0 + %res = insertvalue { i32, i1 } %tmp, i1 %c, 1 + + ret { i32, i1 } %res +} + define <2 x i1> @test4vec(<2 x i32> %a) { ; CHECK-LABEL: @test4vec( ; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> [[A:%.*]], diff --git a/llvm/test/Transforms/PhaseOrdering/loop-rotation-vs-common-code-hoisting.ll b/llvm/test/Transforms/PhaseOrdering/loop-rotation-vs-common-code-hoisting.ll --- a/llvm/test/Transforms/PhaseOrdering/loop-rotation-vs-common-code-hoisting.ll +++ b/llvm/test/Transforms/PhaseOrdering/loop-rotation-vs-common-code-hoisting.ll @@ -69,21 +69,19 @@ ; ROTATE-NEXT: [[CMP:%.*]] = icmp slt i32 [[WIDTH:%.*]], 1 ; ROTATE-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[FOR_COND_PREHEADER:%.*]] ; ROTATE: for.cond.preheader: -; ROTATE-NEXT: [[CMP13_NOT:%.*]] = icmp eq i32 [[WIDTH]], 1 -; ROTATE-NEXT: br i1 [[CMP13_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PREHEADER:%.*]] -; ROTATE: for.body.preheader: -; ROTATE-NEXT: [[TMP0:%.*]] = add i32 [[WIDTH]], -2 -; ROTATE-NEXT: br label [[FOR_BODY:%.*]] +; ROTATE-NEXT: [[SUB:%.*]] = add nsw i32 [[WIDTH]], -1 +; ROTATE-NEXT: [[CMP13_NOT:%.*]] = icmp eq i32 [[SUB]], 0 +; ROTATE-NEXT: br i1 [[CMP13_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]] ; ROTATE: for.cond.cleanup: ; ROTATE-NEXT: tail call void @f0() ; ROTATE-NEXT: tail call void @f2() ; ROTATE-NEXT: br label [[RETURN]] ; ROTATE: for.body: -; ROTATE-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; ROTATE-NEXT: [[I_04:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER:%.*]] ] ; ROTATE-NEXT: tail call void @f0() ; ROTATE-NEXT: tail call void @f1() ; ROTATE-NEXT: [[INC]] = add nuw nsw i32 [[I_04]], 1 -; ROTATE-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[I_04]], [[TMP0]] +; ROTATE-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[SUB]] ; ROTATE-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] ; ROTATE: return: ; ROTATE-NEXT: ret void