[llvm] r358552 - Revert "Temporarily Revert "Add basic loop fusion pass.""

Eric Christopher via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 16 21:53:01 PDT 2019


Added: llvm/trunk/test/Transforms/GlobalOpt/2009-03-05-dbg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-03-05-dbg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-03-05-dbg.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-03-05-dbg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,80 @@
+; REQUIRES: asserts
+; RUN: opt < %s -globalopt -stats -disable-output 2>&1 | FileCheck %s
+; CHECK: 1 globalopt - Number of global vars shrunk to booleans
+
+source_filename = "test/Transforms/GlobalOpt/2009-03-05-dbg.ll"
+
+ at Stop = internal global i32 0, !dbg !0
+
+; Function Attrs: nounwind ssp
+define i32 @foo(i32 %i) #0 {
+entry:
+  %"alloca point" = bitcast i32 0 to i32
+  call void @llvm.dbg.value(metadata i32 %i, metadata !8, metadata !12), !dbg !13
+  %0 = icmp eq i32 %i, 1, !dbg !13
+  br i1 %0, label %bb, label %bb1, !dbg !13
+
+bb:                                               ; preds = %entry
+  store i32 0, i32* @Stop, align 4, !dbg !15
+  %1 = mul nsw i32 %i, 42, !dbg !16
+  call void @llvm.dbg.value(metadata i32 %1, metadata !8, metadata !12), !dbg !16
+  br label %bb2, !dbg !16
+
+bb1:                                              ; preds = %entry
+  store i32 1, i32* @Stop, align 4, !dbg !17
+  br label %bb2, !dbg !17
+
+bb2:                                              ; preds = %bb1, %bb
+  %i_addr.0 = phi i32 [ %1, %bb ], [ %i, %bb1 ]
+  br label %return, !dbg !18
+
+return:                                           ; preds = %bb2
+  ret i32 %i_addr.0, !dbg !18
+}
+
+; Function Attrs: nounwind readnone
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind ssp
+define i32 @bar() #0 {
+entry:
+  %"alloca point" = bitcast i32 0 to i32
+  %0 = load i32, i32* @Stop, align 4, !dbg !19
+  %1 = icmp eq i32 %0, 1, !dbg !19
+  br i1 %1, label %bb, label %bb1, !dbg !19
+
+bb:                                               ; preds = %entry
+
+  br label %bb2, !dbg !24
+
+bb1:                                              ; preds = %entry
+  br label %bb2, !dbg !25
+
+bb2:                                              ; preds = %bb1, %bb
+  %.0 = phi i32 [ 0, %bb ], [ 1, %bb1 ]
+  br label %return, !dbg !25
+
+return:                                           ; preds = %bb2
+  ret i32 %.0, !dbg !25
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind ssp }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!6, !7}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "Stop", scope: !2, file: !3, line: 2, type: !5, isLocal: true, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C89, file: !3, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4)
+!3 = !DIFile(filename: "g.c", directory: "/tmp")
+!4 = !{!0}
+!5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!6 = !{i32 2, !"Dwarf Version", i32 2}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+!8 = !DILocalVariable(name: "i", arg: 1, scope: !9, file: !3, line: 4, type: !5)
+!9 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !2, file: !3, line: 4, type: !10, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2)!10 = !DISubroutineType(types: !11)!11 = !{!5, !5}!12 = !DIExpression()!13 = !DILocation(line: 5, scope: !14)!14 = distinct !DILexicalBlock(scope: !9, file: !3)!15 = !DILocation(line: 6, scope: !14)!16 = !DILocation(line: 7, scope: !14)!17 = !DILocation(line: 9, scope: !14)!18 = !DILocation(line: 11, scope: !14)!19 = !DILocation(line: 14, scope: !20)!20 = distinct !DILexicalBlock(scope: !21, file: !3)!21 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: !2, file: !3, line: 13, type: !22, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2)!22 = !DISubroutineType(types: !23)!23 = !{!5}!24 = !DILocation(line: 15, scope: !20)!25 = !DILocation(line: 16, scope: !20)

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-03-06-Anonymous.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-03-06-Anonymous.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-03-06-Anonymous.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-03-06-Anonymous.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at 0 = global i32 0
+; CHECK-DAG: @0 = internal global i32 0
+
+ at 1 = private global i32 0
+; CHECK-DAG: @1 = private global i32 0
+
+define i32* @2() {
+	ret i32* @0
+}
+; CHECK-DAG: define internal fastcc i32* @2()
+
+define i32* @f() {
+entry:
+	call i32* @2()
+	ret i32* %0
+}
+
+define i32* @g() {
+entry:
+	ret i32* @1
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+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-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+; CHECK: @X = internal unnamed_addr global i32
+ at X = internal global i32* null		; <i32**> [#uses=2]
+ at Y = internal global i32 0		; <i32*> [#uses=1]
+
+define void @foo() nounwind {
+entry:
+	store i32* @Y, i32** @X, align 4
+	ret void
+}
+
+define i32* @get() nounwind {
+entry:
+	%0 = load i32*, i32** @X, align 4		; <i32*> [#uses=1]
+	ret i32* %0
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-06-01-RecursivePHI.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-06-01-RecursivePHI.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-06-01-RecursivePHI.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-06-01-RecursivePHI.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,122 @@
+; RUN: opt < %s -globalopt
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+	%struct.s_annealing_sched = type { i32, float, float, float, float }
+	%struct.s_bb = type { i32, i32, i32, i32 }
+	%struct.s_net = type { i8*, i32, i32*, float, float }
+	%struct.s_placer_opts = type { i32, float, i32, i32, i8*, i32, i32 }
+ at net = internal global %struct.s_net* null		; <%struct.s_net**> [#uses=4]
+
+define fastcc void @alloc_and_load_placement_structs(i32 %place_cost_type, i32 %num_regions, float %place_cost_exp, float*** nocapture %old_region_occ_x, float*** nocapture %old_region_occ_y) nounwind ssp {
+entry:
+	br i1 undef, label %bb.i, label %my_malloc.exit
+
+bb.i:		; preds = %entry
+	unreachable
+
+my_malloc.exit:		; preds = %entry
+	br i1 undef, label %bb.i81, label %my_malloc.exit83
+
+bb.i81:		; preds = %my_malloc.exit
+	unreachable
+
+my_malloc.exit83:		; preds = %my_malloc.exit
+	br i1 undef, label %bb.i.i57, label %my_calloc.exit.i
+
+bb.i.i57:		; preds = %my_malloc.exit83
+	unreachable
+
+my_calloc.exit.i:		; preds = %my_malloc.exit83
+	br i1 undef, label %bb.i4.i, label %my_calloc.exit5.i
+
+bb.i4.i:		; preds = %my_calloc.exit.i
+	unreachable
+
+my_calloc.exit5.i:		; preds = %my_calloc.exit.i
+	%.pre.i58 = load %struct.s_net*, %struct.s_net** @net, align 4		; <%struct.s_net*> [#uses=1]
+	br label %bb17.i78
+
+bb1.i61:		; preds = %bb4.preheader.i, %bb1.i61
+	br i1 undef, label %bb1.i61, label %bb5.i62
+
+bb5.i62:		; preds = %bb1.i61
+	br i1 undef, label %bb6.i64, label %bb15.preheader.i
+
+bb15.preheader.i:		; preds = %bb4.preheader.i, %bb5.i62
+	br label %bb16.i77
+
+bb6.i64:		; preds = %bb5.i62
+	br i1 undef, label %bb7.i65, label %bb8.i67
+
+bb7.i65:		; preds = %bb6.i64
+	unreachable
+
+bb8.i67:		; preds = %bb6.i64
+	br i1 undef, label %bb.i1.i68, label %my_malloc.exit.i70
+
+bb.i1.i68:		; preds = %bb8.i67
+	unreachable
+
+my_malloc.exit.i70:		; preds = %bb8.i67
+	%0 = load %struct.s_net*, %struct.s_net** @net, align 4		; <%struct.s_net*> [#uses=1]
+	br i1 undef, label %bb9.i71, label %bb16.i77
+
+bb9.i71:		; preds = %bb9.i71, %my_malloc.exit.i70
+	%1 = load %struct.s_net*, %struct.s_net** @net, align 4		; <%struct.s_net*> [#uses=1]
+	br i1 undef, label %bb9.i71, label %bb16.i77
+
+bb16.i77:		; preds = %bb9.i71, %my_malloc.exit.i70, %bb15.preheader.i
+	%.pre41.i.rle244 = phi %struct.s_net* [ %.pre41.i, %bb15.preheader.i ], [ %0, %my_malloc.exit.i70 ], [ %1, %bb9.i71 ]		; <%struct.s_net*> [#uses=1]
+	br label %bb17.i78
+
+bb17.i78:		; preds = %bb16.i77, %my_calloc.exit5.i
+	%.pre41.i = phi %struct.s_net* [ %.pre41.i.rle244, %bb16.i77 ], [ %.pre.i58, %my_calloc.exit5.i ]		; <%struct.s_net*> [#uses=1]
+	br i1 undef, label %bb4.preheader.i, label %alloc_and_load_unique_pin_list.exit
+
+bb4.preheader.i:		; preds = %bb17.i78
+	br i1 undef, label %bb1.i61, label %bb15.preheader.i
+
+alloc_and_load_unique_pin_list.exit:		; preds = %bb17.i78
+	ret void
+}
+
+define void @read_net(i8* %net_file) nounwind ssp {
+entry:
+	br i1 undef, label %bb3.us.us.i, label %bb6.preheader
+
+bb6.preheader:		; preds = %entry
+	br i1 undef, label %bb7, label %bb
+
+bb3.us.us.i:		; preds = %entry
+	unreachable
+
+bb:		; preds = %bb6.preheader
+	br i1 undef, label %bb.i34, label %bb1.i38
+
+bb.i34:		; preds = %bb
+	unreachable
+
+bb1.i38:		; preds = %bb
+	%mallocsize = mul i64 28, undef                  ; <i64> [#uses=1]
+	%malloccall = tail call i8* @malloc(i64 %mallocsize)      ; <i8*> [#uses=1]
+	%0 = bitcast i8* %malloccall to %struct.s_net*  ; <%struct.s_net*> [#uses=1]
+	br i1 undef, label %bb.i1.i39, label %my_malloc.exit2.i
+
+bb.i1.i39:		; preds = %bb1.i38
+	unreachable
+
+my_malloc.exit2.i:		; preds = %bb1.i38
+	store %struct.s_net* %0, %struct.s_net** @net, align 4
+	br i1 undef, label %bb.i7.i40, label %my_malloc.exit8.i
+
+bb.i7.i40:		; preds = %my_malloc.exit2.i
+	unreachable
+
+my_malloc.exit8.i:		; preds = %my_malloc.exit2.i
+	unreachable
+
+bb7:		; preds = %bb6.preheader
+	unreachable
+}
+
+declare noalias i8* @malloc(i64)

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin10.0"
+
+%struct.hashheader = type { i16, i16, i16, i16, i16, i16, i32, i32, i32, i32, i32, i32, i32, i32, i32, [5 x i8], [13 x i8], i8, i8, i8, [228 x i16], [228 x i8], [228 x i8], [228 x i8], [228 x i8], [228 x i8], [228 x i8], [128 x i8], [100 x [11 x i8]], [100 x i32], [100 x i32], i16 }
+%struct.strchartype = type { i8*, i8*, i8* }
+
+ at hashheader = internal global %struct.hashheader zeroinitializer, align 32 ; <%struct.hashheader*> [#uses=1]
+ at chartypes = internal global %struct.strchartype* null ; <%struct.strchartype**> [#uses=1]
+; CHECK-NOT: @hashheader
+; CHECK-NOT: @chartypes
+
+; based on linit in office-ispell
+define void @test() nounwind ssp {
+  %1 = load i32, i32* getelementptr inbounds (%struct.hashheader, %struct.hashheader* @hashheader, i64 0, i32 13), align 8 ; <i32> [#uses=1]
+  %2 = sext i32 %1 to i64                         ; <i64> [#uses=1]
+  %3 = mul i64 %2, ptrtoint (%struct.strchartype* getelementptr (%struct.strchartype, %struct.strchartype* null, i64 1) to i64) ; <i64> [#uses=1]
+  %4 = tail call i8* @malloc(i64 %3)              ; <i8*> [#uses=1]
+; CHECK-NOT: call i8* @malloc(i64
+  %5 = bitcast i8* %4 to %struct.strchartype*     ; <%struct.strchartype*> [#uses=1]
+  store %struct.strchartype* %5, %struct.strchartype** @chartypes, align 8
+  ret void
+}
+
+declare noalias i8* @malloc(i64)

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; Test ensures that non-optimizable array mallocs are not optimized; specifically
+; GlobalOpt was treating a non-optimizable array malloc as a non-array malloc
+; and optimizing the global object that the malloc was stored to as a single
+; element global.  The global object @TOP in this test should not be optimized.
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin10.0"
+
+ at TOP = internal global i64* null                    ; <i64**> [#uses=2]
+; CHECK: @TOP = internal unnamed_addr global i64* null
+ at channelColumns = internal global i64 0             ; <i64*> [#uses=2]
+
+; Derived from @DescribeChannel() in yacr2
+define void @test() nounwind ssp {
+  store i64 2335, i64* @channelColumns, align 8
+  %1 = load i64, i64* @channelColumns, align 8         ; <i64> [#uses=1]
+  %2 = shl i64 %1, 3                              ; <i64> [#uses=1]
+  %3 = add i64 %2, 8                              ; <i64> [#uses=1]
+  %4 = call noalias i8* @malloc(i64 %3) nounwind  ; <i8*> [#uses=1]
+; CHECK: call noalias i8* @malloc
+  %5 = bitcast i8* %4 to i64*                     ; <i64*> [#uses=1]
+  store i64* %5, i64** @TOP, align 8
+  %6 = load i64*, i64** @TOP, align 8                   ; <i64*> [#uses=1]
+  %7 = getelementptr inbounds i64, i64* %6, i64 13     ; <i64*> [#uses=1]
+  store i64 0, i64* %7, align 8
+  ret void
+}
+
+declare noalias i8* @malloc(i64) nounwind

Added: llvm/trunk/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; PR6422
+; RUN: opt -globalopt -S < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fixLRBT = internal global i32* null              ; <i32**> [#uses=2]
+
+declare noalias i8* @malloc(i32)
+
+define i32 @parser() nounwind {
+bb918:
+  %malloccall.i10 = call i8* @malloc(i32 16) nounwind ; <i8*> [#uses=1]
+  %0 = bitcast i8* %malloccall.i10 to i32*        ; <i32*> [#uses=1]
+  store i32* %0, i32** @fixLRBT, align 8
+  %1 = load i32*, i32** @fixLRBT, align 8               ; <i32*> [#uses=0]
+  %A = load i32, i32* %1
+  ret i32 %A
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -globalopt -S < %s
+; PR6435
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.xyz = type { double, i32 }
+
+ at Y = internal global %struct.xyz* null            ; <%struct.xyz**> [#uses=2]
+ at numf2s = external global i32                     ; <i32*> [#uses=1]
+
+define fastcc void @init_net() nounwind {
+entry:
+  %0 = load i32, i32* @numf2s, align 4                 ; <i32> [#uses=1]
+  %mallocsize2 = shl i32 %0, 4                    ; <i32> [#uses=1]
+  %malloccall3 = tail call i8* @malloc(i32 %mallocsize2) nounwind ; <i8*> [#uses=1]
+  %1 = bitcast i8* %malloccall3 to %struct.xyz*   ; <%struct.xyz*> [#uses=1]
+  store %struct.xyz* %1, %struct.xyz** @Y, align 8
+  ret void
+}
+
+define fastcc void @load_train(i8* %trainfile, i32 %mode, i32 %objects) nounwind {
+entry:
+  %0 = load %struct.xyz*, %struct.xyz** @Y, align 8             ; <%struct.xyz*> [#uses=0]
+  ret void
+}
+
+declare noalias i8* @malloc(i32)

Added: llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; PR8389: Globals with weak_odr linkage type must not be modified
+
+; CHECK: weak_odr local_unnamed_addr global i32 0
+
+ at SomeVar = weak_odr global i32 0
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR } ]
+
+define internal void @CTOR() {
+  store i32 23, i32* @SomeVar
+  ret void
+}
+
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2011-04-09-EmptyGlobalCtors.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2011-04-09-EmptyGlobalCtors.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2011-04-09-EmptyGlobalCtors.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2011-04-09-EmptyGlobalCtors.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5 @@
+; RUN: opt < %s -globalopt -disable-output
+
+%0 = type { i32, void ()* }
+ at llvm.global_ctors = appending global [0 x %0] zeroinitializer
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2012-05-11-blockaddress.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2012-05-11-blockaddress.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2012-05-11-blockaddress.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2012-05-11-blockaddress.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; Check that the mere presence of a blockaddress doesn't prevent -globalopt
+; from promoting @f to fastcc.
+
+; CHECK-LABEL: define{{.*}}fastcc{{.*}}@f(
+define internal i8* @f() {
+  ret i8* blockaddress(@f, %L1)
+L1:
+  ret i8* null
+}
+
+define void @g() {
+  ; CHECK: call{{.*}}fastcc{{.*}}@f
+  %p = call i8* @f()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/GSROA-section.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/GSROA-section.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/GSROA-section.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/GSROA-section.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; This test lets globalopt split the global struct and array into different
+; values. The pass needs to preserve section attribute.
+
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; Check that the new global values still have their section assignment.
+; CHECK: @struct
+; CHECK: section ".foo"
+; CHECK: @array
+; CHECK-NOT: section ".foo"
+
+ at struct = internal global { i32, i32 } zeroinitializer, section ".foo"
+ at array = internal global [ 2 x i32 ] zeroinitializer
+
+define i32 @foo() {
+  %A = load i32, i32* getelementptr ({ i32, i32 }, { i32, i32 }* @struct, i32 0, i32 0)
+  %B = load i32, i32* getelementptr ([ 2 x i32 ], [ 2 x i32 ]* @array, i32 0, i32 0)
+  ; Use the loaded values, so they won't get removed completely
+  %R = add i32 %A, %B
+  ret i32 %R
+}
+
+; We put stores in a different function, so that the global variables won't get
+; optimized away completely.
+define void @bar(i32 %R) {
+  store i32 %R, i32* getelementptr ([ 2 x i32 ], [ 2 x i32 ]* @array, i32 0, i32 0)
+  store i32 %R, i32* getelementptr ({ i32, i32 }, { i32, i32 }* @struct, i32 0, i32 0)
+  ret void
+}
+
+

Added: llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+; CHECK: @Y
+; CHECK: section ".foo"
+
+%struct.xyz = type { double, i32 }
+
+ at Y = internal global %struct.xyz* null ,section ".foo"            ; <%struct.xyz**> [#uses=2]
+ at numf2s = external global i32                     ; <i32*> [#uses=1]
+
+define void @init_net() #0 {
+; CHECK-LABEL: init_net(
+; CHECK: load i32, i32* @numf2s
+; CHECK: call i8* @malloc
+; CHECK: store %struct.xyz* {{.*}}, %struct.xyz** @Y
+entry:
+  %0 = load i32, i32* @numf2s, align 4                 ; <i32> [#uses=1]
+  %mallocsize2 = shl i32 %0, 4                    ; <i32> [#uses=1]
+  %malloccall3 = tail call i8* @malloc(i32 %mallocsize2)  ; <i8*> [#uses=1]
+  %1 = bitcast i8* %malloccall3 to %struct.xyz*   ; <%struct.xyz*> [#uses=1]
+  store %struct.xyz* %1, %struct.xyz** @Y, align 8
+  ret void
+}
+
+define %struct.xyz* @load_train() #0 {
+; CHECK-LABEL: load_train(
+; CHECK: load %struct.xyz*, %struct.xyz** @Y
+entry:
+  %0 = load %struct.xyz*, %struct.xyz** @Y, align 8             ; <%struct.xyz*> [#uses=0]
+  ret %struct.xyz* %0
+}
+
+declare noalias i8* @malloc(i32)
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/MallocSROA-section.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+; CHECK: @Y.f0
+; CHECK: section ".foo"
+; CHECK: @Y.f1
+; CHECK: section ".foo"
+
+%struct.xyz = type { double, i32 }
+
+ at Y = internal global %struct.xyz* null ,section ".foo"            ; <%struct.xyz**> [#uses=2]
+ at numf2s = external global i32                     ; <i32*> [#uses=1]
+
+define void @init_net()  {
+entry:
+  %0 = load i32, i32* @numf2s, align 4                 ; <i32> [#uses=1]
+  %mallocsize2 = shl i32 %0, 4                    ; <i32> [#uses=1]
+  %malloccall3 = tail call i8* @malloc(i32 %mallocsize2)  ; <i8*> [#uses=1]
+  %1 = bitcast i8* %malloccall3 to %struct.xyz*   ; <%struct.xyz*> [#uses=1]
+  store %struct.xyz* %1, %struct.xyz** @Y, align 8
+  ret void
+}
+
+define void @load_train()  {
+entry:
+  %0 = load %struct.xyz*, %struct.xyz** @Y, align 8             ; <%struct.xyz*> [#uses=0]
+  ret void
+}
+
+declare noalias i8* @malloc(i32)

Added: llvm/trunk/test/Transforms/GlobalOpt/PowerPC/coldcc_coldsites.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/PowerPC/coldcc_coldsites.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/PowerPC/coldcc_coldsites.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/PowerPC/coldcc_coldsites.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt -globalopt -mtriple=powerpc64le-unknown-linux-gnu -ppc-enable-coldcc -S < %s | FileCheck %s -check-prefix=COLDCC
+; RUN: opt -globalopt -S < %s | FileCheck %s -check-prefix=CHECK
+
+define signext i32 @caller(i32 signext %a, i32 signext %b, i32 signext %lim, i32 signext %i) local_unnamed_addr #0 !prof !30 {
+entry:
+; COLDCC: call coldcc signext i32 @callee
+; CHECK: call fastcc signext i32 @callee
+  %add = add nsw i32 %b, %a
+  %sub = add nsw i32 %lim, -1
+  %cmp = icmp eq i32 %sub, %i
+  br i1 %cmp, label %if.then, label %if.end, !prof !31
+
+if.then:                                          ; preds = %entry
+  %call = tail call signext i32 @callee(i32 signext %a, i32 signext %b)
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %f.0 = phi i32 [ %call, %if.then ], [ %add, %entry ]
+  ret i32 %f.0
+}
+
+define internal signext i32 @callee(i32 signext %a, i32 signext %b) unnamed_addr #0 {
+entry:
+  %0 = tail call i32 asm "add $0, $1, $2", "=r,r,r,~{r6},~{r7},~{r8},~{r9}"(i32 %a, i32 %b) #1, !srcloc !32
+  %mul = mul nsw i32 %a, 3
+  %mul1 = shl i32 %0, 1
+  %add = add nsw i32 %mul1, %mul
+  ret i32 %add
+}
+
+define signext i32 @main() local_unnamed_addr #0 !prof !33 {
+entry:
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.body
+  %add.lcssa = phi i32 [ %add, %for.body ]
+  ret i32 %add.lcssa
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.011 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %ret.010 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %call = tail call signext i32 @caller(i32 signext 4, i32 signext 5, i32 signext 10000000, i32 signext %i.011)
+  %add = add nsw i32 %call, %ret.010
+  %inc = add nuw nsw i32 %i.011, 1
+  %exitcond = icmp eq i32 %inc, 10000000
+  br i1 %exitcond, label %for.cond.cleanup, label %for.body, !prof !34
+}
+attributes #0 = { noinline }
+
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 20000003}
+!4 = !{!"MaxCount", i64 10000000}
+!5 = !{!"MaxInternalCount", i64 10000000}
+!6 = !{!"MaxFunctionCount", i64 10000000}
+!7 = !{!"NumCounts", i64 5}
+!8 = !{!"NumFunctions", i64 3}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11, !12, !13, !14, !15, !16, !16, !17, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26}
+!11 = !{i32 10000, i64 10000000, i32 2}
+!12 = !{i32 100000, i64 10000000, i32 2}
+!13 = !{i32 200000, i64 10000000, i32 2}
+!14 = !{i32 300000, i64 10000000, i32 2}
+!15 = !{i32 400000, i64 10000000, i32 2}
+!16 = !{i32 500000, i64 10000000, i32 2}
+!17 = !{i32 600000, i64 10000000, i32 2}
+!18 = !{i32 700000, i64 10000000, i32 2}
+!19 = !{i32 800000, i64 10000000, i32 2}
+!20 = !{i32 900000, i64 10000000, i32 2}
+!21 = !{i32 950000, i64 10000000, i32 2}
+!22 = !{i32 990000, i64 10000000, i32 2}
+!23 = !{i32 999000, i64 10000000, i32 2}
+!24 = !{i32 999900, i64 10000000, i32 2}
+!25 = !{i32 999990, i64 10000000, i32 2}
+!26 = !{i32 999999, i64 10000000, i32 2}
+!30 = !{!"function_entry_count", i64 10000000}
+!31 = !{!"branch_weights", i32 2, i32 10000000}
+!32 = !{i32 59}
+!33 = !{!"function_entry_count", i64 1}
+!34 = !{!"branch_weights", i32 2, i32 10000001}

Added: llvm/trunk/test/Transforms/GlobalOpt/PowerPC/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/PowerPC/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/PowerPC/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/PowerPC/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,3 @@
+if not 'PowerPC' in config.root.targets:
+    config.unsupported = True
+

Added: llvm/trunk/test/Transforms/GlobalOpt/SROA-section.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/SROA-section.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/SROA-section.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/SROA-section.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; Verify that section assignment is copied during SROA
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: @G.0
+; CHECK: section ".foo"
+; CHECK: @G.1
+; CHECK: section ".foo"
+; CHECK: @G.2
+; CHECK: section ".foo"
+
+%T = type { double, double, double }
+ at G = internal global %T zeroinitializer, align 16, section ".foo"
+
+define void @test() {
+  store double 1.0, double* getelementptr (%T, %T* @G, i32 0, i32 0), align 16
+  store double 2.0, double* getelementptr (%T, %T* @G, i32 0, i32 1), align 8
+  store double 3.0, double* getelementptr (%T, %T* @G, i32 0, i32 2), align 16
+  ret void
+}
+
+define double @test2() {
+  %V1 = load double, double* getelementptr (%T, %T* @G, i32 0, i32 0), align 16
+  %V2 = load double, double* getelementptr (%T, %T* @G, i32 0, i32 1), align 8
+  %V3 = load double, double* getelementptr (%T, %T* @G, i32 0, i32 2), align 16
+  %R = fadd double %V1, %V2
+  %R2 = fadd double %R, %V3
+  ret double %R2
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/alias-resolve.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/alias-resolve.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/alias-resolve.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/alias-resolve.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at foo1 = alias void (), void ()* @foo2
+; CHECK: @foo1 = alias void (), void ()* @bar2
+
+ at foo2 = alias void(), void()* @bar1
+; CHECK: @foo2 = alias void (), void ()* @bar2
+
+ at bar1  = alias void (), void ()* @bar2
+; CHECK: @bar1 = alias void (), void ()* @bar2
+
+ at weak1 = weak alias void (), void ()* @bar2
+; CHECK: @weak1 = weak alias void (), void ()* @bar2
+
+ at bar4 = private unnamed_addr constant [2 x i8*] zeroinitializer
+ at foo4 = weak_odr unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @bar4, i32 0, i32 1)
+; CHECK: @foo4 = weak_odr unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @bar4, i32 0, i32 1)
+
+define void @bar2() {
+  ret void
+}
+; CHECK: define void @bar2()
+
+define void @baz() {
+entry:
+         call void @foo1()
+; CHECK: call void @bar2()
+
+         call void @foo2()
+; CHECK: call void @bar2()
+
+         call void @bar1()
+; CHECK: call void @bar2()
+
+         call void @weak1()
+; CHECK: call void @weak1()
+         ret void
+}
+
+ at foo3 = alias void (), void ()* @bar3
+; CHECK-NOT: bar3
+
+define internal void @bar3() {
+  ret void
+}
+;CHECK: define void @foo3

Added: llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+target datalayout = "p:32:32:32-p1:16:16:16"
+
+ at c = addrspace(1) global i8 42
+
+ at i = internal addrspace(1) global i8 42
+
+; CHECK: @ia = internal addrspace(1) global i8 42
+ at ia = internal alias i8, i8 addrspace(1)* @i
+
+ at llvm.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @ca to i8*)], section "llvm.metadata"
+; CHECK-DAG: @llvm.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @ca to i8*)], section "llvm.metadata"
+
+ at llvm.compiler.used = appending global [2 x i8*] [i8* addrspacecast(i8 addrspace(1)* @ia to i8*), i8* addrspacecast (i8 addrspace(1)* @i to i8*)], section "llvm.metadata"
+; CHECK-DAG: @llvm.compiler.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @ia to i8*)], section "llvm.metadata"
+
+ at sameAsUsed = global [1 x i8*] [i8* addrspacecast(i8 addrspace(1)* @ca to i8*)]
+; CHECK-DAG: @sameAsUsed = local_unnamed_addr global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @c to i8*)]
+
+ at ca = internal alias i8, i8 addrspace(1)* @c
+; CHECK: @ca = internal alias i8, i8 addrspace(1)* @c
+
+define i8 addrspace(1)* @h() {
+  ret i8 addrspace(1)* @ca
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/alias-used-section.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/alias-used-section.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/alias-used-section.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/alias-used-section.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+ at _Z17in_custom_section = internal global i8 42, section "CUSTOM"
+ at in_custom_section = internal dllexport alias i8, i8* @_Z17in_custom_section
+
+; CHECK: @in_custom_section = internal dllexport global i8 42, section "CUSTOM"
+
+ at llvm.used = appending global [1 x i8*] [i8* @in_custom_section], section "llvm.metadata"

Added: llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,66 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at c = global i8 42
+
+ at i = internal global i8 42
+; CHECK: @ia = internal global i8 42
+ at ia = internal alias i8, i8* @i
+
+ at llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata"
+; CHECK-DAG: @llvm.used = appending global [3 x i8*] [i8* @ca, i8* bitcast (void ()* @f to i8*), i8* bitcast (void ()* @fa to i8*)], section "llvm.metadata"
+
+ at llvm.compiler.used = appending global [4 x i8*] [i8* bitcast (void ()* @fa3 to i8*), i8* bitcast (void ()* @fa to i8*), i8* @ia, i8* @i], section "llvm.metadata"
+; CHECK-DAG: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @fa3 to i8*), i8* @ia], section "llvm.metadata"
+
+ at sameAsUsed = global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca]
+; CHECK-DAG: @sameAsUsed = local_unnamed_addr global [3 x i8*] [i8* bitcast (void ()* @f to i8*), i8* bitcast (void ()* @f to i8*), i8* @c]
+
+ at other = global i32* bitcast (void ()* @fa to i32*)
+; CHECK-DAG: @other = local_unnamed_addr global i32* bitcast (void ()* @f to i32*)
+
+ at fa = internal alias void (), void ()* @f
+; CHECK: @fa = internal alias void (), void ()* @f
+
+ at fa2 = internal alias void (), void ()* @f
+; CHECK-NOT: @fa2
+
+ at fa3 = internal alias void (), void ()* @f
+; CHECK: @fa3
+
+ at ca = internal alias i8, i8* @c
+; CHECK: @ca = internal alias i8, i8* @c
+
+define void @f() {
+  ret void
+}
+
+define i8* @g() {
+  ret i8* bitcast (void ()* @fa to i8*);
+}
+
+define i8* @g2() {
+  ret i8* bitcast (void ()* @fa2 to i8*);
+}
+
+define i8* @h() {
+  ret i8* @ca
+}
+
+; Check that GlobalOpt doesn't try to resolve aliases with GEP operands.
+
+%struct.S = type { i32, i32, i32 }
+ at s = global %struct.S { i32 1, i32 2, i32 3 }, align 4
+
+ at alias1 = alias i32, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i64 0, i32 1)
+ at alias2 = alias i32, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i64 0, i32 2)
+
+; CHECK: load i32, i32* @alias1, align 4
+; CHECK: load i32, i32* @alias2, align 4
+
+define i32 @foo1() {
+entry:
+  %0 = load i32, i32* @alias1, align 4
+  %1 = load i32, i32* @alias2, align 4
+  %add = add nsw i32 %1, %0
+  ret i32 %add
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/amdgcn-ctor-alloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/amdgcn-ctor-alloca.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/amdgcn-ctor-alloca.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/amdgcn-ctor-alloca.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt -data-layout=A5 -globalopt %s -S -o - | FileCheck %s
+
+; CHECK-NOT: @g
+ at g = internal addrspace(1) global i32* zeroinitializer
+
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }]
+   [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor, i8* null }]
+
+; CHECK-NOT: @ctor
+define internal void @ctor()  {
+  %addr = alloca i32, align 8, addrspace(5)
+  %tmp = addrspacecast i32 addrspace(5)* %addr to i32*
+  store i32* %tmp, i32* addrspace(1)* @g
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/array-elem-refs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -S -globalopt | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.S = type { i8, i8 }
+
+ at c = internal global i8** bitcast (i8* getelementptr (i8, i8* bitcast ([8 x i8*]* @b to i8*), i64 48) to i8**), align 8
+ at b = internal global [8 x i8*] [i8* null, i8* null, i8* null, i8* null, i8* null, i8* null, i8* getelementptr inbounds (%struct.S, %struct.S* @a, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S, %struct.S* @a, i32 0, i32 0), i64 1)], align 16
+ at a = internal global %struct.S zeroinitializer, align 1
+
+; Function Attrs: nounwind uwtable
+define signext i8 @foo() #0 {
+entry:
+  %0 = load i8**, i8*** @c, align 8
+  %1 = load i8*, i8** %0, align 8
+  %2 = load i8, i8* %1, align 1
+  ret i8 %2
+
+; CHECK-LABEL: @foo
+; CHECK: ret i8 0
+}
+
+; Function Attrs: nounwind uwtable
+define i32 @main() #0 {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval
+  ret i32 0
+}
+
+attributes #0 = { nounwind uwtable }
+

Added: llvm/trunk/test/Transforms/GlobalOpt/assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/assume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/assume.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/assume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+; CHECK: @tmp = local_unnamed_addr global i32 42
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+ at tmp = global i32 0
+
+define i32 @TheAnswerToLifeTheUniverseAndEverything() {
+  ret i32 42
+}
+
+define void @_GLOBAL__I_a() {
+enter:
+  %tmp1 = call i32 @TheAnswerToLifeTheUniverseAndEverything()
+  store i32 %tmp1, i32* @tmp
+  %cmp = icmp eq i32 %tmp1, 42
+  call void @llvm.assume(i1 %cmp)
+  ret void
+}
+
+declare void @llvm.assume(i1)

Added: llvm/trunk/test/Transforms/GlobalOpt/atexit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/atexit.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/atexit.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/atexit.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,6 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; CHECK: ModuleID
+define internal i32 @__cxa_atexit(void (i8*)* nocapture %func, i8* nocapture %arg, i8* nocapture %dso_handle) nounwind readnone optsize noimplicitfloat {
+  unreachable
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/atomic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/atomic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/atomic.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/atomic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -globalopt < %s -S -o - | FileCheck %s
+
+ at GV1 = internal global i64 1
+ at GV2 = internal global i32 0
+
+; CHECK: @GV1 = internal unnamed_addr constant i64 1
+; CHECK: @GV2 = internal unnamed_addr global i32 0
+
+define void @test1() {
+entry:
+  %0 = load atomic i8, i8* bitcast (i64* @GV1 to i8*) acquire, align 8
+  ret void
+}
+
+; PR17163
+define void @test2a() {
+entry:
+  store atomic i32 10, i32* @GV2 seq_cst, align 4
+  ret void
+}
+define i32 @test2b() {
+entry:
+  %atomic-load = load atomic i32, i32* @GV2 seq_cst, align 4
+  ret i32 %atomic-load
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/available_externally_global_ctors.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/available_externally_global_ctors.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/available_externally_global_ctors.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/available_externally_global_ctors.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+; Verify that the initialization of the available_externally global is not eliminated
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @foo_static_init, i8* null }]
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @foo_static_init, i8* null }]
+ at foo_external = available_externally global void ()* null
+
+define internal void @foo_static_init() {
+entry:
+  store void ()* @foo_impl, void ()** @foo_external
+  ret void
+}
+
+define internal void @foo_impl() {
+entry:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/basictest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/basictest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/basictest.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/basictest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; RUN: opt < %s -passes=globalopt -S | FileCheck %s
+
+; CHECK-NOT: global
+ at X = internal global i32 4              ; <i32*> [#uses=1]
+
+define i32 @foo() {
+        %V = load i32, i32* @X               ; <i32> [#uses=1]
+        ret i32 %V
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/blockaddress.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/blockaddress.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/blockaddress.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/blockaddress.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at x = internal global i8* zeroinitializer
+
+define void @f() {
+; CHECK-LABEL: @f(
+
+; Check that we don't hit an assert in Constant::IsThreadDependent()
+; when storing this blockaddress into a global.
+
+  store i8* blockaddress(@g, %here), i8** @x, align 8
+  ret void
+}
+
+define void @g() {
+entry:
+  br label %here
+
+; CHECK-LABEL: @g(
+
+here:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/cleanup-pointer-root-users.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -globalopt -S -o - < %s | FileCheck %s
+
+ at glbl = internal global i8* null
+
+define void @test1a() {
+; CHECK-LABEL: @test1a(
+; CHECK-NOT: store
+; CHECK-NEXT: ret void
+  store i8* null, i8** @glbl
+  ret void
+}
+
+define void @test1b(i8* %p) {
+; CHECK-LABEL: @test1b(
+; CHECK-NEXT: store
+; CHECK-NEXT: ret void
+  store i8* %p, i8** @glbl
+  ret void
+}
+
+define void @test2() {
+; CHECK-LABEL: @test2(
+; CHECK: alloca i8
+  %txt = alloca i8
+  call void @foo2(i8* %txt)
+  %call2 = call i8* @strdup(i8* %txt)
+  store i8* %call2, i8** @glbl
+  ret void
+}
+declare i8* @strdup(i8*)
+declare void @foo2(i8*)
+
+define void @test3() uwtable personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 {
+; CHECK-LABEL: @test3(
+; CHECK-NOT: bb1:
+; CHECK-NOT: bb2:
+; CHECK: invoke
+  %ptr = invoke i8* @_Znwm(i64 1)
+          to label %bb1 unwind label %bb2
+bb1:
+  store i8* %ptr, i8** @glbl
+  unreachable
+bb2:
+  %tmp1 = landingpad { i8*, i32 }
+          cleanup
+  resume { i8*, i32 } %tmp1
+}
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
+declare i8* @_Znwm(i64)

Added: llvm/trunk/test/Transforms/GlobalOpt/coldcc_stress_test.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/coldcc_stress_test.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/coldcc_stress_test.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/coldcc_stress_test.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; RUN: opt < %s -globalopt -S -enable-coldcc-stress-test -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=COLDCC
+; RUN: opt < %s -globalopt -S | FileCheck %s -check-prefix=CHECK
+
+define internal i32 @callee_default(i32* %m) {
+; COLDCC-LABEL: define internal coldcc i32 @callee_default
+; CHECK-LABEL: define internal fastcc i32 @callee_default
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define internal fastcc i32 @callee_fastcc(i32* %m) {
+; COLDCC-LABEL: define internal fastcc i32 @callee_fastcc
+; CHECK-LABEL: define internal fastcc i32 @callee_fastcc
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define internal coldcc i32 @callee_coldcc(i32* %m) {
+; COLDCC-LABEL: define internal coldcc i32 @callee_coldcc
+; CHECK-LABEL: define internal coldcc i32 @callee_coldcc
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define i32 @callee(i32* %m) {
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define void @caller() {
+  %m = alloca i32
+  call i32 @callee_default(i32* %m)
+  call fastcc i32 @callee_fastcc(i32* %m)
+  call coldcc i32 @callee_coldcc(i32* %m)
+  call i32 @callee(i32* %m)
+  ret void
+}
+
+; COLDCC-LABEL: define void @caller()
+; COLDCC: call coldcc i32 @callee_default
+; COLDCC: call fastcc i32 @callee_fastcc
+; COLDCC: call coldcc i32 @callee_coldcc
+; COLDCC: call i32 @callee
+; CHECK-LABEL: define void @caller()
+; CHECK: call fastcc i32 @callee_default
+; CHECK: call fastcc i32 @callee_fastcc
+; CHECK: call coldcc i32 @callee_coldcc
+; CHECK: call i32 @callee

Added: llvm/trunk/test/Transforms/GlobalOpt/compiler-used.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/compiler-used.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/compiler-used.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/compiler-used.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; Test that when all members of llvm.compiler.used are found to be redundant
+; we delete it instead of crashing.
+
+define void @foo() {
+  ret void
+}
+
+ at llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)], section "llvm.metadata"
+
+ at llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)], section "llvm.metadata"
+
+; CHECK-NOT: @llvm.compiler.used
+; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)], section "llvm.metadata"
+; CHECK-NOT: @llvm.compiler.used

Added: llvm/trunk/test/Transforms/GlobalOpt/constantexpr-dangle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/constantexpr-dangle.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/constantexpr-dangle.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/constantexpr-dangle.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt < %s -instcombine -globalopt -S | FileCheck %s
+; CHECK: internal fastcc float @foo
+
+define internal float @foo() {
+        ret float 0.000000e+00
+}
+
+define float @bar() {
+        %tmp1 = call float (...) bitcast (float ()* @foo to float (...)*)( )
+        %tmp2 = fmul float %tmp1, 1.000000e+01           ; <float> [#uses=1]
+        ret float %tmp2
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,103 @@
+; RUN: opt < %s -S -globalopt | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+
+ at .str91250 = global [3 x i8] zeroinitializer
+
+; CHECK: @A = local_unnamed_addr global i1 false
+ at A = global i1 icmp ne (i64 sub nsw (i64 ptrtoint (i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str91250, i64 0, i64 1) to i64), i64 ptrtoint ([3 x i8]* @.str91250 to i64)), i64 1)
+
+; PR11352
+
+ at xs = global [2 x i32] zeroinitializer, align 4
+; CHECK: @xs = local_unnamed_addr global [2 x i32] [i32 1, i32 1]
+
+; PR12642
+%PR12642.struct = type { i8 }
+ at PR12642.s = global <{}> zeroinitializer, align 1
+ at PR12642.p = constant %PR12642.struct* bitcast (i8* getelementptr (i8, i8* bitcast (<{}>* @PR12642.s to i8*), i64 1) to %PR12642.struct*), align 8
+
+define internal void @test1() {
+entry:
+  store i32 1, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @xs, i64 0, i64 0)
+  %0 = load i32, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @xs, i32 0, i64 0), align 4
+  store i32 %0, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @xs, i64 0, i64 1)
+  ret void
+}
+
+; PR12060
+
+%closure = type { i32 }
+
+ at f = internal global %closure zeroinitializer, align 4
+ at m = global i32 0, align 4
+; CHECK-NOT: @f
+; CHECK: @m = local_unnamed_addr global i32 13
+
+define internal i32 @test2_helper(%closure* %this, i32 %b) {
+entry:
+  %0 = getelementptr inbounds %closure, %closure* %this, i32 0, i32 0
+  %1 = load i32, i32* %0, align 4
+  %add = add nsw i32 %1, %b
+  ret i32 %add
+}
+
+define internal void @test2() {
+entry:
+  store i32 4, i32* getelementptr inbounds (%closure, %closure* @f, i32 0, i32 0)
+  %call = call i32 @test2_helper(%closure* @f, i32 9)
+  store i32 %call, i32* @m, align 4
+  ret void
+}
+
+; PR19955
+
+ at dllimportptr = global i32* null, align 4
+; CHECK: @dllimportptr = local_unnamed_addr global i32* null, align 4
+ at dllimportvar = external dllimport global i32
+define internal void @test3() {
+entry:
+  store i32* @dllimportvar, i32** @dllimportptr, align 4
+  ret void
+}
+
+ at dllexportptr = global i32* null, align 4
+; CHECK: @dllexportptr = local_unnamed_addr global i32* @dllexportvar, align 4
+ at dllexportvar = dllexport global i32 0, align 4
+; CHECK: @dllexportvar = dllexport global i32 20, align 4
+define internal void @test4() {
+entry:
+  store i32 20, i32* @dllexportvar, align 4
+  store i32* @dllexportvar, i32** @dllexportptr, align 4
+  ret void
+}
+
+ at threadlocalptr = global i32* null, align 4
+; CHECK: @threadlocalptr = global i32* null, align 4
+ at threadlocalvar = external thread_local global i32
+define internal void @test5() {
+entry:
+  store i32* @threadlocalvar, i32** @threadlocalptr, align 4
+  ret void
+}
+
+ at test6_v1 = internal global { i32, i32 } { i32 42, i32 0 }, align 8
+ at test6_v2 = global i32 0, align 4
+; CHECK: @test6_v2 = local_unnamed_addr global i32 42, align 4
+define internal void @test6() {
+  %load = load { i32, i32 }, { i32, i32 }* @test6_v1, align 8
+  %xv0 = extractvalue { i32, i32 } %load, 0
+  %iv = insertvalue { i32, i32 } %load, i32 %xv0, 1
+  %xv1 = extractvalue { i32, i32 } %iv, 1
+  store i32 %xv1, i32* @test6_v2, align 4
+  ret void
+}
+
+ at llvm.global_ctors = appending constant
+  [6 x { i32, void ()* }]
+  [{ i32, void ()* } { i32 65535, void ()* @test1 },
+   { i32, void ()* } { i32 65535, void ()* @test2 },
+   { i32, void ()* } { i32 65535, void ()* @test3 },
+   { i32, void ()* } { i32 65535, void ()* @test4 },
+   { i32, void ()* } { i32 65535, void ()* @test5 },
+   { i32, void ()* } { i32 65535, void ()* @test6 }]

Added: llvm/trunk/test/Transforms/GlobalOpt/crash-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/crash-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/crash-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/crash-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | opt -globalopt -disable-output
+; NOTE: This needs to run through 'llvm-as' first to reproduce the error!
+; PR15440
+
+%union.U5.0.6.12 = type { i32 }
+%struct.S0.1.7.13 = type { i8, i8, i8, i8, i16, [2 x i8] }
+%struct.S1.2.8.14 = type { i32, i16, i8, i8 }
+
+ at .str = external unnamed_addr constant [2 x i8], align 1
+ at g_25 = external global i8, align 1
+ at g_71 = internal global %struct.S0.1.7.13 { i8 1, i8 -93, i8 58, i8 -1, i16 -5, [2 x i8] undef }, align 4
+ at g_114 = external global i8, align 1
+ at g_30 = external global { i32, i8, i32, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 }, align 4
+ at g_271 = internal global [7 x [6 x [5 x i8*]]] [[6 x [5 x i8*]] [[5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* null], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114, i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* null, i8* null], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)]], [6 x [5 x i8*]] [[5 x i8*] [i8* @g_25, i8* null, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* @g_25, i8* @g_114, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25], [5 x i8*] [i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* @g_25, i8* @g_25, i8* @g_25], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)]], [6 x [5 x i8*]] [[5 x i8*] [i8* null, i8* @g_25, i8* @g_25, i8* @g_25, i8* null], [5 x i8*] [i8* @g_25, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* null, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* null, i8* @g_25], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* null], [5 x i8*] [i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)]], [6 x [5 x i8*]] [[5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* null, i8* @g_25], [5 x i8*] [i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* @g_25, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* @g_25], [5 x i8*] [i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* @g_114, i8* @g_25, i8* @g_25, i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)]], [6 x [5 x i8*]] [[5 x i8*] [i8* @g_25, i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* @g_25], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_114], [5 x i8*] [i8* @g_25, i8* null, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* null], [5 x i8*] [i8* @g_114, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114, i8* @g_25]], [6 x [5 x i8*]] [[5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* @g_114, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0)], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25]], [6 x [5 x i8*]] [[5 x i8*] [i8* @g_25, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* null], [5 x i8*] [i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114, i8* @g_25, i8* @g_25, i8* @g_114], [5 x i8*] [i8* null, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_25, i8* null, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_114, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* @g_114, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1)], [5 x i8*] [i8* @g_25, i8* @g_25, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25], [5 x i8*] [i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25, i8* @g_25, i8* getelementptr (i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), i64 1), i8* @g_25]]], align 4
+
+define i32 @func() {
+  %tmp = load i8, i8* getelementptr inbounds (%struct.S0.1.7.13, %struct.S0.1.7.13* @g_71, i32 0, i32 0), align 1
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/crash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,80 @@
+; RUN: opt -globalopt -disable-output < %s
+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-f80:128:128-n8:16:32"
+target triple = "i386-apple-darwin9.8"
+
+%0 = type { i32, void ()* }
+%struct.btSimdScalar = type { %"union.btSimdScalar::$_14" }
+%"union.btSimdScalar::$_14" = type { <4 x float> }
+
+ at _ZL6vTwist =  global %struct.btSimdScalar zeroinitializer ; <%struct.btSimdScalar*> [#uses=1]
+ at llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I__ZN21btConeTwistConstraintC2Ev }] ; <[12 x %0]*> [#uses=0]
+
+define internal void @_GLOBAL__I__ZN21btConeTwistConstraintC2Ev() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
+entry:
+  store float 1.0, float* getelementptr inbounds (%struct.btSimdScalar, %struct.btSimdScalar* @_ZL6vTwist, i32 0, i32 0, i32 0, i32 3), align 4
+  ret void
+}
+
+
+; PR6760
+%T = type { [5 x i32] }
+
+ at switch_inf = internal global %T* null
+
+define void @test(i8* %arch_file, i32 %route_type) {
+entry:
+  %A = sext i32 1 to i64
+  %B = mul i64 %A, 20
+  %C = call noalias i8* @malloc(i64 %B) nounwind
+  %D = bitcast i8* %C to %T*
+  store %T* %D, %T** @switch_inf, align 8
+  unreachable
+
+bb.nph.i: 
+  %scevgep.i539 = getelementptr i8, i8* %C, i64 4
+  unreachable
+
+xx:
+  %E = load %T*, %T** @switch_inf, align 8 
+  unreachable
+}
+
+declare noalias i8* @malloc(i64) nounwind
+
+
+; PR8063
+ at permute_bitrev.bitrev = internal global i32* null, align 8
+define void @permute_bitrev() nounwind {
+entry:
+  %tmp = load i32*, i32** @permute_bitrev.bitrev, align 8
+  %conv = sext i32 0 to i64
+  %mul = mul i64 %conv, 4
+  %call = call i8* @malloc(i64 %mul)
+  %0 = bitcast i8* %call to i32*
+  store i32* %0, i32** @permute_bitrev.bitrev, align 8
+  ret void
+}
+
+
+
+
+ at data8 = internal global [8000 x i8] zeroinitializer, align 16
+define void @memset_with_strange_user() ssp {
+  call void @llvm.memset.p0i8.i64(i8* align 16 getelementptr inbounds ([8000 x i8], [8000 x i8]* @data8, i64 0, i64 0), i8 undef, i64 ptrtoint (i8* getelementptr ([8000 x i8], [8000 x i8]* @data8, i64 1, i64 sub (i64 0, i64 ptrtoint ([8000 x i8]* @data8 to i64))) to i64), i1 false)
+  ret void
+}
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
+
+
+; PR9856
+ at g_52 = internal global i32** null, align 8
+ at g_90 = external global i32*, align 8
+
+define void @icmp_user_of_stored_once() nounwind ssp {
+entry:
+  %tmp4 = load i32**, i32*** @g_52, align 8
+  store i32** @g_90, i32*** @g_52
+  %cmp17 = icmp ne i32*** undef, @g_52
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0.0"
+
+%0 = type { i32, void ()* }
+%struct.foo = type { i32* }
+%struct.bar = type { i128 }
+
+ at G = global i32 0, align 4
+ at H = global i32 0, align 4
+ at X = global %struct.foo zeroinitializer, align 8
+ at X2 = global %struct.bar zeroinitializer, align 8
+ at llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @init1 }, %0 { i32 65535, void ()* @init2 }]
+
+; PR8710 - GlobalOpt shouldn't change the global's initializer to have this
+; arbitrary constant expression, the code generator can't handle it.
+define internal void @init1() {
+entry:
+  %tmp = getelementptr inbounds %struct.foo, %struct.foo* @X, i32 0, i32 0
+  store i32* inttoptr (i64 sdiv (i64 ptrtoint (i32* @G to i64), i64 ptrtoint (i32* @H to i64)) to i32*), i32** %tmp, align 8
+  ret void
+}
+; CHECK-LABEL: @init1(
+; CHECK: store i32*
+
+; PR11705 - ptrtoint isn't safe in general in global initializers.
+define internal void @init2() {
+entry:
+  %tmp = getelementptr inbounds %struct.bar, %struct.bar* @X2, i32 0, i32 0
+  store i128 ptrtoint (i32* @G to i128), i128* %tmp, align 16
+  ret void
+}
+; CHECK-LABEL: @init2(
+; CHECK: store i128

Added: llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; Don't get fooled by the inbounds keyword; it doesn't change
+; the computed address.
+
+; CHECK: @H = local_unnamed_addr global i32 2
+; CHECK: @I = local_unnamed_addr global i32 2
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR } ]
+ at addr = external global i32
+ at G = internal global [6 x [5 x i32]] zeroinitializer
+ at H = global i32 80
+ at I = global i32 90
+
+define internal void @CTOR() {
+  store i32 1, i32* getelementptr ([6 x [5 x i32]], [6 x [5 x i32]]* @G, i64 0, i64 0, i64 0)
+  store i32 2, i32* getelementptr inbounds ([6 x [5 x i32]], [6 x [5 x i32]]* @G, i64 0, i64 0, i64 0)
+  %t = load i32, i32* getelementptr ([6 x [5 x i32]], [6 x [5 x i32]]* @G, i64 0, i64 0, i64 0)
+  store i32 %t, i32* @H
+  %s = load i32, i32* getelementptr inbounds ([6 x [5 x i32]], [6 x [5 x i32]]* @G, i64 0, i64 0, i64 0)
+  store i32 %s, i32* @I
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,115 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: CTOR
+%ini = type { i32, void()*, i8* }
+ at llvm.global_ctors = appending global [11 x %ini] [
+	%ini { i32 65535, void ()* @CTOR1, i8* null },
+	%ini { i32 65535, void ()* @CTOR1, i8* null },
+	%ini { i32 65535, void ()* @CTOR2, i8* null },
+	%ini { i32 65535, void ()* @CTOR3, i8* null },
+	%ini { i32 65535, void ()* @CTOR4, i8* null },
+	%ini { i32 65535, void ()* @CTOR5, i8* null },
+	%ini { i32 65535, void ()* @CTOR6, i8* null },
+	%ini { i32 65535, void ()* @CTOR7, i8* null },
+	%ini { i32 65535, void ()* @CTOR8, i8* null },
+	%ini { i32 65535, void ()* @CTOR9, i8* null },
+	%ini { i32 2147483647, void ()* null, i8* null }
+]
+
+ at G = global i32 0		; <i32*> [#uses=1]
+ at G2 = global i32 0		; <i32*> [#uses=1]
+ at G3 = global i32 -123		; <i32*> [#uses=2]
+ at X = global { i32, [2 x i32] } { i32 0, [2 x i32] [ i32 17, i32 21 ] }		; <{ i32, [2 x i32] }*> [#uses=2]
+ at Y = global i32 -1		; <i32*> [#uses=2]
+ at Z = global i32 123		; <i32*> [#uses=1]
+ at D = global double 0.000000e+00		; <double*> [#uses=1]
+ at CTORGV = internal global i1 false		; <i1*> [#uses=2]
+
+define internal void @CTOR1() {
+	ret void
+}
+
+define internal void @CTOR2() {
+	%A = add i32 1, 23		; <i32> [#uses=1]
+	store i32 %A, i32* @G
+	store i1 true, i1* @CTORGV
+	ret void
+}
+
+define internal void @CTOR3() {
+	%X = or i1 true, false		; <i1> [#uses=1]
+	br label %Cont
+
+Cont:		; preds = %0
+	br i1 %X, label %S, label %T
+
+S:		; preds = %Cont
+	store i32 24, i32* @G2
+	ret void
+
+T:		; preds = %Cont
+	ret void
+}
+
+define internal void @CTOR4() {
+	%X = load i32, i32* @G3		; <i32> [#uses=1]
+	%Y = add i32 %X, 123		; <i32> [#uses=1]
+	store i32 %Y, i32* @G3
+	ret void
+}
+
+define internal void @CTOR5() {
+	%X.2p = getelementptr inbounds { i32, [2 x i32] }, { i32, [2 x i32] }* @X, i32 0, i32 1, i32 0		; <i32*> [#uses=2]
+	%X.2 = load i32, i32* %X.2p		; <i32> [#uses=1]
+	%X.1p = getelementptr inbounds { i32, [2 x i32] }, { i32, [2 x i32] }* @X, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 %X.2, i32* %X.1p
+	store i32 42, i32* %X.2p
+	ret void
+}
+
+define internal void @CTOR6() {
+	%A = alloca i32		; <i32*> [#uses=2]
+	%y = load i32, i32* @Y		; <i32> [#uses=1]
+	store i32 %y, i32* %A
+	%Av = load i32, i32* %A		; <i32> [#uses=1]
+	%Av1 = add i32 %Av, 1		; <i32> [#uses=1]
+	store i32 %Av1, i32* @Y
+	ret void
+}
+
+define internal void @CTOR7() {
+	call void @setto( i32* @Z, i32 0 )
+	ret void
+}
+
+define void @setto(i32* %P, i32 %V) {
+	store i32 %V, i32* %P
+	ret void
+}
+
+declare double @cos(double)
+
+define internal void @CTOR8() {
+	%X = call double @cos( double 0.000000e+00 )		; <double> [#uses=1]
+	store double %X, double* @D
+	ret void
+}
+
+define i1 @accessor() {
+	%V = load i1, i1* @CTORGV		; <i1> [#uses=1]
+	ret i1 %V
+}
+
+%struct.A = type { i32 }
+%struct.B = type { i32 (...)**, i8*, [4 x i8] }
+ at GV1 = global %struct.B zeroinitializer, align 8
+ at GV2 =  constant [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64 }* null to i8*)]
+; CHECK-NOT: CTOR9
+define internal void @CTOR9() {
+entry:
+  %0 = bitcast %struct.B* @GV1 to i8*
+  %1 = getelementptr inbounds i8, i8* %0, i64 16
+  %2 = bitcast i8* %1 to %struct.A*
+  %3 = bitcast %struct.B* @GV1 to i8***
+  store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @GV2, i64 1, i64 0), i8*** %3
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -S -passes='cgscc(inline),function(early-cse),globalopt' | FileCheck %s
+
+%0 = type { i32, void ()* }
+%struct.A = type { i8 }
+%struct.B = type { }
+
+ at a = global %struct.A zeroinitializer, align 1
+ at __dso_handle = external global i8*
+ at llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a }]
+
+; CHECK-NOT: call i32 @__cxa_atexit
+
+define internal void @__cxx_global_var_init() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
+  %1 = call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A, %struct.A* @a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
+  ret void
+}
+
+define linkonce_odr void @_ZN1AD1Ev(%struct.A* %this) nounwind align 2 {
+  %t = bitcast %struct.A* %this to %struct.B*
+  call void @_ZN1BD1Ev(%struct.B* %t)
+  ret void
+}
+
+declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+
+define linkonce_odr void @_ZN1BD1Ev(%struct.B* %this) nounwind align 2 {
+  ret void
+}
+
+define internal void @_GLOBAL__I_a() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @__cxx_global_var_init()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/deaddeclaration.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/deaddeclaration.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/deaddeclaration.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/deaddeclaration.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,7 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; CHECK-NOT: aa
+; CHECK-NOT: bb
+
+declare void @aa()
+ at bb = external global i8

Added: llvm/trunk/test/Transforms/GlobalOpt/deadfunction.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/deadfunction.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/deadfunction.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/deadfunction.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; CHECK-NOT: test
+
+declare void @aa()
+declare void @bb()
+
+; Test that we can erase a function which has a blockaddress referring to it
+ at test.x = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@test, %a), i8* blockaddress(@test, %b), i8* blockaddress(@test, %c)], align 16
+define internal void @test(i32 %n) nounwind noinline {
+entry:
+  %idxprom = sext i32 %n to i64
+  %arrayidx = getelementptr inbounds [3 x i8*], [3 x i8*]* @test.x, i64 0, i64 %idxprom
+  %0 = load i8*, i8** %arrayidx, align 8
+  indirectbr i8* %0, [label %a, label %b, label %c]
+
+a:
+  tail call void @aa() nounwind
+  br label %b
+
+b:
+  tail call void @bb() nounwind
+  br label %c
+
+c:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/deadglobal-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/deadglobal-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/deadglobal-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/deadglobal-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; This is a harder case to delete as the GEP has a variable index.
+
+; CHECK-NOT: internal
+ at G = internal global [4 x i32] zeroinitializer
+
+define void @foo(i32 %X) {
+	%Ptr = getelementptr [4 x i32], [4 x i32]* @G, i32 0, i32 %X
+	store i32 1, i32* %Ptr
+	ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/deadglobal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/deadglobal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/deadglobal.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/deadglobal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at G1 = internal global i32 123            ; <i32*> [#uses=1]
+ at A1 = internal alias i32, i32* @G1
+
+; CHECK-NOT: @G1
+; CHECK: @G2
+; CHECK-NOT: @G3
+
+; CHECK-NOT: @A1
+
+define void @foo1() {
+; CHECK: define void @foo
+; CHECK-NEXT: ret
+        store i32 1, i32* @G1
+        ret void
+}
+
+ at G2 = linkonce_odr constant i32 42
+
+define void @foo2() {
+; CHECK-LABEL: define void @foo2(
+; CHECK-NEXT: store
+        store i32 1, i32* @G2
+        ret void
+}
+
+ at G3 = linkonce_odr constant i32 42

Added: llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -globalopt -instcombine %s -S -o - | FileCheck %s
+
+; Static constructor should have been optimized out
+; CHECK:       i32 @main
+; CHECK-NEXT:     ret i32 69905
+; CHECK-NOT:   _GLOBAL__sub_I_main.cpp
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+%struct.S = type { %struct.A* }
+%struct.A = type { i64, i64 }
+
+ at s = internal local_unnamed_addr global %struct.S zeroinitializer, align 8
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_main.cpp, i8* null }]
+ at gA = available_externally dso_local local_unnamed_addr global %struct.A* inttoptr (i64 69905 to %struct.A*), align 8
+
+define dso_local i32 @main() local_unnamed_addr {
+  %1 = load i64, i64* bitcast (%struct.S* @s to i64*), align 8
+  %2 = trunc i64 %1 to i32
+  ret i32 %2
+}
+
+define internal void @_GLOBAL__sub_I_main.cpp() section ".text.startup" {
+  %1 = load i64, i64* bitcast (%struct.A** @gA to i64*), align 8
+  store i64 %1, i64* bitcast (%struct.S* @s to i64*), align 8
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/evaluate-call-errors.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/evaluate-call-errors.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/evaluate-call-errors.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/evaluate-call-errors.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,99 @@
+; Checks for few bitcasted call evaluation errors
+
+; REQUIRES: asserts
+; RUN: opt -globalopt -instcombine -S -debug-only=evaluator %s -o %t 2>&1 | FileCheck %s
+
+; CHECK: Failed to fold bitcast call expr
+; CHECK: Can not convert function argument
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+%struct.S = type { i32 }
+%struct.Q = type { i32 }
+%struct.Foo = type { i32 }
+
+ at _s = global %struct.S zeroinitializer, align 4
+ at _q = global %struct.Q zeroinitializer, align 4
+ at llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_main2.cpp, i8* null }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_main3.cpp, i8* null }]
+
+define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @_ZN1SC1Ev(%struct.S* @_s)
+  ret void
+}
+
+define linkonce_odr void @_ZN1SC1Ev(%struct.S*) unnamed_addr align 2 {
+  %2 = alloca %struct.S*, align 8
+  store %struct.S* %0, %struct.S** %2, align 8
+  %3 = load %struct.S*, %struct.S** %2, align 8
+  call void @_ZN1SC2Ev(%struct.S* %3)
+  ret void
+}
+
+define internal void @__cxx_global_var_init.1() #0 section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @_ZN1QC1Ev(%struct.Q* @_q)
+  ret void
+}
+
+define linkonce_odr void @_ZN1QC1Ev(%struct.Q*) unnamed_addr  align 2 {
+  %2 = alloca %struct.Q*, align 8
+  store %struct.Q* %0, %struct.Q** %2, align 8
+  %3 = load %struct.Q*, %struct.Q** %2, align 8
+  call void @_ZN1QC2Ev(%struct.Q* %3)
+  ret void
+}
+
+define i32 @main() {
+  %1 = alloca i32, align 4
+  store i32 0, i32* %1, align 4
+  ret i32 0
+}
+
+define linkonce_odr void @_ZN1SC2Ev(%struct.S*) unnamed_addr align 2 {
+  %2 = alloca %struct.S*, align 8
+  %3 = alloca %struct.Foo, align 4
+  store %struct.S* %0, %struct.S** %2, align 8
+  %4 = load %struct.S*, %struct.S** %2, align 8
+  %5 = getelementptr inbounds %struct.S, %struct.S* %4, i32 0, i32 0
+  %6 = call i32 bitcast (%struct.Foo* ()* @_ZL3foov to i32 ()*)()
+  %7 = getelementptr inbounds %struct.Foo, %struct.Foo* %3, i32 0, i32 0
+  store i32 %6, i32* %7, align 4
+  %8 = getelementptr inbounds %struct.Foo, %struct.Foo* %3, i32 0, i32 0
+  %9 = load i32, i32* %8, align 4
+  store i32 %9, i32* %5, align 4
+  ret void
+}
+
+define internal %struct.Foo* @_ZL3foov() {
+  ret %struct.Foo* null
+}
+
+define linkonce_odr void @_ZN1QC2Ev(%struct.Q*) unnamed_addr align 2 {
+  %2 = alloca %struct.Q*, align 8
+  store %struct.Q* %0, %struct.Q** %2, align 8
+  %3 = load %struct.Q*, %struct.Q** %2, align 8
+  %4 = getelementptr inbounds %struct.Q, %struct.Q* %3, i32 0, i32 0
+  %5 = call i32 bitcast (i32 (i32)* @_ZL3baz3Foo to i32 (%struct.Foo*)*)(%struct.Foo* null)
+  store i32 %5, i32* %4, align 4
+  ret void
+}
+
+define internal i32 @_ZL3baz3Foo(i32) {
+  %2 = alloca %struct.Foo, align 4
+  %3 = getelementptr inbounds %struct.Foo, %struct.Foo* %2, i32 0, i32 0
+  store i32 %0, i32* %3, align 4
+  %4 = getelementptr inbounds %struct.Foo, %struct.Foo* %2, i32 0, i32 0
+  %5 = load i32, i32* %4, align 4
+  ret i32 %5
+}
+
+; Function Attrs: noinline ssp uwtable
+define internal void @_GLOBAL__sub_I_main2.cpp() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @__cxx_global_var_init()
+  ret void
+}
+
+define internal void @_GLOBAL__sub_I_main3.cpp() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @__cxx_global_var_init.1()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/evaluate-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/evaluate-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/evaluate-call.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/evaluate-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; Checks if bitcasted call expression can be evaluated
+; Given call expresion:
+;   %struct.Bar* bitcast (%struct.Foo* (%struct.Foo*)* @_ZL3fooP3Foo to %struct.Bar* (%struct.Bar*)*)(%struct.Bar* @gBar)
+; We evaluate call to function @_ZL3fooP3Foo casting both parameter and return value
+; Given call expression:
+;   void bitcast (void (%struct.Foo*)* @_ZL3bazP3Foo to void (%struct.Bar*)*)(%struct.Bar* @gBar) 
+; We evaluate call to function _ZL3bazP3Foo casting its parameter and check that evaluated value (nullptr)
+; is handled correctly
+
+; RUN: opt -globalopt -instcombine -S %s -o - | FileCheck %s
+
+; CHECK:      @gBar = local_unnamed_addr global %struct.Bar { i32 2 }
+; CHECK-NEXT: @_s = local_unnamed_addr global %struct.S { i32 1 }, align 4
+; CHECK-NEXT: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+
+; CHECK:      define i32 @main()
+; CHECK-NEXT:   ret i32 0
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+%struct.Bar = type { i32 }
+%struct.S = type { i32 }
+%struct.Foo = type { i32 }
+
+ at gBar = global %struct.Bar zeroinitializer, align 4
+ at _s = global %struct.S zeroinitializer, align 4
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_main.cpp, i8* null }]
+
+define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @_ZN1SC1Ev_alias(%struct.S* @_s)
+  ret void
+}
+
+ at _ZN1SC1Ev_alias = linkonce_odr unnamed_addr alias void (%struct.S*), void (%struct.S*)* @_ZN1SC1Ev
+
+define linkonce_odr void @_ZN1SC1Ev(%struct.S*) unnamed_addr align 2 {
+  %2 = alloca %struct.S*, align 8
+  store %struct.S* %0, %struct.S** %2, align 8
+  %3 = load %struct.S*, %struct.S** %2, align 8
+  call void @_ZN1SC2Ev(%struct.S* %3)
+  ret void
+}
+
+define i32 @main()  {
+  %1 = alloca i32, align 4
+  store i32 0, i32* %1, align 4
+  ret i32 0
+}
+
+define linkonce_odr void @_ZN1SC2Ev(%struct.S*) unnamed_addr align 2 {
+  %2 = alloca %struct.S*, align 8
+  store %struct.S* %0, %struct.S** %2, align 8
+  %3 = load %struct.S*, %struct.S** %2, align 8
+  %4 = getelementptr inbounds %struct.S, %struct.S* %3, i32 0, i32 0
+  %5 = call %struct.Bar* bitcast (%struct.Foo* (%struct.Foo*)* @_ZL3fooP3Foo to %struct.Bar* (%struct.Bar*)*)(%struct.Bar* @gBar)
+  %6 = getelementptr inbounds %struct.Bar, %struct.Bar* %5, i32 0, i32 0
+  %7 = load i32, i32* %6, align 4
+  store i32 %7, i32* %4, align 4
+  call void bitcast (void (%struct.Foo*)* @_ZL3bazP3Foo to void (%struct.Bar*)*)(%struct.Bar* @gBar)
+  ret void
+}
+
+define internal %struct.Foo* @_ZL3fooP3Foo(%struct.Foo*) {
+  %2 = alloca %struct.Foo*, align 8
+  store %struct.Foo* %0, %struct.Foo** %2, align 8
+  %3 = load %struct.Foo*, %struct.Foo** %2, align 8
+  %4 = getelementptr inbounds %struct.Foo, %struct.Foo* %3, i32 0, i32 0
+  store i32 1, i32* %4, align 4
+  %5 = load %struct.Foo*, %struct.Foo** %2, align 8
+  ret %struct.Foo* %5
+}
+
+define internal void @_ZL3bazP3Foo(%struct.Foo*) {
+  %2 = alloca %struct.Foo*, align 8
+  store %struct.Foo* %0, %struct.Foo** %2, align 8
+  %3 = load %struct.Foo*, %struct.Foo** %2, align 8
+  %4 = getelementptr inbounds %struct.Foo, %struct.Foo* %3, i32 0, i32 0
+  store i32 2, i32* %4, align 4
+  ret void
+}
+
+; Function Attrs: noinline ssp uwtable
+define internal void @_GLOBAL__sub_I_main.cpp() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @__cxx_global_var_init()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/evaluate-constfold-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/evaluate-constfold-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/evaluate-constfold-call.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/evaluate-constfold-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; Check if we can evaluate a bitcasted call to a function which is constant folded.
+; Evaluator folds call to fmodf, replacing it with constant value in case both operands
+; are known at compile time.
+; RUN: opt -globalopt -instcombine %s -S -o - | FileCheck %s
+
+; CHECK:        @_q = dso_local local_unnamed_addr global %struct.Q { i32 1066527622 }
+; CHECK:        define dso_local i32 @main
+; CHECK-NEXT:     %[[V:.+]] = load i32, i32* getelementptr inbounds (%struct.Q, %struct.Q* @_q, i64 0, i32 0)
+; CHECK-NEXT:     ret i32 %[[V]]
+
+source_filename = "main.cpp"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-none-linux-gnu"
+
+%struct.Q = type { i32 }
+
+$_ZN1QC2Ev = comdat any
+
+ at _q = dso_local global %struct.Q zeroinitializer, align 4
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_main.cpp, i8* null }]
+
+define internal void @__cxx_global_var_init() section ".text.startup" {
+  call void @_ZN1QC2Ev(%struct.Q* @_q)
+  ret void
+}
+
+define linkonce_odr dso_local void @_ZN1QC2Ev(%struct.Q*) unnamed_addr #1 comdat align 2 {
+  %2 = alloca %struct.Q*, align 8
+  store %struct.Q* %0, %struct.Q** %2, align 8
+  %3 = load %struct.Q*, %struct.Q** %2, align 8
+  %4 = getelementptr inbounds %struct.Q, %struct.Q* %3, i32 0, i32 0
+  %5 = call i32 bitcast (float (float, float)* @fmodf to i32 (float, float)*)(float 0x40091EB860000000, float 2.000000e+00)
+  store i32 %5, i32* %4, align 4
+  ret void
+}
+
+define dso_local i32 @main(i32, i8**) {
+  %3 = alloca i32, align 4
+  %4 = alloca i32, align 4
+  %5 = alloca i8**, align 8
+  store i32 0, i32* %3, align 4
+  store i32 %0, i32* %4, align 4
+  store i8** %1, i8*** %5, align 8
+  %6 = load i32, i32* getelementptr inbounds (%struct.Q, %struct.Q* @_q, i32 0, i32 0), align 4
+  ret i32 %6
+}
+
+; Function Attrs: nounwind
+declare dso_local float @fmodf(float, float)
+
+; Function Attrs: noinline uwtable
+define internal void @_GLOBAL__sub_I_main.cpp() section ".text.startup" {
+  call void @__cxx_global_var_init()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-aggregate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt < %s -S -globalopt | FileCheck %s
+
+; This global is externally_initialized, so if we split it into scalars we
+; should keep that flag set on all of the new globals. This will prevent the
+; store to @a[0] from being constant propagated to the load in @foo, but will not
+; prevent @a[1] from being removed since it is dead.
+; CHECK: @a.0 = internal unnamed_addr externally_initialized global i32 undef
+; CHECK-NOT: @a.1
+ at a = internal externally_initialized global [2 x i32] undef, align 4
+; This is the same, but a struct rather than an array.
+; CHECK: @b.0 = internal unnamed_addr externally_initialized global i32 undef
+; CHECK-NOT: @b.1
+ at b = internal externally_initialized global {i32, i32} undef, align 4
+
+define i32 @foo() {
+; CHECK-LABEL: define i32 @foo
+entry:
+; This load uses the split global, but cannot be constant-propagated away.
+; CHECK: %0 = load i32, i32* @a.0
+  %0 = load i32, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @a, i32 0, i32 0), align 4
+  ret i32 %0
+}
+
+define i32 @bar() {
+; CHECK-LABEL: define i32 @bar
+entry:
+; This load uses the split global, but cannot be constant-propagated away.
+; CHECK: %0 = load i32, i32* @b.0
+  %0 = load i32, i32* getelementptr inbounds ({i32, i32}, {i32, i32}* @b, i32 0, i32 0), align 4
+  ret i32 %0
+}
+
+define void @init() {
+; CHECK-LABEL: define void @init
+entry:
+; This store uses the split global, but cannot be constant-propagated away.
+; CHECK: store i32 1, i32* @a.0
+  store i32 1, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @a, i32 0, i32 0), align 4
+; This store can be removed, because the second element of @a is never read.
+; CHECK-NOT: store i32 2, i32* @a.1
+  store i32 2, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @a, i32 0, i32 1), align 4
+
+; This store uses the split global, but cannot be constant-propagated away.
+; CHECK: store i32 3, i32* @b.0
+  store i32 3, i32* getelementptr inbounds ({i32, i32}, {i32, i32}* @b, i32 0, i32 0), align 4
+; This store can be removed, because the second element of @b is never read.
+; CHECK-NOT: store i32 4, i32* @b.1
+  store i32 4, i32* getelementptr inbounds ({i32, i32}, {i32, i32}* @b, i32 0, i32 1), align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/externally-initialized-global-ctr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; rdar://12580965.
+; ObjC++ test case.
+
+%struct.ButtonInitData = type { i8* }
+
+ at _ZL14buttonInitData = internal global [1 x %struct.ButtonInitData] zeroinitializer, align 4
+
+@"\01L_OBJC_METH_VAR_NAME_40" = internal global [7 x i8] c"print:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+@"\01L_OBJC_SELECTOR_REFERENCES_41" = internal externally_initialized  global i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_OBJC_METH_VAR_NAME_40", i32 0, i32 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+ at llvm.used = appending global [2 x i8*] [i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_OBJC_METH_VAR_NAME_40", i32 0, i32 0),  i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_41" to i8*)]
+
+define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  %1 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_41", !invariant.load !2009
+  store i8* %1, i8** getelementptr inbounds ([1 x %struct.ButtonInitData], [1 x %struct.ButtonInitData]* @_ZL14buttonInitData, i32 0, i32 0, i32 0), align 4
+  ret void
+}
+
+define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @__cxx_global_var_init()
+  ret void
+}
+
+declare void @test(i8*)
+
+define void @print() {
+; CHECK: %1 = load i8*, i8** @_ZL14buttonInitData.0.0, align 4
+  %1 = load i8*, i8** getelementptr inbounds ([1 x %struct.ButtonInitData], [1 x %struct.ButtonInitData]* @_ZL14buttonInitData, i32 0, i32 0, i32 0), align 4
+  call void @test(i8* %1)
+  ret void
+}
+
+!2009 = !{}

Added: llvm/trunk/test/Transforms/GlobalOpt/externally-initialized.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/externally-initialized.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/externally-initialized.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/externally-initialized.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt < %s -S -globalopt | FileCheck %s
+
+; This global is externally_initialized, which may modify the value between
+; it's static initializer and any code in this module being run, so the only
+; write to it cannot be merged into the static initialiser.
+; CHECK: @a = internal unnamed_addr externally_initialized global i32 undef
+ at a = internal externally_initialized global i32 undef
+
+; This global is stored to by the external initialization, so cannot be
+; constant-propagated and removed, despite the fact that there are no writes
+; to it.
+; CHECK: @b = internal unnamed_addr externally_initialized global i32 undef
+ at b = internal externally_initialized global i32 undef
+
+
+define void @foo() {
+; CHECK-LABEL: foo
+entry:
+; CHECK: store i32 42, i32* @a
+  store i32 42, i32* @a
+  ret void
+}
+define i32 @bar() {
+; CHECK-LABEL: bar
+entry:
+; CHECK: %val = load i32, i32* @a
+  %val = load i32, i32* @a
+  ret i32 %val
+}
+
+define i32 @baz() {
+; CHECK-LABEL: baz
+entry:
+; CHECK: %val = load i32, i32* @b
+  %val = load i32, i32* @b
+  ret i32 %val
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/fastcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/fastcc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/fastcc.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/fastcc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+define internal i32 @f(i32* %m) {
+; CHECK-LABEL: define internal fastcc i32 @f
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define internal x86_thiscallcc i32 @g(i32* %m) {
+; CHECK-LABEL: define internal fastcc i32 @g
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+; Leave this one alone, because the user went out of their way to request this
+; convention.
+define internal coldcc i32 @h(i32* %m) {
+; CHECK-LABEL: define internal coldcc i32 @h
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define internal i32 @j(i32* %m) {
+; CHECK-LABEL: define internal i32 @j
+  %v = load i32, i32* %m
+  ret i32 %v
+}
+
+define internal i32 @inalloca(i32* inalloca %p) {
+; CHECK-LABEL: define internal i32 @inalloca(i32* inalloca %p)
+  %rv = load i32, i32* %p
+  ret i32 %rv
+}
+
+define void @call_things() {
+  %m = alloca i32
+  call i32 @f(i32* %m)
+  call x86_thiscallcc i32 @g(i32* %m)
+  call coldcc i32 @h(i32* %m)
+  call i32 @j(i32* %m)
+  %args = alloca inalloca i32
+  call i32 @inalloca(i32* inalloca %args)
+  ret void
+}
+
+ at llvm.used = appending global [1 x i8*] [
+   i8* bitcast (i32(i32*)* @j to i8*)
+], section "llvm.metadata"
+
+; CHECK-LABEL: define void @call_things()
+; CHECK: call fastcc i32 @f
+; CHECK: call fastcc i32 @g
+; CHECK: call coldcc i32 @h
+; CHECK: call i32 @j
+; CHECK: call i32 @inalloca(i32* inalloca %args)

Added: llvm/trunk/test/Transforms/GlobalOpt/global-demotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/global-demotion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/global-demotion.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/global-demotion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,80 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+
+ at G1 = internal global i32 5
+ at G2 = internal global i32 5
+ at G3 = internal global i32 5
+ at G4 = internal global i32 5
+ at G5 = internal global i32 5
+
+; CHECK-LABEL: @test1
+define internal i32 @test1() norecurse {
+; CHECK-NOT: @G1
+  store i32 4, i32* @G1
+  %a = load i32, i32* @G1
+; CHECK: ret
+  ret i32 %a
+}
+
+; The load comes before the store which makes @G2 live before the call.
+; CHECK-LABEL: @test2
+define internal i32 @test2() norecurse {
+; CHECK-NOT: %G2
+  %a = load i32, i32* @G2
+  store i32 4, i32* @G2
+; CHECK: ret
+  ret i32 %a
+}
+
+; This global is indexed by a GEP - this makes it partial alias and we bail out.
+; FIXME: We don't actually have to bail out in this case.
+
+; CHECK-LABEL: @test3
+define internal i32 @test3() norecurse {
+; CHECK-NOT: %G3
+  %x = getelementptr i32,i32* @G3, i32 0
+  %a = load i32, i32* %x
+  store i32 4, i32* @G3
+; CHECK: ret
+  ret i32 %a
+}
+
+; The global is casted away to a larger type then loaded. The store only partially
+; covers the load, so we must not demote.
+
+; CHECK-LABEL: @test4
+define internal i32 @test4() norecurse {
+; CHECK-NOT: %G4
+  store i32 4, i32* @G4
+  %x = bitcast i32* @G4 to i64*
+  %a = load i64, i64* %x
+  %b = trunc i64 %a to i32
+; CHECK: ret
+  ret i32 %b
+}
+
+; The global is casted away to a smaller type then loaded. This one is fine.
+
+; CHECK-LABEL: @test5
+define internal i32 @test5() norecurse {
+; CHECK-NOT: @G5
+  store i32 4, i32* @G5
+  %x = bitcast i32* @G5 to i16*
+  %a = load i16, i16* %x
+  %b = zext i16 %a to i32
+; CHECK: ret
+  ret i32 %b
+}
+
+define i32 @main() norecurse {
+  %a = call i32 @test1()
+  %b = call i32 @test2()
+  %c = call i32 @test3()
+  %d = call i32 @test4()
+  %e = call i32 @test5()
+
+  %x = or i32 %a, %b
+  %y = or i32 %x, %c
+  %z = or i32 %y, %d
+  %w = or i32 %z, %e
+  ret i32 %w
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/globalsra-multigep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/globalsra-multigep.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/globalsra-multigep.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/globalsra-multigep.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at g_data = internal unnamed_addr global <{ [8 x i16], [8 x i16] }> <{ [8 x i16] [i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16], [8 x i16] zeroinitializer }>, align 16
+; We cannot SRA here due to the second gep meaning the access to g_data may be to either element
+; CHECK: @g_data = internal unnamed_addr constant <{ [8 x i16], [8 x i16] }>
+
+define i16 @test(i64 %a1) {
+entry:
+  %g1 = getelementptr inbounds <{ [8 x i16], [8 x i16] }>, <{ [8 x i16], [8 x i16] }>* @g_data, i64 0, i32 0
+  %arrayidx.i = getelementptr inbounds [8 x i16], [8 x i16]* %g1, i64 0, i64 %a1
+  %r = load i16, i16* %arrayidx.i, align 2
+  ret i16 %r
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/globalsra-partial.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/globalsra-partial.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/globalsra-partial.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/globalsra-partial.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; In this case, the global cannot be merged as i may be out of range
+
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global { i32, [4 x float] } zeroinitializer               ; <{ i32, [4 x float] }*> [#uses=3]
+
+; CHECK: @G = internal unnamed_addr global { i32, [4 x float] }
+; CHECK: 12345
+define void @onlystore() {
+        store i32 12345, i32* getelementptr ({ i32, [4 x float] }, { i32, [4 x float] }* @G, i32 0, i32 0)
+        ret void
+}
+
+define void @storeinit(i32 %i) {
+        %Ptr = getelementptr { i32, [4 x float] }, { i32, [4 x float] }* @G, i32 0, i32 1, i32 %i             ; <float*> [#uses=1]
+        store float 1.000000e+00, float* %Ptr
+        ret void
+}
+
+define float @readval(i32 %i) {
+        %Ptr = getelementptr { i32, [4 x float] }, { i32, [4 x float] }* @G, i32 0, i32 1, i32 %i             ; <float*> [#uses=1]
+        %V = load float, float* %Ptr           ; <float> [#uses=1]
+        ret float %V
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/globalsra-unknown-index.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/globalsra-unknown-index.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/globalsra-unknown-index.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/globalsra-unknown-index.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; globalopt should not sra the global, because it can't see the index.
+
+%struct.X = type { [3 x i32], [3 x i32] }
+
+; CHECK: @Y = internal unnamed_addr global [3 x %struct.X] zeroinitializer
+ at Y = internal global [3 x %struct.X] zeroinitializer
+
+ at addr = external global i8
+
+define void @frob() {
+  store i32 1, i32* getelementptr inbounds ([3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 ptrtoint (i8* @addr to i64)), align 4
+  ret void
+}
+
+; CHECK-LABEL: @borf
+; CHECK: %a = load
+; CHECK: %b = load
+; CHECK: add i32 %a, %b
+define i32 @borf(i64 %i, i64 %j) {
+  %p = getelementptr inbounds [3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 0
+  %a = load i32, i32* %p
+  %q = getelementptr inbounds [3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 0, i32 1, i64 0
+  %b = load i32, i32* %q
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+; CHECK-LABEL: @borg
+; CHECK: %a = load
+; CHECK: %b = load
+; CHECK: add i32 %a, %b
+define i32 @borg(i64 %i, i64 %j) {
+  %p = getelementptr inbounds [3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 1, i32 0, i64 1
+  %a = load i32, i32* %p
+  %q = getelementptr inbounds [3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 1, i32 1, i64 1
+  %b = load i32, i32* %q
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+; CHECK-LABEL: @borh
+; CHECK: %a = load
+; CHECK: %b = load
+; CHECK: add i32 %a, %b
+define i32 @borh(i64 %i, i64 %j) {
+  %p = getelementptr inbounds [3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 2, i32 0, i64 2
+  %a = load i32, i32* %p
+  %q = getelementptr inbounds [3 x %struct.X], [3 x %struct.X]* @Y, i64 0, i64 2, i32 1, i64 2
+  %b = load i32, i32* %q
+  %c = add i32 %a, %b
+  ret i32 %c
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/globalsra.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/globalsra.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/globalsra.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/globalsra.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: global
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global { i32, float, { double } } {
+    i32 1, 
+    float 1.000000e+00, 
+    { double } { double 1.727000e+01 } }                ; <{ i32, float, { double } }*> [#uses=3]
+
+define void @onlystore() {
+        store i32 123, i32* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G, i32 0, i32 0)
+        ret void
+}
+
+define float @storeinit() {
+        store float 1.000000e+00, float* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G, i32 0, i32 1)
+        %X = load float, float* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G, i32 0, i32 1)           ; <float> [#uses=1]
+        ret float %X
+}
+
+define double @constantize() {
+        %X = load double, double* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G, i32 0, i32 2, i32 0)           ; <double> [#uses=1]
+        ret double %X
+}
+
+ at G2 = internal constant { i32, float, { double } } {
+    i32 1, 
+    float 1.000000e+00, 
+    { double } { double 1.727000e+01 } }                ; <{ i32, float, { double } }*> [#uses=3]
+
+define void @onlystore2() {
+        store i32 123, i32* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 0)
+        ret void
+}
+
+define float @storeinit2() {
+        store float 1.000000e+00, float* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 1)
+        %X = load float, float* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 1)           ; <float> [#uses=1]
+        ret float %X
+}
+
+define double @constantize2() {
+        %X = load double, double* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 2, i32 0)           ; <double> [#uses=1]
+        ret double %X
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i64 %Size) nounwind noinline #0 {
+entry:
+  %mallocsize = mul i64 %Size, 8                  ; <i64> [#uses=1]
+  %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+  %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+bb1.thread:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+	%2 = load i32, i32* %1, align 4
+	%3 = add i32 %2, %sum.0.reg2mem.0
+	%indvar.next = add i32 %i.0.reg2mem.0, 1
+	%exitcond = icmp eq i32 %indvar.next, 1200
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null
+; CHECK: @X.f0
+; CHECK: @X.f1
+
+define void @bar(i64 %Size) nounwind noinline {
+entry:
+  %mallocsize = mul i64 %Size, 8                  ; <i64> [#uses=1]
+  %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+  %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4		
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+	%2 = load i32, i32* %1, align 4
+	%3 = add i32 %2, %sum.0.reg2mem.0	
+	%indvar.next = add i32 %i.0.reg2mem.0, 1	
+	%exitcond = icmp eq i32 %indvar.next, 1200		
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null		; <%struct.foo**> [#uses=2]
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i32 %Size) nounwind noinline #0 {
+entry:
+	%malloccall = tail call i8* @malloc(i64 8000000) ; <i8*> [#uses=1]
+	%0 = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1]
+	%.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %0, i32 0, i32 0		; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+bb1.thread:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=1]
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]		; <i32> [#uses=2]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]		; <i32> [#uses=1]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0		; <i32*> [#uses=1]
+	%2 = load i32, i32* %1, align 4		; <i32> [#uses=1]
+	%3 = add i32 %2, %sum.0.reg2mem.0		; <i32> [#uses=2]
+	%indvar.next = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=2]
+	%exitcond = icmp eq i32 %indvar.next, 1200		; <i1> [#uses=1]
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null		; <%struct.foo**> [#uses=2]
+; CHECK: @X.f0
+; CHECK: @X.f1
+
+define void @bar(i32 %Size) nounwind noinline {
+entry:
+	%malloccall = tail call i8* @malloc(i64 8000000) ; <i8*> [#uses=1]
+	%0 = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1]
+	%.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %0, i32 0, i32 0		; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=1]
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]		; <i32> [#uses=2]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]		; <i32> [#uses=1]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0		; <i32*> [#uses=1]
+	%2 = load i32, i32* %1, align 4		; <i32> [#uses=1]
+	%3 = add i32 %2, %sum.0.reg2mem.0		; <i32> [#uses=2]
+	%indvar.next = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=2]
+	%exitcond = icmp eq i32 %indvar.next, 1200		; <i1> [#uses=1]
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+        %0 = load %struct.foo*, %struct.foo** @X, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i64 %Size) nounwind noinline #0 {
+entry:
+  %mallocsize = mul i64 8, %Size ; <i64> [#uses=1]
+; CHECK: mul i64 8, %Size
+  %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+  %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+bb1.thread:
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+	%0 = load %struct.foo*, %struct.foo** @X, align 4
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+	%2 = load i32, i32* %1, align 4
+	%3 = add i32 %2, %sum.0.reg2mem.0
+	%indvar.next = add i32 %i.0.reg2mem.0, 1
+	%exitcond = icmp eq i32 %indvar.next, 1200
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null
+; CHECK: @X.f0
+; CHECK: @X.f1
+
+define void @bar(i64 %Size) nounwind noinline {
+entry:
+  %mallocsize = mul i64 8, %Size ; <i64> [#uses=1]
+; CHECK: mul i64 %Size, 4
+  %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+  %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4		
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+	%2 = load i32, i32* %1, align 4
+	%3 = add i32 %2, %sum.0.reg2mem.0	
+	%indvar.next = add i32 %i.0.reg2mem.0, 1	
+	%exitcond = icmp eq i32 %indvar.next, 1200		
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+        %0 = load %struct.foo*, %struct.foo** @X, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+
+ at X = internal global %struct.foo* null
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i64 %Size) nounwind noinline #0 {
+entry:
+  %mallocsize = shl i64 %Size, 3                  ; <i64> [#uses=1]
+  %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+; CHECK: shl i64 %Size, 3
+  %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+; CHECK-LABEL: @baz(
+bb1.thread:
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+	%0 = load %struct.foo*, %struct.foo** @X, align 4
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+	%2 = load i32, i32* %1, align 4
+; CHECK: load i32, i32* %1, align 4
+	%3 = add i32 %2, %sum.0.reg2mem.0
+	%indvar.next = add i32 %i.0.reg2mem.0, 1
+	%exitcond = icmp eq i32 %indvar.next, 1200
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-4.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null
+; CHECK: @X.f0
+; CHECK: @X.f1
+
+define void @bar(i64 %Size) nounwind noinline {
+entry:
+  %mallocsize = shl i64 %Size, 3                  ; <i64> [#uses=1]
+  %malloccall = tail call i8* @malloc(i64 %mallocsize) ; <i8*> [#uses=1]
+; CHECK: mul i64 %Size, 4
+  %.sub = bitcast i8* %malloccall to %struct.foo* ; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%0 = load %struct.foo*, %struct.foo** @X, align 4		
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %3, %bb1 ]
+	%1 = getelementptr %struct.foo, %struct.foo* %0, i32 %i.0.reg2mem.0, i32 0
+	%2 = load i32, i32* %1, align 4
+	%3 = add i32 %2, %sum.0.reg2mem.0	
+	%indvar.next = add i32 %i.0.reg2mem.0, 1	
+	%exitcond = icmp eq i32 %indvar.next, 1200		
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %3
+}
+
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+        %0 = load %struct.foo*, %struct.foo** @X, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+%struct.foo = type { i32, i32 }
+
+ at X = internal global %struct.foo* null		; <%struct.foo**> [#uses=2]
+; CHECK: @X
+; CHECK-NOT: @X.f0
+
+define void @bar(i32 %Size) nounwind noinline #0 {
+;  CHECK-LABEL: @bar(
+entry:
+	%malloccall = tail call i8* @malloc(i64 8000000) ; <i8*> [#uses=1]
+	%tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1]
+	%.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0		; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline #0 {
+; CHECK-LABEL: @baz(
+bb1.thread:
+	%tmpLD1 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=1]
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+        %tmp = phi %struct.foo* [%tmpLD1, %bb1.thread ], [ %tmpLD2, %bb1 ]		; <i32> [#uses=2]
+; CHECK: %tmp = phi %struct.foo* [ %tmpLD1, %bb1.thread ], [ %tmpLD2, %bb1 ]
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]		; <i32> [#uses=2]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %tmp3, %bb1 ]		; <i32> [#uses=1]
+	%tmp1 = getelementptr %struct.foo, %struct.foo* %tmp, i32 %i.0.reg2mem.0, i32 0		; <i32*> [#uses=1]
+	%tmp2 = load i32, i32* %tmp1, align 4		; <i32> [#uses=1]
+; CHECK: load i32, i32* %tmp1, align 4
+	%tmp6 = add i32 %tmp2, %sum.0.reg2mem.0		; <i32> [#uses=2]
+	%tmp4 = getelementptr %struct.foo, %struct.foo* %tmp, i32 %i.0.reg2mem.0, i32 1		; <i32*> [#uses=1]
+        %tmp5 = load i32 , i32 * %tmp4
+;  CHECK: load i32, i32* %tmp4
+        %tmp3 = add i32 %tmp5, %tmp6
+	%indvar.next = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=2]
+
+      	%tmpLD2 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=1]
+; CHECK: load %struct.foo*, %struct.foo** @X, align 4
+
+	%exitcond = icmp eq i32 %indvar.next, 1200		; <i1> [#uses=1]
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %tmp3
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/heap-sra-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: tmp.f1 = phi i32*
+; CHECK: tmp.f0 = phi i32*
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null		; <%struct.foo**> [#uses=2]
+
+define void @bar(i32 %Size) nounwind noinline {
+entry:
+	%malloccall = tail call i8* @malloc(i64 8000000) ; <i8*> [#uses=1]
+	%tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1]
+	%.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0		; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%tmpLD1 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=1]
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+        %tmp = phi %struct.foo* [%tmpLD1, %bb1.thread ], [ %tmpLD2, %bb1 ]		; <i32> [#uses=2]
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ]		; <i32> [#uses=2]
+	%sum.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %tmp3, %bb1 ]		; <i32> [#uses=1]
+	%tmp1 = getelementptr %struct.foo, %struct.foo* %tmp, i32 %i.0.reg2mem.0, i32 0		; <i32*> [#uses=1]
+	%tmp2 = load i32, i32* %tmp1, align 4		; <i32> [#uses=1]
+	%tmp6 = add i32 %tmp2, %sum.0.reg2mem.0		; <i32> [#uses=2]
+	%tmp4 = getelementptr %struct.foo, %struct.foo* %tmp, i32 %i.0.reg2mem.0, i32 1		; <i32*> [#uses=1]
+        %tmp5 = load i32 , i32 * %tmp4
+        %tmp3 = add i32 %tmp5, %tmp6
+	%indvar.next = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=2]
+        
+      	%tmpLD2 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=1]
+
+	%exitcond = icmp eq i32 %indvar.next, 1200		; <i1> [#uses=1]
+	br i1 %exitcond, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 %tmp3
+}
+
+define void @bam(i64 %Size) nounwind noinline #0 {
+entry:
+        %0 = load %struct.foo*, %struct.foo** @X, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/int_sideeffect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/int_sideeffect.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/int_sideeffect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt -S < %s -globalopt | FileCheck %s
+
+; Static evaluation across a @llvm.sideeffect.
+
+; CHECK-NOT: store
+
+declare void @llvm.sideeffect()
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @ctor } ]
+ at G = global i32 0
+
+define internal void @ctor() {
+    store i32 1, i32* @G
+    call void @llvm.sideeffect()
+    ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/integer-bool-dwarf.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/integer-bool-dwarf.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/integer-bool-dwarf.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/integer-bool-dwarf.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+;RUN: opt -S -globalopt -f %s | FileCheck %s
+
+;CHECK: @foo = internal unnamed_addr global i1 false, align 4, !dbg ![[VAR:.*]]
+;CHECK: ![[VAR]] = !DIGlobalVariableExpression(var: !1, expr:
+;CHECK-SAME: !DIExpression(DW_OP_deref, DW_OP_constu, 111, DW_OP_mul,
+;CHECK-SAME:               DW_OP_constu, 0, DW_OP_plus, DW_OP_stack_value,
+;CHECK-SAME:               DW_OP_LLVM_fragment, 0, 1)) 
+
+ at foo = internal global i32 0, align 4, !dbg !0
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @set1() #0 !dbg !11 {
+entry:
+  store i32 111, i32* @foo, align 4, !dbg !14
+  ret void, !dbg !15
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @set2() #0 !dbg !16 {
+entry:
+  store i32 0, i32* @foo, align 4, !dbg !17
+  ret void, !dbg !18
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define i32 @get() #0 !dbg !19 {
+entry:
+  %0 = load i32, i32* @foo, align 4, !dbg !22
+  ret i32 %0, !dbg !23
+}
+
+attributes #0 = { noinline nounwind optnone uwtable }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 0, 1))
+!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, line: 1, type: !6, isLocal: true, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "integer-bool-dwarf.c", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{!"clang version 6.0.0 "}
+!11 = distinct !DISubprogram(name: "set1", scope: !3, file: !3, line: 3, type: !12, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: false, unit: !2, retainedNodes: !4)
+!12 = !DISubroutineType(types: !13)
+!13 = !{null}
+!14 = !DILocation(line: 5, column: 7, scope: !11)
+!15 = !DILocation(line: 6, column: 1, scope: !11)
+!16 = distinct !DISubprogram(name: "set2", scope: !3, file: !3, line: 8, type: !12, isLocal: false, isDefinition: true, scopeLine: 9, isOptimized: false, unit: !2, retainedNodes: !4)
+!17 = !DILocation(line: 10, column: 7, scope: !16)
+!18 = !DILocation(line: 11, column: 1, scope: !16)
+!19 = distinct !DISubprogram(name: "get", scope: !3, file: !3, line: 13, type: !20, isLocal: false, isDefinition: true, scopeLine: 14, isOptimized: false, unit: !2, retainedNodes: !4)
+!20 = !DISubroutineType(types: !21)
+!21 = !{!6}
+!22 = !DILocation(line: 15, column: 10, scope: !19)
+!23 = !DILocation(line: 15, column: 3, scope: !19)

Added: llvm/trunk/test/Transforms/GlobalOpt/integer-bool.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/integer-bool.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/integer-bool.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/integer-bool.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -S -globalopt -instcombine | FileCheck %s
+;; check that global opt turns integers that only hold 0 or 1 into bools.
+
+ at G = internal addrspace(1) global i32 0
+; CHECK: @G
+; CHECK: addrspace(1)
+; CHECK: global i1 false
+
+define void @set1() {
+  store i32 0, i32 addrspace(1)* @G
+; CHECK: store i1 false
+  ret void
+}
+
+define void @set2() {
+  store i32 1, i32 addrspace(1)* @G
+; CHECK: store i1 true
+  ret void
+}
+
+define i1 @get() {
+; CHECK-LABEL: @get(
+  %A = load i32, i32 addrspace(1) * @G
+  %C = icmp slt i32 %A, 2
+  ret i1 %C
+; CHECK: ret i1 true
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/invariant-nodatalayout.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/invariant-nodatalayout.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/invariant-nodatalayout.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/invariant-nodatalayout.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt -globalopt -S -o - < %s | FileCheck %s
+; The check here is that it doesn't crash.
+
+declare {}* @llvm.invariant.start.p0i8(i64 %size, i8* nocapture %ptr)
+
+ at object1 = global { i32, i32 } zeroinitializer
+; CHECK: @object1 = global { i32, i32 } zeroinitializer
+
+define void @ctor1() {
+  %ptr = bitcast {i32, i32}* @object1 to i8*
+  call {}* @llvm.invariant.start.p0i8(i64 4, i8* %ptr)
+  ret void
+}
+
+ at llvm.global_ctors = appending constant
+  [1 x { i32, void ()* }]
+  [ { i32, void ()* } { i32 65535, void ()* @ctor1 } ]

Added: llvm/trunk/test/Transforms/GlobalOpt/invariant.group.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/invariant.group.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/invariant.group.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/invariant.group.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+; This test is hint, what could globalOpt optimize and what it can't
+; FIXME: @tmp and @tmp2 can be safely set to 42
+; CHECK: @tmp = local_unnamed_addr global i32 0
+; CHECK: @tmp2 = local_unnamed_addr global i32 0
+; CHECK: @tmp3 = global i32 0
+
+ at tmp = global i32 0
+ at tmp2 = global i32 0
+ at tmp3 = global i32 0
+ at ptrToTmp3 = global i32* null
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
+define i32 @TheAnswerToLifeTheUniverseAndEverything() {
+  ret i32 42
+}
+
+define void @_GLOBAL__I_a() {
+enter:
+  call void @_optimizable()
+  call void @_not_optimizable()
+  ret void
+}
+
+define void @_optimizable() {
+enter:
+  %valptr = alloca i32
+
+  %val = call i32 @TheAnswerToLifeTheUniverseAndEverything()
+  store i32 %val, i32* @tmp
+  store i32 %val, i32* %valptr
+
+  %0 = bitcast i32* %valptr to i8*
+  %barr = call i8* @llvm.launder.invariant.group(i8* %0)
+  %1 = bitcast i8* %barr to i32*
+
+  %val2 = load i32, i32* %1
+  store i32 %val2, i32* @tmp2
+  ret void
+}
+
+; We can't step through launder.invariant.group here, because that would change
+; this load in @usage_of_globals()
+; val = load i32, i32* %ptrVal, !invariant.group !0
+; into
+; %val = load i32, i32* @tmp3, !invariant.group !0
+; and then we could assume that %val and %val2 to be the same, which coud be
+; false, because @changeTmp3ValAndCallBarrierInside() may change the value
+; of @tmp3.
+define void @_not_optimizable() {
+enter:
+  store i32 13, i32* @tmp3, !invariant.group !0
+
+  %0 = bitcast i32* @tmp3 to i8*
+  %barr = call i8* @llvm.launder.invariant.group(i8* %0)
+  %1 = bitcast i8* %barr to i32*
+
+  store i32* %1, i32** @ptrToTmp3
+  store i32 42, i32* %1, !invariant.group !0
+
+  ret void
+}
+define void @usage_of_globals() {
+entry:
+  %ptrVal = load i32*, i32** @ptrToTmp3
+  %val = load i32, i32* %ptrVal, !invariant.group !0
+
+  call void @changeTmp3ValAndCallBarrierInside()
+  %val2 = load i32, i32* @tmp3, !invariant.group !0
+  ret void;
+}
+
+declare void @changeTmp3ValAndCallBarrierInside()
+
+declare i8* @llvm.launder.invariant.group(i8*)
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/GlobalOpt/invariant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/invariant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/invariant.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/invariant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -globalopt -S -o - < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare {}* @llvm.invariant.start.p0i8(i64 %size, i8* nocapture %ptr)
+
+define void @test1(i8* %ptr) {
+  call {}* @llvm.invariant.start.p0i8(i64 4, i8* %ptr)
+  ret void
+}
+
+ at object1 = global i32 0
+; CHECK: @object1 = constant i32 -1
+define void @ctor1() {
+  store i32 -1, i32* @object1
+  %A = bitcast i32* @object1 to i8*
+  call void @test1(i8* %A)
+  ret void
+}
+
+
+ at object2 = global i32 0
+; CHECK: @object2 = global i32 0
+define void @ctor2() {
+  store i32 -1, i32* @object2
+  %A = bitcast i32* @object2 to i8*
+  %B = call {}* @llvm.invariant.start.p0i8(i64 4, i8* %A)
+  %C = bitcast {}* %B to i8*
+  ret void
+}
+
+
+ at object3 = global i32 0
+; CHECK: @object3 = global i32 -1
+define void @ctor3() {
+  store i32 -1, i32* @object3
+  %A = bitcast i32* @object3 to i8*
+  call {}* @llvm.invariant.start.p0i8(i64 3, i8* %A)
+  ret void
+}
+
+
+ at object4 = global i32 0
+; CHECK: @object4 = global i32 -1
+define void @ctor4() {
+  store i32 -1, i32* @object4
+  %A = bitcast i32* @object4 to i8*
+  call {}* @llvm.invariant.start.p0i8(i64 -1, i8* %A)
+  ret void
+}
+
+
+ at llvm.global_ctors = appending constant
+  [4 x { i32, void ()* }]
+  [ { i32, void ()* } { i32 65535, void ()* @ctor1 },
+    { i32, void ()* } { i32 65535, void ()* @ctor2 },
+    { i32, void ()* } { i32 65535, void ()* @ctor3 },
+    { i32, void ()* } { i32 65535, void ()* @ctor4 } ]

Added: llvm/trunk/test/Transforms/GlobalOpt/invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/invoke.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/invoke.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/invoke.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+; rdar://11022897
+
+; Globalopt should be able to evaluate an invoke.
+; CHECK: @tmp = local_unnamed_addr global i32 1
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+ at tmp = global i32 0
+
+define i32 @one() {
+  ret i32 1
+}
+
+define void @_GLOBAL__I_a() personality i8* undef {
+bb:
+  %tmp1 = invoke i32 @one()
+          to label %bb2 unwind label %bb4
+
+bb2:                                              ; preds = %bb
+  store i32 %tmp1, i32* @tmp
+  ret void
+
+bb4:                                              ; preds = %bb
+  %tmp5 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+  unreachable
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/iterate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/iterate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/iterate.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/iterate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: %G
+
+ at G = internal global i32 0              ; <i32*> [#uses=1]
+ at H = internal global { i32* } { i32* @G }               ; <{ i32* }*> [#uses=1]
+
+define i32 @loadg() {
+        %G = load i32*, i32** getelementptr ({ i32* }, { i32* }* @H, i32 0, i32 0)              ; <i32*> [#uses=1]
+        %GV = load i32, i32* %G              ; <i32> [#uses=1]
+        ret i32 %GV
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/load-store-global-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at a = internal global i64* null, align 8
+; CHECK: @a
+
+; PR13968
+define void @qux_no_null_opt() nounwind #0 {
+; CHECK-LABEL: @qux_no_null_opt(
+; CHECK: getelementptr i64*, i64** @a, i32 1
+; CHECK: store i64* inttoptr (i64 1 to i64*), i64** @a
+  %b = bitcast i64** @a to i8*
+  %g = getelementptr i64*, i64** @a, i32 1
+  %cmp = icmp ne i8* null, %b
+  %cmp2 = icmp eq i8* null, %b
+  %cmp3 = icmp eq i64** null, %g
+  store i64* inttoptr (i64 1 to i64*), i64** @a, align 8
+  %l = load i64*, i64** @a, align 8
+  ret void
+}
+
+define i64* @bar() {
+  %X = load i64*, i64** @a, align 8
+  ret i64* %X
+; CHECK-LABEL: @bar(
+; CHECK: load
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/load-store-global.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/load-store-global.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/load-store-global.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/load-store-global.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at G = internal global i32 17             ; <i32*> [#uses=3]
+; CHECK-NOT: @G
+
+define void @foo() {
+        %V = load i32, i32* @G               ; <i32> [#uses=1]
+        store i32 %V, i32* @G
+        ret void
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: ret void
+}
+
+define i32 @bar() {
+        %X = load i32, i32* @G               ; <i32> [#uses=1]
+        ret i32 %X
+; CHECK-LABEL: @bar(
+; CHECK-NEXT: ret i32 17
+}
+
+ at a = internal global i64* null, align 8
+; CHECK-NOT: @a
+
+; PR13968
+define void @qux() nounwind {
+  %b = bitcast i64** @a to i8*
+  %g = getelementptr i64*, i64** @a, i32 1
+  %cmp = icmp ne i8* null, %b
+  %cmp2 = icmp eq i8* null, %b
+  %cmp3 = icmp eq i64** null, %g
+  store i64* inttoptr (i64 1 to i64*), i64** @a, align 8
+  %l = load i64*, i64** @a, align 8
+  ret void
+; CHECK-LABEL: @qux(
+; CHECK-NOT: store
+; CHECK-NOT: load
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr-debuginfo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+; RUN: opt -S < %s -globalopt | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at _ZL1x = internal global [200 x i8]* null, align 8, !dbg !0
+
+define i32 @main(i32 %argc, i8** %argv) norecurse !dbg !18 {
+; CHECK: define i32 @main
+; Make sure we localized the global.
+; CHECK: alloca [200 x i8]*
+; Make sure the metadata is sane. Currently, we just drop the metadata,
+; so it points to nothing.
+; CHECK: call void @llvm.dbg.value(metadata !2,
+; CHECK: !2 = !{}
+entry:
+  call void @llvm.dbg.value(metadata i32 %argc, metadata !22, metadata !23), !dbg !24
+  call void @llvm.dbg.value(metadata i8** %argv, metadata !25, metadata !23), !dbg !26
+  %arrayidx = getelementptr inbounds i8*, i8** %argv, i64 0, !dbg !27
+  %0 = load i8*, i8** %arrayidx, align 8, !dbg !27
+  %1 = bitcast i8* %0 to [200 x i8]*, !dbg !28
+  store [200 x i8]* %1, [200 x i8]** @_ZL1x, align 8, !dbg !29
+  call void @llvm.dbg.value(metadata i8** bitcast ([200 x i8]** @_ZL1x to i8**), metadata !30, metadata !23), !dbg !31
+  %2 = load i8*, i8** bitcast ([200 x i8]** @_ZL1x to i8**), align 8, !dbg !32
+  %3 = load i8, i8* %2, align 1, !dbg !33
+  %conv = sext i8 %3 to i32, !dbg !33
+  ret i32 %conv, !dbg !34
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!15, !16}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "x", linkageName: "_ZL1x", scope: !2, file: !14, line: 1, type: !6, isLocal: true, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !13)
+!3 = !DIFile(filename: "-", directory: "/")
+!4 = !{}
+!5 = !{!6, !11}
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 1600, elements: !9)
+!8 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!9 = !{!10}
+!10 = !DISubrange(count: 200)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
+!13 = !{!0}
+!14 = !DIFile(filename: "<stdin>", directory: "/")
+!15 = !{i32 2, !"Dwarf Version", i32 4}
+!16 = !{i32 2, !"Debug Info Version", i32 3}
+!17 = !{!"clang"}
+!18 = distinct !DISubprogram(name: "main", scope: !14, file: !14, line: 2, type: !19, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !2, retainedNodes: !4)
+!19 = !DISubroutineType(types: !20)
+!20 = !{!21, !21, !11}
+!21 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!22 = !DILocalVariable(name: "argc", arg: 1, scope: !18, file: !14, line: 2, type: !21)
+!23 = !DIExpression()
+!24 = !DILocation(line: 2, column: 14, scope: !18)
+!25 = !DILocalVariable(name: "argv", arg: 2, scope: !18, file: !14, line: 2, type: !11)
+!26 = !DILocation(line: 2, column: 26, scope: !18)
+!27 = !DILocation(line: 2, column: 52, scope: !18)
+!28 = !DILocation(line: 2, column: 38, scope: !18)
+!29 = !DILocation(line: 2, column: 36, scope: !18)
+!30 = !DILocalVariable(name: "y", scope: !18, file: !14, line: 2, type: !11)
+!31 = !DILocation(line: 2, column: 68, scope: !18)
+!32 = !DILocation(line: 2, column: 92, scope: !18)
+!33 = !DILocation(line: 2, column: 91, scope: !18)
+!34 = !DILocation(line: 2, column: 84, scope: !18)

Added: llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/localize-constexpr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -S < %s -globalopt | FileCheck %s
+
+ at G = internal global i32 42
+
+define i8 @f() norecurse {
+; CHECK-LABEL: @f
+; CHECK: alloca
+; CHECK-NOT: @G
+; CHECK: }
+  store i32 42, i32* @G
+  %a = load i8, i8* bitcast (i32* @G to i8*)
+  ret i8 %a
+}
+
+ at H = internal global i32 42
+ at Halias = alias i32, i32* @H
+
+; @H can't be localized because @Halias uses it, and @Halias can't be converted to an instruction.
+define i8 @g() norecurse {
+; CHECK-LABEL: @g
+; CHECK-NOT: alloca
+; CHECK: @H
+; CHECK: }
+  store i32 42, i32* @H
+  %a = load i8, i8* bitcast (i32* @H to i8*)
+  ret i8 %a
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global i32* null          ; <i32**> [#uses=3]
+; CHECK: global
+
+define void @init() #0 {
+; CHECK-LABEL: @init(
+; CHECK: store
+; CHECK: load
+        %malloccall = tail call i8* @malloc(i64 4)      ; <i8*> [#uses=1]
+        %P = bitcast i8* %malloccall to i32*            ; <i32*> [#uses=1]
+        store i32* %P, i32** @G
+        %GV = load i32*, i32** @G             ; <i32*> [#uses=1]
+        store i32 0, i32* %GV
+        ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @get() #0 {
+; CHECK-LABEL: @get(
+; CHECK: load i32*, i32** @G
+; CHECK-NEXT: load i32, i32* %GV
+        %GV = load i32*, i32** @G             ; <i32*> [#uses=1]
+        %V = load i32, i32* %GV              ; <i32> [#uses=1]
+        ret i32 %V
+; CHECK: ret i32 %V
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global i32* null          ; <i32**> [#uses=4]
+; CHECK-NOT: global
+
+define void @init() {
+        %malloccall = tail call i8* @malloc(i64 4)      ; <i8*> [#uses=1]
+        %P = bitcast i8* %malloccall to i32*            ; <i32*> [#uses=1]
+        store i32* %P, i32** @G
+        %GV = load i32*, i32** @G             ; <i32*> [#uses=1]
+        store i32 0, i32* %GV
+        ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define i32 @get() {
+        %GV = load i32*, i32** @G             ; <i32*> [#uses=1]
+        %V = load i32, i32* %GV              ; <i32> [#uses=1]
+        ret i32 %V
+; CHECK: ret i32 0
+}
+
+define void @foo(i64 %Size) nounwind noinline #0 {
+entry:
+        %0 = load i32*, i32** @G, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+

Added: llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global i32* null
+
+define void @t() #0 {
+; CHECK: @t()
+; CHECK: call i8* @malloc
+; CHECK: bitcast
+; CHECK: store
+; CHECK: load
+; CHECK: getelementptr
+; CHECK: store
+  %malloccall = tail call i8* @malloc(i64 mul (i64 100, i64 4))
+  %P = bitcast i8* %malloccall to i32*
+  store i32* %P, i32** @G
+  %GV = load i32*, i32** @G
+  %GVe = getelementptr i32, i32* %GV, i32 40
+  store i32 20, i32* %GVe
+  ret void
+}
+
+declare noalias i8* @malloc(i64)
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global i32* null
+
+define void @t() {
+; CHECK: @t()
+; CHECK-NOT: call i8* @malloc
+; CHECK-NEXT: ret void
+  %malloccall = tail call i8* @malloc(i64 mul (i64 100, i64 4))
+  %P = bitcast i8* %malloccall to i32*
+  store i32* %P, i32** @G
+  %GV = load i32*, i32** @G
+  %GVe = getelementptr i32, i32* %GV, i32 40
+  store i32 20, i32* %GVe
+  ret void
+}
+
+declare noalias i8* @malloc(i64)
+
+define void @foo(i64 %Size) nounwind noinline #0 {
+entry:
+        %0 = load i32*, i32** @G, align 4
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-3.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/malloc-promote-3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+ at G = internal global i32* null
+
+define void @t() {
+; CHECK: @t()
+; CHECK: call i8* @malloc
+  %malloccall = tail call i8* @malloc(i64 mul (i64 100, i64 4)) nobuiltin
+  %P = bitcast i8* %malloccall to i32*
+  store i32* %P, i32** @G
+  %GV = load i32*, i32** @G
+  %GVe = getelementptr i32, i32* %GV, i32 40
+  store i32 20, i32* %GVe
+  ret void
+}
+
+declare noalias i8* @malloc(i64)

Added: llvm/trunk/test/Transforms/GlobalOpt/memcpy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/memcpy.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/memcpy.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/memcpy.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: G1 = internal unnamed_addr constant
+
+ at G1 = internal global [58 x i8] c"asdlfkajsdlfkajsd;lfkajds;lfkjasd;flkajsd;lkfja;sdlkfjasd\00"         ; <[58 x i8]*> [#uses=1]
+
+define void @foo() {
+  %Blah = alloca [58 x i8]
+  %tmp.0 = getelementptr [58 x i8], [58 x i8]* %Blah, i32 0, i32 0
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %tmp.0, i8* align 1 getelementptr inbounds ([58 x i8], [58 x i8]* @G1, i32 0, i32 0), i32 58, i1 false)
+  ret void
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind

Added: llvm/trunk/test/Transforms/GlobalOpt/memset-null.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/memset-null.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/memset-null.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/memset-null.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+; PR10047
+
+%0 = type { i32, void ()* }
+%struct.A = type { [100 x i32] }
+
+; CHECK: @a
+ at a = global %struct.A zeroinitializer, align 4
+ at llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @_GLOBAL__I_a }, %0 { i32 65535, void ()* @_GLOBAL__I_b }]
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
+
+; CHECK-NOT: GLOBAL__I_a
+define internal void @_GLOBAL__I_a() nounwind {
+entry:
+  tail call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.A* @a to i8*), i8 0, i64 400, i1 false) nounwind
+  ret void
+}
+
+%struct.X = type { i8 }
+ at y = global i8* null, align 8
+ at x = global %struct.X zeroinitializer, align 1
+
+define internal void @_GLOBAL__I_b() nounwind {
+entry:
+  %tmp.i.i.i = load i8*, i8** @y, align 8
+  tail call void @llvm.memset.p0i8.i64(i8* %tmp.i.i.i, i8 0, i64 10, i1 false) nounwind
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/memset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/memset.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/memset.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/memset.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+; CHECK-NOT: internal
+
+; Both globals are write only, delete them.
+
+ at G0 = internal global [58 x i8] c"asdlfkajsdlfkajsd;lfkajds;lfkjasd;flkajsd;lkfja;sdlkfjasd\00"         ; <[58 x i8]*> [#uses=1]
+ at G1 = internal global [4 x i32] [ i32 1, i32 2, i32 3, i32 4 ]          ; <[4 x i32]*> [#uses=1]
+
+define void @foo() {
+  %Blah = alloca [58 x i8]
+  %tmp3 = bitcast [58 x i8]* %Blah to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast ([4 x i32]* @G1 to i8*), i8* %tmp3, i32 16, i1 false)
+  call void @llvm.memset.p0i8.i32(i8* getelementptr inbounds ([58 x i8], [58 x i8]* @G0, i32 0, i32 0), i8 17, i32 58, i1 false)
+  ret void
+}
+
+ at G0_as1 = internal addrspace(1) global [58 x i8] c"asdlfkajsdlfkajsd;lfkajds;lfkjasd;flkajsd;lkfja;sdlkfjasd\00"         ; <[58 x i8]*> [#uses=1]
+ at G1_as1 = internal addrspace(1) global [4 x i32] [ i32 1, i32 2, i32 3, i32 4 ]          ; <[4 x i32]*> [#uses=1]
+
+define void @foo_as1() {
+  %Blah = alloca [58 x i8]
+  %tmp3 = bitcast [58 x i8]* %Blah to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* addrspacecast ([4 x i32] addrspace(1)* @G1_as1 to i8*), i8* %tmp3, i32 16, i1 false)
+  call void @llvm.memset.p1i8.i32(i8 addrspace(1)* getelementptr inbounds ([58 x i8], [58 x i8] addrspace(1)* @G0_as1, i32 0, i32 0), i8 17, i32 58, i1 false)
+  ret void
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) nounwind
+declare void @llvm.memset.p1i8.i32(i8 addrspace(1)* nocapture, i8, i32, i1) nounwind

Added: llvm/trunk/test/Transforms/GlobalOpt/metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/metadata.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -S -globalopt < %s | FileCheck %s
+
+; PR6112 - When globalopt does RAUW(@G, %G), the metadata reference should drop
+; to null.  Function local metadata that references @G from a different function
+; to that containing %G should likewise drop to null.
+ at G = internal global i8** null
+
+define i32 @main(i32 %argc, i8** %argv) norecurse {
+; CHECK-LABEL: @main(
+; CHECK: %G = alloca
+  store i8** %argv, i8*** @G
+  ret i32 0
+}
+
+define void @foo(i32 %x) {
+; Note: these arguments look like MDNodes, but they're really syntactic sugar
+; for 'MetadataAsValue::get(ValueAsMetadata::get(Value*))'.  When @G drops to
+; null, the ValueAsMetadata instance gets replaced by metadata !{}, or
+; MDNode::get({}).
+  call void @llvm.foo(metadata i8*** @G, metadata i32 %x)
+; CHECK: call void @llvm.foo(metadata ![[EMPTY:[0-9]+]], metadata i32 %x)
+  ret void
+}
+
+declare void @llvm.foo(metadata, metadata) nounwind readnone
+
+!named = !{!0}
+; CHECK: !named = !{![[NULL:[0-9]+]]}
+
+!0 = !{i8*** @G}
+; CHECK-DAG: ![[NULL]] = distinct !{null}
+; CHECK-DAG: ![[EMPTY]] = !{}

Added: llvm/trunk/test/Transforms/GlobalOpt/musttail_cc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/musttail_cc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/musttail_cc.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/musttail_cc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; PR36546
+
+; Check that musttail callee preserves its calling convention
+
+define i32 @test(i32 %a) {
+  ; CHECK: %ca = musttail call i32 @foo(i32 %a)
+  %ca = musttail call i32 @foo(i32 %a)
+  ret i32 %ca
+}
+
+; CHECK-LABEL: define internal i32 @foo(i32 %a)
+define internal i32 @foo(i32 %a) {
+  ret i32 %a
+}
+
+; Check that musttail caller preserves its calling convention
+
+define i32 @test2(i32 %a) {
+  %ca = call i32 @foo1(i32 %a)
+  ret i32 %ca
+}
+
+; CHECK-LABEL: define internal i32 @foo1(i32 %a)
+define internal i32 @foo1(i32 %a) {
+  ; CHECK: %ca = musttail call i32 @foo2(i32 %a)
+  %ca = musttail call i32 @foo2(i32 %a)
+  ret i32 %ca
+}
+
+; CHECK-LABEL: define internal i32 @foo2(i32 %a)
+define internal i32 @foo2(i32 %a) {
+  ret i32 %a
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/naked_functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/naked_functions.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/naked_functions.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/naked_functions.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; Check that naked functions don't get marked with fast calling conventions
+
+ at g = common global i32 0, align 4
+
+define i32 @bar() {
+entry:
+  %call = call i32 @foo(i32* @g)
+; CHECK: %call = call i32 @foo(i32* @g)
+  ret i32 %call
+}
+
+define internal i32 @foo(i32*) #0 {
+entry:
+  %retval = alloca i32, align 4
+  call void asm sideeffect "ldr r0, [r0] \0Abx lr        \0A", ""()
+  unreachable
+}
+
+; CHECK: define internal i32 @foo(i32*)
+
+attributes #0 = { naked }

Added: llvm/trunk/test/Transforms/GlobalOpt/phi-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/phi-select.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/phi-select.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/phi-select.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; Test that PHI nodes and select instructions do not necessarily make stuff
+; non-constant.
+
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: global
+
+ at X = internal global i32 4              ; <i32*> [#uses=2]
+ at Y = internal global i32 5              ; <i32*> [#uses=2]
+
+define i32 @test1(i1 %C) {
+        %P = select i1 %C, i32* @X, i32* @Y             ; <i32*> [#uses=1]
+        %V = load i32, i32* %P               ; <i32> [#uses=1]
+        ret i32 %V
+}
+
+define i32 @test2(i1 %C) {
+; <label>:0
+        br i1 %C, label %T, label %Cont
+
+T:              ; preds = %0
+        br label %Cont
+
+Cont:           ; preds = %T, %0
+        %P = phi i32* [ @X, %0 ], [ @Y, %T ]            ; <i32*> [#uses=1]
+        %V = load i32, i32* %P               ; <i32> [#uses=1]
+        ret i32 %V
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+$c = comdat any
+; CHECK: $c = comdat any
+
+define linkonce_odr void @foo() comdat($c) {
+  ret void
+}
+; CHECK: define linkonce_odr void @foo() local_unnamed_addr comdat($c)
+
+define linkonce_odr void @bar() comdat($c) {
+  ret void
+}
+; CHECK: define linkonce_odr void @bar() local_unnamed_addr comdat($c)
+
+define void @zed()  {
+  call void @foo()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/pr33686.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/pr33686.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/pr33686.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/pr33686.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -globalopt %s | FileCheck %s
+
+ at glob = external global i16, align 1
+
+define void @beth() {
+; CHECK-LABEL: @beth(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret void
+;
+entry:
+  ret void
+
+notreachable:
+  %patatino = select i1 undef, i16* @glob, i16* %patatino
+  br label %notreachable
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+
+$comdat_global = comdat any
+
+ at comdat_global = weak_odr global i8 0, comdat($comdat_global)
+ at simple_global = internal global i8 0
+; CHECK: @comdat_global = weak_odr global i8 0, comdat{{$}}
+; CHECK: @simple_global = internal global i8 42
+
+ at llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [
+    { i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8* @comdat_global },
+    { i32, void ()*, i8* } { i32 65535, void ()* @init_simple_global, i8* null }
+]
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }]
+; CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8* @comdat_global }]
+
+define void @init_comdat_global() {
+  store i8 42, i8* @comdat_global
+  ret void
+}
+; CHECK: define void @init_comdat_global()
+
+define internal void @init_simple_global() comdat($comdat_global) {
+  store i8 42, i8* @simple_global
+  ret void
+}
+; CHECK-NOT: @init_simple_global()
+
+define i8* @use_simple() {
+  ret i8* @simple_global
+}
+; CHECK: define i8* @use_simple()
+
+define i8* @use_comdat() {
+  ret i8* @comdat_global
+}
+; CHECK: define i8* @use_comdat()

Added: llvm/trunk/test/Transforms/GlobalOpt/shrink-address-to-bool.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/shrink-address-to-bool.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/shrink-address-to-bool.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/shrink-address-to-bool.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+;RUN: opt -S -globalopt -f %s | FileCheck %s
+
+;CHECK: @foo = {{.*}}, !dbg !0
+ at foo = global i64 ptrtoint ([1 x i64]* @baa to i64), align 8, !dbg !0
+ at baa = common global [1 x i64] zeroinitializer, align 8, !dbg !6
+
+; Function Attrs: noinline nounwind optnone uwtable
+define void @fun() #0 !dbg !16 {
+entry:
+  %0 = load i64, i64* @foo, align 8, !dbg !19
+  %1 = inttoptr i64 %0 to i64*, !dbg !19
+  %cmp = icmp ugt i64* getelementptr inbounds ([1 x i64], [1 x i64]* @baa, i32 0, i32 0), %1, !dbg !20
+  %conv = zext i1 %cmp to i32, !dbg !20
+  store i64 0, i64* @foo, align 8, !dbg !21
+  ret void, !dbg !22
+}
+
+attributes #0 = { noinline nounwind optnone uwtable }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!12, !13, !14}
+!llvm.ident = !{!15}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "shrink-address-to-bool.c", directory: "/")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "baa", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true)
+!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 64, elements: !10)
+!9 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
+!10 = !{!11}
+!11 = !DISubrange(count: 1)
+!12 = !{i32 2, !"Dwarf Version", i32 4}
+!13 = !{i32 2, !"Debug Info Version", i32 3}
+!14 = !{i32 1, !"wchar_size", i32 4}
+!15 = !{!"clang version 6.0.0 "}
+!16 = distinct !DISubprogram(name: "fun", scope: !3, file: !3, line: 4, type: !17, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: false, unit: !2, retainedNodes: !4)
+!17 = !DISubroutineType(types: !18)
+!18 = !{null}
+!19 = !DILocation(line: 5, column: 9, scope: !16)
+!20 = !DILocation(line: 5, column: 7, scope: !16)
+!21 = !DILocation(line: 6, column: 7, scope: !16)
+!22 = !DILocation(line: 7, column: 1, scope: !16)

Added: llvm/trunk/test/Transforms/GlobalOpt/shrink-global-to-bool-check-debug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/shrink-global-to-bool-check-debug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/shrink-global-to-bool-check-debug.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/shrink-global-to-bool-check-debug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+;RUN: opt -S -debugify -globalopt -f %s | FileCheck %s
+
+ at foo = internal global i32 0, align 4
+
+define dso_local i32 @bar() {
+entry:
+  store i32 5, i32* @foo, align 4
+  %0 = load i32, i32* @foo, align 4
+  ret i32 %0
+}
+
+;CHECK:      @bar
+;CHECK-NEXT: entry:
+;CHECK-NEXT:   store i1 true, i1* @foo, !dbg ![[DbgLocStore:[0-9]+]]
+;CHECK-NEXT:   %.b = load i1, i1* @foo, !dbg ![[DbgLocLoadSel:[0-9]+]]
+;CHECK-NEXT:   %0 = select i1 %.b, i32 5, i32 0, !dbg ![[DbgLocLoadSel]]
+;CHECK-NEXT:   call void @llvm.dbg.value({{.*}}), !dbg ![[DbgLocLoadSel]]
+;CHECK-NEXT:   ret i32 %0, !dbg ![[DbgLocRet:[0-9]+]]
+
+;CHECK: ![[DbgLocStore]] = !DILocation(line: 1,
+;CHECK: ![[DbgLocLoadSel]] = !DILocation(line: 2,
+;CHECK: ![[DbgLocRet]] = !DILocation(line: 3,

Added: llvm/trunk/test/Transforms/GlobalOpt/static-const-bitcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/static-const-bitcast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/static-const-bitcast.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/static-const-bitcast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,62 @@
+; RUN: opt -globalopt %s -S -o - | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.A = type { %class.Wrapper }
+%class.Wrapper = type { i32 }
+
+$Wrapper = comdat any
+
+ at kA = internal global %struct.A zeroinitializer, align 4
+; CHECK: @kA = internal unnamed_addr constant %struct.A { %class.Wrapper { i32 1036831949 } }, align 4
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } {
+i32 65535, void ()* @_GLOBAL__sub_I_const_static.cc, i8* null }]
+
+define dso_local i32 @AsBits(float* %x) #0 {
+entry:
+  %0 = bitcast float* %x to i32*
+  %1 = load i32, i32* %0, align 4
+  ret i32 %1
+}
+
+define internal void @__cxx_global_var_init() #1 section ".text.startup" {
+entry:
+  call void @Wrapper(%class.Wrapper* getelementptr inbounds (%struct.A, %struct.A* @kA, i32 0, i32 0), float 0x3FB99999A0000000)
+  %0 = call {}* @llvm.invariant.start.p0i8(i64 4, i8* bitcast (%struct.A* @kA to i8*))
+  ret void
+}
+
+define linkonce_odr dso_local void @Wrapper(%class.Wrapper* %this, float %x) unnamed_addr #0 comdat align 2 {
+entry:
+  %x.addr = alloca float, align 4
+  store float %x, float* %x.addr, align 4
+  %store_ = getelementptr inbounds %class.Wrapper, %class.Wrapper* %this, i32 0, i32 0
+  %call = call i32 @AsBits(float* %x.addr)
+  store i32 %call, i32* %store_, align 4
+  ret void
+}
+
+declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) #2
+
+; Function Attrs: nounwind uwtable
+define dso_local void @LoadIt(%struct.A* %c) #0 {
+entry:
+  %0 = bitcast %struct.A* %c to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 bitcast (%struct.A* @kA to i8*), i64 4, i1 false)
+  ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #2
+
+; Function Attrs: uwtable
+define internal void @_GLOBAL__sub_I_const_static.cc() #1 section ".text.startup" {
+entry:
+  call void @__cxx_global_var_init()
+  ret void
+}
+
+attributes #0 = { nounwind uwtable "target-cpu"="x86-64" }
+attributes #1 = { uwtable "target-cpu"="x86-64" }
+attributes #2 = { argmemonly nounwind }

Added: llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: global
+
+ at G = internal global void ()* null              ; <void ()**> [#uses=2]
+
+define internal void @Actual() {
+; CHECK-LABEL: Actual(
+        ret void
+}
+
+define void @init() {
+; CHECK-LABEL: init(
+; CHECK: store void ()* @Actual, void ()** @G
+        store void ()* @Actual, void ()** @G
+        ret void
+}
+
+define void @doit() #0 {
+; CHECK-LABEL: doit(
+        %FP = load void ()*, void ()** @G         ; <void ()*> [#uses=2]
+; CHECK: %FP = load void ()*, void ()** @G
+        %CC = icmp eq void ()* %FP, null                ; <i1> [#uses=1]
+; CHECK: %CC = icmp eq void ()* %FP, null
+        br i1 %CC, label %isNull, label %DoCall
+; CHECK: br i1 %CC, label %isNull, label %DoCall
+
+DoCall:         ; preds = %0
+; CHECK: DoCall:
+; CHECK: call void %FP()
+; CHECK: ret void
+        call void %FP( )
+        ret void
+
+isNull:         ; preds = %0
+; CHECK: isNull:
+; CHECK: ret void
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/storepointer-compare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: call void @Actual
+
+; Check that a comparison does not prevent an indirect call from being made 
+; direct.  The global will still remain, but indirect call elim is still good.
+
+ at G = internal global void ()* null              ; <void ()**> [#uses=2]
+
+define internal void @Actual() {
+        ret void
+}
+
+define void @init() {
+        store void ()* @Actual, void ()** @G
+        ret void
+}
+
+define void @doit() {
+        %FP = load void ()*, void ()** @G         ; <void ()*> [#uses=2]
+        %CC = icmp eq void ()* %FP, null                ; <i1> [#uses=1]
+        br i1 %CC, label %isNull, label %DoCall
+
+DoCall:         ; preds = %0
+        call void %FP( )
+        ret void
+
+isNull:         ; preds = %0
+        ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/storepointer-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+ at G = internal global void ()* null              ; <void ()**> [#uses=2]
+; CHECK: global
+
+define internal void @Actual() {
+; CHECK-LABEL: Actual(
+        ret void
+}
+
+define void @init() {
+; CHECK-LABEL: init(
+; CHECK:  store void ()* @Actual, void ()** @G
+        store void ()* @Actual, void ()** @G
+        ret void
+}
+
+define void @doit() #0 {
+; CHECK-LABEL: doit(
+; CHECK: %FP = load void ()*, void ()** @G
+; CHECK: call void %FP()
+        %FP = load void ()*, void ()** @G         ; <void ()*> [#uses=1]
+        call void %FP( )
+        ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/GlobalOpt/storepointer.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/storepointer.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/storepointer.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/storepointer.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: global
+
+ at G = internal global void ()* null              ; <void ()**> [#uses=2]
+
+define internal void @Actual() {
+        ret void
+}
+
+define void @init() {
+        store void ()* @Actual, void ()** @G
+        ret void
+}
+
+define void @doit() {
+        %FP = load void ()*, void ()** @G         ; <void ()*> [#uses=1]
+        call void %FP( )
+        ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/tls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/tls.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/tls.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/tls.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; RUN: opt -emulated-tls < %s -globalopt -S | FileCheck %s
+
+declare void @wait()
+declare void @signal()
+declare void @start_thread(void ()*)
+
+ at x = internal thread_local global [100 x i32] zeroinitializer, align 16
+ at ip = internal global i32* null, align 8
+
+; PR14309: GlobalOpt would think that the value of @ip is always the address of
+; x[1]. However, that address is different for different threads so @ip cannot
+; be replaced with a constant.
+
+define i32 @f() {
+entry:
+  ; Set @ip to point to x[1] for thread 1.
+  store i32* getelementptr inbounds ([100 x i32], [100 x i32]* @x, i64 0, i64 1), i32** @ip, align 8
+
+  ; Run g on a new thread.
+  tail call void @start_thread(void ()* @g) nounwind
+  tail call void @wait() nounwind
+
+  ; Reset x[1] for thread 1.
+  store i32 0, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @x, i64 0, i64 1), align 4
+
+  ; Read the value of @ip, which now points at x[1] for thread 2.
+  %0 = load i32*, i32** @ip, align 8
+
+  %1 = load i32, i32* %0, align 4
+  ret i32 %1
+
+; CHECK-LABEL: @f(
+; Make sure that the load from @ip hasn't been removed.
+; CHECK: load i32*, i32** @ip
+; CHECK: ret
+}
+
+define internal void @g() nounwind uwtable {
+entry:
+  ; Set @ip to point to x[1] for thread 2.
+  store i32* getelementptr inbounds ([100 x i32], [100 x i32]* @x, i64 0, i64 1), i32** @ip, align 8
+
+  ; Store 50 in x[1] for thread 2.
+  store i32 50, i32* getelementptr inbounds ([100 x i32], [100 x i32]* @x, i64 0, i64 1), align 4
+
+  tail call void @signal() nounwind
+  ret void
+
+; CHECK-LABEL: @g(
+; Make sure that the store to @ip hasn't been removed.
+; CHECK: store {{.*}} @ip
+; CHECK: ret
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/trivialstore.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/trivialstore.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/trivialstore.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/trivialstore.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: G
+
+ at G = internal global i32 17             ; <i32*> [#uses=3]
+
+define void @foo() {
+        store i32 17, i32* @G
+        ret void
+}
+
+define i32 @bar() {
+        %X = load i32, i32* @G               ; <i32> [#uses=1]
+        ret i32 %X
+}
+
+define internal void @dead() {
+        store i32 123, i32* @G
+        ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/undef-init.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/undef-init.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/undef-init.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/undef-init.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK-NOT: store
+
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__Z3foov } ]          ; <[1 x { i32, void ()* }]*> [#uses=0]
+ at X.0 = internal global i32 undef                ; <i32*> [#uses=2]
+
+define i32 @_Z3foov() {
+entry:
+        %tmp.1 = load i32, i32* @X.0         ; <i32> [#uses=1]
+        ret i32 %tmp.1
+}
+
+define internal void @_GLOBAL__I__Z3foov() {
+entry:
+        store i32 1, i32* @X.0
+        ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; RUN: opt -globalopt -S < %s | FileCheck %s
+
+ at a = internal global i32 0, align 4
+ at b = internal global i32 0, align 4
+ at c = internal global i32 0, align 4
+ at d = internal constant [4 x i8] c"foo\00", align 1
+ at e = linkonce_odr global i32 0
+
+; CHECK: @a = internal global i32 0, align 4
+; CHECK: @b = internal global i32 0, align 4
+; CHECK: @c = internal unnamed_addr global i32 0, align 4
+; CHECK: @d = internal unnamed_addr constant [4 x i8] c"foo\00", align 1
+; CHECK: @e = linkonce_odr local_unnamed_addr global i32 0
+
+; CHECK: define internal fastcc void @used_internal() unnamed_addr {
+define internal void @used_internal() {
+  ret void
+}
+
+define i32 @get_e() {
+       call void @used_internal()
+       %t = load i32, i32* @e
+       ret i32 %t
+}
+
+define void @set_e(i32 %x) {
+       store i32 %x, i32* @e
+       ret void
+}
+
+define i1 @bah(i64 %i) nounwind readonly optsize ssp {
+entry:
+  %arrayidx4 = getelementptr inbounds [4 x i8], [4 x i8]* @d, i64 0, i64 %i
+  %tmp5 = load i8, i8* %arrayidx4, align 1
+  %array0 = bitcast [4 x i8]* @d to i8*
+  %tmp6 = load i8, i8* %array0, align 1
+  %cmp = icmp eq i8 %tmp5, %tmp6
+  ret i1 %cmp
+}
+
+define void @baz(i32 %x) {
+entry:
+  store i32 %x, i32* @a, align 4
+  store i32 %x, i32* @b, align 4
+  store i32 %x, i32* @c, align 4
+  ret void
+}
+
+define i32 @foo(i32* %x) nounwind readnone optsize ssp {
+entry:
+  %cmp = icmp eq i32* %x, @a
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @bar() {
+entry:
+  switch i64 ptrtoint (i32* @b to i64), label %sw.epilog [
+    i64 1, label %return
+    i64 0, label %return
+  ]
+
+sw.epilog:
+  ret i32 0
+
+return:
+  ret i32 1
+}
+
+define i32 @zed() {
+entry:
+  %tmp1 = load i32, i32* @c, align 4
+  ret i32 %tmp1
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/zeroinitializer-gep-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/zeroinitializer-gep-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/zeroinitializer-gep-load.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/zeroinitializer-gep-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -S -globalopt | FileCheck %s
+
+ at zero = internal global [10 x i32] zeroinitializer
+
+define i32 @test1(i64 %idx) nounwind {
+  %arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* @zero, i64 0, i64 %idx
+  %l = load i32, i32* %arrayidx
+  ret i32 %l
+; CHECK-LABEL: @test1(
+; CHECK: ret i32 0
+}

Added: llvm/trunk/test/Transforms/GlobalSplit/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalSplit/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalSplit/basic.ll (added)
+++ llvm/trunk/test/Transforms/GlobalSplit/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; RUN: opt -S -globalsplit %s | FileCheck %s
+; RUN: opt -S -passes=globalsplit %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @vtt = constant [3 x i8*] [i8* bitcast ([2 x i8* ()*]* @global.0 to i8*), i8* bitcast (i8* ()** getelementptr inbounds ([2 x i8* ()*], [2 x i8* ()*]* @global.0, i32 0, i32 1) to i8*), i8* bitcast ([1 x i8* ()*]* @global.1 to i8*)]
+ at vtt = constant [3 x i8*] [
+  i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 0) to i8*),
+  i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 1) to i8*),
+  i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 1, i32 0) to i8*)
+]
+
+; CHECK-NOT: @global =
+; CHECK: @global.0 = private constant [2 x i8* ()*] [i8* ()* @f1, i8* ()* @f2], !type [[T1:![0-9]+]], !type [[T2:![0-9]+]], !type [[T3:![0-9]+$]]
+; CHECK: @global.1 = private constant [1 x i8* ()*] [i8* ()* @f3], !type [[T4:![0-9]+]], !type [[T5:![0-9]+$]]
+; CHECK-NOT: @global =
+ at global = internal constant { [2 x i8* ()*], [1 x i8* ()*] } {
+  [2 x i8* ()*] [i8* ()* @f1, i8* ()* @f2],
+  [1 x i8* ()*] [i8* ()* @f3]
+}, !type !0, !type !1, !type !2, !type !3, !type !4
+
+; CHECK: define i8* @f1()
+define i8* @f1() {
+  ; CHECK-NEXT: ret i8* bitcast ([2 x i8* ()*]* @global.0 to i8*)
+  ret i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 0) to i8*)
+}
+
+; CHECK: define i8* @f2()
+define i8* @f2() {
+  ; CHECK-NEXT: ret i8* bitcast (i8* ()** getelementptr inbounds ([2 x i8* ()*], [2 x i8* ()*]* @global.0, i32 0, i32 1) to i8*)
+  ret i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 1) to i8*)
+}
+
+; CHECK: define i8* @f3()
+define i8* @f3() {
+  ; CHECK-NEXT: ret i8* bitcast (i8* ()** getelementptr inbounds ([2 x i8* ()*], [2 x i8* ()*]* @global.0, i64 1, i32 0) to i8*)
+  ret i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 2) to i8*)
+}
+
+; CHECK: define i8* @f4()
+define i8* @f4() {
+  ; CHECK-NEXT: ret i8* bitcast ([1 x i8* ()*]* @global.1 to i8*)
+  ret i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 1, i32 0) to i8*)
+}
+
+define void @foo() {
+  %p = call i1 @llvm.type.test(i8* null, metadata !"")
+  ret void
+}
+
+declare i1 @llvm.type.test(i8*, metadata) nounwind readnone
+
+; CHECK: [[T1]] = !{i32 0, !"foo"}
+; CHECK: [[T2]] = !{i32 15, !"bar"}
+; CHECK: [[T3]] = !{i32 16, !"a"}
+; CHECK: [[T4]] = !{i32 1, !"b"}
+; CHECK: [[T5]] = !{i32 8, !"c"}
+!0 = !{i32 0, !"foo"}
+!1 = !{i32 15, !"bar"}
+!2 = !{i32 16, !"a"}
+!3 = !{i32 17, !"b"}
+!4 = !{i32 24, !"c"}

Added: llvm/trunk/test/Transforms/GlobalSplit/non-beneficial.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalSplit/non-beneficial.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalSplit/non-beneficial.ll (added)
+++ llvm/trunk/test/Transforms/GlobalSplit/non-beneficial.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -S -globalsplit %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @global =
+ at global = internal constant { [2 x i8* ()*], [1 x i8* ()*] } {
+  [2 x i8* ()*] [i8* ()* @f, i8* ()* @g],
+  [1 x i8* ()*] [i8* ()* @h]
+}
+
+define i8* @f() {
+  ret i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 0) to i8*)
+}
+
+define i8* @g() {
+  ret i8* null
+}
+
+define i8* @h() {
+  ret i8* null
+}
+
+!0 = !{i32 16}

Added: llvm/trunk/test/Transforms/GlobalSplit/nonlocal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalSplit/nonlocal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalSplit/nonlocal.ll (added)
+++ llvm/trunk/test/Transforms/GlobalSplit/nonlocal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -S -globalsplit %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @global =
+ at global = constant { [2 x i8* ()*], [1 x i8* ()*] } {
+  [2 x i8* ()*] [i8* ()* @f, i8* ()* @g],
+  [1 x i8* ()*] [i8* ()* @h]
+}
+
+define i8* @f() {
+  ret i8* bitcast (i8* ()** getelementptr ({ [2 x i8* ()*], [1 x i8* ()*] }, { [2 x i8* ()*], [1 x i8* ()*] }* @global, i32 0, inrange i32 0, i32 0) to i8*)
+}
+
+define i8* @g() {
+  ret i8* null
+}
+
+define i8* @h() {
+  ret i8* null
+}
+
+define void @foo() {
+  %p = call i1 @llvm.type.test(i8* null, metadata !"")
+  ret void
+}
+
+declare i1 @llvm.type.test(i8*, metadata) nounwind readnone

Added: llvm/trunk/test/Transforms/GuardWidening/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/basic.ll (added)
+++ llvm/trunk/test/Transforms/GuardWidening/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,407 @@
+; RUN: opt -S -guard-widening < %s        | FileCheck %s
+; RUN: opt -S -passes=guard-widening < %s | FileCheck %s
+
+declare void @llvm.experimental.guard(i1,...)
+
+; Basic test case: we wide the first check to check both the
+; conditions.
+define void @f_0(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_0(
+entry:
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  ret void
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+}
+
+; Same as @f_0, but with using a more general notion of postdominance.
+define void @f_1(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_1(
+entry:
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+  br label %merge
+
+right:
+  br label %merge
+
+merge:
+; CHECK: merge:
+; CHECK-NOT: call void (i1, ...) @llvm.experimental.guard(
+; CHECK: ret void
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+}
+
+; Like @f_1, but we have some code we need to hoist before we can
+; widen a dominanting check.
+define void @f_2(i32 %a, i32 %b) {
+; CHECK-LABEL: @f_2(
+entry:
+; CHECK:  %cond_0 = icmp ult i32 %a, 10
+; CHECK:  %cond_1 = icmp ult i32 %b, 10
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ult i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+  br label %merge
+
+right:
+  br label %merge
+
+merge:
+  %cond_1 = icmp ult i32 %b, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+}
+
+; Negative test: don't hoist stuff out of control flow
+; indiscriminately, since that can make us do more work than needed.
+define void @f_3(i32 %a, i32 %b) {
+; CHECK-LABEL: @f_3(
+entry:
+; CHECK:  %cond_0 = icmp ult i32 %a, 10
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ult i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+; CHECK: left:
+; CHECK:   %cond_1 = icmp ult i32 %b, 10
+; CHECK:   call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+; CHECK:   ret void
+
+  %cond_1 = icmp ult i32 %b, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+
+right:
+  ret void
+}
+
+; But hoisting out of control flow is fine if it makes a loop computed
+; condition loop invariant.  This behavior may require some tuning in
+; the future.
+define void @f_4(i32 %a, i32 %b) {
+; CHECK-LABEL: @f_4(
+entry:
+; CHECK:  %cond_0 = icmp ult i32 %a, 10
+; CHECK:  %cond_1 = icmp ult i32 %b, 10
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %loop, label %leave
+
+  %cond_0 = icmp ult i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %loop, label %leave
+
+loop:
+  %cond_1 = icmp ult i32 %b, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  br i1 undef, label %loop, label %leave
+
+leave:
+  ret void
+}
+
+; Hoisting out of control flow is also fine if we can widen the
+; dominating check without doing any extra work.
+define void @f_5(i32 %a) {
+; CHECK-LABEL: @f_5(
+entry:
+; CHECK:  %wide.chk = icmp uge i32 %a, 11
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ugt i32 %a, 7
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+  %cond_1 = icmp ugt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+
+right:
+  ret void
+}
+
+; Negative test: the load from %a can be safely speculated to before
+; the first guard, but there is no guarantee that it will produce the
+; same value.
+define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) {
+; CHECK-LABEL: @f_6(
+; CHECK: call void (i1, ...) @llvm.experimental.guard(
+; CHECK: call void (i1, ...) @llvm.experimental.guard(
+; CHECK: ret void
+entry:
+  %cond_0 = load i1, i1* %a
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  store i1 %unknown, i1* %b
+  %cond_1 = load i1, i1* %a
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+}
+
+; All else equal, we try to widen the earliest guard we can.  This
+; heuristic can use some tuning.
+define void @f_7(i32 %a, i1* %cond_buf) {
+; CHECK-LABEL: @f_7(
+entry:
+; CHECK:  %cond_1 = load volatile i1, i1* %cond_buf
+; CHECK:  %cond_3 = icmp ult i32 %a, 7
+; CHECK:  %wide.chk = and i1 %cond_1, %cond_3
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  %cond_2 = load volatile i1, i1* %cond_buf
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_1 = load volatile i1, i1* %cond_buf
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  %cond_2 = load volatile i1, i1* %cond_buf
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+  %cond_3 = icmp ult i32 %a, 7
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_3) [ "deopt"() ]
+  br label %left
+
+right:
+  ret void
+}
+
+; In this case the earliest dominating guard is in a loop, and we
+; don't want to put extra work in there.  This heuristic can use some
+; tuning.
+define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
+; CHECK-LABEL: @f_8(
+entry:
+  br label %loop
+
+loop:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  br i1 undef, label %loop, label %leave
+
+leave:
+; CHECK: leave:
+; CHECK:  %cond_3 = icmp ult i32 %a, 7
+; CHECK:  %wide.chk = and i1 %cond_2, %cond_3
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %loop2, label %leave2
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ]
+  br i1 undef, label %loop2, label %leave2
+
+loop2:
+  %cond_3 = icmp ult i32 %a, 7
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_3) [ "deopt"() ]
+  br label %loop2
+
+leave2:
+  ret void
+}
+
+; In cases like these where there isn't any "obviously profitable"
+; widening sites, we refuse to do anything.
+define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_9(
+entry:
+  br label %first_loop
+
+first_loop:
+; CHECK: first_loop:
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  br i1 undef, label %first_loop, label %second_loop
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %first_loop, label %second_loop
+
+second_loop:
+; CHECK: second_loop:
+; CHECK:   call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+; CHECK:   br label %second_loop
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  br label %second_loop
+}
+
+; Same situation as in @f_9: no "obviously profitable" widening sites,
+; so we refuse to do anything.
+define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_10(
+entry:
+  br label %loop
+
+loop:
+; CHECK: loop:
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  br i1 undef, label %loop, label %no_loop
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %loop, label %no_loop
+
+no_loop:
+; CHECK: no_loop:
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+; CHECK:  ret void
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+}
+
+; With guards in loops, we're okay hoisting out the guard into the
+; containing loop.
+define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_11(
+entry:
+  br label %inner
+
+inner:
+; CHECK: inner:
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %inner, label %outer
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %inner, label %outer
+
+outer:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  br label %inner
+}
+
+; Checks that we are adequately guarded against exponential-time
+; behavior when hoisting code.
+define void @f_12(i32 %a0) {
+; CHECK-LABEL: @f_12
+
+; Eliding the earlier 29 multiplications for brevity
+; CHECK:  %a30 = mul i32 %a29, %a29
+; CHECK-NEXT:  %cond = trunc i32 %a30 to i1
+; CHECK-NEXT:  %wide.chk = and i1 true, %cond
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK-NEXT:  ret void
+
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
+  %a1 = mul i32 %a0, %a0
+  %a2 = mul i32 %a1, %a1
+  %a3 = mul i32 %a2, %a2
+  %a4 = mul i32 %a3, %a3
+  %a5 = mul i32 %a4, %a4
+  %a6 = mul i32 %a5, %a5
+  %a7 = mul i32 %a6, %a6
+  %a8 = mul i32 %a7, %a7
+  %a9 = mul i32 %a8, %a8
+  %a10 = mul i32 %a9, %a9
+  %a11 = mul i32 %a10, %a10
+  %a12 = mul i32 %a11, %a11
+  %a13 = mul i32 %a12, %a12
+  %a14 = mul i32 %a13, %a13
+  %a15 = mul i32 %a14, %a14
+  %a16 = mul i32 %a15, %a15
+  %a17 = mul i32 %a16, %a16
+  %a18 = mul i32 %a17, %a17
+  %a19 = mul i32 %a18, %a18
+  %a20 = mul i32 %a19, %a19
+  %a21 = mul i32 %a20, %a20
+  %a22 = mul i32 %a21, %a21
+  %a23 = mul i32 %a22, %a22
+  %a24 = mul i32 %a23, %a23
+  %a25 = mul i32 %a24, %a24
+  %a26 = mul i32 %a25, %a25
+  %a27 = mul i32 %a26, %a26
+  %a28 = mul i32 %a27, %a27
+  %a29 = mul i32 %a28, %a28
+  %a30 = mul i32 %a29, %a29
+  %cond = trunc i32 %a30 to i1
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
+  ret void
+}
+
+define void @f_13(i32 %a) {
+; CHECK-LABEL: @f_13(
+entry:
+; CHECK:  %wide.chk = icmp ult i32 %a, 10
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ult i32 %a, 14
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+  %cond_1 = icmp slt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+
+right:
+  ret void
+}
+
+define void @f_14(i32 %a) {
+; CHECK-LABEL: @f_14(
+entry:
+; CHECK:  %cond_0 = icmp ult i32 %a, 14
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ult i32 %a, 14
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+; CHECK: left:
+; CHECK:  %cond_1 = icmp sgt i32 %a, 10
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+
+  %cond_1 = icmp sgt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+
+right:
+  ret void
+}
+
+; Make sure we do not widen guard by trivial true conditions into something.
+define void @f_15(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_15(
+entry:
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
+; CHECK:  ret void
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
+  ret void
+}
+
+; Make sure we do not widen guard by trivial false conditions into something.
+define void @f_16(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_16(
+entry:
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+; CHECK:  ret void
+
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+  ret void
+}

Added: llvm/trunk/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll (added)
+++ llvm/trunk/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1041 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -guard-widening-widen-branch-guards=true -guard-widening < %s        | FileCheck %s
+; RUN: opt -S -guard-widening-widen-branch-guards=true -passes=guard-widening < %s | FileCheck %s
+
+; Basic test case: we wide the first check to check both the
+; conditions.
+define void @f_0(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_0(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  ret void
+}
+
+; Same as @f_0, but with using a more general notion of postdominance.
+define void @f_1(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded
+  br label %merge
+
+right:                                            ; preds = %guarded
+  br label %merge
+
+merge:                                            ; preds = %right, %left
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %merge
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %merge
+  ret void
+}
+
+; Like @f_1, but we have some code we need to hoist before we can
+; widen a dominanting check.
+define void @f_2(i32 %a, i32 %b) {
+; CHECK-LABEL: @f_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ult i32 %a, 10
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded
+  br label %merge
+
+right:                                            ; preds = %guarded
+  br label %merge
+
+merge:                                            ; preds = %right, %left
+  %cond_1 = icmp ult i32 %b, 10
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %merge
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %merge
+  ret void
+}
+
+; Negative test: don't hoist stuff out of control flow
+; indiscriminately, since that can make us do more work than needed.
+define void @f_3(i32 %a, i32 %b) {
+; CHECK-LABEL: @f_3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+; CHECK:       right:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ult i32 %a, 10
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded
+  %cond_1 = icmp ult i32 %b, 10
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %left
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %left
+  ret void
+
+right:                                            ; preds = %guarded
+  ret void
+}
+
+; But hoisting out of control flow is fine if it makes a loop computed
+; condition loop invariant.  This behavior may require some tuning in
+; the future.
+define void @f_4(i32 %a, i32 %b) {
+; CHECK-LABEL: @f_4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LOOP:%.*]], label [[LEAVE:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[LEAVE]]
+; CHECK:       leave:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ult i32 %a, 10
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %loop, label %leave
+
+loop:                                             ; preds = %guarded1, %guarded
+  %cond_1 = icmp ult i32 %b, 10
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %loop
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %loop
+  br i1 undef, label %loop, label %leave
+
+leave:                                            ; preds = %guarded1, %guarded
+  ret void
+}
+
+; Hoisting out of control flow is also fine if we can widen the
+; dominating check without doing any extra work.
+define void @f_5(i32 %a) {
+; CHECK-LABEL: @f_5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ugt i32 [[A]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+; CHECK:       right:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ugt i32 %a, 7
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded
+  %cond_1 = icmp ugt i32 %a, 10
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %left
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %left
+  ret void
+
+right:                                            ; preds = %guarded
+  ret void
+}
+
+; Negative test: the load from %a can be safely speculated to before
+; the first guard, but there is no guarantee that it will produce the
+; same value.
+define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) {
+; CHECK-LABEL: @f_6(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = load i1, i1* [[A:%.*]]
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]]
+; CHECK-NEXT:    [[COND_1:%.*]] = load i1, i1* [[A]]
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = load i1, i1* %a
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  store i1 %unknown, i1* %b
+  %cond_1 = load i1, i1* %a
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  ret void
+}
+
+; All else equal, we try to widen the earliest guard we can.  This
+; heuristic can use some tuning.
+define void @f_7(i32 %a, i1* %cond_buf) {
+; CHECK-LABEL: @f_7(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]]
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]]
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0
+; CHECK:       deopt6:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded5:
+; CHECK-NEXT:    br label [[LEFT]]
+; CHECK:       right:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_1 = load volatile i1, i1* %cond_buf
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  %cond_2 = load volatile i1, i1* %cond_buf
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded5, %guarded1
+  %cond_3 = icmp ult i32 %a, 7
+  %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7
+  br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0
+
+deopt6:                                           ; preds = %left
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded5:                                         ; preds = %left
+  br label %left
+
+right:                                            ; preds = %guarded1
+  ret void
+}
+
+; In this case the earliest dominating guard is in a loop, and we
+; don't want to put extra work in there.  This heuristic can use some
+; tuning.
+define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
+; CHECK-LABEL: @f_8(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[LEAVE:%.*]]
+; CHECK:       leave:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2:%.*]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_2]], [[COND_3]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    br i1 undef, label [[LOOP2:%.*]], label [[LEAVE2:%.*]]
+; CHECK:       loop2:
+; CHECK-NEXT:    [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0
+; CHECK:       deopt6:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded5:
+; CHECK-NEXT:    br label [[LOOP2]]
+; CHECK:       leave2:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:                                             ; preds = %guarded, %entry
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %loop
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %loop
+  br i1 undef, label %loop, label %leave
+
+leave:                                            ; preds = %guarded
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %leave
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %leave
+  br i1 undef, label %loop2, label %leave2
+
+loop2:                                            ; preds = %guarded5, %guarded1
+  %cond_3 = icmp ult i32 %a, 7
+  %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7
+  br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0
+
+deopt6:                                           ; preds = %loop2
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded5:                                         ; preds = %loop2
+  br label %loop2
+
+leave2:                                           ; preds = %guarded1
+  ret void
+}
+
+; In cases like these where there isn't any "obviously profitable"
+; widening sites, we refuse to do anything.
+define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_9(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FIRST_LOOP:%.*]]
+; CHECK:       first_loop:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[FIRST_LOOP]], label [[SECOND_LOOP:%.*]]
+; CHECK:       second_loop:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    br label [[SECOND_LOOP]]
+;
+entry:
+  br label %first_loop
+
+first_loop:                                       ; preds = %guarded, %entry
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %first_loop
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %first_loop
+  br i1 undef, label %first_loop, label %second_loop
+
+second_loop:                                      ; preds = %guarded1, %guarded
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %second_loop
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %second_loop
+  br label %second_loop
+}
+
+; Same situation as in @f_9: no "obviously profitable" widening sites,
+; so we refuse to do anything.
+define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_10(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[NO_LOOP:%.*]]
+; CHECK:       no_loop:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:                                             ; preds = %guarded, %entry
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %loop
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %loop
+  br i1 undef, label %loop, label %no_loop
+
+no_loop:                                          ; preds = %guarded
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %no_loop
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %no_loop
+  ret void
+}
+
+; With guards in loops, we're okay hoisting out the guard into the
+; containing loop.
+define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_11(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
+; CHECK:       outer_header:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br label [[INNER:%.*]]
+; CHECK:       inner:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    br i1 undef, label [[INNER]], label [[OUTER_LATCH:%.*]]
+; CHECK:       outer_latch:
+; CHECK-NEXT:    br i1 undef, label [[OUTER_HEADER]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %outer_header
+
+outer_header:                                     ; preds = %outer_latch, %entry
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %outer_header
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %outer_header
+  br label %inner
+
+inner:                                            ; preds = %guarded1, %guarded
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %inner
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %inner
+  br i1 undef, label %inner, label %outer_latch
+
+outer_latch:                                      ; preds = %guarded1
+  br i1 undef, label %outer_header, label %exit
+
+exit:                                             ; preds = %outer_latch
+  ret void
+}
+
+; Checks that we are adequately guarded against exponential-time
+; behavior when hoisting code.
+define void @f_12(i32 %a0) {
+; CHECK-LABEL: @f_12(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 true, [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]]
+; CHECK-NEXT:    [[A2:%.*]] = mul i32 [[A1]], [[A1]]
+; CHECK-NEXT:    [[A3:%.*]] = mul i32 [[A2]], [[A2]]
+; CHECK-NEXT:    [[A4:%.*]] = mul i32 [[A3]], [[A3]]
+; CHECK-NEXT:    [[A5:%.*]] = mul i32 [[A4]], [[A4]]
+; CHECK-NEXT:    [[A6:%.*]] = mul i32 [[A5]], [[A5]]
+; CHECK-NEXT:    [[A7:%.*]] = mul i32 [[A6]], [[A6]]
+; CHECK-NEXT:    [[A8:%.*]] = mul i32 [[A7]], [[A7]]
+; CHECK-NEXT:    [[A9:%.*]] = mul i32 [[A8]], [[A8]]
+; CHECK-NEXT:    [[A10:%.*]] = mul i32 [[A9]], [[A9]]
+; CHECK-NEXT:    [[A11:%.*]] = mul i32 [[A10]], [[A10]]
+; CHECK-NEXT:    [[A12:%.*]] = mul i32 [[A11]], [[A11]]
+; CHECK-NEXT:    [[A13:%.*]] = mul i32 [[A12]], [[A12]]
+; CHECK-NEXT:    [[A14:%.*]] = mul i32 [[A13]], [[A13]]
+; CHECK-NEXT:    [[A15:%.*]] = mul i32 [[A14]], [[A14]]
+; CHECK-NEXT:    [[A16:%.*]] = mul i32 [[A15]], [[A15]]
+; CHECK-NEXT:    [[A17:%.*]] = mul i32 [[A16]], [[A16]]
+; CHECK-NEXT:    [[A18:%.*]] = mul i32 [[A17]], [[A17]]
+; CHECK-NEXT:    [[A19:%.*]] = mul i32 [[A18]], [[A18]]
+; CHECK-NEXT:    [[A20:%.*]] = mul i32 [[A19]], [[A19]]
+; CHECK-NEXT:    [[A21:%.*]] = mul i32 [[A20]], [[A20]]
+; CHECK-NEXT:    [[A22:%.*]] = mul i32 [[A21]], [[A21]]
+; CHECK-NEXT:    [[A23:%.*]] = mul i32 [[A22]], [[A22]]
+; CHECK-NEXT:    [[A24:%.*]] = mul i32 [[A23]], [[A23]]
+; CHECK-NEXT:    [[A25:%.*]] = mul i32 [[A24]], [[A24]]
+; CHECK-NEXT:    [[A26:%.*]] = mul i32 [[A25]], [[A25]]
+; CHECK-NEXT:    [[A27:%.*]] = mul i32 [[A26]], [[A26]]
+; CHECK-NEXT:    [[A28:%.*]] = mul i32 [[A27]], [[A27]]
+; CHECK-NEXT:    [[A29:%.*]] = mul i32 [[A28]], [[A28]]
+; CHECK-NEXT:    [[A30:%.*]] = mul i32 [[A29]], [[A29]]
+; CHECK-NEXT:    [[COND:%.*]] = trunc i32 [[A30]] to i1
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 true, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  %a1 = mul i32 %a0, %a0
+  %a2 = mul i32 %a1, %a1
+  %a3 = mul i32 %a2, %a2
+  %a4 = mul i32 %a3, %a3
+  %a5 = mul i32 %a4, %a4
+  %a6 = mul i32 %a5, %a5
+  %a7 = mul i32 %a6, %a6
+  %a8 = mul i32 %a7, %a7
+  %a9 = mul i32 %a8, %a8
+  %a10 = mul i32 %a9, %a9
+  %a11 = mul i32 %a10, %a10
+  %a12 = mul i32 %a11, %a11
+  %a13 = mul i32 %a12, %a12
+  %a14 = mul i32 %a13, %a13
+  %a15 = mul i32 %a14, %a14
+  %a16 = mul i32 %a15, %a15
+  %a17 = mul i32 %a16, %a16
+  %a18 = mul i32 %a17, %a17
+  %a19 = mul i32 %a18, %a18
+  %a20 = mul i32 %a19, %a19
+  %a21 = mul i32 %a20, %a20
+  %a22 = mul i32 %a21, %a21
+  %a23 = mul i32 %a22, %a22
+  %a24 = mul i32 %a23, %a23
+  %a25 = mul i32 %a24, %a24
+  %a26 = mul i32 %a25, %a25
+  %a27 = mul i32 %a26, %a26
+  %a28 = mul i32 %a27, %a27
+  %a29 = mul i32 %a28, %a28
+  %a30 = mul i32 %a29, %a29
+  %cond = trunc i32 %a30 to i1
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  ret void
+}
+
+define void @f_13(i32 %a) {
+; CHECK-LABEL: @f_13(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp slt i32 [[A]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+; CHECK:       right:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ult i32 %a, 14
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded
+  %cond_1 = icmp slt i32 %a, 10
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %left
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %left
+  ret void
+
+right:                                            ; preds = %guarded
+  ret void
+}
+
+define void @f_14(i32 %a) {
+; CHECK-LABEL: @f_14(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp sgt i32 [[A]], 10
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+; CHECK:       right:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ult i32 %a, 14
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  br i1 undef, label %left, label %right
+
+left:                                             ; preds = %guarded
+  %cond_1 = icmp sgt i32 %a, 10
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %left
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %left
+  ret void
+
+right:                                            ; preds = %guarded
+  ret void
+}
+
+; Make sure we do not widen guard by trivial true conditions into something.
+define void @f_15(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_15(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 true, [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 true, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  ret void
+}
+
+; Make sure we do not widen guard by trivial false conditions into something.
+define void @f_16(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @f_16(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 false, [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 false, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  ret void
+}
+
+declare void @llvm.experimental.deoptimize.isVoid(...)
+
+; Function Attrs: inaccessiblememonly nounwind
+declare i1 @llvm.experimental.widenable.condition() #0
+
+attributes #0 = { inaccessiblememonly nounwind }
+
+!0 = !{!"branch_weights", i32 1048576, i32 1}

Added: llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll (added)
+++ llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt -S -licm -loop-guard-widening -licm -debug-pass=Structure < %s 2>&1   | FileCheck %s
+
+; Main point of this test is to check the scheduling -- there should be
+; no analysis passes needed between LICM and LoopGuardWidening
+
+; CHECK: Loop Pass Manager
+; CHECK:   Loop Invariant Code Motion
+; CHECK:   Widen guards (within a single loop, as a loop pass)
+; CHECK:   Loop Invariant Code Motion
+
+declare void @llvm.experimental.guard(i1,...)
+
+define void @iter(i32 %a, i32 %b, i1* %c_p) {
+; CHECK-LABEL @iter
+; CHECK:  %cond_0 = icmp ult i32 %a, 10
+; CHECK:  %cond_1 = icmp ult i32 %b, 10
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK-LABEL: loop:
+
+entry:
+  %cond_0 = icmp ult i32 %a, 10
+  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br label %loop
+
+loop:                                             ; preds = %loop.preheader, %loop
+  %cond_1 = icmp ult i32 %b, 10
+  call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  %cnd = load i1, i1* %c_p
+  br i1 %cnd, label %loop, label %leave.loopexit
+
+leave.loopexit:                                   ; preds = %loop
+  br label %leave
+
+leave:                                            ; preds = %leave.loopexit, %entry
+  ret void
+}
+
+define void @within_loop(i32 %a, i32 %b, i1* %c_p) {
+; CHECK-LABEL @within_loop
+; CHECK:  %cond_0 = icmp ult i32 %a, 10
+; CHECK:  %cond_1 = icmp ult i32 %b, 10
+; CHECK:  %wide.chk = and i1 %cond_0, %cond_1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK-LABEL: loop:
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop.preheader, %loop
+  %cond_0 = icmp ult i32 %a, 10
+  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  %cond_1 = icmp ult i32 %b, 10
+  call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  %cnd = load i1, i1* %c_p
+  br i1 %cnd, label %loop, label %leave.loopexit
+
+leave.loopexit:                                   ; preds = %loop
+  br label %leave
+
+leave:                                            ; preds = %leave.loopexit, %entry
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/GuardWidening/mixed_guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/mixed_guards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/mixed_guards.ll (added)
+++ llvm/trunk/test/Transforms/GuardWidening/mixed_guards.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -guard-widening-widen-branch-guards=true -guard-widening < %s        | FileCheck %s
+; RUN: opt -S -guard-widening-widen-branch-guards=true -passes=guard-widening < %s | FileCheck %s
+
+; Interaction between intrinsic and widenable condition guards.
+
+declare void @llvm.experimental.guard(i1,...)
+
+declare void @llvm.experimental.deoptimize.isVoid(...)
+
+; Function Attrs: inaccessiblememonly nounwind
+declare i1 @llvm.experimental.widenable.condition() #0
+
+; Widen condition of intrinsic guard with a condition from widenable branch.
+define void @test_01(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_01(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
+; CHECK:       deopt2:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded1:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
+  br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
+
+deopt2:                                           ; preds = %guarded
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded1:                                         ; preds = %guarded
+  ret void
+}
+
+; Widen condition of widenable condition guard with a condition from intrinsic.
+define void @test_02(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_02(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
+; CHECK-NEXT:    br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
+; CHECK:       deopt:
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       guarded:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
+  %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
+  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
+
+deopt:                                            ; preds = %entry
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+
+guarded:                                          ; preds = %entry
+  call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+}
+
+attributes #0 = { inaccessiblememonly nounwind }
+
+!0 = !{!"branch_weights", i32 1048576, i32 1}

Added: llvm/trunk/test/Transforms/GuardWidening/range-check-merging.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/range-check-merging.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/range-check-merging.ll (added)
+++ llvm/trunk/test/Transforms/GuardWidening/range-check-merging.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,235 @@
+; RUN: opt -S -guard-widening < %s | FileCheck %s
+
+declare void @llvm.experimental.guard(i1,...)
+
+define void @f_0(i32 %x, i32* %length_buf) {
+; CHECK-LABEL: @f_0(
+; CHECK-NOT: @llvm.experimental.guard
+; CHECK:  %wide.chk2 = and i1 %chk3, %chk0
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, 1
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = add i32 %x, 2
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+define void @f_1(i32 %x, i32* %length_buf) {
+; CHECK-LABEL: @f_1(
+; CHECK-NOT: llvm.experimental.guard
+; CHECK:  %wide.chk2 = and i1 %chk3, %chk0
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, 1
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = add i32 %x.inc1, 2
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x.inc2, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+define void @f_2(i32 %a, i32* %length_buf) {
+; CHECK-LABEL: @f_2(
+; CHECK-NOT: llvm.experimental.guard
+; CHECK:  %wide.chk2 = and i1 %chk3, %chk0
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = or i32 %x, 1
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = or i32 %x, 2
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = or i32 %x, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+define void @f_3(i32 %a, i32* %length_buf) {
+; CHECK-LABEL: @f_3(
+; CHECK-NOT: llvm.experimental.guard
+; CHECK:  %wide.chk2 = and i1 %chk3, %chk0
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, 1
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = or i32 %x.inc1, 2
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x.inc2, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+define void @f_4(i32 %x, i32* %length_buf) {
+; CHECK-LABEL: @f_4(
+; CHECK-NOT: llvm.experimental.guard
+
+; Note: we NOT guarding on "and i1 %chk3, %chk0", that would be incorrect.
+; CHECK:  %wide.chk2 = and i1 %chk3, %chk1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, -1024
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = add i32 %x, 2
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+define void @f_5(i32 %x, i32* %length_buf) {
+; CHECK-LABEL: @f_5(
+; CHECK-NOT: llvm.experimental.guard
+; CHECK:  %wide.chk2 = and i1 %chk1, %chk2
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, 1
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = add i32 %x.inc1, -200
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x.inc2, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+
+; Negative test: we can't merge these checks into
+;
+;  (%x + -2147483647) u< L && (%x + 3) u< L
+;
+; because if %length == INT_MAX and %x == -3 then
+;
+; (%x + -2147483647) == i32 2147483646  u< L   (L is 2147483647)
+; (%x + 3) == 0 u< L
+;
+; But (%x + 2) == -1 is not u< L
+;
+define void @f_6(i32 %x, i32* %length_buf) {
+; CHECK-LABEL: @f_6(
+; CHECK-NOT: llvm.experimental.guard
+; CHECK:  %wide.chk = and i1 %chk0, %chk1
+; CHECK:  %wide.chk1 = and i1 %wide.chk, %chk2
+; CHECK:  %wide.chk2 = and i1 %wide.chk1, %chk3
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk2) [ "deopt"() ]
+entry:
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, -2147483647 ;; -2147483647 == (i32 INT_MIN)+1 == -(i32 INT_MAX)
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = add i32 %x, 2
+  %chk2 = icmp ult i32 %x.inc2, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x, 3
+  %chk3 = icmp ult i32 %x.inc3, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+
+define void @f_7(i32 %x, i32* %length_buf) {
+; CHECK-LABEL: @f_7(
+
+; CHECK:  [[COND_0:%[^ ]+]] = and i1 %chk3.b, %chk0.b
+; CHECK:  [[COND_1:%[^ ]+]] = and i1 %chk0.a, [[COND_0]]
+; CHECK:  [[COND_2:%[^ ]+]] = and i1 %chk3.a, [[COND_1]]
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2]]) [ "deopt"() ]
+
+entry:
+  %length_a = load volatile i32, i32* %length_buf, !range !0
+  %length_b = load volatile i32, i32* %length_buf, !range !0
+  %chk0.a = icmp ult i32 %x, %length_a
+  %chk0.b = icmp ult i32 %x, %length_b
+  %chk0 = and i1 %chk0.a, %chk0.b
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add i32 %x, 1
+  %chk1.a = icmp ult i32 %x.inc1, %length_a
+  %chk1.b = icmp ult i32 %x.inc1, %length_b
+  %chk1 = and i1 %chk1.a, %chk1.b
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+
+  %x.inc2 = add i32 %x, 2
+  %chk2.a = icmp ult i32 %x.inc2, %length_a
+  %chk2.b = icmp ult i32 %x.inc2, %length_b
+  %chk2 = and i1 %chk2.a, %chk2.b
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk2) [ "deopt"() ]
+
+  %x.inc3 = add i32 %x, 3
+  %chk3.a = icmp ult i32 %x.inc3, %length_a
+  %chk3.b = icmp ult i32 %x.inc3, %length_b
+  %chk3 = and i1 %chk3.a, %chk3.b
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk3) [ "deopt"() ]
+  ret void
+}
+
+
+!0 = !{i32 0, i32 2147483648}

Added: llvm/trunk/test/Transforms/GuardWidening/widen-frequent-branches.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/widen-frequent-branches.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/widen-frequent-branches.ll (added)
+++ llvm/trunk/test/Transforms/GuardWidening/widen-frequent-branches.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,820 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -guard-widening-widen-frequent-branches=true -guard-widening-frequent-branch-threshold=1000 -S -guard-widening < %s        | FileCheck %s
+; RUN: opt -guard-widening-widen-frequent-branches=true -guard-widening-frequent-branch-threshold=1000 -S -passes='require<branch-prob>,guard-widening' < %s | FileCheck %s
+
+declare void @llvm.experimental.guard(i1,...)
+declare void @foo()
+declare void @bar()
+
+; Check that we don't widen without branch probability.
+define void @test_01(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_01(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 [[COND_1:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  ret void
+}
+
+; Check that we don't widen with branch probability below threshold.
+define void @test_02(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_02(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 [[COND_1:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !0
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !0
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  ret void
+}
+
+; Check that we widen conditions of explicit branches into dominating guards
+; when the probability is high enough.
+define void @test_03(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_03(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  ret void
+}
+
+; Similar to test_03, but the likely taken branch is the false branch.
+define void @test_03_not_taken(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_03_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  ret void
+}
+
+; Widen loop-invariant condition into the guard in preheader.
+define void @test_04(i1 %cond_0, i1 %cond_1, i32 %n) {
+; CHECK-LABEL: @test_04(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  %iv.next = add i32 %iv, 1
+  %cond = icmp slt i32 %iv.next, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Similar to test_04, but the likely taken branch is the false branch.
+define void @test_04_not_taken(i1 %cond_0, i1 %cond_1, i32 %n) {
+; CHECK-LABEL: @test_04_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  %iv.next = add i32 %iv, 1
+  %cond = icmp slt i32 %iv.next, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Widen loop-invariant condition into the guard in the same loop.
+define void @test_05(i1 %cond_0, i1 %cond_1, i32 %n) {
+; CHECK-LABEL: @test_05(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  %iv.next = add i32 %iv, 1
+  %cond = icmp slt i32 %iv.next, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Similar to test_05, but the likely taken branch is the false branch.
+define void @test_05_not_taken(i1 %cond_0, i1 %cond_1, i32 %n) {
+; CHECK-LABEL: @test_05_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[MERGE:%.*]] ]
+; CHECK-NEXT:    [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %merge ]
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  call void @bar()
+  br label %merge
+
+merge:
+  %iv.next = add i32 %iv, 1
+  %cond = icmp slt i32 %iv.next, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Some of checks are frequently taken and some are not, make sure that we only
+; widen frequent ones.
+define void @test_06(i1 %cond_0, i1 %cond_1, i1 %cond_2, i1 %cond_3, i1 %cond_4, i32 %n) {
+; CHECK-LABEL: @test_06(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_4:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT:    br i1 [[COND_1:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]], !prof !3
+; CHECK:       if.true_1:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE_1:%.*]]
+; CHECK:       if.false_1:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE_1]]
+; CHECK:       merge_1:
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]], !prof !1
+; CHECK:       if.true_2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE_2:%.*]]
+; CHECK:       if.false_2:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE_2]]
+; CHECK:       merge_2:
+; CHECK-NEXT:    br i1 [[COND_3:%.*]], label [[IF_TRUE_3:%.*]], label [[IF_FALSE_3:%.*]], !prof !3
+; CHECK:       if.true_3:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE_3:%.*]]
+; CHECK:       if.false_3:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE_3]]
+; CHECK:       merge_3:
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE_4:%.*]], label [[IF_FALSE_4:%.*]], !prof !1
+; CHECK:       if.true_4:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BACKEDGE]]
+; CHECK:       if.false_4:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[BACKEDGE]]
+; CHECK:       backedge:
+; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
+  br i1 %cond_1, label %if.true_1, label %if.false_1, !prof !2
+
+if.true_1:
+  call void @foo()
+  br label %merge_1
+
+if.false_1:
+  call void @bar()
+  br label %merge_1
+
+merge_1:
+  br i1 %cond_2, label %if.true_2, label %if.false_2, !prof !1
+
+if.true_2:
+  call void @foo()
+  br label %merge_2
+
+if.false_2:
+  call void @bar()
+  br label %merge_2
+
+merge_2:
+  br i1 %cond_3, label %if.true_3, label %if.false_3, !prof !2
+
+if.true_3:
+  call void @foo()
+  br label %merge_3
+
+if.false_3:
+  call void @bar()
+  br label %merge_3
+
+merge_3:
+  br i1 %cond_4, label %if.true_4, label %if.false_4, !prof !1
+
+if.true_4:
+  call void @foo()
+  br label %backedge
+
+if.false_4:
+  call void @bar()
+  br label %backedge
+
+backedge:
+  %iv.next = add i32 %iv, 1
+  %cond = icmp slt i32 %iv.next, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Similar to test_06, but the likely taken branch is the false branch.
+define void @test_06_not_taken(i1 %cond_0, i1 %cond_1, i1 %cond_2, i1 %cond_3, i1 %cond_4, i32 %n) {
+; CHECK-LABEL: @test_06_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVERTED:%.*]] = xor i1 [[COND_2:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
+; CHECK-NEXT:    [[INVERTED1:%.*]] = xor i1 [[COND_4:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK]], [[INVERTED1]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT:    br i1 [[COND_1:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]], !prof !3
+; CHECK:       if.true_1:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE_1:%.*]]
+; CHECK:       if.false_1:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE_1]]
+; CHECK:       merge_1:
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]], !prof !2
+; CHECK:       if.true_2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE_2:%.*]]
+; CHECK:       if.false_2:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE_2]]
+; CHECK:       merge_2:
+; CHECK-NEXT:    br i1 [[COND_3:%.*]], label [[IF_TRUE_3:%.*]], label [[IF_FALSE_3:%.*]], !prof !3
+; CHECK:       if.true_3:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE_3:%.*]]
+; CHECK:       if.false_3:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[MERGE_3]]
+; CHECK:       merge_3:
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE_4:%.*]], label [[IF_FALSE_4:%.*]], !prof !2
+; CHECK:       if.true_4:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BACKEDGE]]
+; CHECK:       if.false_4:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[BACKEDGE]]
+; CHECK:       backedge:
+; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
+  br i1 %cond_1, label %if.true_1, label %if.false_1, !prof !2
+
+if.true_1:
+  call void @foo()
+  br label %merge_1
+
+if.false_1:
+  call void @bar()
+  br label %merge_1
+
+merge_1:
+  br i1 %cond_2, label %if.true_2, label %if.false_2, !prof !3
+
+if.true_2:
+  call void @foo()
+  br label %merge_2
+
+if.false_2:
+  call void @bar()
+  br label %merge_2
+
+merge_2:
+  br i1 %cond_3, label %if.true_3, label %if.false_3, !prof !2
+
+if.true_3:
+  call void @foo()
+  br label %merge_3
+
+if.false_3:
+  call void @bar()
+  br label %merge_3
+
+merge_3:
+  br i1 %cond_4, label %if.true_4, label %if.false_4, !prof !3
+
+if.true_4:
+  call void @foo()
+  br label %backedge
+
+if.false_4:
+  call void @bar()
+  br label %backedge
+
+backedge:
+  %iv.next = add i32 %iv, 1
+  %cond = icmp slt i32 %iv.next, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Check triangle CFG pattern.
+define void @test_07(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_07(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[MERGE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %merge, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+merge:
+  ret void
+}
+
+; Similar to test_07, but the likely taken branch is the false branch.
+define void @test_07_not_taken(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_07_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[MERGE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %merge, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+merge:
+  ret void
+}
+
+define void @test_08(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_08(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret void
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  ret void
+
+merge:
+  ret void
+}
+
+define void @test_08_not_taken(i1 %cond_0, i1 %cond_1) {
+; CHECK-LABEL: @test_08_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVERTED:%.*]] = xor i1 [[COND_1:%.*]], true
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[INVERTED]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret void
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  ret void
+
+merge:
+  ret void
+}
+
+; Check that L >u C0 && L >u C1  ->  L >u max(C0, C1).
+define void @test_09(i32 %L) {
+; CHECK-LABEL: @test_09(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ugt i32 [[L]], 456
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret void
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ugt i32 %L, 123
+  %cond_1 = icmp ugt i32 %L, 456
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  ret void
+
+merge:
+  ret void
+}
+
+; Check that L >u C0 && !(L <=u C1)  ->  L >u max(C0, C1).
+define void @test_09_not_taken(i32 %L) {
+; CHECK-LABEL: @test_09_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ule i32 [[L]], 456
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret void
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ugt i32 %L, 123
+  %cond_1 = icmp ule i32 %L, 456
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  ret void
+
+merge:
+  ret void
+}
+
+; Check that a profitable transform is preferred over non-profitable.
+define void @test_10(i32 %L, i1 %irrelevant_cond, i1 %infinite_loop_cond) {
+; CHECK-LABEL: @test_10(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ugt i32 [[L]], 456
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IRRELEVANT_COND:%.*]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 [[INFINITE_LOOP_COND:%.*]], label [[LOOP]], label [[AFTER_LOOP:%.*]]
+; CHECK:       after_loop:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !1
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ugt i32 %L, 123
+  %cond_1 = icmp ugt i32 %L, 456
+  br label %loop
+
+loop:
+  call void(i1, ...) @llvm.experimental.guard(i1 %irrelevant_cond) [ "deopt"() ]
+  br i1 %infinite_loop_cond, label %loop, label %after_loop
+
+after_loop:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !1
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  ret void
+}
+
+; Check that a profitable transform is preferred over non-profitable.
+
+define void @test_10_not_taken(i32 %L, i1 %irrelevant_cond, i1 %infinite_loop_cond) {
+; CHECK-LABEL: @test_10_not_taken(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_0:%.*]] = icmp ugt i32 [[L:%.*]], 123
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ule i32 [[L]], 456
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IRRELEVANT_COND:%.*]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 [[INFINITE_LOOP_COND:%.*]], label [[LOOP]], label [[AFTER_LOOP:%.*]]
+; CHECK:       after_loop:
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp uge i32 [[L]], 457
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    br i1 false, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]], !prof !2
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond_0 = icmp ugt i32 %L, 123
+  %cond_1 = icmp ule i32 %L, 456
+  br label %loop
+
+loop:
+  call void(i1, ...) @llvm.experimental.guard(i1 %irrelevant_cond) [ "deopt"() ]
+  br i1 %infinite_loop_cond, label %loop, label %after_loop
+
+after_loop:
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 %cond_1, label %if.true, label %if.false, !prof !3
+
+if.true:
+  call void @foo()
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  ret void
+}
+
+!0 = !{!"branch_weights", i32 998, i32 1}
+!1 = !{!"branch_weights", i32 999, i32 1}
+!2 = !{!"branch_weights", i32 500, i32 500}
+!3 = !{!"branch_weights", i32 1, i32 999}

Added: llvm/trunk/test/Transforms/HotColdSplit/X86/do-not-split.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/X86/do-not-split.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/X86/do-not-split.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/X86/do-not-split.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,204 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=2 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; Check that these functions are not split. Outlined functions are called from a
+; basic block named codeRepl.
+
+; The cold region is too small to split.
+; CHECK-LABEL: @foo
+; CHECK-NOT: foo.cold.1
+define void @foo() {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  unreachable
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; The cold region is still too small to split.
+; CHECK-LABEL: @bar
+; CHECK-NOT: bar.cold.1
+define void @bar() {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; Make sure we don't try to outline the entire function.
+; CHECK-LABEL: @fun
+; CHECK-NOT: fun.cold.1
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  br label %if.end
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; Do not split `noinline` functions.
+; CHECK-LABEL: @noinline_func
+; CHECK-NOT: noinline_func.cold.1
+define void @noinline_func() noinline {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  br label %if.end
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; Do not split `alwaysinline` functions.
+; CHECK-LABEL: @alwaysinline_func
+; CHECK-NOT: alwaysinline_func.cold.1
+define void @alwaysinline_func() alwaysinline {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  br label %if.end
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; Don't outline infinite loops.
+; CHECK-LABEL: @infinite_loop
+; CHECK-NOT: infinite_loop.cold.1
+define void @infinite_loop() {
+entry:
+  br label %loop
+
+loop:
+  call void @sink()
+  br label %loop
+}
+
+; Don't count debug intrinsics towards the outlining threshold.
+; CHECK-LABEL: @dont_count_debug_intrinsics
+; CHECK-NOT: dont_count_debug_intrinsics.cold.1
+define void @dont_count_debug_intrinsics(i32 %arg1) !dbg !6 {
+entry:
+  %var = add i32 0, 0, !dbg !11
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  ret void
+
+if.end:                                           ; preds = %entry
+  call void @llvm.dbg.value(metadata i32 %arg1, metadata !9, metadata !DIExpression()), !dbg !11
+  call void @llvm.dbg.value(metadata i32 %arg1, metadata !9, metadata !DIExpression()), !dbg !11
+  call void @sink()
+  ret void
+}
+
+; CHECK-LABEL: @sanitize_address
+; CHECK-NOT: sanitize_address.cold.1
+define void @sanitize_address() sanitize_address {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; CHECK-LABEL: @sanitize_hwaddress
+; CHECK-NOT: sanitize_hwaddress.cold.1
+define void @sanitize_hwaddress() sanitize_hwaddress {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; CHECK-LABEL: @sanitize_thread
+; CHECK-NOT: sanitize_thread.cold.1
+define void @sanitize_thread() sanitize_thread {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+; CHECK-LABEL: @sanitize_memory
+; CHECK-NOT: sanitize_memory.cold.1
+define void @sanitize_memory() sanitize_memory {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sink()
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+declare void @llvm.trap() cold noreturn
+
+; CHECK-LABEL: @nosanitize_call
+; CHECK-NOT: nosanitize_call.cold.1
+define void @nosanitize_call() sanitize_memory {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @llvm.trap(), !nosanitize !2
+  unreachable
+
+if.end:                                           ; preds = %entry
+  ret void
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+declare void @sink() cold
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!3, !4}
+!llvm.module.flags = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "<stdin>", directory: "/")
+!2 = !{}
+!3 = !{i32 7}
+!4 = !{i32 1}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = distinct !DISubprogram(name: "dont_count_debug_intrinsics", linkageName: "dont_count_debug_intrinsics", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
+!7 = !DISubroutineType(types: !2)
+!8 = !{!9}
+!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
+!11 = !DILocation(line: 1, column: 1, scope: !6)

Added: llvm/trunk/test/Transforms/HotColdSplit/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/X86/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,3 @@
+if not 'X86' in config.root.targets:
+    config.unsupported = True
+

Added: llvm/trunk/test/Transforms/HotColdSplit/addr-taken.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/addr-taken.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/addr-taken.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/addr-taken.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=-1 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK: define {{.*}} @foo{{.*}}#[[outlined_func_attr:[0-9]+]]
+define void @foo() noreturn cold {
+  unreachable
+}
+
+; CHECK: define {{.*}} @bar.cold.1{{.*}}#[[outlined_func_attr]]
+define void @bar() {
+  br i1 undef, label %normal, label %exit
+
+normal:
+  unreachable
+
+exit:
+  ret void
+}
+
+ at take_addr_of_foo = global void ()* @foo
+ at take_addr_of_bar = global void ()* @bar
+
+; CHECK: attributes #[[outlined_func_attr]] = {
+; CHECK-SAME: cold
+; CHECK-SAME: minsize

Added: llvm/trunk/test/Transforms/HotColdSplit/apply-noreturn-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/apply-noreturn-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/apply-noreturn-bonus.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/apply-noreturn-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; REQUIRES: asserts
+; RUN: opt -hotcoldsplit -debug-only=hotcoldsplit -S < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @sink() cold
+
+define void @foo(i32 %arg) {
+entry:
+  br i1 undef, label %cold1, label %exit
+
+cold1:
+  ; CHECK: Applying bonus for: 4 non-returning terminators
+  call void @sink()
+  br i1 undef, label %cold2, label %cold3
+
+cold2:
+  br label %cold4
+
+cold3:
+  br label %cold4
+
+cold4:
+  unreachable
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-inputs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-inputs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-inputs.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-inputs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; REQUIRES: asserts
+; RUN: opt -hotcoldsplit -debug-only=hotcoldsplit -S < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @sink(i32*, i32, i32) cold
+
+ at g = global i32 0
+
+define void @foo(i32 %arg) {
+  %local = load i32, i32* @g
+  br i1 undef, label %cold, label %exit
+
+cold:
+  ; CHECK: Applying penalty for: 2 inputs
+  call void @sink(i32* @g, i32 %arg, i32 %local)
+  ret void
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-outputs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-outputs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-outputs.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/apply-penalty-for-outputs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; REQUIRES: asserts
+; RUN: opt -hotcoldsplit -debug-only=hotcoldsplit -S < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @sink() cold
+
+ at g = global i32 0
+
+define i32 @foo(i32 %arg) {
+entry:
+  br i1 undef, label %cold, label %exit
+
+cold:
+  ; CHECK: Applying penalty for: 1 output
+  ; CHECK: Applying penalty for: 1 non-region successors
+  %local = load i32, i32* @g
+  call void @sink()
+  br label %exit
+
+exit:
+  %p = phi i32 [ %local, %cold ], [ 0, %entry ]
+  ret i32 %p
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/apply-successor-penalty.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/apply-successor-penalty.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/apply-successor-penalty.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/apply-successor-penalty.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; REQUIRES: asserts
+; RUN: opt -hotcoldsplit -debug-only=hotcoldsplit -S < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare void @sink() cold
+
+; CHECK-LABEL: Outlining in one_non_region_successor
+define void @one_non_region_successor(i32 %arg) {
+entry:
+  br i1 undef, label %cold1, label %exit
+
+cold1:
+  ; CHECK: Applying penalty for: 1 non-region successor
+  call void @sink()
+  br i1 undef, label %cold2, label %cold3
+
+cold2:
+  br i1 undef, label %cold4, label %exit
+
+cold3:
+  br i1 undef, label %cold4, label %exit
+
+cold4:
+  unreachable
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: Outlining in two_non_region_successor
+define void @two_non_region_successors(i32 %arg) {
+entry:
+  br i1 undef, label %cold1, label %exit1
+
+cold1:
+  ; CHECK: Applying penalty for: 2 non-region successors
+  call void @sink()
+  br i1 undef, label %cold2, label %cold3
+
+cold2:
+  br i1 undef, label %cold4, label %exit1
+
+cold3:
+  br i1 undef, label %cold4, label %exit2
+
+cold4:
+  unreachable
+
+exit1:
+  br label %exit2
+
+exit2:
+  ret void
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/coldentrycount.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/coldentrycount.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/coldentrycount.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/coldentrycount.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; Test to ensure that split cold function gets 0 entry count profile
+; metadata when compiling with pgo.
+
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: @fun
+; CHECK: call void @fun.cold.1
+define void @fun() !prof !14 {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ret void
+
+if.else:
+  call void @sink()
+  ret void
+}
+
+declare void @sink() cold
+
+; CHECK: define {{.*}} @fun.cold.1{{.*}} ![[PROF:[0-9]+]]
+; CHECK: ![[PROF]] = !{!"function_entry_count", i64 0}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 10000}
+!4 = !{!"MaxCount", i64 10}
+!5 = !{!"MaxInternalCount", i64 1}
+!6 = !{!"MaxFunctionCount", i64 1000}
+!7 = !{!"NumCounts", i64 3}
+!8 = !{!"NumFunctions", i64 3}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11, !12, !13}
+!11 = !{i32 10000, i64 100, i32 1}
+!12 = !{i32 999000, i64 100, i32 1}
+!13 = !{i32 999999, i64 1, i32 2}
+!14 = !{!"function_entry_count", i64 100}

Added: llvm/trunk/test/Transforms/HotColdSplit/delete-use-without-def-dbg-val.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/delete-use-without-def-dbg-val.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/delete-use-without-def-dbg-val.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/delete-use-without-def-dbg-val.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK-NOT: call {{.*}}llvm.dbg.value
+
+; CHECK-LABEL: define {{.*}}@foo.cold
+; CHECK-NOT: call {{.*}}llvm.dbg.value
+
+define void @foo() !dbg !6 {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %cleanup
+
+if.end:                                           ; preds = %entry
+  ; We expect this block to be outlined. That kills the definition of %var.
+  %var = add i32 0, 0, !dbg !11
+  call void @sink()
+  br label %cleanup
+
+cleanup:
+  ; This dbg.value should be deleted after outlining, otherwise the verifier
+  ; complains about function-local metadata being used outside of a function.
+  call void @llvm.dbg.value(metadata i32 %var, metadata !9, metadata !DIExpression()), !dbg !11
+  ret void
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+declare void @sink() cold
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!3, !4}
+!llvm.module.flags = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "<stdin>", directory: "/")
+!2 = !{}
+!3 = !{i32 7}
+!4 = !{i32 1}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
+!7 = !DISubroutineType(types: !2)
+!8 = !{!9}
+!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
+!11 = !DILocation(line: 1, column: 1, scope: !6)

Added: llvm/trunk/test/Transforms/HotColdSplit/duplicate-phi-preds-crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/duplicate-phi-preds-crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/duplicate-phi-preds-crash.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/duplicate-phi-preds-crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+declare void @sideeffect(i64)
+
+declare i8* @realloc(i8* %ptr, i64 %size)
+
+declare void @free(i8* %ptr)
+
+declare void @sink() cold
+
+; CHECK-LABEL: define {{.*}}@realloc2(
+; CHECK: call {{.*}}@sideeffect(
+; CHECK: call {{.*}}@realloc(
+; CHECK-LABEL: codeRepl:
+; CHECK: call {{.*}}@realloc2.cold.1(i64 %size, i8* %ptr, i8** %retval.0.ce.loc)
+; CHECK-LABEL: cleanup:
+; CHECK-NEXT: phi i8* [ null, %if.then ], [ %call, %if.end ], [ %retval.0.ce.reload, %codeRepl ]
+define i8* @realloc2(i8* %ptr, i64 %size) {
+entry:
+  %0 = add i64 %size, -1
+  %1 = icmp ugt i64 %0, 184549375
+  br i1 %1, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @sideeffect(i64 %size)
+  br label %cleanup
+
+if.end:                                           ; preds = %entry
+  %call = call i8* @realloc(i8* %ptr, i64 %size)
+  %tobool1 = icmp eq i8* %call, null
+  br i1 %tobool1, label %if.then2, label %cleanup
+
+if.then2:                                         ; preds = %if.end
+  call void @sideeffect(i64 %size)
+  call void @sink()
+  %tobool3 = icmp eq i8* %ptr, null
+  br i1 %tobool3, label %cleanup, label %if.then4
+
+if.then4:                                         ; preds = %if.then2
+  call void @free(i8* %ptr)
+  br label %cleanup
+
+cleanup:                                          ; preds = %if.end, %if.then4, %if.then2, %if.then
+  %retval.0 = phi i8* [ null, %if.then ], [ null, %if.then2 ], [ null, %if.then4 ], [ %call, %if.end ]
+  ret i8* %retval.0
+}
+
+; CHECK-LABEL: define {{.*}}@realloc2.cold.1(
+; CHECK: call {{.*}}@sideeffect
+; CHECK: call {{.*}}@sink
+; CHECK: call {{.*}}@free

Added: llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/eh-pads.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,99 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK: landingpad
+; CHECK: sideeffect(i32 2)
+define void @foo(i32 %cond) personality i8 0 {
+entry:
+  invoke void @llvm.donothing() to label %normal unwind label %exception
+
+exception:
+  ; Note: EH pads are not candidates for region entry points.
+  %cleanup = landingpad i8 cleanup
+  br label %continue_exception
+
+continue_exception:
+  call void @sideeffect(i32 0)
+  call void @sink()
+  ret void
+
+normal:
+  call void @sideeffect(i32 2)
+  ret void
+}
+
+; See llvm.org/PR39917. It's currently not safe to outline landingpad
+; instructions.
+;
+; CHECK-LABEL: define {{.*}}@bar(
+; CHECK: landingpad
+define void @bar(i32 %cond) personality i8 0 {
+entry:
+  br i1 undef, label %exit, label %continue
+
+exit:
+  ret void
+
+continue:
+  invoke void @sink() to label %normal unwind label %exception
+
+exception:
+  ; Note: EH pads are not candidates for region entry points.
+  %cleanup = landingpad i8 cleanup
+  br label %trivial-eh-handler
+
+trivial-eh-handler:
+  call void @sideeffect(i32 1)
+  br label %normal
+
+normal:
+  call void @sideeffect(i32 0)
+  ret void
+}
+
+define void @baz() personality i8 0 {
+entry:
+  br i1 undef, label %exit, label %cold1
+
+exit:
+  ret void
+
+cold1:
+  ; The predecessor of a cold invoke may still be extracted (see baz.cold.2).
+  call void @sideeffect(i32 0)
+  br label %cold2
+
+cold2:
+  invoke void @sink() to label %cold3 unwind label %cold4
+
+cold3:
+  ; The successor of a cold invoke may still be extracted (see baz.cold.1).
+  call void @sideeffect(i32 1)
+  ret void
+
+cold4:
+  landingpad i8 cleanup
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK: sideeffect(i32 0)
+; CHECK: sink
+
+; CHECK-LABEL: define {{.*}}@bar.cold.1(
+; CHECK: sideeffect(i32 1)
+
+; CHECK-LABEL: define {{.*}}@baz.cold.1(
+; CHECK: sideeffect(i32 1)
+
+; CHECK-LABEL: define {{.*}}@baz.cold.2(
+; CHECK: sideeffect(i32 0)
+
+declare void @sideeffect(i32)
+
+declare void @sink() cold
+
+declare void @llvm.donothing() nounwind readnone

Added: llvm/trunk/test/Transforms/HotColdSplit/eh-typeid-for.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/eh-typeid-for.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/eh-typeid-for.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/eh-typeid-for.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+; Do not outline calls to @llvm.eh.typeid.for. See llvm.org/PR39545.
+
+ at _ZTIi = external constant i8*
+
+; CHECK-LABEL: @fun
+; CHECK-NOT: call {{.*}}@fun.cold.1
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ret void
+
+if.else:
+  %t = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
+  call void @sink()
+  ret void
+}
+
+declare void @sink() cold
+
+declare i32 @llvm.eh.typeid.for(i8*)

Added: llvm/trunk/test/Transforms/HotColdSplit/forward-dfs-reaches-marked-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/forward-dfs-reaches-marked-block.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/forward-dfs-reaches-marked-block.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/forward-dfs-reaches-marked-block.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@fun
+; CHECK: call {{.*}}@fun.cold.1(
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ; This will be marked by the inverse DFS on sink-predecesors.
+  br label %sink
+
+sink:
+  call void @sink()
+
+  ; Do not allow the forward-DFS on sink-successors to mark the block again.
+  br i1 undef, label %if.then, label %if.then.exit
+
+if.then.exit:
+  ret void
+
+if.else:
+  ret void
+}
+
+declare void @sink() cold

Added: llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s 2>&1 | FileCheck %s
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+declare void @use(i8*)
+
+declare void @cold_use2(i8*, i8*) cold
+
+; CHECK-LABEL: define {{.*}}@foo(
+define void @foo() {
+entry:
+  %local1 = alloca i256
+  %local2 = alloca i256
+  %local1_cast = bitcast i256* %local1 to i8*
+  %local2_cast = bitcast i256* %local2 to i8*
+  br i1 undef, label %normalPath, label %outlinedPath
+
+normalPath:
+  ; These two uses of stack slots are non-overlapping. Based on this alone,
+  ; the stack slots could be merged.
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
+  call void @use(i8* %local1_cast)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local2_cast)
+  call void @use(i8* %local2_cast)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local2_cast)
+  ret void
+
+; CHECK-LABEL: codeRepl:
+; CHECK: [[local1_cast:%.*]] = bitcast i256* %local1 to i8*
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[local1_cast]])
+; CHECK-NEXT: [[local2_cast:%.*]] = bitcast i256* %local2 to i8*
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[local2_cast]])
+; CHECK-NEXT: call i1 @foo.cold.1(i8* %local1_cast, i8* %local2_cast)
+; CHECK-NEXT: br i1
+
+outlinedPath:
+  ; These two uses of stack slots are overlapping. This should prevent
+  ; merging of stack slots. CodeExtractor must replicate the effects of
+  ; these markers in the caller to inhibit stack coloring.
+  %gep1 = getelementptr inbounds i8, i8* %local1_cast, i64 1
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %gep1)
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local2_cast)
+  call void @cold_use2(i8* %local1_cast, i8* %local2_cast)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %gep1)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local2_cast)
+  br i1 undef, label %outlinedPath2, label %outlinedPathExit
+
+outlinedPath2:
+  ; These extra lifetime markers are used to test that we emit only one
+  ; pair of guard markers in the caller per memory object.
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local2_cast)
+  call void @use(i8* %local2_cast)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local2_cast)
+  ret void
+
+outlinedPathExit:
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK-NOT: @llvm.lifetime

Added: llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,182 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s 2>&1 | FileCheck %s
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+declare void @cold_use(i8*) cold
+
+declare void @use(i8*)
+
+; In this CFG, splitting will extract the blocks extract{1,2}. I.e., it will
+; extract a lifetime.start marker, but not the corresponding lifetime.end
+; marker. Make sure that a lifetime.start marker is emitted before the call to
+; the split function, and *only* that marker.
+;
+;            entry
+;          /       \
+;      extract1  no-extract1
+;     (lt.start)    |
+;    /              |
+; extract2          |
+;    \_____         |
+;          \      /
+;            exit
+;          (lt.end)
+;
+; After splitting, we should see:
+;
+;            entry
+;          /       \
+;      codeRepl  no-extract1
+;     (lt.start)   |
+;          \      /
+;            exit
+;          (lt.end)
+define void @only_lifetime_start_is_cold() {
+; CHECK-LABEL: @only_lifetime_start_is_cold(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOCAL1:%.*]] = alloca i256
+; CHECK-NEXT:    [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+; CHECK-NEXT:    br i1 undef, label [[CODEREPL:%.*]], label [[NO_EXTRACT1:%.*]]
+; CHECK:       codeRepl:
+; CHECK-NEXT:    [[LT_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]])
+; CHECK-NEXT:    [[TARGETBLOCK:%.*]] = call i1 @only_lifetime_start_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
+; CHECK-NEXT:    br i1 [[TARGETBLOCK]], label [[NO_EXTRACT1]], label [[EXIT:%.*]]
+; CHECK:       no-extract1:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  %local1 = alloca i256
+  %local1_cast = bitcast i256* %local1 to i8*
+  br i1 undef, label %extract1, label %no-extract1
+
+extract1:
+  ; lt.start
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
+  call void @cold_use(i8* %local1_cast)
+  br i1 undef, label %extract2, label %no-extract1
+
+extract2:
+  br label %exit
+
+no-extract1:
+  br label %exit
+
+exit:
+  ; lt.end
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
+  ret void
+}
+
+; In this CFG, splitting will extract the block extract1. I.e., it will extract
+; a lifetime.end marker, but not the corresponding lifetime.start marker. Do
+; not emit a lifetime.end marker after the call to the split function.
+;
+;            entry
+;         (lt.start)
+;        /          \
+;   no-extract1  extract1
+;    (lt.end)    (lt.end)
+;        \         /
+;            exit
+;
+; After splitting, we should see:
+;
+;            entry
+;         (lt.start)
+;        /          \
+;   no-extract1  codeRepl
+;    (lt.end)
+;        \         /
+;            exit
+define void @only_lifetime_end_is_cold() {
+; CHECK-LABEL: @only_lifetime_end_is_cold(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOCAL1:%.*]] = alloca i256
+; CHECK-NEXT:    [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+; CHECK-NEXT:    br i1 undef, label [[NO_EXTRACT1:%.*]], label [[CODEREPL:%.*]]
+; CHECK:       no-extract1:
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       codeRepl:
+; CHECK-NEXT:    call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  ; lt.start
+  %local1 = alloca i256
+  %local1_cast = bitcast i256* %local1 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
+  br i1 undef, label %no-extract1, label %extract1
+
+no-extract1:
+  ; lt.end
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
+  br label %exit
+
+extract1:
+  ; lt.end
+  call void @cold_use(i8* %local1_cast)
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
+  br label %exit
+
+exit:
+  ret void
+}
+
+; In this CFG, splitting will extract the blocks extract{1,2,3}. Lifting the
+; lifetime.end marker would be a miscompile.
+define void @do_not_lift_lifetime_end() {
+; CHECK-LABEL: @do_not_lift_lifetime_end(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOCAL1:%.*]] = alloca i256
+; CHECK-NEXT:    [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+; CHECK-NEXT:    br label [[HEADER:%.*]]
+; CHECK:       header:
+; CHECK-NEXT:    call void @use(i8* [[LOCAL1_CAST]])
+; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[CODEREPL:%.*]]
+; CHECK:       codeRepl:
+; CHECK-NEXT:    [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) #3
+; CHECK-NEXT:    br i1 [[TARGETBLOCK]], label [[HEADER]], label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  ; lt.start
+  %local1 = alloca i256
+  %local1_cast = bitcast i256* %local1 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
+  br label %header
+
+header:
+  ; If the lifetime.end marker is lifted, this use becomes dead the second time
+  ; the header block is executed.
+  call void @use(i8* %local1_cast)
+  br i1 undef, label %exit, label %extract1
+
+extract1:
+  call void @cold_use(i8* %local1_cast)
+  br i1 undef, label %extract2, label %extract3
+
+extract2:
+  ; Backedge.
+  br label %header
+
+extract3:
+  ; lt.end
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
+  br label %exit
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/mark-the-whole-func-cold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/mark-the-whole-func-cold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/mark-the-whole-func-cold.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/mark-the-whole-func-cold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+; Source:
+; 
+; extern __attribute__((cold)) void sink();
+; extern void sideeffect(int);
+; void foo(int cond1, int cond2) {
+;     if (cond1) {
+;         if (cond2) {
+;             sideeffect(0);
+;         } else {
+;             sideeffect(1);
+;         }
+;         sink();
+;     } else {
+;         sideeffect(2);
+;     }
+;     sink();
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK: define {{.*}}@_Z3fooii{{.*}}#[[outlined_func_attr:[0-9]+]]
+; CHECK-NOT: _Z3fooii.cold
+; CHECK: attributes #[[outlined_func_attr]] = { {{.*}}minsize
+define void @_Z3fooii(i32, i32) {
+  %3 = alloca i32, align 4
+  %4 = alloca i32, align 4
+  store i32 %0, i32* %3, align 4
+  store i32 %1, i32* %4, align 4
+  %5 = load i32, i32* %3, align 4
+  %6 = icmp ne i32 %5, 0
+  br i1 %6, label %7, label %13
+
+; <label>:7:                                      ; preds = %2
+  %8 = load i32, i32* %4, align 4
+  %9 = icmp ne i32 %8, 0
+  br i1 %9, label %10, label %11
+
+; <label>:10:                                     ; preds = %7
+  call void @_Z10sideeffecti(i32 0)
+  br label %12
+
+; <label>:11:                                     ; preds = %7
+  call void @_Z10sideeffecti(i32 1)
+  br label %12
+
+; <label>:12:                                     ; preds = %11, %10
+  call void @_Z4sinkv() #3
+  br label %14
+
+; <label>:13:                                     ; preds = %2
+  call void @_Z10sideeffecti(i32 2)
+  br label %14
+
+; <label>:14:                                     ; preds = %13, %12
+  call void @_Z4sinkv() #3
+  ret void
+}
+
+declare void @_Z10sideeffecti(i32)
+
+declare void @_Z4sinkv() cold

Added: llvm/trunk/test/Transforms/HotColdSplit/minsize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/minsize.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/minsize.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/minsize.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: @fun
+; CHECK: call void @fun.cold.1
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ret void
+
+if.else:
+  call void @sink()
+  ret void
+}
+
+; CHECK: define {{.*}} @foo{{.*}}#[[outlined_func_attr:[0-9]+]]
+define void @foo() cold {
+  ret void
+}
+
+declare void @sink() cold
+
+; CHECK: define {{.*}} @fun.cold.1{{.*}}#[[outlined_func_attr]]
+
+; CHECK: attributes #[[outlined_func_attr]] = {
+; CHECK-SAME: cold
+; CHECK-SAME: minsize

Added: llvm/trunk/test/Transforms/HotColdSplit/multiple-exits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/multiple-exits.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/multiple-exits.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/multiple-exits.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,72 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+; Source:
+;
+; extern void sideeffect(int);
+; extern void __attribute__((cold)) sink();
+; void foo(int cond) {
+;   if (cond) { //< Start outlining here.
+;     sink();
+;     if (cond > 10)
+;       goto exit1;
+;     else
+;       goto exit2;
+;   }
+; exit1:
+;   sideeffect(1);
+;   return;
+; exit2:
+;   sideeffect(2);
+;   return;
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK: br i1 {{.*}}, label %exit1, label %codeRepl
+; CHECK-LABEL: codeRepl:
+; CHECK: [[targetBlock:%.*]] = call i1 @foo.cold.1(
+; CHECK-NEXT: br i1 [[targetBlock]], label %exit1, label %[[return:.*]]
+; CHECK-LABEL: exit1:
+; CHECK: call {{.*}}@sideeffect(i32 1)
+; CHECK: [[return]]:
+; CHECK-NEXT: ret void
+define void @foo(i32 %cond) {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %exit1, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void (...) @sink()
+  %cmp = icmp sgt i32 %cond, 10
+  br i1 %cmp, label %exit1, label %exit2
+
+exit1:                                            ; preds = %entry, %if.then
+  call void @sideeffect(i32 1)
+  br label %return
+
+exit2:                                            ; preds = %if.then
+  call void @sideeffect(i32 2)
+  br label %return
+
+return:                                           ; preds = %exit2, %exit1
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK: br
+; CHECK: [[exit1Stub:.*]]:
+; CHECK-NEXT: ret i1 true
+; CHECK: [[returnStub:.*]]:
+; CHECK-NEXT: ret i1 false
+; CHECK: call {{.*}}@sink
+; CHECK-NEXT: [[cmp:%.*]] = icmp
+; CHECK-NEXT: br i1 [[cmp]], label %[[exit1Stub]], label %exit2
+; CHECK-LABEL: exit2:
+; CHECK-NEXT: call {{.*}}@sideeffect(i32 2)
+; CHECK-NEXT: br label %[[returnStub]]
+
+declare void @sink(...) cold
+
+declare void @sideeffect(i32)

Added: llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/noreturn.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+%struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t }
+%struct.__sigset_t = type { [16 x i64] }
+
+; Don't outline noreturn calls which aren't explicitly marked cold.
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK-NOT: foo.cold.1
+define void @foo(i32, %struct.__jmp_buf_tag*) {
+  %3 = icmp eq i32 %0, 0
+  tail call void @_Z10sideeffectv()
+  br i1 %3, label %5, label %4
+
+; <label>:4:                                      ; preds = %2
+  tail call void @longjmp(%struct.__jmp_buf_tag* %1, i32 0)
+  unreachable
+
+; <label>:5:                                      ; preds = %2
+  ret void
+}
+
+; Do outline noreturn calls marked cold.
+
+; CHECK-LABEL: define {{.*}}@bar(
+; CHECK: call {{.*}}@bar.cold.1(
+define void @bar(i32) {
+  %2 = icmp eq i32 %0, 0
+  tail call void @_Z10sideeffectv()
+  br i1 %2, label %sink, label %exit
+
+sink:
+  tail call void @_Z10sideeffectv()
+  call void @llvm.trap()
+  unreachable
+
+exit:
+  ret void
+}
+
+; Do outline noreturn calls preceded by a cold call.
+
+; CHECK-LABEL: define {{.*}}@baz(
+; CHECK: call {{.*}}@baz.cold.1(
+define void @baz(i32, %struct.__jmp_buf_tag*) {
+  %3 = icmp eq i32 %0, 0
+  tail call void @_Z10sideeffectv()
+  br i1 %3, label %5, label %4
+
+; <label>:4:                                      ; preds = %2
+  call void @sink()
+  tail call void @longjmp(%struct.__jmp_buf_tag* %1, i32 0)
+  unreachable
+
+; <label>:5:                                      ; preds = %2
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@bar.cold.1(
+; CHECK: call {{.*}}@llvm.trap(
+
+declare void @sink() cold
+
+declare void @llvm.trap() noreturn cold
+
+declare void @_Z10sideeffectv()
+
+declare void @longjmp(%struct.__jmp_buf_tag*, i32) noreturn nounwind

Added: llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/outline-cold-asm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@fun(
+; CHECK: call {{.*}}@fun.cold.1(
+
+; CHECK-LABEL: define {{.*}}@fun.cold.1(
+; CHECK: asm ""
+
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ret void
+
+if.else:
+  call void asm "", ""()
+  call void @sink()
+  ret void
+}
+
+declare void @sink() cold

Added: llvm/trunk/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=-1 < %s 2>&1 | FileCheck %s
+
+; CHECK-LABEL: define {{.*}}@fun
+; CHECK: call {{.*}}@fun.cold.2(
+; CHECK-NEXT: ret void
+; CHECK: call {{.*}}@fun.cold.1(
+; CHECK-NEXT: ret void
+define void @fun() {
+entry:
+  br i1 undef, label %A.then, label %A.else
+
+A.else:
+  br label %A.then4
+
+A.then4:
+  br i1 undef, label %A.then5, label %A.end
+
+A.then5:
+  br label %A.cleanup
+
+A.end:
+  br label %A.cleanup
+
+A.cleanup:
+  %A.cleanup.dest.slot.0 = phi i32 [ 1, %A.then5 ], [ 0, %A.end ]
+  unreachable
+
+A.then:
+  br i1 undef, label %B.then, label %B.else
+
+B.then:
+  ret void
+
+B.else:
+  br label %B.then4
+
+B.then4:
+  br i1 undef, label %B.then5, label %B.end
+
+B.then5:
+  br label %B.cleanup
+
+B.end:
+  br label %B.cleanup
+
+B.cleanup:
+  %B.cleanup.dest.slot.0 = phi i32 [ 1, %B.then5 ], [ 0, %B.end ]
+  unreachable
+}
+
+; CHECK-LABEL: define {{.*}}@fun.cold.1(
+; CHECK: %B.cleanup.dest.slot.0 = phi i32 [ 1, %B.then5 ], [ 0, %B.end ]
+; CHECK-NEXT: unreachable
+
+; CHECK-LABEL: define {{.*}}@fun.cold.2(
+; CHECK: %A.cleanup.dest.slot.0 = phi i32 [ 1, %A.then5 ], [ 0, %A.end ]
+; CHECK-NEXT: unreachable

Added: llvm/trunk/test/Transforms/HotColdSplit/outline-if-then-else.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/outline-if-then-else.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/outline-if-then-else.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/outline-if-then-else.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+; Source:
+;
+; extern void sideeffect(int);
+; extern void __attribute__((cold)) sink();
+; void foo(int cond) {
+;   if (cond) { //< Start outlining here.
+;     if (cond > 10)
+;       sideeffect(0);
+;     else
+;       sideeffect(1);
+;     sink();
+;   }
+;   sideeffect(2);
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK: br i1 {{.*}}, label %codeRepl, label %if.end2
+; CHECK-LABEL: codeRepl:
+; CHECK-NEXT: call void @foo.cold.1
+; CHECK-LABEL: if.end2:
+; CHECK: call void @sideeffect(i32 2)
+define void @foo(i32 %cond) {
+entry:
+  %cond.addr = alloca i32
+  store i32 %cond, i32* %cond.addr
+  %0 = load i32, i32* %cond.addr
+  %tobool = icmp ne i32 %0, 0
+  br i1 %tobool, label %if.then, label %if.end2
+
+if.then:                                          ; preds = %entry
+  %1 = load i32, i32* %cond.addr
+  %cmp = icmp sgt i32 %1, 10
+  br i1 %cmp, label %if.then1, label %if.else
+
+if.then1:                                         ; preds = %if.then
+  call void @sideeffect(i32 0)
+  br label %if.end
+
+if.else:                                          ; preds = %if.then
+  call void @sideeffect(i32 1)
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then1
+  call void (...) @sink()
+  ret void
+
+if.end2:                                          ; preds = %entry
+  call void @sideeffect(i32 2)
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1
+; CHECK: call {{.*}}@sideeffect
+; CHECK: call {{.*}}@sideeffect
+; CHECK: call {{.*}}@sink
+
+declare void @sideeffect(i32)
+
+declare void @sink(...) cold

Added: llvm/trunk/test/Transforms/HotColdSplit/outline-multiple-entry-region.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/outline-multiple-entry-region.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/outline-multiple-entry-region.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/outline-multiple-entry-region.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+; Source:
+;
+; extern __attribute__((cold)) void sink();
+; extern void sideeffect(int);
+; void foo(int cond1, int cond2) {
+;     while (true) {
+;         if (cond1) {
+;             sideeffect(0); // This is cold (it reaches sink()).
+;             break;
+;         }
+;         if (cond2) {
+;             sideeffect(1); // This is cold (it reaches sink()).
+;             break;
+;         }
+;         sideeffect(2);
+;         return;
+;     }
+;     sink();
+;     sideeffect(3);
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@_Z3fooii.cold.1
+; CHECK: call void @_Z10sideeffecti(i32 1)
+
+; CHECK-LABEL: define {{.*}}@_Z3fooii.cold.2
+; CHECK: call void @_Z10sideeffecti(i32 0)
+
+; CHECK-LABEL: define {{.*}}@_Z3fooii.cold.3
+; CHECK: call void @_Z4sinkv
+; CHECK: call void @_Z10sideeffecti(i32 3)
+
+define void @_Z3fooii(i32, i32) {
+  %3 = alloca i32, align 4
+  %4 = alloca i32, align 4
+  store i32 %0, i32* %3, align 4
+  store i32 %1, i32* %4, align 4
+  br label %5
+
+; <label>:5:                                      ; preds = %2
+  %6 = load i32, i32* %3, align 4
+  %7 = icmp ne i32 %6, 0
+  br i1 %7, label %8, label %9
+
+; <label>:8:                                      ; preds = %5
+  call void @_Z10sideeffecti(i32 0)
+  br label %14
+
+; <label>:9:                                      ; preds = %5
+  %10 = load i32, i32* %4, align 4
+  %11 = icmp ne i32 %10, 0
+  br i1 %11, label %12, label %13
+
+; <label>:12:                                     ; preds = %9
+  call void @_Z10sideeffecti(i32 1)
+  br label %14
+
+; <label>:13:                                     ; preds = %9
+  call void @_Z10sideeffecti(i32 2)
+  br label %15
+
+; <label>:14:                                     ; preds = %12, %8
+  call void @_Z4sinkv() #3
+  call void @_Z10sideeffecti(i32 3)
+  br label %15
+
+; <label>:15:                                     ; preds = %14, %13
+  ret void
+}
+
+declare void @_Z10sideeffecti(i32)
+
+declare void @_Z4sinkv() cold

Added: llvm/trunk/test/Transforms/HotColdSplit/outline-while-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/outline-while-loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/outline-while-loop.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/outline-while-loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,116 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+; Source:
+;
+; extern void sideeffect(int);
+; extern void __attribute__((cold)) sink();
+; void foo(int cond) {
+;   if (cond) { //< Start outlining here.
+;     while (cond > 10) {
+;       --cond;
+;       sideeffect(0);
+;     }
+;     sink();
+;   }
+;   sideeffect(1);
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK: br i1 {{.*}}, label %if.end, label %codeRepl
+; CHECK-LABEL: codeRepl:
+; CHECK-NEXT: call void @foo.cold.1
+; CHECK-LABEL: if.end:
+; CHECK: call void @sideeffect(i32 1)
+define void @foo(i32 %cond) {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end, label %while.cond.preheader
+
+while.cond.preheader:                             ; preds = %entry
+  %cmp3 = icmp sgt i32 %cond, 10
+  br i1 %cmp3, label %while.body.preheader, label %while.end
+
+while.body.preheader:                             ; preds = %while.cond.preheader
+  br label %while.body
+
+while.body:                                       ; preds = %while.body.preheader, %while.body
+  %cond.addr.04 = phi i32 [ %dec, %while.body ], [ %cond, %while.body.preheader ]
+  %dec = add nsw i32 %cond.addr.04, -1
+  tail call void @sideeffect(i32 0) #3
+  %cmp = icmp sgt i32 %dec, 10
+  br i1 %cmp, label %while.body, label %while.end.loopexit
+
+while.end.loopexit:                               ; preds = %while.body
+  br label %while.end
+
+while.end:                                        ; preds = %while.end.loopexit, %while.cond.preheader
+  tail call void (...) @sink()
+  ret void
+
+if.end:                                           ; preds = %entry
+  tail call void @sideeffect(i32 1)
+  ret void
+}
+
+; This is the same as @foo, but the while loop comes after the sink block.
+; CHECK-LABEL: define {{.*}}@while_loop_after_sink(
+; CHECK: br i1 {{.*}}, label %if.end, label %codeRepl
+; CHECK-LABEL: codeRepl:
+; CHECK-NEXT: call void @while_loop_after_sink.cold.1
+; CHECK-LABEL: if.end:
+; CHECK: call void @sideeffect(i32 1)
+define void @while_loop_after_sink(i32 %cond) {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end, label %sink
+
+sink:
+  tail call void (...) @sink()
+  br label %while.cond.preheader
+
+while.cond.preheader:
+  %cmp3 = icmp sgt i32 %cond, 10
+  br i1 %cmp3, label %while.body.preheader, label %while.end
+
+while.body.preheader:                             ; preds = %while.cond.preheader
+  br label %while.body
+
+while.body:                                       ; preds = %while.body.preheader, %while.body
+  %cond.addr.04 = phi i32 [ %dec, %while.body ], [ %cond, %while.body.preheader ]
+  %dec = add nsw i32 %cond.addr.04, -1
+  tail call void @sideeffect(i32 0) #3
+  %cmp = icmp sgt i32 %dec, 10
+  br i1 %cmp, label %while.body, label %while.end.loopexit
+
+while.end.loopexit:                               ; preds = %while.body
+  br label %while.end
+
+while.end:                                        ; preds = %while.end.loopexit, %while.cond.preheader
+  ret void
+
+if.end:                                           ; preds = %entry
+  tail call void @sideeffect(i32 1)
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1
+; CHECK: phi i32
+; CHECK-NEXT: add nsw i32
+; CHECK-NEXT: call {{.*}}@sideeffect
+; CHECK-NEXT: icmp
+; CHECK-NEXT: br
+
+; CHECK-LABEL: define {{.*}}@while_loop_after_sink.cold.1
+; CHECK: call {{.*}}@sink
+; CHECK: phi i32
+; CHECK-NEXT: add nsw i32
+; CHECK-NEXT: call {{.*}}@sideeffect
+; CHECK-NEXT: icmp
+; CHECK-NEXT: br
+
+declare void @sideeffect(i32)
+
+declare void @sink(...) cold

Added: llvm/trunk/test/Transforms/HotColdSplit/phi-with-distinct-outlined-values.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/phi-with-distinct-outlined-values.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/phi-with-distinct-outlined-values.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/phi-with-distinct-outlined-values.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo(
+; CHECK: phi i32 [ 0, %entry ], [ %p.ce.reload, %codeRepl ]
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK: call {{.*}}@sink
+; CHECK: %p.ce = phi i32 [ 1, %coldbb ], [ 3, %coldbb2 ]
+; CHECK-NEXT: store i32 %p.ce, i32* %p.ce.out 
+
+define void @foo(i32 %cond) {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end, label %coldbb
+
+coldbb:
+  call void @sink()
+  call void @sideeffect()
+  br i1 undef, label %if.end, label %coldbb2
+
+coldbb2:
+  br label %if.end
+
+if.end:
+  %p = phi i32 [0, %entry], [1, %coldbb], [3, %coldbb2]
+  ret void
+}
+
+declare void @sink() cold
+
+declare void @sideeffect()

Added: llvm/trunk/test/Transforms/HotColdSplit/region-overlap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/region-overlap.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/region-overlap.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/region-overlap.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+; Source:
+;
+; __attribute__((cold)) extern void sink(int);
+; extern void sideeffect(int);
+; void foo(int cond1, int cond2) {
+;     if (cond1) {
+;         if (cond2) { // This is the first cold region we visit.
+;             sideeffect(0);
+;             sink(0);
+;         }
+;
+;         // There's a larger, overlapping cold region here. But we ignore it.
+;         // This could be improved.
+;         sideeffect(1);
+;         sink(1);
+;     }
+; }
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@_Z3fooii
+; CHECK: call {{.*}}@_Z3fooii.cold.1
+; CHECK-NOT: _Z3fooii.cold
+define void @_Z3fooii(i32, i32) {
+  %3 = alloca i32, align 4
+  %4 = alloca i32, align 4
+  store i32 %0, i32* %3, align 4
+  store i32 %1, i32* %4, align 4
+  %5 = load i32, i32* %3, align 4
+  %6 = icmp ne i32 %5, 0
+  br i1 %6, label %7, label %12
+
+; <label>:7:                                      ; preds = %2
+  %8 = load i32, i32* %4, align 4
+  %9 = icmp ne i32 %8, 0
+  br i1 %9, label %10, label %11
+
+; <label>:10:                                     ; preds = %7
+  call void @_Z10sideeffecti(i32 0)
+  call void @_Z4sinki(i32 0) #3
+  br label %11
+
+; <label>:11:                                     ; preds = %10, %7
+  call void @_Z10sideeffecti(i32 1)
+  call void @_Z4sinki(i32 1) #3
+  br label %12
+
+; <label>:12:                                     ; preds = %11, %2
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@_Z3fooii.cold.1
+; CHECK: call void @_Z10sideeffecti(i32 0)
+
+declare void @_Z10sideeffecti(i32)
+
+declare void @_Z4sinki(i32) cold

Added: llvm/trunk/test/Transforms/HotColdSplit/resume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/resume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/resume.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/resume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=-1 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; Consider `resume` to be cold.
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK: call {{.*}}@sink(
+
+declare void @sink() cold
+
+define i32 @foo() personality i8 0 {
+entry:
+  br i1 undef, label %pre-resume-eh, label %normal
+
+pre-resume-eh:
+  call void @sink()
+  br label %resume-eh
+
+resume-eh:
+  resume i32 undef
+
+normal:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=-1 -pass-remarks=hotcoldsplit -S < %s 2>&1 | FileCheck %s
+; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=-1 -pass-remarks=hotcoldsplit -S < %s 2>&1 | FileCheck %s
+
+; Make sure this compiles. This test used to fail with an invalid phi node: the
+; two predecessors were outlined and the SSA representation was invalid.
+
+; CHECK: remark: <unknown>:0:0: fun split cold code into fun.cold.1
+; CHECK-LABEL: @fun
+; CHECK: codeRepl:
+; CHECK-NEXT: call void @fun.cold.1
+
+; CHECK: define {{.*}}@fun.cold.1{{.*}} [[cold_attr:#[0-9]+]]
+; CHECK: attributes [[cold_attr]] = { {{.*}}noreturn
+
+define void @fun() {
+entry:
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  ret void
+
+if.else:
+  br label %if.then4
+
+if.then4:
+  br i1 undef, label %if.then5, label %if.end
+
+if.then5:
+  br label %cleanup
+
+if.end:
+  br label %cleanup
+
+cleanup:
+  %cleanup.dest.slot.0 = phi i32 [ 1, %if.then5 ], [ 0, %if.end ]
+  unreachable
+}

Added: llvm/trunk/test/Transforms/HotColdSplit/split-out-dbg-val-of-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/split-out-dbg-val-of-arg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/split-out-dbg-val-of-arg.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/split-out-dbg-val-of-arg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@foo.cold
+; CHECK-NOT: llvm.dbg.value
+
+define void @foo(i32 %arg1) !dbg !6 {
+entry:
+  %var = add i32 0, 0, !dbg !11
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  ret void
+
+if.end:                                           ; preds = %entry
+  call void @llvm.dbg.value(metadata i32 %arg1, metadata !9, metadata !DIExpression()), !dbg !11
+  call void @sink()
+  ret void
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+declare void @sink() cold
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!3, !4}
+!llvm.module.flags = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "<stdin>", directory: "/")
+!2 = !{}
+!3 = !{i32 7}
+!4 = !{i32 1}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !8)
+!7 = !DISubroutineType(types: !2)
+!8 = !{!9}
+!9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
+!10 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
+!11 = !DILocation(line: 1, column: 1, scope: !6)

Added: llvm/trunk/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt -hotcoldsplit-threshold=0 -hotcoldsplit -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@pluto(
+; CHECK-NEXT: bb:
+; CHECK-NEXT:  %tmp8.ce.loc = alloca i1
+; CHECK-NEXT:  switch i8 undef, label %codeRepl [
+; CHECK-NEXT:    i8 0, label %bb7
+; CHECK-NEXT:    i8 1, label %bb7
+; CHECK-NEXT:  ]
+;
+; CHECK:  codeRepl:
+; CHECK-NEXT:    bitcast
+; CHECK-NEXT:    lifetime.start
+; CHECK-NEXT:    call void @pluto.cold.1(i1* %tmp8.ce.loc)
+; CHECK-NEXT:    %tmp8.ce.reload = load i1, i1* %tmp8.ce.loc
+; CHECK-NEXT:    lifetime.end
+; CHECK-NEXT:    br label %bb7
+;
+; CHECK:  bb7:
+; CHECK:    %tmp8 = phi i1 [ true, %bb ], [ true, %bb ], [ %tmp8.ce.reload, %codeRepl ]
+; CHECK:    ret void
+
+; CHECK-LABEL: define {{.*}}@pluto.cold.1(
+; CHECK: call {{.*}}@sideeffect(i32 1)
+; CHECK: call {{.*}}@sink(
+; CHECK: call {{.*}}@sideeffect(i32 3)
+; CHECK: call {{.*}}@sideeffect(i32 4)
+; CHECK: call {{.*}}@sideeffect(i32 5)
+define void @pluto() {
+bb:
+  switch i8 undef, label %bb1 [
+    i8 0, label %bb7
+    i8 1, label %bb7
+  ]
+
+bb1:                                              ; preds = %bb
+  call void @sideeffect(i32 1)
+  br label %bb2
+
+bb2:                                              ; preds = %bb1
+  call void @sink()
+  br i1 undef, label %bb7, label %bb3
+
+bb3:                                              ; preds = %bb2
+  call void @sideeffect(i32 3)
+  br label %bb4
+
+bb4:                                              ; preds = %bb3
+  call void @sideeffect(i32 4)
+  br i1 undef, label %bb5, label %bb6
+
+bb5:                                              ; preds = %bb4
+  call void @sideeffect(i32 5)
+  br label %bb6
+
+bb6:                                              ; preds = %bb5, %bb4
+  %tmp = phi i1 [ true, %bb5 ], [ false, %bb4 ]
+  call void @sideeffect(i32 6)
+  br label %bb7
+
+bb7:                                              ; preds = %bb6, %bb2, %bb, %bb
+  %tmp8 = phi i1 [ true, %bb ], [ true, %bb ], [ true, %bb2 ], [ %tmp, %bb6 ]
+  ret void
+}
+
+declare void @sink() cold
+
+declare void @sideeffect(i32)

Added: llvm/trunk/test/Transforms/HotColdSplit/succ-block-with-self-edge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/succ-block-with-self-edge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/succ-block-with-self-edge.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/succ-block-with-self-edge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; CHECK-LABEL: define {{.*}}@exit_block_with_same_incoming_vals
+; CHECK: call {{.*}}@exit_block_with_same_incoming_vals.cold.1(
+; CHECK-NOT: br i1 undef
+; CHECK: phi i32 [ 0, %entry ], [ %p.ce.reload, %codeRepl ]
+define void @exit_block_with_same_incoming_vals(i32 %cond) {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end, label %coldbb
+
+coldbb:
+  call void @sink()
+  call void @sideeffect()
+  br i1 undef, label %if.end, label %coldbb2
+
+coldbb2:
+  %p2 = phi i32 [0, %coldbb], [1, %coldbb2]
+  br i1 undef, label %if.end, label %coldbb2
+
+if.end:
+  %p = phi i32 [0, %entry], [1, %coldbb], [1, %coldbb2]
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@exit_block_with_distinct_incoming_vals
+; CHECK: call {{.*}}@exit_block_with_distinct_incoming_vals.cold.1(
+; CHECK-NOT: br i1 undef
+; CHECK: phi i32 [ 0, %entry ], [ %p.ce.reload, %codeRepl ]
+define void @exit_block_with_distinct_incoming_vals(i32 %cond) {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end, label %coldbb
+
+coldbb:
+  call void @sink()
+  call void @sideeffect()
+  br i1 undef, label %if.end, label %coldbb2
+
+coldbb2:
+  %p2 = phi i32 [0, %coldbb], [1, %coldbb2]
+  br i1 undef, label %if.end, label %coldbb2
+
+if.end:
+  %p = phi i32 [0, %entry], [1, %coldbb], [2, %coldbb2]
+  ret void
+}
+
+declare void @sink() cold
+
+declare void @sideeffect()

Added: llvm/trunk/test/Transforms/HotColdSplit/swifterror.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/swifterror.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/swifterror.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/swifterror.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+%swift_error = type {i64, i8}
+
+declare void @sink() cold
+
+; CHECK-LABEL: define {{.*}}@in_arg(
+; CHECK: call void @in_arg.cold.1(%swift_error** swifterror
+define void @in_arg(%swift_error** swifterror %error_ptr_ref) {
+  br i1 undef, label %cold, label %exit
+
+cold:
+  store %swift_error* undef, %swift_error** %error_ptr_ref
+  call void @sink()
+  br label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@in_alloca(
+; CHECK: call void @in_alloca.cold.1(%swift_error** swifterror
+define void @in_alloca() {
+  %err = alloca swifterror %swift_error*
+  br i1 undef, label %cold, label %exit
+
+cold:
+  store %swift_error* undef, %swift_error** %err
+  call void @sink()
+  br label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: define {{.*}}@in_arg.cold.1({{.*}} swifterror
+; CHECK: call {{.*}}@sink
+
+; CHECK-LABEL: define {{.*}}@in_alloca.cold.1({{.*}} swifterror
+; CHECK: call {{.*}}@sink

Added: llvm/trunk/test/Transforms/HotColdSplit/unwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/HotColdSplit/unwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/HotColdSplit/unwind.ll (added)
+++ llvm/trunk/test/Transforms/HotColdSplit/unwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+; Do not split out `resume` instructions.
+
+; CHECK-LABEL: define {{.*}}@foo.cold.1(
+; CHECK: call {{.*}}@sink(
+; CHECK-NOT: resume i32 undef
+
+; CHECK-NOT: noreturn
+
+define i32 @foo() personality i8 0 {
+entry:
+  invoke void @llvm.donothing() to label %normal unwind label %exception
+
+exception:
+  %cleanup = landingpad i32 cleanup
+  br i1 undef, label %normal, label %continue_exception
+
+continue_exception:
+  call void @sideeffect(i32 0)
+  call void @sink()
+  br label %resume-eh
+
+resume-eh:
+  resume i32 undef
+
+normal:
+  br i1 undef, label %continue_exception, label %exit
+
+exit:
+  call void @sideeffect(i32 2)
+  ret i32 0
+}
+
+declare void @sideeffect(i32)
+
+declare void @sink() cold
+
+declare void @llvm.donothing() nounwind readnone

Added: llvm/trunk/test/Transforms/IPConstantProp/2008-06-09-WeakProp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/2008-06-09-WeakProp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/2008-06-09-WeakProp.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/2008-06-09-WeakProp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -ipconstprop -S | grep "ret i32 %r"
+; Should not propagate the result of a weak function.
+; PR2411
+
+define weak i32 @foo() nounwind  {
+entry:
+        ret i32 1
+}
+
+define i32 @main() nounwind  {
+entry:
+        %r = call i32 @foo( ) nounwind
+        ret i32 %r
+}
+

Added: llvm/trunk/test/Transforms/IPConstantProp/2009-09-24-byval-ptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/2009-09-24-byval-ptr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/2009-09-24-byval-ptr.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/2009-09-24-byval-ptr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -ipsccp -S | FileCheck %s
+; Don't constant-propagate byval pointers, since they are not pointers!
+; PR5038
+%struct.MYstr = type { i8, i32 }
+ at mystr = internal global %struct.MYstr zeroinitializer ; <%struct.MYstr*> [#uses=3]
+define internal void @vfu1(%struct.MYstr* byval align 4 %u) nounwind {
+entry:
+  %0 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 1 ; <i32*> [#uses=1]
+  store i32 99, i32* %0, align 4
+; CHECK: %struct.MYstr* %u
+  %1 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 0 ; <i8*> [#uses=1]
+  store i8 97, i8* %1, align 4
+; CHECK: %struct.MYstr* %u
+  br label %return
+
+return:                                           ; preds = %entry
+  ret void
+}
+
+define internal i32 @vfu2(%struct.MYstr* byval align 4 %u) nounwind readonly {
+entry:
+  %0 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 1 ; <i32*> [#uses=1]
+  %1 = load i32, i32* %0
+; CHECK: load i32, i32* getelementptr inbounds (%struct.MYstr, %struct.MYstr* @mystr, i32 0, i32 1)
+  %2 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 0 ; <i8*> [#uses=1]
+  %3 = load i8, i8* %2
+; CHECK: load i8, i8* getelementptr inbounds (%struct.MYstr, %struct.MYstr* @mystr, i32 0, i32 0)
+  %4 = zext i8 %3 to i32
+  %5 = add i32 %4, %1
+  ret i32 %5
+}
+
+define i32 @unions() nounwind {
+entry:
+  call void @vfu1(%struct.MYstr* byval align 4 @mystr) nounwind
+  %result = call i32 @vfu2(%struct.MYstr* byval align 4 @mystr) nounwind
+
+  ret i32 %result
+}
+

Added: llvm/trunk/test/Transforms/IPConstantProp/PR16052.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/PR16052.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/PR16052.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/PR16052.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -S -ipsccp | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i64 @fn2() {
+entry:
+  %conv = sext i32 undef to i64
+  %div = sdiv i64 8, %conv
+  %call2 = call i64 @fn1(i64 %div)
+  ret i64 %call2
+}
+
+; CHECK-DAG: define i64 @fn2(
+; CHECK: %[[CALL:.*]] = call i64 @fn1(i64 undef)
+
+define internal i64 @fn1(i64 %p1) {
+entry:
+  %tobool = icmp ne i64 %p1, 0
+  %cond = select i1 %tobool, i64 %p1, i64 %p1
+  ret i64 %cond
+}
+
+; CHECK-DAG: define internal i64 @fn1(
+; CHECK: %[[SEL:.*]] = select i1 undef, i64 undef, i64 undef
+; CHECK: ret i64 %[[SEL]]

Added: llvm/trunk/test/Transforms/IPConstantProp/PR26044.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/PR26044.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/PR26044.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/PR26044.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,62 @@
+; RUN: opt < %s -S -ipsccp | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @fn2() {
+entry:
+  br label %if.end
+
+for.cond1:                                        ; preds = %if.end, %for.end
+  br i1 undef, label %if.end, label %if.end
+
+if.end:                                           ; preds = %lbl, %for.cond1
+  %e.2 = phi i32* [ undef, %entry ], [ null, %for.cond1 ], [ null, %for.cond1 ]
+  %0 = load i32, i32* %e.2, align 4
+  %call = call i32 @fn1(i32 %0)
+  br label %for.cond1
+}
+
+define internal i32 @fn1(i32 %p1) {
+entry:
+  %tobool = icmp ne i32 %p1, 0
+  %cond = select i1 %tobool, i32 %p1, i32 %p1
+  ret i32 %cond
+}
+
+define void @fn_no_null_opt() #0 {
+entry:
+  br label %if.end
+
+for.cond1:                                        ; preds = %if.end, %for.end
+  br i1 undef, label %if.end, label %if.end
+
+if.end:                                           ; preds = %lbl, %for.cond1
+  %e.2 = phi i32* [ undef, %entry ], [ null, %for.cond1 ], [ null, %for.cond1 ]
+  %0 = load i32, i32* %e.2, align 4
+  %call = call i32 @fn0(i32 %0)
+  br label %for.cond1
+}
+
+define internal i32 @fn0(i32 %p1) {
+entry:
+  %tobool = icmp ne i32 %p1, 0
+  %cond = select i1 %tobool, i32 %p1, i32 %p1
+  ret i32 %cond
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+
+; CHECK-LABEL: define void @fn2(
+; CHECK: call i32 @fn1(i32 undef)
+
+; CHECK-LABEL: define internal i32 @fn1(
+; CHECK:%[[COND:.*]] = select i1 undef, i32 undef, i32 undef
+; CHECK: ret i32 %[[COND]]
+
+; CHECK-LABEL: define void @fn_no_null_opt(
+; CHECK: call i32 @fn0(i32 %0)
+
+; CHECK-LABEL: define internal i32 @fn0(
+; CHECK:%[[TOBOOL:.*]] = icmp ne i32 %p1, 0
+; CHECK:%[[COND:.*]] = select i1 %[[TOBOOL]], i32 %p1, i32 %p1
+; CHECK: ret i32 %[[COND]]

Added: llvm/trunk/test/Transforms/IPConstantProp/arg-count-mismatch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/arg-count-mismatch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/arg-count-mismatch.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/arg-count-mismatch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,72 @@
+; RUN: opt < %s -ipconstprop -S -o - | FileCheck %s
+
+; The original C source looked like this:
+;
+;   long long a101, b101, e101;
+;   volatile long c101;
+;   int d101;
+;
+;   static inline int bar(p1, p2)
+;   {
+;       return 0;
+;   }
+;
+;   void foo(unsigned p1)
+;   {
+;       long long *f = &b101, *g = &e101;
+;       c101 = 0;
+;       (void)((*f |= a101) - (*g = bar(d101)));
+;       c101 = (*f |= a101 &= p1) == d101;
+;   }
+;
+; When compiled with Clang it gives a warning
+;   warning: too few arguments in call to 'bar'
+;
+; This ll reproducer has been reduced to only include tha call.
+;
+; Note that -lint will report this as UB, but it passes -verify.
+
+; This test is just to verify that we do not crash/assert due to mismatch in
+; argument count between the caller and callee.
+
+define dso_local void @foo(i16 %a) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:    [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A:%.*]])
+; CHECK-NEXT:    ret void
+;
+  %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16) *)(i16 %a)
+  ret void
+}
+
+define internal i16 @bar(i16 %p1, i16 %p2) {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:    ret i16 0
+;
+  ret i16 0
+}
+
+;-------------------------------------------------------------------------------
+; Additional tests to verify that we still optimize when having a mismatch
+; in argument count due to varargs (as long as all non-variadic arguments have
+; been provided),
+
+define dso_local void @vararg_tests(i16 %a) {
+  %call1 = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 %a)
+  %call2 = call i16 bitcast (i16 (i16, i16, ...) * @vararg_no_prop to i16 (i16) *) (i16 7)
+  ret void
+}
+
+define internal i16 @vararg_prop(i16 %p1, ...) {
+; CHECK-LABEL: define internal i16 @vararg_prop(
+; CHECK-NEXT:    ret i16 7
+;
+  ret i16 %p1
+}
+
+define internal i16 @vararg_no_prop(i16 %p1, i16 %p2, ...) {
+; CHECK-LABEL: define internal i16 @vararg_no_prop(
+; CHECK-NEXT:    ret i16 [[P1:%.*]]
+;
+  ret i16 %p1
+}
+

Added: llvm/trunk/test/Transforms/IPConstantProp/arg-type-mismatch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/arg-type-mismatch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/arg-type-mismatch.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/arg-type-mismatch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -ipconstprop -S -o - | FileCheck %s
+
+; This test is just to verify that we do not crash/assert due to mismatch in
+; argument type between the caller and callee.
+
+define dso_local void @foo(i16 %a) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:    [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16, i32)*)(i16 [[A:%.*]], i32 7)
+; CHECK-NEXT:    ret void
+;
+  %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16, i32) *)(i16 %a, i32 7)
+  ret void
+}
+
+define internal i16 @bar(i16 %p1, i16 %p2) {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:    ret i16 [[P2:%.*]]
+;
+  ret i16 %p2
+}
+
+

Added: llvm/trunk/test/Transforms/IPConstantProp/comdat-ipo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/comdat-ipo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/comdat-ipo.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/comdat-ipo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -ipconstprop -S | FileCheck %s
+
+; See PR26774
+
+define i32 @baz() {
+  ret i32 10
+}
+
+; We can const-prop @baz's return value *into* @foo, but cannot
+; constprop @foo's return value into bar.
+
+define linkonce_odr i32 @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  %val = call i32 @baz()
+; CHECK-NEXT:  ret i32 10
+
+  %val = call i32 @baz()
+  ret i32 %val
+}
+
+define i32 @bar() {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:  %val = call i32 @foo()
+; CHECK-NEXT:  ret i32 %val
+
+  %val = call i32 @foo()
+  ret i32 %val
+}

Added: llvm/trunk/test/Transforms/IPConstantProp/dangling-block-address.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/dangling-block-address.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/dangling-block-address.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/dangling-block-address.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt < %s -internalize -ipsccp -S | FileCheck %s
+; PR5569
+
+; IPSCCP should prove that the blocks are dead and delete them, and
+; properly handle the dangling blockaddress constants.
+
+; CHECK: @bar.l = internal constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
+
+ at code = global [5 x i32] [i32 0, i32 0, i32 0, i32 0, i32 1], align 4 ; <[5 x i32]*> [#uses=0]
+ at bar.l = internal constant [2 x i8*] [i8* blockaddress(@bar, %lab0), i8* blockaddress(@bar, %end)] ; <[2 x i8*]*> [#uses=1]
+
+define void @foo(i32 %x) nounwind readnone {
+entry:
+  %b = alloca i32, align 4                        ; <i32*> [#uses=1]
+  store volatile i32 -1, i32* %b
+  ret void
+}
+
+define void @bar(i32* nocapture %pc) nounwind readonly {
+entry:
+  br label %indirectgoto
+
+lab0:                                             ; preds = %indirectgoto
+  %indvar.next = add i32 %indvar, 1               ; <i32> [#uses=1]
+  br label %indirectgoto
+
+end:                                              ; preds = %indirectgoto
+  ret void
+
+indirectgoto:                                     ; preds = %lab0, %entry
+  %indvar = phi i32 [ %indvar.next, %lab0 ], [ 0, %entry ] ; <i32> [#uses=2]
+  %pc.addr.0 = getelementptr i32, i32* %pc, i32 %indvar ; <i32*> [#uses=1]
+  %tmp1.pn = load i32, i32* %pc.addr.0                 ; <i32> [#uses=1]
+  %indirect.goto.dest.in = getelementptr inbounds [2 x i8*], [2 x i8*]* @bar.l, i32 0, i32 %tmp1.pn ; <i8**> [#uses=1]
+  %indirect.goto.dest = load i8*, i8** %indirect.goto.dest.in ; <i8*> [#uses=1]
+  indirectbr i8* %indirect.goto.dest, [label %lab0, label %end]
+}
+
+define i32 @main() nounwind readnone {
+entry:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/IPConstantProp/deadarg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/deadarg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/deadarg.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/deadarg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,6 @@
+; RUN: opt < %s -ipconstprop -disable-output
+define internal void @foo(i32 %X) {
+        call void @foo( i32 %X )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IPConstantProp/fp-bc-icmp-const-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/fp-bc-icmp-const-fold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/fp-bc-icmp-const-fold.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/fp-bc-icmp-const-fold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt -S -ipsccp < %s | FileCheck %s
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-bgq-linux"
+
+define void @test(i32 signext %n) {
+
+; CHECK-LABEL: @test
+
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  ret void
+
+if.end:                                           ; preds = %entry
+  br i1 undef, label %if.then2, label %if.end4
+
+if.then2:                                         ; preds = %if.end
+  unreachable
+
+if.end4:                                          ; preds = %if.end
+  %sub.n = select i1 undef, i32 undef, i32 %n
+  switch i32 %sub.n, label %if.else14 [
+    i32 0, label %if.then9
+    i32 1, label %if.then12
+  ]
+
+if.then9:                                         ; preds = %if.end4
+  unreachable
+
+if.then12:                                        ; preds = %if.end4
+  unreachable
+
+if.else14:                                        ; preds = %if.end4
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %if.else14
+  %scale.0 = phi ppc_fp128 [ 0xM3FF00000000000000000000000000000, %if.else14 ], [ %scale.0, %do.body ]
+  br i1 undef, label %do.body, label %if.then33
+
+if.then33:                                        ; preds = %do.body
+  br i1 undef, label %_ZN5boost4math4signIgEEiRKT_.exit30, label %cond.false.i28
+
+cond.false.i28:                                   ; preds = %if.then33
+  %0 = bitcast ppc_fp128 %scale.0 to i128
+  %tobool.i26 = icmp slt i128 %0, 0
+  br label %_ZN5boost4math4signIgEEiRKT_.exit30
+
+_ZN5boost4math4signIgEEiRKT_.exit30:              ; preds = %cond.false.i28, %if.then33
+  unreachable
+}
+

Added: llvm/trunk/test/Transforms/IPConstantProp/global.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/global.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/global.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/global.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -S -passes=ipsccp | FileCheck %s
+; RUN: opt < %s -S -ipsccp | FileCheck %s
+
+ at _ZL6test1g = internal global i32 42, align 4
+
+define void @_Z7test1f1v() nounwind {
+entry:
+  %tmp = load i32, i32* @_ZL6test1g, align 4
+  %cmp = icmp eq i32 %tmp, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  store i32 0, i32* @_ZL6test1g, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  ret void
+}
+
+; CHECK: @_Z7test1f2v()
+; CHECK: entry:
+; CHECK-NEXT: ret i32 42
+define i32 @_Z7test1f2v() nounwind {
+entry:
+  %tmp = load i32, i32* @_ZL6test1g, align 4
+  ret i32 %tmp
+}

Added: llvm/trunk/test/Transforms/IPConstantProp/multiple_callbacks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/multiple_callbacks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/multiple_callbacks.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/multiple_callbacks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; RUN: opt -ipconstprop -S < %s | FileCheck %s
+;
+;
+;                            /---------------------------------------|
+;                            |                /----------------------|----|
+;                            |                |                /-----|    |
+;                            V                V                V     |    |
+;    void broker(int (*cb0)(int), int (*cb1)(int), int (*cb2)(int), int, int);
+;
+;    static int cb0(int zero) {
+;      return zero;
+;    }
+;    static int cb1(int unknown) {
+;      return unknown;
+;    }
+;    static int cb2(int unknown) {
+;      cb0(0);
+;      return unknown;
+;    }
+;    static int cb3(int unknown) {
+;      return unknown;
+;    }
+;    static int cb4(int unknown) {
+;      return unknown;
+;    }
+;
+;    void foo() {
+;      cb0(0);
+;      cb3(1);
+;      broker(cb0, cb1, cb0, 0, 1);
+;      broker(cb1, cb2, cb2, 0, 1);
+;      broker(cb3, cb2, cb3, 0, 1);
+;      broker(cb4, cb4, cb4, 0, 1);
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define internal i32 @cb0(i32 %zero) {
+entry:
+; CHECK:      @cb0
+; CHECK-NEXT: entry
+; CHECK-NEXT: ret i32 0
+  ret i32 %zero
+}
+
+define internal i32 @cb1(i32 %unknown) {
+entry:
+; CHECK: ret i32 %unknown
+  ret i32 %unknown
+}
+
+define internal i32 @cb2(i32 %unknown) {
+entry:
+  %call = call i32 @cb0(i32 0)
+; CHECK: ret i32 %unknown
+  ret i32 %unknown
+}
+
+define internal i32 @cb3(i32 %unknown) {
+entry:
+; CHECK: ret i32 %unknown
+  ret i32 %unknown
+}
+
+define internal i32 @cb4(i32 %unknown) {
+entry:
+; CHECK: ret i32 %unknown
+  ret i32 %unknown
+}
+
+define void @foo() {
+entry:
+  %call = call i32 @cb0(i32 0)
+  %call1 = call i32 @cb3(i32 1)
+  call void @broker(i32 (i32)* nonnull @cb0, i32 (i32)* nonnull @cb1, i32 (i32)* nonnull @cb0, i32 0, i32 1)
+  call void @broker(i32 (i32)* nonnull @cb1, i32 (i32)* nonnull @cb2, i32 (i32)* nonnull @cb2, i32 0, i32 1)
+  call void @broker(i32 (i32)* nonnull @cb3, i32 (i32)* nonnull @cb2, i32 (i32)* nonnull @cb3, i32 0, i32 1)
+  call void @broker(i32 (i32)* nonnull @cb4, i32 (i32)* nonnull @cb4, i32 (i32)* nonnull @cb4, i32 0, i32 1)
+  ret void
+}
+
+declare !callback !3 void @broker(i32 (i32)*, i32 (i32)*, i32 (i32)*, i32, i32)
+
+!0 = !{i64 0, i64 3, i1 false}
+!1 = !{i64 1, i64 4, i1 false}
+!2 = !{i64 2, i64 3, i1 false}
+!3 = !{!0, !2, !1}

Added: llvm/trunk/test/Transforms/IPConstantProp/musttail-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/musttail-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/musttail-call.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/musttail-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,58 @@
+; RUN: opt < %s -ipsccp -S | FileCheck %s
+; PR36485
+; musttail call result can\'t be replaced with a constant, unless the call
+; can be removed
+
+declare i32 @external()
+
+define i8* @start(i8 %v) {
+  %c1 = icmp eq i8 %v, 0
+  br i1 %c1, label %true, label %false
+true:
+  ; CHECK: %ca = musttail call i8* @side_effects(i8 0)
+  ; CHECK: ret i8* %ca
+  %ca = musttail call i8* @side_effects(i8 %v)
+  ret i8* %ca
+false:
+  %c2 = icmp eq i8 %v, 1
+  br i1 %c2, label %c2_true, label %c2_false
+c2_true:
+  %ca1 = musttail call i8* @no_side_effects(i8 %v)
+  ; CHECK: ret i8* null
+  ret i8* %ca1
+c2_false:
+  ; CHECK: %ca2 = musttail call i8* @dont_zap_me(i8 %v)
+  ; CHECK: ret i8* %ca2
+  %ca2 = musttail call i8* @dont_zap_me(i8 %v)
+  ret i8* %ca2
+}
+
+define internal i8* @side_effects(i8 %v) {
+  %i1 = call i32 @external()
+
+  ; since this goes back to `start` the SCPP should be see that the return value
+  ; is always `null`.
+  ; The call can't be removed due to `external` call above, though.
+
+  ; CHECK: %ca = musttail call i8* @start(i8 0)
+  %ca = musttail call i8* @start(i8 %v)
+
+  ; Thus the result must be returned anyway
+  ; CHECK: ret i8* %ca
+  ret i8* %ca
+}
+
+define internal i8* @no_side_effects(i8 %v) readonly nounwind {
+  ; The call to this function is removed, so the return value must be zapped
+  ; CHECK: ret i8* undef
+  ret i8* null
+}
+
+define internal i8* @dont_zap_me(i8 %v) {
+  %i1 = call i32 @external()
+
+  ; The call to this function cannot be removed due to side effects. Thus the
+  ; return value should stay as it is, and should not be zapped.
+  ; CHECK: ret i8* null
+  ret i8* null
+}

Added: llvm/trunk/test/Transforms/IPConstantProp/naked-return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/naked-return.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/naked-return.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/naked-return.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -ipsccp -S %s | FileCheck %s
+; RUN: opt -ipconstprop -S %s | FileCheck %s
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc19.0.24215"
+
+define i32 @dipsy(i32, i32) local_unnamed_addr #0 {
+BasicBlock0:
+  call void asm "\0D\0Apushl %ebp\0D\0Amovl 8(%esp),%eax\0D\0Amovl 12(%esp), %ebp\0D\0Acalll *%eax\0D\0Apopl %ebp\0D\0Aretl\0D\0A", ""()
+  ret i32 0
+}
+
+define void @tinkywinky(i32, i32, i32) local_unnamed_addr #0 {
+BasicBlock1:
+  call void asm "\0D\0A    movl 12(%esp), %ebp\0D\0A    movl 4(%esp), %eax\0D\0A    movl 8(%esp), %esp\0D\0A    jmpl *%eax\0D\0A", ""()
+  ret void
+}
+
+define void @patatino(i32, i32, i32) local_unnamed_addr #1 {
+bb:
+  %3 = tail call i32 @dipsy(i32 %0, i32 %1) #0
+; Check that we don't accidentally propagate zero.
+; CHECK: @tinkywinky(i32 %3, i32 %2, i32 %1) #0
+  tail call void @tinkywinky(i32 %3, i32 %2, i32 %1) #0
+  ret void
+}
+
+attributes #0 = { naked }
+attributes #1 = { "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" }

Added: llvm/trunk/test/Transforms/IPConstantProp/openmp_parallel_for.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/openmp_parallel_for.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/openmp_parallel_for.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/openmp_parallel_for.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,120 @@
+; RUN: opt -S -ipconstprop < %s | FileCheck %s
+;
+;    void bar(int, float, double);
+;
+;    void foo(int N) {
+;      float p = 3;
+;      double q = 5;
+;      N = 7;
+;
+;    #pragma omp parallel for firstprivate(q)
+;      for (int i = 2; i < N; i++) {
+;        bar(i, p, q);
+;      }
+;    }
+;
+; Verify the constant value of q is propagated into the outlined function.
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.ident_t = type { i32, i32, i32, i32, i8* }
+
+ at .str = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
+ at 0 = private unnamed_addr global %struct.ident_t { i32 0, i32 514, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
+ at 1 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
+
+define dso_local void @foo(i32 %N) {
+entry:
+  %N.addr = alloca i32, align 4
+  %p = alloca float, align 4
+  store i32 %N, i32* %N.addr, align 4
+  store float 3.000000e+00, float* %p, align 4
+  store i32 7, i32* %N.addr, align 4
+  call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nonnull %N.addr, float* nonnull %p, i64 4617315517961601024)
+  ret void
+}
+
+define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %N, float* dereferenceable(4) %p, i64 %q) {
+entry:
+  %q.addr = alloca i64, align 8
+  %.omp.lb = alloca i32, align 4
+  %.omp.ub = alloca i32, align 4
+  %.omp.stride = alloca i32, align 4
+  %.omp.is_last = alloca i32, align 4
+; CHECK: store i64 4617315517961601024, i64* %q.addr, align 8
+  store i64 %q, i64* %q.addr, align 8
+  %conv = bitcast i64* %q.addr to double*
+  %tmp = load i32, i32* %N, align 4
+  %sub3 = add nsw i32 %tmp, -3
+  %cmp = icmp sgt i32 %tmp, 2
+  br i1 %cmp, label %omp.precond.then, label %omp.precond.end
+
+omp.precond.then:                                 ; preds = %entry
+  store i32 0, i32* %.omp.lb, align 4
+  store i32 %sub3, i32* %.omp.ub, align 4
+  store i32 1, i32* %.omp.stride, align 4
+  store i32 0, i32* %.omp.is_last, align 4
+  %tmp5 = load i32, i32* %.global_tid., align 4
+  call void @__kmpc_for_static_init_4(%struct.ident_t* nonnull @0, i32 %tmp5, i32 34, i32* nonnull %.omp.is_last, i32* nonnull %.omp.lb, i32* nonnull %.omp.ub, i32* nonnull %.omp.stride, i32 1, i32 1)
+  %tmp6 = load i32, i32* %.omp.ub, align 4
+  %cmp6 = icmp sgt i32 %tmp6, %sub3
+  br i1 %cmp6, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %omp.precond.then
+  br label %cond.end
+
+cond.false:                                       ; preds = %omp.precond.then
+  %tmp7 = load i32, i32* %.omp.ub, align 4
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i32 [ %sub3, %cond.true ], [ %tmp7, %cond.false ]
+  store i32 %cond, i32* %.omp.ub, align 4
+  %tmp8 = load i32, i32* %.omp.lb, align 4
+  br label %omp.inner.for.cond
+
+omp.inner.for.cond:                               ; preds = %omp.inner.for.inc, %cond.end
+  %.omp.iv.0 = phi i32 [ %tmp8, %cond.end ], [ %add11, %omp.inner.for.inc ]
+  %tmp9 = load i32, i32* %.omp.ub, align 4
+  %cmp8 = icmp sgt i32 %.omp.iv.0, %tmp9
+  br i1 %cmp8, label %omp.inner.for.cond.cleanup, label %omp.inner.for.body
+
+omp.inner.for.cond.cleanup:                       ; preds = %omp.inner.for.cond
+  br label %omp.inner.for.end
+
+omp.inner.for.body:                               ; preds = %omp.inner.for.cond
+  %add10 = add nsw i32 %.omp.iv.0, 2
+  %tmp10 = load float, float* %p, align 4
+  %tmp11 = load double, double* %conv, align 8
+  call void @bar(i32 %add10, float %tmp10, double %tmp11)
+  br label %omp.body.continue
+
+omp.body.continue:                                ; preds = %omp.inner.for.body
+  br label %omp.inner.for.inc
+
+omp.inner.for.inc:                                ; preds = %omp.body.continue
+  %add11 = add nsw i32 %.omp.iv.0, 1
+  br label %omp.inner.for.cond
+
+omp.inner.for.end:                                ; preds = %omp.inner.for.cond.cleanup
+  br label %omp.loop.exit
+
+omp.loop.exit:                                    ; preds = %omp.inner.for.end
+  %tmp12 = load i32, i32* %.global_tid., align 4
+  call void @__kmpc_for_static_fini(%struct.ident_t* nonnull @0, i32 %tmp12)
+  br label %omp.precond.end
+
+omp.precond.end:                                  ; preds = %omp.loop.exit, %entry
+  ret void
+}
+
+declare dso_local void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32)
+
+declare dso_local void @bar(i32, float, double)
+
+declare dso_local void @__kmpc_for_static_fini(%struct.ident_t*, i32)
+
+declare !callback !0 dso_local void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...)
+
+!1 = !{i64 2, i64 -1, i64 -1, i1 true}
+!0 = !{!1}

Added: llvm/trunk/test/Transforms/IPConstantProp/pthreads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/pthreads.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/pthreads.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/pthreads.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -ipconstprop -S < %s | FileCheck %s
+;
+;    #include <pthread.h>
+;
+;    void *GlobalVPtr;
+;
+;    static void *foo(void *arg) { return arg; }
+;    static void *bar(void *arg) { return arg; }
+;
+;    int main() {
+;      pthread_t thread;
+;      pthread_create(&thread, NULL, foo, NULL);
+;      pthread_create(&thread, NULL, bar, &GlobalVPtr);
+;      return 0;
+;    }
+;
+; Verify the constant values NULL and &GlobalVPtr are propagated into foo and
+; bar, respectively.
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%union.pthread_attr_t = type { i64, [48 x i8] }
+
+ at GlobalVPtr = common dso_local global i8* null, align 8
+
+define dso_local i32 @main() {
+entry:
+  %thread = alloca i64, align 8
+  %call = call i32 @pthread_create(i64* nonnull %thread, %union.pthread_attr_t* null, i8* (i8*)* nonnull @foo, i8* null)
+  %call1 = call i32 @pthread_create(i64* nonnull %thread, %union.pthread_attr_t* null, i8* (i8*)* nonnull @bar, i8* bitcast (i8** @GlobalVPtr to i8*))
+  ret i32 0
+}
+
+declare !callback !0 dso_local i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*)
+
+define internal i8* @foo(i8* %arg) {
+entry:
+; CHECK: ret i8* null
+  ret i8* %arg
+}
+
+define internal i8* @bar(i8* %arg) {
+entry:
+; CHECK: ret i8* bitcast (i8** @GlobalVPtr to i8*)
+  ret i8* %arg
+}
+
+!1 = !{i64 2, i64 3, i1 false}
+!0 = !{!1}

Added: llvm/trunk/test/Transforms/IPConstantProp/recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/recursion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/recursion.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/recursion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt < %s -ipconstprop -deadargelim -S | not grep %X
+define internal i32 @foo(i32 %X) {
+        %Y = call i32 @foo( i32 %X )            ; <i32> [#uses=1]
+        %Z = add i32 %Y, 1              ; <i32> [#uses=1]
+        ret i32 %Z
+}
+
+define void @bar() {
+        call i32 @foo( i32 17 )         ; <i32>:1 [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IPConstantProp/remove-call-inst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/remove-call-inst.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/remove-call-inst.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/remove-call-inst.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -S -ipsccp | FileCheck %s
+; PR5596
+
+; IPSCCP should propagate the 0 argument, eliminate the switch, and propagate
+; the result.
+
+; CHECK: define i32 @main() #0 {
+; CHECK-NEXT: entry:
+; CHECK-NOT: call
+; CHECK-NEXT: ret i32 123
+
+define i32 @main() noreturn nounwind {
+entry:
+  %call2 = tail call i32 @wwrite(i64 0) nounwind
+  ret i32 %call2
+}
+
+define internal i32 @wwrite(i64 %i) nounwind readnone {
+entry:
+  switch i64 %i, label %sw.default [
+    i64 3, label %return
+    i64 10, label %return
+  ]
+
+sw.default:
+  ret i32 123
+
+return:
+  ret i32 0
+}
+
+; CHECK: attributes #0 = { noreturn nounwind }
+; CHECK: attributes #1 = { nounwind readnone }

Added: llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt < %s -ipconstprop -S > %t
+; RUN: cat %t | grep "store i32 %Z, i32\* %Q"
+; RUN: cat %t | grep "add i32 1, 3"
+
+;; This function returns its second argument on all return statements
+define internal i32* @incdec(i1 %C, i32* %V) {
+        %X = load i32, i32* %V
+        br i1 %C, label %T, label %F
+
+T:              ; preds = %0
+        %X1 = add i32 %X, 1
+        store i32 %X1, i32* %V
+        ret i32* %V
+
+F:              ; preds = %0
+        %X2 = sub i32 %X, 1
+        store i32 %X2, i32* %V
+        ret i32* %V
+}
+
+;; This function returns its first argument as a part of a multiple return
+;; value
+define internal { i32, i32 } @foo(i32 %A, i32 %B) {
+        %X = add i32 %A, %B
+        %Y = insertvalue { i32, i32 } undef, i32 %A, 0
+        %Z = insertvalue { i32, i32 } %Y, i32 %X, 1
+        ret { i32, i32 } %Z
+}
+
+define void @caller(i1 %C) personality i32 (...)* @__gxx_personality_v0 {
+        %Q = alloca i32
+        ;; Call incdec to see if %W is properly replaced by %Q
+        %W = call i32* @incdec(i1 %C, i32* %Q )             ; <i32> [#uses=1]
+        ;; Call @foo twice, to prevent the arguments from propagating into the
+        ;; function (so we can check the returned argument is properly
+        ;; propagated per-caller).
+        %S1 = call { i32, i32 } @foo(i32 1, i32 2)
+        %X1 = extractvalue { i32, i32 } %S1, 0
+        %S2 = invoke { i32, i32 } @foo(i32 3, i32 4) to label %OK unwind label %LPAD
+
+OK:
+        %X2 = extractvalue { i32, i32 } %S2, 0
+        ;; Do some stuff with the returned values which we can grep for
+        %Z  = add i32 %X1, %X2
+        store i32 %Z, i32* %W
+        br label %RET
+
+LPAD:
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        br label %RET
+
+RET:
+        ret void
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -ipconstprop -instcombine -S | grep "ret i1 true" | count 2
+define internal i32 @foo(i1 %C) {
+        br i1 %C, label %T, label %F
+
+T:              ; preds = %0
+        ret i32 52
+
+F:              ; preds = %0
+        ret i32 52
+}
+
+define i1 @caller(i1 %C) {
+        %X = call i32 @foo( i1 %C )             ; <i32> [#uses=1]
+        %Y = icmp ne i32 %X, 0          ; <i1> [#uses=1]
+        ret i1 %Y
+}
+
+define i1 @invokecaller(i1 %C) personality i32 (...)* @__gxx_personality_v0 {
+        %X = invoke i32 @foo( i1 %C ) to label %OK unwind label %FAIL             ; <i32> [#uses=1]
+OK:
+        %Y = icmp ne i32 %X, 0          ; <i1> [#uses=1]
+        ret i1 %Y 
+FAIL:
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        ret i1 false
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt < %s -ipconstprop -S > %t
+;; Check that the 21 constants got propagated properly
+; RUN: cat %t | grep "%M = add i32 21, 21"
+;; Check that the second return values didn't get propagated
+; RUN: cat %t | grep "%N = add i32 %B, %D"
+
+%0 = type { i32, i32 }
+
+define internal %0 @foo(i1 %Q) {
+  br i1 %Q, label %T, label %F
+
+T:                                                ; preds = %0
+  %mrv = insertvalue %0 undef, i32 21, 0
+  %mrv1 = insertvalue %0 %mrv, i32 22, 1
+  ret %0 %mrv1
+
+F:                                                ; preds = %0
+  %mrv2 = insertvalue %0 undef, i32 21, 0
+  %mrv3 = insertvalue %0 %mrv2, i32 23, 1
+  ret %0 %mrv3
+}
+
+define internal %0 @bar(i1 %Q) {
+  %A = insertvalue %0 undef, i32 21, 0
+  br i1 %Q, label %T, label %F
+
+T:                                                ; preds = %0
+  %B = insertvalue %0 %A, i32 22, 1
+  ret %0 %B
+
+F:                                                ; preds = %0
+  %C = insertvalue %0 %A, i32 23, 1
+  ret %0 %C
+}
+
+define %0 @caller(i1 %Q) {
+  %X = call %0 @foo(i1 %Q)
+  %A = extractvalue %0 %X, 0
+  %B = extractvalue %0 %X, 1
+  %Y = call %0 @bar(i1 %Q)
+  %C = extractvalue %0 %Y, 0
+  %D = extractvalue %0 %Y, 1
+  %M = add i32 %A, %C
+  %N = add i32 %B, %D
+  ret %0 %X
+}

Added: llvm/trunk/test/Transforms/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt < %s -ipsccp -S | FileCheck %s
+
+; CHECK-LABEL: @testf(
+; CHECK:         ret i32 undef
+;
+define internal i32 @testf() {
+entry:
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry, %if.then
+  br label %if.end
+
+if.end:                                          ; preds = %if.then1, %entry
+  ret i32 10
+}
+
+; CHECK-LABEL: @test1(
+; CHECK:         ret i32 undef
+;
+define internal i32 @test1() {
+entry:
+  br label %if.then
+
+if.then:                                          ; preds = %entry, %if.then
+  %call = call i32 @testf()
+  %res = icmp eq i32 %call, 10
+  br i1 %res, label %ret1, label %ret2
+
+ret1:                                           ; preds = %if.then, %entry
+  ret i32 99
+
+ret2:                                           ; preds = %if.then, %entry
+  ret i32 0
+}
+
+; CHECK-LABEL: @main(
+; CHECK-NEXT:    %res = call i32 @test1()
+; CHECK-NEXT:    ret i32 99
+;
+define i32 @main() {
+  %res = call i32 @test1()
+  ret i32 %res
+}

Added: llvm/trunk/test/Transforms/IPConstantProp/thread_local_acs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/thread_local_acs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/thread_local_acs.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/thread_local_acs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -ipconstprop -S < %s | FileCheck %s
+;
+;    #include <threads.h>
+;    thread_local int gtl = 0;
+;    int gsh = 0;
+;
+;    static int callee(int *thread_local_ptr, int *shared_ptr) {
+;      return *thread_local_ptr + *shared_ptr;
+;    }
+;
+;    void broker(int *, int (*callee)(int *, int *), int *);
+;
+;    void caller() {
+;      broker(&gtl, callee, &gsh);
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+ at gtl = dso_local thread_local global i32 0, align 4
+ at gsh = dso_local global i32 0, align 4
+
+define internal i32 @callee(i32* %thread_local_ptr, i32* %shared_ptr) {
+entry:
+; CHECK:  %tmp = load i32, i32* %thread_local_ptr, align 4
+; CHECK:  %tmp1 = load i32, i32* @gsh, align 4
+; CHECK:  %add = add nsw i32 %tmp, %tmp1
+  %tmp = load i32, i32* %thread_local_ptr, align 4
+  %tmp1 = load i32, i32* %shared_ptr, align 4
+  %add = add nsw i32 %tmp, %tmp1
+  ret i32 %add
+}
+
+define dso_local void @caller() {
+entry:
+  call void @broker(i32* nonnull @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nonnull @gsh)
+  ret void
+}
+
+declare !callback !0 dso_local void @broker(i32*, i32 (i32*, i32*)*, i32*)
+
+!1 = !{i64 1, i64 0, i64 2, i1 false}
+!0 = !{!1}

Added: llvm/trunk/test/Transforms/IPConstantProp/user-with-multiple-uses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/user-with-multiple-uses.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IPConstantProp/user-with-multiple-uses.ll (added)
+++ llvm/trunk/test/Transforms/IPConstantProp/user-with-multiple-uses.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -S -ipsccp | FileCheck %s
+; PR5596
+
+; IPSCCP should propagate the 0 argument, eliminate the switch, and propagate
+; the result.
+
+; CHECK: define i32 @main() #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %call2 = tail call i32 @wwrite(i64 0) [[NUW:#[0-9]+]]
+; CHECK-NEXT: ret i32 123
+
+define i32 @main() noreturn nounwind {
+entry:
+  %call2 = tail call i32 @wwrite(i64 0) nounwind
+  ret i32 %call2
+}
+
+define internal i32 @wwrite(i64 %i) nounwind {
+entry:
+  switch i64 %i, label %sw.default [
+    i64 3, label %return
+    i64 10, label %return
+  ]
+
+sw.default:
+  ret i32 123
+
+return:
+  ret i32 0
+}
+
+; CHECK: attributes #0 = { noreturn nounwind }
+; CHECK: attributes #1 = { nounwind }

Added: llvm/trunk/test/Transforms/IRCE/add-metadata-pre-post-loops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/add-metadata-pre-post-loops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/add-metadata-pre-post-loops.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/add-metadata-pre-post-loops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,82 @@
+; RUN: opt -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; test that the pre and post loops have loop metadata which disables any further
+; loop optimizations.
+
+; generates a post loop, which should have metadata !llvm.loop !2
+; Function Attrs: alwaysinline
+define void @inner_loop(i32* %arr, i32* %a_len_ptr, i32 %n) #0 {
+; CHECK-LABEL: inner_loop(
+; CHECK-LABEL: in.bounds.postloop
+; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit.loopexit, !llvm.loop !2, !irce.loop.clone !7
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+loop:                                             ; preds = %in.bounds, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+in.bounds:                                        ; preds = %loop
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:                                    ; preds = %loop
+  ret void
+
+exit:                                             ; preds = %in.bounds, %entry
+  ret void
+}
+
+; add loop metadata for pre and post loops
+define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
+; CHECK-LABEL: @single_access_with_preloop(
+; CHECK-LABEL: in.bounds.preloop
+; CHECK: br i1 [[COND:%[^ ]+]], label %loop.preloop, label %preloop.exit.selector, !llvm.loop !8, !irce.loop.clone !7
+; CHECK-LABEL: in.bounds.postloop
+; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit.loopexit, !llvm.loop !9, !irce.loop.clone !7
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %array.idx = add i32 %idx, %offset
+  %abc.high = icmp slt i32 %array.idx, %len
+  %abc.low = icmp sge i32 %array.idx, 0
+  %abc = and i1 %abc.low, %abc.high
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %array.idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+attributes #0 = { alwaysinline }
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}
+!2 = distinct !{!2, !3, !4, !5, !6}
+!3 = !{!"llvm.loop.unroll.disable"}
+!4 = !{!"llvm.loop.vectorize.enable", i1 false}
+!5 = !{!"llvm.loop.licm_versioning.disable"}
+!6 = !{!"llvm.loop.distribute.enable", i1 false}
+!7 = !{}
+!8 = distinct !{!8, !3, !4, !5}
+!9 = distinct !{!9, !3, !4, !5}

Added: llvm/trunk/test/Transforms/IRCE/bad-loop-structure.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/bad-loop-structure.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/bad-loop-structure.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/bad-loop-structure.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt -S -irce -irce-print-changed-loops=true < %s | FileCheck %s
+; RUN: opt -S -passes='require<branch-prob>,loop(irce)' -irce-print-changed-loops=true < %s | FileCheck %s
+
+; CHECK-NOT: irce
+
+define void @bad_loop_structure_increasing(i64 %iv.start) {
+entry:
+  br label %for.body
+
+for.body:
+  %indvars.iv = phi i64 [ %iv.start, %entry ], [ %indvars.iv.next, %for.inc ]
+  %cmp = icmp ult i64 %indvars.iv, 100
+  br i1 %cmp, label %switch.lookup, label %for.inc
+
+switch.lookup:
+  br label %for.inc
+
+for.inc:
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %cmp55 = icmp slt i64 %indvars.iv.next, 11
+  br i1 %cmp55, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+
+define void @bad_loop_structure_decreasing(i64 %iv.start) {
+entry:
+  br label %for.body
+
+for.body:
+  %indvars.iv = phi i64 [ %iv.start, %entry ], [ %indvars.iv.next, %for.inc ]
+  %cmp = icmp ult i64 %indvars.iv, 100
+  br i1 %cmp, label %switch.lookup, label %for.inc
+
+switch.lookup:
+  br label %for.inc
+
+for.inc:
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, -1
+  %cmp55 = icmp sgt i64 %indvars.iv.next, 11
+  br i1 %cmp55, label %for.body, label %for.end
+
+for.end:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IRCE/bad_expander.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/bad_expander.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/bad_expander.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/bad_expander.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,136 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
+target triple = "x86_64-unknown-linux-gnu"
+
+; IRCE should fail here because the preheader's exiting value is a phi from the
+; loop, and this value cannot be expanded at loop's preheader.
+
+; CHECK-NOT:   irce: in function test_01: constrained Loop
+; CHECK-NOT:   irce: in function test_02: constrained Loop
+; CHECK-LABEL: irce: in function test_03: constrained Loop
+
+define void @test_01() {
+
+; CHECK-NOT:   irce: in function test_01: constrained Loop
+
+; CHECK-LABEL: test_01
+; CHECK-NOT:   preloop
+; CHECK-NOT:   postloop
+; CHECK-NOT:   br i1 false
+; CHECK-NOT:   br i1 true
+
+entry:
+  br label %loop
+
+exit:                                       ; preds = %guarded, %loop
+  ret void
+
+loop:                                      ; preds = %guarded, %entry
+  %iv = phi i64 [ 380, %entry ], [ %limit, %guarded ]
+  %bad_phi = phi i32 [ 3, %entry ], [ %bad_phi.next, %guarded ]
+  %bad_phi.next = add nuw nsw i32 %bad_phi, 1
+  %iv.next = add nuw nsw i64 %iv, 1
+  %rc = icmp slt i64 %iv.next, 5
+  br i1 %rc, label %guarded, label %exit
+
+guarded:
+  %limit = add nsw i64 %iv, -1
+  %tmp5 = add nuw nsw i32 %bad_phi, 8
+  %tmp6 = zext i32 %tmp5 to i64
+  %tmp7 = icmp eq i64 %limit, %tmp6
+  br i1 %tmp7, label %exit, label %loop
+}
+
+; This test should fail because we are unable to prove that the division is
+; safe to expand it to preheader: if we exit by maybe_exit condition, it is
+; unsafe to execute it there.
+
+define void @test_02(i64* %p1, i64* %p2, i1 %maybe_exit) {
+
+; CHECK-LABEL: test_02
+; CHECK-NOT:   preloop
+; CHECK-NOT:   postloop
+; CHECK-NOT:   br i1 false
+; CHECK-NOT:   br i1 true
+
+
+entry:
+  %num = load i64, i64* %p1, align 4, !range !0
+  %denom = load i64, i64* %p2, align 4, !range !0
+  br label %loop
+
+exit:                                       ; preds = %guarded, %loop
+  ret void
+
+loop:                                      ; preds = %guarded, %entry
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ]
+  %iv.next = add nuw nsw i64 %iv, 1
+  br i1 %maybe_exit, label %range_check, label %exit
+
+range_check:
+  %div_result = udiv i64 %num, %denom
+  %rc = icmp slt i64 %iv.next, %div_result
+  br i1 %rc, label %guarded, label %exit
+
+guarded:
+  %gep = getelementptr i64, i64* %p1, i64 %iv.next
+  %loaded = load i64, i64* %gep, align 4
+  %tmp7 = icmp slt i64 %iv.next, 1000
+  br i1 %tmp7, label %loop, label %exit
+}
+
+define void @test_03(i64* %p1, i64* %p2, i1 %maybe_exit) {
+
+; Show that IRCE would hit test_02 if the division was safe (denom not zero).
+
+; CHECK-LABEL: test_03
+; CHECK:       entry:
+; CHECK-NEXT:    %num = load i64, i64* %p1, align 4
+; CHECK-NEXT:    [[DIV:%[^ ]+]] = udiv i64 %num, 13
+; CHECK-NEXT:    [[DIV_MINUS_1:%[^ ]+]] = add i64 [[DIV]], -1
+; CHECK-NEXT:    [[COMP1:%[^ ]+]] = icmp sgt i64 [[DIV_MINUS_1]], 0
+; CHECK-NEXT:    %exit.mainloop.at = select i1 [[COMP1]], i64 [[DIV_MINUS_1]], i64 0
+; CHECK-NEXT:    [[COMP2:%[^ ]+]] = icmp slt i64 0, %exit.mainloop.at
+; CHECK-NEXT:    br i1 [[COMP2]], label %loop.preheader, label %main.pseudo.exit
+; CHECK-NOT:     preloop
+; CHECK:       loop:
+; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %guarded ], [ 0, %loop.preheader ]
+; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
+; CHECK-NEXT:    %rc = icmp slt i64 %iv.next, %div_result
+; CHECK-NEXT:    %or.cond = and i1 %maybe_exit, true
+; CHECK-NEXT:    br i1 %or.cond, label %guarded, label %exit.loopexit1
+; CHECK:       guarded:
+; CHECK-NEXT:    %gep = getelementptr i64, i64* %p1, i64 %iv.next
+; CHECK-NEXT:    %loaded = load i64, i64* %gep, align 4
+; CHECK-NEXT:    %tmp7 = icmp slt i64 %iv.next, 1000
+; CHECK-NEXT:    [[EXIT_MAIN_LOOP:%[^ ]+]] = icmp slt i64 %iv.next, %exit.mainloop.at
+; CHECK-NEXT:    br i1 [[EXIT_MAIN_LOOP]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %num = load i64, i64* %p1, align 4, !range !0
+  br label %loop
+
+exit:                                       ; preds = %guarded, %loop
+  ret void
+
+loop:                                      ; preds = %guarded, %entry
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ]
+  %iv.next = add nuw nsw i64 %iv, 1
+  br i1 %maybe_exit, label %range_check, label %exit
+
+range_check:
+  %div_result = udiv i64 %num, 13
+  %rc = icmp slt i64 %iv.next, %div_result
+  br i1 %rc, label %guarded, label %exit
+
+guarded:
+  %gep = getelementptr i64, i64* %p1, i64 %iv.next
+  %loaded = load i64, i64* %gep, align 4
+  %tmp7 = icmp slt i64 %iv.next, 1000
+  br i1 %tmp7, label %loop, label %exit
+}
+
+!0 = !{i64 0, i64 100}

Added: llvm/trunk/test/Transforms/IRCE/bug-loop-varying-upper-limit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/bug-loop-varying-upper-limit.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/bug-loop-varying-upper-limit.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/bug-loop-varying-upper-limit.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -irce-print-changed-loops -S -verify-loop-info -irce -verify < %s 2>&1 | FileCheck %s
+; RUN: opt -irce-print-changed-loops -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' -verify < %s 2>&1 | FileCheck %s
+
+; CHECK-NOT: constrained loop
+
+define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/bug-mismatched-types.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/bug-mismatched-types.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/bug-mismatched-types.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/bug-mismatched-types.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,67 @@
+; RUN: opt -verify-loop-info -irce -S < %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s
+
+; These test cases don't check the correctness of the transform, but
+; that -irce does not crash in the presence of certain things in
+; the IR:
+
+define void @mismatched_types_1() {
+; In this test case, the safe range for the only range check in the
+; loop is of type [i32, i32) while the backedge taken count is of type
+; i64.
+
+; CHECK-LABEL: @mismatched_types_1(
+entry:
+  br label %for.body
+
+for.body:
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
+  %0 = trunc i64 %indvars.iv to i32
+  %1 = icmp ult i32 %0, 7
+  br i1 %1, label %switch.lookup, label %for.inc
+
+switch.lookup:
+  br label %for.inc
+
+for.inc:
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %cmp55 = icmp slt i64 %indvars.iv.next, 11
+  br i1 %cmp55, label %for.body, label %for.end
+
+for.end:
+  unreachable
+}
+
+define void @mismatched_types_2() {
+; In this test case, there are two range check in the loop, one with a
+; safe range of type [i32, i32) and one with a safe range of type
+; [i64, i64).
+
+; CHECK-LABEL: @mismatched_types_2(
+entry:
+  br label %for.body.a
+
+for.body.a:
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
+  %cond.a = icmp ult i64 %indvars.iv, 7
+  br i1 %cond.a, label %switch.lookup.a, label %for.body.b
+
+switch.lookup.a:
+  br label %for.body.b
+
+for.body.b:
+  %truncated = trunc i64 %indvars.iv to i32
+  %cond.b = icmp ult i32 %truncated, 7
+  br i1 %cond.b, label %switch.lookup.b, label %for.inc
+
+switch.lookup.b:
+  br label %for.inc
+
+for.inc:
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %cmp55 = icmp slt i64 %indvars.iv.next, 11
+  br i1 %cmp55, label %for.body.a, label %for.end
+
+for.end:
+  unreachable
+}

Added: llvm/trunk/test/Transforms/IRCE/clamp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/clamp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/clamp.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/clamp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,95 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; The test demonstrates that incorrect behavior of Clamp may lead to incorrect
+; calculation of post-loop exit condition.
+
+; CHECK-LABEL: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in_bounds<exiting>,%not_zero<latch><exiting>
+; CHECK-NOT: irce: in function test_02: constrained Loop
+
+define void @test_01() {
+
+; CHECK-LABEL: test_01
+
+entry:
+  %indvars.iv.next467 = add nuw nsw i64 2, 1
+  %length.i167 = load i32, i32 addrspace(1)* undef, align 8
+  %tmp21 = zext i32 %length.i167 to i64
+  %tmp34 = load atomic i32, i32 addrspace(1)* undef unordered, align 4
+  %tmp35 = add i32 %tmp34, -9581
+  %tmp36 = icmp ugt i32 %length.i167, 1
+  br i1 %tmp36, label %preheader, label %exit
+
+exit:                                          ; preds = %in_bounds, %loop, %not_zero, %entry
+  ret void
+
+preheader:                                 ; preds = %entry
+; CHECK:      preheader:
+; CHECK-NEXT:   %length_gep.i146 = getelementptr inbounds i8, i8 addrspace(1)* undef, i64 8
+; CHECK-NEXT:   %length_gep_typed.i147 = bitcast i8 addrspace(1)* undef to i32 addrspace(1)*
+; CHECK-NEXT:   %tmp43 = icmp ult i64 %indvars.iv.next467, %tmp21
+; CHECK-NEXT:   [[C0:%[^ ]+]] = icmp ugt i64 %tmp21, 1
+; CHECK-NEXT:   %exit.mainloop.at = select i1 [[C0]], i64 %tmp21, i64 1
+; CHECK-NEXT:   [[C1:%[^ ]+]] = icmp ult i64 1, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[C1]], label %loop.preheader, label %main.pseudo.exit
+
+  %length_gep.i146 = getelementptr inbounds i8, i8 addrspace(1)* undef, i64 8
+  %length_gep_typed.i147 = bitcast i8 addrspace(1)* undef to i32 addrspace(1)*
+  %tmp43 = icmp ult i64 %indvars.iv.next467, %tmp21
+  br label %loop
+
+not_zero:                                       ; preds = %in_bounds
+; CHECK:      not_zero:
+; CHECK:        %tmp56 = icmp ult i64 %indvars.iv.next, %tmp21
+; CHECK-NEXT:   [[COND:%[^ ]+]] = icmp ult i64 %indvars.iv.next, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND]], label %loop, label %main.exit.selector
+
+  %tmp51 = trunc i64 %indvars.iv.next to i32
+  %tmp53 = mul i32 %tmp51, %tmp51
+  %tmp54 = add i32 %tmp53, -9582
+  %tmp55 = add i32 %tmp54, %tmp62
+  %tmp56 = icmp ult i64 %indvars.iv.next, %tmp21
+  br i1 %tmp56, label %loop, label %exit
+
+loop:                                       ; preds = %not_zero, %preheader
+  %tmp62 = phi i32 [ 1, %preheader ], [ %tmp55, %not_zero ]
+  %indvars.iv750 = phi i64 [ 1, %preheader ], [ %indvars.iv.next, %not_zero ]
+  %length.i148 = load i32, i32 addrspace(1)* %length_gep_typed.i147, align 8
+  %tmp68 = zext i32 %length.i148 to i64
+  %tmp97 = icmp ult i64 2, %tmp68
+  %or.cond = and i1 %tmp43, %tmp97
+  %tmp99 = icmp ult i64 %indvars.iv750, %tmp21
+  %or.cond1 = and i1 %or.cond, %tmp99
+  br i1 %or.cond1, label %in_bounds, label %exit
+
+in_bounds:                                       ; preds = %loop
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv750, 3
+  %tmp107 = icmp ult i64 %indvars.iv.next, 2
+  br i1 %tmp107, label %not_zero, label %exit
+}
+
+define void @test_02() {
+
+; Now IRCE is smart enough to understand that the safe range here is empty.
+; Previously it executed the entire loop in safe preloop and never actually
+; entered the main loop.
+
+entry:
+  br label %loop
+
+loop:                                    ; preds = %in_bounds, %entry
+  %iv1 = phi i64 [ 3, %entry ], [ %iv1.next, %in_bounds ]
+  %iv2 = phi i64 [ 4294967295, %entry ], [ %iv2.next, %in_bounds ]
+  %iv2.offset = add i64 %iv2, 1
+  %rc = icmp ult i64 %iv2.offset, 400
+  br i1 %rc, label %in_bounds, label %bci_321
+
+bci_321:                                          ; preds = %in_bounds, %loop
+  ret void
+
+in_bounds:                                 ; preds = %loop
+  %iv1.next = add nuw nsw i64 %iv1, 2
+  %iv2.next = add nuw nsw i64 %iv2, 2
+  %cond = icmp ugt i64 %iv1, 204
+  br i1 %cond, label %bci_321, label %loop
+}

Added: llvm/trunk/test/Transforms/IRCE/conjunctive-checks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/conjunctive-checks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/conjunctive-checks.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/conjunctive-checks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,110 @@
+; RUN: opt -S -verify-loop-info -irce < %s | FileCheck %s
+; RUN: opt -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s | FileCheck %s
+
+define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) {
+; CHECK-LABEL: @f_0(
+
+; CHECK: loop.preheader:
+; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
+; CHECK: [[not_safe_range_end:[^ ]+]] = sub i32 3, %len
+; CHECK: [[not_exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_n]], [[not_safe_range_end]]
+; CHECK: [[not_exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_main_loop_at_hiclamp_cmp]], i32 [[not_n]], i32 [[not_safe_range_end]]
+; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_main_loop_at_hiclamp]]
+; CHECK: [[exit_main_loop_at_loclamp_cmp:[^ ]+]] = icmp sgt i32 [[exit_main_loop_at_hiclamp]], 0
+; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = select i1 [[exit_main_loop_at_loclamp_cmp]], i32 [[exit_main_loop_at_hiclamp]], i32 0
+; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]]
+; CHECK: br i1 [[enter_main_loop]], label %loop.preheader2, label %main.pseudo.exit
+
+; CHECK: loop.preheader2:
+; CHECK: br label %loop
+
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.for.abc = add i32 %idx, 4
+  %abc.actual = icmp slt i32 %idx.for.abc, %len
+  %cond = load volatile i1, i1* %cond_buf
+  %abc = and i1 %cond, %abc.actual
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+; CHECK: loop:
+; CHECK:  %cond = load volatile i1, i1* %cond_buf
+; CHECK:  %abc = and i1 %cond, true
+; CHECK:  br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit3, !prof !1
+
+; CHECK: out.of.bounds.loopexit:
+; CHECK:  br label %out.of.bounds
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx.for.abc
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+define void @f_1(
+    i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) {
+; CHECK-LABEL: @f_1(
+
+; CHECK: loop.preheader:
+; CHECK: [[not_len_b:[^ ]+]] = sub i32 -1, %len.b
+; CHECK: [[not_len_a:[^ ]+]] = sub i32 -1, %len.a
+; CHECK: [[smax_not_len_cond:[^ ]+]] = icmp sgt i32 [[not_len_b]], [[not_len_a]]
+; CHECK: [[smax_not_len:[^ ]+]] = select i1 [[smax_not_len_cond]], i32 [[not_len_b]], i32 [[not_len_a]]
+; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
+; CHECK: [[not_upper_limit_cond_loclamp:[^ ]+]] = icmp sgt i32 [[smax_not_len]], [[not_n]]
+; CHECK: [[not_upper_limit_loclamp:[^ ]+]] = select i1 [[not_upper_limit_cond_loclamp]], i32 [[smax_not_len]], i32 [[not_n]]
+; CHECK: [[upper_limit_loclamp:[^ ]+]] = sub i32 -1, [[not_upper_limit_loclamp]]
+; CHECK: [[upper_limit_cmp:[^ ]+]] = icmp sgt i32 [[upper_limit_loclamp]], 0
+; CHECK: [[upper_limit:[^ ]+]] = select i1 [[upper_limit_cmp]], i32 [[upper_limit_loclamp]], i32 0
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.b = load i32, i32* %b_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc.a = icmp slt i32 %idx, %len.a
+  %abc.b = icmp slt i32 %idx, %len.b
+  %abc = and i1 %abc.a, %abc.b
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+; CHECK: loop:
+; CHECK:   %abc = and i1 true, true
+; CHECK:   br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit4, !prof !1
+
+; CHECK: out.of.bounds.loopexit:
+; CHECK-NEXT:  br label %out.of.bounds
+
+
+ in.bounds:
+  %addr.a = getelementptr i32, i32* %arr_a, i32 %idx
+  store i32 0, i32* %addr.a
+  %addr.b = getelementptr i32, i32* %arr_b, i32 %idx
+  store i32 -1, i32* %addr.b
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/correct-loop-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/correct-loop-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/correct-loop-info.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/correct-loop-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,183 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -irce < %s -S | FileCheck %s
+; RUN: opt -passes='require<branch-prob>,loop(irce)' < %s -S | FileCheck %s
+
+; REQUIRES: asserts
+
+; IRCE creates the pre and post loop, and invokes the
+; canonicalizing these loops to LCSSA and loop-simplfy structure. Make sure that the update to the loopinfo does not
+; incorrectly change the header while canonicalizing these pre/post loops. We
+; were incorrectly updating LI when the split loop is a subloop as in the case below.
+source_filename = "correct-loop-info.ll"
+
+define void @baz() personality i32* ()* @ham {
+; CHECK-LABEL: @baz(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[OUTERHEADER:%.*]]
+; CHECK:       outerheader:
+; CHECK-NEXT:    [[TMP:%.*]] = icmp slt i32 undef, 84
+; CHECK-NEXT:    br i1 [[TMP]], label [[BB2:%.*]], label [[BB16:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 false, label [[INNERHEADER_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
+; CHECK:       innerheader.preloop.preheader:
+; CHECK-NEXT:    br label [[INNERHEADER_PRELOOP:%.*]]
+; CHECK:       mainloop:
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[INDVAR_END:%.*]], 0
+; CHECK-NEXT:    br i1 [[TMP0]], label [[INNERHEADER_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       innerheader.preheader:
+; CHECK-NEXT:    br label [[INNERHEADER:%.*]]
+; CHECK:       innerheader:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[TMP6:%.*]], [[BB8:%.*]] ], [ [[TMP4_PRELOOP_COPY:%.*]], [[INNERHEADER_PREHEADER]] ]
+; CHECK-NEXT:    invoke void @pluto()
+; CHECK-NEXT:    to label [[BB5:%.*]] unwind label %outer_exiting.loopexit.split-lp.loopexit.split-lp
+; CHECK:       bb5:
+; CHECK-NEXT:    [[TMP6]] = add i32 [[TMP4]], 1
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 1
+; CHECK-NEXT:    br i1 true, label [[BB8]], label [[EXIT3_LOOPEXIT5:%.*]]
+; CHECK:       bb8:
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp slt i32 [[TMP6]], 84
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[TMP6]], 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[INNERHEADER]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[TMP6_LCSSA:%.*]] = phi i32 [ [[TMP6]], [[BB8]] ]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP6_LCSSA]], 84
+; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[BB13:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[TMP4_COPY:%.*]] = phi i32 [ [[TMP4_PRELOOP_COPY]], [[MAINLOOP:%.*]] ], [ [[TMP6_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END1:%.*]] = phi i32 [ [[INDVAR_END]], [[MAINLOOP]] ], [ [[TMP6_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       outer_exiting.loopexit:
+; CHECK-NEXT:    [[LPAD_LOOPEXIT:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    br label [[OUTER_EXITING:%.*]]
+; CHECK:       outer_exiting.loopexit.split-lp.loopexit:
+; CHECK-NEXT:    [[LPAD_LOOPEXIT2:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    br label %outer_exiting.loopexit.split-lp
+; CHECK:       outer_exiting.loopexit.split-lp.loopexit.split-lp:
+; CHECK-NEXT:    %lpad.loopexit.split-lp3 = landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    br label %outer_exiting.loopexit.split-lp
+; CHECK:       outer_exiting.loopexit.split-lp:
+; CHECK-NEXT:    br label [[OUTER_EXITING]]
+; CHECK:       outer_exiting:
+; CHECK-NEXT:    switch i32 undef, label [[EXIT2:%.*]] [
+; CHECK-NEXT:    i32 142, label [[BB14:%.*]]
+; CHECK-NEXT:    i32 448, label [[EXIT:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       exit3.loopexit:
+; CHECK-NEXT:    br label [[EXIT3:%.*]]
+; CHECK:       exit3.loopexit4:
+; CHECK-NEXT:    br label [[EXIT3]]
+; CHECK:       exit3.loopexit5:
+; CHECK-NEXT:    br label [[EXIT3]]
+; CHECK:       exit3:
+; CHECK-NEXT:    ret void
+; CHECK:       bb13.loopexit:
+; CHECK-NEXT:    br label [[BB13]]
+; CHECK:       bb13:
+; CHECK-NEXT:    unreachable
+; CHECK:       bb14:
+; CHECK-NEXT:    br label [[OUTERHEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       bb16:
+; CHECK-NEXT:    ret void
+; CHECK:       exit2:
+; CHECK-NEXT:    ret void
+; CHECK:       innerheader.preloop:
+; CHECK-NEXT:    [[TMP4_PRELOOP:%.*]] = phi i32 [ [[TMP6_PRELOOP:%.*]], [[BB8_PRELOOP:%.*]] ], [ undef, [[INNERHEADER_PRELOOP_PREHEADER]] ]
+; CHECK-NEXT:    invoke void @pluto()
+; CHECK-NEXT:    to label [[BB5_PRELOOP:%.*]] unwind label [[OUTER_EXITING_LOOPEXIT:%.*]]
+; CHECK:       bb5.preloop:
+; CHECK-NEXT:    [[TMP6_PRELOOP]] = add i32 [[TMP4_PRELOOP]], 1
+; CHECK-NEXT:    [[TMP7_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 1
+; CHECK-NEXT:    br i1 [[TMP7_PRELOOP]], label [[BB8_PRELOOP]], label [[EXIT3_LOOPEXIT:%.*]]
+; CHECK:       bb8.preloop:
+; CHECK-NEXT:    [[TMP9_PRELOOP:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], 84
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP6_PRELOOP]], -1
+; CHECK-NEXT:    br i1 [[TMP3]], label [[INNERHEADER_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop !0, !irce.loop.clone !5
+; CHECK:       preloop.exit.selector:
+; CHECK-NEXT:    [[TMP6_PRELOOP_LCSSA:%.*]] = phi i32 [ [[TMP6_PRELOOP]], [[BB8_PRELOOP]] ]
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i32 [[TMP6_PRELOOP_LCSSA]], 84
+; CHECK-NEXT:    br i1 [[TMP4]], label [[PRELOOP_PSEUDO_EXIT]], label [[BB13]]
+; CHECK:       preloop.pseudo.exit:
+; CHECK-NEXT:    [[TMP4_PRELOOP_COPY]] = phi i32 [ undef, [[BB2]] ], [ [[TMP6_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END]] = phi i32 [ undef, [[BB2]] ], [ [[TMP6_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[MAINLOOP]]
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[INNERHEADER_POSTLOOP:%.*]]
+; CHECK:       innerheader.postloop:
+; CHECK-NEXT:    [[TMP4_POSTLOOP:%.*]] = phi i32 [ [[TMP6_POSTLOOP:%.*]], [[BB8_POSTLOOP:%.*]] ], [ [[TMP4_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    invoke void @pluto()
+; CHECK-NEXT:    to label [[BB5_POSTLOOP:%.*]] unwind label %outer_exiting.loopexit.split-lp.loopexit
+; CHECK:       bb5.postloop:
+; CHECK-NEXT:    [[TMP6_POSTLOOP]] = add i32 [[TMP4_POSTLOOP]], 1
+; CHECK-NEXT:    [[TMP7_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 1
+; CHECK-NEXT:    br i1 [[TMP7_POSTLOOP]], label [[BB8_POSTLOOP]], label [[EXIT3_LOOPEXIT4:%.*]]
+; CHECK:       bb8.postloop:
+; CHECK-NEXT:    [[TMP9_POSTLOOP:%.*]] = icmp slt i32 [[TMP6_POSTLOOP]], 84
+; CHECK-NEXT:    br i1 [[TMP9_POSTLOOP]], label [[INNERHEADER_POSTLOOP]], label [[BB13_LOOPEXIT:%.*]], !llvm.loop !6, !irce.loop.clone !5
+;
+bb:
+  br label %outerheader
+
+outerheader:                                              ; preds = %bb14, %bb
+  %tmp = icmp slt i32 undef, 84
+  br i1 %tmp, label %bb2, label %bb16
+
+bb2:                                              ; preds = %outerheader
+  br label %innerheader
+
+innerheader:                                              ; preds = %bb8, %bb2
+  %tmp4 = phi i32 [ %tmp6, %bb8 ], [ undef, %bb2 ]
+  invoke void @pluto()
+  to label %bb5 unwind label %outer_exiting
+
+bb5:                                              ; preds = %innerheader
+  %tmp6 = add i32 %tmp4, 1
+  %tmp7 = icmp slt i32 %tmp6, 1
+  br i1 %tmp7, label %bb8, label %exit3
+
+bb8:                                              ; preds = %bb5
+  %tmp9 = icmp slt i32 %tmp6, 84
+  br i1 %tmp9, label %innerheader, label %bb13
+
+outer_exiting:                                             ; preds = %innerheader
+  %tmp11 = landingpad { i8*, i32 }
+  cleanup
+  switch i32 undef, label %exit2 [
+  i32 142, label %bb14
+  i32 448, label %exit
+  ]
+
+exit3:                                             ; preds = %bb5
+  ret void
+
+bb13:                                             ; preds = %bb8
+  unreachable
+
+bb14:                                             ; preds = %outer_exiting
+  br label %outerheader
+
+exit:                                             ; preds = %outer_exiting
+  ret void
+
+bb16:                                             ; preds = %outerheader
+  ret void
+
+exit2:                                             ; preds = %outer_exiting
+  ret void
+}
+
+declare i32* @ham()
+
+declare void @pluto()
+
+!0 = distinct !{!0, !1, !2, !3, !4}
+!1 = !{!"llvm.loop.unroll.disable"}
+!2 = !{!"llvm.loop.vectorize.enable", i1 false}
+!3 = !{!"llvm.loop.licm_versioning.disable"}
+!4 = !{!"llvm.loop.distribute.enable", i1 false}
+!5 = !{}
+!6 = distinct !{!6, !1, !2, !3, !4}

Added: llvm/trunk/test/Transforms/IRCE/decrementing-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/decrementing-loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/decrementing-loop.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/decrementing-loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,266 @@
+; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
+
+define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  %start = sub i32 %n, 1
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ]
+  %idx.dec = sub i32 %idx, 1
+  %abc.high = icmp slt i32 %idx, %len
+  %abc.low = icmp sge i32 %idx, 0
+  %abc = and i1 %abc.low, %abc.high
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp sgt i32 %idx.dec, -1
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+
+; CHECK: loop.preheader:
+; CHECK:   [[not_len:[^ ]+]] = sub i32 -1, %len
+; CHECK:   [[not_n:[^ ]+]] = sub i32 -1, %n
+; CHECK:   [[not_len_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_len]], [[not_n]]
+; CHECK:   [[not_len_hiclamp:[^ ]+]] = select i1 [[not_len_hiclamp_cmp]], i32 [[not_len]], i32 [[not_n]]
+; CHECK:   [[len_hiclamp:[^ ]+]] = sub i32 -1, [[not_len_hiclamp]]
+; CHECK:   [[not_exit_preloop_at_cmp:[^ ]+]] = icmp sgt i32 [[len_hiclamp]], 0
+; CHECK:   [[not_exit_preloop_at:[^ ]+]] = select i1 [[not_exit_preloop_at_cmp]], i32 [[len_hiclamp]], i32 0
+; CHECK:   %exit.preloop.at = add i32 [[not_exit_preloop_at]], -1
+}
+
+; Make sure that we can eliminate the range check when the loop looks like:
+; for (i = len.a - 1; i >= 0; --i)
+;   b[i] = a[i];
+define void @test_01(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) {
+
+; CHECK-LABEL: test_01
+; CHECK:       mainloop:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK:         %rc = and i1 true, true
+; CHECK:       loop.preloop:
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.b = load i32, i32* %b_len_ptr, !range !0
+  %first.itr.check = icmp ne i32 %len.a, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = sub i32 %idx, 1
+  %rca = icmp ult i32 %idx.next, %len.a
+  %rcb = icmp ult i32 %idx.next, %len.b
+  %rc = and i1 %rca, %rcb
+  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %el.a = getelementptr i32, i32* %a, i32 %idx.next
+  %el.b = getelementptr i32, i32* %b, i32 %idx.next
+  %v = load i32, i32* %el.a
+  store i32 %v, i32* %el.b
+  %loop.cond = icmp slt i32 %idx, 2
+  br i1 %loop.cond, label %exit, label %loop
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; Same as test_01, but the latch condition is unsigned
+define void @test_02(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) {
+
+; CHECK-LABEL: test_02
+; CHECK:       mainloop:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK:         %rc = and i1 true, true
+; CHECK:       loop.preloop:
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.b = load i32, i32* %b_len_ptr, !range !0
+  %first.itr.check = icmp ne i32 %len.a, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = sub i32 %idx, 1
+  %rca = icmp ult i32 %idx.next, %len.a
+  %rcb = icmp ult i32 %idx.next, %len.b
+  %rc = and i1 %rca, %rcb
+  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %el.a = getelementptr i32, i32* %a, i32 %idx.next
+  %el.b = getelementptr i32, i32* %b, i32 %idx.next
+  %v = load i32, i32* %el.a
+  store i32 %v, i32* %el.b
+  %loop.cond = icmp ult i32 %idx, 2
+  br i1 %loop.cond, label %exit, label %loop
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; Check that we can figure out that IV is non-negative via implication through
+; Phi node.
+define void @test_03(i32* %a, i32* %a_len_ptr, i1 %cond) {
+
+; CHECK-LABEL: test_03
+; CHECK:       mainloop:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
+; CHECK:       loop.preloop:
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.minus.one = sub nsw i32 %len.a, 1
+  %len.minus.two = sub nsw i32 %len.a, 2
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ]
+  %first.itr.check = icmp sgt i32 %len.a, 3
+  br i1 %first.itr.check, label %loop, label %exit
+
+loop:
+  %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ]
+  %idx.next = sub i32 %idx, 1
+  %rc = icmp ult i32 %idx.next, %len.a
+  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
+
+in.bounds:
+  %el.a = getelementptr i32, i32* %a, i32 %idx.next
+  %v = load i32, i32* %el.a
+  %loop.cond = icmp slt i32 %idx, 2
+  br i1 %loop.cond, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check that we can figure out that IV is non-negative via implication through
+; two Phi nodes.
+define void @test_04(i32* %a, i32* %a_len_ptr, i1 %cond) {
+
+; CHECK-LABEL: test_04
+; CHECK:       mainloop:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
+; CHECK:       loop.preloop:
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.minus.one = sub nsw i32 %len.a, 1
+  %len.plus.one = add nsw i32 %len.a, 1
+  %len.minus.two = sub nsw i32 %len.a, 2
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ]
+  %len.phi = phi i32 [ %len.a, %if.true ], [ %len.plus.one, %if.false ]
+  %first.itr.check = icmp sgt i32 %len.a, 3
+  br i1 %first.itr.check, label %loop, label %exit
+
+loop:
+  %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ]
+  %idx.next = sub i32 %idx, 1
+  %rc = icmp ult i32 %idx.next, %len.phi
+  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
+
+in.bounds:
+  %el.a = getelementptr i32, i32* %a, i32 %idx.next
+  %v = load i32, i32* %el.a
+  %loop.cond = icmp slt i32 %idx, 2
+  br i1 %loop.cond, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check that we can figure out that IV is non-negative via implication through
+; two Phi nodes, one being AddRec.
+define void @test_05(i32* %a, i32* %a_len_ptr, i1 %cond) {
+
+; CHECK-LABEL: test_05
+; CHECK:       mainloop:
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK:         br i1 true, label %in.bounds, label %out.of.bounds
+; CHECK:       loop.preloop:
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.minus.one = sub nsw i32 %len.a, 1
+  %len.plus.one = add nsw i32 %len.a, 1
+  %len.minus.two = sub nsw i32 %len.a, 2
+  br label %merge
+
+merge:
+  %starting.value = phi i32 [ %len.minus.two, %entry ], [ %len.minus.one, %merge ]
+  %len.phi = phi i32 [ %len.a, %entry ], [ %len.phi.next, %merge ]
+  %len.phi.next = add nsw i32 %len.phi, 1
+  br i1 true, label %first.iter.check, label %merge
+
+first.iter.check:
+  %first.itr.check = icmp sgt i32 %len.a, 3
+  br i1 %first.itr.check, label %loop, label %exit
+
+loop:
+  %idx = phi i32 [ %starting.value, %first.iter.check ] , [ %idx.next, %in.bounds ]
+  %idx.next = sub i32 %idx, 1
+  %rc = icmp ult i32 %idx.next, %len.phi
+  br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1
+
+in.bounds:
+  %el.a = getelementptr i32, i32* %a, i32 %idx.next
+  %v = load i32, i32* %el.a
+  %loop.cond = icmp slt i32 %idx, 2
+  br i1 %loop.cond, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/empty_ranges.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/empty_ranges.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/empty_ranges.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/empty_ranges.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S
+
+; Make sure that IRCE doesn't apply in case of empty ranges.
+; (i + 30 < 40) if i in [-30, 10).
+; Intersected with iteration space, it is [0, 10).
+; (i - 60 < 40) if i in [60 , 100).
+; The intersection with safe iteration space is the empty range [60, 10).
+; It is better to eliminate one range check than attempt to eliminate both given
+; that we will never go to the main loop in the latter case and basically
+; only duplicate code with no benefits.
+
+define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_01(
+; CHECK-NOT:   preloop
+; CHECK:       entry:
+; CHECK-NEXT:    br i1 true, label %loop.preheader, label %main.pseudo.exit
+; CHECK:       in.bounds.1:
+; CHECK-NEXT:    %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:    store i32 0, i32* %addr
+; CHECK-NEXT:    %off1 = add i32 %idx, 30
+; CHECK-NEXT:    %c2 = icmp slt i32 %off1, 40
+; CHECK-NEXT:    br i1 true, label %in.bounds.2, label %exit.loopexit2
+; CHECK:       in.bounds.2:
+; CHECK-NEXT:    %off2 = add i32 %idx, -60
+; CHECK-NEXT:    %c3 = icmp slt i32 %off2, 40
+; CHECK-NEXT:    br i1 %c3, label %in.bounds.3, label %exit.loopexit2
+; CHECK:       in.bounds.3:
+; CHECK-NEXT:    %next = icmp ult i32 %idx.next, 100
+; CHECK-NEXT:    [[COND1:%[^ ]+]] = icmp ult i32 %idx.next, 10
+; CHECK-NEXT:    br i1 [[COND1]], label %loop, label %main.exit.selector
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds.3 ]
+; CHECK-NEXT:    [[COND2:%[^ ]+]] = icmp ult i32 %idx.next.lcssa, 100
+; CHECK-NEXT:    br i1 [[COND2]], label %main.pseudo.exit, label %exit
+; CHECK:       postloop:
+
+entry:
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds.3 ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %c1 = icmp slt i32 %idx, 20
+  br i1 %c1, label %in.bounds.1, label %out.of.bounds
+
+in.bounds.1:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %off1 = add i32 %idx, 30
+  %c2 = icmp slt i32 %off1, 40
+  br i1 %c2, label %in.bounds.2, label %exit
+
+in.bounds.2:
+  %off2 = add i32 %idx, -60
+  %c3 = icmp slt i32 %off2, 40
+  br i1 %c3, label %in.bounds.3, label %exit
+
+in.bounds.3:
+  %next = icmp ult i32 %idx.next, 100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IRCE/eq_ne.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/eq_ne.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/eq_ne.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/eq_ne.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,288 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_01u: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+; Show that IRCE can turn 'ne' condition to 'slt' in increasing IV when the IV
+; can be negative at some point.
+define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_01
+; CHECK:        main.exit.selector:
+; CHECK-NEXT:     [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], 100
+; CHECK-NEXT:     br i1 [[COND]]
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ -3, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ne i32 %idx.next, 100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that IRCE can turn 'ne' condition to 'ult' in increasing IV when IV is
+; non-negative.
+define void @test_01u(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_01u
+; CHECK:        main.exit.selector:
+; CHECK-NEXT:     [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], 100
+; CHECK-NEXT:     br i1 [[COND]]
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ne i32 %idx.next, 100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that if n is not known to be greater than the starting value, IRCE
+; doesn't apply.
+define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_02(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ne i32 %idx.next, -100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that IRCE can turn 'eq' condition to 'sge' in increasing IV.
+define void @test_03(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_03(
+; CHECK:        main.exit.selector:
+; CHECK-NEXT:     [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], 100
+; CHECK-NEXT:     br i1 [[COND]]
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp eq i32 %idx.next, 100
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+define void @test_04(i32* %arr, i32* %a_len_ptr) #0 {
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp eq i32 %idx.next, -100
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that IRCE can turn 'ne' condition to 'sgt' in decreasing IV.
+define void @test_05(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_05(
+; CHECK:        preloop.exit.selector:
+; CHECK-NEXT:     [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], 0
+; CHECK-NEXT:     br i1 [[COND]]
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ne i32 %idx.next, 0
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that IRCE cannot turn 'ne' condition to 'sgt' in decreasing IV if the end
+; value is not proved to be less than the start value.
+define void @test_06(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_06(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ne i32 %idx.next, 120
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that IRCE can turn 'eq' condition to 'slt' in decreasing IV.
+define void @test_07(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_07(
+; CHECK:        preloop.exit.selector:
+; CHECK-NEXT:     [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], 0
+; CHECK-NEXT:     br i1 [[COND]]
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp eq i32 %idx.next, 0
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Show that IRCE cannot turn 'eq' condition to 'slt' in decreasing IV if the end
+; value is not proved to be less than the start value.
+define void @test_08(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_08(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp eq i32 %idx.next, 120
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 50}

Added: llvm/trunk/test/Transforms/IRCE/low-becount.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/low-becount.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/low-becount.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/low-becount.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
+; 
+; TODO: new-pm version should be enabled after we decide on branch-probability handling for loop passes
+; TODO: opt -irce-print-changed-loops -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK-NOT: constrained Loop
+
+define void @low_profiled_be_count(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit, !prof !2
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}
+!2 = !{!"branch_weights", i32 4, i32 64}

Added: llvm/trunk/test/Transforms/IRCE/multiple-access-no-preloop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/multiple-access-no-preloop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/multiple-access-no-preloop.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/multiple-access-no-preloop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,67 @@
+; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
+
+define void @multiple_access_no_preloop(
+    i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) {
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.b = load i32, i32* %b_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds.b ]
+  %idx.next = add i32 %idx, 1
+  %abc.a = icmp slt i32 %idx, %len.a
+  br i1 %abc.a, label %in.bounds.a, label %out.of.bounds, !prof !1
+
+ in.bounds.a:
+  %addr.a = getelementptr i32, i32* %arr_a, i32 %idx
+  store i32 0, i32* %addr.a
+  %abc.b = icmp slt i32 %idx, %len.b
+  br i1 %abc.b, label %in.bounds.b, label %out.of.bounds, !prof !1
+
+ in.bounds.b:
+  %addr.b = getelementptr i32, i32* %arr_b, i32 %idx
+  store i32 -1, i32* %addr.b
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @multiple_access_no_preloop(
+
+; CHECK: loop.preheader:
+; CHECK: [[not_len_b:[^ ]+]] = sub i32 -1, %len.b
+; CHECK: [[not_len_a:[^ ]+]] = sub i32 -1, %len.a
+; CHECK: [[smax_not_len_cond:[^ ]+]] = icmp sgt i32 [[not_len_b]], [[not_len_a]]
+; CHECK: [[smax_not_len:[^ ]+]] = select i1 [[smax_not_len_cond]], i32 [[not_len_b]], i32 [[not_len_a]]
+; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
+; CHECK: [[not_upper_limit_cond_loclamp:[^ ]+]] = icmp sgt i32 [[smax_not_len]], [[not_n]]
+; CHECK: [[not_upper_limit_loclamp:[^ ]+]] = select i1 [[not_upper_limit_cond_loclamp]], i32 [[smax_not_len]], i32 [[not_n]]
+; CHECK: [[upper_limit_loclamp:[^ ]+]] = sub i32 -1, [[not_upper_limit_loclamp]]
+; CHECK: [[upper_limit_cmp:[^ ]+]] = icmp sgt i32 [[upper_limit_loclamp]], 0
+; CHECK: [[upper_limit:[^ ]+]] = select i1 [[upper_limit_cmp]], i32 [[upper_limit_loclamp]], i32 0
+
+; CHECK: loop:
+; CHECK: br i1 true, label %in.bounds.a, label %out.of.bounds
+
+; CHECK: in.bounds.a:
+; CHECK: br i1 true, label %in.bounds.b, label %out.of.bounds
+
+; CHECK: in.bounds.b:
+; CHECK: [[main_loop_cond:[^ ]+]] = icmp slt i32 %idx.next, [[upper_limit]]
+; CHECK: br i1 [[main_loop_cond]], label %loop, label %main.exit.selector
+
+; CHECK: in.bounds.b.postloop:
+; CHECK: %next.postloop = icmp slt i32 %idx.next.postloop, %n
+; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/non_known_positive_end.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/non_known_positive_end.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/non_known_positive_end.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/non_known_positive_end.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,139 @@
+; RUN: opt -verify-loop-info -irce -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
+
+; Make sure that we can pick up both range checks.
+define void @test_01(i32 *%arr, i32* %a_len_ptr, i32* %size_ptr) {
+
+; CHECK-LABEL: @test_01(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %size = load i32, i32* %size_ptr
+  %first_iter_check = icmp sle i32 %size, 0
+  br i1 %first_iter_check, label %exit, label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc1 = icmp slt i32 %iv, %len
+  %rc2 = icmp slt i32 %iv, %size
+  ; CHECK: %rc = and i1 true, true
+  %rc = and i1 %rc1, %rc2
+  br i1 %rc, label %backedge, label %out_of_bounds
+
+
+backedge:
+  %iv.next = add i32 %iv, 1
+  %arr_el_ptr = getelementptr i32, i32* %arr, i32 %iv
+  %el = load i32, i32* %arr_el_ptr
+  %loopcond = icmp ne i32 %iv, %size
+  br i1 %loopcond, label %loop, label %exit
+
+exit:
+  ret void
+
+out_of_bounds:
+  ret void
+}
+
+; Same as test_01, unsigned predicates.
+define void @test_02(i32 *%arr, i32* %a_len_ptr, i32* %size_ptr) {
+
+; CHECK-LABEL: @test_02(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %size = load i32, i32* %size_ptr
+  %first_iter_check = icmp sle i32 %size, 0
+  br i1 %first_iter_check, label %exit, label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc1 = icmp ult i32 %iv, %len
+  %rc2 = icmp ult i32 %iv, %size
+  ; CHECK: %rc = and i1 true, true
+  %rc = and i1 %rc1, %rc2
+  br i1 %rc, label %backedge, label %out_of_bounds
+
+
+backedge:
+  %iv.next = add i32 %iv, 1
+  %arr_el_ptr = getelementptr i32, i32* %arr, i32 %iv
+  %el = load i32, i32* %arr_el_ptr
+  %loopcond = icmp ne i32 %iv, %size
+  br i1 %loopcond, label %loop, label %exit
+
+exit:
+  ret void
+
+out_of_bounds:
+  ret void
+}
+
+define void @test_03(i32 *%arr, i32* %a_len_ptr, i32* %size_ptr) {
+
+; CHECK-LABEL: @test_03(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %size = load i32, i32* %size_ptr
+  %first_iter_check = icmp eq i32 %size, 0
+  br i1 %first_iter_check, label %exit, label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc1 = icmp slt i32 %iv, %len
+  %rc2 = icmp slt i32 %iv, %size
+  ; CHECK: %rc = and i1 true, true
+  %rc = and i1 %rc1, %rc2
+  br i1 %rc, label %backedge, label %out_of_bounds
+
+
+backedge:
+  %iv.next = add i32 %iv, 1
+  %arr_el_ptr = getelementptr i32, i32* %arr, i32 %iv
+  %el = load i32, i32* %arr_el_ptr
+  %loopcond = icmp ne i32 %iv, %len
+  br i1 %loopcond, label %loop, label %exit
+
+exit:
+  ret void
+
+out_of_bounds:
+  ret void
+}
+
+define void @test_04(i32 *%arr, i32* %a_len_ptr, i32* %size_ptr) {
+
+; CHECK-LABEL: @test_04(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %size = load i32, i32* %size_ptr
+  %first_iter_check = icmp eq i32 %size, 0
+  br i1 %first_iter_check, label %exit, label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc1 = icmp ult i32 %iv, %len
+  %rc2 = icmp ult i32 %iv, %size
+  ; CHECK: %rc = and i1 true, true
+  %rc = and i1 %rc1, %rc2
+  br i1 %rc, label %backedge, label %out_of_bounds
+
+
+backedge:
+  %iv.next = add i32 %iv, 1
+  %arr_el_ptr = getelementptr i32, i32* %arr, i32 %iv
+  %el = load i32, i32* %arr_el_ptr
+  %loopcond = icmp ne i32 %iv, %len
+  br i1 %loopcond, label %loop, label %exit
+
+exit:
+  ret void
+
+out_of_bounds:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/not-likely-taken.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/not-likely-taken.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/not-likely-taken.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/not-likely-taken.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
+;
+; TODO: new-pm version should be enabled after we decide on branch-probability handling for loop passes
+; TODO: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' < %s 2>&1 | FileCheck %s
+
+; CHECK-NOT: constrained Loop
+
+define void @multiple_access_no_preloop(
+    i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) {
+
+ entry:
+  %len.a = load i32, i32* %a_len_ptr, !range !0
+  %len.b = load i32, i32* %b_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds.b ]
+  %idx.next = add i32 %idx, 1
+  %abc.a = icmp slt i32 %idx, %len.a
+  br i1 %abc.a, label %in.bounds.a, label %out.of.bounds, !prof !1
+
+ in.bounds.a:
+  %addr.a = getelementptr i32, i32* %arr_a, i32 %idx
+  store i32 0, i32* %addr.a
+  %abc.b = icmp slt i32 %idx, %len.b
+  br i1 %abc.b, label %in.bounds.b, label %out.of.bounds, !prof !1
+
+ in.bounds.b:
+  %addr.b = getelementptr i32, i32* %arr_b, i32 %idx
+  store i32 -1, i32* %addr.b
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 1, i32 1}

Added: llvm/trunk/test/Transforms/IRCE/only-lower-check.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/only-lower-check.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/only-lower-check.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/only-lower-check.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -irce-print-range-checks -irce-print-changed-loops -verify-loop-info -irce < %s 2>&1 | FileCheck %s
+; RUN: opt -irce-print-range-checks -irce-print-changed-loops -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: loop has 1 inductive range checks:
+; CHECK-NEXT: InductiveRangeCheck:
+; CHECK-NEXT:   Begin: (-1 + %n)  Step: -1  End: 2147483647
+; CHECK-NEXT:   CheckUse:   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 Operand: 0
+; CHECK-NEXT: irce: in function only_lower_check: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+define void @only_lower_check(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  %start = sub i32 %n, 1
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ]
+  %idx.dec = sub i32 %idx, 1
+  %abc = icmp sge i32 %idx, 0
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp sgt i32 %idx.dec, -1
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/only-upper-check.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/only-upper-check.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/only-upper-check.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/only-upper-check.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -verify-loop-info -irce -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
+
+; CHECK: irce: loop has 1 inductive range checks:
+; CHECK-NEXT:InductiveRangeCheck:
+; CHECK-NEXT:  Begin: %offset  Step: 1  End:   %len
+; CHECK-NEXT:  CheckUse:   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 Operand: 0
+; CHECK-NEXT: irce: in function incrementing: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+define void @incrementing(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %array.idx = add i32 %idx, %offset
+  %abc = icmp slt i32 %array.idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %array.idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/optimistic_scev.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/optimistic_scev.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/optimistic_scev.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/optimistic_scev.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+
+; CHECK-LABEL: irce: in function test_01: constrained Loop at depth 2 containing:
+
+define void @test_01(i64 %len) {
+
+; CHECK-LABEL: @test_01(
+
+entry:
+  br label %loop
+
+check:
+  %entry_check = icmp eq i32 %idx.next, 0
+  br i1 %entry_check, label %exit, label %loop
+
+loop:
+  %idx = phi i32 [ 1, %entry ], [ %idx.next, %check ]
+  %idx_ext = sext i32 %idx to i64
+  br label %inner_loop
+
+inner_loop:
+  %iv = phi i64 [ 0, %loop ], [ %iv.next, %inner_backedge ]
+  %iv.next = add nuw nsw i64 %iv, 1
+  %inner_check = icmp slt i64 %iv.next, %idx_ext
+  br i1 %inner_check, label %inner, label %outer_check
+
+inner:
+  %iv_next_check = icmp slt i64 %iv.next, 100
+  br i1 %iv_next_check, label %inner_backedge, label %exit
+
+inner_backedge:
+  %cond = icmp eq i64 %iv.next, 100
+  br i1 %cond, label %exit, label %inner_loop
+
+outer_check:
+  %idx.next = add i32 %idx, 1
+  %loopdone = icmp slt i32 %idx.next, 2
+  br i1 %loopdone, label %check, label %exit
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IRCE/pre_post_loops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/pre_post_loops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/pre_post_loops.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/pre_post_loops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,118 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+; Iterate from 0 to SINT_MAX, check that the post-loop is generated.
+define void @test_01(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:       test_01(
+; CHECK:       entry:
+; CHECK-NEXT:    %exit.mainloop.at = load i32, i32* %a_len_ptr
+; CHECK:       loop:
+; CHECK-NEXT:    %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:    %idx.next = add i32 %idx, 1
+; CHECK-NEXT:    %abc = icmp slt i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:    br i1 true, label %in.bounds,
+; CHECK:       in.bounds:
+; CHECK-NEXT:    %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:    store i32 0, i32* %addr
+; CHECK-NEXT:    %next = icmp slt i32 %idx.next, 2147483647
+; CHECK-NEXT:    [[COND:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
+; CHECK-NEXT:    br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    br label %postloop
+; CHECK:       postloop:
+; CHECK-NEXT:    br label %loop.postloop
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:    %idx.next.postloop = add i32 %idx.postloop, 1
+; CHECK-NEXT:    %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:    br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+; CHECK:       in.bounds.postloop:
+; CHECK-NEXT:    %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
+; CHECK-NEXT:    store i32 0, i32* %addr.postloop
+; CHECK-NEXT:    %next.postloop = icmp slt i32 %idx.next.postloop, 2147483647
+; CHECK-NEXT:    br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 2147483647
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Iterate from SINT_MAX to 0, check that the pre-loop is generated.
+define void @test_02(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      test_02(
+; CHECK:      entry:
+; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr, !range !0
+; CHECH-NEXT:    br i1 true, label %loop.preloop.preheader
+; CHECK:      mainloop:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, -1
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
+; CHECK-NEXT:   br i1 true, label %in.bounds
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp sgt i32 %idx.next, -1
+; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
+; CHECK:      loop.preloop:
+; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483647, %loop.preloop.preheader ]
+; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -1
+; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
+; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.preloop:
+; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:   store i32 0, i32* %addr.preloop
+; CHECK-NEXT:   %next.preloop = icmp sgt i32 %idx.next.preloop, -1
+; CHECK-NEXT:   [[COND:%[^ ]+]] = icmp sgt i32 %idx.next.preloop, -1
+; CHECK-NEXT:   br i1 [[COND]], label %loop.preloop, label %preloop.exit.selector
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp sgt i32 %idx.next, -1
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 50}

Added: llvm/trunk/test/Transforms/IRCE/range_intersect_miscompile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/range_intersect_miscompile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/range_intersect_miscompile.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/range_intersect_miscompile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,287 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK-LABEL: irce: in function test_01: constrained Loop at depth 1 containing:
+; CHECK-LABEL: irce: in function test_02: constrained Loop at depth 1 containing:
+; CHECK-LABEL: irce: in function test_03: constrained Loop at depth 1 containing:
+; CHECK-LABEL: irce: in function test_04: constrained Loop at depth 1 containing:
+; CHECK-LABEL: irce: in function test_05: constrained Loop at depth 1 containing:
+
+; This test used to demonstrate a miscompile: the outer loop's IV iterates in
+; range of [2, 400) and the range check is done against value 331. Due to a bug
+; in range intersection IRCE manages to eliminate the range check without
+; inserting a postloop, which is incorrect. We treat the range of this test as
+; an unsigned range and are able to intersect ranges correctly and insert a
+; postloop.
+
+define void @test_01() {
+
+; CHECK-LABEL: test_01
+; CHECK-NOT:     preloop
+; CHECK:         range_check_block:                                ; preds = %inner_loop
+; CHECK-NEXT:      %range_check = icmp slt i32 %iv, 331
+; CHECK-NEXT:      br i1 true, label %loop_latch
+; CHECK:         loop_latch:
+; CHECK-NEXT:      %iv_next = add i32 %iv, 1
+; CHECK-NEXT:      %loop_cond = icmp ult i32 %iv_next, 400
+; CHECK-NEXT:      [[COND:%[^ ]+]] = icmp ult i32 %iv_next, 331
+; CHECK-NEXT:      br i1 [[COND]], label %loop_header, label %main.exit.selector
+; CHECK:         main.exit.selector:                               ; preds = %loop_latch
+; CHECK-NEXT:      %iv_next.lcssa = phi i32 [ %iv_next, %loop_latch ]
+; CHECK-NEXT:      %iv.lcssa = phi i32 [ %iv, %loop_latch ]
+; CHECK-NEXT:      [[MES_COND:%[^ ]+]] = icmp ult i32 %iv_next.lcssa, 400
+; CHECK-NEXT:      br i1 [[MES_COND]], label %main.pseudo.exit, label %exit
+; CHECK:         loop_latch.postloop:                              ; preds = %range_check_block.postloop
+; CHECK-NEXT:      %iv_next.postloop = add i32 %iv.postloop, 1
+; CHECK-NEXT:      %loop_cond.postloop = icmp ult i32 %iv_next.postloop, 400
+; CHECK-NEXT:      br i1 %loop_cond.postloop, label %loop_header.postloop, label %exit.loopexit
+
+entry:
+  br label %loop_header
+
+loop_header:                            ; preds = %loop_latch, %entry
+  %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]
+  %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]
+  %tmp2 = icmp sgt i32 %iv.prev, -1
+  br i1 %tmp2, label %loop_header.split.us, label %exit
+
+loop_header.split.us:                   ; preds = %loop_header
+  br label %inner_loop
+
+inner_loop:                                   ; preds = %inner_loop, %loop_header.split.us
+  %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]
+  %inner_iv_next = add nuw nsw i32 %inner_iv, 1
+  %inner_cond = icmp ult i32 %inner_iv_next, 31
+  br i1 %inner_cond, label %inner_loop, label %range_check_block
+
+exit:                                            ; preds = %loop_latch, %loop_header
+  ret void
+
+range_check_block:                                          ; preds = %inner_loop
+  %range_check = icmp slt i32 %iv, 331
+  br i1 %range_check, label %loop_latch, label %deopt
+
+loop_latch:                                         ; preds = %range_check_block
+  %iv_next = add i32 %iv, 1
+  %loop_cond = icmp ult i32 %iv_next, 400
+  br i1 %loop_cond, label %loop_header, label %exit
+
+deopt:                                          ; preds = %range_check_block
+  ret void
+}
+
+; Similar to test_01, but here the range check is done against 450. No postloop
+; is required.
+
+define void @test_02() {
+
+; CHECK-LABEL: test_02
+; CHECK-NOT:     preloop
+; CHECK-NOT:     postloop
+; CHECK:         range_check_block:                                ; preds = %inner_loop
+; CHECK-NEXT:      %range_check = icmp slt i32 %iv, 450
+; CHECK-NEXT:      br i1 true, label %loop_latch
+; CHECK:         loop_latch:                                       ; preds = %range_check_block
+; CHECK-NEXT:      %iv_next = add i32 %iv, 1
+; CHECK-NEXT:      %loop_cond = icmp ult i32 %iv_next, 400
+; CHECK-NEXT:      br i1 %loop_cond, label %loop_header, label %exit
+
+entry:
+  br label %loop_header
+
+loop_header:                            ; preds = %loop_latch, %entry
+  %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]
+  %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]
+  %tmp2 = icmp sgt i32 %iv.prev, -1
+  br i1 %tmp2, label %loop_header.split.us, label %exit
+
+loop_header.split.us:                   ; preds = %loop_header
+  br label %inner_loop
+
+inner_loop:                                   ; preds = %inner_loop, %loop_header.split.us
+  %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]
+  %inner_iv_next = add nuw nsw i32 %inner_iv, 1
+  %inner_cond = icmp ult i32 %inner_iv_next, 31
+  br i1 %inner_cond, label %inner_loop, label %range_check_block
+
+exit:                                            ; preds = %loop_latch, %loop_header
+  ret void
+
+range_check_block:                                          ; preds = %inner_loop
+  %range_check = icmp slt i32 %iv, 450
+  br i1 %range_check, label %loop_latch, label %deopt
+
+loop_latch:                                         ; preds = %range_check_block
+  %iv_next = add i32 %iv, 1
+  %loop_cond = icmp ult i32 %iv_next, 400
+  br i1 %loop_cond, label %loop_header, label %exit
+
+deopt:                                          ; preds = %range_check_block
+  ret void
+}
+
+; Range check is made against 0, so the safe iteration range is empty. IRCE
+; should not apply to the inner loop. The condition %tmp2 can be eliminated.
+
+define void @test_03() {
+
+; CHECK-LABEL: test_03
+; CHECK-NOT:   preloop
+; CHECK-NOT:   postloop
+; CHECK:         %tmp2 = icmp sgt i32 %iv.prev, -1
+; CHECK-NEXT:    br i1 true, label %loop_header.split.us, label %exit
+; CHECK:       range_check_block:
+; CHECK-NEXT:    %range_check = icmp slt i32 %iv, 0
+; CHECK-NEXT:    br i1 %range_check, label %loop_latch, label %deopt
+
+entry:
+  br label %loop_header
+
+loop_header:                            ; preds = %loop_latch, %entry
+  %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]
+  %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]
+  %tmp2 = icmp sgt i32 %iv.prev, -1
+  br i1 %tmp2, label %loop_header.split.us, label %exit
+
+loop_header.split.us:                   ; preds = %loop_header
+  br label %inner_loop
+
+inner_loop:                                   ; preds = %inner_loop, %loop_header.split.us
+  %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]
+  %inner_iv_next = add nuw nsw i32 %inner_iv, 1
+  %inner_cond = icmp ult i32 %inner_iv_next, 31
+  br i1 %inner_cond, label %inner_loop, label %range_check_block
+
+exit:                                            ; preds = %loop_latch, %loop_header
+  ret void
+
+range_check_block:                                          ; preds = %inner_loop
+  %range_check = icmp slt i32 %iv, 0
+  br i1 %range_check, label %loop_latch, label %deopt
+
+loop_latch:                                         ; preds = %range_check_block
+  %iv_next = add i32 %iv, 1
+  %loop_cond = icmp ult i32 %iv_next, 400
+  br i1 %loop_cond, label %loop_header, label %exit
+
+deopt:                                          ; preds = %range_check_block
+  ret void
+}
+
+; We can also properly eliminate range check against %n which is not always
+; known positive.
+
+define void @test_04(i32* %p) {
+
+; CHECK-LABEL: test_04
+; CHECK:       entry
+; CHECK-NOT:   preloop
+; CHECK:         %tmp2 = icmp sgt i32 %iv.prev, -1
+; CHECK-NEXT:    br i1 true, label %loop_header.split.us, label %exit
+; CHECK:       range_check_block:
+; CHECK-NEXT:    %range_check = icmp slt i32 %iv, %n
+; CHECK-NEXT:    br i1 true, label %loop_latch, label %deopt
+; CHECK:       postloop:
+
+entry:
+  %n = load i32, i32* %p
+  br label %loop_header
+
+loop_header:                            ; preds = %loop_latch, %entry
+  %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]
+  %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]
+  %tmp2 = icmp sgt i32 %iv.prev, -1
+  br i1 %tmp2, label %loop_header.split.us, label %exit
+
+loop_header.split.us:                   ; preds = %loop_header
+  br label %inner_loop
+
+inner_loop:                                   ; preds = %inner_loop, %loop_header.split.us
+  %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]
+  %inner_iv_next = add nuw nsw i32 %inner_iv, 1
+  %inner_cond = icmp ult i32 %inner_iv_next, 31
+  br i1 %inner_cond, label %inner_loop, label %range_check_block
+
+exit:                                            ; preds = %loop_latch, %loop_header
+  ret void
+
+range_check_block:                                          ; preds = %inner_loop
+  %range_check = icmp slt i32 %iv, %n
+  br i1 %range_check, label %loop_latch, label %deopt
+
+loop_latch:                                         ; preds = %range_check_block
+  %iv_next = add i32 %iv, 1
+  %loop_cond = icmp ult i32 %iv_next, 400
+  br i1 %loop_cond, label %loop_header, label %exit
+
+deopt:                                          ; preds = %range_check_block
+  ret void
+}
+
+; Same as test_04, but range guarantees that %n is positive. So we can safely
+; intersect ranges (with insertion of postloop).
+
+define void @test_05(i32* %p) {
+
+; CHECK-LABEL: test_05
+; CHECK-NOT:     preloop
+; CHECK:         entry:
+; CHECK-NEXT:      %n = load i32, i32* %p, !range !
+; CHECK-NEXT:      [[CMP_1:%[^ ]+]] = icmp ugt i32 %n, 2
+; CHECK-NEXT:      %exit.mainloop.at = select i1 [[CMP_1]], i32 %n, i32 2
+; CHECK-NEXT:      [[CMP_2:%[^ ]+]] = icmp ult i32 2, %exit.mainloop.at
+; CHECK-NEXT:      br i1 [[CMP_2]], label %loop_header.preheader, label %main.pseudo.exit
+; CHECK:         range_check_block:                                ; preds = %inner_loop
+; CHECK-NEXT:      %range_check = icmp slt i32 %iv, %n
+; CHECK-NEXT:      br i1 true, label %loop_latch, label %deopt.loopexit2
+; CHECK:         loop_latch:                                       ; preds = %range_check_block
+; CHECK-NEXT:      %iv_next = add i32 %iv, 1
+; CHECK-NEXT:      %loop_cond = icmp ult i32 %iv_next, 400
+; CHECK-NEXT:      [[COND:%[^ ]+]] = icmp ult i32 %iv_next, %exit.mainloop.at
+; CHECK-NEXT:      br i1 [[COND]], label %loop_header, label %main.exit.selector
+; CHECK:         main.exit.selector:                               ; preds = %loop_latch
+; CHECK-NEXT:      %iv_next.lcssa = phi i32 [ %iv_next, %loop_latch ]
+; CHECK-NEXT:      %iv.lcssa = phi i32 [ %iv, %loop_latch ]
+; CHECK-NEXT:      [[MES_COND:%[^ ]+]] = icmp ult i32 %iv_next.lcssa, 400
+; CHECK-NEXT:      br i1 [[MES_COND]], label %main.pseudo.exit, label %exit
+; CHECK:         loop_latch.postloop:                              ; preds = %range_check_block.postloop
+; CHECK-NEXT:      %iv_next.postloop = add i32 %iv.postloop, 1
+; CHECK-NEXT:      %loop_cond.postloop = icmp ult i32 %iv_next.postloop, 400
+; CHECK-NEXT:      br i1 %loop_cond.postloop, label %loop_header.postloop, label %exit.loopexit
+
+entry:
+  %n = load i32, i32* %p, !range !0
+  br label %loop_header
+
+loop_header:                            ; preds = %loop_latch, %entry
+  %iv = phi i32 [ 2, %entry ], [ %iv_next, %loop_latch ]
+  %iv.prev = phi i32 [ 1, %entry ], [ %iv, %loop_latch ]
+  %tmp2 = icmp sgt i32 %iv.prev, -1
+  br i1 %tmp2, label %loop_header.split.us, label %exit
+
+loop_header.split.us:                   ; preds = %loop_header
+  br label %inner_loop
+
+inner_loop:                                   ; preds = %inner_loop, %loop_header.split.us
+  %inner_iv = phi i32 [ 1, %loop_header.split.us ], [ %inner_iv_next, %inner_loop ]
+  %inner_iv_next = add nuw nsw i32 %inner_iv, 1
+  %inner_cond = icmp ult i32 %inner_iv_next, 31
+  br i1 %inner_cond, label %inner_loop, label %range_check_block
+
+exit:                                            ; preds = %loop_latch, %loop_header
+  ret void
+
+range_check_block:                                          ; preds = %inner_loop
+  %range_check = icmp slt i32 %iv, %n
+  br i1 %range_check, label %loop_latch, label %deopt
+
+loop_latch:                                         ; preds = %range_check_block
+  %iv_next = add i32 %iv, 1
+  %loop_cond = icmp ult i32 %iv_next, 400
+  br i1 %loop_cond, label %loop_header, label %exit
+
+deopt:                                          ; preds = %range_check_block
+  ret void
+}
+
+!0 = !{i32 0, i32 50}

Added: llvm/trunk/test/Transforms/IRCE/ranges_of_different_types.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/ranges_of_different_types.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/ranges_of_different_types.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/ranges_of_different_types.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,428 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; Make sure we can eliminate range check with signed latch, unsigned IRC and
+; positive offset. The safe iteration space is:
+; No preloop,
+; %exit.mainloop.at = smax (0, -1 - smax(12 - %len, -102)).
+; Formula verification:
+; %len = 10
+; %exit.mainloop.at = 0
+; %len = 50
+; %exit.mainloop.at = 50 - 13 = 37.
+; %len = 100
+; %exit.mainloop.at = 100 - 13 = 87.
+; %len = 150
+; %exit.mainloop.at = 101.
+; %len = SINT_MAX
+; %exit.mainloop.at = 101
+
+define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_01(
+; CHECK-NOT:     preloop
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 12, %len
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102
+; CHECK-NEXT:      [[SMAX:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102
+; CHECK-NEXT:      [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX]]
+; CHECK-NEXT:      [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0
+; CHECK-NEXT:      %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB2]], i32 0
+; CHECK-NEXT:      [[GOTO_LOOP:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
+; CHECK-NEXT:      br i1 [[GOTO_LOOP]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:         loop
+; CHECK:           br i1 true, label %in.bounds
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = add i32 %idx, 13
+  %abc = icmp ult i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Make sure we can eliminate range check with signed latch, unsigned IRC and
+; negative offset. The safe iteration space is:
+; %exit.preloop.at = 13
+; %exit.mainloop.at = smax(-1 - smax(smax(%len - SINT_MAX, -13) - 1 - %len, -102), 0)
+; Formula verification:
+; %len = 10
+; %exit.mainloop.at = 0
+; %len = 50
+; %exit.mainloop.at = 63
+; %len = 100
+; %exit.mainloop.at = 101
+; %len = 150
+; %exit.mainloop.at = 101
+; %len = SINT_MAX
+; %exit.mainloop.at = 101
+
+define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_02(
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[LEN_MINUS_SMAX:%[^ ]+]] = add i32 %len, -2147483647
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp sgt i32 [[LEN_MINUS_SMAX]], -13
+; CHECK-NEXT:      [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[LEN_MINUS_SMAX]], i32 -13
+; CHECK-NEXT:      [[ADD1:%[^ ]+]] = add i32 [[SMAX1]], -1
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 [[ADD1]], %len
+; CHECK-NEXT:      [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102
+; CHECK-NEXT:      [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 -102
+; CHECK-NEXT:      [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX2]]
+; CHECK-NEXT:      [[CMP3:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0
+; CHECK-NEXT:      %exit.mainloop.at = select i1 [[CMP3]], i32 [[SUB2]], i32 0
+; CHECK-NEXT:      br i1 true, label %loop.preloop.preheader
+; CHECK:         loop.preloop:
+; CHECK-NEXT:      %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 0, %loop.preloop.preheader ]
+; CHECK-NEXT:      %idx.next.preloop = add i32 %idx.preloop, 1
+; CHECK-NEXT:      %idx.offset.preloop = sub i32 %idx.preloop, 13
+; CHECK-NEXT:      %abc.preloop = icmp ult i32 %idx.offset.preloop, %len
+; CHECK-NEXT:      br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+; CHECK:         in.bounds.preloop:
+; CHECK-NEXT:      %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:      store i32 0, i32* %addr.preloop
+; CHECK-NEXT:      %next.preloop = icmp slt i32 %idx.next.preloop, 101
+; CHECK-NEXT:      [[PRELOOP_COND:%[^ ]+]] = icmp slt i32 %idx.next.preloop, 13
+; CHECK-NEXT:      br i1 [[PRELOOP_COND]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = sub i32 %idx, 13
+  %abc = icmp ult i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Make sure we can eliminate range check with unsigned latch, signed IRC and
+; positive offset. The safe iteration space is:
+; No preloop,
+; %exit.mainloop.at = -1 - umax(-2 - %len - smax(-1 - %len, -14), -102)
+; Formula verification:
+; %len = 10
+; %exit.mainloop.at = 0
+; %len = 50
+; %exit.mainloop.at = 37
+; %len = 100
+; %exit.mainloop.at = 87
+; %len = 150
+; %exit.mainloop.at = 101
+; %len = SINT_MAX
+; %exit.mainloop.at = 101
+
+define void @test_03(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_03(
+; CHECK-NOT:     preloop
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 -2, %len
+; CHECK-NEXT:      [[SUB2:%[^ ]+]] = sub i32 -1, %len
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB2]], -14
+; CHECK-NEXT:      [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB2]], i32 -14
+; CHECK-NEXT:      [[SUB3:%[^ ]+]] = sub i32 [[SUB1]], [[SMAX1]]
+; CHECK-NEXT:      [[CMP2:%[^ ]+]] = icmp ugt i32 [[SUB3]], -102
+; CHECK-NEXT:      [[UMAX1:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB3]], i32 -102
+; CHECK-NEXT:      %exit.mainloop.at = sub i32 -1, [[UMAX1]]
+; CHECK-NEXT:      [[CMP3:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:      br i1 [[CMP3]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = add i32 %idx, 13
+  %abc = icmp slt i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Make sure we can eliminate range check with unsigned latch, signed IRC and
+; positive offset. The safe iteration space is:
+; %exit.preloop.at = 13
+; %exit.mainloop.at = -1 - umax(-14 - %len, -102)
+; Formula verification:
+; %len = 10
+; %exit.mainloop.at = 23
+; %len = 50
+; %exit.mainloop.at = 63
+; %len = 100
+; %exit.mainloop.at = 101
+; %len = 150
+; %exit.mainloop.at = 101
+; %len = SINT_MAX
+; %exit.mainloop.at = 101
+
+define void @test_04(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_04(
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 -14, %len
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp ugt i32 [[SUB1]], -102
+; CHECK-NEXT:      [[UMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102
+; CHECK-NEXT:      %exit.mainloop.at = sub i32 -1, [[UMAX1]]
+; CHECK-NEXT:      br i1 true, label %loop.preloop.preheader
+; CHECK:         in.bounds.preloop:
+; CHECK-NEXT:      %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:      store i32 0, i32* %addr.preloop
+; CHECK-NEXT:      %next.preloop = icmp ult i32 %idx.next.preloop, 101
+; CHECK-NEXT:      [[PRELOOP_COND:%[^ ]+]] = icmp ult i32 %idx.next.preloop, 13
+; CHECK-NEXT:      br i1 [[PRELOOP_COND]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = sub i32 %idx, 13
+  %abc = icmp slt i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Signed latch, signed RC, positive offset. Same as test_01.
+define void @test_05(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_05(
+; CHECK-NOT:     preloop
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 12, %len
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102
+; CHECK-NEXT:      [[SMAX:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102
+; CHECK-NEXT:      [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX]]
+; CHECK-NEXT:      [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0
+; CHECK-NEXT:      %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB2]], i32 0
+; CHECK-NEXT:      [[GOTO_LOOP:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
+; CHECK-NEXT:      br i1 [[GOTO_LOOP]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:         loop
+; CHECK:           br i1 true, label %in.bounds
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = add i32 %idx, 13
+  %abc = icmp slt i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Signed latch, signed RC, negative offset. Same as test_02.
+define void @test_06(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_06(
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[LEN_MINUS_SMAX:%[^ ]+]] = add i32 %len, -2147483647
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp sgt i32 [[LEN_MINUS_SMAX]], -13
+; CHECK-NEXT:      [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[LEN_MINUS_SMAX]], i32 -13
+; CHECK-NEXT:      [[ADD1:%[^ ]+]] = add i32 [[SMAX1]], -1
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 [[ADD1]], %len
+; CHECK-NEXT:      [[CMP2:%[^ ]+]] = icmp sgt i32 [[SUB1]], -102
+; CHECK-NEXT:      [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 -102
+; CHECK-NEXT:      [[SUB2:%[^ ]+]] = sub i32 -1, [[SMAX2]]
+; CHECK-NEXT:      [[CMP3:%[^ ]+]] = icmp sgt i32 [[SUB2]], 0
+; CHECK-NEXT:      %exit.mainloop.at = select i1 [[CMP3]], i32 [[SUB2]], i32 0
+; CHECK-NEXT:      br i1 true, label %loop.preloop.preheader
+; CHECK:         in.bounds.preloop:
+; CHECK-NEXT:      %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:      store i32 0, i32* %addr.preloop
+; CHECK-NEXT:      %next.preloop = icmp slt i32 %idx.next.preloop, 101
+; CHECK-NEXT:      [[PRELOOP_COND:%[^ ]+]] = icmp slt i32 %idx.next.preloop, 13
+; CHECK-NEXT:      br i1 [[PRELOOP_COND]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = sub i32 %idx, 13
+  %abc = icmp slt i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Unsigned latch, Unsigned RC, negative offset. Same as test_03.
+define void @test_07(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_07(
+; CHECK-NOT:     preloop
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 -2, %len
+; CHECK-NEXT:      [[SUB2:%[^ ]+]] = sub i32 -1, %len
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp sgt i32 [[SUB2]], -14
+; CHECK-NEXT:      [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB2]], i32 -14
+; CHECK-NEXT:      [[SUB3:%[^ ]+]] = sub i32 [[SUB1]], [[SMAX1]]
+; CHECK-NEXT:      [[CMP2:%[^ ]+]] = icmp ugt i32 [[SUB3]], -102
+; CHECK-NEXT:      [[UMAX1:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB3]], i32 -102
+; CHECK-NEXT:      %exit.mainloop.at = sub i32 -1, [[UMAX1]]
+; CHECK-NEXT:      [[CMP3:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:      br i1 [[CMP3]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:         loop
+; CHECK:           br i1 true, label %in.bounds
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = add i32 %idx, 13
+  %abc = icmp ult i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Unsigned latch, Unsigned RC, negative offset. Same as test_04.
+define void @test_08(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK-LABEL: test_08(
+; CHECK:         entry:
+; CHECK-NEXT:      %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:      [[SUB1:%[^ ]+]] = sub i32 -14, %len
+; CHECK-NEXT:      [[CMP1:%[^ ]+]] = icmp ugt i32 [[SUB1]], -102
+; CHECK-NEXT:      [[UMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[SUB1]], i32 -102
+; CHECK-NEXT:      %exit.mainloop.at = sub i32 -1, [[UMAX1]]
+; CHECK-NEXT:      br i1 true, label %loop.preloop.preheader
+; CHECK:         in.bounds.preloop:
+; CHECK-NEXT:      %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:      store i32 0, i32* %addr.preloop
+; CHECK-NEXT:      %next.preloop = icmp ult i32 %idx.next.preloop, 101
+; CHECK-NEXT:      [[PRELOOP_COND:%[^ ]+]] = icmp ult i32 %idx.next.preloop, 13
+; CHECK-NEXT:      br i1 [[PRELOOP_COND]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:         postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.offset = sub i32 %idx, 13
+  %abc = icmp ult i32 %idx.offset, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 101
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}

Added: llvm/trunk/test/Transforms/IRCE/rc-negative-bound.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/rc-negative-bound.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/rc-negative-bound.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/rc-negative-bound.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,600 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK-NOT: irce: in function test_01: constrained Loop
+; CHECK-NOT: irce: in function test_02: constrained Loop
+; CHECK: irce: in function test_03: constrained Loop
+
+; RC against known negative value. We should not do IRCE here.
+define void @test_01(i32 *%arr, i32 %n) {
+; CHECK-LABEL: @test_01(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], -9
+; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, -9
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; Same as test_01, but the latch condition is unsigned.
+define void @test_02(i32 *%arr, i32 %n) {
+; CHECK-LABEL: @test_02(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], -9
+; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, -9
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; RC against a value which is not known to be non-negative. Here we should
+; expand runtime checks against bound being positive or negative.
+define void @test_03(i32 *%arr, i32 %n, i32 %bound) {
+; CHECK-LABEL: @test_03(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[BOUND:%.*]], -2147483647
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
+; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMAX]]
+; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 -1, [[BOUND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i32 [[TMP3]], -1
+; CHECK-NEXT:    [[SMAX1:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1
+; CHECK-NEXT:    [[TMP5:%.*]] = sub i32 -1, [[SMAX1]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], -1
+; CHECK-NEXT:    [[SMAX2:%.*]] = select i1 [[TMP6]], i32 [[TMP5]], i32 -1
+; CHECK-NEXT:    [[TMP7:%.*]] = add i32 [[SMAX2]], 1
+; CHECK-NEXT:    [[TMP8:%.*]] = mul i32 [[TMP2]], [[TMP7]]
+; CHECK-NEXT:    [[TMP9:%.*]] = sub i32 -1, [[TMP8]]
+; CHECK-NEXT:    [[TMP10:%.*]] = sub i32 -1, [[N]]
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
+; CHECK-NEXT:    [[SMAX3:%.*]] = select i1 [[TMP11]], i32 [[TMP9]], i32 [[TMP10]]
+; CHECK-NEXT:    [[TMP12:%.*]] = sub i32 -1, [[SMAX3]]
+; CHECK-NEXT:    [[TMP13:%.*]] = icmp sgt i32 [[TMP12]], 0
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP13]], i32 [[TMP12]], i32 0
+; CHECK-NEXT:    [[TMP14:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP14]], label [[LOOP_PREHEADER5:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader5:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER5]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[BOUND]]
+; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT6:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    [[TMP15:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP15]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT:    [[TMP16:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]]
+; CHECK-NEXT:    br i1 [[TMP16]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       out.of.bounds.loopexit:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out.of.bounds.loopexit6:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[BOUND]]
+; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0
+; CHECK:       in.bounds.postloop:
+; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR_POSTLOOP]]
+; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !1, !irce.loop.clone !6
+;
+
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %bound
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; RC against a value which is not known to be non-negative. Here we should
+; expand runtime checks against bound being positive or negative.
+define void @test_04(i32 *%arr, i32 %n, i32 %bound) {
+; CHECK-LABEL: @test_04(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 -1, [[BOUND:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], -1
+; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -1
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[BOUND]], [[SMAX]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = sub i32 -1, [[SMAX]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp sgt i32 [[TMP4]], -1
+; CHECK-NEXT:    [[SMAX1:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 -1
+; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[SMAX1]], 1
+; CHECK-NEXT:    [[TMP7:%.*]] = mul i32 [[TMP3]], [[TMP6]]
+; CHECK-NEXT:    [[TMP8:%.*]] = sub i32 -1, [[TMP7]]
+; CHECK-NEXT:    [[TMP9:%.*]] = sub i32 -1, [[N]]
+; CHECK-NEXT:    [[TMP10:%.*]] = icmp ugt i32 [[TMP8]], [[TMP9]]
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP10]], i32 [[TMP8]], i32 [[TMP9]]
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = sub i32 -1, [[UMAX]]
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP11]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader2:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[BOUND]]
+; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    [[TMP12:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT:    [[TMP13:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]]
+; CHECK-NEXT:    br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       out.of.bounds.loopexit:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out.of.bounds.loopexit3:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[BOUND]]
+; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0
+; CHECK:       in.bounds.postloop:
+; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR_POSTLOOP]]
+; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !7, !irce.loop.clone !6
+;
+
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %bound
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; Same as test_01, unsigned range check.
+; FIXME: We could remove the range check here, but it does not happen due to the
+; limintation we posed to fix the miscompile (see comments in the method
+; computeSafeIterationSpace).
+define void @test_05(i32 *%arr, i32 %n) {
+; CHECK-LABEL: @test_05(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], -9
+; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp ult i32 %idx, -9
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; Same as test_02, unsigned range check.
+; FIXME: We could remove the range check here, but it does not happen due to the
+; limintation we posed to fix the miscompile (see comments in the method
+; computeSafeIterationSpace).
+define void @test_06(i32 *%arr, i32 %n) {
+; CHECK-LABEL: @test_06(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], -9
+; CHECK-NEXT:    br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp ult i32 %idx, -9
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; Same as test_03, unsigned range check.
+; FIXME: Currently we remove the check, but we will not execute the main loop if
+; %bound is negative (i.e. in [SINT_MAX + 1, UINT_MAX)). We should be able to
+; safely remove this check (see comments in the method
+; computeSafeIterationSpace).
+define void @test_07(i32 *%arr, i32 %n, i32 %bound) {
+; CHECK-LABEL: @test_07(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[BOUND:%.*]], -2147483647
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0
+; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMAX]]
+; CHECK-NEXT:    [[TMP3:%.*]] = sub i32 -1, [[BOUND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i32 [[TMP3]], -1
+; CHECK-NEXT:    [[SMAX1:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1
+; CHECK-NEXT:    [[TMP5:%.*]] = sub i32 -1, [[SMAX1]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], -1
+; CHECK-NEXT:    [[SMAX2:%.*]] = select i1 [[TMP6]], i32 [[TMP5]], i32 -1
+; CHECK-NEXT:    [[TMP7:%.*]] = add i32 [[SMAX2]], 1
+; CHECK-NEXT:    [[TMP8:%.*]] = mul i32 [[TMP2]], [[TMP7]]
+; CHECK-NEXT:    [[TMP9:%.*]] = sub i32 -1, [[TMP8]]
+; CHECK-NEXT:    [[TMP10:%.*]] = sub i32 -1, [[N]]
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
+; CHECK-NEXT:    [[SMAX3:%.*]] = select i1 [[TMP11]], i32 [[TMP9]], i32 [[TMP10]]
+; CHECK-NEXT:    [[TMP12:%.*]] = sub i32 -1, [[SMAX3]]
+; CHECK-NEXT:    [[TMP13:%.*]] = icmp sgt i32 [[TMP12]], 0
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP13]], i32 [[TMP12]], i32 0
+; CHECK-NEXT:    [[TMP14:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP14]], label [[LOOP_PREHEADER5:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader5:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER5]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[BOUND]]
+; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT6:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    [[TMP15:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP15]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT:    [[TMP16:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]]
+; CHECK-NEXT:    br i1 [[TMP16]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       out.of.bounds.loopexit:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out.of.bounds.loopexit6:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[BOUND]]
+; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0
+; CHECK:       in.bounds.postloop:
+; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR_POSTLOOP]]
+; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !8, !irce.loop.clone !6
+;
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp ult i32 %idx, %bound
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+
+; Same as test_04, unsigned range check.
+; FIXME: Currently we remove the check, but we will not execute the main loop if
+; %bound is negative (i.e. in [SINT_MAX + 1, UINT_MAX)). We should be able to
+; safely remove this check (see comments in the method
+; computeSafeIterationSpace).
+define void @test_08(i32 *%arr, i32 %n, i32 %bound) {
+; CHECK-LABEL: @test_08(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop.preheader:
+; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 -1, [[BOUND:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], -1
+; CHECK-NEXT:    [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -1
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[BOUND]], [[SMAX]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = sub i32 -1, [[SMAX]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp sgt i32 [[TMP4]], -1
+; CHECK-NEXT:    [[SMAX1:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 -1
+; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[SMAX1]], 1
+; CHECK-NEXT:    [[TMP7:%.*]] = mul i32 [[TMP3]], [[TMP6]]
+; CHECK-NEXT:    [[TMP8:%.*]] = sub i32 -1, [[TMP7]]
+; CHECK-NEXT:    [[TMP9:%.*]] = sub i32 -1, [[N]]
+; CHECK-NEXT:    [[TMP10:%.*]] = icmp ugt i32 [[TMP8]], [[TMP9]]
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP10]], i32 [[TMP8]], i32 [[TMP9]]
+; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = sub i32 -1, [[UMAX]]
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP11]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
+; CHECK:       loop.preheader2:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ]
+; CHECK-NEXT:    [[IDX_NEXT]] = add i32 [[IDX]], 1
+; CHECK-NEXT:    [[ABC:%.*]] = icmp ult i32 [[IDX]], [[BOUND]]
+; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof !0
+; CHECK:       in.bounds:
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR]]
+; CHECK-NEXT:    [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]]
+; CHECK-NEXT:    [[TMP12:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
+; CHECK-NEXT:    br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
+; CHECK:       main.exit.selector:
+; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
+; CHECK-NEXT:    [[TMP13:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]]
+; CHECK-NEXT:    br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]]
+; CHECK:       main.pseudo.exit:
+; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
+; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
+; CHECK:       out.of.bounds.loopexit:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
+; CHECK:       out.of.bounds.loopexit3:
+; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
+; CHECK:       out.of.bounds:
+; CHECK-NEXT:    ret void
+; CHECK:       exit.loopexit.loopexit:
+; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
+; CHECK:       exit.loopexit:
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+; CHECK:       postloop:
+; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
+; CHECK:       loop.postloop:
+; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ]
+; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
+; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[BOUND]]
+; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0
+; CHECK:       in.bounds.postloop:
+; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]]
+; CHECK-NEXT:    store i32 0, i32* [[ADDR_POSTLOOP]]
+; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], [[N]]
+; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !9, !irce.loop.clone !6
+;
+  entry:
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+  loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp ult i32 %idx, %bound
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0
+
+  in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+  out.of.bounds:
+  ret void
+
+  exit:
+  ret void
+}
+!0 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/single-access-no-preloop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/single-access-no-preloop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/single-access-no-preloop.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/single-access-no-preloop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,250 @@
+; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
+
+define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @single_access_no_preloop_no_offset(
+
+; CHECK: loop:
+; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
+
+; CHECK: main.exit.selector:
+; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT: [[continue:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, %n
+; CHECK-NEXT: br i1 [[continue]], label %main.pseudo.exit, label %exit.loopexit
+
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: %idx.copy = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT: %indvar.end = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT: br label %postloop
+
+; CHECK: postloop:
+; CHECK-NEXT: br label %loop.postloop
+
+; CHECK: loop.postloop:
+; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.next.postloop, %in.bounds.postloop ], [ %idx.copy, %postloop ]
+; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 1
+; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %len
+; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds
+
+; CHECK: in.bounds.postloop:
+; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
+; CHECK-NEXT: store i32 0, i32* %addr.postloop
+; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, %n
+; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+
+define void @single_access_no_preloop_with_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.for.abc = add i32 %idx, 4
+  %abc = icmp slt i32 %idx.for.abc, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx.for.abc
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @single_access_no_preloop_with_offset(
+
+; CHECK: loop.preheader:
+; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
+; CHECK: [[not_safe_range_end:[^ ]+]] = sub i32 3, %len
+; CHECK: [[not_exit_main_loop_at_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_n]], [[not_safe_range_end]]
+; CHECK: [[not_exit_main_loop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_main_loop_at_hiclamp_cmp]], i32 [[not_n]], i32 [[not_safe_range_end]]
+; CHECK: [[exit_main_loop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_main_loop_at_hiclamp]]
+; CHECK: [[exit_main_loop_at_loclamp_cmp:[^ ]+]] = icmp sgt i32 [[exit_main_loop_at_hiclamp]], 0
+; CHECK: [[exit_main_loop_at_loclamp:[^ ]+]] = select i1 [[exit_main_loop_at_loclamp_cmp]], i32 [[exit_main_loop_at_hiclamp]], i32 0
+; CHECK: [[enter_main_loop:[^ ]+]] = icmp slt i32 0, [[exit_main_loop_at_loclamp]]
+; CHECK: br i1 [[enter_main_loop]], label %loop.preheader2, label %main.pseudo.exit
+
+; CHECK: loop:
+; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
+
+; CHECK: in.bounds:
+; CHECK: [[continue_main_loop:[^ ]+]] = icmp slt i32 %idx.next, [[exit_main_loop_at_loclamp]]
+; CHECK: br i1 [[continue_main_loop]], label %loop, label %main.exit.selector
+
+; CHECK: main.pseudo.exit:
+; CHECK:  %idx.copy = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK:  br label %postloop
+
+; CHECK: loop.postloop:
+; CHECK: %idx.postloop = phi i32 [ %idx.next.postloop, %in.bounds.postloop ], [ %idx.copy, %postloop ]
+
+; CHECK: in.bounds.postloop:
+; CHECK: %next.postloop = icmp slt i32 %idx.next.postloop, %n
+; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+; Make sure that we do not do IRCE if we know that the safe iteration range of
+; the main loop is empty.
+
+define void @single_access_empty_range(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, 0
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @single_access_empty_range(
+; CHECK-NOT:   br i1 false
+; CHECK-NOT:   preloop
+; CHECK-NOT:   postloop
+
+define void @single_access_empty_range_2(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds2 ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, 60
+  br i1 %abc, label %in.bounds1, label %out.of.bounds, !prof !1
+
+ in.bounds1:
+  %def = icmp slt i32 %idx, 0
+  br i1 %def, label %in.bounds2, label %out.of.bounds, !prof !1
+
+in.bounds2:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @single_access_empty_range_2(
+; CHECK-NOT:   br i1 false
+; CHECK-NOT:   preloop
+
+define void @single_access_no_preloop_no_offset_phi_len(i32 *%arr, i32 *%a_len_ptr, i32 *%b_len_ptr, i32 %n, i1 %unknown_cond) {
+ entry:
+  br i1 %unknown_cond, label %if.true, label %if.false
+
+if.true:
+  %len_a = load i32, i32* %a_len_ptr, !range !0
+  br label %merge
+
+if.false:
+  %len_b = load i32, i32* %b_len_ptr, !range !0
+  br label %merge
+
+merge:
+  %len = phi i32 [ %len_a, %if.true ], [ %len_b, %if.false ]
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %merge ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @single_access_no_preloop_no_offset_phi_len(
+
+; CHECK: loop:
+; CHECK: br i1 true, label %in.bounds, label %out.of.bounds
+
+; CHECK: main.exit.selector:
+; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT: [[continue:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, %n
+; CHECK-NEXT: br i1 [[continue]], label %main.pseudo.exit, label %exit.loopexit
+
+; CHECK: main.pseudo.exit:
+; CHECK-NEXT: %idx.copy = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT: %indvar.end = phi i32 [ 0, %loop.preheader ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT: br label %postloop
+
+; CHECK: postloop:
+; CHECK-NEXT: br label %loop.postloop
+
+; CHECK: loop.postloop:
+; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.next.postloop, %in.bounds.postloop ], [ %idx.copy, %postloop ]
+; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 1
+; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %len
+; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds
+
+; CHECK: in.bounds.postloop:
+; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
+; CHECK-NEXT: store i32 0, i32* %addr.postloop
+; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, %n
+; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/single-access-with-preloop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/single-access-with-preloop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/single-access-with-preloop.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/single-access-with-preloop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,93 @@
+; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
+; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s
+
+define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %array.idx = add i32 %idx, %offset
+  %abc.high = icmp slt i32 %array.idx, %len
+  %abc.low = icmp sge i32 %array.idx, 0
+  %abc = and i1 %abc.low, %abc.high
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %array.idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; CHECK-LABEL: @single_access_with_preloop(
+; CHECK: loop.preheader:
+; CHECK: [[check_min_sint_offset:[^ ]+]] = icmp sgt i32 %offset, -2147483647
+; CHECK: [[safe_offset_preloop:[^ ]+]] = select i1 [[check_min_sint_offset]], i32 %offset, i32 -2147483647
+; If Offset was a SINT_MIN, we could have an overflow here. That is why we calculated its safe version.
+; CHECK: [[not_safe_start:[^ ]+]] = add i32 [[safe_offset_preloop]], -1
+; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n
+; CHECK: [[not_exit_preloop_at_cond_loclamp:[^ ]+]] = icmp sgt i32 [[not_safe_start]], [[not_n]]
+; CHECK: [[not_exit_preloop_at_loclamp:[^ ]+]] = select i1 [[not_exit_preloop_at_cond_loclamp]], i32 [[not_safe_start]], i32 [[not_n]]
+; CHECK: [[exit_preloop_at_loclamp:[^ ]+]] = sub i32 -1, [[not_exit_preloop_at_loclamp]]
+; CHECK: [[exit_preloop_at_cond:[^ ]+]] = icmp sgt i32 [[exit_preloop_at_loclamp]], 0
+; CHECK: [[exit_preloop_at:[^ ]+]] = select i1 [[exit_preloop_at_cond]], i32 [[exit_preloop_at_loclamp]], i32 0
+
+
+; CHECK: [[len_minus_sint_max:[^ ]+]] = add i32 %len, -2147483647
+; CHECK: [[check_len_min_sint_offset:[^ ]+]] = icmp sgt i32 %offset, [[len_minus_sint_max]]
+; CHECK: [[safe_offset_mainloop:[^ ]+]] = select i1 [[check_len_min_sint_offset]], i32 %offset, i32 [[len_minus_sint_max]]
+; CHECK: [[not_safe_start_2:[^ ]+]] = add i32 [[safe_offset_mainloop]], -1
+; If Offset was a SINT_MIN, we could have an overflow here. That is why we calculated its safe version.
+; CHECK: [[not_safe_upper_end:[^ ]+]] = sub i32 [[not_safe_start_2]], %len
+; CHECK: [[not_exit_mainloop_at_cond_loclamp:[^ ]+]] = icmp sgt i32 [[not_safe_upper_end]], [[not_n]]
+; CHECK: [[not_exit_mainloop_at_loclamp:[^ ]+]] = select i1 [[not_exit_mainloop_at_cond_loclamp]], i32 [[not_safe_upper_end]], i32 [[not_n]]
+; CHECK: [[check_offset_mainloop_2:[^ ]+]] = icmp sgt i32 %offset, 0
+; CHECK: [[safe_offset_mainloop_2:[^ ]+]] = select i1 [[check_offset_mainloop_2]], i32 %offset, i32 0
+; CHECK: [[not_safe_lower_end:[^ ]+]] = add i32 [[safe_offset_mainloop_2]], -2147483648
+; CHECK: [[not_exit_mainloop_at_cond_hiclamp:[^ ]+]] = icmp sgt i32 [[not_exit_mainloop_at_loclamp]], [[not_safe_lower_end]]
+; CHECK: [[not_exit_mainloop_at_hiclamp:[^ ]+]] = select i1 [[not_exit_mainloop_at_cond_hiclamp]], i32 [[not_exit_mainloop_at_loclamp]], i32 [[not_safe_lower_end]]
+; CHECK: [[exit_mainloop_at_hiclamp:[^ ]+]] = sub i32 -1, [[not_exit_mainloop_at_hiclamp]]
+; CHECK: [[exit_mainloop_at_cmp:[^ ]+]] = icmp sgt i32 [[exit_mainloop_at_hiclamp]], 0
+; CHECK: [[exit_mainloop_at:[^ ]+]] = select i1 [[exit_mainloop_at_cmp]], i32 [[exit_mainloop_at_hiclamp]], i32 0
+
+; CHECK: mainloop:
+; CHECK: br label %loop
+
+; CHECK: loop:
+; CHECK: %abc.high = icmp slt i32 %array.idx, %len
+; CHECK: %abc.low = icmp sge i32 %array.idx, 0
+; CHECK: %abc = and i1 true, true
+; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit11
+
+; CHECK: in.bounds:
+; CHECK: [[continue_mainloop_cond:[^ ]+]] = icmp slt i32 %idx.next, [[exit_mainloop_at]]
+; CHECK: br i1 [[continue_mainloop_cond]], label %loop, label %main.exit.selector
+
+; CHECK: main.exit.selector:
+; CHECK: [[mainloop_its_left:[^ ]+]] = icmp slt i32 %idx.next.lcssa, %n
+; CHECK: br i1 [[mainloop_its_left]], label %main.pseudo.exit, label %exit.loopexit
+
+; CHECK: in.bounds.preloop:
+; CHECK: [[continue_preloop_cond:[^ ]+]] = icmp slt i32 %idx.next.preloop, [[exit_preloop_at]]
+; CHECK: br i1 [[continue_preloop_cond]], label %loop.preloop, label %preloop.exit.selector
+
+; CHECK: preloop.exit.selector:
+; CHECK: [[preloop_its_left:[^ ]+]] = icmp slt i32 %idx.next.preloop.lcssa, %n
+; CHECK: br i1 [[preloop_its_left]], label %preloop.pseudo.exit, label %exit.loopexit
+
+; CHECK: in.bounds.postloop:
+; CHECK: %next.postloop = icmp slt i32 %idx.next.postloop, %n
+; CHECK: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/skip-profitability-checks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/skip-profitability-checks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/skip-profitability-checks.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/skip-profitability-checks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -irce-skip-profitability-checks -S -verify-loop-info -irce < %s | FileCheck %s
+; RUN: opt -irce-skip-profitability-checks -S -verify-loop-info -passes='require<branch-prob>,loop(irce)' < %s | FileCheck %s
+
+define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+; CHECK-LABEL: @single_access_no_preloop_no_offset(
+; CHECK: main.exit.selector:
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 1, i32 64}

Added: llvm/trunk/test/Transforms/IRCE/stride_more_than_1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/stride_more_than_1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/stride_more_than_1.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/stride_more_than_1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,481 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed.
+define void @test_01(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_01(
+; CHECK:      entry:
+; CHECK-NEXT:   %exit.mainloop.at = load i32, i32* %a_len_ptr
+; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:      loop.preheader:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, 7
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp slt i32 %idx.next, 100
+; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND2]], label %loop, label %main.exit.selector
+; CHECK:      main.exit.selector:
+; CHECK-NEXT:   %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 100
+; CHECK-NEXT:   br i1 [[COND3]], label %main.pseudo.exit, label %exit
+; CHECK:      main.pseudo.exit:
+; CHECK-NEXT:   %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    br label %postloop
+; CHECK:      postloop:
+; CHECK-NEXT:   br label %loop.postloop
+; CHECK:      loop.postloop:
+; CHECK-NEXT:   %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:   %idx.next.postloop = add i32 %idx.postloop, 7
+; CHECK-NEXT:   %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:   br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.postloop:
+; CHECK-NEXT:   %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
+; CHECK-NEXT:   store i32 0, i32* %addr.postloop
+; CHECK-NEXT:   %next.postloop = icmp slt i32 %idx.next.postloop, 100
+; CHECK-NEXT:   br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed.
+define void @test_02(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_02(
+; CHECK:      entry:
+; CHECK-NEXT:   %exit.mainloop.at = load i32, i32* %a_len_ptr
+; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:      loop.preheader:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, 7
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp slt i32 %idx.next, 2147483640
+; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND2]], label %loop, label %main.exit.selector
+; CHECK:      main.exit.selector:
+; CHECK-NEXT:   %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483640
+; CHECK-NEXT:   br i1 [[COND3]], label %main.pseudo.exit, label %exit
+; CHECK:      main.pseudo.exit:
+; CHECK-NEXT:   %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    br label %postloop
+; CHECK:      postloop:
+; CHECK-NEXT:   br label %loop.postloop
+; CHECK:      loop.postloop:
+; CHECK-NEXT:   %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:   %idx.next.postloop = add i32 %idx.postloop, 7
+; CHECK-NEXT:   %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:   br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.postloop:
+; CHECK-NEXT:   %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
+; CHECK-NEXT:   store i32 0, i32* %addr.postloop
+; CHECK-NEXT:   %next.postloop = icmp slt i32 %idx.next.postloop, 2147483640
+; CHECK-NEXT:   br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 2147483640
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest
+; value of Len for which IRCE is allowed.
+define void @test_03(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_03(
+; CHECK:      entry:
+; CHECK-NEXT:   %exit.mainloop.at = load i32, i32* %a_len_ptr
+; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:      loop.preheader:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, 7
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp slt i32 %idx.next, 2147483647
+; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at
+; CHECK-NEXT:   br i1 [[COND2]], label %loop, label %main.exit.selector
+; CHECK:      main.exit.selector:
+; CHECK-NEXT:   %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483647
+; CHECK-NEXT:   br i1 [[COND3]], label %main.pseudo.exit, label %exit
+; CHECK:      main.pseudo.exit:
+; CHECK-NEXT:   %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ]
+; CHECK-NEXT:    br label %postloop
+; CHECK:      postloop:
+; CHECK-NEXT:   br label %loop.postloop
+; CHECK:      loop.postloop:
+; CHECK-NEXT:   %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:   %idx.next.postloop = add i32 %idx.postloop, 7
+; CHECK-NEXT:   %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:   br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.postloop:
+; CHECK-NEXT:   %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop
+; CHECK-NEXT:   store i32 0, i32* %addr.postloop
+; CHECK-NEXT:   %next.postloop = icmp slt i32 %idx.next.postloop, 2147483647
+; CHECK-NEXT:   br i1 %next.postloop, label %loop.postloop, label %exit.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !1
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 2147483647
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 6. IRCE is allowed
+; because the branch would fail once idx.next == MAX_INT - 1 keeping the
+; access in bounds.
+define void @test_04(i32* %arr, i32* %a_len_ptr) {
+  ; CHECK:  @test_04(
+  ; CHECK:  loop:
+  ; CHECK:  [[IV:%[^ ]+]] = phi i32
+  ; CHECK:  [[IDX_NEXT:%[^ ]+]] = add i32 [[IV]], 7
+
+  ; CHECK:  main.exit.selector:
+  ; CHECK:  [[PSEUDO_PHI:%[^ ]+]] =  phi i32 [ [[IDX_NEXT]], %in.bounds ]
+  ; CHECK:  [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], 2147483647
+  ; CHECK:  br i1 [[COND]], label %main.pseudo.exit, label %exit
+
+  ; CHECK: loop.postloop:
+  ; CHECK: [[IDX_POST:%[^ ]+]] = phi i32
+  ; CHECK: [[COND_POST:%[^ ]+]] = icmp slt i32 [[IDX_POST]], %exit.mainloop.at
+  ; CHECK: br i1 [[COND_POST]], label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !2
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, 2147483647
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed.
+define void @test_05(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_05(
+; CHECK:      entry:
+; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
+; CHECK-NEXT:   %exit.preloop.at = add i32 %len, -1
+; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp sgt i32 100, %exit.preloop.at
+; CHECK-NEXT:   br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:      loop.preloop.preheader:
+; CHECK-NEXT:   br label %loop.preloop
+; CHECK:      mainloop:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, -7
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
+; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp sgt i32 %idx.next, -1
+; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
+; CHECK:      loop.preloop:
+; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
+; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -7
+; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
+; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.preloop:
+; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:   store i32 0, i32* %addr.preloop
+; CHECK-NEXT:   %next.preloop = icmp sgt i32 %idx.next.preloop, -1
+; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp sgt i32 %idx.next.preloop, %exit.preloop.at
+; CHECK-NEXT:   br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:      preloop.exit.selector:
+; CHECK-NEXT:   %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
+; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp sgt i32 %idx.next.preloop.lcssa, -1
+; CHECK-NEXT:   br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
+; CHECK:      preloop.pseudo.exit:
+; CHECK-NEXT:   %idx.preloop.copy = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
+; CHECK-NEXT:   %indvar.end = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
+; CHECK-NEXT:   br label %mainloop
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp sgt i32 %idx.next, -1
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
+define void @test_06(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_06(
+; CHECK:      entry:
+; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
+; CHECK-NEXT:   %exit.preloop.at = add i32 %len, -1
+; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp ugt i32 2147483640, %exit.preloop.at
+; CHECK-NEXT:   br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:      loop.preloop.preheader:
+; CHECK-NEXT:   br label %loop.preloop
+; CHECK:      mainloop:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, -7
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
+; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp ugt i32 %idx.next, 6
+; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
+; CHECK:      loop.preloop:
+; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483640, %loop.preloop.preheader ]
+; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -7
+; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
+; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.preloop:
+; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:   store i32 0, i32* %addr.preloop
+; CHECK-NEXT:   %next.preloop = icmp ugt i32 %idx.next.preloop, 6
+; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at
+; CHECK-NEXT:   br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:      preloop.exit.selector:
+; CHECK-NEXT:   %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
+; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6
+; CHECK-NEXT:   br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
+; CHECK:      preloop.pseudo.exit:
+; CHECK-NEXT:   %idx.preloop.copy = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
+; CHECK-NEXT:   %indvar.end = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
+; CHECK-NEXT:   br label %mainloop
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !3
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 6
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed,
+; because we can cross the 0 border.
+define void @test_07(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_07(
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !3
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 5
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed.
+define void @test_08(i32* %arr, i32* %a_len_ptr) {
+
+; CHECK:      @test_08(
+; CHECK:      entry:
+; CHECK-NEXT:   %len = load i32, i32* %a_len_ptr
+; CHECK-NEXT:   %exit.preloop.at = add i32 %len, -1
+; CHECK-NEXT:   [[COND1:%[^ ]+]] = icmp ugt i32 2147483647, %exit.preloop.at
+; CHECK-NEXT:   br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:      loop.preloop.preheader:
+; CHECK-NEXT:   br label %loop.preloop
+; CHECK:      mainloop:
+; CHECK-NEXT:   br label %loop
+; CHECK:      loop:
+; CHECK-NEXT:   %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:   %idx.next = add i32 %idx, -7
+; CHECK-NEXT:   %abc = icmp slt i32 %idx, %len
+; CHECK-NEXT:   br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK:      in.bounds:
+; CHECK-NEXT:   %addr = getelementptr i32, i32* %arr, i32 %idx
+; CHECK-NEXT:   store i32 0, i32* %addr
+; CHECK-NEXT:   %next = icmp ugt i32 %idx.next, 6
+; CHECK-NEXT:   br i1 %next, label %loop, label %exit.loopexit
+; CHECK:      loop.preloop:
+; CHECK-NEXT:   %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483647, %loop.preloop.preheader ]
+; CHECK-NEXT:   %idx.next.preloop = add i32 %idx.preloop, -7
+; CHECK-NEXT:   %abc.preloop = icmp slt i32 %idx.preloop, %len
+; CHECK-NEXT:   br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+; CHECK:      in.bounds.preloop:
+; CHECK-NEXT:   %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop
+; CHECK-NEXT:   store i32 0, i32* %addr.preloop
+; CHECK-NEXT:   %next.preloop = icmp ugt i32 %idx.next.preloop, 6
+; CHECK-NEXT:   [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at
+; CHECK-NEXT:   br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector
+; CHECK:      preloop.exit.selector:
+; CHECK-NEXT:   %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ]
+; CHECK-NEXT:   [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6
+; CHECK-NEXT:   br i1 [[COND3]], label %preloop.pseudo.exit, label %exit
+; CHECK:      preloop.pseudo.exit:
+; CHECK-NEXT:   %idx.preloop.copy = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
+; CHECK-NEXT:   %indvar.end = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ]
+; CHECK-NEXT:   br label %mainloop
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !3
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -7
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 6
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 50}
+!1 = !{i32 0, i32 2147483640}
+!2 = !{i32 0, i32 2147483641}
+!3 = !{i32 10, i32 50}

Added: llvm/trunk/test/Transforms/IRCE/unhandled.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/unhandled.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/unhandled.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/unhandled.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -irce-print-changed-loops -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK-NOT: constrained Loop at depth
+
+; Demonstrates that we don't currently handle the general expression
+; `A * I + B'.
+
+define void @general_affine_expressions(i32 *%arr, i32 *%a_len_ptr, i32 %n,
+                                        i32 %scale, i32 %offset) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %idx.mul = mul i32 %idx, %scale
+  %array.idx = add i32 %idx.mul, %offset
+  %abc.high = icmp slt i32 %array.idx, %len
+  %abc.low = icmp sge i32 %array.idx, 0
+  %abc = and i1 %abc.low, %abc.high
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %array.idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+; Check that we do the right thing for a loop that could not be
+; simplified due to an indirectbr.
+
+define void @multiple_latches(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %n.add.1 = add i32 %n, 1
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ], [ %idx.next, %continue ]
+  %idx.next = add i32 %idx, 1
+  %idx.next2 = add i32 %idx, 2
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %continue
+
+ continue:
+  %next2 = icmp slt i32 %idx.next, %n.add.1
+  %dest = select i1 %next2, i8* blockaddress(@multiple_latches, %loop), i8* blockaddress(@multiple_latches, %exit)
+  indirectbr i8* %dest, [ label %loop, label %exit]
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+define void @already_cloned(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
+ entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+ in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit, !irce.loop.clone !{}
+
+ out.of.bounds:
+  ret void
+
+ exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ugt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ugt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ugt.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ugt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,264 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+; UGT condition for increasing loop.
+define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_01(
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 100
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; UGT condition for decreasing loop.
+define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_02(
+; CHECK:        entry:
+; CHECK-NEXT:     %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
+; CHECK-NEXT:     %umax = select i1 [[COND1]], i32 %len, i32 1
+; CHECK-NEXT:     %exit.preloop.at = add i32 %umax, -1
+; CHECK-NEXT:     [[COND2:%[^ ]+]] = icmp ugt i32 100, %exit.preloop.at
+; CHECK-NEXT:     br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:        mainloop:
+; CHECK-NEXT:     br label %loop
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     %idx.next = add i32 %idx, -1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %len
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.postloop:
+; CHECK:        loop.preloop:
+; CHECK-NEXT:     %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
+; CHECK-NEXT:     %idx.next.preloop = add i32 %idx.preloop, -1
+; CHECK-NEXT:     %abc.preloop = icmp ult i32 %idx.preloop, %len
+; CHECK-NEXT:     br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 0
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check SINT_MAX + 1, test is similar to test_01.
+define void @test_03(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_03(
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 2147483648
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check SINT_MAX + 1, test is similar to test_02.
+define void @test_04(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_04(
+; CHECK:        entry:
+; CHECK-NEXT:     %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
+; CHECK-NEXT:     %umax = select i1 [[COND1]], i32 %len, i32 1
+; CHECK-NEXT:     %exit.preloop.at = add i32 %umax, -1
+; CHECK-NEXT:     [[COND2:%[^ ]+]] = icmp ugt i32 -2147483648, %exit.preloop.at
+; CHECK-NEXT:     br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:        mainloop:
+; CHECK-NEXT:     br label %loop
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     %idx.next = add i32 %idx, -1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %len
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.postloop:
+; CHECK:        loop.preloop:
+; CHECK-NEXT:     %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ -2147483648, %loop.preloop.preheader ]
+; CHECK-NEXT:     %idx.next.preloop = add i32 %idx.preloop, -1
+; CHECK-NEXT:     %abc.preloop = icmp ult i32 %idx.preloop, %len
+; CHECK-NEXT:     br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 0
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Increasing loop, UINT_MAX. Negative test: we cannot add 1 to UINT_MAX.
+define void @test_05(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_05(
+; CHECK-NOT:    loop.preloop:
+; CHECK-NOT:    loop.postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 4294967295
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Decreasing loop, UINT_MAX. Positive test.
+define void @test_06(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_06(
+; CHECK:        mainloop:
+; CHECK-NEXT:     br label %loop
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     %idx.next = add nuw i32 %idx, -1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %len
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.postloop:
+; CHECK:        loop.preloop:
+; CHECK-NEXT:     %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ -1, %loop.preloop.preheader ]
+; CHECK-NEXT:     %idx.next.preloop = add nuw i32 %idx.preloop, -1
+; CHECK-NEXT:     %abc.preloop = icmp ult i32 %idx.preloop, %len
+; CHECK-NEXT:     br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nuw i32 %idx, -1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ugt i32 %idx.next, 0
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 50}

Added: llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ult.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ult.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ult.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/unsigned_comparisons_ult.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,391 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+; CHECK-NOT: irce: in function test_09: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+; ULT condition for increasing loop.
+define void @test_01(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_01
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; ULT condition for decreasing loops.
+define void @test_02(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_02(
+; CHECK:        entry:
+; CHECK-NEXT:     %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
+; CHECK-NEXT:     %umax = select i1 [[COND1]], i32 %len, i32 1
+; CHECK-NEXT:     %exit.preloop.at = add i32 %umax, -1
+; CHECK-NEXT:     [[COND2:%[^ ]+]] = icmp ugt i32 100, %exit.preloop.at
+; CHECK-NEXT:     br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:        mainloop:
+; CHECK-NEXT:     br label %loop
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     %idx.next = add i32 %idx, -1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %len
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.postloop:
+; CHECK:        loop.preloop:
+; CHECK-NEXT:     %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ]
+; CHECK-NEXT:     %idx.next.preloop = add i32 %idx.preloop, -1
+; CHECK-NEXT:     %abc.preloop = icmp ult i32 %idx.preloop, %len
+; CHECK-NEXT:     br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 1
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check SINT_MAX.
+define void @test_03(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_03
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 2147483647
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check SINT_MAX + 1, test is similar to test_01.
+define void @test_04(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_04
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 2147483648
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Check SINT_MAX + 1, test is similar to test_02.
+define void @test_05(i32* %arr, i32* %a_len_ptr) #0 {
+; CHECK: test_05(
+; CHECK:        entry:
+; CHECK-NEXT:     %len = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND1:%[^ ]+]] = icmp ugt i32 %len, 1
+; CHECK-NEXT:     %umax = select i1 [[COND1]], i32 %len, i32 1
+; CHECK-NEXT:     %exit.preloop.at = add i32 %umax, -1
+; CHECK-NEXT:     [[COND2:%[^ ]+]] = icmp ugt i32 -2147483648, %exit.preloop.at
+; CHECK-NEXT:     br i1 [[COND2]], label %loop.preloop.preheader, label %preloop.pseudo.exit
+; CHECK:        mainloop:
+; CHECK-NEXT:     br label %loop
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ]
+; CHECK-NEXT:     %idx.next = add i32 %idx, -1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %len
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.postloop:
+; CHECK:        loop.preloop:
+; CHECK-NEXT:     %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ -2147483648, %loop.preloop.preheader ]
+; CHECK-NEXT:     %idx.next.preloop = add i32 %idx.preloop, -1
+; CHECK-NEXT:     %abc.preloop = icmp ult i32 %idx.preloop, %len
+; CHECK-NEXT:     br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 2147483648, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, -1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 1
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Increasing loop, UINT_MAX. Positive test.
+define void @test_06(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_06
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add nuw nsw i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add nuw nsw i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nsw nuw i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 4294967295
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Decreasing loop, UINT_MAX. Negative test: we cannot substract -1 from 0.
+define void @test_07(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK: test_07(
+; CHECK-NOT:    loop.preloop:
+; CHECK-NOT:    loop.postloop:
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 4294967295, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add nuw i32 %idx, -1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 0
+  br i1 %next, label %exit, label %loop
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Unsigned walking through signed border is allowed.
+; Iteration space [0; UINT_MAX - 99), the fact that SINT_MAX is within this
+; range does not prevent us from performing IRCE.
+
+define void @test_08(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_08
+; CHECK:        entry:
+; CHECK-NEXT:     %exit.mainloop.at = load i32, i32* %a_len_ptr, !range !0
+; CHECK-NEXT:     [[COND:%[^ ]+]] = icmp ult i32 0, %exit.mainloop.at
+; CHECK-NEXT:     br i1 [[COND]], label %loop.preheader, label %main.pseudo.exit
+; CHECK:        loop:
+; CHECK-NEXT:     %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ]
+; CHECK-NEXT:     %idx.next = add i32 %idx, 1
+; CHECK-NEXT:     %abc = icmp ult i32 %idx, %exit.mainloop.at
+; CHECK-NEXT:     br i1 true, label %in.bounds, label %out.of.bounds.loopexit1
+; CHECK-NOT:    loop.preloop:
+; CHECK:        loop.postloop:
+; CHECK-NEXT:     %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ]
+; CHECK-NEXT:     %idx.next.postloop = add i32 %idx.postloop, 1
+; CHECK-NEXT:     %abc.postloop = icmp ult i32 %idx.postloop, %exit.mainloop.at
+; CHECK-NEXT:     br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, -100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+; Walking through the border of unsigned range is not allowed
+; (iteration space [-100; 100)). Negative test.
+
+define void @test_09(i32* %arr, i32* %a_len_ptr) #0 {
+
+; CHECK:      test_09
+; CHECK-NOT:  preloop
+; CHECK-NOT:  postloop
+; CHECK-NOT:  br i1 false
+; CHECK-NOT:  br i1 true
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  br label %loop
+
+loop:
+  %idx = phi i32 [ -100, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp ult i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds
+
+in.bounds:
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp ult i32 %idx.next, 100
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:
+  ret void
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 50}

Added: llvm/trunk/test/Transforms/IRCE/variable-loop-bounds.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/variable-loop-bounds.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/variable-loop-bounds.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/variable-loop-bounds.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,354 @@
+; RUN: opt -irce -S -verify-loop-info -irce-print-changed-loops -irce-skip-profitability-checks < %s 2>&1 | FileCheck %s
+
+; CHECK: irce: in function test_inc_eq: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
+; CHECK: irce: in function test_inc_ne: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
+; CHECK: irce: in function test_inc_slt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
+; CHECK: irce: in function test_inc_ult: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting>
+; CHECK: irce: in function signed_var_imm_dec_sgt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
+; CHECK-NOT: irce: in function signed_var_imm_dec_slt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
+; CHECK: irce: in function signed_var_imm_dec_sge: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
+; CHECK: irce: in function signed_var_imm_dec_ne: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
+; CHECK-NOT: irce: in function signed_var_imm_dec_eq: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting>
+
+; CHECK-LABEL: test_inc_eq(
+; CHECK: main.exit.selector:
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N
+; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
+define void @test_inc_eq(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
+entry:
+  %cmp16 = icmp sgt i32 %N, 0
+  br i1 %cmp16, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:
+  ret void
+
+for.body:
+  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+  %cmp1 = icmp ult i32 %i.017, 512
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
+  %1 = load i32, i32* %arrayidx2, align 4
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:
+  %sub = sub i32 %0, %1
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %sub, %2
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+if.else:
+  %add6 = add nsw i32 %1, %0
+  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  store i32 %add6, i32* %arrayidx7, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nuw nsw i32 %i.017, 1
+  %exitcond = icmp eq i32 %inc, %N
+  br i1 %exitcond, label %for.cond.cleanup, label %for.body
+}
+
+; CHECK-LABEL: test_inc_ne
+; CHECK: main.exit.selector:
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N
+; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
+define void @test_inc_ne(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
+entry:
+  %cmp16 = icmp sgt i32 %N, 0
+  br i1 %cmp16, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:
+  ret void
+
+for.body:
+  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+  %cmp1 = icmp ult i32 %i.017, 512
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
+  %1 = load i32, i32* %arrayidx2, align 4
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:
+  %sub = sub i32 %0, %1
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %sub, %2
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+if.else:
+  %add6 = add nsw i32 %1, %0
+  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  store i32 %add6, i32* %arrayidx7, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nuw nsw i32 %i.017, 1
+  %exitcond = icmp ne i32 %inc, %N
+  br i1 %exitcond, label %for.body, label %for.cond.cleanup
+}
+
+; CHECK-LABEL: test_inc_slt(
+; CHECK: main.exit.selector:
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], %N
+; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
+define void @test_inc_slt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
+entry:
+  %cmp16 = icmp sgt i32 %N, 0
+  br i1 %cmp16, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:
+  ret void
+
+for.body:
+  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+  %cmp1 = icmp ult i32 %i.017, 512
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
+  %1 = load i32, i32* %arrayidx2, align 4
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:
+  %sub = sub i32 %0, %1
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %sub, %2
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+if.else:
+  %add6 = add nsw i32 %1, %0
+  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  store i32 %add6, i32* %arrayidx7, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nuw nsw i32 %i.017, 1
+  %exitcond = icmp slt i32 %inc, %N
+  br i1 %exitcond, label %for.body, label %for.cond.cleanup
+}
+
+; CHECK-LABEL: test_inc_ult
+; CHECK: main.exit.selector:
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N
+; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit
+define void @test_inc_ult(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) {
+entry:
+  %cmp16 = icmp ugt i32 %N, 0
+  br i1 %cmp16, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:
+  ret void
+
+for.body:
+  %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+  %cmp1 = icmp ult i32 %i.017, 512
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017
+  %1 = load i32, i32* %arrayidx2, align 4
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:
+  %sub = sub i32 %0, %1
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %sub, %2
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+if.else:
+  %add6 = add nsw i32 %1, %0
+  %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017
+  store i32 %add6, i32* %arrayidx7, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nuw nsw i32 %i.017, 1
+  %exitcond = icmp ult i32 %inc, %N
+  br i1 %exitcond, label %for.body, label %for.cond.cleanup
+}
+
+; CHECK-LABEL: signed_var_imm_dec_sgt(
+; CHECK: main.exit.selector:
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %dec, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M
+; CHECK: br i1 [[COND]]
+define void @signed_var_imm_dec_sgt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
+entry:
+  %cmp14 = icmp slt i32 %M, 1024
+  br i1 %cmp14, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.inc, %entry
+  ret void
+
+for.body:                                         ; preds = %entry, %for.inc
+  %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
+  %cmp1 = icmp slt i32 %iv, 1024
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
+  %1 = load i32, i32* %arrayidx2, align 4
+  %mul = mul nsw i32 %1, %0
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
+  br i1 %cmp1, label %for.inc, label %if.else
+
+if.else:                                          ; preds = %for.body
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %2, %mul
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %if.else
+  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
+  store i32 %storemerge, i32* %arrayidx3, align 4
+  %dec = add nsw i32 %iv, -1
+  %cmp = icmp sgt i32 %dec, %M
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+; CHECK-LABEL: signed_var_imm_dec_sge(
+; CHECK: main.exit.selector:          ; preds = %for.inc
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %iv, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M
+; CHECK: br i1 [[COND]]
+define void @signed_var_imm_dec_sge(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
+entry:
+  %cmp14 = icmp sgt i32 %M, 1024
+  br i1 %cmp14, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.inc, %entry
+  ret void
+
+for.body:                                         ; preds = %entry, %for.inc
+  %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
+  %cmp1 = icmp slt i32 %iv, 1024
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
+  %1 = load i32, i32* %arrayidx2, align 4
+  %mul = mul nsw i32 %1, %0
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
+  br i1 %cmp1, label %for.inc, label %if.else
+
+if.else:                                          ; preds = %for.body
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %2, %mul
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %if.else
+  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
+  store i32 %storemerge, i32* %arrayidx3, align 4
+  %dec = add nsw i32 %iv, -1
+  %cmp = icmp sgt i32 %iv, %M
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+define void @signed_var_imm_dec_slt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
+entry:
+  %cmp14 = icmp sgt i32 %M, 1024
+  br i1 %cmp14, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.inc, %entry
+  ret void
+
+for.body:                                         ; preds = %entry, %for.inc
+  %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
+  %cmp1 = icmp slt i32 %iv, 1024
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
+  %1 = load i32, i32* %arrayidx2, align 4
+  %mul = mul nsw i32 %1, %0
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
+  br i1 %cmp1, label %for.inc, label %if.else
+
+if.else:                                          ; preds = %for.body
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %2, %mul
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %if.else
+  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
+  store i32 %storemerge, i32* %arrayidx3, align 4
+  %dec = add nsw i32 %iv, -1
+  %cmp = icmp slt i32 %iv, %M
+  br i1 %cmp, label %for.cond.cleanup, label %for.body
+}
+
+; CHECK-LABEL: signed_var_imm_dec_ne(
+; CHECK: main.exit.selector:          ; preds = %for.inc
+; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %dec, %for.inc ]
+; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M
+; CHECK: br i1 [[COND]]
+define void @signed_var_imm_dec_ne(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
+entry:
+  %cmp14 = icmp slt i32 %M, 1024
+  br i1 %cmp14, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.inc, %entry
+  ret void
+
+for.body:                                         ; preds = %entry, %for.inc
+  %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
+  %cmp1 = icmp slt i32 %iv, 1024
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
+  %1 = load i32, i32* %arrayidx2, align 4
+  %mul = mul nsw i32 %1, %0
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
+  br i1 %cmp1, label %for.inc, label %if.else
+
+if.else:                                          ; preds = %for.body
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %2, %mul
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %if.else
+  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
+  store i32 %storemerge, i32* %arrayidx3, align 4
+  %dec = add nsw i32 %iv, -1
+  %cmp = icmp ne i32 %dec, %M
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+define void @signed_var_imm_dec_eq(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) {
+entry:
+  %cmp14 = icmp slt i32 %M, 1024
+  br i1 %cmp14, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.inc, %entry
+  ret void
+
+for.body:                                         ; preds = %entry, %for.inc
+  %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ]
+  %cmp1 = icmp slt i32 %iv, 1024
+  %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv
+  %1 = load i32, i32* %arrayidx2, align 4
+  %mul = mul nsw i32 %1, %0
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv
+  br i1 %cmp1, label %for.inc, label %if.else
+
+if.else:                                          ; preds = %for.body
+  %2 = load i32, i32* %arrayidx3, align 4
+  %add = add nsw i32 %2, %mul
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %if.else
+  %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ]
+  store i32 %storemerge, i32* %arrayidx3, align 4
+  %dec = add nsw i32 %iv, -1
+  %cmp = icmp eq i32 %dec, %M
+  br i1 %cmp, label %for.cond.cleanup, label %for.body
+}

Added: llvm/trunk/test/Transforms/IRCE/wide_indvar.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/wide_indvar.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/wide_indvar.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/wide_indvar.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,459 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -irce-allow-narrow-latch=true -S < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -irce-allow-narrow-latch=true -S < %s 2>&1 | FileCheck %s
+
+; Check that we can remove trivially non-failing range check.
+define i32 @test_increasing_slt_slt_wide_simple_no_postloop() {
+
+; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_no_postloop(
+; CHECK-NOT:   preloop
+; CHECK-NOT:   postloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp slt i64 %iv, 100
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp slt i32 %narrow.iv, 100
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; This range check fails on the last iteration, so it needs a postloop.
+define i32 @test_increasing_slt_slt_wide_simple_postloop() {
+
+; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_postloop(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp slt i64 %wide.narrow.iv, 99
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp slt i64 %iv, 99
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp slt i32 %narrow.iv, 100
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; General case. If both %N and %M are non-negative, we do not need a preloop.
+define i32 @test_increasing_slt_slt_wide_non-negative(i32* %n_ptr, i64* %m_ptr) {
+
+; CHECK-LABEL: @test_increasing_slt_slt_wide_non-negative(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp slt i64 %wide.narrow.iv, %exit.mainloop.at
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M = load i64, i64* %m_ptr, !range !1
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp slt i64 %iv, %M
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp slt i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; General case. Even though %M may be negative, we do not need a preloop because
+; we make a non-negativity runtime check against M and do not go to main loop if
+; M was negative.
+define i32 @test_increasing_slt_slt_wide_general(i32* %n_ptr, i64* %m_ptr) {
+
+; CHECK-LABEL: @test_increasing_slt_slt_wide_general(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp slt i64
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M = load i64, i64* %m_ptr
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp slt i64 %iv, %M
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp slt i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; General case with preloop.
+define i32 @test_increasing_slt_slt_wide_general_preloop(i32* %n_ptr, i64* %m_ptr) {
+
+; CHECK-LABEL: @test_increasing_slt_slt_wide_general_preloop(
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp slt i64
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       preloop
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M = load i64, i64* %m_ptr
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp slt i64 %iv, %M
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv to i32
+  %latch.cond = icmp slt i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; Same as above, multiple checks.
+define i32 @test_increasing_slt_slt_wide_multiple_checks(i32* %n_ptr, i64* %m1_ptr, i64* %m2_ptr, i64* %m3_ptr, i64* %m4_ptr) {
+; CHECK-LABEL: @test_increasing_slt_slt_wide_multiple_checks(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       %c1 = and i1 true, true
+; CHECK:       %c2 = and i1 %c1, true
+; CHECK:       %rc = and i1 %c2, true
+; CHECK:       br i1 %rc, label %backedge, label %check_failed.loopexit
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp slt i64
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M1 = load i64, i64* %m1_ptr
+  %M2 = load i64, i64* %m2_ptr
+  %M3 = load i64, i64* %m3_ptr
+  %M4 = load i64, i64* %m4_ptr
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc1 = icmp slt i64 %iv, %M1
+  %rc2 = icmp slt i64 %iv, %M2
+  %rc3 = icmp slt i64 %iv, %M3
+  %rc4 = icmp slt i64 %iv, %M4
+  %c1 = and i1 %rc1, %rc2
+  %c2 = and i1 %c1, %rc3
+  %rc = and i1 %c2, %rc4
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp slt i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; Wide IV against narrow range check. We don't currently support it.
+define i32 @test_increasing_slt_slt_wide_simple_negtest_narrow_rc() {
+
+; CHECK-LABEL: @test_increasing_slt_slt_wide_simple_negtest_narrow_rc(
+; CHECK-NOT:   i1 true
+; CHECK-NOT:   main
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %narrow.iv = trunc i64 %iv to i32
+  %rc = icmp slt i32 %narrow.iv, 101
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %latch.cond = icmp slt i64 %iv, 100
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; Check that we can remove trivially non-failing range check.
+define i32 @test_increasing_ult_ult_wide_simple_no_postloop() {
+
+; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_no_postloop(
+; CHECK-NOT:   preloop
+; CHECK-NOT:   postloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp ult i64 %iv, 100
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp ult i32 %narrow.iv, 100
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; This range check fails on the last iteration, so it needs a postloop.
+define i32 @test_increasing_ult_ult_wide_simple_postloop() {
+
+; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_postloop(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp ult i64 %wide.narrow.iv, 99
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp ult i64 %iv, 99
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp ult i32 %narrow.iv, 100
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; General case. If both %N and %M are non-negative, we do not need a preloop.
+define i32 @test_increasing_ult_ult_wide_non-negative(i32* %n_ptr, i64* %m_ptr) {
+
+; CHECK-LABEL: @test_increasing_ult_ult_wide_non-negative(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp ult i64 %wide.narrow.iv, %exit.mainloop.at
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M = load i64, i64* %m_ptr, !range !1
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp ult i64 %iv, %M
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp ult i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; General case. Even though %M may be negative, we do not need a preloop because
+; we make a non-negativity runtime check against M and do not go to main loop if
+; M was negative.
+define i32 @test_increasing_ult_ult_wide_general(i32* %n_ptr, i64* %m_ptr) {
+
+; CHECK-LABEL: @test_increasing_ult_ult_wide_general(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       br i1 true, label %backedge, label %check_failed
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp ult i64
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M = load i64, i64* %m_ptr
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc = icmp ult i64 %iv, %M
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp ult i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; Same as above, multiple checks.
+define i32 @test_increasing_ult_ult_wide_multiple_checks(i32* %n_ptr, i64* %m1_ptr, i64* %m2_ptr, i64* %m3_ptr, i64* %m4_ptr) {
+; CHECK-LABEL: @test_increasing_ult_ult_wide_multiple_checks(
+; CHECK-NOT:   preloop
+; CHECK:       loop:
+; CHECK:       %c1 = and i1 true, true
+; CHECK:       %c2 = and i1 %c1, true
+; CHECK:       %rc = and i1 %c2, true
+; CHECK:       br i1 %rc, label %backedge, label %check_failed.loopexit
+; CHECK:       backedge
+; CHECK:       [[COND:%[^ ]+]] = icmp ult i64
+; CHECK:       br i1 [[COND]], label %loop, label %main.exit.selector
+; CHECK:       postloop
+
+entry:
+  %N = load i32, i32* %n_ptr, !range !2
+  %M1 = load i64, i64* %m1_ptr
+  %M2 = load i64, i64* %m2_ptr
+  %M3 = load i64, i64* %m3_ptr
+  %M4 = load i64, i64* %m4_ptr
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %rc1 = icmp ult i64 %iv, %M1
+  %rc2 = icmp ult i64 %iv, %M2
+  %rc3 = icmp ult i64 %iv, %M3
+  %rc4 = icmp ult i64 %iv, %M4
+  %c1 = and i1 %rc1, %rc2
+  %c2 = and i1 %c1, %rc3
+  %rc = and i1 %c2, %rc4
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %latch.cond = icmp ult i32 %narrow.iv, %N
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+; Wide IV against narrow range check. We don't currently support it.
+define i32 @test_increasing_ult_ult_wide_simple_negtest_narrow_rc() {
+
+; CHECK-LABEL: @test_increasing_ult_ult_wide_simple_negtest_narrow_rc(
+; CHECK-NOT:   i1 true
+; CHECK-NOT:   main
+
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ]
+  %narrow.iv = trunc i64 %iv to i32
+  %rc = icmp ult i32 %narrow.iv, 101
+  br i1 %rc, label %backedge, label %check_failed
+
+backedge:
+  %iv.next = add i64 %iv, 1
+  %latch.cond = icmp ult i64 %iv, 100
+  br i1 %latch.cond, label %loop, label %exit
+
+exit:
+  ret i32 %narrow.iv
+
+check_failed:
+  ret i32 -1
+}
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{i64 0, i64 9223372036854775807}
+!2 = !{i32 1, i32 2147483647}

Added: llvm/trunk/test/Transforms/IRCE/with-parent-loops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/with-parent-loops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IRCE/with-parent-loops.ll (added)
+++ llvm/trunk/test/Transforms/IRCE/with-parent-loops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,346 @@
+; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
+; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' < %s 2>&1 | FileCheck %s
+
+; This test checks if we update the LoopInfo correctly in the presence
+; of parents, uncles and cousins.
+
+; Function Attrs: alwaysinline
+define void @inner_loop(i32* %arr, i32* %a_len_ptr, i32 %n) #0 {
+; CHECK: irce: in function inner_loop: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
+
+entry:
+  %len = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check = icmp sgt i32 %n, 0
+  br i1 %first.itr.check, label %loop, label %exit
+
+loop:                                             ; preds = %in.bounds, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
+  %idx.next = add i32 %idx, 1
+  %abc = icmp slt i32 %idx, %len
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1
+
+in.bounds:                                        ; preds = %loop
+  %addr = getelementptr i32, i32* %arr, i32 %idx
+  store i32 0, i32* %addr
+  %next = icmp slt i32 %idx.next, %n
+  br i1 %next, label %loop, label %exit
+
+out.of.bounds:                                    ; preds = %loop
+  ret void
+
+exit:                                             ; preds = %in.bounds, %entry
+  ret void
+}
+
+; Function Attrs: alwaysinline
+define void @with_parent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 {
+; CHECK: irce: in function with_parent: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %inner_loop.exit, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit ]
+  %idx.next = add i32 %idx, 1
+  %next = icmp ult i32 %idx.next, %parent.count
+  %len.i = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i, label %loop.i, label %exit.i
+
+loop.i:                                           ; preds = %in.bounds.i, %loop
+  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
+  %idx.next.i = add i32 %idx.i, 1
+  %abc.i = icmp slt i32 %idx.i, %len.i
+  br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
+
+in.bounds.i:                                      ; preds = %loop.i
+  %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
+  store i32 0, i32* %addr.i
+  %next.i = icmp slt i32 %idx.next.i, %n
+  br i1 %next.i, label %loop.i, label %exit.i
+
+out.of.bounds.i:                                  ; preds = %loop.i
+  br label %inner_loop.exit
+
+exit.i:                                           ; preds = %in.bounds.i, %loop
+  br label %inner_loop.exit
+
+inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
+  br i1 %next, label %loop, label %exit
+
+exit:                                             ; preds = %inner_loop.exit
+  ret void
+}
+
+; Function Attrs: alwaysinline
+define void @with_grandparent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
+; CHECK: irce: in function with_grandparent: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %with_parent.exit, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ]
+  %idx.next = add i32 %idx, 1
+  %next = icmp ult i32 %idx.next, %grandparent.count
+  br label %loop.i
+
+loop.i:                                           ; preds = %inner_loop.exit.i, %loop
+  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ]
+  %idx.next.i = add i32 %idx.i, 1
+  %next.i = icmp ult i32 %idx.next.i, %parent.count
+  %len.i.i = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i.i = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
+
+loop.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
+  %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ]
+  %idx.next.i.i = add i32 %idx.i.i, 1
+  %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
+  br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
+
+in.bounds.i.i:                                    ; preds = %loop.i.i
+  %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
+  store i32 0, i32* %addr.i.i
+  %next.i.i = icmp slt i32 %idx.next.i.i, %n
+  br i1 %next.i.i, label %loop.i.i, label %exit.i.i
+
+out.of.bounds.i.i:                                ; preds = %loop.i.i
+  br label %inner_loop.exit.i
+
+exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
+  br label %inner_loop.exit.i
+
+inner_loop.exit.i:                                ; preds = %exit.i.i, %out.of.bounds.i.i
+  br i1 %next.i, label %loop.i, label %with_parent.exit
+
+with_parent.exit:                                 ; preds = %inner_loop.exit.i
+  br i1 %next, label %loop, label %exit
+
+exit:                                             ; preds = %with_parent.exit
+  ret void
+}
+
+; Function Attrs: alwaysinline
+define void @with_sibling(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 {
+; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
+; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i6<header><exiting>,%in.bounds.i9<latch><exiting>
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %inner_loop.exit12, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit12 ]
+  %idx.next = add i32 %idx, 1
+  %next = icmp ult i32 %idx.next, %parent.count
+  %len.i = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i, label %loop.i, label %exit.i
+
+loop.i:                                           ; preds = %in.bounds.i, %loop
+  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
+  %idx.next.i = add i32 %idx.i, 1
+  %abc.i = icmp slt i32 %idx.i, %len.i
+  br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
+
+in.bounds.i:                                      ; preds = %loop.i
+  %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
+  store i32 0, i32* %addr.i
+  %next.i = icmp slt i32 %idx.next.i, %n
+  br i1 %next.i, label %loop.i, label %exit.i
+
+out.of.bounds.i:                                  ; preds = %loop.i
+  br label %inner_loop.exit
+
+exit.i:                                           ; preds = %in.bounds.i, %loop
+  br label %inner_loop.exit
+
+inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
+  %len.i1 = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i2 = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i2, label %loop.i6, label %exit.i11
+
+loop.i6:                                          ; preds = %in.bounds.i9, %inner_loop.exit
+  %idx.i3 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i4, %in.bounds.i9 ]
+  %idx.next.i4 = add i32 %idx.i3, 1
+  %abc.i5 = icmp slt i32 %idx.i3, %len.i1
+  br i1 %abc.i5, label %in.bounds.i9, label %out.of.bounds.i10, !prof !1
+
+in.bounds.i9:                                     ; preds = %loop.i6
+  %addr.i7 = getelementptr i32, i32* %arr, i32 %idx.i3
+  store i32 0, i32* %addr.i7
+  %next.i8 = icmp slt i32 %idx.next.i4, %n
+  br i1 %next.i8, label %loop.i6, label %exit.i11
+
+out.of.bounds.i10:                                ; preds = %loop.i6
+  br label %inner_loop.exit12
+
+exit.i11:                                         ; preds = %in.bounds.i9, %inner_loop.exit
+  br label %inner_loop.exit12
+
+inner_loop.exit12:                                ; preds = %exit.i11, %out.of.bounds.i10
+  br i1 %next, label %loop, label %exit
+
+exit:                                             ; preds = %inner_loop.exit12
+  ret void
+}
+
+; Function Attrs: alwaysinline
+define void @with_cousin(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
+; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
+; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i10<header><exiting>,%in.bounds.i.i13<latch><exiting>
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %with_parent.exit17, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit17 ]
+  %idx.next = add i32 %idx, 1
+  %next = icmp ult i32 %idx.next, %grandparent.count
+  br label %loop.i
+
+loop.i:                                           ; preds = %inner_loop.exit.i, %loop
+  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ]
+  %idx.next.i = add i32 %idx.i, 1
+  %next.i = icmp ult i32 %idx.next.i, %parent.count
+  %len.i.i = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i.i = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
+
+loop.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
+  %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ]
+  %idx.next.i.i = add i32 %idx.i.i, 1
+  %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
+  br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
+
+in.bounds.i.i:                                    ; preds = %loop.i.i
+  %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
+  store i32 0, i32* %addr.i.i
+  %next.i.i = icmp slt i32 %idx.next.i.i, %n
+  br i1 %next.i.i, label %loop.i.i, label %exit.i.i
+
+out.of.bounds.i.i:                                ; preds = %loop.i.i
+  br label %inner_loop.exit.i
+
+exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i
+  br label %inner_loop.exit.i
+
+inner_loop.exit.i:                                ; preds = %exit.i.i, %out.of.bounds.i.i
+  br i1 %next.i, label %loop.i, label %with_parent.exit
+
+with_parent.exit:                                 ; preds = %inner_loop.exit.i
+  br label %loop.i6
+
+loop.i6:                                          ; preds = %inner_loop.exit.i16, %with_parent.exit
+  %idx.i1 = phi i32 [ 0, %with_parent.exit ], [ %idx.next.i2, %inner_loop.exit.i16 ]
+  %idx.next.i2 = add i32 %idx.i1, 1
+  %next.i3 = icmp ult i32 %idx.next.i2, %parent.count
+  %len.i.i4 = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i.i5 = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i.i5, label %loop.i.i10, label %exit.i.i15
+
+loop.i.i10:                                       ; preds = %in.bounds.i.i13, %loop.i6
+  %idx.i.i7 = phi i32 [ 0, %loop.i6 ], [ %idx.next.i.i8, %in.bounds.i.i13 ]
+  %idx.next.i.i8 = add i32 %idx.i.i7, 1
+  %abc.i.i9 = icmp slt i32 %idx.i.i7, %len.i.i4
+  br i1 %abc.i.i9, label %in.bounds.i.i13, label %out.of.bounds.i.i14, !prof !1
+
+in.bounds.i.i13:                                  ; preds = %loop.i.i10
+  %addr.i.i11 = getelementptr i32, i32* %arr, i32 %idx.i.i7
+  store i32 0, i32* %addr.i.i11
+  %next.i.i12 = icmp slt i32 %idx.next.i.i8, %n
+  br i1 %next.i.i12, label %loop.i.i10, label %exit.i.i15
+
+out.of.bounds.i.i14:                              ; preds = %loop.i.i10
+  br label %inner_loop.exit.i16
+
+exit.i.i15:                                       ; preds = %in.bounds.i.i13, %loop.i6
+  br label %inner_loop.exit.i16
+
+inner_loop.exit.i16:                              ; preds = %exit.i.i15, %out.of.bounds.i.i14
+  br i1 %next.i3, label %loop.i6, label %with_parent.exit17
+
+with_parent.exit17:                               ; preds = %inner_loop.exit.i16
+  br i1 %next, label %loop, label %exit
+
+exit:                                             ; preds = %with_parent.exit17
+  ret void
+}
+
+; Function Attrs: alwaysinline
+define void @with_uncle(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 {
+; CHECK: irce: in function with_uncle: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting>
+; CHECK: irce: in function with_uncle: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting>
+
+entry:
+  br label %loop
+
+loop:                                             ; preds = %with_parent.exit, %entry
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ]
+  %idx.next = add i32 %idx, 1
+  %next = icmp ult i32 %idx.next, %grandparent.count
+  %len.i = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i, label %loop.i, label %exit.i
+
+loop.i:                                           ; preds = %in.bounds.i, %loop
+  %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ]
+  %idx.next.i = add i32 %idx.i, 1
+  %abc.i = icmp slt i32 %idx.i, %len.i
+  br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1
+
+in.bounds.i:                                      ; preds = %loop.i
+  %addr.i = getelementptr i32, i32* %arr, i32 %idx.i
+  store i32 0, i32* %addr.i
+  %next.i = icmp slt i32 %idx.next.i, %n
+  br i1 %next.i, label %loop.i, label %exit.i
+
+out.of.bounds.i:                                  ; preds = %loop.i
+  br label %inner_loop.exit
+
+exit.i:                                           ; preds = %in.bounds.i, %loop
+  br label %inner_loop.exit
+
+inner_loop.exit:                                  ; preds = %exit.i, %out.of.bounds.i
+  br label %loop.i4
+
+loop.i4:                                          ; preds = %inner_loop.exit.i, %inner_loop.exit
+  %idx.i1 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i2, %inner_loop.exit.i ]
+  %idx.next.i2 = add i32 %idx.i1, 1
+  %next.i3 = icmp ult i32 %idx.next.i2, %parent.count
+  %len.i.i = load i32, i32* %a_len_ptr, !range !0
+  %first.itr.check.i.i = icmp sgt i32 %n, 0
+  br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i
+
+loop.i.i:                                         ; preds = %in.bounds.i.i, %loop.i4
+  %idx.i.i = phi i32 [ 0, %loop.i4 ], [ %idx.next.i.i, %in.bounds.i.i ]
+  %idx.next.i.i = add i32 %idx.i.i, 1
+  %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i
+  br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1
+
+in.bounds.i.i:                                    ; preds = %loop.i.i
+  %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i
+  store i32 0, i32* %addr.i.i
+  %next.i.i = icmp slt i32 %idx.next.i.i, %n
+  br i1 %next.i.i, label %loop.i.i, label %exit.i.i
+
+out.of.bounds.i.i:                                ; preds = %loop.i.i
+  br label %inner_loop.exit.i
+
+exit.i.i:                                         ; preds = %in.bounds.i.i, %loop.i4
+  br label %inner_loop.exit.i
+
+inner_loop.exit.i:                                ; preds = %exit.i.i, %out.of.bounds.i.i
+  br i1 %next.i3, label %loop.i4, label %with_parent.exit
+
+with_parent.exit:                                 ; preds = %inner_loop.exit.i
+  br i1 %next, label %loop, label %exit
+
+exit:                                             ; preds = %with_parent.exit
+  ret void
+}
+
+attributes #0 = { alwaysinline }
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{!"branch_weights", i32 64, i32 4}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2002-09-09-PointerIndVar.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2002-09-09-PointerIndVar.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2002-09-09-PointerIndVar.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2002-09-09-PointerIndVar.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; Induction variable pass is doing bad things with pointer induction vars, 
+; trying to do arithmetic on them directly.
+;
+; RUN: opt < %s -indvars
+;
+define void @test(i32 %A, i32 %S, i8* %S.upgrd.1) {
+; <label>:0
+        br label %Loop
+
+Loop:           ; preds = %Loop, %0
+        %PIV = phi i8* [ %S.upgrd.1, %0 ], [ %PIVNext.upgrd.3, %Loop ]          ; <i8*> [#uses=1]
+        %PIV.upgrd.2 = ptrtoint i8* %PIV to i64         ; <i64> [#uses=1]
+        %PIVNext = add i64 %PIV.upgrd.2, 8              ; <i64> [#uses=1]
+        %PIVNext.upgrd.3 = inttoptr i64 %PIVNext to i8*         ; <i8*> [#uses=1]
+        br label %Loop
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2003-04-16-ExprAnalysis.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2003-04-16-ExprAnalysis.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2003-04-16-ExprAnalysis.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2003-04-16-ExprAnalysis.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; This is a test case for the expression analysis code, not really indvars.
+; It was assuming any constant of int type was a ConstantInteger.
+;
+; RUN: opt < %s -indvars
+
+ at X = global i32 7               ; <i32*> [#uses=1]
+
+define void @test(i32 %A) {
+; <label>:0
+        br label %Loop
+
+Loop:           ; preds = %Loop, %0
+        %IV = phi i32 [ %A, %0 ], [ %IVNext, %Loop ]            ; <i32> [#uses=1]
+        %IVNext = add i32 %IV, ptrtoint (i32* @X to i32)                ; <i32> [#uses=1]
+        br label %Loop
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2003-09-23-NotAtTop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2003-09-23-NotAtTop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2003-09-23-NotAtTop.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2003-09-23-NotAtTop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; The indvar simplification code should ensure that the first PHI in the block 
+; is the canonical one!
+
+define i32 @test() {
+; <label>:0
+        br label %Loop
+
+Loop:           ; preds = %Loop, %0
+; CHECK: Loop:
+; CHECK-NEXT: Canonical
+        %NonIndvar = phi i32 [ 200, %0 ], [ %NonIndvarNext, %Loop ]             ; <i32> [#uses=1]
+        %Canonical = phi i32 [ 0, %0 ], [ %CanonicalNext, %Loop ]               ; <i32> [#uses=2]
+        store i32 %Canonical, i32* null
+        %NonIndvarNext = sdiv i32 %NonIndvar, 2         ; <i32> [#uses=1]
+        %CanonicalNext = add i32 %Canonical, 1          ; <i32> [#uses=1]
+        br label %Loop
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -indvars -disable-output
+
+define void @test() {
+entry:
+        %inc.2 = add i32 1, 1           ; <i32> [#uses=1]
+        br i1 false, label %no_exit, label %loopexit
+
+no_exit:                ; preds = %no_exit, %entry
+        %j.0.pn = phi i32 [ %inc.3, %no_exit ], [ %inc.2, %entry ]              ; <i32> [#uses=1]
+        %k.0.pn = phi i32 [ %inc.4, %no_exit ], [ 1, %entry ]           ; <i32> [#uses=1]
+        %inc.3 = add i32 %j.0.pn, 1             ; <i32> [#uses=1]
+        %inc.4 = add i32 %k.0.pn, 1             ; <i32> [#uses=1]
+        br i1 undef, label %no_exit, label %loopexit
+
+loopexit:               ; preds = %no_exit, %entry
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -indvars -disable-output 
+define void @_ZN17CoinFactorization7cleanupEv() {
+entry:
+        br i1 false, label %loopexit.14, label %cond_continue.3
+
+cond_continue.3:                ; preds = %entry
+        ret void
+
+loopexit.14:            ; preds = %entry
+        %tmp.738 = sub i32 0, 0         ; <i32> [#uses=1]
+        br i1 undef, label %no_exit.15.preheader, label %loopexit.15
+
+no_exit.15.preheader:           ; preds = %loopexit.14
+        br label %no_exit.15
+
+no_exit.15:             ; preds = %no_exit.15, %no_exit.15.preheader
+        %highC.0 = phi i32 [ %tmp.738, %no_exit.15.preheader ], [ %dec.0, %no_exit.15 ]         ; <i32> [#uses=1]
+        %dec.0 = add i32 %highC.0, -1           ; <i32> [#uses=1]
+        br i1 undef, label %no_exit.15, label %loopexit.15
+
+loopexit.15:            ; preds = %no_exit.15, %loopexit.14
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2004-03-10-PHIInsertionBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2004-03-10-PHIInsertionBug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2004-03-10-PHIInsertionBug.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2004-03-10-PHIInsertionBug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -indvars -disable-output
+
+define void @test() {
+        br label %endif.0.i
+
+endif.0.i:              ; preds = %0
+        br i1 false, label %then.3.i, label %endif.3.i
+
+then.3.i:               ; preds = %endif.0.i
+        br label %endif.3.i
+
+endif.3.i:              ; preds = %then.3.i, %endif.0.i
+        %inxm.0.i = phi i32 [ 8, %then.3.i ], [ 0, %endif.0.i ]         ; <i32> [#uses=1]
+        %doinner.1.i = phi i32 [ 0, %then.3.i ], [ 0, %endif.0.i ]              ; <i32> [#uses=0]
+        br label %loopentry.2.i
+
+loopentry.2.i:          ; preds = %no_exit.2.i, %endif.3.i
+        %inxk.0.i = phi i32 [ %tmp.210.i, %no_exit.2.i ], [ 0, %endif.3.i ]             ; <i32> [#uses=1]
+        br label %no_exit.2.i
+
+no_exit.2.i:            ; preds = %loopentry.2.i
+        %tmp.210.i = sub i32 %inxk.0.i, %inxm.0.i               ; <i32> [#uses=2]
+        %tmp.213.i = add i32 %tmp.210.i, 0              ; <i32> [#uses=0]
+        br label %loopentry.2.i
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,291 @@
+; RUN: opt < %s -indvars -disable-output
+; ModuleID = '2004-04-05-InvokeCastCrash.ll'
+	%struct.__false_type = type { i8 }
+	%"struct.__gnu_cxx::_Hashtable_node<const llvm::Constant*>" = type { %"struct.__gnu_cxx::_Hashtable_node<const llvm::Constant*>"*, %"struct.llvm::Constant"* }
+	%"struct.__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >" = type { %"struct.__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >"*, %"struct.std::pair<const llvm::Value* const,int>" }
+	%"struct.__gnu_cxx::hash_map<const llvm::Value*,int,__gnu_cxx::hash<const llvm::Value*>,std::equal_to<const llvm::Value*>,std::allocator<int> >" = type { %"struct.__gnu_cxx::hashtable<std::pair<const llvm::Value* const, int>,const llvm::Value*,__gnu_cxx::hash<const llvm::Value*>,std::_Select1st<std::pair<const llvm::Value* const, int> >,std::equal_to<const llvm::Value*>,std::allocator<int> >" }
+	%"struct.__gnu_cxx::hash_set<const llvm::Constant*,__gnu_cxx::hash<const llvm::Constant*>,std::equal_to<const llvm::Constant*>,std::allocator<const llvm::Constant*> >" = type { %"struct.__gnu_cxx::hashtable<const llvm::Constant*,const llvm::Constant*,__gnu_cxx::hash<const llvm::Constant*>,std::_Identity<const llvm::Constant*>,std::equal_to<const llvm::Constant*>,std::allocator<const llvm::Constant*> >" }
+	%"struct.__gnu_cxx::hashtable<const llvm::Constant*,const llvm::Constant*,__gnu_cxx::hash<const llvm::Constant*>,std::_Identity<const llvm::Constant*>,std::equal_to<const llvm::Constant*>,std::allocator<const llvm::Constant*> >" = type { %struct.__false_type, %struct.__false_type, %struct.__false_type, %struct.__false_type, %"struct.std::vector<__gnu_cxx::_Hashtable_node<const llvm::Constant*>*,std::allocator<const llvm::Constant*> >", i32 }
+	%"struct.__gnu_cxx::hashtable<std::pair<const llvm::Value* const, int>,const llvm::Value*,__gnu_cxx::hash<const llvm::Value*>,std::_Select1st<std::pair<const llvm::Value* const, int> >,std::equal_to<const llvm::Value*>,std::allocator<int> >" = type { %struct.__false_type, %struct.__false_type, %struct.__false_type, %struct.__false_type, %"struct.std::vector<__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >*,std::allocator<int> >", i32 }
+	%"struct.llvm::AbstractTypeUser" = type { i32 (...)** }
+	%"struct.llvm::Annotable" = type { i32 (...)**, %"struct.llvm::Annotation"* }
+	%"struct.llvm::Annotation" = type { i32 (...)**, %"struct.llvm::AnnotationID", %"struct.llvm::Annotation"* }
+	%"struct.llvm::AnnotationID" = type { i32 }
+	%"struct.llvm::Argument" = type { %"struct.llvm::Value", %"struct.llvm::Function"*, %"struct.llvm::Argument"*, %"struct.llvm::Argument"* }
+	%"struct.llvm::BasicBlock" = type { %"struct.llvm::Value", %"struct.llvm::iplist<llvm::Instruction,llvm::ilist_traits<llvm::Instruction> >", %"struct.llvm::BasicBlock"*, %"struct.llvm::BasicBlock"* }
+	%"struct.llvm::Constant" = type opaque
+	%"struct.llvm::DerivedType" = type { %"struct.llvm::Type", %"struct.llvm::AbstractTypeUser", %"struct.std::vector<llvm::AbstractTypeUser*,std::allocator<llvm::AbstractTypeUser*> >" }
+	%"struct.llvm::Function" = type { %"struct.llvm::GlobalValue", %"struct.llvm::Annotable", %"struct.llvm::iplist<llvm::BasicBlock,llvm::ilist_traits<llvm::BasicBlock> >", %"struct.llvm::iplist<llvm::Argument,llvm::ilist_traits<llvm::Argument> >", %"struct.llvm::SymbolTable"*, %"struct.llvm::Function"*, %"struct.llvm::Function"* }
+	%"struct.llvm::FunctionPass" = type { %"struct.llvm::Pass" }
+	%"struct.llvm::FunctionType" = type { %"struct.llvm::DerivedType", i1 }
+	%"struct.llvm::GlobalValue" = type { %"struct.llvm::User", i32, %"struct.llvm::Module"* }
+	%"struct.llvm::Instruction" = type { %"struct.llvm::User", %"struct.llvm::Annotable", %"struct.llvm::BasicBlock"*, %"struct.llvm::Instruction"*, %"struct.llvm::Instruction"*, i32 }
+	%"struct.llvm::IntrinsicLowering" = type opaque
+	%"struct.llvm::MachineBasicBlock" = type { %"struct.llvm::ilist<llvm::MachineInstr>", %"struct.llvm::MachineBasicBlock"*, %"struct.llvm::MachineBasicBlock"*, %"struct.llvm::BasicBlock"* }
+	%"struct.llvm::MachineConstantPool" = type opaque
+	%"struct.llvm::MachineFrameInfo" = type opaque
+	%"struct.llvm::MachineFunction" = type { %"struct.llvm::Annotation", %"struct.llvm::Function"*, %"struct.llvm::TargetMachine"*, %"struct.llvm::iplist<llvm::MachineBasicBlock,llvm::ilist_traits<llvm::MachineBasicBlock> >", %"struct.llvm::SSARegMap"*, %"struct.llvm::MachineFunctionInfo"*, %"struct.llvm::MachineFrameInfo"*, %"struct.llvm::MachineConstantPool"* }
+	%"struct.llvm::MachineFunctionInfo" = type { %"struct.__gnu_cxx::hash_set<const llvm::Constant*,__gnu_cxx::hash<const llvm::Constant*>,std::equal_to<const llvm::Constant*>,std::allocator<const llvm::Constant*> >", %"struct.__gnu_cxx::hash_map<const llvm::Value*,int,__gnu_cxx::hash<const llvm::Value*>,std::equal_to<const llvm::Value*>,std::allocator<int> >", i32, i32, i32, i32, i32, i32, i32, i1, i1, i1, %"struct.llvm::MachineFunction"* }
+	%"struct.llvm::MachineFunctionPass" = type { %"struct.llvm::FunctionPass" }
+	%"struct.llvm::MachineInstr" = type { i16, i8, %"struct.std::vector<llvm::MachineOperand,std::allocator<llvm::MachineOperand> >", %"struct.llvm::MachineInstr"*, %"struct.llvm::MachineInstr"*, %"struct.llvm::MachineBasicBlock"* }
+	%"struct.llvm::MachineInstrBuilder" = type { %"struct.llvm::MachineInstr"* }
+	%"struct.llvm::MachineOperand" = type { %"union.llvm::MachineOperand::._65", i32, i32 }
+	%"struct.llvm::Module" = type opaque
+	%"struct.llvm::PATypeHandle" = type { %"struct.llvm::Type"*, %"struct.llvm::AbstractTypeUser"* }
+	%"struct.llvm::PATypeHolder" = type { %"struct.llvm::Type"* }
+	%"struct.llvm::Pass" = type { i32 (...)**, %"struct.llvm::AbstractTypeUser"*, %"struct.llvm::PassInfo"*, %"struct.std::vector<std::pair<const llvm::PassInfo*, llvm::Pass*>,std::allocator<std::pair<const llvm::PassInfo*, llvm::Pass*> > >" }
+	%"struct.llvm::PassInfo" = type { i8*, i8*, %"struct.std::type_info"*, i8, %"struct.std::vector<const llvm::PassInfo*,std::allocator<const llvm::PassInfo*> >", %"struct.llvm::Pass"* ()*, %"struct.llvm::Pass"* (%"struct.llvm::TargetMachine"*)* }
+	%"struct.llvm::SSARegMap" = type opaque
+	%"struct.llvm::SymbolTable" = type opaque
+	%"struct.llvm::SymbolTableListTraits<llvm::Argument,llvm::Function,llvm::Function,llvm::ilist_traits<llvm::Argument> >" = type { %"struct.llvm::Function"*, %"struct.llvm::Function"* }
+	%"struct.llvm::SymbolTableListTraits<llvm::Instruction,llvm::BasicBlock,llvm::Function,llvm::ilist_traits<llvm::Instruction> >" = type { %"struct.llvm::Function"*, %"struct.llvm::BasicBlock"* }
+	%"struct.llvm::DataLayout" = type { %"struct.llvm::FunctionPass", i1, i8, i8, i8, i8, i8, i8, i8, i8 }
+	%"struct.llvm::TargetFrameInfo" = type { i32 (...)**, i32, i32, i32 }
+	%"struct.llvm::TargetInstrDescriptor" = type { i8*, i32, i32, i32, i1, i32, i32, i32, i32, i32, i32*, i32* }
+	%"struct.llvm::TargetInstrInfo" = type { i32 (...)**, %"struct.llvm::TargetInstrDescriptor"*, i32, i32 }
+	%"struct.llvm::TargetMachine" = type { i32 (...)**, %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >", %"struct.llvm::DataLayout", %"struct.llvm::IntrinsicLowering"* }
+	%"struct.llvm::TargetRegClassInfo" = type { i32 (...)**, i32, i32, i32 }
+	%"struct.llvm::TargetRegInfo" = type { i32 (...)**, %"struct.std::vector<const llvm::TargetRegClassInfo*,std::allocator<const llvm::TargetRegClassInfo*> >", %"struct.llvm::TargetMachine"* }
+	%"struct.llvm::Type" = type { %"struct.llvm::Value", i32, i32, i1, i32, %"struct.llvm::Type"*, %"struct.std::vector<llvm::PATypeHandle,std::allocator<llvm::PATypeHandle> >" }
+	%"struct.llvm::Use" = type { %"struct.llvm::Value"*, %"struct.llvm::User"*, %"struct.llvm::Use"*, %"struct.llvm::Use"* }
+	%"struct.llvm::User" = type { %"struct.llvm::Value", %"struct.std::vector<llvm::Use,std::allocator<llvm::Use> >" }
+	%"struct.llvm::Value" = type { i32 (...)**, %"struct.llvm::iplist<llvm::Use,llvm::ilist_traits<llvm::Use> >", %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >", %"struct.llvm::PATypeHolder", i32 }
+	%"struct.llvm::_GLOBAL__N_::InsertPrologEpilogCode" = type { %"struct.llvm::MachineFunctionPass" }
+	%"struct.llvm::ilist<llvm::MachineInstr>" = type { %"struct.llvm::iplist<llvm::MachineInstr,llvm::ilist_traits<llvm::MachineInstr> >" }
+	%"struct.llvm::ilist_iterator<const llvm::MachineBasicBlock>" = type { %"struct.llvm::MachineBasicBlock"* }
+	%"struct.llvm::ilist_traits<llvm::Argument>" = type { %"struct.llvm::SymbolTableListTraits<llvm::Argument,llvm::Function,llvm::Function,llvm::ilist_traits<llvm::Argument> >" }
+	%"struct.llvm::ilist_traits<llvm::Instruction>" = type { %"struct.llvm::SymbolTableListTraits<llvm::Instruction,llvm::BasicBlock,llvm::Function,llvm::ilist_traits<llvm::Instruction> >" }
+	%"struct.llvm::iplist<llvm::Argument,llvm::ilist_traits<llvm::Argument> >" = type { %"struct.llvm::ilist_traits<llvm::Argument>", %"struct.llvm::Argument"*, %"struct.llvm::Argument"* }
+	%"struct.llvm::iplist<llvm::BasicBlock,llvm::ilist_traits<llvm::BasicBlock> >" = type { %"struct.llvm::ilist_traits<llvm::Argument>", %"struct.llvm::BasicBlock"*, %"struct.llvm::BasicBlock"* }
+	%"struct.llvm::iplist<llvm::Instruction,llvm::ilist_traits<llvm::Instruction> >" = type { %"struct.llvm::ilist_traits<llvm::Instruction>", %"struct.llvm::Instruction"*, %"struct.llvm::Instruction"* }
+	%"struct.llvm::iplist<llvm::MachineBasicBlock,llvm::ilist_traits<llvm::MachineBasicBlock> >" = type { %"struct.llvm::MachineBasicBlock"*, %"struct.llvm::MachineBasicBlock"* }
+	%"struct.llvm::iplist<llvm::MachineInstr,llvm::ilist_traits<llvm::MachineInstr> >" = type { %"struct.llvm::ilist_iterator<const llvm::MachineBasicBlock>", %"struct.llvm::MachineInstr"*, %"struct.llvm::MachineInstr"* }
+	%"struct.llvm::iplist<llvm::Use,llvm::ilist_traits<llvm::Use> >" = type { %"struct.llvm::Use"*, %"struct.llvm::Use"* }
+	%"struct.std::_Vector_alloc_base<__gnu_cxx::_Hashtable_node<const llvm::Constant*>*,std::allocator<const llvm::Constant*>, true>" = type { %"struct.__gnu_cxx::_Hashtable_node<const llvm::Constant*>"**, %"struct.__gnu_cxx::_Hashtable_node<const llvm::Constant*>"**, %"struct.__gnu_cxx::_Hashtable_node<const llvm::Constant*>"** }
+	%"struct.std::_Vector_alloc_base<__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >*,std::allocator<int>, true>" = type { %"struct.__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >"**, %"struct.__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >"**, %"struct.__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >"** }
+	%"struct.std::_Vector_alloc_base<const llvm::PassInfo*,std::allocator<const llvm::PassInfo*>, true>" = type { %"struct.llvm::PassInfo"**, %"struct.llvm::PassInfo"**, %"struct.llvm::PassInfo"** }
+	%"struct.std::_Vector_alloc_base<const llvm::TargetRegClassInfo*,std::allocator<const llvm::TargetRegClassInfo*>, true>" = type { %"struct.llvm::TargetFrameInfo"**, %"struct.llvm::TargetFrameInfo"**, %"struct.llvm::TargetFrameInfo"** }
+	%"struct.std::_Vector_alloc_base<llvm::AbstractTypeUser*,std::allocator<llvm::AbstractTypeUser*>, true>" = type { %"struct.llvm::AbstractTypeUser"**, %"struct.llvm::AbstractTypeUser"**, %"struct.llvm::AbstractTypeUser"** }
+	%"struct.std::_Vector_alloc_base<llvm::MachineInstr*,std::allocator<llvm::MachineInstr*>, true>" = type { %"struct.llvm::MachineInstr"**, %"struct.llvm::MachineInstr"**, %"struct.llvm::MachineInstr"** }
+	%"struct.std::_Vector_alloc_base<llvm::MachineOperand,std::allocator<llvm::MachineOperand>, true>" = type { %"struct.llvm::MachineOperand"*, %"struct.llvm::MachineOperand"*, %"struct.llvm::MachineOperand"* }
+	%"struct.std::_Vector_alloc_base<llvm::PATypeHandle,std::allocator<llvm::PATypeHandle>, true>" = type { %"struct.llvm::PATypeHandle"*, %"struct.llvm::PATypeHandle"*, %"struct.llvm::PATypeHandle"* }
+	%"struct.std::_Vector_alloc_base<llvm::Use,std::allocator<llvm::Use>, true>" = type { %"struct.llvm::Use"*, %"struct.llvm::Use"*, %"struct.llvm::Use"* }
+	%"struct.std::_Vector_alloc_base<std::pair<const llvm::PassInfo*, llvm::Pass*>,std::allocator<std::pair<const llvm::PassInfo*, llvm::Pass*> >, true>" = type { %"struct.std::pair<const llvm::PassInfo*,llvm::Pass*>"*, %"struct.std::pair<const llvm::PassInfo*,llvm::Pass*>"*, %"struct.std::pair<const llvm::PassInfo*,llvm::Pass*>"* }
+	%"struct.std::_Vector_base<__gnu_cxx::_Hashtable_node<const llvm::Constant*>*,std::allocator<const llvm::Constant*> >" = type { %"struct.std::_Vector_alloc_base<__gnu_cxx::_Hashtable_node<const llvm::Constant*>*,std::allocator<const llvm::Constant*>, true>" }
+	%"struct.std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >*,std::allocator<int> >" = type { %"struct.std::_Vector_alloc_base<__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >*,std::allocator<int>, true>" }
+	%"struct.std::_Vector_base<const llvm::PassInfo*,std::allocator<const llvm::PassInfo*> >" = type { %"struct.std::_Vector_alloc_base<const llvm::PassInfo*,std::allocator<const llvm::PassInfo*>, true>" }
+	%"struct.std::_Vector_base<const llvm::TargetRegClassInfo*,std::allocator<const llvm::TargetRegClassInfo*> >" = type { %"struct.std::_Vector_alloc_base<const llvm::TargetRegClassInfo*,std::allocator<const llvm::TargetRegClassInfo*>, true>" }
+	%"struct.std::_Vector_base<llvm::AbstractTypeUser*,std::allocator<llvm::AbstractTypeUser*> >" = type { %"struct.std::_Vector_alloc_base<llvm::AbstractTypeUser*,std::allocator<llvm::AbstractTypeUser*>, true>" }
+	%"struct.std::_Vector_base<llvm::MachineInstr*,std::allocator<llvm::MachineInstr*> >" = type { %"struct.std::_Vector_alloc_base<llvm::MachineInstr*,std::allocator<llvm::MachineInstr*>, true>" }
+	%"struct.std::_Vector_base<llvm::MachineOperand,std::allocator<llvm::MachineOperand> >" = type { %"struct.std::_Vector_alloc_base<llvm::MachineOperand,std::allocator<llvm::MachineOperand>, true>" }
+	%"struct.std::_Vector_base<llvm::PATypeHandle,std::allocator<llvm::PATypeHandle> >" = type { %"struct.std::_Vector_alloc_base<llvm::PATypeHandle,std::allocator<llvm::PATypeHandle>, true>" }
+	%"struct.std::_Vector_base<llvm::Use,std::allocator<llvm::Use> >" = type { %"struct.std::_Vector_alloc_base<llvm::Use,std::allocator<llvm::Use>, true>" }
+	%"struct.std::_Vector_base<std::pair<const llvm::PassInfo*, llvm::Pass*>,std::allocator<std::pair<const llvm::PassInfo*, llvm::Pass*> > >" = type { %"struct.std::_Vector_alloc_base<std::pair<const llvm::PassInfo*, llvm::Pass*>,std::allocator<std::pair<const llvm::PassInfo*, llvm::Pass*> >, true>" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider" = type { i8* }
+	%"struct.std::pair<const llvm::PassInfo*,llvm::Pass*>" = type { %"struct.llvm::PassInfo"*, %"struct.llvm::Pass"* }
+	%"struct.std::pair<const llvm::Value* const,int>" = type { %"struct.llvm::Value"*, i32 }
+	%"struct.std::type_info" = type { i32 (...)**, i8* }
+	%"struct.std::vector<__gnu_cxx::_Hashtable_node<const llvm::Constant*>*,std::allocator<const llvm::Constant*> >" = type { %"struct.std::_Vector_base<__gnu_cxx::_Hashtable_node<const llvm::Constant*>*,std::allocator<const llvm::Constant*> >" }
+	%"struct.std::vector<__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >*,std::allocator<int> >" = type { %"struct.std::_Vector_base<__gnu_cxx::_Hashtable_node<std::pair<const llvm::Value* const, int> >*,std::allocator<int> >" }
+	%"struct.std::vector<const llvm::PassInfo*,std::allocator<const llvm::PassInfo*> >" = type { %"struct.std::_Vector_base<const llvm::PassInfo*,std::allocator<const llvm::PassInfo*> >" }
+	%"struct.std::vector<const llvm::TargetRegClassInfo*,std::allocator<const llvm::TargetRegClassInfo*> >" = type { %"struct.std::_Vector_base<const llvm::TargetRegClassInfo*,std::allocator<const llvm::TargetRegClassInfo*> >" }
+	%"struct.std::vector<llvm::AbstractTypeUser*,std::allocator<llvm::AbstractTypeUser*> >" = type { %"struct.std::_Vector_base<llvm::AbstractTypeUser*,std::allocator<llvm::AbstractTypeUser*> >" }
+	%"struct.std::vector<llvm::MachineInstr*,std::allocator<llvm::MachineInstr*> >" = type { %"struct.std::_Vector_base<llvm::MachineInstr*,std::allocator<llvm::MachineInstr*> >" }
+	%"struct.std::vector<llvm::MachineOperand,std::allocator<llvm::MachineOperand> >" = type { %"struct.std::_Vector_base<llvm::MachineOperand,std::allocator<llvm::MachineOperand> >" }
+	%"struct.std::vector<llvm::PATypeHandle,std::allocator<llvm::PATypeHandle> >" = type { %"struct.std::_Vector_base<llvm::PATypeHandle,std::allocator<llvm::PATypeHandle> >" }
+	%"struct.std::vector<llvm::Use,std::allocator<llvm::Use> >" = type { %"struct.std::_Vector_base<llvm::Use,std::allocator<llvm::Use> >" }
+	%"struct.std::vector<std::pair<const llvm::PassInfo*, llvm::Pass*>,std::allocator<std::pair<const llvm::PassInfo*, llvm::Pass*> > >" = type { %"struct.std::_Vector_base<std::pair<const llvm::PassInfo*, llvm::Pass*>,std::allocator<std::pair<const llvm::PassInfo*, llvm::Pass*> > >" }
+	%"union.llvm::MachineOperand::._65" = type { %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* }
+
+declare void @_Znwj()
+
+declare void @_ZN4llvm12MachineInstrC1Esjbb()
+
+declare void @_ZNSt6vectorIPN4llvm12MachineInstrESaIS2_EE9push_backERKS2_()
+
+declare void @_ZNK4llvm8Function15getFunctionTypeEv()
+
+declare void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTypeE()
+
+declare void @_ZNK4llvm19MachineInstrBuilder7addSImmEi()
+
+declare i32 @__gxx_personality_v0(...)
+
+define void @_ZN4llvm11_GLOBAL__N_22InsertPrologEpilogCode20runOnMachineFunctionERNS_15MachineFunctionE(%"struct.llvm::MachineFunction"* %F) personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	%tmp.8.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.0.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetFrameInfo"*> [#uses=0]
+
+invoke_catch.0.i:		; preds = %invoke_cont.49.i, %invoke_cont.48.i, %invoke_cont.47.i, %invoke_cont.i53.i, %no_exit.i, %invoke_cont.44.i, %invoke_cont.43.i, %invoke_cont.42.i, %invoke_cont.41.i, %invoke_cont.40.i, %invoke_cont.39.i, %invoke_cont.38.i, %invoke_cont.37.i, %then.2.i, %invoke_cont.35.i, %invoke_cont.34.i, %then.1.i, %endif.0.i, %invoke_cont.9.i, %invoke_cont.8.i, %invoke_cont.7.i, %invoke_cont.i.i, %then.0.i, %invoke_cont.4.i, %invoke_cont.3.i, %invoke_cont.2.i, %invoke_cont.1.i, %endif.0.i.i, %tmp.7.i.noexc.i, %invoke_cont.0.i, %entry
+        %exn0.i = landingpad {i8*, i32}
+                 cleanup
+	ret void
+
+invoke_cont.0.i:		; preds = %entry
+	%tmp.7.i1.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %tmp.7.i.noexc.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetFrameInfo"*> [#uses=2]
+
+tmp.7.i.noexc.i:		; preds = %invoke_cont.0.i
+	%tmp.17.i2.i = invoke i32 null( %"struct.llvm::TargetFrameInfo"* %tmp.7.i1.i )
+			to label %endif.0.i.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+endif.0.i.i:		; preds = %tmp.7.i.noexc.i
+	%tmp.38.i4.i = invoke i32 null( %"struct.llvm::TargetFrameInfo"* %tmp.7.i1.i )
+			to label %tmp.38.i.noexc.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+tmp.38.i.noexc.i:		; preds = %endif.0.i.i
+	br i1 false, label %invoke_cont.1.i, label %then.1.i.i
+
+then.1.i.i:		; preds = %tmp.38.i.noexc.i
+	ret void
+
+invoke_cont.1.i:		; preds = %tmp.38.i.noexc.i
+	%tmp.21.i = invoke %"struct.llvm::TargetRegInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.2.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetRegInfo"*> [#uses=1]
+
+invoke_cont.2.i:		; preds = %invoke_cont.1.i
+	%tmp.28.i = invoke i32 null( %"struct.llvm::TargetRegInfo"* %tmp.21.i )
+			to label %invoke_cont.3.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+invoke_cont.3.i:		; preds = %invoke_cont.2.i
+	%tmp.36.i = invoke %"struct.llvm::TargetInstrInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.4.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetInstrInfo"*> [#uses=1]
+
+invoke_cont.4.i:		; preds = %invoke_cont.3.i
+	%tmp.43.i = invoke i1 null( %"struct.llvm::TargetInstrInfo"* %tmp.36.i, i16 383, i64 0 )
+			to label %invoke_cont.5.i unwind label %invoke_catch.0.i		; <i1> [#uses=1]
+
+invoke_cont.5.i:		; preds = %invoke_cont.4.i
+	br i1 %tmp.43.i, label %then.0.i, label %else.i
+
+then.0.i:		; preds = %invoke_cont.5.i
+	invoke void @_Znwj( )
+			to label %tmp.0.i.noexc.i unwind label %invoke_catch.0.i
+
+tmp.0.i.noexc.i:		; preds = %then.0.i
+	invoke void @_ZN4llvm12MachineInstrC1Esjbb( )
+			to label %invoke_cont.i.i unwind label %cond_true.i.i
+
+cond_true.i.i:		; preds = %tmp.0.i.noexc.i
+        %exn.i.i = landingpad {i8*, i32}
+                 cleanup
+	ret void
+
+invoke_cont.i.i:		; preds = %tmp.0.i.noexc.i
+	invoke void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTypeE( )
+			to label %invoke_cont.7.i unwind label %invoke_catch.0.i
+
+invoke_cont.7.i:		; preds = %invoke_cont.i.i
+	invoke void @_ZNK4llvm19MachineInstrBuilder7addSImmEi( )
+			to label %invoke_cont.8.i unwind label %invoke_catch.0.i
+
+invoke_cont.8.i:		; preds = %invoke_cont.7.i
+	invoke void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTypeE( )
+			to label %invoke_cont.9.i unwind label %invoke_catch.0.i
+
+invoke_cont.9.i:		; preds = %invoke_cont.8.i
+	invoke void @_ZNSt6vectorIPN4llvm12MachineInstrESaIS2_EE9push_backERKS2_( )
+			to label %endif.0.i unwind label %invoke_catch.0.i
+
+else.i:		; preds = %invoke_cont.5.i
+	ret void
+
+endif.0.i:		; preds = %invoke_cont.9.i
+	invoke void @_ZNK4llvm8Function15getFunctionTypeEv( )
+			to label %invoke_cont.33.i unwind label %invoke_catch.0.i
+
+invoke_cont.33.i:		; preds = %endif.0.i
+	br i1 false, label %then.1.i, label %endif.1.i
+
+then.1.i:		; preds = %invoke_cont.33.i
+	invoke void @_ZNK4llvm8Function15getFunctionTypeEv( )
+			to label %invoke_cont.34.i unwind label %invoke_catch.0.i
+
+invoke_cont.34.i:		; preds = %then.1.i
+	%tmp.121.i = invoke %"struct.llvm::TargetRegInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.35.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetRegInfo"*> [#uses=1]
+
+invoke_cont.35.i:		; preds = %invoke_cont.34.i
+	%tmp.128.i = invoke i32 null( %"struct.llvm::TargetRegInfo"* %tmp.121.i )
+			to label %invoke_cont.36.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+invoke_cont.36.i:		; preds = %invoke_cont.35.i
+	br i1 false, label %then.2.i, label %endif.1.i
+
+then.2.i:		; preds = %invoke_cont.36.i
+	%tmp.140.i = invoke %"struct.llvm::TargetRegInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.37.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetRegInfo"*> [#uses=0]
+
+invoke_cont.37.i:		; preds = %then.2.i
+	%tmp.148.i = invoke %"struct.llvm::TargetRegInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.38.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetRegInfo"*> [#uses=1]
+
+invoke_cont.38.i:		; preds = %invoke_cont.37.i
+	%tmp.155.i = invoke i32 null( %"struct.llvm::TargetRegInfo"* %tmp.148.i, %"struct.llvm::Type"* null, i1 false )
+			to label %invoke_cont.39.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+invoke_cont.39.i:		; preds = %invoke_cont.38.i
+	%tmp.163.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.40.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetFrameInfo"*> [#uses=1]
+
+invoke_cont.40.i:		; preds = %invoke_cont.39.i
+	%tmp.170.i = invoke i32 null( %"struct.llvm::TargetFrameInfo"* %tmp.163.i )
+			to label %invoke_cont.41.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+invoke_cont.41.i:		; preds = %invoke_cont.40.i
+	%tmp.177.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.42.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetFrameInfo"*> [#uses=1]
+
+invoke_cont.42.i:		; preds = %invoke_cont.41.i
+	%tmp.184.i = invoke i32 null( %"struct.llvm::TargetFrameInfo"* %tmp.177.i )
+			to label %invoke_cont.43.i unwind label %invoke_catch.0.i		; <i32> [#uses=1]
+
+invoke_cont.43.i:		; preds = %invoke_cont.42.i
+	%tmp.191.i = invoke %"struct.llvm::TargetFrameInfo"* null( %"struct.llvm::TargetMachine"* null )
+			to label %invoke_cont.44.i unwind label %invoke_catch.0.i		; <%"struct.llvm::TargetFrameInfo"*> [#uses=1]
+
+invoke_cont.44.i:		; preds = %invoke_cont.43.i
+	%tmp.198.i = invoke i32 null( %"struct.llvm::TargetFrameInfo"* %tmp.191.i, %"struct.llvm::MachineFunction"* %F, i1* null )
+			to label %invoke_cont.45.i unwind label %invoke_catch.0.i		; <i32> [#uses=0]
+
+invoke_cont.45.i:		; preds = %invoke_cont.44.i
+	br i1 false, label %no_exit.i, label %endif.1.i
+
+no_exit.i:		; preds = %invoke_cont.50.i, %invoke_cont.45.i
+	%nextArgOffset.0.i.1 = phi i32 [ %tmp.221.i, %invoke_cont.50.i ], [ 0, %invoke_cont.45.i ]		; <i32> [#uses=1]
+	invoke void @_Znwj( )
+			to label %tmp.0.i.noexc55.i unwind label %invoke_catch.0.i
+
+tmp.0.i.noexc55.i:		; preds = %no_exit.i
+	invoke void @_ZN4llvm12MachineInstrC1Esjbb( )
+			to label %invoke_cont.i53.i unwind label %cond_true.i52.i
+
+cond_true.i52.i:		; preds = %tmp.0.i.noexc55.i
+        %exn.i52.i = landingpad {i8*, i32}
+                 cleanup
+	ret void
+
+invoke_cont.i53.i:		; preds = %tmp.0.i.noexc55.i
+	invoke void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTypeE( )
+			to label %invoke_cont.47.i unwind label %invoke_catch.0.i
+
+invoke_cont.47.i:		; preds = %invoke_cont.i53.i
+	invoke void @_ZNK4llvm19MachineInstrBuilder7addMRegEiNS_14MachineOperand7UseTypeE( )
+			to label %invoke_cont.48.i unwind label %invoke_catch.0.i
+
+invoke_cont.48.i:		; preds = %invoke_cont.47.i
+	invoke void @_ZNK4llvm19MachineInstrBuilder7addSImmEi( )
+			to label %invoke_cont.49.i unwind label %invoke_catch.0.i
+
+invoke_cont.49.i:		; preds = %invoke_cont.48.i
+	invoke void @_ZNSt6vectorIPN4llvm12MachineInstrESaIS2_EE9push_backERKS2_( )
+			to label %invoke_cont.50.i unwind label %invoke_catch.0.i
+
+invoke_cont.50.i:		; preds = %invoke_cont.49.i
+	%tmp.221.i = add i32 %nextArgOffset.0.i.1, %tmp.184.i		; <i32> [#uses=1]
+	br i1 false, label %no_exit.i, label %endif.1.i
+
+endif.1.i:		; preds = %invoke_cont.50.i, %invoke_cont.45.i, %invoke_cont.36.i, %invoke_cont.33.i
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2004-04-07-ScalarEvolutionCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2004-04-07-ScalarEvolutionCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2004-04-07-ScalarEvolutionCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2004-04-07-ScalarEvolutionCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -indvars -disable-output
+
+define void @.outPlank_21() {
+entry:
+        br i1 false, label %loopexit.0, label %no_exit.0
+
+no_exit.0:              ; preds = %entry
+        ret void
+
+loopexit.0:             ; preds = %entry
+        br i1 false, label %no_exit.1, label %loopexit.1
+
+no_exit.1:              ; preds = %loopexit.2, %loopexit.0
+        %i.0.0 = phi i32 [ %inc, %loopexit.2 ], [ 0, %loopexit.0 ]              ; <i32> [#uses=1]
+        br i1 false, label %loopexit.2, label %no_exit.2
+
+no_exit.2:              ; preds = %no_exit.1
+        ret void
+
+loopexit.2:             ; preds = %no_exit.1
+        %inc = add i32 %i.0.0, 1                ; <i32> [#uses=1]
+        br i1 false, label %no_exit.1, label %loopexit.1
+
+loopexit.1:             ; preds = %loopexit.2, %loopexit.0
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -indvars -disable-output
+
+define void @_ZN5ArrayISt7complexIdEEC2ERK10dim_vector() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+        %tmp.7 = invoke i32 @_ZN5ArrayISt7complexIdEE8get_sizeERK10dim_vector( )
+                        to label %invoke_cont.0 unwind label %cond_true.1               ; <i32> [#uses=2]
+
+invoke_cont.0:          ; preds = %entry
+        %tmp.4.i = bitcast i32 %tmp.7 to i32            ; <i32> [#uses=0]
+        %tmp.14.0.i5 = add i32 %tmp.7, -1               ; <i32> [#uses=1]
+        br label %no_exit.i
+
+no_exit.i:              ; preds = %no_exit.i, %invoke_cont.0
+        %tmp.14.0.i.0 = phi i32 [ %tmp.14.0.i, %no_exit.i ], [ %tmp.14.0.i5, %invoke_cont.0 ]           ; <i32> [#uses=1]
+        %tmp.14.0.i = add i32 %tmp.14.0.i.0, -1         ; <i32> [#uses=1]
+        br label %no_exit.i
+
+cond_true.1:            ; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        resume { i8*, i32 } %exn
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i32 @_ZN5ArrayISt7complexIdEE8get_sizeERK10dim_vector()
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,67 @@
+; RUN: opt < %s -indvars -disable-output
+
+declare void @q_atomic_increment()
+
+declare void @_Z9qt_assertPKcS0_i()
+
+define void @_ZN13QMetaResourceC1EPKh() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	invoke void @_Z9qt_assertPKcS0_i( )
+			to label %endif.1 unwind label %then.i.i551
+
+then.i.i551:		; preds = %entry
+        %exn551 = landingpad {i8*, i32}
+                 cleanup
+	ret void
+
+endif.1:		; preds = %entry
+	br i1 false, label %then.2, label %then.i.i
+
+then.2:		; preds = %endif.1
+	invoke void @q_atomic_increment( )
+			to label %loopentry.0 unwind label %invoke_catch.6
+
+invoke_catch.6:		; preds = %then.2
+        %exn6 = landingpad {i8*, i32}
+                 cleanup
+	ret void
+
+loopentry.0:		; preds = %then.2
+	br i1 false, label %shortcirc_next.i, label %endif.3
+
+endif.3:		; preds = %loopentry.0
+	ret void
+
+shortcirc_next.i:		; preds = %loopentry.0
+	br i1 false, label %_ZNK7QString2atEi.exit, label %then.i
+
+then.i:		; preds = %shortcirc_next.i
+	ret void
+
+_ZNK7QString2atEi.exit:		; preds = %shortcirc_next.i
+	br i1 false, label %endif.4, label %then.4
+
+then.4:		; preds = %_ZNK7QString2atEi.exit
+	ret void
+
+endif.4:		; preds = %_ZNK7QString2atEi.exit
+	%tmp.115 = load i8, i8* null		; <i8> [#uses=1]
+	br i1 false, label %loopexit.1, label %no_exit.0
+
+no_exit.0:		; preds = %no_exit.0, %endif.4
+	%bytes_in_len.4.5 = phi i8 [ %dec, %no_exit.0 ], [ %tmp.115, %endif.4 ]		; <i8> [#uses=1]
+	%off.5.5.in = phi i32 [ %off.5.5, %no_exit.0 ], [ 0, %endif.4 ]		; <i32> [#uses=1]
+	%off.5.5 = add i32 %off.5.5.in, 1		; <i32> [#uses=2]
+	%dec = add i8 %bytes_in_len.4.5, -1		; <i8> [#uses=2]
+	%tmp.123631 = icmp eq i8 %dec, 0		; <i1> [#uses=1]
+	br i1 %tmp.123631, label %loopexit.1, label %no_exit.0
+
+loopexit.1:		; preds = %no_exit.0, %endif.4
+	%off.5.in.6 = phi i32 [ 0, %endif.4 ], [ %off.5.5, %no_exit.0 ]		; <i32> [#uses=0]
+	ret void
+
+then.i.i:		; preds = %endif.1
+	ret void
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/IndVarSimplify/2005-02-26-ExitValueCompute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2005-02-26-ExitValueCompute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2005-02-26-ExitValueCompute.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2005-02-26-ExitValueCompute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+define i32 @main() {
+; CHECK-LABEL: @main(
+; CHECK: ret i32 152
+entry:
+        br label %no_exit
+
+no_exit:                ; preds = %no_exit, %entry
+        %i.1.0 = phi i32 [ 0, %entry ], [ %inc, %no_exit ]              ; <i32> [#uses=2]
+        %tmp.4 = icmp sgt i32 %i.1.0, 50                ; <i1> [#uses=1]
+        %tmp.7 = select i1 %tmp.4, i32 100, i32 0               ; <i32> [#uses=1]
+        %i.0 = add i32 %i.1.0, 1                ; <i32> [#uses=1]
+        %inc = add i32 %i.0, %tmp.7             ; <i32> [#uses=3]
+        %tmp.1 = icmp slt i32 %inc, 100         ; <i1> [#uses=1]
+        br i1 %tmp.1, label %no_exit, label %loopexit
+
+loopexit:               ; preds = %no_exit
+        ret i32 %inc
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2005-06-15-InstMoveCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2005-06-15-InstMoveCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2005-06-15-InstMoveCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2005-06-15-InstMoveCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt < %s -indvars -disable-output
+
+define void @main() {
+entry:
+        br label %no_exit.1.outer
+
+no_exit.1.outer:                ; preds = %endif.0, %entry
+        %l_14237116.1.0.ph = phi i8 [ -46, %entry ], [ 0, %endif.0 ]            ; <i8> [#uses=1]
+        %i.0.0.0.ph = phi i32 [ 0, %entry ], [ %inc.1, %endif.0 ]               ; <i32> [#uses=1]
+        br label %no_exit.1
+
+no_exit.1:              ; preds = %_Z13func_47880058cc.exit, %no_exit.1.outer
+        br i1 false, label %_Z13func_47880058cc.exit, label %then.i
+
+then.i:         ; preds = %no_exit.1
+        br label %_Z13func_47880058cc.exit
+
+_Z13func_47880058cc.exit:               ; preds = %then.i, %no_exit.1
+        br i1 false, label %then.0, label %no_exit.1
+
+then.0:         ; preds = %_Z13func_47880058cc.exit
+        %tmp.6 = bitcast i8 %l_14237116.1.0.ph to i8            ; <i8> [#uses=1]
+        br i1 false, label %endif.0, label %then.1
+
+then.1:         ; preds = %then.0
+        br label %endif.0
+
+endif.0:                ; preds = %then.1, %then.0
+        %inc.1 = add i32 %i.0.0.0.ph, 1         ; <i32> [#uses=2]
+        %tmp.2 = icmp sgt i32 %inc.1, 99                ; <i1> [#uses=1]
+        br i1 %tmp.2, label %loopexit.0, label %no_exit.1.outer
+
+loopexit.0:             ; preds = %endif.0
+        %tmp.28 = zext i8 %tmp.6 to i32         ; <i32> [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -indvars -disable-output
+
+ at fixtab = external global [29 x [29 x [2 x i32]]]               ; <[29 x [29 x [2 x i32]]]*> [#uses=1]
+
+define void @init_optabs() {
+entry:
+        br label %no_exit.0
+
+no_exit.0:              ; preds = %no_exit.0, %entry
+        %p.0.0 = phi i32* [ getelementptr ([29 x [29 x [2 x i32]]], [29 x [29 x [2 x i32]]]* @fixtab, i32 0, i32 0, i32 0, i32 0), %entry ], [ %inc.0, %no_exit.0 ]               ; <i32*> [#uses=1]
+        %inc.0 = getelementptr i32, i32* %p.0.0, i32 1               ; <i32*> [#uses=1]
+        br i1 undef, label %no_exit.0, label %no_exit.1
+
+no_exit.1:              ; preds = %no_exit.0
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2006-03-31-NegativeStride.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2006-03-31-NegativeStride.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2006-03-31-NegativeStride.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2006-03-31-NegativeStride.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; PR726
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Make sure to compute the right exit value based on negative strides.
+
+define i32 @test() {
+; CHECK-LABEL: @test(
+; CHECK: ret i32 27
+entry:
+        br label %cond_true
+
+cond_true:              ; preds = %cond_true, %entry
+        %a.0.0 = phi i32 [ 10, %entry ], [ %tmp4, %cond_true ]          ; <i32> [#uses=2]
+        %b.0.0 = phi i32 [ 0, %entry ], [ %tmp2, %cond_true ]           ; <i32> [#uses=1]
+        %tmp2 = add i32 %b.0.0, %a.0.0          ; <i32> [#uses=2]
+        %tmp4 = add i32 %a.0.0, -1              ; <i32> [#uses=2]
+        %tmp = icmp sgt i32 %tmp4, 7            ; <i1> [#uses=1]
+        br i1 %tmp, label %cond_true, label %bb7
+
+bb7:            ; preds = %cond_true
+        ret i32 %tmp2
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2006-06-16-Indvar-LCSSA-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2006-06-16-Indvar-LCSSA-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2006-06-16-Indvar-LCSSA-Crash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2006-06-16-Indvar-LCSSA-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -indvars -disable-output
+
+define void @get_block() {
+endif.0:
+        br label %no_exit.30
+
+no_exit.30:             ; preds = %no_exit.30, %endif.0
+        %x.12.0 = phi i32 [ %inc.28, %no_exit.30 ], [ -2, %endif.0 ]            ; <i32> [#uses=1]
+        %tmp.583 = load i16, i16* null               ; <i16> [#uses=1]
+        %tmp.584 = zext i16 %tmp.583 to i32             ; <i32> [#uses=1]
+        %tmp.588 = load i32, i32* null               ; <i32> [#uses=1]
+        %tmp.589 = mul i32 %tmp.584, %tmp.588           ; <i32> [#uses=1]
+        %tmp.591 = add i32 %tmp.589, 0          ; <i32> [#uses=1]
+        %inc.28 = add i32 %x.12.0, 1            ; <i32> [#uses=2]
+        %tmp.565 = icmp sgt i32 %inc.28, 3              ; <i1> [#uses=1]
+        br i1 %tmp.565, label %loopexit.30, label %no_exit.30
+
+loopexit.30:            ; preds = %no_exit.30
+        %tmp.591.lcssa = phi i32 [ %tmp.591, %no_exit.30 ]              ; <i32> [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2006-09-20-LFTR-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2006-09-20-LFTR-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2006-09-20-LFTR-Crash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2006-09-20-LFTR-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -indvars -disable-output
+; ModuleID = '2006-09-20-LFTR-Crash.ll'
+	%struct.p7prior_s = type { i32, i32, [200 x float], [200 x [7 x float]], i32, [200 x float], [200 x [20 x float]], i32, [200 x float], [200 x [20 x float]] }
+
+define void @P7DefaultPrior() {
+entry:
+	switch i32 0, label %UnifiedReturnBlock [
+		 i32 2, label %bb160
+		 i32 3, label %bb
+	]
+
+bb:		; preds = %entry
+	br i1 false, label %cond_true.i, label %sre_malloc.exit
+
+cond_true.i:		; preds = %bb
+	unreachable
+
+sre_malloc.exit:		; preds = %bb
+	br label %cond_true
+
+cond_true:		; preds = %cond_true66, %cond_true, %sre_malloc.exit
+	%tmp59 = phi i32 [ 1, %sre_malloc.exit ], [ %phitmp, %cond_true66 ], [ %tmp59, %cond_true ]		; <i32> [#uses=2]
+	%indvar245.0.ph = phi i32 [ 0, %sre_malloc.exit ], [ %indvar.next246, %cond_true66 ], [ %indvar245.0.ph, %cond_true ]		; <i32> [#uses=2]
+	br i1 false, label %bb57, label %cond_true
+
+bb57:		; preds = %cond_true
+	%tmp65 = icmp sgt i32 0, %tmp59		; <i1> [#uses=1]
+	%indvar.next246 = add i32 %indvar245.0.ph, 1		; <i32> [#uses=2]
+	br i1 %tmp65, label %cond_true66, label %bb69
+
+cond_true66:		; preds = %bb57
+	%q.1.0 = bitcast i32 %indvar.next246 to i32		; <i32> [#uses=1]
+	%phitmp = add i32 %q.1.0, 1		; <i32> [#uses=1]
+	br label %cond_true
+
+bb69:		; preds = %bb57
+	ret void
+
+bb160:		; preds = %entry
+	ret void
+
+UnifiedReturnBlock:		; preds = %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -indvars -disable-output
+target datalayout = "e-p:32:32"
+target triple = "i686-apple-darwin8"
+	%struct.vorbis_dsp_state = type { i32, %struct.vorbis_info*, float**, float**, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64, i64, i64, i64, i64, i64, i8* }
+	%struct.vorbis_info = type { i32, i32, i32, i32, i32, i32, i32, i8* }
+
+define void @_ve_envelope_search() {
+entry:
+	br i1 false, label %cond_true27, label %bb137
+
+cond_true27:		; preds = %entry
+	br i1 false, label %cond_true52, label %bb80
+
+cond_true52:		; preds = %cond_true27
+	%tmp152.i = bitcast float 0.000000e+00 to i32		; <i32> [#uses=1]
+	br label %cond_next182.i
+
+cond_next182.i:		; preds = %cond_next182.i, %cond_true52
+	%decay.i.0 = phi i32 [ %tmp195.i.upgrd.1, %cond_next182.i ], [ %tmp152.i, %cond_true52 ]		; <i32> [#uses=1]
+	%tmp194.i53 = bitcast i32 %decay.i.0 to float		; <float> [#uses=1]
+	%tmp195.i = fsub float %tmp194.i53, 8.000000e+00		; <float> [#uses=1]
+	%tmp195.i.upgrd.1 = bitcast float %tmp195.i to i32		; <i32> [#uses=1]
+	br i1 undef, label %cond_next182.i, label %bb418.i.preheader
+
+bb418.i.preheader:		; preds = %cond_next182.i
+	ret void
+
+bb80:		; preds = %cond_true27
+	ret void
+
+bb137:		; preds = %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2007-01-06-TripCount.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2007-01-06-TripCount.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2007-01-06-TripCount.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2007-01-06-TripCount.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; PR1015
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-p:32:32"
+target triple = "i686-apple-darwin8"
+ at foo = internal constant [5 x i8] c"\00abc\00"		; <[5 x i8]*> [#uses=1]
+ at str = internal constant [4 x i8] c"%d\0A\00"		; <[4 x i8]*> [#uses=1]
+
+
+define i32 @test(i32 %J) {
+; CHECK-LABEL: @test(
+; CHECK-NOT: ret i32 0
+entry:
+	br label %bb2
+
+bb:		; preds = %cond_next, %cond_true
+	%tmp1 = add i32 %i.0, 1		; <i32> [#uses=1]
+	br label %bb2
+
+bb2:		; preds = %bb, %entry
+	%i.0 = phi i32 [ 0, %entry ], [ %tmp1, %bb ]		; <i32> [#uses=4]
+	%tmp = icmp eq i32 %i.0, 0		; <i1> [#uses=1]
+	br i1 %tmp, label %cond_true, label %cond_next
+
+cond_true:		; preds = %bb2
+	br label %bb
+
+cond_next:		; preds = %bb2
+	%tmp2 = getelementptr [5 x i8], [5 x i8]* @foo, i32 0, i32 %i.0		; <i8*> [#uses=1]
+	%tmp3 = load i8, i8* %tmp2		; <i8> [#uses=1]
+	%tmp5 = icmp eq i8 %tmp3, 0		; <i1> [#uses=1]
+	br i1 %tmp5, label %bb6, label %bb
+
+bb6:		; preds = %cond_next
+	br label %return
+
+return:		; preds = %bb6
+	ret i32 %i.0
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/2007-06-06-DeleteDanglesPtr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2007-06-06-DeleteDanglesPtr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2007-06-06-DeleteDanglesPtr.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2007-06-06-DeleteDanglesPtr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,117 @@
+; RUN: opt < %s -indvars -disable-output
+; PR1487
+
+	%struct.AVClass = type { i8*, i8* (i8*)*, %struct.AVOption* }
+	%struct.AVCodec = type { i8*, i32, i32, i32, i32 (%struct.AVCodecContext*)*, i32 (%struct.AVCodecContext*, i8*, i32, i8*)*, i32 (%struct.AVCodecContext*)*, i32 (%struct.AVCodecContext*, i8*, i32*, i8*, i32)*, i32, %struct.AVCodec*, void (%struct.AVCodecContext*)*, %struct.AVCodecTag*, i32* }
+	%struct.AVCodecContext = type { %struct.AVClass*, i32, i32, i32, i32, i32, i8*, i32, %struct.AVCodecTag, i32, i32, i32, i32, i32, void (%struct.AVCodecContext*, %struct.AVFrame*, i32*, i32, i32, i32)*, i32, i32, i32, i32, i32, i32, i32, float, float, i32, i32, i32, i32, float, i32, i32, i32, %struct.AVCodec*, i8*, i32, i32, void (%struct.AVCodecContext*, i8*, i32, i32)*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8*, [32 x i8], i32, i32, i32, i32, i32, i32, i32, float, i32, i32 (%struct.AVCodecContext*, %struct.AVFrame*)*, void (%struct.AVCodecContext*, %struct.AVFrame*)*, i32, i32, i32, i32, i8*, i8*, float, float, i32, %struct.RcOverride*, i32, i8*, i32, i32, i32, float, float, float, float, i32, float, float, float, float, float, i32, i32, i32, i32*, i32, i32, i32, i32, %struct.AVCodecTag, %struct.AVFrame*, i32, i32, [4 x i64], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 (%struct.AVCodecContext*, i32*)*, i32, i32, i32, i32, i32, i32, i8*, i32, i32, i32, i32, i32, i32, i16*, i16*, i32, i32, i32, i32, %struct.AVPaletteControl*, i32, i32 (%struct.AVCodecContext*, %struct.AVFrame*)*, i32, i32, i32, i32, i32, i32, i32, i32 (%struct.AVCodecContext*, i32 (%struct.AVCodecContext*, i8*)*, i8**, i32*, i32)*, i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, float, i32, i32, i32, i32, i32, i32, i32, i32, float, i32, i32, i32, i32, i32, i32, float, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64 }
+	%struct.AVCodecTag = type { i32, i32 }
+	%struct.AVFrame = type { [4 x i8*], [4 x i32], [4 x i8*], i32, i32, i64, i32, i32, i32, i32, i32, i8*, i32, i8*, [2 x [2 x i16]*], i32*, i8, i8*, [4 x i64], i32, i32, i32, i32, i32, %struct.AVPanScan*, i32, i32, i16*, [2 x i8*] }
+	%struct.AVOption = type { i8*, i8*, i32, i32, double, double, double, i32, i8* }
+	%struct.AVPaletteControl = type { i32, [256 x i32] }
+	%struct.AVPanScan = type { i32, i32, i32, [3 x [2 x i16]] }
+	%struct.RcOverride = type { i32, i32, i32, float }
+
+define i32 @smc_decode_frame(%struct.AVCodecContext* %avctx, i8* %data, i32* %data_size, i8* %buf, i32 %buf_size) {
+entry:
+	br i1 false, label %cond_next, label %cond_true
+
+cond_true:		; preds = %entry
+	ret i32 -1
+
+cond_next:		; preds = %entry
+	br i1 false, label %bb.outer5.split.split.split.us, label %cond_true194.split
+
+bb.outer5.split.split.split.us:		; preds = %cond_next
+	br i1 false, label %cond_next188.us503.us, label %bb.us481
+
+bb275.us493.us:		; preds = %cond_next188.us503.us, %cond_next188.us503.us
+	ret i32 0
+
+cond_next188.us503.us:		; preds = %bb.outer5.split.split.split.us
+	switch i32 0, label %bb1401 [
+		 i32 0, label %cond_next202.bb215_crit_edge.split
+		 i32 16, label %bb215
+		 i32 32, label %bb275.us493.us
+		 i32 48, label %bb275.us493.us
+		 i32 64, label %cond_next202.bb417_crit_edge.split
+		 i32 80, label %bb417
+		 i32 96, label %cond_next202.bb615_crit_edge.split
+		 i32 112, label %bb615
+		 i32 128, label %cond_next202.bb716_crit_edge.split
+		 i32 144, label %bb716
+		 i32 160, label %cond_next202.bb882_crit_edge.split
+		 i32 176, label %bb882
+		 i32 192, label %cond_next202.bb1062_crit_edge.split
+		 i32 208, label %bb1062
+		 i32 224, label %bb1326.us.outer.outer
+	]
+
+bb.us481:		; preds = %bb.outer5.split.split.split.us
+	ret i32 0
+
+cond_true194.split:		; preds = %cond_next
+	ret i32 %buf_size
+
+cond_next202.bb1062_crit_edge.split:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+cond_next202.bb882_crit_edge.split:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+cond_next202.bb716_crit_edge.split:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+cond_next202.bb615_crit_edge.split:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+cond_next202.bb417_crit_edge.split:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+cond_next202.bb215_crit_edge.split:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb215:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb417:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb615:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb716:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb882:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb1062:		; preds = %cond_next188.us503.us
+	ret i32 0
+
+bb1326.us:		; preds = %bb1326.us.outer.outer, %bb1347.loopexit.us, %bb1326.us
+	%pixel_y.162036.us.ph = phi i32 [ %tmp1352.us, %bb1347.loopexit.us ], [ 0, %bb1326.us.outer.outer ], [ %pixel_y.162036.us.ph, %bb1326.us ]		; <i32> [#uses=2]
+	%stream_ptr.142038.us.ph = phi i32 [ %tmp1339.us, %bb1347.loopexit.us ], [ %stream_ptr.142038.us.ph.ph, %bb1326.us.outer.outer ], [ %stream_ptr.142038.us.ph, %bb1326.us ]		; <i32> [#uses=2]
+	%pixel_x.232031.us = phi i32 [ %tmp1341.us, %bb1326.us ], [ 0, %bb1326.us.outer.outer ], [ 0, %bb1347.loopexit.us ]		; <i32> [#uses=3]
+	%block_ptr.222030.us = add i32 0, %pixel_x.232031.us		; <i32> [#uses=1]
+	%stream_ptr.132032.us = add i32 %pixel_x.232031.us, %stream_ptr.142038.us.ph		; <i32> [#uses=1]
+	%tmp1341.us = add i32 %pixel_x.232031.us, 1		; <i32> [#uses=2]
+	%tmp1344.us = icmp slt i32 %tmp1341.us, 4		; <i1> [#uses=1]
+	br i1 %tmp1344.us, label %bb1326.us, label %bb1347.loopexit.us
+
+bb1347.loopexit.us:		; preds = %bb1326.us
+	%tmp1339.us = add i32 %stream_ptr.132032.us, 1		; <i32> [#uses=2]
+	%tmp1337.us = add i32 %block_ptr.222030.us, 1		; <i32> [#uses=0]
+	%tmp1352.us = add i32 %pixel_y.162036.us.ph, 1		; <i32> [#uses=2]
+	%tmp1355.us = icmp slt i32 %tmp1352.us, 4		; <i1> [#uses=1]
+	br i1 %tmp1355.us, label %bb1326.us, label %bb1358
+
+bb1358:		; preds = %bb1347.loopexit.us
+	br label %bb1326.us.outer.outer
+
+bb1326.us.outer.outer:		; preds = %bb1358, %cond_next188.us503.us
+	%stream_ptr.142038.us.ph.ph = phi i32 [ %tmp1339.us, %bb1358 ], [ 0, %cond_next188.us503.us ]		; <i32> [#uses=1]
+	br label %bb1326.us
+
+bb1401:		; preds = %cond_next188.us503.us
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2007-11-23-BitcastCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2007-11-23-BitcastCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2007-11-23-BitcastCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2007-11-23-BitcastCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -indvars -disable-output
+; PR1814
+target datalayout = "e-p:32:32-f64:32:64-i64:32:64-f80:32:32"
+
+define void @FuncAt1938470480(i32, i32, i32, i32, i32, i32, i32, i32, i64, i64, i64, i64, i64, i64, i64, i64, i1, i1, i1, i1, i1, i1) {
+EntryBlock:
+	br label %asmBlockAt738ab7f3
+
+asmBlockAt738ab9b0:		; preds = %asmBlockAt738ab7f3
+	%.lcssa6 = phi i64 [ %23, %asmBlockAt738ab7f3 ]		; <i64> [#uses=0]
+	ret void
+
+asmBlockAt738ab7f3:		; preds = %asmBlockAt738ab7f3, %EntryBlock
+	%ebp95 = phi i32 [ 128, %EntryBlock ], [ %24, %asmBlockAt738ab7f3 ]		; <i32> [#uses=2]
+	sub <4 x i16> zeroinitializer, zeroinitializer		; <<4 x i16>>:22 [#uses=1]
+	bitcast <4 x i16> %22 to i64		; <i64>:23 [#uses=1]
+	add i32 %ebp95, -64		; <i32>:24 [#uses=1]
+	icmp ult i32 %ebp95, 64		; <i1>:25 [#uses=1]
+	br i1 %25, label %asmBlockAt738ab9b0, label %asmBlockAt738ab7f3
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2008-06-15-SCEVExpanderBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2008-06-15-SCEVExpanderBug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2008-06-15-SCEVExpanderBug.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2008-06-15-SCEVExpanderBug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -indvars -disable-output
+; PR2434
+
+define fastcc void @regcppop() nounwind  {
+entry:
+	%tmp61 = add i32 0, -5		; <i32> [#uses=1]
+	br label %bb
+
+bb:		; preds = %bb, %entry
+	%PL_savestack_ix.tmp.0 = phi i32 [ %tmp61, %entry ], [ %tmp127, %bb ]		; <i32> [#uses=2]
+	%indvar10 = phi i32 [ 0, %entry ], [ %indvar.next11, %bb ]		; <i32> [#uses=2]
+	%tmp13 = mul i32 %indvar10, -4		; <i32> [#uses=0]
+	%tmp111 = add i32 %PL_savestack_ix.tmp.0, -3		; <i32> [#uses=0]
+	%tmp127 = add i32 %PL_savestack_ix.tmp.0, -4		; <i32> [#uses=1]
+	%indvar.next11 = add i32 %indvar10, 1		; <i32> [#uses=1]
+	br label %bb
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2008-09-02-IVType.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2008-09-02-IVType.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2008-09-02-IVType.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2008-09-02-IVType.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; ModuleID = '<stdin>'
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+	%struct.App1Marker = type <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }>
+	%struct.ComponentInstanceRecord = type <{ [1 x i32] }>
+	%struct.DCPredictors = type { [5 x i16] }
+	%struct.DecodeTable = type { i16, i16, i16, i16, i8**, i8** }
+	%struct.ICMDataProcRecord = type <{ i16 (i8**, i32, i32)*, i32 }>
+	%struct.JPEGBitStream = type { i8*, i32, i32, i32, i32, i32, %struct.App1Marker*, i8*, i32, i16, i16, i32 }
+	%struct.JPEGGlobals = type { [2048 x i8], %struct.JPEGBitStream, i8*, i32, i32, %struct.ComponentInstanceRecord*, %struct.ComponentInstanceRecord*, i32, %struct.OpaqueQTMLMutex*, %struct.Rect, i32, i32, %struct.SharedGlobals, %struct.DCPredictors, i8, i8, void (i8*, i16**, i32, %struct.YUVGeneralParams*)*, %struct.YUVGeneralParams, i16, i16, i32, [5 x i16*], [5 x %struct.DecodeTable*], [5 x %struct.DecodeTable*], [5 x i8], [5 x i8], [4 x [65 x i16]], [4 x %struct.DecodeTable], [4 x %struct.DecodeTable], [4 x i8*], [4 x i8*], i16, i16, i32, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, i8**, [18 x i8], [18 x i8], [18 x i8], [18 x i8], i32, i32, i8**, i8**, i8, i8, i8, i8, i16, i16, %struct.App1Marker*, i8, i8, i8, i8, i32**, i8*, i16*, i8*, i16*, i8, [3 x i8], i32, [3 x i32], [3 x i32], [3 x i32], [3 x i32], [3 x i32], [3 x i16*], [3 x i16*], [3 x i8**], [3 x %struct.DecodeTable*], [3 x %struct.DecodeTable*], [3 x i32], i32, [3 x i16*], i32, i32, i32, [3 x i32], i8, i8, i8, i8, %struct.ICMDataProcRecord*, i32, i32, i8**, i8**, i8**, i8**, i32, i32, i8*, i32, i32, i16*, i16*, i8*, i32, i32, i32, i32, i32, i32, i32, [16 x <2 x i64>], [1280 x i8], i8 }
+	%struct.OpaqueQTMLMutex = type opaque
+	%struct.Rect = type { i16, i16, i16, i16 }
+	%struct.SharedDGlobals = type { %struct.DecodeTable, %struct.DecodeTable, %struct.DecodeTable, %struct.DecodeTable }
+	%struct.SharedEGlobals = type { i8**, i8**, i8**, i8** }
+	%struct.SharedGlobals = type { %struct.SharedEGlobals*, %struct.SharedDGlobals* }
+	%struct.YUVGeneralParams = type { i16*, i8*, i8*, i8*, i8*, i8*, void (i8*, i16**, i32, %struct.YUVGeneralParams*)*, i16, i16, i16, [6 x i8], void (i8*, i16**, i32, %struct.YUVGeneralParams*)*, i16, i16 }
+ at llvm.used = appending global [1 x i8*] [ i8* bitcast (i16 (%struct.JPEGGlobals*)* @ExtractBufferedBlocksIgnored to i8*) ], section "llvm.metadata"		; <[1 x i8*]*> [#uses=0]
+
+define signext i16 @ExtractBufferedBlocksIgnored(%struct.JPEGGlobals* %globp)  nounwind {
+; CHECK-LABEL: @ExtractBufferedBlocksIgnored(
+; CHECK: sext
+; CHECK-NOT: sext
+entry:
+	%tmp4311 = getelementptr %struct.JPEGGlobals, %struct.JPEGGlobals* %globp, i32 0, i32 70		; <i32*> [#uses=1]
+	%tmp4412 = load i32, i32* %tmp4311, align 16		; <i32> [#uses=2]
+	%tmp4613 = icmp sgt i32 %tmp4412, 0		; <i1> [#uses=1]
+	br i1 %tmp4613, label %bb, label %bb49
+
+bb:		; preds = %bb28, %entry
+	%component.09 = phi i16 [ 0, %entry ], [ %tmp37, %bb28 ]		; <i16> [#uses=2]
+	%tmp12 = sext i16 %component.09 to i32		; <i32> [#uses=2]
+	%tmp6 = getelementptr %struct.JPEGGlobals, %struct.JPEGGlobals* %globp, i32 0, i32 77, i32 %tmp12		; <i16**> [#uses=2]
+	%tmp7 = load i16*, i16** %tmp6, align 4		; <i16*> [#uses=2]
+	%tmp235 = getelementptr %struct.JPEGGlobals, %struct.JPEGGlobals* %globp, i32 0, i32 71, i32 %tmp12		; <i32*> [#uses=1]
+	%tmp246 = load i32, i32* %tmp235, align 4		; <i32> [#uses=2]
+	%tmp267 = icmp sgt i32 %tmp246, 0		; <i1> [#uses=1]
+	br i1 %tmp267, label %bb8, label %bb28
+
+bb8:		; preds = %bb8, %bb
+	%indvar = phi i32 [ 0, %bb ], [ %indvar.next2, %bb8 ]		; <i32> [#uses=3]
+	%theDCTBufferIter.01.rec = shl i32 %indvar, 6		; <i32> [#uses=1]
+	%tmp10.rec = add i32 %theDCTBufferIter.01.rec, 64		; <i32> [#uses=1]
+	%tmp10 = getelementptr i16, i16* %tmp7, i32 %tmp10.rec		; <i16*> [#uses=1]
+	%i.02 = trunc i32 %indvar to i16		; <i16> [#uses=1]
+	%tmp13 = add i16 %i.02, 1		; <i16> [#uses=1]
+	%phitmp = sext i16 %tmp13 to i32		; <i32> [#uses=1]
+	%tmp26 = icmp slt i32 %phitmp, %tmp246		; <i1> [#uses=1]
+	%indvar.next2 = add i32 %indvar, 1		; <i32> [#uses=1]
+	br i1 %tmp26, label %bb8, label %bb28
+
+bb28:		; preds = %bb8, %bb
+	%theDCTBufferIter.0.lcssa = phi i16* [ %tmp7, %bb ], [ %tmp10, %bb8 ]		; <i16*> [#uses=1]
+	store i16* %theDCTBufferIter.0.lcssa, i16** %tmp6, align 4
+	%tmp37 = add i16 %component.09, 1		; <i16> [#uses=2]
+	%phitmp15 = sext i16 %tmp37 to i32		; <i32> [#uses=1]
+	%tmp46 = icmp slt i32 %phitmp15, 42		; <i1> [#uses=1]
+	br i1 %tmp46, label %bb, label %bb49
+
+bb49:		; preds = %bb28, %entry
+	ret i16 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2008-10-03-CouldNotCompute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2008-10-03-CouldNotCompute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2008-10-03-CouldNotCompute.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2008-10-03-CouldNotCompute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -indvars
+; PR2857
+
+ at foo = external global i32		; <i32*> [#uses=1]
+
+define void @test(i32 %n, i32 %arg) {
+entry:
+	br i1 false, label %bb.nph, label %return
+
+bb.nph:		; preds = %entry
+	%0 = load i32, i32* @foo, align 4		; <i32> [#uses=1]
+	%1 = sext i32 %0 to i64		; <i64> [#uses=1]
+	br label %bb
+
+bb:		; preds = %bb, %bb.nph
+	%.in = phi i32 [ %2, %bb ], [ %n, %bb.nph ]		; <i32> [#uses=1]
+	%val.02 = phi i64 [ %5, %bb ], [ 0, %bb.nph ]		; <i64> [#uses=2]
+	%result.01 = phi i64 [ %4, %bb ], [ 0, %bb.nph ]		; <i64> [#uses=1]
+	%2 = add i32 %.in, -1		; <i32> [#uses=2]
+	%3 = mul i64 %1, %val.02		; <i64> [#uses=1]
+	%4 = add i64 %3, %result.01		; <i64> [#uses=2]
+	%5 = add i64 %val.02, 1		; <i64> [#uses=1]
+	%6 = icmp sgt i32 %2, 0		; <i1> [#uses=1]
+	br i1 %6, label %bb, label %bb3.bb4_crit_edge
+
+bb3.bb4_crit_edge:		; preds = %bb
+	%.lcssa = phi i64 [ %4, %bb ]		; <i64> [#uses=0]
+	ret void
+
+return:		; preds = %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2008-11-25-APFloatAssert.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2008-11-25-APFloatAssert.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2008-11-25-APFloatAssert.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2008-11-25-APFloatAssert.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -indvars
+
+define void @t() nounwind {
+entry:
+	br label %bb23.i91
+
+bb23.i91:		; preds = %bb23.i91, %entry
+	%result.0.i89 = phi ppc_fp128 [ 0xM00000000000000000000000000000000, %entry ], [ %0, %bb23.i91 ]		; <ppc_fp128> [#uses=2]
+	%0 = fmul ppc_fp128 %result.0.i89, %result.0.i89		; <ppc_fp128> [#uses=1]
+	br label %bb23.i91
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,116 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; ModuleID = '<stdin>'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
+target triple = "x86_64-apple-darwin9.6"
+ at a = external global i32*		; <i32**> [#uses=3]
+ at b = external global i32*		; <i32**> [#uses=3]
+ at c = external global i32*		; <i32**> [#uses=3]
+ at d = external global i32*		; <i32**> [#uses=3]
+ at e = external global i32*		; <i32**> [#uses=3]
+ at f = external global i32*		; <i32**> [#uses=3]
+
+define void @foo() nounwind {
+; CHECK-LABEL: @foo(
+; CHECK-NOT: sext
+bb1.thread:
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %84, %bb1 ]		; <i32> [#uses=19]
+	%0 = load i32*, i32** @a, align 8		; <i32*> [#uses=1]
+	%1 = load i32*, i32** @b, align 8		; <i32*> [#uses=1]
+	%2 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%3 = getelementptr i32, i32* %1, i64 %2		; <i32*> [#uses=1]
+	%4 = load i32, i32* %3, align 1		; <i32> [#uses=1]
+	%5 = load i32*, i32** @c, align 8		; <i32*> [#uses=1]
+	%6 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%7 = getelementptr i32, i32* %5, i64 %6		; <i32*> [#uses=1]
+	%8 = load i32, i32* %7, align 1		; <i32> [#uses=1]
+	%9 = add i32 %8, %4		; <i32> [#uses=1]
+	%10 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%11 = getelementptr i32, i32* %0, i64 %10		; <i32*> [#uses=1]
+	store i32 %9, i32* %11, align 1
+	%12 = load i32*, i32** @a, align 8		; <i32*> [#uses=1]
+	%13 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%14 = load i32*, i32** @b, align 8		; <i32*> [#uses=1]
+	%15 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%16 = sext i32 %15 to i64		; <i64> [#uses=1]
+	%17 = getelementptr i32, i32* %14, i64 %16		; <i32*> [#uses=1]
+	%18 = load i32, i32* %17, align 1		; <i32> [#uses=1]
+	%19 = load i32*, i32** @c, align 8		; <i32*> [#uses=1]
+	%20 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%21 = sext i32 %20 to i64		; <i64> [#uses=1]
+	%22 = getelementptr i32, i32* %19, i64 %21		; <i32*> [#uses=1]
+	%23 = load i32, i32* %22, align 1		; <i32> [#uses=1]
+	%24 = add i32 %23, %18		; <i32> [#uses=1]
+	%25 = sext i32 %13 to i64		; <i64> [#uses=1]
+	%26 = getelementptr i32, i32* %12, i64 %25		; <i32*> [#uses=1]
+	store i32 %24, i32* %26, align 1
+	%27 = load i32*, i32** @a, align 8		; <i32*> [#uses=1]
+	%28 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%29 = load i32*, i32** @b, align 8		; <i32*> [#uses=1]
+	%30 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%31 = sext i32 %30 to i64		; <i64> [#uses=1]
+	%32 = getelementptr i32, i32* %29, i64 %31		; <i32*> [#uses=1]
+	%33 = load i32, i32* %32, align 1		; <i32> [#uses=1]
+	%34 = load i32*, i32** @c, align 8		; <i32*> [#uses=1]
+	%35 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%36 = sext i32 %35 to i64		; <i64> [#uses=1]
+	%37 = getelementptr i32, i32* %34, i64 %36		; <i32*> [#uses=1]
+	%38 = load i32, i32* %37, align 1		; <i32> [#uses=1]
+	%39 = add i32 %38, %33		; <i32> [#uses=1]
+	%40 = sext i32 %28 to i64		; <i64> [#uses=1]
+	%41 = getelementptr i32, i32* %27, i64 %40		; <i32*> [#uses=1]
+	store i32 %39, i32* %41, align 1
+	%42 = load i32*, i32** @d, align 8		; <i32*> [#uses=1]
+	%43 = load i32*, i32** @e, align 8		; <i32*> [#uses=1]
+	%44 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%45 = getelementptr i32, i32* %43, i64 %44		; <i32*> [#uses=1]
+	%46 = load i32, i32* %45, align 1		; <i32> [#uses=1]
+	%47 = load i32*, i32** @f, align 8		; <i32*> [#uses=1]
+	%48 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%49 = getelementptr i32, i32* %47, i64 %48		; <i32*> [#uses=1]
+	%50 = load i32, i32* %49, align 1		; <i32> [#uses=1]
+	%51 = add i32 %50, %46		; <i32> [#uses=1]
+	%52 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%53 = getelementptr i32, i32* %42, i64 %52		; <i32*> [#uses=1]
+	store i32 %51, i32* %53, align 1
+	%54 = load i32*, i32** @d, align 8		; <i32*> [#uses=1]
+	%55 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%56 = load i32*, i32** @e, align 8		; <i32*> [#uses=1]
+	%57 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%58 = sext i32 %57 to i64		; <i64> [#uses=1]
+	%59 = getelementptr i32, i32* %56, i64 %58		; <i32*> [#uses=1]
+	%60 = load i32, i32* %59, align 1		; <i32> [#uses=1]
+	%61 = load i32*, i32** @f, align 8		; <i32*> [#uses=1]
+	%62 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%63 = sext i32 %62 to i64		; <i64> [#uses=1]
+	%64 = getelementptr i32, i32* %61, i64 %63		; <i32*> [#uses=1]
+	%65 = load i32, i32* %64, align 1		; <i32> [#uses=1]
+	%66 = add i32 %65, %60		; <i32> [#uses=1]
+	%67 = sext i32 %55 to i64		; <i64> [#uses=1]
+	%68 = getelementptr i32, i32* %54, i64 %67		; <i32*> [#uses=1]
+	store i32 %66, i32* %68, align 1
+	%69 = load i32*, i32** @d, align 8		; <i32*> [#uses=1]
+	%70 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%71 = load i32*, i32** @e, align 8		; <i32*> [#uses=1]
+	%72 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%73 = sext i32 %72 to i64		; <i64> [#uses=1]
+	%74 = getelementptr i32, i32* %71, i64 %73		; <i32*> [#uses=1]
+	%75 = load i32, i32* %74, align 1		; <i32> [#uses=1]
+	%76 = load i32*, i32** @f, align 8		; <i32*> [#uses=1]
+	%77 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%78 = sext i32 %77 to i64		; <i64> [#uses=1]
+	%79 = getelementptr i32, i32* %76, i64 %78		; <i32*> [#uses=1]
+	%80 = load i32, i32* %79, align 1		; <i32> [#uses=1]
+	%81 = add i32 %80, %75		; <i32> [#uses=1]
+	%82 = sext i32 %70 to i64		; <i64> [#uses=1]
+	%83 = getelementptr i32, i32* %69, i64 %82		; <i32*> [#uses=1]
+	store i32 %81, i32* %83, align 1
+	%84 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=2]
+	%85 = icmp sgt i32 %84, 23646		; <i1> [#uses=1]
+	br i1 %85, label %return, label %bb1
+
+return:		; preds = %bb1
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,163 @@
+; RUN: opt < %s -indvars -instcombine -S | FileCheck %s
+; ModuleID = '<stdin>'
+;extern int *a, *b, *c, *d, *e, *f;  /* 64 bit */
+;extern int K[256];
+;void foo () {
+;  int i;
+;  for (i=0; i<23647; i++) {
+;    a[(i&15)] = b[i&15]+c[i&15];
+;    a[(i+1)&15] = b[(i+1)&15]+c[(i+1)&15];
+;    a[(i+2)&15] = b[(i+2)&15]+c[(i+2)&15];
+;    d[i&15] = e[i&15]+f[i&15] +K[i];
+;    d[(i+1)&15] = e[(i+1)&15]+f[(i+1)&15]+K[i+1];
+;    d[(i+2)&15] = e[(i+2)&15]+f[(i+2)&15]+K[i+2];
+;  }
+;}
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
+target triple = "x86_64-apple-darwin9.6"
+ at a = external global i32*		; <i32**> [#uses=3]
+ at b = external global i32*		; <i32**> [#uses=3]
+ at c = external global i32*		; <i32**> [#uses=3]
+ at d = external global i32*		; <i32**> [#uses=3]
+ at e = external global i32*		; <i32**> [#uses=3]
+ at f = external global i32*		; <i32**> [#uses=3]
+ at K = external global [256 x i32]		; <[256 x i32]*> [#uses=3]
+
+define void @foo() nounwind {
+; CHECK-LABEL: @foo(
+; CHECK-NOT: sext
+; CHECK-NOT: zext
+bb1.thread:
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%i.0.reg2mem.0 = phi i32 [ 0, %bb1.thread ], [ %116, %bb1 ]		; <i32> [#uses=22]
+	%0 = load i32*, i32** @a, align 8		; <i32*> [#uses=1]
+	%1 = and i32 %i.0.reg2mem.0, 15		; <i32> [#uses=1]
+	%2 = load i32*, i32** @b, align 8		; <i32*> [#uses=1]
+	%3 = and i32 %i.0.reg2mem.0, 15		; <i32> [#uses=1]
+	%4 = zext i32 %3 to i64		; <i64> [#uses=1]
+	%5 = getelementptr i32, i32* %2, i64 %4		; <i32*> [#uses=1]
+	%6 = load i32, i32* %5, align 1		; <i32> [#uses=1]
+	%7 = load i32*, i32** @c, align 8		; <i32*> [#uses=1]
+	%8 = and i32 %i.0.reg2mem.0, 15		; <i32> [#uses=1]
+	%9 = zext i32 %8 to i64		; <i64> [#uses=1]
+	%10 = getelementptr i32, i32* %7, i64 %9		; <i32*> [#uses=1]
+	%11 = load i32, i32* %10, align 1		; <i32> [#uses=1]
+	%12 = add i32 %11, %6		; <i32> [#uses=1]
+	%13 = zext i32 %1 to i64		; <i64> [#uses=1]
+	%14 = getelementptr i32, i32* %0, i64 %13		; <i32*> [#uses=1]
+	store i32 %12, i32* %14, align 1
+	%15 = load i32*, i32** @a, align 8		; <i32*> [#uses=1]
+	%16 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%17 = and i32 %16, 15		; <i32> [#uses=1]
+	%18 = load i32*, i32** @b, align 8		; <i32*> [#uses=1]
+	%19 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%20 = and i32 %19, 15		; <i32> [#uses=1]
+	%21 = zext i32 %20 to i64		; <i64> [#uses=1]
+	%22 = getelementptr i32, i32* %18, i64 %21		; <i32*> [#uses=1]
+	%23 = load i32, i32* %22, align 1		; <i32> [#uses=1]
+	%24 = load i32*, i32** @c, align 8		; <i32*> [#uses=1]
+	%25 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%26 = and i32 %25, 15		; <i32> [#uses=1]
+	%27 = zext i32 %26 to i64		; <i64> [#uses=1]
+	%28 = getelementptr i32, i32* %24, i64 %27		; <i32*> [#uses=1]
+	%29 = load i32, i32* %28, align 1		; <i32> [#uses=1]
+	%30 = add i32 %29, %23		; <i32> [#uses=1]
+	%31 = zext i32 %17 to i64		; <i64> [#uses=1]
+	%32 = getelementptr i32, i32* %15, i64 %31		; <i32*> [#uses=1]
+	store i32 %30, i32* %32, align 1
+	%33 = load i32*, i32** @a, align 8		; <i32*> [#uses=1]
+	%34 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%35 = and i32 %34, 15		; <i32> [#uses=1]
+	%36 = load i32*, i32** @b, align 8		; <i32*> [#uses=1]
+	%37 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%38 = and i32 %37, 15		; <i32> [#uses=1]
+	%39 = zext i32 %38 to i64		; <i64> [#uses=1]
+	%40 = getelementptr i32, i32* %36, i64 %39		; <i32*> [#uses=1]
+	%41 = load i32, i32* %40, align 1		; <i32> [#uses=1]
+	%42 = load i32*, i32** @c, align 8		; <i32*> [#uses=1]
+	%43 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%44 = and i32 %43, 15		; <i32> [#uses=1]
+	%45 = zext i32 %44 to i64		; <i64> [#uses=1]
+	%46 = getelementptr i32, i32* %42, i64 %45		; <i32*> [#uses=1]
+	%47 = load i32, i32* %46, align 1		; <i32> [#uses=1]
+	%48 = add i32 %47, %41		; <i32> [#uses=1]
+	%49 = zext i32 %35 to i64		; <i64> [#uses=1]
+	%50 = getelementptr i32, i32* %33, i64 %49		; <i32*> [#uses=1]
+	store i32 %48, i32* %50, align 1
+	%51 = load i32*, i32** @d, align 8		; <i32*> [#uses=1]
+	%52 = and i32 %i.0.reg2mem.0, 15		; <i32> [#uses=1]
+	%53 = load i32*, i32** @e, align 8		; <i32*> [#uses=1]
+	%54 = and i32 %i.0.reg2mem.0, 15		; <i32> [#uses=1]
+	%55 = zext i32 %54 to i64		; <i64> [#uses=1]
+	%56 = getelementptr i32, i32* %53, i64 %55		; <i32*> [#uses=1]
+	%57 = load i32, i32* %56, align 1		; <i32> [#uses=1]
+	%58 = load i32*, i32** @f, align 8		; <i32*> [#uses=1]
+	%59 = and i32 %i.0.reg2mem.0, 15		; <i32> [#uses=1]
+	%60 = zext i32 %59 to i64		; <i64> [#uses=1]
+	%61 = getelementptr i32, i32* %58, i64 %60		; <i32*> [#uses=1]
+	%62 = load i32, i32* %61, align 1		; <i32> [#uses=1]
+	%63 = sext i32 %i.0.reg2mem.0 to i64		; <i64> [#uses=1]
+	%64 = getelementptr [256 x i32], [256 x i32]* @K, i64 0, i64 %63		; <i32*> [#uses=1]
+	%65 = load i32, i32* %64, align 4		; <i32> [#uses=1]
+	%66 = add i32 %62, %57		; <i32> [#uses=1]
+	%67 = add i32 %66, %65		; <i32> [#uses=1]
+	%68 = zext i32 %52 to i64		; <i64> [#uses=1]
+	%69 = getelementptr i32, i32* %51, i64 %68		; <i32*> [#uses=1]
+	store i32 %67, i32* %69, align 1
+	%70 = load i32*, i32** @d, align 8		; <i32*> [#uses=1]
+	%71 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%72 = and i32 %71, 15		; <i32> [#uses=1]
+	%73 = load i32*, i32** @e, align 8		; <i32*> [#uses=1]
+	%74 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%75 = and i32 %74, 15		; <i32> [#uses=1]
+	%76 = zext i32 %75 to i64		; <i64> [#uses=1]
+	%77 = getelementptr i32, i32* %73, i64 %76		; <i32*> [#uses=1]
+	%78 = load i32, i32* %77, align 1		; <i32> [#uses=1]
+	%79 = load i32*, i32** @f, align 8		; <i32*> [#uses=1]
+	%80 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%81 = and i32 %80, 15		; <i32> [#uses=1]
+	%82 = zext i32 %81 to i64		; <i64> [#uses=1]
+	%83 = getelementptr i32, i32* %79, i64 %82		; <i32*> [#uses=1]
+	%84 = load i32, i32* %83, align 1		; <i32> [#uses=1]
+	%85 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=1]
+	%86 = sext i32 %85 to i64		; <i64> [#uses=1]
+	%87 = getelementptr [256 x i32], [256 x i32]* @K, i64 0, i64 %86		; <i32*> [#uses=1]
+	%88 = load i32, i32* %87, align 4		; <i32> [#uses=1]
+	%89 = add i32 %84, %78		; <i32> [#uses=1]
+	%90 = add i32 %89, %88		; <i32> [#uses=1]
+	%91 = zext i32 %72 to i64		; <i64> [#uses=1]
+	%92 = getelementptr i32, i32* %70, i64 %91		; <i32*> [#uses=1]
+	store i32 %90, i32* %92, align 1
+	%93 = load i32*, i32** @d, align 8		; <i32*> [#uses=1]
+	%94 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%95 = and i32 %94, 15		; <i32> [#uses=1]
+	%96 = load i32*, i32** @e, align 8		; <i32*> [#uses=1]
+	%97 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%98 = and i32 %97, 15		; <i32> [#uses=1]
+	%99 = zext i32 %98 to i64		; <i64> [#uses=1]
+	%100 = getelementptr i32, i32* %96, i64 %99		; <i32*> [#uses=1]
+	%101 = load i32, i32* %100, align 1		; <i32> [#uses=1]
+	%102 = load i32*, i32** @f, align 8		; <i32*> [#uses=1]
+	%103 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%104 = and i32 %103, 15		; <i32> [#uses=1]
+	%105 = zext i32 %104 to i64		; <i64> [#uses=1]
+	%106 = getelementptr i32, i32* %102, i64 %105		; <i32*> [#uses=1]
+	%107 = load i32, i32* %106, align 1		; <i32> [#uses=1]
+	%108 = add i32 %i.0.reg2mem.0, 2		; <i32> [#uses=1]
+	%109 = sext i32 %108 to i64		; <i64> [#uses=1]
+	%110 = getelementptr [256 x i32], [256 x i32]* @K, i64 0, i64 %109		; <i32*> [#uses=1]
+	%111 = load i32, i32* %110, align 4		; <i32> [#uses=1]
+	%112 = add i32 %107, %101		; <i32> [#uses=1]
+	%113 = add i32 %112, %111		; <i32> [#uses=1]
+	%114 = zext i32 %95 to i64		; <i64> [#uses=1]
+	%115 = getelementptr i32, i32* %93, i64 %114		; <i32*> [#uses=1]
+	store i32 %113, i32* %115, align 1
+	%116 = add i32 %i.0.reg2mem.0, 1		; <i32> [#uses=2]
+	%117 = icmp sgt i32 %116, 23646		; <i1> [#uses=1]
+	br i1 %117, label %return, label %bb1
+
+return:		; preds = %bb1
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -indvars
+; rdar://6817574
+
+define i32 @t1() nounwind ssp {
+entry:
+	br label %bb32
+
+bb32:		; preds = %bb32, %entry
+	%mbPartIdx.0.reg2mem.0 = phi i8 [ %2, %bb32 ], [ 0, %entry ]		; <i8> [#uses=3]
+	%0 = and i8 %mbPartIdx.0.reg2mem.0, 1		; <i8> [#uses=0]
+	%1 = zext i8 %mbPartIdx.0.reg2mem.0 to i64		; <i64> [#uses=0]
+	%2 = add i8 %mbPartIdx.0.reg2mem.0, 1		; <i8> [#uses=2]
+	%3 = icmp ugt i8 %2, 3		; <i1> [#uses=1]
+	br i1 %3, label %bb41, label %bb32
+
+bb41:		; preds = %bb32
+	ret i32 0
+}
+
+define i32 @t2() nounwind ssp {
+entry:
+	br label %bb116
+
+bb116:		; preds = %bb116, %entry
+	%mbPartIdx.1.reg2mem.0 = phi i8 [ %3, %bb116 ], [ 0, %entry ]		; <i8> [#uses=3]
+	%0 = and i8 %mbPartIdx.1.reg2mem.0, 1		; <i8> [#uses=1]
+	%1 = zext i8 %mbPartIdx.1.reg2mem.0 to i64		; <i64> [#uses=0]
+	%2 = zext i8 %0 to i32		; <i32> [#uses=0]
+	%3 = add i8 %mbPartIdx.1.reg2mem.0, 1		; <i8> [#uses=2]
+	%4 = icmp ugt i8 %3, 3		; <i1> [#uses=1]
+	br i1 %4, label %bb131, label %bb116
+
+bb131:		; preds = %bb116
+	unreachable
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2009-04-27-Floating.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-04-27-Floating.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-04-27-Floating.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-04-27-Floating.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR4086
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+declare void @foo()
+
+define void @test() {
+entry:
+        br label %loop_body
+
+loop_body:
+        %i = phi float [ %nexti, %loop_body ], [ 0.0, %entry ]
+        tail call void @foo()
+        %nexti = fadd float %i, 1.0
+        ; CHECK: icmp ne i32 %{{[a-zA-Z$._0-9]+}}, 2
+        %less = fcmp olt float %nexti, 2.0
+        br i1 %less, label %loop_body, label %done
+
+done:
+        ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt < %s -indvars
+; PR4258
+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-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+
+define void @0(i32*, i32*, i32, i32) nounwind {
+	br i1 false, label %bb.nph1.preheader, label %.outer._crit_edge
+
+bb.nph1.preheader:		; preds = %4
+	%smax = select i1 false, i32 -1, i32 0		; <i32> [#uses=1]
+	%tmp12 = sub i32 0, %smax		; <i32> [#uses=1]
+	br label %bb.nph1
+
+bb.nph1:		; preds = %.outer, %bb.nph1.preheader
+	br i1 undef, label %bb.nph3.preheader, label %.outer
+
+bb.nph3.preheader:		; preds = %bb.nph1
+	br label %bb.nph3
+
+bb.nph3:		; preds = %bb.nph3, %bb.nph3.preheader
+	%indvar7 = phi i32 [ %indvar.next8, %bb.nph3 ], [ 0, %bb.nph3.preheader ]		; <i32> [#uses=3]
+	%tmp9 = mul i32 %indvar7, -1		; <i32> [#uses=1]
+	%tmp13 = add i32 %tmp9, %tmp12		; <i32> [#uses=1]
+	%tmp14 = add i32 %tmp13, -2		; <i32> [#uses=1]
+	%5 = icmp sgt i32 %tmp14, 0		; <i1> [#uses=1]
+	%indvar.next8 = add i32 %indvar7, 1		; <i32> [#uses=1]
+	br i1 %5, label %bb.nph3, label %.outer.loopexit
+
+.outer.loopexit:		; preds = %bb.nph3
+	%indvar7.lcssa = phi i32 [ %indvar7, %bb.nph3 ]		; <i32> [#uses=0]
+	br label %.outer
+
+.outer:		; preds = %.outer.loopexit, %bb.nph1
+	br i1 undef, label %bb.nph1, label %.outer._crit_edge.loopexit
+
+.outer._crit_edge.loopexit:		; preds = %.outer
+	br label %.outer._crit_edge
+
+.outer._crit_edge:		; preds = %.outer._crit_edge.loopexit, %4
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; Test WidenIV::GetExtendedOperandRecurrence.
+; %add, %sub and %mul should be extended to i64 because it is nsw, even though its
+; sext cannot be hoisted outside the loop.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+declare void @use(i64 %x)
+
+define void @test() nounwind {
+entry:
+  br i1 undef, label %for.body11, label %for.end285
+
+for.body11:                                       ; preds = %entry
+  %shl = shl i32 1, 1
+  %shl132 = shl i32 %shl, 1
+  br label %for.body153
+
+for.body153:                                      ; preds = %for.body153, %for.body11
+  br i1 undef, label %for.body170, label %for.body153
+
+; CHECK: add nuw nsw i64 %indvars.iv, 1
+; CHECK: sub nsw i64 %indvars.iv, 2
+; CHECK: sub nsw i64 4, %indvars.iv
+; CHECK: mul nsw i64 %indvars.iv, 8
+for.body170:                                      ; preds = %for.body170, %for.body153
+  %i2.19 = phi i32 [ %add249, %for.body170 ], [ 0, %for.body153 ]
+
+  %add = add nsw i32 %i2.19, 1
+  %add.idxprom = sext i32 %add to i64
+  call void @use(i64 %add.idxprom)
+
+  %sub = sub nsw i32 %i2.19, 2
+  %sub.idxprom = sext i32 %sub to i64
+  call void @use(i64 %sub.idxprom)
+
+  %sub.neg = sub nsw i32 4, %i2.19
+  %sub.neg.idxprom = sext i32 %sub.neg to i64
+  call void @use(i64 %sub.neg.idxprom)
+
+  %mul = mul nsw i32 %i2.19, 8
+  %mul.idxprom = sext i32 %mul to i64
+  call void @use(i64 %mul.idxprom)
+
+  %add249 = add nsw i32 %i2.19, %shl132
+  br label %for.body170
+for.end285:                                       ; preds = %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-09-19-vectoriv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR10946: Vector IVs are not SCEVable.
+; CHECK-NOT: phi
+define void @test() nounwind {
+allocas:
+  br i1 undef, label %cif_done, label %for_loop398
+
+cif_done:                                         ; preds = %allocas
+  ret void
+
+for_loop398:                                      ; preds = %for_loop398, %allocas
+  %storemerge35 = phi <4 x i32> [ %storemerge, %for_loop398 ], [ undef, %allocas ]
+  %bincmp431 = icmp sge <4 x i32> %storemerge35, <i32 5, i32 5, i32 5, i32 5>
+  %storemerge = bitcast <4 x float> undef to <4 x i32>
+  br label %for_loop398
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-09-27-hoistsext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; Test indvars' ability to hoist new sext created by WidenIV.
+; From ffbench.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+define internal double @fourn(double* %data, i32 %x, i32 %y, i32 %n) nounwind {
+; CHECK: entry:
+; CHECK: sext
+; CHECK: sext
+entry:
+  br label %for.body
+
+; CHECK: for.body:
+; CHECK-NOT: sext
+; CHECK: br
+for.body:
+  %i2.115 = phi i32 [ 0, %entry ], [ %add249, %for.body ]
+  %add174 = add nsw i32 %i2.115, %x
+  %idxprom177 = sext i32 %add174 to i64
+  %arrayidx179 = getelementptr inbounds double, double* %data, i64 %idxprom177
+  %tmp180 = load double, double* %arrayidx179, align 8
+  %add249 = add nsw i32 %i2.115, %y
+  %cmp168 = icmp sgt i32 %add249, %n
+  br i1 %cmp168, label %exit, label %for.body
+
+exit:
+  ret double %tmp180
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; rdar://10359193: assert "IndVar type must match IVInit type"
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
+target triple = "thumbv7-apple-darwin"
+
+; CHECK-LABEL: @test(
+; CHECK: if.end.i126:
+; CHECK: %exitcond = icmp ne i8* %incdec.ptr.i, null
+define void @test() nounwind {
+entry:
+  br label %while.cond
+
+while.cond:
+  br i1 undef, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  br i1 undef, label %if.then165, label %while.cond
+
+if.then165:                                       ; preds = %while.body
+  br i1 undef, label %while.cond, label %for.body.lr.ph.i81
+
+for.body.lr.ph.i81:                               ; preds = %if.then165
+  br label %for.body.i86
+
+for.body.i86:                                     ; preds = %for.end.i129, %for.body.lr.ph.i81
+  %cmp196.i = icmp ult i32 0, undef
+  br i1 %cmp196.i, label %for.body21.lr.ph.i, label %for.end.i129
+
+for.body21.lr.ph.i:                               ; preds = %for.body.i86
+  br label %for.body21.i
+
+for.body21.i:
+  %destYPixelPtr.010.i = phi i8* [ null, %for.body21.lr.ph.i ], [ %incdec.ptr.i, %if.end.i126 ]
+  %x.09.i = phi i32 [ 0, %for.body21.lr.ph.i ], [ %inc.i125, %if.end.i126 ]
+  br i1 undef, label %if.end.i126, label %if.else.i124
+
+if.else.i124:                                     ; preds = %for.body21.i
+  store i8 undef, i8* %destYPixelPtr.010.i, align 1
+  br label %if.end.i126
+
+if.end.i126:                                      ; preds = %if.else.i124, %for.body21.i
+  %incdec.ptr.i = getelementptr inbounds i8, i8* %destYPixelPtr.010.i, i32 1
+  %inc.i125 = add i32 %x.09.i, 1
+  %cmp19.i = icmp ult i32 %inc.i125, undef
+  br i1 %cmp19.i, label %for.body21.i, label %for.end.i129
+
+for.end.i129:                                     ; preds = %if.end.i126, %for.body.i86
+  br i1 undef, label %for.body.i86, label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  br label %bail
+
+bail:                                             ; preds = %while.end, %lor.lhs.false44, %lor.lhs.false41, %if.end29, %if.end
+  unreachable
+
+return:                                           ; preds = %lor.lhs.false20, %lor.lhs.false12, %lor.lhs.false, %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,144 @@
+; RUN: opt < %s -indvars -S "-data-layout=e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" | FileCheck %s
+; RUN: opt < %s -indvars -S "-data-layout=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-f80:128:128-n8:16:32" | FileCheck %s
+;
+; PR11279: Assertion !IVLimit->getType()->isPointerTy()
+;
+; Test LinearFunctionTestReplace of a pointer-type loop counter. Note
+; that BECount may or may not be a pointer type. A pointer type
+; BECount doesn't really make sense, but that's what falls out of
+; SCEV. Since it's an i8*, it has unit stride so we never adjust the
+; SCEV expression in a way that would convert it to an integer type.
+
+; CHECK-LABEL: @testnullptrptr(
+; CHECK: loop:
+; CHECK: icmp ne
+define i8 @testnullptrptr(i8* %buf, i8* %end) nounwind {
+  br label %loopguard
+
+loopguard:
+  %guard = icmp ult i8* null, %end
+  br i1 %guard, label %preheader, label %exit
+
+preheader:
+  br label %loop
+
+loop:
+  %p.01.us.us = phi i8* [ null, %preheader ], [ %gep, %loop ]
+  %s = phi i8 [0, %preheader], [%snext, %loop]
+  %gep = getelementptr inbounds i8, i8* %p.01.us.us, i64 1
+  %snext = load i8, i8* %gep
+  %cmp = icmp ult i8* %gep, %end
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %ret = phi i8 [0, %loopguard], [%snext, %loop]
+  ret i8 %ret
+}
+
+; CHECK-LABEL: @testptrptr(
+; CHECK: loop:
+; CHECK: icmp ne
+define i8 @testptrptr(i8* %buf, i8* %end) nounwind {
+  br label %loopguard
+
+loopguard:
+  %guard = icmp ult i8* %buf, %end
+  br i1 %guard, label %preheader, label %exit
+
+preheader:
+  br label %loop
+
+loop:
+  %p.01.us.us = phi i8* [ %buf, %preheader ], [ %gep, %loop ]
+  %s = phi i8 [0, %preheader], [%snext, %loop]
+  %gep = getelementptr inbounds i8, i8* %p.01.us.us, i64 1
+  %snext = load i8, i8* %gep
+  %cmp = icmp ult i8* %gep, %end
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %ret = phi i8 [0, %loopguard], [%snext, %loop]
+  ret i8 %ret
+}
+
+; CHECK-LABEL: @testnullptrint(
+; CHECK: loop:
+; CHECK: icmp ne
+define i8 @testnullptrint(i8* %buf, i8* %end) nounwind {
+  br label %loopguard
+
+loopguard:
+  %bi = ptrtoint i8* %buf to i32
+  %ei = ptrtoint i8* %end to i32
+  %cnt = sub i32 %ei, %bi
+  %guard = icmp ult i32 0, %cnt
+  br i1 %guard, label %preheader, label %exit
+
+preheader:
+  br label %loop
+
+loop:
+  %p.01.us.us = phi i8* [ null, %preheader ], [ %gep, %loop ]
+  %iv = phi i32 [ 0, %preheader ], [ %ivnext, %loop ]
+  %s = phi i8 [0, %preheader], [%snext, %loop]
+  %gep = getelementptr inbounds i8, i8* %p.01.us.us, i64 1
+  %snext = load i8, i8* %gep
+  %ivnext = add i32 %iv, 1
+  %cmp = icmp ult i32 %ivnext, %cnt
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %ret = phi i8 [0, %loopguard], [%snext, %loop]
+  ret i8 %ret
+}
+
+; CHECK-LABEL: @testptrint(
+; CHECK: loop:
+; CHECK: icmp ne
+define i8 @testptrint(i8* %buf, i8* %end) nounwind {
+  br label %loopguard
+
+loopguard:
+  %bi = ptrtoint i8* %buf to i32
+  %ei = ptrtoint i8* %end to i32
+  %cnt = sub i32 %ei, %bi
+  %guard = icmp ult i32 %bi, %cnt
+  br i1 %guard, label %preheader, label %exit
+
+preheader:
+  br label %loop
+
+loop:
+  %p.01.us.us = phi i8* [ %buf, %preheader ], [ %gep, %loop ]
+  %iv = phi i32 [ %bi, %preheader ], [ %ivnext, %loop ]
+  %s = phi i8 [0, %preheader], [%snext, %loop]
+  %gep = getelementptr inbounds i8, i8* %p.01.us.us, i64 1
+  %snext = load i8, i8* %gep
+  %ivnext = add i32 %iv, 1
+  %cmp = icmp ult i32 %ivnext, %cnt
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %ret = phi i8 [0, %loopguard], [%snext, %loop]
+  ret i8 %ret
+}
+
+; IV and BECount have two different pointer types here.
+define void @testnullptr([512 x i8]* %base) nounwind {
+entry:
+  %add.ptr1603 = getelementptr [512 x i8], [512 x i8]* %base, i64 0, i64 512
+  br label %preheader
+
+preheader:
+  %cmp1604192 = icmp ult i8* undef, %add.ptr1603
+  br i1 %cmp1604192, label %for.body, label %for.end1609
+
+for.body:
+  %r.17193 = phi i8* [ %incdec.ptr1608, %for.body ], [ null, %preheader ]
+  %incdec.ptr1608 = getelementptr i8, i8* %r.17193, i64 1
+  %cmp1604 = icmp ult i8* %incdec.ptr1608, %add.ptr1603
+  br i1 %cmp1604, label %for.body, label %for.end1609
+
+for.end1609:
+  unreachable
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-11-15-multiexit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-11-15-multiexit.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-11-15-multiexit.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-11-15-multiexit.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+;
+; Prior to the fix for PR11375, indvars would replace %firstIV with a
+; loop-invariant gep computed in the preheader. This was incorrect
+; because it was based on the minimum "ExitNotTaken" count. If the
+; final loop test is skipped (odd number of elements) then the early
+; exit would be taken and the loop invariant value would be incorrect.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-darwin"
+
+; CHECK: if.end:
+; CHECK: phi i32* [ %first.lcssa, %early.exit ]
+define i32 @test(i32* %first, i32* %last) uwtable ssp {
+entry:
+  br i1 undef, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  br i1 undef, label %if.end, label %do.body
+
+do.body:                                          ; preds = %if.else, %if.then
+  %firstIV = phi i32* [ %incdec.ptr2, %if.else ], [ %first, %if.then ]
+  %incdec.ptr1 = getelementptr inbounds i32, i32* %firstIV, i64 1
+  %cmp1 = icmp eq i32* %incdec.ptr1, %last
+  br i1 %cmp1, label %early.exit, label %if.else
+
+if.else:                                        ; preds = %do.body
+  %incdec.ptr2 = getelementptr inbounds i32, i32* %firstIV, i64 2
+  %cmp2 = icmp eq i32* %incdec.ptr2, %last
+  br i1 %cmp2, label %if.end, label %do.body
+
+early.exit:
+  %first.lcssa = phi i32* [ %firstIV, %do.body ]
+  br label %if.end
+
+if.end:
+  %tmp = phi i32* [ %first.lcssa, %early.exit ], [ %first, %if.then ], [ %first, %entry ], [ undef, %if.else ]
+  %val = load i32, i32* %tmp
+  ret i32 %val
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2011-11-17-selfphi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-11-17-selfphi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-11-17-selfphi.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-11-17-selfphi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR11350: Check that SimplifyIndvar handles a cycle of useless self-phis.
+
+; CHECK-LABEL: @test(
+; CHECK-NOT: lcssa = phi
+define void @test() nounwind {
+entry:
+  br label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %entry
+  br label %for.cond.outer
+
+for.cond.outer:                                   ; preds = %for.cond.preheader, %for.end
+  %p_41.addr.0.ph = phi i32 [ %p_41.addr.1.lcssa, %for.end ], [ 1, %for.cond.preheader ]
+  br label %for.cond
+
+for.cond:
+  br i1 true, label %for.end, label %for.ph
+
+for.ph:                                   ; preds = %for.cond4.preheader
+  br label %for.end
+
+for.end:
+  %p_41.addr.1.lcssa = phi i32 [ undef, %for.ph ], [ %p_41.addr.0.ph, %for.cond ]
+  %p_68.lobit.i = lshr i32 %p_41.addr.1.lcssa, 31
+  %cmp7 = icmp eq i32 %p_41.addr.1.lcssa, 0
+  %conv8 = zext i1 %cmp7 to i32
+  br label %for.cond.outer
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2012-07-17-lftr-undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2012-07-17-lftr-undef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2012-07-17-lftr-undef.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2012-07-17-lftr-undef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR13371: indvars pass incorrectly substitutes 'undef' values
+;
+; LFTR should not user %undef as the loop counter.
+; CHECK-LABEL: @test(
+; CHECK-NOT: icmp{{.*}}undef
+ at .str3 = private constant [6 x i8] c"%lld\0A\00", align 1
+declare i32 @printf(i8* noalias nocapture, ...) nounwind
+define i64 @test() nounwind {
+func_start:
+  br label %block9
+block9:                                           ; preds = %block9,%func_start
+  %undef = phi i64 [ %next_undef, %block9 ], [ undef, %func_start ]
+  %iter = phi i64 [ %next_iter, %block9 ], [ 1, %func_start ]
+  %next_iter = add nsw i64 %iter, 1
+  %0 = tail call i32 (i8*, ...) @printf(i8* noalias nocapture getelementptr inbounds ([6 x i8], [6 x i8]* @.str3, i64 0, i64 0), i64 %next_iter, i64 %undef)
+  %next_undef = add nsw i64 %undef, 1
+  %_tmp_3 = icmp slt i64 %next_iter, 100
+  br i1 %_tmp_3, label %block9, label %exit
+exit:                                             ; preds = %block9
+  ret i64 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/2012-10-19-congruent-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2012-10-19-congruent-constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2012-10-19-congruent-constant.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2012-10-19-congruent-constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; PR12627
+define void @test1(i32 %x) nounwind uwtable ssp {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %phi1 = phi i1 [ false, %entry ], [ %cmpa, %for.body ]
+  %phi2 = phi i1 [ false, %entry ], [ %cmpb, %for.body ]
+  %i.07 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  tail call void @aux(i1 %phi1, i1 %phi2) nounwind
+  %cmpa = icmp sgt i32 %i.07, 200
+  %cmpb = icmp sgt i32 %i.07, 100
+  %inc = add nsw i32 %i.07, 1
+  %exitcond = icmp eq i32 %inc, 100
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+  ret void
+
+; CHECK-LABEL: @test1(
+; CHECK-NOT: phi i1
+; CHECK: call void @aux(i1 false, i1 false)
+}
+
+declare void @aux(i1, i1)

Added: llvm/trunk/test/Transforms/IndVarSimplify/2014-06-21-congruent-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2014-06-21-congruent-constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/2014-06-21-congruent-constant.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/2014-06-21-congruent-constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt -S -loop-unswitch -instcombine -indvars < %s | FileCheck %s
+
+; This used to crash in SCEVExpander when there were congruent phis with and
+; undef incoming value from the loop header. The -loop-unswitch -instcombine is
+; necessary to create just this pattern, which is essentially a nop and gets
+; folded away aggressively if spelled out in IR directly.
+; PR 20093
+
+ at c = external global i32**, align 8
+
+define void @test1() {
+entry:
+  br i1 undef, label %for.end12, label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %entry
+  %0 = load i32**, i32*** @c, align 8
+  %1 = load i32*, i32** %0, align 8
+  %2 = load i32, i32* %1, align 4
+  br label %for.body
+
+for.body:                                         ; preds = %for.cond.backedge, %for.body9.us, %for.cond.preheader
+  %3 = phi i32* [ %1, %for.cond.preheader ], [ %3, %for.cond.backedge ], [ %6, %for.body9.us ]
+  %4 = phi i32 [ %2, %for.cond.preheader ], [ undef, %for.cond.backedge ], [ %7, %for.body9.us ]
+  %i.024 = phi i32 [ 0, %for.cond.preheader ], [ %inc, %for.cond.backedge ], [ 0, %for.body9.us ]
+  %tobool1 = icmp eq i32 %4, 0
+  br i1 %tobool1, label %if.end, label %for.cond.backedge
+
+if.end:                                           ; preds = %for.body
+  %5 = load i32, i32* %3, align 4
+  %tobool4 = icmp eq i32 %5, 0
+  br i1 %tobool4, label %for.cond3, label %for.body9.preheader
+
+for.body9.preheader:                              ; preds = %if.end
+  %tobool8 = icmp eq i32 %i.024, 1
+  br i1 %tobool8, label %for.body9.us, label %for.body9
+
+for.body9.us:                                     ; preds = %for.body9.preheader
+  %6 = load i32*, i32** undef, align 8
+  %7 = load i32, i32* %6, align 4
+  br label %for.body
+
+for.cond3:                                        ; preds = %for.cond3, %if.end
+  br label %for.cond3
+
+for.body9:                                        ; preds = %for.body9, %for.body9.preheader
+  br label %for.body9
+
+for.cond.backedge:                                ; preds = %for.body
+  %inc = add nsw i32 %i.024, 1
+  br i1 false, label %for.body, label %for.end12
+
+for.end12:                                        ; preds = %for.cond.backedge, %entry
+  ret void
+
+; CHECK-LABEL: @test1
+; CHECK-NOT: phi
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2 @@
+if not 'AMDGPU' in config.root.targets:
+    config.unsupported = True

Added: llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/no-widen-to-i64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/no-widen-to-i64.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/no-widen-to-i64.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/AMDGPU/no-widen-to-i64.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,98 @@
+; RUN: opt -S -mtriple=amdgcn-unknown-amdhsa -indvars %s | FileCheck %s
+
+; Bug 21148
+
+; Induction variables should not be widened for 64-bit integers,
+; despite being a legal type.
+;
+; The cost of basic arithmetic instructions on a 64-bit integer are
+; twice as expensive as that on a 32-bit integer, or split into 2
+; 32-bit components.
+
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
+
+; CHECK-LABEL: @indvar_32_bit(
+; CHECK-NOT: sext i32
+; CHECK: phi i32
+define amdgpu_kernel void @indvar_32_bit(i32 %n, i32* nocapture %output) {
+entry:
+  %cmp5 = icmp sgt i32 %n, 0
+  br i1 %cmp5, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %i.06 = phi i32 [ 0, %for.body.preheader ], [ %add, %for.body ]
+  %mul = mul nsw i32 %i.06, %i.06
+  %tmp0 = sext i32 %i.06 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %output, i64 %tmp0
+  store i32 %mul, i32* %arrayidx, align 4
+  %add = add nsw i32 %i.06, 3
+  %cmp = icmp slt i32 %add, %n
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void
+}
+
+; CHECK-LABEL: @no_promote_i32(
+; CHECK-NOT: sext i32
+; CHECK: br
+; CHECK-NOT: shl i64
+; CHECK-NOT: ashr i64
+; CHECK-NOT: mul nsw i64
+; CHECK-NOT: add nsw i64
+define amdgpu_kernel void @no_promote_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) {
+entry:
+  br label %for.body
+
+for.body:
+  %inc = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
+  %tmp0 = add i32 %a, %inc
+  %shl = shl i32 %inc, 8
+  %shr = ashr exact i32 %shl, 8
+  %mul = mul nsw i32 %shr, %a
+  %add = add nsw i32 %mul, %b
+  %tmp1 = sext i32 %add to i64
+  %arrayidx1 = getelementptr inbounds i32, i32 addrspace(1)* %out, i64 %tmp1
+  store i32 %tmp0, i32 addrspace(1)* %arrayidx1, align 4
+  %inc.i = add nsw i32 %inc, 1
+  %cmp = icmp slt i32 %inc.i, 16
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+
+; FIXME: This should really be promoted to i64, since it will need to
+; be legalized anyway.
+
+; CHECK-LABEL: @indvar_48_bit(
+define amdgpu_kernel void @indvar_48_bit(i48 %n, i48* nocapture %output) {
+entry:
+  %cmp5 = icmp sgt i48 %n, 0
+  br i1 %cmp5, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %i.06 = phi i48 [ 0, %for.body.preheader ], [ %add, %for.body ]
+  %mul = mul nsw i48 %i.06, %i.06
+  %tmp0 = sext i48 %i.06 to i64
+  %arrayidx = getelementptr inbounds i48, i48* %output, i64 %tmp0
+  store i48 %mul, i48* %arrayidx, align 4
+  %add = add nsw i48 %i.06, 3
+  %cmp = icmp slt i48 %add, %n
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2 @@
+if not 'NVPTX' in config.root.targets:
+    config.unsupported = True

Added: llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target triple = "nvptx64-unknown-unknown"
+
+; For the nvptx64 architecture, the cost of an arithmetic instruction on a
+; 64-bit integer is twice as expensive as that on a 32-bit integer, because the
+; hardware needs to simulate a 64-bit integer using two 32-bit integers.
+; Therefore, in this particular architecture, we should not widen induction
+; variables to 64-bit integers even though i64 is a legal type in the 64-bit
+; PTX ISA.
+
+define void @indvar_32_bit(i32 %n, i32* nocapture %output) {
+; CHECK-LABEL: @indvar_32_bit
+entry:
+  %cmp5 = icmp sgt i32 %n, 0
+  br i1 %cmp5, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %i.06 = phi i32 [ 0, %for.body.preheader ], [ %add, %for.body ]
+; CHECK: phi i32
+  %mul = mul nsw i32 %i.06, %i.06
+  %0 = sext i32 %i.06 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %output, i64 %0
+  store i32 %mul, i32* %arrayidx, align 4
+  %add = add nsw i32 %i.06, 3
+  %cmp = icmp slt i32 %add, %n
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/ada-loops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,99 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+;
+; PR1301
+
+; Do a bunch of analysis and prove that the loops can use an i32 trip
+; count without casting.
+;
+; Note that all four functions should actually be converted to
+; memset. However, this test case validates indvars behavior.  We
+; 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.
+;
+
+; 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]
+	store i32 0, i32* %tmp46
+	br label %bb
+
+bb:		; preds = %bb, %bb.thread
+	%i.0.reg2mem.0 = phi i8 [ -128, %bb.thread ], [ %tmp8, %bb ]		; <i8> [#uses=1]
+	%tmp8 = add i8 %i.0.reg2mem.0, 1		; <i8> [#uses=3]
+	%tmp1 = sext i8 %tmp8 to i32		; <i32> [#uses=1]
+	%tmp3 = add i32 %tmp1, 128		; <i32> [#uses=1]
+	%tmp4 = getelementptr [256 x i32], [256 x i32]* %a, i32 0, i32 %tmp3		; <i32*> [#uses=1]
+	store i32 0, i32* %tmp4
+	%0 = icmp eq i8 %tmp8, 127		; <i1> [#uses=1]
+	br i1 %0, label %return, label %bb
+
+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]
+	store i32 0, i32* %tmp35
+	br label %bb
+
+bb:		; preds = %bb, %bb.thread
+	%i.0.reg2mem.0 = phi i8 [ 0, %bb.thread ], [ %tmp7, %bb ]		; <i8> [#uses=1]
+	%tmp7 = add i8 %i.0.reg2mem.0, 1		; <i8> [#uses=3]
+	%tmp1 = zext i8 %tmp7 to i32		; <i32> [#uses=1]
+	%tmp3 = getelementptr [256 x i32], [256 x i32]* %a, i32 0, i32 %tmp1		; <i32*> [#uses=1]
+	store i32 0, i32* %tmp3
+	%0 = icmp eq i8 %tmp7, -1		; <i1> [#uses=1]
+	br i1 %0, label %return, label %bb
+
+return:		; preds = %bb
+	ret void
+}
+
+define void @kinds__srangezero([21 x i32]* nocapture %a) nounwind {
+bb.thread:
+	br label %bb
+
+bb:		; preds = %bb, %bb.thread
+	%i.0.reg2mem.0 = phi i8 [ -10, %bb.thread ], [ %tmp7, %bb ]		; <i8> [#uses=2]
+	%tmp12 = sext i8 %i.0.reg2mem.0 to i32		; <i32> [#uses=1]
+	%tmp4 = add i32 %tmp12, 10		; <i32> [#uses=1]
+	%tmp5 = getelementptr [21 x i32], [21 x i32]* %a, i32 0, i32 %tmp4		; <i32*> [#uses=1]
+	store i32 0, i32* %tmp5
+	%tmp7 = add i8 %i.0.reg2mem.0, 1		; <i8> [#uses=2]
+	%0 = icmp sgt i8 %tmp7, 10		; <i1> [#uses=1]
+	br i1 %0, label %return, label %bb
+
+return:		; preds = %bb
+	ret void
+}
+
+define void @kinds__urangezero([21 x i32]* nocapture %a) nounwind {
+bb.thread:
+	br label %bb
+
+bb:		; preds = %bb, %bb.thread
+	%i.0.reg2mem.0 = phi i8 [ 10, %bb.thread ], [ %tmp7, %bb ]		; <i8> [#uses=2]
+	%tmp12 = sext i8 %i.0.reg2mem.0 to i32		; <i32> [#uses=1]
+	%tmp4 = add i32 %tmp12, -10		; <i32> [#uses=1]
+	%tmp5 = getelementptr [21 x i32], [21 x i32]* %a, i32 0, i32 %tmp4		; <i32*> [#uses=1]
+	store i32 0, i32* %tmp5
+	%tmp7 = add i8 %i.0.reg2mem.0, 1		; <i8> [#uses=2]
+	%0 = icmp sgt i8 %tmp7, 30		; <i1> [#uses=1]
+	br i1 %0, label %return, label %bb
+
+return:		; preds = %bb
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/ashr-tripcount.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/ashr-tripcount.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/ashr-tripcount.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/ashr-tripcount.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,109 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Indvars should be able to eliminate all of the sign extensions
+; inside the loop.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
+ at pow_2_tab = external constant [0 x float]		; <[0 x float]*> [#uses=1]
+ at pow_2_025_tab = external constant [0 x float]		; <[0 x float]*> [#uses=1]
+ at i_pow_2_tab = external constant [0 x float]		; <[0 x float]*> [#uses=1]
+ at i_pow_2_025_tab = external constant [0 x float]		; <[0 x float]*> [#uses=1]
+
+define void @foo(i32 %gain, i32 %noOfLines, i32* %quaSpectrum, float* %iquaSpectrum, float* %pow4_3_tab_ptr) nounwind {
+; CHECK-LABEL: @foo(
+; CHECK: sext
+; CHECK-NOT: sext
+entry:
+	%t0 = icmp slt i32 %gain, 0		; <i1> [#uses=1]
+	br i1 %t0, label %bb1, label %bb2
+
+bb1:		; preds = %entry
+	%t1 = sub i32 0, %gain		; <i32> [#uses=1]
+	%t2 = sub i32 0, %gain		; <i32> [#uses=1]
+	br label %bb2
+
+bb2:		; preds = %bb1, %entry
+	%pow_2_tab.pn = phi [0 x float]* [ @i_pow_2_tab, %bb1 ], [ @pow_2_tab, %entry ]		; <[0 x float]*> [#uses=1]
+	%.pn3.in.in = phi i32 [ %t1, %bb1 ], [ %gain, %entry ]		; <i32> [#uses=1]
+	%pow_2_025_tab.pn = phi [0 x float]* [ @i_pow_2_025_tab, %bb1 ], [ @pow_2_025_tab, %entry ]		; <[0 x float]*> [#uses=1]
+	%.pn2.in.in = phi i32 [ %t2, %bb1 ], [ %gain, %entry ]		; <i32> [#uses=1]
+	%.pn3.in = ashr i32 %.pn3.in.in, 2		; <i32> [#uses=1]
+	%.pn2.in = and i32 %.pn2.in.in, 3		; <i32> [#uses=1]
+	%.pn3 = sext i32 %.pn3.in to i64		; <i64> [#uses=1]
+	%.pn2 = zext i32 %.pn2.in to i64		; <i64> [#uses=1]
+	%.pn.in = getelementptr [0 x float], [0 x float]* %pow_2_tab.pn, i64 0, i64 %.pn3		; <float*> [#uses=1]
+	%.pn1.in = getelementptr [0 x float], [0 x float]* %pow_2_025_tab.pn, i64 0, i64 %.pn2		; <float*> [#uses=1]
+	%.pn = load float, float* %.pn.in		; <float> [#uses=1]
+	%.pn1 = load float, float* %.pn1.in		; <float> [#uses=1]
+	%invQuantizer.0 = fmul float %.pn, %.pn1		; <float> [#uses=4]
+	%t3 = ashr i32 %noOfLines, 2		; <i32> [#uses=1]
+	%t4 = icmp sgt i32 %t3, 0		; <i1> [#uses=1]
+	br i1 %t4, label %bb.nph, label %return
+
+bb.nph:		; preds = %bb2
+	%t5 = ashr i32 %noOfLines, 2		; <i32> [#uses=1]
+	br label %bb3
+
+bb3:		; preds = %bb4, %bb.nph
+	%i.05 = phi i32 [ %t49, %bb4 ], [ 0, %bb.nph ]		; <i32> [#uses=9]
+	%k.04 = phi i32 [ %t48, %bb4 ], [ 0, %bb.nph ]		; <i32> [#uses=1]
+	%t6 = sext i32 %i.05 to i64		; <i64> [#uses=1]
+	%t7 = getelementptr i32, i32* %quaSpectrum, i64 %t6		; <i32*> [#uses=1]
+	%t8 = load i32, i32* %t7, align 4		; <i32> [#uses=1]
+	%t9 = zext i32 %t8 to i64		; <i64> [#uses=1]
+	%t10 = getelementptr float, float* %pow4_3_tab_ptr, i64 %t9		; <float*> [#uses=1]
+	%t11 = load float, float* %t10, align 4		; <float> [#uses=1]
+	%t12 = or i32 %i.05, 1		; <i32> [#uses=1]
+	%t13 = sext i32 %t12 to i64		; <i64> [#uses=1]
+	%t14 = getelementptr i32, i32* %quaSpectrum, i64 %t13		; <i32*> [#uses=1]
+	%t15 = load i32, i32* %t14, align 4		; <i32> [#uses=1]
+	%t16 = zext i32 %t15 to i64		; <i64> [#uses=1]
+	%t17 = getelementptr float, float* %pow4_3_tab_ptr, i64 %t16		; <float*> [#uses=1]
+	%t18 = load float, float* %t17, align 4		; <float> [#uses=1]
+	%t19 = or i32 %i.05, 2		; <i32> [#uses=1]
+	%t20 = sext i32 %t19 to i64		; <i64> [#uses=1]
+	%t21 = getelementptr i32, i32* %quaSpectrum, i64 %t20		; <i32*> [#uses=1]
+	%t22 = load i32, i32* %t21, align 4		; <i32> [#uses=1]
+	%t23 = zext i32 %t22 to i64		; <i64> [#uses=1]
+	%t24 = getelementptr float, float* %pow4_3_tab_ptr, i64 %t23		; <float*> [#uses=1]
+	%t25 = load float, float* %t24, align 4		; <float> [#uses=1]
+	%t26 = or i32 %i.05, 3		; <i32> [#uses=1]
+	%t27 = sext i32 %t26 to i64		; <i64> [#uses=1]
+	%t28 = getelementptr i32, i32* %quaSpectrum, i64 %t27		; <i32*> [#uses=1]
+	%t29 = load i32, i32* %t28, align 4		; <i32> [#uses=1]
+	%t30 = zext i32 %t29 to i64		; <i64> [#uses=1]
+	%t31 = getelementptr float, float* %pow4_3_tab_ptr, i64 %t30		; <float*> [#uses=1]
+	%t32 = load float, float* %t31, align 4		; <float> [#uses=1]
+	%t33 = fmul float %t11, %invQuantizer.0		; <float> [#uses=1]
+	%t34 = sext i32 %i.05 to i64		; <i64> [#uses=1]
+	%t35 = getelementptr float, float* %iquaSpectrum, i64 %t34		; <float*> [#uses=1]
+	store float %t33, float* %t35, align 4
+	%t36 = or i32 %i.05, 1		; <i32> [#uses=1]
+	%t37 = fmul float %t18, %invQuantizer.0		; <float> [#uses=1]
+	%t38 = sext i32 %t36 to i64		; <i64> [#uses=1]
+	%t39 = getelementptr float, float* %iquaSpectrum, i64 %t38		; <float*> [#uses=1]
+	store float %t37, float* %t39, align 4
+	%t40 = or i32 %i.05, 2		; <i32> [#uses=1]
+	%t41 = fmul float %t25, %invQuantizer.0		; <float> [#uses=1]
+	%t42 = sext i32 %t40 to i64		; <i64> [#uses=1]
+	%t43 = getelementptr float, float* %iquaSpectrum, i64 %t42		; <float*> [#uses=1]
+	store float %t41, float* %t43, align 4
+	%t44 = or i32 %i.05, 3		; <i32> [#uses=1]
+	%t45 = fmul float %t32, %invQuantizer.0		; <float> [#uses=1]
+	%t46 = sext i32 %t44 to i64		; <i64> [#uses=1]
+	%t47 = getelementptr float, float* %iquaSpectrum, i64 %t46		; <float*> [#uses=1]
+	store float %t45, float* %t47, align 4
+	%t48 = add i32 %k.04, 1		; <i32> [#uses=2]
+	%t49 = add i32 %i.05, 4		; <i32> [#uses=1]
+	br label %bb4
+
+bb4:		; preds = %bb3
+	%t50 = icmp sgt i32 %t5, %t48		; <i1> [#uses=1]
+	br i1 %t50, label %bb3, label %bb4.return_crit_edge
+
+bb4.return_crit_edge:		; preds = %bb4
+	br label %return
+
+return:		; preds = %bb4.return_crit_edge, %bb2
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/avoid-i0.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,126 @@
+; RUN: opt < %s -indvars
+; PR4052
+; PR4054
+
+; Don't treat an and with 0 as a mask (trunc+zext).
+
+define i32 @int80(i8 signext %p_71) nounwind {
+entry:
+	br label %bb
+
+bb:		; preds = %bb6, %entry
+	%p_71_addr.0 = phi i8 [ %p_71, %entry ], [ %0, %bb6 ]		; <i8> [#uses=0]
+	br i1 undef, label %bb4, label %bb1
+
+bb1:		; preds = %bb
+	ret i32 0
+
+bb4:		; preds = %bb4, %bb
+	br i1 undef, label %bb6, label %bb4
+
+bb6:		; preds = %bb4
+	%0 = and i8 0, 0		; <i8> [#uses=1]
+	br label %bb
+}
+
+ at x = common global i32 0		; <i32*> [#uses=1]
+
+define signext i8 @safe_sub_func_int32_t_s_s(i32 %_si1, i8 signext %_si2) nounwind {
+entry:
+	%_si1_addr = alloca i32		; <i32*> [#uses=3]
+	%_si2_addr = alloca i8		; <i8*> [#uses=3]
+	%retval = alloca i32		; <i32*> [#uses=2]
+	%0 = alloca i32		; <i32*> [#uses=2]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	store i32 %_si1, i32* %_si1_addr
+	store i8 %_si2, i8* %_si2_addr
+	%1 = load i8, i8* %_si2_addr, align 1		; <i8> [#uses=1]
+	%2 = sext i8 %1 to i32		; <i32> [#uses=1]
+	%3 = load i32, i32* %_si1_addr, align 4		; <i32> [#uses=1]
+	%4 = xor i32 %2, %3		; <i32> [#uses=1]
+	%5 = load i8, i8* %_si2_addr, align 1		; <i8> [#uses=1]
+	%6 = sext i8 %5 to i32		; <i32> [#uses=1]
+	%7 = sub i32 7, %6		; <i32> [#uses=1]
+	%8 = load i32, i32* %_si1_addr, align 4		; <i32> [#uses=1]
+	%9 = shl i32 %8, %7		; <i32> [#uses=1]
+	%10 = and i32 %4, %9		; <i32> [#uses=1]
+	%11 = icmp slt i32 %10, 0		; <i1> [#uses=1]
+	%12 = zext i1 %11 to i32		; <i32> [#uses=1]
+	store i32 %12, i32* %0, align 4
+	%13 = load i32, i32* %0, align 4		; <i32> [#uses=1]
+	store i32 %13, i32* %retval, align 4
+	br label %return
+
+return:		; preds = %entry
+	%retval1 = load i32, i32* %retval		; <i32> [#uses=1]
+	%retval12 = trunc i32 %retval1 to i8		; <i8> [#uses=1]
+	ret i8 %retval12
+}
+
+define i32 @safe_sub_func_uint64_t_u_u(i32 %_ui1, i32 %_ui2) nounwind {
+entry:
+	%_ui1_addr = alloca i32		; <i32*> [#uses=2]
+	%_ui2_addr = alloca i32		; <i32*> [#uses=1]
+	%retval = alloca i32		; <i32*> [#uses=2]
+	%0 = alloca i32		; <i32*> [#uses=2]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	store i32 %_ui1, i32* %_ui1_addr
+	store i32 %_ui2, i32* %_ui2_addr
+	%1 = load i32, i32* %_ui1_addr, align 4		; <i32> [#uses=1]
+	%2 = sub i32 %1, 1		; <i32> [#uses=1]
+	store i32 %2, i32* %0, align 4
+	%3 = load i32, i32* %0, align 4		; <i32> [#uses=1]
+	store i32 %3, i32* %retval, align 4
+	br label %return
+
+return:		; preds = %entry
+	%retval1 = load i32, i32* %retval		; <i32> [#uses=1]
+	ret i32 %retval1
+}
+
+define void @int87(i8 signext %p_48, i8 signext %p_49) nounwind {
+entry:
+	%p_48_addr = alloca i8		; <i8*> [#uses=1]
+	%p_49_addr = alloca i8		; <i8*> [#uses=1]
+	%l_52 = alloca i32		; <i32*> [#uses=7]
+	%vol.0 = alloca i32		; <i32*> [#uses=1]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	store i8 %p_48, i8* %p_48_addr
+	store i8 %p_49, i8* %p_49_addr
+	br label %bb4
+
+bb:		; preds = %bb4
+	%0 = load volatile i32, i32* @x, align 4		; <i32> [#uses=1]
+	store i32 %0, i32* %vol.0, align 4
+	store i32 0, i32* %l_52, align 4
+	br label %bb2
+
+bb1:		; preds = %bb2
+	%1 = load i32, i32* %l_52, align 4		; <i32> [#uses=1]
+	%2 = call i32 @safe_sub_func_uint64_t_u_u(i32 %1, i32 1) nounwind		; <i32> [#uses=1]
+	store i32 %2, i32* %l_52, align 4
+	br label %bb2
+
+bb2:		; preds = %bb1, %bb
+	%3 = load i32, i32* %l_52, align 4		; <i32> [#uses=1]
+	%4 = icmp eq i32 %3, 0		; <i1> [#uses=1]
+	br i1 %4, label %bb1, label %bb3
+
+bb3:		; preds = %bb2
+	%5 = load i32, i32* %l_52, align 4		; <i32> [#uses=1]
+	%6 = call signext i8 @safe_sub_func_int32_t_s_s(i32 %5, i8 signext 1) nounwind		; <i8> [#uses=1]
+	%7 = sext i8 %6 to i32		; <i32> [#uses=1]
+	store i32 %7, i32* %l_52, align 4
+	br label %bb4
+
+bb4:		; preds = %bb3, %entry
+	%8 = load i32, i32* %l_52, align 4		; <i32> [#uses=1]
+	%9 = icmp ne i32 %8, 0		; <i1> [#uses=1]
+	br i1 %9, label %bb, label %bb5
+
+bb5:		; preds = %bb4
+	br label %return
+
+return:		; preds = %bb5
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/backedge-on-min-max.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/backedge-on-min-max.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/backedge-on-min-max.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/backedge-on-min-max.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,454 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; RUN: opt -lcssa -loop-simplify -S < %s | opt -S -passes='require<targetir>,require<scalar-evolution>,require<domtree>,loop(indvars)'
+
+;; --- signed ---
+
+define void @min.signed.1(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @min.signed.1
+ entry:
+  %smin.cmp = icmp slt i32 %a_len, %n
+  %smin = select i1 %smin.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp slt i32 0, %smin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp slt i32 %idx, %a_len
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp slt i32 %idx.inc, %smin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @min.signed.2(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @min.signed.2
+ entry:
+  %smin.cmp = icmp slt i32 %a_len, %n
+  %smin = select i1 %smin.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp slt i32 0, %smin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp sgt i32 %a_len, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp slt i32 %idx.inc, %smin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @min.signed.3(i32* %a, i32 %n) {
+; CHECK-LABEL: @min.signed.3
+ entry:
+  %smin.cmp = icmp slt i32 42, %n
+  %smin = select i1 %smin.cmp, i32 42, i32 %n
+  %entry.cond = icmp slt i32 0, %smin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp slt i32 %idx, 42
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp slt i32 %idx.inc, %smin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @min.signed.4(i32* %a, i32 %n) {
+; CHECK-LABEL: @min.signed.4
+ entry:
+  %smin.cmp = icmp slt i32 42, %n
+  %smin = select i1 %smin.cmp, i32 42, i32 %n
+  %entry.cond = icmp slt i32 0, %smin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp sgt i32 42, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp slt i32 %idx.inc, %smin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.signed.1(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @max.signed.1
+ entry:
+  %smax.cmp = icmp sgt i32 %a_len, %n
+  %smax = select i1 %smax.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp sgt i32 0, %smax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp sgt i32 %idx, %a_len
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp sgt i32 %idx.inc, %smax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.signed.2(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @max.signed.2
+ entry:
+  %smax.cmp = icmp sgt i32 %a_len, %n
+  %smax = select i1 %smax.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp sgt i32 0, %smax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp slt i32 %a_len, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp sgt i32 %idx.inc, %smax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.signed.3(i32* %a, i32 %n, i32 %init) {
+; CHECK-LABEL: @max.signed.3
+ entry:
+  %smax.cmp = icmp sgt i32 42, %n
+  %smax = select i1 %smax.cmp, i32 42, i32 %n
+  %entry.cond = icmp sgt i32 %init, %smax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp sgt i32 %idx, 42
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp sgt i32 %idx.inc, %smax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.signed.4(i32* %a, i32 %n, i32 %init) {
+; CHECK-LABEL: @max.signed.4
+ entry:
+  %smax.cmp = icmp sgt i32 42, %n
+  %smax = select i1 %smax.cmp, i32 42, i32 %n
+  %entry.cond = icmp sgt i32 %init, %smax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp slt i32 42, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp sgt i32 %idx.inc, %smax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+;; --- unsigned ---
+
+define void @min.unsigned.1(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @min.unsigned.1
+ entry:
+  %umin.cmp = icmp ult i32 %a_len, %n
+  %umin = select i1 %umin.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp ult i32 5, %umin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ult i32 %idx, %a_len
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ult i32 %idx.inc, %umin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @min.unsigned.2(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @min.unsigned.2
+ entry:
+  %umin.cmp = icmp ult i32 %a_len, %n
+  %umin = select i1 %umin.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp ult i32 5, %umin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ugt i32 %a_len, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ult i32 %idx.inc, %umin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @min.unsigned.3(i32* %a, i32 %n) {
+; CHECK-LABEL: @min.unsigned.3
+ entry:
+  %umin.cmp = icmp ult i32 42, %n
+  %umin = select i1 %umin.cmp, i32 42, i32 %n
+  %entry.cond = icmp ult i32 5, %umin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ult i32 %idx, 42
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ult i32 %idx.inc, %umin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @min.unsigned.4(i32* %a, i32 %n) {
+; CHECK-LABEL: @min.unsigned.4
+ entry:
+  %umin.cmp = icmp ult i32 42, %n
+  %umin = select i1 %umin.cmp, i32 42, i32 %n
+  %entry.cond = icmp ult i32 5, %umin
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ugt i32 42, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ult i32 %idx.inc, %umin
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.unsigned.1(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @max.unsigned.1
+ entry:
+  %umax.cmp = icmp ugt i32 %a_len, %n
+  %umax = select i1 %umax.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp ugt i32 5, %umax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ugt i32 %idx, %a_len
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ugt i32 %idx.inc, %umax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.unsigned.2(i32* %a, i32 %a_len, i32 %n) {
+; CHECK-LABEL: @max.unsigned.2
+ entry:
+  %umax.cmp = icmp ugt i32 %a_len, %n
+  %umax = select i1 %umax.cmp, i32 %a_len, i32 %n
+  %entry.cond = icmp ugt i32 5, %umax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ult i32 %a_len, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ugt i32 %idx.inc, %umax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.unsigned.3(i32* %a, i32 %n, i32 %init) {
+; CHECK-LABEL: @max.unsigned.3
+ entry:
+  %umax.cmp = icmp ugt i32 42, %n
+  %umax = select i1 %umax.cmp, i32 42, i32 %n
+  %entry.cond = icmp ugt i32 %init, %umax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ugt i32 %idx, 42
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ugt i32 %idx.inc, %umax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}
+
+define void @max.unsigned.4(i32* %a, i32 %n, i32 %init) {
+; CHECK-LABEL: @max.unsigned.4
+ entry:
+  %umax.cmp = icmp ugt i32 42, %n
+  %umax = select i1 %umax.cmp, i32 42, i32 %n
+  %entry.cond = icmp ugt i32 %init, %umax
+  br i1 %entry.cond, label %loop, label %exit
+
+ loop:
+  %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ]
+  %idx.inc = add i32 %idx, 1
+  %in.bounds = icmp ult i32 42, %idx
+  br i1 %in.bounds, label %ok, label %latch
+; CHECK: br i1 true, label %ok, label %latch
+
+ ok:
+  %addr = getelementptr i32, i32* %a, i32 %idx
+  store i32 %idx, i32* %addr
+  br label %latch
+
+ latch:
+  %be.cond = icmp ugt i32 %idx.inc, %umax
+  br i1 %be.cond, label %loop, label %exit
+
+ exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/bec-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/bec-cmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/bec-cmp.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/bec-cmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define void @foo(i32* nocapture %a, i32* nocapture readonly %b, i32 signext %n) #0 {
+entry:
+
+; CHECK-LABEL: @foo
+
+  %cmp.10 = icmp sgt i32 %n, 0
+  br i1 %cmp.10, label %for.body.lr.ph, label %for.cond.cleanup
+
+for.body.lr.ph:                                   ; preds = %entry
+  br label %for.body
+
+for.cond.for.cond.cleanup_crit_edge:              ; preds = %for.inc
+  br label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond.for.cond.cleanup_crit_edge, %entry
+  ret void
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.inc
+  %i.011 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
+  %cmp1 = icmp sgt i32 %i.011, %n
+  br i1 %cmp1, label %if.then, label %for.inc
+
+; CHECK-NOT: br i1 %cmp1, label %if.then, label %for.inc
+; CHECK: br i1 false, label %if.then, label %for.inc
+
+if.then:                                          ; preds = %for.body
+  %idxprom = sext i32 %i.011 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %b, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %0, 1
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  store i32 %add, i32* %arrayidx3, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body, %if.then
+  %inc = add nsw i32 %i.011, 1
+  %cmp = icmp slt i32 %inc, %n
+  br i1 %cmp, label %for.body, label %for.cond.for.cond.cleanup_crit_edge
+}
+
+attributes #0 = { nounwind }
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/canonicalize-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/canonicalize-cmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/canonicalize-cmp.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/canonicalize-cmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,98 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; Check that we replace signed comparisons between non-negative values with
+; unsigned comparisons if we can.
+
+target datalayout = "n8:16:32:64"
+
+define i32 @test_01(i32 %a, i32 %b, i32* %p) {
+
+; CHECK-LABEL: @test_01(
+; CHECK-NOT:   icmp slt
+; CHECK:       %cmp1 = icmp ult i32 %iv, 100
+; CHECK:       %cmp2 = icmp ult i32 %iv, 100
+; CHECK-NOT:   %cmp3
+; CHECK:       %exitcond = icmp ne i32 %iv.next, 1000
+
+entry:
+  br label %loop.entry
+
+loop.entry:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.be ]
+  %cmp1 = icmp slt i32 %iv, 100
+  br i1 %cmp1, label %b1, label %b2
+
+b1:
+  store i32 %iv, i32* %p
+  br label %merge
+
+b2:
+  store i32 %a, i32* %p
+  br label %merge
+
+merge:
+  %cmp2 = icmp ult i32 %iv, 100
+  br i1 %cmp2, label %b3, label %b4
+
+b3:
+  store i32 %iv, i32* %p
+  br label %loop.be
+
+b4:
+  store i32 %b, i32* %p
+  br label %loop.be
+
+loop.be:
+  %iv.next = add i32 %iv, 1
+  %cmp3 = icmp slt i32 %iv.next, 1000
+  br i1 %cmp3, label %loop.entry, label %exit
+
+exit:
+  ret i32 %iv
+}
+
+define i32 @test_02(i32 %a, i32 %b, i32* %p) {
+
+; CHECK-LABEL: @test_02(
+; CHECK-NOT:   icmp sgt
+; CHECK:       %cmp1 = icmp ugt i32 100, %iv
+; CHECK:       %cmp2 = icmp ugt i32 100, %iv
+; CHECK-NOT:   %cmp3
+; CHECK:       %exitcond = icmp ne i32 %iv.next, 1000
+
+entry:
+  br label %loop.entry
+
+loop.entry:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.be ]
+  %cmp1 = icmp sgt i32 100, %iv
+  br i1 %cmp1, label %b1, label %b2
+
+b1:
+  store i32 %iv, i32* %p
+  br label %merge
+
+b2:
+  store i32 %a, i32* %p
+  br label %merge
+
+merge:
+  %cmp2 = icmp ugt i32 100, %iv
+  br i1 %cmp2, label %b3, label %b4
+
+b3:
+  store i32 %iv, i32* %p
+  br label %loop.be
+
+b4:
+  store i32 %b, i32* %p
+  br label %loop.be
+
+loop.be:
+  %iv.next = add i32 %iv, 1
+  %cmp3 = icmp sgt i32 1000, %iv.next
+  br i1 %cmp3, label %loop.entry, label %exit
+
+exit:
+  ret i32 %iv
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/casted-argument.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt < %s -indvars -disable-output
+; PR4009
+; PR4038
+
+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-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+
+define void @safe_bcopy(i8* %to) nounwind {
+entry:
+	%cmp11 = icmp ult i8* %to, null		; <i1> [#uses=1]
+	br i1 %cmp11, label %loop, label %return
+
+return:		; preds = %entry
+	ret void
+
+loop:		; preds = %loop, %if.else
+	%pn = phi i8* [ %ge, %loop ], [ null, %entry ]		; <i8*> [#uses=1]
+	%cp = ptrtoint i8* %to to i32		; <i32> [#uses=1]
+	%su = sub i32 0, %cp		; <i32> [#uses=1]
+	%ge = getelementptr i8, i8* %pn, i32 %su		; <i8*> [#uses=2]
+	tail call void @bcopy(i8* %ge) nounwind
+	br label %loop
+}
+
+define void @safe_bcopy_4038(i8* %from, i8* %to, i32 %size) nounwind {
+entry:
+	br i1 false, label %if.else, label %if.then12
+
+if.then12:		; preds = %entry
+	ret void
+
+if.else:		; preds = %entry
+	%sub.ptr.rhs.cast40 = ptrtoint i8* %from to i32		; <i32> [#uses=1]
+	br label %if.end54
+
+if.end54:		; preds = %if.end54, %if.else
+	%sub.ptr4912.pn = phi i8* [ %sub.ptr4912, %if.end54 ], [ null, %if.else ]		; <i8*> [#uses=1]
+	%sub.ptr7 = phi i8* [ %sub.ptr, %if.end54 ], [ null, %if.else ]		; <i8*> [#uses=2]
+	%sub.ptr.rhs.cast46.pn = ptrtoint i8* %from to i32		; <i32> [#uses=1]
+	%sub.ptr.lhs.cast45.pn = ptrtoint i8* %to to i32		; <i32> [#uses=1]
+	%sub.ptr.sub47.pn = sub i32 %sub.ptr.rhs.cast46.pn, %sub.ptr.lhs.cast45.pn		; <i32> [#uses=1]
+	%sub.ptr4912 = getelementptr i8, i8* %sub.ptr4912.pn, i32 %sub.ptr.sub47.pn		; <i8*> [#uses=2]
+	tail call void @bcopy_4038(i8* %sub.ptr4912, i8* %sub.ptr7, i32 0) nounwind
+	%sub.ptr = getelementptr i8, i8* %sub.ptr7, i32 %sub.ptr.rhs.cast40		; <i8*> [#uses=1]
+	br label %if.end54
+}
+
+declare void @bcopy(i8* nocapture) nounwind
+
+declare void @bcopy_4038(i8*, i8*, i32) nounwind

Added: llvm/trunk/test/Transforms/IndVarSimplify/const_phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/const_phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/const_phi.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/const_phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; PR25372
+; We can compute the expression of %phi0 and that is a SCEV
+; constant. However, instcombine can't deduce this, so we can
+; potentially end up trying to handle a constant when replacing
+; congruent IVs.
+
+; CHECK-LABEL: crash
+define void @crash() {
+entry:
+  br i1 false, label %not_taken, label %pre
+
+not_taken:
+  br label %pre
+
+pre:
+; %phi0.pre and %phi1.pre are evaluated by SCEV to constant 0.
+  %phi0.pre = phi i32 [ 0, %entry ], [ 2, %not_taken ]
+  %phi1.pre = phi i32 [ 0, %entry ], [ 1, %not_taken ]
+  br label %loop
+
+loop:
+; %phi0 and %phi1 are evaluated by SCEV to constant 0.
+  %phi0 = phi i32 [ 0, %loop ], [ %phi0.pre, %pre ]
+  %phi1 = phi i32 [ 0, %loop ], [ %phi1.pre, %pre ]
+  br i1 undef, label %exit, label %loop
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/constant-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/constant-fold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/constant-fold.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/constant-fold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+define void @test0(i32* %x) {
+entry:
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.inc, %entry
+  %i.01 = phi i32 [ 0, %entry ], [ %add, %for.inc ]
+  %and = and i32 %i.01, 3
+  %cmp1 = icmp eq i32 %and, 0
+  %cond = select i1 %cmp1, i32 0, i32 1
+  store i32 %cond, i32* %x, align 4
+  %add = add i32 %i.01, 4
+  %cmp = icmp ult i32 %add, 8
+  br i1 %cmp, label %for.inc, label %for.end
+
+for.end:                                          ; preds = %for.inc
+  ret void
+}
+
+; Should fold the condition of the select into constant
+; CHECK-LABEL: void @test0(
+; CHECK:         icmp eq i32 0, 0
+
+define void @test1(i32* %a) {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %mul = mul nsw i32 %i.01, 64
+  %rem = srem i32 %mul, 8
+  %idxprom = sext i32 %rem to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  store i32 %i.01, i32* %arrayidx, align 4
+  %inc = add nsw i32 %i.01, 1
+  %cmp = icmp slt i32 %inc, 64
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+; Should fold the rem since %mul is multiple of 8
+; CHECK-LABEL: @test1(
+; CHECK-NOT:     rem
+; CHECK:         sext i32 0 to i64

Added: llvm/trunk/test/Transforms/IndVarSimplify/constant_result.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/constant_result.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/constant_result.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/constant_result.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+ at Y = global [400 x i16] zeroinitializer, align 1
+
+define i16 @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[I:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [400 x i16], [400 x i16]* @Y, i16 0, i16 [[I]]
+; CHECK-NEXT:    store i16 0, i16* [[ARRAYIDX]], align 1
+; CHECK-NEXT:    [[INC]] = add nuw nsw i16 [[I]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i16 [[INC]], 400
+; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
+; CHECK:       for.end:
+; CHECK-NEXT:    ret i16 400
+;
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i = phi i16 [ 0, %entry ], [ %inc, %for.body ]
+
+  %arrayidx = getelementptr inbounds [400 x i16], [400 x i16]* @Y, i16 0, i16 %i
+  store i16 0, i16* %arrayidx, align 1
+  %inc = add nuw nsw i16 %i, 1
+  %cmp = icmp ult i16 %inc, 400
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  %inc.lcssa = phi i16 [ %inc, %for.body ]
+  ret i16 %inc.lcssa
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/crash.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,133 @@
+; RUN: opt -indvars -disable-output < %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+declare i32 @putchar(i8) nounwind
+
+define void @t2(i1* %P) nounwind {
+; <label>:0
+  br label %1
+
+; <label>:1                                       ; preds = %1, %0
+  %2 = phi double [ 9.000000e+00, %0 ], [ %4, %1 ] ; <double> [#uses=1]
+  %3 = tail call i32 @putchar(i8 72)              ; <i32> [#uses=0]
+  %4 = fadd double %2, -1.000000e+00              ; <double> [#uses=2]
+  %5 = fcmp ult double %4, 0.000000e+00           ; <i1> [#uses=1]
+  store i1 %5, i1* %P
+  br i1 %5, label %6, label %1
+
+; <label>:6                                       ; preds = %1
+  ret void
+}
+
+; PR7562
+define void @fannkuch() nounwind {
+entry:                                              ; preds = %entry
+  br label %bb12
+
+bb12:                                             ; preds = %bb29, %entry
+  %i.1 = phi i32 [ undef, %entry ], [ %i.0, %bb29 ] ; <i32> [#uses=2]
+  %r.1 = phi i32 [ undef, %entry ], [ %r.0, %bb29 ] ; <i32> [#uses=2]
+  br i1 undef, label %bb13, label %bb24
+
+bb13:                                             ; preds = %bb12
+  br label %bb24
+
+bb24:                                             ; preds = %bb30, %bb13, %bb12
+  %i.2 = phi i32 [ %i.1, %bb13 ], [ %i.0, %bb30 ], [ %i.1, %bb12 ] ; <i32> [#uses=1]
+  %r.0 = phi i32 [ %r.1, %bb13 ], [ %2, %bb30 ], [ %r.1, %bb12 ] ; <i32> [#uses=3]
+  br label %bb28
+
+bb27:                                             ; preds = %bb28
+  %0 = add nsw i32 %i.0, 1                        ; <i32> [#uses=1]
+  br label %bb28
+
+bb28:                                             ; preds = %bb27, %bb26
+  %i.0 = phi i32 [ %i.2, %bb24 ], [ %0, %bb27 ]   ; <i32> [#uses=4]
+  %1 = icmp slt i32 %i.0, %r.0                    ; <i1> [#uses=1]
+  br i1 %1, label %bb27, label %bb29
+
+bb29:                                             ; preds = %bb28
+  br i1 undef, label %bb12, label %bb30
+
+bb30:                                             ; preds = %bb29
+  %2 = add nsw i32 %r.0, 1                        ; <i32> [#uses=1]
+  br label %bb24
+}
+
+; PR10770
+
+declare void @__go_panic() noreturn
+
+declare void @__go_undefer()
+
+declare i32 @__gccgo_personality_v0(i32, i64, i8*, i8*)
+
+define void @main.main() uwtable personality i32 (i32, i64, i8*, i8*)* @__gccgo_personality_v0 {
+entry:
+  invoke void @__go_panic() noreturn
+          to label %0 unwind label %"5.i"
+
+; <label>:0                                       ; preds = %entry
+  unreachable
+
+"3.i":                                            ; preds = %"7.i", %"5.i"
+  invoke void @__go_undefer()
+          to label %main.f.exit unwind label %"7.i"
+
+"5.i":                                            ; preds = %entry
+  %1 = landingpad { i8*, i32 }
+          catch i8* null
+  br label %"3.i"
+
+"7.i":                                            ; preds = %"3.i"
+  %2 = landingpad { i8*, i32 }
+          catch i8* null
+  br label %"3.i"
+
+main.f.exit:                                      ; preds = %"3.i"
+  unreachable
+}
+
+
+; PR13967
+
+define void @f() nounwind ssp {
+bb:
+  br label %bb4
+
+bb4:
+  %tmp = phi i64 [ %tmp5, %bb7 ], [ undef, %bb ]
+  %tmp5 = add nsw i64 %tmp, 1
+  %extract.t1 = trunc i64 %tmp5 to i32
+  br i1 false, label %bb6, label %bb7
+
+bb6:
+  br label %bb7
+
+bb7:
+  %.off0 = phi i32 [ undef, %bb6 ], [ %extract.t1, %bb4 ]
+  %tmp8 = icmp eq i32 %.off0, 0
+  br i1 %tmp8, label %bb9, label %bb4
+
+bb9:
+  ret void
+}
+
+; PR12536
+define void @fn1() noreturn nounwind {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.end, %entry
+  %b.0 = phi i32 [ undef, %entry ], [ %conv, %for.end ]
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.cond1, %for.cond
+  %c.0 = phi i32 [ %b.0, %for.cond1 ], [ 0, %for.cond ]
+  br i1 undef, label %for.cond1, label %for.end
+
+for.end:                                          ; preds = %for.cond1
+  %cmp2 = icmp slt i32 %c.0, 1
+  %conv = zext i1 %cmp2 to i32
+  br label %for.cond
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/dangling-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/dangling-use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/dangling-use.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/dangling-use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt -indvars -disable-output < %s 
+
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i8:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128-n32"
+target triple = "powerpc-unknown-linux-gnu"
+
+define void @vec_inverse_5_7_vert_loop_copyseparate(i8* %x, i32 %n, i32 %rowbytes) nounwind {
+entry:
+  %tmp1 = sdiv i32 %n, 3                          ; <i32> [#uses=1]
+  %tmp2 = sdiv i32 %rowbytes, 5                   ; <i32> [#uses=2]
+  br label %bb49
+
+bb49:                                             ; preds = %bb48, %entry
+  %x_addr.0 = phi i8* [ %x, %entry ], [ %tmp481, %bb48 ] ; <i8*> [#uses=2]
+  br label %bb10
+
+bb10:                                             ; preds = %bb49
+  %tmp326 = mul nsw i32 %tmp1, %tmp2              ; <i32> [#uses=1]
+  %tmp351 = getelementptr inbounds i8, i8* %x_addr.0, i32 %tmp326 ; <i8*> [#uses=1]
+  br i1 false, label %bb.nph, label %bb48
+
+bb.nph:                                           ; preds = %bb10
+  br label %bb23
+
+bb23:                                             ; preds = %bb28, %bb.nph
+  %pOriginHi.01 = phi i8* [ %tmp351, %bb.nph ], [ %pOriginHi.0, %bb28 ] ; <i8*> [#uses=2]
+  %tmp378 = bitcast i8* %pOriginHi.01 to i8*      ; <i8*> [#uses=1]
+  store i8* %tmp378, i8** null
+  %tmp385 = getelementptr inbounds i8, i8* %pOriginHi.01, i32 %tmp2 ; <i8*> [#uses=1]
+  br label %bb28
+
+bb28:                                             ; preds = %bb23
+  %pOriginHi.0 = phi i8* [ %tmp385, %bb23 ]       ; <i8*> [#uses=1]
+  br i1 false, label %bb23, label %bb28.bb48_crit_edge
+
+bb28.bb48_crit_edge:                              ; preds = %bb28
+  br label %bb48
+
+bb48:                                             ; preds = %bb28.bb48_crit_edge, %bb10
+  %tmp481 = getelementptr inbounds i8, i8* %x_addr.0, i32 1 ; <i8*> [#uses=1]
+  br label %bb49
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/divide-pointer.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/divide-pointer.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/divide-pointer.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/divide-pointer.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,95 @@
+; RUN: opt < %s -indvars
+; PR4271
+
+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-f80:128:128"
+target triple = "i386-apple-darwin10.0"
+	%struct.xyz = type <{ i64, i64, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64, [8 x i8], i64, i64, i32, i32, [4 x i32], i32, i32, i32, i32, i32, i32, [76 x i32], i32, [2 x %struct.uvw] }>
+	%struct.uvw = type <{ i64, i64 }>
+
+define i32 @foo(%struct.xyz* %header, i8* %p2, i8* %p3, i8* nocapture %p4) nounwind {
+entry:
+	br label %while.body.i
+
+while.body.i:		; preds = %while.body.i, %entry
+	br i1 undef, label %while.body.i, label %bcopy_internal.exit
+
+bcopy_internal.exit:		; preds = %while.body.i
+	%conv135 = ptrtoint %struct.xyz* %header to i32		; <i32> [#uses=1]
+	%shr136 = lshr i32 %conv135, 12		; <i32> [#uses=1]
+	br label %for.body
+
+for.body:		; preds = %for.body, %bcopy_internal.exit
+	%ppnum.052 = phi i32 [ %inc, %for.body ], [ %shr136, %bcopy_internal.exit ]		; <i32> [#uses=1]
+	%inc = add i32 %ppnum.052, 1		; <i32> [#uses=2]
+	%cmp = icmp ugt i32 %inc, undef		; <i1> [#uses=1]
+	br i1 %cmp, label %if.then199, label %for.body
+
+if.then199:		; preds = %if.then199, %for.body
+	br label %if.then199
+}
+
+define i32 @same_thing_but_signed(%struct.xyz* %header, i8* %p2, i8* %p3, i8* nocapture %p4) nounwind {
+entry:
+	br label %while.body.i
+
+while.body.i:		; preds = %while.body.i, %entry
+	br i1 undef, label %while.body.i, label %bcopy_internal.exit
+
+bcopy_internal.exit:		; preds = %while.body.i
+	%conv135 = ptrtoint %struct.xyz* %header to i32		; <i32> [#uses=1]
+	%shr136 = ashr i32 %conv135, 12		; <i32> [#uses=1]
+	br label %for.body
+
+for.body:		; preds = %for.body, %bcopy_internal.exit
+	%ppnum.052 = phi i32 [ %inc, %for.body ], [ %shr136, %bcopy_internal.exit ]		; <i32> [#uses=1]
+	%inc = add i32 %ppnum.052, 1		; <i32> [#uses=2]
+	%cmp = icmp ugt i32 %inc, undef		; <i1> [#uses=1]
+	br i1 %cmp, label %if.then199, label %for.body
+
+if.then199:		; preds = %if.then199, %for.body
+	br label %if.then199
+}
+
+define i32 @same_thing_but_multiplied(%struct.xyz* %header, i8* %p2, i8* %p3, i8* nocapture %p4) nounwind {
+entry:
+	br label %while.body.i
+
+while.body.i:		; preds = %while.body.i, %entry
+	br i1 undef, label %while.body.i, label %bcopy_internal.exit
+
+bcopy_internal.exit:		; preds = %while.body.i
+	%conv135 = ptrtoint %struct.xyz* %header to i32		; <i32> [#uses=1]
+	%shr136 = shl i32 %conv135, 12		; <i32> [#uses=1]
+	br label %for.body
+
+for.body:		; preds = %for.body, %bcopy_internal.exit
+	%ppnum.052 = phi i32 [ %inc, %for.body ], [ %shr136, %bcopy_internal.exit ]		; <i32> [#uses=1]
+	%inc = add i32 %ppnum.052, 1		; <i32> [#uses=2]
+	%cmp = icmp ugt i32 %inc, undef		; <i1> [#uses=1]
+	br i1 %cmp, label %if.then199, label %for.body
+
+if.then199:		; preds = %if.then199, %for.body
+	br label %if.then199
+}
+
+define i32 @same_thing_but_xored(%struct.xyz* %header, i8* %p2, i8* %p3, i8* nocapture %p4) nounwind {
+entry:
+	br label %while.body.i
+
+while.body.i:		; preds = %while.body.i, %entry
+	br i1 undef, label %while.body.i, label %bcopy_internal.exit
+
+bcopy_internal.exit:		; preds = %while.body.i
+	%conv135 = ptrtoint %struct.xyz* %header to i32		; <i32> [#uses=1]
+	%shr136 = xor i32 %conv135, 12		; <i32> [#uses=1]
+	br label %for.body
+
+for.body:		; preds = %for.body, %bcopy_internal.exit
+	%ppnum.052 = phi i32 [ %inc, %for.body ], [ %shr136, %bcopy_internal.exit ]		; <i32> [#uses=1]
+	%inc = add i32 %ppnum.052, 1		; <i32> [#uses=2]
+	%cmp = icmp ugt i32 %inc, undef		; <i1> [#uses=1]
+	br i1 %cmp, label %if.then199, label %for.body
+
+if.then199:		; preds = %if.then199, %for.body
+	br label %if.then199
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/dont-recompute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/dont-recompute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/dont-recompute.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/dont-recompute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,176 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; This tests that the IV is not recomputed outside of the loop when it is known
+; to be computed by the loop and used in the loop any way. In the example below
+; although a's value can be computed outside of the loop, there is no benefit
+; in doing so as it has to be computed by the loop anyway.
+;
+; extern void func(unsigned val);
+;
+; void test(unsigned m)
+; {
+;   unsigned a = 0;
+;
+;   for (int i=0; i<186; i++) {
+;     a += m;
+;     func(a);
+;   }
+;
+;   func(a);
+; }
+
+declare void @func(i32)
+
+; CHECK-LABEL: @test(
+define void @test(i32 %m) nounwind uwtable {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %add = add i32 %a.05, %m
+; CHECK: tail call void @func(i32 %add)
+  tail call void @func(i32 %add)
+  %inc = add nsw i32 %i.06, 1
+  %exitcond = icmp eq i32 %inc, 186
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+; CHECK: for.end:
+; CHECK-NOT: mul i32 %m, 186
+; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
+; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
+  tail call void @func(i32 %add)
+  ret void
+}
+
+; CHECK-LABEL: @test2(
+define i32 @test2(i32 %m) nounwind uwtable {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %add = add i32 %a.05, %m
+; CHECK: tail call void @func(i32 %add)
+  tail call void @func(i32 %add)
+  %inc = add nsw i32 %i.06, 1
+  %exitcond = icmp eq i32 %inc, 186
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+; CHECK: for.end:
+; CHECK-NOT: mul i32 %m, 186
+; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
+; CHECK-NEXT: ret i32 %add.lcssa
+  ret i32 %add
+}
+
+; CHECK-LABEL: @test3(
+define void @test3(i32 %m) nounwind uwtable {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %add = add i32 %a.05, %m
+  mul i32 %add, 1
+  mul i32 %add, 1
+  mul i32 %add, 1
+  mul i32 %add, 1
+  mul i32 %add, 1
+  mul i32 %add, 1
+; CHECK: tail call void @func(i32 %add)
+  tail call void @func(i32 %add)
+  %inc = add nsw i32 %i.06, 1
+  %exitcond = icmp eq i32 %inc, 186
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+; CHECK: for.end:
+; CHECK-NOT: mul i32 %m, 186
+; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
+; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
+  tail call void @func(i32 %add)
+  ret void
+}
+
+; CHECK-LABEL: @test4(
+define void @test4(i32 %m) nounwind uwtable {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %add = add i32 %a.05, %m
+; CHECK: tail call void @func(i32 %add)
+  tail call void @func(i32 %add)
+  %inc = add nsw i32 %i.06, 1
+  %exitcond = icmp eq i32 %inc, 186
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+; CHECK: for.end:
+; CHECK-NOT: mul i32 %m, 186
+; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
+; CHECK-NEXT: %soft_use = add i32 %add.lcssa, 123
+; CHECK-NEXT: tail call void @func(i32 %soft_use)
+  %soft_use = add i32 %add, 123
+  tail call void @func(i32 %soft_use)
+  ret void
+}
+
+; CHECK-LABEL: @test5(
+define void @test5(i32 %m) nounwind uwtable {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %add = add i32 %a.05, %m
+  %soft_use = add i32 %add, 123
+; CHECK: tail call void @func(i32 %soft_use)
+  tail call void @func(i32 %soft_use)
+  %inc = add nsw i32 %i.06, 1
+  %exitcond = icmp eq i32 %inc, 186
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+; CHECK: for.end:
+; CHECK-NOT: mul i32 %m, 186
+; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
+; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
+  tail call void @func(i32 %add)
+  ret void
+}
+
+; CHECK-LABEL: @test6(
+define void @test6(i32 %m, i32* %p) nounwind uwtable {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %add = add i32 %a.05, %m
+  %soft_use = add i32 %add, 123
+; CHECK: store i32 %soft_use, i32* %pidx
+  %pidx = getelementptr i32, i32* %p, i32 %add
+  store i32 %soft_use, i32* %pidx
+  %inc = add nsw i32 %i.06, 1
+  %exitcond = icmp eq i32 %inc, 186
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body
+; CHECK: for.end:
+; CHECK-NOT: mul i32 %m, 186
+; CHECK:%add.lcssa = phi i32 [ %add, %for.body ]
+; CHECK-NEXT: tail call void @func(i32 %add.lcssa)
+  tail call void @func(i32 %add)
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/drop-exact.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/drop-exact.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/drop-exact.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/drop-exact.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,99 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
+
+; We make a transform by getting rid of add nsw i32 %tmp17, -1; make sure that
+; we drop "exact" flag on lshr as we do it.
+define void @drop_exact(i32* %p, i64* %p1) {
+; CHECK-LABEL: @drop_exact(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB12:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    ret void
+; CHECK:       bb12:
+; CHECK-NEXT:    [[TMP13:%.*]] = phi i32 [ -47436, [[BB:%.*]] ], [ [[TMP15:%.*]], [[BB12]] ]
+; CHECK-NEXT:    [[TMP14:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP42:%.*]], [[BB12]] ]
+; CHECK-NEXT:    [[TMP15]] = add nsw i32 [[TMP13]], -1
+; CHECK-NEXT:    [[TMP16:%.*]] = shl i32 [[TMP15]], 1
+; CHECK-NEXT:    [[TMP17:%.*]] = sub nsw i32 42831, [[TMP16]]
+; CHECK-NEXT:    [[TMP19:%.*]] = lshr i32 [[TMP17]], 1
+; CHECK-NEXT:    [[TMP20:%.*]] = urem i32 [[TMP19]], 250
+; CHECK-NEXT:    [[TMP22:%.*]] = lshr i32 [[TMP17]], 1
+; CHECK-NEXT:    store i32 [[TMP22]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    [[TMP26:%.*]] = zext i32 [[TMP20]] to i64
+; CHECK-NEXT:    store i64 [[TMP26]], i64* [[P1:%.*]], align 4
+; CHECK-NEXT:    [[TMP42]] = add nuw nsw i32 [[TMP14]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[TMP42]], 719
+; CHECK-NEXT:    br i1 [[EXITCOND]], label [[BB7:%.*]], label [[BB12]]
+;
+bb:
+  br label %bb12
+
+bb7:                                              ; preds = %bb12
+  ret void
+
+bb12:                                             ; preds = %bb12, %bb
+  %tmp13 = phi i32 [ -47436, %bb ], [ %tmp15, %bb12 ]
+  %tmp14 = phi i32 [ 0, %bb ], [ %tmp42, %bb12 ]
+  %tmp15 = add i32 %tmp13, -1
+  %tmp16 = shl i32 %tmp15, 1
+  %tmp17 = sub i32 42831, %tmp16
+  %tmp19 = lshr i32 %tmp17, 1
+  %tmp20 = urem i32 %tmp19, 250
+  %tmp21 = add nsw i32 %tmp17, -1
+  %tmp22 = lshr exact i32 %tmp21, 1
+  store i32 %tmp22, i32* %p, align 4
+  %tmp26 = zext i32 %tmp20 to i64
+  store i64 %tmp26, i64* %p1, align 4
+  %tmp42 = add nuw nsw i32 %tmp14, 1
+  %tmp43 = icmp ugt i32 %tmp14, 717
+  br i1 %tmp43, label %bb7, label %bb12
+}
+
+; Throw away add nsw i32 %tmp17, 0, do not drop exact flag.
+define void @dont_drop_exact(i32* %p, i64* %p1) {
+; CHECK-LABEL: @dont_drop_exact(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB12:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    ret void
+; CHECK:       bb12:
+; CHECK-NEXT:    [[TMP13:%.*]] = phi i32 [ -47436, [[BB:%.*]] ], [ [[TMP15:%.*]], [[BB12]] ]
+; CHECK-NEXT:    [[TMP14:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP42:%.*]], [[BB12]] ]
+; CHECK-NEXT:    [[TMP15]] = add nsw i32 [[TMP13]], -1
+; CHECK-NEXT:    [[TMP16:%.*]] = shl i32 [[TMP15]], 1
+; CHECK-NEXT:    [[TMP17:%.*]] = sub nsw i32 42831, [[TMP16]]
+; CHECK-NEXT:    [[TMP19:%.*]] = lshr i32 [[TMP17]], 1
+; CHECK-NEXT:    [[TMP20:%.*]] = urem i32 [[TMP19]], 250
+; CHECK-NEXT:    [[TMP22:%.*]] = lshr exact i32 [[TMP17]], 1
+; CHECK-NEXT:    store i32 [[TMP22]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    [[TMP26:%.*]] = zext i32 [[TMP20]] to i64
+; CHECK-NEXT:    store i64 [[TMP26]], i64* [[P1:%.*]], align 4
+; CHECK-NEXT:    [[TMP42]] = add nuw nsw i32 [[TMP14]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[TMP42]], 719
+; CHECK-NEXT:    br i1 [[EXITCOND]], label [[BB7:%.*]], label [[BB12]]
+;
+bb:
+  br label %bb12
+
+bb7:                                              ; preds = %bb12
+  ret void
+
+bb12:                                             ; preds = %bb12, %bb
+  %tmp13 = phi i32 [ -47436, %bb ], [ %tmp15, %bb12 ]
+  %tmp14 = phi i32 [ 0, %bb ], [ %tmp42, %bb12 ]
+  %tmp15 = add i32 %tmp13, -1
+  %tmp16 = shl i32 %tmp15, 1
+  %tmp17 = sub i32 42831, %tmp16
+  %tmp19 = lshr i32 %tmp17, 1
+  %tmp20 = urem i32 %tmp19, 250
+  %tmp21 = add nsw i32 %tmp17, 0
+  %tmp22 = lshr exact i32 %tmp21, 1
+  store i32 %tmp22, i32* %p, align 4
+  %tmp26 = zext i32 %tmp20 to i64
+  store i64 %tmp26, i64* %p1, align 4
+  %tmp42 = add nuw nsw i32 %tmp14, 1
+  %tmp43 = icmp ugt i32 %tmp14, 717
+  br i1 %tmp43, label %bb7, label %bb12
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/elim-extend.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/elim-extend.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/elim-extend.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/elim-extend.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,155 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; IV with constant start, preinc and postinc sign extends, with and without NSW.
+; IV rewrite only removes one sext. WidenIVs removes all three.
+define void @postincConstIV(i8* %base, i32 %limit) nounwind {
+entry:
+  br label %loop
+; CHECK: loop:
+; CHECK-NOT: sext
+; CHECK: exit:
+loop:
+  %iv = phi i32 [ %postiv, %loop ], [ 0, %entry ]
+  %ivnsw = phi i32 [ %postivnsw, %loop ], [ 0, %entry ]
+  %preofs = sext i32 %iv to i64
+  %preadr = getelementptr i8, i8* %base, i64 %preofs
+  store i8 0, i8* %preadr
+  %postiv = add i32 %iv, 1
+  %postofs = sext i32 %postiv to i64
+  %postadr = getelementptr i8, i8* %base, i64 %postofs
+  store i8 0, i8* %postadr
+  %postivnsw = add nsw i32 %ivnsw, 1
+  %postofsnsw = sext i32 %postivnsw to i64
+  %postadrnsw = getelementptr inbounds i8, i8* %base, i64 %postofsnsw
+  store i8 0, i8* %postadrnsw
+  %cond = icmp sgt i32 %limit, %iv
+  br i1 %cond, label %loop, label %exit
+exit:
+  br label %return
+return:
+  ret void
+}
+
+; IV with nonconstant start, preinc and postinc sign extends,
+; with and without NSW.
+; As with postincConstIV, WidenIVs removes all three sexts.
+define void @postincVarIV(i8* %base, i32 %init, i32 %limit) nounwind {
+entry:
+  %precond = icmp sgt i32 %limit, %init
+  br i1 %precond, label %loop, label %return
+; CHECK: loop:
+; CHECK-NOT: sext
+; CHECK: wide.trip.count = sext
+; CHECK-NOT: sext
+; CHECK: exit:
+loop:
+  %iv = phi i32 [ %postiv, %loop ], [ %init, %entry ]
+  %ivnsw = phi i32 [ %postivnsw, %loop ], [ %init, %entry ]
+  %preofs = sext i32 %iv to i64
+  %preadr = getelementptr i8, i8* %base, i64 %preofs
+  store i8 0, i8* %preadr
+  %postiv = add i32 %iv, 1
+  %postofs = sext i32 %postiv to i64
+  %postadr = getelementptr i8, i8* %base, i64 %postofs
+  store i8 0, i8* %postadr
+  %postivnsw = add nsw i32 %ivnsw, 1
+  %postofsnsw = sext i32 %postivnsw to i64
+  %postadrnsw = getelementptr i8, i8* %base, i64 %postofsnsw
+  store i8 0, i8* %postadrnsw
+  %cond = icmp sgt i32 %limit, %postiv
+  br i1 %cond, label %loop, label %exit
+exit:
+  br label %return
+return:
+  ret void
+}
+
+; Test sign extend elimination in the inner and outer loop.
+; %outercount is straightforward to widen, besides being in an outer loop.
+; %innercount is currently blocked by lcssa, so is not widened.
+; %inneriv can be widened only after proving it has no signed-overflow
+;   based on the loop test.
+define void @nestedIV(i8* %address, i32 %limit) nounwind {
+entry:
+  %limitdec = add i32 %limit, -1
+  br label %outerloop
+
+; CHECK: outerloop:
+;
+; Eliminate %ofs1 after widening outercount.
+; CHECK-NOT: sext
+; CHECK: getelementptr
+;
+; IV rewriting hoists a gep into this block. We don't like that.
+; CHECK-NOT: getelementptr
+outerloop:
+  %outercount   = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ]
+  %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ]
+
+  %outercountdec = add i32 %outercount, -1
+  %ofs1 = sext i32 %outercountdec to i64
+  %adr1 = getelementptr i8, i8* %address, i64 %ofs1
+  store i8 0, i8* %adr1
+
+  br label %innerpreheader
+
+innerpreheader:
+  %innerprecmp = icmp sgt i32 %limitdec, %innercount
+  br i1 %innerprecmp, label %innerloop, label %outermerge
+
+; CHECK: innerloop:
+;
+; Eliminate %ofs2 after widening inneriv.
+; Eliminate %ofs3 after normalizing sext(innerpostiv)
+; CHECK-NOT: sext
+; CHECK: getelementptr
+;
+; FIXME: We should check that indvars does not increase the number of
+; IVs in this loop. sext elimination plus LFTR currently results in 2 final
+; IVs. Waiting to remove LFTR.
+innerloop:
+  %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ]
+  %innerpostiv = add i32 %inneriv, 1
+
+  %ofs2 = sext i32 %inneriv to i64
+  %adr2 = getelementptr i8, i8* %address, i64 %ofs2
+  store i8 0, i8* %adr2
+
+  %ofs3 = sext i32 %innerpostiv to i64
+  %adr3 = getelementptr i8, i8* %address, i64 %ofs3
+  store i8 0, i8* %adr3
+
+  %innercmp = icmp sgt i32 %limitdec, %innerpostiv
+  br i1 %innercmp, label %innerloop, label %innerexit
+
+innerexit:
+  %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ]
+  br label %outermerge
+
+; CHECK: outermerge:
+;
+; Eliminate %ofs4 after widening outercount
+; CHECK-NOT: sext
+; CHECK: getelementptr
+;
+; TODO: Eliminate %ofs5 after removing lcssa
+outermerge:
+  %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ]
+
+  %ofs4 = sext i32 %outercount to i64
+  %adr4 = getelementptr i8, i8* %address, i64 %ofs4
+  store i8 0, i8* %adr4
+
+  %ofs5 = sext i32 %innercount.merge to i64
+  %adr5 = getelementptr i8, i8* %address, i64 %ofs5
+  store i8 0, i8* %adr5
+
+  %outerpostcount = add i32 %outercount, 1
+  %tmp47 = icmp slt i32 %outerpostcount, %limit
+  br i1 %tmp47, label %outerloop, label %return
+
+return:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,559 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+ at X = external global [0 x double]
+
+; Indvars should be able to simplify simple comparisons involving
+; induction variables.
+
+; CHECK-LABEL: @foo(
+; CHECK: %cond = and i1 %tobool.not, true
+
+define void @foo(i64 %n, i32* nocapture %p) nounwind {
+entry:
+  %cmp9 = icmp sgt i64 %n, 0
+  br i1 %cmp9, label %pre, label %return
+
+pre:
+  %t3 = load i32, i32* %p
+  %tobool.not = icmp ne i32 %t3, 0
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %pre ], [ %inc, %for.inc ]
+  %cmp6 = icmp slt i64 %i, %n
+  %cond = and i1 %tobool.not, %cmp6
+  br i1 %cond, label %if.then, label %for.inc
+
+if.then:
+  %arrayidx = getelementptr [0 x double], [0 x double]* @X, i64 0, i64 %i
+  store double 3.200000e+00, double* %arrayidx
+  br label %for.inc
+
+for.inc:
+  %inc = add nsw i64 %i, 1
+  %exitcond = icmp sge i64 %inc, %n
+  br i1 %exitcond, label %return, label %loop
+
+return:
+  ret void
+}
+
+; Don't eliminate an icmp that's contributing to the loop exit test though.
+
+; CHECK-LABEL: @_ZNK4llvm5APInt3ultERKS0_(
+; CHECK: %tmp99 = icmp sgt i32 %i, -1
+
+define i32 @_ZNK4llvm5APInt3ultERKS0_(i32 %tmp2.i1, i64** %tmp65, i64** %tmp73, i64** %tmp82, i64** %tmp90) {
+entry:
+  br label %bb18
+
+bb13:
+  %tmp66 = load i64*, i64** %tmp65, align 4
+  %tmp68 = getelementptr inbounds i64, i64* %tmp66, i32 %i
+  %tmp69 = load i64, i64* %tmp68, align 4
+  %tmp74 = load i64*, i64** %tmp73, align 4
+  %tmp76 = getelementptr inbounds i64, i64* %tmp74, i32 %i
+  %tmp77 = load i64, i64* %tmp76, align 4
+  %tmp78 = icmp ugt i64 %tmp69, %tmp77
+  br i1 %tmp78, label %bb20.loopexit, label %bb15
+
+bb15:
+  %tmp83 = load i64*, i64** %tmp82, align 4
+  %tmp85 = getelementptr inbounds i64, i64* %tmp83, i32 %i
+  %tmp86 = load i64, i64* %tmp85, align 4
+  %tmp91 = load i64*, i64** %tmp90, align 4
+  %tmp93 = getelementptr inbounds i64, i64* %tmp91, i32 %i
+  %tmp94 = load i64, i64* %tmp93, align 4
+  %tmp95 = icmp ult i64 %tmp86, %tmp94
+  br i1 %tmp95, label %bb20.loopexit, label %bb17
+
+bb17:
+  %tmp97 = add nsw i32 %i, -1
+  br label %bb18
+
+bb18:
+  %i = phi i32 [ %tmp2.i1, %entry ], [ %tmp97, %bb17 ]
+  %tmp99 = icmp sgt i32 %i, -1
+  br i1 %tmp99, label %bb13, label %bb20.loopexit
+
+bb20.loopexit:
+  %tmp.0.ph = phi i32 [ 0, %bb18 ], [ 1, %bb15 ], [ 0, %bb13 ]
+  ret i32 %tmp.0.ph
+}
+
+; Indvars should eliminate the icmp here.
+
+; CHECK-LABEL: @func_10(
+; CHECK-NOT: icmp
+; CHECK: ret void
+
+define void @func_10() nounwind {
+entry:
+  br label %loop
+
+loop:
+  %i = phi i32 [ %i.next, %loop ], [ 0, %entry ]
+  %t0 = icmp slt i32 %i, 0
+  %t1 = zext i1 %t0 to i32
+  %t2 = add i32 %t1, %i
+  %u3 = zext i32 %t2 to i64
+  store i64 %u3, i64* null
+  %i.next = add i32 %i, 1
+  br i1 undef, label %loop, label %return
+
+return:
+  ret void
+}
+
+; PR14432
+; Indvars should not turn the second loop into an infinite one.
+
+; CHECK-LABEL: @func_11(
+; CHECK: %tmp5 = icmp ult i32 %__key6.0, 10
+; CHECK-NOT: br i1 true, label %noassert68, label %unrolledend
+
+define i32 @func_11() nounwind uwtable {
+entry:
+  br label %forcond
+
+forcond:                                          ; preds = %noassert, %entry
+  %__key6.0 = phi i32 [ 2, %entry ], [ %tmp37, %noassert ]
+  %tmp5 = icmp slt i32 %__key6.0, 10
+  br i1 %tmp5, label %noassert, label %forcond38.preheader
+
+forcond38.preheader:                              ; preds = %forcond
+  br label %forcond38
+
+noassert:                                         ; preds = %forbody
+  %tmp13 = sdiv i32 -32768, %__key6.0
+  %tmp2936 = shl i32 %tmp13, 24
+  %sext23 = shl i32 %tmp13, 24
+  %tmp32 = icmp eq i32 %tmp2936, %sext23
+  %tmp37 = add i32 %__key6.0, 1
+  br i1 %tmp32, label %forcond, label %assert33
+
+assert33:                                         ; preds = %noassert
+  tail call void @llvm.trap()
+  unreachable
+
+forcond38:                                        ; preds = %noassert68, %forcond38.preheader
+  %__key8.0 = phi i32 [ %tmp81, %noassert68 ], [ 2, %forcond38.preheader ]
+  %tmp46 = icmp slt i32 %__key8.0, 10
+  br i1 %tmp46, label %noassert68, label %unrolledend
+
+noassert68:                                       ; preds = %forbody39
+  %tmp57 = sdiv i32 -32768, %__key8.0
+  %sext34 = shl i32 %tmp57, 16
+  %sext21 = shl i32 %tmp57, 16
+  %tmp76 = icmp eq i32 %sext34, %sext21
+  %tmp81 = add i32 %__key8.0, 1
+  br i1 %tmp76, label %forcond38, label %assert77
+
+assert77:                                         ; preds = %noassert68
+  tail call void @llvm.trap()
+  unreachable
+
+unrolledend:                                      ; preds = %forcond38
+  ret i32 0
+}
+
+declare void @llvm.trap() noreturn nounwind
+
+; In this case the second loop only has a single iteration, fold the header away
+; CHECK-LABEL: @func_12(
+; CHECK: %tmp5 = icmp ult i32 %__key6.0, 10
+; CHECK: br i1 true, label %noassert68, label %unrolledend
+define i32 @func_12() nounwind uwtable {
+entry:
+  br label %forcond
+
+forcond:                                          ; preds = %noassert, %entry
+  %__key6.0 = phi i32 [ 2, %entry ], [ %tmp37, %noassert ]
+  %tmp5 = icmp slt i32 %__key6.0, 10
+  br i1 %tmp5, label %noassert, label %forcond38.preheader
+
+forcond38.preheader:                              ; preds = %forcond
+  br label %forcond38
+
+noassert:                                         ; preds = %forbody
+  %tmp13 = sdiv i32 -32768, %__key6.0
+  %tmp2936 = shl i32 %tmp13, 24
+  %sext23 = shl i32 %tmp13, 24
+  %tmp32 = icmp eq i32 %tmp2936, %sext23
+  %tmp37 = add i32 %__key6.0, 1
+  br i1 %tmp32, label %forcond, label %assert33
+
+assert33:                                         ; preds = %noassert
+  tail call void @llvm.trap()
+  unreachable
+
+forcond38:                                        ; preds = %noassert68, %forcond38.preheader
+  %__key8.0 = phi i32 [ %tmp81, %noassert68 ], [ 2, %forcond38.preheader ]
+  %tmp46 = icmp slt i32 %__key8.0, 10
+  br i1 %tmp46, label %noassert68, label %unrolledend
+
+noassert68:                                       ; preds = %forbody39
+  %tmp57 = sdiv i32 -32768, %__key8.0
+  %sext34 = shl i32 %tmp57, 16
+  %sext21 = shl i32 %tmp57, 16
+  %tmp76 = icmp ne i32 %sext34, %sext21
+  %tmp81 = add i32 %__key8.0, 1
+  br i1 %tmp76, label %forcond38, label %assert77
+
+assert77:                                         ; preds = %noassert68
+  tail call void @llvm.trap()
+  unreachable
+
+unrolledend:                                      ; preds = %forcond38
+  ret i32 0
+}
+
+declare void @side_effect()
+
+define void @func_13(i32* %len.ptr) {
+; CHECK-LABEL: @func_13(
+ entry:
+  %len = load i32, i32* %len.ptr, !range !0
+  %len.sub.1 = add i32 %len, -1
+  %len.is.zero = icmp eq i32 %len, 0
+  br i1 %len.is.zero, label %leave, label %loop
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  call void @side_effect()
+  %iv.inc = add i32 %iv, 1
+  %iv.cmp = icmp ult i32 %iv, %len
+  br i1 %iv.cmp, label %be, label %leave
+; CHECK: br i1 true, label %be, label %leave
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp ult i32 %iv, %len.sub.1
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_14(i32* %len.ptr) {
+; CHECK-LABEL: @func_14(
+ entry:
+  %len = load i32, i32* %len.ptr, !range !0
+  %len.sub.1 = add i32 %len, -1
+  %len.is.zero = icmp eq i32 %len, 0
+  %len.is.int_min = icmp eq i32 %len, 2147483648
+  %no.entry = or i1 %len.is.zero, %len.is.int_min
+  br i1 %no.entry, label %leave, label %loop
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  call void @side_effect()
+  %iv.inc = add i32 %iv, 1
+  %iv.cmp = icmp slt i32 %iv, %len
+  br i1 %iv.cmp, label %be, label %leave
+; CHECK: br i1 true, label %be, label %leave
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv, %len.sub.1
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_15(i32* %len.ptr) {
+; CHECK-LABEL: @func_15(
+ entry:
+  %len = load i32, i32* %len.ptr, !range !0
+  %len.add.1 = add i32 %len, 1
+  %len.add.1.is.zero = icmp eq i32 %len.add.1, 0
+  br i1 %len.add.1.is.zero, label %leave, label %loop
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  call void @side_effect()
+  %iv.inc = add i32 %iv, 1
+  %iv.cmp = icmp ult i32 %iv, %len.add.1
+  br i1 %iv.cmp, label %be, label %leave
+; CHECK: br i1 true, label %be, label %leave
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp ult i32 %iv, %len
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_16(i32* %len.ptr) {
+; CHECK-LABEL: @func_16(
+ entry:
+  %len = load i32, i32* %len.ptr, !range !0
+  %len.add.5 = add i32 %len, 5
+  %entry.cond.0 = icmp slt i32 %len, 2147483643
+  %entry.cond.1 = icmp slt i32 4, %len.add.5
+  %entry.cond = and i1 %entry.cond.0, %entry.cond.1
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  call void @side_effect()
+  %iv.inc = add i32 %iv, 1
+  %iv.add.4 = add i32 %iv, 4
+  %iv.cmp = icmp slt i32 %iv.add.4, %len.add.5
+  br i1 %iv.cmp, label %be, label %leave
+; CHECK: br i1 true, label %be, label %leave
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv, %len
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_17(i32* %len.ptr) {
+; CHECK-LABEL: @func_17(
+ entry:
+  %len = load i32, i32* %len.ptr
+  %len.add.5 = add i32 %len, -5
+  %entry.cond.0 = icmp slt i32 %len, 2147483653 ;; 2147483653 == INT_MIN - (-5)
+  %entry.cond.1 = icmp slt i32 -6, %len.add.5
+  %entry.cond = and i1 %entry.cond.0, %entry.cond.1
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv.2 = phi i32 [ 0, %entry ], [ %iv.2.inc, %be ]
+  %iv = phi i32 [ -6, %entry ], [ %iv.inc, %be ]
+  call void @side_effect()
+  %iv.inc = add i32 %iv, 1
+  %iv.2.inc = add i32 %iv.2, 1
+  %iv.cmp = icmp slt i32 %iv, %len.add.5
+
+; Deduces {-5,+,1} s< (-5 + %len) from {0,+,1} < %len
+; since %len s< INT_MIN - (-5) from the entry condition
+
+; CHECK: br i1 true, label %be, label %leave
+  br i1 %iv.cmp, label %be, label %leave
+
+ be:
+; CHECK: be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv.2, %len
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define i1 @func_18(i16* %tmp20, i32* %len.addr) {
+; CHECK-LABEL: @func_18(
+entry:
+  %len = load i32, i32* %len.addr, !range !0
+  %tmp18 = icmp eq i32 %len, 0
+  br i1 %tmp18, label %bb2, label %bb0.preheader
+
+bb0.preheader:
+  br label %bb0
+
+bb0:
+; CHECK: bb0:
+  %var_0.in = phi i32 [ %var_0, %bb1 ], [ %len, %bb0.preheader ]
+  %var_1 = phi i32 [ %tmp30, %bb1 ], [ 0, %bb0.preheader ]
+  %var_0 = add nsw i32 %var_0.in, -1
+  %tmp23 = icmp ult i32 %var_1, %len
+; CHECK: br i1 true, label %stay, label %bb2.loopexit
+  br i1 %tmp23, label %stay, label %bb2
+
+stay:
+; CHECK: stay:
+  %tmp25 = getelementptr inbounds i16, i16* %tmp20, i32 %var_1
+  %tmp26 = load i16, i16* %tmp25
+  %tmp29 = icmp eq i16 %tmp26, 0
+  br i1 %tmp29, label %bb1, label %bb2
+
+bb1:
+  %tmp30 = add i32 %var_1, 1
+  %tmp31 = icmp eq i32 %var_0, 0
+  br i1 %tmp31, label %bb3, label %bb0
+
+bb2:
+  ret i1 false
+
+bb3:
+  ret i1 true
+}
+
+define void @func_19(i32* %length.ptr) {
+; CHECK-LABEL: @func_19(
+ entry:
+  %length = load i32, i32* %length.ptr, !range !0
+  %length.is.nonzero = icmp ne i32 %length, 0
+  br i1 %length.is.nonzero, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  %iv.inc = add i32 %iv, 1
+  %range.check = icmp ult i32 %iv, %length
+  br i1 %range.check, label %be, label %leave
+; CHECK:   br i1 true, label %be, label %leave.loopexit
+; CHECK: be:
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv.inc, %length
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_20(i32* %length.ptr) {
+; Like @func_19, but %length is no longer provably positive, so
+; %range.check cannot be proved to be always true.
+
+; CHECK-LABEL: @func_20(
+ entry:
+  %length = load i32, i32* %length.ptr
+  %length.is.nonzero = icmp ne i32 %length, 0
+  br i1 %length.is.nonzero, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  %iv.inc = add i32 %iv, 1
+  %range.check = icmp ult i32 %iv, %length
+  br i1 %range.check, label %be, label %leave
+; CHECK:   br i1 %range.check, label %be, label %leave.loopexit
+; CHECK: be:
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv.inc, %length
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_21(i32* %length.ptr) {
+; CHECK-LABEL: @func_21(
+
+; This checks that the backedge condition, (I + 1) < Length - 1 implies
+; (I + 1) < Length
+ entry:
+  %length = load i32, i32* %length.ptr, !range !0
+  %lim = sub i32 %length, 1
+  %entry.cond = icmp sgt i32 %length, 1
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  %iv.inc = add i32 %iv, 1
+  %range.check = icmp slt i32 %iv, %length
+  br i1 %range.check, label %be, label %leave
+; CHECK:   br i1 true, label %be, label %leave.loopexit
+; CHECK: be:
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv.inc, %lim
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_22(i32* %length.ptr) {
+; CHECK-LABEL: @func_22(
+
+; This checks that the backedge condition, (I + 1) < Length - 1 implies
+; (I + 1) < Length
+ entry:
+  %length = load i32, i32* %length.ptr, !range !0
+  %lim = sub i32 %length, 1
+  %entry.cond = icmp sgt i32 %length, 1
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
+  %iv.inc = add i32 %iv, 1
+  %range.check = icmp sle i32 %iv, %length
+  br i1 %range.check, label %be, label %leave
+; CHECK:   br i1 true, label %be, label %leave.loopexit
+; CHECK: be:
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp sle i32 %iv.inc, %lim
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_23(i32* %length.ptr) {
+; CHECK-LABEL: @func_23(
+ entry:
+  %length = load i32, i32* %length.ptr, !range !0
+  %entry.cond = icmp ult i32 4, %length
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ 4, %entry ], [ %iv.inc, %be ]
+  %iv.inc = add i32 %iv, 1
+  %range.check = icmp slt i32 %iv, %length
+  br i1 %range.check, label %be, label %leave
+; CHECK:   br i1 true, label %be, label %leave.loopexit
+; CHECK: be:
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp slt i32 %iv.inc, %length
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+define void @func_24(i32* %init.ptr) {
+; CHECK-LABEL: @func_24(
+ entry:
+  %init = load i32, i32* %init.ptr, !range !0
+  %entry.cond = icmp ugt i32 %init, 4
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i32 [ %init, %entry ], [ %iv.dec, %be ]
+  %iv.dec = add i32 %iv, -1
+  %range.check = icmp sgt i32 %iv, 4
+  br i1 %range.check, label %be, label %leave
+; CHECK:   br i1 true, label %be, label %leave.loopexit
+; CHECK: be:
+
+ be:
+  call void @side_effect()
+  %be.cond = icmp sgt i32 %iv.dec, 4
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+
+!0 = !{i32 0, i32 2147483647}

Added: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-max.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-max.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-max.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-max.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt < %s -S -indvars | FileCheck %s
+; PR4914.ll
+
+; Indvars should be able to do range analysis and eliminate icmps.
+; There are two here which cannot be eliminated.
+; There's one that icmp which can be eliminated and which indvars currently
+; cannot eliminate, because it requires analyzing more than just the
+; range of the induction variable.
+
+ at 0 = private constant [4 x i8] c"%d\0A\00", align 1 ; <[4 x i8]*> [#uses=1]
+
+define i32 @main() nounwind {
+; CHECK-LABEL: @main(
+; CHECK: = icmp
+; CHECK: = icmp
+; CHECK: = icmp
+; CHECK-NOT: = icmp
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb14, %bb
+  %t = phi i32 [ 0, %bb ], [ %t19, %bb14 ]        ; <i32> [#uses=5]
+  %t2 = phi i32 [ 0, %bb ], [ %t18, %bb14 ]       ; <i32> [#uses=1]
+  %t3 = icmp slt i32 %t, 0                        ; <i1> [#uses=1]
+  br i1 %t3, label %bb7, label %bb4
+
+bb4:                                              ; preds = %bb1
+  %t5 = icmp sgt i32 %t, 255                      ; <i1> [#uses=1]
+  %t6 = select i1 %t5, i32 255, i32 %t            ; <i32> [#uses=1]
+  br label %bb7
+
+bb7:                                              ; preds = %bb4, %bb1
+  %t8 = phi i32 [ %t6, %bb4 ], [ 0, %bb1 ]        ; <i32> [#uses=1]
+  %t9 = sub i32 0, %t                             ; <i32> [#uses=3]
+  %t10 = icmp slt i32 %t9, 0                      ; <i1> [#uses=1]
+  br i1 %t10, label %bb14, label %bb11
+
+bb11:                                             ; preds = %bb7
+  %t12 = icmp sgt i32 %t9, 255                    ; <i1> [#uses=1]
+  %t13 = select i1 %t12, i32 255, i32 %t9         ; <i32> [#uses=1]
+  br label %bb14
+
+bb14:                                             ; preds = %bb11, %bb7
+  %t15 = phi i32 [ %t13, %bb11 ], [ 0, %bb7 ]     ; <i32> [#uses=1]
+  %t16 = add nsw i32 %t2, 255                     ; <i32> [#uses=1]
+  %t17 = add nsw i32 %t16, %t8                    ; <i32> [#uses=1]
+  %t18 = add nsw i32 %t17, %t15                   ; <i32> [#uses=2]
+  %t19 = add nsw i32 %t, 1                        ; <i32> [#uses=2]
+  %t20 = icmp slt i32 %t19, 1000000000            ; <i1> [#uses=1]
+  br i1 %t20, label %bb1, label %bb21
+
+bb21:                                             ; preds = %bb14
+  %t22 = call i32 (i8*, ...) @printf(i8* noalias getelementptr inbounds ([4 x i8], [4 x i8]* @0, i32 0, i32 0), i32 %t18) nounwind
+  ret i32 0
+}
+
+declare i32 @printf(i8* noalias nocapture, ...) nounwind

Added: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-rem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-rem.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-rem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,121 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; Indvars should be able to eliminate this srem.
+; CHECK-LABEL: @simple(
+; CHECK-NOT: rem
+; CHECK: ret
+
+define void @simple(i64 %arg, double* %arg3) nounwind {
+bb:
+  %t = icmp slt i64 0, %arg                     ; <i1> [#uses=1]
+  br i1 %t, label %bb4, label %bb12
+
+bb4:                                              ; preds = %bb
+  br label %bb5
+
+bb5:                                              ; preds = %bb4, %bb5
+  %t6 = phi i64 [ %t9, %bb5 ], [ 0, %bb4 ]    ; <i64> [#uses=2]
+  %t7 = srem i64 %t6, %arg                    ; <i64> [#uses=1]
+  %t8 = getelementptr inbounds double, double* %arg3, i64 %t7 ; <double*> [#uses=1]
+  store double 0.000000e+00, double* %t8
+  %t9 = add nsw i64 %t6, 1                    ; <i64> [#uses=2]
+  %t10 = icmp slt i64 %t9, %arg               ; <i1> [#uses=1]
+  br i1 %t10, label %bb5, label %bb11
+
+bb11:                                             ; preds = %bb5
+  br label %bb12
+
+bb12:                                             ; preds = %bb11, %bb
+  ret void
+}
+
+; Indvars should be able to eliminate the (i+1)%n.
+; CHECK-LABEL: @f(
+; CHECK-NOT: {{[us]}}rem
+; CHECK: {{[us]}}rem
+; CHECK-NOT: {{[us]}}rem
+; CHECK: ret
+
+define i32 @f(i64* %arg, i64 %arg1, i64 %arg2, i64 %arg3) nounwind {
+bb:
+  %t = icmp sgt i64 %arg1, 0                      ; <i1> [#uses=1]
+  br i1 %t, label %bb4, label %bb54
+
+bb4:                                              ; preds = %bb
+  br label %bb5
+
+bb5:                                              ; preds = %bb49, %bb4
+  %t6 = phi i64 [ %t51, %bb49 ], [ 0, %bb4 ]      ; <i64> [#uses=4]
+  %t7 = phi i32 [ %t50, %bb49 ], [ 0, %bb4 ]      ; <i32> [#uses=2]
+  %t8 = add nsw i64 %t6, %arg1                    ; <i64> [#uses=1]
+  %t9 = add nsw i64 %t8, -2                       ; <i64> [#uses=1]
+  %t10 = srem i64 %t9, %arg1                      ; <i64> [#uses=1]
+  %t11 = add nsw i64 %t10, 1                      ; <i64> [#uses=1]
+  %t12 = add nsw i64 %t6, 1                       ; <i64> [#uses=1]
+  %t13 = srem i64 %t12, %arg1                     ; <i64> [#uses=1]
+  %t14 = icmp sgt i64 %arg1, 0                    ; <i1> [#uses=1]
+  br i1 %t14, label %bb15, label %bb49
+
+bb15:                                             ; preds = %bb5
+  br label %bb16
+
+bb16:                                             ; preds = %bb44, %bb15
+  %t17 = phi i64 [ %t46, %bb44 ], [ 0, %bb15 ]    ; <i64> [#uses=1]
+  %t18 = phi i32 [ %t45, %bb44 ], [ %t7, %bb15 ]  ; <i32> [#uses=2]
+  %t19 = icmp sgt i64 %arg1, 0                    ; <i1> [#uses=1]
+  br i1 %t19, label %bb20, label %bb44
+
+bb20:                                             ; preds = %bb16
+  br label %bb21
+
+bb21:                                             ; preds = %bb21, %bb20
+  %t22 = phi i64 [ %t41, %bb21 ], [ 0, %bb20 ]    ; <i64> [#uses=4]
+  %t23 = phi i32 [ %t40, %bb21 ], [ %t18, %bb20 ] ; <i32> [#uses=1]
+  %t24 = mul i64 %t6, %arg1                       ; <i64> [#uses=1]
+  %t25 = mul i64 %t13, %arg1                      ; <i64> [#uses=1]
+  %t26 = add nsw i64 %t24, %t22                   ; <i64> [#uses=1]
+  %t27 = mul i64 %t11, %arg1                      ; <i64> [#uses=1]
+  %t28 = add nsw i64 %t25, %t22                   ; <i64> [#uses=1]
+  %t29 = getelementptr inbounds i64, i64* %arg, i64 %t26 ; <i64*> [#uses=1]
+  %t30 = add nsw i64 %t27, %t22                   ; <i64> [#uses=1]
+  %t31 = getelementptr inbounds i64, i64* %arg, i64 %t28 ; <i64*> [#uses=1]
+  %t32 = zext i32 %t23 to i64                     ; <i64> [#uses=1]
+  %t33 = load i64, i64* %t29                           ; <i64> [#uses=1]
+  %t34 = getelementptr inbounds i64, i64* %arg, i64 %t30 ; <i64*> [#uses=1]
+  %t35 = load i64, i64* %t31                           ; <i64> [#uses=1]
+  %t36 = add nsw i64 %t32, %t33                   ; <i64> [#uses=1]
+  %t37 = add nsw i64 %t36, %t35                   ; <i64> [#uses=1]
+  %t38 = load i64, i64* %t34                           ; <i64> [#uses=1]
+  %t39 = add nsw i64 %t37, %t38                   ; <i64> [#uses=1]
+  %t40 = trunc i64 %t39 to i32                    ; <i32> [#uses=2]
+  %t41 = add nsw i64 %t22, 1                      ; <i64> [#uses=2]
+  %t42 = icmp slt i64 %t41, %arg1                 ; <i1> [#uses=1]
+  br i1 %t42, label %bb21, label %bb43
+
+bb43:                                             ; preds = %bb21
+  br label %bb44
+
+bb44:                                             ; preds = %bb43, %bb16
+  %t45 = phi i32 [ %t18, %bb16 ], [ %t40, %bb43 ] ; <i32> [#uses=2]
+  %t46 = add nsw i64 %t17, 1                      ; <i64> [#uses=2]
+  %t47 = icmp slt i64 %t46, %arg1                 ; <i1> [#uses=1]
+  br i1 %t47, label %bb16, label %bb48
+
+bb48:                                             ; preds = %bb44
+  br label %bb49
+
+bb49:                                             ; preds = %bb48, %bb5
+  %t50 = phi i32 [ %t7, %bb5 ], [ %t45, %bb48 ]   ; <i32> [#uses=2]
+  %t51 = add nsw i64 %t6, 1                       ; <i64> [#uses=2]
+  %t52 = icmp slt i64 %t51, %arg1                 ; <i1> [#uses=1]
+  br i1 %t52, label %bb5, label %bb53
+
+bb53:                                             ; preds = %bb49
+  br label %bb54
+
+bb54:                                             ; preds = %bb53, %bb
+  %t55 = phi i32 [ 0, %bb ], [ %t50, %bb53 ]      ; <i32> [#uses=1]
+  ret i32 %t55
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-trunc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,564 @@
+; 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: @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: @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: @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: @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: @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: @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: @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: @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
+}
+
+define void @test_11() {
+; CHECK-LABEL: @test_11(
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br i1 undef, label [[BB2:%.*]], label [[BB6:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 undef, label [[BB3:%.*]], label [[BB4:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb4:
+; CHECK-NEXT:    br label [[BB6]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[_TMP24:%.*]] = icmp slt i16 undef, 0
+; CHECK-NEXT:    br i1 [[_TMP24]], label [[BB5:%.*]], label [[BB5]]
+; CHECK:       bb6:
+; CHECK-NEXT:    br i1 false, label [[BB1]], label [[BB7:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    ret void
+;
+  br label %bb1
+
+bb1:                                              ; preds = %bb6, %0
+  %e.5.0 = phi i32 [ 0, %0 ], [ %_tmp32, %bb6 ]
+  br i1 undef, label %bb2, label %bb6
+
+bb2:                                              ; preds = %bb1
+  %_tmp15 = trunc i32 %e.5.0 to i16
+  br i1 undef, label %bb3, label %bb4
+
+bb3:                                              ; preds = %bb2
+  br label %bb4
+
+bb4:                                              ; preds = %bb3, %bb2
+  br label %bb6
+
+bb5:                                              ; preds = %bb5, %bb5
+  %_tmp24 = icmp slt i16 %_tmp15, 0
+  br i1 %_tmp24, label %bb5, label %bb5
+
+bb6:                                              ; preds = %bb4, %bb1
+  %_tmp32 = add nuw nsw i32 %e.5.0, 1
+  br i1 false, label %bb1, label %bb7
+
+bb7:                                             ; preds = %bb6
+  ret void
+}
+
+; Show that we can turn signed comparison to unsigned and use zext while
+; comparing non-negative values.
+define void @test_12(i32* %p) {
+; CHECK-LABEL: @test_12(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[N:%.*]] = load i32, i32* [[P:%.*]], !range !0
+; 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 ult i64 [[IV_NEXT]], [[ZEXT]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %n = load i32, i32* %p, !range !0
+  br label %loop
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %iv.next = add i64 %iv, 1
+  %narrow.iv = trunc i64 %iv.next to i32
+  %cmp = icmp slt i32 %narrow.iv, %n
+  br i1 %cmp, label %loop, label %exit
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 1000}

Added: llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test2.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; PR23538
+; RUN: opt < %s -indvars -loop-deletion -S | FileCheck %s
+
+; Check IndVarSimplify should not replace exit value because or else
+; udiv will be introduced by expand and the cost will be high.
+
+declare void @_Z3mixRjj(i32* dereferenceable(4), i32)
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+define i32 @_Z3fooPKcjj(i8* nocapture readonly %s, i32 %len, i32 %c) {
+; CHECK-LABEL: @_Z3fooPKcjj(
+; CHECK-NOT: udiv
+entry:
+  %a = alloca i32, align 4
+  %tmp = bitcast i32* %a to i8*
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* %tmp)
+  store i32 -1640531527, i32* %a, align 4
+  %cmp8 = icmp ugt i32 %len, 11
+  br i1 %cmp8, label %while.body.lr.ph, label %while.end
+
+while.body.lr.ph:                                 ; preds = %entry
+  br label %while.body
+
+while.body:                                       ; preds = %while.body, %while.body.lr.ph
+  %keylen.010 = phi i32 [ %len, %while.body.lr.ph ], [ %sub, %while.body ]
+  %s.addr.09 = phi i8* [ %s, %while.body.lr.ph ], [ %add.ptr, %while.body ]
+  %tmp1 = bitcast i8* %s.addr.09 to i32*
+  %tmp2 = load i32, i32* %tmp1, align 4
+  %shl.i = shl i32 %tmp2, 1
+  %and.i = and i32 %shl.i, 16843008
+  %tmp3 = load i32, i32* %a, align 4
+  %sub.i = add i32 %tmp3, %tmp2
+  %add = sub i32 %sub.i, %and.i
+  store i32 %add, i32* %a, align 4
+  %add.ptr = getelementptr inbounds i8, i8* %s.addr.09, i64 12
+  %sub = add i32 %keylen.010, -12
+  %cmp = icmp ugt i32 %sub, 11
+  br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
+
+while.cond.while.end_crit_edge:                   ; preds = %while.body
+  %sub.lcssa = phi i32 [ %sub, %while.body ]
+  br label %while.end
+
+while.end:                                        ; preds = %while.cond.while.end_crit_edge, %entry
+  %keylen.0.lcssa = phi i32 [ %sub.lcssa, %while.cond.while.end_crit_edge ], [ %len, %entry ]
+  call void @_Z3mixRjj(i32* dereferenceable(4) %a, i32 %keylen.0.lcssa)
+  %tmp4 = load i32, i32* %a, align 4
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* %tmp)
+  ret i32 %tmp4
+}
+
+define i32 @zero_backedge_count_test(i32 %unknown_init, i32* %unknown_mem) {
+; CHECK-LABEL: @zero_backedge_count_test(
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry], [ %iv.inc, %loop ]
+  %unknown_phi = phi i32 [ %unknown_init, %entry ], [ %unknown_next, %loop ]
+  %iv.inc = add i32 %iv, 1
+  %be_taken = icmp ne i32 %iv.inc, 1
+  %unknown_next = load volatile i32, i32* %unknown_mem
+  br i1 %be_taken, label %loop, label %leave
+
+leave:
+; We can fold %unknown_phi even though the backedge value for it is completely
+; unknown, since we can prove that the loop's backedge taken count is 0.
+
+; CHECK: leave:
+; CHECK: ret i32 %unknown_init
+  %exit_val = phi i32 [ %unknown_phi, %loop ]
+  ret i32 %exit_val
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test3.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/exit_value_test3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -indvars -loop-deletion -S |FileCheck %s
+
+; Check IndVarSimplify should replace exit value even if the expansion cost
+; is high because the loop can be deleted after the exit value rewrite.
+;
+; CHECK-LABEL: @_Z3fooPKcjj(
+; CHECK: udiv
+; CHECK: [[LABEL:^[a-zA-Z0-9_.]+]]:
+; CHECK-NOT: br {{.*}} [[LABEL]]
+
+define i32 @_Z3fooPKcjj(i8* nocapture readnone %s, i32 %len, i32 %c) #0 {
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond, %entry
+  %klen.0 = phi i32 [ %len, %entry ], [ %sub, %while.cond ]
+  %cmp = icmp ugt i32 %klen.0, 11
+  %sub = add i32 %klen.0, -12
+  br i1 %cmp, label %while.cond, label %while.end
+
+while.end:                                        ; preds = %while.cond
+  %klen.0.lcssa = phi i32 [ %klen.0, %while.cond ]
+  ret i32 %klen.0.lcssa
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/exit_value_tests.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,115 @@
+; Test that we can evaluate the exit values of various expression types.  Since
+; these loops all have predictable exit values we can replace the use outside
+; of the loop with a closed-form computation, making the loop dead.
+;
+; RUN: opt < %s -indvars -loop-deletion -simplifycfg -S | FileCheck %s
+
+; CHECK-NOT: br
+
+define i32 @polynomial_constant() {
+; <label>:0
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	%A1 = phi i32 [ 0, %0 ], [ %A2, %Loop ]		; <i32> [#uses=3]
+	%B1 = phi i32 [ 0, %0 ], [ %B2, %Loop ]		; <i32> [#uses=1]
+	%A2 = add i32 %A1, 1		; <i32> [#uses=1]
+	%B2 = add i32 %B1, %A1		; <i32> [#uses=2]
+	%C = icmp eq i32 %A1, 1000		; <i1> [#uses=1]
+	br i1 %C, label %Out, label %Loop
+
+Out:		; preds = %Loop
+	ret i32 %B2
+}
+
+define i32 @NSquare(i32 %N) {
+; <label>:0
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	%X = phi i32 [ 0, %0 ], [ %X2, %Loop ]		; <i32> [#uses=4]
+	%X2 = add i32 %X, 1		; <i32> [#uses=1]
+	%c = icmp eq i32 %X, %N		; <i1> [#uses=1]
+	br i1 %c, label %Out, label %Loop
+
+Out:		; preds = %Loop
+	%Y = mul i32 %X, %X		; <i32> [#uses=1]
+	ret i32 %Y
+}
+
+define i32 @NSquareOver2(i32 %N) {
+; <label>:0
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	%X = phi i32 [ 0, %0 ], [ %X2, %Loop ]		; <i32> [#uses=3]
+	%Y = phi i32 [ 15, %0 ], [ %Y2, %Loop ]		; <i32> [#uses=1]
+	%Y2 = add i32 %Y, %X		; <i32> [#uses=2]
+	%X2 = add i32 %X, 1		; <i32> [#uses=1]
+	%c = icmp eq i32 %X, %N		; <i1> [#uses=1]
+	br i1 %c, label %Out, label %Loop
+
+Out:		; preds = %Loop
+	ret i32 %Y2
+}
+
+define i32 @strength_reduced() {
+; <label>:0
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	%A1 = phi i32 [ 0, %0 ], [ %A2, %Loop ]		; <i32> [#uses=3]
+	%B1 = phi i32 [ 0, %0 ], [ %B2, %Loop ]		; <i32> [#uses=1]
+	%A2 = add i32 %A1, 1		; <i32> [#uses=1]
+	%B2 = add i32 %B1, %A1		; <i32> [#uses=2]
+	%C = icmp eq i32 %A1, 1000		; <i1> [#uses=1]
+	br i1 %C, label %Out, label %Loop
+
+Out:		; preds = %Loop
+	ret i32 %B2
+}
+
+define i32 @chrec_equals() {
+entry:
+	br label %no_exit
+
+no_exit:		; preds = %no_exit, %entry
+	%i0 = phi i32 [ 0, %entry ], [ %i1, %no_exit ]		; <i32> [#uses=3]
+	%ISq = mul i32 %i0, %i0		; <i32> [#uses=1]
+	%i1 = add i32 %i0, 1		; <i32> [#uses=2]
+	%tmp.1 = icmp ne i32 %ISq, 10000		; <i1> [#uses=1]
+	br i1 %tmp.1, label %no_exit, label %loopexit
+
+loopexit:		; preds = %no_exit
+	ret i32 %i1
+}
+
+define i16 @cast_chrec_test() {
+; <label>:0
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	%A1 = phi i32 [ 0, %0 ], [ %A2, %Loop ]		; <i32> [#uses=2]
+	%B1 = trunc i32 %A1 to i16		; <i16> [#uses=2]
+	%A2 = add i32 %A1, 1		; <i32> [#uses=1]
+	%C = icmp eq i16 %B1, 1000		; <i1> [#uses=1]
+	br i1 %C, label %Out, label %Loop
+
+Out:		; preds = %Loop
+	ret i16 %B1
+}
+
+define i32 @linear_div_fold() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 4, %entry ], [ %i.next, %loop ]		; <i32> [#uses=3]
+	%i.next = add i32 %i, 8		; <i32> [#uses=1]
+	%RV = udiv i32 %i, 2		; <i32> [#uses=1]
+	%c = icmp ne i32 %i, 68		; <i1> [#uses=1]
+	br i1 %c, label %loop, label %loopexit
+
+loopexit:		; preds = %loop
+	ret i32 %RV
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/floating-point-iv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/floating-point-iv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/floating-point-iv.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/floating-point-iv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,92 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+define void @test1() nounwind {
+entry:
+	br label %bb
+
+bb:		; preds = %bb, %entry
+	%x.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %1, %bb ]		; <double> [#uses=2]
+	%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind		; <i32> [#uses=0]
+	%1 = fadd double %x.0.reg2mem.0, 1.000000e+00		; <double> [#uses=2]
+	%2 = fcmp olt double %1, 1.000000e+04		; <i1> [#uses=1]
+	br i1 %2, label %bb, label %return
+
+return:		; preds = %bb
+	ret void
+; CHECK-LABEL: @test1(
+; CHECK: icmp
+}
+
+declare i32 @foo(double)
+
+define void @test2() nounwind {
+entry:
+	br label %bb
+
+bb:		; preds = %bb, %entry
+	%x.0.reg2mem.0 = phi double [ -10.000000e+00, %entry ], [ %1, %bb ]		; <double> [#uses=2]
+	%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind		; <i32> [#uses=0]
+	%1 = fadd double %x.0.reg2mem.0, 2.000000e+00		; <double> [#uses=2]
+	%2 = fcmp olt double %1, -1.000000e+00		; <i1> [#uses=1]
+	br i1 %2, label %bb, label %return
+
+return:		; preds = %bb
+	ret void
+; CHECK-LABEL: @test2(
+; CHECK: icmp
+}
+
+
+define void @test3() nounwind {
+entry:
+	br label %bb
+
+bb:		; preds = %bb, %entry
+	%x.0.reg2mem.0 = phi double [ 0.000000e+00, %entry ], [ %1, %bb ]
+	%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind
+	%1 = fadd double %x.0.reg2mem.0, 1.000000e+00
+	%2 = fcmp olt double %1, -1.000000e+00
+	br i1 %2, label %bb, label %return
+
+return:
+	ret void
+; CHECK-LABEL: @test3(
+; CHECK: fcmp
+}
+
+define void @test4() nounwind {
+entry:
+	br label %bb
+
+bb:		; preds = %bb, %entry
+	%x.0.reg2mem.0 = phi double [ 40.000000e+00, %entry ], [ %1, %bb ]		; <double> [#uses=2]
+	%0 = tail call i32 @foo(double %x.0.reg2mem.0) nounwind		; <i32> [#uses=0]
+	%1 = fadd double %x.0.reg2mem.0, -1.000000e+00		; <double> [#uses=2]
+	%2 = fcmp olt double %1, 1.000000e+00		; <i1> [#uses=1]
+	br i1 %2, label %bb, label %return
+
+return:
+	ret void
+; CHECK-LABEL: @test4(
+; CHECK-NOT: cmp
+; CHECK: br i1 false
+}
+
+; PR6761
+define void @test5() nounwind {
+; <label>:0
+  br label %1
+
+; <label>:1                                       ; preds = %1, %0
+  %2 = phi double [ 9.000000e+00, %0 ], [ %4, %1 ] ; <double> [#uses=1]
+  %3 = tail call i32 @foo(double 0.0)              ; <i32> [#uses=0]
+  %4 = fadd double %2, -1.000000e+00              ; <double> [#uses=2]
+  %5 = fcmp ult double %4, 0.000000e+00           ; <i1> [#uses=1]
+  br i1 %5, label %exit, label %1
+
+exit:
+  ret void
+
+; CHECK-LABEL: @test5(
+; CHECK: icmp slt i32 {{.*}}, 0
+; CHECK-NEXT: br i1
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/full_widening.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/full_widening.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/full_widening.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/full_widening.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; Make sure that we do not insert trunc in the loop.
+define i32 @test_01(double* %p, double %x, i32* %np, i32* %mp, i32 %k) {
+; CHECK-LABEL: @test_01(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[K:%.*]] to i64
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV_WIDE:%.*]] = phi i64 [ [[CANONICAL_IV_NEXT_I:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[CANONICAL_IV_NEXT_I]] = add nuw nsw i64 [[IV_WIDE]], 1
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds double, double* [[P:%.*]], i64 [[IV_WIDE]]
+; CHECK-NEXT:    [[LOAD:%.*]] = load atomic double, double* [[GEP]] unordered, align 8
+; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[X:%.*]], [[LOAD]]
+; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds double, double* [[P]], i64 [[IV_WIDE]]
+; CHECK-NEXT:    store atomic double [[MUL]], double* [[GEP2]] unordered, align 8
+; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i64 [[CANONICAL_IV_NEXT_I]], [[TMP0]]
+; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %loop
+
+loop:
+  %iv.wide = phi i64 [ %canonical.iv.next.i, %loop ], [ 0, %entry ]
+  %iv.narrow = phi i32 [ %iv.narrow.next, %loop ], [ 0, %entry ]
+  %canonical.iv.next.i = add nuw nsw i64 %iv.wide, 1
+  %zext = zext i32 %iv.narrow to i64
+  %gep = getelementptr inbounds double, double* %p, i64 %zext
+  %load = load atomic double, double* %gep unordered, align 8
+  %mul = fmul double %x, %load
+  %gep2 = getelementptr inbounds double, double* %p, i64 %zext
+  store atomic double %mul, double* %gep2 unordered, align 8
+  %iv.narrow.next = add nuw nsw i32 %iv.narrow, 1
+  %loop.cond = icmp slt i32 %iv.narrow.next, %k
+  br i1 %loop.cond, label %loop, label %exit
+
+exit:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/huge_muls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/huge_muls.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/huge_muls.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/huge_muls.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This test takes excessively long time if SCEV tries to construct huge
+; SCEVMulExpr's (with ~1000 ops) due to non-linear analysis cost.
+define i32 @test() {
+; CHECK-LABEL: @test(
+bci_0:
+  br label %bci_12
+
+bci_133:                                          ; preds = %bci_127.unr-lcssa
+  ret i32 %tmp17
+
+bci_12:                                           ; preds = %bci_127.unr-lcssa, %bci_0
+  %indvars.iv184 = phi i64 [ %indvars.iv.next185, %bci_127.unr-lcssa ], [ 3, %bci_0 ]
+  %tmp1 = trunc i64 %indvars.iv184 to i32
+  br label %bci_55.postloop
+
+bci_127.unr-lcssa:                                ; preds = %bci_90.postloop
+  %indvars.iv.next185 = add nuw nsw i64 %indvars.iv184, 1
+  %tmp4 = icmp sgt i64 %indvars.iv184, 91
+  br i1 %tmp4, label %bci_133, label %bci_12
+
+bci_55.postloop:                                  ; preds = %bci_90.postloop, %bci_12
+  %indvars.iv180.postloop = phi i64 [ %indvars.iv.next181.postloop, %bci_90.postloop ], [ 15, %bci_12 ]
+  %local_2_16.postloop = phi i32 [ %tmp17, %bci_90.postloop ], [ 4, %bci_12 ]
+  %indvars.iv.next181.postloop = add nuw nsw i64 %indvars.iv180.postloop, 1
+  %tmp6 = load i32, i32 addrspace(1)* undef, align 4
+  %tmp7 = mul i32 %tmp6, %tmp1
+  br label %not_zero65.us.postloop
+
+not_zero65.us.postloop:                           ; preds = %not_zero65.us.postloop.1, %bci_55.postloop
+  %local_2_24.us.postloop = phi i32 [ %local_2_16.postloop, %bci_55.postloop ], [ %tmp49, %not_zero65.us.postloop.1 ]
+  %local_6_.us.postloop = phi i32 [ 3, %bci_55.postloop ], [ %tmp50, %not_zero65.us.postloop.1 ]
+  %tmp8 = mul i32 %tmp7, %local_2_24.us.postloop
+  %tmp9 = mul i32 %tmp8, %local_2_24.us.postloop
+  %tmp10 = mul i32 %tmp7, %tmp9
+  %tmp11 = mul i32 %tmp10, %tmp9
+  %tmp12 = mul i32 %tmp7, %tmp11
+  %tmp13 = mul i32 %tmp12, %tmp11
+  %tmp14 = mul i32 %tmp7, %tmp13
+  %tmp15 = mul i32 %tmp14, %tmp13
+  %tmp16 = mul i32 %tmp7, %tmp15
+  %tmp17 = mul i32 %tmp16, %tmp15
+  %tmp18 = icmp sgt i32 %local_6_.us.postloop, 82
+  br i1 %tmp18, label %bci_90.postloop, label %not_zero65.us.postloop.1
+
+bci_90.postloop:                                  ; preds = %not_zero65.us.postloop
+  %tmp19 = icmp sgt i64 %indvars.iv180.postloop, 68
+  br i1 %tmp19, label %bci_127.unr-lcssa, label %bci_55.postloop
+
+not_zero65.us.postloop.1:                         ; preds = %not_zero65.us.postloop
+  %tmp20 = mul i32 %tmp7, %tmp17
+  %tmp21 = mul i32 %tmp20, %tmp17
+  %tmp22 = mul i32 %tmp7, %tmp21
+  %tmp23 = mul i32 %tmp22, %tmp21
+  %tmp24 = mul i32 %tmp7, %tmp23
+  %tmp25 = mul i32 %tmp24, %tmp23
+  %tmp26 = mul i32 %tmp7, %tmp25
+  %tmp27 = mul i32 %tmp26, %tmp25
+  %tmp28 = mul i32 %tmp7, %tmp27
+  %tmp29 = mul i32 %tmp28, %tmp27
+  %tmp30 = mul i32 %tmp7, %tmp29
+  %tmp31 = mul i32 %tmp30, %tmp29
+  %tmp32 = mul i32 %tmp7, %tmp31
+  %tmp33 = mul i32 %tmp32, %tmp31
+  %tmp34 = mul i32 %tmp7, %tmp33
+  %tmp35 = mul i32 %tmp34, %tmp33
+  %tmp36 = mul i32 %tmp7, %tmp35
+  %tmp37 = mul i32 %tmp36, %tmp35
+  %tmp38 = mul i32 %tmp7, %tmp37
+  %tmp39 = mul i32 %tmp38, %tmp37
+  %tmp40 = mul i32 %tmp7, %tmp39
+  %tmp41 = mul i32 %tmp40, %tmp39
+  %tmp42 = mul i32 %tmp7, %tmp41
+  %tmp43 = mul i32 %tmp42, %tmp41
+  %tmp44 = mul i32 %tmp7, %tmp43
+  %tmp45 = mul i32 %tmp44, %tmp43
+  %tmp46 = mul i32 %tmp7, %tmp45
+  %tmp47 = mul i32 %tmp46, %tmp45
+  %tmp48 = mul i32 %tmp7, %tmp47
+  %tmp49 = mul i32 %tmp48, %tmp47
+  %tmp50 = add nsw i32 %local_6_.us.postloop, 20
+  br label %not_zero65.us.postloop
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/indirectbr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/indirectbr.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/indirectbr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt < %s -indvars -S -disable-output
+
+; PR5758
+define zeroext i1 @foo() nounwind {
+entry:
+  indirectbr i8* undef, [label %"202", label %"133"]
+
+"132":                                            ; preds = %"133"
+  %0 = add i32 %1, 1                              ; <i32> [#uses=1]
+  br label %"133"
+
+"133":                                            ; preds = %"132", %entry
+  %1 = phi i32 [ %0, %"132" ], [ 0, %entry ]      ; <i32> [#uses=2]
+  %2 = icmp eq i32 %1, 4                          ; <i1> [#uses=1]
+  br i1 %2, label %"134", label %"132"
+
+"134":                                            ; preds = %"133"
+  ret i1 true
+
+"202":                                            ; preds = %entry
+  ret i1 false
+}
+
+; PR7333
+define void @__atomvec_module__put_vrml_bonds() nounwind {
+bb7.preheader:                                    ; preds = %entry
+  indirectbr i8* undef, [label %bb14, label %bb16]
+
+bb14:                                             ; preds = %bb14, %bb7.preheader
+  br label %bb16
+
+bb16:                                             ; preds = %bb16, %bb14, %bb7.preheader
+  %S.31.0 = phi i64 [ %3, %bb16 ], [ 1, %bb7.preheader ], [ 1, %bb14 ] ; <i64> [#uses=2]
+  %0 = add nsw i64 %S.31.0, -1                    ; <i64> [#uses=1]
+  %1 = getelementptr inbounds [3 x double], [3 x double]* undef, i64 0, i64 %0 ; <double*> [#uses=1]
+  %2 = load double, double* %1, align 8                   ; <double> [#uses=0]
+  %3 = add nsw i64 %S.31.0, 1                     ; <i64> [#uses=1]
+  br label %bb16
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/inner-loop-by-latch-cond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/inner-loop-by-latch-cond.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/inner-loop-by-latch-cond.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/inner-loop-by-latch-cond.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @foo(i64)
+
+; CHECK-LABEL: @test
+define void @test(i64 %a) {
+entry:
+  br label %outer_header
+
+outer_header:
+  %i = phi i64 [20, %entry], [%i.next, %outer_latch]
+  %i.next = add nuw nsw i64 %i, 1
+  br label %inner_header
+
+inner_header:
+  %j = phi i64 [1, %outer_header], [%j.next, %inner_header]
+  %cmp = icmp ult i64 %j, %i.next
+; CHECK-NOT: select
+  %s = select i1 %cmp, i64 %j, i64 %i
+; CHECK: call void @foo(i64 %j)
+  call void @foo(i64 %s)
+  %j.next = add nuw nsw i64 %j, 1
+  %cond = icmp ult i64 %j, %i
+  br i1 %cond, label %inner_header, label %outer_latch
+
+outer_latch:
+  %cond2 = icmp ne i64 %i.next, 40
+  br i1 %cond2, label %outer_header, label %return
+
+return:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/inner-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/inner-loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/inner-loop.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/inner-loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; This is regression test for the bug in ScalarEvolution::isKnownPredicate.
+; It does not check whether SCEV is available at loop entry before invoking
+; and utility function isLoopEntryGuardedByCond and that leads to miscompile.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @foo(i64)
+declare void @bar(i32)
+
+define void @test(i8* %arr) {
+entry:
+  br label %outer_header
+
+outer_header:
+  %i = phi i32 [40, %entry], [%i.next, %outer_latch]
+  %i.64 = sext i32 %i to i64
+  br label %inner_header
+
+inner_header:
+  %j = phi i32 [27, %outer_header], [%j.next, %inner_backedge]
+  %j1 = zext i32 %j to i64
+; The next 4 lines are required for avoid widening of %j and
+; SCEV at %cmp would not be AddRec.
+  %gep = getelementptr inbounds i8, i8*  %arr, i64 %j1
+  %ld = load i8, i8* %gep
+  %ec = icmp eq i8 %ld, 0
+  br i1 %ec, label %return, label %inner_backedge
+
+inner_backedge:
+  %cmp = icmp ult i32 %j, %i
+  %s = select i1 %cmp, i32 %i, i32 %j
+; Select should not be simplified because if
+; %i == 26 and %j == 27, %s should be equal to %j.
+; In case of a bug the instruction is simplified to
+; %s = select i1 true, i32 %0, i32 %j
+; CHECK-NOT: %s = select i1 true
+  call void @bar(i32 %s)
+  %j.next = add nsw i32 %j, -2
+  %cond = icmp ult i32 %j, 3
+  br i1 %cond, label %outer_latch, label %inner_header
+
+outer_latch:
+  %i.next = add i32 %i, -1
+  %cond2 = icmp sgt i32 %i.next, 13
+; This line is just for forcing widening of %i
+  call void @foo(i64 %i.64)
+  br i1 %cond2, label %outer_header, label %return
+
+return:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/interesting-invoke-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/interesting-invoke-use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/interesting-invoke-use.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/interesting-invoke-use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; RUN: opt < %s -indvars
+
+; An invoke has a result value which is used in an "Interesting"
+; expression inside the loop. IndVars should be able to rewrite
+; the expression in the correct place.
+
+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-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+  %struct.string___XUB = type { i32, i32 }
+  %struct.string___XUP = type { [0 x i8]*, %struct.string___XUB* }
+ at .str7 = external constant [24 x i8]            ; <[24 x i8]*> [#uses=1]
+ at C.17.316 = external constant %struct.string___XUB              ; <%struct.string___XUB*> [#uses=1]
+
+define void @_ada_c35503g() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  br label %bb
+
+bb:             ; preds = %bb, %entry
+  br i1 false, label %bb65.loopexit, label %bb
+
+bb65.loopexit:          ; preds = %bb
+  br label %bb123
+
+bb123:          ; preds = %bb178, %bb65.loopexit
+  %i.0 = phi i32 [ %3, %bb178 ], [ 0, %bb65.loopexit ]          ; <i32> [#uses=3]
+  %0 = invoke i32 @report__ident_int(i32 1)
+      to label %invcont127 unwind label %lpad266                ; <i32> [#uses=1]
+
+invcont127:             ; preds = %bb123
+  %1 = sub i32 %i.0, %0         ; <i32> [#uses=1]
+  %2 = icmp eq i32 0, %1                ; <i1> [#uses=1]
+  br i1 %2, label %bb178, label %bb128
+
+bb128:          ; preds = %invcont127
+  invoke void @system__img_int__image_integer(%struct.string___XUP* noalias sret null, i32 %i.0)
+      to label %invcont129 unwind label %lpad266
+
+invcont129:             ; preds = %bb128
+  invoke void @system__string_ops__str_concat(%struct.string___XUP* noalias sret null, [0 x i8]* bitcast ([24 x i8]* @.str7 to [0 x i8]*), %struct.string___XUB* @C.17.316, [0 x i8]* null, %struct.string___XUB* null)
+      to label %invcont138 unwind label %lpad266
+
+invcont138:             ; preds = %invcont129
+  unreachable
+
+bb178:          ; preds = %invcont127
+  %3 = add i32 %i.0, 1          ; <i32> [#uses=1]
+  br label %bb123
+
+lpad266:                ; preds = %invcont129, %bb128, %bb123
+  %exn = landingpad {i8*, i32}
+            cleanup
+  unreachable
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @system__img_int__image_integer(%struct.string___XUP* noalias sret, i32)
+
+declare void @system__string_ops__str_concat(%struct.string___XUP* noalias sret, [0 x i8]*, %struct.string___XUB*, [0 x i8]*, %struct.string___XUB*)
+
+declare i32 @report__ident_int(i32)

Added: llvm/trunk/test/Transforms/IndVarSimplify/iterationCount_zext_or_trunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iterationCount_zext_or_trunc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/iterationCount_zext_or_trunc.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/iterationCount_zext_or_trunc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -indvars -disable-output
+
+; ModuleID = 'testcase.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"
+target triple = "i686-pc-linux-gnu"
+
+define i32 @testcase(i5 zeroext  %k) {
+entry:
+	br label %bb2
+
+bb:		; preds = %bb2
+	%tmp1 = add i32 %tmp2, %result		; <i32> [#uses=1]
+	%indvar_next1 = add i5 %k_0, 1		; <i5> [#uses=1]
+	br label %bb2
+
+bb2:		; preds = %bb, %entry
+	%k_0 = phi i5 [ 0, %entry ], [ %indvar_next1, %bb ]		; <i5> [#uses=2]
+	%result = phi i32 [ 0, %entry ], [ %tmp1, %bb ]		; <i32> [#uses=2]
+	%tmp2 = zext i5 %k_0 to i32		; <i32> [#uses=1]
+	%exitcond = icmp eq i32 %tmp2, 16		; <i1> [#uses=1]
+	br i1 %exitcond, label %bb3, label %bb
+
+bb3:		; preds = %bb2
+	ret i32 %result
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
+
+; Indvars should be able to fold IV increments into shr when low bits are zero.
+;
+; CHECK-LABEL: @foldIncShr(
+; CHECK: shr.1 = lshr i32 %0, 5
+define i32 @foldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
+entry:
+  br label %while.body
+
+while.body:
+  %0 = phi i32 [ 0, %entry ], [ %inc.2, %while.body ]
+  %shr = lshr i32 %0, 5
+  %arrayidx = getelementptr inbounds i32, i32* %bitmap, i32 %shr
+  %tmp6 = load i32, i32* %arrayidx, align 4
+  %inc.1 = add i32 %0, 1
+  %shr.1 = lshr i32 %inc.1, 5
+  %arrayidx.1 = getelementptr inbounds i32, i32* %bitmap, i32 %shr.1
+  %tmp6.1 = load i32, i32* %arrayidx.1, align 4
+  %inc.2 = add i32 %inc.1, 1
+  %exitcond.3 = icmp eq i32 %inc.2, 128
+  br i1 %exitcond.3, label %while.end, label %while.body
+
+while.end:
+  %r = add i32 %tmp6, %tmp6.1
+  ret i32 %r
+}
+
+; Invdars should not fold an increment into shr unless 2^shiftBits is
+; a multiple of the recurrence step.
+;
+; CHECK-LABEL: @noFoldIncShr(
+; CHECK: shr.1 = lshr i32 %inc.1, 5
+define i32 @noFoldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
+entry:
+  br label %while.body
+
+while.body:
+  %0 = phi i32 [ 0, %entry ], [ %inc.3, %while.body ]
+  %shr = lshr i32 %0, 5
+  %arrayidx = getelementptr inbounds i32, i32* %bitmap, i32 %shr
+  %tmp6 = load i32, i32* %arrayidx, align 4
+  %inc.1 = add i32 %0, 1
+  %shr.1 = lshr i32 %inc.1, 5
+  %arrayidx.1 = getelementptr inbounds i32, i32* %bitmap, i32 %shr.1
+  %tmp6.1 = load i32, i32* %arrayidx.1, align 4
+  %inc.3 = add i32 %inc.1, 2
+  %exitcond.3 = icmp eq i32 %inc.3, 96
+  br i1 %exitcond.3, label %while.end, label %while.body
+
+while.end:
+  %r = add i32 %tmp6, %tmp6.1
+  ret i32 %r
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/iv-sext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-sext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/iv-sext.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/iv-sext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,149 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Indvars should be able to promote the hiPart induction variable in the
+; inner loop to i64.
+; TODO: it should promote hiPart to i64 in the outer loop too.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n32:64"
+
+define void @t(float* %pTmp1, float* %peakWeight, float* %nrgReducePeakrate, i32 %bandEdgeIndex, float %tmp1) nounwind {
+entry:
+	%tmp = load float, float* %peakWeight, align 4		; <float> [#uses=1]
+	%tmp2 = icmp sgt i32 %bandEdgeIndex, 0		; <i1> [#uses=1]
+	br i1 %tmp2, label %bb.nph22, label %return
+
+bb.nph22:		; preds = %entry
+	%tmp3 = add i32 %bandEdgeIndex, -1		; <i32> [#uses=2]
+	br label %bb
+
+; CHECK: bb:
+; CHECK: phi i64
+; CHECK-NOT: phi i64
+bb:		; preds = %bb8, %bb.nph22
+	%distERBhi.121 = phi float [ %distERBhi.2.lcssa, %bb8 ], [ 0.000000e+00, %bb.nph22 ]		; <float> [#uses=2]
+	%distERBlo.120 = phi float [ %distERBlo.0.lcssa, %bb8 ], [ 0.000000e+00, %bb.nph22 ]		; <float> [#uses=2]
+	%hiPart.119 = phi i32 [ %hiPart.0.lcssa, %bb8 ], [ 0, %bb.nph22 ]		; <i32> [#uses=3]
+	%loPart.118 = phi i32 [ %loPart.0.lcssa, %bb8 ], [ 0, %bb.nph22 ]		; <i32> [#uses=2]
+	%peakCount.117 = phi float [ %peakCount.2.lcssa, %bb8 ], [ %tmp, %bb.nph22 ]		; <float> [#uses=2]
+	%part.016 = phi i32 [ %tmp46, %bb8 ], [ 0, %bb.nph22 ]		; <i32> [#uses=5]
+	%tmp4 = icmp sgt i32 %part.016, 0		; <i1> [#uses=1]
+	br i1 %tmp4, label %bb1, label %bb3.preheader
+
+; CHECK: bb1:
+bb1:		; preds = %bb
+	%tmp5 = add i32 %part.016, -1		; <i32> [#uses=1]
+	%tmp6 = sext i32 %tmp5 to i64		; <i64> [#uses=1]
+	%tmp7 = getelementptr float, float* %pTmp1, i64 %tmp6		; <float*> [#uses=1]
+	%tmp8 = load float, float* %tmp7, align 4		; <float> [#uses=1]
+	%tmp9 = fadd float %tmp8, %distERBlo.120		; <float> [#uses=1]
+	%tmp10 = add i32 %part.016, -1		; <i32> [#uses=1]
+	%tmp11 = sext i32 %tmp10 to i64		; <i64> [#uses=1]
+	%tmp12 = getelementptr float, float* %pTmp1, i64 %tmp11		; <float*> [#uses=1]
+	%tmp13 = load float, float* %tmp12, align 4		; <float> [#uses=1]
+	%tmp14 = fsub float %distERBhi.121, %tmp13		; <float> [#uses=1]
+	br label %bb3.preheader
+
+bb3.preheader:		; preds = %bb1, %bb
+	%distERBlo.0.ph = phi float [ %distERBlo.120, %bb ], [ %tmp9, %bb1 ]		; <float> [#uses=3]
+	%distERBhi.0.ph = phi float [ %distERBhi.121, %bb ], [ %tmp14, %bb1 ]		; <float> [#uses=3]
+	%tmp15 = fcmp ogt float %distERBlo.0.ph, 2.500000e+00		; <i1> [#uses=1]
+	br i1 %tmp15, label %bb.nph, label %bb5.preheader
+
+bb.nph:		; preds = %bb3.preheader
+	br label %bb2
+
+bb2:		; preds = %bb3, %bb.nph
+	%distERBlo.03 = phi float [ %tmp19, %bb3 ], [ %distERBlo.0.ph, %bb.nph ]		; <float> [#uses=1]
+	%loPart.02 = phi i32 [ %tmp24, %bb3 ], [ %loPart.118, %bb.nph ]		; <i32> [#uses=3]
+	%peakCount.01 = phi float [ %tmp23, %bb3 ], [ %peakCount.117, %bb.nph ]		; <float> [#uses=1]
+	%tmp16 = sext i32 %loPart.02 to i64		; <i64> [#uses=1]
+	%tmp17 = getelementptr float, float* %pTmp1, i64 %tmp16		; <float*> [#uses=1]
+	%tmp18 = load float, float* %tmp17, align 4		; <float> [#uses=1]
+	%tmp19 = fsub float %distERBlo.03, %tmp18		; <float> [#uses=3]
+	%tmp20 = sext i32 %loPart.02 to i64		; <i64> [#uses=1]
+	%tmp21 = getelementptr float, float* %peakWeight, i64 %tmp20		; <float*> [#uses=1]
+	%tmp22 = load float, float* %tmp21, align 4		; <float> [#uses=1]
+	%tmp23 = fsub float %peakCount.01, %tmp22		; <float> [#uses=2]
+	%tmp24 = add i32 %loPart.02, 1		; <i32> [#uses=2]
+	br label %bb3
+
+bb3:		; preds = %bb2
+	%tmp25 = fcmp ogt float %tmp19, 2.500000e+00		; <i1> [#uses=1]
+	br i1 %tmp25, label %bb2, label %bb3.bb5.preheader_crit_edge
+
+bb3.bb5.preheader_crit_edge:		; preds = %bb3
+	%tmp24.lcssa = phi i32 [ %tmp24, %bb3 ]		; <i32> [#uses=1]
+	%tmp23.lcssa = phi float [ %tmp23, %bb3 ]		; <float> [#uses=1]
+	%tmp19.lcssa = phi float [ %tmp19, %bb3 ]		; <float> [#uses=1]
+	br label %bb5.preheader
+
+bb5.preheader:		; preds = %bb3.bb5.preheader_crit_edge, %bb3.preheader
+	%distERBlo.0.lcssa = phi float [ %tmp19.lcssa, %bb3.bb5.preheader_crit_edge ], [ %distERBlo.0.ph, %bb3.preheader ]		; <float> [#uses=2]
+	%loPart.0.lcssa = phi i32 [ %tmp24.lcssa, %bb3.bb5.preheader_crit_edge ], [ %loPart.118, %bb3.preheader ]		; <i32> [#uses=1]
+	%peakCount.0.lcssa = phi float [ %tmp23.lcssa, %bb3.bb5.preheader_crit_edge ], [ %peakCount.117, %bb3.preheader ]		; <float> [#uses=2]
+	%.not10 = fcmp olt float %distERBhi.0.ph, 2.500000e+00		; <i1> [#uses=1]
+	%tmp26 = icmp sgt i32 %tmp3, %hiPart.119		; <i1> [#uses=1]
+	%or.cond11 = and i1 %tmp26, %.not10		; <i1> [#uses=1]
+	br i1 %or.cond11, label %bb.nph12, label %bb7
+
+bb.nph12:		; preds = %bb5.preheader
+	br label %bb4
+; CHECK: bb4:
+; CHECK: phi i64
+; CHECK-NOT: phi i64
+; CHECK-NOT: sext
+bb4:		; preds = %bb5, %bb.nph12
+	%distERBhi.29 = phi float [ %tmp30, %bb5 ], [ %distERBhi.0.ph, %bb.nph12 ]		; <float> [#uses=1]
+	%hiPart.08 = phi i32 [ %tmp31, %bb5 ], [ %hiPart.119, %bb.nph12 ]		; <i32> [#uses=2]
+	%peakCount.27 = phi float [ %tmp35, %bb5 ], [ %peakCount.0.lcssa, %bb.nph12 ]		; <float> [#uses=1]
+	%tmp27 = sext i32 %hiPart.08 to i64		; <i64> [#uses=1]
+	%tmp28 = getelementptr float, float* %pTmp1, i64 %tmp27		; <float*> [#uses=1]
+	%tmp29 = load float, float* %tmp28, align 4		; <float> [#uses=1]
+	%tmp30 = fadd float %tmp29, %distERBhi.29		; <float> [#uses=3]
+	%tmp31 = add i32 %hiPart.08, 1		; <i32> [#uses=4]
+	%tmp32 = sext i32 %tmp31 to i64		; <i64> [#uses=1]
+	%tmp33 = getelementptr float, float* %peakWeight, i64 %tmp32		; <float*> [#uses=1]
+	%tmp34 = load float, float* %tmp33, align 4		; <float> [#uses=1]
+	%tmp35 = fadd float %tmp34, %peakCount.27		; <float> [#uses=2]
+	br label %bb5
+
+; CHECK: bb5:
+bb5:		; preds = %bb4
+	%.not = fcmp olt float %tmp30, 2.500000e+00		; <i1> [#uses=1]
+	%tmp36 = icmp sgt i32 %tmp3, %tmp31		; <i1> [#uses=1]
+	%or.cond = and i1 %tmp36, %.not		; <i1> [#uses=1]
+	br i1 %or.cond, label %bb4, label %bb5.bb7_crit_edge
+
+bb5.bb7_crit_edge:		; preds = %bb5
+	%tmp35.lcssa = phi float [ %tmp35, %bb5 ]		; <float> [#uses=1]
+	%tmp31.lcssa = phi i32 [ %tmp31, %bb5 ]		; <i32> [#uses=1]
+	%tmp30.lcssa = phi float [ %tmp30, %bb5 ]		; <float> [#uses=1]
+	br label %bb7
+
+bb7:		; preds = %bb5.bb7_crit_edge, %bb5.preheader
+	%distERBhi.2.lcssa = phi float [ %tmp30.lcssa, %bb5.bb7_crit_edge ], [ %distERBhi.0.ph, %bb5.preheader ]		; <float> [#uses=2]
+	%hiPart.0.lcssa = phi i32 [ %tmp31.lcssa, %bb5.bb7_crit_edge ], [ %hiPart.119, %bb5.preheader ]		; <i32> [#uses=1]
+	%peakCount.2.lcssa = phi float [ %tmp35.lcssa, %bb5.bb7_crit_edge ], [ %peakCount.0.lcssa, %bb5.preheader ]		; <float> [#uses=2]
+	%tmp37 = fadd float %distERBlo.0.lcssa, %distERBhi.2.lcssa		; <float> [#uses=1]
+	%tmp38 = fdiv float %peakCount.2.lcssa, %tmp37		; <float> [#uses=1]
+	%tmp39 = fmul float %tmp38, %tmp1		; <float> [#uses=2]
+	%tmp40 = fmul float %tmp39, %tmp39		; <float> [#uses=2]
+	%tmp41 = fmul float %tmp40, %tmp40		; <float> [#uses=1]
+	%tmp42 = fadd float %tmp41, 1.000000e+00		; <float> [#uses=1]
+	%tmp43 = fdiv float 1.000000e+00, %tmp42		; <float> [#uses=1]
+	%tmp44 = sext i32 %part.016 to i64		; <i64> [#uses=1]
+	%tmp45 = getelementptr float, float* %nrgReducePeakrate, i64 %tmp44		; <float*> [#uses=1]
+	store float %tmp43, float* %tmp45, align 4
+	%tmp46 = add i32 %part.016, 1		; <i32> [#uses=2]
+	br label %bb8
+
+bb8:		; preds = %bb7
+	%tmp47 = icmp slt i32 %tmp46, %bandEdgeIndex		; <i1> [#uses=1]
+	br i1 %tmp47, label %bb, label %bb8.return_crit_edge
+
+bb8.return_crit_edge:		; preds = %bb8
+	br label %return
+
+return:		; preds = %bb8.return_crit_edge, %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,359 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-p:64:64:64-n8:16:32:64-S128"
+
+; When widening IV and its users, trunc and zext/sext are not needed
+; if the original 32-bit user is known to be non-negative, whether
+; the IV is considered signed or unsigned.
+define void @foo(i32* %A, i32* %B, i32* %C, i32 %N) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %N
+; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
+; CHECK:       for.body.lr.ph:
+; CHECK-NEXT:    br label %for.body
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* %B, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2
+; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* %C, i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
+; CHECK-NEXT:    [[ADD3:%.*]] = add nsw i32 [[TMP0]], [[TMP2]]
+; CHECK-NEXT:    [[TRUNC0:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT:    [[DIV0:%.*]] = udiv i32 5, [[TRUNC0]]
+; CHECK-NEXT:    [[ADD4:%.*]] = add nsw i32 [[ADD3]], [[DIV0]]
+; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, i32* %A, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i32 [[ADD4]], i32* [[ARRAYIDX5]], align 4
+; CHECK-NEXT:    br label %for.inc
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %N to i64
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
+; CHECK:       for.cond.for.end_crit_edge:
+; CHECK-NEXT:    br label %for.end
+; CHECK:       for.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp1 = icmp slt i32 0, %N
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:                                   ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.inc
+  %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
+  %idxprom = sext i32 %i.02 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %i.02, 2
+  %idxprom1 = zext i32 %add to i64
+  %arrayidx2 = getelementptr inbounds i32, i32* %C, i64 %idxprom1
+  %1 = load i32, i32* %arrayidx2, align 4
+  %add3 = add nsw i32 %0, %1
+  %div0 = udiv i32 5, %add
+  %add4 = add nsw i32 %add3, %div0
+  %idxprom4 = zext i32 %i.02 to i64
+  %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %idxprom4
+  store i32 %add4, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.02, 1
+  %cmp = icmp slt i32 %inc, %N
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.inc
+  br label %for.end
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
+  ret void
+}
+
+define void @foo1(i32* %A, i32* %B, i32* %C, i32 %N) {
+; CHECK-LABEL: @foo1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %N
+; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
+; CHECK:       for.body.lr.ph:
+; CHECK-NEXT:    br label %for.body
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* %B, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2
+; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* %C, i64 [[TMP1]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
+; CHECK-NEXT:    [[ADD3:%.*]] = add nsw i32 [[TMP0]], [[TMP2]]
+; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, i32* %A, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i32 [[ADD3]], i32* [[ARRAYIDX5]], align 4
+; CHECK-NEXT:    br label %for.inc
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %N to i64
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
+; CHECK:       for.cond.for.end_crit_edge:
+; CHECK-NEXT:    br label %for.end
+; CHECK:       for.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp1 = icmp slt i32 0, %N
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:                                   ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.inc
+  %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
+  %idxprom = zext i32 %i.02 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %i.02, 2
+  %idxprom1 = sext i32 %add to i64
+  %arrayidx2 = getelementptr inbounds i32, i32* %C, i64 %idxprom1
+  %1 = load i32, i32* %arrayidx2, align 4
+  %add3 = add nsw i32 %0, %1
+  %idxprom4 = sext i32 %i.02 to i64
+  %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %idxprom4
+  store i32 %add3, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.02, 1
+  %cmp = icmp slt i32 %inc, %N
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.inc
+  br label %for.end
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
+  ret void
+}
+
+
+ at a = common global [100 x i32] zeroinitializer, align 16
+ at b = common global [100 x i32] zeroinitializer, align 16
+
+define i32 @foo2(i32 %M) {
+; CHECK-LABEL: @foo2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %M
+; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
+; CHECK:       for.body.lr.ph:
+; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 %M to i64
+; CHECK-NEXT:    br label %for.body
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
+; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[TMP3]]
+; CHECK-NEXT:    store i32 [[ADD]], i32* [[ARRAYIDX5]], align 4
+; CHECK-NEXT:    br label %for.inc
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %M to i64
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
+; CHECK:       for.cond.for.end_crit_edge:
+; CHECK-NEXT:    br label %for.end
+; CHECK:       for.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %cmp1 = icmp slt i32 0, %M
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:                                   ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.inc
+  %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
+  %idxprom = zext i32 %i.02 to i64
+  %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %idxprom1 = sext i32 %i.02 to i64
+  %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 %idxprom1
+  %1 = load i32, i32* %arrayidx2, align 4
+  %add = add nsw i32 %0, %1
+  %add3 = add nsw i32 %i.02, %M
+  %idxprom4 = sext i32 %add3 to i64
+  %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom4
+  store i32 %add, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.02, 1
+  %cmp = icmp slt i32 %inc, %M
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.inc
+  br label %for.end
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
+  %call = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
+  ret i32 0
+}
+
+declare i32 @dummy(i32*, i32*)
+
+; A case where zext should not be eliminated when its operands could only be extended by sext.
+define i32 @foo3(i32 %M) {
+; CHECK-LABEL: @foo3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %M
+; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
+; CHECK:       for.body.lr.ph:
+; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 %M to i64
+; CHECK-NEXT:    br label %for.body
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
+; CHECK-NEXT:    [[IDXPROM4:%.*]] = zext i32 [[TMP4]] to i64
+; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[IDXPROM4]]
+; CHECK-NEXT:    store i32 [[ADD]], i32* [[ARRAYIDX5]], align 4
+; CHECK-NEXT:    br label %for.inc
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %M to i64
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
+; CHECK:       for.cond.for.end_crit_edge:
+; CHECK-NEXT:    br label %for.end
+; CHECK:       for.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %cmp1 = icmp slt i32 0, %M
+  br i1 %cmp1, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:                                   ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.inc
+  %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
+  %idxprom = sext i32 %i.02 to i64
+  %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %idxprom1 = sext i32 %i.02 to i64
+  %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 %idxprom1
+  %1 = load i32, i32* %arrayidx2, align 4
+  %add = add nsw i32 %0, %1
+  %add3 = add nsw i32 %i.02, %M
+  %idxprom4 = zext i32 %add3 to i64
+  %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom4
+  store i32 %add, i32* %arrayidx5, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.02, 1
+  %cmp = icmp slt i32 %inc, %M
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.inc
+  br label %for.end
+
+for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
+  %call = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
+  ret i32 0
+}
+
+%struct.image = type {i32, i32}
+define i32 @foo4(%struct.image* %input, i32 %length, i32* %in) {
+entry:
+  %stride = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 1
+  %0 = load i32, i32* %stride, align 4
+  %cmp17 = icmp sgt i32 %length, 1
+  br i1 %cmp17, label %for.body.lr.ph, label %for.cond.cleanup
+
+for.body.lr.ph:                                   ; preds = %entry
+  %channel = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 0
+  br label %for.body
+
+for.cond.cleanup.loopexit:                        ; preds = %for.body
+  %1 = phi i32 [ %6, %for.body ]
+  br label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit, %entry
+  %2 = phi i32 [ 0, %entry ], [ %1, %for.cond.cleanup.loopexit ]
+  ret i32 %2
+
+; mul instruction below is widened instead of generating a truncate instruction for it
+; regardless if Load operand of mul is inside or outside the loop (we have both cases).
+; CHECK: for.body:
+; CHECK-NOT: trunc
+for.body:                                         ; preds = %for.body.lr.ph, %for.body
+  %x.018 = phi i32 [ 1, %for.body.lr.ph ], [ %add, %for.body ]
+  %add = add nuw nsw i32 %x.018, 1
+  %3 = load i32, i32* %channel, align 8
+  %mul = mul nsw i32 %3, %add
+  %idx.ext = sext i32 %mul to i64
+  %add.ptr = getelementptr inbounds i32, i32* %in, i64 %idx.ext
+  %4 = load i32, i32* %add.ptr, align 4
+  %mul1 = mul nsw i32 %0, %add
+  %idx.ext1 = sext i32 %mul1 to i64
+  %add.ptr1 = getelementptr inbounds i32, i32* %in, i64 %idx.ext1
+  %5 = load i32, i32* %add.ptr1, align 4
+  %6 = add i32 %4, %5
+  %cmp = icmp slt i32 %add, %length
+  br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit
+}
+
+
+define i32 @foo5(%struct.image* %input, i32 %length, i32* %in) {
+entry:
+  %stride = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 1
+  %0 = load i32, i32* %stride, align 4
+  %cmp17 = icmp sgt i32 %length, 1
+  br i1 %cmp17, label %for.body.lr.ph, label %for.cond.cleanup
+
+for.body.lr.ph:                                   ; preds = %entry
+  %channel = getelementptr inbounds %struct.image, %struct.image* %input, i64 0, i32 0
+  br label %for.body
+
+for.cond.cleanup.loopexit:                        ; preds = %for.body
+  %1 = phi i32 [ %7, %for.body ]
+  br label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit, %entry
+  %2 = phi i32 [ 0, %entry ], [ %1, %for.cond.cleanup.loopexit ]
+  ret i32 %2
+
+; This example is the same as above except that the first mul is used in two places
+; and this may result in having two versions of the multiply: an i32 and i64 version.
+; In this case, keep the trucate instructions to avoid this redundancy.
+; CHECK: for.body:
+; CHECK: trunc
+for.body:                                         ; preds = %for.body.lr.ph, %for.body
+  %x.018 = phi i32 [ 1, %for.body.lr.ph ], [ %add, %for.body ]
+  %add = add nuw nsw i32 %x.018, 1
+  %3 = load i32, i32* %channel, align 8
+  %mul = mul nsw i32 %3, %add
+  %idx.ext = sext i32 %mul to i64
+  %add.ptr = getelementptr inbounds i32, i32* %in, i64 %idx.ext
+  %4 = load i32, i32* %add.ptr, align 4
+  %mul1 = mul nsw i32 %0, %add
+  %idx.ext1 = sext i32 %mul1 to i64
+  %add.ptr1 = getelementptr inbounds i32, i32* %in, i64 %idx.ext1
+  %5 = load i32, i32* %add.ptr1, align 4
+  %6 = add i32 %4, %5
+  %7 = add i32 %6, %mul
+  %cmp = icmp slt i32 %add, %length
+  br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/iv-widen.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-widen.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/iv-widen.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/iv-widen.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,160 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; RUN: opt -lcssa -loop-simplify -S < %s | opt -S -passes='require<targetir>,require<scalar-evolution>,require<domtree>,loop(indvars)'
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+target triple = "x86_64-apple-darwin"
+
+declare void @use(i64 %x)
+
+; CHECK-LABEL: @loop_0
+; CHECK-LABEL: B18:
+; Only one phi now.
+; CHECK: phi i64
+; CHECK-NOT: phi
+; One trunc for the gep.
+; CHECK: trunc i64 %indvars.iv to i32
+; One trunc for the dummy() call.
+; CHECK-LABEL: exit24:
+; CHECK: trunc i64 {{.*}}lcssa.wide to i32
+define void @loop_0(i32* %a) {
+Prologue:
+  br i1 undef, label %B18, label %B6
+
+B18:                                        ; preds = %B24, %Prologue
+  %.02 = phi i32 [ 0, %Prologue ], [ %tmp33, %B24 ]
+  %tmp23 = zext i32 %.02 to i64
+  call void @use(i64 %tmp23)
+  %tmp33 = add i32 %.02, 1
+  %o = getelementptr i32, i32* %a, i32 %.02
+  %v = load i32, i32* %o
+  %t = icmp eq i32 %v, 0
+  br i1 %t, label %exit24, label %B24
+
+B24:                                        ; preds = %B18
+  %t2 = icmp eq i32 %tmp33, 20
+  br i1 %t2, label %B6, label %B18
+
+B6:                                       ; preds = %Prologue
+  ret void
+
+exit24:                      ; preds = %B18
+  call void @dummy(i32 %.02)
+  unreachable
+}
+
+; Make sure that dead zext is removed and no widening happens.
+; CHECK-LABEL: @loop_0.dead
+; CHECK: phi i32
+; CHECK-NOT: zext
+; CHECK-NOT: trunc
+define void @loop_0.dead(i32* %a) {
+Prologue:
+  br i1 undef, label %B18, label %B6
+
+B18:                                        ; preds = %B24, %Prologue
+  %.02 = phi i32 [ 0, %Prologue ], [ %tmp33, %B24 ]
+  %tmp23 = zext i32 %.02 to i64
+  %tmp33 = add i32 %.02, 1
+  %o = getelementptr i32, i32* %a, i32 %.02
+  %v = load i32, i32* %o
+  %t = icmp eq i32 %v, 0
+  br i1 %t, label %exit24, label %B24
+
+B24:                                        ; preds = %B18
+  %t2 = icmp eq i32 %tmp33, 20
+  br i1 %t2, label %B6, label %B18
+
+B6:                                       ; preds = %Prologue
+  ret void
+
+exit24:                      ; preds = %B18
+  call void @dummy(i32 %.02)
+  unreachable
+}
+
+define void @loop_1(i32 %lim) {
+; CHECK-LABEL: @loop_1(
+ entry:
+  %entry.cond = icmp ne i32 %lim, 0
+  br i1 %entry.cond, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+; CHECK:  %indvars.iv = phi i64 [ 1, %loop.preheader ], [ %indvars.iv.next, %loop ]
+; CHECK:  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK:  [[IV_INC:%[^ ]+]] = add nsw i64 %indvars.iv, -1
+; CHECK:  call void @dummy.i64(i64 [[IV_INC]])
+
+  %iv = phi i32 [ 1, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i32 %iv, 1
+  %iv.inc.sub = add i32 %iv, -1
+  %iv.inc.sub.zext = zext i32 %iv.inc.sub to i64
+  call void @dummy.i64(i64 %iv.inc.sub.zext)
+  %be.cond = icmp ult i32 %iv.inc, %lim
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}
+
+declare void @dummy(i32)
+declare void @dummy.i64(i64)
+
+
+define void @loop_2(i32 %size, i32 %nsteps, i32 %hsize, i32* %lined, i8 %tmp1) {
+; CHECK-LABEL: @loop_2(
+entry:
+  %cmp215 = icmp sgt i32 %size, 1
+  %tmp0 = bitcast i32* %lined to i8*
+  br label %for.body
+
+for.body:
+  %j = phi i32 [ 0, %entry ], [ %inc6, %for.inc ]
+  %mul = mul nsw i32 %j, %size
+  %add = add nsw i32 %mul, %hsize
+  br i1 %cmp215, label %for.body2, label %for.inc
+
+; check that the induction variable of the inner loop has been widened after indvars.
+; CHECK:  [[INNERLOOPINV:%[^ ]+]] = add nsw i64
+; CHECK: for.body2:
+; CHECK-NEXT:  %indvars.iv = phi i64 [ 1, %for.body2.preheader ], [ %indvars.iv.next, %for.body2 ]
+; CHECK-NEXT:  [[WIDENED:%[^ ]+]] = add nsw i64 [[INNERLOOPINV]], %indvars.iv
+; CHECK-NEXT:  %add.ptr = getelementptr inbounds i8, i8* %tmp0, i64 [[WIDENED]]
+for.body2:
+  %k = phi i32 [ %inc, %for.body2 ], [ 1, %for.body ]
+  %add4 = add nsw i32 %add, %k
+  %idx.ext = sext i32 %add4 to i64
+  %add.ptr = getelementptr inbounds i8, i8* %tmp0, i64 %idx.ext
+  store i8 %tmp1, i8* %add.ptr, align 1
+  %inc = add nsw i32 %k, 1
+  %cmp2 = icmp slt i32 %inc, %size
+  br i1 %cmp2, label %for.body2, label %for.body3
+
+; check that the induction variable of the inner loop has been widened after indvars.
+; CHECK: for.body3.preheader:
+; CHECK:  [[INNERLOOPINV:%[^ ]+]] = zext i32
+; CHECK: for.body3:
+; CHECK-NEXT:  %indvars.iv2 = phi i64 [ 1, %for.body3.preheader ], [ %indvars.iv.next3, %for.body3 ]
+; CHECK-NEXT:  [[WIDENED:%[^ ]+]] = add nuw nsw i64 [[INNERLOOPINV]], %indvars.iv2
+; CHECK-NEXT:  %add.ptr2 = getelementptr inbounds i8, i8* %tmp0, i64 [[WIDENED]]
+for.body3:
+  %l = phi i32 [ %inc2, %for.body3 ], [ 1, %for.body2 ]
+  %add5 = add nuw i32 %add, %l
+  %idx.ext2 = zext i32 %add5 to i64
+  %add.ptr2 = getelementptr inbounds i8, i8* %tmp0, i64 %idx.ext2
+  store i8 %tmp1, i8* %add.ptr2, align 1
+  %inc2 = add nsw i32 %l, 1
+  %cmp3 = icmp slt i32 %inc2, %size
+  br i1 %cmp3, label %for.body3, label %for.inc
+
+for.inc:
+  %inc6 = add nsw i32 %j, 1
+  %cmp = icmp slt i32 %inc6, %nsteps
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/iv-zext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-zext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/iv-zext.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/iv-zext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; CHECK-NOT: and
+; CHECK-NOT: zext
+
+target datalayout = "p:64:64:64-n32:64"
+
+define void @foo(double* %d, i64 %n) nounwind {
+entry:
+	br label %loop
+
+loop:
+	%indvar = phi i64 [ 0, %entry ], [ %indvar.next, %loop ]
+	%indvar.i8 = and i64 %indvar, 255
+	%t0 = getelementptr double, double* %d, i64 %indvar.i8
+	%t1 = load double, double* %t0
+	%t2 = fmul double %t1, 0.1
+	store double %t2, double* %t0
+	%indvar.i24 = and i64 %indvar, 16777215
+	%t3 = getelementptr double, double* %d, i64 %indvar.i24
+	%t4 = load double, double* %t3
+	%t5 = fmul double %t4, 2.3
+	store double %t5, double* %t3
+	%t6 = getelementptr double, double* %d, i64 %indvar
+	%t7 = load double, double* %t6
+	%t8 = fmul double %t7, 4.5
+	store double %t8, double* %t6
+	%indvar.next = add i64 %indvar, 1
+	%exitcond = icmp eq i64 %indvar.next, 10
+	br i1 %exitcond, label %return, label %loop
+
+return:
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lcssa-preservation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lcssa-preservation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lcssa-preservation.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lcssa-preservation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt < %s -indvars -replexitval=always -S | FileCheck %s
+; Make sure IndVars preserves LCSSA form, especially across loop nests. 
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+define void @PR18642(i32 %x) {
+; CHECK-LABEL: @PR18642(
+entry:
+  br label %outer.header
+; CHECK:   br label %outer.header
+
+outer.header:
+; CHECK: outer.header:
+  %outer.iv = phi i32 [ 0, %entry ], [ %x, %outer.latch ]
+  br label %inner.header
+; CHECK:   %[[SCEV_EXPANDED:.*]] = add i32
+; CHECK:   br label %inner.header
+
+inner.header:
+; CHECK: inner.header:
+  %inner.iv = phi i32 [ undef, %outer.header ], [ %inc, %inner.latch ]
+  %cmp1 = icmp slt i32 %inner.iv, %outer.iv
+  br i1 %cmp1, label %inner.latch, label %outer.latch
+; CHECK:   br i1 {{.*}}, label %inner.latch, label %outer.latch
+
+inner.latch:
+; CHECK: inner.latch:
+  %inc = add nsw i32 %inner.iv, 1
+  %cmp2 = icmp slt i32 %inner.iv, %outer.iv
+  br i1 %cmp2, label %inner.header, label %exit
+; CHECK:   br i1 {{.*}}, label %inner.header, label %[[EXIT_FROM_INNER:.*]]
+
+outer.latch:
+; CHECK: outer.latch:
+  br i1 undef, label %outer.header, label %exit
+; CHECK:   br i1 {{.*}}, label %outer.header, label %[[EXIT_FROM_OUTER:.*]]
+
+; CHECK: [[EXIT_FROM_INNER]]:
+; CHECK-NEXT: %[[LCSSA:.*]] = phi i32 [ %[[SCEV_EXPANDED]], %inner.latch ]
+; CHECK-NEXT: br label %exit
+
+; CHECK: [[EXIT_FROM_OUTER]]:
+; CHECK-NEXT: br label %exit
+
+exit:
+; CHECK: exit:
+  %exit.phi = phi i32 [ %inc, %inner.latch ], [ undef, %outer.latch ]
+; CHECK-NEXT: phi i32 [ %[[LCSSA]], %[[EXIT_FROM_INNER]] ], [ undef, %[[EXIT_FROM_OUTER]] ]
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -S -indvars -o - %s | FileCheck %s
+target datalayout = "e-p:32:32:32-p1:64:64:64-p2:8:8:8-p3:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-n8:16:32:64"
+
+; Derived from ptriv in lftr-reuse.ll
+define void @ptriv_as2(i8 addrspace(2)* %base, i32 %n) nounwind {
+; CHECK-LABEL: @ptriv_as2(
+entry:
+  %idx.trunc = trunc i32 %n to i8
+  %add.ptr = getelementptr inbounds i8, i8 addrspace(2)* %base, i8 %idx.trunc
+  %cmp1 = icmp ult i8 addrspace(2)* %base, %add.ptr
+  br i1 %cmp1, label %for.body, label %for.end
+
+; Make sure the added GEP has the right index type
+; CHECK: %lftr.limit = getelementptr i8, i8 addrspace(2)* %base, i8 %idx.trunc
+
+; CHECK: for.body:
+; CHECK: phi i8 addrspace(2)*
+; CHECK-NOT: phi
+; CHECK-NOT: add{{^rspace}}
+; CHECK: icmp ne i8 addrspace(2)*
+; CHECK: br i1
+for.body:
+  %p.02 = phi i8 addrspace(2)* [ %base, %entry ], [ %incdec.ptr, %for.body ]
+  ; cruft to make the IV useful
+  %sub.ptr.lhs.cast = ptrtoint i8 addrspace(2)* %p.02 to i8
+  %sub.ptr.rhs.cast = ptrtoint i8 addrspace(2)* %base to i8
+  %sub.ptr.sub = sub i8 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  store i8 %sub.ptr.sub, i8 addrspace(2)* %p.02
+  %incdec.ptr = getelementptr inbounds i8, i8 addrspace(2)* %p.02, i32 1
+  %cmp = icmp ult i8 addrspace(2)* %incdec.ptr, %add.ptr
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+
+define void @ptriv_as3(i8 addrspace(3)* %base, i32 %n) nounwind {
+; CHECK-LABEL: @ptriv_as3(
+entry:
+  %idx.trunc = trunc i32 %n to i16
+  %add.ptr = getelementptr inbounds i8, i8 addrspace(3)* %base, i16 %idx.trunc
+  %cmp1 = icmp ult i8 addrspace(3)* %base, %add.ptr
+  br i1 %cmp1, label %for.body, label %for.end
+
+; Make sure the added GEP has the right index type
+; CHECK: %lftr.limit = getelementptr i8, i8 addrspace(3)* %base, i16 %idx.trunc
+
+; CHECK: for.body:
+; CHECK: phi i8 addrspace(3)*
+; CHECK-NOT: phi
+; CHECK-NOT: add{{^rspace}}
+; CHECK: icmp ne i8 addrspace(3)*
+; CHECK: br i1
+for.body:
+  %p.02 = phi i8 addrspace(3)* [ %base, %entry ], [ %incdec.ptr, %for.body ]
+  ; cruft to make the IV useful
+  %sub.ptr.lhs.cast = ptrtoint i8 addrspace(3)* %p.02 to i16
+  %sub.ptr.rhs.cast = ptrtoint i8 addrspace(3)* %base to i16
+  %sub.ptr.sub = sub i16 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  %conv = trunc i16 %sub.ptr.sub to i8
+  store i8 %conv, i8 addrspace(3)* %p.02
+  %incdec.ptr = getelementptr inbounds i8, i8 addrspace(3)* %p.02, i32 1
+  %cmp = icmp ult i8 addrspace(3)* %incdec.ptr, %add.ptr
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-extend-const.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-extend-const.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-extend-const.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-extend-const.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+;RUN: opt -S %s -indvars | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+; CHECK-LABEL: @foo(
+; CHECK-NOT: %lftr.wideiv = trunc i32 %indvars.iv.next to i16
+; CHECK: %exitcond = icmp ne i32 %indvars.iv.next, 512
+define void @foo() #0 {
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i16 [ 0, %entry ], [ %inc, %for.body ]
+  %conv2 = sext i16 %i.01 to i32
+  call void @bar(i32 %conv2) #1
+  %inc = add i16 %i.01, 1
+  %cmp = icmp slt i16 %inc, 512
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  ret void
+}
+
+; Check that post-incrementing the backedge taken count does not overflow.
+; CHECK-LABEL: @postinc(
+; CHECK: icmp eq i32 %indvars.iv, 255
+define i32 @postinc() #0 {
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %entry
+  %first.0 = phi i8 [ 0, %entry ], [ %inc, %do.body ]
+  %conv = zext i8 %first.0 to i32
+  call void  @bar(i32 %conv) #1
+  %inc = add i8 %first.0, 1
+  %cmp = icmp eq i8 %first.0, -1
+  br i1 %cmp, label %do.end, label %do.body
+
+do.end:                                           ; preds = %do.body
+  ret i32 0
+}
+
+declare void @bar(i32)
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind }

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-other-uses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-other-uses.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-other-uses.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-other-uses.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -indvars -disable-output
+
+; Don't RAUW the loop's original comparison instruction if it has
+; other uses which aren't dominated by the new comparison instruction.
+
+	%struct.DecRefPicMarking_s = type { i32, i32, i32, i32, i32, %struct.DecRefPicMarking_s* }
+	%struct.datapartition = type { %typedef.Bitstream*, %typedef.DecodingEnvironment, i32 (%struct.syntaxelement*, %struct.img_par*, %struct.inp_par*, %struct.datapartition*)* }
+	%struct.img_par = type { i32, i32, i32, i32, i32*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [16 x [16 x i16]], [6 x [32 x i32]], [16 x [16 x i32]], [4 x [12 x [4 x [4 x i32]]]], [16 x i32], i32**, i32*, i32***, i32**, i32, i32, i32, i32, %typedef.Slice*, %struct.macroblock*, i32, i32, i32, i32, i32, i32, i32**, %struct.DecRefPicMarking_s*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [3 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32***, i32***, i32****, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %struct.timeb, %struct.timeb, i32, i32, i32, i32, i32, i32, i32, i32 }
+	%struct.inp_par = type { [100 x i8], [100 x i8], [100 x i8], i32, i32, i32, i32, i32, i32, i32 }
+	%struct.macroblock = type { i32, i32, i32, %struct.macroblock*, %struct.macroblock*, i32, [2 x [4 x [4 x [2 x i32]]]], i32, i64, i64, i32, i32, [4 x i32], [4 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }
+	%struct.syntaxelement = type { i32, i32, i32, i32, i32, i32, i32, i32, void (i32, i32, i32*, i32*)*, void (%struct.syntaxelement*, %struct.inp_par*, %struct.img_par*, %typedef.DecodingEnvironment*)* }
+	%struct.timeb = type { i32, i16, i16, i16 }
+	%typedef.BiContextType = type { i16, i8 }
+	%typedef.Bitstream = type { i32, i32, i32, i32, i8*, i32 }
+	%typedef.DecodingEnvironment = type { i32, i32, i32, i32, i32, i8*, i32* }
+	%typedef.MotionInfoContexts = type { [4 x [11 x %typedef.BiContextType]], [2 x [9 x %typedef.BiContextType]], [2 x [10 x %typedef.BiContextType]], [2 x [6 x %typedef.BiContextType]], [4 x %typedef.BiContextType], [4 x %typedef.BiContextType], [3 x %typedef.BiContextType] }
+	%typedef.Slice = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, %struct.datapartition*, %typedef.MotionInfoContexts*, %typedef.TextureInfoContexts*, i32, i32*, i32*, i32*, i32, i32*, i32*, i32*, i32 (%struct.img_par*, %struct.inp_par*)*, i32, i32, i32, i32 }
+	%typedef.TextureInfoContexts = type { [2 x %typedef.BiContextType], [4 x %typedef.BiContextType], [3 x [4 x %typedef.BiContextType]], [10 x [4 x %typedef.BiContextType]], [10 x [15 x %typedef.BiContextType]], [10 x [15 x %typedef.BiContextType]], [10 x [5 x %typedef.BiContextType]], [10 x [5 x %typedef.BiContextType]], [10 x [15 x %typedef.BiContextType]], [10 x [15 x %typedef.BiContextType]] }
+
+define void @readCBP_CABAC(%struct.syntaxelement* %se, %struct.inp_par* %inp, %struct.img_par* %img.1, %typedef.DecodingEnvironment* %dep_dp) {
+entry:
+	br label %loopentry.0
+
+loopentry.0:		; preds = %loopentry.1, %entry
+	%mb_y.0 = phi i32 [ 0, %entry ], [ %tmp.152, %loopentry.1 ]		; <i32> [#uses=2]
+	%tmp.14 = icmp sle i32 %mb_y.0, 3		; <i1> [#uses=2]
+	%tmp.15 = zext i1 %tmp.14 to i32		; <i32> [#uses=0]
+	br i1 %tmp.14, label %loopentry.1, label %loopexit.0
+
+loopentry.1:		; preds = %loopentry.0
+	%tmp.152 = add i32 %mb_y.0, 2		; <i32> [#uses=1]
+	br label %loopentry.0
+
+loopexit.0:		; preds = %loopentry.0
+	unreachable
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-promote.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-promote.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-promote.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-promote.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Indvars should be able to compute the exit value of this loop
+; without any additional arithmetic. The only add needed should
+; be the canonical IV increment.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+
+define void @foo(double* %p, i32 %n) nounwind {
+; CHECK-LABEL: @foo(
+; CHECK: add
+; CHECK-NOT: add
+
+entry:
+	%0 = icmp sgt i32 %n, 0		; <i1> [#uses=1]
+	br i1 %0, label %bb.nph, label %return
+
+bb.nph:		; preds = %entry
+	br label %bb2
+
+bb2:		; preds = %bb3, %bb.nph
+	%i.01 = phi i32 [ %7, %bb3 ], [ 0, %bb.nph ]		; <i32> [#uses=3]
+	%1 = sext i32 %i.01 to i64		; <i64> [#uses=1]
+	%2 = getelementptr double, double* %p, i64 %1		; <double*> [#uses=1]
+	%3 = load double, double* %2, align 8		; <double> [#uses=1]
+	%4 = fmul double %3, 1.100000e+00		; <double> [#uses=1]
+	%5 = sext i32 %i.01 to i64		; <i64> [#uses=1]
+	%6 = getelementptr double, double* %p, i64 %5		; <double*> [#uses=1]
+	store double %4, double* %6, align 8
+	%7 = add i32 %i.01, 1		; <i32> [#uses=2]
+	br label %bb3
+
+bb3:		; preds = %bb2
+	%8 = icmp slt i32 %7, %n		; <i1> [#uses=1]
+	br i1 %8, label %bb2, label %bb3.return_crit_edge
+
+bb3.return_crit_edge:		; preds = %bb3
+	br label %return
+
+return:		; preds = %bb3.return_crit_edge, %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-reuse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-reuse.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-reuse.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-reuse.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,234 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+;
+; Make sure that indvars can perform LFTR without a canonical IV.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+; Perform LFTR using the original pointer-type IV.
+
+declare void @use(double %x)
+
+;  for(char* p = base; p < base + n; ++p) {
+;    *p = p-base;
+;  }
+define void @ptriv(i8* %base, i32 %n) nounwind {
+entry:
+  %idx.ext = sext i32 %n to i64
+  %add.ptr = getelementptr inbounds i8, i8* %base, i64 %idx.ext
+  %cmp1 = icmp ult i8* %base, %add.ptr
+  br i1 %cmp1, label %for.body, label %for.end
+
+; CHECK: for.body:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK-NOT: add
+; CHECK: icmp ne i8*
+; CHECK: br i1
+for.body:
+  %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ]
+  ; cruft to make the IV useful
+  %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64
+  %sub.ptr.rhs.cast = ptrtoint i8* %base to i64
+  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  %conv = trunc i64 %sub.ptr.sub to i8
+  store i8 %conv, i8* %p.02
+  %incdec.ptr = getelementptr inbounds i8, i8* %p.02, i32 1
+  %cmp = icmp ult i8* %incdec.ptr, %add.ptr
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+
+; This test checks that SCEVExpander can handle an outer loop that has been
+; simplified, and as a result the inner loop's exit test will be rewritten.
+define void @expandOuterRecurrence(i32 %arg) nounwind {
+entry:
+  %sub1 = sub nsw i32 %arg, 1
+  %cmp1 = icmp slt i32 0, %sub1
+  br i1 %cmp1, label %outer, label %exit
+
+; CHECK: outer:
+; CHECK: icmp slt
+outer:
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
+  %sub2 = sub nsw i32 %arg, %i
+  %sub3 = sub nsw i32 %sub2, 1
+  %cmp2 = icmp slt i32 0, %sub3
+  br i1 %cmp2, label %inner.ph, label %outer.inc
+
+inner.ph:
+  br label %inner
+
+; CHECK: inner:
+; CHECK: br i1
+inner:
+  %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
+  %j.inc = add nsw i32 %j, 1
+  %cmp3 = icmp slt i32 %j.inc, %sub3
+  br i1 %cmp3, label %inner, label %outer.inc
+
+; CHECK: outer.inc:
+; CHECK: icmp ne
+; CHECK: br i1
+outer.inc:
+  %i.inc = add nsw i32 %i, 1
+  %cmp4 = icmp slt i32 %i.inc, %sub1
+  br i1 %cmp4, label %outer, label %exit
+
+exit:
+  ret void
+}
+
+; Force SCEVExpander to look for an existing well-formed phi.
+; Perform LFTR without generating extra preheader code.
+define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector,
+                         i32 %irow, i32 %ilead) nounwind {
+; CHECK: entry:
+; CHECK-NOT: zext
+; CHECK-NOT: add
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK: phi i64
+; CHECK-NOT: phi
+; CHECK: icmp ne
+; CHECK: br i1
+entry:
+  %cmp = icmp slt i32 1, %irow
+  br i1 %cmp, label %loop, label %return
+
+loop:
+  %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+  %diagidx = add nsw i32 %rowidx, %i
+  %diagidxw = sext i32 %diagidx to i64
+  %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw
+  %v1 = load double, double* %matrixp
+  call void @use(double %v1)
+  %iw = sext i32 %i to i64
+  %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw
+  %v2 = load double, double* %vectorp
+  call void @use(double %v2)
+  %row.inc = add nsw i32 %rowidx, %ilead
+  %i.inc = add nsw i32 %i, 1
+  %cmp196 = icmp slt i32 %i.inc, %irow
+  br i1 %cmp196, label %loop, label %return
+
+return:
+  ret void
+}
+
+; Avoid generating extra code to materialize a trip count. Skip LFTR.
+define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
+                           i32 %irow, i32 %ilead) nounwind {
+entry:
+  br label %loop
+
+; CHECK: entry:
+; CHECK-NOT: zext
+; CHECK-NOT: add
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK-NOT: phi
+; CHECK: icmp slt
+; CHECK: br i1
+loop:
+  %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+  %diagidx = add nsw i32 %rowidx, %i
+  %diagidxw = sext i32 %diagidx to i64
+  %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw
+  %v1 = load double, double* %matrixp
+  %iw = sext i32 %i to i64
+  %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw
+  %v2 = load double, double* %vectorp
+  %row.inc = add nsw i32 %rowidx, %ilead
+  %i.inc = add nsw i32 %i, 1
+  %cmp196 = icmp slt i32 %i.inc, %irow
+  br i1 %cmp196, label %loop, label %return
+
+return:
+  ret void
+}
+
+; Remove %i which is only used by the exit test.
+; Verify that SCEV can still compute a backedge count from the sign
+; extended %n, used for pointer comparison by LFTR.
+;
+; TODO: Fix for PR13371 currently makes this impossible. See
+; IndVarSimplify.cpp hasConcreteDef(). We may want to change to undef rules.
+define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind {
+entry:
+  %x.ext = sext i32 %x to i64
+  %add.ptr = getelementptr inbounds i8, i8* %base, i64 %x.ext
+  %y.ext = sext i32 %y to i64
+  %add.ptr10 = getelementptr inbounds i8, i8* %add.ptr, i64 %y.ext
+  %lim = add i32 %x, %n
+  %cmp.ph = icmp ult i32 %x, %lim
+  br i1 %cmp.ph, label %loop, label %exit
+; CHECK-LABEL: @geplftr(
+; CHECK: loop:
+; CHECK: phi i8*
+; DISABLE-NOT: phi      // This check is currently disabled
+; CHECK: getelementptr
+; CHECK: store
+; DISABLE: icmp ne i8*  // This check is currently disabled
+; CHECK: br i1
+loop:
+  %i = phi i32 [ %x, %entry ], [ %inc, %loop ]
+  %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ]
+  %incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1
+  store i8 3, i8* %aptr
+  %inc = add i32 %i, 1
+  %cmp = icmp ult i32 %inc, %lim
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Exercise backedge taken count verification with a never-taken loop.
+define void @nevertaken() nounwind uwtable ssp {
+entry:
+  br label %loop
+; CHECK-LABEL: @nevertaken(
+; CHECK: loop:
+; CHECK-NOT: phi
+; CHECK-NOT: add
+; CHECK-NOT: icmp
+; CHECK: exit:
+loop:
+  %i = phi i32 [ 0, %entry ], [ %inc, %loop ]
+  %inc = add nsw i32 %i, 1
+  %cmp = icmp sle i32 %inc, 0
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; Test LFTR on an IV whose recurrence start is a non-unit pointer type.
+define void @aryptriv([256 x i8]* %base, i32 %n) nounwind {
+entry:
+  %ivstart = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 0
+  %ivend = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 %n
+  %cmp.ph = icmp ult i8* %ivstart, %ivend
+  br i1 %cmp.ph, label %loop, label %exit
+
+; CHECK: loop:
+; CHECK: phi i8*
+; CHECK-NOT: phi
+; CHECK: getelementptr
+; CHECK: store
+; CHECK: icmp ne i8*
+; CHECK: br i1
+loop:
+  %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ]
+  %incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1
+  store i8 3, i8* %aptr
+  %cmp = icmp ult i8* %incdec.ptr, %ivend
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-udiv-tripcount.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+; It is okay to do LFTR on this loop even though the trip count is a
+; division because in this case the division can be optimized to a
+; shift.
+
+define void @foo(i8* %a, i8 %n) nounwind uwtable ssp {
+; CHECK-LABEL: @foo(
+ entry:
+  %e = icmp sgt i8 %n, 3
+  br i1 %e, label %loop, label %exit
+
+ loop:
+; CHECK-LABEL: loop:
+  %i = phi i8 [ 0, %entry ], [ %i.inc, %loop ]
+  %i1 = phi i8 [ 0, %entry ], [ %i1.inc, %loop ]
+  %i.inc = add nsw i8 %i, 4
+  %i1.inc = add i8 %i1, 1
+  store volatile i8 0, i8* %a
+  %c = icmp slt i8 %i, %n
+; CHECK-LABEL:  %exitcond = icmp ne i8 %i1.inc
+  br i1 %c, label %loop, label %exit
+
+ exit:
+; CHECK-LABEL: exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-wide-trip-count.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-wide-trip-count.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-wide-trip-count.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-wide-trip-count.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,158 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+define void @test1(float* %autoc,
+                   float* %data,
+                   float %d, i32 %data_len, i32 %sample) nounwind {
+entry:
+  %sub = sub i32 %data_len, %sample
+  %cmp4 = icmp eq i32 %data_len, %sample
+  br i1 %cmp4, label %for.end, label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 68719476736, %entry ]
+  %temp = trunc i64 %indvars.iv to i32
+  %add = add i32 %temp, %sample
+  %idxprom = zext i32 %add to i64
+  %arrayidx = getelementptr inbounds float, float* %data, i64 %idxprom
+  %temp1 = load float, float* %arrayidx, align 4
+  %mul = fmul float %temp1, %d
+  %arrayidx2 = getelementptr inbounds float, float* %autoc, i64 %indvars.iv
+  %temp2 = load float, float* %arrayidx2, align 4
+  %add3 = fadd float %temp2, %mul
+  store float %add3, float* %arrayidx2, align 4
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %temp3 = trunc i64 %indvars.iv.next to i32
+  %cmp = icmp ult i32 %temp3, %sub
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body, %entry
+  ret void
+
+; CHECK-LABEL: @test1(
+
+; With the given initial value for IV, it is not legal to widen
+; trip count to IV size
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK: %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+; CHECK: %exitcond = icmp ne i32 %lftr.wideiv, %sub
+; CHECK: br i1 %exitcond, label %for.body, label %for.end.loopexit
+}
+
+define float @test2(float* %a,
+                    float* %b,
+                    i32 zeroext %m) local_unnamed_addr #0 {
+entry:
+  %cmp5 = icmp ugt i32 %m, 500
+  br i1 %cmp5, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %sum.07 = phi float [ %add, %for.body ], [ 0.000000e+00, %for.body.preheader ]
+  %i.06 = phi i32 [ %inc, %for.body ], [ 500, %for.body.preheader ]
+  %idxprom = zext i32 %i.06 to i64
+  %arrayidx = getelementptr inbounds float, float* %b, i64 %idxprom
+  %temp = load float, float* %arrayidx, align 4
+  %arrayidx2 = getelementptr inbounds float, float* %a, i64 %idxprom
+  %temp1 = load float, float* %arrayidx2, align 4
+  %mul = fmul float %temp, %temp1
+  %add = fadd float %sum.07, %mul
+  %inc = add i32 %i.06, 1
+  %cmp = icmp ult i32 %inc, %m
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add, %for.end.loopexit ]
+  ret float %sum.0.lcssa
+
+; CHECK-LABEL: @test2(
+; Trip count should be widened and LFTR should canonicalize the condition
+; CHECK: %wide.trip.count = zext
+; CHECK: %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count
+; CHECK: br i1 %exitcond
+}
+
+define float @test3(float* %b,
+                    i32 signext %m) local_unnamed_addr #0 {
+entry:
+  %cmp5 = icmp sgt i32 %m, -10
+  br i1 %cmp5, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %sum.07 = phi float [ %add1, %for.body ], [ 0.000000e+00, %for.body.preheader ]
+  %i.06 = phi i32 [ %inc, %for.body ], [ -10, %for.body.preheader ]
+  %add = add nsw i32 %i.06, 20
+  %idxprom = sext i32 %add to i64
+  %arrayidx = getelementptr inbounds float, float* %b, i64 %idxprom
+  %temp = load float, float* %arrayidx, align 4
+  %conv = sitofp i32 %i.06 to float
+  %mul = fmul float %conv, %temp
+  %add1 = fadd float %sum.07, %mul
+  %inc = add nsw i32 %i.06, 1
+  %cmp = icmp slt i32 %inc, %m
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add1, %for.end.loopexit ]
+  ret float %sum.0.lcssa
+
+; CHECK-LABEL: @test3(
+; Trip count should be widened and LFTR should canonicalize the condition
+; CHECK: %wide.trip.count = sext
+; CHECK: %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count
+; CHECK: br i1 %exitcond
+}
+
+define float @test4(float* %b,
+                    i32 signext %m) local_unnamed_addr #0 {
+entry:
+  %cmp5 = icmp sgt i32 %m, 10
+  br i1 %cmp5, label %for.body.preheader, label %for.end
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body.preheader, %for.body
+  %sum.07 = phi float [ %add1, %for.body ], [ 0.000000e+00, %for.body.preheader ]
+  %i.06 = phi i32 [ %inc, %for.body ], [ 10, %for.body.preheader ]
+  %add = add nsw i32 %i.06, 20
+  %idxprom = sext i32 %add to i64
+  %arrayidx = getelementptr inbounds float, float* %b, i64 %idxprom
+  %temp = load float, float* %arrayidx, align 4
+  %conv = sitofp i32 %i.06 to float
+  %mul = fmul float %conv, %temp
+  %add1 = fadd float %sum.07, %mul
+  %inc = add nsw i32 %i.06, 1
+  %cmp = icmp slt i32 %inc, %m
+  br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:                                 ; preds = %for.body
+  %add1.lcssa = phi float [ %add1, %for.body ]
+  br label %for.end
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  %sum.0.lcssa = phi float [ 0.000000e+00, %entry ], [ %add1.lcssa, %for.end.loopexit ]
+  ret float %sum.0.lcssa
+
+; CHECK-LABEL: @test4(
+; Trip count should be widened and LFTR should canonicalize the condition
+; CHECK: %wide.trip.count = zext
+; CHECK: %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count
+; CHECK: br i1 %exitcond
+}
+
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr-zext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr-zext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr-zext.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-zext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.9.0"
+
+ at data = common global [240 x i8] zeroinitializer, align 16
+
+define void @foo(i8* %a) nounwind uwtable ssp {
+; CHECK: %exitcond
+; CHECK-NOT: ([240 x i8]* @data, i64 0, i64 -16)
+  br label %1
+
+; <label>:1                                       ; preds = %0, %1
+  %i.0 = phi i8 [ 0, %0 ], [ %5, %1 ]
+  %p.0 = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), %0 ], [ %4, %1 ]
+  %.0 = phi i8* [ %a, %0 ], [ %2, %1 ]
+  %2 = getelementptr inbounds i8, i8* %.0, i64 1
+  %3 = load i8, i8* %.0, align 1
+  %4 = getelementptr inbounds i8, i8* %p.0, i64 1
+  store i8 %3, i8* %p.0, align 1
+  %5 = add i8 %i.0, 1
+  %6 = icmp ult i8 %5, -16
+  br i1 %6, label %1, label %7
+
+; <label>:7                                       ; preds = %1
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr_disabled.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr_disabled.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr_disabled.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr_disabled.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; LFTR should not eliminate the need for the computation of i*i completely
+; due to LFTR is disabled.
+; RUN: opt < %s -indvars -dce -disable-lftr -S | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+ at A = external global i32                ; <i32*> [#uses=1]
+
+define i32 @quadratic_setlt() {
+; CHECK-LABEL: @quadratic_setlt(
+; CHECK: mul
+entry:
+        br label %loop
+
+loop:           ; preds = %loop, %entry
+        %i = phi i32 [ 7, %entry ], [ %i.next, %loop ]          ; <i32> [#uses=5]
+        %i.next = add i32 %i, 1         ; <i32> [#uses=1]
+        store i32 %i, i32* @A
+        %i2 = mul i32 %i, %i            ; <i32> [#uses=1]
+        %c = icmp slt i32 %i2, 1000             ; <i1> [#uses=1]
+        br i1 %c, label %loop, label %loopexit
+
+loopexit:               ; preds = %loop
+        ret i32 %i
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/lftr_simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lftr_simple.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lftr_simple.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lftr_simple.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; LFTR should eliminate the need for the computation of i*i completely.  It
+; is only used to compute the exit value.
+; RUN: opt < %s -indvars -dce -S | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+ at A = external global i32                ; <i32*> [#uses=1]
+
+define i32 @quadratic_setlt() {
+; CHECK-LABEL: @quadratic_setlt(
+; CHECK-NOT: mul
+entry:
+        br label %loop
+
+loop:           ; preds = %loop, %entry
+        %i = phi i32 [ 7, %entry ], [ %i.next, %loop ]          ; <i32> [#uses=5]
+        %i.next = add i32 %i, 1         ; <i32> [#uses=1]
+        store i32 %i, i32* @A
+        %i2 = mul i32 %i, %i            ; <i32> [#uses=1]
+        %c = icmp slt i32 %i2, 1000             ; <i1> [#uses=1]
+        br i1 %c, label %loop, label %loopexit
+
+loopexit:               ; preds = %loop
+        ret i32 %i
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,394 @@
+; RUN: opt -S -indvars %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @test1(i64 %start) {
+; CHECK-LABEL: @test1
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+; CHECK: %cmp1 = icmp slt i64 %start, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test2(i64 %start) {
+; CHECK-LABEL: @test2
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+; CHECK: %cmp1 = icmp sle i64 %start, -1
+  %cmp1 = icmp sle i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+; As long as the test dominates the backedge, we're good
+define void @test3(i64 %start) {
+; CHECK-LABEL: @test3
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+  br i1 %cmp, label %backedge, label %for.end
+
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+; CHECK: %cmp1 = icmp slt i64 %start, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test4(i64 %start) {
+; CHECK-LABEL: @test4
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+  br i1 %cmp, label %backedge, label %for.end
+
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+; CHECK: %cmp1 = icmp sgt i64 %start, -1
+  %cmp1 = icmp sgt i64 %indvars.iv, -1
+  br i1 %cmp1, label %loop, label %for.end
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test5(i64 %start) {
+; CHECK-LABEL: @test5
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nuw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+  br i1 %cmp, label %backedge, label %for.end
+
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+; CHECK: %cmp1 = icmp ugt i64 %start, 100
+  %cmp1 = icmp ugt i64 %indvars.iv, 100
+  br i1 %cmp1, label %loop, label %for.end
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test6(i64 %start) {
+; CHECK-LABEL: @test6
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nuw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+  br i1 %cmp, label %backedge, label %for.end
+
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+; CHECK: %cmp1 = icmp ult i64 %start, 100
+  %cmp1 = icmp ult i64 %indvars.iv, 100
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test7(i64 %start, i64* %inc_ptr) {
+; CHECK-LABEL: @test7
+entry:
+  %inc = load i64, i64* %inc_ptr, !range !0
+  %ok = icmp sge i64 %inc, 0
+  br i1 %ok, label %loop, label %for.end
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
+; CHECK: %cmp1 = icmp slt i64 %start, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+; Negative test - we can't show that the internal branch executes, so we can't
+; fold the test to a loop invariant one.
+define void @test1_neg(i64 %start) {
+; CHECK-LABEL: @test1_neg
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+  br i1 %cmp, label %backedge, label %skip
+skip:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %backedge
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+  br label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+; Slightly subtle version of @test4 where the icmp dominates the backedge,
+; but the exit branch doesn't.  
+define void @test2_neg(i64 %start) {
+; CHECK-LABEL: @test2_neg
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp, label %backedge, label %skip
+skip:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+  br i1 %cmp1, label %for.end, label %backedge
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+  br label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+; The branch has to exit the loop if the condition is true
+define void @test3_neg(i64 %start) {
+; CHECK-LABEL: @test3_neg
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %loop, label %for.end
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test4_neg(i64 %start) {
+; CHECK-LABEL: @test4_neg
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+  %cmp = icmp eq i64 %indvars.iv.next, 25
+  br i1 %cmp, label %backedge, label %for.end
+
+backedge:
+  ; prevent flattening, needed to make sure we're testing what we intend
+  call void @foo() 
+; CHECK: %cmp1 = icmp sgt i64 %indvars.iv, -1
+  %cmp1 = icmp sgt i64 %indvars.iv, -1
+
+; %cmp1 can be made loop invariant only if the branch below goes to
+; %the header when %cmp1 is true.
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test5_neg(i64 %start, i64 %inc) {
+; CHECK-LABEL: @test5_neg
+entry:
+  br label %loop
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
+; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+define void @test8(i64 %start, i64* %inc_ptr) {
+; CHECK-LABEL: @test8
+entry:
+  %inc = load i64, i64* %inc_ptr, !range !1
+  %ok = icmp sge i64 %inc, 0
+  br i1 %ok, label %loop, label %for.end
+
+loop:
+  %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, %inc
+; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+; check to handle loops without preheaders, but invariant operands
+; (we handle this today by inserting a preheader)
+define void @test9(i1 %cnd, i64 %start) {
+; CHECK-LABEL: @test9
+; CHECK-LABEL: loop.preheader:
+entry:
+  br i1 %cnd, label %entry1, label %entry2
+entry1:
+  br label %loop
+entry2:
+  br label %loop
+loop:
+  %indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+; CHECK: %cmp1 = icmp slt i64 %start, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
+declare void @use(i1 %x)
+
+; check that we handle conditions with loop invariant operands which
+; *aren't* in the header - this is a very rare and fragile case where
+; we have a "loop" which is known to run exactly one iteration but
+; haven't yet simplified the uses of the IV
+define void @test10() {
+; CHECK-LABEL: @test10
+entry:
+  br label %loop
+
+loop:
+  %phi1 = phi i32 [ %phi2, %latch ], [ 0, %entry ]
+  %dec = add i32 %phi1, -1
+  br i1 false, label %left, label %right
+
+left:
+  br label %latch
+
+right:
+  br label %latch
+
+latch:
+  %phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ]
+  ; CHECK: %cmp = icmp slt i32 -1, undef
+  %cmp = icmp slt i32 %phi2, undef
+  br i1 true, label %exit, label %loop
+
+exit:
+  call void @use(i1 %cmp)
+  ret void
+}
+
+; check that we can figure out that iv.next > 1 from the facts that iv >= 0 and
+; iv.start != 0.
+define void @test11(i64* %inc_ptr) {
+; CHECK-LABEL: @test11
+entry:
+  %inc = load i64, i64* %inc_ptr, !range !0
+  %ne.cond = icmp ne i64 %inc, 0
+  br i1 %ne.cond, label %loop, label %exit
+
+loop:
+  %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
+  %iv.next = add i64 %iv, 1
+  %brcond = icmp sgt i64 %iv.next, 1
+  ; CHECK: br i1 true, label %if.true, label %if.false
+  br i1 %brcond, label %if.true, label %if.false
+
+if.true:
+  br label %backedge
+
+if.false:
+  br label %backedge
+
+backedge:
+  %loopcond = icmp slt i64 %iv, 200
+  br i1 %loopcond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+; check that we can prove that a recurrency is greater than another recurrency
+; in the same loop, with the same step, and with smaller starting value.
+define void @test12(i64* %inc_ptr) {
+; CHECK-LABEL: @test12
+entry:
+  %inc = load i64, i64* %inc_ptr, !range !0
+  %inc.minus.1 = sub i64 %inc, 1
+  br label %loop
+
+loop:
+  %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ]
+  %iv.minus.1 = phi i64 [ %inc.minus.1, %entry ], [ %iv.minus.1.next, %backedge ]
+  %iv.next = add i64 %iv, 1
+  %iv.minus.1.next = add i64 %iv.minus.1, 1
+  %brcond = icmp sgt i64 %iv.next, %iv.minus.1.next
+  ; CHECK: br i1 true, label %if.true, label %if.false
+  br i1 %brcond, label %if.true, label %if.false
+
+if.true:
+  br label %backedge
+
+if.false:
+  br label %backedge
+
+backedge:
+  %loopcond = icmp slt i64 %iv, 200
+  br i1 %loopcond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+!0 = !{i64 0, i64 100}
+!1 = !{i64 -1, i64 100}
+
+declare void @foo()

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate10.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate10.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate10.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate10.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+;
+; This loop has multiple exits, and the value of %b1 depends on which
+; exit is taken. Indvars should correctly compute the exit values.
+;
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-pc-linux-gnu"
+	%struct..0anon = type <{ i8, [3 x i8] }>
+
+define i32 @main() nounwind {
+; CHECK-LABEL: @main(
+; CHECK: %b.1 = phi i32 [ 2, %bb ], [ 1, %bb2 ]
+entry:
+	br label %bb2
+
+bb2:		; preds = %bb, %entry
+	%sdata.0 = phi i32 [ 1, %entry ], [ %ins10, %bb ]		; <i32> [#uses=2]
+	%b.0 = phi i32 [ 0, %entry ], [ %t0, %bb ]		; <i32> [#uses=2]
+	%tmp6 = trunc i32 %sdata.0 to i8		; <i8> [#uses=2]
+	%t2 = and i8 %tmp6, 1		; <i8> [#uses=1]
+	%t3 = icmp eq i8 %t2, 0		; <i1> [#uses=1]
+	%t4 = xor i8 %tmp6, 1		; <i8> [#uses=1]
+	%tmp8 = zext i8 %t4 to i32		; <i32> [#uses=1]
+	%mask9 = and i32 %sdata.0, -256		; <i32> [#uses=1]
+	%ins10 = or i32 %tmp8, %mask9		; <i32> [#uses=1]
+	br i1 %t3, label %bb3, label %bb
+
+bb:		; preds = %bb2
+	%t0 = add i32 %b.0, 1		; <i32> [#uses=3]
+	%t1 = icmp sgt i32 %t0, 100		; <i1> [#uses=1]
+	br i1 %t1, label %bb3, label %bb2
+
+bb3:		; preds = %bb, %bb2
+	%b.1 = phi i32 [ %t0, %bb ], [ %b.0, %bb2 ]		; <i32> [#uses=1]
+	%t5 = icmp eq i32 %b.1, 1		; <i1> [#uses=1]
+	br i1 %t5, label %bb5, label %bb4
+
+bb4:		; preds = %bb3
+	tail call void @abort() noreturn nounwind
+	unreachable
+
+bb5:		; preds = %bb3
+	ret i32 0
+}
+
+declare void @abort() noreturn nounwind

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate11.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate11.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate11.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate11.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -domfrontier -indvars -loop-deletion
+
+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-f80:128:128"
+
+define void @slap_sl_mem_create() nounwind {
+entry:
+	br label %bb15
+
+bb15:		; preds = %bb15, %entry
+	%order_end.0 = phi i32 [ 0, %entry ], [ %tmp, %bb15 ]		; <i32> [#uses=1]
+	%tmp = add i32 %order_end.0, 1		; <i32> [#uses=2]
+	br i1 undef, label %bb17, label %bb15
+
+bb17:		; preds = %bb17, %bb15
+	%order_start.0 = phi i32 [ %tmp1, %bb17 ], [ 0, %bb15 ]		; <i32> [#uses=2]
+	%tmp1 = add i32 %order_start.0, 1		; <i32> [#uses=2]
+	%tmp2 = icmp eq i32 undef, 0		; <i1> [#uses=1]
+	br i1 %tmp2, label %bb18, label %bb17
+
+bb18:		; preds = %bb17
+	%tmp3 = sub i32 %tmp, %tmp1		; <i32> [#uses=0]
+	br label %bb59
+
+bb51:		; preds = %bb59
+	%tmp4 = add i32 %order_start.0, 2		; <i32> [#uses=1]
+	%tmp5 = add i32 %tmp4, undef		; <i32> [#uses=1]
+	%tmp6 = lshr i32 undef, %tmp5		; <i32> [#uses=1]
+	%tmp7 = icmp eq i32 %tmp6, 0		; <i1> [#uses=1]
+	br i1 %tmp7, label %bb52, label %bb59
+
+bb59:		; preds = %bb51, %bb18
+	br label %bb51
+
+bb52:		; preds = %bb51
+	unreachable
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate7.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate7.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate7.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate7.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; RUN: opt < %s -indvars
+; PR4436
+
+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-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+
+define i8* @string_expandtabs(i32 %n, i8* %m) nounwind {
+entry:
+	br i1 undef, label %bb33, label %bb1
+
+bb1:		; preds = %entry
+	br i1 undef, label %overflow1, label %bb15
+
+bb15:		; preds = %bb1
+	br i1 undef, label %bb33, label %bb17
+
+bb17:		; preds = %bb15
+	br label %bb30
+
+bb19:		; preds = %bb30
+	br i1 undef, label %bb20, label %bb29
+
+bb20:		; preds = %bb19
+	%0 = load i32, i32* undef, align 4		; <i32> [#uses=1]
+	%1 = sub i32 %0, %n		; <i32> [#uses=1]
+	br label %bb23
+
+bb21:		; preds = %bb23
+	%2 = icmp ult i8* %q.0, %m		; <i1> [#uses=1]
+	br i1 %2, label %bb22, label %overflow2
+
+bb22:		; preds = %bb21
+	%3 = getelementptr i8, i8* %q.0, i32 1		; <i8*> [#uses=1]
+	br label %bb23
+
+bb23:		; preds = %bb22, %bb20
+	%i.2 = phi i32 [ %1, %bb20 ], [ %4, %bb22 ]		; <i32> [#uses=1]
+	%q.0 = phi i8* [ undef, %bb20 ], [ %3, %bb22 ]		; <i8*> [#uses=3]
+	%4 = add i32 %i.2, -1		; <i32> [#uses=2]
+	%5 = icmp eq i32 %4, -1		; <i1> [#uses=1]
+	br i1 %5, label %bb29, label %bb21
+
+bb29:		; preds = %bb23, %bb19
+	%q.1 = phi i8* [ undef, %bb19 ], [ %q.0, %bb23 ]		; <i8*> [#uses=0]
+	br label %bb30
+
+bb30:		; preds = %bb29, %bb17
+	br i1 undef, label %bb19, label %bb33
+
+overflow2:		; preds = %bb21
+	br i1 undef, label %bb32, label %overflow1
+
+bb32:		; preds = %overflow2
+	br label %overflow1
+
+overflow1:		; preds = %bb32, %overflow2, %bb1
+	ret i8* null
+
+bb33:		; preds = %bb30, %bb15, %entry
+	ret i8* undef
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate8.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate8.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate8.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate8.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; This loop has backedge-taken-count zero. Indvars shouldn't expand any
+; instructions to compute a trip count.
+
+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-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+
+define i8* @string_expandtabs() nounwind {
+; CHECK-LABEL: @string_expandtabs(
+; CHECK-NOT: select
+entry:
+	br i1 undef, label %bb33, label %bb1
+
+bb1:		; preds = %entry
+	br i1 undef, label %overflow1, label %bb15
+
+bb15:		; preds = %bb1
+	br i1 undef, label %bb33, label %bb17
+
+bb17:		; preds = %bb15
+	br label %bb30
+
+bb19:		; preds = %bb30
+	br i1 undef, label %bb20, label %bb29
+
+bb20:		; preds = %bb19
+	%0 = load i32, i32* undef, align 4		; <i32> [#uses=1]
+	%1 = sub i32 %0, undef		; <i32> [#uses=1]
+	br label %bb23
+
+bb21:		; preds = %bb23
+	%2 = icmp ult i8* %q.0, undef		; <i1> [#uses=1]
+	br i1 %2, label %bb22, label %overflow2
+
+bb22:		; preds = %bb21
+	%3 = getelementptr i8, i8* %q.0, i32 1		; <i8*> [#uses=1]
+	br label %bb23
+
+bb23:		; preds = %bb22, %bb20
+	%i.2 = phi i32 [ %1, %bb20 ], [ %4, %bb22 ]		; <i32> [#uses=1]
+	%q.0 = phi i8* [ undef, %bb20 ], [ %3, %bb22 ]		; <i8*> [#uses=3]
+	%4 = add i32 %i.2, -1		; <i32> [#uses=2]
+	%5 = icmp eq i32 %4, -1		; <i1> [#uses=1]
+	br i1 %5, label %bb29, label %bb21
+
+bb29:		; preds = %bb23, %bb19
+	%q.1 = phi i8* [ undef, %bb19 ], [ %q.0, %bb23 ]		; <i8*> [#uses=0]
+	br label %bb30
+
+bb30:		; preds = %bb29, %bb17
+	br i1 undef, label %bb19, label %bb33
+
+overflow2:		; preds = %bb21
+	br i1 undef, label %bb32, label %overflow1
+
+bb32:		; preds = %overflow2
+	br label %overflow1
+
+overflow1:		; preds = %bb32, %overflow2, %bb1
+	ret i8* null
+
+bb33:		; preds = %bb30, %bb15, %entry
+	ret i8* undef
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate9.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate9.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate9.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate9.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,85 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR4477
+; Indvars should compute the exit values in loop.
+;
+; XFAIL: *
+; Indvars does not currently replace loop invariant values unless all
+; loop exits have the same exit value. We could handle some cases,
+; such as this, by making getSCEVAtScope() sensitive to a particular
+; loop exit.  See PR11388.
+
+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-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+	%struct.cc70a02__complex_integers__complex_type = type { i8, i8 }
+ at .str = internal constant [13 x i8] c"fc70a00.adb\00\00", align 1		; <[13 x i8]*> [#uses=1]
+
+define void @_ada_cc70a02() {
+; CHECK-LABEL: @_ada_cc70a02(
+; CHECK: [%]tmp7 = icmp eq i8 -28, -28
+; CHECK: [%]tmp8 = icmp eq i8 63, 63
+
+entry:
+	br label %bb1.i
+
+bb1.i:		; preds = %bb2.i, %entry
+	%indvar.i = phi i32 [ 0, %entry ], [ %indvar.next.i, %bb2.i ]		; <i32> [#uses=2]
+	%result.0.i = phi i16 [ 0, %entry ], [ %ins36.i, %bb2.i ]		; <i16> [#uses=2]
+	%tmp38.i = trunc i16 %result.0.i to i8		; <i8> [#uses=2]
+	%tmp = add i8 %tmp38.i, 96		; <i8> [#uses=1]
+	%tmp1 = icmp ugt i8 %tmp, -56		; <i1> [#uses=1]
+	br i1 %tmp1, label %bb.i.i, label %bb1.i.i
+
+bb.i.i:		; preds = %bb1.i
+	tail call void @__gnat_rcheck_12(i8* getelementptr ([13 x i8], [13 x i8]* @.str, i32 0, i32 0), i32 24) noreturn
+	unreachable
+
+bb1.i.i:		; preds = %bb1.i
+	%tmp41.i = lshr i16 %result.0.i, 8		; <i16> [#uses=1]
+	%tmp42.i = trunc i16 %tmp41.i to i8		; <i8> [#uses=2]
+	%tmp2 = add i8 %tmp42.i, 109		; <i8> [#uses=1]
+	%tmp3 = icmp ugt i8 %tmp2, -56		; <i1> [#uses=1]
+	br i1 %tmp3, label %bb2.i.i, label %cc70a02__complex_integers__Oadd.153.exit.i
+
+bb2.i.i:		; preds = %bb1.i.i
+	tail call void @__gnat_rcheck_12(i8* getelementptr ([13 x i8], [13 x i8]* @.str, i32 0, i32 0), i32 24) noreturn
+	unreachable
+
+cc70a02__complex_integers__Oadd.153.exit.i:		; preds = %bb1.i.i
+	%tmp4 = add i8 %tmp38.i, -4		; <i8> [#uses=2]
+	%tmp5 = add i8 %tmp42.i, 9		; <i8> [#uses=2]
+	%tmp25.i = zext i8 %tmp4 to i16		; <i16> [#uses=1]
+	%tmp33.i = zext i8 %tmp5 to i16		; <i16> [#uses=1]
+	%tmp34.i = shl i16 %tmp33.i, 8		; <i16> [#uses=1]
+	%ins36.i = or i16 %tmp34.i, %tmp25.i		; <i16> [#uses=1]
+	%tmp6 = icmp eq i32 %indvar.i, 6		; <i1> [#uses=1]
+	br i1 %tmp6, label %cc70a02__complex_multiplication.170.exit, label %bb2.i
+
+bb2.i:		; preds = %cc70a02__complex_integers__Oadd.153.exit.i
+	%indvar.next.i = add i32 %indvar.i, 1		; <i32> [#uses=1]
+	br label %bb1.i
+
+cc70a02__complex_multiplication.170.exit:		; preds = %cc70a02__complex_integers__Oadd.153.exit.i
+	%tmp7 = icmp eq i8 %tmp4, -28		; <i1> [#uses=1]
+	%tmp8 = icmp eq i8 %tmp5, 63		; <i1> [#uses=1]
+	%or.cond = and i1 %tmp8, %tmp7		; <i1> [#uses=1]
+	br i1 %or.cond, label %return, label %bb1
+
+bb1:		; preds = %cc70a02__complex_multiplication.170.exit
+	tail call void @exit(i32 1)
+	ret void
+
+return:		; preds = %cc70a02__complex_multiplication.170.exit
+	ret void
+}
+
+declare fastcc void @cc70a02__complex_integers__complex.164(%struct.cc70a02__complex_integers__complex_type* noalias nocapture sret, i8 signext, i8 signext) nounwind
+
+declare fastcc void @cc70a02__complex_integers__Osubtract.149(%struct.cc70a02__complex_integers__complex_type* noalias sret, %struct.cc70a02__complex_integers__complex_type* byval align 4)
+
+declare fastcc void @cc70a02__complex_integers__Oadd.153(%struct.cc70a02__complex_integers__complex_type* noalias sret, %struct.cc70a02__complex_integers__complex_type* byval align 4, %struct.cc70a02__complex_integers__complex_type* byval align 4)
+
+declare fastcc void @cc70a02__complex_multiplication.170(%struct.cc70a02__complex_integers__complex_type* noalias sret, %struct.cc70a02__complex_integers__complex_type* byval align 4)
+
+declare void @__gnat_rcheck_12(i8*, i32) noreturn
+
+declare void @exit(i32)

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_1.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt < %s -indvars -loop-deletion -simplifycfg -S | FileCheck %s
+
+; Testcase distilled from 256.bzip2
+; CHECK-LABEL: @test1
+; CHECK-NOT: br
+define i32 @test1() {
+entry:
+        br label %loopentry
+
+loopentry:              ; preds = %loopentry, %entry
+        %indvar1 = phi i32 [ 0, %entry ], [ %indvar.next2, %loopentry ]         ; <i32> [#uses=1]
+        %h.0 = phi i32 [ %tmp.2, %loopentry ], [ 4, %entry ]            ; <i32> [#uses=1]
+        %tmp.1 = mul i32 %h.0, 3                ; <i32> [#uses=1]
+        %tmp.2 = add i32 %tmp.1, 1              ; <i32> [#uses=2]
+        %indvar.next2 = add i32 %indvar1, 1             ; <i32> [#uses=2]
+        %exitcond3 = icmp ne i32 %indvar.next2, 4               ; <i1> [#uses=1]
+        br i1 %exitcond3, label %loopentry, label %loopexit
+
+loopexit:               ; preds = %loopentry
+        ret i32 %tmp.2
+}
+
+
+; PR12377
+; CHECK-LABEL: @test2
+; CHECK: [[VAR1:%.+]] = add i32 %arg, -11
+; CHECK: [[VAR2:%.+]] = lshr i32 [[VAR1]], 1
+; CHECK: [[VAR3:%.+]] = add i32 [[VAR2]], 1
+; CHECK: [[VAR4:%.+]] = phi i32 [ 0, %bb ], [ [[VAR3]], %bb1.preheader ]
+; CHECK: ret i32 [[VAR4]]
+define i32 @test2(i32 %arg) {
+bb:
+  %tmp = icmp ugt i32 %arg, 10
+  br i1 %tmp, label %bb1, label %bb7
+
+bb1:                                              ; preds = %bb1, %bb
+  %tmp2 = phi i32 [ %tmp5, %bb1 ], [ 0, %bb ]
+  %tmp3 = phi i32 [ %tmp4, %bb1 ], [ %arg, %bb ]
+  %tmp4 = add i32 %tmp3, -2
+  %tmp5 = add i32 %tmp2, 1
+  %tmp6 = icmp ugt i32 %tmp4, 10
+  br i1 %tmp6, label %bb1, label %bb7
+
+bb7:                                              ; preds = %bb1, %bb
+  %tmp8 = phi i32 [ 0, %bb ], [ %tmp5, %bb1 ]
+  ret i32 %tmp8
+}




More information about the llvm-commits mailing list