diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1767,11 +1767,19 @@ return new ICmpInst(NewPred, X, Zero); } + const APInt *C3; + APInt newC2 = *C2; + // If if one of And's operands is lshr, ValueTracking will simplify the + // other constant of 'And'. It will break the fold below. + if (match(And->getOperand(0), m_LShr(m_APInt(C3), m_Value()))) { + newC2 = *C2 + + APInt::getHighBitsSet(C2->getBitWidth(), C3->countLeadingZeros()); + } + // Restrict this fold only for single-use 'and' (PR10267). // ((%x & C) == 0) --> %x u< (-C) iff (-C) is power of two. - if ((~(*C2) + 1).isPowerOf2()) { - Constant *NegBOC = - ConstantExpr::getNeg(cast(And->getOperand(1))); + if ((~(newC2) + 1).isPowerOf2()) { + 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 --- 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 @@ 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,10 @@ 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 ult i32 [[LSHR]], 8 ; CHECK-NEXT: ret i1 [[R]] ; %lshr = lshr i32 268435456, %y