diff options
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 64 |
1 files changed, 16 insertions, 48 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fec51aa5ec6..2be03bd7f04 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1052,69 +1052,37 @@ Instruction *InstCombiner::FoldICmpCstShrCst(ICmpInst &I, Value *Op, Value *A, APInt AP1 = CI1->getValue(); APInt AP2 = CI2->getValue(); - if (!AP1) { - if (!AP2) { - // Both Constants are 0. - return getConstant(true); - } - - if (cast<BinaryOperator>(Op)->isExact()) - return getConstant(false); - - if (AP2.isNegative()) { - // MSB is set, so a lshr with a large enough 'A' would be undefined. - return getConstant(false); - } + assert(AP2 != 0 && "Handled in InstSimplify"); + assert(!AP2.isAllOnesValue() && "Handled in InstSimplify"); + if (!AP1) // 'A' must be large enough to shift out the highest set bit. return getICmp(I.ICMP_UGT, A, ConstantInt::get(A->getType(), AP2.logBase2())); - } - - if (!AP2) { - // Shifting 0 by any value gives 0. - return getConstant(false); - } - bool IsAShr = isa<AShrOperator>(Op); - if (AP1 == AP2) { - if (AP1.isAllOnesValue() && IsAShr) { - // Arithmatic shift of -1 is always -1. - return getConstant(true); - } + if (AP1 == AP2) return getICmp(I.ICMP_EQ, A, ConstantInt::getNullValue(A->getType())); - } - - bool IsNegative = false; - if (IsAShr) { - if (AP1.isNegative() != AP2.isNegative()) { - // Arithmetic shift will never change the sign. - return getConstant(false); - } - // Both the constants are negative, take their positive to calculate log. - if (AP1.isNegative()) { - if (AP1.slt(AP2)) - // Right-shifting won't increase the magnitude. - return getConstant(false); - IsNegative = true; - } - } - if (!IsNegative && AP1.ugt(AP2)) - // Right-shifting will not increase the value. - return getConstant(false); + bool IsAShr = isa<AShrOperator>(Op); + // If we are dealing with an arithmetic shift, both constants should agree in + // sign. InstSimplify's SimplifyICmpInst range analysis is supposed to catch + // the cases when they disagree. + assert((!IsAShr || (AP1.isNegative() == AP2.isNegative() && AP1.sgt(AP2))) && + "Handled in InstSimplify"); // Get the distance between the highest bit that's set. int Shift; - if (IsNegative) + // Both the constants are negative, take their positive to calculate log. + if (IsAShr && AP1.isNegative()) // Get the ones' complement of AP2 and AP1 when computing the distance. Shift = (~AP2).logBase2() - (~AP1).logBase2(); else Shift = AP2.logBase2() - AP1.logBase2(); - if (IsAShr ? AP1 == AP2.ashr(Shift) : AP1 == AP2.lshr(Shift)) - return getICmp(I.ICMP_EQ, A, ConstantInt::get(A->getType(), Shift)); - + if (Shift > 0) { + if (IsAShr ? AP1 == AP2.ashr(Shift) : AP1 == AP2.lshr(Shift)) + return getICmp(I.ICMP_EQ, A, ConstantInt::get(A->getType(), Shift)); + } // Shifting const2 will never be equal to const1. return getConstant(false); } |