[PATCH] fix incorrect codegen from instcombine (PR17827)

Kay Tiong Khoo kkhoo at perfwizard.com
Mon Dec 2 10:53:14 PST 2013


Thanks, Evan. Committed as r196129.

After doing more testing with Z3 (see comments in the bug report), I made
the patch a bit more conservative for now. Will try to loosen the
constraints a bit after running more testing.

Bill, please consider this patch for inclusion with 3.4 if it's not too
late - it fixes a case where wrong codegen is produced.


On Sun, Dec 1, 2013 at 11:26 AM, Evan Cheng <evan.cheng at apple.com> wrote:

> Sorry about the delay. LGTM.
>
> Evan
> On Nov 25, 2013, at 10:55 AM, Kay Tiong Khoo <kkhoo at perfwizard.com> wrote:
>
> Thanks, Evan. Please see the revised patch here. I cached the opcode value
> in a local variable since we're using it all over the place. I also
> adjusted the if-check as you suggested and check each of the individual
> opcode cases rather than mixing 'isArithmeticShift' in there and assuming
> LShr on the last case.
>
> I'd certainly like to try some stronger verification for this and other
> bugs. I've cc'd you and Nuno on bug 17827 and hope to continue the
> discussion there.
>
> I don't think we should hold up this patch waiting for that though. I'd
> think this patch is also a 3.4 branch candidate since we're generating
> wrong code. Please let me know if you agree and if it's ok to commit.
>
> Thanks!
>
>
> Index: lib/Transforms/InstCombine/InstCombineCompares.cpp
> ===================================================================
> --- lib/Transforms/InstCombine/InstCombineCompares.cpp  (revision 195371)
> +++ lib/Transforms/InstCombine/InstCombineCompares.cpp  (working copy)
> @@ -1198,11 +1198,15 @@
>        Type *AndTy = AndCST->getType();          // Type of the and.
>
>        // We can fold this as long as we can't shift unknown bits
> -      // into the mask.  This can only happen with signed shift
> -      // rights, as they sign-extend.
> +      // into the mask. This can happen with signed shift
> +      // rights, as they sign-extend. With a left shift and a
> +      // signed comparison, we must also make sure that 'nsw' is
> +      // set on the shift because we are effectively changing the
> +      // position of the sign bit (PR17827).
>        if (ShAmt) {
> -        bool CanFold = Shift->isLogicalShift();
> -        if (!CanFold) {
> +        bool CanFold = false;
> +        unsigned ShiftOpcode = Shift->getOpcode();
> +        if (ShiftOpcode == Instruction::AShr) {
>            // To test for the bad case of the signed shr, see if any
>            // of the bits shifted in could be tested after the mask.
>            uint32_t TyBits = Ty->getPrimitiveSizeInBits();
> @@ -1212,19 +1216,22 @@
>            if ((APInt::getHighBitsSet(BitWidth, BitWidth-ShAmtVal) &
>                 AndCST->getValue()) == 0)
>              CanFold = true;
> +        } else if (ShiftOpcode == Instruction::Shl) {
> +          CanFold = Shift->hasNoSignedWrap() || !ICI.isSigned();
> +        } else if (ShiftOpcode == Instruction::LShr){
> +          CanFold = true;
>          }
>
>          if (CanFold) {
>            Constant *NewCst;
> -          if (Shift->getOpcode() == Instruction::Shl)
> +          if (ShiftOpcode == Instruction::Shl)
>              NewCst = ConstantExpr::getLShr(RHS, ShAmt);
>            else
>              NewCst = ConstantExpr::getShl(RHS, ShAmt);
>
>            // Check to see if we are shifting out any of the bits being
>            // compared.
> -          if (ConstantExpr::get(Shift->getOpcode(),
> -                                       NewCst, ShAmt) != RHS) {
> +          if (ConstantExpr::get(ShiftOpcode, NewCst, ShAmt) != RHS) {
>              // If we shifted bits out, the fold is not going to work out.
>              // As a special case, check to see if this means that the
>              // result is always true or false now.
> @@ -1235,7 +1242,7 @@
>            } else {
>              ICI.setOperand(1, NewCst);
>              Constant *NewAndCST;
> -            if (Shift->getOpcode() == Instruction::Shl)
> +            if (ShiftOpcode == Instruction::Shl)
>                NewAndCST = ConstantExpr::getLShr(AndCST, ShAmt);
>              else
>                NewAndCST = ConstantExpr::getShl(AndCST, ShAmt);
>
>
>
>
> On Thu, Nov 21, 2013 at 6:34 PM, Evan Cheng <evan.cheng at apple.com> wrote:
>
>> I looked at the analysis in the bug report and I think I agree with your
>> assessment. Perhaps you can use Nuno's technique to verify the optimization
>> with a SMT solver?
>>
>> As for the patch itself, (assuming the analysis is correct), the patch is
>> trivially correct. The only adjustment I would make is mechanical:
>>
>> +        } else { // logical shift left or right
>> +          if (Shift->getOpcode() == Instruction::Shl) {
>> +            CanFold = Shift->hasNoSignedWrap() || !ICI.isSigned();
>> +          } else { // logical shift right
>> +            CanFold = true;
>> +          }
>>          }
>>
>> I would have combined the else and the first if to
>> } else if (Shift->getOpcode() == Instruction::Shl) {
>>
>> Evan
>>
>> On Nov 21, 2013, at 11:46 AM, Kay Tiong Khoo <kkhoo at perfwizard.com>
>> wrote:
>>
>> Detailed description of problem in instcombine's compare optimizer:
>> http://llvm.org/bugs/show_bug.cgi?id=17827
>>
>> Fix suggested by Henrique Santos via dev mailing list:
>> http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-November/067822.html
>> <pr17827.patch>_______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>>
>>
> <pr17827_r2.patch>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131202/a55abdb5/attachment.html>


More information about the llvm-commits mailing list