From b43dd2f6c4a370f11a386dde73ad9bb51a0b6b5c Mon Sep 17 00:00:00 2001 From: Chenbing Zheng Date: Tue, 5 Jul 2022 17:14:22 +0800 Subject: [PATCH] [InstCombine] improve fold for icmp_eq_and to icmp_ult In D95959, the improve analysis for "C >> X" broken the fold ((%x & C) == 0) --> %x u< (-C) iff (-C) is power of two. It simplifies C, but fails to satisfy the fold condition. This patch try to restore C before the fold. Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D128790 --- .../InstCombine/InstCombineCompares.cpp | 11 ++++-- .../InstCombine/lshr-and-negC-icmpeq-zero.ll | 37 +++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 49951d19b0c3..acfab42d957d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1777,11 +1777,16 @@ Instruction *InstCombinerImpl::foldICmpAndConstConst(ICmpInst &Cmp, return new ICmpInst(NewPred, X, Zero); } + APInt NewC2 = *C2; + KnownBits Know = computeKnownBits(And->getOperand(0), 0, And); + // Set high zeros of C2 to allow matching negated power-of-2. + NewC2 = *C2 + APInt::getHighBitsSet(C2->getBitWidth(), + Know.countMinLeadingZeros()); + // Restrict this fold only for single-use 'and' (PR10267). // ((%x & C) == 0) --> %x u< (-C) iff (-C) is power of two. - if (C2->isNegatedPowerOf2()) { - Constant *NegBOC = - ConstantExpr::getNeg(cast(And->getOperand(1))); + if (NewC2.isNegatedPowerOf2()) { + Constant *NegBOC = ConstantInt::get(And->getType(), -NewC2); auto NewPred = isICMP_NE ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_ULT; return new ICmpInst(NewPred, X, NegBOC); } diff --git a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll index 0b4d6c7f0781..9f9cbb4a26a8 100644 --- a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll @@ -177,15 +177,10 @@ define i1 @scalar_lshr_and_negC_eq_extra_use_lshr_and(i32 %x, i32 %y, i32 %z, i3 ret i1 %r } -; Negative tests - -; TODO: This could be reduced to lshr+icmp ult. - define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant1(i32 %y) { ; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant1( ; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 12345, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 16376 -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[LSHR]], 8 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 12345, %y @@ -194,13 +189,9 @@ define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant1(i32 %y) { ret i1 %r } -; TODO: This could be reduced to lshr+icmp ult. - define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) { ; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant2( -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 268435456, [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 536870904 -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[Y:%.*]], 25 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 268435456, %y @@ -208,7 +199,31 @@ define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant2(i32 %y) { %r = icmp eq i32 %and, 0 ret i1 %r } +define i1 @scalar_i32_udiv_and_negC_eq_X_is_constant3(i32 %y) { +; CHECK-LABEL: @scalar_i32_udiv_and_negC_eq_X_is_constant3( +; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y:%.*]], 1544 +; CHECK-NEXT: ret i1 [[R]] +; + %lshr = udiv i32 12345, %y + %and = and i32 %lshr, 16376 ; 0x3ff8 + %r = icmp ne i32 %and, 0 + ret i1 %r +} +; Negative test + +define i1 @scalar_i32_lshr_and_negC_eq_X_is_constant_negtive(i32 %y) { +; CHECK-LABEL: @scalar_i32_lshr_and_negC_eq_X_is_constant_negtive( +; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 16384, [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 16376 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %lshr = lshr i32 16384, %y ; 0x4000 + %and = and i32 %lshr, 16376 ; 0x3ff8 + %r = icmp eq i32 %and, 0 + ret i1 %r +} ; Check 'slt' predicate define i1 @scalar_i32_lshr_and_negC_slt(i32 %x, i32 %y) {