[llvm] r335020 - [SimplifyIndVars] Eliminate redundant truncs

Maxim Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 27 02:57:12 PDT 2018


Please let me know if you still see a failure like this with the fix patch in tree. I'm suspecting that there can be another bug (a general one in this algorithm), but have no proof nor that it exists neither that it doesn't. :)

-----Original Message-----
From: Mikael Holmén [mailto:mikael.holmen at ericsson.com] 
Sent: Monday, August 27, 2018 4:24 PM
To: Maxim Kazantsev <max.kazantsev at azul.com>
Cc: llvm-commits at lists.llvm.org
Subject: Re: [llvm] r335020 - [SimplifyIndVars] Eliminate redundant truncs

Hi,

On 08/27/2018 09:59 AM, Maxim Kazantsev wrote:
> Hi Mikael,
> 
> That's a nasty case, maybe more than one case. :) I was able to fix this particular situation with https://reviews.llvm.org/D51286, but it's not clear for me why underlying algorithm is expected to preserve LCSSA. I will dig a bit more and try to construct something more tricky which will expose the problem.
> 

Great!

Csmith-generated programs combined with running random optimizations in random order seems to be able to trigger many nasty (and sometimes totally weird) situations...

The crash went away with the patch and I ran a few other local tests on my out-of-tree target too without finding anything odd so it's looking good.

Thanks,
Mikael

> -- Max
> 
> -----Original Message-----
> From: Mikael Holmén [mailto:mikael.holmen at ericsson.com]
> Sent: Thursday, August 23, 2018 12:40 PM
> To: Maxim Kazantsev <max.kazantsev at azul.com>
> Cc: llvm-commits at lists.llvm.org
> Subject: Re: [llvm] r335020 - [SimplifyIndVars] Eliminate redundant 
> truncs
> 
> Hi,
> 
> On 08/23/2018 04:18 AM, Maxim Kazantsev wrote:
>> Hi Mikael,
>>
>> Thanks for finding this! Looks like a completely different issue,
>> rL335816 was against another assertion failure. Could you please file 
>> this on bugs.llvm.org? I cannot take a look into it today, but will 
>> do it within next couple of days unless someone else will pick it up 
>> faster than me. :)
>>
> 
> Sure, here's the PR:
>    https://bugs.llvm.org/show_bug.cgi?id=38674
> 
> Thanks,
> Mikael
> 
>> -- Max
>>
>> -----Original Message-----
>> From: Mikael Holmén [mailto:mikael.holmen at ericsson.com]
>> Sent: Wednesday, August 22, 2018 8:41 PM
>> To: Maxim Kazantsev <max.kazantsev at azul.com>
>> Cc: llvm-commits at lists.llvm.org
>> Subject: Re: [llvm] r335020 - [SimplifyIndVars] Eliminate redundant 
>> truncs
>>
>> Hi again!
>>
>> I found another case which starts crashing with r335020. (It seems to 
>> be something else than the previous crash so r335816 doesn't help.)
>>
>> opt -S -o - bbi-16913.ll -indvars
>>
>> crashes with
>>
>> opt: ../lib/Transforms/Scalar/IndVarSimplify.cpp:2519: bool (anonymous namespace)::IndVarSimplify::run(llvm::Loop *): Assertion `L->isRecursivelyLCSSAForm(*DT, *LI) && "Indvars did not preserve LCSSA!"' failed.
>>
>> The function looks like this when the assertion fails
>>
>> define i32 @f1() {
>> entry:
>>      br label %for.cond1.preheader
>>
>> for.cond1.preheader:                              ; preds = %for.end9,
>> %entry
>>      br label %for.cond4.preheader
>>
>> for.cond4.preheader:                              ; preds = %for.end,
>> %for.cond1.preheader
>>      %zext = zext i16 1 to i32
>>      br label %for.body6
>>
>> for.cond4:                                        ; preds = %for.body6
>>      %cmp5 = icmp ult i32 %inc, 2
>>      br i1 %cmp5, label %for.body6, label %for.end
>>
>> for.body6:                                        ; preds = %for.cond4,
>> %for.cond4.preheader
>>      %storemerge26 = phi i32 [ 0, %for.cond4.preheader ], [ %inc, %for.cond4 ]
>>      %0 = icmp eq i32 %storemerge26, %zext
>>      %inc = add nuw nsw i32 %storemerge26, 1
>>      br i1 %0, label %return.loopexit, label %for.cond4
>>
>> for.end:                                          ; preds = %for.cond4
>>      br i1 false, label %for.cond4.preheader, label %for.end9
>>
>> for.end9:                                         ; preds = %for.end
>>      br i1 false, label %for.cond1.preheader, label %return.loopexit3
>>
>> return.loopexit:                                  ; preds = %for.body6
>>      unreachable
>>
>> return.loopexit3:                                 ; preds = %for.end9
>>      %inc11.lcssa = phi i32 [ %zext, %for.end9 ]
>>      br label %return
>>
>> return:                                           ; preds =
>> %return.loopexit3
>>      ret i32 %inc11.lcssa
>> }
>>
>> Regards,
>> Mikael
>>
>> On 06/28/2018 10:37 AM, Mikael Holmén via llvm-commits wrote:
>>>
>>>
>>> On 06/28/2018 10:27 AM, Maxim Kazantsev wrote:
>>>> Yes indeed. I think we also have some other pieces of code that get 
>>>> pessimized by such users (i.e. some transform is rejected because 
>>>> of some bad user). It would be interesting to look for such cases.
>>>>
>>>> BTW, the assertion failire should be gone with
>>>> https://reviews.llvm.org/rL335816 .
>>>>
>>>
>>> Yep!
>>>
>>> Thanks,
>>> Mikael
>>>
>>>> -----Original Message-----
>>>> From: Mikael Holmén [mailto:mikael.holmen at ericsson.com]
>>>> Sent: Thursday, June 28, 2018 2:58 PM
>>>> To: Maxim Kazantsev <max.kazantsev at azul.com>
>>>> Cc: llvm-commits at lists.llvm.org
>>>> Subject: Re: [llvm] r335020 - [SimplifyIndVars] Eliminate redundant 
>>>> truncs
>>>>
>>>>
>>>>
>>>> On 06/28/2018 09:47 AM, Maxim Kazantsev wrote:
>>>>> Interesting. A user in block unreachable from entry, I didn't 
>>>>> think we can end up with something like this. :) I'll come up with 
>>>>> a fix soon. Thanks for test!
>>>>
>>>> Yes I don't know how many problems I've stumbled upon now due to 
>>>> weird code in blocks that are unreachable from entry that several 
>>>> passes then flips out on.
>>>>
>>>> I hope the gain from allowing such code is huge since there are 
>>>> certainly many problems with it.
>>>>
>>>> Thanks,
>>>> Mikael
>>>>
>>>>>
>>>>> -- Max
>>>>>
>>>>> -----Original Message-----
>>>>> From: Mikael Holmén [mailto:mikael.holmen at ericsson.com]
>>>>> Sent: Thursday, June 28, 2018 2:34 PM
>>>>> To: Maxim Kazantsev <max.kazantsev at azul.com>
>>>>> Cc: llvm-commits at lists.llvm.org
>>>>> Subject: Re: [llvm] r335020 - [SimplifyIndVars] Eliminate 
>>>>> redundant truncs
>>>>>
>>>>> Hi Max,
>>>>>
>>>>> With
>>>>>
>>>>>       opt -S -o - bbi-15696.ll -indvars
>>>>>
>>>>> I trigger one of the new asserts in this patch:
>>>>>
>>>>> opt: ../lib/Transforms/Utils/SimplifyIndVar.cpp:540: bool 
>>>>> (anonymous namespace)::SimplifyIndvar::eliminateTrunc(llvm::TruncInst *):
>>>>> Assertion
>>>>> `L->contains(ICI->getParent()) && "LCSSA form broken?"' failed.
>>>>> Stack dump:
>>>>> 0.      Program arguments: build-all/bin/opt -S -o - bbi-15696.ll 
>>>>> -indvars 1.      Running pass 'Function Pass Manager' on module 
>>>>> 'bbi-15696.ll'.
>>>>> 2.      Running pass 'Loop Pass Manager' on function '@f3'
>>>>> 3.      Running pass 'Induction Variable Simplification' on basic 
>>>>> block '%bb1'
>>>>> #0 0x0000000001ff1b44 PrintStackTraceSignalHandler(void*)
>>>>> (build-all/bin/opt+0x1ff1b44)
>>>>> #1 0x0000000001fefdb0 llvm::sys::RunSignalHandlers()
>>>>> (build-all/bin/opt+0x1fefdb0)
>>>>> #2 0x0000000001ff1ea8 SignalHandler(int)
>>>>> (build-all/bin/opt+0x1ff1ea8)
>>>>> #3 0x00007f314bd38330 __restore_rt
>>>>> (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)
>>>>> #4 0x00007f314a927c37 gsignal
>>>>> /build/eglibc-ripdx6/eglibc-2.19/signal/../nptl/sysdeps/unix/sysv/
>>>>> l
>>>>> i
>>>>> nu
>>>>> x/raise.c:56:0
>>>>> #5 0x00007f314a92b028 abort
>>>>> /build/eglibc-ripdx6/eglibc-2.19/stdlib/abort.c:91:0
>>>>> #6 0x00007f314a920bf6 __assert_fail_base
>>>>> /build/eglibc-ripdx6/eglibc-2.19/assert/assert.c:92:0
>>>>> #7 0x00007f314a920ca2 (/lib/x86_64-linux-gnu/libc.so.6+0x2fca2)
>>>>> #8 0x00000000020d2906 (anonymous
>>>>> namespace)::SimplifyIndvar::eliminateIVUser(llvm::Instruction*,
>>>>> llvm::Instruction*) (build-all/bin/opt+0x20d2906)
>>>>> #9 0x00000000020cf81b llvm::simplifyUsersOfIV(llvm::PHINode*,
>>>>> llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::LoopInfo*, 
>>>>> llvm::SmallVectorImpl<llvm::WeakTrackingVH>&, llvm::SCEVExpander&,
>>>>> llvm::IVVisitor*) (build-all/bin/opt+0x20cf81b)
>>>>> #10 0x0000000001ded2c1 (anonymous
>>>>> namespace)::IndVarSimplify::run(llvm::Loop*)
>>>>> (build-all/bin/opt+0x1ded2c1)
>>>>> #11 0x0000000001df202c (anonymous
>>>>> namespace)::IndVarSimplifyLegacyPass::runOnLoop(llvm::Loop*,
>>>>> llvm::LPPassManager&) (build-all/bin/opt+0x1df202c)
>>>>> #12 0x0000000001533995
>>>>> llvm::LPPassManager::runOnFunction(llvm::Function&)
>>>>> (build-all/bin/opt+0x1533995)
>>>>> #13 0x0000000001a7f5da
>>>>> llvm::FPPassManager::runOnFunction(llvm::Function&)
>>>>> (build-all/bin/opt+0x1a7f5da)
>>>>> #14 0x0000000001a7f838
>>>>> llvm::FPPassManager::runOnModule(llvm::Module&)
>>>>> (build-all/bin/opt+0x1a7f838)
>>>>> #15 0x0000000001a7fd6d
>>>>> llvm::legacy::PassManagerImpl::run(llvm::Module&)
>>>>> (build-all/bin/opt+0x1a7fd6d)
>>>>> #16 0x0000000000744f4c main (build-all/bin/opt+0x744f4c)
>>>>> #17 0x00007f314a912f45 __libc_start_main
>>>>> /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:321:0
>>>>> #18 0x000000000072e2ad _start (build-all/bin/opt+0x72e2ad) Abort
>>>>>
>>>>> When the assertion fails TI is
>>>>>        %_tmp15 = trunc i32 %e.5.0 to i16 and ICI is
>>>>>        %_tmp24 = icmp slt i16 %_tmp15, 0 and L is
>>>>>       Loop at depth 1 containing:
>>>>> %bb1<header>,%bb2,%bb3,%bb4,%bb6<latch><exiting>
>>>>>
>>>>> %bb5 which contains the icmp is only reached from itself
>>>>>
>>>>> bb5:                                              ; preds = %bb5,
>>>>> %bb5
>>>>>        %_tmp24 = icmp slt i16 %_tmp15, 0
>>>>>        br i1 %_tmp24, label %bb5, label %bb5
>>>>>
>>>>> Regards,
>>>>> Mikael
>>>>>
>>>>> On 06/19/2018 06:48 AM, Max Kazantsev via llvm-commits wrote:
>>>>>> Author: mkazantsev
>>>>>> Date: Mon Jun 18 21:48:34 2018
>>>>>> New Revision: 335020
>>>>>>
>>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=335020&view=rev
>>>>>> Log:
>>>>>> [SimplifyIndVars] Eliminate redundant truncs
>>>>>>
>>>>>> This patch adds logic to deal with the following constructions:
>>>>>>
>>>>>>        %iv = phi i64 ...
>>>>>>        %trunc = trunc i64 %iv to i32
>>>>>>        %cmp = icmp <pred> i32 %trunc, %invariant
>>>>>>
>>>>>> Replacing it with
>>>>>>        %iv = phi i64 ...
>>>>>>        %cmp = icmp <pred> i64 %iv, sext/zext(%invariant)
>>>>>>
>>>>>> In case if it is legal. Specifically, if `%iv` has signed 
>>>>>> comparison users, it is required that `sext(trunc(%iv)) == %iv`, 
>>>>>> and if it has unsigned comparison uses then we require `zext(trunc(%iv)) == %iv`.
>>>>>> The current implementation bails if `%trunc` has other uses than 
>>>>>> `icmp`, but in theory we can handle more cases here (e.g. if the 
>>>>>> user of trunc is bitcast).
>>>>>>
>>>>>> Differential Revision: https://reviews.llvm.org/D47928 Reviewed By:
>>>>>> reames
>>>>>>
>>>>>> Added:
>>>>>>          
>>>>>> llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
>>>>>> Modified:
>>>>>>          llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
>>>>>>          llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll
>>>>>>          
>>>>>> llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
>>>>>>
>>>>>> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
>>>>>> URL:
>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Uti
>>>>>> l s /S i 
>>>>>> mplifyIndVar.cpp?rev=335020&r1=335019&r2=335020&view=diff
>>>>>> =================================================================
>>>>>> =
>>>>>> =
>>>>>> ==
>>>>>> =
>>>>>> ========
>>>>>> --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)
>>>>>> +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Mon Jun 18
>>>>>> +++ 21:48:34 2018
>>>>>> @@ -81,6 +81,7 @@ namespace {
>>>>>>           bool replaceIVUserWithLoopInvariant(Instruction
>>>>>> *UseInst);
>>>>>>           bool eliminateOverflowIntrinsic(CallInst *CI);
>>>>>> +    bool eliminateTrunc(TruncInst *TI);
>>>>>>           bool eliminateIVUser(Instruction *UseInst, Instruction 
>>>>>> *IVOperand);
>>>>>>           bool makeIVComparisonInvariant(ICmpInst *ICmp, Value 
>>>>>> *IVOperand);
>>>>>>           void eliminateIVComparison(ICmpInst *ICmp, Value 
>>>>>> *IVOperand); @@
>>>>>> -494,6 +495,93 @@ bool SimplifyIndvar::eliminateOverflowIn
>>>>>>         return true;
>>>>>>       }
>>>>>> +bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
>>>>>> +  // It is always legal to replace
>>>>>> +  //   icmp <pred> i32 trunc(iv), n
>>>>>> +  // with
>>>>>> +  //   icmp <pred> i64 sext(trunc(iv)), sext(n), if pred is 
>>>>>> +signed
>>>>>> predicate.
>>>>>> +  // Or with
>>>>>> +  //   icmp <pred> i64 zext(trunc(iv)), zext(n), if pred is
>>>>>> unsigned predicate.
>>>>>> +  // Or with either of these if pred is an equality predicate.
>>>>>> +  //
>>>>>> +  // If we can prove that iv == sext(trunc(iv)) or iv ==
>>>>>> +zext(trunc(iv)) for
>>>>>> +  // every comparison which uses trunc, it means that we can 
>>>>>> +replace each of
>>>>>> +  // them with comparison of iv against sext/zext(n). We no 
>>>>>> +longer need trunc
>>>>>> +  // after that.
>>>>>> +  //
>>>>>> +  // TODO: Should we do this if we can widen *some* comparisons, 
>>>>>> +but not all
>>>>>> +  // of them? Sometimes it is enough to enable other 
>>>>>> +optimizations, but the
>>>>>> +  // trunc instruction will stay in the loop.
>>>>>> +  Value *IV = TI->getOperand(0);
>>>>>> +  Type *IVTy = IV->getType();
>>>>>> +  const SCEV *IVSCEV = SE->getSCEV(IV);
>>>>>> +  const SCEV *TISCEV = SE->getSCEV(TI);
>>>>>> +
>>>>>> +  // Check if iv == zext(trunc(iv)) and if iv == sext(trunc(iv)).
>>>>>> +If  so, we can  // get rid of trunc  bool DoesSExtCollapse = 
>>>>>> +false;  bool DoesZExtCollapse = false;  if (IVSCEV ==
>>>>>> + SE->getSignExtendExpr(TISCEV, IVTy))
>>>>>> +    DoesSExtCollapse = true;
>>>>>> +  if (IVSCEV == SE->getZeroExtendExpr(TISCEV, IVTy))
>>>>>> +    DoesZExtCollapse = true;
>>>>>> +
>>>>>> +  // If neither sext nor zext does collapse, it is not 
>>>>>> +profitable to  do any  // transform. Bail.
>>>>>> +  if (!DoesSExtCollapse && !DoesZExtCollapse)
>>>>>> +    return false;
>>>>>> +
>>>>>> +  // Collect users of the trunc that look like comparisons 
>>>>>> +against
>>>>>> invariants.
>>>>>> +  // Bail if we find something different.
>>>>>> +  SmallVector<ICmpInst *, 4> ICmpUsers;  for (auto *U :
>>>>>> +TI->users())  {
>>>>>> +    if (ICmpInst *ICI = dyn_cast<ICmpInst>(U)) {
>>>>>> +      if (ICI->getOperand(0) == TI &&
>>>>>> L->isLoopInvariant(ICI->getOperand(1))) {
>>>>>> +        assert(L->contains(ICI->getParent()) && "LCSSA form 
>>>>>> +broken?");
>>>>>> +        // If we cannot get rid of trunc, bail.
>>>>>> +        if (ICI->isSigned() && !DoesSExtCollapse)
>>>>>> +          return false;
>>>>>> +        if (ICI->isUnsigned() && !DoesZExtCollapse)
>>>>>> +          return false;
>>>>>> +        // For equality, either signed or unsigned works.
>>>>>> +        ICmpUsers.push_back(ICI);
>>>>>> +      } else
>>>>>> +        return false;
>>>>>> +    } else
>>>>>> +      return false;
>>>>>> +  }
>>>>>> +
>>>>>> +  // Replace all comparisons against trunc with comparisons 
>>>>>> +against
>>>>>> IV.
>>>>>> +  for (auto *ICI : ICmpUsers) {
>>>>>> +    auto *Op1 = ICI->getOperand(1);
>>>>>> +    Instruction *Ext = nullptr;
>>>>>> +    // For signed/unsigned predicate, replace the old comparison
>>>>>> with comparison
>>>>>> +    // of immediate IV against sext/zext of the invariant argument.
>>>>>> If we can
>>>>>> +    // use either sext or zext (i.e. we are dealing with 
>>>>>> +equality
>>>>>> predicate),
>>>>>> +    // then prefer zext as a more canonical form.
>>>>>> +    // TODO: If we see a signed comparison which can be turned 
>>>>>> +into
>>>>>> unsigned,
>>>>>> +    // we can do it here for canonicalization purposes.
>>>>>> +    if (ICI->isUnsigned() || (ICI->isEquality() &&
>>>>>> DoesZExtCollapse)) {
>>>>>> +      assert(DoesZExtCollapse && "Unprofitable zext?");
>>>>>> +      Ext = new ZExtInst(Op1, IVTy, "zext", ICI);
>>>>>> +    } else {
>>>>>> +      assert(DoesSExtCollapse && "Unprofitable sext?");
>>>>>> +      Ext = new SExtInst(Op1, IVTy, "sext", ICI);
>>>>>> +    }
>>>>>> +    bool Changed;
>>>>>> +    L->makeLoopInvariant(Ext, Changed);
>>>>>> +    (void)Changed;
>>>>>> +    ICmpInst *NewICI = new ICmpInst(ICI, ICI->getPredicate(), 
>>>>>> +IV,
>>>>>> Ext);
>>>>>> +    ICI->replaceAllUsesWith(NewICI);
>>>>>> +    DeadInsts.emplace_back(ICI);
>>>>>> +  }
>>>>>> +
>>>>>> +  // Trunc no longer needed.
>>>>>> +  TI->replaceAllUsesWith(UndefValue::get(TI->getType()));
>>>>>> +  DeadInsts.emplace_back(TI);
>>>>>> +  return true;
>>>>>> +}
>>>>>> +
>>>>>>       /// Eliminate an operation that consumes a simple IV and 
>>>>>> has no observable
>>>>>>       /// side-effect given the range of IV values.  IVOperand is 
>>>>>> guaranteed SCEVable,
>>>>>>       /// but UseInst may not be.
>>>>>> @@ -518,6 +606,10 @@ bool SimplifyIndvar::eliminateIVUser(Ins
>>>>>>           if (eliminateOverflowIntrinsic(CI))
>>>>>>             return true;
>>>>>> +  if (auto *TI = dyn_cast<TruncInst>(UseInst))
>>>>>> +    if (eliminateTrunc(TI))
>>>>>> +      return true;
>>>>>> +
>>>>>>         if (eliminateIdentitySCEV(UseInst, IVOperand))
>>>>>>           return true;
>>>>>>
>>>>>> Modified: llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll
>>>>>> URL:
>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/In
>>>>>> d
>>>>>> V ar S
>>>>>> implify/ada-loops.ll?rev=335020&r1=335019&r2=335020&view=diff
>>>>>> =================================================================
>>>>>> =
>>>>>> =
>>>>>> ==
>>>>>> =
>>>>>> ========
>>>>>> --- llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll
>>>>>> (original)
>>>>>> +++ llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll Mon 
>>>>>> +++ Jun
>>>>>> +++ 18
>>>>>> +++ 21:48:34 2018
>>>>>> @@ -10,12 +10,17 @@
>>>>>>       ; don't check that phis are "folded together" because that 
>>>>>> is a job
>>>>>>       ; for loop strength reduction. But indvars must remove 
>>>>>> sext, zext, and add i8.
>>>>>>       ;
>>>>>> -; CHECK-NOT: {{sext|zext|add i8}}
>>>>>>       ; ModuleID = 'ada.bc'
>>>>>>       target datalayout =
>>>>>> "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32"
>>>>>>
>>>>>>       target triple = "i686-pc-linux-gnu"
>>>>>> +; CHECK-LABEL: @kinds__sbytezero ; CHECK:         bb.thread:
>>>>>> +; CHECK:         sext
>>>>>> +; CHECK:         bb:
>>>>>> +; CHECK-NOT:     {{sext i8|zext i8|add i8|trunc}}
>>>>>> +
>>>>>>       define void @kinds__sbytezero([256 x i32]* nocapture %a) 
>>>>>> nounwind {
>>>>>>       bb.thread:
>>>>>>           %tmp46 = getelementptr [256 x i32], [256 x i32]* %a, 
>>>>>> i32 0,
>>>>>> i32 0        ; <i32*> [#uses=1]
>>>>>> @@ -36,6 +41,8 @@ return:        ; preds = %bb
>>>>>>           ret void
>>>>>>       }
>>>>>> +; CHECK-LABEL: @kinds__ubytezero
>>>>>> +
>>>>>>       define void @kinds__ubytezero([256 x i32]* nocapture %a) 
>>>>>> nounwind {
>>>>>>       bb.thread:
>>>>>>           %tmp35 = getelementptr [256 x i32], [256 x i32]* %a, 
>>>>>> i32 0,
>>>>>> i32 0        ; <i32*> [#uses=1]
>>>>>>
>>>>>> Added:
>>>>>> llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
>>>>>> URL:
>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/In
>>>>>> d V ar S implify/eliminate-trunc.ll?rev=335020&view=auto
>>>>>> =================================================================
>>>>>> =
>>>>>> =
>>>>>> ==
>>>>>> =
>>>>>> ========
>>>>>> --- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
>>>>>> (added)
>>>>>> +++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
>>>>>> +++ Mon Jun 18 21:48:34 2018
>>>>>> @@ -0,0 +1,486 @@
>>>>>> +; NOTE: Assertions have been autogenerated by 
>>>>>> +utils/update_test_checks.py ; RUN: opt -indvars -S < %s | 
>>>>>> +FileCheck %s
>>>>>> +
>>>>>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>>>>>> +target triple = "x86_64-unknown-linux-gnu"
>>>>>> +
>>>>>> +; General case: without extra knowledge, trunc cannot be eliminated.
>>>>>> +define void @test_00(i64 %start, i32 %n) { ; ; CHECK-LABEL:
>>>>>> + at test_00( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]],
>>>>>> [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT:
>>>>>> +[[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ; CHECK-NEXT:
>>>>>> +[[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], [[N:%.*]] ; CHECK-NEXT:
>>>>>> +br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK:
>>>>>> +exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +
>>>>>> +define void @test_01(i32 %n) {
>>>>>> +;
>>>>>> +; CHECK-LABEL: @test_01(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] ;
>>>>>> +CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Max value at which we can eliminate trunc: SINT_MAX - 1.
>>>>>> +define void @test_02(i32 %n) {
>>>>>> +;
>>>>>> +; CHECK-LABEL: @test_02(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 2147483646, 
>>>>>> +[[ENTRY:%.*]]
>>>>>> ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] ;
>>>>>> +CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 2147483646, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; If we start from SINT_MAX then the predicate is always false.
>>>>>> +define void @test_03(i32 %n) {
>>>>>> +;
>>>>>> +; CHECK-LABEL: @test_03(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]] 
>>>>>> +;
>>>>>> +CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [2147483647, %entry], [%iv.next, %loop]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Minimum value at which we can apply the transform: SINT_MIN + 1.
>>>>>> +define void @test_04(i32 %n) {
>>>>>> +;
>>>>>> +; CHECK-LABEL: @test_04(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -2147483647, 
>>>>>> +[[ENTRY:%.*]]
>>>>>> ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 1 ; CHECK-NEXT:
>>>>>> +[[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] ; CHECK-NEXT:    br
>>>>>> +i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK:
>>>>>> +exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ -2147483647, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; FIXME: Harmful LFTR should be thrown away.
>>>>>> +define void @test_05(i32 %n) {
>>>>>> +;
>>>>>> +; CHECK-LABEL: @test_05(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1 ; CHECK-NEXT:
>>>>>> +br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -2147483648, 
>>>>>> +[[ENTRY:%.*]]
>>>>>> ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 1 ; CHECK-NEXT:
>>>>>> +[[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 ; CHECK-NEXT:
>>>>>> +[[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]],
>>>>>> [[TMP0]]
>>>>>> +; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label
>>>>>> [[EXIT:%.*]]
>>>>>> +; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ -2147483648, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Trunc changes the actual value of the IV, so it is invalid to
>>>>>> remove it: SINT_MIN - 1.
>>>>>> +define void @test_06(i32 %n) {
>>>>>> +;
>>>>>> +; CHECK-LABEL: @test_06(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -2147483649, 
>>>>>> +[[ENTRY:%.*]]
>>>>>> ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ;
>>>>>> +CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], 
>>>>>> +[[N:%.*]] ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ -2147483649, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; General case: without extra knowledge, trunc cannot be eliminated.
>>>>>> +define void @test_00_unsigned(i64 %start, i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_00_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]],
>>>>>> [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT:
>>>>>> +[[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ; CHECK-NEXT:
>>>>>> +[[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]] ; CHECK-NEXT:
>>>>>> +br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK:
>>>>>> +exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; FIXME: Harmful LFTR should be thrown away.
>>>>>> +define void @test_01_unsigned(i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_01_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1 ; CHECK-NEXT:
>>>>>> +br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to 
>>>>>> +i32 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 
>>>>>> +[[LFTR_WIDEIV]],
>>>>>> [[TMP0]]
>>>>>> +; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label
>>>>>> [[EXIT:%.*]]
>>>>>> +; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Max value at which we can eliminate trunc: UINT_MAX - 1.
>>>>>> +define void @test_02_unsigned(i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_02_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 4294967294, 
>>>>>> +[[ENTRY:%.*]]
>>>>>> ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] ;
>>>>>> +CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 4294967294, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; If we start from UINT_MAX then the predicate is always false.
>>>>>> +define void @test_03_unsigned(i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_03_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[EXIT:%.*]] 
>>>>>> +;
>>>>>> +CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 4294967295, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Minimum value at which we can apply the transform: UINT_MIN.
>>>>>> +define void @test_04_unsigned(i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_04_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], 1 ; CHECK-NEXT:
>>>>>> +br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to 
>>>>>> +i32 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 
>>>>>> +[[LFTR_WIDEIV]],
>>>>>> [[TMP0]]
>>>>>> +; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label
>>>>>> [[EXIT:%.*]]
>>>>>> +; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Start from 1.
>>>>>> +define void @test_05_unsigned(i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_05_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] ;
>>>>>> +CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Trunc changes the actual value of the IV, so it is invalid to
>>>>>> remove it: UINT_MIN - 1.
>>>>>> +define void @test_06_unsigned(i32 %n) { ; CHECK-LABEL:
>>>>>> + at test_06_unsigned( ; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -1, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], 1 ; CHECK-NEXT:
>>>>>> +[[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ; CHECK-NEXT:
>>>>>> +[[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]] ; CHECK-NEXT:
>>>>>> +br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK:
>>>>>> +exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ -1, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ult i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Do not eliminate trunc if it is used by something different 
>>>>>> +from
>>>>>> icmp.
>>>>>> +define void @test_07(i32* %p, i32 %n) { ; CHECK-LABEL: @test_07( 
>>>>>> +;
>>>>>> +CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ;
>>>>>> +CHECK-NEXT:    store i32 [[NARROW_IV]], i32* [[P:%.*]] ;
>>>>>> +CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], 
>>>>>> +[[N:%.*]] ; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  store i32 %narrow.iv, i32* %p
>>>>>> +  %cmp = icmp slt i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Check that we can eliminate both signed and unsigned compare.
>>>>>> +define void @test_08(i32 %n) {
>>>>>> +; CHECK-LABEL: @test_08(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N]] to i64 ; CHECK-NEXT:
>>>>>> +br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] ;
>>>>>> +CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] ;
>>>>>> +CHECK-NEXT:    [[CMP:%.*]] = and i1 [[TMP0]], [[TMP1]] ;
>>>>>> +CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 
>>>>>> +;
>>>>>> +CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp1 = icmp slt i32 %narrow.iv, %n
>>>>>> +  %cmp2 = icmp ult i32 %narrow.iv, %n
>>>>>> +  %cmp = and i1 %cmp1, %cmp2
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Widen NE as unsigned.
>>>>>> +define void @test_09(i32 %n) {
>>>>>> +; CHECK-LABEL: @test_09(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]] ;
>>>>>> +CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label 
>>>>>> +[[EXIT:%.*]] ; CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %cmp = icmp ne i32 %narrow.iv, %n
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>> +
>>>>>> +; Widen NE as signed.
>>>>>> +define void @test_10(i32 %n) {
>>>>>> +; CHECK-LABEL: @test_10(
>>>>>> +; CHECK-NEXT:  entry:
>>>>>> +; CHECK-NEXT:    [[SEXT:%.*]] = sext i32 [[N:%.*]] to i64 ;
>>>>>> +CHECK-NEXT:    br label [[LOOP:%.*]] ; CHECK:       loop:
>>>>>> +; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ -100, [[ENTRY:%.*]] ], [
>>>>>> [[IV_NEXT:%.*]], [[LOOP]] ]
>>>>>> +; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ;
>>>>>> +CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[IV]], [[SEXT]] ;
>>>>>> +CHECK-NEXT:    [[NEGCMP:%.*]] = icmp slt i64 [[IV]], -10 ;
>>>>>> +CHECK-NEXT:    [[CMP:%.*]] = and i1 [[TMP0]], [[NEGCMP]] ;
>>>>>> +CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 
>>>>>> +;
>>>>>> +CHECK:       exit:
>>>>>> +; CHECK-NEXT:    ret void
>>>>>> +;
>>>>>> +entry:
>>>>>> +  br label %loop
>>>>>> +loop:
>>>>>> +  %iv = phi i64 [ -100, %entry ], [ %iv.next, %loop ]
>>>>>> +  %iv.next = add i64 %iv, 1
>>>>>> +  %narrow.iv = trunc i64 %iv to i32
>>>>>> +  %trunccmp = icmp ne i32 %narrow.iv, %n
>>>>>> +  %negcmp = icmp slt i64 %iv, -10
>>>>>> +  %cmp = and i1 %trunccmp, %negcmp
>>>>>> +  br i1 %cmp, label %loop, label %exit
>>>>>> +exit:
>>>>>> +  ret void
>>>>>> +}
>>>>>>
>>>>>> Modified:
>>>>>> llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
>>>>>> URL:
>>>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/In
>>>>>> d
>>>>>> V
>>>>>> ar S
>>>>>> implify/widen-loop-comp.ll?rev=335020&r1=335019&r2=335020&view=di
>>>>>> f
>>>>>> f
>>>>>> =================================================================
>>>>>> =
>>>>>> =
>>>>>> ==
>>>>>> =
>>>>>> ========
>>>>>> --- llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
>>>>>> (original)
>>>>>> +++ llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
>>>>>> +++ Mon Jun 18 21:48:34 2018
>>>>>> @@ -332,12 +332,12 @@ define i32 @test10(i32 %v) {
>>>>>>         br label %loop
>>>>>>        loop:
>>>>>> +; CHECK: [[WIDE_V:%[a-z0-9]+]] = sext i32 %v to i64
>>>>>>       ; CHECK: loop:
>>>>>>       ; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], 
>>>>>> [ 0, %entry ]
>>>>>>       ; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
>>>>>>       ; CHECK: [[MUL:%[a-z0-9]+]] = mul nsw i64 %indvars.iv, -1 -; CHECK:
>>>>>> [[MUL_TRUNC:%[a-z0-9]+]] = trunc i64 [[MUL]] to i32 -; CHECK:
>>>>>> [[CMP:%[a-z0-9]+]] = icmp eq i32 [[MUL_TRUNC]], %v
>>>>>> +; CHECK: [[CMP:%[a-z0-9]+]] = icmp eq i64 [[MUL]], [[WIDE_V]]
>>>>>>       ; CHECK: call void @consume.i1(i1 [[CMP]])
>>>>>>         %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
>>>>>>
>>>>>>
>>>>>> _______________________________________________
>>>>>> 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


More information about the llvm-commits mailing list