[llvm] r290733 - [InstCombine] More thoroughly canonicalize the position of zexts

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 12 13:33:32 PST 2017


Have any tests been added for these transforms?

On Thu, Dec 29, 2016 at 8:47 PM, David Majnemer via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Addressed in r290741, thanks.
>
> On Thu, Dec 29, 2016 at 5:18 PM, Craig Topper <craig.topper at gmail.com>
> wrote:
>
>> Why does (add (zext x), cst) --> (zext (add x, cst')) check for signed
>> overflow but then create an NUW add. That's not valid is it?
>>
>> ~Craig
>>
>> On Thu, Dec 29, 2016 at 4:28 PM, David Majnemer via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>>
>>> Author: majnemer
>>> Date: Thu Dec 29 18:28:58 2016
>>> New Revision: 290733
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=290733&view=rev
>>> Log:
>>> [InstCombine] More thoroughly canonicalize the position of zexts
>>>
>>> We correctly canonicalized (add (sext x), (sext y)) to (sext (add x, y))
>>> where possible.  However, we didn't perform the same canonicalization
>>> for zexts or for muls.
>>>
>>> Modified:
>>>     llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
>>>     llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
>>>
>>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/InstCombine/InstCombineAddSub.cpp?rev=290733&r1=290732&r2=
>>> 290733&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp
>>> (original)
>>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAddSub.cpp Thu Dec
>>> 29 18:28:58 2016
>>> @@ -1226,15 +1226,16 @@ Instruction *InstCombiner::visitAdd(Bina
>>>    if (SExtInst *LHSConv = dyn_cast<SExtInst>(LHS)) {
>>>      // (add (sext x), cst) --> (sext (add x, cst'))
>>>      if (ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS)) {
>>> -      Constant *CI =
>>> -        ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getTyp
>>> e());
>>> -      if (LHSConv->hasOneUse() &&
>>> -          ConstantExpr::getSExt(CI, I.getType()) == RHSC &&
>>> -          WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) {
>>> -        // Insert the new, smaller add.
>>> -        Value *NewAdd = Builder->CreateNSWAdd(LHSConv->getOperand(0),
>>> -                                              CI, "addconv");
>>> -        return new SExtInst(NewAdd, I.getType());
>>> +      if (LHSConv->hasOneUse()) {
>>> +        Constant *CI =
>>> +            ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getTyp
>>> e());
>>> +        if (ConstantExpr::getSExt(CI, I.getType()) == RHSC &&
>>> +            WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) {
>>> +          // Insert the new, smaller add.
>>> +          Value *NewAdd =
>>> +              Builder->CreateNSWAdd(LHSConv->getOperand(0), CI,
>>> "addconv");
>>> +          return new SExtInst(NewAdd, I.getType());
>>> +        }
>>>        }
>>>      }
>>>
>>> @@ -1255,6 +1256,43 @@ Instruction *InstCombiner::visitAdd(Bina
>>>        }
>>>      }
>>>    }
>>> +
>>> +  // Check for (add (zext x), y), see if we can merge this into an
>>> +  // integer add followed by a zext.
>>> +  if (auto *LHSConv = dyn_cast<ZExtInst>(LHS)) {
>>> +    // (add (zext x), cst) --> (zext (add x, cst'))
>>> +    if (ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS)) {
>>> +      if (LHSConv->hasOneUse()) {
>>> +        Constant *CI =
>>> +            ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getTyp
>>> e());
>>> +        if (ConstantExpr::getZExt(CI, I.getType()) == RHSC &&
>>> +            WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) {
>>> +          // Insert the new, smaller add.
>>> +          Value *NewAdd =
>>> +              Builder->CreateNUWAdd(LHSConv->getOperand(0), CI,
>>> "addconv");
>>> +          return new ZExtInst(NewAdd, I.getType());
>>> +        }
>>> +      }
>>> +    }
>>> +
>>> +    // (add (zext x), (zext y)) --> (zext (add int x, y))
>>> +    if (auto *RHSConv = dyn_cast<ZExtInst>(RHS)) {
>>> +      // Only do this if x/y have the same type, if at last one of them
>>> has a
>>> +      // single use (so we don't increase the number of zexts), and if
>>> the
>>> +      // integer add will not overflow.
>>> +      if (LHSConv->getOperand(0)->getType() ==
>>> +              RHSConv->getOperand(0)->getType() &&
>>> +          (LHSConv->hasOneUse() || RHSConv->hasOneUse()) &&
>>> +          computeOverflowForUnsignedAdd(LHSConv->getOperand(0),
>>> +                                        RHSConv->getOperand(0),
>>> +                                        &I) ==
>>> OverflowResult::NeverOverflows) {
>>> +        // Insert the new integer add.
>>> +        Value *NewAdd = Builder->CreateNUWAdd(
>>> +            LHSConv->getOperand(0), RHSConv->getOperand(0), "addconv");
>>> +        return new ZExtInst(NewAdd, I.getType());
>>> +      }
>>> +    }
>>> +  }
>>>
>>>    // (add (xor A, B) (and A, B)) --> (or A, B)
>>>    {
>>>
>>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transform
>>> s/InstCombine/InstCombineMulDivRem.cpp?rev=290733&r1=290732&
>>> r2=290733&view=diff
>>> ============================================================
>>> ==================
>>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
>>> (original)
>>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Thu
>>> Dec 29 18:28:58 2016
>>> @@ -389,6 +389,79 @@ Instruction *InstCombiner::visitMul(Bina
>>>      }
>>>    }
>>>
>>> +  // Check for (mul (sext x), y), see if we can merge this into an
>>> +  // integer mul followed by a sext.
>>> +  if (SExtInst *Op0Conv = dyn_cast<SExtInst>(Op0)) {
>>> +    // (mul (sext x), cst) --> (sext (mul x, cst'))
>>> +    if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
>>> +      if (Op0Conv->hasOneUse()) {
>>> +        Constant *CI =
>>> +            ConstantExpr::getTrunc(Op1C, Op0Conv->getOperand(0)->getTyp
>>> e());
>>> +        if (ConstantExpr::getSExt(CI, I.getType()) == Op1C &&
>>> +            WillNotOverflowSignedMul(Op0Conv->getOperand(0), CI, I)) {
>>> +          // Insert the new, smaller mul.
>>> +          Value *NewMul =
>>> +              Builder->CreateNSWMul(Op0Conv->getOperand(0), CI,
>>> "mulconv");
>>> +          return new SExtInst(NewMul, I.getType());
>>> +        }
>>> +      }
>>> +    }
>>> +
>>> +    // (mul (sext x), (sext y)) --> (sext (mul int x, y))
>>> +    if (SExtInst *Op1Conv = dyn_cast<SExtInst>(Op1)) {
>>> +      // Only do this if x/y have the same type, if at last one of them
>>> has a
>>> +      // single use (so we don't increase the number of sexts), and if
>>> the
>>> +      // integer mul will not overflow.
>>> +      if (Op0Conv->getOperand(0)->getType() ==
>>> +              Op1Conv->getOperand(0)->getType() &&
>>> +          (Op0Conv->hasOneUse() || Op1Conv->hasOneUse()) &&
>>> +          WillNotOverflowSignedMul(Op0Conv->getOperand(0),
>>> +                                   Op1Conv->getOperand(0), I)) {
>>> +        // Insert the new integer mul.
>>> +        Value *NewMul = Builder->CreateNSWMul(
>>> +            Op0Conv->getOperand(0), Op1Conv->getOperand(0), "mulconv");
>>> +        return new SExtInst(NewMul, I.getType());
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +  // Check for (mul (zext x), y), see if we can merge this into an
>>> +  // integer mul followed by a zext.
>>> +  if (auto *Op0Conv = dyn_cast<ZExtInst>(Op0)) {
>>> +    // (mul (zext x), cst) --> (zext (mul x, cst'))
>>> +    if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
>>> +      if (Op0Conv->hasOneUse()) {
>>> +        Constant *CI =
>>> +            ConstantExpr::getTrunc(Op1C, Op0Conv->getOperand(0)->getTyp
>>> e());
>>> +        if (ConstantExpr::getZExt(CI, I.getType()) == Op1C &&
>>> +            WillNotOverflowSignedMul(Op0Conv->getOperand(0), CI, I)) {
>>> +          // Insert the new, smaller mul.
>>> +          Value *NewMul =
>>> +              Builder->CreateNUWMul(Op0Conv->getOperand(0), CI,
>>> "mulconv");
>>> +          return new ZExtInst(NewMul, I.getType());
>>> +        }
>>> +      }
>>> +    }
>>> +
>>> +    // (mul (zext x), (zext y)) --> (zext (mul int x, y))
>>> +    if (auto *Op1Conv = dyn_cast<ZExtInst>(Op1)) {
>>> +      // Only do this if x/y have the same type, if at last one of them
>>> has a
>>> +      // single use (so we don't increase the number of zexts), and if
>>> the
>>> +      // integer mul will not overflow.
>>> +      if (Op0Conv->getOperand(0)->getType() ==
>>> +              Op1Conv->getOperand(0)->getType() &&
>>> +          (Op0Conv->hasOneUse() || Op1Conv->hasOneUse()) &&
>>> +          computeOverflowForUnsignedMul(Op0Conv->getOperand(0),
>>> +                                        Op1Conv->getOperand(0),
>>> +                                        &I) ==
>>> OverflowResult::NeverOverflows) {
>>> +        // Insert the new integer mul.
>>> +        Value *NewMul = Builder->CreateNUWMul(
>>> +            Op0Conv->getOperand(0), Op1Conv->getOperand(0), "mulconv");
>>> +        return new ZExtInst(NewMul, I.getType());
>>> +      }
>>> +    }
>>> +  }
>>> +
>>>    if (!I.hasNoSignedWrap() && WillNotOverflowSignedMul(Op0, Op1, I)) {
>>>      Changed = true;
>>>      I.setHasNoSignedWrap(true);
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>>
>>
>>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170112/91fdc053/attachment.html>


More information about the llvm-commits mailing list