[llvm] r335020 - [SimplifyIndVars] Eliminate redundant truncs

Maxim Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 22 19:18:08 PDT 2018


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. :)

-- 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/li
>>> 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/Utils
>>>> /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/IndV
>>>> 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/IndV
>>>> 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/IndV
>>>> ar S 
>>>> implify/widen-loop-comp.ll?rev=335020&r1=335019&r2=335020&view=diff
>>>> ===================================================================
>>>> ==
>>>> =
>>>> ========
>>>> --- 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