From 02e2e1a226bfd31497aac199213e6966f29ace95 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 11 Sep 2018 22:40:20 +0000 Subject: [PATCH] [InstCombine] add folds for unsigned-overflow compares Name: op_ugt_sum %a = add i8 %x, %y %r = icmp ugt i8 %x, %a => %notx = xor i8 %x, -1 %r = icmp ugt i8 %y, %notx Name: sum_ult_op %a = add i8 %x, %y %r = icmp ult i8 %a, %x => %notx = xor i8 %x, -1 %r = icmp ugt i8 %y, %notx https://rise4fun.com/Alive/ZRxI AFAICT, this doesn't interfere with any add-saturation patterns because those have >1 use for the 'add'. But this should be better for IR analysis and codegen in the basic cases. This is another fold inspired by PR14613: https://bugs.llvm.org/show_bug.cgi?id=14613 llvm-svn: 342004 --- .../InstCombine/InstCombineCompares.cpp | 12 ++++++++++++ test/Transforms/InstCombine/icmp-add.ll | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index e8e9e86d08b..875d6d9f053 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3047,6 +3047,18 @@ Instruction *InstCombiner::foldICmpBinOp(ICmpInst &I) { return nullptr; const CmpInst::Predicate Pred = I.getPredicate(); + Value *X; + + // Convert add-with-unsigned-overflow comparisons into a 'not' with compare. + // (Op1 + X) ~Op1 u (Op0 + X) --> X >u ~Op0 + if (match(Op0, m_OneUse(m_c_Add(m_Specific(Op1), m_Value(X)))) && + Pred == ICmpInst::ICMP_ULT) + return new ICmpInst(Pred, Builder.CreateNot(Op1), X); + if (match(Op1, m_OneUse(m_c_Add(m_Specific(Op0), m_Value(X)))) && + Pred == ICmpInst::ICMP_UGT) + return new ICmpInst(Pred, X, Builder.CreateNot(Op0)); + bool NoOp0WrapProblem = false, NoOp1WrapProblem = false; if (BO0 && isa(BO0)) NoOp0WrapProblem = diff --git a/test/Transforms/InstCombine/icmp-add.ll b/test/Transforms/InstCombine/icmp-add.ll index 4fe31e78a2a..24593640af2 100644 --- a/test/Transforms/InstCombine/icmp-add.ll +++ b/test/Transforms/InstCombine/icmp-add.ll @@ -377,8 +377,8 @@ define i1 @op_ugt_sum_commute1(i8 %p1, i8 %p2) { ; CHECK-LABEL: @op_ugt_sum_commute1( ; CHECK-NEXT: [[X:%.*]] = sdiv i8 42, [[P1:%.*]] ; CHECK-NEXT: [[Y:%.*]] = sdiv i8 42, [[P2:%.*]] -; CHECK-NEXT: [[A:%.*]] = add i8 [[X]], [[Y]] -; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], -1 +; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[Y]], [[TMP1]] ; CHECK-NEXT: ret i1 [[C]] ; %x = sdiv i8 42, %p1 @@ -392,8 +392,8 @@ define <2 x i1> @op_ugt_sum_vec_commute2(<2 x i8> %p1, <2 x i8> %p2) { ; CHECK-LABEL: @op_ugt_sum_vec_commute2( ; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> , [[P1:%.*]] ; CHECK-NEXT: [[Y:%.*]] = sdiv <2 x i8> , [[P2:%.*]] -; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[Y]], [[X]] -; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i8> [[X]], [[A]] +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X]], +; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i8> [[Y]], [[TMP1]] ; CHECK-NEXT: ret <2 x i1> [[C]] ; %x = sdiv <2 x i8> , %p1 @@ -424,8 +424,8 @@ define <2 x i1> @sum_ult_op_vec_commute1(<2 x i8> %p1, <2 x i8> %p2) { ; CHECK-LABEL: @sum_ult_op_vec_commute1( ; CHECK-NEXT: [[X:%.*]] = sdiv <2 x i8> , [[P1:%.*]] ; CHECK-NEXT: [[Y:%.*]] = sdiv <2 x i8> , [[P2:%.*]] -; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X]], [[Y]] -; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i8> [[A]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X]], +; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i8> [[Y]], [[TMP1]] ; CHECK-NEXT: ret <2 x i1> [[C]] ; %x = sdiv <2 x i8> , %p1 @@ -439,8 +439,8 @@ define i1 @sum_ult_op_commute2(i8 %p1, i8 %p2) { ; CHECK-LABEL: @sum_ult_op_commute2( ; CHECK-NEXT: [[X:%.*]] = sdiv i8 42, [[P1:%.*]] ; CHECK-NEXT: [[Y:%.*]] = sdiv i8 42, [[P2:%.*]] -; CHECK-NEXT: [[A:%.*]] = add i8 [[Y]], [[X]] -; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[A]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], -1 +; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[Y]], [[TMP1]] ; CHECK-NEXT: ret i1 [[C]] ; %x = sdiv i8 42, %p1