[llvm] r177856 - InstCombine: simplify comparisons to zero of (shl %x, Cst) or (mul %x, Cst)
Duncan Sands
baldrick at free.fr
Mon Mar 25 04:41:39 PDT 2013
Hi Arnaud, LGTM.
Ciao, Duncan.
On 25/03/13 12:31, Arnaud A. de Grandmaison wrote:
> On 03/25/2013 11:22 AM, Duncan Sands wrote:
>> Hi Arnaud,
>>
>
> Hi Duncan,
>
>>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
>> (original)
>>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Mon
>>> Mar 25 04:48:49 2013
>>> @@ -139,6 +139,42 @@ static bool isSignBitCheck(ICmpInst::Pre
>>> }
>>> }
>>>
>>> +/// Returns true if the exploded icmp can be expressed as a
>>> comparison to zero
>>> +/// and update the predicate accordingly. The signedness of the
>>> comparison is
>>
>> This comment is incomplete.
>>
>
> Fixed.
>
>>> +static bool isSignTest(ICmpInst::Predicate &pred, const ConstantInt
>>> *RHS) {
>>> + if (!ICmpInst::isSigned(pred))
>>> + return false;
>>> +
>>> + if (RHS->isZero())
>>> + return true;
>>> +
>>> + if (RHS->isOne())
>>> + switch (pred) {
>>> + case ICmpInst::ICMP_SGE:
>>
>> Is this case needed? I thought instcombine normalized SGE to SGT
>> whenever
>> possible. Likewise for SLE below.
>>
>
> I was not aware of this invariant. I removed those cases and the tests
> still passes, so the invariant seems to hold :) This does simplify the
> routine.
>
>>> + pred = ICmpInst::ICMP_SGT;
>>> + return true;
>>> + case ICmpInst::ICMP_SLT:
>>> + pred = ICmpInst::ICMP_SLE;
>>> + return true;
>>> + default:
>>> + return false;
>>> + }
>>> +
>>> + if (RHS->isAllOnesValue())
>>> + switch (pred) {
>>> + case ICmpInst::ICMP_SLE:
>>> + pred = ICmpInst::ICMP_SLT;
>>> + return true;
>>> + case ICmpInst::ICMP_SGT:
>>> + pred = ICmpInst::ICMP_SGE;
>>> + return true;
>>> + default:
>>> + return false;
>>> + }
>>> +
>>> + return false;
>>> +}
>>> +
>>> // isHighOnes - Return true if the constant is of the form 1+0+.
>>> // This is the same as lowones(~X).
>>> static bool isHighOnes(const ConstantInt *CI) {
>>> @@ -1282,6 +1318,25 @@ Instruction *InstCombiner::visitICmpInst
>>> break;
>>> }
>>>
>>> + case Instruction::Mul: { // (icmp pred (mul X, Val), CI)
>>> + ConstantInt *Val = dyn_cast<ConstantInt>(LHSI->getOperand(1));
>>> + if (!Val) break;
>>> +
>>> + if (!ICI.isEquality()) {
>>
>> Is this check needed? Won't the isSignTest check take care of it? If
>> not, it
>> probably should.
>
> I addressed this in the rework of isSignTest.
>
>>
>>> + // If this is a signed comparison to 0 and the mul is sign
>>> preserving,
>>> + // use the mul LHS operand instead.
>>> + ICmpInst::Predicate pred = ICI.getPredicate();
>>> + if (isSignTest(pred, RHS) && !Val->isZero() &&
>>> + cast<BinaryOperator>(LHSI)->hasNoSignedWrap())
>>> + return new ICmpInst(Val->isNegative() ?
>>> +
>>> ICmpInst::getSwappedPredicate(pred) : pred,
>>> + LHSI->getOperand(0),
>>> + Constant::getNullValue(RHS->getType()));
>>> + }
>>> +
>>> + break;
>>> + }
>>> +
>>> case Instruction::Shl: { // (icmp pred (shl X, ShAmt), CI)
>>> ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
>>> if (!ShAmt) break;
>>> @@ -1541,6 +1611,19 @@ Instruction *InstCombiner::visitICmpInst
>>> return new ICmpInst(pred, X, NegX);
>>> }
>>> }
>>> + break;
>>> + case Instruction::Mul:
>>> + if (RHSV == 0) {
>>> + if (ConstantInt *BOC =
>>> dyn_cast<ConstantInt>(BO->getOperand(1))) {
>>> + // The trivial case (mul X, 0) is handled by InstSimplify
>>> + // General case : (mul X, C) != 0 iff X != 0
>>> + // (mul X, C) == 0 iff X == 0
>>> + if (!BOC->isZero())
>>> + return new ICmpInst(ICI.getPredicate(),
>>> BO->getOperand(0),
>>> +
>>> Constant::getNullValue(RHS->getType()));
>>
>> Looks like you forgot to check for nsw here.
>
> Fixed.
>
>>
>> Ciao, Duncan.
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
More information about the llvm-commits
mailing list