From: Luqman Aden Date: Thu, 4 Apr 2019 07:08:30 +0000 (+0000) Subject: [InstCombine] Combine no-wrap sub and icmp w/ constant. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0f925da273a9d9f7806487bbf208f22eb37c0cd2;p=llvm [InstCombine] Combine no-wrap sub and icmp w/ constant. Teach InstCombine the transformation `(icmp P (sub nuw|nsw C2, Y), C) -> (icmp swap(P) Y, C2-C)` Reviewers: majnemer, apilipenko, sanjoy, spatel, lebedev.ri Reviewed By: lebedev.ri Subscribers: dmgreen, lebedev.ri, nikic, hiraditya, JDevlieghere, jfb, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59916 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357674 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index dc2672537aa..7b589280593 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2321,6 +2321,16 @@ Instruction *InstCombiner::foldICmpSubConstant(ICmpInst &Cmp, 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 @@ Instruction *InstCombiner::foldICmpSubConstant(ICmpInst &Cmp, return new ICmpInst(ICmpInst::ICMP_SLE, X, Y); } - const APInt *C2; if (!match(X, m_APInt(C2))) return nullptr; diff --git a/test/Transforms/InstCombine/icmp-sub.ll b/test/Transforms/InstCombine/icmp-sub.ll index e9fbec9068d..c66581b3b5a 100644 --- a/test/Transforms/InstCombine/icmp-sub.ll +++ b/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_nuw_and_unsigned_pred(i64 %x) { 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_nsw_and_signed_pred(i64 %x) { 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_unsigned_pred(i64 %x) { 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