[llvm] r177856 - InstCombine: simplify comparisons to zero of (shl %x, Cst) or (mul %x, Cst)
Arnaud A. de Grandmaison
arnaud.adegm at gmail.com
Mon Mar 25 04:49:55 PDT 2013
Committed as r177863.
Thanks Duncan,
--
Arnaud
On 03/25/2013 12:41 PM, Duncan Sands wrote:
> 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
>>
>>
>
--
Arnaud A. de Grandmaison
More information about the llvm-commits
mailing list