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 =================================================================== --- /dev/null +++ llvm/test/Transforms/InstCombine/icmp-sub.ll @@ -0,0 +1,86 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +define i1 @test1(i64 %x) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 7 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nuw i64 10, %x + %z = icmp ult i64 %y, 3 + ret i1 %z +} + +define i1 @test2(i64 %x) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[X:%.*]], 7 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nsw i64 10, %x + %z = icmp sgt i64 %y, 3 + ret i1 %z +} + +define i1 @test3(i64 %x) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 6 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nuw nsw i64 10, %x + %z = icmp ule i64 %y, 3 + ret i1 %z +} + +define i1 @test4(i64 %x) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[Z:%.*]] = icmp sgt i64 [[X:%.*]], 7 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nuw nsw i64 10, %x + %z = icmp slt i64 %y, 3 + ret i1 %z +} + +define i1 @test5(i64 %x) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: [[Y:%.*]] = sub nuw i64 10, [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[Y]], 3 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nuw i64 10, %x + %z = icmp slt i64 %y, 3 + ret i1 %z +} + +define i1 @test6(i64 %x) { +; CHECK-LABEL: @test6( +; CHECK-NEXT: [[Y:%.*]] = sub nsw i64 10, [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 3 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nsw i64 10, %x + %z = icmp ult i64 %y, 3 + ret i1 %z +} + +define i1 @test7(i64 %x) { +; CHECK-LABEL: @test7( +; CHECK-NEXT: [[Y:%.*]] = sub nuw i64 10, [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 11 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nuw i64 10, %x + %z = icmp ult i64 %y, 11 + ret i1 %z +} + +define i1 @test8(i64 %x) { +; CHECK-LABEL: @test8( +; CHECK-NEXT: [[Y:%.*]] = sub nuw i64 10, [[X:%.*]] +; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[Y]], 11 +; CHECK-NEXT: ret i1 [[Z]] +; + %y = sub nuw i64 10, %x + %z = icmp ult i64 %y, 11 + ret i1 %z +}