From bcca3be4b549ec3eaae7091d0d8e5513273cad97 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 5 Apr 2017 17:57:05 +0000 Subject: [PATCH] [InstCombine] add fold for icmp with or mask of low bits (PR32542) We already have these 'and' folds: // X & -C == -C -> X > u ~C // X & -C != -C -> X <= u ~C // iff C is a power of 2 ...but we were missing the 'or' siblings. http://rise4fun.com/Alive/n6 This should improve: https://bugs.llvm.org/show_bug.cgi?id=32524 ...but there are 2 or more other pieces to fix still. Differential Revision: https://reviews.llvm.org/D31712 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299570 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineCompares.cpp | 9 +++++++++ test/Transforms/InstCombine/icmp.ll | 13 +++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 69bc38e8c76..2419d4f3288 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1794,6 +1794,15 @@ Instruction *InstCombiner::foldICmpOrConstant(ICmpInst &Cmp, BinaryOperator *Or, ConstantInt::get(V->getType(), 1)); } + // X | C == C --> X <=u C + // X | C != C --> X >u C + // iff C+1 is a power of 2 (C is a bitmask of the low bits) + if (Cmp.isEquality() && Cmp.getOperand(1) == Or->getOperand(1) && + (*C + 1).isPowerOf2()) { + Pred = (Pred == CmpInst::ICMP_EQ) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT; + return new ICmpInst(Pred, Or->getOperand(0), Or->getOperand(1)); + } + if (!Cmp.isEquality() || *C != 0 || !Or->hasOneUse()) return nullptr; diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index c95257139a7..b1dc395b3d9 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1876,12 +1876,12 @@ define <2 x i1> @icmp_and_X_-16_ne-16_vec(<2 x i32> %X) { ret <2 x i1> %cmp } +; PR32524: https://bugs.llvm.org/show_bug.cgi?id=32524 ; X | C == C --> X <=u C (when C+1 is PowerOf2). define i1 @or1_eq1(i32 %x) { ; CHECK-LABEL: @or1_eq1( -; CHECK-NEXT: [[T0:%.*]] = or i32 %x, 1 -; CHECK-NEXT: [[T1:%.*]] = icmp eq i32 [[T0]], 1 +; CHECK-NEXT: [[T1:%.*]] = icmp ult i32 %x, 2 ; CHECK-NEXT: ret i1 [[T1]] ; %t0 = or i32 %x, 1 @@ -1893,8 +1893,7 @@ define i1 @or1_eq1(i32 %x) { define <2 x i1> @or3_eq3_vec(<2 x i8> %x) { ; CHECK-LABEL: @or3_eq3_vec( -; CHECK-NEXT: [[T0:%.*]] = or <2 x i8> %x, -; CHECK-NEXT: [[T1:%.*]] = icmp eq <2 x i8> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = icmp ult <2 x i8> %x, ; CHECK-NEXT: ret <2 x i1> [[T1]] ; %t0 = or <2 x i8> %x, @@ -1906,8 +1905,7 @@ define <2 x i1> @or3_eq3_vec(<2 x i8> %x) { define i1 @or7_ne7(i32 %x) { ; CHECK-LABEL: @or7_ne7( -; CHECK-NEXT: [[T0:%.*]] = or i32 %x, 7 -; CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 7 +; CHECK-NEXT: [[T1:%.*]] = icmp ugt i32 %x, 7 ; CHECK-NEXT: ret i1 [[T1]] ; %t0 = or i32 %x, 7 @@ -1919,8 +1917,7 @@ define i1 @or7_ne7(i32 %x) { define <2 x i1> @or63_ne63_vec(<2 x i8> %x) { ; CHECK-LABEL: @or63_ne63_vec( -; CHECK-NEXT: [[T0:%.*]] = or <2 x i8> %x, -; CHECK-NEXT: [[T1:%.*]] = icmp ne <2 x i8> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = icmp ugt <2 x i8> %x, ; CHECK-NEXT: ret <2 x i1> [[T1]] ; %t0 = or <2 x i8> %x,