Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2321,6 +2321,16 @@ const APInt &C) { Value *X = Sub->getOperand(0), *Y = Sub->getOperand(1); ICmpInst::Predicate Pred = Cmp.getPredicate(); + const APInt *C2; + APInt SubResult; + + // (icmp P (sub nuw|nsw C2, Y), C) -> (icmp swap(P) Y, C2-C) + if (match(X, m_APInt(C2)) && + ((Cmp.isUnsigned() && Sub->hasNoUnsignedWrap()) || + (Cmp.isSigned() && Sub->hasNoSignedWrap())) && + !subWithOverflow(SubResult, *C2, C, Cmp.isSigned())) + return new ICmpInst(Cmp.getSwappedPredicate(), Y, + ConstantInt::get(Y->getType(), SubResult)); // The following transforms are only worth it if the only user of the subtract // is the icmp. @@ -2345,7 +2355,6 @@ return new ICmpInst(ICmpInst::ICMP_SLE, X, Y); } - const APInt *C2; if (!match(X, m_APInt(C2))) return nullptr; Index: llvm/test/Transforms/InstCombine/icmp-sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-sub.ll +++ llvm/test/Transforms/InstCombine/icmp-sub.ll @@ -3,8 +3,7 @@ define i1 @test_nuw_and_unsigned_pred(i64 %x) { ; CHECK-LABEL: @test_nuw_and_unsigned_pred( -; CHECK-NEXT: [[Y:%.*]] = sub nuw i64 10, [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 3 +; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 7 ; CHECK-NEXT: ret i1 [[Z]] ; %y = sub nuw i64 10, %x @@ -14,8 +13,7 @@ define i1 @test_nsw_and_signed_pred(i64 %x) { ; CHECK-LABEL: @test_nsw_and_signed_pred( -; CHECK-NEXT: [[Y:%.*]] = sub nsw i64 3, [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp sgt i64 [[Y]], 10 +; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[X:%.*]], -7 ; CHECK-NEXT: ret i1 [[Z]] ; %y = sub nsw i64 3, %x @@ -25,8 +23,7 @@ define i1 @test_nuw_nsw_and_unsigned_pred(i64 %x) { ; CHECK-LABEL: @test_nuw_nsw_and_unsigned_pred( -; CHECK-NEXT: [[Y:%.*]] = sub nuw nsw i64 10, [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 4 +; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 6 ; CHECK-NEXT: ret i1 [[Z]] ; %y = sub nuw nsw i64 10, %x @@ -36,8 +33,7 @@ define i1 @test_nuw_nsw_and_signed_pred(i64 %x) { ; CHECK-LABEL: @test_nuw_nsw_and_signed_pred( -; CHECK-NEXT: [[Y:%.*]] = sub nuw nsw i64 10, [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[Y]], 3 +; CHECK-NEXT: [[Z:%.*]] = icmp sgt i64 [[X:%.*]], 7 ; CHECK-NEXT: ret i1 [[Z]] ; %y = sub nuw nsw i64 10, %x