[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/IndVarSimplify/loop_evaluate_2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_2.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -indvars -loop-deletion -simplifycfg | opt -analyze -loops | FileCheck %s
+; PR1179
+
+; CHECK-NOT: Loop Containing
+
+define i32 @ltst(i32 %x) {
+entry:
+        icmp sgt i32 %x, 0              ; <i1>:0 [#uses=1]
+        br i1 %0, label %bb.preheader, label %bb8
+
+bb.preheader:           ; preds = %entry
+        br label %bb
+
+bb:             ; preds = %bb, %bb.preheader
+        %i.01.0 = phi i32 [ %tmp4, %bb ], [ 0, %bb.preheader ]          ; <i32> [#uses=1]
+        %j.03.0 = phi i32 [ %tmp2, %bb ], [ 0, %bb.preheader ]          ; <i32> [#uses=1]
+        %tmp4 = add i32 %i.01.0, 1              ; <i32> [#uses=2]
+        %tmp2 = add i32 %j.03.0, 1              ; <i32> [#uses=2]
+        icmp slt i32 %tmp4, %x          ; <i1>:1 [#uses=1]
+        br i1 %1, label %bb, label %bb8.loopexit
+
+bb8.loopexit:           ; preds = %bb
+        br label %bb8
+
+bb8:            ; preds = %bb8.loopexit, %entry
+        %j.03.1 = phi i32 [ 0, %entry ], [ %tmp2, %bb8.loopexit ]               ; <i32> [#uses=1]
+        ret i32 %j.03.1
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_3.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR1179
+
+define i32 @foo() {
+; CHECK-LABEL: @foo(
+; CHECK: ret i32 600000
+entry:
+        br label %bb5
+
+bb5:            ; preds = %bb5, %entry
+        %i.01.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb5 ]                ; <i32> [#uses=1]
+        %x.03.0 = phi i32 [ 0, %entry ], [ %tmp4, %bb5 ]                ; <i32> [#uses=1]
+        %tmp2 = add i32 %i.01.0, 3              ; <i32> [#uses=2]
+        %tmp4 = add i32 %x.03.0, 1              ; <i32> [#uses=2]
+        icmp slt i32 %tmp4, 200000              ; <i1>:0 [#uses=1]
+        br i1 %0, label %bb5, label %bb7
+
+bb7:            ; preds = %bb5
+        ret i32 %tmp2
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_4.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_4.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_4.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+; PR1179
+
+define i32 @test4() {
+; CHECK-LABEL: @test4(
+; CHECK: ret i32 9900
+entry:
+        br label %bb7
+
+bb7:            ; preds = %bb7, %entry
+        %v.01.0 = phi i32 [ 0, %entry ], [ %tmp4, %bb7 ]                ; <i32> [#uses=1]
+        %i.03.0 = phi i32 [ 0, %entry ], [ %tmp6, %bb7 ]                ; <i32> [#uses=2]
+        %tmp2 = shl i32 %i.03.0, 1              ; <i32> [#uses=1]
+        %tmp4 = add i32 %tmp2, %v.01.0          ; <i32> [#uses=2]
+        %tmp6 = add i32 %i.03.0, 1              ; <i32> [#uses=2]
+        icmp slt i32 %tmp6, 100         ; <i1>:0 [#uses=1]
+        br i1 %0, label %bb7, label %bb9
+
+bb9:            ; preds = %bb7
+        ret i32 %tmp4
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_5.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_5.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_5.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_5.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt < %s -indvars -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"
+target triple = "i686-pc-linux-gnu"
+
+; Indvars should be able to compute an exit value for %tmp1.
+
+define i32 @testcase(i5 zeroext %k) nounwind readnone {
+; CHECK-LABEL: @testcase
+; CHECK: 120, %bb2.bb3_crit_edge
+entry:
+	br i1 false, label %bb3, label %bb.nph
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb2, %bb.nph
+	%result2 = phi i32 [ %tmp1, %bb2 ], [ 0, %bb.nph ]		; <i32> [#uses=1]
+	%k_01 = phi i5 [ %indvar_next1, %bb2 ], [ 0, %bb.nph ]		; <i5> [#uses=2]
+	%tmp2 = zext i5 %k_01 to i32		; <i32> [#uses=1]
+	%tmp1 = add i32 %tmp2, %result2		; <i32> [#uses=2]
+	%indvar_next1 = add i5 %k_01, 1		; <i5> [#uses=2]
+	br label %bb2
+
+bb2:		; preds = %bb
+	%phitmp = icmp eq i5 %indvar_next1, -16		; <i1> [#uses=1]
+	br i1 %phitmp, label %bb2.bb3_crit_edge, label %bb
+
+bb2.bb3_crit_edge:		; preds = %bb2
+	br label %bb3
+
+bb3:		; preds = %bb2.bb3_crit_edge, %entry
+	%result.lcssa = phi i32 [ %tmp1, %bb2.bb3_crit_edge ], [ 0, %entry ]		; <i32> [#uses=1]
+	ret i32 %result.lcssa
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_6.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_6.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_6.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop_evaluate_6.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt < %s -indvars -loop-deletion -S | FileCheck %s
+
+define i32 @test(i32 %x_offs) nounwind readnone {
+; CHECK-LABEL: @test(
+; CHECK: phi
+; CHECK-NOT: phi
+
+entry:
+	%0 = icmp sgt i32 %x_offs, 4		; <i1> [#uses=1]
+	br i1 %0, label %bb.nph, label %bb2
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb1, %bb.nph
+	%x_offs_addr.01 = phi i32 [ %1, %bb1 ], [ %x_offs, %bb.nph ]		; <i32> [#uses=1]
+	%1 = add i32 %x_offs_addr.01, -4		; <i32> [#uses=3]
+	br label %bb1
+
+bb1:		; preds = %bb
+	%2 = icmp sgt i32 %1, 4		; <i1> [#uses=1]
+	br i1 %2, label %bb, label %bb1.bb2_crit_edge
+
+bb1.bb2_crit_edge:		; preds = %bb1
+	br label %bb2
+
+bb2:		; preds = %bb1.bb2_crit_edge, %entry
+	%x_offs_addr.0.lcssa = phi i32 [ %1, %bb1.bb2_crit_edge ], [ %x_offs, %entry ]		; <i32> [#uses=1]
+	ret i32 %x_offs_addr.0.lcssa
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/lrev-existing-umin.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/lrev-existing-umin.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/lrev-existing-umin.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/lrev-existing-umin.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; Do not rewrite the user outside the loop because we must keep the instruction
+; inside the loop due to store. Rewrite doesn't give us any profit.
+define void @f(i32 %length.i.88, i32 %length.i, i8* %tmp12, i32 %tmp10, i8* %tmp8) {
+; CHECK-LABEL: @f(
+not_zero11.preheader:
+  %tmp13 = icmp ugt i32 %length.i, %length.i.88
+  %tmp14 = select i1 %tmp13, i32 %length.i.88, i32 %length.i
+  %tmp15 = icmp sgt i32 %tmp14, 0
+  br i1 %tmp15, label %not_zero11, label %not_zero11.postloop
+
+not_zero11:
+  %v_1 = phi i32 [ %tmp22, %not_zero11 ], [ 0, %not_zero11.preheader ]
+  %tmp16 = zext i32 %v_1 to i64
+  %tmp17 = getelementptr inbounds i8, i8* %tmp8, i64 %tmp16
+  %tmp18 = load i8, i8* %tmp17, align 1
+  %tmp19 = zext i8 %tmp18 to i32
+  %tmp20 = or i32 %tmp19, %tmp10
+  %tmp21 = trunc i32 %tmp20 to i8
+  %addr22 = getelementptr inbounds i8, i8* %tmp12, i64 %tmp16
+  store i8 %tmp21, i8* %addr22, align 1
+  %tmp22 = add nuw nsw i32 %v_1, 1
+  %tmp23 = icmp slt i32 %tmp22, %tmp14
+  br i1 %tmp23, label %not_zero11, label %main.exit.selector
+
+main.exit.selector:
+; CHECK-LABEL: main.exit.selector:
+; CHECK:   %tmp22.lcssa = phi i32 [ %tmp22, %not_zero11 ]
+; CHECK:   %tmp24 = icmp slt i32 %tmp22.lcssa, %length.
+  %tmp24 = icmp slt i32 %tmp22, %length.i
+  br i1 %tmp24, label %not_zero11.postloop, label %leave
+
+leave:
+  ret void
+
+not_zero11.postloop:
+  ret void
+}
+
+; Rewrite the user outside the loop because there is no hard users inside the loop.
+define void @f1(i32 %length.i.88, i32 %length.i, i8* %tmp12, i32 %tmp10, i8* %tmp8) {
+; CHECK-LABEL: @f1(
+not_zero11.preheader:
+  %tmp13 = icmp ugt i32 %length.i, %length.i.88
+  %tmp14 = select i1 %tmp13, i32 %length.i.88, i32 %length.i
+  %tmp15 = icmp sgt i32 %tmp14, 0
+  br i1 %tmp15, label %not_zero11, label %not_zero11.postloop
+
+not_zero11:
+  %v_1 = phi i32 [ %tmp22, %not_zero11 ], [ 0, %not_zero11.preheader ]
+  %tmp16 = zext i32 %v_1 to i64
+  %tmp17 = getelementptr inbounds i8, i8* %tmp8, i64 %tmp16
+  %tmp18 = load i8, i8* %tmp17, align 1
+  %tmp19 = zext i8 %tmp18 to i32
+  %tmp20 = or i32 %tmp19, %tmp10
+  %tmp21 = trunc i32 %tmp20 to i8
+  %addr22 = getelementptr inbounds i8, i8* %tmp12, i64 %tmp16
+  %tmp22 = add nuw nsw i32 %v_1, 1
+  %tmp23 = icmp slt i32 %tmp22, %tmp14
+  br i1 %tmp23, label %not_zero11, label %main.exit.selector
+
+main.exit.selector:
+; CHECK-LABEL: main.exit.selector:
+; CHECK: %tmp24 = icmp slt i32 %tmp14, %length.i
+  %tmp24 = icmp slt i32 %tmp22, %length.i
+  br i1 %tmp24, label %not_zero11.postloop, label %leave
+
+leave:
+  ret void
+
+not_zero11.postloop:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/masked-iv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/masked-iv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/masked-iv.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/masked-iv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Indvars should do the IV arithmetic in the canonical IV type (i64),
+; and only use one truncation.
+
+define void @foo(i64* %A, i64* %B, i64 %n, i64 %a, i64 %s) nounwind {
+; CHECK-LABEL: @foo(
+; CHECK-NOT: trunc
+; CHECK: and
+; CHECK-NOT: and
+entry:
+	%t0 = icmp sgt i64 %n, 0		; <i1> [#uses=1]
+	br i1 %t0, label %bb.preheader, label %return
+
+bb.preheader:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb, %bb.preheader
+	%i.01 = phi i64 [ %t6, %bb ], [ %a, %bb.preheader ]		; <i64> [#uses=3]
+	%t1 = and i64 %i.01, 255		; <i64> [#uses=1]
+	%t2 = getelementptr i64, i64* %A, i64 %t1		; <i64*> [#uses=1]
+	store i64 %i.01, i64* %t2, align 8
+	%t6 = add i64 %i.01, %s		; <i64> [#uses=1]
+	br label %bb
+
+return:		; preds = %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/no-iv-rewrite.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,397 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+;
+; Make sure that indvars isn't inserting canonical IVs.
+; This is kinda hard to do until linear function test replacement is removed.
+
+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 i32 @sum(i32* %arr, i32 %n) nounwind {
+entry:
+  %precond = icmp slt i32 0, %n
+  br i1 %precond, label %ph, label %return
+
+ph:
+  br label %loop
+
+; CHECK: loop:
+;
+; We should only have 2 IVs.
+; CHECK: phi
+; CHECK: phi
+; CHECK-NOT: phi
+;
+; sext should be eliminated while preserving gep inboundsness.
+; CHECK-NOT: sext
+; CHECK: getelementptr inbounds
+; CHECK: exit:
+loop:
+  %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ]
+  %s.01 = phi i32 [ 0, %ph ], [ %sinc, %loop ]
+  %ofs = sext i32 %i.02 to i64
+  %adr = getelementptr inbounds i32, i32* %arr, i64 %ofs
+  %val = load i32, i32* %adr
+  %sinc = add nsw i32 %s.01, %val
+  %iinc = add nsw i32 %i.02, 1
+  %cond = icmp slt i32 %iinc, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  %s.lcssa = phi i32 [ %sinc, %loop ]
+  br label %return
+
+return:
+  %s.0.lcssa = phi i32 [ %s.lcssa, %exit ], [ 0, %entry ]
+  ret i32 %s.0.lcssa
+}
+
+define i64 @suml(i32* %arr, i32 %n) nounwind {
+entry:
+  %precond = icmp slt i32 0, %n
+  br i1 %precond, label %ph, label %return
+
+ph:
+  br label %loop
+
+; CHECK: loop:
+;
+; We should only have 2 IVs.
+; CHECK: phi
+; CHECK: phi
+; CHECK-NOT: phi
+;
+; %ofs sext should be eliminated while preserving gep inboundsness.
+; CHECK-NOT: sext
+; CHECK: getelementptr inbounds
+; %vall sext should obviously not be eliminated
+; CHECK: sext
+; CHECK: exit:
+loop:
+  %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ]
+  %s.01 = phi i64 [ 0, %ph ], [ %sinc, %loop ]
+  %ofs = sext i32 %i.02 to i64
+  %adr = getelementptr inbounds i32, i32* %arr, i64 %ofs
+  %val = load i32, i32* %adr
+  %vall = sext i32 %val to i64
+  %sinc = add nsw i64 %s.01, %vall
+  %iinc = add nsw i32 %i.02, 1
+  %cond = icmp slt i32 %iinc, %n
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  %s.lcssa = phi i64 [ %sinc, %loop ]
+  br label %return
+
+return:
+  %s.0.lcssa = phi i64 [ %s.lcssa, %exit ], [ 0, %entry ]
+  ret i64 %s.0.lcssa
+}
+
+define void @outofbounds(i32* %first, i32* %last, i32 %idx) nounwind {
+  %precond = icmp ne i32* %first, %last
+  br i1 %precond, label %ph, label %return
+
+; CHECK: ph:
+; It's not indvars' job to perform LICM on %ofs
+; CHECK-NOT: sext
+ph:
+  br label %loop
+
+; CHECK: loop:
+;
+; Preserve exactly one pointer type IV.
+; CHECK: phi i32*
+; CHECK-NOT: phi
+;
+; Don't create any extra adds.
+; CHECK-NOT: add
+;
+; Preserve gep inboundsness, and don't factor it.
+; CHECK: getelementptr inbounds i32, i32* %ptriv, i32 1
+; CHECK-NOT: add
+; CHECK: exit:
+loop:
+  %ptriv = phi i32* [ %first, %ph ], [ %ptrpost, %loop ]
+  %ofs = sext i32 %idx to i64
+  %adr = getelementptr inbounds i32, i32* %ptriv, i64 %ofs
+  store i32 3, i32* %adr
+  %ptrpost = getelementptr inbounds i32, i32* %ptriv, i32 1
+  %cond = icmp ne i32* %ptrpost, %last
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  br label %return
+
+return:
+  ret void
+}
+
+%structI = type { i32 }
+
+define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %structI* %base)
+nounwind
+{
+entry:
+  br label %loop
+
+; CHECK: loop:
+;
+; Preserve casts
+; CHECK: phi i32
+; CHECK: bitcast
+; CHECK: getelementptr
+; CHECK: exit:
+loop:
+  %iv = phi i32 [%start, %entry], [%next, %loop]
+  %p = phi %structI* [%base, %entry], [%pinc, %loop]
+  %adr = getelementptr %structI, %structI* %p, i32 0, i32 0
+  store i32 3, i32* %adr
+  %pp = bitcast %structI* %p to i32*
+  store i32 4, i32* %pp
+  %pinc = getelementptr %structI, %structI* %p, i32 1
+  %next = add i32 %iv, 1
+  %cond = icmp ne i32 %next, %limit
+  br i1 %cond, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+define void @maxvisitor(i32 %limit, i32* %base) nounwind {
+entry:
+ br label %loop
+
+; Test inserting a truncate at a phi use.
+;
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK: trunc
+; CHECK: exit:
+loop:
+  %idx = phi i32 [ 0, %entry ], [ %idx.next, %loop.inc ]
+  %max = phi i32 [ 0, %entry ], [ %max.next, %loop.inc ]
+  %idxprom = sext i32 %idx to i64
+  %adr = getelementptr inbounds i32, i32* %base, i64 %idxprom
+  %val = load i32, i32* %adr
+  %cmp19 = icmp sgt i32 %val, %max
+  br i1 %cmp19, label %if.then, label %if.else
+
+if.then:
+  br label %loop.inc
+
+if.else:
+  br label %loop.inc
+
+loop.inc:
+  %max.next = phi i32 [ %idx, %if.then ], [ %max, %if.else ]
+  %idx.next = add nsw i32 %idx, 1
+  %cmp = icmp slt i32 %idx.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+define void @identityphi(i32 %limit) nounwind {
+entry:
+  br label %loop
+
+; Test an edge case of removing an identity phi that directly feeds
+; back to the loop iv.
+;
+; CHECK: loop:
+; CHECK-NOT: phi
+; CHECK: exit:
+loop:
+  %iv = phi i32 [ 0, %entry], [ %iv.next, %control ]
+  br i1 undef, label %if.then, label %control
+
+if.then:
+  br label %control
+
+control:
+  %iv.next = phi i32 [ %iv, %loop ], [ undef, %if.then ]
+  %cmp = icmp slt i32 %iv.next, %limit
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+define i64 @cloneOr(i32 %limit, i64* %base) nounwind {
+entry:
+  ; ensure that the loop can't overflow
+  %halfLim = ashr i32 %limit, 2
+  br label %loop
+
+; Test cloning an or, which is not an OverflowBinaryOperator.
+;
+; CHECK: sext
+; CHECK: loop:
+; CHECK: phi i64
+; CHECK-NOT: sext
+; CHECK: or i64
+; CHECK: exit:
+loop:
+  %iv = phi i32 [ 0, %entry], [ %iv.next, %loop ]
+  %t1 = sext i32 %iv to i64
+  %adr = getelementptr i64, i64* %base, i64 %t1
+  %val = load i64, i64* %adr
+  %t2 = or i32 %iv, 1
+  %t3 = sext i32 %t2 to i64
+  %iv.next = add i32 %iv, 2
+  %cmp = icmp slt i32 %iv.next, %halfLim
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  %result = and i64 %val, %t3
+  ret i64 %result
+}
+
+; The i induction variable looks like a wrap-around, but it really is just
+; a simple affine IV.  Make sure that indvars simplifies through.
+define i32 @indirectRecurrence() nounwind {
+entry:
+  br label %loop
+
+; ReplaceLoopExitValue should fold the return value to constant 9.
+; CHECK: loop:
+; CHECK: phi i32
+; CHECK: ret i32 9
+loop:
+  %j.0 = phi i32 [ 1, %entry ], [ %j.next, %cond_true ]
+  %i.0 = phi i32 [ 0, %entry ], [ %j.0, %cond_true ]
+  %tmp = icmp ne i32 %j.0, 10
+  br i1 %tmp, label %cond_true, label %return
+
+cond_true:
+  %j.next = add i32 %j.0, 1
+  br label %loop
+
+return:
+  ret i32 %i.0
+}
+
+; Eliminate the congruent phis j, k, and l.
+; Eliminate the redundant IV increments k.next and l.next.
+; Two phis should remain, one starting at %init, and one at %init1.
+; Two increments should remain, one by %step and one by %step1.
+; CHECK: loop:
+; CHECK: phi i32
+; CHECK: phi i32
+; CHECK-NOT: phi
+; CHECK: add i32
+; CHECK: add i32
+; CHECK: add i32
+; CHECK-NOT: add
+; CHECK: return:
+;
+; Five live-outs should remain.
+; CHECK: lcssa = phi
+; CHECK: lcssa = phi
+; CHECK: lcssa = phi
+; CHECK: lcssa = phi
+; CHECK: lcssa = phi
+; CHECK-NOT: phi
+; CHECK: ret
+define i32 @isomorphic(i32 %init, i32 %step, i32 %lim) nounwind {
+entry:
+  %step1 = add i32 %step, 1
+  %init1 = add i32 %init, %step1
+  %l.0 = sub i32 %init1, %step1
+  br label %loop
+
+loop:
+  %ii = phi i32 [ %init1, %entry ], [ %ii.next, %loop ]
+  %i = phi i32 [ %init, %entry ], [ %ii, %loop ]
+  %j = phi i32 [ %init, %entry ], [ %j.next, %loop ]
+  %k = phi i32 [ %init1, %entry ], [ %k.next, %loop ]
+  %l = phi i32 [ %l.0, %entry ], [ %l.next, %loop ]
+  %ii.next = add i32 %ii, %step1
+  %j.next = add i32 %j, %step1
+  %k.next = add i32 %k, %step1
+  %l.step = add i32 %l, %step
+  %l.next = add i32 %l.step, 1
+  %cmp = icmp ne i32 %ii.next, %lim
+  br i1 %cmp, label %loop, label %return
+
+return:
+  %sum1 = add i32 %i, %j.next
+  %sum2 = add i32 %sum1, %k.next
+  %sum3 = add i32 %sum1, %l.step
+  %sum4 = add i32 %sum1, %l.next
+  ret i32 %sum4
+}
+
+; Test a GEP IV that is derived from another GEP IV by a nop gep that
+; lowers the type without changing the expression.
+%structIF = type { i32, float }
+
+define void @congruentgepiv(%structIF* %base) nounwind uwtable ssp {
+entry:
+  %first = getelementptr inbounds %structIF, %structIF* %base, i64 0, i32 0
+  br label %loop
+
+; CHECK: loop:
+; CHECK: phi %structIF*
+; CHECK-NOT: phi
+; CHECK: getelementptr inbounds
+; CHECK-NOT: getelementptr
+; CHECK: exit:
+loop:
+  %ptr.iv = phi %structIF* [ %ptr.inc, %latch ], [ %base, %entry ]
+  %next = phi i32* [ %next.inc, %latch ], [ %first, %entry ]
+  store i32 4, i32* %next
+  br i1 undef, label %latch, label %exit
+
+latch:                         ; preds = %for.inc50.i
+  %ptr.inc = getelementptr inbounds %structIF, %structIF* %ptr.iv, i64 1
+  %next.inc = getelementptr inbounds %structIF, %structIF* %ptr.inc, i64 0, i32 0
+  br label %loop
+
+exit:
+  ret void
+}
+
+declare void @use32(i32 %x)
+declare void @use64(i64 %x)
+
+; Test a widened IV that is used by a phi on different paths within the loop.
+;
+; CHECK: for.body:
+; CHECK: phi i64
+; CHECK: trunc i64
+; CHECK: if.then:
+; CHECK: for.inc:
+; CHECK: phi i32
+; CHECK: for.end:
+define void @phiUsesTrunc() nounwind {
+entry:
+  br i1 undef, label %for.body, label %for.end
+
+for.body:
+  %iv = phi i32 [ %inc, %for.inc ], [ 1, %entry ]
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  br i1 undef, label %if.then33, label %for.inc
+
+if.then33:
+  br label %for.inc
+
+if.else:
+  br i1 undef, label %if.then97, label %for.inc
+
+if.then97:
+  %idxprom100 = sext i32 %iv to i64
+  call void @use64(i64 %idxprom100)
+  br label %for.inc
+
+for.inc:
+  %kmin.1 = phi i32 [ %iv, %if.then33 ], [ 0, %if.then ], [ %iv, %if.then97 ], [ 0, %if.else ]
+  call void @use32(i32 %kmin.1)
+  %inc = add nsw i32 %iv, 1
+  br i1 undef, label %for.body, label %for.end
+
+for.end:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/overflow-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/overflow-intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/overflow-intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/overflow-intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,137 @@
+; 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 @f_sadd(i8* %a) {
+; CHECK-LABEL: @f_sadd(
+entry:
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %cont
+  ret void
+
+for.body:                                         ; preds = %entry, %cont
+  %i.04 = phi i32 [ 0, %entry ], [ %2, %cont ]
+  %idxprom = sext i32 %i.04 to i64
+  %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
+  store i8 0, i8* %arrayidx, align 1
+  %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %i.04, i32 1)
+  %1 = extractvalue { i32, i1 } %0, 1
+; CHECK: for.body:
+; CHECK-NOT: @llvm.sadd.with.overflow
+; CHECK:  br i1 false, label %trap, label %cont, !nosanitize !0
+  br i1 %1, label %trap, label %cont, !nosanitize !{}
+
+trap:                                             ; preds = %for.body
+  tail call void @llvm.trap() #2, !nosanitize !{}
+  unreachable, !nosanitize !{}
+
+cont:                                             ; preds = %for.body
+  %2 = extractvalue { i32, i1 } %0, 0
+  %cmp = icmp slt i32 %2, 16
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+define void @f_uadd(i8* %a) {
+; CHECK-LABEL: @f_uadd(
+entry:
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %cont
+  ret void
+
+for.body:                                         ; preds = %entry, %cont
+  %i.04 = phi i32 [ 0, %entry ], [ %2, %cont ]
+  %idxprom = sext i32 %i.04 to i64
+  %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
+  store i8 0, i8* %arrayidx, align 1
+  %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %i.04, i32 1)
+  %1 = extractvalue { i32, i1 } %0, 1
+; CHECK: for.body:
+; CHECK-NOT: @llvm.uadd.with.overflow
+; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
+  br i1 %1, label %trap, label %cont, !nosanitize !{}
+
+trap:                                             ; preds = %for.body
+  tail call void @llvm.trap(), !nosanitize !{}
+  unreachable, !nosanitize !{}
+
+cont:                                             ; preds = %for.body
+  %2 = extractvalue { i32, i1 } %0, 0
+  %cmp = icmp slt i32 %2, 16
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+define void @f_ssub(i8* nocapture %a) {
+; CHECK-LABEL: @f_ssub(
+entry:
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %cont
+  ret void
+
+for.body:                                         ; preds = %entry, %cont
+  %i.04 = phi i32 [ 15, %entry ], [ %2, %cont ]
+  %idxprom = sext i32 %i.04 to i64
+  %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
+  store i8 0, i8* %arrayidx, align 1
+  %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %i.04, i32 1)
+  %1 = extractvalue { i32, i1 } %0, 1
+; CHECK: for.body:
+; CHECK-NOT: @llvm.ssub.with.overflow.i32
+; CHECK: br i1 false, label %trap, label %cont, !nosanitize !0
+  br i1 %1, label %trap, label %cont, !nosanitize !{}
+
+trap:                                             ; preds = %for.body
+  tail call void @llvm.trap(), !nosanitize !{}
+  unreachable, !nosanitize !{}
+
+cont:                                             ; preds = %for.body
+  %2 = extractvalue { i32, i1 } %0, 0
+  %cmp = icmp sgt i32 %2, -1
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+define void @f_usub(i8* nocapture %a) {
+; CHECK-LABEL: @f_usub(
+entry:
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %cont
+  ret void
+
+for.body:                                         ; preds = %entry, %cont
+  %i.04 = phi i32 [ 15, %entry ], [ %2, %cont ]
+  %idxprom = sext i32 %i.04 to i64
+  %arrayidx = getelementptr inbounds i8, i8* %a, i64 %idxprom
+  store i8 0, i8* %arrayidx, align 1
+  %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.04, i32 1)
+  %1 = extractvalue { i32, i1 } %0, 1
+
+; It is theoretically possible to prove this, but SCEV cannot
+; represent non-unsigned-wrapping subtraction operations.
+
+; CHECK: for.body:
+; CHECK:  [[COND:%[^ ]+]] = extractvalue { i32, i1 } %1, 1
+; CHECK-NEXT:  br i1 [[COND]], label %trap, label %cont, !nosanitize !0
+  br i1 %1, label %trap, label %cont, !nosanitize !{}
+
+trap:                                             ; preds = %for.body
+  tail call void @llvm.trap(), !nosanitize !{}
+  unreachable, !nosanitize !{}
+
+cont:                                             ; preds = %for.body
+  %2 = extractvalue { i32, i1 } %0, 0
+  %cmp = icmp sgt i32 %2, -1
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+}
+
+declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
+declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
+declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone
+declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone
+declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone
+declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
+
+declare void @llvm.trap() #2

Added: llvm/trunk/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; REQUIRES: asserts
+; RUN: opt < %s -indvars -disable-output -stats -info-output-file - | FileCheck %s
+; Check that IndVarSimplify is not creating unnecessary canonical IVs
+; that will never be used.
+; CHECK-NOT: indvars
+
+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 ue = external global i64
+
+define i32 @foo() nounwind {
+entry:
+	br label %bb38.i
+
+bb14.i27:
+	%t0 = load i64, i64* @ue, align 8
+	%t1 = sub i64 %t0, %i.0.i35
+	%t2 = add i64 %t1, 1
+	br i1 undef, label %bb15.i28, label %bb19.i31
+
+bb15.i28:
+	br label %bb19.i31
+
+bb19.i31:
+	%y.0.i = phi i64 [ %t2, %bb15.i28 ], [ %t2, %bb14.i27 ]
+	br label %bb35.i
+
+bb35.i:
+	br i1 undef, label %bb37.i, label %bb14.i27
+
+bb37.i:
+	%t3 = add i64 %i.0.i35, 1
+	br label %bb38.i
+
+bb38.i:
+	%i.0.i35 = phi i64 [ 1, %entry ], [ %t3, %bb37.i ]
+	br label %bb35.i
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/polynomial-expand.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/polynomial-expand.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/polynomial-expand.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/polynomial-expand.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -indvars -disable-output
+; PR5073
+
+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"
+
+define void @ctpmv_(float* noalias nocapture %tmp4, i32 %tmp21) nounwind {
+bb20:                                             ; preds = %bb19
+  br label %bb24
+
+bb24:                                             ; preds = %bb40, %bb23
+  %tmp25 = phi i32 [ %tmp43, %bb40 ], [ %tmp21, %bb20 ] ; <i32> [#uses=4]
+  %tmp26 = phi i32 [ %tmp41, %bb40 ], [ undef, %bb20 ] ; <i32> [#uses=2]
+  %tmp27 = add nsw i32 %tmp26, -1                 ; <i32> [#uses=1]
+  %tmp28 = add nsw i32 %tmp25, -1                 ; <i32> [#uses=2]
+  %tmp29 = icmp sgt i32 %tmp28, 0                 ; <i1> [#uses=1]
+  br i1 %tmp29, label %bb30, label %bb40
+
+bb30:                                             ; preds = %bb30, %bb24
+  %tmp31 = phi i32 [ %tmp39, %bb30 ], [ %tmp28, %bb24 ] ; <i32> [#uses=2]
+  %tmp32 = phi i32 [ %tmp37, %bb30 ], [ %tmp27, %bb24 ] ; <i32> [#uses=2]
+  %tmp33 = sext i32 %tmp32 to i64                 ; <i64> [#uses=1]
+  %tmp35 = getelementptr float, float* %tmp4, i64 %tmp33 ; <%0*> [#uses=1]
+  %tmp36 = load float, float* %tmp35, align 4               ; <%0> [#uses=0]
+  %tmp37 = add nsw i32 %tmp32, -1                 ; <i32> [#uses=1]
+  %tmp39 = add nsw i32 %tmp31, -1                 ; <i32> [#uses=1]
+  %tmp38 = icmp eq i32 %tmp31, 1                  ; <i1> [#uses=1]
+  br i1 %tmp38, label %bb40, label %bb30
+
+bb40:                                             ; preds = %bb30, %bb24
+  %tmp41 = sub i32 %tmp26, %tmp25                 ; <i32> [#uses=1]
+  %tmp43 = add nsw i32 %tmp25, -1                 ; <i32> [#uses=1]
+  %tmp42 = icmp eq i32 %tmp25, 1                  ; <i1> [#uses=1]
+  br i1 %tmp42, label %bb46, label %bb24
+
+bb46:                                             ; preds = %bb40, %bb23, %bb19
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/post-inc-range.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/post-inc-range.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/post-inc-range.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/post-inc-range.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,289 @@
+; RUN: opt < %s -indvars -indvars-post-increment-ranges -S | FileCheck %s
+
+target datalayout = "p:64:64:64-n32:64"
+
+; When the IV in this loop is widened we want to widen this use as well:
+; icmp slt i32 %i.inc, %limit
+; In order to do this indvars need to prove that the narrow IV def (%i.inc)
+; is not-negative from the range check inside of the loop.
+define void @test(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test(
+; CHECK-NOT: trunc
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %within_limits = icmp ult i32 %i, 64
+  br i1 %within_limits, label %continue, label %for.end
+
+continue:
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test_false_edge(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_false_edge(
+; CHECK-NOT: trunc
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %out_of_bounds = icmp ugt i32 %i, 64
+  br i1 %out_of_bounds, label %for.end, label %continue
+
+continue:
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test_range_metadata(i32* %array_length_ptr, i32* %base,
+                                 i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_range_metadata(
+; CHECK-NOT: trunc
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %array_length = load i32, i32* %array_length_ptr, !range !{i32 0, i32 64 }
+  %within_limits = icmp ult i32 %i, %array_length
+  br i1 %within_limits, label %continue, label %for.end
+
+continue:
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Negative version of the test above, we don't know anything about
+; array_length_ptr range.
+define void @test_neg(i32* %array_length_ptr, i32* %base,
+                      i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_neg(
+; CHECK: trunc i64
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %array_length = load i32, i32* %array_length_ptr
+  %within_limits = icmp ult i32 %i, %array_length
+  br i1 %within_limits, label %continue, label %for.end
+
+continue:
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test_transitive_use(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_transitive_use(
+; CHECK-NOT: trunc
+; CHECK: %result = icmp slt i64
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %within_limits = icmp ult i32 %i, 64
+  br i1 %within_limits, label %continue, label %for.end
+
+continue:
+  %i.mul.3 = mul nsw nuw i32 %i, 3
+  %mul_within = icmp ult i32 %i.mul.3, 64
+  br i1 %mul_within, label %guarded, label %continue.2
+  
+guarded:
+  %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1
+  %result = icmp slt i32 %i.mul.3.inc, %limit
+  br i1 %result, label %continue.2, label %for.end
+
+continue.2:
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+declare void @llvm.experimental.guard(i1, ...)
+
+define void @test_guard_one_bb(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_guard_one_bb(
+; CHECK-NOT: trunc
+; CHECK-NOT: icmp slt i32
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
+  %within_limits = icmp ult i32 %i, 64
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test_guard_in_the_same_bb(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_guard_in_the_same_bb(
+; CHECK-NOT: trunc
+; CHECK-NOT: icmp slt i32
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %within_limits = icmp ult i32 %i, 64
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test_guard_in_idom(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_guard_in_idom(
+; CHECK-NOT: trunc
+; CHECK-NOT: icmp slt i32
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
+  %within_limits = icmp ult i32 %i, 64
+  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test_guard_merge_ranges(i32* %base, i32 %limit, i32 %start) {
+; CHECK-LABEL: @test_guard_merge_ranges(
+; CHECK-NOT: trunc
+; CHECK-NOT: icmp slt i32
+
+for.body.lr.ph:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
+  %within_limits.1 = icmp ult i32 %i, 64
+  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ]
+  %within_limits.2 = icmp ult i32 %i, 2147483647
+  call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ]
+  %i.i64 = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
+  %val = load i32, i32* %arrayidx, align 4
+  %i.inc = add nsw nuw i32 %i, 1
+  %cmp = icmp slt i32 %i.inc, %limit
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  br label %exit
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr18223.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr18223.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr18223.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr18223.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+; indvars should transform the phi node pair from the for-loop
+; CHECK-LABEL: @main(
+; CHECK: ret = phi i32 [ 0, %entry ], [ 0, {{.*}} ]
+
+ at c = common global i32 0, align 4
+
+define i32 @main() #0 {
+entry:
+  %0 = load i32, i32* @c, align 4
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %for.body, label %exit
+
+for.body:
+  %inc2 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %sub = add i32 %inc2, -1
+  %cmp1 = icmp uge i32 %sub, %inc2
+  %conv = zext i1 %cmp1 to i32
+  br label %for.inc
+
+for.inc:
+  %inc = add nsw i32 %inc2, 1
+  %cmp = icmp slt i32 %inc, 5
+  br i1 %cmp, label %for.body, label %exit
+
+exit:
+  %ret = phi i32 [ 0, %entry ], [ %conv, %for.inc ]
+  ret i32 %ret
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr20680.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr20680.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr20680.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr20680.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,223 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+ at a = common global i32 0, align 4
+ at c = common global i32 0, align 4
+ at b = common global i32 0, align 4
+
+define void @f() {
+; CHECK-LABEL: @f(
+; CHECK-LABEL: entry:
+; CHECK: br label %[[for_cond2_preheader:.*]]
+
+; CHECK: [[for_cond2_preheader]]:
+; CHECK-NEXT: %[[indvars_iv:.*]] = phi i32 [ %[[indvars_iv_next:.*]], %[[for_inc13:.*]] ], [ -14, %entry ]
+; br i1 {{.*}}, label %[[for_inc13]], label %
+entry:
+  %0 = load i32, i32* @a, align 4
+  %tobool2 = icmp eq i32 %0, 0
+  %1 = load i32, i32* @a, align 4
+  %tobool = icmp eq i32 %1, 0
+  br label %for.cond2.preheader
+
+for.cond2.preheader:                              ; preds = %for.inc13, %entry
+  %storemerge15 = phi i8 [ -14, %entry ], [ %inc14, %for.inc13 ]
+  br i1 %tobool2, label %for.inc13, label %for.body3.lr.ph
+
+for.body3.lr.ph:                                  ; preds = %for.cond2.preheader
+  %tobool5 = icmp eq i8 %storemerge15, 0
+  %conv7 = sext i8 %storemerge15 to i32
+  %2 = add nsw i32 %conv7, 1
+  %3 = icmp ult i32 %2, 3
+  %div = select i1 %3, i32 %conv7, i32 0
+  br i1 %tobool5, label %for.body3.lr.ph.split.us, label %for.body3.lr.ph.for.body3.lr.ph.split_crit_edge
+
+for.body3.lr.ph.for.body3.lr.ph.split_crit_edge:  ; preds = %for.body3.lr.ph
+  br label %for.body3.lr.ph.split
+
+for.body3.lr.ph.split.us:                         ; preds = %for.body3.lr.ph
+  br i1 %tobool, label %for.body3.lr.ph.split.us.split.us, label %for.body3.lr.ph.split.us.for.body3.lr.ph.split.us.split_crit_edge
+
+for.body3.lr.ph.split.us.for.body3.lr.ph.split.us.split_crit_edge: ; preds = %for.body3.lr.ph.split.us
+  br label %for.body3.lr.ph.split.us.split
+
+for.body3.lr.ph.split.us.split.us:                ; preds = %for.body3.lr.ph.split.us
+  br label %for.body3.us.us
+
+for.body3.us.us:                                  ; preds = %for.cond2.loopexit.us.us, %for.body3.lr.ph.split.us.split.us
+  br i1 true, label %cond.false.us.us, label %cond.end.us.us
+
+cond.false.us.us:                                 ; preds = %for.body3.us.us
+  br label %cond.end.us.us
+
+cond.end.us.us:                                   ; preds = %cond.false.us.us, %for.body3.us.us
+  %cond.us.us = phi i32 [ %div, %cond.false.us.us ], [ %conv7, %for.body3.us.us ]
+  %4 = load i32, i32* @b, align 4
+  %cmp91.us.us = icmp slt i32 %4, 1
+  br i1 %cmp91.us.us, label %for.inc.lr.ph.us.us, label %for.cond2.loopexit.us.us
+
+for.cond2.loopexit.us.us:                         ; preds = %for.cond8.for.cond2.loopexit_crit_edge.us.us, %cond.end.us.us
+  br i1 true, label %for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa.us, label %for.body3.us.us
+
+for.inc.lr.ph.us.us:                              ; preds = %cond.end.us.us
+  br label %for.inc.us.us
+
+for.cond8.for.cond2.loopexit_crit_edge.us.us:     ; preds = %for.inc.us.us
+  %inc.lcssa.us.us = phi i32 [ %inc.us.us, %for.inc.us.us ]
+  store i32 %inc.lcssa.us.us, i32* @b, align 4
+  br label %for.cond2.loopexit.us.us
+
+for.inc.us.us:                                    ; preds = %for.inc.us.us, %for.inc.lr.ph.us.us
+  %5 = phi i32 [ %4, %for.inc.lr.ph.us.us ], [ %inc.us.us, %for.inc.us.us ]
+  %inc.us.us = add nsw i32 %5, 1
+  %cmp9.us.us = icmp slt i32 %inc.us.us, 1
+  br i1 %cmp9.us.us, label %for.inc.us.us, label %for.cond8.for.cond2.loopexit_crit_edge.us.us
+
+for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa.us: ; preds = %for.cond2.loopexit.us.us
+  %cond.lcssa.ph.us.ph.us = phi i32 [ %cond.us.us, %for.cond2.loopexit.us.us ]
+  br label %for.cond2.for.inc13_crit_edge.us-lcssa.us
+
+for.body3.lr.ph.split.us.split:                   ; preds = %for.body3.lr.ph.split.us.for.body3.lr.ph.split.us.split_crit_edge
+  br label %for.body3.us
+
+for.body3.us:                                     ; preds = %for.cond2.loopexit.us, %for.body3.lr.ph.split.us.split
+  br i1 true, label %cond.false.us, label %cond.end.us
+
+cond.false.us:                                    ; preds = %for.body3.us
+  br label %cond.end.us
+
+cond.end.us:                                      ; preds = %cond.false.us, %for.body3.us
+  %cond.us = phi i32 [ %div, %cond.false.us ], [ %conv7, %for.body3.us ]
+  %6 = load i32, i32* @b, align 4
+  %cmp91.us = icmp slt i32 %6, 1
+  br i1 %cmp91.us, label %for.inc.lr.ph.us, label %for.cond2.loopexit.us
+
+for.inc.us:                                       ; preds = %for.inc.lr.ph.us, %for.inc.us
+  %7 = phi i32 [ %6, %for.inc.lr.ph.us ], [ %inc.us, %for.inc.us ]
+  %inc.us = add nsw i32 %7, 1
+  %cmp9.us = icmp slt i32 %inc.us, 1
+  br i1 %cmp9.us, label %for.inc.us, label %for.cond8.for.cond2.loopexit_crit_edge.us
+
+for.cond2.loopexit.us:                            ; preds = %for.cond8.for.cond2.loopexit_crit_edge.us, %cond.end.us
+  br i1 false, label %for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa, label %for.body3.us
+
+for.inc.lr.ph.us:                                 ; preds = %cond.end.us
+  br label %for.inc.us
+
+for.cond8.for.cond2.loopexit_crit_edge.us:        ; preds = %for.inc.us
+  %inc.lcssa.us = phi i32 [ %inc.us, %for.inc.us ]
+  store i32 %inc.lcssa.us, i32* @b, align 4
+  br label %for.cond2.loopexit.us
+
+for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa: ; preds = %for.cond2.loopexit.us
+  %cond.lcssa.ph.us.ph = phi i32 [ %cond.us, %for.cond2.loopexit.us ]
+  br label %for.cond2.for.inc13_crit_edge.us-lcssa.us
+
+for.cond2.for.inc13_crit_edge.us-lcssa.us:        ; preds = %for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa, %for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa.us
+  %cond.lcssa.ph.us = phi i32 [ %cond.lcssa.ph.us.ph, %for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa ], [ %cond.lcssa.ph.us.ph.us, %for.cond2.for.inc13_crit_edge.us-lcssa.us.us-lcssa.us ]
+  br label %for.cond2.for.inc13_crit_edge
+
+for.body3.lr.ph.split:                            ; preds = %for.body3.lr.ph.for.body3.lr.ph.split_crit_edge
+  br i1 %tobool, label %for.body3.lr.ph.split.split.us, label %for.body3.lr.ph.split.for.body3.lr.ph.split.split_crit_edge
+
+for.body3.lr.ph.split.for.body3.lr.ph.split.split_crit_edge: ; preds = %for.body3.lr.ph.split
+  br label %for.body3.lr.ph.split.split
+
+for.body3.lr.ph.split.split.us:                   ; preds = %for.body3.lr.ph.split
+  br label %for.body3.us3
+
+for.body3.us3:                                    ; preds = %for.cond2.loopexit.us11, %for.body3.lr.ph.split.split.us
+  br i1 false, label %cond.false.us4, label %cond.end.us5
+
+cond.false.us4:                                   ; preds = %for.body3.us3
+  br label %cond.end.us5
+
+cond.end.us5:                                     ; preds = %cond.false.us4, %for.body3.us3
+  %cond.us6 = phi i32 [ %div, %cond.false.us4 ], [ %conv7, %for.body3.us3 ]
+  %8 = load i32, i32* @b, align 4
+  %cmp91.us7 = icmp slt i32 %8, 1
+  br i1 %cmp91.us7, label %for.inc.lr.ph.us12, label %for.cond2.loopexit.us11
+
+for.inc.us8:                                      ; preds = %for.inc.lr.ph.us12, %for.inc.us8
+  %9 = phi i32 [ %8, %for.inc.lr.ph.us12 ], [ %inc.us9, %for.inc.us8 ]
+  %inc.us9 = add nsw i32 %9, 1
+  %cmp9.us10 = icmp slt i32 %inc.us9, 1
+  br i1 %cmp9.us10, label %for.inc.us8, label %for.cond8.for.cond2.loopexit_crit_edge.us13
+
+for.cond2.loopexit.us11:                          ; preds = %for.cond8.for.cond2.loopexit_crit_edge.us13, %cond.end.us5
+  br i1 true, label %for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa.us, label %for.body3.us3
+
+for.inc.lr.ph.us12:                               ; preds = %cond.end.us5
+  br label %for.inc.us8
+
+for.cond8.for.cond2.loopexit_crit_edge.us13:      ; preds = %for.inc.us8
+  %inc.lcssa.us14 = phi i32 [ %inc.us9, %for.inc.us8 ]
+  store i32 %inc.lcssa.us14, i32* @b, align 4
+  br label %for.cond2.loopexit.us11
+
+for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa.us: ; preds = %for.cond2.loopexit.us11
+  %cond.lcssa.ph.ph.us = phi i32 [ %cond.us6, %for.cond2.loopexit.us11 ]
+  br label %for.cond2.for.inc13_crit_edge.us-lcssa
+
+for.body3.lr.ph.split.split:                      ; preds = %for.body3.lr.ph.split.for.body3.lr.ph.split.split_crit_edge
+  br label %for.body3
+
+for.cond8.for.cond2.loopexit_crit_edge:           ; preds = %for.inc
+  %inc.lcssa = phi i32 [ %inc, %for.inc ]
+  store i32 %inc.lcssa, i32* @b, align 4
+  br label %for.cond2.loopexit
+
+for.cond2.loopexit:                               ; preds = %cond.end, %for.cond8.for.cond2.loopexit_crit_edge
+  br i1 false, label %for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa, label %for.body3
+
+for.body3:                                        ; preds = %for.cond2.loopexit, %for.body3.lr.ph.split.split
+  br i1 false, label %cond.false, label %cond.end
+
+cond.false:                                       ; preds = %for.body3
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %for.body3
+  %cond = phi i32 [ %div, %cond.false ], [ %conv7, %for.body3 ]
+  %10 = load i32, i32* @b, align 4
+  %cmp91 = icmp slt i32 %10, 1
+  br i1 %cmp91, label %for.inc.lr.ph, label %for.cond2.loopexit
+
+for.inc.lr.ph:                                    ; preds = %cond.end
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.inc, %for.inc.lr.ph
+  %11 = phi i32 [ %10, %for.inc.lr.ph ], [ %inc, %for.inc ]
+  %inc = add nsw i32 %11, 1
+  %cmp9 = icmp slt i32 %inc, 1
+  br i1 %cmp9, label %for.inc, label %for.cond8.for.cond2.loopexit_crit_edge
+
+for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa:  ; preds = %for.cond2.loopexit
+  %cond.lcssa.ph.ph = phi i32 [ %cond, %for.cond2.loopexit ]
+  br label %for.cond2.for.inc13_crit_edge.us-lcssa
+
+for.cond2.for.inc13_crit_edge.us-lcssa:           ; preds = %for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa, %for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa.us
+  %cond.lcssa.ph = phi i32 [ %cond.lcssa.ph.ph, %for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa ], [ %cond.lcssa.ph.ph.us, %for.cond2.for.inc13_crit_edge.us-lcssa.us-lcssa.us ]
+  br label %for.cond2.for.inc13_crit_edge
+
+for.cond2.for.inc13_crit_edge:                    ; preds = %for.cond2.for.inc13_crit_edge.us-lcssa, %for.cond2.for.inc13_crit_edge.us-lcssa.us
+  %cond.lcssa = phi i32 [ %cond.lcssa.ph, %for.cond2.for.inc13_crit_edge.us-lcssa ], [ %cond.lcssa.ph.us, %for.cond2.for.inc13_crit_edge.us-lcssa.us ]
+  store i32 %cond.lcssa, i32* @c, align 4
+  br label %for.inc13
+
+; CHECK: [[for_inc13]]:
+; CHECK-NEXT: %[[indvars_iv_next]] = add nsw i32 %[[indvars_iv]], 1
+; CHECK-NEXT: %[[exitcond4:.*]] = icmp ne i32 %[[indvars_iv_next]], 0
+; CHECK-NEXT: br i1 %[[exitcond4]], label %[[for_cond2_preheader]], label %[[for_end15:.*]]
+for.inc13:                                        ; preds = %for.cond2.for.inc13_crit_edge, %for.cond2.preheader
+  %inc14 = add i8 %storemerge15, 1
+  %cmp = icmp ugt i8 %inc14, 50
+  br i1 %cmp, label %for.cond2.preheader, label %for.end15
+
+; CHECK: [[for_end15]]:
+; CHECK-NEXT: ret void
+for.end15:                                        ; preds = %for.inc13
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr22222.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr22222.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr22222.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr22222.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+ at b = common global i32 0, align 4
+ at c = common global i32 0, align 4
+ at a = common global i32 0, align 4
+
+declare void @abort() #1
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @main() {
+entry:
+  %a.promoted13 = load i32, i32* @a, align 4
+  br label %for.cond1.preheader
+
+for.cond1.preheader:                              ; preds = %entry, %for.end
+  %or.lcssa14 = phi i32 [ %a.promoted13, %entry ], [ %or.lcssa, %for.end ]
+  %d.010 = phi i32 [ 1, %entry ], [ 0, %for.end ]
+  br label %for.body3
+
+for.body3:                                        ; preds = %for.cond1.preheader, %for.body3
+  %inc12 = phi i32 [ 0, %for.cond1.preheader ], [ %inc, %for.body3 ]
+  %or11 = phi i32 [ %or.lcssa14, %for.cond1.preheader ], [ %or, %for.body3 ]
+; CHECK-NOT: sub nuw i32 %inc12, %d.010
+; CHECK: sub i32 %inc12, %d.010
+  %add = sub i32 %inc12, %d.010
+  %or = or i32 %or11, %add
+  %inc = add i32 %inc12, 1
+  br i1 false, label %for.body3, label %for.end
+
+for.end:                                          ; preds = %for.body3
+  %or.lcssa = phi i32 [ %or, %for.body3 ]
+  br i1 false, label %for.cond1.preheader, label %for.end6
+
+for.end6:                                         ; preds = %for.end
+  %or.lcssa.lcssa = phi i32 [ %or.lcssa, %for.end ]
+  store i32 %or.lcssa.lcssa, i32* @a, align 4
+  %cmp7 = icmp eq i32 %or.lcssa.lcssa, -1
+  br i1 %cmp7, label %if.end, label %if.then
+
+if.then:                                          ; preds = %for.end6
+  tail call void @abort() #2
+  unreachable
+
+if.end:                                           ; preds = %for.end6
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr24356.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr24356.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr24356.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr24356.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+ at a = common global i32 0, align 4
+
+; Function Attrs: nounwind ssp uwtable
+define void @fn1() {
+; CHECK-LABEL: @fn1(
+bb:
+  br label %bb4.preheader
+
+bb4.preheader:                                    ; preds = %bb, %bb16
+; CHECK-LABEL:  bb4.preheader:
+  %b.03 = phi i8 [ 0, %bb ], [ %tmp17, %bb16 ]
+; CHECK: %tmp9 = icmp ugt i8 %b.03, 1
+; CHECK-NOT: %tmp9 = icmp ugt i8 0, 1
+
+  %tmp9 = icmp ugt i8 %b.03, 1
+  br i1 %tmp9, label %bb4.preheader.bb18.loopexit.split_crit_edge, label %bb4.preheader.bb4.preheader.split_crit_edge
+
+bb4.preheader.bb4.preheader.split_crit_edge:      ; preds = %bb4.preheader
+  br label %bb4.preheader.split
+
+bb4.preheader.bb18.loopexit.split_crit_edge:      ; preds = %bb4.preheader
+  store i32 0, i32* @a, align 4
+  br label %bb18.loopexit.split
+
+bb4.preheader.split:                              ; preds = %bb4.preheader.bb4.preheader.split_crit_edge
+  br label %bb7
+
+bb4:                                              ; preds = %bb7
+  %tmp6 = icmp slt i32 %storemerge2, 0
+  br i1 %tmp6, label %bb7, label %bb16
+
+bb7:                                              ; preds = %bb4.preheader.split, %bb4
+  %storemerge2 = phi i32 [ 0, %bb4.preheader.split ], [ %tmp14, %bb4 ]
+  %tmp14 = add nsw i32 %storemerge2, 1
+  br i1 false, label %bb18.loopexit, label %bb4
+
+bb16:                                             ; preds = %bb4
+  %tmp14.lcssa5 = phi i32 [ %tmp14, %bb4 ]
+  %tmp17 = add i8 %b.03, -1
+  %tmp2 = icmp eq i8 %tmp17, -2
+  br i1 %tmp2, label %bb18.loopexit1, label %bb4.preheader
+
+bb18.loopexit:                                    ; preds = %bb7
+  br label %bb18.loopexit.split
+
+bb18.loopexit.split:                              ; preds = %bb4.preheader.bb18.loopexit.split_crit_edge, %bb18.loopexit
+  br label %bb18
+
+bb18.loopexit1:                                   ; preds = %bb16
+  %tmp14.lcssa5.lcssa = phi i32 [ %tmp14.lcssa5, %bb16 ]
+  store i32 %tmp14.lcssa5.lcssa, i32* @a, align 4
+  br label %bb18
+
+bb18:                                             ; preds = %bb18.loopexit1, %bb18.loopexit.split
+  ret void
+}
+
+declare void @abort()

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr24783.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr24783.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr24783.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr24783.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+define void @f(i32* %end.s, i8** %loc, i32 %p) {
+; CHECK-LABEL: @f(
+entry:
+  %end = getelementptr inbounds i32, i32* %end.s, i32 %p
+  %init = bitcast i32* %end.s to i8*
+  br label %while.body.i
+
+while.body.i:
+  %ptr = phi i8* [ %ptr.inc, %while.body.i ], [ %init, %entry ]
+  %ptr.inc = getelementptr inbounds i8, i8* %ptr, i8 1
+  %ptr.inc.cast = bitcast i8* %ptr.inc to i32*
+  %cmp.i = icmp eq i32* %ptr.inc.cast, %end
+  br i1 %cmp.i, label %loop.exit, label %while.body.i
+
+loop.exit:
+; CHECK: loop.exit:
+; CHECK: [[END_BCASTED:%[a-z0-9]+]] = bitcast i32* %end to i8*
+; CHECK: store i8* [[END_BCASTED]], i8** %loc
+  %ptr.inc.lcssa = phi i8* [ %ptr.inc, %while.body.i ]
+  store i8* %ptr.inc.lcssa, i8** %loc
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr24804.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr24804.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr24804.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr24804.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -indvars -loop-idiom -loop-deletion -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"
+
+; Checking for a crash
+
+define void @f(i32* %a) {
+; CHECK-LABEL: @f(
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %for.cond, %entry
+  %iv = phi i32 [ 0, %entry ], [ %add, %for.inc ], [ %iv, %for.cond ]
+  %add = add nsw i32 %iv, 1
+  %idxprom = sext i32 %add to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  br i1 undef, label %for.cond, label %for.inc
+
+for.inc:                                          ; preds = %for.cond
+  br i1 undef, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.inc
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr24952.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr24952.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr24952.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr24952.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @f() {
+; CHECK-LABEL: @f(
+ entry:
+  %x = alloca i32
+  %y = alloca i32
+  br label %loop
+
+ loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i32 %iv, 1
+
+  %x.gep = getelementptr i32, i32* %x, i32 %iv
+  %eql = icmp eq i32* %x.gep, %y
+; CHECK-NOT: @use(i1 true)
+  call void @use(i1 %eql)
+
+  ; %be.cond deliberately 'false' -- we want want the trip count to be 0.
+  %be.cond = icmp ult i32 %iv, 0
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr24956.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr24956.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr24956.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr24956.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; Check that this test does not crash.
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+define void @re_update_line(i8* %new) {
+; CHECK: @re_update_line(
+entry:
+  %incdec.ptr6 = getelementptr inbounds i8, i8* %new, i64 1
+  br label %for.cond.11.preheader
+
+for.cond.11.preheader:                            ; preds = %for.inc.26, %entry
+  %n.154 = phi i8* [ %new, %entry ], [ %incdec.ptr27, %for.inc.26 ]
+  %cmp12.52 = icmp ult i8* %n.154, %incdec.ptr6
+  br i1 %cmp12.52, label %land.rhs.16.lr.ph, label %for.inc.26
+
+land.rhs.16.lr.ph:                                ; preds = %for.cond.11.preheader
+  br label %land.rhs.16
+
+for.cond.11:                                      ; preds = %land.rhs.16
+  %incdec.ptr24 = getelementptr inbounds i8, i8* %p.053, i64 1
+  %cmp12 = icmp ult i8* %p.053, %new
+  br i1 %cmp12, label %land.rhs.16, label %for.inc.26
+
+land.rhs.16:                                      ; preds = %for.cond.11, %land.rhs.16.lr.ph
+  %p.053 = phi i8* [ %n.154, %land.rhs.16.lr.ph ], [ %incdec.ptr24, %for.cond.11 ]
+  br i1 undef, label %for.cond.11, label %for.inc.26
+
+for.inc.26:                                       ; preds = %land.rhs.16, %for.cond.11, %for.cond.11.preheader
+  %incdec.ptr27 = getelementptr inbounds i8, i8* %n.154, i64 1
+  br i1 false, label %for.cond.11.preheader, label %for.end.28
+
+for.end.28:                                       ; preds = %for.inc.26
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25047.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25047.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25047.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25047.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+define void @fn1(i1 %c0, i1 %c1) {
+; CHECK-LABEL: @fn1(
+entry:
+  br i1 %c0, label %for.end.34, label %for.cond.1thread-pre-split
+
+for.cond.loopexit:                                ; preds = %for.end.29, %for.end.7
+  %f.lcssa = phi i32 [ %f.1, %for.end.29 ], [ %f.1, %for.end.7 ]
+  br i1 %c1, label %for.end.34, label %for.cond.1thread-pre-split
+
+for.cond.1thread-pre-split:                       ; preds = %for.cond.loopexit, %entry
+  %f.047 = phi i32 [ %f.lcssa, %for.cond.loopexit ], [ 0, %entry ]
+  br label %for.cond.1
+
+for.cond.1:                                       ; preds = %for.cond.1, %for.cond.1thread-pre-split
+  br i1 %c1, label %for.cond.4, label %for.cond.1
+
+for.cond.4:                                       ; preds = %for.end.29, %for.cond.1
+  %f.1 = phi i32 [ 0, %for.end.29 ], [ %f.047, %for.cond.1 ]
+  br label %for.cond.5
+
+for.cond.5:                                       ; preds = %for.cond.5, %for.cond.4
+  %h.0 = phi i32 [ 0, %for.cond.4 ], [ %inc, %for.cond.5 ]
+  %cmp = icmp slt i32 %h.0, 1
+  %inc = add nsw i32 %h.0, 1
+  br i1 %cmp, label %for.cond.5, label %for.end.7
+
+for.end.7:                                        ; preds = %for.cond.5
+  %g.lcssa = phi i32 [ %h.0, %for.cond.5 ]
+  %tobool10 = icmp eq i32 %g.lcssa, 0
+  br i1 %tobool10, label %for.end.8, label %for.cond.loopexit
+
+for.end.8:                       ; preds = %for.end.7
+  br i1 %c1, label %for.cond.19, label %for.end.29
+
+for.cond.19:                                      ; preds = %for.cond.19, %for.end.8
+  br label %for.cond.19
+
+for.end.29:                                       ; preds = %for.end.8
+  %tobool30 = icmp eq i32 %f.1, 0
+  br i1 %tobool30, label %for.cond.4, label %for.cond.loopexit
+
+for.end.34:                                       ; preds = %for.cond.loopexit, %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25051.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25051.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25051.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25051.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+define i32 @somefunc(double* %arr) {
+; CHECK-LABEL: @somefunc(
+entry:
+  br label %for.cond.1.preheader
+
+for.cond.1.preheader:                             ; preds = %for.inc.9, %entry
+  %index3.013 = phi i32 [ 0, %entry ], [ %index3.1.lcssa, %for.inc.9 ]
+  %index.012 = phi i32 [ 0, %entry ], [ %inc10, %for.inc.9 ]
+  %cmp2.9 = icmp sgt i32 %index.012, 0
+  br i1 %cmp2.9, label %for.body.3.lr.ph, label %for.inc.9
+
+for.body.3.lr.ph:                                 ; preds = %for.cond.1.preheader
+  %idxprom5 = sext i32 %index.012 to i64 
+  br label %for.body.3
+
+for.body.3:                                       ; preds = %for.body.3, %for.body.3.lr.ph
+  %index3.111 = phi i32 [ %index3.013, %for.body.3.lr.ph ], [ %inc, %for.body.3 ]
+  %index2.010 = phi i32 [ 0, %for.body.3.lr.ph ], [ %inc8, %for.body.3 ]
+  %inc = add nsw i32 %index3.111, 1
+  %idxprom = sext i32 %index3.111 to i64
+  %arrayidx = getelementptr inbounds double, double* %arr, i64 %idxprom
+  %idxprom4 = sext i32 %index2.010 to i64
+  %inc8 = add nsw i32 %index2.010, 1
+  %cmp2 = icmp slt i32 %inc8, %index.012
+  br i1 %cmp2, label %for.body.3, label %for.inc.9.loopexit
+
+for.inc.9.loopexit:                               ; preds = %for.body.3
+  %inc.lcssa = phi i32 [ %inc, %for.body.3 ]
+  br label %for.inc.9
+
+for.inc.9:                                        ; preds = %for.inc.9.loopexit, %for.cond.1.preheader
+  %index3.1.lcssa = phi i32 [ %index3.013, %for.cond.1.preheader ], [ %inc.lcssa, %for.inc.9.loopexit ]
+  %inc10 = add nsw i32 %index.012, 1
+  %cmp = icmp slt i32 %inc10, 10
+  br i1 %cmp, label %for.cond.1.preheader, label %for.end.11
+
+for.end.11:                                       ; preds = %for.inc.9
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25060.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25060.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25060.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25060.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+define i16 @fn1() {
+; CHECK-LABEL: @fn1(
+entry:
+  br label %bb1
+
+bb1:
+  %i = phi i16 [ 0, %entry ], [ 1, %bb1 ]
+  %storemerge = phi i16 [ %storemerge2, %bb1 ], [ 0, %entry ]
+  %storemerge2 = phi i16 [ 10, %entry ], [ 200, %bb1 ]
+  %tmp10 = icmp eq i16 %i, 1
+  br i1 %tmp10, label %bb5, label %bb1
+
+bb5:
+  %storemerge.lcssa = phi i16 [ %storemerge, %bb1 ]
+; CHECK: ret i16 10
+  ret i16 %storemerge.lcssa
+}
+
+define i16 @fn2() {
+; CHECK-LABEL: @fn2(
+entry:
+  br label %bb1
+
+bb1:
+  %canary = phi i16 [ 0, %entry ], [ %canary.inc, %bb1 ]
+  %i = phi i16 [ 0, %entry ], [ %storemerge, %bb1 ]
+  %storemerge = phi i16 [ 0, %bb1 ], [ 10, %entry ]
+  %canary.inc = add i16 %canary, 1
+  %_tmp10 = icmp eq i16 %i, 10
+  br i1 %_tmp10, label %bb5, label %bb1
+
+bb5:
+; CHECK: ret i16 1
+  ret i16 %canary
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25360.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25360.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25360.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25360.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+
+; Ensure that does not crash
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+; CHECK-LABEL: @f(
+entry:
+  br label %for.end
+
+for.condt:                         ; preds = %for.end
+  br i1 true, label %for.cond.0, label %for.end
+
+for.end:                                          ; preds = %for.body.3
+  %inc = select i1 undef, i32 2, i32 1
+  br i1 false, label %for.condt, label %for.cond.0
+
+for.cond.0:                       ; preds = %for.end, %for.condt
+  %init = phi i32 [ 0, %for.condt ], [ %inc, %for.end ]
+  br i1 true, label %for.end.13, label %for.body.9
+
+for.body.9:                                       ; preds = %for.body.9, %for.cond.0
+  %p1.addr.22 = phi i32 [ %inc10, %for.body.9 ], [ %init, %for.cond.0 ]
+  %inc10 = add i32 %p1.addr.22, 1
+  br i1 true, label %for.end.13, label %for.body.9
+
+for.end.13:                                       ; preds = %for.cond.7.for.end.13_crit_edge, %for.cond.0
+  %p1.addr.2.lcssa = phi i32 [ %inc10, %for.body.9 ], [ %init, %for.cond.0 ]
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25421.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25421.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25421.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25421.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+declare void @use(i1)
+
+define void @f(i32 %x) {
+; CHECK-LABEL: @f(
+ entry:
+  %conv = sext i32 %x to i64
+  %sub = add i64 %conv, -1
+  %ec = icmp sgt i32 %x, 0
+  br i1 %ec, label %loop, label %leave
+
+ loop:
+; CHECK: loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i64 %iv, 1
+  %cmp = icmp slt i64 %iv, %sub
+  call void @use(i1 %cmp)
+; CHECK: call void @use(i1 %cmp)
+; CHECK-NOT: call void @use(i1 true)
+
+  %be.cond = icmp slt i64 %iv.inc, %conv
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25576.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25576.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25576.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25576.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; 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 @fn1() {
+; CHECK-LABEL: @fn1(
+entry:
+  br label %for.cond.loopexit
+
+for.cond.loopexit:                                ; preds = %for.inc7, %for.cond.loopexit, %entry
+  %c.1.lcssa = phi i32 [ %inc8, %for.inc7 ], [ 0, %for.cond.loopexit ], [ 0, %entry ]
+  br i1 undef, label %for.cond.loopexit, label %for.cond4.preheader
+
+for.cond4.preheader:                              ; preds = %for.inc7, %for.cond.loopexit
+  %c.17 = phi i32 [ %inc8, %for.inc7 ], [ 0, %for.cond.loopexit ]
+  br label %for.body6
+
+for.body6:                                        ; preds = %for.body6, %for.cond4.preheader
+  %inc14 = phi i32 [ 0, %for.cond4.preheader ], [ %inc, %for.body6 ]
+  %idxprom = zext i32 %inc14 to i64
+  %inc = add i32 %inc14, 1
+  %cmp5 = icmp ult i32 %inc, 2
+  br i1 %cmp5, label %for.body6, label %for.inc7
+
+for.inc7:                                         ; preds = %for.body6
+  %inc.lcssa = phi i32 [ %inc, %for.body6 ]
+  %inc8 = add i32 %c.17, 1
+  %cmp = icmp ult i32 %inc8, %inc.lcssa
+  br i1 %cmp, label %for.cond4.preheader, label %for.cond.loopexit
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr25578.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr25578.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr25578.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr25578.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @use(i64 %x)
+
+; CHECK-LABEL: @foo
+define void @foo() {
+entry:
+  br label %L1_header
+
+L1_header:
+  br label %L2_header
+
+; CHECK: L2_header:
+; CHECK: %[[INDVAR:.*]] = phi i64
+; CHECK: %[[TRUNC:.*]] = trunc i64 %[[INDVAR]] to i32
+L2_header:
+  %i = phi i32 [ 0, %L1_header ], [ %i_next, %L2_latch ]
+  %i_prom = sext i32 %i to i64
+  call void @use(i64 %i_prom)
+  br label %L3_header
+
+L3_header:
+  br i1 undef, label %L3_latch, label %L2_exiting_1
+
+L3_latch:
+  br i1 undef, label %L3_header, label %L2_exiting_2
+
+L2_exiting_1:
+  br i1 undef, label %L2_latch, label %L1_latch
+
+L2_exiting_2:
+  br i1 undef, label %L2_latch, label %L1_latch
+
+L2_latch:
+  %i_next = add nsw i32 %i, 1
+  br label %L2_header
+
+L1_latch:
+; CHECK: L1_latch:
+; CHECK: %i_lcssa = phi i32 [ %[[TRUNC]], %L2_exiting_1 ], [ %[[TRUNC]], %L2_exiting_2 ]
+
+  %i_lcssa = phi i32 [ %i, %L2_exiting_1 ], [ %i, %L2_exiting_2 ]
+  br i1 undef, label %exit, label %L1_header
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr26973.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr26973.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr26973.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr26973.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+ at a = common global double* null, align 8
+ at b = common global double 0.000000e+00, align 8
+
+define void @fn1(i32 %p1) {
+; CHECK-LABEL: @fn1(
+entry:
+  %ld = load double*, double** @a, align 8
+  br label %outer.loop
+
+outer.loop:
+  %iv.outer = phi i32 [ %p1, %entry ], [ %iv.outer.dec, %outer.be ]
+  %idxprom = sext i32 %iv.outer to i64
+  %arrayidx = getelementptr inbounds double, double* %ld, i64 %idxprom
+  %arrayidx.bc = bitcast double* %arrayidx to i64*
+  br label %inner.loop
+
+inner.loop:
+  %iv.inner = phi i32 [ %iv.outer, %outer.loop ], [ %iv.inner.dec, %inner.loop ]
+  %ld.arr = load i64, i64* %arrayidx.bc, align 8
+  store i64 %ld.arr, i64* bitcast (double* @b to i64*), align 8
+  %iv.inner.dec = add nsw i32 %iv.inner, -1
+  %cmp = icmp slt i32 %iv.outer, %iv.inner.dec
+  br i1 %cmp, label %outer.be, label %inner.loop
+
+outer.be:
+  %iv.outer.dec = add nsw i32 %iv.outer, -1
+  br label %outer.loop
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr26974.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr26974.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr26974.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr26974.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt -indvars  -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; indvars will try to replace %b.0.lcssa with %t.1. If it does this,
+; it will break LCSSA.
+
+ at c = external global i32, align 4
+
+; CHECK-LABEL: @fn1
+define void @fn1() {
+entry:
+  br label %for.body
+
+for.cond1.preheader:                              ; preds = %for.body
+  %0 = load i32, i32* @c, align 4
+  br i1 undef, label %for.cond1.us.preheader, label %for.cond1
+
+for.cond1.us.preheader:                           ; preds = %for.cond1.preheader
+  br label %for.cond1.us
+
+for.cond1.us:                                     ; preds = %for.cond1.us, %for.cond1.us.preheader
+  br label %for.cond1.us
+
+for.body:                                         ; preds = %for.body, %entry
+  br i1 undef, label %for.body, label %for.cond1.preheader
+
+for.cond1:                                        ; preds = %for.cond1.preheader
+  br i1 true, label %for.body9.lr.ph, label %for.cond13.preheader
+
+for.body9.lr.ph:                                  ; preds = %for.cond1
+  br i1 undef, label %for.body9.us.preheader, label %for.body9
+
+for.body9.us.preheader:                           ; preds = %for.body9.lr.ph
+  br label %for.body9.us
+
+for.body9.us:                                     ; preds = %for.body9.us, %for.body9.us.preheader
+  br label %for.body9.us
+
+for.cond13.preheader:                             ; preds = %for.body9, %for.cond1
+  %b.0.lcssa = phi i32 [ %0, %for.body9 ], [ 0, %for.cond1 ]
+  br label %for.cond13
+
+for.body9:                                        ; preds = %for.body9.lr.ph
+  br label %for.cond13.preheader
+
+for.cond13:                                       ; preds = %for.cond13, %for.cond13.preheader
+  %d.1 = phi i32 [ %t.1, %for.cond13 ], [ %0, %for.cond13.preheader ]
+  %t.1 = phi i32 [ %b.0.lcssa, %for.cond13 ], [ %0, %for.cond13.preheader ]
+  br i1 undef, label %for.cond18.preheader, label %for.cond13
+
+for.cond18.preheader:                             ; preds = %for.cond13
+  br label %for.cond18
+
+for.cond18:                                       ; preds = %for.cond18, %for.cond18.preheader
+  %b.1 = phi i32 [ %xor, %for.cond18 ], [ %b.0.lcssa, %for.cond18.preheader ]
+  %add = add nsw i32 %b.1, %d.1
+  %xor = xor i32 %add, %b.1
+  br label %for.cond18
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr27133.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr27133.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr27133.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr27133.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+define i32 @fn2() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %c.0 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+; CHECK: %[[WIDE:.*]] = phi i64
+; CHECK: %[[NORM:.*]] = phi i32
+; CHECK: invoke void @fn1(i64 %[[WIDE]])
+  %idxprom = sext i32 %c.0 to i64
+  invoke void @fn1(i64 %idxprom)
+          to label %for.inc unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %for.cond
+  %c.0.lcssa = phi i32 [ %c.0, %for.cond ]
+; CHECK: %[[LCSSA:.*]] = phi i32 [ %[[NORM]],
+  %0 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %0 [i8* null, i32 64, i8* null]
+  catchret from %1 to label %exit
+
+exit:
+; CHECK: ret i32 %[[LCSSA]]
+  ret i32 %c.0.lcssa
+
+for.inc:                                          ; preds = %for.cond
+  %inc = add nsw nuw i32 %c.0, 1
+  br label %for.cond
+}
+
+declare void @fn1(i64 %idxprom)
+
+declare i32 @__CxxFrameHandler3(...)

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr28935.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr28935.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr28935.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr28935.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; 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"
+
+declare i16 @fn1(i16 returned, i64)
+
+define void @fn2() {
+; CHECK-LABEL: @fn2(
+entry:
+  br label %for.cond
+
+for.cond:
+  %f.0 = phi i64 [ undef, %entry ], [ %inc, %for.cond ]
+  %conv = trunc i64 %f.0 to i16
+  %call = tail call i16 @fn1(i16 %conv, i64 %f.0)
+  %conv2 = zext i16 %call to i32
+  %inc = add nsw i64 %f.0, 1
+  br label %for.cond
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr32045.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr32045.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr32045.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr32045.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; This is not an IndVarSimplify bug, but the original symptom
+; manifested as one.
+
+define i32 @foo(i32 %a, i32 %b, i32 %c, i32* %sink) {
+; CHECK-LABEL: @foo(
+; CHECK:       for.end:
+; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 %neg3, -1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 0, [[SHR]]
+; CHECK-NEXT:    [[SHR1:%.*]] = ashr i32 [[SUB]], [[B:%.*]]
+; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[SHR1]], -1
+; CHECK-NEXT:    store i32 [[NEG]], i32* %sink
+;
+entry:
+  %tobool2 = icmp eq i32 %a, 0
+  br i1 %tobool2, label %exit, label %preheader
+
+preheader:
+  %neg3 = phi i32 [ %c, %entry ], [ %neg, %for.end ]
+  br label %for
+
+for:
+  %p = phi i32 [ %dec, %for ], [ 1, %preheader ]
+  %cmp = icmp sgt i32 %p, -1
+  %dec = add nsw i32 %p, -1
+  br i1 %cmp, label %for, label %for.end
+
+for.end:
+  %shr = ashr i32 %neg3, %p
+  %sub = sub nsw i32 0, %shr
+  %shr1 = ashr i32 %sub, %b
+  %neg = xor i32 %shr1, -1
+  store i32 %neg, i32* %sink
+  br i1 false, label %exit, label %preheader
+
+exit:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr35406.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr35406.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr35406.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr35406.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,88 @@
+; 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"
+
+define i32 @testDiv(i8* %p, i64* %p1) {
+; CHECK-LABEL: @testDiv
+entry:
+  br label %loop1
+
+loop1:
+  %local_0_ = phi i32 [ 8, %entry ], [ %9, %loop2.exit ]
+  %local_2_ = phi i32 [ 63864, %entry ], [ %local_2_43, %loop2.exit ]
+  %local_3_ = phi i32 [ 51, %entry ], [ %local_3_44, %loop2.exit ]
+; CHECK-NOT:  udiv
+  %0 = udiv i32 14, %local_0_
+  %1 = icmp ugt i32 %local_0_, 14
+  br i1 %1, label %exit, label %general_case24
+
+; CHECK-LABEL: general_case24
+general_case24:
+  %2 = udiv i32 60392, %0
+  br i1 false, label %loop2, label %loop2.exit
+
+loop2:
+  %local_1_56 = phi i32 [ %2, %general_case24 ], [ %3, %loop2 ]
+  %local_2_57 = phi i32 [ 1, %general_case24 ], [ %7, %loop2 ]
+  %3 = add i32 %local_1_56, -1
+  %4 = load atomic i64, i64* %p1 unordered, align 8
+  %5 = sext i32 %3 to i64
+  %6 = sub i64 %4, %5
+  store atomic i64 %6, i64* %p1 unordered, align 8
+  %7 = add nuw nsw i32 %local_2_57, 1
+  %8 = icmp ugt i32 %local_2_57, 7
+  br i1 %8, label %loop2.exit, label %loop2
+
+loop2.exit:
+  %local_2_43 = phi i32 [ %local_2_, %general_case24 ], [ 9, %loop2 ]
+  %local_3_44 = phi i32 [ %local_3_, %general_case24 ], [ %local_1_56, %loop2 ]
+  %9 = add nuw nsw i32 %local_0_, 1
+  %10 = icmp ugt i32 %local_0_, 129
+  br i1 %10, label %exit, label %loop1
+
+exit:
+  ret i32 0
+}
+
+define i32 @testRem(i8* %p, i64* %p1) {
+; CHECK-LABEL: @testRem
+entry:
+  br label %loop1
+
+loop1:
+  %local_0_ = phi i32 [ 8, %entry ], [ %9, %loop2.exit ]
+  %local_2_ = phi i32 [ 63864, %entry ], [ %local_2_43, %loop2.exit ]
+  %local_3_ = phi i32 [ 51, %entry ], [ %local_3_44, %loop2.exit ]
+; CHECK:  udiv
+; CHECK-NOT:  udiv
+  %0 = udiv i32 14, %local_0_
+  %1 = icmp ugt i32 %local_0_, 14
+  br i1 %1, label %exit, label %general_case24
+
+; CHECK-LABEL: general_case24
+general_case24:
+  %2 = urem i32 60392, %0
+  br i1 false, label %loop2, label %loop2.exit
+
+loop2:
+  %local_1_56 = phi i32 [ %2, %general_case24 ], [ %3, %loop2 ]
+  %local_2_57 = phi i32 [ 1, %general_case24 ], [ %7, %loop2 ]
+  %3 = add i32 %local_1_56, -1
+  %4 = load atomic i64, i64* %p1 unordered, align 8
+  %5 = sext i32 %3 to i64
+  %6 = sub i64 %4, %5
+  store atomic i64 %6, i64* %p1 unordered, align 8
+  %7 = add nuw nsw i32 %local_2_57, 1
+  %8 = icmp ugt i32 %local_2_57, 7
+  br i1 %8, label %loop2.exit, label %loop2
+
+loop2.exit:
+  %local_2_43 = phi i32 [ %local_2_, %general_case24 ], [ 9, %loop2 ]
+  %local_3_44 = phi i32 [ %local_3_, %general_case24 ], [ %local_1_56, %loop2 ]
+  %9 = add nuw nsw i32 %local_0_, 1
+  %10 = icmp ugt i32 %local_0_, 129
+  br i1 %10, label %exit, label %loop1
+
+exit:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr38674.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr38674.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr38674.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr38674.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,141 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; Check that we don't reuse %zext instead of %inc11 for LCSSA Phi node. Case
+; with constants SCEV.
+
+define i32 @test_01() {
+; CHECK-LABEL: @test_01(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER:%.*]]
+; CHECK:       for.cond1.preheader:
+; CHECK-NEXT:    br label [[FOR_COND4_PREHEADER:%.*]]
+; CHECK:       for.cond4.preheader:
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext i16 1 to i32
+; CHECK-NEXT:    br label [[FOR_BODY6:%.*]]
+; CHECK:       for.cond4:
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[INC:%.*]], 2
+; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY6]], label [[FOR_END:%.*]]
+; CHECK:       for.body6:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[FOR_COND4_PREHEADER]] ], [ [[INC]], [[FOR_COND4:%.*]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i32 [[IV]], [[ZEXT]]
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    br i1 [[TMP0]], label [[RETURN_LOOPEXIT:%.*]], label [[FOR_COND4]]
+; CHECK:       for.end:
+; CHECK-NEXT:    br i1 false, label [[FOR_COND4_PREHEADER]], label [[FOR_END9:%.*]]
+; CHECK:       for.end9:
+; CHECK-NEXT:    br i1 false, label [[FOR_COND1_PREHEADER]], label [[RETURN_LOOPEXIT3:%.*]]
+; CHECK:       return.loopexit:
+; CHECK-NEXT:    unreachable
+; CHECK:       return.loopexit3:
+; CHECK-NEXT:    br label [[RETURN:%.*]]
+; CHECK:       return:
+; CHECK-NEXT:    ret i32 1
+;
+entry:
+  br label %for.cond1.preheader
+
+for.cond1.preheader:                              ; preds = %for.end9, %entry
+  br label %for.cond4.preheader
+
+for.cond4.preheader:                              ; preds = %for.end, %for.cond1.preheader
+  %zext = zext i16 1 to i32
+  br label %for.body6
+
+for.cond4:                                        ; preds = %for.body6
+  %cmp5 = icmp ult i32 %inc, 2
+  br i1 %cmp5, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4, %for.cond4.preheader
+  %iv = phi i32 [ 0, %for.cond4.preheader ], [ %inc, %for.cond4 ]
+  %0 = icmp eq i32 %iv, %zext
+  %inc = add nuw nsw i32 %iv, 1
+  br i1 %0, label %return.loopexit, label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br i1 false, label %for.cond4.preheader, label %for.end9
+
+for.end9:                                         ; preds = %for.end
+  %inc11 = add nuw nsw i32 0, 1
+  br i1 false, label %for.cond1.preheader, label %return.loopexit3
+
+return.loopexit:                                  ; preds = %for.body6
+  unreachable
+
+return.loopexit3:                                 ; preds = %for.end9
+  %inc11.lcssa = phi i32 [ %inc11, %for.end9 ]
+  br label %return
+
+return:                                           ; preds = %return.loopexit3
+  ret i32 %inc11.lcssa
+}
+
+; Same as test_01, but the instructions with the same SCEV have a non-constant
+; SCEV.
+define i32 @test_02(i32 %x) {
+; CHECK-LABEL: @test_02(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER:%.*]]
+; CHECK:       for.cond1.preheader:
+; CHECK-NEXT:    br label [[FOR_COND4_PREHEADER:%.*]]
+; CHECK:       for.cond4.preheader:
+; CHECK-NEXT:    [[ZEXT:%.*]] = mul i32 [[X:%.*]], 1
+; CHECK-NEXT:    br label [[FOR_BODY6:%.*]]
+; CHECK:       for.cond4:
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp ult i32 [[INC:%.*]], 2
+; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY6]], label [[FOR_END:%.*]]
+; CHECK:       for.body6:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[FOR_COND4_PREHEADER]] ], [ [[INC]], [[FOR_COND4:%.*]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i32 [[IV]], [[ZEXT]]
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    br i1 [[TMP0]], label [[RETURN_LOOPEXIT:%.*]], label [[FOR_COND4]]
+; CHECK:       for.end:
+; CHECK-NEXT:    br i1 false, label [[FOR_COND4_PREHEADER]], label [[FOR_END9:%.*]]
+; CHECK:       for.end9:
+; CHECK-NEXT:    [[INC11:%.*]] = add nuw nsw i32 0, [[X]]
+; CHECK-NEXT:    br i1 false, label [[FOR_COND1_PREHEADER]], label [[RETURN_LOOPEXIT3:%.*]]
+; CHECK:       return.loopexit:
+; CHECK-NEXT:    unreachable
+; CHECK:       return.loopexit3:
+; CHECK-NEXT:    [[INC11_LCSSA:%.*]] = phi i32 [ [[INC11]], [[FOR_END9]] ]
+; CHECK-NEXT:    br label [[RETURN:%.*]]
+; CHECK:       return:
+; CHECK-NEXT:    ret i32 [[INC11_LCSSA]]
+;
+entry:
+  br label %for.cond1.preheader
+
+for.cond1.preheader:                              ; preds = %for.end9, %entry
+  br label %for.cond4.preheader
+
+for.cond4.preheader:                              ; preds = %for.end, %for.cond1.preheader
+  %zext = mul i32 %x, 1
+  br label %for.body6
+
+for.cond4:                                        ; preds = %for.body6
+  %cmp5 = icmp ult i32 %inc, 2
+  br i1 %cmp5, label %for.body6, label %for.end
+
+for.body6:                                        ; preds = %for.cond4, %for.cond4.preheader
+  %iv = phi i32 [ 0, %for.cond4.preheader ], [ %inc, %for.cond4 ]
+  %0 = icmp eq i32 %iv, %zext
+  %inc = add nuw nsw i32 %iv, 1
+  br i1 %0, label %return.loopexit, label %for.cond4
+
+for.end:                                          ; preds = %for.cond4
+  br i1 false, label %for.cond4.preheader, label %for.end9
+
+for.end9:                                         ; preds = %for.end
+  %inc11 = add nuw nsw i32 0, %x
+  br i1 false, label %for.cond1.preheader, label %return.loopexit3
+
+return.loopexit:                                  ; preds = %for.body6
+  unreachable
+
+return.loopexit3:                                 ; preds = %for.end9
+  %inc11.lcssa = phi i32 [ %inc11, %for.end9 ]
+  br label %return
+
+return:                                           ; preds = %return.loopexit3
+  ret i32 %inc11.lcssa
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr38855.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr38855.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr38855.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr38855.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -disable-nounwind-inference=false -inline -functionattrs -indvars  < %s | FileCheck %s
+
+; Check that the invalidation happens correctly and the test does not crash.
+define void @f2() {
+; CHECK-LABEL: @f2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    br label [[FOR_COND]]
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond, %entry
+  %a.0 = phi i32 [ 1, %entry ], [ 0, %for.cond ]
+  call void @f1(i32 %a.0)
+  br label %for.cond
+}
+
+define internal void @f1(i32 %p1) noinline {
+entry:
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr39673.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+define i16 @test() {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP1:%.*]]
+; CHECK:       loop1:
+; CHECK-NEXT:    [[L1:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[L1_ADD:%.*]], [[LOOP1]] ]
+; CHECK-NEXT:    [[L1_ADD]] = add nuw nsw i16 [[L1]], 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i16 [[L1_ADD]], 2
+; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP1]], label [[LOOP2_PREHEADER:%.*]]
+; CHECK:       loop2.preheader:
+; CHECK-NEXT:    br label [[LOOP2:%.*]]
+; CHECK:       loop2:
+; CHECK-NEXT:    [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ 182, [[LOOP2_PREHEADER]] ]
+; CHECK-NEXT:    [[L2:%.*]] = phi i16 [ [[L2_ADD:%.*]], [[LOOP2]] ], [ 0, [[LOOP2_PREHEADER]] ]
+; CHECK-NEXT:    [[L2_ADD]] = add nuw nsw i16 [[L2]], 1
+; CHECK-NEXT:    tail call void @foo(i16 [[K2]])
+; CHECK-NEXT:    [[K2_ADD]] = add nuw nsw i16 [[K2]], 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i16 [[L2_ADD]], 2
+; CHECK-NEXT:    br i1 [[CMP2]], label [[LOOP2]], label [[LOOP2_END:%.*]]
+; CHECK:       loop2.end:
+; CHECK-NEXT:    [[K2_ADD_LCSSA:%.*]] = phi i16 [ [[K2_ADD]], [[LOOP2]] ]
+; CHECK-NEXT:    ret i16 [[K2_ADD_LCSSA]]
+;
+entry:
+  br label %loop1
+
+loop1:                                           ; preds = %entry, %loop1
+  %k1 = phi i16 [ 180, %entry ], [ %k1.add, %loop1 ]
+  %l1 = phi i16 [ 0, %entry ], [ %l1.add, %loop1 ]
+  %k1.add = add nuw nsw i16 %k1, 1
+  %l1.add = add nuw nsw i16 %l1, 1
+  %cmp1 = icmp ult i16 %l1.add, 2
+  br i1 %cmp1, label %loop1, label %loop2.preheader
+
+loop2.preheader:                                 ; preds = %loop1
+  %k1.add.lcssa = phi i16 [ %k1.add, %loop1 ]
+  br label %loop2
+
+loop2:                                           ; preds = %loop2.preheader, %loop2
+  %k2 = phi i16 [ %k2.add, %loop2 ], [ %k1.add.lcssa, %loop2.preheader ]
+  %l2 = phi i16 [ %l2.add, %loop2 ], [ 0, %loop2.preheader ]
+  %l2.add = add nuw i16 %l2, 1
+  tail call void @foo(i16 %k2)
+  %k2.add = add nuw nsw i16 %k2, 1
+  %cmp2 = icmp ult i16 %l2.add, 2
+  br i1 %cmp2, label %loop2, label %loop2.end
+
+loop2.end:                                       ; preds = %loop2
+  %k2.add.lcssa = phi i16 [ %k2.add, %loop2 ]
+  ret i16 %k2.add.lcssa
+}
+
+declare void @foo(i16)

Added: llvm/trunk/test/Transforms/IndVarSimplify/pr40454.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/pr40454.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/pr40454.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/pr40454.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,62 @@
+; 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"
+
+define void @test() {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ -9, [[BB:%.*]] ], [ [[TMP6:%.*]], [[BB1:%.*]] ]
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ -9, [[BB2]] ], [ [[TMP6]], [[BB10:%.*]] ]
+; CHECK-NEXT:    br i1 false, label [[BB5:%.*]], label [[BB12:%.*]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[TMP6]] = add nsw i32 [[TMP4]], -1
+; CHECK-NEXT:    br i1 undef, label [[BB8:%.*]], label [[BB9:%.*]]
+; CHECK:       bb8:
+; CHECK-NEXT:    br label [[BB10]]
+; CHECK:       bb9:
+; CHECK-NEXT:    br label [[BB10]]
+; CHECK:       bb10:
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb12:
+; CHECK-NEXT:    ret void
+;
+
+bb:
+  br label %bb2
+
+bb1:                                              ; No predecessors!
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb
+  %tmp = phi i32 [ -9, %bb ], [ %tmp6, %bb1 ]
+  br label %bb3
+
+bb3:                                              ; preds = %bb10, %bb2
+  %tmp4 = phi i32 [ -9, %bb2 ], [ %tmp6, %bb10 ]
+  br i1 undef, label %bb5, label %bb12
+
+bb5:                                              ; preds = %bb3
+  %tmp6 = add i32 %tmp4, -1
+  %tmp7 = zext i32 %tmp6 to i64
+  br i1 undef, label %bb8, label %bb9
+
+bb8:                                              ; preds = %bb5
+  br label %bb10
+
+bb9:                                              ; preds = %bb5
+  br label %bb10
+
+bb10:                                             ; preds = %bb9, %bb8
+  %tmp11 = and i64 undef, %tmp7
+  br label %bb3
+
+bb12:                                             ; preds = %bb3
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Indvars should insert a 64-bit induction variable to eliminate the
+; sext for the addressing, however it shouldn't eliminate the sext
+; on the other phi, since that value undergoes signed wrapping.
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+define void @foo(i32* nocapture %d, i32 %n) nounwind {
+entry:
+	%0 = icmp sgt i32 %n, 0		; <i1> [#uses=1]
+	br i1 %0, label %bb.nph, label %return
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+; CHECK: bb:
+; CHECK: phi i64
+; CHECK: sext i8
+; CHECK-NOT: sext
+bb:		; preds = %bb1, %bb.nph
+	%i.02 = phi i32 [ %5, %bb1 ], [ 0, %bb.nph ]		; <i32> [#uses=2]
+	%p.01 = phi i8 [ %4, %bb1 ], [ -1, %bb.nph ]		; <i8> [#uses=2]
+	%1 = sext i8 %p.01 to i32		; <i32> [#uses=1]
+	%2 = sext i32 %i.02 to i64		; <i64> [#uses=1]
+	%3 = getelementptr i32, i32* %d, i64 %2		; <i32*> [#uses=1]
+	store i32 %1, i32* %3, align 4
+	%4 = add i8 %p.01, 1		; <i8> [#uses=1]
+	%5 = add i32 %i.02, 1		; <i32> [#uses=2]
+	br label %bb1
+
+bb1:		; preds = %bb
+	%6 = icmp slt i32 %5, %n		; <i1> [#uses=1]
+	br i1 %6, label %bb, label %bb1.return_crit_edge
+
+bb1.return_crit_edge:		; preds = %bb1
+	br label %return
+
+return:		; preds = %bb1.return_crit_edge, %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,230 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+; CHECK-NOT: sext
+
+define i64 @test(i64* nocapture %first, i32 %count) nounwind readonly {
+entry:
+	%t0 = icmp sgt i32 %count, 0		; <i1> [#uses=1]
+	br i1 %t0, label %bb.nph, label %bb2
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb1, %bb.nph
+	%result.02 = phi i64 [ %t5, %bb1 ], [ 0, %bb.nph ]		; <i64> [#uses=1]
+	%n.01 = phi i32 [ %t6, %bb1 ], [ 0, %bb.nph ]		; <i32> [#uses=2]
+	%t1 = sext i32 %n.01 to i64		; <i64> [#uses=1]
+	%t2 = getelementptr i64, i64* %first, i64 %t1		; <i64*> [#uses=1]
+	%t3 = load i64, i64* %t2, align 8		; <i64> [#uses=1]
+	%t4 = lshr i64 %t3, 4		; <i64> [#uses=1]
+	%t5 = add i64 %t4, %result.02		; <i64> [#uses=2]
+	%t6 = add i32 %n.01, 1		; <i32> [#uses=2]
+	br label %bb1
+
+bb1:		; preds = %bb
+	%t7 = icmp slt i32 %t6, %count		; <i1> [#uses=1]
+	br i1 %t7, label %bb, label %bb1.bb2_crit_edge
+
+bb1.bb2_crit_edge:		; preds = %bb1
+	%.lcssa = phi i64 [ %t5, %bb1 ]		; <i64> [#uses=1]
+	br label %bb2
+
+bb2:		; preds = %bb1.bb2_crit_edge, %entry
+	%result.0.lcssa = phi i64 [ %.lcssa, %bb1.bb2_crit_edge ], [ 0, %entry ]		; <i64> [#uses=1]
+	ret i64 %result.0.lcssa
+}
+
+define void @foo(i16 signext %N, i32* nocapture %P) nounwind {
+entry:
+	%t0 = icmp sgt i16 %N, 0		; <i1> [#uses=1]
+	br i1 %t0, label %bb.nph, label %return
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb1, %bb.nph
+	%i.01 = phi i16 [ %t3, %bb1 ], [ 0, %bb.nph ]		; <i16> [#uses=2]
+	%t1 = sext i16 %i.01 to i64		; <i64> [#uses=1]
+	%t2 = getelementptr i32, i32* %P, i64 %t1		; <i32*> [#uses=1]
+	store i32 123, i32* %t2, align 4
+	%t3 = add i16 %i.01, 1		; <i16> [#uses=2]
+	br label %bb1
+
+bb1:		; preds = %bb
+	%t4 = icmp slt i16 %t3, %N		; <i1> [#uses=1]
+	br i1 %t4, label %bb, label %bb1.return_crit_edge
+
+bb1.return_crit_edge:		; preds = %bb1
+	br label %return
+
+return:		; preds = %bb1.return_crit_edge, %entry
+	ret void
+}
+
+; Test cases from PR1301:
+
+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
+}
+
+define void @promote_latch_condition_decrementing_loop_01(i32* %p, i32* %a) {
+
+; CHECK-LABEL: @promote_latch_condition_decrementing_loop_01(
+; CHECK-NOT:     trunc
+
+entry:
+  %len = load i32, i32* %p, align 4, !range !0
+  %len.minus.1 = add nsw i32 %len, -1
+  %zero_check = icmp eq i32 %len, 0
+  br i1 %zero_check, label %loopexit, label %preheader
+
+preheader:
+  br label %loop
+
+loopexit:
+  ret void
+
+loop:
+  %iv = phi i32 [ %iv.next, %loop ], [ %len.minus.1, %preheader ]
+  ; CHECK: %indvars.iv = phi i64
+  %iv.wide = zext i32 %iv to i64
+  %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide
+  store atomic i32 0, i32* %el unordered, align 4
+  %iv.next = add nsw i32 %iv, -1
+  ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1
+  %loopcond = icmp slt i32 %iv, 1
+  br i1 %loopcond, label %loopexit, label %loop
+}
+
+define void @promote_latch_condition_decrementing_loop_02(i32* %p, i32* %a) {
+
+; CHECK-LABEL: @promote_latch_condition_decrementing_loop_02(
+; CHECK-NOT:     trunc
+
+entry:
+  %len = load i32, i32* %p, align 4, !range !0
+  %zero_check = icmp eq i32 %len, 0
+  br i1 %zero_check, label %loopexit, label %preheader
+
+preheader:
+  br label %loop
+
+loopexit:
+  ret void
+
+loop:
+  %iv = phi i32 [ %iv.next, %loop ], [ %len, %preheader ]
+  ; CHECK: %indvars.iv = phi i64
+  %iv.wide = zext i32 %iv to i64
+  %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide
+  store atomic i32 0, i32* %el unordered, align 4
+  %iv.next = add nsw i32 %iv, -1
+  ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1
+  %loopcond = icmp slt i32 %iv, 1
+  br i1 %loopcond, label %loopexit, label %loop
+}
+
+define void @promote_latch_condition_decrementing_loop_03(i32* %p, i32* %a) {
+
+; CHECK-LABEL: @promote_latch_condition_decrementing_loop_03(
+; CHECK-NOT:     trunc
+
+entry:
+  %len = load i32, i32* %p, align 4, !range !0
+  %len.plus.1 = add i32 %len, 1
+  %zero_check = icmp eq i32 %len, 0
+  br i1 %zero_check, label %loopexit, label %preheader
+
+preheader:
+  br label %loop
+
+loopexit:
+  ret void
+
+loop:
+  %iv = phi i32 [ %iv.next, %loop ], [ %len.plus.1, %preheader ]
+  ; CHECK: %indvars.iv = phi i64
+  %iv.wide = zext i32 %iv to i64
+  %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide
+  store atomic i32 0, i32* %el unordered, align 4
+  %iv.next = add nsw i32 %iv, -1
+  ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1
+  %loopcond = icmp slt i32 %iv, 1
+  br i1 %loopcond, label %loopexit, label %loop
+}
+
+define void @promote_latch_condition_decrementing_loop_04(i32* %p, i32* %a, i1 %cond) {
+
+; CHECK-LABEL: @promote_latch_condition_decrementing_loop_04(
+; CHECK-NOT:     trunc
+
+entry:
+  %len = load i32, i32* %p, align 4, !range !0
+  %len.minus.1 = add nsw i32 %len, -1
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %iv_start = phi i32 [ %len, %if.true ], [%len.minus.1, %if.false ]
+  %zero_check = icmp eq i32 %len, 0
+  br i1 %zero_check, label %loopexit, label %preheader
+
+preheader:
+  br label %loop
+
+loopexit:
+  ret void
+
+loop:
+  %iv = phi i32 [ %iv.next, %loop ], [ %iv_start, %preheader ]
+  ; CHECK: %indvars.iv = phi i64
+  %iv.wide = zext i32 %iv to i64
+  %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide
+  store atomic i32 0, i32* %el unordered, align 4
+  %iv.next = add nsw i32 %iv, -1
+  ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1
+  %loopcond = icmp slt i32 %iv, 1
+  br i1 %loopcond, label %loopexit, label %loop
+}
+
+!0 = !{i32 0, i32 2147483647}

Added: llvm/trunk/test/Transforms/IndVarSimplify/replace-iv-with-loop-invariant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/replace-iv-with-loop-invariant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/replace-iv-with-loop-invariant.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/replace-iv-with-loop-invariant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,88 @@
+; 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"
+
+ at G = external global i32
+
+define void @test0(i64* %arg) {
+bb:
+  br label %bb2
+
+bb2:
+  %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
+  %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* null)
+  %tmp5 = load i32, i32* %tmp4, align 8
+  %tmp7 = load i64*, i64** undef, align 8
+  br label %bb2
+}
+
+; CHECK-LABEL: void @test0
+; CHECK:         load i32, i32* null
+
+define void @test1(i64* %arg) {
+bb:
+  br label %bb2
+
+bb2:
+  %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
+  %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* inttoptr (i64 4 to i32*))
+  %tmp5 = load i32, i32* %tmp4
+  %tmp7 = load i64*, i64** undef, align 8
+  br label %bb2
+}
+
+; CHECK-LABEL: void @test1
+; CHECK:         load i32, i32* inttoptr (i64 4 to i32*)
+
+define void @test2(i64* %arg) {
+bb:
+  br label %bb2
+
+bb2:
+  %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
+  %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* @G)
+  %tmp5 = load i32, i32* %tmp4
+  %tmp7 = load i64*, i64** undef, align 8
+  br label %bb2
+}
+
+; CHECK-LABEL: void @test2
+; CHECK:         load i32, i32* @G
+
+
+define void @test3(i64* %arg, i32* %loop.invariant) {
+bb:
+  br label %bb2
+
+bb2:
+  %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
+  %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* %loop.invariant)
+  %tmp5 = load i32, i32* %tmp4
+  %tmp7 = load i64*, i64** undef, align 8
+  br label %bb2
+}
+
+; CHECK-LABEL: void @test3
+; CHECK:         load i32, i32* %loop.invariant
+
+define void @test4(i64* %arg, i32* %loop.invariant, i64 %N) {
+bb:
+  br label %bb2
+
+bb2:
+  %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
+  %mul = mul nsw i64 %N, 64
+  %ptr = getelementptr inbounds i32, i32* %loop.invariant, i64 %mul 
+  %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* %ptr)
+  %tmp5 = load i32, i32* %tmp4
+  %tmp7 = load i64*, i64** undef, align 8
+  br label %bb2
+}
+
+; CHECK-LABEL: void @test4
+; CHECK:         [[P:%[a-zA-Z$._0-9]+]] = getelementptr i32, i32* %loop.invariant
+; CHECK:         phi
+; CHECK:         load i32, i32* [[P]]
+
+declare i32* @wobble(i64*, i32* returned)

Added: llvm/trunk/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,197 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+define i32 @remove_loop(i32 %size) {
+; CHECK-LABEL: @remove_loop(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 -1, [[SIZE:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[TMP0]], -32
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -32
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[SIZE]], [[UMAX]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 32
+; CHECK-NEXT:    [[TMP4:%.*]] = lshr i32 [[TMP3]], 5
+; CHECK-NEXT:    [[TMP5:%.*]] = shl i32 [[TMP4]], 5
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[SIZE_ADDR_0:%.*]] = phi i32 [ [[SIZE]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[WHILE_COND]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[SIZE_ADDR_0]], 31
+; CHECK-NEXT:    [[SUB]] = add i32 [[SIZE_ADDR_0]], -32
+; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_COND]], label [[WHILE_END:%.*]]
+; CHECK:       while.end:
+; CHECK-NEXT:    [[TMP6:%.*]] = sub i32 [[SIZE]], [[TMP5]]
+; CHECK-NEXT:    ret i32 [[TMP6]]
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond, %entry
+  %size.addr.0 = phi i32 [ %size, %entry ], [ %sub, %while.cond ]
+  %cmp = icmp ugt i32 %size.addr.0, 31
+  %sub = add i32 %size.addr.0, -32
+  br i1 %cmp, label %while.cond, label %while.end
+
+while.end:                                        ; preds = %while.cond
+  %size.lcssa = phi i32 [ %size.addr.0, %while.cond ]
+  ret i32 %size.lcssa
+}
+
+define i32 @used_loop(i32 %size) minsize {
+; CHECK-LABEL: @used_loop(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[SIZE_ADDR_0:%.*]] = phi i32 [ [[SIZE:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[WHILE_COND]] ]
+; CHECK-NEXT:    tail call void @call()
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[SIZE_ADDR_0]], 31
+; CHECK-NEXT:    [[SUB]] = add i32 [[SIZE_ADDR_0]], -32
+; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_COND]], label [[WHILE_END:%.*]]
+; CHECK:       while.end:
+; CHECK-NEXT:    [[SIZE_LCSSA:%.*]] = phi i32 [ [[SIZE_ADDR_0]], [[WHILE_COND]] ]
+; CHECK-NEXT:    ret i32 [[SIZE_LCSSA]]
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond, %entry
+  %size.addr.0 = phi i32 [ %size, %entry ], [ %sub, %while.cond ]
+  tail call void @call()
+  %cmp = icmp ugt i32 %size.addr.0, 31
+  %sub = add i32 %size.addr.0, -32
+  br i1 %cmp, label %while.cond, label %while.end
+
+while.end:                                        ; preds = %while.cond
+  %size.lcssa = phi i32 [ %size.addr.0, %while.cond ]
+  ret i32 %size.lcssa
+}
+
+
+define i32 @test_signed_while(i32 %S) {
+; CHECK-LABEL: @test_signed_while(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[S_ADDR_0:%.*]] = phi i32 [ [[S:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[WHILE_BODY:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[S_ADDR_0]], 31
+; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_END:%.*]]
+; CHECK:       while.body:
+; CHECK-NEXT:    [[SUB]] = add nsw i32 [[S_ADDR_0]], -32
+; CHECK-NEXT:    tail call void @call()
+; CHECK-NEXT:    br label [[WHILE_COND]]
+; CHECK:       while.end:
+; CHECK-NEXT:    [[S_ADDR_0_LCSSA:%.*]] = phi i32 [ [[S_ADDR_0]], [[WHILE_COND]] ]
+; CHECK-NEXT:    ret i32 [[S_ADDR_0_LCSSA]]
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %entry
+  %S.addr.0 = phi i32 [ %S, %entry ], [ %sub, %while.body ]
+  %cmp = icmp sgt i32 %S.addr.0, 31
+  br i1 %cmp, label %while.body, label %while.end
+
+while.body:                                       ; preds = %while.cond
+  %sub = add nsw i32 %S.addr.0, -32
+  tail call void @call()
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  %S.addr.0.lcssa = phi i32 [ %S.addr.0, %while.cond ]
+  ret i32 %S.addr.0.lcssa
+}
+
+define i32 @test_signed_do(i32 %S) {
+; CHECK-LABEL: @test_signed_do(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[DO_BODY:%.*]]
+; CHECK:       do.body:
+; CHECK-NEXT:    [[S_ADDR_0:%.*]] = phi i32 [ [[S:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[DO_BODY]] ]
+; CHECK-NEXT:    [[SUB]] = add nsw i32 [[S_ADDR_0]], -16
+; CHECK-NEXT:    tail call void @call()
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[SUB]], 15
+; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]]
+; CHECK:       do.end:
+; CHECK-NEXT:    [[SUB_LCSSA:%.*]] = phi i32 [ [[SUB]], [[DO_BODY]] ]
+; CHECK-NEXT:    ret i32 [[SUB_LCSSA]]
+;
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %entry
+  %S.addr.0 = phi i32 [ %S, %entry ], [ %sub, %do.body ]
+  %sub = add nsw i32 %S.addr.0, -16
+  tail call void @call()
+  %cmp = icmp sgt i32 %sub, 15
+  br i1 %cmp, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.body
+  %sub.lcssa = phi i32 [ %sub, %do.body ]
+  ret i32 %sub.lcssa
+}
+
+define i32 @test_unsigned_while(i32 %S) {
+; CHECK-LABEL: @test_unsigned_while(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[S_ADDR_0:%.*]] = phi i32 [ [[S:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[WHILE_BODY:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[S_ADDR_0]], 15
+; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_END:%.*]]
+; CHECK:       while.body:
+; CHECK-NEXT:    [[SUB]] = add i32 [[S_ADDR_0]], -16
+; CHECK-NEXT:    tail call void @call()
+; CHECK-NEXT:    br label [[WHILE_COND]]
+; CHECK:       while.end:
+; CHECK-NEXT:    [[S_ADDR_0_LCSSA:%.*]] = phi i32 [ [[S_ADDR_0]], [[WHILE_COND]] ]
+; CHECK-NEXT:    ret i32 [[S_ADDR_0_LCSSA]]
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %entry
+  %S.addr.0 = phi i32 [ %S, %entry ], [ %sub, %while.body ]
+  %cmp = icmp ugt i32 %S.addr.0, 15
+  br i1 %cmp, label %while.body, label %while.end
+
+while.body:                                       ; preds = %while.cond
+  %sub = add i32 %S.addr.0, -16
+  tail call void @call()
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  %S.addr.0.lcssa = phi i32 [ %S.addr.0, %while.cond ]
+  ret i32 %S.addr.0.lcssa
+}
+
+define i32 @test_unsigned_do(i32 %S) {
+; CHECK-LABEL: @test_unsigned_do(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[DO_BODY:%.*]]
+; CHECK:       do.body:
+; CHECK-NEXT:    [[S_ADDR_0:%.*]] = phi i32 [ [[S:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[DO_BODY]] ]
+; CHECK-NEXT:    [[SUB]] = add i32 [[S_ADDR_0]], -16
+; CHECK-NEXT:    tail call void @call()
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[SUB]], 15
+; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]]
+; CHECK:       do.end:
+; CHECK-NEXT:    [[SUB_LCSSA:%.*]] = phi i32 [ [[SUB]], [[DO_BODY]] ]
+; CHECK-NEXT:    ret i32 [[SUB_LCSSA]]
+;
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %entry
+  %S.addr.0 = phi i32 [ %S, %entry ], [ %sub, %do.body ]
+  %sub = add i32 %S.addr.0, -16
+  tail call void @call()
+  %cmp = icmp ugt i32 %sub, 15
+  br i1 %cmp, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.body
+  %sub.lcssa = phi i32 [ %sub, %do.body ]
+  ret i32 %sub.lcssa
+}
+
+
+declare void @call()

Added: llvm/trunk/test/Transforms/IndVarSimplify/replace-sdiv-by-udiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/replace-sdiv-by-udiv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/replace-sdiv-by-udiv.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/replace-sdiv-by-udiv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,130 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+define void @test0(i32* %a) {
+; CHECK-LABEL: @test0(
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %div = sdiv i32 %i.01, 2
+; CHECK-NOT: sdiv
+; CHECK:     udiv
+  %idxprom = sext i32 %div 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
+}
+
+define void @test1(i32* %a) {
+; CHECK-LABEL: @test1(
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %div = sdiv exact i32 %i.01, 2
+; CHECK-NOT: sdiv
+; CHECK:     udiv exact
+  %idxprom = sext i32 %div 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
+}
+
+define void @test2(i32* %a, i32 %d) {
+; CHECK-LABEL: @test2(
+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
+  %div = sdiv i32 %mul, %d
+; CHECK-NOT: udiv
+  %idxprom = sext i32 %div 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
+}
+
+define void @test3(i32* %a) {
+; CHECK-LABEL: @test3(
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %div = sdiv i32 2048, %i.01
+; CHECK:     udiv
+; CHECK-NOT: sdiv
+  %idxprom = sext i32 %div 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
+}
+
+define void @test4(i32* %a) {
+; CHECK-LABEL: @test4(
+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
+  %div = sdiv i32 %mul, 8
+; CHECK:     udiv
+; CHECK-NOT: sdiv
+  %idxprom = sext i32 %div 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
+}
+
+define void @test5(i32* %a) {
+; CHECK-LABEL: @test5(
+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
+  %div = sdiv i32 %mul, 6
+; CHECK:     udiv
+; CHECK-NOT: sdiv
+  %idxprom = sext i32 %div 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
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/replace-srem-by-urem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/replace-srem-by-urem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/replace-srem-by-urem.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/replace-srem-by-urem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,109 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+define void @test0(i32* %a) {
+; CHECK-LABEL: @test0(
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %rem = srem i32 %i.01, 2
+; CHECK-NOT: srem
+; CHECK:     urem
+  %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
+}
+
+define void @test2(i32* %a, i32 %d) {
+; CHECK-LABEL: @test2(
+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, %d
+; CHECK-NOT: urem
+  %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
+}
+
+define void @test3(i32* %a) {
+; CHECK-LABEL: @test3(
+entry:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.01 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %rem = srem i32 2048, %i.01
+; CHECK:     urem
+; CHECK-NOT: srem
+  %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
+}
+
+define void @test4(i32* %a) {
+; CHECK-LABEL: @test4(
+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, 7
+; CHECK:     urem
+; CHECK-NOT: srem
+  %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
+}
+
+define void @test5(i32* %a) {
+; CHECK-LABEL: @test5(
+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, 6
+; CHECK:     urem
+; CHECK-NOT: srem
+  %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
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; RUN: opt -indvars -instcombine -S < %s | FileCheck %s
+
+;; Test that loop's exit value is rewritten to its initial
+;; value from loop preheader
+define i32 @test1(i32* %var) {
+; CHECK-LABEL: @test1
+entry:
+ %cond = icmp eq i32* %var, null 
+ br label %header
+
+header:
+ %phi_indvar = phi i32 [0, %entry], [%indvar, %loop]
+ br i1 %cond, label %loop, label %exit
+
+loop:
+ %indvar = add i32 %phi_indvar, 1
+ br label %header
+
+exit:
+; CHECK: ret i32 0
+ ret i32 %phi_indvar
+}
+
+;; Test that we can not rewrite loop exit value if it's not
+;; a phi node (%indvar is an add instruction in this test).
+define i32 @test2(i32* %var) {
+; CHECK-LABEL: @test2
+entry:
+ %cond = icmp eq i32* %var, null 
+ br label %header
+
+header:
+ %phi_indvar = phi i32 [0, %entry], [%indvar, %header]
+ %indvar = add i32 %phi_indvar, 1
+ br i1 %cond, label %header, label %exit
+
+exit:
+; CHECK: ret i32 %indvar
+ ret i32 %indvar
+}
+
+;; Test that we can not rewrite loop exit value if the condition
+;; is not in loop header.
+define i32 @test3(i32* %var) {
+; CHECK-LABEL: @test3
+entry:
+ %cond1 = icmp eq i32* %var, null 
+ br label %header
+
+header:
+ %phi_indvar = phi i32 [0, %entry], [%indvar, %header], [%indvar, %body]
+ %indvar = add i32 %phi_indvar, 1
+ %cond2 = icmp eq i32 %indvar, 10
+ br i1 %cond2, label %header, label %body
+ 
+body:
+ br i1 %cond1, label %header, label %exit
+
+exit:
+; CHECK: ret i32 %phi_indvar
+ ret i32 %phi_indvar
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/scev-phi-debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/scev-phi-debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/scev-phi-debug-info.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/scev-phi-debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt %s -indvars -S -o - | FileCheck %s
+source_filename = "/Data/llvm/test/Transforms/IndVarSimplify/scev-phi-debug-info.ll"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.status = type { i32, i8* }
+
+ at status = internal unnamed_addr global [32 x %struct.status] zeroinitializer, align 16, !dbg !0
+
+define void @f0() local_unnamed_addr !dbg !20 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 0, metadata !23, metadata !DIExpression()), !dbg !24
+  br label %for.cond, !dbg !24
+
+for.cond:                                         ; preds = %for.body, %entry
+  ; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
+  ; CHECK: call void @llvm.dbg.value(metadata i64 %indvars.iv, metadata !23, metadata !DIExpression()), !dbg !24
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  tail call void @llvm.dbg.value(metadata i32 %i.0, metadata !23, metadata !DIExpression()), !dbg !24
+  %cmp = icmp slt i32 %i.0, 32, !dbg !24
+  br i1 %cmp, label %for.body, label %for.end, !dbg !24
+
+for.body:                                         ; preds = %for.cond
+  %idxprom = sext i32 %i.0 to i64, !dbg !24
+  %value = getelementptr inbounds [32 x %struct.status], [32 x %struct.status]* @status, i64 0, i64 %idxprom, i32 0, !dbg !24
+  store i32 42, i32* %value, align 16, !dbg !24
+  tail call void @use(i32 %i.0), !dbg !24
+  %inc = add nsw i32 %i.0, 1, !dbg !24
+  tail call void @llvm.dbg.value(metadata i32 %inc, metadata !23, metadata !DIExpression()), !dbg !24
+  br label %for.cond, !dbg !24
+
+for.end:                                          ; preds = %for.cond
+  ret void, !dbg !24
+}
+
+declare void @use(i32)
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!16, !17, !18}
+!llvm.ident = !{!19}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "status", scope: !2, file: !3, line: 5, type: !6, isLocal: true, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 6.0.0 (trunk 316001) (llvm/trunk 316171)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "x.c", directory: "/home/davide/work/llvm/build-release/bin")
+!4 = !{}
+!5 = !{!0}
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 4096, elements: !14)
+!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "status", file: !3, line: 2, size: 128, elements: !8)
+!8 = !{!9, !11}
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: !7, file: !3, line: 3, baseType: !10, size: 32)
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "p", scope: !7, file: !3, line: 4, baseType: !12, size: 64, offset: 64)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
+!13 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+!14 = !{!15}
+!15 = !DISubrange(count: 32)
+!16 = !{i32 2, !"Dwarf Version", i32 4}
+!17 = !{i32 2, !"Debug Info Version", i32 3}
+!18 = !{i32 1, !"wchar_size", i32 4}
+!19 = !{!"clang version 6.0.0 (trunk 316001) (llvm/trunk 316171)"}
+!20 = distinct !DISubprogram(name: "f0", scope: !3, file: !3, line: 6, type: !21, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true, unit: !2, retainedNodes: !22)
+!21 = !DISubroutineType(types: !4)
+!22 = !{!23}
+!23 = !DILocalVariable(name: "i", scope: !20, file: !3, line: 8, type: !10)
+!24 = !DILocation(line: 9, scope: !20)

Added: llvm/trunk/test/Transforms/IndVarSimplify/scevexpander-phi-base-case.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/scevexpander-phi-base-case.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/scevexpander-phi-base-case.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/scevexpander-phi-base-case.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+define i32 @fn() {
+entry:
+  ret i32 10
+}
+
+define i32 @test_nested2(i32 %tnr) {
+; CHECK-LABEL: test_nested2
+; CHECK-NOT: %indvars.iv
+; CHECK: %i.0
+
+; indvars should not replace the i.0 variable with a new one; SCEVExpander
+; should determine that the old one is good to reuse.
+
+entry:
+  %res = alloca i32, align 4
+  store volatile i32 0, i32* %res, align 4
+  %call = call i32 @fn()
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc6, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc7, %for.inc6 ]
+  %cmp = icmp slt i32 %i.0, %call
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  br label %for.end8
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc5, %for.inc ]
+  %cmp2 = icmp slt i32 %j.0, %i.0
+  br i1 %cmp2, label %for.body4, label %for.cond.cleanup3
+
+for.cond.cleanup3:                                ; preds = %for.cond1
+  br label %for.end
+
+for.body4:                                        ; preds = %for.cond1
+  %0 = load volatile i32, i32* %res, align 4
+  %inc = add nsw i32 %0, 1
+  store volatile i32 %inc, i32* %res, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body4
+  %inc5 = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond.cleanup3
+  br label %for.inc6
+
+for.inc6:                                         ; preds = %for.end
+  %inc7 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end8:                                         ; preds = %for.cond.cleanup
+  %1 = load volatile i32, i32* %res, align 4
+  %cmp9 = icmp eq i32 %1, 45
+  %conv = zext i1 %cmp9 to i32
+  ret i32 %conv
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/sharpen-range.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,114 @@
+;; RUN: opt -S < %s -indvars | FileCheck %s
+; RUN: opt -lcssa -loop-simplify -S < %s | opt -S -passes='require<targetir>,require<scalar-evolution>,require<domtree>,loop(indvars)'
+
+;; Check if llvm can narrow !range metadata based on loop entry
+;; predicates.
+
+declare void @abort()
+
+define i1 @bounded_below_slt(i32* nocapture readonly %buffer) {
+; CHECK-LABEL: bounded_below_slt
+entry:
+  %length = load i32, i32* %buffer, !range !0
+  %entry.pred = icmp eq i32 %length, 0
+  br i1 %entry.pred, label %abort, label %loop.preheader
+
+loop.preheader:
+  br label %loop
+
+loop:
+; CHECK: loop
+  %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ]
+  %oob.pred = icmp slt i32 %idx, %length
+  br i1 %oob.pred, label %loop.next, label %oob
+; CHECK: br i1 true, label %loop.next, label %oob
+
+loop.next:
+; CHECK: loop.next
+  %idx.inc = add i32 %idx, 1
+  %exit.pred = icmp slt i32 %idx.inc, %length
+  br i1 %exit.pred, label %loop, label %abort.loopexit
+
+abort.loopexit:
+  br label %abort
+
+abort:
+  ret i1 false
+
+oob:
+  tail call void @abort()
+  ret i1 false
+}
+
+define i1 @bounded_below_sle(i32* nocapture readonly %buffer) {
+; CHECK-LABEL: bounded_below_sle
+entry:
+  %length = load i32, i32* %buffer, !range !0
+  %entry.pred = icmp eq i32 %length, 0
+  br i1 %entry.pred, label %abort, label %loop.preheader
+
+loop.preheader:
+  br label %loop
+
+loop:
+; CHECK: loop
+  %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ]
+  %oob.pred = icmp sle i32 %idx, %length
+  br i1 %oob.pred, label %loop.next, label %oob
+; CHECK: br i1 true, label %loop.next, label %oob
+
+loop.next:
+; CHECK: loop.next
+  %idx.inc = add i32 %idx, 1
+  %exit.pred = icmp sle i32 %idx.inc, %length
+  br i1 %exit.pred, label %loop, label %abort.loopexit
+
+abort.loopexit:
+  br label %abort
+
+abort:
+  ret i1 false
+
+oob:
+  tail call void @abort()
+  ret i1 false
+}
+
+;; Assert that we're not making an incorrect transform.
+
+declare i32 @check(i8*)
+
+define void @NoChange() {
+; CHECK-LABEL: NoChange
+entry:
+  br label %loop.begin
+
+loop.begin:
+; CHECK: loop.begin:
+  %i.01 = phi i64 [ 2, %entry ], [ %add, %loop.end ]
+  %cmp = icmp ugt i64 %i.01, 1
+; CHECK: %cmp = icmp ugt i64 %i.01, 1
+  br i1 %cmp, label %loop, label %loop.end
+
+loop:
+; CHECK: loop
+  %.sum = add i64 %i.01, -2
+  %v = getelementptr inbounds i8, i8* null, i64 %.sum
+  %r = tail call i32 @check(i8* %v)
+  %c = icmp eq i32 %r, 0
+  br i1 %c, label %loop.end, label %abort.now
+
+abort.now:
+  tail call void @abort()
+  unreachable
+
+loop.end:
+  %add = add i64 %i.01, -1
+  %eq = icmp eq i64 %add, 0
+  br i1 %eq, label %exit, label %loop.begin
+
+exit:
+  ret void
+}
+
+!0 = !{i32 0, i32 100}

Added: llvm/trunk/test/Transforms/IndVarSimplify/shrunk-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/shrunk-constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/shrunk-constant.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/shrunk-constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -scalar-evolution -analyze | FileCheck %s
+
+; CHECK: -->  (1 + (zext i4 {-8,+,-8}<%loop> to i32))<nuw><nsw>
+
+define fastcc void @foo() nounwind {
+entry:
+	br label %loop
+
+loop:
+	%i = phi i32 [ 0, %entry ], [ %t2, %loop ]
+	%t0 = add i32 %i, 9
+	%t1 = and i32 %t0, 9
+        store i32 %t1, i32* null
+	%t2 = add i32 %i, 8
+	br label %loop
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/signed-trip-count.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/signed-trip-count.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/signed-trip-count.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/signed-trip-count.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+define void @foo(i64* nocapture %x, i32 %n) nounwind {
+; CHECK-LABEL: @foo(
+; CHECK-NOT: sext
+; CHECK: phi
+; CHECK-NOT: phi
+entry:
+	%tmp102 = icmp sgt i32 %n, 0		; <i1> [#uses=1]
+	br i1 %tmp102, label %bb.nph, label %return
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb7, %bb.nph
+	%i.01 = phi i32 [ %tmp6, %bb7 ], [ 0, %bb.nph ]		; <i32> [#uses=3]
+	%tmp1 = sext i32 %i.01 to i64		; <i64> [#uses=1]
+	%tmp4 = getelementptr i64, i64* %x, i32 %i.01		; <i64*> [#uses=1]
+	store i64 %tmp1, i64* %tmp4, align 8
+	%tmp6 = add i32 %i.01, 1		; <i32> [#uses=2]
+	br label %bb7
+
+bb7:		; preds = %bb
+	%tmp10 = icmp slt i32 %tmp6, %n		; <i1> [#uses=1]
+	br i1 %tmp10, label %bb, label %bb7.return_crit_edge
+
+bb7.return_crit_edge:		; preds = %bb7
+	br label %return
+
+return:		; preds = %bb7.return_crit_edge, %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/single-element-range.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/single-element-range.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/single-element-range.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/single-element-range.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -indvars
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64"
+target triple = "armv6-apple-darwin10"
+
+define void @sqlite3_free_table(i8** %azResult) nounwind {
+entry:
+	br i1 undef, label %return, label %bb
+
+bb:		; preds = %entry
+	%0 = load i8*, i8** undef, align 4		; <i8*> [#uses=2]
+	%1 = ptrtoint i8* %0 to i32		; <i32> [#uses=1]
+	%2 = icmp sgt i8* %0, inttoptr (i32 1 to i8*)		; <i1> [#uses=1]
+	br i1 %2, label %bb1, label %bb5
+
+bb1:		; preds = %bb1, %bb
+	%i.01 = phi i32 [ %3, %bb1 ], [ 1, %bb ]		; <i32> [#uses=1]
+	%3 = add i32 %i.01, 1		; <i32> [#uses=2]
+	%4 = icmp slt i32 %3, %1		; <i1> [#uses=1]
+	br i1 %4, label %bb1, label %bb5
+
+bb5:		; preds = %bb1, %bb
+	ret void
+
+return:		; preds = %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/sink-alloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/sink-alloca.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/sink-alloca.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/sink-alloca.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt < %s -indvars -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-darwin10.0"
+
+; PR4775
+; Indvars shouldn't sink the alloca out of the entry block, even though
+; it's not used until after the loop.
+define i32 @main() nounwind {
+; CHECK: entry:
+; CHECK-NEXT: %result.i = alloca i32, align 4
+entry:
+  %result.i = alloca i32, align 4                 ; <i32*> [#uses=2]
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond, %entry
+  %call = call i32 @bar() nounwind                ; <i32> [#uses=1]
+  %tobool = icmp eq i32 %call, 0                  ; <i1> [#uses=1]
+  br i1 %tobool, label %while.end, label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  store volatile i32 0, i32* %result.i
+  %tmp.i = load volatile i32, i32* %result.i           ; <i32> [#uses=0]
+  ret i32 0
+}
+declare i32 @bar()
+
+; <rdar://problem/10352360>
+; Indvars shouldn't sink the first alloca between the stacksave and stackrestore
+; intrinsics.
+declare i8* @a(...)
+declare i8* @llvm.stacksave() nounwind
+declare void @llvm.stackrestore(i8*) nounwind
+define void @h(i64 %n) nounwind uwtable ssp {
+; CHECK: entry:
+; CHECK-NEXT: %vla = alloca i8*
+; CHECK-NEXT: %savedstack = call i8* @llvm.stacksave()
+entry:
+  %vla = alloca i8*, i64 %n, align 16
+  %savedstack = call i8* @llvm.stacksave() nounwind
+  %vla.i = alloca i8*, i64 %n, align 16
+  br label %for.body.i
+
+for.body.i:
+  %indvars.iv37.i = phi i64 [ %indvars.iv.next38.i, %for.body.i ], [ 0, %entry ]
+  %call.i = call i8* (...) @a() nounwind
+  %arrayidx.i = getelementptr inbounds i8*, i8** %vla.i, i64 %indvars.iv37.i
+  store i8* %call.i, i8** %arrayidx.i, align 8
+  %indvars.iv.next38.i = add i64 %indvars.iv37.i, 1
+  %exitcond5 = icmp eq i64 %indvars.iv.next38.i, %n
+  br i1 %exitcond5, label %g.exit, label %for.body.i
+
+g.exit:
+  call void @llvm.stackrestore(i8* %savedstack) nounwind
+  %call1 = call i8* (...) @a(i8** %vla) nounwind
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/sink-from-preheader.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/sink-from-preheader.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/sink-from-preheader.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/sink-from-preheader.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -indvars -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-darwin10.0"
+
+; We make sinking here, Changed flag should be set properly.
+define i32 @test(i32 %a, i32 %b, i32 %N) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    ret i32 [[ADD]]
+;
+entry:
+  %add = add i32 %a, %b
+  br label %loop
+
+loop:
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+  %iv.next = add i32 %iv, 1
+  %cmp = icmp slt i32 %iv.next, %N
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret i32 %add
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/sink-trapping.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/sink-trapping.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/sink-trapping.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/sink-trapping.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+declare i1 @b()
+
+define i32 @a(i32 %x) nounwind {
+for.body.preheader:
+    %y = sdiv i32 10, %x
+	br label %for.body
+
+for.body:
+    %cmp = call i1 @b()
+	br i1 %cmp, label %for.body, label %for.end.loopexit
+
+for.end.loopexit:
+	ret i32 %y
+}
+; CHECK: for.end.loopexit:
+; CHECK: sdiv
+; CHECK: ret

Added: llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,192 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+define i32 @test.signed.add.0(i32* %array, i32 %length, i32 %init) {
+; CHECK-LABEL: @test.signed.add.0
+ entry:
+  %upper = icmp slt i32 %init, %length
+  br i1 %upper, label %loop, label %exit
+
+ loop:
+; CHECK-LABEL: loop
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]
+  %civ.inc = add i32 %civ, 1
+; CHECK: %civ.inc = add nsw i32 %civ, 1
+  %cmp = icmp slt i32 %civ.inc, %length
+  br i1 %cmp, label %latch, label %break
+
+ latch:
+  store i32 0, i32* %array
+  %check = icmp slt i32 %civ.inc, %length
+  br i1 %check, label %loop, label %break
+
+ break:
+  ret i32 %civ.inc
+
+ exit:
+  ret i32 42
+}
+
+define i32 @test.signed.add.1(i32* %array, i32 %length, i32 %init) {
+; CHECK-LABEL: @test.signed.add.1
+ entry:
+  %upper = icmp sle i32 %init, %length
+  br i1 %upper, label %loop, label %exit
+
+ loop:
+; CHECK-LABEL: loop
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]
+  %civ.inc = add i32 %civ, 1
+; CHECK: %civ.inc = add i32 %civ, 1
+  %cmp = icmp slt i32 %civ.inc, %length
+  br i1 %cmp, label %latch, label %break
+
+ latch:
+  store i32 0, i32* %array
+  %check = icmp slt i32 %civ.inc, %length
+  br i1 %check, label %loop, label %break
+
+ break:
+  ret i32 %civ.inc
+
+ exit:
+  ret i32 42
+}
+
+define i32 @test.unsigned.add.0(i32* %array, i32 %length, i32 %init) {
+; CHECK-LABEL: @test.unsigned.add.0
+ entry:
+  %upper = icmp ult i32 %init, %length
+  br i1 %upper, label %loop, label %exit
+
+ loop:
+; CHECK-LABEL: loop
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]
+  %civ.inc = add i32 %civ, 1
+; CHECK: %civ.inc = add nuw i32 %civ, 1
+  %cmp = icmp slt i32 %civ.inc, %length
+  br i1 %cmp, label %latch, label %break
+
+ latch:
+  store i32 0, i32* %array
+  %check = icmp ult i32 %civ.inc, %length
+  br i1 %check, label %loop, label %break
+
+ break:
+  ret i32 %civ.inc
+
+ exit:
+  ret i32 42
+}
+
+define i32 @test.unsigned.add.1(i32* %array, i32 %length, i32 %init) {
+; CHECK-LABEL: @test.unsigned.add.1
+ entry:
+  %upper = icmp ule i32 %init, %length
+  br i1 %upper, label %loop, label %exit
+
+ loop:
+; CHECK-LABEL: loop
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]
+  %civ.inc = add i32 %civ, 1
+; CHECK: %civ.inc = add i32 %civ, 1
+  %cmp = icmp slt i32 %civ.inc, %length
+  br i1 %cmp, label %latch, label %break
+
+ latch:
+  store i32 0, i32* %array
+  %check = icmp ult i32 %civ.inc, %length
+  br i1 %check, label %loop, label %break
+
+ break:
+  ret i32 %civ.inc
+
+ exit:
+  ret i32 42
+}
+
+define hidden void @test.shl.exact.equal() {
+; CHECK-LABEL: @test.shl.exact.equal
+entry:
+  br label %for.body
+
+for.body:
+; CHECK-LABEL: for.body
+  %k.021 = phi i32 [ 1, %entry ], [ %inc, %for.body ]
+  %shl = shl i32 1, %k.021
+  %shr1 = ashr i32 %shl, 1
+; CHECK: %shr1 = ashr exact i32 %shl, 1
+  %shr2 = lshr i32 %shl, 1
+; CHECK: %shr2 = lshr exact i32 %shl, 1
+  %inc = add nuw nsw i32 %k.021, 1
+  %exitcond = icmp eq i32 %inc, 9
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+define hidden void @test.shl.exact.greater() {
+; CHECK-LABEL: @test.shl.exact.greater
+entry:
+  br label %for.body
+
+for.body:
+; CHECK-LABEL: for.body
+  %k.021 = phi i32 [ 3, %entry ], [ %inc, %for.body ]
+  %shl = shl i32 1, %k.021
+  %shr1 = ashr i32 %shl, 2
+; CHECK: %shr1 = ashr exact i32 %shl, 2
+  %shr2 = lshr i32 %shl, 2
+; CHECK: %shr2 = lshr exact i32 %shl, 2
+  %inc = add nuw nsw i32 %k.021, 1
+  %exitcond = icmp eq i32 %inc, 9
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+define hidden void @test.shl.exact.unbound(i32 %arg) {
+; CHECK-LABEL: @test.shl.exact.unbound
+entry:
+  br label %for.body
+
+for.body:
+; CHECK-LABEL: for.body
+  %k.021 = phi i32 [ 2, %entry ], [ %inc, %for.body ]
+  %shl = shl i32 1, %k.021
+  %shr1 = ashr i32 %shl, 2
+; CHECK: %shr1 = ashr exact i32 %shl, 2
+  %shr2 = lshr i32 %shl, 2
+; CHECK: %shr2 = lshr exact i32 %shl, 2
+  %inc = add nuw nsw i32 %k.021, 1
+  %exitcond = icmp eq i32 %inc, %arg
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+define hidden void @test.shl.nonexact() {
+; CHECK-LABEL: @test.shl.nonexact
+entry:
+  br label %for.body
+
+for.body:
+; CHECK-LABEL: for.body
+  %k.021 = phi i32 [ 2, %entry ], [ %inc, %for.body ]
+  %shl = shl i32 1, %k.021
+  %shr1 = ashr i32 %shl, 3
+; CHECK: %shr1 = ashr i32 %shl, 3
+  %shr2 = lshr i32 %shl, 3
+; CHECK: %shr2 = lshr i32 %shl, 3
+  %inc = add nuw nsw i32 %k.021, 1
+  %exitcond = icmp eq i32 %inc, 9
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:
+  ret void
+}
+
+!0 = !{i32 0, i32 2}
+!1 = !{i32 0, i32 42}

Added: llvm/trunk/test/Transforms/IndVarSimplify/tripcount_compute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/tripcount_compute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/tripcount_compute.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/tripcount_compute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,193 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+; These tests ensure that we can compute the trip count of various forms of
+; loops.  If the trip count of the loop is computable, then we will know what
+; the exit value of the loop will be for some value, allowing us to substitute
+; it directly into users outside of the loop, making the loop dead.
+
+; CHECK-LABEL: @linear_setne(
+; CHECK: ret i32 100
+
+define i32 @linear_setne() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 0, %entry ], [ %i.next, %loop ]		; <i32> [#uses=3]
+	%i.next = add i32 %i, 1		; <i32> [#uses=1]
+	%c = icmp ne i32 %i, 100		; <i1> [#uses=1]
+	br i1 %c, label %loop, label %loopexit
+
+loopexit:		; preds = %loop
+	ret i32 %i
+}
+
+; CHECK-LABEL: @linear_setne_2(
+; CHECK: ret i32 100
+
+define i32 @linear_setne_2() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 0, %entry ], [ %i.next, %loop ]		; <i32> [#uses=3]
+	%i.next = add i32 %i, 2		; <i32> [#uses=1]
+	%c = icmp ne i32 %i, 100		; <i1> [#uses=1]
+	br i1 %c, label %loop, label %loopexit
+
+loopexit:		; preds = %loop
+	ret i32 %i
+}
+
+; CHECK-LABEL: @linear_setne_overflow(
+; CHECK: ret i32 0
+
+define i32 @linear_setne_overflow() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 1024, %entry ], [ %i.next, %loop ]		; <i32> [#uses=3]
+	%i.next = add i32 %i, 1024		; <i32> [#uses=1]
+	%c = icmp ne i32 %i, 0		; <i1> [#uses=1]
+	br i1 %c, label %loop, label %loopexit
+
+loopexit:		; preds = %loop
+	ret i32 %i
+}
+
+; CHECK-LABEL: @linear_setlt(
+; CHECK: ret i32 100
+
+define i32 @linear_setlt() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 0, %entry ], [ %i.next, %loop ]		; <i32> [#uses=3]
+	%i.next = add i32 %i, 1		; <i32> [#uses=1]
+	%c = icmp slt i32 %i, 100		; <i1> [#uses=1]
+	br i1 %c, label %loop, label %loopexit
+
+loopexit:		; preds = %loop
+	ret i32 %i
+}
+
+; CHECK-LABEL: @quadratic_setlt(
+; CHECK: ret i32 34
+
+define i32 @quadratic_setlt() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 7, %entry ], [ %i.next, %loop ]		; <i32> [#uses=4]
+	%i.next = add i32 %i, 3		; <i32> [#uses=1]
+	%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
+}
+
+; CHECK-LABEL: @chained(
+; CHECK: ret i32 200
+
+define i32 @chained() {
+entry:
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi i32 [ 0, %entry ], [ %i.next, %loop ]		; <i32> [#uses=3]
+	%i.next = add i32 %i, 1		; <i32> [#uses=1]
+	%c = icmp ne i32 %i, 100		; <i1> [#uses=1]
+	br i1 %c, label %loop, label %loopexit
+
+loopexit:		; preds = %loop
+	br label %loop2
+
+loop2:		; preds = %loop2, %loopexit
+	%j = phi i32 [ %i, %loopexit ], [ %j.next, %loop2 ]		; <i32> [#uses=3]
+	%j.next = add i32 %j, 1		; <i32> [#uses=1]
+	%c2 = icmp ne i32 %j, 200		; <i1> [#uses=1]
+	br i1 %c2, label %loop2, label %loopexit2
+
+loopexit2:		; preds = %loop2
+	ret i32 %j
+}
+
+; CHECK-LABEL: @chained4(
+; CHECK: ret i32 400
+
+define i32 @chained4() {
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]  ; <i32> [#uses=3]
+  %i.next = add i32 %i, 1                         ; <i32> [#uses=1]
+  %c = icmp ne i32 %i.next, 100                   ; <i1> [#uses=1]
+  br i1 %c, label %loop, label %loopexit
+
+loopexit:                                         ; preds = %loop
+  br label %loop2
+
+loop2:                                            ; preds = %loop2, %loopexit
+  %j = phi i32 [ %i.next, %loopexit ], [ %j.next, %loop2 ] ; <i32> [#uses=3]
+  %j.next = add i32 %j, 1                         ; <i32> [#uses=1]
+  %c2 = icmp ne i32 %j.next, 200                  ; <i1> [#uses=1]
+  br i1 %c2, label %loop2, label %loopexit2
+
+loopexit2:                                        ; preds = %loop
+  br label %loop8
+
+loop8:                                            ; preds = %loop2, %loopexit
+  %k = phi i32 [ %j.next, %loopexit2 ], [ %k.next, %loop8 ] ; <i32> [#uses=3]
+  %k.next = add i32 %k, 1                         ; <i32> [#uses=1]
+  %c8 = icmp ne i32 %k.next, 300                  ; <i1> [#uses=1]
+  br i1 %c8, label %loop8, label %loopexit8
+
+loopexit8:                                        ; preds = %loop2
+  br label %loop9
+
+loop9:                                            ; preds = %loop2, %loopexit
+  %l = phi i32 [ %k.next, %loopexit8 ], [ %l.next, %loop9 ] ; <i32> [#uses=3]
+  %l.next = add i32 %l, 1                         ; <i32> [#uses=1]
+  %c9 = icmp ne i32 %l.next, 400                  ; <i1> [#uses=1]
+  br i1 %c9, label %loop9, label %loopexit9
+
+loopexit9:                                        ; preds = %loop2
+  ret i32 %l.next
+}
+
+; PR18449. Check that the early exit is reduced to never taken.
+;
+; CHECK-LABEL: @twoexit
+; CHECK-LABEL: loop:
+; CHECK: phi
+; CHECK: br i1 false
+; CHECK: br
+; CHECK: ret
+define void @twoexit() {
+"function top level":
+  br label %loop
+
+loop:                                             ; preds = %body, %"function top level"
+  %0 = phi i64 [ 0, %"function top level" ], [ %2, %body ]
+  %1 = icmp ugt i64 %0, 2
+  br i1 %1, label %fail, label %body
+
+fail:                                             ; preds = %loop
+  tail call void @bounds_fail()
+  unreachable
+
+body:                                             ; preds = %loop
+  %2 = add i64 %0, 1
+  %3 = icmp slt i64 %2, 3
+  br i1 %3, label %loop, label %out
+
+out:                                              ; preds = %body
+  ret void
+}
+declare void @bounds_fail()

Added: llvm/trunk/test/Transforms/IndVarSimplify/tripcount_infinite.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/tripcount_infinite.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/tripcount_infinite.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/tripcount_infinite.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; These tests have an infinite trip count.  We obviously shouldn't remove the 
+; loops!  :)
+;
+; RUN: opt < %s -indvars -adce -simplifycfg -S | FileCheck %s
+
+;; test for (i = 1; i != 100; i += 2)
+define i32 @infinite_linear() {
+; CHECK-LABEL: @infinite_linear(
+entry:
+        br label %loop
+
+loop:           ; preds = %loop, %entry
+; CHECK-LABEL: loop:
+        %i = phi i32 [ 1, %entry ], [ %i.next, %loop ]          ; <i32> [#uses=3]
+        %i.next = add i32 %i, 2         ; <i32> [#uses=1]
+        %c = icmp ne i32 %i, 100                ; <i1> [#uses=1]
+; CHECK: icmp
+; CHECK: br
+        br i1 %c, label %loop, label %loopexit
+
+loopexit:               ; preds = %loop
+; CHECK-LABEL: loopexit:
+        ret i32 %i
+}
+
+;; test for (i = 1; i*i != 63; ++i)
+define i32 @infinite_quadratic() {
+; CHECK-LABEL: @infinite_quadratic(
+entry:
+        br label %loop
+
+loop:           ; preds = %loop, %entry
+; CHECK-LABEL: loop:
+        %i = phi i32 [ 1, %entry ], [ %i.next, %loop ]          ; <i32> [#uses=4]
+        %isquare = mul i32 %i, %i               ; <i32> [#uses=1]
+        %i.next = add i32 %i, 1         ; <i32> [#uses=1]
+        %c = icmp ne i32 %isquare, 63           ; <i1> [#uses=1]
+; CHECK: icmp
+; CHECK: br
+        br i1 %c, label %loop, label %loopexit
+
+loopexit:               ; preds = %loop
+; CHECK-LABEL: loopexit:
+        ret i32 %i
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+ at b = common global i32 0, align 4
+
+define i32 @foo(i32 %x, i1 %y) {
+bb0:
+  br label %bb1
+
+bb1:
+  br i1 %y, label %bb14, label %bb8
+
+bb8:
+  %i = phi i64 [ %i.next, %bb8 ], [ 0, %bb1 ]
+  %i.next = add i64 %i, 1
+  %div = udiv i32 1, %x
+  %c = icmp eq i64 %i.next, 6
+  br i1 %c, label %bb11, label %bb8
+
+bb11:
+  br i1 %y, label %bb1, label %bb13
+
+bb13:
+  store i32 %div, i32* @b, align 4
+  br label %bb14
+
+bb14:
+  ret i32 0
+}
+
+; CHECK-LABEL: @foo(
+; CHECK: bb8:
+; CHECK: udiv

Added: llvm/trunk/test/Transforms/IndVarSimplify/udiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/udiv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/udiv.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/udiv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,162 @@
+; 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 main.flags = internal global [8193 x i8] zeroinitializer, align 1 ; <[8193 x i8]*> [#uses=5]
+ at .str = private constant [11 x i8] c"Count: %d\0A\00" ; <[11 x i8]*> [#uses=1]
+
+; Indvars shouldn't emit a udiv here, because there's no udiv in the
+; original code. This comes from SingleSource/Benchmarks/Shootout/sieve.c.
+
+; CHECK-LABEL: @main(
+; CHECK-NOT: div
+
+define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
+entry:
+  %cmp = icmp eq i32 %argc, 2                     ; <i1> [#uses=1]
+  br i1 %cmp, label %cond.true, label %while.cond.preheader
+
+cond.true:                                        ; preds = %entry
+  %arrayidx = getelementptr inbounds i8*, i8** %argv, i64 1 ; <i8**> [#uses=1]
+  %tmp2 = load i8*, i8** %arrayidx                     ; <i8*> [#uses=1]
+  %call = tail call i32 @atoi(i8* %tmp2) nounwind readonly ; <i32> [#uses=1]
+  br label %while.cond.preheader
+
+while.cond.preheader:                             ; preds = %entry, %cond.true
+  %NUM.0.ph = phi i32 [ %call, %cond.true ], [ 170000, %entry ] ; <i32> [#uses=2]
+  %tobool18 = icmp eq i32 %NUM.0.ph, 0            ; <i1> [#uses=1]
+  br i1 %tobool18, label %while.end, label %bb.nph30
+
+while.cond.loopexit:                              ; preds = %for.cond12.while.cond.loopexit_crit_edge, %for.cond12.loopexit
+  %count.2.lcssa = phi i32 [ %count.1.lcssa, %for.cond12.while.cond.loopexit_crit_edge ], [ 0, %for.cond12.loopexit ] ; <i32> [#uses=1]
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond.loopexit
+  %tobool = icmp eq i32 %dec19, 0                 ; <i1> [#uses=1]
+  br i1 %tobool, label %while.cond.while.end_crit_edge, label %for.cond.preheader
+
+while.cond.while.end_crit_edge:                   ; preds = %while.cond
+  %count.2.lcssa.lcssa = phi i32 [ %count.2.lcssa, %while.cond ] ; <i32> [#uses=1]
+  br label %while.end
+
+bb.nph30:                                         ; preds = %while.cond.preheader
+  br label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %bb.nph30, %while.cond
+  %dec19.in = phi i32 [ %NUM.0.ph, %bb.nph30 ], [ %dec19, %while.cond ] ; <i32> [#uses=1]
+  %dec19 = add i32 %dec19.in, -1                  ; <i32> [#uses=2]
+  br i1 true, label %bb.nph, label %for.cond12.loopexit
+
+for.cond:                                         ; preds = %for.body
+  %cmp8 = icmp slt i64 %inc, 8193                 ; <i1> [#uses=1]
+  br i1 %cmp8, label %for.body, label %for.cond.for.cond12.loopexit_crit_edge
+
+for.cond.for.cond12.loopexit_crit_edge:           ; preds = %for.cond
+  br label %for.cond12.loopexit
+
+bb.nph:                                           ; preds = %for.cond.preheader
+  br label %for.body
+
+for.body:                                         ; preds = %bb.nph, %for.cond
+  %i.02 = phi i64 [ 2, %bb.nph ], [ %inc, %for.cond ] ; <i64> [#uses=2]
+  %arrayidx10 = getelementptr inbounds [8193 x i8], [8193 x i8]* @main.flags, i64 0, i64 %i.02 ; <i8*> [#uses=1]
+  store i8 1, i8* %arrayidx10
+  %inc = add nsw i64 %i.02, 1                     ; <i64> [#uses=2]
+  br label %for.cond
+
+for.cond12.loopexit:                              ; preds = %for.cond.for.cond12.loopexit_crit_edge, %for.cond.preheader
+  br i1 true, label %bb.nph16, label %while.cond.loopexit
+
+for.cond12:                                       ; preds = %for.inc35
+  %cmp14 = icmp slt i64 %inc37, 8193              ; <i1> [#uses=1]
+  br i1 %cmp14, label %for.body15, label %for.cond12.while.cond.loopexit_crit_edge
+
+for.cond12.while.cond.loopexit_crit_edge:         ; preds = %for.cond12
+  %count.1.lcssa = phi i32 [ %count.1, %for.cond12 ] ; <i32> [#uses=1]
+  br label %while.cond.loopexit
+
+bb.nph16:                                         ; preds = %for.cond12.loopexit
+  br label %for.body15
+
+for.body15:                                       ; preds = %bb.nph16, %for.cond12
+  %count.212 = phi i32 [ 0, %bb.nph16 ], [ %count.1, %for.cond12 ] ; <i32> [#uses=2]
+  %i.17 = phi i64 [ 2, %bb.nph16 ], [ %inc37, %for.cond12 ] ; <i64> [#uses=4]
+  %arrayidx17 = getelementptr inbounds [8193 x i8], [8193 x i8]* @main.flags, i64 0, i64 %i.17 ; <i8*> [#uses=1]
+  %tmp18 = load i8, i8* %arrayidx17                   ; <i8> [#uses=1]
+  %tobool19 = icmp eq i8 %tmp18, 0                ; <i1> [#uses=1]
+  br i1 %tobool19, label %for.inc35, label %if.then
+
+if.then:                                          ; preds = %for.body15
+  %add = shl i64 %i.17, 1                         ; <i64> [#uses=2]
+  %cmp243 = icmp slt i64 %add, 8193               ; <i1> [#uses=1]
+  br i1 %cmp243, label %bb.nph5, label %for.end32
+
+for.cond22:                                       ; preds = %for.body25
+  %cmp24 = icmp slt i64 %add31, 8193              ; <i1> [#uses=1]
+  br i1 %cmp24, label %for.body25, label %for.cond22.for.end32_crit_edge
+
+for.cond22.for.end32_crit_edge:                   ; preds = %for.cond22
+  br label %for.end32
+
+bb.nph5:                                          ; preds = %if.then
+  br label %for.body25
+
+for.body25:                                       ; preds = %bb.nph5, %for.cond22
+  %k.04 = phi i64 [ %add, %bb.nph5 ], [ %add31, %for.cond22 ] ; <i64> [#uses=2]
+  %arrayidx27 = getelementptr inbounds [8193 x i8], [8193 x i8]* @main.flags, i64 0, i64 %k.04 ; <i8*> [#uses=1]
+  store i8 0, i8* %arrayidx27
+  %add31 = add nsw i64 %k.04, %i.17               ; <i64> [#uses=2]
+  br label %for.cond22
+
+for.end32:                                        ; preds = %for.cond22.for.end32_crit_edge, %if.then
+  %inc34 = add nsw i32 %count.212, 1              ; <i32> [#uses=1]
+  br label %for.inc35
+
+for.inc35:                                        ; preds = %for.body15, %for.end32
+  %count.1 = phi i32 [ %inc34, %for.end32 ], [ %count.212, %for.body15 ] ; <i32> [#uses=2]
+  %inc37 = add nsw i64 %i.17, 1                   ; <i64> [#uses=2]
+  br label %for.cond12
+
+while.end:                                        ; preds = %while.cond.while.end_crit_edge, %while.cond.preheader
+  %count.0.lcssa = phi i32 [ %count.2.lcssa.lcssa, %while.cond.while.end_crit_edge ], [ 0, %while.cond.preheader ] ; <i32> [#uses=1]
+  %call40 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i64 0, i64 0), i32 %count.0.lcssa) nounwind ; <i32> [#uses=0]
+  ret i32 0
+}
+
+declare i32 @atoi(i8* nocapture) nounwind readonly
+
+declare i32 @printf(i8* nocapture, ...) nounwind
+
+; IndVars doesn't emit a udiv in for.body.preheader since SCEVExpander::expand will
+; find out there's already a udiv in the original code.
+
+; CHECK-LABEL: @foo(
+; CHECK: for.body.preheader:
+; CHECK-NOT: udiv
+
+define void @foo(double* %p, i64 %n) nounwind {
+entry:
+  %div0 = udiv i64 %n, 7                          ; <i64> [#uses=1]
+  %div1 = add i64 %div0, 1
+  %cmp2 = icmp ult i64 0, %div1                   ; <i1> [#uses=1]
+  br i1 %cmp2, 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.03 = phi i64 [ %inc, %for.body ], [ 0, %for.body.preheader ] ; <i64> [#uses=2]
+  %arrayidx = getelementptr inbounds double, double* %p, i64 %i.03 ; <double*> [#uses=1]
+  store double 0.000000e+00, double* %arrayidx
+  %inc = add i64 %i.03, 1                         ; <i64> [#uses=2]
+  %divx = udiv i64 %n, 7                           ; <i64> [#uses=1]
+  %div = add i64 %divx, 1
+  %cmp = icmp ult i64 %inc, %div                  ; <i1> [#uses=1]
+  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/uglygep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/uglygep.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/uglygep.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/uglygep.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+; rdar://8197217
+
+; Indvars should be able to emit a clean GEP here, not an uglygep.
+
+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-darwin11.0"
+
+ at numf2s = external global i32                     ; <i32*> [#uses=1]
+ at numf1s = external global i32                     ; <i32*> [#uses=1]
+ at tds = external global double**                   ; <double***> [#uses=1]
+
+define void @init_td(i32 %tmp7) nounwind {
+; CHECK-LABEL: @init_td
+; CHECK-NOT: uglygep
+entry:
+  br label %bb4
+
+bb4:                                              ; preds = %bb3, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %tmp9, %bb3 ]   ; <i32> [#uses=3]
+  br label %bb
+
+bb:                                               ; preds = %bb4
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb
+  %j.0 = phi i32 [ 0, %bb ], [ %tmp6, %bb1 ]      ; <i32> [#uses=3]
+  %tmp8 = icmp slt i32 %j.0, %tmp7                ; <i1> [#uses=1]
+  br i1 %tmp8, label %bb1, label %bb3
+
+bb1:                                              ; preds = %bb2
+  %tmp = load double**, double*** @tds, align 8             ; <double**> [#uses=1]
+  %tmp1 = sext i32 %i.0 to i64                    ; <i64> [#uses=1]
+  %tmp2 = getelementptr inbounds double*, double** %tmp, i64 %tmp1 ; <double**> [#uses=1]
+  %tmp3 = load double*, double** %tmp2, align 1            ; <double*> [#uses=1]
+  %tmp6 = add nsw i32 %j.0, 1                     ; <i32> [#uses=1]
+  br label %bb2
+
+bb3:                                              ; preds = %bb2
+  %tmp9 = add nsw i32 %i.0, 1                     ; <i32> [#uses=1]
+  br label %bb4
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/ult-sub-to-eq.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt -S -indvars < %s | FileCheck %s
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+define void @test1(float* nocapture %autoc, float* nocapture %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 ], [ 0, %entry ]
+  %0 = trunc i64 %indvars.iv to i32
+  %add = add i32 %0, %sample
+  %idxprom = zext i32 %add to i64
+  %arrayidx = getelementptr inbounds float, float* %data, i64 %idxprom
+  %1 = load float, float* %arrayidx, align 4
+  %mul = fmul float %1, %d
+  %arrayidx2 = getelementptr inbounds float, float* %autoc, i64 %indvars.iv
+  %2 = load float, float* %arrayidx2, align 4
+  %add3 = fadd float %2, %mul
+  store float %add3, float* %arrayidx2, align 4
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  %3 = trunc i64 %indvars.iv.next to i32
+  %cmp = icmp ult i32 %3, %sub
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body, %entry
+  ret void
+
+; CHECK-LABEL: @test1(
+
+; check that we turn the IV test into an eq.
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK: %wide.trip.count = zext i32 %sub to i64
+; CHECK: %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count
+; CHECK: br i1 %exitcond, label %for.body, label %for.end.loopexit
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/use-range-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/use-range-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/use-range-metadata.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/use-range-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+;; RUN: opt -S < %s -indvars | FileCheck %s
+
+;; Check if IndVarSimplify understands !range metadata.
+
+declare void @abort()
+
+define i1 @iterate(i32* nocapture readonly %buffer) {
+entry:
+  %length = load i32, i32* %buffer, !range !0
+  br label %loop.preheader
+
+loop.preheader:
+  br label %loop
+
+loop:
+  %idx = phi i32 [ %idx.inc, %loop.next ], [ 0, %loop.preheader ]
+  %oob.pred = icmp slt i32 %idx, %length
+  br i1 %oob.pred, label %loop.next, label %oob
+; CHECK: br i1 true, label %loop.next, label %oob
+
+loop.next:
+  %idx.inc = add i32 %idx, 1
+  %exit.pred = icmp slt i32 %idx.inc, %length
+  br i1 %exit.pred, label %loop, label %abort.loopexit
+
+abort.loopexit:
+  br label %abort
+
+abort:
+  ret i1 false
+
+oob:
+  tail call void @abort()
+  ret i1 false
+}
+
+!0 = !{i32 1, i32 100}

Added: llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt < %s -indvars -instcombine -S | FileCheck %s
+;
+; Test that -indvars can reduce variable stride IVs.  If it can reduce variable
+; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without
+; cycles, allowing the tmp.21 subtraction to be eliminated.
+
+define void @vnum_test8(i32* %data) {
+entry:
+        %tmp.1 = getelementptr i32, i32* %data, i32 3                ; <i32*> [#uses=1]
+        %tmp.2 = load i32, i32* %tmp.1               ; <i32> [#uses=2]
+        %tmp.4 = getelementptr i32, i32* %data, i32 4                ; <i32*> [#uses=1]
+        %tmp.5 = load i32, i32* %tmp.4               ; <i32> [#uses=2]
+        %tmp.8 = getelementptr i32, i32* %data, i32 2                ; <i32*> [#uses=1]
+        %tmp.9 = load i32, i32* %tmp.8               ; <i32> [#uses=3]
+        %tmp.125 = icmp sgt i32 %tmp.2, 0               ; <i1> [#uses=1]
+        br i1 %tmp.125, label %no_exit.preheader, label %return
+
+no_exit.preheader:              ; preds = %entry
+        %tmp.16 = getelementptr i32, i32* %data, i32 %tmp.9          ; <i32*> [#uses=1]
+        br label %no_exit
+
+; CHECK: store i32 0
+no_exit:                ; preds = %no_exit, %no_exit.preheader
+        %iv.ui = phi i32 [ 0, %no_exit.preheader ], [ %iv..inc.ui, %no_exit ]           ; <i32> [#uses=1]
+        %iv. = phi i32 [ %tmp.5, %no_exit.preheader ], [ %iv..inc, %no_exit ]           ; <i32> [#uses=2]
+        %m.0.0 = phi i32 [ %tmp.5, %no_exit.preheader ], [ %tmp.24, %no_exit ]          ; <i32> [#uses=2]
+        store i32 2, i32* %tmp.16
+        %tmp.21 = sub i32 %m.0.0, %iv.          ; <i32> [#uses=1]
+        store i32 %tmp.21, i32* %data
+        %tmp.24 = add i32 %m.0.0, %tmp.9                ; <i32> [#uses=1]
+        %iv..inc = add i32 %tmp.9, %iv.         ; <i32> [#uses=1]
+        %iv..inc.ui = add i32 %iv.ui, 1         ; <i32> [#uses=2]
+        %iv..inc1 = bitcast i32 %iv..inc.ui to i32              ; <i32> [#uses=1]
+        %tmp.12 = icmp slt i32 %iv..inc1, %tmp.2                ; <i1> [#uses=1]
+        br i1 %tmp.12, label %no_exit, label %return.loopexit
+
+return.loopexit:                ; preds = %no_exit
+        br label %return
+
+return:         ; preds = %return.loopexit, %entry
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt < %s -indvars
+; PR4315
+
+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-f80:128:128"
+target triple = "x86_64-undermydesk-freebsd8.0"
+	%struct.mbuf = type <{ %struct.mbuf*, i8*, i32, i8, i8, i8, i8 }>
+
+define i32 @crash(%struct.mbuf* %m) nounwind {
+entry:
+	br label %for.cond
+
+for.cond:		; preds = %if.end, %entry
+	%i.0 = phi i32 [ 0, %entry ], [ %inc, %if.end ]		; <i32> [#uses=3]
+	%chksum.0 = phi i8 [ 0, %entry ], [ %conv3, %if.end ]		; <i8> [#uses=3]
+	%cmp = icmp slt i32 %i.0, 1		; <i1> [#uses=1]
+	br i1 %cmp, label %for.body, label %do.body
+
+for.body:		; preds = %for.cond
+	br i1 undef, label %if.end, label %do.body
+
+if.end:		; preds = %for.body
+	%i.02 = trunc i32 %i.0 to i8		; <i8> [#uses=1]
+	%conv3 = add i8 %chksum.0, %i.02		; <i8> [#uses=1]
+	%inc = add i32 %i.0, 1		; <i32> [#uses=1]
+	br label %for.cond
+
+do.body:		; preds = %do.cond, %for.body, %for.cond
+	%chksum.2 = phi i8 [ undef, %do.cond ], [ %chksum.0, %for.body ], [ %chksum.0, %for.cond ]		; <i8> [#uses=1]
+	br i1 undef, label %do.cond, label %bb.nph
+
+bb.nph:		; preds = %do.body
+	br label %while.body
+
+while.body:		; preds = %while.body, %bb.nph
+	%chksum.13 = phi i8 [ undef, %while.body ], [ %chksum.2, %bb.nph ]		; <i8> [#uses=0]
+	br i1 undef, label %do.cond, label %while.body
+
+do.cond:		; preds = %while.body, %do.body
+	br i1 false, label %do.end, label %do.body
+
+do.end:		; preds = %do.cond
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/verify-scev.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/verify-scev.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/verify-scev.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/verify-scev.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,421 @@
+; RUN: opt < %s -S -indvars -verify-scev
+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.8.0"
+
+define void @test1() nounwind uwtable ssp {
+entry:
+  br i1 undef, label %for.end, label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  br i1 false, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %entry
+  br i1 undef, label %for.end11, label %for.body3
+
+for.body3:                                        ; preds = %for.end
+  unreachable
+
+for.end11:                                        ; preds = %for.end
+  br i1 undef, label %while.body, label %while.end
+
+while.body:                                       ; preds = %for.end11
+  unreachable
+
+while.end:                                        ; preds = %for.end11
+  br i1 undef, label %if.end115, label %for.cond109
+
+for.cond109:                                      ; preds = %while.end
+  unreachable
+
+if.end115:                                        ; preds = %while.end
+  br i1 undef, label %while.body119.lr.ph.lr.ph, label %for.cond612
+
+while.body119.lr.ph.lr.ph:                        ; preds = %if.end115
+  br i1 undef, label %for.cond612, label %if.end123.us
+
+if.end123.us:                                     ; preds = %while.body119.lr.ph.lr.ph
+  br label %for.cond132.us
+
+for.cond132.us:                                   ; preds = %for.cond132.us, %if.end123.us
+  br i1 undef, label %if.then136.us, label %for.cond132.us
+
+if.then136.us:                                    ; preds = %for.cond132.us
+  br i1 undef, label %while.end220, label %while.body211
+
+while.body211:                                    ; preds = %while.body211, %if.then136.us
+  br i1 undef, label %while.end220, label %while.body211
+
+while.end220:                                     ; preds = %while.body211, %if.then136.us
+  br label %for.cond246.outer
+
+for.cond246.outer:                                ; preds = %for.inc558, %for.cond394.preheader, %if.then274, %for.cond404.preheader, %while.end220
+  br label %for.cond246
+
+for.cond246:                                      ; preds = %for.cond372.loopexit, %for.cond246.outer
+  br i1 undef, label %for.end562, label %if.end250
+
+if.end250:                                        ; preds = %for.cond246
+  br i1 undef, label %if.end256, label %for.end562
+
+if.end256:                                        ; preds = %if.end250
+  %cmp272 = icmp eq i32 undef, undef
+  br i1 %cmp272, label %if.then274, label %for.cond404.preheader
+
+for.cond404.preheader:                            ; preds = %if.end256
+  br i1 undef, label %for.cond246.outer, label %for.body409.lr.ph
+
+for.body409.lr.ph:                                ; preds = %for.cond404.preheader
+  br label %for.body409
+
+if.then274:                                       ; preds = %if.end256
+  br i1 undef, label %for.cond246.outer, label %if.end309
+
+if.end309:                                        ; preds = %if.then274
+  br i1 undef, label %for.cond372.loopexit, label %for.body361
+
+for.body361:                                      ; preds = %for.body361, %if.end309
+  br i1 undef, label %for.cond372.loopexit, label %for.body361
+
+for.cond372.loopexit:                             ; preds = %for.body361, %if.end309
+  br i1 undef, label %for.cond394.preheader, label %for.cond246
+
+for.cond394.preheader:                            ; preds = %for.cond372.loopexit
+  br i1 undef, label %for.cond246.outer, label %for.body397
+
+for.body397:                                      ; preds = %for.cond394.preheader
+  unreachable
+
+for.body409:                                      ; preds = %for.inc558, %for.body409.lr.ph
+  %k.029 = phi i32 [ 1, %for.body409.lr.ph ], [ %inc559, %for.inc558 ]
+  br i1 undef, label %if.then412, label %if.else433
+
+if.then412:                                       ; preds = %for.body409
+  br label %if.end440
+
+if.else433:                                       ; preds = %for.body409
+  br label %if.end440
+
+if.end440:                                        ; preds = %if.else433, %if.then412
+  br i1 undef, label %for.inc558, label %if.end461
+
+if.end461:                                        ; preds = %if.end440
+  br i1 undef, label %for.cond528.loopexit, label %for.body517
+
+for.body517:                                      ; preds = %for.body517, %if.end461
+  br i1 undef, label %for.cond528.loopexit, label %for.body517
+
+for.cond528.loopexit:                             ; preds = %for.body517, %if.end461
+  br label %for.inc558
+
+for.inc558:                                       ; preds = %for.cond528.loopexit, %if.end440
+  %inc559 = add nsw i32 %k.029, 1
+  %cmp407 = icmp sgt i32 %inc559, undef
+  br i1 %cmp407, label %for.cond246.outer, label %for.body409
+
+for.end562:                                       ; preds = %if.end250, %for.cond246
+  unreachable
+
+for.cond612:                                      ; preds = %while.body119.lr.ph.lr.ph, %if.end115
+  unreachable
+}
+
+define void @test2() nounwind uwtable ssp {
+entry:
+  br i1 undef, label %for.end, label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  br i1 undef, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %entry
+  br i1 undef, label %for.end11, label %for.body3
+
+for.body3:                                        ; preds = %for.end
+  unreachable
+
+for.end11:                                        ; preds = %for.end
+  br i1 undef, label %while.body, label %while.end
+
+while.body:                                       ; preds = %for.end11
+  unreachable
+
+while.end:                                        ; preds = %for.end11
+  br i1 undef, label %if.end115, label %for.cond109
+
+for.cond109:                                      ; preds = %while.end
+  unreachable
+
+if.end115:                                        ; preds = %while.end
+  br i1 undef, label %while.body119.lr.ph.lr.ph, label %for.cond612
+
+while.body119.lr.ph.lr.ph:                        ; preds = %if.end115
+  br i1 undef, label %for.cond612, label %if.end123.us
+
+if.end123.us:                                     ; preds = %while.body119.lr.ph.lr.ph
+  br label %for.cond132.us
+
+for.cond132.us:                                   ; preds = %for.cond132.us, %if.end123.us
+  br i1 undef, label %if.then136.us, label %for.cond132.us
+
+if.then136.us:                                    ; preds = %for.cond132.us
+  br i1 undef, label %while.end220, label %while.body211
+
+while.body211:                                    ; preds = %while.body211, %if.then136.us
+  br i1 undef, label %while.end220, label %while.body211
+
+while.end220:                                     ; preds = %while.body211, %if.then136.us
+  br label %for.cond246.outer
+
+for.cond246.outer:                                ; preds = %for.inc558, %for.cond394.preheader, %if.then274, %for.cond404.preheader, %while.end220
+  br label %for.cond246
+
+for.cond246:                                      ; preds = %for.cond372.loopexit, %for.cond246.outer
+  br i1 undef, label %for.end562, label %if.end250
+
+if.end250:                                        ; preds = %for.cond246
+  br i1 undef, label %if.end256, label %for.end562
+
+if.end256:                                        ; preds = %if.end250
+  %0 = load i32, i32* undef, align 4
+  br i1 undef, label %if.then274, label %for.cond404.preheader
+
+for.cond404.preheader:                            ; preds = %if.end256
+  %add406 = add i32 0, %0
+  br i1 undef, label %for.cond246.outer, label %for.body409.lr.ph
+
+for.body409.lr.ph:                                ; preds = %for.cond404.preheader
+  br label %for.body409
+
+if.then274:                                       ; preds = %if.end256
+  br i1 undef, label %for.cond246.outer, label %if.end309
+
+if.end309:                                        ; preds = %if.then274
+  br i1 undef, label %for.cond372.loopexit, label %for.body361
+
+for.body361:                                      ; preds = %for.body361, %if.end309
+  br i1 undef, label %for.cond372.loopexit, label %for.body361
+
+for.cond372.loopexit:                             ; preds = %for.body361, %if.end309
+  br i1 undef, label %for.cond394.preheader, label %for.cond246
+
+for.cond394.preheader:                            ; preds = %for.cond372.loopexit
+  br i1 undef, label %for.cond246.outer, label %for.body397
+
+for.body397:                                      ; preds = %for.cond394.preheader
+  unreachable
+
+for.body409:                                      ; preds = %for.inc558, %for.body409.lr.ph
+  %k.029 = phi i32 [ 1, %for.body409.lr.ph ], [ %inc559, %for.inc558 ]
+  br i1 undef, label %if.then412, label %if.else433
+
+if.then412:                                       ; preds = %for.body409
+  br label %if.end440
+
+if.else433:                                       ; preds = %for.body409
+  br label %if.end440
+
+if.end440:                                        ; preds = %if.else433, %if.then412
+  br i1 undef, label %for.inc558, label %if.end461
+
+if.end461:                                        ; preds = %if.end440
+  br i1 undef, label %for.cond528.loopexit, label %for.body517
+
+for.body517:                                      ; preds = %for.body517, %if.end461
+  br i1 undef, label %for.cond528.loopexit, label %for.body517
+
+for.cond528.loopexit:                             ; preds = %for.body517, %if.end461
+  br label %for.inc558
+
+for.inc558:                                       ; preds = %for.cond528.loopexit, %if.end440
+  %inc559 = add nsw i32 %k.029, 1
+  %cmp407 = icmp sgt i32 %inc559, %add406
+  br i1 %cmp407, label %for.cond246.outer, label %for.body409
+
+for.end562:                                       ; preds = %if.end250, %for.cond246
+  unreachable
+
+for.cond612:                                      ; preds = %while.body119.lr.ph.lr.ph, %if.end115
+  unreachable
+}
+
+define void @test3() nounwind uwtable ssp {
+entry:
+  br i1 undef, label %for.end, label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  br i1 undef, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %entry
+  br i1 undef, label %for.end11, label %for.body3
+
+for.body3:                                        ; preds = %for.end
+  unreachable
+
+for.end11:                                        ; preds = %for.end
+  br i1 undef, label %while.body, label %while.end
+
+while.body:                                       ; preds = %for.end11
+  unreachable
+
+while.end:                                        ; preds = %for.end11
+  br i1 undef, label %if.end115, label %for.cond109
+
+for.cond109:                                      ; preds = %while.end
+  unreachable
+
+if.end115:                                        ; preds = %while.end
+  br i1 undef, label %while.body119.lr.ph.lr.ph, label %for.cond612
+
+while.body119.lr.ph.lr.ph:                        ; preds = %if.end115
+  br i1 undef, label %for.cond612, label %if.end123.us
+
+if.end123.us:                                     ; preds = %while.body119.lr.ph.lr.ph
+  br label %for.cond132.us
+
+for.cond132.us:                                   ; preds = %for.cond132.us, %if.end123.us
+  br i1 undef, label %if.then136.us, label %for.cond132.us
+
+if.then136.us:                                    ; preds = %for.cond132.us
+  br i1 undef, label %while.end220, label %while.body211
+
+while.body211:                                    ; preds = %while.body211, %if.then136.us
+  br i1 undef, label %while.end220, label %while.body211
+
+while.end220:                                     ; preds = %while.body211, %if.then136.us
+  br label %for.cond246.outer
+
+for.cond246.outer:                                ; preds = %for.inc558, %for.cond394.preheader, %if.then274, %for.cond404.preheader, %while.end220
+  br label %for.cond246
+
+for.cond246:                                      ; preds = %for.cond372.loopexit, %for.cond246.outer
+  br i1 undef, label %for.end562, label %if.end250
+
+if.end250:                                        ; preds = %for.cond246
+  br i1 undef, label %if.end256, label %for.end562
+
+if.end256:                                        ; preds = %if.end250
+  br i1 undef, label %if.then274, label %for.cond404.preheader
+
+for.cond404.preheader:                            ; preds = %if.end256
+  br i1 undef, label %for.cond246.outer, label %for.body409.lr.ph
+
+for.body409.lr.ph:                                ; preds = %for.cond404.preheader
+  br label %for.body409
+
+if.then274:                                       ; preds = %if.end256
+  br i1 undef, label %for.cond246.outer, label %if.end309
+
+if.end309:                                        ; preds = %if.then274
+  br i1 undef, label %for.cond372.loopexit, label %for.body361
+
+for.body361:                                      ; preds = %for.body361, %if.end309
+  br i1 undef, label %for.cond372.loopexit, label %for.body361
+
+for.cond372.loopexit:                             ; preds = %for.body361, %if.end309
+  br i1 undef, label %for.cond394.preheader, label %for.cond246
+
+for.cond394.preheader:                            ; preds = %for.cond372.loopexit
+  br i1 undef, label %for.cond246.outer, label %for.body397
+
+for.body397:                                      ; preds = %for.cond394.preheader
+  unreachable
+
+for.body409:                                      ; preds = %for.inc558, %for.body409.lr.ph
+  br i1 undef, label %if.then412, label %if.else433
+
+if.then412:                                       ; preds = %for.body409
+  br label %if.end440
+
+if.else433:                                       ; preds = %for.body409
+  br label %if.end440
+
+if.end440:                                        ; preds = %if.else433, %if.then412
+  br i1 undef, label %for.inc558, label %if.end461
+
+if.end461:                                        ; preds = %if.end440
+  br i1 undef, label %for.cond528.loopexit, label %for.body517
+
+for.body517:                                      ; preds = %for.body517, %if.end461
+  br i1 undef, label %for.cond528.loopexit, label %for.body517
+
+for.cond528.loopexit:                             ; preds = %for.body517, %if.end461
+  br label %for.inc558
+
+for.inc558:                                       ; preds = %for.cond528.loopexit, %if.end440
+  br i1 undef, label %for.cond246.outer, label %for.body409
+
+for.end562:                                       ; preds = %if.end250, %for.cond246
+  unreachable
+
+for.cond612:                                      ; preds = %while.body119.lr.ph.lr.ph, %if.end115
+  unreachable
+}
+
+define void @test4() nounwind uwtable ssp {
+entry:
+  br i1 undef, label %if.end8, label %if.else
+
+if.else:                                          ; preds = %entry
+  br label %if.end8
+
+if.end8:                                          ; preds = %if.else, %entry
+  br i1 undef, label %if.end26, label %if.else22
+
+if.else22:                                        ; preds = %if.end8
+  br label %if.end26
+
+if.end26:                                         ; preds = %if.else22, %if.end8
+  br i1 undef, label %if.end35, label %if.else31
+
+if.else31:                                        ; preds = %if.end26
+  br label %if.end35
+
+if.end35:                                         ; preds = %if.else31, %if.end26
+  br i1 undef, label %for.end226, label %for.body.lr.ph
+
+for.body.lr.ph:                                   ; preds = %if.end35
+  br label %for.body48
+
+for.body48:                                       ; preds = %for.inc221, %for.body.lr.ph
+  br i1 undef, label %for.inc221, label %for.body65.lr.ph
+
+for.body65.lr.ph:                                 ; preds = %for.body48
+  %0 = load i32, i32* undef, align 4
+  %1 = sext i32 %0 to i64
+  br label %for.body65.us
+
+for.body65.us:                                    ; preds = %for.inc219.us, %for.body65.lr.ph
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc219.us ], [ 1, %for.body65.lr.ph ]
+  br i1 undef, label %for.inc219.us, label %if.end72.us
+
+if.end72.us:                                      ; preds = %for.body65.us
+  br i1 undef, label %if.end93.us, label %if.then76.us
+
+if.then76.us:                                     ; preds = %if.end72.us
+  br label %if.end93.us
+
+if.end93.us:                                      ; preds = %if.then76.us, %if.end72.us
+  br i1 undef, label %if.end110.us, label %for.inc219.us
+
+if.end110.us:                                     ; preds = %if.end93.us
+  br i1 undef, label %for.inc219.us, label %for.body142.us
+
+for.body142.us:                                   ; preds = %for.cond139.loopexit.us, %if.end110.us
+  br label %for.cond152.us
+
+for.cond152.us:                                   ; preds = %for.cond152.us, %for.body142.us
+  br i1 undef, label %for.cond139.loopexit.us, label %for.cond152.us
+
+for.inc219.us:                                    ; preds = %for.cond139.loopexit.us, %if.end110.us, %if.end93.us, %for.body65.us
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %cmp64.us = icmp sgt i64 %indvars.iv.next, %1
+  br i1 %cmp64.us, label %for.inc221, label %for.body65.us
+
+for.cond139.loopexit.us:                          ; preds = %for.cond152.us
+  br i1 undef, label %for.inc219.us, label %for.body142.us
+
+for.inc221:                                       ; preds = %for.inc219.us, %for.body48
+  br label %for.body48
+
+for.end226:                                       ; preds = %if.end35
+  ret void
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/widen-loop-comp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,355 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+target triple = "aarch64--linux-gnu"
+
+; Provide legal integer types.
+target datalayout = "n8:16:32:64"
+
+
+; Check the loop exit i32 compare instruction and operand are widened to i64
+; instead of truncating IV before its use in the i32 compare instruction.
+
+ at idx = common global i32 0, align 4
+ at e = common global i32 0, align 4
+ at ptr = common global i32* null, align 8
+
+; CHECK-LABEL: @test1
+; CHECK: for.body.lr.ph:
+; CHECK: sext i32
+; CHECK: for.cond:
+; CHECK: icmp slt i64
+; CHECK: for.body:
+; CHECK: phi i64
+
+define i32 @test1() {
+entry:
+  store i32 -1, i32* @idx, align 4
+  %0 = load i32, i32* @e, align 4
+  %cmp4 = icmp slt i32 %0, 0
+  br i1 %cmp4, label %for.end.loopexit, label %for.body.lr.ph
+
+for.body.lr.ph:
+  %1 = load i32*, i32** @ptr, align 8
+  %2 = load i32, i32* @e, align 4
+  br label %for.body
+
+for.cond:
+  %inc = add nsw i32 %i.05, 1
+  %cmp = icmp slt i32 %i.05, %2
+  br i1 %cmp, label %for.body, label %for.cond.for.end.loopexit_crit_edge
+
+for.body:
+  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.cond ]
+  %idxprom = sext i32 %i.05 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %1, i64 %idxprom
+  %3 = load i32, i32* %arrayidx, align 4
+  %tobool = icmp eq i32 %3, 0
+  br i1 %tobool, label %if.then, label %for.cond
+
+if.then:
+  %i.05.lcssa = phi i32 [ %i.05, %for.body ]
+  store i32 %i.05.lcssa, i32* @idx, align 4
+  br label %for.end
+
+for.cond.for.end.loopexit_crit_edge:
+  br label %for.end.loopexit
+
+for.end.loopexit:
+  br label %for.end
+
+for.end:
+  %4 = load i32, i32* @idx, align 4
+  ret i32 %4
+}
+
+; CHECK-LABEL: @test2
+; CHECK: for.body4.us
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK: %cmp2.us = icmp ult i64
+; CHECK-NOT: %2 = trunc i64 %indvars.iv.next to i32
+; CHECK-NOT: %cmp2.us = icmp slt i32
+
+define void @test2([8 x i8]* %a, i8* %b, i8 %limit) {
+entry:
+  %conv = zext i8 %limit to i32
+  br i1 undef, label %for.cond1.preheader, label %for.cond1.preheader.us
+
+for.cond1.preheader.us:
+  %storemerge5.us = phi i32 [ 0, %entry ], [ %inc14.us, %for.inc13.us ]
+  br i1 true, label %for.body4.lr.ph.us, label %for.inc13.us
+
+for.inc13.us:
+  %inc14.us = add nsw i32 %storemerge5.us, 1
+  %cmp.us = icmp slt i32 %inc14.us, 4
+  br i1 %cmp.us, label %for.cond1.preheader.us, label %for.end
+
+for.body4.us:
+  %storemerge14.us = phi i32 [ 0, %for.body4.lr.ph.us ], [ %inc.us, %for.body4.us ]
+  %idxprom.us = sext i32 %storemerge14.us to i64
+  %arrayidx6.us = getelementptr inbounds [8 x i8], [8 x i8]* %a, i64 %idxprom5.us, i64 %idxprom.us
+  %0 = load i8, i8* %arrayidx6.us, align 1
+  %idxprom7.us = zext i8 %0 to i64
+  %arrayidx8.us = getelementptr inbounds i8, i8* %b, i64 %idxprom7.us
+  %1 = load i8, i8* %arrayidx8.us, align 1
+  store i8 %1, i8* %arrayidx6.us, align 1
+  %inc.us = add nsw i32 %storemerge14.us, 1
+  %cmp2.us = icmp slt i32 %inc.us, %conv
+  br i1 %cmp2.us, label %for.body4.us, label %for.inc13.us
+
+for.body4.lr.ph.us:
+  %idxprom5.us = sext i32 %storemerge5.us to i64
+  br label %for.body4.us
+
+for.cond1.preheader:
+  %storemerge5 = phi i32 [ 0, %entry ], [ %inc14, %for.inc13 ]
+  br i1 false, label %for.inc13, label %for.inc13
+
+for.inc13:
+  %inc14 = add nsw i32 %storemerge5, 1
+  %cmp = icmp slt i32 %inc14, 4
+  br i1 %cmp, label %for.cond1.preheader, label %for.end
+
+for.end:
+  ret void
+}
+
+; CHECK-LABEL: @test3
+; CHECK: sext i32 %b
+; CHECK: for.cond:
+; CHECK: phi i64
+; CHECK: icmp slt i64
+
+define i32 @test3(i32* %a, i32 %b) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i32 %i.0, %b
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  ret i32 %sum.0
+}
+
+declare i32 @fn1(i8 signext)
+
+; PR21030
+; CHECK-LABEL: @test4
+; CHECK: for.body:
+; CHECK: phi i32
+; CHECK: icmp sgt i8
+
+define i32 @test4(i32 %a) {
+entry:
+  br label %for.body
+
+for.body:
+  %c.07 = phi i8 [ -3, %entry ], [ %dec, %for.body ]
+  %conv6 = zext i8 %c.07 to i32
+  %or = or i32 %a, %conv6
+  %conv3 = trunc i32 %or to i8
+  %call = call i32 @fn1(i8 signext %conv3)
+  %dec = add i8 %c.07, -1
+  %cmp = icmp sgt i8 %dec, -14
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret i32 0
+}
+
+; CHECK-LABEL: @test5
+; CHECK: zext i32 %b
+; CHECK: for.cond:
+; CHECK: phi i64
+; CHECK: icmp ule i64
+
+define i32 @test5(i32* %a, i32 %b) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp ule i32 %i.0, %b
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %idxprom = zext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  ret i32 %sum.0
+}
+
+define i32 @test6(i32* %a, i32 %b) {
+; CHECK-LABEL: @test6(
+; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64
+; CHECK: for.cond:
+; CHECK: icmp sle i64 %indvars.iv, [[B_SEXT]]
+
+entry:
+  br label %for.cond
+
+for.cond:
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp sle i32 %i.0, %b
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %idxprom = zext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  ret i32 %sum.0
+}
+
+define i32 @test7(i32* %a, i32 %b) {
+; CHECK-LABEL: @test7(
+; CHECK: [[B_ZEXT:%[a-z0-9]+]] = zext i32 %b to i64
+; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64
+; CHECK: for.cond:
+; CHECK: icmp ule i64 %indvars.iv, [[B_ZEXT]]
+; CHECK: for.body:
+; CHECK: icmp sle i64 %indvars.iv, [[B_SEXT]]
+
+entry:
+  br label %for.cond
+
+for.cond:
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp ule i32 %i.0, %b
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  %cmp2 = icmp sle i32 %i.0, %b
+  br i1 %cmp2, label %for.cond, label %for.end
+
+for.end:
+  ret i32 %sum.0
+}
+
+define i32 @test8(i32* %a, i32 %b, i32 %init) {
+; CHECK-LABEL: @test8(
+; CHECK: [[INIT_SEXT:%[a-z0-9]+]] = sext i32 %init to i64
+; CHECK: [[B_ZEXT:%[a-z0-9]+]] = zext i32 %b to i64
+; CHECK: for.cond:
+;     Note: %indvars.iv is the sign extension of %i.0
+; CHECK: %indvars.iv = phi i64 [ [[INIT_SEXT]], %for.cond.preheader ], [ %indvars.iv.next, %for.body ]
+; CHECK: icmp ule i64 %indvars.iv, [[B_ZEXT]]
+
+entry:
+  %e = icmp sgt i32 %init, 0
+  br i1 %e, label %for.cond, label %leave
+
+for.cond:
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]
+  %cmp = icmp ule i32 %i.0, %b
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  %cmp2 = icmp slt i32 0, %inc
+  br i1 %cmp2, label %for.cond, label %for.end
+
+for.end:
+  ret i32 %sum.0
+
+leave:
+  ret i32 0
+}
+
+define i32 @test9(i32* %a, i32 %b, i32 %init) {
+; CHECK-LABEL: @test9(
+; CHECK: [[INIT_ZEXT:%[a-z0-9]+]] = zext i32 %init to i64
+; CHECK: [[B_SEXT:%[a-z0-9]+]] = sext i32 %b to i64
+; CHECK: for.cond:
+;     Note: %indvars.iv is the zero extension of %i.0
+; CHECK: %indvars.iv = phi i64 [ [[INIT_ZEXT]], %for.cond.preheader ], [ %indvars.iv.next, %for.body ]
+; CHECK: icmp slt i64 %indvars.iv, [[B_SEXT]]
+
+entry:
+  %e = icmp sgt i32 %init, 0
+  br i1 %e, label %for.cond, label %leave
+
+for.cond:
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i32 %i.0, %b
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %idxprom = zext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  %cmp2 = icmp slt i32 0, %inc
+  br i1 %cmp2, label %for.cond, label %for.end
+
+for.end:
+  ret i32 %sum.0
+
+leave:
+  ret i32 0
+}
+
+declare void @consume.i64(i64)
+declare void @consume.i1(i1)
+
+define i32 @test10(i32 %v) {
+; CHECK-LABEL: @test10(
+ entry:
+; CHECK-NOT: zext
+  br label %loop
+
+ loop:
+; CHECK: [[WIDE_V:%[a-z0-9]+]] = sext i32 %v to i64
+; CHECK: loop:
+; CHECK: %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ]
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+; CHECK: [[MUL:%[a-z0-9]+]] = mul nsw i64 %indvars.iv, -1
+; CHECK: [[CMP:%[a-z0-9]+]] = icmp eq i64 [[MUL]], [[WIDE_V]]
+; CHECK: call void @consume.i1(i1 [[CMP]])
+
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
+  %i.inc = add i32 %i, 1
+  %iv = mul i32 %i, -1
+  %cmp = icmp eq i32 %iv, %v
+  call void @consume.i1(i1 %cmp)
+  %be.cond = icmp slt i32 %i.inc, 11
+  %ext = sext i32 %iv to i64
+  call void @consume.i64(i64 %ext)
+  br i1 %be.cond, label %loop, label %leave
+
+ leave:
+  ret i32 22
+}

Added: llvm/trunk/test/Transforms/IndVarSimplify/widen-nsw.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/widen-nsw.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/widen-nsw.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/widen-nsw.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"
+target triple = "x86_64-apple-macosx"
+
+; CHECK-LABEL: @test1
+; CHECK: %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+define i32 @test1(i32* %a) #0 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ]
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i32 %i.0, 1000
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %idxprom = sext i32 %i.0 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %sum.0, %0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret i32 %sum.0
+}
+
+attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }

Added: llvm/trunk/test/Transforms/IndVarSimplify/zext-nuw.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/zext-nuw.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/zext-nuw.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/zext-nuw.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -indvars -S %s | FileCheck %s
+
+%struct.A = type { i8 }
+
+ at c = global %struct.A* null
+ at d = global i32 4
+
+define void @_Z3fn1v() {
+  %x2 = load i32, i32* @d
+  %x3 = icmp slt i32 %x2, 1
+  %x4 = select i1 %x3, i32 1, i32 %x2
+  %x5 = load %struct.A*, %struct.A** @c
+  %j.sroa.0.0..sroa_idx = getelementptr %struct.A, %struct.A* %x5, i64 0, i32 0
+  %j.sroa.0.0.copyload = load i8, i8* %j.sroa.0.0..sroa_idx
+  br label %.preheader4.lr.ph
+
+.preheader4.lr.ph:                                ; preds = %0
+  ; CHECK-NOT: add i64 {{.*}}, 4294967296
+  br label %.preheader4
+
+.preheader4:                                      ; preds = %x22, %.preheader4.lr.ph
+  %k.09 = phi i8* [ undef, %.preheader4.lr.ph ], [ %x25, %x22 ]
+  %x8 = icmp ult i32 0, 4
+  br i1 %x8, label %.preheader.lr.ph, label %x22
+
+.preheader.lr.ph:                                 ; preds = %.preheader4
+  br label %.preheader
+
+.preheader:                                       ; preds = %x17, %.preheader.lr.ph
+  %k.17 = phi i8* [ %k.09, %.preheader.lr.ph ], [ %x19, %x17 ]
+  %v.06 = phi i32 [ 0, %.preheader.lr.ph ], [ %x20, %x17 ]
+  br label %x17
+
+x17:                                              ; preds = %.preheader
+  %x18 = sext i8 %j.sroa.0.0.copyload to i64
+  %x19 = getelementptr i8, i8* %k.17, i64 %x18
+  %x20 = add i32 %v.06, 1
+  %x21 = icmp ult i32 %x20, %x4
+  br i1 %x21, label %.preheader, label %._crit_edge.8
+
+._crit_edge.8:                                    ; preds = %x17
+  %split = phi i8* [ %x19, %x17 ]
+  br label %x22
+
+x22:                                              ; preds = %._crit_edge.8, %.preheader4
+  %k.1.lcssa = phi i8* [ %split, %._crit_edge.8 ], [ %k.09, %.preheader4 ]
+  %x25 = getelementptr i8, i8* %k.1.lcssa
+  br label %.preheader4
+}

Added: llvm/trunk/test/Transforms/IndirectBrExpand/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndirectBrExpand/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/IndirectBrExpand/basic.ll (added)
+++ llvm/trunk/test/Transforms/IndirectBrExpand/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; RUN: opt < %s -indirectbr-expand -S | FileCheck %s
+;
+; REQUIRES: x86-registered-target
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at test1.targets = constant [4 x i8*] [i8* blockaddress(@test1, %bb0),
+                                     i8* blockaddress(@test1, %bb1),
+                                     i8* blockaddress(@test1, %bb2),
+                                     i8* blockaddress(@test1, %bb3)]
+; CHECK-LABEL: @test1.targets = constant [4 x i8*]
+; CHECK:       [i8* inttoptr (i64 1 to i8*),
+; CHECK:        i8* inttoptr (i64 2 to i8*),
+; CHECK:        i8* inttoptr (i64 3 to i8*),
+; CHECK:        i8* blockaddress(@test1, %bb3)]
+
+define void @test1(i64* readonly %p, i64* %sink) #0 {
+; CHECK-LABEL: define void @test1(
+entry:
+  %i0 = load i64, i64* %p
+  %target.i0 = getelementptr [4 x i8*], [4 x i8*]* @test1.targets, i64 0, i64 %i0
+  %target0 = load i8*, i8** %target.i0
+  ; Only a subset of blocks are viable successors here.
+  indirectbr i8* %target0, [label %bb0, label %bb1]
+; CHECK-NOT:     indirectbr
+; CHECK:         %[[ENTRY_V:.*]] = ptrtoint i8* %{{.*}} to i64
+; CHECK-NEXT:    br label %[[SWITCH_BB:.*]]
+
+bb0:
+  store volatile i64 0, i64* %sink
+  br label %latch
+
+bb1:
+  store volatile i64 1, i64* %sink
+  br label %latch
+
+bb2:
+  store volatile i64 2, i64* %sink
+  br label %latch
+
+bb3:
+  store volatile i64 3, i64* %sink
+  br label %latch
+
+latch:
+  %i.next = load i64, i64* %p
+  %target.i.next = getelementptr [4 x i8*], [4 x i8*]* @test1.targets, i64 0, i64 %i.next
+  %target.next = load i8*, i8** %target.i.next
+  ; A different subset of blocks are viable successors here.
+  indirectbr i8* %target.next, [label %bb1, label %bb2]
+; CHECK-NOT:     indirectbr
+; CHECK:         %[[LATCH_V:.*]] = ptrtoint i8* %{{.*}} to i64
+; CHECK-NEXT:    br label %[[SWITCH_BB]]
+;
+; CHECK:       [[SWITCH_BB]]:
+; CHECK-NEXT:    %[[V:.*]] = phi i64 [ %[[ENTRY_V]], %entry ], [ %[[LATCH_V]], %latch ]
+; CHECK-NEXT:    switch i64 %[[V]], label %bb0 [
+; CHECK-NEXT:      i64 2, label %bb1
+; CHECK-NEXT:      i64 3, label %bb2
+; CHECK-NEXT:    ]
+}
+
+attributes #0 = { "target-features"="+retpoline" }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,185 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; Trivial optimization of generic addressing
+
+; CHECK-LABEL: @load_global_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(1)*
+; CHECK-NEXT: %tmp1 = load float, float addrspace(1)* %tmp0
+; CHECK-NEXT: ret float %tmp1
+define float @load_global_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(1)*
+  %tmp1 = load float, float addrspace(1)* %tmp0
+  ret float %tmp1
+}
+
+; CHECK-LABEL: @load_constant_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(4)*
+; CHECK-NEXT: %tmp1 = load float, float addrspace(4)* %tmp0
+; CHECK-NEXT: ret float %tmp1
+define float @load_constant_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(4)*
+  %tmp1 = load float, float addrspace(4)* %tmp0
+  ret float %tmp1
+}
+
+; CHECK-LABEL: @load_group_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(3)*
+; CHECK-NEXT: %tmp1 = load float, float addrspace(3)* %tmp0
+; CHECK-NEXT: ret float %tmp1
+define float @load_group_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(3)*
+  %tmp1 = load float, float addrspace(3)* %tmp0
+  ret float %tmp1
+}
+
+; CHECK-LABEL: @load_private_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(5)*
+; CHECK-NEXT: %tmp1 = load float, float addrspace(5)* %tmp0
+; CHECK-NEXT: ret float %tmp1
+define float @load_private_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(5)*
+  %tmp1 = load float, float addrspace(5)* %tmp0
+  ret float %tmp1
+}
+
+; CHECK-LABEL: @store_global_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(1)*
+; CHECK-NEXT: store float 0.000000e+00, float addrspace(1)* %tmp0
+define amdgpu_kernel void @store_global_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(1)*
+  store float 0.0, float addrspace(1)* %tmp0
+  ret void
+}
+
+; CHECK-LABEL: @store_group_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(3)*
+; CHECK-NEXT: store float 0.000000e+00, float addrspace(3)* %tmp0
+define amdgpu_kernel void @store_group_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(3)*
+  store float 0.0, float addrspace(3)* %tmp0
+  ret void
+}
+
+; CHECK-LABEL: @store_private_from_flat(
+; CHECK-NEXT: %tmp0 = addrspacecast float* %generic_scalar to float addrspace(5)*
+; CHECK-NEXT: store float 0.000000e+00, float addrspace(5)* %tmp0
+define amdgpu_kernel void @store_private_from_flat(float* %generic_scalar) #0 {
+  %tmp0 = addrspacecast float* %generic_scalar to float addrspace(5)*
+  store float 0.0, float addrspace(5)* %tmp0
+  ret void
+}
+
+; optimized to global load/store.
+; CHECK-LABEL: @load_store_global(
+; CHECK-NEXT: %val = load i32, i32 addrspace(1)* %input, align 4
+; CHECK-NEXT: store i32 %val, i32 addrspace(1)* %output, align 4
+; CHECK-NEXT: ret void
+define amdgpu_kernel void @load_store_global(i32 addrspace(1)* nocapture %input, i32 addrspace(1)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(1)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(1)* %output to i32*
+  %val = load i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; Optimized to group load/store.
+; CHECK-LABEL: @load_store_group(
+; CHECK-NEXT: %val = load i32, i32 addrspace(3)* %input, align 4
+; CHECK-NEXT: store i32 %val, i32 addrspace(3)* %output, align 4
+; CHECK-NEXT: ret void
+define amdgpu_kernel void @load_store_group(i32 addrspace(3)* nocapture %input, i32 addrspace(3)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(3)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(3)* %output to i32*
+  %val = load i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; Optimized to private load/store.
+; CHECK-LABEL: @load_store_private(
+; CHECK-NEXT: %val = load i32, i32 addrspace(5)* %input, align 4
+; CHECK-NEXT: store i32 %val, i32 addrspace(5)* %output, align 4
+; CHECK-NEXT: ret void
+define amdgpu_kernel void @load_store_private(i32 addrspace(5)* nocapture %input, i32 addrspace(5)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(5)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(5)* %output to i32*
+  %val = load i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; No optimization. flat load/store.
+; CHECK-LABEL: @load_store_flat(
+; CHECK-NEXT: %val = load i32, i32* %input, align 4
+; CHECK-NEXT: store i32 %val, i32* %output, align 4
+; CHECK-NEXT: ret void
+define amdgpu_kernel void @load_store_flat(i32* nocapture %input, i32* nocapture %output) #0 {
+  %val = load i32, i32* %input, align 4
+  store i32 %val, i32* %output, align 4
+  ret void
+}
+
+; CHECK-LABEL: @store_addrspacecast_ptr_value(
+; CHECK: %cast = addrspacecast i32 addrspace(1)* %input to i32*
+; CHECK-NEXT: store i32* %cast, i32* addrspace(1)* %output, align 4
+define amdgpu_kernel void @store_addrspacecast_ptr_value(i32 addrspace(1)* nocapture %input, i32* addrspace(1)* nocapture %output) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %input to i32*
+  store i32* %cast, i32* addrspace(1)* %output, align 4
+  ret void
+}
+
+; CHECK-LABEL: @atomicrmw_add_global_to_flat(
+; CHECK-NEXT: %ret = atomicrmw add i32 addrspace(1)* %global.ptr, i32 %y seq_cst
+define i32 @atomicrmw_add_global_to_flat(i32 addrspace(1)* %global.ptr, i32 %y) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = atomicrmw add i32* %cast, i32 %y seq_cst
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @atomicrmw_add_group_to_flat(
+; CHECK-NEXT: %ret = atomicrmw add i32 addrspace(3)* %group.ptr, i32 %y seq_cst
+define i32 @atomicrmw_add_group_to_flat(i32 addrspace(3)* %group.ptr, i32 %y) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = atomicrmw add i32* %cast, i32 %y seq_cst
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @cmpxchg_global_to_flat(
+; CHECK: %ret = cmpxchg i32 addrspace(1)* %global.ptr, i32 %cmp, i32 %val seq_cst monotonic
+define { i32, i1 } @cmpxchg_global_to_flat(i32 addrspace(1)* %global.ptr, i32 %cmp, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = cmpxchg i32* %cast, i32 %cmp, i32 %val seq_cst monotonic
+  ret { i32, i1 } %ret
+}
+
+; CHECK-LABEL: @cmpxchg_group_to_flat(
+; CHECK: %ret = cmpxchg i32 addrspace(3)* %group.ptr, i32 %cmp, i32 %val seq_cst monotonic
+define { i32, i1 } @cmpxchg_group_to_flat(i32 addrspace(3)* %group.ptr, i32 %cmp, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = cmpxchg i32* %cast, i32 %cmp, i32 %val seq_cst monotonic
+  ret { i32, i1 } %ret
+}
+
+; Not pointer operand
+; CHECK-LABEL: @cmpxchg_group_to_flat_wrong_operand(
+; CHECK: %cast.cmp = addrspacecast i32 addrspace(3)* %cmp.ptr to i32*
+; CHECK: %ret = cmpxchg i32* addrspace(3)* %cas.ptr, i32* %cast.cmp, i32* %val seq_cst monotonic
+define { i32*, i1 } @cmpxchg_group_to_flat_wrong_operand(i32* addrspace(3)* %cas.ptr, i32 addrspace(3)* %cmp.ptr, i32* %val) #0 {
+  %cast.cmp = addrspacecast i32 addrspace(3)* %cmp.ptr to i32*
+  %ret = cmpxchg i32* addrspace(3)* %cas.ptr, i32* %cast.cmp, i32* %val seq_cst monotonic
+  ret { i32*, i1 } %ret
+}
+
+; Null pointer in local addr space
+; CHECK-LABEL: @local_nullptr
+; CHECK: icmp ne i8 addrspace(3)* %a, addrspacecast (i8 addrspace(5)* null to i8 addrspace(3)*)
+; CHECK-NOT: i8 addrspace(3)* null
+define void @local_nullptr(i32 addrspace(1)* nocapture %results, i8 addrspace(3)* %a) {
+entry:
+  %tobool = icmp ne i8 addrspace(3)* %a, addrspacecast (i8 addrspace(5)* null to i8 addrspace(3)*)
+  %conv = zext i1 %tobool to i32
+  store i32 %conv, i32 addrspace(1)* %results, align 4
+  ret void
+}
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/icmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/icmp.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/icmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,160 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; CHECK-LABEL: @icmp_flat_cmp_self(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %group.ptr.0, %group.ptr.0
+define i1 @icmp_flat_cmp_self(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, %cast0
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_flat_flat_from_group(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %group.ptr.0, %group.ptr.1
+define i1 @icmp_flat_flat_from_group(i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* %group.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+  %cmp = icmp eq i32* %cast0, %cast1
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_mismatch_flat_from_group_private(
+; CHECK: %1 = addrspacecast i32 addrspace(5)* %private.ptr.0 to i32*
+; CHECK: %2 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+; CHECK: %cmp = icmp eq i32* %1, %2
+define i1 @icmp_mismatch_flat_from_group_private(i32 addrspace(5)* %private.ptr.0, i32 addrspace(3)* %group.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(5)* %private.ptr.0 to i32*
+  %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+  %cmp = icmp eq i32* %cast0, %cast1
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_flat_group_flat(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %cmp = icmp eq i32* %1, %flat.ptr.1
+define i1 @icmp_flat_group_flat(i32 addrspace(3)* %group.ptr.0, i32* %flat.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, %flat.ptr.1
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_flat_flat_group(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+; CHECK: %cmp = icmp eq i32* %flat.ptr.0, %1
+define i1 @icmp_flat_flat_group(i32* %flat.ptr.0, i32 addrspace(3)* %group.ptr.1) #0 {
+  %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+  %cmp = icmp eq i32* %flat.ptr.0, %cast1
+  ret i1 %cmp
+}
+
+; Keeping as cmp addrspace(3)* is better
+; CHECK-LABEL: @icmp_flat_to_group_cmp(
+; CHECK: %cast0 = addrspacecast i32* %flat.ptr.0 to i32 addrspace(3)*
+; CHECK: %cast1 = addrspacecast i32* %flat.ptr.1 to i32 addrspace(3)*
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %cast0, %cast1
+define i1 @icmp_flat_to_group_cmp(i32* %flat.ptr.0, i32* %flat.ptr.1) #0 {
+  %cast0 = addrspacecast i32* %flat.ptr.0 to i32 addrspace(3)*
+  %cast1 = addrspacecast i32* %flat.ptr.1 to i32 addrspace(3)*
+  %cmp = icmp eq i32 addrspace(3)* %cast0, %cast1
+  ret i1 %cmp
+}
+
+; FIXME: Should be able to ask target about how to constant fold the
+; constant cast if this is OK to change if 0 is a valid pointer.
+
+; CHECK-LABEL: @icmp_group_flat_cmp_null(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %group.ptr.0, addrspacecast (i32* null to i32 addrspace(3)*)
+define i1 @icmp_group_flat_cmp_null(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, null
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_group_flat_cmp_constant_inttoptr(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %group.ptr.0, addrspacecast (i32* inttoptr (i64 400 to i32*) to i32 addrspace(3)*)
+define i1 @icmp_group_flat_cmp_constant_inttoptr(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, inttoptr (i64 400 to i32*)
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_mismatch_flat_group_private_cmp_null(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %cmp = icmp eq i32* %1, addrspacecast (i32 addrspace(5)* null to i32*)
+define i1 @icmp_mismatch_flat_group_private_cmp_null(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, addrspacecast (i32 addrspace(5)* null to i32*)
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_mismatch_flat_group_private_cmp_undef(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %group.ptr.0, undef
+define i1 @icmp_mismatch_flat_group_private_cmp_undef(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, addrspacecast (i32 addrspace(5)* undef to i32*)
+  ret i1 %cmp
+}
+
+ at lds0 = internal addrspace(3) global i32 0, align 4
+ at global0 = internal addrspace(1) global i32 0, align 4
+
+; CHECK-LABEL: @icmp_mismatch_flat_group_global_cmp_gv(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %cmp = icmp eq i32* %1, addrspacecast (i32 addrspace(1)* @global0 to i32*)
+define i1 @icmp_mismatch_flat_group_global_cmp_gv(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, addrspacecast (i32 addrspace(1)* @global0 to i32*)
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_mismatch_group_global_cmp_gv_gv(
+; CHECK: %cmp = icmp eq i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), addrspacecast (i32 addrspace(1)* @global0 to i32*)
+define i1 @icmp_mismatch_group_global_cmp_gv_gv(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cmp = icmp eq i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), addrspacecast (i32 addrspace(1)* @global0 to i32*)
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_group_flat_cmp_undef(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* %group.ptr.0, undef
+define i1 @icmp_group_flat_cmp_undef(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* %cast0, undef
+  ret i1 %cmp
+}
+
+; Test non-canonical orders
+; CHECK-LABEL: @icmp_mismatch_flat_group_private_cmp_null_swap(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %cmp = icmp eq i32* addrspacecast (i32 addrspace(5)* null to i32*), %1
+define i1 @icmp_mismatch_flat_group_private_cmp_null_swap(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* addrspacecast (i32 addrspace(5)* null to i32*), %cast0
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_group_flat_cmp_undef_swap(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* undef, %group.ptr.0
+define i1 @icmp_group_flat_cmp_undef_swap(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* undef, %cast0
+  ret i1 %cmp
+}
+
+; CHECK-LABEL: @icmp_mismatch_flat_group_private_cmp_undef_swap(
+; CHECK: %cmp = icmp eq i32 addrspace(3)* undef, %group.ptr.0
+define i1 @icmp_mismatch_flat_group_private_cmp_undef_swap(i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cmp = icmp eq i32* addrspacecast (i32 addrspace(5)* undef to i32*), %cast0
+  ret i1 %cmp
+}
+
+; TODO: Should be handled
+; CHECK-LABEL: @icmp_flat_flat_from_group_vector(
+; CHECK: %cmp = icmp eq <2 x i32*> %cast0, %cast1
+define <2 x i1> @icmp_flat_flat_from_group_vector(<2 x i32 addrspace(3)*> %group.ptr.0, <2 x i32 addrspace(3)*> %group.ptr.1) #0 {
+  %cast0 = addrspacecast <2 x i32 addrspace(3)*> %group.ptr.0 to <2 x i32*>
+  %cast1 = addrspacecast <2 x i32 addrspace(3)*> %group.ptr.1 to <2 x i32*>
+  %cmp = icmp eq <2 x i32*> %cast0, %cast1
+  ret <2 x i1> %cmp
+}
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-address-space.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-address-space.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-address-space.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-address-space.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,184 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+; Ports of most of test/CodeGen/NVPTX/access-non-generic.ll
+
+ at scalar = internal addrspace(3) global float 0.0, align 4
+ at array = internal addrspace(3) global [10 x float] zeroinitializer, align 4
+
+; CHECK-LABEL: @load_store_lds_f32(
+; CHECK: %tmp = load float, float addrspace(3)* @scalar, align 4
+; CHECK: call void @use(float %tmp)
+; CHECK: store float %v, float addrspace(3)* @scalar, align 4
+; CHECK: call void @llvm.amdgcn.s.barrier()
+; CHECK: %tmp2 = load float, float addrspace(3)* @scalar, align 4
+; CHECK: call void @use(float %tmp2)
+; CHECK: store float %v, float addrspace(3)* @scalar, align 4
+; CHECK: call void @llvm.amdgcn.s.barrier()
+; CHECK: %tmp3 = load float, float addrspace(3)* getelementptr inbounds ([10 x float], [10 x float] addrspace(3)* @array, i32 0, i32 5), align 4
+; CHECK: call void @use(float %tmp3)
+; CHECK: store float %v, float addrspace(3)* getelementptr inbounds ([10 x float], [10 x float] addrspace(3)* @array, i32 0, i32 5), align 4
+; CHECK: call void @llvm.amdgcn.s.barrier()
+; CHECK: %tmp4 = getelementptr inbounds [10 x float], [10 x float] addrspace(3)* @array, i32 0, i32 5
+; CHECK: %tmp5 = load float, float addrspace(3)* %tmp4, align 4
+; CHECK: call void @use(float %tmp5)
+; CHECK: store float %v, float addrspace(3)* %tmp4, align 4
+; CHECK: call void @llvm.amdgcn.s.barrier()
+; CHECK: %tmp7 = getelementptr inbounds [10 x float], [10 x float] addrspace(3)* @array, i32 0, i32 %i
+; CHECK: %tmp8 = load float, float addrspace(3)* %tmp7, align 4
+; CHECK: call void @use(float %tmp8)
+; CHECK: store float %v, float addrspace(3)* %tmp7, align 4
+; CHECK: call void @llvm.amdgcn.s.barrier()
+; CHECK: ret void
+define amdgpu_kernel void @load_store_lds_f32(i32 %i, float %v) #0 {
+bb:
+  %tmp = load float, float* addrspacecast (float addrspace(3)* @scalar to float*), align 4
+  call void @use(float %tmp)
+  store float %v, float* addrspacecast (float addrspace(3)* @scalar to float*), align 4
+  call void @llvm.amdgcn.s.barrier()
+  %tmp1 = addrspacecast float addrspace(3)* @scalar to float*
+  %tmp2 = load float, float* %tmp1, align 4
+  call void @use(float %tmp2)
+  store float %v, float* %tmp1, align 4
+  call void @llvm.amdgcn.s.barrier()
+  %tmp3 = load float, float* getelementptr inbounds ([10 x float], [10 x float]* addrspacecast ([10 x float] addrspace(3)* @array to [10 x float]*), i32 0, i32 5), align 4
+  call void @use(float %tmp3)
+  store float %v, float* getelementptr inbounds ([10 x float], [10 x float]* addrspacecast ([10 x float] addrspace(3)* @array to [10 x float]*), i32 0, i32 5), align 4
+  call void @llvm.amdgcn.s.barrier()
+  %tmp4 = getelementptr inbounds [10 x float], [10 x float]* addrspacecast ([10 x float] addrspace(3)* @array to [10 x float]*), i32 0, i32 5
+  %tmp5 = load float, float* %tmp4, align 4
+  call void @use(float %tmp5)
+  store float %v, float* %tmp4, align 4
+  call void @llvm.amdgcn.s.barrier()
+  %tmp6 = addrspacecast [10 x float] addrspace(3)* @array to [10 x float]*
+  %tmp7 = getelementptr inbounds [10 x float], [10 x float]* %tmp6, i32 0, i32 %i
+  %tmp8 = load float, float* %tmp7, align 4
+  call void @use(float %tmp8)
+  store float %v, float* %tmp7, align 4
+  call void @llvm.amdgcn.s.barrier()
+  ret void
+}
+
+; CHECK-LABEL: @constexpr_load_int_from_float_lds(
+; CHECK: %tmp = load i32, i32 addrspace(3)* bitcast (float addrspace(3)* @scalar to i32 addrspace(3)*), align 4
+define i32 @constexpr_load_int_from_float_lds() #0 {
+bb:
+  %tmp = load i32, i32* addrspacecast (i32 addrspace(3)* bitcast (float addrspace(3)* @scalar to i32 addrspace(3)*) to i32*), align 4
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: @load_int_from_global_float(
+; CHECK: %tmp1 = getelementptr float, float addrspace(1)* %input, i32 %i
+; CHECK: %tmp2 = getelementptr float, float addrspace(1)* %tmp1, i32 %j
+; CHECK: %tmp3 = bitcast float addrspace(1)* %tmp2 to i32 addrspace(1)*
+; CHECK: %tmp4 = load i32, i32 addrspace(1)* %tmp3
+; CHECK: ret i32 %tmp4
+define i32 @load_int_from_global_float(float addrspace(1)* %input, i32 %i, i32 %j) #0 {
+bb:
+  %tmp = addrspacecast float addrspace(1)* %input to float*
+  %tmp1 = getelementptr float, float* %tmp, i32 %i
+  %tmp2 = getelementptr float, float* %tmp1, i32 %j
+  %tmp3 = bitcast float* %tmp2 to i32*
+  %tmp4 = load i32, i32* %tmp3
+  ret i32 %tmp4
+}
+
+; CHECK-LABEL: @nested_const_expr(
+; CHECK: store i32 1, i32 addrspace(3)* bitcast (float addrspace(3)* getelementptr inbounds ([10 x float], [10 x float] addrspace(3)* @array, i64 0, i64 1) to i32 addrspace(3)*), align 4
+define amdgpu_kernel void @nested_const_expr() #0 {
+  store i32 1, i32* bitcast (float* getelementptr ([10 x float], [10 x float]* addrspacecast ([10 x float] addrspace(3)* @array to [10 x float]*), i64 0, i64 1) to i32*), align 4
+  ret void
+}
+
+; CHECK-LABEL: @rauw(
+; CHECK: %addr = getelementptr float, float addrspace(1)* %input, i64 10
+; CHECK-NEXT: %v = load float, float addrspace(1)* %addr
+; CHECK-NEXT: store float %v, float addrspace(1)* %addr
+; CHECK-NEXT: ret void
+define amdgpu_kernel void @rauw(float addrspace(1)* %input) #0 {
+bb:
+  %generic_input = addrspacecast float addrspace(1)* %input to float*
+  %addr = getelementptr float, float* %generic_input, i64 10
+  %v = load float, float* %addr
+  store float %v, float* %addr
+  ret void
+}
+
+; FIXME: Should be able to eliminate the cast inside the loop
+; CHECK-LABEL: @loop(
+
+; CHECK: %p = bitcast [10 x float] addrspace(3)* @array to float addrspace(3)*
+; CHECK: %end = getelementptr float, float addrspace(3)* %p, i64 10
+; CHECK: br label %loop
+
+; CHECK: loop:                                             ; preds = %loop, %entry
+; CHECK: %i = phi float addrspace(3)* [ %p, %entry ], [ %i2, %loop ]
+; CHECK: %v = load float, float addrspace(3)* %i
+; CHECK: call void @use(float %v)
+; CHECK: %i2 = getelementptr float, float addrspace(3)* %i, i64 1
+; CHECK: %exit_cond = icmp eq float addrspace(3)* %i2, %end
+
+; CHECK: br i1 %exit_cond, label %exit, label %loop
+define amdgpu_kernel void @loop() #0 {
+entry:
+  %p = addrspacecast [10 x float] addrspace(3)* @array to float*
+  %end = getelementptr float, float* %p, i64 10
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  %i = phi float* [ %p, %entry ], [ %i2, %loop ]
+  %v = load float, float* %i
+  call void @use(float %v)
+  %i2 = getelementptr float, float* %i, i64 1
+  %exit_cond = icmp eq float* %i2, %end
+  br i1 %exit_cond, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  ret void
+}
+
+ at generic_end = external addrspace(1) global float*
+
+; CHECK-LABEL: @loop_with_generic_bound(
+; CHECK: %p = bitcast [10 x float] addrspace(3)* @array to float addrspace(3)*
+; CHECK: %end = load float*, float* addrspace(1)* @generic_end
+; CHECK: br label %loop
+
+; CHECK: loop:
+; CHECK: %i = phi float addrspace(3)* [ %p, %entry ], [ %i2, %loop ]
+; CHECK: %v = load float, float addrspace(3)* %i
+; CHECK: call void @use(float %v)
+; CHECK: %i2 = getelementptr float, float addrspace(3)* %i, i64 1
+; CHECK: %0 = addrspacecast float addrspace(3)* %i2 to float*
+; CHECK: %exit_cond = icmp eq float* %0, %end
+; CHECK: br i1 %exit_cond, label %exit, label %loop
+define amdgpu_kernel void @loop_with_generic_bound() #0 {
+entry:
+  %p = addrspacecast [10 x float] addrspace(3)* @array to float*
+  %end = load float*, float* addrspace(1)* @generic_end
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  %i = phi float* [ %p, %entry ], [ %i2, %loop ]
+  %v = load float, float* %i
+  call void @use(float %v)
+  %i2 = getelementptr float, float* %i, i64 1
+  %exit_cond = icmp eq float* %i2, %end
+  br i1 %exit_cond, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  ret void
+}
+
+; CHECK-LABEL: @select_bug(
+; CHECK: %add.ptr157 = getelementptr inbounds i64, i64* undef, i64 select (i1 icmp ne (i32* inttoptr (i64 4873 to i32*), i32* null), i64 73, i64 93)
+; CHECK: %cmp169 = icmp uge i64* undef, %add.ptr157
+define void @select_bug() #0 {
+  %add.ptr157 = getelementptr inbounds i64, i64* undef, i64 select (i1 icmp ne (i32* inttoptr (i64 4873 to i32*), i32* null), i64 73, i64 93)
+  %cmp169 = icmp uge i64* undef, %add.ptr157
+  unreachable
+}
+
+declare void @llvm.amdgcn.s.barrier() #1
+declare void @use(float) #0
+
+attributes #0 = { nounwind }
+attributes #1 = { convergent nounwind }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-addrspacecast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-addrspacecast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-addrspacecast.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-addrspacecast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; Test that pure addrspacecast instructions not directly connected to
+; a memory operation are inferred.
+
+; CHECK-LABEL: @addrspacecast_gep_addrspacecast(
+; CHECK: %gep0 = getelementptr i32, i32 addrspace(3)* %ptr, i64 9
+; CHECK-NEXT: store i32 8, i32 addrspace(3)* %gep0, align 8
+; CHECK-NEXT: ret void
+define void @addrspacecast_gep_addrspacecast(i32 addrspace(3)* %ptr) {
+  %asc0 = addrspacecast i32 addrspace(3)* %ptr to i32*
+  %gep0 = getelementptr i32, i32* %asc0, i64 9
+  %asc1 = addrspacecast i32* %gep0 to i32 addrspace(3)*
+  store i32 8, i32 addrspace(3)* %asc1, align 8
+  ret void
+}
+
+; CHECK-LABEL: @addrspacecast_different_pointee_type(
+; CHECK: [[GEP:%.*]] = getelementptr i32, i32 addrspace(3)* %ptr, i64 9
+; CHECK: [[CAST:%.*]] = bitcast i32 addrspace(3)* [[GEP]] to i8 addrspace(3)*
+; CHECK-NEXT: store i8 8, i8 addrspace(3)* [[CAST]], align 8
+; CHECK-NEXT: ret void
+define void @addrspacecast_different_pointee_type(i32 addrspace(3)* %ptr) {
+  %asc0 = addrspacecast i32 addrspace(3)* %ptr to i32*
+  %gep0 = getelementptr i32, i32* %asc0, i64 9
+  %asc1 = addrspacecast i32* %gep0 to i8 addrspace(3)*
+  store i8 8, i8 addrspace(3)* %asc1, align 8
+  ret void
+}
+
+; CHECK-LABEL: @addrspacecast_to_memory(
+; CHECK: %gep0 = getelementptr i32, i32 addrspace(3)* %ptr, i64 9
+; CHECK-NEXT: store volatile i32 addrspace(3)* %gep0, i32 addrspace(3)* addrspace(1)* undef
+; CHECK-NEXT: ret void
+define void @addrspacecast_to_memory(i32 addrspace(3)* %ptr) {
+  %asc0 = addrspacecast i32 addrspace(3)* %ptr to i32*
+  %gep0 = getelementptr i32, i32* %asc0, i64 9
+  %asc1 = addrspacecast i32* %gep0 to i32 addrspace(3)*
+  store volatile i32 addrspace(3)* %asc1, i32 addrspace(3)* addrspace(1)* undef
+  ret void
+}
+
+; CHECK-LABEL: @multiuse_addrspacecast_gep_addrspacecast(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %ptr to i32*
+; CHECK-NEXT: store volatile i32* %1, i32* addrspace(1)* undef
+; CHECK-NEXT: %gep0 = getelementptr i32, i32 addrspace(3)* %ptr, i64 9
+; CHECK-NEXT: store i32 8, i32 addrspace(3)* %gep0, align 8
+; CHECK-NEXT: ret void
+define void @multiuse_addrspacecast_gep_addrspacecast(i32 addrspace(3)* %ptr) {
+  %asc0 = addrspacecast i32 addrspace(3)* %ptr to i32*
+  store volatile i32* %asc0, i32* addrspace(1)* undef
+  %gep0 = getelementptr i32, i32* %asc0, i64 9
+  %asc1 = addrspacecast i32* %gep0 to i32 addrspace(3)*
+  store i32 8, i32 addrspace(3)* %asc1, align 8
+  ret void
+}

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-getelementptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-getelementptr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-getelementptr.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/infer-getelementptr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,73 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; Test that pure GetElementPtr instructions not directly connected to
+; a memory operation are inferred.
+
+ at lds = internal unnamed_addr addrspace(3) global [648 x double] undef, align 8
+
+; CHECK-LABEL: @simplified_constexpr_gep_addrspacecast(
+; CHECK: %gep0 = getelementptr inbounds double, double addrspace(3)* getelementptr inbounds ([648 x double], [648 x double] addrspace(3)* @lds, i64 0, i64 384), i64 %idx0
+; CHECK-NEXT: store double 1.000000e+00, double addrspace(3)* %gep0, align 8
+define void @simplified_constexpr_gep_addrspacecast(i64 %idx0, i64 %idx1) {
+  %gep0 = getelementptr inbounds double, double* addrspacecast (double addrspace(3)* getelementptr inbounds ([648 x double], [648 x double] addrspace(3)* @lds, i64 0, i64 384) to double*), i64 %idx0
+  %asc = addrspacecast double* %gep0 to double addrspace(3)*
+  store double 1.000000e+00, double addrspace(3)* %asc, align 8
+  ret void
+}
+
+; CHECK-LABEL: @constexpr_gep_addrspacecast(
+; CHECK-NEXT: %gep0 = getelementptr inbounds double, double addrspace(3)* getelementptr inbounds ([648 x double], [648 x double] addrspace(3)* @lds, i64 0, i64 384), i64 %idx0
+; CHECK-NEXT: store double 1.000000e+00, double addrspace(3)* %gep0, align 8
+define void @constexpr_gep_addrspacecast(i64 %idx0, i64 %idx1) {
+  %gep0 = getelementptr inbounds double, double* getelementptr ([648 x double], [648 x double]* addrspacecast ([648 x double] addrspace(3)* @lds to [648 x double]*), i64 0, i64 384), i64 %idx0
+  %asc = addrspacecast double* %gep0 to double addrspace(3)*
+  store double 1.0, double addrspace(3)* %asc, align 8
+  ret void
+}
+
+; CHECK-LABEL: @constexpr_gep_gep_addrspacecast(
+; CHECK: %gep0 = getelementptr inbounds double, double addrspace(3)* getelementptr inbounds ([648 x double], [648 x double] addrspace(3)* @lds, i64 0, i64 384), i64 %idx0
+; CHECK-NEXT: %gep1 = getelementptr inbounds double, double addrspace(3)* %gep0, i64 %idx1
+; CHECK-NEXT: store double 1.000000e+00, double addrspace(3)* %gep1, align 8
+define void @constexpr_gep_gep_addrspacecast(i64 %idx0, i64 %idx1) {
+  %gep0 = getelementptr inbounds double, double* getelementptr ([648 x double], [648 x double]* addrspacecast ([648 x double] addrspace(3)* @lds to [648 x double]*), i64 0, i64 384), i64 %idx0
+  %gep1 = getelementptr inbounds double, double* %gep0, i64 %idx1
+  %asc = addrspacecast double* %gep1 to double addrspace(3)*
+  store double 1.0, double addrspace(3)* %asc, align 8
+  ret void
+}
+
+; Don't crash
+; CHECK-LABEL: @vector_gep(
+; CHECK: %cast = addrspacecast <4 x [1024 x i32] addrspace(3)*> %array to <4 x [1024 x i32]*>
+define amdgpu_kernel void @vector_gep(<4 x [1024 x i32] addrspace(3)*> %array) nounwind {
+  %cast = addrspacecast <4 x [1024 x i32] addrspace(3)*> %array to <4 x [1024 x i32]*>
+  %p = getelementptr [1024 x i32], <4 x [1024 x i32]*> %cast, <4 x i16> zeroinitializer, <4 x i16> <i16 16, i16 16, i16 16, i16 16>
+  %p0 = extractelement <4 x i32*> %p, i32 0
+  %p1 = extractelement <4 x i32*> %p, i32 1
+  %p2 = extractelement <4 x i32*> %p, i32 2
+  %p3 = extractelement <4 x i32*> %p, i32 3
+  store i32 99, i32* %p0
+  store i32 99, i32* %p1
+  store i32 99, i32* %p2
+  store i32 99, i32* %p3
+  ret void
+}
+
+; CHECK-LABEL: @repeated_constexpr_gep_addrspacecast(
+; CHECK-NEXT: %gep0 = getelementptr inbounds double, double addrspace(3)* getelementptr inbounds ([648 x double], [648 x double] addrspace(3)* @lds, i64 0, i64 384), i64 %idx0
+; CHECK-NEXT: store double 1.000000e+00, double addrspace(3)* %gep0, align 8
+; CHECK-NEXT: %gep1 = getelementptr inbounds double, double addrspace(3)* getelementptr inbounds ([648 x double], [648 x double] addrspace(3)* @lds, i64 0, i64 384), i64 %idx1
+; CHECK-NEXT: store double 1.000000e+00, double addrspace(3)* %gep1, align 8
+; CHECK-NEXT: ret void
+define void @repeated_constexpr_gep_addrspacecast(i64 %idx0, i64 %idx1) {
+  %gep0 = getelementptr inbounds double, double* getelementptr ([648 x double], [648 x double]* addrspacecast ([648 x double] addrspace(3)* @lds to [648 x double]*), i64 0, i64 384), i64 %idx0
+  %asc0 = addrspacecast double* %gep0 to double addrspace(3)*
+  store double 1.0, double addrspace(3)* %asc0, align 8
+
+  %gep1 = getelementptr inbounds double, double* getelementptr ([648 x double], [648 x double]* addrspacecast ([648 x double] addrspace(3)* @lds to [648 x double]*), i64 0, i64 384), i64 %idx1
+  %asc1 = addrspacecast double* %gep1 to double addrspace(3)*
+  store double 1.0, double addrspace(3)* %asc1, align 8
+
+  ret void
+}

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,137 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; CHECK-LABEL: @objectsize_group_to_flat_i32(
+; CHECK: %val = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* %group.ptr, i1 true, i1 false, i1 false)
+define i32 @objectsize_group_to_flat_i32(i8 addrspace(3)* %group.ptr) #0 {
+  %cast = addrspacecast i8 addrspace(3)* %group.ptr to i8*
+  %val = call i32 @llvm.objectsize.i32.p0i8(i8* %cast, i1 true, i1 false, i1 false)
+  ret i32 %val
+}
+
+; CHECK-LABEL: @objectsize_global_to_flat_i64(
+; CHECK: %val = call i64 @llvm.objectsize.i64.p3i8(i8 addrspace(3)* %global.ptr, i1 true, i1 false, i1 false)
+define i64 @objectsize_global_to_flat_i64(i8 addrspace(3)* %global.ptr) #0 {
+  %cast = addrspacecast i8 addrspace(3)* %global.ptr to i8*
+  %val = call i64 @llvm.objectsize.i64.p0i8(i8* %cast, i1 true, i1 false, i1 false)
+  ret i64 %val
+}
+
+; CHECK-LABEL: @atomicinc_global_to_flat_i32(
+; CHECK: call i32 @llvm.amdgcn.atomic.inc.i32.p1i32(i32 addrspace(1)* %global.ptr, i32 %y, i32 0, i32 0, i1 false)
+define i32 @atomicinc_global_to_flat_i32(i32 addrspace(1)* %global.ptr, i32 %y) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = call i32 @llvm.amdgcn.atomic.inc.i32.p0i32(i32* %cast, i32 %y, i32 0, i32 0, i1 false)
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @atomicinc_group_to_flat_i32(
+; CHECK: %ret = call i32 @llvm.amdgcn.atomic.inc.i32.p3i32(i32 addrspace(3)* %group.ptr, i32 %y, i32 0, i32 0, i1 false)
+define i32 @atomicinc_group_to_flat_i32(i32 addrspace(3)* %group.ptr, i32 %y) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = call i32 @llvm.amdgcn.atomic.inc.i32.p0i32(i32* %cast, i32 %y, i32 0, i32 0, i1 false)
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @atomicinc_global_to_flat_i64(
+; CHECK: call i64 @llvm.amdgcn.atomic.inc.i64.p1i64(i64 addrspace(1)* %global.ptr, i64 %y, i32 0, i32 0, i1 false)
+define i64 @atomicinc_global_to_flat_i64(i64 addrspace(1)* %global.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(1)* %global.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.inc.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 false)
+  ret i64 %ret
+}
+
+; CHECK-LABEL: @atomicinc_group_to_flat_i64(
+; CHECK: call i64 @llvm.amdgcn.atomic.inc.i64.p3i64(i64 addrspace(3)* %group.ptr, i64 %y, i32 0, i32 0, i1 false)
+define i64 @atomicinc_group_to_flat_i64(i64 addrspace(3)* %group.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(3)* %group.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.inc.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 false)
+  ret i64 %ret
+}
+
+; CHECK-LABEL: @atomicdec_global_to_flat_i32(
+; CHECK: call i32 @llvm.amdgcn.atomic.dec.i32.p1i32(i32 addrspace(1)* %global.ptr, i32 %val, i32 0, i32 0, i1 false)
+define i32 @atomicdec_global_to_flat_i32(i32 addrspace(1)* %global.ptr, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* %cast, i32 %val, i32 0, i32 0, i1 false)
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @atomicdec_group_to_flat_i32(
+; CHECK: %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p3i32(i32 addrspace(3)* %group.ptr, i32 %val, i32 0, i32 0, i1 false)
+define i32 @atomicdec_group_to_flat_i32(i32 addrspace(3)* %group.ptr, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* %cast, i32 %val, i32 0, i32 0, i1 false)
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @atomicdec_global_to_flat_i64(
+; CHECK: call i64 @llvm.amdgcn.atomic.dec.i64.p1i64(i64 addrspace(1)* %global.ptr, i64 %y, i32 0, i32 0, i1 false)
+define i64 @atomicdec_global_to_flat_i64(i64 addrspace(1)* %global.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(1)* %global.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 false)
+  ret i64 %ret
+}
+
+; CHECK-LABEL: @atomicdec_group_to_flat_i64(
+; CHECK: call i64 @llvm.amdgcn.atomic.dec.i64.p3i64(i64 addrspace(3)* %group.ptr, i64 %y, i32 0, i32 0, i1 false
+define i64 @atomicdec_group_to_flat_i64(i64 addrspace(3)* %group.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(3)* %group.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 false)
+  ret i64 %ret
+}
+
+; CHECK-LABEL: @volatile_atomicinc_group_to_flat_i64(
+; CHECK-NEXT: %1 = addrspacecast i64 addrspace(3)* %group.ptr to i64*
+; CHECK-NEXT: %ret = call i64 @llvm.amdgcn.atomic.inc.i64.p0i64(i64* %1, i64 %y, i32 0, i32 0, i1 true)
+define i64 @volatile_atomicinc_group_to_flat_i64(i64 addrspace(3)* %group.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(3)* %group.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.inc.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 true)
+  ret i64 %ret
+}
+
+; CHECK-LABEL: @volatile_atomicdec_global_to_flat_i32(
+; CHECK-NEXT: %1 = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+; CHECK-NEXT: %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* %1, i32 %val, i32 0, i32 0, i1 true)
+define i32 @volatile_atomicdec_global_to_flat_i32(i32 addrspace(1)* %global.ptr, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* %cast, i32 %val, i32 0, i32 0, i1 true)
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @volatile_atomicdec_group_to_flat_i32(
+; CHECK-NEXT: %1 = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+; CHECK-NEXT: %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* %1, i32 %val, i32 0, i32 0, i1 true)
+define i32 @volatile_atomicdec_group_to_flat_i32(i32 addrspace(3)* %group.ptr, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = call i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* %cast, i32 %val, i32 0, i32 0, i1 true)
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @volatile_atomicdec_global_to_flat_i64(
+; CHECK-NEXT: %1 = addrspacecast i64 addrspace(1)* %global.ptr to i64*
+; CHECK-NEXT: %ret = call i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* %1, i64 %y, i32 0, i32 0, i1 true)
+define i64 @volatile_atomicdec_global_to_flat_i64(i64 addrspace(1)* %global.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(1)* %global.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 true)
+  ret i64 %ret
+}
+
+; CHECK-LABEL: @volatile_atomicdec_group_to_flat_i64(
+; CHECK-NEXT: %1 = addrspacecast i64 addrspace(3)* %group.ptr to i64*
+; CHECK-NEXT: %ret = call i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* %1, i64 %y, i32 0, i32 0, i1 true)
+define i64 @volatile_atomicdec_group_to_flat_i64(i64 addrspace(3)* %group.ptr, i64 %y) #0 {
+  %cast = addrspacecast i64 addrspace(3)* %group.ptr to i64*
+  %ret = call i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* %cast, i64 %y, i32 0, i32 0, i1 true)
+  ret i64 %ret
+}
+
+declare i32 @llvm.objectsize.i32.p0i8(i8*, i1, i1, i1) #1
+declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) #1
+declare i32 @llvm.amdgcn.atomic.inc.i32.p0i32(i32* nocapture, i32, i32, i32, i1) #2
+declare i64 @llvm.amdgcn.atomic.inc.i64.p0i64(i64* nocapture, i64, i32, i32, i1) #2
+declare i32 @llvm.amdgcn.atomic.dec.i32.p0i32(i32* nocapture, i32, i32, i32, i1) #2
+declare i64 @llvm.amdgcn.atomic.dec.i64.p0i64(i64* nocapture, i64, i32, i32, i1) #2
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind argmemonly }

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

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,134 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; CHECK-LABEL: @memset_group_to_flat(
+; CHECK: call void @llvm.memset.p3i8.i64(i8 addrspace(3)* align 4 %group.ptr, i8 4, i64 32, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memset_group_to_flat(i8 addrspace(3)* %group.ptr, i32 %y) #0 {
+  %cast = addrspacecast i8 addrspace(3)* %group.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 4 %cast, i8 4, i64 32, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memset_global_to_flat(
+; CHECK: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 %global.ptr, i8 4, i64 32, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memset_global_to_flat(i8 addrspace(1)* %global.ptr, i32 %y) #0 {
+  %cast = addrspacecast i8 addrspace(1)* %global.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 4 %cast, i8 4, i64 32, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memset_group_to_flat_no_md(
+; CHECK: call void @llvm.memset.p3i8.i64(i8 addrspace(3)* align 4 %group.ptr, i8 4, i64 %size, i1 false){{$}}
+define amdgpu_kernel void @memset_group_to_flat_no_md(i8 addrspace(3)* %group.ptr, i64 %size) #0 {
+  %cast = addrspacecast i8 addrspace(3)* %group.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 4 %cast, i8 4, i64 %size, i1 false)
+  ret void
+}
+
+; CHECK-LABEL: @memset_global_to_flat_no_md(
+; CHECK: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 %global.ptr, i8 4, i64 %size, i1 false){{$}}
+define amdgpu_kernel void @memset_global_to_flat_no_md(i8 addrspace(1)* %global.ptr, i64 %size) #0 {
+  %cast = addrspacecast i8 addrspace(1)* %global.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 4 %cast, i8 4, i64 %size, i1 false)
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_flat_to_flat_replace_src_with_group(
+; CHECK: call void @llvm.memcpy.p0i8.p3i8.i64(i8* align 4 %dest, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memcpy_flat_to_flat_replace_src_with_group(i8* %dest, i8 addrspace(3)* %src.group.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %dest, i8* align 4 %cast.src, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_flat_to_flat_replace_dest_with_group(
+; CHECK: call void @llvm.memcpy.p3i8.p0i8.i64(i8 addrspace(3)* align 4 %dest.group.ptr, i8* align 4 %src.ptr, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memcpy_flat_to_flat_replace_dest_with_group(i8 addrspace(3)* %dest.group.ptr, i8* %src.ptr, i64 %size) #0 {
+  %cast.dest = addrspacecast i8 addrspace(3)* %dest.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %cast.dest, i8* align 4 %src.ptr, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_flat_to_flat_replace_dest_src_with_group(
+; CHECK: call void @llvm.memcpy.p3i8.p3i8.i64(i8 addrspace(3)* align 4 %src.group.ptr, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memcpy_flat_to_flat_replace_dest_src_with_group(i8 addrspace(3)* %dest.group.ptr, i8 addrspace(3)* %src.group.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  %cast.dest = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %cast.dest, i8* align 4 %cast.src, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_flat_to_flat_replace_dest_group_src_global(
+; CHECK: call void @llvm.memcpy.p3i8.p1i8.i64(i8 addrspace(3)* align 4 %dest.group.ptr, i8 addrspace(1)* align 4 %src.global.ptr, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memcpy_flat_to_flat_replace_dest_group_src_global(i8 addrspace(3)* %dest.group.ptr, i8 addrspace(1)* %src.global.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(1)* %src.global.ptr to i8*
+  %cast.dest = addrspacecast i8 addrspace(3)* %dest.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %cast.dest, i8* align 4 %cast.src, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_group_to_flat_replace_dest_global(
+; CHECK: call void @llvm.memcpy.p1i8.p3i8.i32(i8 addrspace(1)* align 4 %dest.global.ptr, i8 addrspace(3)* align 4 %src.group.ptr, i32 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memcpy_group_to_flat_replace_dest_global(i8 addrspace(1)* %dest.global.ptr, i8 addrspace(3)* %src.group.ptr, i32 %size) #0 {
+  %cast.dest = addrspacecast i8 addrspace(1)* %dest.global.ptr to i8*
+  call void @llvm.memcpy.p0i8.p3i8.i32(i8* align 4 %cast.dest, i8 addrspace(3)* align 4 %src.group.ptr, i32 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_flat_to_flat_replace_src_with_group_tbaa_struct(
+; CHECK: call void @llvm.memcpy.p0i8.p3i8.i64(i8* align 4 %dest, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false), !tbaa.struct !7
+define amdgpu_kernel void @memcpy_flat_to_flat_replace_src_with_group_tbaa_struct(i8* %dest, i8 addrspace(3)* %src.group.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %dest, i8* align 4 %cast.src, i64 %size, i1 false), !tbaa.struct !7
+  ret void
+}
+
+; CHECK-LABEL: @memcpy_flat_to_flat_replace_src_with_group_no_md(
+; CHECK: call void @llvm.memcpy.p0i8.p3i8.i64(i8* align 4 %dest, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false){{$}}
+define amdgpu_kernel void @memcpy_flat_to_flat_replace_src_with_group_no_md(i8* %dest, i8 addrspace(3)* %src.group.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %dest, i8* align 4 %cast.src, i64 %size, i1 false)
+  ret void
+}
+
+; CHECK-LABEL: @multiple_memcpy_flat_to_flat_replace_src_with_group_no_md(
+; CHECK: call void @llvm.memcpy.p0i8.p3i8.i64(i8* align 4 %dest0, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false){{$}}
+; CHECK: call void @llvm.memcpy.p0i8.p3i8.i64(i8* align 4 %dest1, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false){{$}}
+define amdgpu_kernel void @multiple_memcpy_flat_to_flat_replace_src_with_group_no_md(i8* %dest0, i8* %dest1, i8 addrspace(3)* %src.group.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %dest0, i8* align 4 %cast.src, i64 %size, i1 false)
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %dest1, i8* align 4 %cast.src, i64 %size, i1 false)
+  ret void
+}
+
+; Check for iterator problems if the pointer has 2 uses in the same call
+; CHECK-LABEL: @memcpy_group_flat_to_flat_self(
+; CHECK: call void @llvm.memcpy.p3i8.p3i8.i64(i8 addrspace(3)* align 4 %group.ptr, i8 addrspace(3)* align 4 %group.ptr, i64 32, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memcpy_group_flat_to_flat_self(i8 addrspace(3)* %group.ptr) #0 {
+  %cast = addrspacecast i8 addrspace(3)* %group.ptr to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8* align 4 %cast, i8* align 4 %cast, i64 32, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+; CHECK-LABEL: @memmove_flat_to_flat_replace_src_with_group(
+; CHECK: call void @llvm.memmove.p0i8.p3i8.i64(i8* align 4 %dest, i8 addrspace(3)* align 4 %src.group.ptr, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+define amdgpu_kernel void @memmove_flat_to_flat_replace_src_with_group(i8* %dest, i8 addrspace(3)* %src.group.ptr, i64 %size) #0 {
+  %cast.src = addrspacecast i8 addrspace(3)* %src.group.ptr to i8*
+  call void @llvm.memmove.p4i8.p0i8.i64(i8* align 4 %dest, i8* align 4 %cast.src, i64 %size, i1 false), !tbaa !0, !alias.scope !3, !noalias !4
+  ret void
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #1
+declare void @llvm.memcpy.p4i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #1
+declare void @llvm.memcpy.p0i8.p3i8.i32(i8* nocapture writeonly, i8 addrspace(3)* nocapture readonly, i32, i1) #1
+declare void @llvm.memmove.p4i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
+
+!0 = !{!1, !1, i64 0}
+!1 = !{!"A", !2}
+!2 = !{!"tbaa root"}
+!3 = !{!"B", !2}
+!4 = !{!5}
+!5 = distinct !{!5, !6, !"some scope"}
+!6 = distinct !{!6, !"some domain"}
+!7 = !{i64 0, i64 8, null}

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/old-pass-regressions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/old-pass-regressions.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/old-pass-regressions.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/old-pass-regressions.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,143 @@
+; RUN: opt -data-layout=A5 -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; Regression tests from old HSAIL addrspacecast optimization pass
+
+ at data = internal addrspace(1) global [100 x double] [double 0.00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 7.000000e-01, double 8.000000e-01, double 9.000000e-01, double 1.00, double 1.10, double 1.20, double 1.30, double 1.40, double 1.50, double 1.60, double 1.70, double 1.80, double 1.90, double 2.00, double 2.10, double 2.20, double 2.30, double 2.40, double 2.50, double 2.60, double 2.70, double 2.80, double 2.90, double 3.00, double 3.10, double 3.20, double 3.30, double 3.40, double 3.50, double 3.60, double 3.70, double 3.80, double 3.90, double 4.00, double 4.10, double 4.20, double 4.30, double 4.40, double 4.50, double 4.60, double 4.70, double 4.80, double 4.90, double 5.00, double 5.10, double 5.20, double 5.30, double 5.40, double 5.50, double 5.60, double 5.70, double 5.80, double 5.90, double 6.00, double 6.10, double 6.20, double 6.30, double 6.40, double 6.50, double 6.60, double 6.70, double 6.80, double 6.90, double 7.00, double 7.10, double 7.20, double 7.30, double 7.40, double 7.50, double 7.60, double 7.70, double 7.80, double 7.90, double 8.00, double 8.10, double 8.20, double 8.30, double 8.40, double 8.50, double 8.60, double 8.70, double 8.80, double 8.90, double 9.00, double 9.10, double 9.20, double 9.30, double 9.40, double 9.50, double 9.60, double 9.70, double 9.80, double 9.90], align 8
+
+
+; Should generate flat load
+
+; CHECK-LABEL: @generic_address_bitcast_const(
+; CHECK: %vecload1 = load <2 x double>, <2 x double> addrspace(1)* bitcast (double addrspace(1)* getelementptr inbounds ([100 x double], [100 x double] addrspace(1)* @data, i64 0, i64 4) to <2 x double> addrspace(1)*), align 8
+define amdgpu_kernel void @generic_address_bitcast_const(i64 %arg0, i32 addrspace(1)* nocapture %results) #0 {
+entry:
+  %tmp1 = call i32 @llvm.amdgcn.workitem.id.x()
+  %tmp2 = zext i32 %tmp1 to i64
+  %tmp3 = add i64 %tmp2, %arg0
+  %vecload1 = load <2 x double>, <2 x double>* bitcast (double* getelementptr ([100 x double], [100 x double]* addrspacecast ([100 x double] addrspace(1)* @data to [100 x double]*), i64 0, i64 4) to <2 x double>*), align 8
+  %cmp = fcmp ord <2 x double> %vecload1, zeroinitializer
+  %sext = sext <2 x i1> %cmp to <2 x i64>
+  %tmp4 = extractelement <2 x i64> %sext, i64 0
+  %tmp5 = extractelement <2 x i64> %sext, i64 1
+  %tmp6 = and i64 %tmp4, %tmp5
+  %tmp7 = lshr i64 %tmp6, 63
+  %tmp8 = trunc i64 %tmp7 to i32
+  %idxprom = and i64 %tmp3, 4294967295
+  %arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %results, i64 %idxprom
+  store i32 %tmp8, i32 addrspace(1)* %arrayidx, align 4
+  ret void
+}
+
+ at generic_address_bug9749.val = internal addrspace(1) global float 0.0, align 4
+
+declare i32 @_Z9get_fencePv(i8*)
+%opencl.pipe_t = type opaque
+
+; This is a compile time assert bug, but we still want to check optimization
+; is performed to generate ld_global.
+; CHECK-LABEL: @generic_address_pipe_bug9673(
+; CHECK: %tmp1 = bitcast %opencl.pipe_t addrspace(3)* %in_pipe to i32 addrspace(3)*
+; CHECK: %add.ptr = getelementptr inbounds i32, i32 addrspace(3)* %tmp1, i32 2
+; CHECK: %tmp2 = load i32, i32 addrspace(3)* %add.ptr, align 4
+define amdgpu_kernel void @generic_address_pipe_bug9673(%opencl.pipe_t addrspace(3)* nocapture %in_pipe, i32 addrspace(1)* nocapture %dst) #0 {
+entry:
+  %tmp = call i32 @llvm.amdgcn.workitem.id.x()
+  %tmp1 = bitcast %opencl.pipe_t addrspace(3)* %in_pipe to i32 addrspace(3)*
+  %add.ptr = getelementptr inbounds i32, i32 addrspace(3)* %tmp1, i32 2
+  %tmp2 = load i32, i32 addrspace(3)* %add.ptr, align 4
+  %arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %dst, i32 %tmp
+  store i32 %tmp2, i32 addrspace(1)* %arrayidx, align 4
+  ret void
+}
+
+; Should generate flat load
+; CHECK-LABEL: @generic_address_bug9749(
+; CHECK: br i1
+; CHECK: load float, float*
+; CHECK: br label
+define amdgpu_kernel void @generic_address_bug9749(i32 addrspace(1)* nocapture %results) #0 {
+entry:
+  %ptr = alloca float*, align 8, addrspace(5)
+  %tmp = call i32 @llvm.amdgcn.workitem.id.x()
+  %tmp1 = zext i32 %tmp to i64
+  store float 0x3FB99999A0000000, float addrspace(1)* @generic_address_bug9749.val, align 4
+  store volatile float* addrspacecast (float addrspace(1)* @generic_address_bug9749.val to float*), float* addrspace(5)* %ptr, align 8
+  %tmp2 = load volatile float*, float* addrspace(5)* %ptr, align 8
+  %tmp3 = load float, float addrspace(1)* @generic_address_bug9749.val, align 4
+  %tmp4 = bitcast float* %tmp2 to i8*
+  %call.i = call i32 @_Z9get_fencePv(i8* %tmp4) #1
+  %switch.i.i = icmp ult i32 %call.i, 4
+  br i1 %switch.i.i, label %if.end.i, label %helperFunction.exit
+
+if.end.i:                                         ; preds = %entry
+  %tmp5 = load float, float* %tmp2, align 4
+  %not.cmp.i = fcmp oeq float %tmp5, %tmp3
+  %phitmp = zext i1 %not.cmp.i to i32
+  br label %helperFunction.exit
+
+helperFunction.exit:                              ; preds = %if.end.i, %entry
+  %retval.0.i = phi i32 [ 0, %entry ], [ %phitmp, %if.end.i ]
+  %arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %results, i64 %tmp1
+  store i32 %retval.0.i, i32 addrspace(1)* %arrayidx, align 4
+  ret void
+}
+
+; CHECK-LABEL: @generic_address_opt_phi_bug9776_simple_phi_kernel(
+; CHECK: phi i32 addrspace(3)*
+; CHECK: store i32 %i.03, i32 addrspace(3)* %
+define amdgpu_kernel void @generic_address_opt_phi_bug9776_simple_phi_kernel(i32 addrspace(3)* nocapture %in, i32 %numElems) #0 {
+entry:
+  %cmp1 = icmp eq i32 %numElems, 0
+  br i1 %cmp1, label %for.end, label %for.body.lr.ph
+
+for.body.lr.ph:                                   ; preds = %entry
+  %tmp = addrspacecast i32 addrspace(3)* %in to i32*
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %for.body.lr.ph
+  %i.03 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
+  %ptr.02 = phi i32* [ %tmp, %for.body.lr.ph ], [ %add.ptr, %for.body ]
+  store i32 %i.03, i32* %ptr.02, align 4
+  %add.ptr = getelementptr inbounds i32, i32* %ptr.02, i64 4
+  %inc = add nuw i32 %i.03, 1
+  %exitcond = icmp eq i32 %inc, %numElems
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %entry
+  ret void
+}
+
+; CHECK-LABEL: @generic_address_bug9899(
+; CHECK: %vecload = load <2 x i32>, <2 x i32> addrspace(3)*
+; CHECK: store <2 x i32> %tmp16, <2 x i32> addrspace(3)*
+define amdgpu_kernel void @generic_address_bug9899(i64 %arg0, i32 addrspace(3)* nocapture %sourceA, i32 addrspace(3)* nocapture %destValues) #0 {
+entry:
+  %tmp1 = call i32 @llvm.amdgcn.workitem.id.x()
+  %tmp2 = zext i32 %tmp1 to i64
+  %tmp3 = add i64 %tmp2, %arg0
+  %sext = shl i64 %tmp3, 32
+  %tmp4 = addrspacecast i32 addrspace(3)* %destValues to i32*
+  %tmp5 = addrspacecast i32 addrspace(3)* %sourceA to i32*
+  %tmp6 = ashr exact i64 %sext, 31
+  %tmp7 = getelementptr inbounds i32, i32* %tmp5, i64 %tmp6
+  %arrayidx_v4 = bitcast i32* %tmp7 to <2 x i32>*
+  %vecload = load <2 x i32>, <2 x i32>* %arrayidx_v4, align 4
+  %tmp8 = extractelement <2 x i32> %vecload, i32 0
+  %tmp9 = extractelement <2 x i32> %vecload, i32 1
+  %tmp10 = icmp eq i32 %tmp8, 0
+  %tmp11 = select i1 %tmp10, i32 32, i32 %tmp8
+  %tmp12 = icmp eq i32 %tmp9, 0
+  %tmp13 = select i1 %tmp12, i32 32, i32 %tmp9
+  %tmp14 = getelementptr inbounds i32, i32* %tmp4, i64 %tmp6
+  %tmp15 = insertelement <2 x i32> undef, i32 %tmp11, i32 0
+  %tmp16 = insertelement <2 x i32> %tmp15, i32 %tmp13, i32 1
+  %arrayidx_v41 = bitcast i32* %tmp14 to <2 x i32>*
+  store <2 x i32> %tmp16, <2 x i32>* %arrayidx_v41, align 4
+  ret void
+}
+
+declare i32 @llvm.amdgcn.workitem.id.x() #2
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readonly }
+attributes #2 = { nounwind readnone }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/select.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/select.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/select.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,264 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; Instcombine pulls the addrspacecast out of the select, make sure
+;  this doesn't do something insane on non-canonical IR.
+
+; CHECK-LABEL: @return_select_group_flat(
+; CHECK-NEXT: %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK-NEXT: %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+; CHECK-NEXT: %select = select i1 %c, i32* %cast0, i32* %cast1
+; CHECK-NEXT: ret i32* %select
+define i32* @return_select_group_flat(i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* %group.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+  %select = select i1 %c, i32* %cast0, i32* %cast1
+  ret i32* %select
+}
+
+; CHECK-LABEL: @store_select_group_flat(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* %group.ptr.1
+; CHECK: store i32 -1, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat(i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* %group.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+  %select = select i1 %c, i32* %cast0, i32* %cast1
+  store i32 -1, i32* %select
+  ret void
+}
+
+; Make sure metadata is preserved
+; CHECK-LABEL: @load_select_group_flat_md(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* %group.ptr.1, !prof !0
+; CHECK: %load = load i32, i32 addrspace(3)* %select
+define i32 @load_select_group_flat_md(i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* %group.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cast1 = addrspacecast i32 addrspace(3)* %group.ptr.1 to i32*
+  %select = select i1 %c, i32* %cast0, i32* %cast1, !prof !0
+  %load = load i32, i32* %select
+  ret i32 %load
+}
+
+; CHECK-LABEL: @store_select_mismatch_group_private_flat(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %2 = addrspacecast i32 addrspace(5)* %private.ptr.1 to i32*
+; CHECK: %select = select i1 %c, i32* %1, i32* %2
+; CHECK: store i32 -1, i32* %select
+define amdgpu_kernel void @store_select_mismatch_group_private_flat(i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(5)* %private.ptr.1) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %cast1 = addrspacecast i32 addrspace(5)* %private.ptr.1 to i32*
+  %select = select i1 %c, i32* %cast0, i32* %cast1
+  store i32 -1, i32* %select
+  ret void
+}
+
+ at lds0 = internal addrspace(3) global i32 123, align 4
+ at lds1 = internal addrspace(3) global i32 456, align 4
+
+; CHECK-LABEL: @constexpr_select_group_flat(
+; CHECK: %tmp = load i32, i32 addrspace(3)* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32 addrspace(3)* @lds0, i32 addrspace(3)* @lds1)
+define i32 @constexpr_select_group_flat() #0 {
+bb:
+  %tmp = load i32, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), i32* addrspacecast (i32 addrspace(3)* @lds1 to i32*))
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: @constexpr_select_group_global_flat_mismatch(
+; CHECK: %tmp = load i32, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), i32* addrspacecast (i32 addrspace(1)* @global0 to i32*))
+define i32 @constexpr_select_group_global_flat_mismatch() #0 {
+bb:
+  %tmp = load i32, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), i32* addrspacecast (i32 addrspace(1)* @global0 to i32*))
+  ret i32 %tmp
+}
+
+; CHECK-LABEL: @store_select_group_flat_null(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* addrspacecast (i32* null to i32 addrspace(3)*)
+; CHECK: store i32 -1, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_null(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* null
+  store i32 -1, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_flat_null_swap(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* addrspacecast (i32* null to i32 addrspace(3)*), i32 addrspace(3)* %group.ptr.0
+; CHECK: store i32 -1, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_null_swap(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* null, i32* %cast0
+  store i32 -1, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_flat_undef(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* undef
+; CHECK: store i32 -1, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_undef(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* undef
+  store i32 -1, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_flat_undef_swap(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* undef, i32 addrspace(3)* %group.ptr.0
+; CHECK: store i32 -1, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_undef_swap(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* undef, i32* %cast0
+  store i32 -1, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_gep_group_flat_null(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* addrspacecast (i32* null to i32 addrspace(3)*)
+; CHECK: %gep = getelementptr i32, i32 addrspace(3)* %select, i64 16
+; CHECK: store i32 -1, i32 addrspace(3)* %gep
+define amdgpu_kernel void @store_select_gep_group_flat_null(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* null
+  %gep = getelementptr i32, i32* %select, i64 16
+  store i32 -1, i32* %gep
+  ret void
+}
+
+ at global0 = internal addrspace(1) global i32 123, align 4
+
+; CHECK-LABEL: @store_select_group_flat_constexpr(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* @lds1
+; CHECK: store i32 7, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_constexpr(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* addrspacecast (i32 addrspace(3)* @lds1 to i32*)
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_flat_inttoptr_flat(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* addrspacecast (i32* inttoptr (i64 12345 to i32*) to i32 addrspace(3)*)
+; CHECK: store i32 7, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_inttoptr_flat(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* inttoptr (i64 12345 to i32*)
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_flat_inttoptr_group(
+; CHECK: %select = select i1 %c, i32 addrspace(3)* %group.ptr.0, i32 addrspace(3)* inttoptr (i32 400 to i32 addrspace(3)*)
+; CHECK-NEXT: store i32 7, i32 addrspace(3)* %select
+define amdgpu_kernel void @store_select_group_flat_inttoptr_group(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* addrspacecast (i32 addrspace(3)* inttoptr (i32 400 to i32 addrspace(3)*) to i32*)
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_flat_constexpr(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %select = select i1 %c, i32* %1, i32* addrspacecast (i32 addrspace(1)* @global0 to i32*)
+; CHECK: store i32 7, i32* %select
+define amdgpu_kernel void @store_select_group_global_mismatch_flat_constexpr(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* addrspacecast (i32 addrspace(1)* @global0 to i32*)
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_flat_constexpr_swap(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %select = select i1 %c, i32* addrspacecast (i32 addrspace(1)* @global0 to i32*), i32* %1
+; CHECK: store i32 7, i32* %select
+define amdgpu_kernel void @store_select_group_global_mismatch_flat_constexpr_swap(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* addrspacecast (i32 addrspace(1)* @global0 to i32*), i32* %cast0
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_null_null(
+; CHECK: %select = select i1 %c, i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)
+; CHECK: store i32 7, i32* %select
+define amdgpu_kernel void @store_select_group_global_mismatch_null_null(i1 %c) #0 {
+  %select = select i1 %c, i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_null_null_constexpr(
+; CHECK: store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+define amdgpu_kernel void @store_select_group_global_mismatch_null_null_constexpr() #0 {
+  store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_gv_null_constexpr(
+; CHECK: store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+define amdgpu_kernel void @store_select_group_global_mismatch_gv_null_constexpr() #0 {
+  store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* @lds0 to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_null_gv_constexpr(
+; CHECK: store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* @global0 to i32*)), align 4
+define amdgpu_kernel void @store_select_group_global_mismatch_null_gv_constexpr() #0 {
+  store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* @global0 to i32*)), align 4
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_inttoptr_null_constexpr(
+; CHECK: store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* inttoptr (i64 123 to i32 addrspace(3)*) to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+define amdgpu_kernel void @store_select_group_global_mismatch_inttoptr_null_constexpr() #0 {
+  store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* inttoptr (i64 123 to i32 addrspace(3)*) to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_inttoptr_flat_null_constexpr(
+; CHECK: store i32 7, i32 addrspace(1)* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32 addrspace(1)* addrspacecast (i32* inttoptr (i64 123 to i32*) to i32 addrspace(1)*), i32 addrspace(1)* null), align 4
+define amdgpu_kernel void @store_select_group_global_mismatch_inttoptr_flat_null_constexpr() #0 {
+  store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* inttoptr (i64 123 to i32*), i32* addrspacecast (i32 addrspace(1)* null to i32*)), align 4
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_global_mismatch_undef_undef_constexpr(
+; CHECK: store i32 7, i32 addrspace(3)* null
+define amdgpu_kernel void @store_select_group_global_mismatch_undef_undef_constexpr() #0 {
+  store i32 7, i32* select (i1 icmp eq (i32 ptrtoint (i32 addrspace(3)* @lds1 to i32), i32 4), i32* addrspacecast (i32 addrspace(3)* null to i32*), i32* addrspacecast (i32 addrspace(1)* undef to i32*)), align 4
+  ret void
+}
+
+ at lds2 = external addrspace(3) global [1024 x i32], align 4
+
+; CHECK-LABEL: @store_select_group_constexpr_ptrtoint(
+; CHECK: %1 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+; CHECK: %select = select i1 %c, i32* %1, i32* addrspacecast (i32 addrspace(1)* inttoptr (i32 add (i32 ptrtoint ([1024 x i32] addrspace(3)* @lds2 to i32), i32 124) to i32 addrspace(1)*) to i32*)
+; CHECK: store i32 7, i32* %select
+define amdgpu_kernel void @store_select_group_constexpr_ptrtoint(i1 %c, i32 addrspace(3)* %group.ptr.0) #0 {
+  %cast0 = addrspacecast i32 addrspace(3)* %group.ptr.0 to i32*
+  %select = select i1 %c, i32* %cast0, i32* addrspacecast (i32 addrspace(1)* inttoptr (i32 add (i32 ptrtoint ([1024 x i32] addrspace(3)* @lds2 to i32), i32 124) to i32 addrspace(1)*) to i32*)
+  store i32 7, i32* %select
+  ret void
+}
+
+; CHECK-LABEL: @store_select_group_flat_vector(
+; CHECK: %cast0 = addrspacecast <2 x i32 addrspace(3)*> %group.ptr.0 to <2 x i32*>
+; CHECK: %cast1 = addrspacecast <2 x i32 addrspace(3)*> %group.ptr.1 to <2 x i32*>
+; CHECK: %select = select i1 %c, <2 x i32*> %cast0, <2 x i32*> %cast1
+; CHECK: %extract0 = extractelement <2 x i32*> %select, i32 0
+; CHECK: %extract1 = extractelement <2 x i32*> %select, i32 1
+; CHECK: store i32 -1, i32* %extract0
+; CHECK: store i32 -2, i32* %extract1
+define amdgpu_kernel void @store_select_group_flat_vector(i1 %c, <2 x i32 addrspace(3)*> %group.ptr.0, <2 x i32 addrspace(3)*> %group.ptr.1) #0 {
+  %cast0 = addrspacecast <2 x i32 addrspace(3)*> %group.ptr.0 to <2 x i32*>
+  %cast1 = addrspacecast <2 x i32 addrspace(3)*> %group.ptr.1 to <2 x i32*>
+  %select = select i1 %c, <2 x i32*> %cast0, <2 x i32*> %cast1
+  %extract0 = extractelement <2 x i32*> %select, i32 0
+  %extract1 = extractelement <2 x i32*> %select, i32 1
+  store i32 -1, i32* %extract0
+  store i32 -2, i32* %extract1
+  ret void
+}
+
+attributes #0 = { nounwind }
+
+!0 = !{!"branch_weights", i32 2, i32 10}

Added: llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/volatile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/volatile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/volatile.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/AMDGPU/volatile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,140 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -infer-address-spaces %s | FileCheck %s
+
+; Check that volatile users of addrspacecast are not replaced.
+
+; CHECK-LABEL: @volatile_load_flat_from_global(
+; CHECK: load volatile i32, i32*
+; CHECK: store i32 %val, i32 addrspace(1)*
+define amdgpu_kernel void @volatile_load_flat_from_global(i32 addrspace(1)* nocapture %input, i32 addrspace(1)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(1)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(1)* %output to i32*
+  %val = load volatile i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_load_flat_from_constant(
+; CHECK: load volatile i32, i32*
+; CHECK: store i32 %val, i32 addrspace(1)*
+define amdgpu_kernel void @volatile_load_flat_from_constant(i32 addrspace(4)* nocapture %input, i32 addrspace(1)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(4)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(1)* %output to i32*
+  %val = load volatile i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_load_flat_from_group(
+; CHECK: load volatile i32, i32*
+; CHECK: store i32 %val, i32 addrspace(3)*
+define amdgpu_kernel void @volatile_load_flat_from_group(i32 addrspace(3)* nocapture %input, i32 addrspace(3)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(3)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(3)* %output to i32*
+  %val = load volatile i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_load_flat_from_private(
+; CHECK: load volatile i32, i32*
+; CHECK: store i32 %val, i32 addrspace(5)*
+define amdgpu_kernel void @volatile_load_flat_from_private(i32 addrspace(5)* nocapture %input, i32 addrspace(5)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(5)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(5)* %output to i32*
+  %val = load volatile i32, i32* %tmp0, align 4
+  store i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_store_flat_to_global(
+; CHECK: load i32, i32 addrspace(1)*
+; CHECK: store volatile i32 %val, i32*
+define amdgpu_kernel void @volatile_store_flat_to_global(i32 addrspace(1)* nocapture %input, i32 addrspace(1)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(1)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(1)* %output to i32*
+  %val = load i32, i32* %tmp0, align 4
+  store volatile i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_store_flat_to_group(
+; CHECK: load i32, i32 addrspace(3)*
+; CHECK: store volatile i32 %val, i32*
+define amdgpu_kernel void @volatile_store_flat_to_group(i32 addrspace(3)* nocapture %input, i32 addrspace(3)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(3)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(3)* %output to i32*
+  %val = load i32, i32* %tmp0, align 4
+  store volatile i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_store_flat_to_private(
+; CHECK: load i32, i32 addrspace(5)*
+; CHECK: store volatile i32 %val, i32*
+define amdgpu_kernel void @volatile_store_flat_to_private(i32 addrspace(5)* nocapture %input, i32 addrspace(5)* nocapture %output) #0 {
+  %tmp0 = addrspacecast i32 addrspace(5)* %input to i32*
+  %tmp1 = addrspacecast i32 addrspace(5)* %output to i32*
+  %val = load i32, i32* %tmp0, align 4
+  store volatile i32 %val, i32* %tmp1, align 4
+  ret void
+}
+
+; CHECK-LABEL: @volatile_atomicrmw_add_group_to_flat(
+; CHECK: addrspacecast i32 addrspace(3)* %group.ptr to i32*
+; CHECK: atomicrmw volatile add i32*
+define i32 @volatile_atomicrmw_add_group_to_flat(i32 addrspace(3)* %group.ptr, i32 %y) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = atomicrmw volatile add i32* %cast, i32 %y seq_cst
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @volatile_atomicrmw_add_global_to_flat(
+; CHECK: addrspacecast i32 addrspace(1)* %global.ptr to i32*
+; CHECK: %ret = atomicrmw volatile add i32*
+define i32 @volatile_atomicrmw_add_global_to_flat(i32 addrspace(1)* %global.ptr, i32 %y) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = atomicrmw volatile add i32* %cast, i32 %y seq_cst
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @volatile_cmpxchg_global_to_flat(
+; CHECK: addrspacecast i32 addrspace(1)* %global.ptr to i32*
+; CHECK: cmpxchg volatile i32*
+define { i32, i1 } @volatile_cmpxchg_global_to_flat(i32 addrspace(1)* %global.ptr, i32 %cmp, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(1)* %global.ptr to i32*
+  %ret = cmpxchg volatile i32* %cast, i32 %cmp, i32 %val seq_cst monotonic
+  ret { i32, i1 } %ret
+}
+
+; CHECK-LABEL: @volatile_cmpxchg_group_to_flat(
+; CHECK: addrspacecast i32 addrspace(3)* %group.ptr to i32*
+; CHECK: cmpxchg volatile i32*
+define { i32, i1 } @volatile_cmpxchg_group_to_flat(i32 addrspace(3)* %group.ptr, i32 %cmp, i32 %val) #0 {
+  %cast = addrspacecast i32 addrspace(3)* %group.ptr to i32*
+  %ret = cmpxchg volatile i32* %cast, i32 %cmp, i32 %val seq_cst monotonic
+  ret { i32, i1 } %ret
+}
+
+; FIXME: Shouldn't be losing names
+; CHECK-LABEL: @volatile_memset_group_to_flat(
+; CHECK: addrspacecast i8 addrspace(3)* %group.ptr to i8*
+; CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 4, i64 32, i1 true)
+define amdgpu_kernel void @volatile_memset_group_to_flat(i8 addrspace(3)* %group.ptr, i32 %y) #0 {
+  %cast = addrspacecast i8 addrspace(3)* %group.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 4 %cast, i8 4, i64 32, i1 true)
+  ret void
+}
+
+; CHECK-LABEL: @volatile_memset_global_to_flat(
+; CHECK: addrspacecast i8 addrspace(1)* %global.ptr to i8*
+; CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 4, i64 32, i1 true)
+define amdgpu_kernel void @volatile_memset_global_to_flat(i8 addrspace(1)* %global.ptr, i32 %y) #0 {
+  %cast = addrspacecast i8 addrspace(1)* %global.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 4 %cast, i8 4, i64 32, i1 true)
+  ret void
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/bug31948.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/bug31948.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/bug31948.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/bug31948.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -S -mtriple=nvptx64-nvidia-cuda -infer-address-spaces %s | FileCheck %s
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
+
+%struct.bar = type { float, float* }
+
+ at var1 = local_unnamed_addr addrspace(3) externally_initialized global %struct.bar undef, align 8
+
+; CHECK-LABEL: @bug31948(
+; CHECK: %tmp = load float*, float* addrspace(3)* getelementptr inbounds (%struct.bar, %struct.bar addrspace(3)* @var1, i64 0, i32 1), align 8
+; CHECK: %tmp1 = load float, float* %tmp, align 4
+; CHECK: store float %conv1, float* %tmp, align 4
+; CHECK: store i32 32, i32 addrspace(3)* bitcast (float* addrspace(3)* getelementptr inbounds (%struct.bar, %struct.bar addrspace(3)* @var1, i64 0, i32 1) to i32 addrspace(3)*), align 4
+define void @bug31948(float %a, float* nocapture readnone %x, float* nocapture readnone %y) local_unnamed_addr #0 {
+entry:
+  %tmp = load float*, float** getelementptr (%struct.bar, %struct.bar* addrspacecast (%struct.bar addrspace(3)* @var1 to %struct.bar*), i64 0, i32 1), align 8
+  %tmp1 = load float, float* %tmp, align 4
+  %conv1 = fadd float %tmp1, 1.000000e+00
+  store float %conv1, float* %tmp, align 4
+  store i32 32, i32* bitcast (float** getelementptr (%struct.bar, %struct.bar* addrspacecast (%struct.bar addrspace(3)* @var1 to %struct.bar*), i64 0, i32 1) to i32*), align 4
+  ret void
+}
+
+attributes #0 = { norecurse nounwind }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt -S -mtriple=nvptx64-nvidia-cuda -infer-address-spaces %s | FileCheck %s
+
+%struct.S = type { [5 x i32] }
+
+$g1 = comdat any
+
+ at g1 = linkonce_odr addrspace(3) global %struct.S zeroinitializer, comdat, align 4
+
+; CHECK-LABEL: @foo(
+; CHECK:  %x0 = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x() #2
+; CHECK:  %idxprom.i = zext i32 %x0 to i64
+; CHECK:  %arrayidx.i = getelementptr %struct.S, %struct.S* addrspacecast (%struct.S addrspace(3)* @g1 to %struct.S*), i64 0, i32 0, i64 %idxprom.i
+; CHECK:  tail call void @f1(i32* %arrayidx.i, i32 undef) #0
+; CHECK:  %x1 = load i32, i32* getelementptr (%struct.S, %struct.S* addrspacecast (%struct.S addrspace(3)* @g1 to %struct.S*), i64 0, i32 0, i64 0), align 4
+; CHECK:  %L.sroa.0.0.insert.ext.i = zext i32 %x1 to i64
+; CHECK:  tail call void @f2(i64* null, i64 %L.sroa.0.0.insert.ext.i) #0
+; CHECK:  ret void
+define void @foo() local_unnamed_addr #0 {
+entry:
+  %x0 = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x() #2
+  %idxprom.i = zext i32 %x0 to i64
+  %arrayidx.i = getelementptr %struct.S, %struct.S* addrspacecast (%struct.S addrspace(3)* @g1 to %struct.S*), i64 0, i32 0, i64 %idxprom.i
+  tail call void @f1(i32* %arrayidx.i, i32 undef) #0
+  %x1 = load i32, i32* getelementptr (%struct.S, %struct.S* addrspacecast (%struct.S addrspace(3)* @g1 to %struct.S*), i64 0, i32 0, i64 0), align 4
+  %L.sroa.0.0.insert.ext.i = zext i32 %x1 to i64
+  tail call void @f2(i64* null, i64 %L.sroa.0.0.insert.ext.i) #0
+  ret void
+}
+
+declare void @f1(i32*, i32) local_unnamed_addr #0
+declare void @f2(i64*, i64) local_unnamed_addr #0
+declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() #1
+
+attributes #0 = { convergent nounwind }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind }

Added: llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferAddressSpaces/NVPTX/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/InferAddressSpaces/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/InferFunctionAttrs/annotate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll (added)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/annotate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1015 @@
+; RUN: opt < %s -mtriple=x86_64-- -inferattrs -S | FileCheck -check-prefix=CHECK-UNKNOWN %s
+; RUN: opt < %s -mtriple=x86_64-- -passes=inferattrs -S | FileCheck -check-prefix=CHECK-UNKNOWN %s
+; RUN: opt < %s -mtriple=x86_64-apple-macosx10.8.0 -inferattrs -S | FileCheck -check-prefix=CHECK -check-prefix=CHECK-DARWIN %s
+; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -inferattrs -S | FileCheck -check-prefix=CHECK -check-prefix=CHECK-LINUX %s
+; RUN: opt < %s -mtriple=nvptx -inferattrs -S | FileCheck -check-prefix=CHECK-NVPTX %s
+
+; operator new routines
+declare i8* @_Znwj(i64)
+; CHECK: declare noalias nonnull i8* @_Znwj(i64)
+declare i8* @_Znwm(i64)
+; CHECK: declare noalias nonnull i8* @_Znwm(i64)
+
+declare i32 @__nvvm_reflect(i8*)
+; CHECK-NVPTX: declare i32 @__nvvm_reflect(i8*) [[G0:#[0-9]+]]
+; CHECK-NVPTX: attributes [[G0]] = { nounwind readnone }
+
+
+; Check all the libc functions (thereby also exercising the prototype check).
+; Note that it's OK to modify these as attributes might be missing. These checks
+; reflect the currently inferred attributes.
+
+; Use an opaque pointer type for all the (possibly opaque) structs.
+%opaque = type opaque
+
+; CHECK: declare double @__acos_finite(double)
+declare double @__acos_finite(double)
+
+; CHECK: declare float @__acosf_finite(float)
+declare float @__acosf_finite(float)
+
+; CHECK: declare double @__acosh_finite(double)
+declare double @__acosh_finite(double)
+
+; CHECK: declare float @__acoshf_finite(float)
+declare float @__acoshf_finite(float)
+
+; CHECK: declare x86_fp80 @__acoshl_finite(x86_fp80)
+declare x86_fp80 @__acoshl_finite(x86_fp80)
+
+; CHECK: declare x86_fp80 @__acosl_finite(x86_fp80)
+declare x86_fp80 @__acosl_finite(x86_fp80)
+
+; CHECK: declare double @__asin_finite(double)
+declare double @__asin_finite(double)
+
+; CHECK: declare float @__asinf_finite(float)
+declare float @__asinf_finite(float)
+
+; CHECK: declare x86_fp80 @__asinl_finite(x86_fp80)
+declare x86_fp80 @__asinl_finite(x86_fp80)
+
+; CHECK: declare double @__atan2_finite(double, double)
+declare double @__atan2_finite(double, double)
+
+; CHECK: declare float @__atan2f_finite(float, float)
+declare float @__atan2f_finite(float, float)
+
+; CHECK: declare x86_fp80 @__atan2l_finite(x86_fp80, x86_fp80)
+declare x86_fp80 @__atan2l_finite(x86_fp80, x86_fp80)
+
+; CHECK: declare double @__atanh_finite(double)
+declare double @__atanh_finite(double)
+
+; CHECK: declare float @__atanhf_finite(float)
+declare float @__atanhf_finite(float)
+
+; CHECK: declare x86_fp80 @__atanhl_finite(x86_fp80)
+declare x86_fp80 @__atanhl_finite(x86_fp80)
+
+; CHECK: declare double @__cosh_finite(double)
+declare double @__cosh_finite(double)
+
+; CHECK: declare float @__coshf_finite(float)
+declare float @__coshf_finite(float)
+
+; CHECK: declare x86_fp80 @__coshl_finite(x86_fp80)
+declare x86_fp80 @__coshl_finite(x86_fp80)
+
+; CHECK: declare double @__cospi(double)
+declare double @__cospi(double)
+
+; CHECK: declare float @__cospif(float)
+declare float @__cospif(float)
+
+; CHECK: declare double @__exp10_finite(double)
+declare double @__exp10_finite(double)
+
+; CHECK: declare float @__exp10f_finite(float)
+declare float @__exp10f_finite(float)
+
+; CHECK: declare x86_fp80 @__exp10l_finite(x86_fp80)
+declare x86_fp80 @__exp10l_finite(x86_fp80)
+
+; CHECK: declare double @__exp2_finite(double)
+declare double @__exp2_finite(double)
+
+; CHECK: declare float @__exp2f_finite(float)
+declare float @__exp2f_finite(float)
+
+; CHECK: declare x86_fp80 @__exp2l_finite(x86_fp80)
+declare x86_fp80 @__exp2l_finite(x86_fp80)
+
+; CHECK: declare double @__exp_finite(double)
+declare double @__exp_finite(double)
+
+; CHECK: declare float @__expf_finite(float)
+declare float @__expf_finite(float)
+
+; CHECK: declare x86_fp80 @__expl_finite(x86_fp80)
+declare x86_fp80 @__expl_finite(x86_fp80)
+
+; CHECK: declare double @__log10_finite(double)
+declare double @__log10_finite(double)
+
+; CHECK: declare float @__log10f_finite(float)
+declare float @__log10f_finite(float)
+
+; CHECK: declare x86_fp80 @__log10l_finite(x86_fp80)
+declare x86_fp80 @__log10l_finite(x86_fp80)
+
+; CHECK: declare double @__log2_finite(double)
+declare double @__log2_finite(double)
+
+; CHECK: declare float @__log2f_finite(float)
+declare float @__log2f_finite(float)
+
+; CHECK: declare x86_fp80 @__log2l_finite(x86_fp80)
+declare x86_fp80 @__log2l_finite(x86_fp80)
+
+; CHECK: declare double @__log_finite(double)
+declare double @__log_finite(double)
+
+; CHECK: declare float @__logf_finite(float)
+declare float @__logf_finite(float)
+
+; CHECK: declare x86_fp80 @__logl_finite(x86_fp80)
+declare x86_fp80 @__logl_finite(x86_fp80)
+
+; CHECK: declare double @__pow_finite(double, double)
+declare double @__pow_finite(double, double)
+
+; CHECK: declare float @__powf_finite(float, float)
+declare float @__powf_finite(float, float)
+
+; CHECK: declare x86_fp80 @__powl_finite(x86_fp80, x86_fp80)
+declare x86_fp80 @__powl_finite(x86_fp80, x86_fp80)
+
+; CHECK: declare double @__sinh_finite(double)
+declare double @__sinh_finite(double)
+
+; CHECK: declare float @__sinhf_finite(float)
+declare float @__sinhf_finite(float)
+
+; CHECK: declare x86_fp80 @__sinhl_finite(x86_fp80)
+declare x86_fp80 @__sinhl_finite(x86_fp80)
+
+; CHECK: declare double @__sinpi(double)
+declare double @__sinpi(double)
+
+; CHECK: declare float @__sinpif(float)
+declare float @__sinpif(float)
+
+; CHECK: declare i32 @abs(i32)
+declare i32 @abs(i32)
+
+; CHECK: declare i32 @access(i8* nocapture readonly, i32) [[G0:#[0-9]+]]
+declare i32 @access(i8*, i32)
+
+; CHECK: declare double @acos(double)
+declare double @acos(double)
+
+; CHECK: declare float @acosf(float)
+declare float @acosf(float)
+
+; CHECK: declare double @acosh(double)
+declare double @acosh(double)
+
+; CHECK: declare float @acoshf(float)
+declare float @acoshf(float)
+
+; CHECK: declare x86_fp80 @acoshl(x86_fp80)
+declare x86_fp80 @acoshl(x86_fp80)
+
+; CHECK: declare x86_fp80 @acosl(x86_fp80)
+declare x86_fp80 @acosl(x86_fp80)
+
+; CHECK: declare double @asin(double)
+declare double @asin(double)
+
+; CHECK: declare float @asinf(float)
+declare float @asinf(float)
+
+; CHECK: declare double @asinh(double)
+declare double @asinh(double)
+
+; CHECK: declare float @asinhf(float)
+declare float @asinhf(float)
+
+; CHECK: declare x86_fp80 @asinhl(x86_fp80)
+declare x86_fp80 @asinhl(x86_fp80)
+
+; CHECK: declare x86_fp80 @asinl(x86_fp80)
+declare x86_fp80 @asinl(x86_fp80)
+
+; CHECK: declare double @atan(double)
+declare double @atan(double)
+
+; CHECK: declare double @atan2(double, double)
+declare double @atan2(double, double)
+
+; CHECK: declare float @atan2f(float, float)
+declare float @atan2f(float, float)
+
+; CHECK: declare x86_fp80 @atan2l(x86_fp80, x86_fp80)
+declare x86_fp80 @atan2l(x86_fp80, x86_fp80)
+
+; CHECK: declare float @atanf(float)
+declare float @atanf(float)
+
+; CHECK: declare double @atanh(double)
+declare double @atanh(double)
+
+; CHECK: declare float @atanhf(float)
+declare float @atanhf(float)
+
+; CHECK: declare x86_fp80 @atanhl(x86_fp80)
+declare x86_fp80 @atanhl(x86_fp80)
+
+; CHECK: declare x86_fp80 @atanl(x86_fp80)
+declare x86_fp80 @atanl(x86_fp80)
+
+; CHECK: declare double @atof(i8* nocapture) [[G1:#[0-9]+]]
+declare double @atof(i8*)
+
+; CHECK: declare i32 @atoi(i8* nocapture) [[G1]]
+declare i32 @atoi(i8*)
+
+; CHECK: declare i64 @atol(i8* nocapture) [[G1]]
+declare i64 @atol(i8*)
+
+; CHECK: declare i64 @atoll(i8* nocapture) [[G1]]
+declare i64 @atoll(i8*)
+
+; CHECK-DARWIN: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK-LINUX: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK-UNKNOWN-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+; CHECK-NVPTX-NOT: declare i32 @bcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+declare i32 @bcmp(i8*, i8*, i64)
+
+; CHECK: declare void @bcopy(i8* nocapture readonly, i8* nocapture, i64) [[G0]]
+declare void @bcopy(i8*, i8*, i64)
+
+; CHECK: declare void @bzero(i8* nocapture, i64) [[G0]]
+declare void @bzero(i8*, i64)
+
+; CHECK: declare noalias i8* @calloc(i64, i64) [[G0]]
+declare i8* @calloc(i64, i64)
+
+; CHECK: declare double @cbrt(double)
+declare double @cbrt(double)
+
+; CHECK: declare float @cbrtf(float)
+declare float @cbrtf(float)
+
+; CHECK: declare x86_fp80 @cbrtl(x86_fp80)
+declare x86_fp80 @cbrtl(x86_fp80)
+
+; CHECK: declare double @ceil(double)
+declare double @ceil(double)
+
+; CHECK: declare float @ceilf(float)
+declare float @ceilf(float)
+
+; CHECK: declare x86_fp80 @ceill(x86_fp80)
+declare x86_fp80 @ceill(x86_fp80)
+
+; CHECK: declare i32 @chmod(i8* nocapture readonly, i16 zeroext) [[G0]]
+declare i32 @chmod(i8*, i16 zeroext)
+
+; CHECK: declare i32 @chown(i8* nocapture readonly, i32, i32) [[G0]]
+declare i32 @chown(i8*, i32, i32)
+
+; CHECK: declare void @clearerr(%opaque* nocapture) [[G0]]
+declare void @clearerr(%opaque*)
+
+; CHECK: declare i32 @closedir(%opaque* nocapture) [[G0]]
+declare i32 @closedir(%opaque*)
+
+; CHECK: declare double @copysign(double, double)
+declare double @copysign(double, double)
+
+; CHECK: declare float @copysignf(float, float)
+declare float @copysignf(float, float)
+
+; CHECK: declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
+declare x86_fp80 @copysignl(x86_fp80, x86_fp80)
+
+; CHECK: declare double @cos(double)
+declare double @cos(double)
+
+; CHECK: declare float @cosf(float)
+declare float @cosf(float)
+
+; CHECK: declare double @cosh(double)
+declare double @cosh(double)
+
+; CHECK: declare float @coshf(float)
+declare float @coshf(float)
+
+; CHECK: declare x86_fp80 @coshl(x86_fp80)
+declare x86_fp80 @coshl(x86_fp80)
+
+; CHECK: declare x86_fp80 @cosl(x86_fp80)
+declare x86_fp80 @cosl(x86_fp80)
+
+; CHECK: declare i8* @ctermid(i8* nocapture) [[G0]]
+declare i8* @ctermid(i8*)
+
+; CHECK: declare double @exp(double)
+declare double @exp(double)
+
+; CHECK: declare double @exp2(double)
+declare double @exp2(double)
+
+; CHECK: declare float @exp2f(float)
+declare float @exp2f(float)
+
+; CHECK: declare x86_fp80 @exp2l(x86_fp80)
+declare x86_fp80 @exp2l(x86_fp80)
+
+; CHECK: declare float @expf(float)
+declare float @expf(float)
+
+; CHECK: declare x86_fp80 @expl(x86_fp80)
+declare x86_fp80 @expl(x86_fp80)
+
+; CHECK: declare double @expm1(double)
+declare double @expm1(double)
+
+; CHECK: declare float @expm1f(float)
+declare float @expm1f(float)
+
+; CHECK: declare x86_fp80 @expm1l(x86_fp80)
+declare x86_fp80 @expm1l(x86_fp80)
+
+; CHECK: declare double @fabs(double)
+declare double @fabs(double)
+
+; CHECK: declare float @fabsf(float)
+declare float @fabsf(float)
+
+; CHECK: declare x86_fp80 @fabsl(x86_fp80)
+declare x86_fp80 @fabsl(x86_fp80)
+
+; CHECK: declare i32 @fclose(%opaque* nocapture) [[G0]]
+declare i32 @fclose(%opaque*)
+
+; CHECK: declare noalias %opaque* @fdopen(i32, i8* nocapture readonly) [[G0]]
+declare %opaque* @fdopen(i32, i8*)
+
+; CHECK: declare i32 @feof(%opaque* nocapture) [[G0]]
+declare i32 @feof(%opaque*)
+
+; CHECK: declare i32 @ferror(%opaque* nocapture) [[G1]]
+declare i32 @ferror(%opaque*)
+
+; CHECK: declare i32 @fflush(%opaque* nocapture) [[G0]]
+declare i32 @fflush(%opaque*)
+
+; CHECK: declare i32 @ffs(i32)
+declare i32 @ffs(i32)
+
+; CHECK: declare i32 @ffsl(i64)
+declare i32 @ffsl(i64)
+
+; CHECK: declare i32 @ffsll(i64)
+declare i32 @ffsll(i64)
+
+; CHECK: declare i32 @fgetc(%opaque* nocapture) [[G0]]
+declare i32 @fgetc(%opaque*)
+
+; CHECK: declare i32 @fgetpos(%opaque* nocapture, i64* nocapture) [[G0]]
+declare i32 @fgetpos(%opaque*, i64*)
+
+; CHECK: declare i8* @fgets(i8*, i32, %opaque* nocapture) [[G0]]
+declare i8* @fgets(i8*, i32, %opaque*)
+
+; CHECK: declare i32 @fileno(%opaque* nocapture) [[G0]]
+declare i32 @fileno(%opaque*)
+
+; CHECK: declare void @flockfile(%opaque* nocapture) [[G0]]
+declare void @flockfile(%opaque*)
+
+; CHECK: declare double @floor(double)
+declare double @floor(double)
+
+; CHECK: declare float @floorf(float)
+declare float @floorf(float)
+
+; CHECK: declare x86_fp80 @floorl(x86_fp80)
+declare x86_fp80 @floorl(x86_fp80)
+
+; CHECK: declare i32 @fls(i32)
+declare i32 @fls(i32)
+
+; CHECK: declare i32 @flsl(i64)
+declare i32 @flsl(i64)
+
+; CHECK: declare i32 @flsll(i64)
+declare i32 @flsll(i64)
+
+; CHECK: declare double @fmax(double, double)
+declare double @fmax(double, double)
+
+; CHECK: declare float @fmaxf(float, float)
+declare float @fmaxf(float, float)
+
+; CHECK: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
+declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
+
+; CHECK: declare double @fmin(double, double)
+declare double @fmin(double, double)
+
+; CHECK: declare float @fminf(float, float)
+declare float @fminf(float, float)
+
+; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80)
+declare x86_fp80 @fminl(x86_fp80, x86_fp80)
+
+; CHECK: declare double @fmod(double, double)
+declare double @fmod(double, double)
+
+; CHECK: declare float @fmodf(float, float)
+declare float @fmodf(float, float)
+
+; CHECK: declare x86_fp80 @fmodl(x86_fp80, x86_fp80)
+declare x86_fp80 @fmodl(x86_fp80, x86_fp80)
+
+; CHECK: declare noalias %opaque* @fopen(i8* nocapture readonly, i8* nocapture readonly) [[G0]]
+declare %opaque* @fopen(i8*, i8*)
+
+; CHECK: declare i32 @fprintf(%opaque* nocapture, i8* nocapture readonly, ...) [[G0]]
+declare i32 @fprintf(%opaque*, i8*, ...)
+
+; CHECK: declare i32 @fputc(i32, %opaque* nocapture) [[G0]]
+declare i32 @fputc(i32, %opaque*)
+
+; CHECK: declare i32 @fputs(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @fputs(i8*, %opaque*)
+
+; CHECK: declare i64 @fread(i8* nocapture, i64, i64, %opaque* nocapture) [[G0]]
+declare i64 @fread(i8*, i64, i64, %opaque*)
+
+; CHECK: declare void @free(i8* nocapture) [[G0]]
+declare void @free(i8*)
+
+; CHECK: declare double @frexp(double, i32* nocapture) [[G0]]
+declare double @frexp(double, i32*)
+
+; CHECK: declare float @frexpf(float, i32* nocapture) [[G0]]
+declare float @frexpf(float, i32*)
+
+; CHECK: declare x86_fp80 @frexpl(x86_fp80, i32* nocapture) [[G0]]
+declare x86_fp80 @frexpl(x86_fp80, i32*)
+
+; CHECK: declare i32 @fscanf(%opaque* nocapture, i8* nocapture readonly, ...) [[G0]]
+declare i32 @fscanf(%opaque*, i8*, ...)
+
+; CHECK: declare i32 @fseek(%opaque* nocapture, i64, i32) [[G0]]
+declare i32 @fseek(%opaque*, i64, i32)
+
+; CHECK: declare i32 @fseeko(%opaque* nocapture, i64, i32) [[G0]]
+declare i32 @fseeko(%opaque*, i64, i32)
+
+; CHECK-LINUX: declare i32 @fseeko64(%opaque* nocapture, i64, i32) [[G0]]
+declare i32 @fseeko64(%opaque*, i64, i32)
+
+; CHECK: declare i32 @fsetpos(%opaque* nocapture, i64*) [[G0]]
+declare i32 @fsetpos(%opaque*, i64*)
+
+; CHECK: declare i32 @fstat(i32, %opaque* nocapture) [[G0]]
+declare i32 @fstat(i32, %opaque*)
+
+; CHECK-LINUX: declare i32 @fstat64(i32, %opaque* nocapture) [[G0]]
+declare i32 @fstat64(i32, %opaque*)
+
+; CHECK: declare i32 @fstatvfs(i32, %opaque* nocapture) [[G0]]
+declare i32 @fstatvfs(i32, %opaque*)
+
+; CHECK-LINUX: declare i32 @fstatvfs64(i32, %opaque* nocapture) [[G0]]
+declare i32 @fstatvfs64(i32, %opaque*)
+
+; CHECK: declare i64 @ftell(%opaque* nocapture) [[G0]]
+declare i64 @ftell(%opaque*)
+
+; CHECK: declare i64 @ftello(%opaque* nocapture) [[G0]]
+declare i64 @ftello(%opaque*)
+
+; CHECK-LINUX: declare i64 @ftello64(%opaque* nocapture) [[G0]]
+declare i64 @ftello64(%opaque*)
+
+; CHECK: declare i32 @ftrylockfile(%opaque* nocapture) [[G0]]
+declare i32 @ftrylockfile(%opaque*)
+
+; CHECK: declare void @funlockfile(%opaque* nocapture) [[G0]]
+declare void @funlockfile(%opaque*)
+
+; CHECK: declare i64 @fwrite(i8* nocapture, i64, i64, %opaque* nocapture) [[G0]]
+declare i64 @fwrite(i8*, i64, i64, %opaque*)
+
+; CHECK: declare i32 @getc(%opaque* nocapture) [[G0]]
+declare i32 @getc(%opaque*)
+
+; CHECK: declare i32 @getc_unlocked(%opaque* nocapture) [[G0]]
+declare i32 @getc_unlocked(%opaque*)
+
+; CHECK: declare i32 @getchar()
+declare i32 @getchar()
+
+; CHECK: declare i32 @getchar_unlocked()
+declare i32 @getchar_unlocked()
+
+; CHECK: declare i8* @getenv(i8* nocapture) [[G1]]
+declare i8* @getenv(i8*)
+
+; CHECK: declare i32 @getitimer(i32, %opaque* nocapture) [[G0]]
+declare i32 @getitimer(i32, %opaque*)
+
+; CHECK: declare i32 @getlogin_r(i8* nocapture, i64) [[G0]]
+declare i32 @getlogin_r(i8*, i64)
+
+; CHECK: declare %opaque* @getpwnam(i8* nocapture readonly) [[G0]]
+declare %opaque* @getpwnam(i8*)
+
+; CHECK: declare i8* @gets(i8*)
+declare i8* @gets(i8*)
+
+; CHECK: declare i32 @gettimeofday(%opaque* nocapture, i8* nocapture) [[G0]]
+declare i32 @gettimeofday(%opaque*, i8*)
+
+; CHECK: declare i32 @isascii(i32)
+declare i32 @isascii(i32)
+
+; CHECK: declare i32 @isdigit(i32)
+declare i32 @isdigit(i32)
+
+; CHECK: declare i64 @labs(i64)
+declare i64 @labs(i64)
+
+; CHECK: declare i32 @lchown(i8* nocapture readonly, i32, i32) [[G0]]
+declare i32 @lchown(i8*, i32, i32)
+
+; CHECK: declare double @ldexp(double, i32)
+declare double @ldexp(double, i32)
+
+; CHECK: declare float @ldexpf(float, i32)
+declare float @ldexpf(float, i32)
+
+; CHECK: declare x86_fp80 @ldexpl(x86_fp80, i32)
+declare x86_fp80 @ldexpl(x86_fp80, i32)
+
+; CHECK: declare i64 @llabs(i64)
+declare i64 @llabs(i64)
+
+; CHECK: declare double @log(double)
+declare double @log(double)
+
+; CHECK: declare double @log10(double)
+declare double @log10(double)
+
+; CHECK: declare float @log10f(float)
+declare float @log10f(float)
+
+; CHECK: declare x86_fp80 @log10l(x86_fp80)
+declare x86_fp80 @log10l(x86_fp80)
+
+; CHECK: declare double @log1p(double)
+declare double @log1p(double)
+
+; CHECK: declare float @log1pf(float)
+declare float @log1pf(float)
+
+; CHECK: declare x86_fp80 @log1pl(x86_fp80)
+declare x86_fp80 @log1pl(x86_fp80)
+
+; CHECK: declare double @log2(double)
+declare double @log2(double)
+
+; CHECK: declare float @log2f(float)
+declare float @log2f(float)
+
+; CHECK: declare x86_fp80 @log2l(x86_fp80)
+declare x86_fp80 @log2l(x86_fp80)
+
+; CHECK: declare double @logb(double)
+declare double @logb(double)
+
+; CHECK: declare float @logbf(float)
+declare float @logbf(float)
+
+; CHECK: declare x86_fp80 @logbl(x86_fp80)
+declare x86_fp80 @logbl(x86_fp80)
+
+; CHECK: declare float @logf(float)
+declare float @logf(float)
+
+; CHECK: declare x86_fp80 @logl(x86_fp80)
+declare x86_fp80 @logl(x86_fp80)
+
+; CHECK: declare i32 @lstat(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @lstat(i8*, %opaque*)
+
+; CHECK-LINUX: declare i32 @lstat64(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @lstat64(i8*, %opaque*)
+
+; CHECK: declare noalias i8* @malloc(i64) [[G0]]
+declare i8* @malloc(i64)
+
+; CHECK-LINUX: declare noalias i8* @memalign(i64, i64)
+declare i8* @memalign(i64, i64)
+
+; CHECK: declare i8* @memccpy(i8*, i8* nocapture readonly, i32, i64) [[G0]]
+declare i8* @memccpy(i8*, i8*, i32, i64)
+
+; CHECK: declare i8* @memchr(i8*, i32, i64) [[G1]]
+declare i8* @memchr(i8*, i32, i64)
+
+; CHECK: declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+declare i32 @memcmp(i8*, i8*, i64)
+
+; CHECK: declare i8* @memcpy(i8* returned, i8* nocapture readonly, i64) [[G0]]
+declare i8* @memcpy(i8*, i8*, i64)
+
+; CHECK: declare i8* @mempcpy(i8*, i8* nocapture readonly, i64) [[G0]]
+declare i8* @mempcpy(i8*, i8*, i64)
+
+; CHECK: declare i8* @memmove(i8* returned, i8* nocapture readonly, i64) [[G0]]
+declare i8* @memmove(i8*, i8*, i64)
+
+; CHECK: declare i8* @memset(i8*, i32, i64)
+declare i8* @memset(i8*, i32, i64)
+
+; CHECK: declare i32 @mkdir(i8* nocapture readonly, i16 zeroext) [[G0]]
+declare i32 @mkdir(i8*, i16 zeroext)
+
+; CHECK: declare i64 @mktime(%opaque* nocapture) [[G0]]
+declare i64 @mktime(%opaque*)
+
+; CHECK: declare double @modf(double, double* nocapture) [[G0]]
+declare double @modf(double, double*)
+
+; CHECK: declare float @modff(float, float* nocapture) [[G0]]
+declare float @modff(float, float*)
+
+; CHECK: declare x86_fp80 @modfl(x86_fp80, x86_fp80* nocapture) [[G0]]
+declare x86_fp80 @modfl(x86_fp80, x86_fp80*)
+
+; CHECK: declare double @nearbyint(double)
+declare double @nearbyint(double)
+
+; CHECK: declare float @nearbyintf(float)
+declare float @nearbyintf(float)
+
+; CHECK: declare x86_fp80 @nearbyintl(x86_fp80)
+declare x86_fp80 @nearbyintl(x86_fp80)
+
+; CHECK: declare i32 @open(i8* nocapture readonly, i32, ...)
+declare i32 @open(i8*, i32, ...)
+
+; CHECK-LINUX: declare i32 @open64(i8* nocapture readonly, i32, ...)
+declare i32 @open64(i8*, i32, ...)
+
+; CHECK: declare noalias %opaque* @opendir(i8* nocapture readonly) [[G0]]
+declare %opaque* @opendir(i8*)
+
+; CHECK: declare i32 @pclose(%opaque* nocapture) [[G0]]
+declare i32 @pclose(%opaque*)
+
+; CHECK: declare void @perror(i8* nocapture readonly) [[G0]]
+declare void @perror(i8*)
+
+; CHECK: declare noalias %opaque* @popen(i8* nocapture readonly, i8* nocapture readonly) [[G0]]
+declare %opaque* @popen(i8*, i8*)
+
+; CHECK: declare i32 @posix_memalign(i8**, i64, i64)
+declare i32 @posix_memalign(i8**, i64, i64)
+
+; CHECK: declare double @pow(double, double)
+declare double @pow(double, double)
+
+; CHECK: declare float @powf(float, float)
+declare float @powf(float, float)
+
+; CHECK: declare x86_fp80 @powl(x86_fp80, x86_fp80)
+declare x86_fp80 @powl(x86_fp80, x86_fp80)
+
+; CHECK: declare i64 @pread(i32, i8* nocapture, i64, i64)
+declare i64 @pread(i32, i8*, i64, i64)
+
+; CHECK: declare i32 @printf(i8* nocapture readonly, ...) [[G0]]
+declare i32 @printf(i8*, ...)
+
+; CHECK: declare i32 @putc(i32, %opaque* nocapture) [[G0]]
+declare i32 @putc(i32, %opaque*)
+
+; CHECK: declare i32 @putchar(i32)
+declare i32 @putchar(i32)
+
+; CHECK: declare i32 @putchar_unlocked(i32)
+declare i32 @putchar_unlocked(i32)
+
+; CHECK: declare i32 @puts(i8* nocapture readonly) [[G0]]
+declare i32 @puts(i8*)
+
+; CHECK: declare i64 @pwrite(i32, i8* nocapture readonly, i64, i64)
+declare i64 @pwrite(i32, i8*, i64, i64)
+
+; CHECK: declare void @qsort(i8*, i64, i64, i32 (i8*, i8*)* nocapture)
+declare void @qsort(i8*, i64, i64, i32 (i8*, i8*)*)
+
+; CHECK: declare i64 @read(i32, i8* nocapture, i64)
+declare i64 @read(i32, i8*, i64)
+
+; CHECK: declare i64 @readlink(i8* nocapture readonly, i8* nocapture, i64) [[G0]]
+declare i64 @readlink(i8*, i8*, i64)
+
+; CHECK: declare noalias i8* @realloc(i8* nocapture, i64) [[G0]]
+declare i8* @realloc(i8*, i64)
+
+; CHECK: declare i8* @reallocf(i8*, i64)
+declare i8* @reallocf(i8*, i64)
+
+; CHECK: declare i8* @realpath(i8* nocapture readonly, i8*)
+declare i8* @realpath(i8*, i8*)
+
+; CHECK: declare i32 @remove(i8* nocapture readonly) [[G0]]
+declare i32 @remove(i8*)
+
+; CHECK: declare i32 @rename(i8* nocapture readonly, i8* nocapture readonly) [[G0]]
+declare i32 @rename(i8*, i8*)
+
+; CHECK: declare void @rewind(%opaque* nocapture) [[G0]]
+declare void @rewind(%opaque*)
+
+; CHECK: declare double @rint(double)
+declare double @rint(double)
+
+; CHECK: declare float @rintf(float)
+declare float @rintf(float)
+
+; CHECK: declare x86_fp80 @rintl(x86_fp80)
+declare x86_fp80 @rintl(x86_fp80)
+
+; CHECK: declare i32 @rmdir(i8* nocapture readonly) [[G0]]
+declare i32 @rmdir(i8*)
+
+; CHECK: declare double @round(double)
+declare double @round(double)
+
+; CHECK: declare float @roundf(float)
+declare float @roundf(float)
+
+; CHECK: declare x86_fp80 @roundl(x86_fp80)
+declare x86_fp80 @roundl(x86_fp80)
+
+; CHECK: declare i32 @scanf(i8* nocapture readonly, ...) [[G0]]
+declare i32 @scanf(i8*, ...)
+
+; CHECK: declare void @setbuf(%opaque* nocapture, i8*) [[G0]]
+declare void @setbuf(%opaque*, i8*)
+
+; CHECK: declare i32 @setitimer(i32, %opaque* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @setitimer(i32, %opaque*, %opaque*)
+
+; CHECK: declare i32 @setvbuf(%opaque* nocapture, i8*, i32, i64) [[G0]]
+declare i32 @setvbuf(%opaque*, i8*, i32, i64)
+
+; CHECK: declare double @sin(double)
+declare double @sin(double)
+
+; CHECK: declare float @sinf(float)
+declare float @sinf(float)
+
+; CHECK: declare double @sinh(double)
+declare double @sinh(double)
+
+; CHECK: declare float @sinhf(float)
+declare float @sinhf(float)
+
+; CHECK: declare x86_fp80 @sinhl(x86_fp80)
+declare x86_fp80 @sinhl(x86_fp80)
+
+; CHECK: declare x86_fp80 @sinl(x86_fp80)
+declare x86_fp80 @sinl(x86_fp80)
+
+; CHECK: declare i32 @snprintf(i8* nocapture, i64, i8* nocapture readonly, ...) [[G0]]
+declare i32 @snprintf(i8*, i64, i8*, ...)
+
+; CHECK: declare i32 @sprintf(i8* nocapture, i8* nocapture readonly, ...) [[G0]]
+declare i32 @sprintf(i8*, i8*, ...)
+
+; CHECK: declare double @sqrt(double)
+declare double @sqrt(double)
+
+; CHECK: declare float @sqrtf(float)
+declare float @sqrtf(float)
+
+; CHECK: declare x86_fp80 @sqrtl(x86_fp80)
+declare x86_fp80 @sqrtl(x86_fp80)
+
+; CHECK: declare i32 @sscanf(i8* nocapture readonly, i8* nocapture readonly, ...) [[G0]]
+declare i32 @sscanf(i8*, i8*, ...)
+
+; CHECK: declare i32 @stat(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @stat(i8*, %opaque*)
+
+; CHECK-LINUX: declare i32 @stat64(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @stat64(i8*, %opaque*)
+
+; CHECK: declare i32 @statvfs(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @statvfs(i8*, %opaque*)
+
+; CHECK-LINUX: declare i32 @statvfs64(i8* nocapture readonly, %opaque* nocapture) [[G0]]
+declare i32 @statvfs64(i8*, %opaque*)
+
+; CHECK: declare i8* @stpcpy(i8*, i8* nocapture readonly) [[G0]]
+declare i8* @stpcpy(i8*, i8*)
+
+; CHECK: declare i8* @stpncpy(i8*, i8* nocapture readonly, i64) [[G0]]
+declare i8* @stpncpy(i8*, i8*, i64)
+
+; CHECK: declare i32 @strcasecmp(i8* nocapture, i8* nocapture) [[G1]]
+declare i32 @strcasecmp(i8*, i8*)
+
+; CHECK: declare i8* @strcat(i8* returned, i8* nocapture readonly) [[G0]]
+declare i8* @strcat(i8*, i8*)
+
+; CHECK: declare i8* @strchr(i8*, i32) [[G1]]
+declare i8* @strchr(i8*, i32)
+
+; CHECK: declare i32 @strcmp(i8* nocapture, i8* nocapture) [[G1]]
+declare i32 @strcmp(i8*, i8*)
+
+; CHECK: declare i32 @strcoll(i8* nocapture, i8* nocapture) [[G1]]
+declare i32 @strcoll(i8*, i8*)
+
+; CHECK: declare i8* @strcpy(i8* returned, i8* nocapture readonly) [[G0]]
+declare i8* @strcpy(i8*, i8*)
+
+; CHECK: declare i64 @strcspn(i8* nocapture, i8* nocapture) [[G1]]
+declare i64 @strcspn(i8*, i8*)
+
+; CHECK: declare noalias i8* @strdup(i8* nocapture readonly) [[G0]]
+declare i8* @strdup(i8*)
+
+; CHECK: declare i64 @strlen(i8* nocapture) [[G2:#[0-9]+]]
+declare i64 @strlen(i8*)
+
+; CHECK: declare i32 @strncasecmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+declare i32 @strncasecmp(i8*, i8*, i64)
+
+; CHECK: declare i8* @strncat(i8* returned, i8* nocapture readonly, i64) [[G0]]
+declare i8* @strncat(i8*, i8*, i64)
+
+; CHECK: declare i32 @strncmp(i8* nocapture, i8* nocapture, i64) [[G1]]
+declare i32 @strncmp(i8*, i8*, i64)
+
+; CHECK: declare i8* @strncpy(i8* returned, i8* nocapture readonly, i64) [[G0]]
+declare i8* @strncpy(i8*, i8*, i64)
+
+; CHECK: declare noalias i8* @strndup(i8* nocapture readonly, i64) [[G0]]
+declare i8* @strndup(i8*, i64)
+
+; CHECK: declare i64 @strnlen(i8*, i64)
+declare i64 @strnlen(i8*, i64)
+
+; CHECK: declare i8* @strpbrk(i8*, i8* nocapture) [[G1]]
+declare i8* @strpbrk(i8*, i8*)
+
+; CHECK: declare i8* @strrchr(i8*, i32) [[G1]]
+declare i8* @strrchr(i8*, i32)
+
+; CHECK: declare i64 @strspn(i8* nocapture, i8* nocapture) [[G1]]
+declare i64 @strspn(i8*, i8*)
+
+; CHECK: declare i8* @strstr(i8*, i8* nocapture) [[G1]]
+declare i8* @strstr(i8*, i8*)
+
+; CHECK: declare double @strtod(i8* readonly, i8** nocapture) [[G0]]
+declare double @strtod(i8*, i8**)
+
+; CHECK: declare float @strtof(i8* readonly, i8** nocapture) [[G0]]
+declare float @strtof(i8*, i8**)
+
+; CHECK: declare i8* @strtok(i8*, i8* nocapture readonly) [[G0]]
+declare i8* @strtok(i8*, i8*)
+
+; CHECK: declare i8* @strtok_r(i8*, i8* nocapture readonly, i8**) [[G0]]
+declare i8* @strtok_r(i8*, i8*, i8**)
+
+; CHECK: declare i64 @strtol(i8* readonly, i8** nocapture, i32) [[G0]]
+declare i64 @strtol(i8*, i8**, i32)
+
+; CHECK: declare x86_fp80 @strtold(i8* readonly, i8** nocapture) [[G0]]
+declare x86_fp80 @strtold(i8*, i8**)
+
+; CHECK: declare i64 @strtoll(i8* readonly, i8** nocapture, i32) [[G0]]
+declare i64 @strtoll(i8*, i8**, i32)
+
+; CHECK: declare i64 @strtoul(i8* readonly, i8** nocapture, i32) [[G0]]
+declare i64 @strtoul(i8*, i8**, i32)
+
+; CHECK: declare i64 @strtoull(i8* readonly, i8** nocapture, i32) [[G0]]
+declare i64 @strtoull(i8*, i8**, i32)
+
+; CHECK: declare i64 @strxfrm(i8* nocapture, i8* nocapture readonly, i64) [[G0]]
+declare i64 @strxfrm(i8*, i8*, i64)
+
+; CHECK: declare i32 @system(i8* nocapture readonly)
+declare i32 @system(i8*)
+
+; CHECK: declare double @tan(double)
+declare double @tan(double)
+
+; CHECK: declare float @tanf(float)
+declare float @tanf(float)
+
+; CHECK: declare double @tanh(double)
+declare double @tanh(double)
+
+; CHECK: declare float @tanhf(float)
+declare float @tanhf(float)
+
+; CHECK: declare x86_fp80 @tanhl(x86_fp80)
+declare x86_fp80 @tanhl(x86_fp80)
+
+; CHECK: declare x86_fp80 @tanl(x86_fp80)
+declare x86_fp80 @tanl(x86_fp80)
+
+; CHECK: declare i64 @times(%opaque* nocapture) [[G0]]
+declare i64 @times(%opaque*)
+
+; CHECK: declare noalias %opaque* @tmpfile() [[G0]]
+declare %opaque* @tmpfile()
+
+; CHECK-LINUX: declare noalias %opaque* @tmpfile64() [[G0]]
+declare %opaque* @tmpfile64()
+
+; CHECK: declare i32 @toascii(i32)
+declare i32 @toascii(i32)
+
+; CHECK: declare double @trunc(double)
+declare double @trunc(double)
+
+; CHECK: declare float @truncf(float)
+declare float @truncf(float)
+
+; CHECK: declare x86_fp80 @truncl(x86_fp80)
+declare x86_fp80 @truncl(x86_fp80)
+
+; CHECK: declare i32 @uname(%opaque* nocapture) [[G0]]
+declare i32 @uname(%opaque*)
+
+; CHECK: declare i32 @ungetc(i32, %opaque* nocapture) [[G0]]
+declare i32 @ungetc(i32, %opaque*)
+
+; CHECK: declare i32 @unlink(i8* nocapture readonly) [[G0]]
+declare i32 @unlink(i8*)
+
+; CHECK: declare i32 @unsetenv(i8* nocapture readonly) [[G0]]
+declare i32 @unsetenv(i8*)
+
+; CHECK: declare i32 @utime(i8* nocapture readonly, %opaque* nocapture readonly) [[G0]]
+declare i32 @utime(i8*, %opaque*)
+
+; CHECK: declare i32 @utimes(i8* nocapture readonly, %opaque* nocapture readonly) [[G0]]
+declare i32 @utimes(i8*, %opaque*)
+
+; CHECK: declare noalias i8* @valloc(i64) [[G0]]
+declare i8* @valloc(i64)
+
+; CHECK: declare i32 @vfprintf(%opaque* nocapture, i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vfprintf(%opaque*, i8*, %opaque*)
+
+; CHECK: declare i32 @vfscanf(%opaque* nocapture, i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vfscanf(%opaque*, i8*, %opaque*)
+
+; CHECK: declare i32 @vprintf(i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vprintf(i8*, %opaque*)
+
+; CHECK: declare i32 @vscanf(i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vscanf(i8*, %opaque*)
+
+; CHECK: declare i32 @vsnprintf(i8* nocapture, i64, i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vsnprintf(i8*, i64, i8*, %opaque*)
+
+; CHECK: declare i32 @vsprintf(i8* nocapture, i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vsprintf(i8*, i8*, %opaque*)
+
+; CHECK: declare i32 @vsscanf(i8* nocapture readonly, i8* nocapture readonly, %opaque*) [[G0]]
+declare i32 @vsscanf(i8*, i8*, %opaque*)
+
+; CHECK: declare i64 @write(i32, i8* nocapture readonly, i64)
+declare i64 @write(i32, i8*, i64)
+
+
+; memset_pattern16 isn't available everywhere.
+; CHECK-DARWIN: declare void @memset_pattern16(i8* nocapture, i8* nocapture readonly, i64) [[G3:#[0-9]+]]
+declare void @memset_pattern16(i8*, i8*, i64)
+
+
+; CHECK: attributes [[G0]] = { nounwind }
+; CHECK: attributes [[G1]] = { nounwind readonly }
+; CHECK: attributes [[G2]] = { argmemonly nounwind readonly }
+; CHECK-DARWIN: attributes [[G3]] = { argmemonly }

Added: llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll (added)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/no-proto.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,979 @@
+; RUN: opt < %s -mtriple=x86_64-unknown-linux -inferattrs -S | FileCheck %s
+; RUN: opt < %s -mtriple=x86_64-apple-macosx10.8.0 -inferattrs -S | FileCheck %s
+
+; Check that we don't modify libc functions with invalid prototypes.
+
+; CHECK: declare void @__acos_finite(...)
+declare void @__acos_finite(...)
+
+; CHECK: declare void @__acosf_finite(...)
+declare void @__acosf_finite(...)
+
+; CHECK: declare void @__acosh_finite(...)
+declare void @__acosh_finite(...)
+
+; CHECK: declare void @__acoshf_finite(...)
+declare void @__acoshf_finite(...)
+
+; CHECK: declare void @__acoshl_finite(...)
+declare void @__acoshl_finite(...)
+
+; CHECK: declare void @__acosl_finite(...)
+declare void @__acosl_finite(...)
+
+; CHECK: declare void @__asin_finite(...)
+declare void @__asin_finite(...)
+
+; CHECK: declare void @__asinf_finite(...)
+declare void @__asinf_finite(...)
+
+; CHECK: declare void @__asinl_finite(...)
+declare void @__asinl_finite(...)
+
+; CHECK: declare void @__atan2_finite(...)
+declare void @__atan2_finite(...)
+
+; CHECK: declare void @__atan2f_finite(...)
+declare void @__atan2f_finite(...)
+
+; CHECK: declare void @__atan2l_finite(...)
+declare void @__atan2l_finite(...)
+
+; CHECK: declare void @__atanh_finite(...)
+declare void @__atanh_finite(...)
+
+; CHECK: declare void @__atanhf_finite(...)
+declare void @__atanhf_finite(...)
+
+; CHECK: declare void @__atanhl_finite(...)
+declare void @__atanhl_finite(...)
+
+; CHECK: declare void @__cosh_finite(...)
+declare void @__cosh_finite(...)
+
+; CHECK: declare void @__coshf_finite(...)
+declare void @__coshf_finite(...)
+
+; CHECK: declare void @__coshl_finite(...)
+declare void @__coshl_finite(...)
+
+; CHECK: declare void @__cospi(...)
+declare void @__cospi(...)
+
+; CHECK: declare void @__cospif(...)
+declare void @__cospif(...)
+
+; CHECK: declare void @__exp10_finite(...)
+declare void @__exp10_finite(...)
+
+; CHECK: declare void @__exp10f_finite(...)
+declare void @__exp10f_finite(...)
+
+; CHECK: declare void @__exp10l_finite(...)
+declare void @__exp10l_finite(...)
+
+; CHECK: declare void @__exp2_finite(...)
+declare void @__exp2_finite(...)
+
+; CHECK: declare void @__exp2f_finite(...)
+declare void @__exp2f_finite(...)
+
+; CHECK: declare void @__exp2l_finite(...)
+declare void @__exp2l_finite(...)
+
+; CHECK: declare void @__exp_finite(...)
+declare void @__exp_finite(...)
+
+; CHECK: declare void @__expf_finite(...)
+declare void @__expf_finite(...)
+
+; CHECK: declare void @__expl_finite(...)
+declare void @__expl_finite(...)
+
+; CHECK: declare void @__log10_finite(...)
+declare void @__log10_finite(...)
+
+; CHECK: declare void @__log10f_finite(...)
+declare void @__log10f_finite(...)
+
+; CHECK: declare void @__log10l_finite(...)
+declare void @__log10l_finite(...)
+
+; CHECK: declare void @__log2_finite(...)
+declare void @__log2_finite(...)
+
+; CHECK: declare void @__log2f_finite(...)
+declare void @__log2f_finite(...)
+
+; CHECK: declare void @__log2l_finite(...)
+declare void @__log2l_finite(...)
+
+; CHECK: declare void @__log_finite(...)
+declare void @__log_finite(...)
+
+; CHECK: declare void @__logf_finite(...)
+declare void @__logf_finite(...)
+
+; CHECK: declare void @__logl_finite(...)
+declare void @__logl_finite(...)
+
+; CHECK: declare void @__pow_finite(...)
+declare void @__pow_finite(...)
+
+; CHECK: declare void @__powf_finite(...)
+declare void @__powf_finite(...)
+
+; CHECK: declare void @__powl_finite(...)
+declare void @__powl_finite(...)
+
+; CHECK: declare void @__sinh_finite(...)
+declare void @__sinh_finite(...)
+
+; CHECK: declare void @__sinhf_finite(...)
+declare void @__sinhf_finite(...)
+
+; CHECK: declare void @__sinhl_finite(...)
+declare void @__sinhl_finite(...)
+
+; CHECK: declare void @__sinpi(...)
+declare void @__sinpi(...)
+
+; CHECK: declare void @__sinpif(...)
+declare void @__sinpif(...)
+
+; CHECK: declare void @abs(...)
+declare void @abs(...)
+
+; CHECK: declare void @access(...)
+declare void @access(...)
+
+; CHECK: declare void @acos(...)
+declare void @acos(...)
+
+; CHECK: declare void @acosf(...)
+declare void @acosf(...)
+
+; CHECK: declare void @acosh(...)
+declare void @acosh(...)
+
+; CHECK: declare void @acoshf(...)
+declare void @acoshf(...)
+
+; CHECK: declare void @acoshl(...)
+declare void @acoshl(...)
+
+; CHECK: declare void @acosl(...)
+declare void @acosl(...)
+
+; CHECK: declare void @asin(...)
+declare void @asin(...)
+
+; CHECK: declare void @asinf(...)
+declare void @asinf(...)
+
+; CHECK: declare void @asinh(...)
+declare void @asinh(...)
+
+; CHECK: declare void @asinhf(...)
+declare void @asinhf(...)
+
+; CHECK: declare void @asinhl(...)
+declare void @asinhl(...)
+
+; CHECK: declare void @asinl(...)
+declare void @asinl(...)
+
+; CHECK: declare void @atan(...)
+declare void @atan(...)
+
+; CHECK: declare void @atan2(...)
+declare void @atan2(...)
+
+; CHECK: declare void @atan2f(...)
+declare void @atan2f(...)
+
+; CHECK: declare void @atan2l(...)
+declare void @atan2l(...)
+
+; CHECK: declare void @atanf(...)
+declare void @atanf(...)
+
+; CHECK: declare void @atanh(...)
+declare void @atanh(...)
+
+; CHECK: declare void @atanhf(...)
+declare void @atanhf(...)
+
+; CHECK: declare void @atanhl(...)
+declare void @atanhl(...)
+
+; CHECK: declare void @atanl(...)
+declare void @atanl(...)
+
+; CHECK: declare void @atof(...)
+declare void @atof(...)
+
+; CHECK: declare void @atoi(...)
+declare void @atoi(...)
+
+; CHECK: declare void @atol(...)
+declare void @atol(...)
+
+; CHECK: declare void @atoll(...)
+declare void @atoll(...)
+
+; CHECK: declare void @bcmp(...)
+declare void @bcmp(...)
+
+; CHECK: declare void @bcopy(...)
+declare void @bcopy(...)
+
+; CHECK: declare void @bzero(...)
+declare void @bzero(...)
+
+; CHECK: declare void @calloc(...)
+declare void @calloc(...)
+
+; CHECK: declare void @cbrt(...)
+declare void @cbrt(...)
+
+; CHECK: declare void @cbrtf(...)
+declare void @cbrtf(...)
+
+; CHECK: declare void @cbrtl(...)
+declare void @cbrtl(...)
+
+; CHECK: declare void @ceil(...)
+declare void @ceil(...)
+
+; CHECK: declare void @ceilf(...)
+declare void @ceilf(...)
+
+; CHECK: declare void @ceill(...)
+declare void @ceill(...)
+
+; CHECK: declare void @chmod(...)
+declare void @chmod(...)
+
+; CHECK: declare void @chown(...)
+declare void @chown(...)
+
+; CHECK: declare void @clearerr(...)
+declare void @clearerr(...)
+
+; CHECK: declare void @closedir(...)
+declare void @closedir(...)
+
+; CHECK: declare void @copysign(...)
+declare void @copysign(...)
+
+; CHECK: declare void @copysignf(...)
+declare void @copysignf(...)
+
+; CHECK: declare void @copysignl(...)
+declare void @copysignl(...)
+
+; CHECK: declare void @cos(...)
+declare void @cos(...)
+
+; CHECK: declare void @cosf(...)
+declare void @cosf(...)
+
+; CHECK: declare void @cosh(...)
+declare void @cosh(...)
+
+; CHECK: declare void @coshf(...)
+declare void @coshf(...)
+
+; CHECK: declare void @coshl(...)
+declare void @coshl(...)
+
+; CHECK: declare void @cosl(...)
+declare void @cosl(...)
+
+; CHECK: declare void @ctermid(...)
+declare void @ctermid(...)
+
+; CHECK: declare void @exp(...)
+declare void @exp(...)
+
+; CHECK: declare void @exp2(...)
+declare void @exp2(...)
+
+; CHECK: declare void @exp2f(...)
+declare void @exp2f(...)
+
+; CHECK: declare void @exp2l(...)
+declare void @exp2l(...)
+
+; CHECK: declare void @expf(...)
+declare void @expf(...)
+
+; CHECK: declare void @expl(...)
+declare void @expl(...)
+
+; CHECK: declare void @expm1(...)
+declare void @expm1(...)
+
+; CHECK: declare void @expm1f(...)
+declare void @expm1f(...)
+
+; CHECK: declare void @expm1l(...)
+declare void @expm1l(...)
+
+; CHECK: declare void @fabs(...)
+declare void @fabs(...)
+
+; CHECK: declare void @fabsf(...)
+declare void @fabsf(...)
+
+; CHECK: declare void @fabsl(...)
+declare void @fabsl(...)
+
+; CHECK: declare void @fclose(...)
+declare void @fclose(...)
+
+; CHECK: declare void @fdopen(...)
+declare void @fdopen(...)
+
+; CHECK: declare void @feof(...)
+declare void @feof(...)
+
+; CHECK: declare void @ferror(...)
+declare void @ferror(...)
+
+; CHECK: declare void @fflush(...)
+declare void @fflush(...)
+
+; CHECK: declare void @ffs(...)
+declare void @ffs(...)
+
+; CHECK: declare void @ffsl(...)
+declare void @ffsl(...)
+
+; CHECK: declare void @ffsll(...)
+declare void @ffsll(...)
+
+; CHECK: declare void @fgetc(...)
+declare void @fgetc(...)
+
+; CHECK: declare void @fgetpos(...)
+declare void @fgetpos(...)
+
+; CHECK: declare void @fgets(...)
+declare void @fgets(...)
+
+; CHECK: declare void @fileno(...)
+declare void @fileno(...)
+
+; CHECK: declare void @flockfile(...)
+declare void @flockfile(...)
+
+; CHECK: declare void @floor(...)
+declare void @floor(...)
+
+; CHECK: declare void @floorf(...)
+declare void @floorf(...)
+
+; CHECK: declare void @floorl(...)
+declare void @floorl(...)
+
+; CHECK: declare void @fls(...)
+declare void @fls(...)
+
+; CHECK: declare void @flsl(...)
+declare void @flsl(...)
+
+; CHECK: declare void @flsll(...)
+declare void @flsll(...)
+
+; CHECK: declare void @fmax(...)
+declare void @fmax(...)
+
+; CHECK: declare void @fmaxf(...)
+declare void @fmaxf(...)
+
+; CHECK: declare void @fmaxl(...)
+declare void @fmaxl(...)
+
+; CHECK: declare void @fmin(...)
+declare void @fmin(...)
+
+; CHECK: declare void @fminf(...)
+declare void @fminf(...)
+
+; CHECK: declare void @fminl(...)
+declare void @fminl(...)
+
+; CHECK: declare void @fmod(...)
+declare void @fmod(...)
+
+; CHECK: declare void @fmodf(...)
+declare void @fmodf(...)
+
+; CHECK: declare void @fmodl(...)
+declare void @fmodl(...)
+
+; CHECK: declare void @fopen(...)
+declare void @fopen(...)
+
+; CHECK: declare void @fprintf(...)
+declare void @fprintf(...)
+
+; CHECK: declare void @fputc(...)
+declare void @fputc(...)
+
+; CHECK: declare void @fputs(...)
+declare void @fputs(...)
+
+; CHECK: declare void @fread(...)
+declare void @fread(...)
+
+; CHECK: declare void @free(...)
+declare void @free(...)
+
+; CHECK: declare void @frexp(...)
+declare void @frexp(...)
+
+; CHECK: declare void @frexpf(...)
+declare void @frexpf(...)
+
+; CHECK: declare void @frexpl(...)
+declare void @frexpl(...)
+
+; CHECK: declare void @fscanf(...)
+declare void @fscanf(...)
+
+; CHECK: declare void @fseek(...)
+declare void @fseek(...)
+
+; CHECK: declare void @fseeko(...)
+declare void @fseeko(...)
+
+; CHECK: declare void @fseeko64(...)
+declare void @fseeko64(...)
+
+; CHECK: declare void @fsetpos(...)
+declare void @fsetpos(...)
+
+; CHECK: declare void @fstat(...)
+declare void @fstat(...)
+
+; CHECK: declare void @fstat64(...)
+declare void @fstat64(...)
+
+; CHECK: declare void @fstatvfs(...)
+declare void @fstatvfs(...)
+
+; CHECK: declare void @fstatvfs64(...)
+declare void @fstatvfs64(...)
+
+; CHECK: declare void @ftell(...)
+declare void @ftell(...)
+
+; CHECK: declare void @ftello(...)
+declare void @ftello(...)
+
+; CHECK: declare void @ftello64(...)
+declare void @ftello64(...)
+
+; CHECK: declare void @ftrylockfile(...)
+declare void @ftrylockfile(...)
+
+; CHECK: declare void @funlockfile(...)
+declare void @funlockfile(...)
+
+; CHECK: declare void @fwrite(...)
+declare void @fwrite(...)
+
+; CHECK: declare void @getc(...)
+declare void @getc(...)
+
+; CHECK: declare void @getc_unlocked(...)
+declare void @getc_unlocked(...)
+
+; CHECK: declare void @getchar(...)
+declare void @getchar(...)
+
+; CHECK: declare void @getenv(...)
+declare void @getenv(...)
+
+; CHECK: declare void @getitimer(...)
+declare void @getitimer(...)
+
+; CHECK: declare void @getlogin_r(...)
+declare void @getlogin_r(...)
+
+; CHECK: declare void @getpwnam(...)
+declare void @getpwnam(...)
+
+; CHECK: declare void @gets(...)
+declare void @gets(...)
+
+; CHECK: declare void @gettimeofday(...)
+declare void @gettimeofday(...)
+
+; CHECK: declare void @isascii(...)
+declare void @isascii(...)
+
+; CHECK: declare void @isdigit(...)
+declare void @isdigit(...)
+
+; CHECK: declare void @labs(...)
+declare void @labs(...)
+
+; CHECK: declare void @lchown(...)
+declare void @lchown(...)
+
+; CHECK: declare void @ldexp(...)
+declare void @ldexp(...)
+
+; CHECK: declare void @ldexpf(...)
+declare void @ldexpf(...)
+
+; CHECK: declare void @ldexpl(...)
+declare void @ldexpl(...)
+
+; CHECK: declare void @llabs(...)
+declare void @llabs(...)
+
+; CHECK: declare void @log(...)
+declare void @log(...)
+
+; CHECK: declare void @log10(...)
+declare void @log10(...)
+
+; CHECK: declare void @log10f(...)
+declare void @log10f(...)
+
+; CHECK: declare void @log10l(...)
+declare void @log10l(...)
+
+; CHECK: declare void @log1p(...)
+declare void @log1p(...)
+
+; CHECK: declare void @log1pf(...)
+declare void @log1pf(...)
+
+; CHECK: declare void @log1pl(...)
+declare void @log1pl(...)
+
+; CHECK: declare void @log2(...)
+declare void @log2(...)
+
+; CHECK: declare void @log2f(...)
+declare void @log2f(...)
+
+; CHECK: declare void @log2l(...)
+declare void @log2l(...)
+
+; CHECK: declare void @logb(...)
+declare void @logb(...)
+
+; CHECK: declare void @logbf(...)
+declare void @logbf(...)
+
+; CHECK: declare void @logbl(...)
+declare void @logbl(...)
+
+; CHECK: declare void @logf(...)
+declare void @logf(...)
+
+; CHECK: declare void @logl(...)
+declare void @logl(...)
+
+; CHECK: declare void @lstat(...)
+declare void @lstat(...)
+
+; CHECK: declare void @lstat64(...)
+declare void @lstat64(...)
+
+; CHECK: declare void @malloc(...)
+declare void @malloc(...)
+
+; CHECK: declare void @memalign(...)
+declare void @memalign(...)
+
+; CHECK: declare void @memccpy(...)
+declare void @memccpy(...)
+
+; CHECK: declare void @memchr(...)
+declare void @memchr(...)
+
+; CHECK: declare void @memcmp(...)
+declare void @memcmp(...)
+
+; CHECK: declare void @memcpy(...)
+declare void @memcpy(...)
+
+; CHECK: declare void @mempcpy(...)
+declare void @mempcpy(...)
+
+; CHECK: declare void @memmove(...)
+declare void @memmove(...)
+
+; CHECK: declare void @memset(...)
+declare void @memset(...)
+
+; CHECK: declare void @memset_pattern16(...)
+declare void @memset_pattern16(...)
+
+; CHECK: declare void @mkdir(...)
+declare void @mkdir(...)
+
+; CHECK: declare void @mktime(...)
+declare void @mktime(...)
+
+; CHECK: declare void @modf(...)
+declare void @modf(...)
+
+; CHECK: declare void @modff(...)
+declare void @modff(...)
+
+; CHECK: declare void @modfl(...)
+declare void @modfl(...)
+
+; CHECK: declare void @nearbyint(...)
+declare void @nearbyint(...)
+
+; CHECK: declare void @nearbyintf(...)
+declare void @nearbyintf(...)
+
+; CHECK: declare void @nearbyintl(...)
+declare void @nearbyintl(...)
+
+; CHECK: declare void @open(...)
+declare void @open(...)
+
+; CHECK: declare void @open64(...)
+declare void @open64(...)
+
+; CHECK: declare void @opendir(...)
+declare void @opendir(...)
+
+; CHECK: declare void @pclose(...)
+declare void @pclose(...)
+
+; CHECK: declare void @perror(...)
+declare void @perror(...)
+
+; CHECK: declare void @popen(...)
+declare void @popen(...)
+
+; CHECK: declare void @posix_memalign(...)
+declare void @posix_memalign(...)
+
+; CHECK: declare void @pow(...)
+declare void @pow(...)
+
+; CHECK: declare void @powf(...)
+declare void @powf(...)
+
+; CHECK: declare void @powl(...)
+declare void @powl(...)
+
+; CHECK: declare void @pread(...)
+declare void @pread(...)
+
+; CHECK: declare void @printf(...)
+declare void @printf(...)
+
+; CHECK: declare void @putc(...)
+declare void @putc(...)
+
+; CHECK: declare void @putchar(...)
+declare void @putchar(...)
+
+; CHECK: declare void @puts(...)
+declare void @puts(...)
+
+; CHECK: declare void @pwrite(...)
+declare void @pwrite(...)
+
+; CHECK: declare void @qsort(...)
+declare void @qsort(...)
+
+; CHECK: declare void @read(...)
+declare void @read(...)
+
+; CHECK: declare void @readlink(...)
+declare void @readlink(...)
+
+; CHECK: declare void @realloc(...)
+declare void @realloc(...)
+
+; CHECK: declare void @reallocf(...)
+declare void @reallocf(...)
+
+; CHECK: declare void @realpath(...)
+declare void @realpath(...)
+
+; CHECK: declare void @remove(...)
+declare void @remove(...)
+
+; CHECK: declare void @rename(...)
+declare void @rename(...)
+
+; CHECK: declare void @rewind(...)
+declare void @rewind(...)
+
+; CHECK: declare void @rint(...)
+declare void @rint(...)
+
+; CHECK: declare void @rintf(...)
+declare void @rintf(...)
+
+; CHECK: declare void @rintl(...)
+declare void @rintl(...)
+
+; CHECK: declare void @rmdir(...)
+declare void @rmdir(...)
+
+; CHECK: declare void @round(...)
+declare void @round(...)
+
+; CHECK: declare void @roundf(...)
+declare void @roundf(...)
+
+; CHECK: declare void @roundl(...)
+declare void @roundl(...)
+
+; CHECK: declare void @scanf(...)
+declare void @scanf(...)
+
+; CHECK: declare void @setbuf(...)
+declare void @setbuf(...)
+
+; CHECK: declare void @setitimer(...)
+declare void @setitimer(...)
+
+; CHECK: declare void @setvbuf(...)
+declare void @setvbuf(...)
+
+; CHECK: declare void @sin(...)
+declare void @sin(...)
+
+; CHECK: declare void @sinf(...)
+declare void @sinf(...)
+
+; CHECK: declare void @sinh(...)
+declare void @sinh(...)
+
+; CHECK: declare void @sinhf(...)
+declare void @sinhf(...)
+
+; CHECK: declare void @sinhl(...)
+declare void @sinhl(...)
+
+; CHECK: declare void @sinl(...)
+declare void @sinl(...)
+
+; CHECK: declare void @snprintf(...)
+declare void @snprintf(...)
+
+; CHECK: declare void @sprintf(...)
+declare void @sprintf(...)
+
+; CHECK: declare void @sqrt(...)
+declare void @sqrt(...)
+
+; CHECK: declare void @sqrtf(...)
+declare void @sqrtf(...)
+
+; CHECK: declare void @sqrtl(...)
+declare void @sqrtl(...)
+
+; CHECK: declare void @sscanf(...)
+declare void @sscanf(...)
+
+; CHECK: declare void @stat(...)
+declare void @stat(...)
+
+; CHECK: declare void @stat64(...)
+declare void @stat64(...)
+
+; CHECK: declare void @statvfs(...)
+declare void @statvfs(...)
+
+; CHECK: declare void @statvfs64(...)
+declare void @statvfs64(...)
+
+; CHECK: declare void @stpcpy(...)
+declare void @stpcpy(...)
+
+; CHECK: declare void @stpncpy(...)
+declare void @stpncpy(...)
+
+; CHECK: declare void @strcasecmp(...)
+declare void @strcasecmp(...)
+
+; CHECK: declare void @strcat(...)
+declare void @strcat(...)
+
+; CHECK: declare void @strchr(...)
+declare void @strchr(...)
+
+; CHECK: declare void @strcmp(...)
+declare void @strcmp(...)
+
+; CHECK: declare void @strcoll(...)
+declare void @strcoll(...)
+
+; CHECK: declare void @strcpy(...)
+declare void @strcpy(...)
+
+; CHECK: declare void @strcspn(...)
+declare void @strcspn(...)
+
+; CHECK: declare void @strdup(...)
+declare void @strdup(...)
+
+; CHECK: declare void @strlen(...)
+declare void @strlen(...)
+
+; CHECK: declare void @strncasecmp(...)
+declare void @strncasecmp(...)
+
+; CHECK: declare void @strncat(...)
+declare void @strncat(...)
+
+; CHECK: declare void @strncmp(...)
+declare void @strncmp(...)
+
+; CHECK: declare void @strncpy(...)
+declare void @strncpy(...)
+
+; CHECK: declare void @strndup(...)
+declare void @strndup(...)
+
+; CHECK: declare void @strnlen(...)
+declare void @strnlen(...)
+
+; CHECK: declare void @strpbrk(...)
+declare void @strpbrk(...)
+
+; CHECK: declare void @strrchr(...)
+declare void @strrchr(...)
+
+; CHECK: declare void @strspn(...)
+declare void @strspn(...)
+
+; CHECK: declare void @strstr(...)
+declare void @strstr(...)
+
+; CHECK: declare void @strtod(...)
+declare void @strtod(...)
+
+; CHECK: declare void @strtof(...)
+declare void @strtof(...)
+
+; CHECK: declare void @strtok(...)
+declare void @strtok(...)
+
+; CHECK: declare void @strtok_r(...)
+declare void @strtok_r(...)
+
+; CHECK: declare void @strtol(...)
+declare void @strtol(...)
+
+; CHECK: declare void @strtold(...)
+declare void @strtold(...)
+
+; CHECK: declare void @strtoll(...)
+declare void @strtoll(...)
+
+; CHECK: declare void @strtoul(...)
+declare void @strtoul(...)
+
+; CHECK: declare void @strtoull(...)
+declare void @strtoull(...)
+
+; CHECK: declare void @strxfrm(...)
+declare void @strxfrm(...)
+
+; CHECK: declare void @system(...)
+declare void @system(...)
+
+; CHECK: declare void @tan(...)
+declare void @tan(...)
+
+; CHECK: declare void @tanf(...)
+declare void @tanf(...)
+
+; CHECK: declare void @tanh(...)
+declare void @tanh(...)
+
+; CHECK: declare void @tanhf(...)
+declare void @tanhf(...)
+
+; CHECK: declare void @tanhl(...)
+declare void @tanhl(...)
+
+; CHECK: declare void @tanl(...)
+declare void @tanl(...)
+
+; CHECK: declare void @times(...)
+declare void @times(...)
+
+; CHECK: declare void @tmpfile(...)
+declare void @tmpfile(...)
+
+; CHECK: declare void @tmpfile64(...)
+declare void @tmpfile64(...)
+
+; CHECK: declare void @toascii(...)
+declare void @toascii(...)
+
+; CHECK: declare void @trunc(...)
+declare void @trunc(...)
+
+; CHECK: declare void @truncf(...)
+declare void @truncf(...)
+
+; CHECK: declare void @truncl(...)
+declare void @truncl(...)
+
+; CHECK: declare void @uname(...)
+declare void @uname(...)
+
+; CHECK: declare void @ungetc(...)
+declare void @ungetc(...)
+
+; CHECK: declare void @unlink(...)
+declare void @unlink(...)
+
+; CHECK: declare void @unsetenv(...)
+declare void @unsetenv(...)
+
+; CHECK: declare void @utime(...)
+declare void @utime(...)
+
+; CHECK: declare void @utimes(...)
+declare void @utimes(...)
+
+; CHECK: declare void @valloc(...)
+declare void @valloc(...)
+
+; CHECK: declare void @vfprintf(...)
+declare void @vfprintf(...)
+
+; CHECK: declare void @vfscanf(...)
+declare void @vfscanf(...)
+
+; CHECK: declare void @vprintf(...)
+declare void @vprintf(...)
+
+; CHECK: declare void @vscanf(...)
+declare void @vscanf(...)
+
+; CHECK: declare void @vsnprintf(...)
+declare void @vsnprintf(...)
+
+; CHECK: declare void @vsprintf(...)
+declare void @vsprintf(...)
+
+; CHECK: declare void @vsscanf(...)
+declare void @vsscanf(...)
+
+; CHECK: declare void @write(...)
+declare void @write(...)

Added: llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll (added)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/norecurse_debug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt < %s -O2 -S | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "armv4t-none-unknown-eabi"
+
+ at foo.coefficient1 = internal unnamed_addr global i32* null, align 4, !dbg !0
+ at iirLow1 = external dso_local local_unnamed_addr global i32*, align 4
+
+; Function Attrs: nounwind
+define dso_local void @foo(i32 %i2) local_unnamed_addr #0 !dbg !2 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %i2, metadata !11, metadata !DIExpression()), !dbg !18
+  %0 = load i32*, i32** @iirLow1, align 4, !dbg !19
+  store i32 0, i32* %0, align 4, !dbg !24
+  %1 = ptrtoint i32* %0 to i32, !dbg !27
+  store i32 %1, i32* bitcast (i32** @foo.coefficient1 to i32*), align 4, !dbg !28
+  ret void, !dbg !29
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!7}
+!llvm.module.flags = !{!13, !14, !15, !16}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "coefficient1", scope: !2, file: !3, line: 5, type: !12, isLocal: true, isDefinition: true)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 3, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: true, unit: !7, retainedNodes: !10)
+!3 = !DIFile(filename: "norecurse_debug.c", directory: "/")
+!4 = !DISubroutineType(types: !5)
+!5 = !{null, !6}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
+!8 = !{}
+!9 = !{!0}
+!10 = !{!11}
+!11 = !DILocalVariable(name: "i2", arg: 1, scope: !2, file: !3, line: 3, type: !6)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 32)
+!13 = !{i32 2, !"Dwarf Version", i32 4}
+!14 = !{i32 2, !"Debug Info Version", i32 3}
+!15 = !{i32 1, !"wchar_size", i32 4}
+!16 = !{i32 1, !"min_enum_size", i32 4}
+!17 = !{!""}
+!18 = !DILocation(line: 3, column: 14, scope: !2)
+!19 = !DILocation(line: 7, column: 6, scope: !2)
+!24 = !DILocation(line: 7, column: 14, scope: !2)
+!27 = !DILocation(line: 9, column: 20, scope: !2)
+!28 = !DILocation(line: 9, column: 18, scope: !2)
+!29 = !DILocation(line: 10, column: 1, scope: !2)
+
+; CHECK: attributes #0 = { norecurse nounwind }
+; CHECK-NOT foo.coefficient1

Added: llvm/trunk/test/Transforms/InferFunctionAttrs/pr30455.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InferFunctionAttrs/pr30455.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InferFunctionAttrs/pr30455.ll (added)
+++ llvm/trunk/test/Transforms/InferFunctionAttrs/pr30455.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -inferattrs -S | FileCheck %s
+%struct.statvfs64 = type { i32 }
+
+; Function Attrs: norecurse uwtable
+define i32 @foo() {
+entry:
+  %st = alloca %struct.statvfs64, align 4
+  %0 = bitcast %struct.statvfs64* %st to i8*
+  ret i32 0
+}
+
+; CHECK: declare i32 @statvfs64(%struct.statvfs64*){{$}}
+declare i32 @statvfs64(%struct.statvfs64*)

Added: llvm/trunk/test/Transforms/Inline/2003-09-14-InlineValue.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2003-09-14-InlineValue.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2003-09-14-InlineValue.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2003-09-14-InlineValue.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -inline -disable-output
+
+declare i32 @External()
+
+define internal i32 @Callee() {
+        %I = call i32 @External( )              ; <i32> [#uses=2]
+        %J = add i32 %I, %I             ; <i32> [#uses=1]
+        ret i32 %J
+}
+
+define i32 @Caller() personality i32 (...)* @__gxx_personality_v0 {
+        %V = invoke i32 @Callee( )
+                        to label %Ok unwind label %Bad          ; <i32> [#uses=1]
+
+Ok:             ; preds = %0
+        ret i32 %V
+
+Bad:            ; preds = %0
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        ret i32 0
+}
+
+declare i32 @__gxx_personality_v0(...)
+

Added: llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodeInlineFail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodeInlineFail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodeInlineFail.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodeInlineFail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -inline -disable-output
+
+define i32 @main() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+        invoke void @__main( )
+                        to label %LongJmpBlkPost unwind label %LongJmpBlkPre
+
+LongJmpBlkPost:
+        ret i32 0
+
+LongJmpBlkPre:
+        %i.3 = phi i32 [ 0, %entry ]
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        ret i32 0
+}
+
+define void @__main() {
+        ret void
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -inline -disable-output
+
+define i32 @main() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+        invoke void @__main( )
+                        to label %Call2Invoke unwind label %LongJmpBlkPre
+
+Call2Invoke:            ; preds = %entry
+        br label %exit
+
+LongJmpBlkPre:          ; preds = %Call2Invoke, %entry
+        %i.3 = phi i32 [ 0, %entry ]
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        br label %exit
+
+exit:
+        ret i32 0
+}
+
+define void @__main() {
+        call void @__llvm_getGlobalCtors( )
+        call void @__llvm_getGlobalDtors( )
+        ret void
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @__llvm_getGlobalCtors()
+
+declare void @__llvm_getGlobalDtors()
+

Added: llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInNormalInvokeDest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInNormalInvokeDest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInNormalInvokeDest.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2003-09-22-PHINodesInNormalInvokeDest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -inline -disable-output
+
+define i32 @main() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+        invoke void @__main( )
+                        to label %else unwind label %RethrowExcept
+
+else:           ; preds = %LJDecisionBB, %entry
+        %i.2 = phi i32 [ 36, %entry ], [ %i.2, %LJDecisionBB ]          ; <i32> [#uses=1]
+        br label %LJDecisionBB
+
+LJDecisionBB:           ; preds = %else
+        br label %else
+
+RethrowExcept:          ; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        ret i32 0
+}
+
+define void @__main() {
+        ret void
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/2003-10-13-AllocaDominanceProblem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2003-10-13-AllocaDominanceProblem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2003-10-13-AllocaDominanceProblem.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2003-10-13-AllocaDominanceProblem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -inline -disable-output
+
+define i32 @reload() {
+reloadentry:
+        br label %A
+
+A:              ; preds = %reloadentry
+        call void @callee( )
+        ret i32 0
+}
+
+define internal void @callee() {
+entry:
+        %X = alloca i8, i32 0           ; <i8*> [#uses=0]
+        %Y = bitcast i32 0 to i32               ; <i32> [#uses=1]
+        %Z = alloca i8, i32 %Y          ; <i8*> [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -inline -disable-output
+
+; Inlining the first call caused the inliner function to delete the second
+; call.  Then the inliner tries to inline the second call, which no longer
+; exists.
+
+define internal void @Callee1() {
+        unreachable
+}
+
+define void @Callee2() {
+        ret void
+}
+
+define void @caller() {
+        call void @Callee1( )
+        call void @Callee2( )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/2004-04-20-InlineLinkOnce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2004-04-20-InlineLinkOnce.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2004-04-20-InlineLinkOnce.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2004-04-20-InlineLinkOnce.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -inline -prune-eh -disable-output
+
+define linkonce void @caller() {
+        call void @callee( )
+        ret void
+}
+
+define linkonce void @callee() {
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -inline -disable-output
+
+define i32 @test() {
+        unreachable
+}
+
+define i32 @caller() {
+        %X = call i32 @test( )          ; <i32> [#uses=1]
+        ret i32 %X
+}
+

Added: llvm/trunk/test/Transforms/Inline/2006-01-14-CallGraphUpdate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2006-01-14-CallGraphUpdate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2006-01-14-CallGraphUpdate.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2006-01-14-CallGraphUpdate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -inline -prune-eh -disable-output
+
+        %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>" = type { %"struct.std::locale::facet" }
+        %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >" = type { i32 (...)**, i32*, i32*, i32*, i32*, i32*, i32*, %"struct.std::locale" }
+        %"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"struct.std::locale" }
+        %"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 }
+        %"struct.std::ios_base::_Words" = type { i8*, i32 }
+        %"struct.std::locale" = type { %"struct.std::locale::_Impl"* }
+        %"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** }
+        %"struct.std::locale::facet" = type { i32 (...)**, i32 }
+        %"struct.std::ostreambuf_iterator<wchar_t,std::char_traits<wchar_t> >" = type { %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >"*, i32 }
+
+define void @_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE6do_putES3_RSt8ios_basewl(%"struct.std::ostreambuf_iterator<wchar_t,std::char_traits<wchar_t> >"* %agg.result, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"* %this, %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >"* %__s.0__, i32 %__s.1__, %"struct.std::ios_base"* %__io, i32 %__fill, i32 %__v) {
+entry:
+        tail call fastcc void @_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES3_S3_RSt8ios_basewT_( )
+        ret void
+}
+
+define fastcc void @_ZNKSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE13_M_insert_intIlEES3_S3_RSt8ios_basewT_() {
+entry:
+        %tmp.38 = shl i32 0, 3          ; <i32> [#uses=1]
+        %tmp.39 = alloca i8, i32 %tmp.38                ; <i8*> [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/2006-07-12-InlinePruneCGUpdate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2006-07-12-InlinePruneCGUpdate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2006-07-12-InlinePruneCGUpdate.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2006-07-12-InlinePruneCGUpdate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,840 @@
+; RUN: opt < %s -inline -prune-eh -disable-output
+; PR827
+ at _ZTV8CRjii = internal global [1 x i32 (...)*] [ i32 (...)* @_ZN8CRjii12NlFeeEPN5Jr7sE ]		; <[1 x i32 (...)*]*> [#uses=0]
+
+define internal i32 @_ZN8CRjii12NlFeeEPN5Jr7sE(...) {
+entry:
+	br i1 false, label %cond_true, label %cond_false179
+
+cond_true:		; preds = %entry
+	br label %bb9
+
+bb:		; preds = %cond_true14
+	br label %bb9
+
+bb9:		; preds = %bb, %cond_true
+	br i1 false, label %cond_true14, label %cond_false
+
+cond_true14:		; preds = %bb9
+	br label %bb
+
+cond_false:		; preds = %bb9
+	br label %bb15
+
+cond_next:		; No predecessors!
+	br label %bb15
+
+bb15:		; preds = %cond_next, %cond_false
+	br label %bb24
+
+bb17:		; preds = %cond_true29
+	br label %bb24
+
+bb24:		; preds = %bb17, %bb15
+	br i1 false, label %cond_true29, label %cond_false30
+
+cond_true29:		; preds = %bb24
+	br label %bb17
+
+cond_false30:		; preds = %bb24
+	br label %bb32
+
+cond_next31:		; No predecessors!
+	br label %bb32
+
+bb32:		; preds = %cond_next31, %cond_false30
+	br label %bb41
+
+bb34:		; preds = %cond_true46
+	br label %bb41
+
+bb41:		; preds = %bb34, %bb32
+	br i1 false, label %cond_true46, label %cond_false47
+
+cond_true46:		; preds = %bb41
+	br label %bb34
+
+cond_false47:		; preds = %bb41
+	br label %bb49
+
+cond_next48:		; No predecessors!
+	br label %bb49
+
+bb49:		; preds = %cond_next48, %cond_false47
+	br label %bb58
+
+bb51:		; preds = %cond_true63
+	br label %bb58
+
+bb58:		; preds = %bb51, %bb49
+	br i1 false, label %cond_true63, label %cond_false64
+
+cond_true63:		; preds = %bb58
+	br label %bb51
+
+cond_false64:		; preds = %bb58
+	br label %bb66
+
+cond_next65:		; No predecessors!
+	br label %bb66
+
+bb66:		; preds = %cond_next65, %cond_false64
+	br label %bb76
+
+bb68:		; preds = %cond_true81
+	br label %bb76
+
+bb76:		; preds = %bb68, %bb66
+	br i1 false, label %cond_true81, label %cond_false82
+
+cond_true81:		; preds = %bb76
+	br label %bb68
+
+cond_false82:		; preds = %bb76
+	br label %bb84
+
+cond_next83:		; No predecessors!
+	br label %bb84
+
+bb84:		; preds = %cond_next83, %cond_false82
+	br label %bb94
+
+bb86:		; preds = %cond_true99
+	br label %bb94
+
+bb94:		; preds = %bb86, %bb84
+	br i1 false, label %cond_true99, label %cond_false100
+
+cond_true99:		; preds = %bb94
+	br label %bb86
+
+cond_false100:		; preds = %bb94
+	br label %bb102
+
+cond_next101:		; No predecessors!
+	br label %bb102
+
+bb102:		; preds = %cond_next101, %cond_false100
+	br label %bb112
+
+bb104:		; preds = %cond_true117
+	br label %bb112
+
+bb112:		; preds = %bb104, %bb102
+	br i1 false, label %cond_true117, label %cond_false118
+
+cond_true117:		; preds = %bb112
+	br label %bb104
+
+cond_false118:		; preds = %bb112
+	br label %bb120
+
+cond_next119:		; No predecessors!
+	br label %bb120
+
+bb120:		; preds = %cond_next119, %cond_false118
+	br label %bb130
+
+bb122:		; preds = %cond_true135
+	br label %bb130
+
+bb130:		; preds = %bb122, %bb120
+	br i1 false, label %cond_true135, label %cond_false136
+
+cond_true135:		; preds = %bb130
+	br label %bb122
+
+cond_false136:		; preds = %bb130
+	br label %bb138
+
+cond_next137:		; No predecessors!
+	br label %bb138
+
+bb138:		; preds = %cond_next137, %cond_false136
+	br label %bb148
+
+bb140:		; preds = %cond_true153
+	call fastcc void @_Zjrf1( )
+	br label %bb148
+
+bb148:		; preds = %bb140, %bb138
+	br i1 false, label %cond_true153, label %cond_false154
+
+cond_true153:		; preds = %bb148
+	br label %bb140
+
+cond_false154:		; preds = %bb148
+	br label %bb156
+
+cond_next155:		; No predecessors!
+	br label %bb156
+
+bb156:		; preds = %cond_next155, %cond_false154
+	br label %bb166
+
+bb158:		; preds = %cond_true171
+	br label %bb166
+
+bb166:		; preds = %bb158, %bb156
+	br i1 false, label %cond_true171, label %cond_false172
+
+cond_true171:		; preds = %bb166
+	br label %bb158
+
+cond_false172:		; preds = %bb166
+	br label %bb174
+
+cond_next173:		; No predecessors!
+	br label %bb174
+
+bb174:		; preds = %cond_next173, %cond_false172
+	br label %cleanup
+
+cleanup:		; preds = %bb174
+	br label %finally
+
+finally:		; preds = %cleanup
+	br label %cond_next180
+
+cond_false179:		; preds = %entry
+	br label %cond_next180
+
+cond_next180:		; preds = %cond_false179, %finally
+	br label %return
+
+return:		; preds = %cond_next180
+	ret i32 0
+}
+
+define internal fastcc void @_Zjrf2() {
+entry:
+	br label %bb3
+
+bb:		; preds = %cond_true
+	br label %bb3
+
+bb3:		; preds = %bb, %entry
+	%tmp5 = load i8*, i8** null		; <i8*> [#uses=1]
+	%tmp = icmp ne i8* null, %tmp5		; <i1> [#uses=1]
+	br i1 %tmp, label %cond_true, label %cond_false
+
+cond_true:		; preds = %bb3
+	br label %bb
+
+cond_false:		; preds = %bb3
+	br label %bb6
+
+cond_next:		; No predecessors!
+	br label %bb6
+
+bb6:		; preds = %cond_next, %cond_false
+	br label %return
+
+return:		; preds = %bb6
+	ret void
+}
+
+define internal fastcc void @_Zjrf3() {
+entry:
+	call fastcc void @_Zjrf2( )
+	br label %return
+
+return:		; preds = %entry
+	ret void
+}
+
+define internal fastcc void @_Zjrf4() {
+entry:
+	br label %bb6
+
+bb:		; preds = %cond_true
+	br label %bb6
+
+bb6:		; preds = %bb, %entry
+	br i1 false, label %cond_true, label %cond_false
+
+cond_true:		; preds = %bb6
+	br label %bb
+
+cond_false:		; preds = %bb6
+	br label %bb8
+
+cond_next:		; No predecessors!
+	br label %bb8
+
+bb8:		; preds = %cond_next, %cond_false
+	br i1 false, label %cond_true9, label %cond_false12
+
+cond_true9:		; preds = %bb8
+	call fastcc void @_Zjrf3( )
+	br label %cond_next13
+
+cond_false12:		; preds = %bb8
+	br label %cond_next13
+
+cond_next13:		; preds = %cond_false12, %cond_true9
+	br label %return
+
+return:		; preds = %cond_next13
+	ret void
+}
+
+define internal fastcc void @_Zjrf5() {
+entry:
+	call fastcc void @_Zjrf4( )
+	br label %return
+
+return:		; preds = %entry
+	ret void
+}
+
+define internal fastcc void @_Zjrf6() {
+entry:
+	call fastcc void @_Zjrf5( )
+	br label %return
+
+return:		; preds = %entry
+	ret void
+}
+
+define internal fastcc void @_Zjrf7() {
+entry:
+	br label %cleanup
+
+cleanup:		; preds = %entry
+	br label %finally
+
+finally:		; preds = %cleanup
+	call fastcc void @_Zjrf6( )
+	br label %cleanup9
+
+cleanup9:		; preds = %finally
+	br label %finally8
+
+finally8:		; preds = %cleanup9
+	br label %cleanup11
+
+cleanup11:		; preds = %finally8
+	br label %finally10
+
+finally10:		; preds = %cleanup11
+	br label %finally23
+
+finally23:		; preds = %finally10
+	br label %return
+
+return:		; preds = %finally23
+	ret void
+}
+
+define internal fastcc void @_Zjrf11() {
+entry:
+	br label %bb7
+
+bb:		; preds = %cond_true
+	br label %bb7
+
+bb7:		; preds = %bb, %entry
+	br i1 false, label %cond_true, label %cond_false
+
+cond_true:		; preds = %bb7
+	br label %bb
+
+cond_false:		; preds = %bb7
+	br label %bb9
+
+cond_next:		; No predecessors!
+	br label %bb9
+
+bb9:		; preds = %cond_next, %cond_false
+	br label %return
+		; No predecessors!
+	br i1 false, label %cond_true12, label %cond_false15
+
+cond_true12:		; preds = %0
+	call fastcc void @_Zjrf3( )
+	br label %cond_next16
+
+cond_false15:		; preds = %0
+	br label %cond_next16
+
+cond_next16:		; preds = %cond_false15, %cond_true12
+	br label %return
+
+return:		; preds = %cond_next16, %bb9
+	ret void
+}
+
+define internal fastcc void @_Zjrf9() {
+entry:
+	call fastcc void @_Zjrf11( )
+	br label %return
+
+return:		; preds = %entry
+	ret void
+}
+
+define internal fastcc void @_Zjrf10() {
+entry:
+	call fastcc void @_Zjrf9( )
+	br label %return
+
+return:		; preds = %entry
+	ret void
+}
+
+define internal fastcc void @_Zjrf8() {
+entry:
+	br i1 false, label %cond_true, label %cond_false201
+
+cond_true:		; preds = %entry
+	br i1 false, label %cond_true36, label %cond_false
+
+cond_true36:		; preds = %cond_true
+	br label %cleanup
+
+cleanup:		; preds = %cond_true36
+	br label %finally
+
+finally:		; preds = %cleanup
+	br label %cond_next189
+
+cond_false:		; preds = %cond_true
+	br i1 false, label %cond_true99, label %cond_false137
+
+cond_true99:		; preds = %cond_false
+	br label %cleanup136
+
+cleanup136:		; preds = %cond_true99
+	br label %finally135
+
+finally135:		; preds = %cleanup136
+	br label %cond_next
+
+cond_false137:		; preds = %cond_false
+	call fastcc void @_Zjrf10( )
+	br label %cleanup188
+
+cleanup188:		; preds = %cond_false137
+	br label %finally187
+
+finally187:		; preds = %cleanup188
+	br label %cond_next
+
+cond_next:		; preds = %finally187, %finally135
+	br label %cond_next189
+
+cond_next189:		; preds = %cond_next, %finally
+	br label %cond_next202
+
+cond_false201:		; preds = %entry
+	br label %cond_next202
+
+cond_next202:		; preds = %cond_false201, %cond_next189
+	br label %return
+
+return:		; preds = %cond_next202
+	ret void
+}
+
+define internal fastcc void @_Zjrf1() {
+entry:
+	br label %bb492
+
+bb:		; preds = %cond_true499
+	br label %cleanup
+
+cleanup:		; preds = %bb
+	br label %finally
+
+finally:		; preds = %cleanup
+	br label %cleanup11
+
+cleanup11:		; preds = %finally
+	br label %finally10
+
+finally10:		; preds = %cleanup11
+	br i1 false, label %cond_true, label %cond_false286
+
+cond_true:		; preds = %finally10
+	br label %cleanup26
+
+cleanup26:		; preds = %cond_true
+	br label %finally25
+
+finally25:		; preds = %cleanup26
+	br label %bb30
+
+bb27:		; preds = %cond_true37
+	br label %bb30
+
+bb30:		; preds = %bb27, %finally25
+	br i1 false, label %cond_true37, label %cond_false
+
+cond_true37:		; preds = %bb30
+	br label %bb27
+
+cond_false:		; preds = %bb30
+	br label %bb38
+
+cond_next:		; No predecessors!
+	br label %bb38
+
+bb38:		; preds = %cond_next, %cond_false
+	br label %bb148
+
+bb40:		; preds = %cond_true156
+	br label %bb139
+
+bb41:		; preds = %cond_true142
+	call fastcc void @_Zjrf7( )
+	br label %bb105
+
+bb44:		; preds = %cond_true112
+	br label %bb74
+
+bb66:		; preds = %cond_true80
+	br label %bb74
+
+bb74:		; preds = %bb66, %bb44
+	br i1 false, label %cond_true80, label %cond_false81
+
+cond_true80:		; preds = %bb74
+	br label %bb66
+
+cond_false81:		; preds = %bb74
+	br label %bb83
+
+cond_next82:		; No predecessors!
+	br label %bb83
+
+bb83:		; preds = %cond_next82, %cond_false81
+	br label %cleanup97
+
+cleanup97:		; preds = %bb83
+	br label %finally96
+
+finally96:		; preds = %cleanup97
+	br label %cleanup99
+
+cleanup99:		; preds = %finally96
+	br label %finally98
+
+finally98:		; preds = %cleanup99
+	br label %bb105
+
+bb105:		; preds = %finally98, %bb41
+	br i1 false, label %cond_true112, label %cond_false113
+
+cond_true112:		; preds = %bb105
+	br label %bb44
+
+cond_false113:		; preds = %bb105
+	br label %bb115
+
+cond_next114:		; No predecessors!
+	br label %bb115
+
+bb115:		; preds = %cond_next114, %cond_false113
+	br i1 false, label %cond_true119, label %cond_false123
+
+cond_true119:		; preds = %bb115
+	call fastcc void @_Zjrf8( )
+	br label %cond_next124
+
+cond_false123:		; preds = %bb115
+	br label %cond_next124
+
+cond_next124:		; preds = %cond_false123, %cond_true119
+	br i1 false, label %cond_true131, label %cond_false132
+
+cond_true131:		; preds = %cond_next124
+	br label %cleanup135
+
+cond_false132:		; preds = %cond_next124
+	br label %cond_next133
+
+cond_next133:		; preds = %cond_false132
+	br label %cleanup136
+
+cleanup135:		; preds = %cond_true131
+	br label %done
+
+cleanup136:		; preds = %cond_next133
+	br label %finally134
+
+finally134:		; preds = %cleanup136
+	br label %bb139
+
+bb139:		; preds = %finally134, %bb40
+	br i1 false, label %cond_true142, label %cond_false143
+
+cond_true142:		; preds = %bb139
+	br label %bb41
+
+cond_false143:		; preds = %bb139
+	br label %bb145
+
+cond_next144:		; No predecessors!
+	br label %bb145
+
+bb145:		; preds = %cond_next144, %cond_false143
+	br label %bb148
+
+bb148:		; preds = %bb145, %bb38
+	br i1 false, label %cond_true156, label %cond_false157
+
+cond_true156:		; preds = %bb148
+	br label %bb40
+
+cond_false157:		; preds = %bb148
+	br label %bb159
+
+cond_next158:		; No predecessors!
+	br label %bb159
+
+bb159:		; preds = %cond_next158, %cond_false157
+	br label %done
+
+done:		; preds = %bb159, %cleanup135
+	br label %bb214
+
+bb185:		; preds = %cond_true218
+	br i1 false, label %cond_true193, label %cond_false206
+
+cond_true193:		; preds = %bb185
+	br label %cond_next211
+
+cond_false206:		; preds = %bb185
+	br label %cond_next211
+
+cond_next211:		; preds = %cond_false206, %cond_true193
+	br label %bb214
+
+bb214:		; preds = %cond_next211, %done
+	br i1 false, label %cond_true218, label %cond_false219
+
+cond_true218:		; preds = %bb214
+	br label %bb185
+
+cond_false219:		; preds = %bb214
+	br label %bb221
+
+cond_next220:		; No predecessors!
+	br label %bb221
+
+bb221:		; preds = %cond_next220, %cond_false219
+	br i1 false, label %cond_true236, label %cond_false245
+
+cond_true236:		; preds = %bb221
+	br label %cond_next249
+
+cond_false245:		; preds = %bb221
+	br label %cond_next249
+
+cond_next249:		; preds = %cond_false245, %cond_true236
+	br i1 false, label %cond_true272, label %cond_false277
+
+cond_true272:		; preds = %cond_next249
+	br label %cond_next278
+
+cond_false277:		; preds = %cond_next249
+	br label %cond_next278
+
+cond_next278:		; preds = %cond_false277, %cond_true272
+	br label %cleanup285
+
+cleanup285:		; preds = %cond_next278
+	br label %finally284
+
+finally284:		; preds = %cleanup285
+	br label %cond_next287
+
+cond_false286:		; preds = %finally10
+	br label %cond_next287
+
+cond_next287:		; preds = %cond_false286, %finally284
+	br i1 false, label %cond_true317, label %cond_false319
+
+cond_true317:		; preds = %cond_next287
+	br label %cond_next321
+
+cond_false319:		; preds = %cond_next287
+	br label %cond_next321
+
+cond_next321:		; preds = %cond_false319, %cond_true317
+	br label %bb348
+
+bb335:		; preds = %cond_true355
+	br label %bb348
+
+bb348:		; preds = %bb335, %cond_next321
+	br i1 false, label %cond_true355, label %cond_false356
+
+cond_true355:		; preds = %bb348
+	br label %bb335
+
+cond_false356:		; preds = %bb348
+	br label %bb358
+
+cond_next357:		; No predecessors!
+	br label %bb358
+
+bb358:		; preds = %cond_next357, %cond_false356
+	br i1 false, label %cond_true363, label %cond_false364
+
+cond_true363:		; preds = %bb358
+	br label %bb388
+
+cond_false364:		; preds = %bb358
+	br label %cond_next365
+
+cond_next365:		; preds = %cond_false364
+	br i1 false, label %cond_true370, label %cond_false371
+
+cond_true370:		; preds = %cond_next365
+	br label %bb388
+
+cond_false371:		; preds = %cond_next365
+	br label %cond_next372
+
+cond_next372:		; preds = %cond_false371
+	br i1 false, label %cond_true385, label %cond_false386
+
+cond_true385:		; preds = %cond_next372
+	br label %bb388
+
+cond_false386:		; preds = %cond_next372
+	br label %cond_next387
+
+cond_next387:		; preds = %cond_false386
+	br label %bb389
+
+bb388:		; preds = %cond_true385, %cond_true370, %cond_true363
+	br label %bb389
+
+bb389:		; preds = %bb388, %cond_next387
+	br i1 false, label %cond_true392, label %cond_false443
+
+cond_true392:		; preds = %bb389
+	br label %bb419
+
+bb402:		; preds = %cond_true425
+	br i1 false, label %cond_true406, label %cond_false412
+
+cond_true406:		; preds = %bb402
+	br label %cond_next416
+
+cond_false412:		; preds = %bb402
+	br label %cond_next416
+
+cond_next416:		; preds = %cond_false412, %cond_true406
+	br label %bb419
+
+bb419:		; preds = %cond_next416, %cond_true392
+	br i1 false, label %cond_true425, label %cond_false426
+
+cond_true425:		; preds = %bb419
+	br label %bb402
+
+cond_false426:		; preds = %bb419
+	br label %bb428
+
+cond_next427:		; No predecessors!
+	br label %bb428
+
+bb428:		; preds = %cond_next427, %cond_false426
+	br label %cond_next478
+
+cond_false443:		; preds = %bb389
+	br label %bb460
+
+bb450:		; preds = %cond_true466
+	br label %bb460
+
+bb460:		; preds = %bb450, %cond_false443
+	br i1 false, label %cond_true466, label %cond_false467
+
+cond_true466:		; preds = %bb460
+	br label %bb450
+
+cond_false467:		; preds = %bb460
+	br label %bb469
+
+cond_next468:		; No predecessors!
+	br label %bb469
+
+bb469:		; preds = %cond_next468, %cond_false467
+	br label %cond_next478
+
+cond_next478:		; preds = %bb469, %bb428
+	br label %cleanup485
+
+cleanup485:		; preds = %cond_next478
+	br label %finally484
+
+finally484:		; preds = %cleanup485
+	br label %cleanup487
+
+cleanup487:		; preds = %finally484
+	br label %finally486
+
+finally486:		; preds = %cleanup487
+	br label %cleanup489
+
+cleanup489:		; preds = %finally486
+	br label %finally488
+
+finally488:		; preds = %cleanup489
+	br label %bb492
+
+bb492:		; preds = %finally488, %entry
+	br i1 false, label %cond_true499, label %cond_false500
+
+cond_true499:		; preds = %bb492
+	br label %bb
+
+cond_false500:		; preds = %bb492
+	br label %bb502
+
+cond_next501:		; No predecessors!
+	br label %bb502
+
+bb502:		; preds = %cond_next501, %cond_false500
+	br label %return
+
+return:		; preds = %bb502
+	ret void
+}
+
+define internal fastcc void @_ZSt26__unguarded_insertion_sortIN9__gnu_cxx17__normal_iteratorIPSsSt6vectorISsSaISsEEEEEvT_S7_() {
+entry:
+	br label %bb12
+
+bb:		; preds = %cond_true
+	br label %cleanup
+
+cleanup:		; preds = %bb
+	br label %finally
+
+finally:		; preds = %cleanup
+	br label %bb12
+
+bb12:		; preds = %finally, %entry
+	br i1 false, label %cond_true, label %cond_false
+
+cond_true:		; preds = %bb12
+	br label %bb
+
+cond_false:		; preds = %bb12
+	br label %bb14
+
+cond_next:		; No predecessors!
+	br label %bb14
+
+bb14:		; preds = %cond_next, %cond_false
+	br label %return
+
+return:		; preds = %bb14
+	ret void
+}

Added: llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,252 @@
+; RUN: opt < %s -inline -prune-eh -disable-output
+; PR993
+target datalayout = "e-p:32:32"
+target triple = "i386-unknown-openbsd3.9"
+	%"struct.__gnu_cxx::__normal_iterator<char*,std::basic_string<char, std::char_traits<char>, std::allocator<char> > >" = type { i8* }
+	%"struct.__gnu_cxx::char_producer<char>" = type { i32 (...)** }
+	%struct.__sFILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, i8*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
+	%struct.__sbuf = type { i8*, i32 }
+	%"struct.std::__basic_file<char>" = type { %struct.__sFILE*, i1 }
+	%"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>" = type { %"struct.std::locale::facet" }
+	%"struct.std::bad_alloc" = type { %"struct.__gnu_cxx::char_producer<char>" }
+	%"struct.std::basic_filebuf<char,std::char_traits<char> >" = type { %"struct.std::basic_streambuf<char,std::char_traits<char> >", i32, %"struct.std::__basic_file<char>", i32, %union.__mbstate_t, %union.__mbstate_t, i8*, i32, i1, i1, i1, i1, i8, i8*, i8*, i1, %"struct.std::codecvt<char,char,__mbstate_t>"*, i8*, i32, i8*, i8* }
+	%"struct.std::basic_ios<char,std::char_traits<char> >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8, i1, %"struct.std::basic_streambuf<char,std::char_traits<char> >"*, %"struct.std::ctype<char>"*, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"*, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"* }
+	%"struct.std::basic_iostream<char,std::char_traits<char> >" = type { %"struct.std::locale::facet", %"struct.__gnu_cxx::char_producer<char>", %"struct.std::basic_ios<char,std::char_traits<char> >" }
+	%"struct.std::basic_ofstream<char,std::char_traits<char> >" = type { %"struct.__gnu_cxx::char_producer<char>", %"struct.std::basic_filebuf<char,std::char_traits<char> >", %"struct.std::basic_ios<char,std::char_traits<char> >" }
+	%"struct.std::basic_ostream<char,std::char_traits<char> >" = type { i32 (...)**, %"struct.std::basic_ios<char,std::char_traits<char> >" }
+	%"struct.std::basic_streambuf<char,std::char_traits<char> >" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"struct.std::locale" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.__gnu_cxx::__normal_iterator<char*,std::basic_string<char, std::char_traits<char>, std::allocator<char> > >" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep" = type { %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep_base" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep_base" = type { i32, i32, i32 }
+	%"struct.std::codecvt<char,char,__mbstate_t>" = type { %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>", i32* }
+	%"struct.std::ctype<char>" = type { %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>", i32*, i1, i32*, i32*, i32* }
+	%"struct.std::domain_error" = type { %"struct.std::logic_error" }
+	%"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %struct.__sbuf, [8 x %struct.__sbuf], i32, %struct.__sbuf*, %"struct.std::locale" }
+	%"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 }
+	%"struct.std::ios_base::_Words" = type { i8*, i32 }
+	%"struct.std::locale" = type { %"struct.std::locale::_Impl"* }
+	%"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** }
+	%"struct.std::locale::facet" = type { i32 (...)**, i32 }
+	%"struct.std::logic_error" = type { %"struct.__gnu_cxx::char_producer<char>", %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" }
+	%union.__mbstate_t = type { i64, [120 x i8] }
+ at .str_1 = external global [17 x i8]		; <[17 x i8]*> [#uses=0]
+ at .str_9 = external global [24 x i8]		; <[24 x i8]*> [#uses=0]
+
+define void @main() {
+entry:
+	call fastcc void @_ZNSt14basic_ofstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode( )
+	ret void
+}
+
+define fastcc void @_ZNSt14basic_ofstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode() {
+entry:
+	%tmp.6 = icmp eq %"struct.std::basic_filebuf<char,std::char_traits<char> >"* null, null		; <i1> [#uses=1]
+	br i1 %tmp.6, label %then, label %UnifiedReturnBlock
+
+then:		; preds = %entry
+	tail call fastcc void @_ZNSt9basic_iosIcSt11char_traitsIcEE8setstateESt12_Ios_Iostate( )
+	ret void
+
+UnifiedReturnBlock:		; preds = %entry
+	ret void
+}
+
+define fastcc void @_ZN10__cxxabiv111__terminateEPFvvE() {
+entry:
+	unreachable
+}
+
+define void @_ZNSdD0Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZThn8_NSdD1Ev() {
+entry:
+	ret void
+}
+
+define void @_ZNSt13basic_filebufIcSt11char_traitsIcEED0Ev() {
+entry:
+	ret void
+}
+
+define void @_ZNSt13basic_filebufIcSt11char_traitsIcEE9pbackfailEi() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSoD2Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSt9basic_iosIcSt11char_traitsIcEED2Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSt9basic_iosIcSt11char_traitsIcEE8setstateESt12_Ios_Iostate() {
+entry:
+	tail call fastcc void @_ZSt19__throw_ios_failurePKc( )
+	ret void
+}
+
+declare fastcc void @_ZNSaIcED1Ev()
+
+define fastcc void @_ZNSsC1EPKcRKSaIcE() {
+entry:
+	tail call fastcc void @_ZNSs16_S_construct_auxIPKcEEPcT_S3_RKSaIcE12__false_type( )
+	unreachable
+}
+
+define fastcc void @_ZSt14__convert_to_vIyEvPKcRT_RSt12_Ios_IostateRKPii() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEEC1Ej() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZSt19__throw_ios_failurePKc() {
+entry:
+	call fastcc void @_ZNSsC1EPKcRKSaIcE( )
+	unreachable
+}
+
+define void @_GLOBAL__D__ZSt23lexicographical_compareIPKaS1_EbT_S2_T0_S3_() {
+entry:
+	ret void
+}
+
+define void @_ZNSt9bad_allocD1Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZSt19__throw_logic_errorPKc() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	invoke fastcc void @_ZNSt11logic_errorC1ERKSs( )
+			to label %try_exit.0 unwind label %try_catch.0
+
+try_catch.0:		; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+	resume { i8*, i32 } %exn
+
+try_exit.0:		; preds = %entry
+	unreachable
+}
+
+define fastcc void @_ZNSt11logic_errorC1ERKSs() {
+entry:
+	call fastcc void @_ZNSsC1ERKSs( )
+	ret void
+}
+
+define void @_ZNSt12domain_errorD1Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZSt20__throw_length_errorPKc() {
+entry:
+	call fastcc void @_ZNSt12length_errorC1ERKSs( )
+	unreachable
+}
+
+define fastcc void @_ZNSt12length_errorC1ERKSs() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	invoke fastcc void @_ZNSsC1ERKSs( )
+			to label %_ZNSt11logic_errorC2ERKSs.exit unwind label %invoke_catch.i
+
+invoke_catch.i:		; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+	resume { i8*, i32 } %exn
+
+_ZNSt11logic_errorC2ERKSs.exit:		; preds = %entry
+	ret void
+}
+
+define fastcc void @_ZNSs4_Rep9_S_createEjRKSaIcE() {
+entry:
+	call fastcc void @_ZSt20__throw_length_errorPKc( )
+	unreachable
+}
+
+define fastcc void @_ZNSs12_S_constructIN9__gnu_cxx17__normal_iteratorIPcSsEEEES2_T_S4_RKSaIcESt20forward_iterator_tag() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSs16_S_construct_auxIPKcEEPcT_S3_RKSaIcE12__false_type() {
+entry:
+	br i1 false, label %then.1.i, label %endif.1.i
+
+then.1.i:		; preds = %entry
+	call fastcc void @_ZSt19__throw_logic_errorPKc( )
+	br label %endif.1.i
+
+endif.1.i:		; preds = %then.1.i, %entry
+	call fastcc void @_ZNSs4_Rep9_S_createEjRKSaIcE( )
+	unreachable
+}
+
+define fastcc void @_ZNSsC1ERKSs() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	call fastcc void @_ZNSs4_Rep7_M_grabERKSaIcES2_( )
+	invoke fastcc void @_ZNSaIcEC1ERKS_( )
+			to label %invoke_cont.1 unwind label %invoke_catch.1
+
+invoke_catch.1:		; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+	call fastcc void @_ZNSaIcED1Ev( )
+	resume { i8*, i32 } %exn
+
+invoke_cont.1:		; preds = %entry
+	call fastcc void @_ZNSaIcEC2ERKS_( )
+	ret void
+}
+
+define fastcc void @_ZNSaIcEC1ERKS_() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSs7replaceEN9__gnu_cxx17__normal_iteratorIPcSsEES2_jc() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSs4_Rep7_M_grabERKSaIcES2_() {
+entry:
+	br i1 false, label %else.i, label %cond_true
+
+cond_true:		; preds = %entry
+	ret void
+
+else.i:		; preds = %entry
+	tail call fastcc void @_ZNSs4_Rep9_S_createEjRKSaIcE( )
+	unreachable
+}
+
+define fastcc void @_ZNSaIcEC2ERKS_() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZN9__gnu_cxx12__pool_allocILb1ELi0EE8allocateEj() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZN9__gnu_cxx12__pool_allocILb1ELi0EE9_S_refillEj() {
+entry:
+	unreachable
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,343 @@
+; RUN: opt < %s -inline -prune-eh -disable-output
+; PR992
+target datalayout = "e-p:32:32"
+target triple = "i686-pc-linux-gnu"
+	%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i32, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i32, [52 x i8] }
+	%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
+	%"struct.__cxxabiv1::__array_type_info" = type { %"struct.std::type_info" }
+	%"struct.__cxxabiv1::__si_class_type_info" = type { %"struct.__cxxabiv1::__array_type_info", %"struct.__cxxabiv1::__array_type_info"* }
+	%"struct.__gnu_cxx::_Rope_rep_alloc_base<char,std::allocator<char>, true>" = type { i32 }
+	%"struct.__gnu_cxx::__normal_iterator<char*,std::basic_string<char, std::char_traits<char>, std::allocator<char> > >" = type { i8* }
+	%"struct.__gnu_cxx::__normal_iterator<const wchar_t*,std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >" = type { i32* }
+	%"struct.__gnu_cxx::char_producer<char>" = type { i32 (...)** }
+	%"struct.__gnu_cxx::stdio_sync_filebuf<char,std::char_traits<char> >" = type { %"struct.std::basic_streambuf<char,std::char_traits<char> >", %struct._IO_FILE*, i32 }
+	%"struct.__gnu_cxx::stdio_sync_filebuf<wchar_t,std::char_traits<wchar_t> >" = type { %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >", %struct._IO_FILE*, i32 }
+	%struct.__locale_struct = type { [13 x %struct.locale_data*], i16*, i32*, i32*, [13 x i8*] }
+	%struct.__mbstate_t = type { i32, %"struct.__gnu_cxx::_Rope_rep_alloc_base<char,std::allocator<char>, true>" }
+	%struct.locale_data = type opaque
+	%"struct.std::__basic_file<char>" = type { %struct._IO_FILE*, i1 }
+	%"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>" = type { %"struct.std::locale::facet" }
+	%"struct.std::basic_filebuf<char,std::char_traits<char> >" = type { %"struct.std::basic_streambuf<char,std::char_traits<char> >", i32, %"struct.std::__basic_file<char>", i32, %struct.__mbstate_t, %struct.__mbstate_t, i8*, i32, i1, i1, i1, i1, i8, i8*, i8*, i1, %"struct.std::codecvt<char,char,__mbstate_t>"*, i8*, i32, i8*, i8* }
+	%"struct.std::basic_filebuf<wchar_t,std::char_traits<wchar_t> >" = type { %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >", i32, %"struct.std::__basic_file<char>", i32, %struct.__mbstate_t, %struct.__mbstate_t, i32*, i32, i1, i1, i1, i1, i32, i32*, i32*, i1, %"struct.std::codecvt<char,char,__mbstate_t>"*, i8*, i32, i8*, i8* }
+	%"struct.std::basic_fstream<char,std::char_traits<char> >" = type { { %"struct.std::locale::facet", %"struct.__gnu_cxx::char_producer<char>" }, %"struct.std::basic_filebuf<char,std::char_traits<char> >", %"struct.std::basic_ios<char,std::char_traits<char> >" }
+	%"struct.std::basic_fstream<wchar_t,std::char_traits<wchar_t> >" = type { { %"struct.std::locale::facet", %"struct.__gnu_cxx::char_producer<char>" }, %"struct.std::basic_filebuf<wchar_t,std::char_traits<wchar_t> >", %"struct.std::basic_ios<wchar_t,std::char_traits<wchar_t> >" }
+	%"struct.std::basic_ios<char,std::char_traits<char> >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8, i1, %"struct.std::basic_streambuf<char,std::char_traits<char> >"*, %"struct.std::ctype<char>"*, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"*, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"* }
+	%"struct.std::basic_ios<wchar_t,std::char_traits<wchar_t> >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream<wchar_t,std::char_traits<wchar_t> >"*, i32, i1, %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >"*, %"struct.std::codecvt<char,char,__mbstate_t>"*, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"*, %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>"* }
+	%"struct.std::basic_iostream<wchar_t,std::char_traits<wchar_t> >" = type { %"struct.std::locale::facet", %"struct.__gnu_cxx::char_producer<char>", %"struct.std::basic_ios<wchar_t,std::char_traits<wchar_t> >" }
+	%"struct.std::basic_ostream<char,std::char_traits<char> >" = type { i32 (...)**, %"struct.std::basic_ios<char,std::char_traits<char> >" }
+	%"struct.std::basic_ostream<wchar_t,std::char_traits<wchar_t> >" = type { i32 (...)**, %"struct.std::basic_ios<wchar_t,std::char_traits<wchar_t> >" }
+	%"struct.std::basic_streambuf<char,std::char_traits<char> >" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"struct.std::locale" }
+	%"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >" = type { i32 (...)**, i32*, i32*, i32*, i32*, i32*, i32*, %"struct.std::locale" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" = type { %"struct.__gnu_cxx::__normal_iterator<char*,std::basic_string<char, std::char_traits<char>, std::allocator<char> > >" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep" = type { %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep_base" }
+	%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Rep_base" = type { i32, i32, i32 }
+	%"struct.std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >" = type { %"struct.__gnu_cxx::__normal_iterator<const wchar_t*,std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > >" }
+	%"struct.std::codecvt<char,char,__mbstate_t>" = type { %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>", %struct.__locale_struct* }
+	%"struct.std::collate<char>" = type { %"struct.std::locale::facet", %struct.__locale_struct* }
+	%"struct.std::collate_byname<char>" = type { %"struct.std::collate<char>" }
+	%"struct.std::ctype<char>" = type { %"struct.std::__codecvt_abstract_base<char,char,__mbstate_t>", %struct.__locale_struct*, i1, i32*, i32*, i16* }
+	%"struct.std::ctype_byname<char>" = type { %"struct.std::ctype<char>" }
+	%"struct.std::domain_error" = type { %"struct.std::logic_error" }
+	%"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"struct.std::locale" }
+	%"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 }
+	%"struct.std::ios_base::_Words" = type { i8*, i32 }
+	%"struct.std::istreambuf_iterator<char,std::char_traits<char> >" = type { %"struct.std::basic_streambuf<char,std::char_traits<char> >"*, i32 }
+	%"struct.std::istreambuf_iterator<wchar_t,std::char_traits<wchar_t> >" = type { %"struct.std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >"*, i32 }
+	%"struct.std::locale" = type { %"struct.std::locale::_Impl"* }
+	%"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** }
+	%"struct.std::locale::facet" = type { i32 (...)**, i32 }
+	%"struct.std::logic_error" = type { %"struct.__gnu_cxx::char_producer<char>", %"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >" }
+	%"struct.std::type_info" = type { i32 (...)**, i8* }
+ at .str_11 = external global [42 x i8]		; <[42 x i8]*> [#uses=0]
+ at .str_9 = external global [24 x i8]		; <[24 x i8]*> [#uses=0]
+ at .str_1 = external global [17 x i8]		; <[17 x i8]*> [#uses=0]
+
+define void @main() {
+entry:
+	tail call fastcc void @_ZNSolsEi( )
+	ret void
+}
+
+define fastcc void @_ZNSolsEi() {
+entry:
+	%tmp.22 = icmp eq i32 0, 0		; <i1> [#uses=1]
+	br i1 %tmp.22, label %else, label %then
+
+then:		; preds = %entry
+	ret void
+
+else:		; preds = %entry
+	tail call fastcc void @_ZNSolsEl( )
+	ret void
+}
+
+define void @_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSt9basic_iosIcSt11char_traitsIcEE8setstateESt12_Ios_Iostate() {
+entry:
+	tail call fastcc void @_ZSt19__throw_ios_failurePKc( )
+	ret void
+}
+
+define fastcc void @_ZNSo3putEc() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSolsEl() {
+entry:
+	%tmp.21.i = icmp eq %"struct.std::basic_ostream<char,std::char_traits<char> >"* null, null		; <i1> [#uses=1]
+	br i1 %tmp.21.i, label %endif.0.i, label %shortcirc_next.i
+
+shortcirc_next.i:		; preds = %entry
+	ret void
+
+endif.0.i:		; preds = %entry
+	call fastcc void @_ZNSt9basic_iosIcSt11char_traitsIcEE8setstateESt12_Ios_Iostate( )
+	ret void
+}
+
+define fastcc void @_ZSt19__throw_ios_failurePKc() {
+entry:
+	call fastcc void @_ZNSsC1EPKcRKSaIcE( )
+	ret void
+}
+
+define fastcc void @_ZNSt8ios_baseD2Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZN9__gnu_cxx18stdio_sync_filebufIwSt11char_traitsIwEE5uflowEv() {
+entry:
+	unreachable
+}
+
+define void @_ZN9__gnu_cxx18stdio_sync_filebufIcSt11char_traitsIcEED1Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZNSt15basic_streambufIcSt11char_traitsIcEE6setbufEPci() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZSt9use_facetISt5ctypeIcEERKT_RKSt6locale() {
+entry:
+	ret void
+}
+
+declare fastcc void @_ZNSaIcED1Ev()
+
+define fastcc void @_ZSt19__throw_logic_errorPKc() {
+entry:
+	call fastcc void @_ZNSt11logic_errorC1ERKSs( )
+	ret void
+}
+
+define fastcc void @_ZNSs4_Rep9_S_createEjRKSaIcE() {
+entry:
+	br i1 false, label %then.0, label %endif.0
+
+then.0:		; preds = %entry
+	call fastcc void @_ZSt20__throw_length_errorPKc( )
+	ret void
+
+endif.0:		; preds = %entry
+	ret void
+}
+
+define fastcc void @_ZSt20__throw_length_errorPKc() {
+entry:
+	call fastcc void @_ZNSt12length_errorC1ERKSs( )
+	ret void
+}
+
+define fastcc void @_ZNSs16_S_construct_auxIPKcEEPcT_S3_RKSaIcE12__false_type() {
+entry:
+	br i1 false, label %then.1.i, label %endif.1.i
+
+then.1.i:		; preds = %entry
+	call fastcc void @_ZSt19__throw_logic_errorPKc( )
+	ret void
+
+endif.1.i:		; preds = %entry
+	call fastcc void @_ZNSs4_Rep9_S_createEjRKSaIcE( )
+	unreachable
+}
+
+define fastcc void @_ZNSsC1ERKSs() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	call fastcc void @_ZNSs4_Rep7_M_grabERKSaIcES2_( )
+	invoke fastcc void @_ZNSaIcEC1ERKS_( )
+			to label %invoke_cont.1 unwind label %invoke_catch.1
+
+invoke_catch.1:		; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+	call fastcc void @_ZNSaIcED1Ev( )
+	resume { i8*, i32 } %exn
+
+invoke_cont.1:		; preds = %entry
+	call fastcc void @_ZNSaIcEC2ERKS_( )
+	ret void
+}
+
+define fastcc void @_ZNSs7reserveEj() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSaIcEC1ERKS_() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSs4_Rep7_M_grabERKSaIcES2_() {
+entry:
+	br i1 false, label %else.i, label %cond_true
+
+cond_true:		; preds = %entry
+	ret void
+
+else.i:		; preds = %entry
+	tail call fastcc void @_ZNSs4_Rep9_S_createEjRKSaIcE( )
+	ret void
+}
+
+define fastcc void @_ZNSsC1EPKcRKSaIcE() {
+entry:
+	tail call fastcc void @_ZNSs16_S_construct_auxIPKcEEPcT_S3_RKSaIcE12__false_type( )
+	unreachable
+}
+
+define fastcc void @_ZNSaIcEC2ERKS_() {
+entry:
+	ret void
+}
+
+define void @_ZNSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEED1Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZNSt14collate_bynameIcED1Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZNKSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE6do_getES3_S3_RSt8ios_baseRSt12_Ios_IostateRy() {
+entry:
+	ret void
+}
+
+define void @_ZNSt23__codecvt_abstract_baseIcc11__mbstate_tED1Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZNSt12ctype_bynameIcED0Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSt8messagesIwEC1Ej() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZSt14__convert_to_vIlEvPKcRT_RSt12_Ios_IostateRKP15__locale_structi() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSt8time_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEEC1Ej() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEEC1Ej() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNKSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE16_M_extract_floatES3_S3_RSt8ios_baseRSt12_Ios_IostateRSs() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSbIwSt11char_traitsIwESaIwEE4swapERS2_() {
+entry:
+	ret void
+}
+
+define void @_ZNSt14basic_iostreamIwSt11char_traitsIwEED0Ev() {
+entry:
+	unreachable
+}
+
+define void @_ZNSt15basic_streambufIcSt11char_traitsIcEE9showmanycEv() {
+entry:
+	ret void
+}
+
+define void @_ZNSt9exceptionD0Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSt11logic_errorC1ERKSs() {
+entry:
+	call fastcc void @_ZNSsC1ERKSs( )
+	ret void
+}
+
+define fastcc void @_ZNSt11logic_errorD2Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSt12length_errorC1ERKSs() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+	invoke fastcc void @_ZNSsC1ERKSs( )
+			to label %_ZNSt11logic_errorC2ERKSs.exit unwind label %invoke_catch.i
+
+invoke_catch.i:		; preds = %entry
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+	resume { i8*, i32 } %exn
+
+_ZNSt11logic_errorC2ERKSs.exit:		; preds = %entry
+	ret void
+}
+
+define void @_ZNK10__cxxabiv120__si_class_type_info20__do_find_public_srcEiPKvPKNS_17__class_type_infoES2_() {
+entry:
+	ret void
+}
+
+define fastcc void @_ZNSbIwSt11char_traitsIwESaIwEE16_S_construct_auxIPKwEEPwT_S7_RKS1_12__false_type() {
+entry:
+	ret void
+}
+
+define void @_ZTv0_n12_NSt13basic_fstreamIwSt11char_traitsIwEED1Ev() {
+entry:
+	ret void
+}
+
+define void @_ZNSt13basic_fstreamIcSt11char_traitsIcEED1Ev() {
+entry:
+	unreachable
+}
+
+define fastcc void @_ZNSt5ctypeIcEC1EPKtbj() {
+entry:
+	ret void
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/2007-04-15-InlineEH.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2007-04-15-InlineEH.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2007-04-15-InlineEH.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2007-04-15-InlineEH.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+; PR1335
+
+target triple = "i686-pc-linux-gnu"
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @a()
+
+declare void @b()
+
+declare void @c()
+
+define void @f() {
+; CHECK-LABEL: define void @f()
+entry:
+  call void asm "rdtsc\0A\09movl %eax, $0\0A\09movl %edx, $1", "=*imr,=*imr,~{dirflag},~{fpsr},~{flags},~{dx},~{ax}"( i32* null, i32* null ) nounwind
+; CHECK: call void asm
+  unreachable
+}
+
+define void @g() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: define void @g() personality i32 (...)* @__gxx_personality_v0
+entry:
+  invoke void @a() to label %invcont1 unwind label %cleanup
+; CHECK-NOT: {{call|invoke}}
+; CHECK: invoke void @a()
+
+invcont1:
+  invoke void @b() to label %invcont2 unwind label %cleanup
+; CHECK-NOT: {{call|invoke}}
+; CHECK: invoke void @b()
+
+invcont2:
+  invoke void @c() to label %invcont3 unwind label %cleanup
+; CHECK-NOT: {{call|invoke}}
+; CHECK: invoke void @c()
+
+invcont3:
+  invoke void @f() to label %invcont4 unwind label %cleanup
+; CHECK-NOT: {{call|invoke}}
+; CHECK: call void asm
+; CHECK-NOT: {{call|invoke}}
+
+invcont4:
+  ret void
+
+cleanup:
+  %ex = landingpad {i8*, i32} cleanup
+  resume { i8*, i32 } %ex
+}
+
+define void @h() {
+; CHECK-LABEL: define void @h() personality i32 (...)* @__gxx_personality_v0
+entry:
+  call void @g()
+; CHECK-NOT: {{call|invoke}}
+; CHECK: invoke void @a()
+; CHECK-NOT: {{call|invoke}}
+; CHECK: invoke void @b()
+; CHECK-NOT: {{call|invoke}}
+; CHECK: invoke void @c()
+; CHECK-NOT: {{call|invoke}}
+; CHECK: call void asm
+; CHECK-NOT: {{call|invoke}}
+
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/2007-06-25-WeakInline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2007-06-25-WeakInline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2007-06-25-WeakInline.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2007-06-25-WeakInline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; 'bar' can be overridden at link-time, don't inline it.
+define weak void @bar() {
+; CHECK-LABEL: define weak void @bar()
+entry:
+  ret void
+}
+
+define void @foo() {
+; CHECK-LABEL: define void @foo()
+entry:
+  tail call void @bar()
+; CHECK: tail call void @bar()
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+declare i1 @extern()
+
+define internal i32 @test() {
+; CHECK-NOT: define .* @test()
+entry:
+  %n = call i1 @extern()
+  br i1 %n, label %r, label %u
+
+r:
+  ret i32 0
+
+u:
+  unreachable
+}
+
+define i32 @caller() {
+; CHECK-LABEL: define i32 @caller()
+entry:
+  %X = call i32 @test() nounwind
+; CHECK-NOT: call i32 @test()
+; CHECK: call i1 @extern() #0
+; CHECK: br i1 %{{.*}}, label %[[R:.*]], label %[[U:.*]]
+
+; CHECK: [[U]]:
+; CHECK:   unreachable
+
+; CHECK: [[R]]:
+  ret i32 %X
+; CHECK:   ret i32 0
+}
+
+; CHECK: attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/Inline/2008-09-02-NoInline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2008-09-02-NoInline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2008-09-02-NoInline.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2008-09-02-NoInline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+define i32 @fn2() noinline {
+; CHECK-LABEL: define i32 @fn2()
+entry:
+  ret i32 1
+}
+
+define i32 @fn3() {
+; CHECK-LABEL: define i32 @fn3()
+entry:
+  %r = call i32 @fn2()
+; CHECK: call i32 @fn2()
+
+  ret i32 %r
+}

Added: llvm/trunk/test/Transforms/Inline/2009-01-08-NoInlineDynamicAlloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2009-01-08-NoInlineDynamicAlloca.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2009-01-08-NoInlineDynamicAlloca.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2009-01-08-NoInlineDynamicAlloca.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+; Do not inline calls with variable-sized alloca.
+
+ at q = common global i8* null
+
+define i8* @a(i32 %i) nounwind {
+; CHECK-LABEL: define i8* @a
+entry:
+  %i_addr = alloca i32
+  %retval = alloca i8*
+  %p = alloca i8*
+  %"alloca point" = bitcast i32 0 to i32
+  store i32 %i, i32* %i_addr
+  %0 = load i32, i32* %i_addr, align 4
+  %1 = alloca i8, i32 %0
+  store i8* %1, i8** %p, align 4
+  %2 = load i8*, i8** %p, align 4
+  store i8* %2, i8** @q, align 4
+  br label %return
+
+return:
+  %retval1 = load i8*, i8** %retval
+  ret i8* %retval1
+}
+
+define void @b(i32 %i) nounwind {
+; CHECK-LABEL: define void @b
+entry:
+  %i_addr = alloca i32
+  %"alloca point" = bitcast i32 0 to i32
+  store i32 %i, i32* %i_addr
+  %0 = load i32, i32* %i_addr, align 4
+  %1 = call i8* @a(i32 %0) nounwind
+; CHECK: call i8* @a
+  br label %return
+
+return:
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/2009-01-13-RecursiveInlineCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2009-01-13-RecursiveInlineCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2009-01-13-RecursiveInlineCrash.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2009-01-13-RecursiveInlineCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,293 @@
+; RUN: opt < %s -inline -argpromotion -disable-output
+; ModuleID = '<stdin>'
+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-darwin9.6"
+	%struct.quad_struct = type { i32, i32, %struct.quad_struct*, %struct.quad_struct*, %struct.quad_struct*, %struct.quad_struct*, %struct.quad_struct* }
+ at NumNodes = external global i32		; <i32*> [#uses=0]
+@"\01LC" = external constant [43 x i8]		; <[43 x i8]*> [#uses=0]
+@"\01LC1" = external constant [19 x i8]		; <[19 x i8]*> [#uses=0]
+@"\01LC2" = external constant [17 x i8]		; <[17 x i8]*> [#uses=0]
+
+declare i32 @dealwithargs(i32, i8** nocapture) nounwind
+
+declare i32 @atoi(i8*)
+
+define internal fastcc i32 @adj(i32 %d, i32 %ct) nounwind readnone {
+entry:
+	switch i32 %d, label %return [
+		i32 0, label %bb
+		i32 1, label %bb10
+		i32 2, label %bb5
+		i32 3, label %bb15
+	]
+
+bb:		; preds = %entry
+	switch i32 %ct, label %bb3 [
+		i32 1, label %return
+		i32 0, label %return
+	]
+
+bb3:		; preds = %bb
+	ret i32 0
+
+bb5:		; preds = %entry
+	switch i32 %ct, label %bb8 [
+		i32 3, label %return
+		i32 2, label %return
+	]
+
+bb8:		; preds = %bb5
+	ret i32 0
+
+bb10:		; preds = %entry
+	switch i32 %ct, label %bb13 [
+		i32 1, label %return
+		i32 3, label %return
+	]
+
+bb13:		; preds = %bb10
+	ret i32 0
+
+bb15:		; preds = %entry
+	switch i32 %ct, label %bb18 [
+		i32 2, label %return
+		i32 0, label %return
+	]
+
+bb18:		; preds = %bb15
+	ret i32 0
+
+return:		; preds = %bb15, %bb15, %bb10, %bb10, %bb5, %bb5, %bb, %bb, %entry
+	ret i32 1
+}
+
+declare fastcc i32 @reflect(i32, i32) nounwind readnone
+
+declare i32 @CountTree(%struct.quad_struct* nocapture) nounwind readonly
+
+define internal fastcc %struct.quad_struct* @child(%struct.quad_struct* nocapture %tree, i32 %ct) nounwind readonly {
+entry:
+	switch i32 %ct, label %bb5 [
+		i32 0, label %bb1
+		i32 1, label %bb
+		i32 2, label %bb3
+		i32 3, label %bb2
+	]
+
+bb:		; preds = %entry
+	%0 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 3		; <%struct.quad_struct**> [#uses=1]
+	%1 = load %struct.quad_struct*, %struct.quad_struct** %0, align 4		; <%struct.quad_struct*> [#uses=1]
+	ret %struct.quad_struct* %1
+
+bb1:		; preds = %entry
+	%2 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 2		; <%struct.quad_struct**> [#uses=1]
+	%3 = load %struct.quad_struct*, %struct.quad_struct** %2, align 4		; <%struct.quad_struct*> [#uses=1]
+	ret %struct.quad_struct* %3
+
+bb2:		; preds = %entry
+	%4 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 5		; <%struct.quad_struct**> [#uses=1]
+	%5 = load %struct.quad_struct*, %struct.quad_struct** %4, align 4		; <%struct.quad_struct*> [#uses=1]
+	ret %struct.quad_struct* %5
+
+bb3:		; preds = %entry
+	%6 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 4		; <%struct.quad_struct**> [#uses=1]
+	%7 = load %struct.quad_struct*, %struct.quad_struct** %6, align 4		; <%struct.quad_struct*> [#uses=1]
+	ret %struct.quad_struct* %7
+
+bb5:		; preds = %entry
+	ret %struct.quad_struct* null
+}
+
+define internal fastcc %struct.quad_struct* @gtequal_adj_neighbor(%struct.quad_struct* nocapture %tree, i32 %d) nounwind readonly {
+entry:
+	%0 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 6		; <%struct.quad_struct**> [#uses=1]
+	%1 = load %struct.quad_struct*, %struct.quad_struct** %0, align 4		; <%struct.quad_struct*> [#uses=4]
+	%2 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 1		; <i32*> [#uses=1]
+	%3 = load i32, i32* %2, align 4		; <i32> [#uses=2]
+	%4 = icmp eq %struct.quad_struct* %1, null		; <i1> [#uses=1]
+	br i1 %4, label %bb3, label %bb
+
+bb:		; preds = %entry
+	%5 = call fastcc i32 @adj(i32 %d, i32 %3) nounwind		; <i32> [#uses=1]
+	%6 = icmp eq i32 %5, 0		; <i1> [#uses=1]
+	br i1 %6, label %bb3, label %bb1
+
+bb1:		; preds = %bb
+	%7 = call fastcc %struct.quad_struct* @gtequal_adj_neighbor(%struct.quad_struct* %1, i32 %d) nounwind		; <%struct.quad_struct*> [#uses=1]
+	br label %bb3
+
+bb3:		; preds = %bb1, %bb, %entry
+	%q.0 = phi %struct.quad_struct* [ %7, %bb1 ], [ %1, %bb ], [ %1, %entry ]		; <%struct.quad_struct*> [#uses=4]
+	%8 = icmp eq %struct.quad_struct* %q.0, null		; <i1> [#uses=1]
+	br i1 %8, label %bb7, label %bb4
+
+bb4:		; preds = %bb3
+	%9 = getelementptr %struct.quad_struct, %struct.quad_struct* %q.0, i32 0, i32 0		; <i32*> [#uses=1]
+	%10 = load i32, i32* %9, align 4		; <i32> [#uses=1]
+	%11 = icmp eq i32 %10, 2		; <i1> [#uses=1]
+	br i1 %11, label %bb5, label %bb7
+
+bb5:		; preds = %bb4
+	%12 = call fastcc i32 @reflect(i32 %d, i32 %3) nounwind		; <i32> [#uses=1]
+	%13 = call fastcc %struct.quad_struct* @child(%struct.quad_struct* %q.0, i32 %12) nounwind		; <%struct.quad_struct*> [#uses=1]
+	ret %struct.quad_struct* %13
+
+bb7:		; preds = %bb4, %bb3
+	ret %struct.quad_struct* %q.0
+}
+
+declare fastcc i32 @sum_adjacent(%struct.quad_struct* nocapture, i32, i32, i32) nounwind readonly
+
+define i32 @perimeter(%struct.quad_struct* nocapture %tree, i32 %size) nounwind readonly {
+entry:
+	%0 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 0		; <i32*> [#uses=1]
+	%1 = load i32, i32* %0, align 4		; <i32> [#uses=1]
+	%2 = icmp eq i32 %1, 2		; <i1> [#uses=1]
+	br i1 %2, label %bb, label %bb2
+
+bb:		; preds = %entry
+	%3 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 4		; <%struct.quad_struct**> [#uses=1]
+	%4 = load %struct.quad_struct*, %struct.quad_struct** %3, align 4		; <%struct.quad_struct*> [#uses=1]
+	%5 = sdiv i32 %size, 2		; <i32> [#uses=1]
+	%6 = call i32 @perimeter(%struct.quad_struct* %4, i32 %5) nounwind		; <i32> [#uses=1]
+	%7 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 5		; <%struct.quad_struct**> [#uses=1]
+	%8 = load %struct.quad_struct*, %struct.quad_struct** %7, align 4		; <%struct.quad_struct*> [#uses=1]
+	%9 = sdiv i32 %size, 2		; <i32> [#uses=1]
+	%10 = call i32 @perimeter(%struct.quad_struct* %8, i32 %9) nounwind		; <i32> [#uses=1]
+	%11 = add i32 %10, %6		; <i32> [#uses=1]
+	%12 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 3		; <%struct.quad_struct**> [#uses=1]
+	%13 = load %struct.quad_struct*, %struct.quad_struct** %12, align 4		; <%struct.quad_struct*> [#uses=1]
+	%14 = sdiv i32 %size, 2		; <i32> [#uses=1]
+	%15 = call i32 @perimeter(%struct.quad_struct* %13, i32 %14) nounwind		; <i32> [#uses=1]
+	%16 = add i32 %15, %11		; <i32> [#uses=1]
+	%17 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 2		; <%struct.quad_struct**> [#uses=1]
+	%18 = load %struct.quad_struct*, %struct.quad_struct** %17, align 4		; <%struct.quad_struct*> [#uses=1]
+	%19 = sdiv i32 %size, 2		; <i32> [#uses=1]
+	%20 = call i32 @perimeter(%struct.quad_struct* %18, i32 %19) nounwind		; <i32> [#uses=1]
+	%21 = add i32 %20, %16		; <i32> [#uses=1]
+	ret i32 %21
+
+bb2:		; preds = %entry
+	%22 = getelementptr %struct.quad_struct, %struct.quad_struct* %tree, i32 0, i32 0		; <i32*> [#uses=1]
+	%23 = load i32, i32* %22, align 4		; <i32> [#uses=1]
+	%24 = icmp eq i32 %23, 0		; <i1> [#uses=1]
+	br i1 %24, label %bb3, label %bb23
+
+bb3:		; preds = %bb2
+	%25 = call fastcc %struct.quad_struct* @gtequal_adj_neighbor(%struct.quad_struct* %tree, i32 0) nounwind		; <%struct.quad_struct*> [#uses=4]
+	%26 = icmp eq %struct.quad_struct* %25, null		; <i1> [#uses=1]
+	br i1 %26, label %bb8, label %bb4
+
+bb4:		; preds = %bb3
+	%27 = getelementptr %struct.quad_struct, %struct.quad_struct* %25, i32 0, i32 0		; <i32*> [#uses=1]
+	%28 = load i32, i32* %27, align 4		; <i32> [#uses=1]
+	%29 = icmp eq i32 %28, 1		; <i1> [#uses=1]
+	br i1 %29, label %bb8, label %bb6
+
+bb6:		; preds = %bb4
+	%30 = getelementptr %struct.quad_struct, %struct.quad_struct* %25, i32 0, i32 0		; <i32*> [#uses=1]
+	%31 = load i32, i32* %30, align 4		; <i32> [#uses=1]
+	%32 = icmp eq i32 %31, 2		; <i1> [#uses=1]
+	br i1 %32, label %bb7, label %bb8
+
+bb7:		; preds = %bb6
+	%33 = call fastcc i32 @sum_adjacent(%struct.quad_struct* %25, i32 3, i32 2, i32 %size) nounwind		; <i32> [#uses=1]
+	br label %bb8
+
+bb8:		; preds = %bb7, %bb6, %bb4, %bb3
+	%retval1.1 = phi i32 [ 0, %bb6 ], [ %33, %bb7 ], [ %size, %bb4 ], [ %size, %bb3 ]		; <i32> [#uses=3]
+	%34 = call fastcc %struct.quad_struct* @gtequal_adj_neighbor(%struct.quad_struct* %tree, i32 1) nounwind		; <%struct.quad_struct*> [#uses=4]
+	%35 = icmp eq %struct.quad_struct* %34, null		; <i1> [#uses=1]
+	br i1 %35, label %bb10, label %bb9
+
+bb9:		; preds = %bb8
+	%36 = getelementptr %struct.quad_struct, %struct.quad_struct* %34, i32 0, i32 0		; <i32*> [#uses=1]
+	%37 = load i32, i32* %36, align 4		; <i32> [#uses=1]
+	%38 = icmp eq i32 %37, 1		; <i1> [#uses=1]
+	br i1 %38, label %bb10, label %bb11
+
+bb10:		; preds = %bb9, %bb8
+	%39 = add i32 %retval1.1, %size		; <i32> [#uses=1]
+	br label %bb13
+
+bb11:		; preds = %bb9
+	%40 = getelementptr %struct.quad_struct, %struct.quad_struct* %34, i32 0, i32 0		; <i32*> [#uses=1]
+	%41 = load i32, i32* %40, align 4		; <i32> [#uses=1]
+	%42 = icmp eq i32 %41, 2		; <i1> [#uses=1]
+	br i1 %42, label %bb12, label %bb13
+
+bb12:		; preds = %bb11
+	%43 = call fastcc i32 @sum_adjacent(%struct.quad_struct* %34, i32 2, i32 0, i32 %size) nounwind		; <i32> [#uses=1]
+	%44 = add i32 %43, %retval1.1		; <i32> [#uses=1]
+	br label %bb13
+
+bb13:		; preds = %bb12, %bb11, %bb10
+	%retval1.2 = phi i32 [ %retval1.1, %bb11 ], [ %44, %bb12 ], [ %39, %bb10 ]		; <i32> [#uses=3]
+	%45 = call fastcc %struct.quad_struct* @gtequal_adj_neighbor(%struct.quad_struct* %tree, i32 2) nounwind		; <%struct.quad_struct*> [#uses=4]
+	%46 = icmp eq %struct.quad_struct* %45, null		; <i1> [#uses=1]
+	br i1 %46, label %bb15, label %bb14
+
+bb14:		; preds = %bb13
+	%47 = getelementptr %struct.quad_struct, %struct.quad_struct* %45, i32 0, i32 0		; <i32*> [#uses=1]
+	%48 = load i32, i32* %47, align 4		; <i32> [#uses=1]
+	%49 = icmp eq i32 %48, 1		; <i1> [#uses=1]
+	br i1 %49, label %bb15, label %bb16
+
+bb15:		; preds = %bb14, %bb13
+	%50 = add i32 %retval1.2, %size		; <i32> [#uses=1]
+	br label %bb18
+
+bb16:		; preds = %bb14
+	%51 = getelementptr %struct.quad_struct, %struct.quad_struct* %45, i32 0, i32 0		; <i32*> [#uses=1]
+	%52 = load i32, i32* %51, align 4		; <i32> [#uses=1]
+	%53 = icmp eq i32 %52, 2		; <i1> [#uses=1]
+	br i1 %53, label %bb17, label %bb18
+
+bb17:		; preds = %bb16
+	%54 = call fastcc i32 @sum_adjacent(%struct.quad_struct* %45, i32 0, i32 1, i32 %size) nounwind		; <i32> [#uses=1]
+	%55 = add i32 %54, %retval1.2		; <i32> [#uses=1]
+	br label %bb18
+
+bb18:		; preds = %bb17, %bb16, %bb15
+	%retval1.3 = phi i32 [ %retval1.2, %bb16 ], [ %55, %bb17 ], [ %50, %bb15 ]		; <i32> [#uses=3]
+	%56 = call fastcc %struct.quad_struct* @gtequal_adj_neighbor(%struct.quad_struct* %tree, i32 3) nounwind		; <%struct.quad_struct*> [#uses=4]
+	%57 = icmp eq %struct.quad_struct* %56, null		; <i1> [#uses=1]
+	br i1 %57, label %bb20, label %bb19
+
+bb19:		; preds = %bb18
+	%58 = getelementptr %struct.quad_struct, %struct.quad_struct* %56, i32 0, i32 0		; <i32*> [#uses=1]
+	%59 = load i32, i32* %58, align 4		; <i32> [#uses=1]
+	%60 = icmp eq i32 %59, 1		; <i1> [#uses=1]
+	br i1 %60, label %bb20, label %bb21
+
+bb20:		; preds = %bb19, %bb18
+	%61 = add i32 %retval1.3, %size		; <i32> [#uses=1]
+	ret i32 %61
+
+bb21:		; preds = %bb19
+	%62 = getelementptr %struct.quad_struct, %struct.quad_struct* %56, i32 0, i32 0		; <i32*> [#uses=1]
+	%63 = load i32, i32* %62, align 4		; <i32> [#uses=1]
+	%64 = icmp eq i32 %63, 2		; <i1> [#uses=1]
+	br i1 %64, label %bb22, label %bb23
+
+bb22:		; preds = %bb21
+	%65 = call fastcc i32 @sum_adjacent(%struct.quad_struct* %56, i32 1, i32 3, i32 %size) nounwind		; <i32> [#uses=1]
+	%66 = add i32 %65, %retval1.3		; <i32> [#uses=1]
+	ret i32 %66
+
+bb23:		; preds = %bb21, %bb2
+	%retval1.0 = phi i32 [ 0, %bb2 ], [ %retval1.3, %bb21 ]		; <i32> [#uses=1]
+	ret i32 %retval1.0
+}
+
+declare i32 @main(i32, i8** nocapture) noreturn nounwind
+
+declare i32 @printf(i8*, ...) nounwind
+
+declare void @exit(i32) noreturn nounwind
+
+declare fastcc i32 @CheckOutside(i32, i32) nounwind readnone
+
+declare fastcc i32 @CheckIntersect(i32, i32, i32) nounwind readnone
+
+declare %struct.quad_struct* @MakeTree(i32, i32, i32, i32, i32, %struct.quad_struct*, i32, i32) nounwind

Added: llvm/trunk/test/Transforms/Inline/2009-05-07-CallUsingSelfCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2009-05-07-CallUsingSelfCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2009-05-07-CallUsingSelfCrash.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2009-05-07-CallUsingSelfCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -inline -disable-output
+; PR4123
+	%struct.S0 = type <{ i32 }>
+	%struct.S1 = type <{ i8, i8, i8, i8, %struct.S0 }>
+	%struct.S2 = type <{ %struct.S1, i32 }>
+
+define void @func_113(%struct.S1* noalias nocapture sret %agg.result, i8 signext %p_114) noreturn nounwind {
+entry:
+	unreachable
+
+for.inc:		; preds = %for.inc
+	%call48 = call fastcc signext i8 @safe_sub_func_uint8_t_u_u(i8 signext %call48)		; <i8> [#uses=1]
+	br label %for.inc
+}
+
+define fastcc signext i8 @safe_sub_func_uint8_t_u_u(i8 signext %_ui1) nounwind readnone {
+entry:
+	ret i8 %_ui1
+}
+

Added: llvm/trunk/test/Transforms/Inline/2010-05-12-ValueMap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/2010-05-12-ValueMap.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/2010-05-12-ValueMap.ll (added)
+++ llvm/trunk/test/Transforms/Inline/2010-05-12-ValueMap.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -inline -mergefunc -disable-output < %s
+
+; This tests for a bug where the inliner kept the functions in a ValueMap after
+; it had completed and a ModulePass started to run. LLVM would crash deleting
+; a function that was still a key in the ValueMap.
+
+define internal fastcc void @list_Cdr1918() nounwind inlinehint {
+  unreachable
+}
+
+define internal fastcc void @list_PairSecond1927() nounwind inlinehint {
+  call fastcc void @list_Cdr1918() nounwind inlinehint
+  unreachable
+}
+
+define internal fastcc void @list_Cdr3164() nounwind inlinehint {
+  unreachable
+}
+
+define internal fastcc void @list_Nconc3167() nounwind inlinehint {
+  call fastcc void @list_Cdr3164() nounwind inlinehint
+  unreachable
+}
+
+define void @term_Equal() nounwind {
+  call fastcc void @list_Cdr3164() nounwind inlinehint
+  unreachable
+}

Added: llvm/trunk/test/Transforms/Inline/AArch64/binop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/binop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/binop.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/binop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,291 @@
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -o - < %s -inline-threshold=0 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+declare void @pad()
+ at glbl = external global i32
+
+define i32 @outer_add1(i32 %a) {
+; CHECK-LABEL: @outer_add1(
+; CHECK-NOT: call i32 @add
+  %C = call i32 @add(i32 %a, i32 0)
+  ret i32 %C
+}
+
+define i32 @outer_add2(i32 %a) {
+; CHECK-LABEL: @outer_add2(
+; CHECK-NOT: call i32 @add
+  %C = call i32 @add(i32 0, i32 %a)
+  ret i32 %C
+}
+
+define i32 @add(i32 %a, i32 %b) {
+  %add = add i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %add
+}
+
+
+
+define i32 @outer_sub1(i32 %a) {
+; CHECK-LABEL: @outer_sub1(
+; CHECK-NOT: call i32 @sub1
+  %C = call i32 @sub1(i32 %a, i32 0)
+  ret i32 %C
+}
+
+define i32 @sub1(i32 %a, i32 %b) {
+  %sub = sub i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %sub
+}
+
+
+define i32 @outer_sub2(i32 %a) {
+; CHECK-LABEL: @outer_sub2(
+; CHECK-NOT: call i32 @sub2
+  %C = call i32 @sub2(i32 %a)
+  ret i32 %C
+}
+
+define i32 @sub2(i32 %a) {
+  %sub = sub i32 %a, %a
+  call void @pad()
+  ret i32 %sub
+}
+
+
+
+define i32 @outer_mul1(i32 %a) {
+; CHECK-LABEL: @outer_mul1(
+; CHECK-NOT: call i32 @mul
+  %C = call i32 @mul(i32 %a, i32 0)
+  ret i32 %C
+}
+
+define i32 @outer_mul2(i32 %a) {
+; CHECK-LABEL: @outer_mul2(
+; CHECK-NOT: call i32 @mul
+  %C = call i32 @mul(i32 %a, i32 1)
+  ret i32 %C
+}
+
+define i32 @mul(i32 %a, i32 %b) {
+  %mul = mul i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %mul
+}
+
+
+
+define i32 @outer_div1(i32 %a) {
+; CHECK-LABEL: @outer_div1(
+; CHECK-NOT: call i32 @div1
+  %C = call i32 @div1(i32 0, i32 %a)
+  ret i32 %C
+}
+
+define i32 @outer_div2(i32 %a) {
+; CHECK-LABEL: @outer_div2(
+; CHECK-NOT: call i32 @div1
+  %C = call i32 @div1(i32 %a, i32 1)
+  ret i32 %C
+}
+
+define i32 @div1(i32 %a, i32 %b) {
+  %div = sdiv i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %div
+}
+
+
+define i32 @outer_div3(i32 %a) {
+; CHECK-LABEL: @outer_div3(
+; CHECK-NOT: call i32 @div
+  %C = call i32 @div2(i32 %a)
+  ret i32 %C
+}
+
+define i32 @div2(i32 %a) {
+  %div = sdiv i32 %a, %a
+  call void @pad()
+  ret i32 %div
+}
+
+
+
+define i32 @outer_rem1(i32 %a) {
+; CHECK-LABEL: @outer_rem1(
+; CHECK-NOT: call i32 @rem
+  %C = call i32 @rem1(i32 0, i32 %a)
+  ret i32 %C
+}
+
+define i32 @outer_rem2(i32 %a) {
+; CHECK-LABEL: @outer_rem2(
+; CHECK-NOT: call i32 @rem
+  %C = call i32 @rem1(i32 %a, i32 1)
+  ret i32 %C
+}
+
+define i32 @rem1(i32 %a, i32 %b) {
+  %rem = urem i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %rem
+}
+
+
+define i32 @outer_rem3(i32 %a) {
+; CHECK-LABEL: @outer_rem3(
+; CHECK-NOT: call i32 @rem
+  %C = call i32 @rem2(i32 %a)
+  ret i32 %C
+}
+
+define i32 @rem2(i32 %a) {
+  %rem = urem i32 %a, %a
+  call void @pad()
+  ret i32 %rem
+}
+
+
+
+define i32 @outer_shl1(i32 %a) {
+; CHECK-LABEL: @outer_shl1(
+; CHECK-NOT: call i32 @shl
+  %C = call i32 @shl(i32 %a, i32 0)
+  ret i32 %C
+}
+
+define i32 @shl(i32 %a, i32 %b) {
+  %shl = shl i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %shl
+}
+
+
+
+define i32 @outer_shr1(i32 %a) {
+; CHECK-LABEL: @outer_shr1(
+; CHECK-NOT: call i32 @shr
+  %C = call i32 @shr(i32 %a, i32 0)
+  ret i32 %C
+}
+
+define i32 @shr(i32 %a, i32 %b) {
+  %shr = ashr i32 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %shr
+}
+
+
+
+define i1 @outer_and1(i1 %a) {
+; check-label: @outer_and1(
+; check-not: call i1 @and1
+  %c = call i1 @and1(i1 %a, i1 false)
+  ret i1 %c
+}
+
+define i1 @outer_and2(i1 %a) {
+; check-label: @outer_and2(
+; check-not: call i1 @and1
+  %c = call i1 @and1(i1 %a, i1 true)
+  ret i1 %c
+}
+
+define i1 @and1(i1 %a, i1 %b) {
+  %and = and i1 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i1 %and
+}
+
+
+define i1 @outer_and3(i1 %a) {
+; check-label: @outer_and3(
+; check-not: call i1 @and2
+  %c = call i1 @and2(i1 %a)
+  ret i1 %c
+}
+
+define i1 @and2(i1 %a) {
+  %and = and i1 %a, %a
+  call void @pad()
+  ret i1 %and
+}
+
+
+
+define i1 @outer_or1(i1 %a) {
+; check-label: @outer_or1(
+; check-not: call i1 @or1
+  %c = call i1 @or1(i1 %a, i1 false)
+  ret i1 %c
+}
+
+define i1 @outer_or2(i1 %a) {
+; check-label: @outer_or2(
+; check-not: call i1 @or1
+  %c = call i1 @or1(i1 %a, i1 true)
+  ret i1 %c
+}
+
+define i1 @or1(i1 %a, i1 %b) {
+  %or = or i1 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i1 %or
+}
+
+
+define i1 @outer_or3(i1 %a) {
+; check-label: @outer_or3(
+; check-not: call i1 @or2
+  %c = call i1 @or2(i1 %a)
+  ret i1 %c
+}
+
+define i1 @or2(i1 %a) {
+  %or = or i1 %a, %a
+  call void @pad()
+  ret i1 %or
+}
+
+
+
+define i1 @outer_xor1(i1 %a) {
+; check-label: @outer_xor1(
+; check-not: call i1 @xor
+  %c = call i1 @xor1(i1 %a, i1 false)
+  ret i1 %c
+}
+
+define i1 @xor1(i1 %a, i1 %b) {
+  %xor = xor i1 %a, %b
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i1 %xor
+}
+
+
+define i1 @outer_xor3(i1 %a) {
+; check-label: @outer_xor3(
+; check-not: call i1 @xor
+  %c = call i1 @xor2(i1 %a)
+  ret i1 %c
+}
+
+define i1 @xor2(i1 %a) {
+  %xor = xor i1 %a, %a
+  call void @pad()
+  ret i1 %xor
+}

Added: llvm/trunk/test/Transforms/Inline/AArch64/ext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/ext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/ext.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/ext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,249 @@
+; REQUIRES: asserts
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+define i32 @outer1(i32* %ptr, i32 %i) {
+  %C = call i32 @inner1(i32* %ptr, i32 %i)
+  ret i32 %C
+}
+
+; sext can be folded into gep.
+; CHECK: Analyzing call of inner1
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i32 @inner1(i32* %ptr, i32 %i) {
+  %E = sext i32 %i to i64
+  %G = getelementptr inbounds i32, i32* %ptr, i64 %E
+  %L = load i32, i32* %G
+  ret i32 %L
+}
+
+define i32 @outer2(i32* %ptr, i32 %i) {
+  %C = call i32 @inner2(i32* %ptr, i32 %i)
+  ret i32 %C
+}
+
+; zext from i32 to i64 is free.
+; CHECK: Analyzing call of inner2
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i32 @inner2(i32* %ptr, i32 %i) {
+  %E = zext i32 %i to i64
+  %G = getelementptr inbounds i32, i32* %ptr, i64 %E
+  %L = load i32, i32* %G
+  ret i32 %L
+}
+
+define i32 @outer3(i32* %ptr, i16 %i) {
+  %C = call i32 @inner3(i32* %ptr, i16 %i)
+  ret i32 %C
+}
+
+; zext can be folded into gep.
+; CHECK: Analyzing call of inner3
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i32 @inner3(i32* %ptr, i16 %i) {
+  %E = zext i16 %i to i64
+  %G = getelementptr inbounds i32, i32* %ptr, i64 %E
+  %L = load i32, i32* %G
+  ret i32 %L
+}
+
+define i16 @outer4(i8* %ptr) {
+  %C = call i16 @inner4(i8* %ptr)
+  ret i16 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner4
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i16 @inner4(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i16
+  ret i16 %E
+}
+
+define i16 @outer5(i8* %ptr) {
+  %C = call i16 @inner5(i8* %ptr)
+  ret i16 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner5
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i16 @inner5(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = sext i8 %L to i16
+  ret i16 %E
+}
+
+define i32 @outer6(i8* %ptr) {
+  %C = call i32 @inner6(i8* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner6
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner6(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer7(i8* %ptr) {
+  %C = call i32 @inner7(i8* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner7
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner7(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = sext i8 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer8(i16* %ptr) {
+  %C = call i32 @inner8(i16* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner8
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner8(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = zext i16 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer9(i16* %ptr) {
+  %C = call i32 @inner9(i16* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner9
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner9(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = sext i16 %L to i32
+  ret i32 %E
+}
+
+define i64 @outer10(i8* %ptr) {
+  %C = call i64 @inner10(i8* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner10
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner10(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer11(i8* %ptr) {
+  %C = call i64 @inner11(i8* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner11
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner11(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = sext i8 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer12(i16* %ptr) {
+  %C = call i64 @inner12(i16* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner12
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner12(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = zext i16 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer13(i16* %ptr) {
+  %C = call i64 @inner13(i16* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner13
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner13(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = sext i16 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer14(i32* %ptr) {
+  %C = call i64 @inner14(i32* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner14
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner14(i32* %ptr) {
+  %L = load i32, i32* %ptr
+  %E = zext i32 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer15(i32* %ptr) {
+  %C = call i64 @inner15(i32* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner15
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner15(i32* %ptr) {
+  %L = load i32, i32* %ptr
+  %E = sext i32 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer16(i32 %V1, i64 %V2) {
+  %C = call i64 @inner16(i32 %V1, i64 %V2)
+  ret i64 %C
+}
+
+; sext can be folded into shl.
+; CHECK: Analyzing call of inner16
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 4
+define i64 @inner16(i32 %V1, i64 %V2) {
+  %E = sext i32 %V1 to i64
+  %S = shl i64 %E, 3
+  %A = add i64 %V2, %S
+  ret i64 %A
+}

Added: llvm/trunk/test/Transforms/Inline/AArch64/gep-cost.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/gep-cost.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/gep-cost.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/gep-cost.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; REQUIRES: asserts
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -mcpu=kryo -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+define void @outer1([4 x i32]* %ptr, i32 %i) {
+  call void @inner1([4 x i32]* %ptr, i32 %i)
+  ret void
+}
+
+define void @outer2([4 x i32]* %ptr, i32 %i) {
+  call void @inner2([4 x i32]* %ptr, i32 %i)
+  ret void
+}
+
+define void @outer3([4 x i32]* %ptr, i32 %j) {
+  call void @inner3([4 x i32]* %ptr, i32 0, i32 %j)
+  ret void
+}
+
+; The gep in inner1() is reg+reg, which is a legal addressing mode for AArch64.
+; Thus, both the gep and ret can be simplified.
+; CHECK: Analyzing call of inner1
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 2
+define void @inner1([4 x i32]* %ptr, i32 %i) {
+  %G = getelementptr inbounds [4 x i32], [4 x i32]* %ptr, i32 0, i32 %i
+  ret void
+}
+
+; The gep in inner2() is reg+imm+reg, which is not a legal addressing mode for
+; AArch64.  Thus, only the ret can be simplified and not the gep.
+; CHECK: Analyzing call of inner2
+; CHECK: NumInstructionsSimplified: 1
+; CHECK: NumInstructions: 2
+define void @inner2([4 x i32]* %ptr, i32 %i) {
+  %G = getelementptr inbounds [4 x i32], [4 x i32]* %ptr, i32 1, i32 %i
+  ret void
+}
+
+; The gep in inner3() is reg+reg because %i is a known constant from the
+; callsite. This case is a legal addressing mode for AArch64.  Thus, both the
+; gep and ret can be simplified.
+; CHECK: Analyzing call of inner3
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 2
+define void @inner3([4 x i32]* %ptr, i32 %i, i32 %j) {
+  %G = getelementptr inbounds [4 x i32], [4 x i32]* %ptr, i32 %i, i32 %j
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/AArch64/inline-target-attr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/inline-target-attr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/inline-target-attr.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/inline-target-attr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -mtriple=aarch64-unknown-linux-gnu -S -inline | FileCheck %s
+; RUN: opt < %s -mtriple=aarch64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s
+; Check that we only inline when we have compatible target attributes.
+
+define i32 @foo() #0 {
+entry:
+  %call = call i32 (...) @baz()
+  ret i32 %call
+; CHECK-LABEL: foo
+; CHECK: call i32 (...) @baz()
+}
+declare i32 @baz(...) #0
+
+define i32 @bar() #1 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: bar
+; CHECK: call i32 (...) @baz()
+}
+
+define i32 @qux() #0 {
+entry:
+  %call = call i32 @bar()
+  ret i32 %call
+; CHECK-LABEL: qux
+; CHECK: call i32 @bar()
+}
+
+define i32 @strict_align() #2 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: strict_align
+; CHECK: call i32 (...) @baz()
+}
+
+attributes #0 = { "target-cpu"="generic" "target-features"="+crc,+neon" }
+attributes #1 = { "target-cpu"="generic" "target-features"="+crc,+neon,+crypto" }
+attributes #2 = { "target-cpu"="generic" "target-features"="+crc,+neon,+strict-align" }

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

Added: llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,94 @@
+; REQUIRES: asserts
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+; FIXME: Once the 'or' or 'and' is simplified the second compare is dead, but
+; the inline cost model has already added the cost.
+
+define i1 @outer1(i32 %a) {
+  %C = call i1 @inner1(i32 0, i32 %a)
+  ret i1 %C
+}
+
+; CHECK: Analyzing call of inner1
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i1 @inner1(i32 %a, i32 %b) {
+  %tobool = icmp eq i32 %a, 0         ; Simplifies to true
+  %tobool1 = icmp eq i32 %b, 0        ; Should be dead once 'or' is simplified
+  %or.cond = or i1 %tobool, %tobool1  ; Simplifies to true
+  ret i1 %or.cond                     ; Simplifies to ret i1 true
+}
+
+define i1 @outer2(i32 %a) {
+  %C = call i1 @inner2(i32 1, i32 %a)
+  ret i1 %C
+}
+
+; CHECK: Analyzing call of inner2
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i1 @inner2(i32 %a, i32 %b) {
+  %tobool = icmp eq i32 %a, 0          ; Simplifies to false
+  %tobool1 = icmp eq i32 %b, 0         ; Should be dead once 'and' is simplified
+  %and.cond = and i1 %tobool, %tobool1 ; Simplifies to false
+  ret i1 %and.cond                     ; Simplifies to ret i1 false
+}
+
+
+define i32 @outer3(i32 %a) {
+  %C = call i32 @inner3(i32 4294967295, i32 %a)
+  ret i32 %C
+}
+
+; CHECK: Analyzing call of inner3
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 2
+define i32 @inner3(i32 %a, i32 %b) {
+  %or.cond = or i32 %a, %b         ; Simplifies to 4294967295
+  ret i32 %or.cond                 ; Simplifies to ret i32 4294967295
+}
+
+
+define i32 @outer4(i32 %a) {
+  %C = call i32 @inner4(i32 0, i32 %a)
+  ret i32 %C
+}
+
+; CHECK: Analyzing call of inner4
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 2
+define i32 @inner4(i32 %a, i32 %b) {
+  %and.cond = and i32 %a, %b       ; Simplifies to 0
+  ret i32 %and.cond                ; Simplifies to ret i32 0
+}
+
+define i1 @outer5(i32 %a) {
+  %C = call i1 @inner5(i32 0, i32 %a)
+  ret i1 %C
+}
+
+; CHECK: Analyzing call of inner5
+; CHECK: NumInstructionsSimplified: 4
+; CHECK: NumInstructions: 5
+define i1 @inner5(i32 %a, i32 %b) {
+  %tobool = icmp eq i32 %a, 0         ; Simplifies to true
+  %tobool1 = icmp eq i32 %b, 0        ; Should be dead once 'or' is simplified
+  %or.cond = or i1 %tobool, %tobool1  ; Simplifies to true
+  br i1 %or.cond, label %end, label %isfalse ; Simplifies to br label %end
+
+isfalse:             ; This block is unreachable once inlined
+  call void @dead()
+  call void @dead()
+  call void @dead()
+  call void @dead()
+  call void @dead()
+  br label %end
+
+end:
+  ret i1 %or.cond    ; Simplifies to ret i1 true
+}
+
+declare void @dead()

Added: llvm/trunk/test/Transforms/Inline/AArch64/phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/phi.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,504 @@
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -o - < %s -inline-threshold=0 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+declare void @pad()
+ at glbl = external global i32
+
+define i1 @outer1() {
+; CHECK-LABEL: @outer1(
+; CHECK-NOT: call i1 @inner1
+  %C = call i1 @inner1()
+  ret i1 %C
+}
+
+define i1 @inner1() {
+entry:
+  br label %if_true
+
+if_true:
+  %phi = phi i1 [0, %entry], [%phi, %if_true] ; Simplified to 0
+  br i1 %phi, label %if_true, label %exit
+
+exit:
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  store i32 2, i32* @glbl
+  store i32 3, i32* @glbl
+  store i32 4, i32* @glbl
+  ret i1 %phi
+}
+
+
+define i1 @outer2(i1 %val) {
+; CHECK-LABEL: @outer2(
+; CHECK: call i1 @inner2
+  %C = call i1 @inner2(i1 %val)
+  ret i1 %C
+}
+
+define i1 @inner2(i1 %val) {
+entry:
+  br label %if_true
+
+if_true:
+  %phi = phi i1 [%val, %entry], [%phi, %if_true] ; Cannot be simplified to a constant
+  br i1 %phi, label %if_true, label %exit
+
+exit:
+  call void @pad()
+  ret i1 %phi
+}
+
+
+define i1 @outer3(i1 %cond) {
+; CHECK-LABEL: @outer3(
+; CHECK-NOT: call i1 @inner3
+  %C = call i1 @inner3(i1 %cond)
+  ret i1 %C
+}
+
+define i1 @inner3(i1 %cond) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32 [0, %entry], [0, %if_true] ; Simplified to 0
+  %cmp = icmp eq i32 %phi, 0
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  store i32 2, i32* @glbl
+  store i32 3, i32* @glbl
+  store i32 4, i32* @glbl
+  ret i1 %cmp
+}
+
+
+define i1 @outer4(i1 %cond) {
+; CHECK-LABEL: @outer4(
+; CHECK-NOT: call i1 @inner4
+  %C = call i1 @inner4(i1 %cond, i32 0)
+  ret i1 %C
+}
+
+define i1 @inner4(i1 %cond, i32 %val) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32 [0, %entry], [%val, %if_true] ; Simplified to 0
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  ret i1 %cmp
+}
+
+
+define i1 @outer5_1(i1 %cond) {
+; CHECK-LABEL: @outer5_1(
+; CHECK-NOT: call i1 @inner5
+  %C = call i1 @inner5(i1 %cond, i32 0, i32 0)
+  ret i1 %C
+}
+
+
+define i1 @outer5_2(i1 %cond) {
+; CHECK-LABEL: @outer5_2(
+; CHECK: call i1 @inner5
+  %C = call i1 @inner5(i1 %cond, i32 0, i32 1)
+  ret i1 %C
+}
+
+define i1 @inner5(i1 %cond, i32 %val1, i32 %val2) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32 [%val1, %entry], [%val2, %if_true] ; Can be simplified to a constant if %val1 and %val2 are the same constants
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i1 %cmp
+}
+
+
+define i1 @outer6(i1 %cond, i32 %val) {
+; CHECK-LABEL: @outer6(
+; CHECK-NOT: call i1 @inner6
+  %C = call i1 @inner6(i1 true, i32 %val, i32 0)
+  ret i1 %C
+}
+
+define i1 @inner6(i1 %cond, i32 %val1, i32 %val2) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32 [%val1, %entry], [%val2, %if_true] ; Simplified to 0
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i1 %cmp
+}
+
+
+define i1 @outer7(i1 %cond, i32 %val) {
+; CHECK-LABEL: @outer7(
+; CHECK-NOT: call i1 @inner7
+  %C = call i1 @inner7(i1 false, i32 0, i32 %val)
+  ret i1 %C
+}
+
+define i1 @inner7(i1 %cond, i32 %val1, i32 %val2) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32 [%val1, %entry], [%val2, %if_true] ; Simplified to 0
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i1 %cmp
+}
+
+
+define i1 @outer8_1() {
+; CHECK-LABEL: @outer8_1(
+; CHECK-NOT: call i1 @inner8
+  %C = call i1 @inner8(i32 0)
+  ret i1 %C
+}
+
+
+
+define i1 @outer8_2() {
+; CHECK-LABEL: @outer8_2(
+; CHECK-NOT: call i1 @inner8
+  %C = call i1 @inner8(i32 3)
+  ret i1 %C
+}
+
+define i1 @inner8(i32 %cond) {
+entry:
+  switch i32 %cond, label %default [ i32 0, label %zero
+                                     i32 1, label %one
+                                     i32 2, label %two ]
+
+zero:
+  br label %exit
+
+one:
+  br label %exit
+
+two:
+  br label %exit
+
+default:
+  br label %exit
+
+exit:
+  %phi = phi i32 [0, %zero], [1, %one], [2, %two], [-1, %default] ; Can be simplified to a constant if the switch condition is known
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  ret i1 %cmp
+}
+
+
+define i1 @outer9(i1 %cond) {
+; CHECK-LABEL: @outer9(
+; CHECK-NOT: call i1 @inner9
+  %C = call i1 @inner9(i32 0, i1 %cond)
+  ret i1 %C
+}
+
+define i1 @inner9(i32 %cond1, i1 %cond2) {
+entry:
+  switch i32 %cond1, label %exit [ i32 0, label %zero
+                                   i32 1, label %one
+                                   i32 2, label %two ]
+
+zero:
+  br label %exit
+
+one:
+  br label %exit
+
+two:
+  br i1 %cond2, label %two_true, label %two_false
+
+two_true:
+  br label %exit
+
+two_false:
+  br label %exit
+
+exit:
+  %phi = phi i32 [0, %zero], [1, %one], [2, %two_true], [2, %two_false], [-1, %entry] ; Simplified to 0
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i1 %cmp
+}
+
+
+define i32 @outer10(i1 %cond) {
+; CHECK-LABEL: @outer10(
+; CHECK-NOT: call i32 @inner10
+  %A = alloca i32
+  %C = call i32 @inner10(i1 %cond, i32* %A)
+  ret i32 %C
+}
+
+define i32 @inner10(i1 %cond, i32* %A) {
+entry:
+  br label %if_true
+
+if_true:
+  %phi = phi i32* [%A, %entry], [%phi, %if_true] ; Simplified to %A
+  %load = load i32, i32* %phi
+  br i1 %cond, label %if_true, label %exit
+
+exit:
+  call void @pad()
+  ret i32 %load
+}
+
+
+define i32 @outer11(i1 %cond, i32* %ptr) {
+; CHECK-LABEL: @outer11(
+; CHECK: call i32 @inner11
+  %C = call i32 @inner11(i1 %cond, i32* %ptr)
+  ret i32 %C
+}
+
+define i32 @inner11(i1 %cond, i32* %ptr) {
+entry:
+  br label %if_true
+
+if_true:
+  %phi = phi i32* [%ptr, %entry], [%phi, %if_true] ; Cannot be simplified
+  %load = load i32, i32* %phi
+  br i1 %cond, label %if_true, label %exit
+
+exit:
+  call void @pad()
+  ret i32 %load
+}
+
+
+define i32 @outer12(i1 %cond) {
+; CHECK-LABEL: @outer12(
+; CHECK-NOT: call i32 @inner12
+  %A = alloca i32
+  %C = call i32 @inner12(i1 %cond, i32* %A)
+  ret i32 %C
+}
+
+define i32 @inner12(i1 %cond, i32* %ptr) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32* [%ptr, %entry], [%ptr, %if_true] ; Simplified to %A
+  %load = load i32, i32* %phi
+  call void @pad()
+  ret i32 %load
+}
+
+
+define i32 @outer13(i1 %cond) {
+; CHECK-LABEL: @outer13(
+; CHECK-NOT: call i32 @inner13
+  %A = alloca i32
+  %C = call i32 @inner13(i1 %cond, i32* %A)
+  ret i32 %C
+}
+
+define i32 @inner13(i1 %cond, i32* %ptr) {
+entry:
+  %gep1 = getelementptr inbounds i32, i32* %ptr, i32 2
+  %gep2 = getelementptr inbounds i32, i32* %ptr, i32 1
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  %gep3 = getelementptr inbounds i32, i32* %gep2, i32 1
+  br label %exit
+
+exit:
+  %phi = phi i32* [%gep1, %entry], [%gep3, %if_true] ; Simplifeid to %gep1
+  %load = load i32, i32* %phi
+  call void @pad()
+  ret i32 %load
+}
+
+
+define i32 @outer14(i1 %cond) {
+; CHECK-LABEL: @outer14(
+; CHECK: call i32 @inner14
+  %A1 = alloca i32
+  %A2 = alloca i32
+  %C = call i32 @inner14(i1 %cond, i32* %A1, i32* %A2)
+  ret i32 %C
+}
+
+define i32 @inner14(i1 %cond, i32* %ptr1, i32* %ptr2) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32* [%ptr1, %entry], [%ptr2, %if_true] ; Cannot be simplified
+  %load = load i32, i32* %phi
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %load
+}
+
+
+define i32 @outer15(i1 %cond, i32* %ptr) {
+; CHECK-LABEL: @outer15(
+; CHECK-NOT: call i32 @inner15
+  %A = alloca i32
+  %C = call i32 @inner15(i1 true, i32* %ptr, i32* %A)
+  ret i32 %C
+}
+
+define i32 @inner15(i1 %cond, i32* %ptr1, i32* %ptr2) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32* [%ptr1, %entry], [%ptr2, %if_true] ; Simplified to %A
+  %load = load i32, i32* %phi
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i32 %load
+}
+
+
+define i32 @outer16(i1 %cond, i32* %ptr) {
+; CHECK-LABEL: @outer16(
+; CHECK-NOT: call i32 @inner16
+  %A = alloca i32
+  %C = call i32 @inner16(i1 false, i32* %A, i32* %ptr)
+  ret i32 %C
+}
+
+define i32 @inner16(i1 %cond, i32* %ptr1, i32* %ptr2) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32* [%ptr1, %entry], [%ptr2, %if_true] ; Simplified to %A
+  %load = load i32, i32* %phi
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i32 %load
+}
+
+
+define i1 @outer17(i1 %cond) {
+; CHECK-LABEL: @outer17(
+; CHECK: call i1 @inner17
+  %A = alloca i32
+  %C = call i1 @inner17(i1 %cond, i32* %A)
+  ret i1 %C
+}
+
+define i1 @inner17(i1 %cond, i32* %ptr) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32* [null, %entry], [%ptr, %if_true] ; Cannot be mapped to a constant
+  %cmp = icmp eq i32* %phi, null
+  call void @pad()
+  ret i1 %cmp
+}
+
+
+define i1 @outer18(i1 %cond) {
+; CHECK-LABEL: @outer18(
+; CHECK-NOT: call i1 @inner18
+  %C = call i1 @inner18(i1 %cond, i1 true)
+  ret i1 %C
+}
+
+define i1 @inner18(i1 %cond1, i1 %cond2) {
+entry:
+  br i1 %cond1, label %block1, label %block2
+
+block1:
+  br i1 %cond2, label %block3, label %block4
+
+block2:
+  br i1 %cond2, label %block5, label %block4
+
+block3:
+  %phi = phi i32 [0, %block1], [1, %block4], [0, %block5] ; Simplified to 0
+  %cmp = icmp eq i32 %phi, 0
+  call void @pad()
+  ret i1 %cmp
+
+block4:                                                   ; Unreachable block
+  br label %block3
+
+block5:
+  br label %block3
+}
+
+
+define i1 @outer19(i1 %cond) {
+; CHECK-LABEL: @outer19(
+; CHECK: call i1 @inner19
+  %A = alloca i32
+  %C = call i1 @inner19(i1 %cond, i32* %A)
+  ret i1 %C
+}
+
+define i1 @inner19(i1 %cond, i32* %ptr) {
+entry:
+  br i1 %cond, label %if_true, label %exit
+
+if_true:
+  br label %exit
+
+exit:
+  %phi = phi i32* [%ptr, %entry], [null, %if_true] ; Cannot be mapped to a constant
+  %cmp = icmp eq i32* %phi, null
+  call void @pad()
+  ret i1 %cmp
+}

Added: llvm/trunk/test/Transforms/Inline/AArch64/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/select.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/select.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/select.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,251 @@
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -o - < %s -inline-threshold=0 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+declare void @pad()
+ at glbl = external global i32
+
+define i32 @outer1(i1 %cond) {
+; CHECK-LABEL: @outer1(
+; CHECK-NOT: call i32 @inner1
+  %C = call i32 @inner1(i1 %cond, i32 1)
+  ret i32 %C
+}
+
+define i32 @inner1(i1 %cond, i32 %val) {
+  %select = select i1 %cond, i32 1, i32 %val       ; Simplified to 1
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %select                                  ; Simplifies to ret i32 1
+}
+
+
+define i32 @outer2(i32 %val) {
+; CHECK-LABEL: @outer2(
+; CHECK-NOT: call i32 @inner2
+  %C = call i32 @inner2(i1 true, i32 %val)
+  ret i32 %C
+}
+
+define i32 @inner2(i1 %cond, i32 %val) {
+  %select = select i1 %cond, i32 1, i32 %val       ; Simplifies to 1
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %select                                  ; Simplifies to ret i32 1
+}
+
+
+define i32 @outer3(i32 %val) {
+; CHECK-LABEL: @outer3(
+; CHECK-NOT: call i32 @inner3
+  %C = call i32 @inner3(i1 false, i32 %val)
+  ret i32 %C
+}
+
+define i32 @inner3(i1 %cond, i32 %val) {
+  %select = select i1 %cond, i32 %val, i32 -1      ; Simplifies to -1
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %select                                  ; Simplifies to ret i32 -1
+}
+
+
+define i32 @outer4() {
+; CHECK-LABEL: @outer4(
+; CHECK-NOT: call i32 @inner4
+  %C = call i32 @inner4(i1 true, i32 1, i32 -1)
+  ret i32 %C
+}
+
+define i32 @inner4(i1 %cond, i32 %val1, i32 %val2) {
+  %select = select i1 %cond, i32 %val1, i32 %val2  ; Simplifies to 1
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i32 %select                                  ; Simplifies to ret i32 1
+}
+
+
+define i1 @outer5() {
+; CHECK-LABEL: @outer5(
+; CHECK-NOT: call i1 @inner5
+  %C = call i1 @inner5(i1 true, i1 true, i1 false)
+  ret i1 %C
+}
+
+declare void @dead()
+
+define i1 @inner5(i1 %cond, i1 %val1, i1 %val2) {
+  %select = select i1 %cond, i1 %val1, i1 %val2    ; Simplifies to true
+  br i1 %select, label %exit, label %isfalse       ; Simplifies to br label %end
+
+isfalse:                                           ; This block is unreachable once inlined
+  call void @dead()
+  br label %exit
+
+exit:
+  store i32 0, i32* @glbl
+  ret i1 %select                                   ; Simplifies to ret i1 true
+}
+
+
+define i32 @outer6(i1 %cond) {
+; CHECK-LABEL: @outer6(
+; CHECK-NOT: call i32 @inner6
+  %A = alloca i32
+  %C = call i32 @inner6(i1 %cond, i32* %A)
+  ret i32 %C
+}
+
+define i32 @inner6(i1 %cond, i32* %ptr) {
+  %G1 = getelementptr inbounds i32, i32* %ptr, i32 1
+  %G2 = getelementptr inbounds i32, i32* %G1, i32 1
+  %G3 = getelementptr inbounds i32, i32* %ptr, i32 2
+  %select = select i1 %cond, i32* %G2, i32* %G3    ; Simplified to %A[2]
+  %load = load i32, i32* %select                   ; SROA'ed
+  call void @pad()
+  ret i32 %load                                    ; Simplified
+}
+
+
+define i32 @outer7(i32* %ptr) {
+; CHECK-LABEL: @outer7(
+; CHECK-NOT: call i32 @inner7
+  %A = alloca i32
+  %C = call i32 @inner7(i1 true, i32* %A, i32* %ptr)
+  ret i32 %C
+}
+
+define i32 @inner7(i1 %cond, i32* %p1, i32* %p2) {
+  %select = select i1 %cond, i32* %p1, i32* %p2    ; Simplifies to %A
+  %load = load i32, i32* %select                   ; SROA'ed
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %load                                    ; Simplified
+}
+
+
+define i32 @outer8(i32* %ptr) {
+; CHECK-LABEL: @outer8(
+; CHECK-NOT: call i32 @inner8
+  %A = alloca i32
+  %C = call i32 @inner8(i1 false, i32* %ptr, i32* %A)
+  ret i32 %C
+}
+
+define i32 @inner8(i1 %cond, i32* %p1, i32* %p2) {
+  %select = select i1 %cond, i32* %p1, i32* %p2    ; Simplifies to %A
+  %load = load i32, i32* %select                   ; SROA'ed
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i32 %load                                    ; Simplified
+}
+
+
+define <2 x i32> @outer9(<2 x i32> %val) {
+; CHECK-LABEL: @outer9(
+; CHECK-NOT: call <2 x i32> @inner9
+  %C = call <2 x i32> @inner9(<2 x i1> <i1 true, i1 true>, <2 x i32> %val)
+  ret <2 x i32> %C
+}
+
+define <2 x i32> @inner9(<2 x i1> %cond, <2 x i32> %val) {
+  %select = select <2 x i1> %cond, <2 x i32> <i32 1, i32 1>, <2 x i32> %val              ; Simplifies to <1, 1>
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret <2 x i32> %select                                                                  ; Simplifies to ret <2 x i32> <1, 1>
+}
+
+
+define <2 x i32> @outer10(<2 x i32> %val) {
+; CHECK-LABEL: @outer10(
+; CHECK-NOT: call <2 x i32> @inner10
+  %C = call <2 x i32> @inner10(<2 x i1> <i1 false, i1 false>, <2 x i32> %val)
+  ret <2 x i32> %C
+}
+
+define <2 x i32> @inner10(<2 x i1> %cond, <2 x i32> %val) {
+  %select = select <2 x i1> %cond, < 2 x i32> %val, <2 x i32> <i32 -1, i32 -1>           ; Simplifies to <-1, -1>
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret <2 x i32> %select                                                                  ; Simplifies to ret <2 x i32> <-1, -1>
+}
+
+
+define <2 x i32> @outer11() {
+; CHECK-LABEL: @outer11(
+; CHECK-NOT: call <2 x i32> @inner11
+  %C = call <2 x i32> @inner11(<2 x i1> <i1 true, i1 false>)
+  ret <2 x i32> %C
+}
+
+define <2 x i32> @inner11(<2 x i1> %cond) {
+  %select = select <2 x i1> %cond, <2 x i32> <i32 1, i32 1>, < 2 x i32> <i32 -1, i32 -1> ; Simplifies to <1, -1>
+  call void @pad()
+  ret <2 x i32> %select                                                                  ; Simplifies to ret <2 x i32> <1, -1>
+}
+
+
+define i1 @outer12(i32* %ptr) {
+; CHECK-LABEL: @outer12(
+; CHECK-NOT: call i1 @inner12
+  %C = call i1 @inner12(i1 true, i32* @glbl, i32* %ptr)
+  ret i1 %C
+}
+
+define i1 @inner12(i1 %cond, i32* %ptr1, i32* %ptr2) {
+  %select = select i1 %cond, i32* %ptr1, i32* %ptr2 ; Simplified to @glbl
+  %cmp = icmp eq i32* %select, @glbl                ; Simplified to true
+  call void @pad()
+  store i32 0, i32* @glbl
+  ret i1 %cmp                                       ; Simplifies to ret i1 true
+}
+
+
+define <2 x i32> @outer13(<2 x i32> %val1, <2 x i32> %val2) {
+; CHECK-LABEL: @outer13(
+; CHECK: call <2 x i32> @inner13
+  %C = call <2 x i32> @inner13(<2 x i1> <i1 true, i1 false>, <2 x i32> %val1, <2 x i32> %val2)
+  ret <2 x i32> %C
+}
+
+define <2 x i32> @inner13(<2 x i1> %cond, <2 x i32> %val1, < 2 x i32> %val2) {
+  %select = select <2 x i1> %cond, <2 x i32> %val1, < 2 x i32> %val2 ; Cannot be Simplified
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret <2 x i32> %select                                              ; Simplified
+}
+
+
+define i32 @outer14(i32 %val1, i32 %val2) {
+; CHECK-LABEL: @outer14(
+; CHECK-NOT: call i32 @inner14
+  %C = call i32 @inner14(i1 true, i32 %val1, i32 %val2)
+  ret i32 %C
+}
+
+define i32 @inner14(i1 %cond, i32 %val1, i32 %val2) {
+  %select = select i1 %cond, i32 %val1, i32 %val2   ; Simplified to %val1
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i32 %select                                   ; Simplifies to ret i32 %val1
+}
+
+
+define i32 @outer15(i32 %val1, i32 %val2) {
+; CHECK-LABEL: @outer15(
+; CHECK-NOT: call i32 @inner15
+  %C = call i32 @inner15(i1 false, i32 %val1, i32 %val2)
+  ret i32 %C
+}
+
+define i32 @inner15(i1 %cond, i32 %val1, i32 %val2) {
+  %select = select i1 %cond, i32 %val1, i32 %val2   ; Simplified to %val2
+  call void @pad()
+  store i32 0, i32* @glbl
+  store i32 1, i32* @glbl
+  ret i32 %select                                   ; Simplifies to ret i32 %val2
+}

Added: llvm/trunk/test/Transforms/Inline/AArch64/switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/switch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/switch.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/switch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,160 @@
+; RUN: opt < %s -inline -inline-threshold=20 -S -mtriple=aarch64-none-linux  | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S -mtriple=aarch64-none-linux | FileCheck %s
+
+define i32 @callee_range(i32 %a, i32* %P) {
+  switch i32 %a, label %sw.default [
+    i32 0, label %sw.bb0
+    i32 1000, label %sw.bb1
+    i32 2000, label %sw.bb1
+    i32 3000, label %sw.bb1
+    i32 4000, label %sw.bb1
+    i32 5000, label %sw.bb1
+    i32 6000, label %sw.bb1
+    i32 7000, label %sw.bb1
+    i32 8000, label %sw.bb1
+    i32 9000, label %sw.bb1
+  ]
+
+sw.default:
+  store volatile i32 %a, i32* %P
+  br label %return
+sw.bb0:
+  store volatile i32 %a, i32* %P
+  br label %return
+sw.bb1:
+  store volatile i32 %a, i32* %P
+  br label %return
+return:
+  ret i32 42
+}
+
+define i32 @caller_range(i32 %a, i32* %P) {
+; CHECK-LABEL: @caller_range(
+; CHECK: call i32 @callee_range
+  %r = call i32 @callee_range(i32 %a, i32* %P)
+  ret i32 %r
+}
+
+define i32 @callee_bittest(i32 %a, i32* %P) {
+  switch i32 %a, label %sw.default [
+    i32 0, label %sw.bb0
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb0
+    i32 4, label %sw.bb1
+    i32 5, label %sw.bb2
+    i32 6, label %sw.bb0
+    i32 7, label %sw.bb1
+    i32 8, label %sw.bb2
+  ]
+
+sw.default:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+sw.bb0:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+sw.bb1:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+sw.bb2:
+  br label %return
+
+return:
+  ret i32 42
+}
+
+
+define i32 @caller_bittest(i32 %a, i32* %P) {
+; CHECK-LABEL: @caller_bittest(
+; CHECK-NOT: call i32 @callee_bittest
+  %r= call i32 @callee_bittest(i32 %a, i32* %P)
+  ret i32 %r
+}
+
+define i32 @callee_jumptable(i32 %a, i32* %P) {
+  switch i32 %a, label %sw.default [
+    i32 1001, label %sw.bb101
+    i32 1002, label %sw.bb102
+    i32 1003, label %sw.bb103
+    i32 1004, label %sw.bb104
+    i32 1005, label %sw.bb101
+    i32 1006, label %sw.bb102
+    i32 1007, label %sw.bb103
+    i32 1008, label %sw.bb104
+    i32 1009, label %sw.bb101
+    i32 1010, label %sw.bb102
+    i32 1011, label %sw.bb103
+    i32 1012, label %sw.bb104
+ ]
+
+sw.default:
+  br label %return
+
+sw.bb101:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+sw.bb102:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+sw.bb103:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+sw.bb104:
+  store volatile i32 %a, i32* %P
+  br label %return
+
+return:
+  ret i32 42
+}
+
+define i32 @caller_jumptable(i32 %a, i32 %b, i32* %P) {
+; CHECK-LABEL: @caller_jumptable(
+; CHECK: call i32 @callee_jumptable
+  %r = call i32 @callee_jumptable(i32 %b, i32* %P)
+  ret i32 %r
+}
+
+
+define internal i32 @callee_negativeCost(i32 %t)  {
+entry:
+  switch i32 %t, label %sw.default [
+    i32 1, label %sw.bb
+    i32 0, label %sw.bb1
+    i32 42, label %sw.bb2
+    i32 43, label %sw.bb3
+  ]
+
+sw.bb:                                            ; preds = %entry
+  br label %cleanup
+
+sw.bb1:                                           ; preds = %entry
+  br label %cleanup
+
+sw.bb2:                                           ; preds = %entry
+  br label %cleanup
+
+sw.bb3:                                           ; preds = %entry
+  br label %cleanup
+
+sw.default:                                       ; preds = %entry
+  br label %cleanup
+
+cleanup:                                          ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb
+  %retval.0 = phi i32 [ 1, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 0, %sw.bb1 ], [ 0, %sw.bb ]
+  ret i32 %retval.0
+}
+
+define i32 @caller_negativeCost(i32 %t) {
+; CHECK-LABEL: @caller_negativeCost(
+; CHECK-NOT: call i32 @callee_negativeCost
+entry:
+  %call = call i32 @callee_negativeCost(i32 %t)
+  ret i32 %call
+}

Added: llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-dx10-clamp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-dx10-clamp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-dx10-clamp.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-dx10-clamp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,107 @@
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -inline < %s | FileCheck %s
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes='cgscc(inline)' < %s | FileCheck %s
+
+define i32 @func_default() #0 {
+  ret i32 0
+}
+
+define i32 @func_dx10_clamp_enabled() #1 {
+  ret i32 0
+}
+
+define i32 @func_dx10_clamp_disabled() #2 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @default_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @default_call_default() #0 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @dx10_clamp_enabled_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @dx10_clamp_enabled_call_default() #1 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @dx10_clamp_enabled_call_dx10_clamp_enabled(
+; CHECK-NEXT: ret i32 0
+define i32 @dx10_clamp_enabled_call_dx10_clamp_enabled() #1 {
+  %call = call i32 @func_dx10_clamp_enabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @dx10_clamp_enabled_call_dx10_clamp_disabled(
+; CHECK-NEXT: call i32 @func_dx10_clamp_disabled()
+define i32 @dx10_clamp_enabled_call_dx10_clamp_disabled() #1 {
+  %call = call i32 @func_dx10_clamp_disabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @dx10_clamp_disabled_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define i32 @dx10_clamp_disabled_call_default() #2 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @dx10_clamp_disabled_call_dx10_clamp_enabled(
+; CHECK-NEXT: call i32 @func_dx10_clamp_enabled()
+define i32 @dx10_clamp_disabled_call_dx10_clamp_enabled() #2 {
+  %call = call i32 @func_dx10_clamp_enabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @dx10_clamp_disabled_call_dx10_clamp_disabled(
+; CHECK-NEXT: ret i32 0
+define i32 @dx10_clamp_disabled_call_dx10_clamp_disabled() #2 {
+  %call = call i32 @func_dx10_clamp_disabled()
+  ret i32 %call
+}
+
+; Shader calling a compute function
+; CHECK-LABEL: @amdgpu_ps_default_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define amdgpu_ps i32 @amdgpu_ps_default_call_default() #0 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; Shader with dx10_clamp enabled calling a compute function. Default
+; also implies ieee_mode, so this isn't inlinable.
+; CHECK-LABEL: @amdgpu_ps_dx10_clamp_enabled_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define amdgpu_ps i32 @amdgpu_ps_dx10_clamp_enabled_call_default() #1 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @amdgpu_ps_dx10_clamp_disabled_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define amdgpu_ps i32 @amdgpu_ps_dx10_clamp_disabled_call_default() #2 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @amdgpu_ps_dx10_clamp_enabled_ieee_call_default(
+; CHECK-NEXT: ret i32 0
+define amdgpu_ps i32 @amdgpu_ps_dx10_clamp_enabled_ieee_call_default() #3 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @amdgpu_ps_dx10_clamp_disabled_ieee_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define amdgpu_ps i32 @amdgpu_ps_dx10_clamp_disabled_ieee_call_default() #4 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind "amdgpu-dx10-clamp"="true" }
+attributes #2 = { nounwind "amdgpu-dx10-clamp"="false" }
+attributes #3 = { nounwind "amdgpu-dx10-clamp"="true" "amdgpu-ieee"="true" }
+attributes #4 = { nounwind "amdgpu-dx10-clamp"="false" "amdgpu-ieee"="true" }

Added: llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-ieee.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-ieee.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-ieee.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AMDGPU/inline-amdgpu-ieee.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,90 @@
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -inline < %s | FileCheck %s
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes='cgscc(inline)' < %s | FileCheck %s
+
+define i32 @func_default() #0 {
+  ret i32 0
+}
+
+define i32 @func_ieee_enabled() #1 {
+  ret i32 0
+}
+
+define i32 @func_ieee_disabled() #2 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @default_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @default_call_default() #0 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ieee_enabled_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @ieee_enabled_call_default() #1 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ieee_enabled_call_ieee_enabled(
+; CHECK-NEXT: ret i32 0
+define i32 @ieee_enabled_call_ieee_enabled() #1 {
+  %call = call i32 @func_ieee_enabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ieee_enabled_call_ieee_disabled(
+; CHECK-NEXT: call i32 @func_ieee_disabled()
+define i32 @ieee_enabled_call_ieee_disabled() #1 {
+  %call = call i32 @func_ieee_disabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ieee_disabled_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define i32 @ieee_disabled_call_default() #2 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ieee_disabled_call_ieee_enabled(
+; CHECK-NEXT: call i32 @func_ieee_enabled()
+define i32 @ieee_disabled_call_ieee_enabled() #2 {
+  %call = call i32 @func_ieee_enabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ieee_disabled_call_ieee_disabled(
+; CHECK-NEXT: ret i32 0
+define i32 @ieee_disabled_call_ieee_disabled() #2 {
+  %call = call i32 @func_ieee_disabled()
+  ret i32 %call
+}
+
+; Shader calling a compute function
+; CHECK-LABEL: @amdgpu_ps_default_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define amdgpu_ps i32 @amdgpu_ps_default_call_default() #0 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; Shader with ieee enabled calling a compute function
+; CHECK-LABEL: @amdgpu_ps_ieee_enabled_call_default(
+; CHECK-NEXT: ret i32 0
+define amdgpu_ps i32 @amdgpu_ps_ieee_enabled_call_default() #1 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @amdgpu_ps_ieee_disabled_call_default(
+; CHECK-NEXT: call i32 @func_default()
+define amdgpu_ps i32 @amdgpu_ps_ieee_disabled_call_default() #2 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind "amdgpu-ieee"="true" }
+attributes #2 = { nounwind "amdgpu-ieee"="false" }

Added: llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-cpu.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-cpu.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-cpu.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-cpu.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,103 @@
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -inline < %s | FileCheck %s
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes='cgscc(inline)' < %s | FileCheck %s
+
+; CHECK-LABEL: @func_no_target_cpu(
+define i32 @func_no_target_cpu() #0 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @target_cpu_call_no_target_cpu(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_call_no_target_cpu() #1 {
+  %call = call i32 @func_no_target_cpu()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @target_cpu_target_features_call_no_target_cpu(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_target_features_call_no_target_cpu() #2 {
+  %call = call i32 @func_no_target_cpu()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @fp32_denormals(
+define i32 @fp32_denormals() #3 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @no_fp32_denormals_call_f32_denormals(
+; CHECK-NEXT: call i32 @fp32_denormals()
+define i32 @no_fp32_denormals_call_f32_denormals() #4 {
+  %call = call i32 @fp32_denormals()
+  ret i32 %call
+}
+
+; Make sure gfx9 can call unspecified functions because of movrel
+; feature change.
+; CHECK-LABEL: @gfx9_target_features_call_no_target_cpu(
+; CHECK-NEXT: ret i32 0
+define i32 @gfx9_target_features_call_no_target_cpu() #5 {
+  %call = call i32 @func_no_target_cpu()
+  ret i32 %call
+}
+
+define i32 @func_no_halfrate64ops() #6 {
+  ret i32 0
+}
+
+define i32 @func_with_halfrate64ops() #7 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @call_func_without_halfrate64ops(
+; CHECK-NEXT: ret i32 0
+define i32 @call_func_without_halfrate64ops() #7 {
+  %call = call i32 @func_no_halfrate64ops()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @call_func_with_halfrate64ops(
+; CHECK-NEXT: ret i32 0
+define i32 @call_func_with_halfrate64ops() #6 {
+  %call = call i32 @func_with_halfrate64ops()
+  ret i32 %call
+}
+
+define i32 @func_no_loadstoreopt() #8 {
+  ret i32 0
+}
+
+define i32 @func_with_loadstoreopt() #9 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @call_func_without_loadstoreopt(
+; CHECK-NEXT: ret i32 0
+define i32 @call_func_without_loadstoreopt() #9 {
+  %call = call i32 @func_no_loadstoreopt()
+  ret i32 %call
+}
+
+define i32 @enable_codeobjectv3() #10 {
+  ret i32 999
+}
+
+; CHECK-LABEL: @disable_codeobjectv3_call_codeobjectv3(
+; CHECK-NEXT: ret i32 999
+define i32 @disable_codeobjectv3_call_codeobjectv3() #11 {
+  %call = call i32 @enable_codeobjectv3()
+  ret i32 %call
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind "target-cpu"="fiji" }
+attributes #2 = { nounwind "target-cpu"="fiji" "target-features"="+fp32-denormals" }
+attributes #3 = { nounwind "target-features"="+fp32-denormals" }
+attributes #4 = { nounwind "target-features"="-fp32-denormals" }
+attributes #5 = { nounwind "target-cpu"="gfx900" }
+attributes #6 = { nounwind "target-features"="-half-rate-64-ops" }
+attributes #7 = { nounwind "target-features"="+half-rate-64-ops" }
+attributes #8 = { nounwind "target-features"="-load-store-opt" }
+attributes #9 = { nounwind "target-features"="+load-store-opt" }
+attributes #10 = { nounwind "target-features"="+code-object-v3" }
+attributes #11 = { nounwind "target-features"="-code-object-v3" }

Added: llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-feature-sram-ecc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-feature-sram-ecc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-feature-sram-ecc.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AMDGPU/inline-target-feature-sram-ecc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -inline < %s | FileCheck %s
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -passes='cgscc(inline)' < %s | FileCheck %s
+
+; sram-ecc can be safely ignored when inlining, since no intrinisics
+; or other directly exposed operations depend on it.
+
+define i32 @func_default() #0 {
+  ret i32 0
+}
+
+define i32 @func_ecc_enabled() #1 {
+  ret i32 0
+}
+
+define i32 @func_ecc_disabled() #2 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @default_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @default_call_default() #0 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ecc_enabled_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @ecc_enabled_call_default() #1 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ecc_enabled_call_ecc_enabled(
+; CHECK-NEXT: ret i32 0
+define i32 @ecc_enabled_call_ecc_enabled() #1 {
+  %call = call i32 @func_ecc_enabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ecc_enabled_call_ecc_disabled(
+; CHECK-NEXT: ret i32 0
+define i32 @ecc_enabled_call_ecc_disabled() #1 {
+  %call = call i32 @func_ecc_disabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ecc_disabled_call_default(
+; CHECK-NEXT: ret i32 0
+define i32 @ecc_disabled_call_default() #2 {
+  %call = call i32 @func_default()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ecc_disabled_call_ecc_enabled(
+; CHECK-NEXT: ret i32 0
+define i32 @ecc_disabled_call_ecc_enabled() #2 {
+  %call = call i32 @func_ecc_enabled()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @ecc_disabled_call_ecc_disabled(
+; CHECK-NEXT: ret i32 0
+define i32 @ecc_disabled_call_ecc_disabled() #2 {
+  %call = call i32 @func_ecc_disabled()
+  ret i32 %call
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind "target-features"="+sram-ecc" }
+attributes #2 = { nounwind "target-features"="-sram-ecc" }

Added: llvm/trunk/test/Transforms/Inline/AMDGPU/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AMDGPU/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AMDGPU/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/Inline/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/Inline/ARM/inline-fp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ARM/inline-fp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ARM/inline-fp.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ARM/inline-fp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,113 @@
+; RUN: opt -S -inline -mtriple=arm-eabi -pass-remarks=.* -pass-remarks-missed=.* < %s 2>&1 | FileCheck %s -check-prefix=NOFP
+; RUN: opt -S -inline -mtriple=arm-eabi -mattr=+vfp2 -pass-remarks=.* -pass-remarks-missed=.* < %s 2>&1 | FileCheck %s -check-prefix=FULLFP
+; RUN: opt -S -inline -mtriple=arm-eabi -mattr=+vfp2,+fp-only-sp -pass-remarks=.* -pass-remarks-missed=.* < %s 2>&1 | FileCheck %s -check-prefix=SINGLEFP
+; Make sure that soft float implementations are calculated as being more expensive
+; to the inliner.
+
+; NOFP-DAG: single not inlined into test_single because too costly to inline (cost=125, threshold=75)
+; NOFP-DAG: single not inlined into test_single because too costly to inline (cost=125, threshold=75)
+; NOFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15, threshold=75)
+; NOFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15015, threshold=75)
+; NOFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
+; NOFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
+; NOFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
+; NOFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
+
+; FULLFP-DAG: single inlined into test_single with (cost=0, threshold=75)
+; FULLFP-DAG: single inlined into test_single with (cost=-15000, threshold=75)
+; FULLFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15, threshold=75)
+; FULLFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15015, threshold=75)
+; FULLFP-DAG: double inlined into test_double with (cost=0, threshold=75)
+; FULLFP-DAG: double inlined into test_double with (cost=-15000, threshold=75)
+; FULLFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
+; FULLFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
+
+; SINGLEFP-DAG: single inlined into test_single with (cost=0, threshold=75)
+; SINGLEFP-DAG: single inlined into test_single with (cost=-15000, threshold=75)
+; SINGLEFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15, threshold=75)
+; SINGLEFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15015, threshold=75)
+; SINGLEFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
+; SINGLEFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
+; SINGLEFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
+; SINGLEFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
+
+define i32 @test_single(i32 %a, i8 %b, i32 %c, i8 %d) #0 {
+  %call = call float @single(i32 %a, i8 zeroext %b)
+  %call2 = call float @single(i32 %c, i8 zeroext %d)
+  ret i32 0
+}
+
+define i32 @test_single_cheap(i32 %a, i8 %b, i32 %c, i8 %d) #0 {
+  %call = call float @single_cheap(i32 %a, i8 zeroext %b)
+  %call2 = call float @single_cheap(i32 %c, i8 zeroext %d)
+  ret i32 0
+}
+
+define i32 @test_double(i32 %a, i8 %b, i32 %c, i8 %d) #0 {
+  %call = call double @double(i32 %a, i8 zeroext %b)
+  %call2 = call double @double(i32 %c, i8 zeroext %d)
+  ret i32 0
+}
+
+define i32 @test_single_force_soft(i32 %a, i8 %b, i32 %c, i8 %d) #1 {
+  %call = call float @single_force_soft(i32 %a, i8 zeroext %b) #1
+  %call2 = call float @single_force_soft(i32 %c, i8 zeroext %d) #1
+  ret i32 0
+}
+
+define internal float @single(i32 %response, i8 zeroext %value1) #0 {
+entry:
+  %conv = zext i8 %value1 to i32
+  %sub = add nsw i32 %conv, -1
+  %conv1 = sitofp i32 %sub to float
+  %0 = tail call float @llvm.pow.f32(float 0x3FF028F5C0000000, float %conv1)
+  %mul = fmul float %0, 2.620000e+03
+  %conv2 = sitofp i32 %response to float
+  %sub3 = fsub float %conv2, %mul
+  %div = fdiv float %sub3, %mul
+  ret float %div
+}
+
+define internal float @single_cheap(i32 %response, i8 zeroext %value1) #0 {
+entry:
+  %conv = zext i8 %value1 to i32
+  %sub = add nsw i32 %conv, -1
+  %conv1 = bitcast i32 %sub to float
+  %conv2 = bitcast i32 %response to float
+  %0 = tail call float @llvm.pow.f32(float %conv2, float %conv1)
+  %1 = tail call float @llvm.pow.f32(float %0, float %0)
+  %2 = tail call float @llvm.pow.f32(float %1, float %1)
+  ret float %2
+}
+
+define internal double @double(i32 %response, i8 zeroext %value1) #0 {
+entry:
+  %conv = zext i8 %value1 to i32
+  %sub = add nsw i32 %conv, -1
+  %conv1 = sitofp i32 %sub to double
+  %0 = tail call double @llvm.pow.f64(double 0x3FF028F5C0000000, double %conv1)
+  %mul = fmul double %0, 2.620000e+03
+  %conv2 = sitofp i32 %response to double
+  %sub3 = fsub double %conv2, %mul
+  %div = fdiv double %sub3, %mul
+  ret double %div
+}
+
+define internal float @single_force_soft(i32 %response, i8 zeroext %value1) #1 {
+entry:
+  %conv = zext i8 %value1 to i32
+  %sub = add nsw i32 %conv, -1
+  %conv1 = sitofp i32 %sub to float
+  %0 = tail call float @llvm.pow.f32(float 0x3FF028F5C0000000, float %conv1)
+  %mul = fmul float %0, 2.620000e+03
+  %conv2 = sitofp i32 %response to float
+  %sub3 = fsub float %conv2, %mul
+  %div = fdiv float %sub3, %mul
+  ret float %div
+}
+
+declare float @llvm.pow.f32(float, float) optsize minsize
+declare double @llvm.pow.f64(double, double) optsize minsize
+
+attributes #0 = { optsize }
+attributes #1 = { optsize "use-soft-float"="true" "target-features"="+soft-float" }

Added: llvm/trunk/test/Transforms/Inline/ARM/inline-target-attr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ARM/inline-target-attr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ARM/inline-target-attr.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ARM/inline-target-attr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt < %s -mtriple=arm-unknown-linux-gnu -S -inline | FileCheck %s
+; RUN: opt < %s -mtriple=arm-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s
+; Check that we only inline when we have compatible target attributes.
+; ARM has implemented a target attribute that will verify that the attribute
+; sets are compatible.
+
+define i32 @foo() #0 {
+entry:
+  %call = call i32 (...) @baz()
+  ret i32 %call
+; CHECK-LABEL: foo
+; CHECK: call i32 (...) @baz()
+}
+declare i32 @baz(...) #0
+
+define i32 @bar() #1 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: bar
+; CHECK: call i32 (...) @baz()
+}
+
+define i32 @qux() #0 {
+entry:
+  %call = call i32 @bar()
+  ret i32 %call
+; CHECK-LABEL: qux
+; CHECK: call i32 @bar()
+}
+
+define i32 @thumb_fn() #2 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: thumb_fn
+; CHECK: call i32 @foo
+}
+
+define i32 @strict_align() #3 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: strict_align
+; CHECK: call i32 (...) @baz()
+}
+
+define i32 @soft_float_fn() #4 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: soft_float_fn
+; CHECK: call i32 @foo
+}
+
+attributes #0 = { "target-cpu"="generic" "target-features"="+dsp,+neon" }
+attributes #1 = { "target-cpu"="generic" "target-features"="+dsp,+neon,+fp16" }
+attributes #2 = { "target-cpu"="generic" "target-features"="+dsp,+neon,+fp16,+thumb-mode" }
+attributes #3 = { "target-cpu"="generic" "target-features"="+dsp,+neon,+strict-align" }
+attributes #4 = { "target-cpu"="generic" "target-features"="+dsp,+neon,+fp16,+soft-float" }

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

Added: llvm/trunk/test/Transforms/Inline/ARM/loop-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ARM/loop-add.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ARM/loop-add.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ARM/loop-add.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,95 @@
+; RUN: opt -inline %s -S | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-arm-none-eabi"
+
+; CHECK-LABEL: void @doCalls
+define void @doCalls(i8* nocapture %p1, i8* nocapture %p2, i32 %n) #0 {
+entry:
+  %div = lshr i32 %n, 1
+; CHECK: call void @LoopCall
+  tail call void @LoopCall(i8* %p1, i8* %p2, i32 %div) #0
+
+  %div2 = lshr i32 %n, 2
+; CHECK: call void @LoopCall
+  tail call void @LoopCall(i8* %p1, i8* %p2, i32 %div2) #0
+
+; CHECK-NOT: call void @LoopCall
+  tail call void @LoopCall(i8* %p2, i8* %p1, i32 0) #0
+
+; CHECK-NOT: call void @LoopCall_internal
+  tail call void @LoopCall_internal(i8* %p1, i8* %p2, i32 %div2) #0
+
+  %div3 = lshr i32 %n, 4
+; CHECK-NOT: call void @SimpleCall
+  tail call void @SimpleCall(i8* %p2, i8* %p1, i32 %div3) #0
+  ret void
+}
+
+; CHECK-LABEL: define void @LoopCall
+define void @LoopCall(i8* nocapture %dest, i8* nocapture readonly %source, i32 %num) #0 {
+entry:
+  %c = icmp ne i32 %num, 0
+  br i1 %c, label %while.cond, label %while.end
+
+while.cond:                                       ; preds = %while.body, %entry
+  %num.addr.0 = phi i32 [ %num, %entry ], [ %dec, %while.body ]
+  %p_dest.0 = phi i8* [ %dest, %entry ], [ %incdec.ptr2, %while.body ]
+  %p_source.0 = phi i8* [ %source, %entry ], [ %incdec.ptr, %while.body ]
+  %cmp = icmp eq i32 %num.addr.0, 0
+  br i1 %cmp, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  %incdec.ptr = getelementptr inbounds i8, i8* %p_source.0, i32 1
+  %0 = load i8, i8* %p_source.0, align 1
+  %1 = trunc i32 %num.addr.0 to i8
+  %conv1 = add i8 %0, %1
+  %incdec.ptr2 = getelementptr inbounds i8, i8* %p_dest.0, i32 1
+  store i8 %conv1, i8* %p_dest.0, align 1
+  %dec = add i32 %num.addr.0, -1
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  ret void
+}
+
+; CHECK-LABEL-NOT: define void @LoopCall_internal
+define internal void @LoopCall_internal(i8* nocapture %dest, i8* nocapture readonly %source, i32 %num) #0 {
+entry:
+  %c = icmp ne i32 %num, 0
+  br i1 %c, label %while.cond, label %while.end
+
+while.cond:                                       ; preds = %while.body, %entry
+  %num.addr.0 = phi i32 [ %num, %entry ], [ %dec, %while.body ]
+  %p_dest.0 = phi i8* [ %dest, %entry ], [ %incdec.ptr2, %while.body ]
+  %p_source.0 = phi i8* [ %source, %entry ], [ %incdec.ptr, %while.body ]
+  %cmp = icmp eq i32 %num.addr.0, 0
+  br i1 %cmp, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  %incdec.ptr = getelementptr inbounds i8, i8* %p_source.0, i32 1
+  %0 = load i8, i8* %p_source.0, align 1
+  %1 = trunc i32 %num.addr.0 to i8
+  %conv1 = add i8 %0, %1
+  %incdec.ptr2 = getelementptr inbounds i8, i8* %p_dest.0, i32 1
+  store i8 %conv1, i8* %p_dest.0, align 1
+  %dec = add i32 %num.addr.0, -1
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  ret void
+}
+
+; CHECK-LABEL: define void @SimpleCall
+define void @SimpleCall(i8* nocapture %dest, i8* nocapture readonly %source, i32 %num) #0 {
+entry:
+  %arrayidx = getelementptr inbounds i8, i8* %source, i32 %num
+  %0 = load i8, i8* %arrayidx, align 1
+  %1 = xor i8 %0, 127
+  %arrayidx2 = getelementptr inbounds i8, i8* %dest, i32 %num
+  store i8 %1, i8* %arrayidx2, align 1
+  ret void
+}
+
+attributes #0 = { minsize optsize }
+

Added: llvm/trunk/test/Transforms/Inline/ARM/loop-memcpy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ARM/loop-memcpy.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ARM/loop-memcpy.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ARM/loop-memcpy.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; RUN: opt -inline %s -S | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-arm-none-eabi"
+
+; CHECK-LABEL: define void @matcpy
+define void @matcpy(i8* %dest, i8* %source, i32 %num) #0 {
+entry:
+  %0 = ptrtoint i8* %dest to i32
+  %1 = ptrtoint i8* %source to i32
+  %2 = xor i32 %0, %1
+  %3 = and i32 %2, 3
+  %cmp = icmp eq i32 %3, 0
+  br i1 %cmp, label %if.then, label %if.else20
+
+if.then:                                          ; preds = %entry
+  %sub = sub i32 0, %0
+  %and2 = and i32 %sub, 3
+  %add = or i32 %and2, 4
+  %cmp3 = icmp ugt i32 %add, %num
+  br i1 %cmp3, label %if.else, label %if.then4
+
+if.then4:                                         ; preds = %if.then
+  %sub5 = sub i32 %num, %and2
+  %shr = and i32 %sub5, -4
+  %sub7 = sub i32 %sub5, %shr
+  %tobool = icmp eq i32 %and2, 0
+  br i1 %tobool, label %if.end, label %if.then8
+
+if.then8:                                         ; preds = %if.then4
+; CHECK: call fastcc void @memcpy
+  call fastcc void @memcpy(i8* %dest, i8* %source, i32 %and2) #0
+  %add.ptr = getelementptr inbounds i8, i8* %dest, i32 %and2
+  %add.ptr9 = getelementptr inbounds i8, i8* %source, i32 %and2
+  br label %if.end
+
+if.end:                                           ; preds = %if.then4, %if.then8
+  %p_dest.0 = phi i8* [ %add.ptr, %if.then8 ], [ %dest, %if.then4 ]
+  %p_source.0 = phi i8* [ %add.ptr9, %if.then8 ], [ %source, %if.then4 ]
+  %tobool14 = icmp eq i32 %sub7, 0
+  br i1 %tobool14, label %if.end22, label %if.then15
+
+if.then15:                                        ; preds = %if.end
+  %add.ptr13 = getelementptr inbounds i8, i8* %p_source.0, i32 %shr
+  %add.ptr11 = getelementptr inbounds i8, i8* %p_dest.0, i32 %shr
+; CHECK: call fastcc void @memcpy
+  call fastcc void @memcpy(i8* %add.ptr11, i8* %add.ptr13, i32 %sub7) #0
+  br label %if.end22
+
+if.else:                                          ; preds = %if.then
+  call fastcc void @memcpy(i8* %dest, i8* %source, i32 %num) #0
+  br label %if.end22
+
+if.else20:                                        ; preds = %entry
+  call fastcc void @memcpy(i8* %dest, i8* %source, i32 %num) #0
+  br label %if.end22
+
+if.end22:                                         ; preds = %if.then15, %if.end, %if.else, %if.else20
+  ret void
+}
+
+; CHECK-LABEL: define internal void @memcpy
+define internal void @memcpy(i8* nocapture %dest, i8* nocapture readonly %source, i32 %num) #0 {
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %entry
+  %num.addr.0 = phi i32 [ %num, %entry ], [ %dec, %while.body ]
+  %p_dest.0 = phi i8* [ %dest, %entry ], [ %incdec.ptr1, %while.body ]
+  %p_source.0 = phi i8* [ %source, %entry ], [ %incdec.ptr, %while.body ]
+  %cmp = icmp eq i32 %num.addr.0, 0
+  br i1 %cmp, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  %incdec.ptr = getelementptr inbounds i8, i8* %p_source.0, i32 1
+  %0 = load i8, i8* %p_source.0, align 1
+  %incdec.ptr1 = getelementptr inbounds i8, i8* %p_dest.0, i32 1
+  store i8 %0, i8* %p_dest.0, align 1
+  %dec = add i32 %num.addr.0, -1
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  ret void
+}
+
+attributes #0 = { minsize optsize }
+

Added: llvm/trunk/test/Transforms/Inline/ARM/loop-noinline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ARM/loop-noinline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ARM/loop-noinline.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ARM/loop-noinline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -inline %s -S | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-arm-none-eabi"
+
+; Check we don't inline loops at -Oz. They tend to be larger than we
+; expect.
+
+; CHECK: define i8* @H
+ at digits = constant [16 x i8] c"0123456789ABCDEF", align 1
+define i8* @H(i8* %p, i32 %val, i32 %num) #0 {
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %entry
+  %p.addr.0 = phi i8* [ %p, %entry ], [ %incdec.ptr, %do.body ]
+  %val.addr.0 = phi i32 [ %val, %entry ], [ %shl, %do.body ]
+  %num.addr.0 = phi i32 [ %num, %entry ], [ %dec, %do.body ]
+  %shr = lshr i32 %val.addr.0, 28
+  %arrayidx = getelementptr inbounds [16 x i8], [16 x i8]* @digits, i32 0, i32 %shr
+  %0 = load i8, i8* %arrayidx, align 1
+  %incdec.ptr = getelementptr inbounds i8, i8* %p.addr.0, i32 1
+  store i8 %0, i8* %p.addr.0, align 1
+  %shl = shl i32 %val.addr.0, 4
+  %dec = add i32 %num.addr.0, -1
+  %tobool = icmp eq i32 %dec, 0
+  br i1 %tobool, label %do.end, label %do.body
+
+do.end:                                           ; preds = %do.body
+  %scevgep = getelementptr i8, i8* %p, i32 %num
+  ret i8* %scevgep
+}
+
+define nonnull i8* @call1(i8* %p, i32 %val, i32 %num) #0 {
+entry:
+; CHECK: tail call i8* @H
+  %call = tail call i8* @H(i8* %p, i32 %val, i32 %num) #0
+  ret i8* %call
+}
+
+define nonnull i8* @call2(i8* %p, i32 %val) #0 {
+entry:
+; CHECK: tail call i8* @H
+  %call = tail call i8* @H(i8* %p, i32 %val, i32 32) #0
+  ret i8* %call
+}
+
+attributes #0 = { minsize optsize }
+

Added: llvm/trunk/test/Transforms/Inline/PR4909.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/PR4909.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/PR4909.ll (added)
+++ llvm/trunk/test/Transforms/Inline/PR4909.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -partial-inliner -disable-output
+; RUN: opt < %s -passes=partial-inliner -disable-output
+
+define i32 @f() {
+entry:
+  br label %return
+
+return:                                           ; preds = %entry
+  ret i32 undef
+}
+
+define i32 @g() {
+entry:
+  %0 = call i32 @f()
+  ret i32 %0
+}

Added: llvm/trunk/test/Transforms/Inline/PowerPC/ext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/PowerPC/ext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/PowerPC/ext.ll (added)
+++ llvm/trunk/test/Transforms/Inline/PowerPC/ext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,140 @@
+; REQUIRES: asserts
+; RUN: opt -inline -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
+
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64le-ibm-linux-gnu"
+
+define i16 @outer1(i8* %ptr) {
+  %C = call i16 @inner1(i8* %ptr)
+  ret i16 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner1
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i16 @inner1(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i16
+  ret i16 %E
+}
+
+define i32 @outer2(i8* %ptr) {
+  %C = call i32 @inner2(i8* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner2
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner2(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer3(i16* %ptr) {
+  %C = call i32 @inner3(i16* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner3
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner3(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = zext i16 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer4(i16* %ptr) {
+  %C = call i32 @inner4(i16* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner4
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner4(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = sext i16 %L to i32
+  ret i32 %E
+}
+
+define i64 @outer5(i8* %ptr) {
+  %C = call i64 @inner5(i8* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner5
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner5(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer6(i16* %ptr) {
+  %C = call i64 @inner6(i16* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner6
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner6(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = zext i16 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer7(i16* %ptr) {
+  %C = call i64 @inner7(i16* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner7
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner7(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = sext i16 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer8(i32* %ptr) {
+  %C = call i64 @inner8(i32* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner8
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner8(i32* %ptr) {
+  %L = load i32, i32* %ptr
+  %E = zext i32 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer9(i32* %ptr) {
+  %C = call i64 @inner9(i32* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner9
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner9(i32* %ptr) {
+  %L = load i32, i32* %ptr
+  %E = sext i32 %L to i64
+  ret i64 %E
+}

Added: llvm/trunk/test/Transforms/Inline/PowerPC/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/PowerPC/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/PowerPC/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/Inline/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/Inline/X86/ext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/X86/ext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/X86/ext.ll (added)
+++ llvm/trunk/test/Transforms/Inline/X86/ext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,201 @@
+; REQUIRES: asserts
+; RUN: opt -inline -mtriple=x86_64-unknown-unknown -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-unknown"
+
+define i32 @outer1(i32* %ptr, i32 %i) {
+  %C = call i32 @inner1(i32* %ptr, i32 %i)
+  ret i32 %C
+}
+
+; zext from i32 to i64 is free.
+; CHECK: Analyzing call of inner1
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i32 @inner1(i32* %ptr, i32 %i) {
+  %E = zext i32 %i to i64
+  %G = getelementptr inbounds i32, i32* %ptr, i64 %E
+  %L = load i32, i32* %G
+  ret i32 %L
+}
+
+define i16 @outer2(i8* %ptr) {
+  %C = call i16 @inner2(i8* %ptr)
+  ret i16 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner2
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i16 @inner2(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i16
+  ret i16 %E
+}
+
+define i16 @outer3(i8* %ptr) {
+  %C = call i16 @inner3(i8* %ptr)
+  ret i16 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner3
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i16 @inner3(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = sext i8 %L to i16
+  ret i16 %E
+}
+
+define i32 @outer4(i8* %ptr) {
+  %C = call i32 @inner4(i8* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner4
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner4(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer5(i8* %ptr) {
+  %C = call i32 @inner5(i8* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner5
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner5(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = sext i8 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer6(i16* %ptr) {
+  %C = call i32 @inner6(i16* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner6
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner6(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = zext i16 %L to i32
+  ret i32 %E
+}
+
+define i32 @outer7(i16* %ptr) {
+  %C = call i32 @inner7(i16* %ptr)
+  ret i32 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner7
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i32 @inner7(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = sext i16 %L to i32
+  ret i32 %E
+}
+
+define i64 @outer8(i8* %ptr) {
+  %C = call i64 @inner8(i8* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner8
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner8(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = zext i8 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer9(i8* %ptr) {
+  %C = call i64 @inner9(i8* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner9
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner9(i8* %ptr) {
+  %L = load i8, i8* %ptr
+  %E = sext i8 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer10(i16* %ptr) {
+  %C = call i64 @inner10(i16* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner10
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner10(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = zext i16 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer11(i16* %ptr) {
+  %C = call i64 @inner11(i16* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner11
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner11(i16* %ptr) {
+  %L = load i16, i16* %ptr
+  %E = sext i16 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer12(i32* %ptr) {
+  %C = call i64 @inner12(i32* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner12
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner12(i32* %ptr) {
+  %L = load i32, i32* %ptr
+  %E = zext i32 %L to i64
+  ret i64 %E
+}
+
+define i64 @outer13(i32* %ptr) {
+  %C = call i64 @inner13(i32* %ptr)
+  ret i64 %C
+}
+
+; It is an ExtLoad.
+; CHECK: Analyzing call of inner13
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 3
+define i64 @inner13(i32* %ptr) {
+  %L = load i32, i32* %ptr
+  %E = sext i32 %L to i64
+  ret i64 %E
+}

Added: llvm/trunk/test/Transforms/Inline/X86/inline-target-attr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/X86/inline-target-attr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/X86/inline-target-attr.ll (added)
+++ llvm/trunk/test/Transforms/Inline/X86/inline-target-attr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -S -inline | FileCheck %s
+; RUN: opt < %s -mtriple=x86_64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s
+; Check that we only inline when we have compatible target attributes.
+; X86 has implemented a target attribute that will verify that the attribute
+; sets are compatible.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @foo() #0 {
+entry:
+  %call = call i32 (...) @baz()
+  ret i32 %call
+; CHECK-LABEL: foo
+; CHECK: call i32 (...) @baz()
+}
+declare i32 @baz(...) #0
+
+define i32 @bar() #1 {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+; CHECK-LABEL: bar
+; CHECK: call i32 (...) @baz()
+}
+
+define i32 @qux() #0 {
+entry:
+  %call = call i32 @bar()
+  ret i32 %call
+; CHECK-LABEL: qux
+; CHECK: call i32 @bar()
+}
+
+attributes #0 = { "target-cpu"="x86-64" "target-features"="+sse,+sse2" }
+attributes #1 = { "target-cpu"="x86-64" "target-features"="+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3" }

Added: llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-i686.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-i686.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-i686.ll (added)
+++ llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-i686.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -mtriple=i686-unknown-unknown -S -inline | FileCheck %s
+
+define i32 @func_target_cpu_nocona() #0 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @target_cpu_prescott_call_target_cpu_nocona(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_prescott_call_target_cpu_nocona() #1 {
+  %call = call i32 @func_target_cpu_nocona()
+  ret i32 %call
+}
+
+attributes #0 = { nounwind "target-cpu"="nocona" }
+attributes #1 = { nounwind "target-cpu"="prescott" }

Added: llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-x86_64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-x86_64.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-x86_64.ll (added)
+++ llvm/trunk/test/Transforms/Inline/X86/inline-target-cpu-x86_64.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt < %s -mtriple=x86_64-unknown-unknown -S -inline | FileCheck %s
+
+define i32 @func_target_cpu_base() #0 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @target_cpu_k8_call_target_cpu_base(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_k8_call_target_cpu_base() #1 {
+  %call = call i32 @func_target_cpu_base()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @target_cpu_target_nehalem_call_target_cpu_base(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_target_nehalem_call_target_cpu_base() #2 {
+  %call = call i32 @func_target_cpu_base()
+  ret i32 %call
+}
+
+; CHECK-LABEL: @target_cpu_target_goldmont_call_target_cpu_base(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_target_goldmont_call_target_cpu_base() #3 {
+  %call = call i32 @func_target_cpu_base()
+  ret i32 %call
+}
+
+define i32 @func_target_cpu_nocona() #4 {
+  ret i32 0
+}
+
+; CHECK-LABEL: @target_cpu_target_base_call_target_cpu_nocona(
+; CHECK-NEXT: ret i32 0
+define i32 @target_cpu_target_base_call_target_cpu_nocona() #0 {
+  %call = call i32 @func_target_cpu_nocona()
+  ret i32 %call
+}
+
+attributes #0 = { nounwind "target-cpu"="x86-64" }
+attributes #1 = { nounwind "target-cpu"="k8" }
+attributes #2 = { nounwind "target-cpu"="nehalem" }
+attributes #3 = { nounwind "target-cpu"="goldmont" }
+attributes #4 = { nounwind "target-cpu"="nocona" "target-features"="-sse3" }

Added: llvm/trunk/test/Transforms/Inline/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/Inline/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/Inline/align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/align.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/align.ll (added)
+++ llvm/trunk/test/Transforms/Inline/align.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,98 @@
+; RUN: opt -inline -preserve-alignment-assumptions-during-inlining -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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @hello(float* align 128 nocapture %a, float* nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 5
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 {
+entry:
+  tail call void @hello(float* %a, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %ptrint = ptrtoint float* %a to i64
+; CHECK:   %maskedptr = and i64 %ptrint, 127
+; CHECK:   %maskcond = icmp eq i64 %maskedptr, 0
+; CHECK:   call void @llvm.assume(i1 %maskcond)
+; CHECK:   %0 = load float, float* %c, align 4
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i, align 4
+; CHECK:   %1 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+define void @fooa(float* nocapture align 128 %a, float* nocapture readonly %c) #0 {
+entry:
+  tail call void @hello(float* %a, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @fooa(float* nocapture align 128 %a, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %0 = load float, float* %c, align 4
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i, align 4
+; CHECK:   %1 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+define void @hello2(float* align 128 nocapture %a, float* align 128 nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 5
+  store float %0, float* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds float, float* %b, i64 8
+  store float %0, float* %arrayidx1, align 4
+  ret void
+}
+
+define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  tail call void @hello2(float* %a, float* %b, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %ptrint = ptrtoint float* %a to i64
+; CHECK:   %maskedptr = and i64 %ptrint, 127
+; CHECK:   %maskcond = icmp eq i64 %maskedptr, 0
+; CHECK:   call void @llvm.assume(i1 %maskcond)
+; CHECK:   %ptrint1 = ptrtoint float* %b to i64
+; CHECK:   %maskedptr2 = and i64 %ptrint1, 127
+; CHECK:   %maskcond3 = icmp eq i64 %maskedptr2, 0
+; CHECK:   call void @llvm.assume(i1 %maskcond3)
+; CHECK:   %0 = load float, float* %c, align 4
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i, align 4
+; CHECK:   %arrayidx1.i = getelementptr inbounds float, float* %b, i64 8
+; CHECK:   store float %0, float* %arrayidx1.i, align 4
+; CHECK:   %1 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+attributes #0 = { nounwind uwtable }
+

Added: llvm/trunk/test/Transforms/Inline/alloca-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/alloca-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/alloca-bonus.ll (added)
+++ llvm/trunk/test/Transforms/Inline/alloca-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,162 @@
+; RUN: opt -inline < %s -S -o - -inline-threshold=8 | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' < %s -S -o - -inline-threshold=8 | FileCheck %s
+
+target datalayout = "p:32:32"
+
+declare void @llvm.lifetime.start.p0i8(i64 %size, i8* nocapture %ptr)
+
+ at glbl = external global i32
+
+define void @outer1() {
+; CHECK-LABEL: @outer1(
+; CHECK-NOT: call void @inner1
+  %ptr = alloca i32
+  call void @inner1(i32* %ptr)
+  ret void
+}
+
+define void @inner1(i32 *%ptr) {
+  %A = load i32, i32* %ptr
+  store i32 0, i32* %ptr
+  %C = getelementptr inbounds i32, i32* %ptr, i32 0
+  %D = getelementptr inbounds i32, i32* %ptr, i32 1
+  %E = bitcast i32* %ptr to i8*
+  %F = select i1 false, i32* %ptr, i32* @glbl
+  call void @llvm.lifetime.start.p0i8(i64 0, i8* %E)
+  call void @extern()
+  ret void
+}
+
+define void @outer2() {
+; CHECK-LABEL: @outer2(
+; CHECK: call void @inner2
+  %ptr = alloca i32
+  call void @inner2(i32* %ptr)
+  ret void
+}
+
+; %D poisons this call, scalar-repl can't handle that instruction.
+define void @inner2(i32 *%ptr) {
+  %A = load i32, i32* %ptr
+  store i32 0, i32* %ptr
+  %C = getelementptr inbounds i32, i32* %ptr, i32 0
+  %D = getelementptr inbounds i32, i32* %ptr, i32 %A
+  %E = bitcast i32* %ptr to i8*
+  %F = select i1 false, i32* %ptr, i32* @glbl
+  call void @llvm.lifetime.start.p0i8(i64 0, i8* %E)
+  call void @extern()
+  ret void
+}
+
+define void @outer3() {
+; CHECK-LABEL: @outer3(
+; CHECK-NOT: call void @inner3
+  %ptr = alloca i32
+  call void @inner3(i32* %ptr, i1 undef)
+  ret void
+}
+
+define void @inner3(i32 *%ptr, i1 %x) {
+  %A = icmp eq i32* %ptr, null
+  %B = and i1 %x, %A
+  call void @extern()
+  br i1 %A, label %bb.true, label %bb.false
+bb.true:
+  ; This block musn't be counted in the inline cost.
+  %t1 = load i32, i32* %ptr
+  %t2 = add i32 %t1, 1
+  %t3 = add i32 %t2, 1
+  %t4 = add i32 %t3, 1
+  %t5 = add i32 %t4, 1
+  %t6 = add i32 %t5, 1
+  %t7 = add i32 %t6, 1
+  %t8 = add i32 %t7, 1
+  %t9 = add i32 %t8, 1
+  %t10 = add i32 %t9, 1
+  %t11 = add i32 %t10, 1
+  %t12 = add i32 %t11, 1
+  %t13 = add i32 %t12, 1
+  %t14 = add i32 %t13, 1
+  %t15 = add i32 %t14, 1
+  %t16 = add i32 %t15, 1
+  %t17 = add i32 %t16, 1
+  %t18 = add i32 %t17, 1
+  %t19 = add i32 %t18, 1
+  %t20 = add i32 %t19, 1
+  ret void
+bb.false:
+  ret void
+}
+
+define void @outer4(i32 %A) {
+; CHECK-LABEL: @outer4(
+; CHECK-NOT: call void @inner4
+  %ptr = alloca i32
+  call void @inner4(i32* %ptr, i32 %A)
+  ret void
+}
+
+; %B poisons this call, scalar-repl can't handle that instruction. However, we
+; still want to detect that the icmp and branch *can* be handled.
+define void @inner4(i32 *%ptr, i32 %A) {
+  %B = getelementptr inbounds i32, i32* %ptr, i32 %A
+  %C = icmp eq i32* %ptr, null
+  call void @extern()
+  br i1 %C, label %bb.true, label %bb.false
+bb.true:
+  ; This block musn't be counted in the inline cost.
+  %t1 = load i32, i32* %ptr
+  %t2 = add i32 %t1, 1
+  %t3 = add i32 %t2, 1
+  %t4 = add i32 %t3, 1
+  %t5 = add i32 %t4, 1
+  %t6 = add i32 %t5, 1
+  %t7 = add i32 %t6, 1
+  %t8 = add i32 %t7, 1
+  %t9 = add i32 %t8, 1
+  %t10 = add i32 %t9, 1
+  %t11 = add i32 %t10, 1
+  %t12 = add i32 %t11, 1
+  %t13 = add i32 %t12, 1
+  %t14 = add i32 %t13, 1
+  %t15 = add i32 %t14, 1
+  %t16 = add i32 %t15, 1
+  %t17 = add i32 %t16, 1
+  %t18 = add i32 %t17, 1
+  %t19 = add i32 %t18, 1
+  %t20 = add i32 %t19, 1
+  ret void
+bb.false:
+  ret void
+}
+
+define void @outer5() {
+; CHECK-LABEL: @outer5(
+; CHECK-NOT: call void @inner5
+  %ptr = alloca i32
+  call void @inner5(i1 false, i32* %ptr)
+  ret void
+}
+
+; %D poisons this call, scalar-repl can't handle that instruction. However, if
+; the flag is set appropriately, the poisoning instruction is inside of dead
+; code, and so shouldn't be counted.
+define void @inner5(i1 %flag, i32 *%ptr) {
+  %A = load i32, i32* %ptr
+  store i32 0, i32* %ptr
+  call void @extern()
+  %C = getelementptr inbounds i32, i32* %ptr, i32 0
+  br i1 %flag, label %if.then, label %exit
+
+if.then:
+  %D = getelementptr inbounds i32, i32* %ptr, i32 %A
+  %E = bitcast i32* %ptr to i8*
+  %F = select i1 false, i32* %ptr, i32* @glbl
+  call void @llvm.lifetime.start.p0i8(i64 0, i8* %E)
+  ret void
+
+exit:
+  ret void
+}
+
+declare void @extern()

Added: llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare-merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare-merge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare-merge.ll (added)
+++ llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare-merge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,101 @@
+; Test that alloca merging in the inliner places dbg.declare calls immediately
+; after the merged alloca. Not at the end of the entry BB, and definitely not
+; before the alloca.
+;
+; clang -g -S -emit-llvm -Xclang -disable-llvm-optzns
+;
+;__attribute__((always_inline)) void f() {
+;  char aaa[100];
+;  aaa[10] = 1;
+;}
+;
+;__attribute__((always_inline)) void g() {
+;  char bbb[100];
+;  bbb[20] = 1;
+;}
+;
+;void h() {
+;  f();
+;  g();
+;}
+;
+; RUN: opt -always-inline -S < %s | FileCheck %s
+;
+; CHECK:      define void @h()
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %[[AI:.*]] = alloca [100 x i8]
+; CHECK-NEXT:   call void @llvm.dbg.declare(metadata [100 x i8]* %[[AI]],
+; CHECK-NEXT:   call void @llvm.dbg.declare(metadata [100 x i8]* %[[AI]],
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: alwaysinline nounwind uwtable
+define void @f() #0 !dbg !4 {
+entry:
+  %aaa = alloca [100 x i8], align 16
+  call void @llvm.dbg.declare(metadata [100 x i8]* %aaa, metadata !12, metadata !17), !dbg !18
+  %arrayidx = getelementptr inbounds [100 x i8], [100 x i8]* %aaa, i64 0, i64 10, !dbg !19
+  store i8 1, i8* %arrayidx, align 2, !dbg !20
+  ret void, !dbg !21
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: alwaysinline nounwind uwtable
+define void @g() #0 !dbg !7 {
+entry:
+  %bbb = alloca [100 x i8], align 16
+  call void @llvm.dbg.declare(metadata [100 x i8]* %bbb, metadata !22, metadata !17), !dbg !23
+  %arrayidx = getelementptr inbounds [100 x i8], [100 x i8]* %bbb, i64 0, i64 20, !dbg !24
+  store i8 1, i8* %arrayidx, align 4, !dbg !25
+  ret void, !dbg !26
+}
+
+; Function Attrs: nounwind uwtable
+define void @h() #2 !dbg !8 {
+entry:
+  call void @f(), !dbg !27
+  call void @g(), !dbg !28
+  ret void, !dbg !29
+}
+
+attributes #0 = { alwaysinline nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (trunk 248518) (llvm/trunk 248512)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "../1.c", directory: "/code/llvm-git/build")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null}
+!7 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 6, type: !5, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: false, unit: !0, retainedNodes: !2)
+!8 = distinct !DISubprogram(name: "h", scope: !1, file: !1, line: 11, type: !5, isLocal: false, isDefinition: true, scopeLine: 11, isOptimized: false, unit: !0, retainedNodes: !2)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{!"clang version 3.8.0 (trunk 248518) (llvm/trunk 248512)"}
+!12 = !DILocalVariable(name: "aaa", scope: !4, file: !1, line: 2, type: !13)
+!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !14, size: 800, align: 8, elements: !15)
+!14 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
+!15 = !{!16}
+!16 = !DISubrange(count: 100)
+!17 = !DIExpression()
+!18 = !DILocation(line: 2, column: 8, scope: !4)
+!19 = !DILocation(line: 3, column: 3, scope: !4)
+!20 = !DILocation(line: 3, column: 11, scope: !4)
+!21 = !DILocation(line: 4, column: 1, scope: !4)
+!22 = !DILocalVariable(name: "bbb", scope: !7, file: !1, line: 7, type: !13)
+!23 = !DILocation(line: 7, column: 8, scope: !7)
+!24 = !DILocation(line: 8, column: 3, scope: !7)
+!25 = !DILocation(line: 8, column: 11, scope: !7)
+!26 = !DILocation(line: 9, column: 1, scope: !7)
+!27 = !DILocation(line: 12, column: 3, scope: !8)
+!28 = !DILocation(line: 13, column: 3, scope: !8)
+!29 = !DILocation(line: 14, column: 1, scope: !8)

Added: llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare.ll (added)
+++ llvm/trunk/test/Transforms/Inline/alloca-dbgdeclare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,131 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+; struct A {
+;   int arg0;
+;   double arg1[2];
+; } a, b;
+;  
+; void fn3(A p1) {
+;   if (p1.arg0)
+;     a = p1;
+; }
+;  
+; void fn4() { fn3(b); }
+;  
+; void fn5() {
+;   while (1)
+;     fn4();
+; }
+; ModuleID = 'test.cpp'
+source_filename = "test/Transforms/Inline/alloca-dbgdeclare.ll"
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-apple-darwin"
+
+%struct.A = type { i32, [2 x double] }
+
+ at a = global %struct.A zeroinitializer, align 8, !dbg !0
+ at b = global %struct.A zeroinitializer, align 8, !dbg !12
+
+; Function Attrs: nounwind
+declare void @_Z3fn31A(%struct.A* nocapture readonly) #0
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) #2
+
+; Function Attrs: nounwind
+define void @_Z3fn4v() #0 !dbg !22 {
+entry:
+; Test that the dbg.declare is moved together with the alloca.
+; CHECK: define void @_Z3fn5v()
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %agg.tmp.sroa.3.i = alloca [20 x i8], align 4
+; CHECK-NEXT:   call void @llvm.dbg.declare(metadata [20 x i8]* %agg.tmp.sroa.3.i,
+  %agg.tmp.sroa.3 = alloca [20 x i8], align 4
+  tail call void @llvm.dbg.declare(metadata [20 x i8]* %agg.tmp.sroa.3, metadata !25, metadata !30), !dbg !31
+  %agg.tmp.sroa.0.0.copyload = load i32, i32* getelementptr inbounds (%struct.A, %struct.A* @b, i64 0, i32 0), align 8, !dbg !33
+  tail call void @llvm.dbg.value(metadata i32 %agg.tmp.sroa.0.0.copyload, metadata !25, metadata !34), !dbg !31
+  %agg.tmp.sroa.3.0..sroa_idx = getelementptr inbounds [20 x i8], [20 x i8]* %agg.tmp.sroa.3, i64 0, i64 0, !dbg !33
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %agg.tmp.sroa.3.0..sroa_idx, i8* align 4 getelementptr (i8, i8* bitcast (%struct.A* @b to i8*), i64 4), i64 20, i1 false), !dbg !33
+  tail call void @llvm.dbg.declare(metadata %struct.A* undef, metadata !25, metadata !35) #0, !dbg !31
+  %tobool.i = icmp eq i32 %agg.tmp.sroa.0.0.copyload, 0, !dbg !36
+  br i1 %tobool.i, label %_Z3fn31A.exit, label %if.then.i, !dbg !38
+
+if.then.i:                                        ; preds = %entry
+  store i32 %agg.tmp.sroa.0.0.copyload, i32* getelementptr inbounds (%struct.A, %struct.A* @a, i64 0, i32 0), align 8, !dbg !39
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 4), i8* align 4 %agg.tmp.sroa.3.0..sroa_idx, i64 20, i1 false), !dbg !39
+  br label %_Z3fn31A.exit, !dbg !39
+
+_Z3fn31A.exit:                                    ; preds = %if.then.i, %entry
+
+  ret void, !dbg !33
+}
+
+; Function Attrs: noreturn nounwind
+define void @_Z3fn5v() #3 !dbg !40 {
+entry:
+  br label %while.body, !dbg !41
+
+while.body:                                       ; preds = %while.body, %entry
+  call void @_Z3fn4v(), !dbg !42
+  br label %while.body, !dbg !41
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+attributes #2 = { argmemonly nounwind }
+attributes #3 = { noreturn nounwind }
+
+!llvm.dbg.cu = !{!14}
+!llvm.module.flags = !{!19, !20}
+!llvm.ident = !{!21}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 4, type: !3, isLocal: false, isDefinition: true)
+!2 = !DIFile(filename: "test.cpp", directory: "")
+!3 = !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !2, line: 1, size: 192, align: 64, elements: !4, identifier: "_ZTS1A")
+!4 = !{!5, !7}
+!5 = !DIDerivedType(tag: DW_TAG_member, name: "arg0", scope: !3, file: !2, line: 2, baseType: !6, size: 32, align: 32)
+!6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!7 = !DIDerivedType(tag: DW_TAG_member, name: "arg1", scope: !3, file: !2, line: 3, baseType: !8, size: 128, align: 64, offset: 64)
+!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 128, align: 64, elements: !10)
+!9 = !DIBasicType(name: "double", size: 64, align: 64, encoding: DW_ATE_float)
+!10 = !{!11}
+!11 = !DISubrange(count: 2)
+!12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression())
+!13 = !DIGlobalVariable(name: "b", scope: null, file: !2, line: 4, type: !3, isLocal: false, isDefinition: true)
+!14 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !15, producer: "clang version 3.7.0 (trunk 227480) (llvm/trunk 227517)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !16, retainedTypes: !17, globals: !18, imports: !16)
+!15 = !DIFile(filename: "<stdin>", directory: "")
+!16 = !{}
+!17 = !{!3}
+!18 = !{!0, !12}
+!19 = !{i32 2, !"Dwarf Version", i32 4}
+!20 = !{i32 2, !"Debug Info Version", i32 3}
+!21 = !{!"clang version 3.7.0 (trunk 227480) (llvm/trunk 227517)"}
+!22 = distinct !DISubprogram(name: "fn4", linkageName: "_Z3fn4v", scope: !2, file: !2, line: 11, type: !23, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: true, unit: !14, retainedNodes: !16)
+!23 = !DISubroutineType(types: !24)
+!24 = !{null}
+!25 = !DILocalVariable(name: "p1", arg: 1, scope: !26, file: !2, line: 6, type: !3)
+!26 = distinct !DISubprogram(name: "fn3", linkageName: "_Z3fn31A", scope: !2, file: !2, line: 6, type: !27, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !14, retainedNodes: !29)
+!27 = !DISubroutineType(types: !28)
+!28 = !{null, !3}
+!29 = !{!25}
+!30 = !DIExpression(DW_OP_LLVM_fragment, 32, 160)
+!31 = !DILocation(line: 6, scope: !26, inlinedAt: !32)
+!32 = distinct !DILocation(line: 11, scope: !22)
+!33 = !DILocation(line: 11, scope: !22)
+!34 = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+!35 = !DIExpression(DW_OP_deref)
+!36 = !DILocation(line: 7, scope: !37, inlinedAt: !32)
+!37 = distinct !DILexicalBlock(scope: !26, file: !2, line: 7)
+!38 = !DILocation(line: 7, scope: !26, inlinedAt: !32)
+!39 = !DILocation(line: 8, scope: !37, inlinedAt: !32)
+!40 = distinct !DISubprogram(name: "fn5", linkageName: "_Z3fn5v", scope: !2, file: !2, line: 13, type: !23, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !14, retainedNodes: !16)
+!41 = !DILocation(line: 14, scope: !40)
+!42 = !DILocation(line: 15, scope: !40)
+

Added: llvm/trunk/test/Transforms/Inline/alloca-in-scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/alloca-in-scc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/alloca-in-scc.ll (added)
+++ llvm/trunk/test/Transforms/Inline/alloca-in-scc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt < %s -inline | llvm-dis
+
+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"
+
+define i32 @main(i32 %argc, i8** %argv) nounwind ssp {
+entry:
+  call fastcc void @c() nounwind
+  unreachable
+}
+
+define internal fastcc void @a() nounwind ssp {
+entry:
+  %al = alloca [3 x i32], align 4
+  %0 = getelementptr inbounds [3 x i32], [3 x i32]* %al, i32 0, i32 2 
+  
+  call fastcc void @c() nounwind
+  unreachable
+}
+
+define internal fastcc void @b() nounwind ssp {
+entry:
+  tail call fastcc void @a() nounwind ssp
+  unreachable
+}
+
+define internal fastcc void @c() nounwind ssp {
+entry:
+  call fastcc void @b() nounwind
+  unreachable
+}

Added: llvm/trunk/test/Transforms/Inline/alloca-merge-align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/alloca-merge-align.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/alloca-merge-align.ll (added)
+++ llvm/trunk/test/Transforms/Inline/alloca-merge-align.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,104 @@
+; RUN: opt < %s -inline -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-f128:128:128-v128:128:128-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+%struct.s = type { i32, i32 }
+
+define void @foo(%struct.s* byval nocapture readonly %a) {
+entry:
+  %x = alloca [2 x i32], align 4
+  %a1 = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 0
+  %0 = load i32, i32* %a1, align 4
+  %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 0
+  store i32 %0, i32* %arrayidx, align 4
+  %b = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 1
+  %1 = load i32, i32* %b, align 4
+  %arrayidx2 = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 1
+  store i32 %1, i32* %arrayidx2, align 4
+  call void @bar(i32* %arrayidx) #2
+  ret void
+}
+
+define void @foo0(%struct.s* byval nocapture readonly %a) {
+entry:
+  %x = alloca [2 x i32]
+  %a1 = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 0
+  %0 = load i32, i32* %a1, align 4
+  %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 0
+  store i32 %0, i32* %arrayidx, align 4
+  %b = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 1
+  %1 = load i32, i32* %b, align 4
+  %arrayidx2 = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 1
+  store i32 %1, i32* %arrayidx2, align 4
+  call void @bar(i32* %arrayidx) #2
+  ret void
+}
+
+define void @foo1(%struct.s* byval nocapture readonly %a) {
+entry:
+  %x = alloca [2 x i32], align 1
+  %a1 = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 0
+  %0 = load i32, i32* %a1, align 4
+  %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 0
+  store i32 %0, i32* %arrayidx, align 4
+  %b = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 1
+  %1 = load i32, i32* %b, align 4
+  %arrayidx2 = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 1
+  store i32 %1, i32* %arrayidx2, align 4
+  call void @bar(i32* %arrayidx) #2
+  ret void
+}
+
+declare void @bar(i32*) #1
+
+define void @goo(%struct.s* byval nocapture readonly %a) {
+entry:
+  %x = alloca [2 x i32], align 32
+  %a1 = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 0
+  %0 = load i32, i32* %a1, align 4
+  %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 0
+  store i32 %0, i32* %arrayidx, align 32
+  %b = getelementptr inbounds %struct.s, %struct.s* %a, i64 0, i32 1
+  %1 = load i32, i32* %b, align 4
+  %arrayidx2 = getelementptr inbounds [2 x i32], [2 x i32]* %x, i64 0, i64 1
+  store i32 %1, i32* %arrayidx2, align 4
+  call void @bar(i32* %arrayidx) #2
+  ret void
+}
+
+; CHECK-LABEL: @main
+; CHECK: alloca [2 x i32], align 32
+; CHECK-NOT: alloca [2 x i32]
+; CHECK: ret i32 0
+
+define signext i32 @main() {
+entry:
+  %a = alloca i64, align 8
+  %tmpcast = bitcast i64* %a to %struct.s*
+  store i64 0, i64* %a, align 8
+  %a1 = bitcast i64* %a to i32*
+  store i32 1, i32* %a1, align 8
+  call void @foo(%struct.s* byval %tmpcast)
+  store i32 2, i32* %a1, align 8
+  call void @goo(%struct.s* byval %tmpcast)
+  ret i32 0
+}
+
+; CHECK-LABEL: @test0
+; CHECK: alloca [2 x i32], align 32
+; CHECK-NOT: alloca [2 x i32]
+; CHECK: ret i32 0
+
+define signext i32 @test0() {
+entry:
+  %a = alloca i64, align 8
+  %tmpcast = bitcast i64* %a to %struct.s*
+  store i64 0, i64* %a, align 8
+  %a1 = bitcast i64* %a to i32*
+  store i32 1, i32* %a1, align 8
+  call void @foo0(%struct.s* byval %tmpcast)
+  store i32 2, i32* %a1, align 8
+  call void @goo(%struct.s* byval %tmpcast)
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/Inline/alloca_test.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/alloca_test.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/alloca_test.ll (added)
+++ llvm/trunk/test/Transforms/Inline/alloca_test.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; This test ensures that alloca instructions in the entry block for an inlined
+; function are moved to the top of the function they are inlined into.
+;
+; RUN: opt -S -inline < %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' < %s | FileCheck %s
+
+define i32 @func(i32 %i) {
+  %X = alloca i32
+  store i32 %i, i32* %X
+  ret i32 %i
+}
+
+declare void @bar()
+
+define i32 @main(i32 %argc) {
+; CHECK-LABEL: @main(
+; CHECK-NEXT:  Entry:
+; CHECK-NEXT:    [[X_I:%.*]] = alloca i32
+;
+Entry:
+  call void @bar( )
+  %X = call i32 @func( i32 7 )
+  %Y = add i32 %X, %argc
+  ret i32 %Y
+}
+
+; https://llvm.org/bugs/show_bug.cgi?id=27277
+; Don't assume that the size is a ConstantInt (an undef value is also a constant).
+
+define void @PR27277(i32 %p1) {
+; CHECK-LABEL: @PR27277(
+; CHECK-NEXT:    [[VLA:%.*]] = alloca double, i32 %p1
+; CHECK-NEXT:    call void @PR27277(i32 undef)
+; CHECK-NEXT:    ret void
+;
+  %vla = alloca double, i32 %p1
+  call void @PR27277(i32 undef)
+  ret void
+}
+
+; Don't assume that the size is a ConstantInt (a ConstExpr is also a constant).
+
+ at GV = common global i32* null
+
+define void @PR27277_part2(i32 %p1) {
+; CHECK-LABEL: @PR27277_part2(
+; CHECK-NEXT:    [[VLA:%.*]] = alloca double, i32 %p1
+; CHECK-NEXT:    call void @PR27277_part2(i32 ptrtoint (i32** @GV to i32))
+; CHECK-NEXT:    ret void
+;
+  %vla = alloca double, i32 %p1
+  call void @PR27277_part2(i32 ptrtoint (i32** @GV to i32))
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/always-inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/always-inline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/always-inline.ll (added)
+++ llvm/trunk/test/Transforms/Inline/always-inline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,318 @@
+; RUN: opt < %s -inline-threshold=0 -always-inline -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL
+;
+; Ensure the threshold has no impact on these decisions.
+; RUN: opt < %s -inline-threshold=20000000 -always-inline -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL
+; RUN: opt < %s -inline-threshold=-20000000 -always-inline -S | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CALL
+;
+; The new pass manager doesn't re-use any threshold based infrastructure for
+; the always inliner, but test that we get the correct result. The new PM
+; always inliner also doesn't support inlining call-site alwaysinline
+; annotations. It isn't clear that this is a reasonable use case for
+; 'alwaysinline'.
+; RUN: opt < %s -passes=always-inline -S | FileCheck %s --check-prefix=CHECK
+
+define internal i32 @inner1() alwaysinline {
+; CHECK-NOT: @inner1(
+  ret i32 1
+}
+define i32 @outer1() {
+; CHECK-LABEL: @outer1(
+; CHECK-NOT: call
+; CHECK: ret
+
+   %r = call i32 @inner1()
+   ret i32 %r
+}
+
+; The always inliner can't DCE arbitrary internal functions. PR2945
+define internal i32 @pr2945() nounwind {
+; CHECK-LABEL: @pr2945(
+  ret i32 0
+}
+
+define internal void @inner2(i32 %N) alwaysinline {
+; CHECK-NOT: @inner2(
+  %P = alloca i32, i32 %N
+  ret void
+}
+define void @outer2(i32 %N) {
+; The always inliner (unlike the normal one) should be willing to inline
+; a function with a dynamic alloca into one without a dynamic alloca.
+; rdar://6655932
+;
+; CHECK-LABEL: @outer2(
+; CHECK-NOT: call void @inner2
+; CHECK-NOT: call void @inner2
+; CHECK: ret void
+
+  call void @inner2( i32 %N )
+  ret void
+}
+
+declare i32 @a() returns_twice
+declare i32 @b() returns_twice
+
+; Cannot alwaysinline when that would introduce a returns_twice call.
+define internal i32 @inner3() alwaysinline {
+; CHECK-LABEL: @inner3(
+entry:
+  %call = call i32 @a() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+define i32 @outer3() {
+entry:
+; CHECK-LABEL: @outer3(
+; CHECK-NOT: call i32 @a
+; CHECK: ret
+
+  %call = call i32 @inner3()
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define internal i32 @inner4() alwaysinline returns_twice {
+; CHECK-NOT: @inner4(
+entry:
+  %call = call i32 @b() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define i32 @outer4() {
+entry:
+; CHECK-LABEL: @outer4(
+; CHECK: call i32 @b()
+; CHECK: ret
+
+  %call = call i32 @inner4() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+; We can't inline this even though it has alwaysinline!
+define internal i32 @inner5(i8* %addr) alwaysinline {
+; CHECK-LABEL: @inner5(
+entry:
+  indirectbr i8* %addr, [ label %one, label %two ]
+
+one:
+  ret i32 42
+
+two:
+  ret i32 44
+}
+define i32 @outer5(i32 %x) {
+; CHECK-LABEL: @outer5(
+; CHECK: call i32 @inner5
+; CHECK: ret
+
+  %cmp = icmp slt i32 %x, 42
+  %addr = select i1 %cmp, i8* blockaddress(@inner5, %one), i8* blockaddress(@inner5, %two)
+  %call = call i32 @inner5(i8* %addr)
+  ret i32 %call
+}
+
+; We alwaysinline a function that call itself recursively.
+define internal void @inner6(i32 %x) alwaysinline {
+; CHECK-LABEL: @inner6(
+entry:
+  %icmp = icmp slt i32 %x, 0
+  br i1 %icmp, label %return, label %bb
+
+bb:
+  %sub = sub nsw i32 %x, 1
+  call void @inner6(i32 %sub)
+  ret void
+
+return:
+  ret void
+}
+define void @outer6() {
+; CHECK-LABEL: @outer6(
+; CHECK: call void @inner6(i32 42)
+; CHECK: ret
+
+entry:
+  call void @inner6(i32 42)
+  ret void
+}
+
+; This is not an alwaysinline function and is actually external.
+define i32 @inner7() {
+; CHECK-LABEL: @inner7(
+  ret i32 1
+}
+define i32 @outer7() {
+; CHECK-CALL-LABEL: @outer7(
+; CHECK-CALL-NOT: call
+; CHECK-CALL: ret
+
+   %r = call i32 @inner7() alwaysinline
+   ret i32 %r
+}
+
+define internal float* @inner8(float* nocapture align 128 %a) alwaysinline {
+; CHECK-NOT: @inner8(
+  ret float* %a
+}
+define float @outer8(float* nocapture %a) {
+; CHECK-LABEL: @outer8(
+; CHECK-NOT: call float* @inner8
+; CHECK: ret
+
+  %inner_a = call float* @inner8(float* %a)
+  %f = load float, float* %inner_a, align 4
+  ret float %f
+}
+
+
+; The 'inner9*' and 'outer9' functions are designed to check that we remove
+; a function that is inlined by the always inliner even when it is used by
+; a complex constant expression prior to being inlined.
+
+; The 'a' function gets used in a complex constant expression that, despite
+; being constant folded, means it isn't dead. As a consequence it shouldn't be
+; deleted. If it is, then the constant expression needs to become more complex
+; to accurately test this scenario.
+define internal void @inner9a(i1 %b) alwaysinline {
+; CHECK-LABEL: @inner9a(
+entry:
+  ret void
+}
+
+define internal void @inner9b(i1 %b) alwaysinline {
+; CHECK-NOT: @inner9b(
+entry:
+  ret void
+}
+
+declare void @dummy9(i1 %b)
+
+define void @outer9() {
+; CHECK-LABEL: @outer9(
+entry:
+  ; First we use @inner9a in a complex constant expression that may get folded
+  ; but won't get removed, and then we call it which will get inlined. Despite
+  ; this the function can't be deleted because of the constant expression
+  ; usage.
+  %sink = alloca i1
+  store volatile i1 icmp eq (i64 ptrtoint (void (i1)* @inner9a to i64), i64 ptrtoint(void (i1)* @dummy9 to i64)), i1* %sink
+; CHECK: store volatile
+  call void @inner9a(i1 false)
+; CHECK-NOT: call void @inner9a
+
+  ; Next we call @inner9b passing in a constant expression. This constant
+  ; expression will in fact be removed by inlining, so we should also be able
+  ; to delete the function.
+  call void @inner9b(i1 icmp eq (i64 ptrtoint (void (i1)* @inner9b to i64), i64 ptrtoint(void (i1)* @dummy9 to i64)))
+; CHECK-NOT: @inner9b
+
+  ret void
+; CHECK: ret void
+}
+
+; The 'inner10' and 'outer10' functions test a frustrating consquence of the
+; current 'alwaysinline' semantic model. Because such functions are allowed to
+; be external functions, it may be necessary to both inline all of their uses
+; and leave them in the final output. These tests can be removed if and when
+; we restrict alwaysinline further.
+define void @inner10() alwaysinline {
+; CHECK-LABEL: @inner10(
+entry:
+  ret void
+}
+
+define void @outer10() {
+; CHECK-LABEL: @outer10(
+entry:
+  call void @inner10()
+; CHECK-NOT: call void @inner10
+
+  ret void
+; CHECK: ret void
+}
+
+; The 'inner11' and 'outer11' functions test another dimension of non-internal
+; functions with alwaysinline. These functions use external linkages that we can
+; actually remove safely and so we should.
+define linkonce void @inner11a() alwaysinline {
+; CHECK-NOT: @inner11a(
+entry:
+  ret void
+}
+
+define available_externally void @inner11b() alwaysinline {
+; CHECK-NOT: @inner11b(
+entry:
+  ret void
+}
+
+define void @outer11() {
+; CHECK-LABEL: @outer11(
+entry:
+  call void @inner11a()
+  call void @inner11b()
+; CHECK-NOT: call void @inner11a
+; CHECK-NOT: call void @inner11b
+
+  ret void
+; CHECK: ret void
+}
+
+; The 'inner12' and 'outer12' functions test that we don't remove functions
+; which are part of a comdat group even if they otherwise seem dead.
+$comdat12 = comdat any
+
+define linkonce void @inner12() alwaysinline comdat($comdat12) {
+; CHECK-LABEL: @inner12(
+  ret void
+}
+
+define void @outer12() comdat($comdat12) {
+; CHECK-LABEL: @outer12(
+entry:
+  call void @inner12()
+; CHECK-NOT: call void @inner12
+
+  ret void
+; CHECK: ret void
+}
+
+; The 'inner13*' and 'outer13' functions test that we do remove functions
+; which are part of a comdat group where all of the members are removed during
+; always inlining.
+$comdat13 = comdat any
+
+define linkonce void @inner13a() alwaysinline comdat($comdat13) {
+; CHECK-NOT: @inner13a(
+  ret void
+}
+
+define linkonce void @inner13b() alwaysinline comdat($comdat13) {
+; CHECK-NOT: @inner13b(
+  ret void
+}
+
+define void @outer13() {
+; CHECK-LABEL: @outer13(
+entry:
+  call void @inner13a()
+  call void @inner13b()
+; CHECK-NOT: call void @inner13a
+; CHECK-NOT: call void @inner13b
+
+  ret void
+; CHECK: ret void
+}
+
+define void @inner14() readnone nounwind {
+; CHECK: define void @inner14
+  ret void
+}
+
+define void @outer14() {
+; CHECK: call void @inner14
+  call void @inner14()
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/arg-attr-propagation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/arg-attr-propagation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/arg-attr-propagation.ll (added)
+++ llvm/trunk/test/Transforms/Inline/arg-attr-propagation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+
+; The callee guarantees that the pointer argument is nonnull and dereferenceable.
+; That information should transfer to the caller.
+
+define i32 @callee(i32* dereferenceable(32) %t1) {
+; CHECK-LABEL: @callee(i32* dereferenceable(32) %t1)
+; CHECK-NEXT:    [[T2:%.*]] = load i32, i32* %t1
+; CHECK-NEXT:    ret i32 [[T2]]
+;
+  %t2 = load i32, i32* %t1
+  ret i32 %t2
+}
+
+; FIXME: All dereferenceability information is lost.
+; The caller argument could be known nonnull and dereferenceable(32).
+
+define i32 @caller1(i32* %t1) {
+; CHECK-LABEL: @caller1(i32* %t1)
+; CHECK-NEXT:    [[T2_I:%.*]] = load i32, i32* %t1
+; CHECK-NEXT:    ret i32 [[T2_I]]
+;
+  %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1)
+  ret i32 %t2
+}
+
+; The caller argument is nonnull, but that can be explicit.
+; The dereferenceable amount could be increased.
+
+define i32 @caller2(i32* dereferenceable(31) %t1) {
+; CHECK-LABEL: @caller2(i32* dereferenceable(31) %t1)
+; CHECK-NEXT:    [[T2_I:%.*]] = load i32, i32* %t1
+; CHECK-NEXT:    ret i32 [[T2_I]]
+;
+  %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1)
+  ret i32 %t2
+}
+
+; The caller argument is nonnull, but that can be explicit.
+; Make sure that we don't propagate a smaller dereferenceable amount.
+
+define i32 @caller3(i32* dereferenceable(33) %t1) {
+; CHECK-LABEL: @caller3(i32* dereferenceable(33) %t1)
+; CHECK-NEXT:    [[T2_I:%.*]] = load i32, i32* %t1
+; CHECK-NEXT:    ret i32 [[T2_I]]
+;
+  %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1)
+  ret i32 %t2
+}
+

Added: llvm/trunk/test/Transforms/Inline/array-alloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/array-alloca.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/array-alloca.ll (added)
+++ llvm/trunk/test/Transforms/Inline/array-alloca.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+%struct.A = type { i32 }
+
+define void @callee1(i32 %M) {
+entry:
+  %vla = alloca i32, i32 %M, align 16
+  ret void
+}
+
+define void @callee2(i32 %M) {
+entry:
+  %vla = alloca %struct.A, i32 %M, align 16
+  ret void
+}
+
+define void @callee3(i128 %M) {
+entry:
+  %vla = alloca i32, i128 %M, align 16
+  ret void
+}
+
+; CHECK-LABEL: @caller
+define void @caller() #0 {
+entry:
+  call void @caller()
+; CHECK-NOT: call void @callee1
+  call void @callee1(i32 256)
+; CHECK: call void @callee2
+  call void @callee2(i32 4096)
+; CHECK: call void @callee3
+; This is to test that there is no overflow in computing allocated size
+; call void @callee3(i128 0x8000000000000000);
+  call void @callee3(i128 9223372036854775808);
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/array_merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/array_merge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/array_merge.ll (added)
+++ llvm/trunk/test/Transforms/Inline/array_merge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; rdar://7173846
+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"
+
+define internal void @foo() nounwind ssp {
+entry:
+  %A = alloca [100 x i32]
+  %B = alloca [100 x i32]
+  call void @bar([100 x i32]* %A, [100 x i32]* %B) nounwind
+  ret void
+}
+
+declare void @bar([100 x i32]*, [100 x i32]*)
+
+define void @test() nounwind ssp {
+entry:
+; CHECK: @test()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %A.i = alloca
+; CHECK-NEXT: %B.i = alloca
+; CHECK-NOT: alloca
+  call void @foo() nounwind
+  call void @foo() nounwind
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/attributes.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/attributes.ll (added)
+++ llvm/trunk/test/Transforms/Inline/attributes.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,418 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -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"
+
+define i32 @noattr_callee(i32 %i) {
+  ret i32 %i
+}
+
+define i32 @sanitize_address_callee(i32 %i) sanitize_address {
+  ret i32 %i
+}
+
+define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress {
+  ret i32 %i
+}
+
+define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {
+  ret i32 %i
+}
+
+define i32 @sanitize_memory_callee(i32 %i) sanitize_memory {
+  ret i32 %i
+}
+
+define i32 @safestack_callee(i32 %i) safestack {
+  ret i32 %i
+}
+
+define i32 @slh_callee(i32 %i) speculative_load_hardening {
+  ret i32 %i
+}
+
+define i32 @alwaysinline_callee(i32 %i) alwaysinline {
+  ret i32 %i
+}
+
+define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address {
+  ret i32 %i
+}
+
+define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress {
+  ret i32 %i
+}
+
+define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread {
+  ret i32 %i
+}
+
+define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory {
+  ret i32 %i
+}
+
+define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack {
+  ret i32 %i
+}
+
+
+; Check that:
+;  * noattr callee is inlined into noattr caller,
+;  * sanitize_(address|memory|thread) callee is not inlined into noattr caller,
+;  * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
+
+define i32 @test_no_sanitize_address(i32 %arg) {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_address_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_no_sanitize_address(
+; CHECK-NEXT: @sanitize_address_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no_sanitize_hwaddress(i32 %arg) {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_no_sanitize_hwaddress(
+; CHECK-NEXT: @sanitize_hwaddress_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no_sanitize_memory(i32 %arg) {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_memory_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_no_sanitize_memory(
+; CHECK-NEXT: @sanitize_memory_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no_sanitize_thread(i32 %arg) {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_thread_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_no_sanitize_thread(
+; CHECK-NEXT: @sanitize_thread_callee
+; CHECK-NEXT: ret i32
+}
+
+
+; Check that:
+;  * noattr callee is not inlined into sanitize_(address|memory|thread) caller,
+;  * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute,
+;  * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
+
+define i32 @test_sanitize_address(i32 %arg) sanitize_address {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_address_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_sanitize_address(
+; CHECK-NEXT: @noattr_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_sanitize_hwaddress(
+; CHECK-NEXT: @noattr_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_memory_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_sanitize_memory(
+; CHECK-NEXT: @noattr_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_sanitize_thread(i32 %arg) sanitize_thread {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @sanitize_thread_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_sanitize_thread(
+; CHECK-NEXT: @noattr_callee
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_safestack(i32 %arg) safestack {
+  %x1 = call i32 @noattr_callee(i32 %arg)
+  %x2 = call i32 @safestack_callee(i32 %x1)
+  %x3 = call i32 @alwaysinline_callee(i32 %x2)
+  %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3)
+  ret i32 %x4
+; CHECK-LABEL: @test_safestack(
+; CHECK-NEXT: @noattr_callee
+; CHECK-NEXT: ret i32
+}
+
+; Can inline a normal function into an SLH'ed function.
+define i32 @test_caller_slh(i32 %i) speculative_load_hardening {
+; CHECK-LABEL: @test_caller_slh(
+; CHECK-SAME: ) [[SLH:.*]] {
+; CHECK-NOT: call
+; CHECK: ret i32
+entry:
+  %callee = call i32 @noattr_callee(i32 %i)
+  ret i32 %callee
+}
+
+; Can inline a SLH'ed function into a normal one, propagating SLH.
+define i32 @test_callee_slh(i32 %i) {
+; CHECK-LABEL: @test_callee_slh(
+; CHECK-SAME: ) [[SLH:.*]] {
+; CHECK-NOT: call
+; CHECK: ret i32
+entry:
+  %callee = call i32 @slh_callee(i32 %i)
+  ret i32 %callee
+}
+
+; Check that a function doesn't get inlined if target-cpu strings don't match
+; exactly.
+define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" {
+  ret i32 %i
+}
+
+define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" {
+  %1 = call i32 @test_target_cpu_callee0(i32 %i)
+  ret i32 %1
+; CHECK-LABEL: @test_target_cpu0(
+; CHECK-NOT: @test_target_cpu_callee0
+}
+
+define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" {
+  ret i32 %i
+}
+
+define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" {
+  %1 = call i32 @test_target_cpu_callee1(i32 %i)
+  ret i32 %1
+; CHECK-LABEL: @test_target_cpu1(
+; CHECK-NEXT: @test_target_cpu_callee1
+; CHECK-NEXT: ret i32
+}
+
+; Check that a function doesn't get inlined if target-features strings don't
+; match exactly.
+define i32 @test_target_features_callee0(i32 %i)  "target-features"="+sse4.2" {
+  ret i32 %i
+}
+
+define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" {
+  %1 = call i32 @test_target_features_callee0(i32 %i)
+  ret i32 %1
+; CHECK-LABEL: @test_target_features0(
+; CHECK-NOT: @test_target_features_callee0
+}
+
+define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" {
+  ret i32 %i
+}
+
+define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" {
+  %1 = call i32 @test_target_features_callee1(i32 %i)
+  ret i32 %1
+; CHECK-LABEL: @test_target_features1(
+; CHECK-NEXT: @test_target_features_callee1
+; CHECK-NEXT: ret i32
+}
+
+define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" {
+  ret i32 %i
+; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" {
+  ret i32 %i
+; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" {
+  %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" {
+  %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" {
+  %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" {
+  %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @no-implicit-float_callee0(i32 %i) {
+  ret i32 %i
+; CHECK: @no-implicit-float_callee0(i32 %i) {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat {
+  ret i32 %i
+; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-implicit-float0(i32 %i) {
+  %1 = call i32 @no-implicit-float_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-implicit-float0(i32 %i) {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-implicit-float1(i32 %i) {
+  %1 = call i32 @no-implicit-float_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat {
+  %1 = call i32 @no-implicit-float_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {
+  %1 = call i32 @no-implicit-float_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] {
+; CHECK-NEXT: ret i32
+}
+
+; Check that no-jump-tables flag propagates from inlined callee to caller 
+
+define i32 @no-use-jump-tables_callee0(i32 %i) {
+  ret i32 %i
+; CHECK: @no-use-jump-tables_callee0(i32 %i) {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" {
+  ret i32 %i
+; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-use-jump-tables0(i32 %i) {
+  %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-use-jump-tables0(i32 %i) {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-use-jump-tables1(i32 %i) {
+  %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" {
+  %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] {
+; CHECK-NEXT: ret i32
+}
+
+define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" {
+  %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] {
+; CHECK-NEXT: ret i32
+}
+
+; Callee with "null-pointer-is-valid"="true" attribute should not be inlined
+; into a caller without this attribute.
+; Exception: alwaysinline callee can still be inlined but
+; "null-pointer-is-valid"="true" should get copied to caller.
+
+define i32 @null-pointer-is-valid_callee0(i32 %i) "null-pointer-is-valid"="true" {
+  ret i32 %i
+; CHECK: @null-pointer-is-valid_callee0(i32 %i)
+; CHECK-NEXT: ret i32
+}
+
+define i32 @null-pointer-is-valid_callee1(i32 %i) alwaysinline "null-pointer-is-valid"="true" {
+  ret i32 %i
+; CHECK: @null-pointer-is-valid_callee1(i32 %i)
+; CHECK-NEXT: ret i32
+}
+
+define i32 @null-pointer-is-valid_callee2(i32 %i)  {
+  ret i32 %i
+; CHECK: @null-pointer-is-valid_callee2(i32 %i)
+; CHECK-NEXT: ret i32
+}
+
+; No inlining since caller does not have "null-pointer-is-valid"="true" attribute.
+define i32 @test_null-pointer-is-valid0(i32 %i) {
+  %1 = call i32 @null-pointer-is-valid_callee0(i32 %i)
+  ret i32 %1
+; CHECK: @test_null-pointer-is-valid0(
+; CHECK: call i32 @null-pointer-is-valid_callee0
+; CHECK-NEXT: ret i32
+}
+
+; alwaysinline should force inlining even when caller does not have
+; "null-pointer-is-valid"="true" attribute. However, the attribute should be
+; copied to caller.
+define i32 @test_null-pointer-is-valid1(i32 %i) "null-pointer-is-valid"="false" {
+  %1 = call i32 @null-pointer-is-valid_callee1(i32 %i)
+  ret i32 %1
+; CHECK: @test_null-pointer-is-valid1(i32 %i) [[NULLPOINTERISVALID:#[0-9]+]] {
+; CHECK-NEXT: ret i32
+}
+
+; Can inline since both caller and callee have "null-pointer-is-valid"="true"
+; attribute.
+define i32 @test_null-pointer-is-valid2(i32 %i) "null-pointer-is-valid"="true" {
+  %1 = call i32 @null-pointer-is-valid_callee2(i32 %i)
+  ret i32 %1
+; CHECK: @test_null-pointer-is-valid2(i32 %i) [[NULLPOINTERISVALID]] {
+; CHECK-NEXT: ret i32
+}
+
+; CHECK: attributes [[SLH]] = { speculative_load_hardening }
+; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }
+; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }
+; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }
+; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }
+; CHECK: attributes [[NULLPOINTERISVALID]] = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/Inline/basictest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/basictest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/basictest.ll (added)
+++ llvm/trunk/test/Transforms/Inline/basictest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,117 @@
+; RUN: opt < %s -inline -sroa -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline,function(sroa))' -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"
+
+define i32 @test1f(i32 %i) {
+        ret i32 %i
+}
+
+define i32 @test1(i32 %W) {
+        %X = call i32 @test1f(i32 7)
+        %Y = add i32 %X, %W
+        ret i32 %Y
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: %Y = add i32 7, %W
+; CHECK-NEXT: ret i32 %Y
+}
+
+
+
+; rdar://7339069
+
+%T = type { i32, i32 }
+
+; CHECK-NOT: @test2f(
+define internal %T* @test2f(i1 %cond, %T* %P) {
+  br i1 %cond, label %T, label %F
+  
+T:
+  %A = getelementptr %T, %T* %P, i32 0, i32 0
+  store i32 42, i32* %A
+  ret %T* %P
+  
+F:
+  ret %T* %P
+}
+
+define i32 @test2(i1 %cond) {
+  %A = alloca %T
+  
+  %B = call %T* @test2f(i1 %cond, %T* %A)
+  %C = getelementptr %T, %T* %B, i32 0, i32 0
+  %D = load i32, i32* %C
+  ret i32 %D
+  
+; CHECK-LABEL: @test2(
+; CHECK-NOT: = alloca
+; CHECK: ret i32
+}
+
+declare void @barrier() noduplicate
+
+define internal i32 @f() {
+  call void @barrier() noduplicate
+  ret i32 1
+}
+
+define i32 @g() {
+  call void @barrier() noduplicate
+  ret i32 2
+}
+
+define internal i32 @h() {
+  call void @barrier() noduplicate
+  ret i32 3
+}
+
+define i32 @test3() {
+  %b = call i32 @f()
+  ret i32 %b
+}
+
+; The call to @f cannot be inlined as there is another callsite
+; calling @f, and @f contains a noduplicate call.
+;
+; The call to @g cannot be inlined as it has external linkage.
+;
+; The call to @h *can* be inlined.
+
+; CHECK-LABEL: @test(
+define i32 @test() {
+; CHECK: call i32 @f()
+  %a = call i32 @f()
+; CHECK: call i32 @g()
+  %b = call i32 @g()
+; CHECK-NOT: call i32 @h()
+  %c = call i32 @h()
+
+  %d = add i32 %a, %b
+  %e = add i32 %d, %c
+
+  ret i32 %e
+; CHECK: }
+}
+
+; Inliner shouldn't delete calls it can't inline, even if they're trivially dead
+; CHECK-LABEL: @outer4(
+define void @outer4(void ()* %inner4) {
+entry:
+; CHECK: call void %inner4()
+  call void %inner4() nounwind readnone
+  ret void
+}
+
+declare void @inner5_inner()
+
+define void @inner5(void ()* %x) {
+  call void %x() nounwind readnone
+  ret void
+}
+
+; Inliner shouldn't delete calls it can't inline, even if they're trivially dead and temporarily indirect
+; CHECK-LABEL: @outer5(
+define void @outer5() {
+; CHECK: call void @inner5_inner(
+  call void @inner5(void ()* @inner5_inner)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/bfi-update.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/bfi-update.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/bfi-update.ll (added)
+++ llvm/trunk/test/Transforms/Inline/bfi-update.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,93 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S -inline-threshold=50 -inline-cold-callsite-threshold=0 -hot-callsite-threshold=50 | FileCheck %s
+; This tests incremental updates to caller's BFI as a callee gets inlined.
+; In bottom-up inlining, first c->e inlining is considered and fails because
+; e's size exceeds the threshold of 50. Then a->c inlining is considered and it
+; succeeds. a's BFI is updated incrementally. As c's blocks get pruned, the 
+; block with label cond_false is removed and since the remanining code is
+; straight-line a single block gets cloned into a. This block should get the
+; maximum block frequency among the original blocks in c. If it gets the
+; frequency of the block with label cond_true in @c, its frequency will be
+; 1/10th of function a's entry block frequency, resulting in a callsite count of
+; 2 (since a's entry count is 20) which means that a->e callsite will be
+; considered cold and not inlined. 
+
+ at data = external global i32
+; CHECK-LABEL: define i32 @a(
+define i32 @a(i32 %a1) !prof !21 {
+; CHECK-NOT: call i32 @c
+; CHECK-NOT: call i32 @e
+; CHECK: ret
+entry:
+  %cond = icmp sle i32 %a1, 1
+  %a2 = call i32 @c(i32 1)
+  br label %exit
+exit:
+  ret i32 %a2
+}
+
+declare void @ext();
+
+; CHECK: @c(i32 %c1) !prof [[COUNT1:![0-9]+]]
+define i32 @c(i32 %c1) !prof !23 {
+  call void @ext()
+  %cond = icmp sle i32 %c1, 1
+  br i1 %cond, label %cond_true, label %cond_false, !prof !25
+
+cond_false:
+  br label %exit
+
+cond_true:
+  %c11 = call i32 @e(i32 %c1)
+  br label %exit
+exit:
+  %c12 = phi i32 [ 0, %cond_false], [ %c11, %cond_true ]
+  ret i32 %c12
+}
+
+
+; CHECK: @e(i32 %c1) !prof [[COUNT2:![0-9]+]]
+define i32 @e(i32 %c1) !prof !24 {
+  call void @ext()
+  call void @ext()
+  %cond = icmp sle i32 %c1, 1
+  br i1 %cond, label %cond_true, label %cond_false
+
+cond_false:
+  call void @ext()
+  %c2 = load i32, i32* @data, align 4
+  %c3 = add i32 %c1, %c2
+  %c4 = mul i32 %c3, %c2
+  %c5 = add i32 %c4, %c2
+  %c6 = mul i32 %c5, %c2
+  %c7 = add i32 %c6, %c2
+  %c8 = mul i32 %c7, %c2
+  %c9 = add i32 %c8, %c2
+  %c10 = mul i32 %c9, %c2
+  ret i32 %c10
+
+cond_true:
+  ret i32 0
+}
+
+; CHECK: [[COUNT1]] = !{!"function_entry_count", i64 480}
+; CHECK: [[COUNT2]] = !{!"function_entry_count", i64 80}
+!21 = !{!"function_entry_count", i64 20}
+!23 = !{!"function_entry_count", i64 500}
+!24 = !{!"function_entry_count", i64 100}
+!25 = !{!"branch_weights", i32 1, i32 9}
+
+!llvm.module.flags = !{!1}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 1000}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 1000, i32 1}
+!13 = !{i32 999000, i64 1000, i32 1}
+!14 = !{i32 999999, i64 5, i32 2}

Added: llvm/trunk/test/Transforms/Inline/blockaddress.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/blockaddress.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/blockaddress.ll (added)
+++ llvm/trunk/test/Transforms/Inline/blockaddress.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+; PR10162
+
+; Make sure doit is not inlined since the blockaddress is taken
+; which could be unsafe
+; CHECK: store i8* blockaddress(@doit, %here), i8** %pptr, align 8
+
+ at i = global i32 1, align 4
+ at ptr1 = common global i8* null, align 8
+
+define void @doit(i8** nocapture %pptr, i32 %cond) nounwind uwtable {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end, label %here
+
+here:
+  store i8* blockaddress(@doit, %here), i8** %pptr, align 8
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define void @f(i32 %cond) nounwind uwtable {
+entry:
+  call void @doit(i8** @ptr1, i32 %cond)
+  ret void
+}
+
+; PR27233: We can inline @run into @init.  Don't crash on it.
+;
+; CHECK-LABEL: define void @init
+; CHECK:         store i8* blockaddress(@run, %bb)
+; CHECK-SAME:        @run.bb
+define void @init() {
+entry:
+  call void @run()
+  ret void
+}
+
+define void @run() {
+entry:
+  store i8* blockaddress(@run, %bb), i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @run.bb, i64 0, i64 0), align 8
+  ret void
+
+bb:
+  unreachable
+}
+
+ at run.bb = global [1 x i8*] zeroinitializer

Added: llvm/trunk/test/Transforms/Inline/byval-tail-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/byval-tail-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/byval-tail-call.ll (added)
+++ llvm/trunk/test/Transforms/Inline/byval-tail-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; RUN: opt < %s -basicaa -tailcallelim -inline -instcombine -dse -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='function(tailcallelim),cgscc(inline,function(instcombine,dse))' -S | FileCheck %s
+; PR7272
+
+; Calls that capture byval parameters cannot be marked as tail calls. Other
+; tails that don't capture byval parameters can still be tail calls.
+
+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-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+declare void @ext(i32*)
+
+define void @bar(i32* byval %x) {
+  call void @ext(i32* %x)
+  ret void
+}
+
+define void @foo(i32* %x) {
+; CHECK-LABEL: define void @foo(
+; CHECK: llvm.lifetime.start
+; CHECK: store i32 %2, i32* %x
+  call void @bar(i32* byval %x)
+  ret void
+}
+
+define internal void @qux(i32* byval %x) {
+  call void @ext(i32* %x)
+  tail call void @ext(i32* null)
+  ret void
+}
+
+define void @frob(i32* %x) {
+; CHECK-LABEL: define void @frob(
+; CHECK: %[[POS:.*]] = alloca i32
+; CHECK: %[[VAL:.*]] = load i32, i32* %x
+; CHECK: store i32 %[[VAL]], i32* %[[POS]]
+; CHECK: {{^ *}}call void @ext(i32* nonnull %[[POS]]
+; CHECK: tail call void @ext(i32* null)
+; CHECK: ret void
+  tail call void @qux(i32* byval %x)
+  ret void
+}
+
+; A byval parameter passed into a function which is passed out as byval does
+; not block the call from being marked as tail.
+
+declare void @ext2(i32* byval)
+
+define void @bar2(i32* byval %x) {
+  call void @ext2(i32* byval %x)
+  ret void
+}
+
+define void @foobar(i32* %x) {
+; CHECK-LABEL: define void @foobar(
+; CHECK: %[[POS:.*]] = alloca i32
+; CHECK: %[[VAL:.*]] = load i32, i32* %x
+; CHECK: store i32 %[[VAL]], i32* %[[POS]]
+; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]
+; CHECK: ret void
+  tail call void @bar2(i32* byval %x)
+  ret void
+}
+
+define void @barfoo() {
+; CHECK-LABEL: define void @barfoo(
+; CHECK: %[[POS:.*]] = alloca i32
+; CHECK: %[[VAL:.*]] = load i32, i32* %x
+; CHECK: store i32 %[[VAL]], i32* %[[POS]]
+; CHECK: tail call void @ext2(i32* byval nonnull %[[POS]]
+; CHECK: ret void
+  %x = alloca i32
+  tail call void @bar2(i32* byval %x)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/byval.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/byval.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/byval.ll (added)
+++ llvm/trunk/test/Transforms/Inline/byval.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,165 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; The verifier does catch problems with inlining of byval arguments that has a
+; different address space compared to the alloca. But running instcombine
+; after inline used to trigger asserts unless we disallow such inlining.
+; RUN: opt < %s -inline -instcombine -disable-output 2>/dev/null
+
+target datalayout = "p:32:32-p1:64:64-p2:16:16-n16:32:64"
+
+; Inlining a byval struct should cause an explicit copy into an alloca.
+
+	%struct.ss = type { i32, i64 }
+ at .str = internal constant [10 x i8] c"%d, %lld\0A\00"		; <[10 x i8]*> [#uses=1]
+
+define internal void @f(%struct.ss* byval  %b) nounwind  {
+entry:
+	%tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0		; <i32*> [#uses=2]
+	%tmp1 = load i32, i32* %tmp, align 4		; <i32> [#uses=1]
+	%tmp2 = add i32 %tmp1, 1		; <i32> [#uses=1]
+	store i32 %tmp2, i32* %tmp, align 4
+	ret void
+}
+
+declare i32 @printf(i8*, ...) nounwind 
+
+define i32 @test1() nounwind  {
+entry:
+	%S = alloca %struct.ss		; <%struct.ss*> [#uses=4]
+	%tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 1, i32* %tmp1, align 8
+	%tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1		; <i64*> [#uses=1]
+	store i64 2, i64* %tmp4, align 4
+	call void @f( %struct.ss* byval  %S ) nounwind 
+	ret i32 0
+; CHECK: @test1()
+; CHECK: %S1 = alloca %struct.ss
+; CHECK: %S = alloca %struct.ss
+; CHECK: call void @llvm.memcpy
+; CHECK: ret i32 0
+}
+
+; Inlining a byval struct should NOT cause an explicit copy 
+; into an alloca if the function is readonly
+
+define internal i32 @f2(%struct.ss* byval  %b) nounwind readonly {
+entry:
+	%tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0		; <i32*> [#uses=2]
+	%tmp1 = load i32, i32* %tmp, align 4		; <i32> [#uses=1]
+	%tmp2 = add i32 %tmp1, 1		; <i32> [#uses=1]
+	ret i32 %tmp2
+}
+
+define i32 @test2() nounwind  {
+entry:
+	%S = alloca %struct.ss		; <%struct.ss*> [#uses=4]
+	%tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 1, i32* %tmp1, align 8
+	%tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1		; <i64*> [#uses=1]
+	store i64 2, i64* %tmp4, align 4
+	%X = call i32 @f2( %struct.ss* byval  %S ) nounwind 
+	ret i32 %X
+; CHECK: @test2()
+; CHECK: %S = alloca %struct.ss
+; CHECK-NOT: call void @llvm.memcpy
+; CHECK: ret i32
+}
+
+
+; Inlining a byval with an explicit alignment needs to use *at least* that
+; alignment on the generated alloca.
+; PR8769
+declare void @g3(%struct.ss* %p)
+
+define internal void @f3(%struct.ss* byval align 64 %b) nounwind {
+   call void @g3(%struct.ss* %b)  ;; Could make alignment assumptions!
+   ret void
+}
+
+define void @test3() nounwind  {
+entry:
+	%S = alloca %struct.ss, align 1  ;; May not be aligned.
+	call void @f3( %struct.ss* byval align 64 %S) nounwind 
+	ret void
+; CHECK: @test3()
+; CHECK: %S1 = alloca %struct.ss, align 64
+; CHECK: %S = alloca %struct.ss
+; CHECK: call void @llvm.memcpy
+; CHECK: call void @g3(%struct.ss* %S1)
+; CHECK: ret void
+}
+
+
+; Inlining a byval struct should NOT cause an explicit copy 
+; into an alloca if the function is readonly, but should increase an alloca's
+; alignment to satisfy an explicit alignment request.
+
+define internal i32 @f4(%struct.ss* byval align 64 %b) nounwind readonly {
+        call void @g3(%struct.ss* %b)
+	ret i32 4
+}
+
+define i32 @test4() nounwind  {
+entry:
+	%S = alloca %struct.ss, align 2		; <%struct.ss*> [#uses=4]
+	%X = call i32 @f4( %struct.ss* byval align 64 %S ) nounwind 
+	ret i32 %X
+; CHECK: @test4()
+; CHECK: %S = alloca %struct.ss, align 64
+; CHECK-NOT: call void @llvm.memcpy
+; CHECK: call void @g3
+; CHECK: ret i32 4
+}
+
+%struct.S0 = type { i32 }
+
+ at b = global %struct.S0 { i32 1 }, align 4
+ at a = common global i32 0, align 4
+
+define internal void @f5(%struct.S0* byval nocapture readonly align 4 %p) {
+entry:
+	store i32 0, i32* getelementptr inbounds (%struct.S0, %struct.S0* @b, i64 0, i32 0), align 4
+	%f2 = getelementptr inbounds %struct.S0, %struct.S0* %p, i64 0, i32 0
+	%0 = load i32, i32* %f2, align 4
+	store i32 %0, i32* @a, align 4
+	ret void
+}
+
+define i32 @test5() {
+entry:
+	tail call void @f5(%struct.S0* byval align 4 @b)
+	%0 = load i32, i32* @a, align 4
+	ret i32 %0
+; CHECK: @test5()
+; CHECK: store i32 0, i32* getelementptr inbounds (%struct.S0, %struct.S0* @b, i64 0, i32 0), align 4
+; CHECK-NOT: load i32, i32* getelementptr inbounds (%struct.S0, %struct.S0* @b, i64 0, i32 0), align 4
+}
+
+; Inlining a byval struct that is in a different address space compared to the
+; alloca address space is at the moment not expected. That would need
+; adjustments inside the inlined function since the address space attribute of
+; the inlined argument changes.
+
+%struct.S1 = type { i32 }
+
+ at d = addrspace(1) global %struct.S1 { i32 1 }, align 4
+ at c = common addrspace(1) global i32 0, align 4
+
+define internal void @f5_as1(%struct.S1 addrspace(1)* byval nocapture readonly align 4 %p) {
+entry:
+	store i32 0, i32 addrspace(1)* getelementptr inbounds (%struct.S1, %struct.S1 addrspace(1)* @d, i64 0, i32 0), align 4
+	%f2 = getelementptr inbounds %struct.S1, %struct.S1 addrspace(1)* %p, i64 0, i32 0
+	%0 = load i32, i32 addrspace(1)* %f2, align 4
+	store i32 %0, i32 addrspace(1)* @c, align 4
+	ret void
+}
+
+define i32 @test5_as1() {
+entry:
+	tail call void @f5_as1(%struct.S1 addrspace(1)* byval align 4 @d)
+	%0 = load i32, i32 addrspace(1)* @c, align 4
+	ret i32 %0
+; CHECK: @test5_as1()
+; CHECK: call void @f5_as1
+}

Added: llvm/trunk/test/Transforms/Inline/byval_lifetime.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/byval_lifetime.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/byval_lifetime.ll (added)
+++ llvm/trunk/test/Transforms/Inline/byval_lifetime.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -S -inline < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+; By inlining foo, an alloca is created in main to hold the byval argument, so
+; a lifetime marker should be generated as well by default.
+
+%struct.foo = type { i32, [16 x i32] }
+
+ at gFoo = global %struct.foo zeroinitializer, align 8
+
+define i32 @foo(%struct.foo* byval align 8 %f, i32 %a) {
+entry:
+  %a1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i32 0, i32 1
+  %arrayidx = getelementptr inbounds [16 x i32], [16 x i32]* %a1, i32 0, i32 %a
+  %tmp2 = load i32, i32* %arrayidx, align 1
+  ret i32 %tmp2
+}
+
+define i32 @main(i32 %argc, i8** %argv) {
+; CHECK-LABEL: @main
+; CHECK: llvm.lifetime.start
+; CHECK: memcpy
+entry:
+  %call = call i32 @foo(%struct.foo* byval align 8 @gFoo, i32 %argc)
+  ret i32 %call
+}

Added: llvm/trunk/test/Transforms/Inline/callgraph-update.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/callgraph-update.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/callgraph-update.ll (added)
+++ llvm/trunk/test/Transforms/Inline/callgraph-update.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -inline -loop-rotate -verify-dom-info -verify-loop-info -disable-output
+; PR3601
+declare void @solve()
+
+define internal fastcc void @read() {
+	br label %bb4
+
+bb3:
+	br label %bb4
+
+bb4:
+	call void @solve()
+	br i1 false, label %bb5, label %bb3
+
+bb5:
+	unreachable
+}
+
+define internal fastcc void @parse() {
+	call fastcc void @read()
+	ret void
+}
+
+define void @main() personality i32 (...)* @__gxx_personality_v0 {
+	invoke fastcc void @parse()
+			to label %invcont unwind label %lpad
+
+invcont:
+	unreachable
+
+lpad:
+        %exn = landingpad {i8*, i32}
+                 cleanup
+	unreachable
+}
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/casts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/casts.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/casts.ll (added)
+++ llvm/trunk/test/Transforms/Inline/casts.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+define i32 @testByte(i8 %X) {
+entry:
+  %tmp = icmp ne i8 %X, 0
+  %tmp.i = zext i1 %tmp to i32
+  ret i32 %tmp.i
+}
+
+define i32 @main() {
+; CHECK-LABEL: define i32 @main()
+entry:
+  %rslt = call i32 @testByte(i8 123)
+; CHECK-NOT: call
+  ret i32 %rslt
+; CHECK: ret i32 1
+}

Added: llvm/trunk/test/Transforms/Inline/cfg_preserve_test.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cfg_preserve_test.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cfg_preserve_test.ll (added)
+++ llvm/trunk/test/Transforms/Inline/cfg_preserve_test.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; This test ensures that inlining an "empty" function does not destroy the CFG
+;
+; RUN: opt < %s -inline -S | FileCheck %s
+
+define i32 @func(i32 %i) {
+  ret i32 %i
+}
+
+
+define i32 @main() {
+; CHECK-LABEL: define i32 @main()
+entry:
+  %X = call i32 @func(i32 7)
+; CHECK-NOT: call
+; CHECK-NOT: br
+
+  ret i32 %X
+; CHECK: ret i32 7
+}
+

Added: llvm/trunk/test/Transforms/Inline/cgscc-cycle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-cycle.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cgscc-cycle.ll (added)
+++ llvm/trunk/test/Transforms/Inline/cgscc-cycle.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,232 @@
+; This test contains extremely tricky call graph structures for the inliner to
+; handle correctly. They form cycles where the inliner introduces code that is
+; immediately or can eventually be transformed back into the original code. And
+; each step changes the call graph and so will trigger iteration. This requires
+; some out-of-band way to prevent infinitely re-inlining and re-transforming the
+; code.
+;
+; RUN: opt < %s -passes='cgscc(inline,function(sroa,instcombine))' -inline-threshold=50 -S | FileCheck %s
+
+
+; The `test1_*` collection of functions form a directly cycling pattern.
+
+define void @test1_a(i8** %ptr) {
+; CHECK-LABEL: define void @test1_a(
+entry:
+  call void @test1_b(i8* bitcast (void (i8*, i1, i32)* @test1_b to i8*), i1 false, i32 0)
+; Inlining and simplifying this call will reliably produce the exact same call,
+; over and over again. However, each inlining increments the count, and so we
+; expect this test case to stop after one round of inlining with a final
+; argument of '1'.
+; CHECK-NOT:     call
+; CHECK:         call void @test1_b(i8* bitcast (void (i8*, i1, i32)* @test1_b to i8*), i1 false, i32 1)
+; CHECK-NOT:     call
+
+  ret void
+}
+
+define void @test1_b(i8* %arg, i1 %flag, i32 %inline_count) {
+; CHECK-LABEL: define void @test1_b(
+entry:
+  %a = alloca i8*
+  store i8* %arg, i8** %a
+; This alloca and store should remain through any optimization.
+; CHECK:         %[[A:.*]] = alloca
+; CHECK:         store i8* %arg, i8** %[[A]]
+
+  br i1 %flag, label %bb1, label %bb2
+
+bb1:
+  call void @test1_a(i8** %a) noinline
+  br label %bb2
+
+bb2:
+  %cast = bitcast i8** %a to void (i8*, i1, i32)**
+  %p = load void (i8*, i1, i32)*, void (i8*, i1, i32)** %cast
+  %inline_count_inc = add i32 %inline_count, 1
+  call void %p(i8* %arg, i1 %flag, i32 %inline_count_inc)
+; And we should continue to load and call indirectly through optimization.
+; CHECK:         %[[CAST:.*]] = bitcast i8** %[[A]] to void (i8*, i1, i32)**
+; CHECK:         %[[P:.*]] = load void (i8*, i1, i32)*, void (i8*, i1, i32)** %[[CAST]]
+; CHECK:         call void %[[P]](
+
+  ret void
+}
+
+define void @test2_a(i8** %ptr) {
+; CHECK-LABEL: define void @test2_a(
+entry:
+  call void @test2_b(i8* bitcast (void (i8*, i8*, i1, i32)* @test2_b to i8*), i8* bitcast (void (i8*, i8*, i1, i32)* @test2_c to i8*), i1 false, i32 0)
+; Inlining and simplifying this call will reliably produce the exact same call,
+; but only after doing two rounds if inlining, first from @test2_b then
+; @test2_c. We check the exact number of inlining rounds before we cut off to
+; break the cycle by inspecting the last paramater that gets incremented with
+; each inlined function body.
+; CHECK-NOT:     call
+; CHECK:         call void @test2_b(i8* bitcast (void (i8*, i8*, i1, i32)* @test2_b to i8*), i8* bitcast (void (i8*, i8*, i1, i32)* @test2_c to i8*), i1 false, i32 2)
+; CHECK-NOT:     call
+  ret void
+}
+
+define void @test2_b(i8* %arg1, i8* %arg2, i1 %flag, i32 %inline_count) {
+; CHECK-LABEL: define void @test2_b(
+entry:
+  %a = alloca i8*
+  store i8* %arg2, i8** %a
+; This alloca and store should remain through any optimization.
+; CHECK:         %[[A:.*]] = alloca
+; CHECK:         store i8* %arg2, i8** %[[A]]
+
+  br i1 %flag, label %bb1, label %bb2
+
+bb1:
+  call void @test2_a(i8** %a) noinline
+  br label %bb2
+
+bb2:
+  %p = load i8*, i8** %a
+  %cast = bitcast i8* %p to void (i8*, i8*, i1, i32)*
+  %inline_count_inc = add i32 %inline_count, 1
+  call void %cast(i8* %arg1, i8* %arg2, i1 %flag, i32 %inline_count_inc)
+; And we should continue to load and call indirectly through optimization.
+; CHECK:         %[[CAST:.*]] = bitcast i8** %[[A]] to void (i8*, i8*, i1, i32)**
+; CHECK:         %[[P:.*]] = load void (i8*, i8*, i1, i32)*, void (i8*, i8*, i1, i32)** %[[CAST]]
+; CHECK:         call void %[[P]](
+
+  ret void
+}
+
+define void @test2_c(i8* %arg1, i8* %arg2, i1 %flag, i32 %inline_count) {
+; CHECK-LABEL: define void @test2_c(
+entry:
+  %a = alloca i8*
+  store i8* %arg1, i8** %a
+; This alloca and store should remain through any optimization.
+; CHECK:         %[[A:.*]] = alloca
+; CHECK:         store i8* %arg1, i8** %[[A]]
+
+  br i1 %flag, label %bb1, label %bb2
+
+bb1:
+  call void @test2_a(i8** %a) noinline
+  br label %bb2
+
+bb2:
+  %p = load i8*, i8** %a
+  %cast = bitcast i8* %p to void (i8*, i8*, i1, i32)*
+  %inline_count_inc = add i32 %inline_count, 1
+  call void %cast(i8* %arg1, i8* %arg2, i1 %flag, i32 %inline_count_inc)
+; And we should continue to load and call indirectly through optimization.
+; CHECK:         %[[CAST:.*]] = bitcast i8** %[[A]] to void (i8*, i8*, i1, i32)**
+; CHECK:         %[[P:.*]] = load void (i8*, i8*, i1, i32)*, void (i8*, i8*, i1, i32)** %[[CAST]]
+; CHECK:         call void %[[P]](
+
+  ret void
+}
+
+; Another infinite inlining case. The initial callgraph is like following:
+;
+;         test3_a <---> test3_b
+;             |         ^
+;             v         |
+;         test3_c <---> test3_d
+;
+; For all the call edges in the call graph, only test3_c and test3_d can be
+; inlined into test3_a, and no other call edge can be inlined.
+;
+; After test3_c is inlined into test3_a, the original call edge test3_a->test3_c
+; will be removed, a new call edge will be added and the call graph becomes:
+;
+;            test3_a <---> test3_b
+;                  \      ^
+;                   v    /
+;     test3_c <---> test3_d
+; But test3_a, test3_b, test3_c and test3_d still belong to the same SCC.
+;
+; Then after test3_a->test3_d is inlined, when test3_a->test3_d is converted to
+; a ref edge, the original SCC will be split into two: {test3_c, test3_d} and
+; {test3_a, test3_b}, immediately after the newly added ref edge
+; test3_a->test3_c will be converted to a call edge, and the two SCCs will be
+; merged into the original one again. During this cycle, the original SCC will
+; be added into UR.CWorklist again and this creates an infinite loop.
+
+ at a = global i64 0
+ at b = global i64 0
+
+define void @test3_c(i32 %i) {
+entry:
+  %cmp = icmp eq i32 %i, 5
+  br i1 %cmp, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %call = tail call i64 @random()
+  %t0 = load i64, i64* @a
+  %add = add nsw i64 %t0, %call
+  store i64 %add, i64* @a
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  tail call void @test3_d(i32 %i)
+  %t6 = load i64, i64* @a
+  %add85 = add nsw i64 %t6, 1
+  store i64 %add85, i64* @a
+  ret void
+}
+
+declare i64 @random()
+
+define void @test3_d(i32 %i) {
+entry:
+  %cmp = icmp eq i32 %i, 5
+  br i1 %cmp, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %call = tail call i64 @random()
+  %t0 = load i64, i64* @a
+  %add = add nsw i64 %t0, %call
+  store i64 %add, i64* @a
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  tail call void @test3_c(i32 %i)
+  tail call void @test3_b()
+  %t6 = load i64, i64* @a
+  %add79 = add nsw i64 %t6, 3
+  store i64 %add79, i64* @a
+  ret void
+}
+
+; Function Attrs: noinline
+define void @test3_b() #0 {
+entry:
+  tail call void @test3_a()
+  %t0 = load i64, i64* @a
+  %add = add nsw i64 %t0, 2
+  store i64 %add, i64* @a
+  ret void
+}
+
+; Check test3_c is inlined into test3_a once and only once.
+; CHECK-LABEL: @test3_a(
+; CHECK: tail call void @test3_b()
+; CHECK-NEXT: tail call void @test3_d(i32 5)
+; CHECK-NEXT: %[[LD1:.*]] = load i64, i64* @a
+; CHECK-NEXT: %[[ADD1:.*]] = add nsw i64 %[[LD1]], 1
+; CHECK-NEXT: store i64 %[[ADD1]], i64* @a
+; CHECK-NEXT: %[[LD2:.*]] = load i64, i64* @b
+; CHECK-NEXT: %[[ADD2:.*]] = add nsw i64 %[[LD2]], 5
+; CHECK-NEXT: store i64 %[[ADD2]], i64* @b
+; CHECK-NEXT: ret void
+
+; Function Attrs: noinline
+define void @test3_a() #0 {
+entry:
+  tail call void @test3_b()
+  tail call void @test3_c(i32 5)
+  %t0 = load i64, i64* @b
+  %add = add nsw i64 %t0, 5
+  store i64 %add, i64* @b
+  ret void
+}
+
+attributes #0 = { noinline }

Added: llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll (added)
+++ llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,206 @@
+; Test for a subtle bug when computing analyses during inlining and mutating
+; the SCC structure. Without care, this can fail to invalidate analyses.
+;
+; RUN: opt < %s -passes='cgscc(inline,function(verify<domtree>))' -debug-pass-manager -S 2>&1 | FileCheck %s
+
+; First we check that the passes run in the way we expect. Otherwise this test
+; may stop testing anything.
+;
+; CHECK-LABEL: Starting llvm::Module pass manager run.
+; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
+; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
+; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
+; CHECK: Invalidating all non-preserved analyses for: (test1_f)
+; CHECK: Invalidating all non-preserved analyses for: test1_f
+; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f
+; CHECK: Invalidating analysis: LoopAnalysis on test1_f
+; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_f
+; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_f
+; CHECK: Invalidating all non-preserved analyses for: (test1_g, test1_h)
+; CHECK: Invalidating all non-preserved analyses for: test1_g
+; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g
+; CHECK: Invalidating analysis: LoopAnalysis on test1_g
+; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_g
+; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_g
+; CHECK: Invalidating all non-preserved analyses for: test1_h
+; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_h
+; CHECK: Invalidating analysis: LoopAnalysis on test1_h
+; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_h
+; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_h
+; CHECK-NOT: Invalidating analysis:
+; CHECK: Starting llvm::Function pass manager run.
+; CHECK-NEXT: Running pass: DominatorTreeVerifierPass on test1_g
+; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_g
+; CHECK-NEXT: Finished llvm::Function pass manager run.
+; CHECK-NOT: Invalidating analysis:
+; CHECK: Starting llvm::Function pass manager run.
+; CHECK-NEXT: Running pass: DominatorTreeVerifierPass on test1_h
+; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_h
+; CHECK-NEXT: Finished llvm::Function pass manager run.
+; CHECK-NOT: Invalidating analysis:
+; CHECK: Running pass: DominatorTreeVerifierPass on test1_f
+; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_f
+
+; An external function used to control branches.
+declare i1 @flag()
+; CHECK-LABEL: declare i1 @flag()
+
+; The utility function with interesting control flow that gets inlined below to
+; perturb the dominator tree.
+define internal void @callee() {
+entry:
+  %ptr = alloca i8
+  %flag = call i1 @flag()
+  br i1 %flag, label %then, label %else
+
+then:
+  store volatile i8 42, i8* %ptr
+  br label %return
+
+else:
+  store volatile i8 -42, i8* %ptr
+  br label %return
+
+return:
+  ret void
+}
+
+; The 'test1_' prefixed functions work to carefully test that incrementally
+; reducing an SCC in the inliner cannot accidentially leave stale function
+; analysis results due to failing to invalidate them for all the functions.
+
+; The inliner visits this last function. It can't actually break any cycles
+; here, but because we visit this function we compute fresh analyses for it.
+; These analyses are then invalidated when we inline callee disrupting the
+; CFG, and it is important that they be freed.
+define void @test1_h() {
+; CHECK-LABEL: define void @test1_h()
+entry:
+  call void @test1_g()
+; CHECK: call void @test1_g()
+
+  ; Pull interesting CFG into this function.
+  call void @callee()
+; CHECK-NOT: call void @callee()
+
+  ret void
+; CHECK: ret void
+}
+
+; We visit this function second and here we inline the edge to 'test1_f'
+; separating it into its own SCC. The current SCC is now just 'test1_g' and
+; 'test1_h'.
+define void @test1_g() {
+; CHECK-LABEL: define void @test1_g()
+entry:
+  ; This edge gets inlined away.
+  call void @test1_f()
+; CHECK-NOT: call void @test1_f()
+; CHECK: call void @test1_g()
+
+  ; We force this edge to survive inlining.
+  call void @test1_h() noinline
+; CHECK: call void @test1_h()
+
+  ; Pull interesting CFG into this function.
+  call void @callee()
+; CHECK-NOT: call void @callee()
+
+  ret void
+; CHECK: ret void
+}
+
+; We visit this function first in the inliner, and while we inline callee
+; perturbing the CFG, we don't inline anything else and the SCC structure
+; remains in tact.
+define void @test1_f() {
+; CHECK-LABEL: define void @test1_f()
+entry:
+  ; We force this edge to survive inlining.
+  call void @test1_g() noinline
+; CHECK: call void @test1_g()
+
+  ; Pull interesting CFG into this function.
+  call void @callee()
+; CHECK-NOT: call void @callee()
+
+  ret void
+; CHECK: ret void
+}
+
+; The 'test2_' prefixed code works to carefully trigger forming an SCC with
+; a dominator tree for one of the functions but not the other and without even
+; a function analysis manager proxy for the SCC that things get merged into.
+; Without proper handling when updating the call graph this will find a stale
+; dominator tree.
+
+ at test2_global = external global i32, align 4
+
+define void @test2_hoge(i1 (i32*)* %arg) {
+; CHECK-LABEL: define void @test2_hoge(
+bb:
+  %tmp2 = call zeroext i1 %arg(i32* @test2_global)
+; CHECK: call zeroext i1 %arg(
+  br label %bb3
+
+bb3:
+  %tmp5 = call zeroext i1 %arg(i32* @test2_global)
+; CHECK: call zeroext i1 %arg(
+  br i1 %tmp5, label %bb3, label %bb6
+
+bb6:
+  ret void
+}
+
+define zeroext i1 @test2_widget(i32* %arg) {
+; CHECK-LABEL: define zeroext i1 @test2_widget(
+bb:
+  %tmp1 = alloca i8, align 1
+  %tmp2 = alloca i32, align 4
+  call void @test2_quux()
+; CHECK-NOT:     call
+;
+; CHECK:         call zeroext i1 @test2_widget(i32* @test2_global)
+; CHECK-NEXT:    br label %[[NEW_BB:.*]]
+;
+; CHECK:       [[NEW_BB]]:
+; CHECK-NEXT:    call zeroext i1 @test2_widget(i32* @test2_global)
+;
+; CHECK:       {{.*}}:
+
+  call void @test2_hoge.1(i32* %arg)
+; CHECK-NEXT:    call void @test2_hoge.1(
+
+  %tmp4 = call zeroext i1 @test2_barney(i32* %tmp2)
+  %tmp5 = zext i1 %tmp4 to i32
+  store i32 %tmp5, i32* %tmp2, align 4
+  %tmp6 = call zeroext i1 @test2_barney(i32* null)
+  call void @test2_ham(i8* %tmp1)
+; CHECK:         call void @test2_ham(
+
+  call void @test2_quux()
+; CHECK-NOT:     call
+;
+; CHECK:         call zeroext i1 @test2_widget(i32* @test2_global)
+; CHECK-NEXT:    br label %[[NEW_BB:.*]]
+;
+; CHECK:       [[NEW_BB]]:
+; CHECK-NEXT:    call zeroext i1 @test2_widget(i32* @test2_global)
+;
+; CHECK:       {{.*}}:
+  ret i1 true
+; CHECK-NEXT:    ret i1 true
+}
+
+define internal void @test2_quux() {
+; CHECK-NOT: @test2_quux
+bb:
+  call void @test2_hoge(i1 (i32*)* @test2_widget)
+  ret void
+}
+
+declare void @test2_hoge.1(i32*)
+
+declare zeroext i1 @test2_barney(i32*)
+
+declare void @test2_ham(i8*)

Added: llvm/trunk/test/Transforms/Inline/cgscc-invalidate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-invalidate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cgscc-invalidate.ll (added)
+++ llvm/trunk/test/Transforms/Inline/cgscc-invalidate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,104 @@
+; This test tries to ensure that the inliner successfully invalidates function
+; analyses after inlining into the function body.
+;
+; The strategy for these tests is to compute domtree over all the functions,
+; then run the inliner, and then verify the domtree. Then we can arrange the
+; inline to disturb the domtree (easy) and detect any stale cached entries in
+; the verifier. We do the initial computation both *inside* the CGSCC walk and
+; in a pre-step to make sure both work.
+;
+; RUN: opt < %s -passes='function(require<domtree>),cgscc(inline,function(verify<domtree>))' -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(function(require<domtree>),inline,function(verify<domtree>))' -S | FileCheck %s
+
+; An external function used to control branches.
+declare i1 @flag()
+; CHECK-LABEL: declare i1 @flag()
+
+; The utility function with interesting control flow that gets inlined below to
+; perturb the dominator tree.
+define internal void @callee() {
+; CHECK-LABEL: @callee
+entry:
+  %ptr = alloca i8
+  %flag = call i1 @flag()
+  br i1 %flag, label %then, label %else
+
+then:
+  store volatile i8 42, i8* %ptr
+  br label %return
+
+else:
+  store volatile i8 -42, i8* %ptr
+  br label %return
+
+return:
+  ret void
+}
+
+
+; The 'test1_' prefixed functions test the basic scenario of inlining
+; destroying dominator tree.
+
+define void @test1_caller() {
+; CHECK-LABEL: define void @test1_caller()
+entry:
+  call void @callee()
+; CHECK-NOT: @callee
+  ret void
+; CHECK: ret void
+}
+
+
+; The 'test2_' prefixed functions test the scenario of not inlining preserving
+; dominators.
+
+define void @test2_caller() {
+; CHECK-LABEL: define void @test2_caller()
+entry:
+  call void @callee() noinline
+; CHECK: call void @callee
+  ret void
+; CHECK: ret void
+}
+
+
+; The 'test3_' prefixed functions test the scenario of not inlining preserving
+; dominators after splitting an SCC into two smaller SCCs.
+
+; This function ends up split into a separate SCC, which can cause its analyses
+; to become stale if the splitting doesn't properly invalidate things. Also, as
+; a consequence of being split out, test3_f is too large to inline by the time
+; we get here.
+define void @test3_g() {
+; CHECK-LABEL: define void @test3_g()
+entry:
+  ; Create the second edge in the SCC cycle.
+  call void @test3_f()
+; CHECK: call void @test3_f()
+
+  ; Pull interesting CFG into this function.
+  call void @callee()
+; CHECK-NOT: call void @callee()
+
+  ret void
+; CHECK: ret void
+}
+
+; The second function gets visited first and we end up inlining everything we
+; can into this routine. That splits test3_g into a separate SCC that is enqued
+; for later processing.
+define void @test3_f() {
+; CHECK-LABEL: define void @test3_f()
+entry:
+  ; Create the first edge in the SCC cycle.
+  call void @test3_g()
+; CHECK-NOT: @test3_g()
+; CHECK: call void @test3_f()
+
+  ; Pull interesting CFG into this function.
+  call void @callee()
+; CHECK-NOT: call void @callee()
+
+  ret void
+; CHECK: ret void
+}

Added: llvm/trunk/test/Transforms/Inline/cgscc-update.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-update.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/cgscc-update.ll (added)
+++ llvm/trunk/test/Transforms/Inline/cgscc-update.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,184 @@
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs,inline)' -S | FileCheck %s
+; This test runs the inliner and the function attribute deduction. It ensures
+; that when the inliner mutates the call graph it correctly updates the CGSCC
+; iteration so that we can compute refined function attributes. In this way it
+; is leveraging function attribute computation to observe correct call graph
+; updates.
+
+; Boring unknown external function call.
+; CHECK: declare void @unknown()
+declare void @unknown()
+
+; Sanity check: this should get annotated as readnone.
+; CHECK: Function Attrs: nounwind readnone
+; CHECK-NEXT: declare void @readnone()
+declare void @readnone() readnone nounwind
+
+; The 'test1_' prefixed functions are designed to trigger forming a new direct
+; call in the inlined body of the function. After that, we form a new SCC and
+; using that can deduce precise function attrs.
+
+; This function should no longer exist.
+; CHECK-NOT: @test1_f()
+define internal void @test1_f(void()* %p) {
+entry:
+  call void %p()
+  ret void
+}
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline nounwind readnone
+; CHECK-NEXT: define void @test1_g()
+define void @test1_g() noinline {
+entry:
+  call void @test1_f(void()* @test1_h)
+  ret void
+}
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline nounwind readnone
+; CHECK-NEXT: define void @test1_h()
+define void @test1_h() noinline {
+entry:
+  call void @test1_g()
+  call void @readnone()
+  ret void
+}
+
+
+; The 'test2_' prefixed functions are designed to trigger forming a new direct
+; call due to RAUW-ing the returned value of a called function into the caller.
+; This too should form a new SCC which can then be reasoned about to compute
+; precise function attrs.
+
+; This function should no longer exist.
+; CHECK-NOT: @test2_f()
+define internal void()* @test2_f() {
+entry:
+  ret void()* @test2_h
+}
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline nounwind readnone
+; CHECK-NEXT: define void @test2_g()
+define void @test2_g() noinline {
+entry:
+  %p = call void()* @test2_f()
+  call void %p()
+  ret void
+}
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline nounwind readnone
+; CHECK-NEXT: define void @test2_h()
+define void @test2_h() noinline {
+entry:
+  call void @test2_g()
+  call void @readnone()
+  ret void
+}
+
+
+; The 'test3_' prefixed functions are designed to inline in a way that causes
+; call sites to become trivially dead during the middle of inlining callsites of
+; a single function to make sure that the inliner does not get confused by this
+; pattern.
+
+; CHECK-NOT: @test3_maybe_unknown(
+define internal void @test3_maybe_unknown(i1 %b) {
+entry:
+  br i1 %b, label %then, label %exit
+
+then:
+  call void @unknown()
+  br label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-NOT: @test3_f(
+define internal i1 @test3_f() {
+entry:
+  ret i1 false
+}
+
+; CHECK-NOT: @test3_g(
+define internal i1 @test3_g(i1 %b) {
+entry:
+  br i1 %b, label %then1, label %if2
+
+then1:
+  call void @test3_maybe_unknown(i1 true)
+  br label %if2
+
+if2:
+  %f = call i1 @test3_f()
+  br i1 %f, label %then2, label %exit
+
+then2:
+  call void @test3_maybe_unknown(i1 true)
+  br label %exit
+
+exit:
+  ret i1 false
+}
+
+; FIXME: Currently the inliner doesn't successfully mark this as readnone
+; because while it simplifies trivially dead CFGs when inlining callees it
+; doesn't simplify the caller's trivially dead CFG and so we end with a dead
+; block calling @unknown.
+; CHECK-NOT: Function Attrs: readnone
+; CHECK: define void @test3_h()
+define void @test3_h() {
+entry:
+  %g = call i1 @test3_g(i1 false)
+  br i1 %g, label %then, label %exit
+
+then:
+  call void @test3_maybe_unknown(i1 true)
+  br label %exit
+
+exit:
+  call void @test3_maybe_unknown(i1 false)
+  ret void
+}
+
+
+; The 'test4_' prefixed functions are designed to trigger forming a new direct
+; call in the inlined body of the function similar to 'test1_'. However, after
+; that we continue to inline another edge of the graph forcing us to do a more
+; interesting call graph update for the new call edge. Eventually, we still
+; form a new SCC and should use that can deduce precise function attrs.
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline nounwind readnone
+; CHECK-NEXT: define void @test4_f1()
+define void @test4_f1() noinline {
+entry:
+  call void @test4_h()
+  ret void
+}
+
+; CHECK-NOT: @test4_f2
+define internal void @test4_f2() {
+entry:
+  call void @test4_f1()
+  ret void
+}
+
+; CHECK-NOT: @test4_g
+define internal void @test4_g(void()* %p) {
+entry:
+  call void %p()
+  ret void
+}
+
+; This function should have had 'readnone' deduced for its SCC.
+; CHECK: Function Attrs: noinline nounwind readnone
+; CHECK-NEXT: define void @test4_h()
+define void @test4_h() noinline {
+entry:
+  call void @test4_g(void()* @test4_f2)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/clear-analyses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/clear-analyses.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/clear-analyses.ll (added)
+++ llvm/trunk/test/Transforms/Inline/clear-analyses.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; Test that when a pass like correlated-propagation populates an analysis such
+; as LVI with references back into the IR of a function that the inliner will
+; delete, this doesn't crash or go awry despite the inliner clearing the analyses
+; separately from when it deletes the function.
+;
+; RUN: opt -debug-pass-manager -S < %s 2>&1 \
+; RUN:     -passes='cgscc(inline,function(correlated-propagation))' \
+; RUN:     | FileCheck %s
+;
+; CHECK-LABEL: Starting llvm::Module pass manager run.
+; CHECK: Running pass: InlinerPass on (callee)
+; CHECK: Running pass: CorrelatedValuePropagationPass on callee
+; CHECK: Running analysis: LazyValueAnalysis
+; CHECK: Running pass: InlinerPass on (caller)
+; CHECK: Clearing all analysis results for: callee
+; CHECK: Running pass: CorrelatedValuePropagationPass on caller
+; CHECK: Running analysis: LazyValueAnalysis
+
+define internal i32 @callee(i32 %x) {
+; CHECK-NOT: @callee
+entry:
+  ret i32 %x
+}
+
+define i32 @caller(i32 %x) {
+; CHECK-LABEL: define i32 @caller
+entry:
+  %call = call i32 @callee(i32 %x)
+; CHECK-NOT: call
+  ret i32 %call
+; CHECK: ret i32 %x
+}

Added: llvm/trunk/test/Transforms/Inline/comdat-ipo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/comdat-ipo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/comdat-ipo.ll (added)
+++ llvm/trunk/test/Transforms/Inline/comdat-ipo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+define i32 @caller() {
+; CHECK-LABEL: @caller(
+; CHECK-NEXT:  %val2 = call i32 @linkonce_callee(i32 42)
+; CHECK-NEXT:  ret i32 %val2
+
+  %val = call i32 @odr_callee()
+  %val2 = call i32 @linkonce_callee(i32 %val);
+  ret i32 %val2
+}
+
+define linkonce_odr i32 @odr_callee() {
+  ret i32 42
+}
+
+define linkonce i32 @linkonce_callee(i32 %val) {
+  ret i32 %val
+}

Added: llvm/trunk/test/Transforms/Inline/crash-lifetime-marker.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/crash-lifetime-marker.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/crash-lifetime-marker.ll (added)
+++ llvm/trunk/test/Transforms/Inline/crash-lifetime-marker.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; InlineFunction would assert inside the loop that leaves lifetime markers if
+; there was an zero-sized AllocaInst. Check that it doesn't assert and doesn't
+; leave lifetime markers in that case.
+
+declare i32 @callee2(i8*)
+
+define i32 @callee1(i32 %count) {
+  %a0 = alloca i8, i32 %count, align 4
+  %call0 = call i32 @callee2(i8* %a0)
+  ret i32 %call0
+}
+
+; CHECK-LABEL: define i32 @caller1(
+; CHECK: [[ALLOCA:%[a-z0-9\.]+]] = alloca i8
+; CHECK-NOT: call void @llvm.lifetime.start.p0i8(
+; CHECK: call i32 @callee2(i8* [[ALLOCA]])
+; CHECK-NOT: call void @llvm.lifetime.end.p0i8(
+
+define i32 @caller1(i32 %count) {
+  %call0 = call i32 @callee1(i32 0)
+  ret i32 %call0
+}

Added: llvm/trunk/test/Transforms/Inline/crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/crash.ll (added)
+++ llvm/trunk/test/Transforms/Inline/crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,127 @@
+; RUN: opt < %s -inline -argpromotion -instcombine -disable-output
+
+; This test was failing because the inliner would inline @list_DeleteElement
+; into @list_DeleteDuplicates and then into @inf_GetBackwardPartnerLits,
+; turning the indirect call into a direct one.  This allowed instcombine to see
+; the bitcast and eliminate it, deleting the original call and introducing
+; another one.  This crashed the inliner because the new call was not in the
+; callgraph.
+
+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"
+
+
+define void @list_DeleteElement(i32 (i8*, i8*)* nocapture %Test) nounwind ssp {
+entry:
+  %0 = call i32 %Test(i8* null, i8* undef) nounwind
+  ret void
+}
+
+
+define void @list_DeleteDuplicates(i32 (i8*, i8*)* nocapture %Test) nounwind ssp {
+foo:
+  call void @list_DeleteElement(i32 (i8*, i8*)* %Test) nounwind ssp 
+  call fastcc void @list_Rplacd1284() nounwind ssp
+  unreachable
+
+}
+
+define internal i32 @inf_LiteralsHaveSameSubtermAndAreFromSameClause(i32* nocapture %L1, i32* nocapture %L2) nounwind readonly ssp {
+entry:
+  unreachable
+}
+
+
+define internal fastcc void @inf_GetBackwardPartnerLits(i32* nocapture %Flags) nounwind ssp {
+test:
+  call void @list_DeleteDuplicates(i32 (i8*, i8*)* bitcast (i32 (i32*, i32*)* @inf_LiteralsHaveSameSubtermAndAreFromSameClause to i32 (i8*, i8*)*)) nounwind 
+  ret void
+}
+
+
+define void @inf_BackwardEmptySortPlusPlus() nounwind ssp {
+entry:
+  call fastcc void @inf_GetBackwardPartnerLits(i32* null) nounwind ssp
+  unreachable
+}
+
+define void @inf_BackwardWeakening() nounwind ssp {
+entry:
+  call fastcc void @inf_GetBackwardPartnerLits(i32* null) nounwind ssp
+  unreachable
+}
+
+declare fastcc void @list_Rplacd1284() nounwind ssp
+
+
+
+
+;============================
+; PR5208
+
+define void @AAA() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  %A = alloca i8, i32 undef, align 1
+  invoke fastcc void @XXX()
+          to label %invcont98 unwind label %lpad156 
+
+invcont98:                          
+  unreachable
+
+lpad156:                            
+  %exn = landingpad {i8*, i32}
+            cleanup
+  unreachable
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare fastcc void @YYY()
+
+define internal fastcc void @XXX() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  %B = alloca i8, i32 undef, align 1
+  invoke fastcc void @YYY()
+          to label %bb260 unwind label %lpad
+
+bb260:                              
+  ret void
+
+lpad:                               
+  %exn = landingpad {i8*, i32}
+            cleanup
+  resume { i8*, i32 } %exn
+}
+
+
+
+;; This exposed a crash handling devirtualized calls.
+define void @f1(void ()* %f) ssp {
+entry:
+  call void %f()
+  ret void
+}
+
+define void @f4(i32 %size) ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @f1(void ()* @f3)
+          to label %invcont3 unwind label %lpad18
+
+invcont3:                                         ; preds = %bb1
+  ret void
+
+lpad18:                                           ; preds = %invcont3, %bb1
+  %exn = landingpad {i8*, i32}
+            cleanup
+  unreachable
+}
+
+define void @f3() ssp {
+entry:
+  unreachable
+}
+
+declare void @f5() ssp
+
+
+

Added: llvm/trunk/test/Transforms/Inline/crash2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/crash2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/crash2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/crash2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt  -inline -sroa -max-cg-scc-iterations=1 -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"
+target triple = "x86_64-apple-darwin10.3"
+
+declare i8* @f1(i8*) ssp align 2
+
+define linkonce_odr void @f2(i8* %t) inlinehint ssp {
+entry:
+  unreachable
+}
+
+define linkonce_odr void @f3(void (i8*)* %__f) ssp {
+entry:
+  %__f_addr = alloca void (i8*)*, align 8
+  store void (i8*)* %__f, void (i8*)** %__f_addr
+
+  %0 = load void (i8*)*, void (i8*)** %__f_addr, align 8
+  call void %0(i8* undef)
+  call i8* @f1(i8* undef) ssp
+  unreachable
+}
+
+define linkonce_odr void @f4(i8* %this) ssp align 2 {
+entry:
+  %0 = alloca i32
+  call void @f3(void (i8*)* @f2) ssp
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/debug-info-duplicate-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/debug-info-duplicate-calls.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/debug-info-duplicate-calls.ll (added)
+++ llvm/trunk/test/Transforms/Inline/debug-info-duplicate-calls.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,121 @@
+; RUN: opt < %s -always-inline -S | FileCheck %s
+; RUN: opt -passes='always-inline' -S < %s | FileCheck %s
+
+; Original input generated from clang -emit-llvm -S -c -mllvm -disable-llvm-optzns
+;
+; #define CALLS1 f2(); f2();
+; #define CALLS2 f4(); f4();
+; void f1();
+; inline __attribute__((always_inline)) void f2() {
+;   f1();
+; }
+; inline __attribute__((always_inline)) void f3() {
+;   CALLS1
+; }
+; inline __attribute__((always_inline)) void f4() {
+;   f3();
+; }
+; void f() {
+;   CALLS2
+; }
+
+; There should be unique locations for all 4 of these instructions, correctly
+; describing the inlining that has occurred, even in the face of duplicate call
+; site locations.
+
+; The nomenclature used for the tags here is <function name>[cs<number>] where
+; 'cs' is an abbreviation for 'call site' and the number indicates which call
+; site from within the named function this is. (so, given the above inlining, we
+; should have 4 calls to 'f1', two from the first call to f4 and two from the
+; second call to f4)
+
+; CHECK: call void @_Z2f1v(), !dbg [[fcs1_f4_f3cs1_f2:![0-9]+]]
+; CHECK: call void @_Z2f1v(), !dbg [[fcs1_f4_f3cs2_f2:![0-9]+]]
+; CHECK: call void @_Z2f1v(), !dbg [[fcs2_f4_f3cs1_f2:![0-9]+]]
+; CHECK: call void @_Z2f1v(), !dbg [[fcs2_f4_f3cs2_f2:![0-9]+]]
+
+; CHECK-DAG: [[F:![0-9]+]]  = distinct !DISubprogram(name: "f"
+; CHECK-DAG: [[F2:![0-9]+]] = distinct !DISubprogram(name: "f2"
+; CHECK-DAG: [[F3:![0-9]+]] = distinct !DISubprogram(name: "f3"
+; CHECK-DAG: [[F4:![0-9]+]] = distinct !DISubprogram(name: "f4"
+
+; CHECK-DAG: [[fcs1_f4_f3cs1_f2]] = {{.*}}, scope: [[F2]], inlinedAt: [[fcs1_f4_f3cs1:![0-9]+]])
+; CHECK-DAG: [[fcs1_f4_f3cs1]] = {{.*}}, scope: [[F3]], inlinedAt: [[fcs1_f4:![0-9]+]])
+; CHECK-DAG: [[fcs1_f4]] = {{.*}}, scope: [[F4]], inlinedAt: [[fcs1:![0-9]+]])
+; CHECK-DAG: [[fcs1]] = {{.*}}, scope: [[F]])
+; CHECK-DAG: [[fcs1_f4_f3cs2_f2]] = {{.*}}, scope: [[F2]], inlinedAt: [[fcs1_f4_f3cs2:![0-9]+]])
+; CHECK-DAG: [[fcs1_f4_f3cs2]] = {{.*}}, scope: [[F3]], inlinedAt: [[fcs1_f4]])
+
+; CHECK-DAG: [[fcs2_f4_f3cs1_f2]] = {{.*}}, scope: [[F2]], inlinedAt: [[fcs2_f4_f3cs1:![0-9]+]])
+; CHECK-DAG: [[fcs2_f4_f3cs1]] = {{.*}}, scope: [[F3]], inlinedAt: [[fcs2_f4:![0-9]+]])
+; CHECK-DAG: [[fcs2_f4]] = {{.*}}, scope: [[F4]], inlinedAt: [[fcs2:![0-9]+]])
+; CHECK-DAG: [[fcs2]] = {{.*}}, scope: [[F]])
+; CHECK-DAG: [[fcs2_f4_f3cs2_f2]] = {{.*}}, scope: [[F2]], inlinedAt: [[fcs2_f4_f3cs2:![0-9]+]])
+; CHECK-DAG: [[fcs2_f4_f3cs2]] = {{.*}}, scope: [[F3]], inlinedAt: [[fcs2_f4]])
+
+$_Z2f4v = comdat any
+
+$_Z2f3v = comdat any
+
+$_Z2f2v = comdat any
+
+; Function Attrs: uwtable
+define void @_Z1fv() #0 !dbg !4 {
+entry:
+  call void @_Z2f4v(), !dbg !13
+  call void @_Z2f4v(), !dbg !13
+  ret void, !dbg !14
+}
+
+; Function Attrs: alwaysinline inlinehint uwtable
+define linkonce_odr void @_Z2f4v() #1 comdat !dbg !7 {
+entry:
+  call void @_Z2f3v(), !dbg !15
+  ret void, !dbg !16
+}
+
+; Function Attrs: alwaysinline inlinehint uwtable
+define linkonce_odr void @_Z2f3v() #1 comdat !dbg !8 {
+entry:
+  call void @_Z2f2v(), !dbg !17
+  call void @_Z2f2v(), !dbg !17
+  ret void, !dbg !18
+}
+
+; Function Attrs: alwaysinline inlinehint uwtable
+define linkonce_odr void @_Z2f2v() #1 comdat !dbg !9 {
+entry:
+  call void @_Z2f1v(), !dbg !19
+  ret void, !dbg !20
+}
+
+declare void @_Z2f1v() #2
+
+attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { alwaysinline inlinehint uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11}
+!llvm.ident = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.7.0 (trunk 226474) (llvm/trunk 226478)", isOptimized: false, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+!1 = !DIFile(filename: "debug-info-duplicate-calls.cpp", directory: "/tmp/dbginfo")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "f", line: 13, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 13, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!5 = !DIFile(filename: "debug-info-duplicate-calls.cpp", directory: "/tmp/dbginfo")
+!6 = !DISubroutineType(types: !2)
+!7 = distinct !DISubprogram(name: "f4", line: 10, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 10, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!8 = distinct !DISubprogram(name: "f3", line: 7, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 7, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!9 = distinct !DISubprogram(name: "f2", line: 4, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 4, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{!"clang version 3.7.0 (trunk 226474) (llvm/trunk 226478)"}
+!13 = !DILocation(line: 14, column: 3, scope: !4)
+!14 = !DILocation(line: 15, column: 1, scope: !4)
+!15 = !DILocation(line: 11, column: 3, scope: !7)
+!16 = !DILocation(line: 12, column: 1, scope: !7)
+!17 = !DILocation(line: 8, column: 3, scope: !8)
+!18 = !DILocation(line: 9, column: 1, scope: !8)
+!19 = !DILocation(line: 5, column: 3, scope: !9)
+!20 = !DILocation(line: 6, column: 1, scope: !9)

Added: llvm/trunk/test/Transforms/Inline/debug-invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/debug-invoke.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/debug-invoke.ll (added)
+++ llvm/trunk/test/Transforms/Inline/debug-invoke.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -always-inline -S | FileCheck %s
+
+; Test that the debug location is preserved when rewriting an inlined call as an invoke
+
+; CHECK: invoke void @test()
+; CHECK-NEXT: to label {{.*}} unwind label {{.*}}, !dbg [[INL_LOC:!.*]]
+; CHECK: [[SP:.*]] = distinct !DISubprogram(
+; CHECK: [[INL_LOC]] = !DILocation(line: 1, scope: [[SP]], inlinedAt: [[INL_AT:.*]])
+; CHECK: [[INL_AT]] = distinct !DILocation(line: 2, scope: [[SP]])
+
+declare void @test()
+declare i32 @__gxx_personality_v0(...)
+
+attributes #0 = { alwaysinline }
+define void @inl() #0 {
+  call void @test(), !dbg !3
+  ret void
+}
+
+define void @caller() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+  invoke void @inl()
+    to label %cont unwind label %lpad, !dbg !4
+
+cont:
+  ret void
+
+lpad:
+  landingpad { i8*, i32 }
+    cleanup
+  ret void
+}
+
+!llvm.module.flags = !{!1}
+!llvm.dbg.cu = !{!5}
+
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DISubprogram(unit: !5)
+!3 = !DILocation(line: 1, scope: !2)
+!4 = !DILocation(line: 2, scope: !2)
+!5 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
+                             file: !6,
+                             isOptimized: true, flags: "-O2",
+                             splitDebugFilename: "abc.debug", emissionKind: 2)
+!6 = !DIFile(filename: "path/davidino", directory: "/path/to/dir")

Added: llvm/trunk/test/Transforms/Inline/delete-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/delete-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/delete-call.ll (added)
+++ llvm/trunk/test/Transforms/Inline/delete-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; REQUIRES: asserts
+; RUN: opt -S -inline -stats < %s 2>&1 | FileCheck %s
+; CHECK: Number of functions inlined
+
+; RUN: opt -S -inline -functionattrs -stats < %s 2>&1 | FileCheck -check-prefix=CHECK-FUNCTIONATTRS %s
+; CHECK-FUNCTIONATTRS: Number of call sites deleted, not inlined
+
+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"
+
+define internal i32 @test(i32 %x, i32 %y, i32 %z) nounwind {
+entry:
+  %0 = add nsw i32 %y, %z                         ; <i32> [#uses=1]
+  %1 = mul i32 %0, %x                             ; <i32> [#uses=1]
+  %2 = mul i32 %y, %z                             ; <i32> [#uses=1]
+  %3 = add nsw i32 %1, %2                         ; <i32> [#uses=1]
+  ret i32 %3
+}
+
+define i32 @test2() nounwind {
+entry:
+  %0 = call i32 @test(i32 1, i32 2, i32 4) nounwind ; <i32> [#uses=1]
+  ret i32 14
+}
+
+

Added: llvm/trunk/test/Transforms/Inline/deopt-bundles.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/deopt-bundles.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/deopt-bundles.ll (added)
+++ llvm/trunk/test/Transforms/Inline/deopt-bundles.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,203 @@
+; RUN: opt -S -always-inline < %s | FileCheck %s
+
+declare void @f()
+declare i32 @g()
+declare fastcc i32 @g.fastcc()
+
+define i32 @callee_0() alwaysinline {
+ entry:
+  call void @f()
+  ret i32 2
+}
+
+define i32 @caller_0() {
+; CHECK-LABEL: @caller_0(
+ entry:
+; CHECK: entry:
+; CHECK-NEXT: call void @f()
+; CHECK-NEXT: ret i32 2
+  %x = call i32 @callee_0() [ "deopt"(i32 5) ]
+  ret i32 %x
+}
+
+define i32 @callee_1() alwaysinline {
+ entry:
+  call void @f() [ "deopt"() ]
+  call void @f() [ "deopt"(i32 0, i32 1) ]
+  call void @f() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  ret i32 2
+}
+
+define i32 @caller_1() {
+; CHECK-LABEL: @caller_1(
+ entry:
+; CHECK: entry:
+; CHECK-NEXT:  call void @f() [ "deopt"(i32 5) ]
+; CHECK-NEXT:  call void @f() [ "deopt"(i32 5, i32 0, i32 1) ]
+; CHECK-NEXT:  call void @f() [ "deopt"(i32 5, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+; CHECK-NEXT:  ret i32 2
+
+  %x = call i32 @callee_1() [ "deopt"(i32 5) ]
+  ret i32 %x
+}
+
+define i32 @callee_2() alwaysinline {
+ entry:
+  %v = call i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  ret i32 %v
+}
+
+define i32 @caller_2(i32 %val) {
+; CHECK-LABEL: @caller_2(
+ entry:
+; CHECK: entry:
+; CHECK-NEXT:   [[RVAL:%[^ ]+]] = call i32 @g() [ "deopt"(i32 %val, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+; CHECK-NEXT:   ret i32 [[RVAL]]
+  %x = call i32 @callee_2() [ "deopt"(i32 %val) ]
+  ret i32 %x
+}
+
+define i32 @callee_3() alwaysinline {
+ entry:
+  %v = call i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  ret i32 %v
+}
+
+define i32 @caller_3() personality i8 3 {
+; CHECK-LABEL: @caller_3(
+ entry:
+  %x = invoke i32 @callee_3() [ "deopt"(i32 7) ] to label %normal unwind label %unwind
+; CHECK: invoke i32 @g() [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+
+ normal:
+  ret i32 %x
+
+ unwind:
+  %cleanup = landingpad i8 cleanup
+  ret i32 101
+}
+
+define i32 @callee_4() alwaysinline personality i8 3 {
+ entry:
+  %v = invoke i32 @g() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] to label %normal unwind label %unwind
+
+ normal:
+  ret i32 %v
+
+ unwind:
+  %cleanup = landingpad i8 cleanup
+  ret i32 100
+}
+
+define i32 @caller_4() {
+; CHECK-LABEL: @caller_4(
+ entry:
+; CHECK: invoke i32 @g() [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+  %x = call i32 @callee_4() [ "deopt"(i32 7) ]
+  ret i32 %x
+}
+
+define i32 @callee_5() alwaysinline personality i8 3 {
+ entry:
+  %v = invoke fastcc i32 @g.fastcc() #0 [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ] to label %normal unwind label %unwind
+
+ normal:
+  ret i32 %v
+
+ unwind:
+  %cleanup = landingpad i8 cleanup
+  ret i32 100
+}
+
+define i32 @caller_5() {
+; CHECK-LABEL: @caller_5(
+ entry:
+; CHECK:  invoke fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX:[0-9]+]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+  %x = call i32 @callee_5() [ "deopt"(i32 7) ]
+  ret i32 %x
+}
+
+define i32 @callee_6() alwaysinline personality i8 3 {
+ entry:
+  %v = call fastcc i32 @g.fastcc() #0 [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  ret i32 %v
+}
+
+define i32 @caller_6() {
+; CHECK-LABEL: @caller_6(
+ entry:
+; CHECK: call fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+  %x = call i32 @callee_6() [ "deopt"(i32 7) ]
+  ret i32 %x
+}
+
+define i32 @callee_7(i1 %val) alwaysinline personality i8 3 {
+; We want something that PruningFunctionCloner is not smart enough to
+; recognize, but can be recognized by recursivelySimplifyInstruction.
+
+ entry:
+  br i1 %val, label %check, label %precheck
+
+ precheck:
+  br label %check
+
+ check:
+  %p = phi i1 [ %val, %entry ], [ true, %precheck ]
+  br i1 %p, label %do.not, label %do
+
+ do.not:
+  ret i32 0
+
+ do:
+  %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  ret i32 %v
+}
+
+define i32 @caller_7() {
+; CHECK-LABEL: @caller_7(
+ entry:
+; CHECK-NOT: call fastcc i32 @g.fastcc()
+; CHECK: ret i32 0
+  %x = call i32 @callee_7(i1 true) [ "deopt"(i32 7) ]
+  ret i32 %x
+}
+
+define i32 @callee_8(i1 %val) alwaysinline personality i8 3 {
+; We want something that PruningFunctionCloner is not smart enough to
+; recognize, but can be recognized by recursivelySimplifyInstruction.
+
+ entry:
+  br i1 %val, label %check, label %precheck
+
+ precheck:
+  br label %check
+
+ check:
+  %p = phi i1 [ %val, %entry ], [ true, %precheck ]
+  br i1 %p, label %do.not, label %do
+
+ do.not:
+  ret i32 0
+
+ do:
+  %phi = phi i32 [ 0, %check ], [ %v, %do ]
+  %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  %ic = icmp eq i32 %v, 42
+  br i1 %ic, label %do, label %done
+
+ done:
+  ret i32 %phi
+}
+
+define i32 @caller_8() {
+; CHECK-LABEL: @caller_8(
+ entry:
+; CHECK-NOT: call fastcc i32 @g.fastcc()
+; CHECK: ret i32 0
+  %x = call i32 @callee_8(i1 true) [ "deopt"(i32 7) ]
+  ret i32 %x
+}
+
+attributes #0 = { "foo"="bar" }
+
+; CHECK: attributes #[[FOO_BAR_ATTR_IDX]] = { "foo"="bar" }

Added: llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll (added)
+++ llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic-cconv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt -S -always-inline < %s | FileCheck %s
+
+declare cc42 i32 @llvm.experimental.deoptimize.i32(...)
+
+define i32 @callee_with_coldcc() alwaysinline {
+  %v0 = call cc42 i32(...) @llvm.experimental.deoptimize.i32(i32 1) [ "deopt"() ]
+  ret i32 %v0
+}
+
+define void @caller_with_coldcc() {
+; CHECK-LABEL: @caller_with_coldcc(
+; CHECK-NEXT:  call cc42 void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"() ]
+; CHECK-NEXT:  ret void
+
+  %val = call i32 @callee_with_coldcc()
+  ret void
+}
+
+; CHECK: declare cc42 void @llvm.experimental.deoptimize.isVoid(...)

Added: llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic.ll (added)
+++ llvm/trunk/test/Transforms/Inline/deoptimize-intrinsic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,123 @@
+; RUN: opt -S -always-inline < %s | FileCheck %s
+
+declare i8 @llvm.experimental.deoptimize.i8(...)
+declare i32 @llvm.experimental.deoptimize.i32(...)
+
+define i8 @callee(i1* %c) alwaysinline {
+  %c0 = load volatile i1, i1* %c
+  br i1 %c0, label %left, label %right
+
+left:
+  %c1 = load volatile i1, i1* %c
+  br i1 %c1, label %lleft, label %lright
+
+lleft:
+  %v0 = call i8(...) @llvm.experimental.deoptimize.i8(i32 1) [ "deopt"(i32 1) ]
+  ret i8 %v0
+
+lright:
+  ret i8 10
+
+right:
+  %c2 = load volatile i1, i1* %c
+  br i1 %c2, label %rleft, label %rright
+
+rleft:
+  %v1 = call i8(...) @llvm.experimental.deoptimize.i8(i32 1, i32 300, float 500.0, <2 x i32*> undef) [ "deopt"(i32 1) ]
+  ret i8 %v1
+
+rright:
+  %v2 = call i8(...) @llvm.experimental.deoptimize.i8() [ "deopt"(i32 1) ]
+  ret i8 %v2
+}
+
+define void @caller_0(i1* %c, i8* %ptr) {
+; CHECK-LABEL: @caller_0(
+entry:
+  %v = call i8 @callee(i1* %c)  [ "deopt"(i32 2) ]
+  store i8 %v, i8* %ptr
+  ret void
+
+; CHECK: lleft.i:
+; CHECK-NEXT:  call void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"(i32 2, i32 1) ]
+; CHECK-NEXT:  ret void
+
+; CHECK: rleft.i:
+; CHECK-NEXT:  call void (...) @llvm.experimental.deoptimize.isVoid(i32 1, i32 300, float 5.000000e+02, <2 x i32*> undef) [ "deopt"(i32 2, i32 1) ]
+; CHECK-NEXT:  ret void
+
+; CHECK: rright.i:
+; CHECK-NEXT:  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"(i32 2, i32 1) ]
+; CHECK-NEXT:  ret void
+
+; CHECK: callee.exit:
+; CHECK-NEXT:  store i8 10, i8* %ptr
+; CHECK-NEXT:  ret void
+
+}
+
+define i32 @caller_1(i1* %c, i8* %ptr) personality i8 3 {
+; CHECK-LABEL: @caller_1(
+entry:
+  %v = invoke i8 @callee(i1* %c)  [ "deopt"(i32 3) ] to label %normal
+       unwind label %unwind
+
+; CHECK: lleft.i:
+; CHECK-NEXT:  %0 = call i32 (...) @llvm.experimental.deoptimize.i32(i32 1) [ "deopt"(i32 3, i32 1) ]
+; CHECK-NEXT:  ret i32 %0
+
+; CHECK: rleft.i:
+; CHECK-NEXT:  %1 = call i32 (...) @llvm.experimental.deoptimize.i32(i32 1, i32 300, float 5.000000e+02, <2 x i32*> undef) [ "deopt"(i32 3, i32 1) ]
+; CHECK-NEXT:  ret i32 %1
+
+; CHECK: rright.i:
+; CHECK-NEXT:  %2 = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 3, i32 1) ]
+; CHECK-NEXT:  ret i32 %2
+
+; CHECK: callee.exit:
+; CHECK-NEXT:  br label %normal
+
+; CHECK: normal:
+; CHECK-NEXT:  store i8 10, i8* %ptr
+; CHECK-NEXT:  ret i32 42
+
+unwind:
+  %lp = landingpad i32 cleanup
+  ret i32 43
+
+normal:
+  store i8 %v, i8* %ptr
+  ret i32 42
+}
+
+define i8 @callee_with_alloca() alwaysinline {
+  %t = alloca i8
+  %v0 = call i8(...) @llvm.experimental.deoptimize.i8(i32 1) [ "deopt"(i8* %t) ]
+  ret i8 %v0
+}
+
+define void @caller_with_lifetime() {
+; CHECK-LABEL: @caller_with_lifetime(
+; CHECK:  call void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"(i8* %t.i) ]
+; CHECK-NEXT:  ret void
+
+entry:
+  call i8 @callee_with_alloca();
+  ret void
+}
+
+define i8 @callee_with_dynamic_alloca(i32 %n) alwaysinline {
+  %p = alloca i8, i32 %n
+  %v = call i8(...) @llvm.experimental.deoptimize.i8(i32 1) [ "deopt"(i8* %p) ]
+  ret i8 %v
+}
+
+define void @caller_with_stacksaverestore(i32 %n) {
+; CHECK-LABEL: void @caller_with_stacksaverestore(
+; CHECK:  call void (...) @llvm.experimental.deoptimize.isVoid(i32 1) [ "deopt"(i8* %p.i) ]
+; CHECK-NEXT:  ret void
+
+  %p = alloca i32, i32 %n
+  call i8 @callee_with_dynamic_alloca(i32 %n)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/devirtualize-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/devirtualize-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/devirtualize-2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/devirtualize-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(devirt<4>(inline))' -S | FileCheck %s
+; PR4834
+
+define i32 @test1() {
+  %funcall1_ = call fastcc i32 ()* () @f1()
+  %executecommandptr1_ = call i32 %funcall1_()
+  ret i32 %executecommandptr1_
+}
+
+define internal fastcc i32 ()* @f1() nounwind readnone {
+  ret i32 ()* @f2
+}
+
+define internal i32 @f2() nounwind readnone {
+  ret i32 1
+}
+
+; CHECK: @test1()
+; CHECK-NEXT: ret i32 1
+
+
+
+
+
+declare i8* @f1a(i8*) ssp align 2
+
+define internal i32 @f2a(i8* %t) inlinehint ssp {
+entry:
+  ret i32 41
+}
+
+define internal i32 @f3a(i32 (i8*)* %__f) ssp {
+entry:
+  %A = call i32 %__f(i8* undef)
+  ret i32 %A
+}
+
+define i32 @test2(i8* %this) ssp align 2 {
+  %X = call i32 @f3a(i32 (i8*)* @f2a) ssp
+  ret i32 %X
+}
+
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: ret i32 41

Added: llvm/trunk/test/Transforms/Inline/devirtualize-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/devirtualize-3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/devirtualize-3.ll (added)
+++ llvm/trunk/test/Transforms/Inline/devirtualize-3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; RUN: opt -basicaa -inline -S -sroa -gvn -instcombine < %s | FileCheck %s
+; PR5009
+
+; CHECK: define i32 @main() 
+; CHECK-NEXT: entry:
+; CHECK-NEXT:  call void @exit(i32 38) 
+
+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"
+
+%struct.cont_t = type { void (i8*, i32)*, i8* }
+%struct.foo_sf_t = type { %struct.cont_t*, i32 }
+
+define i32 @main() nounwind ssp {
+entry:
+  %cont = alloca %struct.cont_t, align 8          ; <%struct.cont_t*> [#uses=4]
+  %tmp = getelementptr inbounds %struct.cont_t, %struct.cont_t* %cont, i32 0, i32 0 ; <void (i8*, i32)**> [#uses=1]
+  %tmp1 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %cont, i32 0, i32 0 ; <void (i8*, i32)**> [#uses=2]
+  store void (i8*, i32)* bitcast (void (%struct.cont_t*, i32)* @quit to void (i8*, i32)*), void (i8*, i32)** %tmp1
+  %tmp2 = load void (i8*, i32)*, void (i8*, i32)** %tmp1            ; <void (i8*, i32)*> [#uses=1]
+  store void (i8*, i32)* %tmp2, void (i8*, i32)** %tmp
+  %tmp3 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %cont, i32 0, i32 1 ; <i8**> [#uses=1]
+  store i8* null, i8** %tmp3
+  call void @foo(%struct.cont_t* %cont)
+  ret i32 0
+}
+
+define internal void @quit(%struct.cont_t* %cont, i32 %rcode) nounwind ssp {
+entry:
+  call void @exit(i32 %rcode) noreturn
+  unreachable
+}
+
+define internal void @foo(%struct.cont_t* %c) nounwind ssp {
+entry:
+  %sf = alloca %struct.foo_sf_t, align 8          ; <%struct.foo_sf_t*> [#uses=3]
+  %next = alloca %struct.cont_t, align 8          ; <%struct.cont_t*> [#uses=3]
+  %tmp = getelementptr inbounds %struct.foo_sf_t, %struct.foo_sf_t* %sf, i32 0, i32 0 ; <%struct.cont_t**> [#uses=1]
+  store %struct.cont_t* %c, %struct.cont_t** %tmp
+  %tmp2 = getelementptr inbounds %struct.foo_sf_t, %struct.foo_sf_t* %sf, i32 0, i32 1 ; <i32*> [#uses=1]
+  store i32 2, i32* %tmp2
+  %tmp4 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %next, i32 0, i32 0 ; <void (i8*, i32)**> [#uses=1]
+  store void (i8*, i32)* bitcast (void (%struct.foo_sf_t*, i32)* @foo2 to void (i8*, i32)*), void (i8*, i32)** %tmp4
+  %tmp5 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %next, i32 0, i32 1 ; <i8**> [#uses=1]
+  %conv = bitcast %struct.foo_sf_t* %sf to i8*    ; <i8*> [#uses=1]
+  store i8* %conv, i8** %tmp5
+  call void @bar(%struct.cont_t* %next, i32 14)
+  ret void
+}
+
+define internal void @foo2(%struct.foo_sf_t* %sf, i32 %y) nounwind ssp {
+entry:
+  %tmp1 = getelementptr inbounds %struct.foo_sf_t, %struct.foo_sf_t* %sf, i32 0, i32 0 ; <%struct.cont_t**> [#uses=1]
+  %tmp2 = load %struct.cont_t*, %struct.cont_t** %tmp1             ; <%struct.cont_t*> [#uses=1]
+  %tmp3 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %tmp2, i32 0, i32 0 ; <void (i8*, i32)**> [#uses=1]
+  %tmp4 = load void (i8*, i32)*, void (i8*, i32)** %tmp3            ; <void (i8*, i32)*> [#uses=1]
+  %tmp6 = getelementptr inbounds %struct.foo_sf_t, %struct.foo_sf_t* %sf, i32 0, i32 0 ; <%struct.cont_t**> [#uses=1]
+  %tmp7 = load %struct.cont_t*, %struct.cont_t** %tmp6             ; <%struct.cont_t*> [#uses=1]
+  %conv = bitcast %struct.cont_t* %tmp7 to i8*    ; <i8*> [#uses=1]
+  %tmp9 = getelementptr inbounds %struct.foo_sf_t, %struct.foo_sf_t* %sf, i32 0, i32 1 ; <i32*> [#uses=1]
+  %tmp10 = load i32, i32* %tmp9                        ; <i32> [#uses=1]
+  %mul = mul i32 %tmp10, %y                       ; <i32> [#uses=1]
+  call void %tmp4(i8* %conv, i32 %mul)
+  ret void
+}
+
+define internal void @bar(%struct.cont_t* %c, i32 %y) nounwind ssp {
+entry:
+  %tmp1 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %c, i32 0, i32 0 ; <void (i8*, i32)**> [#uses=1]
+  %tmp2 = load void (i8*, i32)*, void (i8*, i32)** %tmp1            ; <void (i8*, i32)*> [#uses=1]
+  %tmp4 = getelementptr inbounds %struct.cont_t, %struct.cont_t* %c, i32 0, i32 1 ; <i8**> [#uses=1]
+  %tmp5 = load i8*, i8** %tmp4                         ; <i8*> [#uses=1]
+  %add = add nsw i32 %y, 5                        ; <i32> [#uses=1]
+  call void %tmp2(i8* %tmp5, i32 %add)
+  ret void
+}
+
+declare void @exit(i32) noreturn
+

Added: llvm/trunk/test/Transforms/Inline/devirtualize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/devirtualize.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/devirtualize.ll (added)
+++ llvm/trunk/test/Transforms/Inline/devirtualize.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,182 @@
+; RUN: opt -S -Os < %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"
+
+
+; Simple devirt testcase, requires iteration between inliner and GVN.
+;  rdar://6295824
+define i32 @foo(i32 ()** noalias %p, i64* noalias %q) nounwind ssp {
+entry:
+  store i32 ()* @bar, i32 ()** %p
+  store i64 0, i64* %q
+  %tmp3 = load i32 ()*, i32 ()** %p                        ; <i32 ()*> [#uses=1]
+  %call = call i32 %tmp3()                        ; <i32> [#uses=1]
+  %X = add i32 %call, 4
+  ret i32 %X
+  
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: store
+; CHECK-NEXT: store
+; CHECK-NEXT: ret i32 11
+}
+
+define internal i32 @bar() nounwind ssp {
+entry:
+  ret i32 7
+}
+
+
+;; More complex devirt case, from PR6724
+; CHECK: @_Z1gv()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i32 7
+
+%0 = type { i8*, i8* }
+%1 = type { i8*, i8*, i32, i32, i8*, i64, i8*, i64 }
+%2 = type { i8*, i8*, i8* }
+%struct.A = type { i8** }
+%struct.B = type { i8** }
+%struct.C = type { [16 x i8] }
+%struct.D = type { [16 x i8] }
+
+ at _ZTV1D = linkonce_odr constant [6 x i8*] [i8* null, i8* bitcast (%2* @_ZTI1D to i8*), i8* bitcast (i32 (%struct.C*)* @_ZN1D1fEv to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%2* @_ZTI1D to i8*), i8* bitcast (i32 (%struct.C*)* @_ZThn8_N1D1fEv to i8*)] ; <[6 x i8*]*> [#uses=2]
+ at _ZTVN10__cxxabiv120__si_class_type_infoE = external global i8* ; <i8**> [#uses=1]
+ at _ZTS1D = linkonce_odr constant [3 x i8] c"1D\00"     ; <[3 x i8]*> [#uses=1]
+ at _ZTVN10__cxxabiv121__vmi_class_type_infoE = external global i8* ; <i8**> [#uses=1]
+ at _ZTS1C = linkonce_odr constant [3 x i8] c"1C\00"     ; <[3 x i8]*> [#uses=1]
+ at _ZTVN10__cxxabiv117__class_type_infoE = external global i8* ; <i8**> [#uses=1]
+ at _ZTS1A = linkonce_odr constant [3 x i8] c"1A\00"     ; <[3 x i8]*> [#uses=1]
+ at _ZTI1A = linkonce_odr constant %0 { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1A, i32 0, i32 0) } ; <%0*> [#uses=1]
+ at _ZTS1B = linkonce_odr constant [3 x i8] c"1B\00"     ; <[3 x i8]*> [#uses=1]
+ at _ZTI1B = linkonce_odr constant %0 { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv117__class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1B, i32 0, i32 0) } ; <%0*> [#uses=1]
+ at _ZTI1C = linkonce_odr constant %1 { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1C, i32 0, i32 0), i32 0, i32 2, i8* bitcast (%0* @_ZTI1A to i8*), i64 2, i8* bitcast (%0* @_ZTI1B to i8*), i64 2050 } ; <%1*> [#uses=1]
+ at _ZTI1D = linkonce_odr constant %2 { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @_ZTS1D, i32 0, i32 0), i8* bitcast (%1* @_ZTI1C to i8*) } ; <%2*> [#uses=1]
+ at _ZTV1C = linkonce_odr constant [6 x i8*] [i8* null, i8* bitcast (%1* @_ZTI1C to i8*), i8* bitcast (i32 (%struct.C*)* @_ZN1C1fEv to i8*), i8* inttoptr (i64 -8 to i8*), i8* bitcast (%1* @_ZTI1C to i8*), i8* bitcast (i32 (%struct.C*)* @_ZThn8_N1C1fEv to i8*)] ; <[6 x i8*]*> [#uses=2]
+ at _ZTV1B = linkonce_odr constant [3 x i8*] [i8* null, i8* bitcast (%0* @_ZTI1B to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1B1fEv to i8*)] ; <[3 x i8*]*> [#uses=1]
+ at _ZTV1A = linkonce_odr constant [3 x i8*] [i8* null, i8* bitcast (%0* @_ZTI1A to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A1fEv to i8*)] ; <[3 x i8*]*> [#uses=1]
+
+define i32 @_Z1gv() ssp {
+entry:
+  %d = alloca %struct.C, align 8                  ; <%struct.C*> [#uses=2]
+  call void @_ZN1DC1Ev(%struct.C* %d)
+  %call = call i32 @_Z1fP1D(%struct.C* %d)        ; <i32> [#uses=1]
+  %X = add i32 %call, 3
+  ret i32 %X
+}
+
+define linkonce_odr void @_ZN1DC1Ev(%struct.C* %this) inlinehint ssp align 2 {
+entry:
+  call void @_ZN1DC2Ev(%struct.C* %this)
+  ret void
+}
+
+define internal i32 @_Z1fP1D(%struct.C* %d) ssp {
+entry:
+  %0 = icmp eq %struct.C* %d, null                ; <i1> [#uses=1]
+  br i1 %0, label %cast.end, label %cast.notnull
+
+cast.notnull:                                     ; preds = %entry
+  %1 = bitcast %struct.C* %d to i8*               ; <i8*> [#uses=1]
+  %add.ptr = getelementptr i8, i8* %1, i64 8          ; <i8*> [#uses=1]
+  %2 = bitcast i8* %add.ptr to %struct.A*         ; <%struct.A*> [#uses=1]
+  br label %cast.end
+
+cast.end:                                         ; preds = %entry, %cast.notnull
+  %3 = phi %struct.A* [ %2, %cast.notnull ], [ null, %entry ] ; <%struct.A*> [#uses=2]
+  %4 = bitcast %struct.A* %3 to i32 (%struct.A*)*** ; <i32 (%struct.A*)***> [#uses=1]
+  %5 = load i32 (%struct.A*)**, i32 (%struct.A*)*** %4                ; <i32 (%struct.A*)**> [#uses=1]
+  %vfn = getelementptr inbounds i32 (%struct.A*)*, i32 (%struct.A*)** %5, i64 0 ; <i32 (%struct.A*)**> [#uses=1]
+  %6 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn               ; <i32 (%struct.A*)*> [#uses=1]
+  %call = call i32 %6(%struct.A* %3)              ; <i32> [#uses=1]
+  ret i32 %call
+}
+
+define linkonce_odr i32 @_ZN1D1fEv(%struct.C* %this) ssp align 2 {
+entry:
+  ret i32 4
+}
+
+define linkonce_odr i32 @_ZThn8_N1D1fEv(%struct.C* %this) {
+entry:
+  %0 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %1 = getelementptr inbounds i8, i8* %0, i64 -8      ; <i8*> [#uses=1]
+  %2 = bitcast i8* %1 to %struct.C*               ; <%struct.C*> [#uses=1]
+  %call = call i32 @_ZN1D1fEv(%struct.C* %2)      ; <i32> [#uses=1]
+  ret i32 %call
+}
+
+define linkonce_odr void @_ZN1DC2Ev(%struct.C* %this) inlinehint ssp align 2 {
+entry:
+  call void @_ZN1CC2Ev(%struct.C* %this)
+  %0 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %1 = getelementptr inbounds i8, i8* %0, i64 0       ; <i8*> [#uses=1]
+  %2 = bitcast i8* %1 to i8***                    ; <i8***> [#uses=1]
+  store i8** getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTV1D, i64 0, i64 2), i8*** %2
+  %3 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %4 = getelementptr inbounds i8, i8* %3, i64 8       ; <i8*> [#uses=1]
+  %5 = bitcast i8* %4 to i8***                    ; <i8***> [#uses=1]
+  store i8** getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTV1D, i64 0, i64 5), i8*** %5
+  ret void
+}
+
+define linkonce_odr void @_ZN1CC2Ev(%struct.C* %this) inlinehint ssp align 2 {
+entry:
+  %0 = bitcast %struct.C* %this to %struct.A*     ; <%struct.A*> [#uses=1]
+  call void @_ZN1AC2Ev(%struct.A* %0)
+  %1 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %2 = getelementptr inbounds i8, i8* %1, i64 8       ; <i8*> [#uses=1]
+  %3 = bitcast i8* %2 to %struct.A*               ; <%struct.A*> [#uses=1]
+  call void @_ZN1BC2Ev(%struct.A* %3)
+  %4 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %5 = getelementptr inbounds i8, i8* %4, i64 0       ; <i8*> [#uses=1]
+  %6 = bitcast i8* %5 to i8***                    ; <i8***> [#uses=1]
+  store i8** getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTV1C, i64 0, i64 2), i8*** %6
+  %7 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %8 = getelementptr inbounds i8, i8* %7, i64 8       ; <i8*> [#uses=1]
+  %9 = bitcast i8* %8 to i8***                    ; <i8***> [#uses=1]
+  store i8** getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTV1C, i64 0, i64 5), i8*** %9
+  ret void
+}
+
+define linkonce_odr i32 @_ZN1C1fEv(%struct.C* %this) ssp align 2 {
+entry:
+  ret i32 3
+}
+
+define linkonce_odr i32 @_ZThn8_N1C1fEv(%struct.C* %this) {
+entry:
+  %0 = bitcast %struct.C* %this to i8*            ; <i8*> [#uses=1]
+  %1 = getelementptr inbounds i8, i8* %0, i64 -8      ; <i8*> [#uses=1]
+  %2 = bitcast i8* %1 to %struct.C*               ; <%struct.C*> [#uses=1]
+  %call = call i32 @_ZN1C1fEv(%struct.C* %2)      ; <i32> [#uses=1]
+  ret i32 %call
+}
+
+define linkonce_odr void @_ZN1AC2Ev(%struct.A* %this) inlinehint ssp align 2 {
+entry:
+  %0 = bitcast %struct.A* %this to i8*            ; <i8*> [#uses=1]
+  %1 = getelementptr inbounds i8, i8* %0, i64 0       ; <i8*> [#uses=1]
+  %2 = bitcast i8* %1 to i8***                    ; <i8***> [#uses=1]
+  store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2), i8*** %2
+  ret void
+}
+
+define linkonce_odr void @_ZN1BC2Ev(%struct.A* %this) inlinehint ssp align 2 {
+entry:
+  %0 = bitcast %struct.A* %this to i8*            ; <i8*> [#uses=1]
+  %1 = getelementptr inbounds i8, i8* %0, i64 0       ; <i8*> [#uses=1]
+  %2 = bitcast i8* %1 to i8***                    ; <i8***> [#uses=1]
+  store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i64 0, i64 2), i8*** %2
+  ret void
+}
+
+define linkonce_odr i32 @_ZN1B1fEv(%struct.A* %this) ssp align 2 {
+entry:
+  ret i32 2
+}
+
+define linkonce_odr i32 @_ZN1A1fEv(%struct.A* %this) ssp align 2 {
+entry:
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/Inline/dynamic_alloca_test.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/dynamic_alloca_test.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/dynamic_alloca_test.ll (added)
+++ llvm/trunk/test/Transforms/Inline/dynamic_alloca_test.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; Test that functions with dynamic allocas get inlined in a case where
+; naively inlining it would result in a miscompilation.
+; Functions with dynamic allocas can only be inlined into functions that
+; already have dynamic allocas.
+
+; RUN: opt < %s -inline -S | FileCheck %s
+;
+; FIXME: This test is xfailed because the inline cost rewrite disabled *all*
+; inlining of functions which contain a dynamic alloca. It should be re-enabled
+; once that functionality is restored.
+; XFAIL: *
+
+declare void @ext(i32*)
+
+define internal void @callee(i32 %N) {
+  %P = alloca i32, i32 %N
+  call void @ext(i32* %P)
+  ret void
+}
+
+define void @foo(i32 %N) {
+; CHECK-LABEL: @foo(
+; CHECK: alloca i32, i32 %{{.*}}
+; CHECK: call i8* @llvm.stacksave()
+; CHECK: alloca i32, i32 %{{.*}}
+; CHECK: call void @ext
+; CHECK: call void @llvm.stackrestore
+; CHECK: ret
+
+entry:
+  %P = alloca i32, i32 %N
+  call void @ext(i32* %P)
+  br label %loop
+
+loop:
+  %count = phi i32 [ 0, %entry ], [ %next, %loop ]
+  %next = add i32 %count, 1
+  call void @callee(i32 %N)
+  %cond = icmp eq i32 %count, 100000
+  br i1 %cond, label %out, label %loop
+
+out:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/ephemeral.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ephemeral.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ephemeral.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ephemeral.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -S -Oz %s | FileCheck %s
+
+ at a = global i32 4
+
+define i32 @inner() {
+  %a1 = load volatile i32, i32* @a
+
+  ; Here are enough instructions to prevent inlining, but because they are used
+  ; only by the @llvm.assume intrinsic, they're free (and, thus, inlining will
+  ; still happen).
+  %a2 = mul i32 %a1, %a1
+  %a3 = sub i32 %a1, 5
+  %a4 = udiv i32 %a3, -13
+  %a5 = mul i32 %a4, %a4
+  %a6 = add i32 %a5, %a5
+  %ca = icmp sgt i32 %a6, -7
+  tail call void @llvm.assume(i1 %ca)
+
+  ret i32 %a1
+}
+
+; @inner() should be inlined for -Oz.
+; CHECK-NOT: call i1 @inner
+define i32 @outer() optsize {
+   %r = call i32 @inner()
+   ret i32 %r
+}
+
+declare void @llvm.assume(i1) nounwind
+

Added: llvm/trunk/test/Transforms/Inline/externally_available.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/externally_available.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/externally_available.ll (added)
+++ llvm/trunk/test/Transforms/Inline/externally_available.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -inline -constprop -S | FileCheck %s
+
+define available_externally i32 @test_function() {
+; CHECK-NOT: @test_function
+entry:
+  ret i32 4
+}
+
+
+define i32 @result() {
+; CHECK-LABEL: define i32 @result()
+entry:
+  %A = call i32 @test_function()
+; CHECK-NOT: call
+; CHECK-NOT: @test_function
+
+  %B = add i32 %A, 1
+  ret i32 %B
+; CHECK: ret i32 5
+}
+
+; CHECK-NOT: @test_function

Added: llvm/trunk/test/Transforms/Inline/frameescape.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/frameescape.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/frameescape.ll (added)
+++ llvm/trunk/test/Transforms/Inline/frameescape.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+; PR23216: We can't inline functions using llvm.localescape.
+
+declare void @llvm.localescape(...)
+declare i8* @llvm.frameaddress(i32)
+declare i8* @llvm.localrecover(i8*, i8*, i32)
+
+define internal void @foo(i8* %fp) {
+  %a.i8 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @bar to i8*), i8* %fp, i32 0)
+  %a = bitcast i8* %a.i8 to i32*
+  store i32 42, i32* %a
+  ret void
+}
+
+define internal i32 @bar() {
+entry:
+  %a = alloca i32
+  call void (...) @llvm.localescape(i32* %a)
+  %fp = call i8* @llvm.frameaddress(i32 0)
+  tail call void @foo(i8* %fp)
+  %r = load i32, i32* %a
+  ret i32 %r
+}
+
+; We even bail when someone marks it alwaysinline.
+define internal i32 @bar_alwaysinline() alwaysinline {
+entry:
+  %a = alloca i32
+  call void (...) @llvm.localescape(i32* %a)
+  tail call void @foo(i8* null)
+  ret i32 0
+}
+
+define i32 @bazz() {
+entry:
+  %r = tail call i32 @bar()
+  %r1 = tail call i32 @bar_alwaysinline()
+  ret i32 %r
+}
+
+; CHECK: define i32 @bazz()
+; CHECK: call i32 @bar()
+; CHECK: call i32 @bar_alwaysinline()

Added: llvm/trunk/test/Transforms/Inline/function-count-update-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/function-count-update-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/function-count-update-2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/function-count-update-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S | FileCheck %s
+
+; This tests that the function count of a callee gets correctly updated after it
+; has been inlined into a two callsites.
+
+; CHECK: @callee() !prof [[COUNT:![0-9]+]]
+define i32 @callee() !prof !1 {
+  ret i32 0
+}
+
+define i32 @caller1() !prof !2 {
+; CHECK-LABEL: @caller1
+; CHECK-NOT: callee
+; CHECK: ret
+  %i = call i32 @callee()
+  ret i32 %i
+}
+
+define i32 @caller2() !prof !3 {
+; CHECK-LABEL: @caller2
+; CHECK-NOT: callee
+; CHECK: ret
+  %i = call i32 @callee()
+  ret i32 %i
+}
+
+!llvm.module.flags = !{!0}
+; CHECK: [[COUNT]] = !{!"function_entry_count", i64 0}
+!0 = !{i32 1, !"MaxFunctionCount", i32 1000}
+!1 = !{!"function_entry_count", i64 1000}
+!2 = !{!"function_entry_count", i64 600}
+!3 = !{!"function_entry_count", i64 400}
+

Added: llvm/trunk/test/Transforms/Inline/function-count-update-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/function-count-update-3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/function-count-update-3.ll (added)
+++ llvm/trunk/test/Transforms/Inline/function-count-update-3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,78 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S -inline-threshold=50 | FileCheck %s
+
+; This tests that the function count of a function gets properly scaled after 
+; inlining a call chain leading to the function.
+; Function a calls c with count 200 (C1)
+; Function c calls e with count 250 (C2)
+; Entry count of e is 500 (C3)
+; Entry count of c is 500 (C4)
+; Function b calls c with count 300 (C5)
+; c->e inlining does not happen since the cost exceeds threshold.
+; c then inlined into a.
+; e now gets inlined into a (through c) since the branch condition in e is now
+; known and hence the cost gets reduced.
+; Estimated count of a->e callsite = C2 * (C1 / C4)
+; Estimated count of a->e callsite = 250 * (200 / 500) = 100
+; Remaining count of e = C3 - 100 = 500 - 100 = 400
+; Remaining count of c = C4 - C1 - C5 = 500 - 200 - 300 = 0
+
+ at data = external global i32
+
+define i32 @a(i32 %a1) !prof !1 {
+  %a2 = call i32 @c(i32 %a1, i32 1)
+  ret i32 %a2
+}
+
+define i32 @b(i32 %b1) !prof !2 {
+  %b2 = call i32 @c(i32 %b1, i32 %b1)
+  ret i32 %b2
+}
+
+declare void @ext();
+
+; CHECK: @c(i32 %c1, i32 %c100) !prof [[COUNT1:![0-9]+]]
+define i32 @c(i32 %c1, i32 %c100) !prof !3 {
+  call void @ext()
+  %cond = icmp sle i32 %c1, 1
+  br i1 %cond, label %cond_true, label %cond_false
+
+cond_false:
+  ret i32 0
+
+cond_true:
+  %c11 = call i32 @e(i32 %c100)
+  ret i32 %c11
+}
+
+
+; CHECK: @e(i32 %c1) !prof [[COUNT2:![0-9]+]]
+define i32 @e(i32 %c1) !prof !4 {
+  %cond = icmp sle i32 %c1, 1
+  br i1 %cond, label %cond_true, label %cond_false
+
+cond_false:
+  call void @ext()
+  %c2 = load i32, i32* @data, align 4
+  %c3 = add i32 %c1, %c2
+  %c4 = mul i32 %c3, %c2
+  %c5 = add i32 %c4, %c2
+  %c6 = mul i32 %c5, %c2
+  %c7 = add i32 %c6, %c2
+  %c8 = mul i32 %c7, %c2
+  %c9 = add i32 %c8, %c2
+  %c10 = mul i32 %c9, %c2
+  ret i32 %c10
+
+cond_true:
+  ret i32 0
+}
+
+!llvm.module.flags = !{!0}
+; CHECK: [[COUNT1]] = !{!"function_entry_count", i64 0}
+; CHECK: [[COUNT2]] = !{!"function_entry_count", i64 400}
+!0 = !{i32 1, !"MaxFunctionCount", i32 5000}
+!1 = !{!"function_entry_count", i64 200}
+!2 = !{!"function_entry_count", i64 300}
+!3 = !{!"function_entry_count", i64 500}
+!4 = !{!"function_entry_count", i64 500}
+

Added: llvm/trunk/test/Transforms/Inline/function-count-update.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/function-count-update.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/function-count-update.ll (added)
+++ llvm/trunk/test/Transforms/Inline/function-count-update.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S | FileCheck %s
+
+; This tests that the function count of two callees get correctly updated after
+; they have been inlined into two back-to-back callsites in a single basic block
+; in the caller. The callees have the alwaysinline attribute and so they get
+; inlined both with the regular inliner pass and the always inline pass. In
+; both cases, the new count of each callee is the original count minus callsite
+; count which is 200 (since the caller's entry count is 400 and the block
+; containing the calls have a relative block frequency of 0.5).
+
+; CHECK: @callee1(i32 %n) #0 !prof [[COUNT1:![0-9]+]]
+define i32 @callee1(i32 %n) #0 !prof !1 {
+  %cond = icmp sle i32 %n, 10
+  br i1 %cond, label %cond_true, label %cond_false
+
+cond_true:
+  %r1 = add i32 %n, 1
+  ret i32 %r1
+cond_false:
+  %r2 = add i32 %n, 2
+  ret i32 %r2
+}
+
+; CHECK: @callee2(i32 %n) #0 !prof [[COUNT2:![0-9]+]]
+define i32 @callee2(i32 %n) #0 !prof !2 {
+  %r1 = add i32 %n, 1
+  ret i32 %r1
+}
+
+define i32 @caller(i32 %n) !prof !3 {
+  %cond = icmp sle i32 %n, 100
+  br i1 %cond, label %cond_true, label %cond_false
+
+cond_true:
+  %i = call i32 @callee1(i32 %n)
+  %j = call i32 @callee2(i32 %i)
+  ret i32 %j
+cond_false:
+  ret i32 0
+}
+
+!llvm.module.flags = !{!0}
+; CHECK: [[COUNT1]] = !{!"function_entry_count", i64 800}
+; CHECK: [[COUNT2]] = !{!"function_entry_count", i64 1800}
+!0 = !{i32 1, !"MaxFunctionCount", i32 1000}
+!1 = !{!"function_entry_count", i64 1000}
+!2 = !{!"function_entry_count", i64 2000}
+!3 = !{!"function_entry_count", i64 400}
+attributes #0 = { alwaysinline }
+

Added: llvm/trunk/test/Transforms/Inline/guard-intrinsic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/guard-intrinsic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/guard-intrinsic.ll (added)
+++ llvm/trunk/test/Transforms/Inline/guard-intrinsic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -S -always-inline < %s | FileCheck %s
+
+declare void @llvm.experimental.guard(i1, ...)
+
+define i8 @callee(i1* %c_ptr) alwaysinline {
+  %c = load volatile i1, i1* %c_ptr
+  call void(i1, ...) @llvm.experimental.guard(i1 %c, i32 1) [ "deopt"(i32 1) ]
+  ret i8 5
+}
+
+define void @caller_0(i1* %c, i8* %ptr) {
+; CHECK-LABEL: @caller_0(
+entry:
+; CHECK:  [[COND:%[^ ]+]] = load volatile i1, i1* %c
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 [[COND]], i32 1) [ "deopt"(i32 2, i32 1) ]
+; CHECK-NEXT:  store i8 5, i8* %ptr
+
+  %v = call i8 @callee(i1* %c)  [ "deopt"(i32 2) ]
+  store i8 %v, i8* %ptr
+  ret void
+}
+
+define i32 @caller_1(i1* %c, i8* %ptr) personality i8 3 {
+; CHECK-LABEL: @caller_1(
+; CHECK:  [[COND:%[^ ]+]] = load volatile i1, i1* %c
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 [[COND]], i32 1) [ "deopt"(i32 3, i32 1) ]
+; CHECK-NEXT:  br label %normal
+entry:
+  %v = invoke i8 @callee(i1* %c)  [ "deopt"(i32 3) ] to label %normal
+       unwind label %unwind
+
+unwind:
+  %lp = landingpad i32 cleanup
+  ret i32 43
+
+normal:
+  store i8 %v, i8* %ptr
+  ret i32 42
+}

Added: llvm/trunk/test/Transforms/Inline/gvn-inline-iteration.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/gvn-inline-iteration.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/gvn-inline-iteration.ll (added)
+++ llvm/trunk/test/Transforms/Inline/gvn-inline-iteration.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -basicaa -inline -gvn -S -max-cg-scc-iterations=1 < %s | FileCheck %s
+; rdar://6295824 and PR6724
+
+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"
+
+define i32 @foo(i32 ()** noalias nocapture %p, i64* noalias nocapture %q) nounwind ssp {
+entry:
+  store i32 ()* @bar, i32 ()** %p
+  store i64 0, i64* %q
+  %tmp3 = load i32 ()*, i32 ()** %p                        ; <i32 ()*> [#uses=1]
+  %call = tail call i32 %tmp3() nounwind          ; <i32> [#uses=1]
+  ret i32 %call
+}
+; CHECK-LABEL: @foo(
+; CHECK: ret i32 7
+; CHECK-LABEL: @bar(
+; CHECK: ret i32 7
+
+define internal i32 @bar() nounwind readnone ssp {
+entry:
+  ret i32 7
+}

Added: llvm/trunk/test/Transforms/Inline/ignore-debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ignore-debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ignore-debug-info.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ignore-debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,58 @@
+; RUN: opt < %s -S -inline -inline-threshold=2 | FileCheck %s
+; RUN: opt < %s -S -strip-debug -inline -inline-threshold=2 | FileCheck %s
+; RUN: opt < %s -S -passes='cgscc(inline)' -inline-threshold=2 | FileCheck %s
+; RUN: opt < %s -S -strip-debug -passes='cgscc(inline)' -inline-threshold=2 | FileCheck %s
+;
+; The purpose of this test is to check that debug info doesn't influence
+; inlining decisions.
+
+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 void @llvm.dbg.declare(metadata, metadata, metadata) #1
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+define <4 x float> @inner_vectors(<4 x float> %a, <4 x float> %b) {
+entry:
+  call void @llvm.dbg.value(metadata i32 undef, metadata !DILocalVariable(scope: !6), metadata !DIExpression()), !dbg !DILocation(scope: !6)
+  %mul = fmul <4 x float> %a, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00>
+  call void @llvm.dbg.value(metadata i32 undef, metadata !DILocalVariable(scope: !6), metadata !DIExpression()), !dbg !DILocation(scope: !6)
+  %mul1 = fmul <4 x float> %b, <float 5.000000e+00, float 5.000000e+00, float 5.000000e+00, float 5.000000e+00>
+  call void @llvm.dbg.value(metadata i32 undef, metadata !DILocalVariable(scope: !6), metadata !DIExpression()), !dbg !DILocation(scope: !6)
+  %add = fadd <4 x float> %mul, %mul1
+  ret <4 x float> %add
+}
+
+define float @outer_vectors(<4 x float> %a, <4 x float> %b) {
+; CHECK-LABEL: @outer_vectors(
+; CHECK-NOT: call <4 x float> @inner_vectors(
+; CHECK: ret float
+
+entry:
+  call void @llvm.dbg.value(metadata i32 undef, metadata !DILocalVariable(scope: !6), metadata !DIExpression()), !dbg !DILocation(scope: !6)
+  call void @llvm.dbg.value(metadata i32 undef, metadata !DILocalVariable(scope: !6), metadata !DIExpression()), !dbg !DILocation(scope: !6)
+  %call = call <4 x float> @inner_vectors(<4 x float> %a, <4 x float> %b)
+  call void @llvm.dbg.value(metadata i32 undef, metadata !DILocalVariable(scope: !6), metadata !DIExpression()), !dbg !DILocation(scope: !6)
+  %vecext = extractelement <4 x float> %call, i32 0
+  %vecext1 = extractelement <4 x float> %call, i32 1
+  %add = fadd float %vecext, %vecext1
+  %vecext2 = extractelement <4 x float> %call, i32 2
+  %add3 = fadd float %add, %vecext2
+  %vecext4 = extractelement <4 x float> %call, i32 3
+  %add5 = fadd float %add3, %vecext4
+  ret float %add5
+}
+
+attributes #0 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+!1 = !DIFile(filename: "test.c", directory: "")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 1, !"Debug Info Version", i32 3}
+!5 = !{!""}
+!6 = distinct !DISubprogram(unit: !0)

Added: llvm/trunk/test/Transforms/Inline/inalloca-not-static.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inalloca-not-static.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inalloca-not-static.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inalloca-not-static.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; RUN: opt -always-inline -S < %s | FileCheck %s
+; RUN: opt -passes=always-inline -S < %s | FileCheck %s
+
+; We used to misclassify inalloca as a static alloca in the inliner. This only
+; arose with for alwaysinline functions, because the normal inliner refuses to
+; inline such things.
+
+; Generated using this C++ source:
+; struct Foo {
+;   Foo();
+;   Foo(const Foo &o);
+;   ~Foo();
+;   int a;
+; };
+; __forceinline void h(Foo o) {}
+; __forceinline void g() { h(Foo()); }
+; void f() { g(); }
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i386-pc-windows-msvc19.0.24210"
+
+%struct.Foo = type { i32 }
+
+declare i8* @llvm.stacksave()
+declare void @llvm.stackrestore(i8*)
+
+declare x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE at XZ"(%struct.Foo* returned) unnamed_addr
+declare x86_thiscallcc void @"\01??1Foo@@QAE at XZ"(%struct.Foo*) unnamed_addr
+
+define void @f() {
+entry:
+  call void @g()
+  ret void
+}
+
+define internal void @g() alwaysinline {
+entry:
+  %inalloca.save = call i8* @llvm.stacksave()
+  %argmem = alloca inalloca <{ %struct.Foo }>, align 4
+  %0 = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %argmem, i32 0, i32 0
+  %call = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE at XZ"(%struct.Foo* %0)
+  call void @h(<{ %struct.Foo }>* inalloca %argmem)
+  call void @llvm.stackrestore(i8* %inalloca.save)
+  ret void
+}
+
+; Function Attrs: alwaysinline inlinehint nounwind
+define internal void @h(<{ %struct.Foo }>* inalloca) alwaysinline {
+entry:
+  %o = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
+  call x86_thiscallcc void @"\01??1Foo@@QAE at XZ"(%struct.Foo* %o)
+  ret void
+}
+
+; CHECK: define void @f()
+; CHECK:   %[[STACKSAVE:.*]] = call i8* @llvm.stacksave()
+; CHECK:   %[[ARGMEM:.*]] = alloca inalloca <{ %struct.Foo }>, align 4
+; CHECK:   %[[GEP1:.*]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %[[ARGMEM]], i32 0, i32 0
+; CHECK:   %[[CALL:.*]] = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE at XZ"(%struct.Foo* %[[GEP1]])
+; CHECK:   %[[GEP2:.*]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %[[ARGMEM]], i32 0, i32 0
+; CHECK:   call x86_thiscallcc void @"\01??1Foo@@QAE at XZ"(%struct.Foo* %[[GEP2]])
+; CHECK:   call void @llvm.stackrestore(i8* %[[STACKSAVE]])
+; CHECK:   ret void

Added: llvm/trunk/test/Transforms/Inline/infinite-loop-two-predecessors.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/infinite-loop-two-predecessors.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/infinite-loop-two-predecessors.ll (added)
+++ llvm/trunk/test/Transforms/Inline/infinite-loop-two-predecessors.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -S -o - %s -inline | FileCheck %s
+
+define void @f1() {
+bb.0:
+  br i1 false, label %bb.2, label %bb.1
+
+bb.1:                                             ; preds = %bb.0
+  br label %bb.2
+
+bb.2:                                             ; preds = %bb.0, %bb.1
+  %tmp0 = phi i1 [ true, %bb.1 ], [ false, %bb.0 ]
+  br i1 %tmp0, label %bb.4, label %bb.3
+
+bb.3:                                             ; preds = %bb.3, %bb.3
+  br i1 undef, label %bb.3, label %bb.3
+
+bb.4:                                             ; preds = %bb.2
+  ret void
+}
+
+define void @f2() {
+bb.0:
+  call void @f1()
+  ret void
+}
+
+; f1 should be inlined into f2 and simplified/collapsed to nothing.
+
+; CHECK-LABEL: define void @f2() {
+; CHECK-NEXT:  bb.0:
+; CHECK-NEXT:    ret void
+; CHECK-NEXT:  }

Added: llvm/trunk/test/Transforms/Inline/inline-assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-assume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-assume.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-assume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -inline -S -o - < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+%0 = type opaque
+%struct.Foo = type { i32, %0* }
+
+; Test that we don't crash when inlining @bar (rdar://22521387).
+define void @foo(%struct.Foo* align 4 %a) {
+entry:
+  call fastcc void @bar(%struct.Foo* nonnull align 4 undef)
+
+; CHECK: call void @llvm.assume(i1 undef)
+; CHECK: unreachable
+
+  ret void
+}
+
+define fastcc void @bar(%struct.Foo* align 4 %a) {
+; CHECK-LABEL: @bar
+entry:
+  %b = getelementptr inbounds %struct.Foo, %struct.Foo* %a, i32 0, i32 1
+  br i1 undef, label %if.end, label %if.then.i.i
+
+if.then.i.i:
+  call void @llvm.assume(i1 undef)
+  unreachable
+
+if.end:
+  ret void
+}
+
+declare void @llvm.assume(i1)

Added: llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; Test that inliner skips @llvm.icall.branch.funnel
+; RUN: opt < %s -inline -S | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @llvm.icall.branch.funnel(...)
+
+; CHECK-LABEL: define void @fn_musttail(
+define void @fn_musttail() {
+  call void (...) @bf_musttail()
+  ; CHECK: call void (...) @bf_musttail(
+  ret void
+}
+
+; CHECK-LABEL: define internal void @bf_musttail(
+define internal void @bf_musttail(...) {
+  musttail call void (...) @llvm.icall.branch.funnel(...)
+  ; CHECK: musttail call void (...) @llvm.icall.branch.funnel(
+  ret void
+}
+
+; CHECK-LABEL: define void @fn_musttail_always(
+define void @fn_musttail_always() {
+  call void (...) @bf_musttail_always()
+  ; CHECK: call void (...) @bf_musttail_always(
+  ret void
+}
+
+; CHECK-LABEL: define internal void @bf_musttail_always(
+define internal void @bf_musttail_always(...) alwaysinline {
+  musttail call void (...) @llvm.icall.branch.funnel(...)
+  ; CHECK: musttail call void (...) @llvm.icall.branch.funnel(
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/inline-byval-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-byval-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-byval-bonus.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-byval-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,194 @@
+; RUN: opt -S -inline -inline-threshold=275 < %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' -inline-threshold=275 < %s | FileCheck %s
+; PR13095
+
+; The performance of the c-ray benchmark largely depends on the inlining of a
+; specific call to @ray_sphere. This test case is designed to verify that it's
+; inlined at -O3.
+
+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.8.0"
+
+%struct.sphere = type { %struct.vec3, double, %struct.material, %struct.sphere* }
+%struct.vec3 = type { double, double, double }
+%struct.material = type { %struct.vec3, double, double }
+%struct.ray = type { %struct.vec3, %struct.vec3 }
+%struct.spoint = type { %struct.vec3, %struct.vec3, %struct.vec3, double }
+
+define i32 @caller(%struct.sphere* %i) {
+  %shadow_ray = alloca %struct.ray, align 8
+  call void @fix(%struct.ray* %shadow_ray)
+
+  %call = call i32 @ray_sphere(%struct.sphere* %i, %struct.ray* byval align 8 %shadow_ray, %struct.spoint* null)
+  ret i32 %call
+
+; CHECK-LABEL: @caller(
+; CHECK-NOT: call i32 @ray_sphere
+; CHECK: ret i32
+}
+
+declare void @fix(%struct.ray*)
+
+define i32 @ray_sphere(%struct.sphere* nocapture %sph, %struct.ray* nocapture byval align 8 %ray, %struct.spoint* %sp) nounwind uwtable ssp {
+  %1 = getelementptr inbounds %struct.ray, %struct.ray* %ray, i64 0, i32 1, i32 0
+  %2 = load double, double* %1, align 8
+  %3 = fmul double %2, %2
+  %4 = getelementptr inbounds %struct.ray, %struct.ray* %ray, i64 0, i32 1, i32 1
+  %5 = load double, double* %4, align 8
+  %6 = fmul double %5, %5
+  %7 = fadd double %3, %6
+  %8 = getelementptr inbounds %struct.ray, %struct.ray* %ray, i64 0, i32 1, i32 2
+  %9 = load double, double* %8, align 8
+  %10 = fmul double %9, %9
+  %11 = fadd double %7, %10
+  %12 = fmul double %2, 2.000000e+00
+  %13 = getelementptr inbounds %struct.ray, %struct.ray* %ray, i64 0, i32 0, i32 0
+  %14 = load double, double* %13, align 8
+  %15 = getelementptr inbounds %struct.sphere, %struct.sphere* %sph, i64 0, i32 0, i32 0
+  %16 = load double, double* %15, align 8
+  %17 = fsub double %14, %16
+  %18 = fmul double %12, %17
+  %19 = fmul double %5, 2.000000e+00
+  %20 = getelementptr inbounds %struct.ray, %struct.ray* %ray, i64 0, i32 0, i32 1
+  %21 = load double, double* %20, align 8
+  %22 = getelementptr inbounds %struct.sphere, %struct.sphere* %sph, i64 0, i32 0, i32 1
+  %23 = load double, double* %22, align 8
+  %24 = fsub double %21, %23
+  %25 = fmul double %19, %24
+  %26 = fadd double %18, %25
+  %27 = fmul double %9, 2.000000e+00
+  %28 = getelementptr inbounds %struct.ray, %struct.ray* %ray, i64 0, i32 0, i32 2
+  %29 = load double, double* %28, align 8
+  %30 = getelementptr inbounds %struct.sphere, %struct.sphere* %sph, i64 0, i32 0, i32 2
+  %31 = load double, double* %30, align 8
+  %32 = fsub double %29, %31
+  %33 = fmul double %27, %32
+  %34 = fadd double %26, %33
+  %35 = fmul double %16, %16
+  %36 = fmul double %23, %23
+  %37 = fadd double %35, %36
+  %38 = fmul double %31, %31
+  %39 = fadd double %37, %38
+  %40 = fmul double %14, %14
+  %41 = fadd double %40, %39
+  %42 = fmul double %21, %21
+  %43 = fadd double %42, %41
+  %44 = fmul double %29, %29
+  %45 = fadd double %44, %43
+  %46 = fsub double -0.000000e+00, %16
+  %47 = fmul double %14, %46
+  %48 = fmul double %21, %23
+  %49 = fsub double %47, %48
+  %50 = fmul double %29, %31
+  %51 = fsub double %49, %50
+  %52 = fmul double %51, 2.000000e+00
+  %53 = fadd double %52, %45
+  %54 = getelementptr inbounds %struct.sphere, %struct.sphere* %sph, i64 0, i32 1
+  %55 = load double, double* %54, align 8
+  %56 = fmul double %55, %55
+  %57 = fsub double %53, %56
+  %58 = fmul double %34, %34
+  %59 = fmul double %11, 4.000000e+00
+  %60 = fmul double %59, %57
+  %61 = fsub double %58, %60
+  %62 = fcmp olt double %61, 0.000000e+00
+  br i1 %62, label %130, label %63
+
+; <label>:63                                      ; preds = %0
+  %64 = tail call double @sqrt(double %61) nounwind readnone
+  %65 = fsub double -0.000000e+00, %34
+  %66 = fsub double %64, %34
+  %67 = fmul double %11, 2.000000e+00
+  %68 = fdiv double %66, %67
+  %69 = fsub double %65, %64
+  %70 = fdiv double %69, %67
+  %71 = fcmp olt double %68, 1.000000e-06
+  %72 = fcmp olt double %70, 1.000000e-06
+  %or.cond = and i1 %71, %72
+  br i1 %or.cond, label %130, label %73
+
+; <label>:73                                      ; preds = %63
+  %74 = fcmp ogt double %68, 1.000000e+00
+  %75 = fcmp ogt double %70, 1.000000e+00
+  %or.cond1 = and i1 %74, %75
+  br i1 %or.cond1, label %130, label %76
+
+; <label>:76                                      ; preds = %73
+  %77 = icmp eq %struct.spoint* %sp, null
+  br i1 %77, label %130, label %78
+
+; <label>:78                                      ; preds = %76
+  %t1.0 = select i1 %71, double %70, double %68
+  %t2.0 = select i1 %72, double %t1.0, double %70
+  %79 = fcmp olt double %t1.0, %t2.0
+  %80 = select i1 %79, double %t1.0, double %t2.0
+  %81 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 3
+  store double %80, double* %81, align 8
+  %82 = fmul double %80, %2
+  %83 = fadd double %14, %82
+  %84 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 0, i32 0
+  store double %83, double* %84, align 8
+  %85 = fmul double %5, %80
+  %86 = fadd double %21, %85
+  %87 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 0, i32 1
+  store double %86, double* %87, align 8
+  %88 = fmul double %9, %80
+  %89 = fadd double %29, %88
+  %90 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 0, i32 2
+  store double %89, double* %90, align 8
+  %91 = load double, double* %15, align 8
+  %92 = fsub double %83, %91
+  %93 = load double, double* %54, align 8
+  %94 = fdiv double %92, %93
+  %95 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 1, i32 0
+  store double %94, double* %95, align 8
+  %96 = load double, double* %22, align 8
+  %97 = fsub double %86, %96
+  %98 = load double, double* %54, align 8
+  %99 = fdiv double %97, %98
+  %100 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 1, i32 1
+  store double %99, double* %100, align 8
+  %101 = load double, double* %30, align 8
+  %102 = fsub double %89, %101
+  %103 = load double, double* %54, align 8
+  %104 = fdiv double %102, %103
+  %105 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 1, i32 2
+  store double %104, double* %105, align 8
+  %106 = fmul double %2, %94
+  %107 = fmul double %5, %99
+  %108 = fadd double %106, %107
+  %109 = fmul double %9, %104
+  %110 = fadd double %108, %109
+  %111 = fmul double %110, 2.000000e+00
+  %112 = fmul double %94, %111
+  %113 = fsub double %112, %2
+  %114 = fsub double -0.000000e+00, %113
+  %115 = fmul double %99, %111
+  %116 = fsub double %115, %5
+  %117 = fsub double -0.000000e+00, %116
+  %118 = fmul double %104, %111
+  %119 = fsub double %118, %9
+  %120 = fsub double -0.000000e+00, %119
+  %.06 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 2, i32 0
+  %.18 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 2, i32 1
+  %.210 = getelementptr inbounds %struct.spoint, %struct.spoint* %sp, i64 0, i32 2, i32 2
+  %121 = fmul double %113, %113
+  %122 = fmul double %116, %116
+  %123 = fadd double %121, %122
+  %124 = fmul double %119, %119
+  %125 = fadd double %123, %124
+  %126 = tail call double @sqrt(double %125) nounwind readnone
+  %127 = fdiv double %114, %126
+  store double %127, double* %.06, align 8
+  %128 = fdiv double %117, %126
+  store double %128, double* %.18, align 8
+  %129 = fdiv double %120, %126
+  store double %129, double* %.210, align 8
+  br label %130
+
+; <label>:130                                     ; preds = %78, %76, %73, %63, %0
+  %.0 = phi i32 [ 0, %0 ], [ 0, %73 ], [ 0, %63 ], [ 1, %76 ], [ 1, %78 ]
+  ret i32 %.0
+}
+
+declare double @sqrt(double) nounwind readnone

Added: llvm/trunk/test/Transforms/Inline/inline-cold-callee.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-cold-callee.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-cold-callee.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-cold-callee.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -inline -inlinecold-threshold=0 -S | FileCheck %s
+
+; This tests that a cold callee gets the (lower) inlinecold-threshold even without
+; Cold hint and does not get inlined because the cost exceeds the inlinecold-threshold.
+; A callee with identical body does gets inlined because cost fits within the
+; inline-threshold
+
+define i32 @callee1(i32 %x) !prof !21 {
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @callee2(i32 %x) !prof !22 {
+; CHECK-LABEL: @callee2(
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @caller2(i32 %y1) !prof !22 {
+; CHECK-LABEL: @caller2(
+; CHECK: call i32 @callee2
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+  %y2 = call i32 @callee2(i32 %y1)
+  %y3 = call i32 @callee1(i32 %y2)
+  ret i32 %y3
+}
+
+declare void @extern()
+
+!llvm.module.flags = !{!1}
+!21 = !{!"function_entry_count", i64 100}
+!22 = !{!"function_entry_count", i64 1}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 1000}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}

Added: llvm/trunk/test/Transforms/Inline/inline-cold-callsite-pgo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-cold-callsite-pgo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-cold-callsite-pgo.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-cold-callsite-pgo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -inline-threshold=100 -inline-cold-callsite-threshold=0 -S | FileCheck %s
+
+; This tests that a cold callsite gets the inline-cold-callsite-threshold
+; and does not get inlined. Another callsite to an identical callee that
+; is not cold gets inlined because cost is below the inline-threshold.
+
+define i32 @callee1(i32 %x) !prof !21 {
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @caller(i32 %n) !prof !22 {
+; CHECK-LABEL: @caller(
+  %cond = icmp sle i32 %n, 100
+  br i1 %cond, label %cond_true, label %cond_false, !prof !0
+
+cond_true:
+; CHECK-LABEL: cond_true:
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+  %i = call i32 @callee1(i32 %n)
+  ret i32 %i
+cond_false:
+; CHECK-LABEL: cond_false:
+; CHECK: call i32 @callee1
+; CHECK: ret i32 %j
+  %j = call i32 @callee1(i32 %n)
+  ret i32 %j
+}
+declare void @extern()
+
+!0 = !{!"branch_weights", i32 200, i32 1}
+
+!llvm.module.flags = !{!1}
+!21 = !{!"function_entry_count", i64 200}
+!22 = !{!"function_entry_count", i64 200}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 1000}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 1000, i32 1}
+!13 = !{i32 999000, i64 1000, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}

Added: llvm/trunk/test/Transforms/Inline/inline-cold-callsite.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-cold-callsite.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-cold-callsite.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-cold-callsite.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -inline-threshold=100 -inline-cold-callsite-threshold=0 -S | FileCheck %s
+
+; This tests that a cold callsite gets the inline-cold-callsite-threshold
+; and does not get inlined. Another callsite to an identical callee that
+; is not cold gets inlined because cost is below the inline-threshold.
+
+define void @callee() {
+  call void @extern()
+  call void @extern()
+  ret void
+}
+
+declare void @extern()
+declare i1 @ext(i32)
+
+; CHECK-LABEL: caller
+define i32 @caller(i32 %n) {
+entry:
+  %cmp4 = icmp sgt i32 %n, 0
+  br i1 %cmp4, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:
+  ret i32 0
+
+for.body:
+  %i.05 = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+; CHECK: %call = tail call
+  %call = tail call zeroext i1 @ext(i32 %i.05)
+; CHECK-NOT: call void @callee
+; CHECK-NEXT: call void @extern
+  call void @callee()
+  br i1 %call, label %cold, label %for.inc, !prof !0
+
+cold:
+; CHECK: call void @callee
+  call void @callee()
+  br label %for.inc
+
+for.inc:
+  %inc = add nuw nsw i32 %i.05, 1
+  %exitcond = icmp eq i32 %inc, %n
+  br i1 %exitcond, label %for.cond.cleanup, label %for.body
+}
+
+
+!0 = !{!"branch_weights", i32 1, i32 2000}

Added: llvm/trunk/test/Transforms/Inline/inline-cold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-cold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-cold.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-cold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,188 @@
+; RUN: opt < %s -inline -S -inlinecold-threshold=25 | FileCheck %s
+; Test that functions with attribute Cold are not inlined while the 
+; same function without attribute Cold will be inlined.
+
+; RUN: opt < %s -inline -S -inline-threshold=600 | FileCheck %s -check-prefix=OVERRIDE
+; The command line argument for inline-threshold should override
+; the default cold threshold, so a cold function with size bigger
+; than the default cold threshold (225) will be inlined.
+
+; RUN: opt < %s -inline -S | FileCheck %s -check-prefix=DEFAULT
+; The same cold function will not be inlined with the default behavior.
+
+ at a = global i32 4
+
+; This function should be larger than the cold threshold (75), but smaller
+; than the regular threshold.
+; Function Attrs: nounwind readnone uwtable
+define i32 @simpleFunction(i32 %a) #0 {
+entry:
+  call void @extern()
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %a2 = load volatile i32, i32* @a
+  %x2 = add i32 %x1, %a2
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %a5 = load volatile i32, i32* @a
+  %x5 = add i32 %x4, %a5
+  %a6 = load volatile i32, i32* @a
+  %x6 = add i32 %x5, %a6
+  %a7 = load volatile i32, i32* @a
+  %x7 = add i32 %x6, %a6
+  %a8 = load volatile i32, i32* @a
+  %x8 = add i32 %x7, %a8
+  %a9 = load volatile i32, i32* @a
+  %x9 = add i32 %x8, %a9
+  %a10 = load volatile i32, i32* @a
+  %x10 = add i32 %x9, %a10
+  %a11 = load volatile i32, i32* @a
+  %x11 = add i32 %x10, %a11
+  %a12 = load volatile i32, i32* @a
+  %x12 = add i32 %x11, %a12
+  %add = add i32 %x12, %a
+  ret i32 %add
+}
+
+; Function Attrs: nounwind cold readnone uwtable
+define i32 @ColdFunction(i32 %a) #1 {
+; CHECK-LABEL: @ColdFunction
+; CHECK: ret
+; OVERRIDE-LABEL: @ColdFunction
+; OVERRIDE: ret
+; DEFAULT-LABEL: @ColdFunction
+; DEFAULT: ret
+entry:
+  call void @extern()
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %a2 = load volatile i32, i32* @a
+  %x2 = add i32 %x1, %a2
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %add = add i32 %x4, %a
+  ret i32 %add
+}
+
+; This function should be larger than the default cold threshold (225).
+define i32 @ColdFunction2(i32 %a) #1 {
+; CHECK-LABEL: @ColdFunction2
+; CHECK: ret
+; OVERRIDE-LABEL: @ColdFunction2
+; OVERRIDE: ret
+; DEFAULT-LABEL: @ColdFunction2
+; DEFAULT: ret
+entry:
+  call void @extern()
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %a2 = load volatile i32, i32* @a
+  %x2 = add i32 %x1, %a2
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %a5 = load volatile i32, i32* @a
+  %x5 = add i32 %x4, %a5
+  %a6 = load volatile i32, i32* @a
+  %x6 = add i32 %x5, %a6
+  %a7 = load volatile i32, i32* @a
+  %x7 = add i32 %x6, %a7
+  %a8 = load volatile i32, i32* @a
+  %x8 = add i32 %x7, %a8
+  %a9 = load volatile i32, i32* @a
+  %x9 = add i32 %x8, %a9
+  %a10 = load volatile i32, i32* @a
+  %x10 = add i32 %x9, %a10
+  %a11 = load volatile i32, i32* @a
+  %x11 = add i32 %x10, %a11
+  %a12 = load volatile i32, i32* @a
+  %x12 = add i32 %x11, %a12
+
+  %a21 = load volatile i32, i32* @a
+  %x21 = add i32 %x12, %a21
+  %a22 = load volatile i32, i32* @a
+  %x22 = add i32 %x21, %a22
+  %a23 = load volatile i32, i32* @a
+  %x23 = add i32 %x22, %a23
+  %a24 = load volatile i32, i32* @a
+  %x24 = add i32 %x23, %a24
+  %a25 = load volatile i32, i32* @a
+  %x25 = add i32 %x24, %a25
+  %a26 = load volatile i32, i32* @a
+  %x26 = add i32 %x25, %a26
+  %a27 = load volatile i32, i32* @a
+  %x27 = add i32 %x26, %a27
+  %a28 = load volatile i32, i32* @a
+  %x28 = add i32 %x27, %a28
+  %a29 = load volatile i32, i32* @a
+  %x29 = add i32 %x28, %a29
+  %a30 = load volatile i32, i32* @a
+  %x30 = add i32 %x29, %a30
+  %a31 = load volatile i32, i32* @a
+  %x31 = add i32 %x30, %a31
+  %a32 = load volatile i32, i32* @a
+  %x32 = add i32 %x31, %a32
+
+  %a41 = load volatile i32, i32* @a
+  %x41 = add i32 %x32, %a41
+  %a42 = load volatile i32, i32* @a
+  %x42 = add i32 %x41, %a42
+  %a43 = load volatile i32, i32* @a
+  %x43 = add i32 %x42, %a43
+  %a44 = load volatile i32, i32* @a
+  %x44 = add i32 %x43, %a44
+  %a45 = load volatile i32, i32* @a
+  %x45 = add i32 %x44, %a45
+  %a46 = load volatile i32, i32* @a
+  %x46 = add i32 %x45, %a46
+  %a47 = load volatile i32, i32* @a
+  %x47 = add i32 %x46, %a47
+  %a48 = load volatile i32, i32* @a
+  %x48 = add i32 %x47, %a48
+  %a49 = load volatile i32, i32* @a
+  %x49 = add i32 %x48, %a49
+  %a50 = load volatile i32, i32* @a
+  %x50 = add i32 %x49, %a50
+  %a51 = load volatile i32, i32* @a
+  %x51 = add i32 %x50, %a51
+  %a52 = load volatile i32, i32* @a
+  %x52 = add i32 %x51, %a52
+
+  %add = add i32 %x52, %a
+  ret i32 %add
+}
+
+; Function Attrs: nounwind readnone uwtable
+define i32 @bar(i32 %a) #0 {
+; CHECK-LABEL: @bar
+; CHECK: call i32 @ColdFunction(i32 5)
+; CHECK-NOT: call i32 @simpleFunction(i32 6)
+; CHECK: call i32 @ColdFunction2(i32 5)
+; CHECK: ret
+; OVERRIDE-LABEL: @bar
+; OVERRIDE-NOT: call i32 @ColdFunction(i32 5)
+; OVERRIDE-NOT: call i32 @simpleFunction(i32 6)
+; OVERRIDE-NOT: call i32 @ColdFunction2(i32 5)
+; OVERRIDE: ret
+; DEFAULT-LABEL: @bar
+; DEFAULT-NOT: call i32 @ColdFunction(i32 5)
+; DEFAULT-NOT: call i32 @simpleFunction(i32 6)
+; DEFAULT: call i32 @ColdFunction2(i32 5)
+; DEFAULT: ret
+entry:
+  %0 = tail call i32 @ColdFunction(i32 5)
+  %1 = tail call i32 @simpleFunction(i32 6)
+  %2 = tail call i32 @ColdFunction2(i32 5)
+  %3 = add i32 %0, %1
+  %add = add i32 %2, %3
+  ret i32 %add
+}
+
+declare void @extern()
+attributes #0 = { nounwind readnone uwtable }
+attributes #1 = { nounwind cold readnone uwtable }

Added: llvm/trunk/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-constexpr-addrspacecast-argument.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -S -inline < %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' < %s | FileCheck %s
+
+target datalayout = "e-p3:32:32-p4:64:64-n32"
+
+ at lds = internal addrspace(3) global [64 x i64] zeroinitializer
+
+; CHECK-LABEL: @constexpr_addrspacecast_ptr_size_change(
+; CHECK: load i64, i64 addrspace(4)* addrspacecast (i64 addrspace(3)* getelementptr inbounds ([64 x i64], [64 x i64] addrspace(3)* @lds, i32 0, i32 0) to i64 addrspace(4)*)
+; CHECK-NEXT: br
+define void @constexpr_addrspacecast_ptr_size_change() #0 {
+  %tmp0 = call i32 @foo(i64 addrspace(4)* addrspacecast (i64 addrspace(3)* getelementptr inbounds ([64 x i64], [64 x i64] addrspace(3)* @lds, i32 0, i32 0) to i64 addrspace(4)*)) #1
+  ret void
+}
+
+define i32 @foo(i64 addrspace(4)* %arg) #1 {
+bb:
+  %tmp = getelementptr i64, i64 addrspace(4)* %arg, i64 undef
+  %tmp1 = load i64, i64 addrspace(4)* %tmp
+  br i1 undef, label %bb2, label %bb3
+
+bb2:
+  store i64 0, i64 addrspace(4)* %tmp
+  br label %bb3
+
+bb3:
+  unreachable
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { alwaysinline nounwind }

Added: llvm/trunk/test/Transforms/Inline/inline-fast-math-flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-fast-math-flags.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-fast-math-flags.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-fast-math-flags.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -S -inline -inline-threshold=20 | FileCheck %s
+; RUN: opt < %s -S -passes='cgscc(inline)' -inline-threshold=20 | FileCheck %s
+; Check that we don't drop FastMathFlag when estimating inlining profitability.
+;
+; In this test we should inline 'foo'  to 'boo', because it'll fold to a
+; constant.
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define float @foo(float* %a, float %b) {
+entry:
+  %a0 = load float, float* %a, align 4
+  %mul = fmul fast float %a0, %b
+  %tobool = fcmp une float %mul, 0.000000e+00
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %a1 = load float, float* %a, align 8
+  %arrayidx1 = getelementptr inbounds float, float* %a, i64 1
+  %a2 = load float, float* %arrayidx1, align 4
+  %add = fadd fast float %a1, %a2
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %storemerge = phi float [ %add, %if.then ], [ 1.000000e+00, %entry ]
+  ret float %storemerge
+}
+
+; CHECK-LABEL: @boo
+; CHECK-NOT: call float @foo
+define float @boo(float* %a) {
+entry:
+  %call = call float @foo(float* %a, float 0.000000e+00)
+  ret float %call
+}

Added: llvm/trunk/test/Transforms/Inline/inline-funclets.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-funclets.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-funclets.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-funclets.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,676 @@
+; RUN: opt -inline -S %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S %s | FileCheck %s
+
+declare void @g()
+
+
+;;; Test with a call in a funclet that needs to remain a call
+;;; when inlined because the funclet doesn't unwind to caller.
+;;; CHECK-LABEL: define void @test1(
+define void @test1() personality void ()* @g {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test1_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test1_inlinee() alwaysinline personality void ()* @g {
+entry:
+  invoke void @g()
+    to label %exit unwind label %cleanup.inner
+; CHECK-NEXT:  invoke void @g()
+; CHECK-NEXT:    unwind label %[[cleanup_inner:.+]]
+
+cleanup.inner:
+  %pad.inner = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad.inner) ]
+  cleanupret from %pad.inner unwind label %cleanup.outer
+; CHECK: [[cleanup_inner]]:
+; The call here needs to remain a call becuase pad.inner has a cleanupret
+; that stays within the inlinee.
+; CHECK-NEXT:  %[[pad_inner:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT:  call void @g() [ "funclet"(token %[[pad_inner]]) ]
+; CHECK-NEXT:  cleanupret from %[[pad_inner]] unwind label %[[cleanup_outer:.+]]
+
+cleanup.outer:
+  %pad.outer = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad.outer) ]
+  cleanupret from %pad.outer unwind to caller
+; CHECK: [[cleanup_outer]]:
+; The call and cleanupret here need to be redirected to caller cleanup
+; CHECK-NEXT: %[[pad_outer:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[pad_outer]]) ]
+; CHECK-NEXT:   unwind label %cleanup
+; CHECK: cleanupret from %[[pad_outer]] unwind label %cleanup{{$}}
+
+exit:
+  ret void
+}
+
+
+
+;;; Test with an "unwind to caller" catchswitch in a parent funclet
+;;; that needs to remain "unwind to caller" because the parent
+;;; doesn't unwind to caller.
+;;; CHECK-LABEL: define void @test2(
+define void @test2() personality void ()* @g {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test2_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test2_inlinee() alwaysinline personality void ()* @g {
+entry:
+  invoke void @g()
+    to label %exit unwind label %cleanup1
+; CHECK-NEXT:   invoke void @g()
+; CHECK-NEXT:     unwind label %[[cleanup1:.+]]
+
+cleanup1:
+  %outer = cleanuppad within none []
+  invoke void @g() [ "funclet"(token %outer) ]
+    to label %ret1 unwind label %catchswitch
+; CHECK: [[cleanup1]]:
+; CHECK-NEXT: %[[outer:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[outer]]) ]
+; CHECK-NEXT:   unwind label %[[catchswitch:.+]]
+
+catchswitch:
+  %cs = catchswitch within %outer [label %catch] unwind to caller
+; CHECK: [[catchswitch]]:
+; The catchswitch here needs to remain "unwind to caller" since %outer
+; has a cleanupret that remains within the inlinee.
+; CHECK-NEXT: %[[cs:[^ ]+]] = catchswitch within %[[outer]] [label %[[catch:.+]]] unwind to caller
+
+catch:
+  %inner = catchpad within %cs []
+  call void @g() [ "funclet"(token %inner) ]
+  catchret from %inner to label %ret1
+; CHECK: [[catch]]:
+; The call here needs to remain a call since it too is within %outer
+; CHECK:   %[[inner:[^ ]+]] = catchpad within %[[cs]]
+; CHECK-NEXT: call void @g() [ "funclet"(token %[[inner]]) ]
+
+ret1:
+  cleanupret from %outer unwind label %cleanup2
+; CHECK: cleanupret from %[[outer]] unwind label %[[cleanup2:.+]]
+
+cleanup2:
+  %later = cleanuppad within none []
+  cleanupret from %later unwind to caller
+; CHECK: [[cleanup2]]:
+; The cleanupret here needs to get redirected to the caller cleanup
+; CHECK-NEXT: %[[later:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: cleanupret from %[[later]] unwind label %cleanup{{$}}
+
+exit:
+  ret void
+}
+
+
+;;; Test with a call in a cleanup that has no definitive unwind
+;;; destination, that must be rewritten to an invoke.
+;;; CHECK-LABEL: define void @test3(
+define void @test3() personality void ()* @g {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test3_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test3_inlinee() alwaysinline personality void ()* @g {
+entry:
+  invoke void @g()
+    to label %exit unwind label %cleanup
+; CHECK-NEXT:  invoke void @g()
+; CHECK-NEXT:    unwind label %[[cleanup:.+]]
+
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  unreachable
+; CHECK: [[cleanup]]:
+; The call must be rewritten to an invoke targeting the caller cleanup
+; because it may well unwind to there.
+; CHECK-NEXT: %[[pad:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[pad]]) ]
+; CHECK-NEXT:   unwind label %cleanup{{$}}
+
+exit:
+  ret void
+}
+
+
+;;; Test with a catchswitch in a cleanup that has no definitive
+;;; unwind destination, that must be rewritten to unwind to the
+;;; inlined invoke's unwind dest
+;;; CHECK-LABEL: define void @test4(
+define void @test4() personality void ()* @g {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test4_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test4_inlinee() alwaysinline personality void ()* @g {
+entry:
+  invoke void @g()
+    to label %exit unwind label %cleanup
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT:   unwind label %[[cleanup:.+]]
+
+cleanup:
+  %clean = cleanuppad within none []
+  invoke void @g() [ "funclet"(token %clean) ]
+    to label %unreachable unwind label %dispatch
+; CHECK: [[cleanup]]:
+; CHECK-NEXT: %[[clean:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[clean]]) ]
+; CHECK-NEXT:   unwind label %[[dispatch:.+]]
+
+dispatch:
+  %cs = catchswitch within %clean [label %catch] unwind to caller
+; CHECK: [[dispatch]]:
+; The catchswitch must be rewritten to unwind to %cleanup in the caller
+; because it may well unwind to there.
+; CHECK-NEXT: %[[cs:[^ ]+]] = catchswitch within %[[clean]] [label %[[catch:.+]]] unwind label %cleanup{{$}}
+
+catch:
+  catchpad within %cs []
+  br label %unreachable
+unreachable:
+  unreachable
+exit:
+  ret void
+}
+
+
+;;; Test with multiple levels of nesting, and unwind dests
+;;; that need to be inferred from ancestors, descendants,
+;;; and cousins.
+;;; CHECK-LABEL: define void @test5(
+define void @test5() personality void ()* @g {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test5_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test5_inlinee() alwaysinline personality void ()* @g {
+entry:
+  invoke void @g()
+    to label %cont unwind label %noinfo.root
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT:   to label %[[cont:[^ ]+]] unwind label %[[noinfo_root:.+]]
+
+noinfo.root:
+  %noinfo.root.pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %noinfo.root.pad) ]
+  invoke void @g() [ "funclet"(token %noinfo.root.pad) ]
+    to label %noinfo.root.cont unwind label %noinfo.left
+; CHECK: [[noinfo_root]]:
+; Nothing under "noinfo.root" has a definitive unwind destination, so
+; we must assume all of it may actually unwind, and redirect unwinds
+; to the cleanup in the caller.
+; CHECK-NEXT: %[[noinfo_root_pad:[^ ]+]] = cleanuppad within none []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_root_pad]]) ]
+; CHECK-NEXT:   to label %[[next:[^ ]+]] unwind label %cleanup{{$}}
+; CHECK: [[next]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_root_pad]]) ]
+; CHECK-NEXT:   to label %[[noinfo_root_cont:[^ ]+]] unwind label %[[noinfo_left:.+]]
+
+noinfo.left:
+  %noinfo.left.pad = cleanuppad within %noinfo.root.pad []
+  invoke void @g() [ "funclet"(token %noinfo.left.pad) ]
+    to label %unreachable unwind label %noinfo.left.child
+; CHECK: [[noinfo_left]]:
+; CHECK-NEXT: %[[noinfo_left_pad:[^ ]+]] = cleanuppad within %[[noinfo_root_pad]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_left_pad]]) ]
+; CHECK-NEXT:   unwind label %[[noinfo_left_child:.+]]
+
+noinfo.left.child:
+  %noinfo.left.child.cs = catchswitch within %noinfo.left.pad [label %noinfo.left.child.catch] unwind to caller
+; CHECK: [[noinfo_left_child]]:
+; CHECK-NEXT: %[[noinfo_left_child_cs:[^ ]+]] = catchswitch within %[[noinfo_left_pad]] [label %[[noinfo_left_child_catch:[^ ]+]]] unwind label %cleanup{{$}}
+
+noinfo.left.child.catch:
+  %noinfo.left.child.pad = catchpad within %noinfo.left.child.cs []
+  call void @g() [ "funclet"(token %noinfo.left.child.pad) ]
+  br label %unreachable
+; CHECK: [[noinfo_left_child_catch]]:
+; CHECK-NEXT: %[[noinfo_left_child_pad:[^ ]+]] = catchpad within %[[noinfo_left_child_cs]] []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_left_child_pad]]) ]
+; CHECK-NEXT:   unwind label %cleanup{{$}}
+
+noinfo.root.cont:
+  invoke void @g() [ "funclet"(token %noinfo.root.pad) ]
+    to label %unreachable unwind label %noinfo.right
+; CHECK: [[noinfo_root_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_root_pad]]) ]
+; CHECK-NEXT:   unwind label %[[noinfo_right:.+]]
+
+noinfo.right:
+  %noinfo.right.cs = catchswitch within %noinfo.root.pad [label %noinfo.right.catch] unwind to caller
+; CHECK: [[noinfo_right]]:
+; CHECK-NEXT: %[[noinfo_right_cs:[^ ]+]] = catchswitch within %[[noinfo_root_pad]] [label %[[noinfo_right_catch:[^ ]+]]] unwind label %cleanup{{$}}
+
+noinfo.right.catch:
+  %noinfo.right.pad = catchpad within %noinfo.right.cs []
+  invoke void @g() [ "funclet"(token %noinfo.right.pad) ]
+    to label %unreachable unwind label %noinfo.right.child
+; CHECK: [[noinfo_right_catch]]:
+; CHECK-NEXT: %[[noinfo_right_pad:[^ ]+]] = catchpad within %[[noinfo_right_cs]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_right_pad]]) ]
+; CHECK-NEXT:   unwind label %[[noinfo_right_child:.+]]
+
+noinfo.right.child:
+  %noinfo.right.child.pad = cleanuppad within %noinfo.right.pad []
+  call void @g() [ "funclet"(token %noinfo.right.child.pad) ]
+  br label %unreachable
+; CHECK: [[noinfo_right_child]]:
+; CHECK-NEXT: %[[noinfo_right_child_pad:[^ ]+]] = cleanuppad within %[[noinfo_right_pad]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[noinfo_right_child_pad]]) ]
+; CHECK-NEXT:   unwind label %cleanup{{$}}
+
+cont:
+  invoke void @g()
+    to label %exit unwind label %implicit.root
+; CHECK: [[cont]]:
+; CHECK-NEXT: invoke void @g()
+; CHECK-NEXT:   unwind label %[[implicit_root:.+]]
+
+implicit.root:
+  %implicit.root.pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %implicit.root.pad) ]
+  invoke void @g() [ "funclet"(token %implicit.root.pad) ]
+    to label %implicit.root.cont unwind label %implicit.left
+; CHECK: [[implicit_root]]:
+; There's an unwind edge to %internal in implicit.right, and we need to propagate that
+; fact down to implicit.right.grandchild, up to implicit.root, and down to
+; implicit.left.child.catch, leaving all calls and "unwind to caller" catchswitches
+; alone to so they don't conflict with the unwind edge in implicit.right
+; CHECK-NEXT: %[[implicit_root_pad:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: call void @g() [ "funclet"(token %[[implicit_root_pad]]) ]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_root_pad]]) ]
+; CHECK-NEXT:   to label %[[implicit_root_cont:[^ ]+]] unwind label %[[implicit_left:.+]]
+
+implicit.left:
+  %implicit.left.pad = cleanuppad within %implicit.root.pad []
+  invoke void @g() [ "funclet"(token %implicit.left.pad) ]
+    to label %unreachable unwind label %implicit.left.child
+; CHECK: [[implicit_left]]:
+; CHECK-NEXT: %[[implicit_left_pad:[^ ]+]] = cleanuppad within %[[implicit_root_pad:[^ ]+]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_left_pad]]) ]
+; CHECK-NEXT:   unwind label %[[implicit_left_child:.+]]
+
+implicit.left.child:
+  %implicit.left.child.cs = catchswitch within %implicit.left.pad [label %implicit.left.child.catch] unwind to caller
+; CHECK: [[implicit_left_child]]:
+; CHECK-NEXT: %[[implicit_left_child_cs:[^ ]+]] = catchswitch within %[[implicit_left_pad]] [label %[[implicit_left_child_catch:[^ ]+]]] unwind to caller
+
+implicit.left.child.catch:
+  %implicit.left.child.pad = catchpad within %implicit.left.child.cs []
+  call void @g() [ "funclet"(token %implicit.left.child.pad) ]
+  br label %unreachable
+; CHECK: [[implicit_left_child_catch]]:
+; CHECK-NEXT: %[[implicit_left_child_pad:[^ ]+]] = catchpad within %[[implicit_left_child_cs]]
+; CHECK-NEXT: call void @g() [ "funclet"(token %[[implicit_left_child_pad]]) ]
+
+implicit.root.cont:
+  invoke void @g() [ "funclet"(token %implicit.root.pad) ]
+    to label %unreachable unwind label %implicit.right
+; CHECK: [[implicit_root_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_root_pad]]) ]
+; CHECK-NEXT:   unwind label %[[implicit_right:.+]]
+
+implicit.right:
+  %implicit.right.cs = catchswitch within %implicit.root.pad [label %implicit.right.catch] unwind label %internal
+; CHECK: [[implicit_right]]:
+; This is the unwind edge (to %internal) whose existence needs to get propagated around the "implicit" tree
+; CHECK-NEXT: %[[implicit_right_cs:[^ ]+]] = catchswitch within %[[implicit_root_pad]] [label %[[implicit_right_catch:[^ ]+]]] unwind label %[[internal:.+]]
+
+implicit.right.catch:
+  %implicit.right.pad = catchpad within %implicit.right.cs []
+  invoke void @g() [ "funclet"(token %implicit.right.pad) ]
+    to label %unreachable unwind label %implicit.right.child
+; CHECK: [[implicit_right_catch]]:
+; CHECK-NEXT: %[[implicit_right_pad:[^ ]+]] = catchpad within %[[implicit_right_cs]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_right_pad]]) ]
+; CHECK-NEXT:   unwind label %[[implicit_right_child:.+]]
+
+implicit.right.child:
+  %implicit.right.child.pad = cleanuppad within %implicit.right.pad []
+  invoke void @g() [ "funclet"(token %implicit.right.child.pad) ]
+    to label %unreachable unwind label %implicit.right.grandchild
+; CHECK: [[implicit_right_child]]:
+; CHECK-NEXT: %[[implicit_right_child_pad:[^ ]+]] = cleanuppad within %[[implicit_right_pad]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[implicit_right_child_pad]]) ]
+; CHECK-NEXT:   unwind label %[[implicit_right_grandchild:.+]]
+
+implicit.right.grandchild:
+  %implicit.right.grandchild.cs = catchswitch within %implicit.right.child.pad [label %implicit.right.grandchild.catch] unwind to caller
+; CHECK: [[implicit_right_grandchild]]:
+; CHECK-NEXT: %[[implicit_right_grandchild_cs:[^ ]+]] = catchswitch within %[[implicit_right_child_pad]] [label %[[implicit_right_grandchild_catch:[^ ]+]]] unwind to caller
+
+implicit.right.grandchild.catch:
+  %implicit.right.grandhcild.pad = catchpad within %implicit.right.grandchild.cs []
+  call void @g() [ "funclet"(token %implicit.right.grandhcild.pad) ]
+  br label %unreachable
+; CHECK: [[implicit_right_grandchild_catch]]:
+; CHECK-NEXT: %[[implicit_right_grandhcild_pad:[^ ]+]] = catchpad within %[[implicit_right_grandchild_cs]]
+; CHECK-NEXT: call void @g() [ "funclet"(token %[[implicit_right_grandhcild_pad]]) ]
+
+internal:
+  %internal.pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %internal.pad) ]
+  cleanupret from %internal.pad unwind to caller
+; CHECK: [[internal]]:
+; internal is a cleanup with a "return to caller" cleanuppad; that needs to get redirected
+; to %cleanup in the caller, and the call needs to get similarly rewritten to an invoke.
+; CHECK-NEXT: %[[internal_pad:[^ ]+]] = cleanuppad within none
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %internal.pad.i) ]
+; CHECK-NEXT:   to label %[[next:[^ ]+]] unwind label %cleanup{{$}}
+; CHECK: [[next]]:
+; CHECK-NEXT: cleanupret from %[[internal_pad]] unwind label %cleanup{{$}}
+
+unreachable:
+  unreachable
+exit:
+  ret void
+}
+
+;;; Test with funclets that don't have information for themselves, but have
+;;; descendants which unwind to other descendants (left.left unwinds to
+;;; left.right, and right unwinds to far_right).  Make sure that these local
+;;; unwinds don't trip up processing of the ancestor nodes (left and root) that
+;;; ultimately have no information.
+;;; CHECK-LABEL: define void @test6(
+define void @test6() personality void()* @ProcessCLRException {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test6_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test6_inlinee() alwaysinline personality void ()* @ProcessCLRException {
+entry:
+  invoke void @g()
+    to label %exit unwind label %root
+    ; CHECK-NEXT:  invoke void @g()
+    ; CHECK-NEXT:    unwind label %[[root:.+]]
+root:
+  %root.pad = cleanuppad within none []
+  invoke void @g() [ "funclet"(token %root.pad) ]
+    to label %root.cont unwind label %left
+; CHECK: [[root]]:
+; CHECK-NEXT: %[[root_pad:.+]] = cleanuppad within none []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_pad]]) ]
+; CHECK-NEXT:   to label %[[root_cont:.+]] unwind label %[[left:.+]]
+
+left:
+  %left.cs = catchswitch within %root.pad [label %left.catch] unwind to caller
+; CHECK: [[left]]:
+; CHECK-NEXT: %[[left_cs:.+]] = catchswitch within %[[root_pad]] [label %[[left_catch:.+]]] unwind label %cleanup
+
+left.catch:
+  %left.cp = catchpad within %left.cs []
+  call void @g() [ "funclet"(token %left.cp) ]
+  invoke void @g() [ "funclet"(token %left.cp) ]
+    to label %unreach unwind label %left.left
+; CHECK: [[left_catch:.+]]:
+; CHECK-NEXT: %[[left_cp:.+]] = catchpad within %[[left_cs]] []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
+; CHECK-NEXT:   to label %[[lc_cont:.+]] unwind label %cleanup
+; CHECK: [[lc_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
+; CHECK-NEXT:   to label %[[unreach:.+]] unwind label %[[left_left:.+]]
+
+left.left:
+  %ll.pad = cleanuppad within %left.cp []
+  cleanupret from %ll.pad unwind label %left.right
+; CHECK: [[left_left]]:
+; CHECK-NEXT: %[[ll_pad:.+]] = cleanuppad within %[[left_cp]] []
+; CHECK-NEXT: cleanupret from %[[ll_pad]] unwind label %[[left_right:.+]]
+
+left.right:
+  %lr.pad = cleanuppad within %left.cp []
+  unreachable
+; CHECK: [[left_right]]:
+; CHECK-NEXT: %[[lr_pad:.+]] = cleanuppad within %[[left_cp]] []
+; CHECK-NEXT: unreachable
+
+root.cont:
+  call void @g() [ "funclet"(token %root.pad) ]
+  invoke void @g() [ "funclet"(token %root.pad) ]
+    to label %unreach unwind label %right
+; CHECK: [[root_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_pad]]) ]
+; CHECK-NEXT:   to label %[[root_cont_cont:.+]] unwind label %cleanup
+; CHECK: [[root_cont_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_pad]]) ]
+; CHECK-NEXT:   to label %[[unreach]] unwind label %[[right:.+]]
+
+right:
+  %right.pad = cleanuppad within %root.pad []
+  invoke void @g() [ "funclet"(token %right.pad) ]
+    to label %unreach unwind label %right.child
+; CHECK: [[right]]:
+; CHECK-NEXT: %[[right_pad:.+]] = cleanuppad within %[[root_pad]] []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[right_pad]]) ]
+; CHECK-NEXT:   to label %[[unreach]] unwind label %[[right_child:.+]]
+
+right.child:
+  %rc.pad = cleanuppad within %right.pad []
+  invoke void @g() [ "funclet"(token %rc.pad) ]
+    to label %unreach unwind label %far_right
+; CHECK: [[right_child]]:
+; CHECK-NEXT: %[[rc_pad:.+]] = cleanuppad within %[[right_pad]] []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[rc_pad]]) ]
+; CHECK-NEXT:   to label %[[unreach]] unwind label %[[far_right:.+]]
+
+far_right:
+  %fr.cs = catchswitch within %root.pad [label %fr.catch] unwind to caller
+; CHECK: [[far_right]]:
+; CHECK-NEXT: %[[fr_cs:.+]] = catchswitch within %[[root_pad]] [label %[[fr_catch:.+]]] unwind label %cleanup
+
+fr.catch:
+  %fr.cp = catchpad within %fr.cs []
+  unreachable
+; CHECK: [[fr_catch]]:
+; CHECK-NEXT: %[[fr_cp:.+]] = catchpad within %[[fr_cs]] []
+; CHECK-NEXT: unreachable
+
+unreach:
+  unreachable
+; CHECK: [[unreach]]:
+; CHECK-NEXT: unreachable
+
+exit:
+  ret void
+}
+
+
+;;; Test with a no-info funclet (right) which has a cousin (left.left) that
+;;; unwinds to another cousin (left.right); make sure we don't trip over this
+;;; when propagating unwind destination info to "right".
+;;; CHECK-LABEL: define void @test7(
+define void @test7() personality void()* @ProcessCLRException {
+entry:
+; CHECK-NEXT: entry:
+  invoke void @test7_inlinee()
+    to label %exit unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test7_inlinee() alwaysinline personality void ()* @ProcessCLRException {
+entry:
+  invoke void @g()
+    to label %exit unwind label %root
+; CHECK-NEXT:  invoke void @g()
+; CHECK-NEXT:    unwind label %[[root:.+]]
+
+root:
+  %root.cp = cleanuppad within none []
+  invoke void @g() [ "funclet"(token %root.cp) ]
+    to label %root.cont unwind label %child
+; CHECK: [[root]]:
+; CHECK-NEXT: %[[root_cp:.+]] = cleanuppad within none []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[root_cp]]) ]
+; CHECK-NEXT:   to label %[[root_cont:.+]] unwind label %[[child:.+]]
+
+root.cont:
+  cleanupret from %root.cp unwind to caller
+; CHECK: [[root_cont]]:
+; CHECK-NEXT: cleanupret from %[[root_cp]] unwind label %cleanup
+
+child:
+  %child.cp = cleanuppad within %root.cp []
+  invoke void @g() [ "funclet"(token %child.cp) ]
+    to label %child.cont unwind label %left
+; CHECK: [[child]]:
+; CHECK-NEXT: %[[child_cp:.+]] = cleanuppad within %[[root_cp]] []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[child_cp]]) ]
+; CHECK-NEXT:   to label %[[child_cont:.+]] unwind label %[[left:.+]]
+
+left:
+  %left.cp = cleanuppad within %child.cp []
+  invoke void @g() [ "funclet"(token %left.cp) ]
+    to label %left.cont unwind label %left.left
+; CHECK: [[left]]:
+; CHECK-NEXT: %[[left_cp:.+]] = cleanuppad within %[[child_cp]] []
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
+; CHECK-NEXT:   to label %[[left_cont:.+]] unwind label %[[left_left:.+]]
+
+left.left:
+  %ll.cp = cleanuppad within %left.cp []
+  cleanupret from %ll.cp unwind label %left.right
+; CHECK: [[left_left]]:
+; CHECK-NEXT: %[[ll_cp:.+]] = cleanuppad within %[[left_cp]] []
+; CHECK-NEXT: cleanupret from %[[ll_cp]] unwind label %[[left_right:.+]]
+
+left.cont:
+  invoke void @g() [ "funclet"(token %left.cp) ]
+    to label %unreach unwind label %left.right
+; CHECK: [[left_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[left_cp]]) ]
+; CHECK-NEXT:   to label %[[unreach:.+]] unwind label %[[left_right]]
+
+left.right:
+  %lr.cp = cleanuppad within %left.cp []
+  unreachable
+; CHECK: [[left_right]]:
+; CHECK-NEXT: %[[lr_cp:.+]] = cleanuppad within %[[left_cp]] []
+; CHECK-NEXT: unreachable
+
+child.cont:
+  invoke void @g() [ "funclet"(token %child.cp) ]
+    to label %unreach unwind label %right
+; CHECK: [[child_cont]]:
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[child_cp]]) ]
+; CHECK-NEXT:   to label %[[unreach]] unwind label %[[right:.+]]
+
+right:
+  %right.cp = cleanuppad within %child.cp []
+  call void @g() [ "funclet"(token %right.cp) ]
+  unreachable
+; CHECK: [[right]]:
+; CHECK-NEXT: %[[right_cp:.+]] = cleanuppad within %[[child_cp]]
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[right_cp]]) ]
+; CHECK-NEXT:   to label %[[right_cont:.+]] unwind label %cleanup
+; CHECK: [[right_cont]]:
+; CHECK-NEXT: unreachable
+
+unreach:
+  unreachable
+; CHECK: [[unreach]]:
+; CHECK-NEXT: unreachable
+
+exit:
+  ret void
+}
+
+declare void @ProcessCLRException()
+
+; Make sure the logic doesn't get tripped up when the inlined invoke is
+; itself within a funclet in the caller.
+; CHECK-LABEL: define void @test8(
+define void @test8() personality void ()* @ProcessCLRException {
+entry:
+  invoke void @g()
+    to label %exit unwind label %callsite_parent
+callsite_parent:
+  %callsite_parent.pad = cleanuppad within none []
+; CHECK: %callsite_parent.pad = cleanuppad within none
+  invoke void @test8_inlinee() [ "funclet"(token %callsite_parent.pad) ]
+    to label %ret unwind label %cleanup
+ret:
+  cleanupret from %callsite_parent.pad unwind label %cleanup
+cleanup:
+  %pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %pad) ]
+  cleanupret from %pad unwind to caller
+exit:
+  ret void
+}
+
+define void @test8_inlinee() alwaysinline personality void ()* @ProcessCLRException {
+entry:
+  invoke void @g()
+    to label %exit unwind label %inlinee_cleanup
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %callsite_parent.pad) ]
+; CHECK-NEXT:   unwind label %[[inlinee_cleanup:.+]]
+
+inlinee_cleanup:
+  %inlinee.pad = cleanuppad within none []
+  call void @g() [ "funclet"(token %inlinee.pad) ]
+  unreachable
+; CHECK: [[inlinee_cleanup]]:
+; CHECK-NEXT: %[[inlinee_pad:[^ ]+]] = cleanuppad within %callsite_parent.pad
+; CHECK-NEXT: invoke void @g() [ "funclet"(token %[[inlinee_pad]]) ]
+; CHECK-NEXT:   unwind label %cleanup{{$}}
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/inline-hot-callee.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-hot-callee.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-hot-callee.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-hot-callee.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt < %s -inline -inline-threshold=0 -inlinehint-threshold=100 -S | FileCheck %s
+
+; This tests that a hot callee gets the (higher) inlinehint-threshold even
+; without inline hints and gets inlined because the cost is less than
+; inlinehint-threshold. A cold callee with identical body does not get inlined
+; because cost exceeds the inline-threshold. This test is relevant only when the
+; old pass manager is used.
+
+define i32 @callee1(i32 %x) !prof !21 {
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @callee2(i32 %x) !prof !22 {
+; CHECK-LABEL: @callee2(
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @caller2(i32 %y1) !prof !22 {
+; CHECK-LABEL: @caller2(
+; CHECK: call i32 @callee2
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+  %y2 = call i32 @callee2(i32 %y1)
+  %y3 = call i32 @callee1(i32 %y2)
+  ret i32 %y3
+}
+
+declare void @extern()
+
+!llvm.module.flags = !{!1}
+!21 = !{!"function_entry_count", i64 300}
+!22 = !{!"function_entry_count", i64 1}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 1000}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}

Added: llvm/trunk/test/Transforms/Inline/inline-hot-callsite-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-hot-callsite-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-hot-callsite-2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-hot-callsite-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -inline-threshold=0 -inlinehint-threshold=0 -hot-callsite-threshold=100 -S | FileCheck %s
+
+; This tests that a callsite which is determined to be hot based on the caller's
+; entry count and the callsite block frequency gets the hot-callsite-threshold.
+; Another callsite with the same callee that is not hot does not get inlined
+; because cost exceeds the inline-threshold. inlinthint-threshold is set to 0
+; to ensure callee's hotness is not used to boost the threshold.
+
+define i32 @callee1(i32 %x) !prof !21 {
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @caller(i32 %n) !prof !22 {
+; CHECK-LABEL: @caller(
+  %cond = icmp sle i32 %n, 100
+  br i1 %cond, label %cond_true, label %cond_false, !prof !0
+
+cond_true:
+; CHECK-LABEL: cond_true:
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+  %i = call i32 @callee1(i32 %n)
+  ret i32 %i
+cond_false:
+; CHECK-LABEL: cond_false:
+; CHECK: call i32 @callee1
+; CHECK: ret i32 %j
+  %j = call i32 @callee1(i32 %n)
+  ret i32 %j
+}
+declare void @extern()
+
+!0 = !{!"branch_weights", i32 64, i32 4}
+
+!llvm.module.flags = !{!1}
+!21 = !{!"function_entry_count", i64 200}
+!22 = !{!"function_entry_count", i64 200}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 1000}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}

Added: llvm/trunk/test/Transforms/Inline/inline-hot-callsite.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-hot-callsite.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-hot-callsite.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-hot-callsite.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; This tests that a hot callsite gets the (higher) inlinehint-threshold even without
+; without inline hints and gets inlined because the cost is less than
+; inlinehint-threshold. A cold callee with identical body does not get inlined because
+; cost exceeds the inline-threshold
+
+; RUN: opt < %s -inline -inline-threshold=0 -hot-callsite-threshold=100 -S | FileCheck %s
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -inline-threshold=0 -hot-callsite-threshold=100 -S | FileCheck %s
+
+; Run this with the default O2 pipeline to test that profile summary analysis
+; is available during inlining.
+; RUN: opt < %s -passes='default<O2>' -inline-threshold=0 -hot-callsite-threshold=100 -S | FileCheck %s
+
+define i32 @callee1(i32 %x) {
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @callee2(i32 %x) {
+; CHECK-LABEL: @callee2(
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  call void @extern()
+  call void @extern()
+  ret i32 %x3
+}
+
+define i32 @caller2(i32 %y1) {
+; CHECK-LABEL: @caller2(
+; CHECK: call i32 @callee2
+; CHECK-NOT: call i32 @callee1
+; CHECK: ret i32 %x3.i
+  %y2 = call i32 @callee2(i32 %y1), !prof !22
+  %y3 = call i32 @callee1(i32 %y2), !prof !21
+  ret i32 %y3
+}
+
+declare void @extern()
+
+!llvm.module.flags = !{!1}
+!21 = !{!"branch_weights", i64 300}
+!22 = !{!"branch_weights", i64 1}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"SampleProfile"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 1000}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}

Added: llvm/trunk/test/Transforms/Inline/inline-indirect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-indirect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-indirect.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-indirect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -inline -disable-output 2>/dev/null
+; This test used to trigger an assertion in the assumption cache when
+; inlining the indirect call
+declare void @llvm.assume(i1)
+
+define void @foo() {
+  ret void
+}
+
+define void @bar(void ()*) {
+  call void @llvm.assume(i1 true)
+  call void %0();
+  ret void
+}
+
+define void @baz() {
+  call void @bar(void ()* @foo)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/inline-invoke-tail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-invoke-tail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-invoke-tail.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-invoke-tail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -inline -S | not grep "tail call void @llvm.memcpy.p0i8.p0i8.i32"
+; PR3550
+
+define internal void @foo(i32* %p, i32* %q) {
+; CHECK-NOT: @foo
+entry:
+  %pp = bitcast i32* %p to i8*
+  %qq = bitcast i32* %q to i8*
+  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %pp, i8* %qq, i32 4, i1 false)
+  ret void
+}
+
+define i32 @main() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: define i32 @main() personality i32 (...)* @__gxx_personality_v0
+entry:
+  %a = alloca i32
+  %b = alloca i32
+  store i32 1, i32* %a, align 4
+  store i32 0, i32* %b, align 4
+  invoke void @foo(i32* %a, i32* %b)
+      to label %invcont unwind label %lpad
+; CHECK-NOT: invoke
+; CHECK-NOT: @foo
+; CHECK-NOT: tail
+; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32
+; CHECK: br
+
+invcont:
+  %retval = load i32, i32* %a, align 4
+  ret i32 %retval
+
+lpad:
+  %exn = landingpad {i8*, i32}
+         catch i8* null
+  unreachable
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind

Added: llvm/trunk/test/Transforms/Inline/inline-invoke-with-asm-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-invoke-with-asm-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-invoke-with-asm-call.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-invoke-with-asm-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+target triple = "x86_64-apple-darwin"
+
+; In inliner, we assume that inline asm does not throw. This testing case makes
+; sure that the inliner does not convert "call asm" to "invoke asm".
+; rdar://15317907
+; CHECK-LABEL: @caller
+; Make sure we are generating "call asm" instead of "invoke asm".
+; CHECK: call void asm
+; CHECK-LABEL: @callee_with_asm
+define void @caller() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+  br i1 undef, label %1, label %4
+
+; <label>:1
+  invoke void @callee_with_asm()
+          to label %4 unwind label %2
+
+; <label>:2
+  %3 = landingpad { i8*, i32 }
+          cleanup
+  resume { i8*, i32 } undef
+
+; <label>:4
+  ret void
+}
+
+define void @callee_with_asm() {
+  call void asm sideeffect "mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue", ""()
+  ret void
+}
+
+declare i32 @__objc_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/inline-min-legal-vector-width.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-min-legal-vector-width.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-min-legal-vector-width.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-min-legal-vector-width.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt %s -inline -S | FileCheck %s
+
+define internal void @innerSmall() "min-legal-vector-width"="128" {
+  ret void
+}
+
+define internal void @innerLarge() "min-legal-vector-width"="512" {
+  ret void
+}
+
+define internal void @innerNoAttribute() {
+  ret void
+}
+
+; We should not add an attribute during inlining. No attribute means unknown.
+; Inlining doesn't change the fact that we don't know anything about this
+; function.
+define void @outerNoAttribute() {
+  call void @innerLarge()
+  ret void
+}
+
+define void @outerConflictingAttributeSmall() "min-legal-vector-width"="128" {
+  call void @innerLarge()
+  ret void
+}
+
+define void @outerConflictingAttributeLarge() "min-legal-vector-width"="512" {
+  call void @innerSmall()
+  ret void
+}
+
+; We should remove the attribute after inlining since the callee's
+; vector width requirements are unknown.
+define void @outerAttribute() "min-legal-vector-width"="128" {
+  call void @innerNoAttribute()
+  ret void
+}
+
+; CHECK: define void @outerNoAttribute() {
+; CHECK: define void @outerConflictingAttributeSmall() #0
+; CHECK: define void @outerConflictingAttributeLarge() #0
+; CHECK: define void @outerAttribute() {
+; CHECK: attributes #0 = { "min-legal-vector-width"="512" }

Added: llvm/trunk/test/Transforms/Inline/inline-optnone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-optnone.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-optnone.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-optnone.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+
+; Test that functions with attribute optnone are not inlined.
+; Also test that only functions with attribute alwaysinline are
+; valid candidates for inlining if the caller has the optnone attribute.
+
+; Function Attrs: alwaysinline nounwind readnone uwtable
+define i32 @alwaysInlineFunction(i32 %a) #0 {
+entry:
+  %mul = mul i32 %a, %a
+  ret i32 %mul
+}
+
+; Function Attrs: nounwind readnone uwtable
+define i32 @simpleFunction(i32 %a) #1 {
+entry:
+  %add = add i32 %a, %a
+  ret i32 %add
+}
+
+; Function Attrs: nounwind noinline optnone readnone uwtable
+define i32 @OptnoneFunction(i32 %a) #2 {
+entry:
+  %0 = tail call i32 @alwaysInlineFunction(i32 %a)
+  %1 = tail call i32 @simpleFunction(i32 %a)
+  %add = add i32 %0, %1
+  ret i32 %add
+}
+
+; CHECK-LABEL: @OptnoneFunction
+; CHECK-NOT: call i32 @alwaysInlineFunction(i32 %a)
+; CHECK: call i32 @simpleFunction(i32 %a)
+; CHECK: ret
+
+; Function Attrs: nounwind readnone uwtable
+define i32 @bar(i32 %a) #1 {
+entry:
+  %0 = tail call i32 @OptnoneFunction(i32 5)
+  %1 = tail call i32 @simpleFunction(i32 6)
+  %add = add i32 %0, %1
+  ret i32 %add
+}
+
+; CHECK-LABEL: @bar
+; CHECK: call i32 @OptnoneFunction(i32 5)
+; CHECK-NOT: call i32 @simpleFunction(i32 6)
+; CHECK: ret
+
+
+attributes #0 = { alwaysinline nounwind readnone uwtable }
+attributes #1 = { nounwind readnone uwtable }
+attributes #2 = { nounwind noinline optnone readnone uwtable }

Added: llvm/trunk/test/Transforms/Inline/inline-optsize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-optsize.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-optsize.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-optsize.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt -S -Oz < %s | FileCheck %s -check-prefix=OZ
+; RUN: opt -S -O2 < %s | FileCheck %s -check-prefix=O2
+; RUN: opt -S -Os < %s | FileCheck %s -check-prefix=OS
+
+; The inline threshold for a function with the optsize attribute is currently
+; the same as the global inline threshold for -Os. Check that the optsize
+; function attribute doesn't alter the function-specific inline threshold if the
+; global inline threshold is lower (as for -Oz).
+
+ at a = global i32 4
+
+; This function should be larger than the inline threshold for -Oz (25), but
+; smaller than the inline threshold for optsize (75).
+define i32 @inner() {
+  call void @extern()
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %a2 = load volatile i32, i32* @a
+  %x2 = add i32 %x1, %a2
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %a5 = load volatile i32, i32* @a
+  %x5 = add i32 %x3, %a5
+  ret i32 %x5
+}
+
+; @inner() should be inlined for -O2 and -Os but not for -Oz.
+; OZ: call
+; O2-NOT: call
+; OS-NOT: call
+define i32 @outer() optsize {
+   %r = call i32 @inner()
+   ret i32 %r
+}
+
+; @inner() should not be inlined for -O2, -Os and -Oz.
+; OZ: call
+; O2: call
+; OS: call
+define i32 @outer2() minsize {
+   %r = call i32 @inner()
+   ret i32 %r
+}
+
+declare void @extern()
\ No newline at end of file

Added: llvm/trunk/test/Transforms/Inline/inline-probe-stack.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-probe-stack.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-probe-stack.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-probe-stack.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt %s -inline -S | FileCheck %s
+
+define internal void @inner() "probe-stack"="__probestackinner" {
+  ret void
+}
+
+define void @outerNoAttribute() {
+  call void @inner()
+  ret void
+}
+
+define void @outerConflictingAttribute() "probe-stack"="__probestackouter" {
+  call void @inner()
+  ret void
+}
+
+; CHECK: define void @outerNoAttribute() #0
+; CHECK: define void @outerConflictingAttribute() #1
+; CHECK: attributes #0 = { "probe-stack"="__probestackinner" }
+; CHECK: attributes #1 = { "probe-stack"="__probestackouter" }

Added: llvm/trunk/test/Transforms/Inline/inline-remark.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-remark.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-remark.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-remark.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; RUN: opt < %s -inline -inline-remark-attribute --inline-threshold=0 -S | FileCheck %s
+
+; Test that the inliner adds inline remark attributes to non-inlined callsites.
+
+declare void @ext();
+
+define void @foo() {
+  call void @bar(i1 true)
+  ret void
+}
+
+define void @bar(i1 %p) {
+  br i1 %p, label %bb1, label %bb2
+
+bb1:
+  call void @foo()
+  call void @ext()
+  ret void
+
+bb2:
+  call void @bar(i1 true)
+  ret void
+}
+
+;; Test 1 - Add different inline remarks to similar callsites.
+define void @test1() {
+; CHECK-LABEL: @test1
+; CHECK-NEXT: call void @bar(i1 true) [[ATTR1:#[0-9]+]]
+; CHECK-NEXT: call void @bar(i1 false) [[ATTR2:#[0-9]+]]
+  call void @bar(i1 true)
+  call void @bar(i1 false)
+  ret void
+}
+
+define void @noop() {
+  ret void
+}
+
+;; Test 2 - Printed InlineResult messages are followed by InlineCost.
+define void @test2(i8*) {
+; CHECK-LABEL: @test2
+; CHECK-NEXT: call void @noop() [[ATTR3:#[0-9]+]] [ "CUSTOM_OPERAND_BUNDLE"() ]
+; CHECK-NEXT: ret void
+  call void @noop() ; extepected to be inlined
+  call void @noop() [ "CUSTOM_OPERAND_BUNDLE"() ] ; cannot be inlined because of unsupported operand bundle
+  ret void
+}
+
+;; Test 3 - InlineResult messages come from llvm::isInlineViable()
+define void @test3() {
+; CHECK-LABEL: @test3
+; CHECK-NEXT: call void @test3() [[ATTR4:#[0-9]+]]
+; CHECK-NEXT: ret void
+  call void @test3() alwaysinline
+  ret void
+}
+
+; CHECK: attributes [[ATTR1]] = { "inline-remark"="(cost=25, threshold=0)" }
+; CHECK: attributes [[ATTR2]] = { "inline-remark"="(cost=never): recursive" }
+; CHECK: attributes [[ATTR3]] = { "inline-remark"="unsupported operand bundle; (cost={{.*}}, threshold={{.*}})" }
+; CHECK: attributes [[ATTR4]] = { alwaysinline "inline-remark"="(cost=never): recursive call" }

Added: llvm/trunk/test/Transforms/Inline/inline-stack-probe-size.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-stack-probe-size.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-stack-probe-size.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-stack-probe-size.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt %s -inline -S | FileCheck %s
+
+define internal void @innerSmall() "stack-probe-size"="4096" {
+  ret void
+}
+
+define internal void @innerLarge() "stack-probe-size"="8192" {
+  ret void
+}
+
+define void @outerNoAttribute() {
+  call void @innerSmall()
+  ret void
+}
+
+define void @outerConflictingAttributeSmall() "stack-probe-size"="4096" {
+  call void @innerLarge()
+  ret void
+}
+
+define void @outerConflictingAttributeLarge() "stack-probe-size"="8192" {
+  call void @innerSmall()
+  ret void
+}
+
+; CHECK: define void @outerNoAttribute() #0
+; CHECK: define void @outerConflictingAttributeSmall() #0
+; CHECK: define void @outerConflictingAttributeLarge() #0
+; CHECK: attributes #0 = { "stack-probe-size"="4096" }

Added: llvm/trunk/test/Transforms/Inline/inline-tail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-tail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-tail.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-tail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,219 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; We have to apply the less restrictive TailCallKind of the call site being
+; inlined and any call sites cloned into the caller.
+
+; No tail marker after inlining, since test_capture_c captures an alloca.
+; CHECK: define void @test_capture_a(
+; CHECK-NOT: tail
+; CHECK: call void @test_capture_c(
+
+declare void @test_capture_c(i32*)
+define internal void @test_capture_b(i32* %P) {
+  tail call void @test_capture_c(i32* %P)
+  ret void
+}
+define void @test_capture_a() {
+  %A = alloca i32  		; captured by test_capture_b
+  call void @test_capture_b(i32* %A)
+  ret void
+}
+
+; No musttail marker after inlining, since the prototypes don't match.
+; CHECK: define void @test_proto_mismatch_a(
+; CHECK-NOT: musttail
+; CHECK: call void @test_proto_mismatch_c(
+
+declare void @test_proto_mismatch_c(i32*)
+define internal void @test_proto_mismatch_b(i32* %p) {
+  musttail call void @test_proto_mismatch_c(i32* %p)
+  ret void
+}
+define void @test_proto_mismatch_a() {
+  call void @test_proto_mismatch_b(i32* null)
+  ret void
+}
+
+; After inlining through a musttail call site, we need to keep musttail markers
+; to prevent unbounded stack growth.
+; CHECK: define void @test_musttail_basic_a(
+; CHECK: musttail call void @test_musttail_basic_c(
+
+declare void @test_musttail_basic_c(i32* %p)
+define internal void @test_musttail_basic_b(i32* %p) {
+  musttail call void @test_musttail_basic_c(i32* %p)
+  ret void
+}
+define void @test_musttail_basic_a(i32* %p) {
+  musttail call void @test_musttail_basic_b(i32* %p)
+  ret void
+}
+
+; Don't insert lifetime end markers here, the lifetime is trivially over due
+; the return.
+; CHECK: define void @test_byval_a(
+; CHECK: musttail call void @test_byval_c(
+; CHECK-NEXT: ret void
+
+declare void @test_byval_c(i32* byval %p)
+define internal void @test_byval_b(i32* byval %p) {
+  musttail call void @test_byval_c(i32* byval %p)
+  ret void
+}
+define void @test_byval_a(i32* byval %p) {
+  musttail call void @test_byval_b(i32* byval %p)
+  ret void
+}
+
+; Don't insert a stack restore, we're about to return.
+; CHECK: define void @test_dynalloca_a(
+; CHECK: call i8* @llvm.stacksave(
+; CHECK: alloca i8, i32 %n
+; CHECK: musttail call void @test_dynalloca_c(
+; CHECK-NEXT: ret void
+
+declare void @escape(i8* %buf)
+declare void @test_dynalloca_c(i32* byval %p, i32 %n)
+define internal void @test_dynalloca_b(i32* byval %p, i32 %n) alwaysinline {
+  %buf = alloca i8, i32 %n              ; dynamic alloca
+  call void @escape(i8* %buf)           ; escape it
+  musttail call void @test_dynalloca_c(i32* byval %p, i32 %n)
+  ret void
+}
+define void @test_dynalloca_a(i32* byval %p, i32 %n) {
+  musttail call void @test_dynalloca_b(i32* byval %p, i32 %n)
+  ret void
+}
+
+; We can't merge the returns.
+; CHECK: define void @test_multiret_a(
+; CHECK: musttail call void @test_multiret_c(
+; CHECK-NEXT: ret void
+; CHECK: musttail call void @test_multiret_d(
+; CHECK-NEXT: ret void
+
+declare void @test_multiret_c(i1 zeroext %b)
+declare void @test_multiret_d(i1 zeroext %b)
+define internal void @test_multiret_b(i1 zeroext %b) {
+  br i1 %b, label %c, label %d
+c:
+  musttail call void @test_multiret_c(i1 zeroext %b)
+  ret void
+d:
+  musttail call void @test_multiret_d(i1 zeroext %b)
+  ret void
+}
+define void @test_multiret_a(i1 zeroext %b) {
+  musttail call void @test_multiret_b(i1 zeroext %b)
+  ret void
+}
+
+; We have to avoid bitcast chains.
+; CHECK: define i32* @test_retptr_a(
+; CHECK: musttail call i8* @test_retptr_c(
+; CHECK-NEXT: bitcast i8* {{.*}} to i32*
+; CHECK-NEXT: ret i32*
+
+declare i8* @test_retptr_c()
+define internal i16* @test_retptr_b() {
+  %rv = musttail call i8* @test_retptr_c()
+  %v = bitcast i8* %rv to i16*
+  ret i16* %v
+}
+define i32* @test_retptr_a() {
+  %rv = musttail call i16* @test_retptr_b()
+  %v = bitcast i16* %rv to i32*
+  ret i32* %v
+}
+
+; Combine the last two cases: multiple returns with pointer bitcasts.
+; CHECK: define i32* @test_multiptrret_a(
+; CHECK: musttail call i8* @test_multiptrret_c(
+; CHECK-NEXT: bitcast i8* {{.*}} to i32*
+; CHECK-NEXT: ret i32*
+; CHECK: musttail call i8* @test_multiptrret_d(
+; CHECK-NEXT: bitcast i8* {{.*}} to i32*
+; CHECK-NEXT: ret i32*
+
+declare i8* @test_multiptrret_c(i1 zeroext %b)
+declare i8* @test_multiptrret_d(i1 zeroext %b)
+define internal i16* @test_multiptrret_b(i1 zeroext %b) {
+  br i1 %b, label %c, label %d
+c:
+  %c_rv = musttail call i8* @test_multiptrret_c(i1 zeroext %b)
+  %c_v = bitcast i8* %c_rv to i16*
+  ret i16* %c_v
+d:
+  %d_rv = musttail call i8* @test_multiptrret_d(i1 zeroext %b)
+  %d_v = bitcast i8* %d_rv to i16*
+  ret i16* %d_v
+}
+define i32* @test_multiptrret_a(i1 zeroext %b) {
+  %rv = musttail call i16* @test_multiptrret_b(i1 zeroext %b)
+  %v = bitcast i16* %rv to i32*
+  ret i32* %v
+}
+
+; Inline a musttail call site which contains a normal return and a musttail call.
+; CHECK: define i32 @test_mixedret_a(
+; CHECK: br i1 %b
+; CHECK: musttail call i32 @test_mixedret_c(
+; CHECK-NEXT: ret i32
+; CHECK: call i32 @test_mixedret_d(i1 zeroext %b)
+; CHECK: add i32 1,
+; CHECK-NOT: br
+; CHECK: ret i32
+
+declare i32 @test_mixedret_c(i1 zeroext %b)
+declare i32 @test_mixedret_d(i1 zeroext %b)
+define internal i32 @test_mixedret_b(i1 zeroext %b) {
+  br i1 %b, label %c, label %d
+c:
+  %c_rv = musttail call i32 @test_mixedret_c(i1 zeroext %b)
+  ret i32 %c_rv
+d:
+  %d_rv = call i32 @test_mixedret_d(i1 zeroext %b)
+  %d_rv1 = add i32 1, %d_rv
+  ret i32 %d_rv1
+}
+define i32 @test_mixedret_a(i1 zeroext %b) {
+  %rv = musttail call i32 @test_mixedret_b(i1 zeroext %b)
+  ret i32 %rv
+}
+
+declare i32 @donttailcall()
+
+define i32 @notail() {
+  %rv = notail call i32 @donttailcall()
+  ret i32 %rv
+}
+
+; CHECK: @test_notail
+; CHECK: notail call i32 @donttailcall
+; CHECK: ret
+define i32 @test_notail() {
+  %rv = tail call i32 @notail()
+  ret i32 %rv
+}
+
+; PR31014: Inlining a musttail call through a notail call site should remove
+; any tail marking, otherwise we break verifier invariants.
+
+declare void @do_ret(i32)
+
+define void @test_notail_inline_musttail(i32 %a) {
+  notail call void @inline_musttail(i32 %a)
+  musttail call void @do_ret(i32 %a)
+  ret void
+}
+
+define internal void @inline_musttail(i32 %a) {
+  musttail call void @do_ret(i32 %a)
+  ret void
+}
+
+; CHECK-LABEL: define void @test_notail_inline_musttail(i32 %a)
+; CHECK:   {{^ *}}call void @do_ret(i32 %a)
+; CHECK:   musttail call void @do_ret(i32 %a)
+; CHECK:   ret void

Added: llvm/trunk/test/Transforms/Inline/inline-threshold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-threshold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-threshold.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-threshold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,89 @@
+; Test that -inline-threshold overrides thresholds derived from opt levels.
+; RUN: opt < %s -O2 -inline-threshold=500 -S  | FileCheck %s
+; RUN: opt < %s -O3 -inline-threshold=500 -S  | FileCheck %s
+; RUN: opt < %s -Os -inline-threshold=500 -S  | FileCheck %s
+; RUN: opt < %s -Oz -inline-threshold=500 -S  | FileCheck %s
+
+ at a = global i32 4
+
+define i32 @simpleFunction(i32 %a) #0 {
+entry:
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %cmp = icmp eq i32 %a1, 0
+  br i1 %cmp, label %if.then, label %if.else
+if.then:
+  %a2 = load volatile i32, i32* @a
+  %x2_0 = add i32 %x1, %a2
+  br label %if.else
+if.else:
+  %x2 = phi i32 [ %x1, %entry ], [ %x2_0, %if.then ]
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %a5 = load volatile i32, i32* @a
+  %x5 = add i32 %x4, %a5
+  %a6 = load volatile i32, i32* @a
+  %x6 = add i32 %x5, %a6
+  %a7 = load volatile i32, i32* @a
+  %x7 = add i32 %x6, %a7
+  %a8 = load volatile i32, i32* @a
+  %x8 = add i32 %x7, %a8
+  %a9 = load volatile i32, i32* @a
+  %x9 = add i32 %x8, %a9
+  %a10 = load volatile i32, i32* @a
+  %x10 = add i32 %x9, %a10
+  %a11 = load volatile i32, i32* @a
+  %x11 = add i32 %x10, %a11
+  %a12 = load volatile i32, i32* @a
+  %x12 = add i32 %x11, %a12
+  %a13 = load volatile i32, i32* @a
+  %x13 = add i32 %x12, %a13
+  %a14 = load volatile i32, i32* @a
+  %x14 = add i32 %x13, %a14
+  %a15 = load volatile i32, i32* @a
+  %x15 = add i32 %x14, %a15
+  %a16 = load volatile i32, i32* @a
+  %x16 = add i32 %x15, %a16
+  %a17 = load volatile i32, i32* @a
+  %x17 = add i32 %x16, %a17
+  %a18 = load volatile i32, i32* @a
+  %x18 = add i32 %x17, %a18
+  %a19 = load volatile i32, i32* @a
+  %x19 = add i32 %x18, %a19
+  %a20 = load volatile i32, i32* @a
+  %x20 = add i32 %x19, %a20
+  %a21 = load volatile i32, i32* @a
+  %x21 = add i32 %x20, %a21
+  %a22 = load volatile i32, i32* @a
+  %x22 = add i32 %x21, %a22
+  %a23 = load volatile i32, i32* @a
+  %x23 = add i32 %x22, %a23
+  %a24 = load volatile i32, i32* @a
+  %x24 = add i32 %x23, %a24
+  %a25 = load volatile i32, i32* @a
+  %x25 = add i32 %x24, %a25
+  %a26 = load volatile i32, i32* @a
+  %x26 = add i32 %x25, %a26
+  %a27 = load volatile i32, i32* @a
+  %x27 = add i32 %x26, %a27
+  %a28 = load volatile i32, i32* @a
+  %x28 = add i32 %x27, %a28
+  %a29 = load volatile i32, i32* @a
+  %x29 = add i32 %x28, %a29
+  %add = add i32 %x29, %a
+  ret i32 %add
+}
+
+; Function Attrs: nounwind readnone uwtable
+define i32 @bar(i32 %a) #0 {
+; CHECK-LABEL: @bar
+; CHECK-NOT: call i32 @simpleFunction(i32 6)
+; CHECK: ret
+entry:
+  %i = tail call i32 @simpleFunction(i32 6)
+  ret i32 %i
+}
+
+attributes #0 = { nounwind readnone uwtable }

Added: llvm/trunk/test/Transforms/Inline/inline-varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-varargs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-varargs.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-varargs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,120 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline,function(instcombine))' -S | FileCheck %s
+
+declare void @ext_method(i8*, i32)
+declare signext i16 @vararg_fn(...) #0
+declare "cc 9" void @vararg_fn_cc9(i8* %p, ...)
+
+define linkonce_odr void @thunk(i8* %this, ...) {
+  %this_adj = getelementptr i8, i8* %this, i32 4
+  musttail call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* nonnull %this_adj, ...)
+  ret void
+}
+
+define void @thunk_caller(i8* %p) {
+  call void (i8*, ...) @thunk(i8* %p, i32 42)
+  ret void
+}
+; CHECK-LABEL: define void @thunk_caller(i8* %p)
+; CHECK: call void (i8*, ...) bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* nonnull %this_adj.i, i32 42)
+
+define signext i16 @test_callee_2(...) {
+  %res = musttail call signext i16 (...) @vararg_fn(...) #0
+  ret i16 %res
+}
+
+define void @test_caller_2(i8* %p, i8* %q, i16 %r) {
+  call signext i16 (...) @test_callee_2(i8* %p, i8* byval %q, i16 signext %r)
+  ret void
+}
+; CHECK-LABEL: define void @test_caller_2
+; CHECK: call signext i16 (...) @vararg_fn(i8* %p, i8* byval %q, i16 signext %r) [[FN_ATTRS:#[0-9]+]]
+
+define void @test_callee_3(i8* %p, ...) {
+  call signext i16 (...) @vararg_fn()
+  ret void
+}
+
+define void @test_caller_3(i8* %p, i8* %q) {
+  call void (i8*, ...) @test_callee_3(i8* nonnull %p, i8* %q)
+  ret void
+}
+; CHECK-LABEL: define void @test_caller_3
+; CHECK: call signext i16 (...) @vararg_fn()
+
+define void @test_preserve_cc(i8* %p, ...) {
+  musttail call "cc 9" void (i8*, ...) @vararg_fn_cc9(i8* %p, ...)
+  ret void
+}
+
+define void @test_caller_preserve_cc(i8* %p, i8* %q) {
+  call void (i8*, ...) @test_preserve_cc(i8* %p, i8* %q)
+  ret void
+}
+; CHECK-LABEL: define void @test_caller_preserve_cc
+; CHECK: call "cc 9" void (i8*, ...) @vararg_fn_cc9(i8* %p, i8* %q)
+
+define internal i32 @varg_accessed(...) {
+entry:
+  %vargs = alloca i8*, align 8
+  %vargs.ptr = bitcast i8** %vargs to i8*
+  call void @llvm.va_start(i8* %vargs.ptr)
+  %va1 = va_arg i8** %vargs, i32
+  call void @llvm.va_end(i8* %vargs.ptr)
+  ret i32 %va1
+}
+
+define internal i32 @varg_accessed_alwaysinline(...) alwaysinline {
+entry:
+  %vargs = alloca i8*, align 8
+  %vargs.ptr = bitcast i8** %vargs to i8*
+  call void @llvm.va_start(i8* %vargs.ptr)
+  %va1 = va_arg i8** %vargs, i32
+  call void @llvm.va_end(i8* %vargs.ptr)
+  ret i32 %va1
+}
+
+define i32 @call_vargs() {
+  %res1 = call i32 (...) @varg_accessed(i32 10)
+  %res2 = call i32 (...) @varg_accessed_alwaysinline(i32 15)
+  %res = add i32 %res1, %res2
+  ret i32 %res
+}
+; CHECK-LABEL: @call_vargs
+; CHECK: %res1 = call i32 (...) @varg_accessed(i32 10)
+; CHECK-NEXT: %res2 = call i32 (...) @varg_accessed_alwaysinline(i32 15)
+
+define void @caller_with_vastart(i8* noalias nocapture readnone %args, ...) {
+entry:
+  %ap = alloca i8*, align 4
+  %ap.ptr = bitcast i8** %ap to i8*
+  %ap2 = alloca i8*, align 4
+  %ap2.ptr = bitcast i8** %ap to i8*
+  call void @llvm.va_start(i8* nonnull %ap.ptr)
+  call fastcc void @callee_with_vaend(i8* nonnull %ap.ptr)
+  call void @llvm.va_start(i8* nonnull %ap2.ptr)
+  call fastcc void @callee_with_vaend_alwaysinline(i8* nonnull %ap2.ptr)
+  ret void
+}
+
+define internal fastcc void @callee_with_vaend_alwaysinline(i8* %a) alwaysinline {
+entry:
+  tail call void @llvm.va_end(i8* %a)
+  ret void
+}
+
+define internal fastcc void @callee_with_vaend(i8* %a) {
+entry:
+  tail call void @llvm.va_end(i8* %a)
+  ret void
+}
+
+; CHECK-LABEL: @caller_with_vastart
+; CHECK-NOT: @callee_with_vaend
+; CHECK-NOT: @callee_with_vaend_alwaysinline
+
+declare void @llvm.va_start(i8*)
+declare void @llvm.va_end(i8*)
+
+; CHECK: attributes [[FN_ATTRS]] = { "foo"="bar" }
+attributes #0 = { "foo"="bar" }

Added: llvm/trunk/test/Transforms/Inline/inline-vla.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-vla.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-vla.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-vla.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -S -inline %s -o - | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' %s -o - | FileCheck %s
+
+; Check that memcpy2 is completely inlined away.
+; CHECK-NOT: memcpy2
+
+ at .str = private unnamed_addr constant [2 x i8] c"a\00", align 1
+ at .str1 = private unnamed_addr constant [3 x i8] c"ab\00", align 1
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 {
+entry:
+  %data = alloca [2 x i8], align 1
+  %arraydecay = getelementptr inbounds [2 x i8], [2 x i8]* %data, i64 0, i64 0
+  call fastcc void @memcpy2(i8* %arraydecay, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0), i64 1)
+  call fastcc void @memcpy2(i8* %arraydecay, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str1, i64 0, i64 0), i64 2)
+  ret i32 0
+}
+
+; Function Attrs: inlinehint nounwind ssp uwtable
+define internal fastcc void @memcpy2(i8* nocapture %dst, i8* nocapture readonly %src, i64 %size) #1 {
+entry:
+  %vla = alloca i64, i64 %size, align 16
+  %0 = bitcast i64* %vla to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %src, i64 %size, i1 false)
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %0, i64 %size, i1 false)
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) #2
+
+attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { inlinehint nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.5.0 (trunk 205695) (llvm/trunk 205706)"}

Added: llvm/trunk/test/Transforms/Inline/inline_cleanup.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_cleanup.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_cleanup.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_cleanup.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,214 @@
+; Test that the inliner doesn't leave around dead allocas, and that it folds
+; uncond branches away after it is done specializing.
+
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+ at A = weak global i32 0		; <i32*> [#uses=1]
+ at B = weak global i32 0		; <i32*> [#uses=1]
+ at C = weak global i32 0		; <i32*> [#uses=1]
+
+define internal fastcc void @foo(i32 %X) {
+entry:
+	%ALL = alloca i32, align 4		; <i32*> [#uses=1]
+	%tmp1 = and i32 %X, 1		; <i32> [#uses=1]
+	%tmp1.upgrd.1 = icmp eq i32 %tmp1, 0		; <i1> [#uses=1]
+	br i1 %tmp1.upgrd.1, label %cond_next, label %cond_true
+
+cond_true:		; preds = %entry
+	store i32 1, i32* @A
+	br label %cond_next
+
+cond_next:		; preds = %cond_true, %entry
+	%tmp4 = and i32 %X, 2		; <i32> [#uses=1]
+	%tmp4.upgrd.2 = icmp eq i32 %tmp4, 0		; <i1> [#uses=1]
+	br i1 %tmp4.upgrd.2, label %cond_next7, label %cond_true5
+
+cond_true5:		; preds = %cond_next
+	store i32 1, i32* @B
+	br label %cond_next7
+
+cond_next7:		; preds = %cond_true5, %cond_next
+	%tmp10 = and i32 %X, 4		; <i32> [#uses=1]
+	%tmp10.upgrd.3 = icmp eq i32 %tmp10, 0		; <i1> [#uses=1]
+	br i1 %tmp10.upgrd.3, label %cond_next13, label %cond_true11
+
+cond_true11:		; preds = %cond_next7
+	store i32 1, i32* @C
+	br label %cond_next13
+
+cond_next13:		; preds = %cond_true11, %cond_next7
+	%tmp16 = and i32 %X, 8		; <i32> [#uses=1]
+	%tmp16.upgrd.4 = icmp eq i32 %tmp16, 0		; <i1> [#uses=1]
+	br i1 %tmp16.upgrd.4, label %UnifiedReturnBlock, label %cond_true17
+
+cond_true17:		; preds = %cond_next13
+	call void @ext( i32* %ALL )
+	ret void
+
+UnifiedReturnBlock:		; preds = %cond_next13
+	ret void
+}
+
+declare void @ext(i32*)
+
+define void @test() {
+; CHECK-LABEL: @test(
+; CHECK-NOT: ret
+;
+; FIXME: This should be a CHECK-NOT, but currently we have a bug that causes us
+; to not nuke unused allocas.
+; CHECK: alloca
+; CHECK-NOT: ret
+;
+; No branches should survive the inliner's cleanup.
+; CHECK-NOT: br
+; CHECK: ret void
+
+entry:
+	tail call fastcc void @foo( i32 1 )
+	tail call fastcc void @foo( i32 2 )
+	tail call fastcc void @foo( i32 3 )
+	tail call fastcc void @foo( i32 8 )
+	ret void
+}
+
+declare void @f(i32 %x)
+
+define void @inner2(i32 %x, i32 %y, i32 %z, i1 %b) {
+entry:
+  %cmp1 = icmp ne i32 %x, 0
+  br i1 %cmp1, label %then1, label %end1
+
+then1:
+  call void @f(i32 %x)
+  br label %end1
+
+end1:
+  %x2 = and i32 %x, %z
+  %cmp2 = icmp sgt i32 %x2, 1
+  br i1 %cmp2, label %then2, label %end2
+
+then2:
+  call void @f(i32 %x2)
+  br label %end2
+
+end2:
+  %y2 = or i32 %y, %z
+  %cmp3 = icmp sgt i32 %y2, 0
+  br i1 %cmp3, label %then3, label %end3
+
+then3:
+  call void @f(i32 %y2)
+  br label %end3
+
+end3:
+  br i1 %b, label %end3.1, label %end3.2
+
+end3.1:
+  %x3.1 = or i32 %x, 10
+  br label %end3.3
+
+end3.2:
+  %x3.2 = or i32 %x, 10
+  br label %end3.3
+
+end3.3:
+  %x3.3 = phi i32 [ %x3.1, %end3.1 ], [ %x3.2, %end3.2 ]
+  %cmp4 = icmp slt i32 %x3.3, 1
+  br i1 %cmp4, label %then4, label %end4
+
+then4:
+  call void @f(i32 %x3.3)
+  br label %end4
+
+end4:
+  ret void
+}
+
+define void @outer2(i32 %z, i1 %b) {
+; Ensure that after inlining, none of the blocks with a call to @f actually
+; make it through inlining.
+; CHECK-LABEL: define void @outer2(
+; CHECK-NOT: call
+; CHECK: ret void
+
+entry:
+  call void @inner2(i32 0, i32 -1, i32 %z, i1 %b)
+  ret void
+}
+
+define void @PR12470_inner(i16 signext %p1) nounwind uwtable {
+entry:
+  br i1 undef, label %cond.true, label %cond.false
+
+cond.true:
+  br label %cond.end
+
+cond.false:
+  %conv = sext i16 %p1 to i32
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ undef, %cond.true ], [ 0, %cond.false ]
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %if.end5, label %if.then
+
+if.then:
+  ret void
+
+if.end5:
+  ret void
+}
+
+define void @PR12470_outer() {
+; This previously crashed during inliner cleanup and folding inner return
+; instructions. Check that we don't crash and we produce a function with a single
+; return instruction due to merging the returns of the inlined function.
+; CHECK-LABEL: define void @PR12470_outer(
+; CHECK-NOT: call
+; CHECK: ret void
+; CHECK-NOT: ret void
+; CHECK: }
+
+entry:
+  call void @PR12470_inner(i16 signext 1)
+  ret void
+}
+
+define void @crasher_inner() nounwind uwtable {
+entry:
+  br i1 false, label %for.end28, label %for.body6
+
+for.body6:
+  br i1 undef, label %for.body6, label %for.cond12.for.inc26_crit_edge
+
+for.cond12.for.inc26_crit_edge:
+  br label %for.body6.1
+
+for.end28:
+  ret void
+
+for.body6.1:
+  br i1 undef, label %for.body6.1, label %for.cond12.for.inc26_crit_edge.1
+
+for.cond12.for.inc26_crit_edge.1:
+  br label %for.body6.2
+
+for.body6.2:
+  br i1 undef, label %for.body6.2, label %for.cond12.for.inc26_crit_edge.2
+
+for.cond12.for.inc26_crit_edge.2:
+  br label %for.end28
+}
+
+define void @crasher_outer() {
+; CHECK-LABEL: @crasher_outer(
+; CHECK-NOT: call
+; CHECK: ret void
+; CHECK-NOT: ret
+; CHECK: }
+entry:
+  tail call void @crasher_inner()
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/inline_constprop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_constprop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_constprop.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_constprop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,347 @@
+; RUN: opt < %s -inline -inline-threshold=20 -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S | FileCheck %s
+
+define internal i32 @callee1(i32 %A, i32 %B) {
+  %C = sdiv i32 %A, %B
+  ret i32 %C
+}
+
+define i32 @caller1() {
+; CHECK-LABEL: define i32 @caller1(
+; CHECK-NEXT: ret i32 3
+
+  %X = call i32 @callee1( i32 10, i32 3 )
+  ret i32 %X
+}
+
+define i32 @caller2() {
+; Check that we can constant-prop through instructions after inlining callee21
+; to get constants in the inlined callsite to callee22.
+; FIXME: Currently, the threshold is fixed at 20 because we don't perform
+; *recursive* cost analysis to realize that the nested call site will definitely
+; inline and be cheap. We should eventually do that and lower the threshold here
+; to 1.
+;
+; CHECK-LABEL: @caller2(
+; CHECK-NOT: call void @callee2
+; CHECK: ret
+
+  %x = call i32 @callee21(i32 42, i32 48)
+  ret i32 %x
+}
+
+define i32 @callee21(i32 %x, i32 %y) {
+  %sub = sub i32 %y, %x
+  %result = call i32 @callee22(i32 %sub)
+  ret i32 %result
+}
+
+declare i8* @getptr()
+
+define i32 @callee22(i32 %x) {
+  %icmp = icmp ugt i32 %x, 42
+  br i1 %icmp, label %bb.true, label %bb.false
+bb.true:
+  ; This block musn't be counted in the inline cost.
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  %x4 = add i32 %x3, 1
+  %x5 = add i32 %x4, 1
+  %x6 = add i32 %x5, 1
+  %x7 = add i32 %x6, 1
+  %x8 = add i32 %x7, 1
+
+  ret i32 %x8
+bb.false:
+  ret i32 %x
+}
+
+define i32 @caller3() {
+; Check that even if the expensive path is hidden behind several basic blocks,
+; it doesn't count toward the inline cost when constant-prop proves those paths
+; dead.
+;
+; CHECK-LABEL: @caller3(
+; CHECK-NOT: call
+; CHECK: ret i32 6
+
+entry:
+  %x = call i32 @callee3(i32 42, i32 48)
+  ret i32 %x
+}
+
+define i32 @callee3(i32 %x, i32 %y) {
+  %sub = sub i32 %y, %x
+  %icmp = icmp ugt i32 %sub, 42
+  br i1 %icmp, label %bb.true, label %bb.false
+
+bb.true:
+  %icmp2 = icmp ult i32 %sub, 64
+  br i1 %icmp2, label %bb.true.true, label %bb.true.false
+
+bb.true.true:
+  ; This block musn't be counted in the inline cost.
+  %x1 = add i32 %x, 1
+  %x2 = add i32 %x1, 1
+  %x3 = add i32 %x2, 1
+  %x4 = add i32 %x3, 1
+  %x5 = add i32 %x4, 1
+  %x6 = add i32 %x5, 1
+  %x7 = add i32 %x6, 1
+  %x8 = add i32 %x7, 1
+  br label %bb.merge
+
+bb.true.false:
+  ; This block musn't be counted in the inline cost.
+  %y1 = add i32 %y, 1
+  %y2 = add i32 %y1, 1
+  %y3 = add i32 %y2, 1
+  %y4 = add i32 %y3, 1
+  %y5 = add i32 %y4, 1
+  %y6 = add i32 %y5, 1
+  %y7 = add i32 %y6, 1
+  %y8 = add i32 %y7, 1
+  br label %bb.merge
+
+bb.merge:
+  %result = phi i32 [ %x8, %bb.true.true ], [ %y8, %bb.true.false ]
+  ret i32 %result
+
+bb.false:
+  ret i32 %sub
+}
+
+declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b)
+
+define i8 @caller4(i8 %z) {
+; Check that we can constant fold through intrinsics such as the
+; overflow-detecting arithmetic instrinsics. These are particularly important
+; as they are used heavily in standard library code and generic C++ code where
+; the arguments are oftent constant but complete generality is required.
+;
+; CHECK-LABEL: @caller4(
+; CHECK-NOT: call
+; CHECK: ret i8 -1
+
+entry:
+  %x = call i8 @callee4(i8 254, i8 14, i8 %z)
+  ret i8 %x
+}
+
+define i8 @callee4(i8 %x, i8 %y, i8 %z) {
+  %uadd = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %x, i8 %y)
+  %o = extractvalue {i8, i1} %uadd, 1
+  br i1 %o, label %bb.true, label %bb.false
+
+bb.true:
+  ret i8 -1
+
+bb.false:
+  ; This block musn't be counted in the inline cost.
+  %z1 = add i8 %z, 1
+  %z2 = add i8 %z1, 1
+  %z3 = add i8 %z2, 1
+  %z4 = add i8 %z3, 1
+  %z5 = add i8 %z4, 1
+  %z6 = add i8 %z5, 1
+  %z7 = add i8 %z6, 1
+  %z8 = add i8 %z7, 1
+  ret i8 %z8
+}
+
+define i64 @caller5(i64 %y) {
+; Check that we can round trip constants through various kinds of casts etc w/o
+; losing track of the constant prop in the inline cost analysis.
+;
+; CHECK-LABEL: @caller5(
+; CHECK-NOT: call
+; CHECK: ret i64 -1
+
+entry:
+  %x = call i64 @callee5(i64 42, i64 %y)
+  ret i64 %x
+}
+
+define i64 @callee5(i64 %x, i64 %y) {
+  %inttoptr = inttoptr i64 %x to i8*
+  %bitcast = bitcast i8* %inttoptr to i32*
+  %ptrtoint = ptrtoint i32* %bitcast to i64
+  %trunc = trunc i64 %ptrtoint to i32
+  %zext = zext i32 %trunc to i64
+  %cmp = icmp eq i64 %zext, 42
+  br i1 %cmp, label %bb.true, label %bb.false
+
+bb.true:
+  ret i64 -1
+
+bb.false:
+  ; This block musn't be counted in the inline cost.
+  %y1 = add i64 %y, 1
+  %y2 = add i64 %y1, 1
+  %y3 = add i64 %y2, 1
+  %y4 = add i64 %y3, 1
+  %y5 = add i64 %y4, 1
+  %y6 = add i64 %y5, 1
+  %y7 = add i64 %y6, 1
+  %y8 = add i64 %y7, 1
+  ret i64 %y8
+}
+
+define float @caller6() {
+; Check that we can constant-prop through fcmp instructions
+;
+; CHECK-LABEL: @caller6(
+; CHECK-NOT: call
+; CHECK: ret
+  %x = call float @callee6(float 42.0)
+  ret float %x
+}
+
+define float @callee6(float %x) {
+  %icmp = fcmp ugt float %x, 42.0
+  br i1 %icmp, label %bb.true, label %bb.false
+
+bb.true:
+  ; This block musn't be counted in the inline cost.
+  %x1 = fadd float %x, 1.0
+  %x2 = fadd float %x1, 1.0
+  %x3 = fadd float %x2, 1.0
+  %x4 = fadd float %x3, 1.0
+  %x5 = fadd float %x4, 1.0
+  %x6 = fadd float %x5, 1.0
+  %x7 = fadd float %x6, 1.0
+  %x8 = fadd float %x7, 1.0
+  ret float %x8
+
+bb.false:
+  ret float %x
+}
+
+
+
+define i32 @PR13412.main() {
+; This is a somewhat complicated three layer subprogram that was reported to
+; compute the wrong value for a branch due to assuming that an argument
+; mid-inline couldn't be equal to another pointer.
+;
+; After inlining, the branch should point directly to the exit block, not to
+; the intermediate block.
+; CHECK: @PR13412.main
+; CHECK: br i1 true, label %[[TRUE_DEST:.*]], label %[[FALSE_DEST:.*]]
+; CHECK: [[FALSE_DEST]]:
+; CHECK-NEXT: call void @PR13412.fail()
+; CHECK: [[TRUE_DEST]]:
+; CHECK-NEXT: ret i32 0
+
+entry:
+  %i1 = alloca i64
+  store i64 0, i64* %i1
+  %arraydecay = bitcast i64* %i1 to i32*
+  %call = call i1 @PR13412.first(i32* %arraydecay, i32* %arraydecay)
+  br i1 %call, label %cond.end, label %cond.false
+
+cond.false:
+  call void @PR13412.fail()
+  br label %cond.end
+
+cond.end:
+  ret i32 0
+}
+
+define internal i1 @PR13412.first(i32* %a, i32* %b) {
+entry:
+  %call = call i32* @PR13412.second(i32* %a, i32* %b)
+  %cmp = icmp eq i32* %call, %b
+  ret i1 %cmp
+}
+
+declare void @PR13412.fail()
+
+define internal i32* @PR13412.second(i32* %a, i32* %b) {
+entry:
+  %sub.ptr.lhs.cast = ptrtoint i32* %b to i64
+  %sub.ptr.rhs.cast = ptrtoint i32* %a to i64
+  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  %sub.ptr.div = ashr exact i64 %sub.ptr.sub, 2
+  %cmp = icmp ugt i64 %sub.ptr.div, 1
+  br i1 %cmp, label %if.then, label %if.end3
+
+if.then:
+  %0 = load i32, i32* %a
+  %1 = load i32, i32* %b
+  %cmp1 = icmp eq i32 %0, %1
+  br i1 %cmp1, label %return, label %if.end3
+
+if.end3:
+  br label %return
+
+return:
+  %retval.0 = phi i32* [ %b, %if.end3 ], [ %a, %if.then ]
+  ret i32* %retval.0
+}
+
+declare i32 @PR28802.external(i32 returned %p1)
+
+define internal i32 @PR28802.callee() {
+entry:
+  br label %cont
+
+cont:
+  %0 = phi i32 [ 0, %entry ]
+  %call = call i32 @PR28802.external(i32 %0)
+  ret i32 %call
+}
+
+define i32 @PR28802() {
+entry:
+  %call = call i32 @PR28802.callee()
+  ret i32 %call
+}
+
+; CHECK-LABEL: define i32 @PR28802(
+; CHECK: %[[call:.*]] = call i32 @PR28802.external(i32 0)
+; CHECK: ret i32 %[[call]]
+
+define internal i32 @PR28848.callee(i32 %p2, i1 %c) {
+entry:
+  br i1 %c, label %cond.end, label %cond.true
+
+cond.true:
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ 0, %cond.true ], [ %p2, %entry ]
+  %or = or i32 %cond, %p2
+  ret i32 %or
+}
+
+define i32 @PR28848() {
+entry:
+  %call = call i32 @PR28848.callee(i32 0, i1 false)
+  ret i32 %call
+}
+; CHECK-LABEL: define i32 @PR28848(
+; CHECK: ret i32 0
+
+define internal void @callee7(i16 %param1, i16 %param2) {
+entry:
+  br label %bb
+
+bb:
+  %phi = phi i16 [ %param2, %entry ]
+  %add = add i16 %phi, %param1
+  ret void
+}
+
+declare i16 @caller7.external(i16 returned)
+
+define void @caller7() {
+bb1:
+  %call = call i16 @caller7.external(i16 1)
+  call void @callee7(i16 0, i16 %call)
+  ret void
+}
+; CHECK-LABEL: define void @caller7(
+; CHECK: %call = call i16 @caller7.external(i16 1)
+; CHECK-NEXT: ret void

Added: llvm/trunk/test/Transforms/Inline/inline_dbg_declare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_dbg_declare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_dbg_declare.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_dbg_declare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,99 @@
+; RUN: opt < %s -S -inline | FileCheck %s
+; RUN: opt < %s -S -passes='cgscc(inline)' | FileCheck %s
+;
+; The purpose of this test is to check that inline pass preserves debug info
+; for variable using the dbg.declare intrinsic.
+;
+;; This test was generated by running this command:
+;; clang.exe -S -O0 -emit-llvm -g foo.c
+;;
+;; foo.c
+;; ==========================
+;; float foo(float x)
+;; {
+;;    return x;
+;; }
+;;
+;; void bar(float *dst)
+;; {
+;;    dst[0] = foo(dst[0]);
+;; }
+;; ==========================
+
+target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
+target triple = "i686-pc-windows-msvc"
+
+; Function Attrs: nounwind
+define float @foo(float %x) #0 !dbg !4 {
+entry:
+  %x.addr = alloca float, align 4
+  store float %x, float* %x.addr, align 4
+  call void @llvm.dbg.declare(metadata float* %x.addr, metadata !16, metadata !17), !dbg !18
+  %0 = load float, float* %x.addr, align 4, !dbg !19
+  ret float %0, !dbg !19
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; CHECK: define void @bar
+
+; Function Attrs: nounwind
+define void @bar(float* %dst) #0 !dbg !9 {
+entry:
+
+; CHECK: [[x_addr_i:%[a-zA-Z0-9.]+]] = alloca float, align 4
+; CHECK-NEXT: void @llvm.dbg.declare(metadata float* [[x_addr_i]], metadata [[m23:![0-9]+]], metadata !DIExpression()), !dbg [[m24:![0-9]+]]
+
+  %dst.addr = alloca float*, align 4
+  store float* %dst, float** %dst.addr, align 4
+  call void @llvm.dbg.declare(metadata float** %dst.addr, metadata !20, metadata !17), !dbg !21
+  %0 = load float*, float** %dst.addr, align 4, !dbg !22
+  %arrayidx = getelementptr inbounds float, float* %0, i32 0, !dbg !22
+  %1 = load float, float* %arrayidx, align 4, !dbg !22
+  %call = call float @foo(float %1), !dbg !22
+
+; CHECK-NOT: call float @foo
+
+  %2 = load float*, float** %dst.addr, align 4, !dbg !22
+  %arrayidx1 = getelementptr inbounds float, float* %2, i32 0, !dbg !22
+  store float %call, float* %arrayidx1, align 4, !dbg !22
+  ret void, !dbg !23
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!13, !14}
+!llvm.ident = !{!15}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.6.0 (trunk)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+!1 = !DIFile(filename: "foo.c", directory: "")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!5 = !DIFile(filename: "foo.c", directory: "")
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8, !8}
+!8 = !DIBasicType(tag: DW_TAG_base_type, name: "float", size: 32, align: 32, encoding: DW_ATE_float)
+!9 = distinct !DISubprogram(name: "bar", line: 6, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 7, file: !1, scope: !5, type: !10, retainedNodes: !2)
+!10 = !DISubroutineType(types: !11)
+!11 = !{null, !12}
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 32, align: 32, baseType: !8)
+!13 = !{i32 2, !"Dwarf Version", i32 4}
+!14 = !{i32 2, !"Debug Info Version", i32 3}
+!15 = !{!"clang version 3.6.0 (trunk)"}
+!16 = !DILocalVariable(name: "x", line: 1, arg: 1, scope: !4, file: !5, type: !8)
+!17 = !DIExpression()
+!18 = !DILocation(line: 1, column: 17, scope: !4)
+!19 = !DILocation(line: 3, column: 5, scope: !4)
+!20 = !DILocalVariable(name: "dst", line: 6, arg: 1, scope: !9, file: !5, type: !12)
+!21 = !DILocation(line: 6, column: 17, scope: !9)
+!22 = !DILocation(line: 8, column: 14, scope: !9)
+!23 = !DILocation(line: 9, column: 1, scope: !9)
+
+; CHECK: [[FOO:![0-9]+]] = distinct !DISubprogram(name: "foo",
+; CHECK: [[m23]] = !DILocalVariable(name: "x", arg: 1, scope: [[FOO]]
+; CHECK: [[BAR:![0-9]+]] = distinct !DISubprogram(name: "bar",
+; CHECK: [[m24]] = !DILocation(line: 1, column: 17, scope: [[FOO]], inlinedAt: [[CALL_SITE:![0-9]+]])
+; CHECK: [[CALL_SITE]] = distinct !DILocation(line: 8, column: 14, scope: [[BAR]])

Added: llvm/trunk/test/Transforms/Inline/inline_dce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_dce.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_dce.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_dce.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; This checks to ensure that the inline pass deletes functions if they get 
+; inlined into all of their callers.
+
+; RUN: opt < %s -inline -S | \
+; RUN:   not grep @reallysmall
+
+define internal i32 @reallysmall(i32 %A) {
+; CHECK-NOT: @reallysmall
+entry:
+  ret i32 %A
+}
+
+define void @caller1() {
+; CHECK-LABEL: define void @caller1()
+entry:
+  call i32 @reallysmall(i32 5)
+; CHECK-NOT: call
+  ret void
+}
+
+define void @caller2(i32 %A) {
+; CHECK-LABEL: define void @caller2(i32 %A)
+entry:
+  call i32 @reallysmall(i32 %A)
+; CHECK-NOT: call
+  ret void
+}
+
+define i32 @caller3(i32 %A) {
+; CHECK-LABEL: define void @caller3(i32 %A)
+entry:
+  %B = call i32 @reallysmall(i32 %A)
+; CHECK-NOT: call
+  ret i32 %B
+}
+

Added: llvm/trunk/test/Transforms/Inline/inline_inv_group.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_inv_group.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_inv_group.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_inv_group.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -inline -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 i8* @callee() alwaysinline {
+; CHECK-LABEL: define i8* @callee()
+    %1 = call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+    ret i8* %1
+}
+
+define i8* @caller() {
+; CHECK-LABEL: define i8* @caller()
+; CHECK-NEXT: call i8* @llvm.strip.invariant.group.p0i8(i8* null)
+    %1 = call i8* @callee()
+    ret i8* %1
+}
+
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)

Added: llvm/trunk/test/Transforms/Inline/inline_invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_invoke.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_invoke.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_invoke.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,349 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; Test that the inliner correctly handles inlining into invoke sites
+; by appending selectors and forwarding _Unwind_Resume directly to the
+; enclosing landing pad.
+
+;; Test 0 - basic functionality.
+
+%struct.A = type { i8 }
+
+ at _ZTIi = external constant i8*
+
+declare void @_ZN1AC1Ev(%struct.A*)
+
+declare void @_ZN1AD1Ev(%struct.A*)
+
+declare void @use(i32) nounwind
+
+declare void @opaque()
+
+declare i32 @llvm.eh.typeid.for(i8*) nounwind
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()
+
+declare void @_ZSt9terminatev()
+
+define internal void @test0_in() alwaysinline uwtable ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  %a = alloca %struct.A, align 1
+  %b = alloca %struct.A, align 1
+  call void @_ZN1AC1Ev(%struct.A* %a)
+  invoke void @_ZN1AC1Ev(%struct.A* %b)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  invoke void @_ZN1AD1Ev(%struct.A* %b)
+          to label %invoke.cont1 unwind label %lpad
+
+invoke.cont1:
+  call void @_ZN1AD1Ev(%struct.A* %a)
+  ret void
+
+lpad:
+  %exn = landingpad {i8*, i32}
+            cleanup
+  invoke void @_ZN1AD1Ev(%struct.A* %a)
+          to label %invoke.cont2 unwind label %terminate.lpad
+
+invoke.cont2:
+  resume { i8*, i32 } %exn
+
+terminate.lpad:
+  %exn1 = landingpad {i8*, i32}
+            catch i8* null
+  call void @_ZSt9terminatev() noreturn nounwind
+  unreachable
+}
+
+define void @test0_out() uwtable ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @test0_in()
+          to label %ret unwind label %lpad
+
+ret:
+  ret void
+
+lpad:                                             ; preds = %entry
+  %exn = landingpad {i8*, i32}
+            catch i8* bitcast (i8** @_ZTIi to i8*)
+  %eh.exc = extractvalue { i8*, i32 } %exn, 0
+  %eh.selector = extractvalue { i8*, i32 } %exn, 1
+  %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
+  %1 = icmp eq i32 %eh.selector, %0
+  br i1 %1, label %catch, label %eh.resume
+
+catch:
+  %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
+  call void @__cxa_end_catch() nounwind
+  br label %ret
+
+eh.resume:
+  resume { i8*, i32 } %exn
+}
+
+; CHECK:    define void @test0_out()
+; CHECK:      [[A:%.*]] = alloca %struct.A,
+; CHECK:      [[B:%.*]] = alloca %struct.A,
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A]])
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B]])
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B]])
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A]])
+; CHECK:      landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A]])
+; CHECK-NEXT:   to label %[[LBL:[^\s]+]] unwind
+; CHECK: [[LBL]]:
+; CHECK-NEXT: br label %[[LPAD:[^\s]+]]
+; CHECK:      ret void
+; CHECK:      landingpad { i8*, i32 }
+; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: br label %[[LPAD]]
+; CHECK: [[LPAD]]:
+; CHECK-NEXT: phi { i8*, i32 } [
+; CHECK-NEXT: extractvalue { i8*, i32 }
+; CHECK-NEXT: extractvalue { i8*, i32 }
+; CHECK-NEXT: call i32 @llvm.eh.typeid.for(
+
+
+;; Test 1 - Correctly handle phis in outer landing pads.
+
+define void @test1_out() uwtable ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @test0_in()
+          to label %cont unwind label %lpad
+
+cont:
+  invoke void @test0_in()
+          to label %ret unwind label %lpad
+
+ret:
+  ret void
+
+lpad:
+  %x = phi i32 [ 0, %entry ], [ 1, %cont ]
+  %y = phi i32 [ 1, %entry ], [ 4, %cont ]
+  %exn = landingpad {i8*, i32}
+            catch i8* bitcast (i8** @_ZTIi to i8*)
+  %eh.exc = extractvalue { i8*, i32 } %exn, 0
+  %eh.selector = extractvalue { i8*, i32 } %exn, 1
+  %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
+  %1 = icmp eq i32 %eh.selector, %0
+  br i1 %1, label %catch, label %eh.resume
+
+catch:
+  %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
+  call void @use(i32 %x)
+  call void @use(i32 %y)
+  call void @__cxa_end_catch() nounwind
+  br label %ret
+
+eh.resume:
+  resume { i8*, i32 } %exn
+}
+
+; CHECK:    define void @test1_out()
+; CHECK:      [[A2:%.*]] = alloca %struct.A,
+; CHECK:      [[B2:%.*]] = alloca %struct.A,
+; CHECK:      [[A1:%.*]] = alloca %struct.A,
+; CHECK:      [[B1:%.*]] = alloca %struct.A,
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A1]])
+; CHECK-NEXT:   unwind label %[[LPAD:[^\s]+]]
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B1]])
+; CHECK-NEXT:   unwind label %[[LPAD1:[^\s]+]]
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B1]])
+; CHECK-NEXT:   unwind label %[[LPAD1]]
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
+; CHECK-NEXT:   unwind label %[[LPAD]]
+
+; Inner landing pad from first inlining.
+; CHECK:    [[LPAD1]]:
+; CHECK-NEXT: [[LPADVAL1:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
+; CHECK-NEXT:   to label %[[RESUME1:[^\s]+]] unwind
+; CHECK: [[RESUME1]]:
+; CHECK-NEXT: br label %[[LPAD_JOIN1:[^\s]+]]
+
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A2]])
+; CHECK-NEXT:   unwind label %[[LPAD]]
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B2]])
+; CHECK-NEXT:   unwind label %[[LPAD2:[^\s]+]]
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B2]])
+; CHECK-NEXT:   unwind label %[[LPAD2]]
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
+; CHECK-NEXT:   unwind label %[[LPAD]]
+
+; Inner landing pad from second inlining.
+; CHECK:    [[LPAD2]]:
+; CHECK-NEXT: [[LPADVAL2:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:   cleanup
+; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
+; CHECK-NEXT:   to label %[[RESUME2:[^\s]+]] unwind
+; CHECK: [[RESUME2]]:
+; CHECK-NEXT: br label %[[LPAD_JOIN2:[^\s]+]]
+
+; CHECK:      ret void
+
+; CHECK:    [[LPAD]]:
+; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, %entry ], [ 0, {{%.*}} ], [ 1, %cont ], [ 1, {{%.*}} ]
+; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 1, %entry ], [ 1, {{%.*}} ], [ 4, %cont ], [ 4, {{%.*}} ]
+; CHECK-NEXT: [[LPADVAL:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: br label %[[LPAD_JOIN2]]
+
+; CHECK: [[LPAD_JOIN2]]:
+; CHECK-NEXT: [[XJ2:%.*]] = phi i32 [ [[X]], %[[LPAD]] ], [ 1, %[[RESUME2]] ]
+; CHECK-NEXT: [[YJ2:%.*]] = phi i32 [ [[Y]], %[[LPAD]] ], [ 4, %[[RESUME2]] ]
+; CHECK-NEXT: [[EXNJ2:%.*]] = phi { i8*, i32 } [ [[LPADVAL]], %[[LPAD]] ], [ [[LPADVAL2]], %[[RESUME2]] ]
+; CHECK-NEXT: br label %[[LPAD_JOIN1]]
+
+; CHECK: [[LPAD_JOIN1]]:
+; CHECK-NEXT: [[XJ1:%.*]] = phi i32 [ [[XJ2]], %[[LPAD_JOIN2]] ], [ 0, %[[RESUME1]] ]
+; CHECK-NEXT: [[YJ1:%.*]] = phi i32 [ [[YJ2]], %[[LPAD_JOIN2]] ], [ 1, %[[RESUME1]] ]
+; CHECK-NEXT: [[EXNJ1:%.*]] = phi { i8*, i32 } [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[LPADVAL1]], %[[RESUME1]] ]
+; CHECK-NEXT: extractvalue { i8*, i32 } [[EXNJ1]], 0
+; CHECK-NEXT: [[SELJ1:%.*]] = extractvalue { i8*, i32 } [[EXNJ1]], 1
+; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for(
+; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]]
+
+; CHECK:      call void @use(i32 [[XJ1]])
+; CHECK:      call void @use(i32 [[YJ1]])
+
+; CHECK:      resume { i8*, i32 }
+
+
+;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls
+define void @test2_out() uwtable ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @test0_in()
+          to label %ret unwind label %lpad
+
+ret:
+  ret void
+
+lpad:
+  %exn = landingpad {i8*, i32}
+            cleanup
+  call void @_ZSt9terminatev()
+  unreachable
+}
+
+; CHECK: define void @test2_out()
+; CHECK:      [[A:%.*]] = alloca %struct.A,
+; CHECK:      [[B:%.*]] = alloca %struct.A,
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A]])
+; CHECK-NEXT:   unwind label %[[LPAD:[^\s]+]]
+; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B]])
+; CHECK-NEXT:   unwind label %[[LPAD2:[^\s]+]]
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B]])
+; CHECK-NEXT:   unwind label %[[LPAD2]]
+; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A]])
+; CHECK-NEXT:   unwind label %[[LPAD]]
+
+
+;; Test 3 - Deal correctly with split unwind edges.
+define void @test3_out() uwtable ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @test0_in()
+          to label %ret unwind label %lpad
+
+ret:
+  ret void
+
+lpad:
+  %exn = landingpad {i8*, i32}
+            catch i8* bitcast (i8** @_ZTIi to i8*)
+  br label %lpad.cont
+
+lpad.cont:
+  call void @_ZSt9terminatev()
+  unreachable
+}
+
+; CHECK: define void @test3_out()
+; CHECK:      landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: invoke void @_ZN1AD1Ev(
+; CHECK-NEXT:   to label %[[L:[^\s]+]] unwind
+; CHECK:    [[L]]:
+; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
+; CHECK:    [[JOIN]]:
+; CHECK-NEXT: phi { i8*, i32 }
+; CHECK-NEXT: br label %lpad.cont
+; CHECK:    lpad.cont:
+; CHECK-NEXT: call void @_ZSt9terminatev()
+
+
+;; Test 4 - Split unwind edges with a dominance problem
+define void @test4_out() uwtable ssp personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @test0_in()
+          to label %cont unwind label %lpad.crit
+
+cont:
+  invoke void @opaque()
+          to label %ret unwind label %lpad
+
+ret:
+  ret void
+
+lpad.crit:
+  %exn = landingpad {i8*, i32}
+            catch i8* bitcast (i8** @_ZTIi to i8*)
+  call void @opaque() nounwind
+  br label %terminate
+
+lpad:
+  %exn2 = landingpad {i8*, i32}
+            catch i8* bitcast (i8** @_ZTIi to i8*)
+  br label %terminate
+
+terminate:
+  %phi = phi i32 [ 0, %lpad.crit ], [ 1, %lpad ]
+  call void @use(i32 %phi)
+  call void @_ZSt9terminatev()
+  unreachable
+}
+
+; CHECK: define void @test4_out()
+; CHECK:      landingpad { i8*, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: invoke void @_ZN1AD1Ev(
+; CHECK-NEXT:   to label %[[L:[^\s]+]] unwind
+; CHECK:    [[L]]:
+; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
+; CHECK:      invoke void @opaque()
+; CHECK-NEXT:                  unwind label %lpad
+; CHECK:    lpad.crit:
+; CHECK-NEXT: landingpad { i8*, i32 }
+; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: br label %[[JOIN]]
+; CHECK:    [[JOIN]]:
+; CHECK-NEXT: phi { i8*, i32 }
+; CHECK-NEXT: call void @opaque() [[NUW:#[0-9]+]]
+; CHECK-NEXT: br label %[[FIX:[^\s]+]]
+; CHECK:    lpad:
+; CHECK-NEXT: landingpad { i8*, i32 }
+; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
+; CHECK-NEXT: br label %[[FIX]]
+; CHECK:    [[FIX]]:
+; CHECK-NEXT: [[T1:%.*]] = phi i32 [ 0, %[[JOIN]] ], [ 1, %lpad ]
+; CHECK-NEXT: call void @use(i32 [[T1]])
+; CHECK-NEXT: call void @_ZSt9terminatev()
+
+; CHECK: attributes [[NUW]] = { nounwind }
+; CHECK: attributes #1 = { nounwind readnone }
+; CHECK: attributes #2 = { ssp uwtable }
+; CHECK: attributes #3 = { argmemonly nounwind }
+; CHECK: attributes #4 = { noreturn nounwind }

Added: llvm/trunk/test/Transforms/Inline/inline_minisize.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_minisize.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_minisize.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_minisize.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,232 @@
+; RUN: opt -O2 -S < %s | FileCheck %s
+
+ at data = common global i32* null, align 8
+
+define i32 @fct1(i32 %a) nounwind uwtable ssp {
+entry:
+  %a.addr = alloca i32, align 4
+  %res = alloca i32, align 4
+  %i = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  %tmp = load i32, i32* %a.addr, align 4
+  %idxprom = sext i32 %tmp to i64
+  %tmp1 = load i32*, i32** @data, align 8
+  %arrayidx = getelementptr inbounds i32, i32* %tmp1, i64 %idxprom
+  %tmp2 = load i32, i32* %arrayidx, align 4
+  %tmp3 = load i32, i32* %a.addr, align 4
+  %add = add nsw i32 %tmp3, 1
+  %idxprom1 = sext i32 %add to i64
+  %tmp4 = load i32*, i32** @data, align 8
+  %arrayidx2 = getelementptr inbounds i32, i32* %tmp4, i64 %idxprom1
+  %tmp5 = load i32, i32* %arrayidx2, align 4
+  %mul = mul nsw i32 %tmp2, %tmp5
+  store i32 %mul, i32* %res, align 4
+  store i32 0, i32* %i, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %tmp6 = load i32, i32* %i, align 4
+  %tmp7 = load i32, i32* %res, align 4
+  %cmp = icmp slt i32 %tmp6, %tmp7
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp8 = load i32, i32* %i, align 4
+  %idxprom3 = sext i32 %tmp8 to i64
+  %tmp9 = load i32*, i32** @data, align 8
+  %arrayidx4 = getelementptr inbounds i32, i32* %tmp9, i64 %idxprom3
+  call void @fct0(i32* %arrayidx4)
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %tmp10 = load i32, i32* %i, align 4
+  %inc = add nsw i32 %tmp10, 1
+  store i32 %inc, i32* %i, align 4
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  store i32 0, i32* %i, align 4
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.inc10, %for.end
+  %tmp11 = load i32, i32* %i, align 4
+  %tmp12 = load i32, i32* %res, align 4
+  %cmp6 = icmp slt i32 %tmp11, %tmp12
+  br i1 %cmp6, label %for.body7, label %for.end12
+
+for.body7:                                        ; preds = %for.cond5
+  %tmp13 = load i32, i32* %i, align 4
+  %idxprom8 = sext i32 %tmp13 to i64
+  %tmp14 = load i32*, i32** @data, align 8
+  %arrayidx9 = getelementptr inbounds i32, i32* %tmp14, i64 %idxprom8
+  call void @fct0(i32* %arrayidx9)
+  br label %for.inc10
+
+for.inc10:                                        ; preds = %for.body7
+  %tmp15 = load i32, i32* %i, align 4
+  %inc11 = add nsw i32 %tmp15, 1
+  store i32 %inc11, i32* %i, align 4
+  br label %for.cond5
+
+for.end12:                                        ; preds = %for.cond5
+  store i32 0, i32* %i, align 4
+  br label %for.cond13
+
+for.cond13:                                       ; preds = %for.inc18, %for.end12
+  %tmp16 = load i32, i32* %i, align 4
+  %tmp17 = load i32, i32* %res, align 4
+  %cmp14 = icmp slt i32 %tmp16, %tmp17
+  br i1 %cmp14, label %for.body15, label %for.end20
+
+for.body15:                                       ; preds = %for.cond13
+  %tmp18 = load i32, i32* %i, align 4
+  %idxprom16 = sext i32 %tmp18 to i64
+  %tmp19 = load i32*, i32** @data, align 8
+  %arrayidx17 = getelementptr inbounds i32, i32* %tmp19, i64 %idxprom16
+  call void @fct0(i32* %arrayidx17)
+  br label %for.inc18
+
+for.inc18:                                        ; preds = %for.body15
+  %tmp20 = load i32, i32* %i, align 4
+  %inc19 = add nsw i32 %tmp20, 1
+  store i32 %inc19, i32* %i, align 4
+  br label %for.cond13
+
+for.end20:                                        ; preds = %for.cond13
+  %tmp21 = load i32, i32* %res, align 4
+  ret i32 %tmp21
+}
+
+declare void @fct0(i32*)
+
+define i32 @fct2(i32 %a) nounwind uwtable inlinehint ssp {
+entry:
+  %a.addr = alloca i32, align 4
+  %res = alloca i32, align 4
+  %i = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  %tmp = load i32, i32* %a.addr, align 4
+  %shl = shl i32 %tmp, 1
+  %idxprom = sext i32 %shl to i64
+  %tmp1 = load i32*, i32** @data, align 8
+  %arrayidx = getelementptr inbounds i32, i32* %tmp1, i64 %idxprom
+  %tmp2 = load i32, i32* %arrayidx, align 4
+  %tmp3 = load i32, i32* %a.addr, align 4
+  %shl1 = shl i32 %tmp3, 1
+  %add = add nsw i32 %shl1, 13
+  %idxprom2 = sext i32 %add to i64
+  %tmp4 = load i32*, i32** @data, align 8
+  %arrayidx3 = getelementptr inbounds i32, i32* %tmp4, i64 %idxprom2
+  %tmp5 = load i32, i32* %arrayidx3, align 4
+  %mul = mul nsw i32 %tmp2, %tmp5
+  store i32 %mul, i32* %res, align 4
+  store i32 0, i32* %i, align 4
+  store i32 0, i32* %i, align 4
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %tmp6 = load i32, i32* %i, align 4
+  %tmp7 = load i32, i32* %res, align 4
+  %cmp = icmp slt i32 %tmp6, %tmp7
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %tmp8 = load i32, i32* %i, align 4
+  %idxprom4 = sext i32 %tmp8 to i64
+  %tmp9 = load i32*, i32** @data, align 8
+  %arrayidx5 = getelementptr inbounds i32, i32* %tmp9, i64 %idxprom4
+  call void @fct0(i32* %arrayidx5)
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %tmp10 = load i32, i32* %i, align 4
+  %inc = add nsw i32 %tmp10, 1
+  store i32 %inc, i32* %i, align 4
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  store i32 0, i32* %i, align 4
+  br label %for.cond6
+
+for.cond6:                                        ; preds = %for.inc11, %for.end
+  %tmp11 = load i32, i32* %i, align 4
+  %tmp12 = load i32, i32* %res, align 4
+  %cmp7 = icmp slt i32 %tmp11, %tmp12
+  br i1 %cmp7, label %for.body8, label %for.end13
+
+for.body8:                                        ; preds = %for.cond6
+  %tmp13 = load i32, i32* %i, align 4
+  %idxprom9 = sext i32 %tmp13 to i64
+  %tmp14 = load i32*, i32** @data, align 8
+  %arrayidx10 = getelementptr inbounds i32, i32* %tmp14, i64 %idxprom9
+  call void @fct0(i32* %arrayidx10)
+  br label %for.inc11
+
+for.inc11:                                        ; preds = %for.body8
+  %tmp15 = load i32, i32* %i, align 4
+  %inc12 = add nsw i32 %tmp15, 1
+  store i32 %inc12, i32* %i, align 4
+  br label %for.cond6
+
+for.end13:                                        ; preds = %for.cond6
+  store i32 0, i32* %i, align 4
+  br label %for.cond14
+
+for.cond14:                                       ; preds = %for.inc19, %for.end13
+  %tmp16 = load i32, i32* %i, align 4
+  %tmp17 = load i32, i32* %res, align 4
+  %cmp15 = icmp slt i32 %tmp16, %tmp17
+  br i1 %cmp15, label %for.body16, label %for.end21
+
+for.body16:                                       ; preds = %for.cond14
+  %tmp18 = load i32, i32* %i, align 4
+  %idxprom17 = sext i32 %tmp18 to i64
+  %tmp19 = load i32*, i32** @data, align 8
+  %arrayidx18 = getelementptr inbounds i32, i32* %tmp19, i64 %idxprom17
+  call void @fct0(i32* %arrayidx18)
+  br label %for.inc19
+
+for.inc19:                                        ; preds = %for.body16
+  %tmp20 = load i32, i32* %i, align 4
+  %inc20 = add nsw i32 %tmp20, 1
+  store i32 %inc20, i32* %i, align 4
+  br label %for.cond14
+
+for.end21:                                        ; preds = %for.cond14
+  %tmp21 = load i32, i32* %res, align 4
+  ret i32 %tmp21
+}
+
+define i32 @fct3(i32 %c) nounwind uwtable ssp {
+entry:
+  ;CHECK-LABEL: @fct3(
+  ;CHECK: call i32 @fct1
+  ; The inline keyword gives a sufficient benefits to inline fct2
+  ;CHECK-NOT: call i32 @fct2
+  %c.addr = alloca i32, align 4
+  store i32 %c, i32* %c.addr, align 4
+  %tmp = load i32, i32* %c.addr, align 4
+  %call = call i32 @fct1(i32 %tmp)
+  %tmp1 = load i32, i32* %c.addr, align 4
+  %call1 = call i32 @fct2(i32 %tmp1)
+  %add = add nsw i32 %call, %call1
+  ret i32 %add
+}
+
+define i32 @fct4(i32 %c) minsize nounwind uwtable ssp {
+entry:
+  ;CHECK-LABEL: @fct4(
+  ;CHECK: call i32 @fct1
+  ; With Oz (minsize attribute), the benefit of inlining fct2
+  ; is the same as fct1, thus no inlining for fct2
+  ;CHECK: call i32 @fct2
+  %c.addr = alloca i32, align 4
+  store i32 %c, i32* %c.addr, align 4
+  %tmp = load i32, i32* %c.addr, align 4
+  %call = call i32 @fct1(i32 %tmp)
+  %tmp1 = load i32, i32* %c.addr, align 4
+  %call1 = call i32 @fct2(i32 %tmp1)
+  %add = add nsw i32 %call, %call1
+  ret i32 %add
+}

Added: llvm/trunk/test/Transforms/Inline/inline_prune.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_prune.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_prune.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_prune.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+define internal i32 @callee1(i32 %A, i32 %B) {
+; CHECK-NOT: @callee1
+entry:
+  %cond = icmp eq i32 %A, 123
+  br i1 %cond, label %T, label %F
+
+T:
+  %C = mul i32 %B, %B
+  ret i32 %C
+
+F:
+  ret i32 0
+}
+
+define internal i32 @callee2(i32 %A, i32 %B) {
+; CHECK-NOT: @callee2
+entry:
+  switch i32 %A, label %T [
+           i32 10, label %F
+           i32 1234, label %G
+  ]
+
+dead:
+  %cond = icmp eq i32 %A, 123
+  br i1 %cond, label %T, label %F
+
+T:
+  %C = mul i32 %B, %B
+  ret i32 %C
+
+F:
+  ret i32 0
+
+G:
+  %D = mul i32 %B, %B
+  %E = mul i32 %D, %B
+  ret i32 %E
+}
+
+define i32 @test(i32 %A) {
+; CHECK-LABEL: define i32 @test(i32 %A)
+entry:
+  %X = call i32 @callee1( i32 10, i32 %A )
+  %Y = call i32 @callee2( i32 10, i32 %A )
+; CHECK-NOT: call
+; CHECK-NOT: mul
+
+  %Z = add i32 %X, %Y
+  ret i32 %Z
+}
+

Added: llvm/trunk/test/Transforms/Inline/inline_returns_twice.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_returns_twice.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_returns_twice.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_returns_twice.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,85 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; Check that functions with "returns_twice" calls are only inlined,
+; if they are themselves marked as such.
+
+declare i32 @a() returns_twice
+
+define i32 @inner1() {
+entry:
+  %call = call i32 @a() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define i32 @outer1() {
+entry:
+; CHECK-LABEL: define i32 @outer1(
+; CHECK: call i32 @inner1()
+  %call = call i32 @inner1()
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define i32 @inner2() returns_twice {
+entry:
+  %call = call i32 @a() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define i32 @outer2() {
+entry:
+; CHECK-LABEL: define i32 @outer2(
+; CHECK: call i32 @a()
+  %call = call i32 @inner2() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define i32 @inner3() personality i8* null {
+entry:
+  %invoke = invoke i32 @a() returns_twice
+      to label %cont unwind label %lpad
+
+cont:
+  %add = add nsw i32 1, %invoke
+  ret i32 %add
+
+lpad:
+  %lp = landingpad i32 cleanup
+  resume i32 %lp
+}
+
+define i32 @outer3() {
+entry:
+; CHECK-LABEL: define i32 @outer3(
+; CHECK: call i32 @inner3()
+  %call = call i32 @inner3()
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}
+
+define i32 @inner4() returns_twice personality i8* null {
+entry:
+  %invoke = invoke i32 @a() returns_twice
+      to label %cont unwind label %lpad
+
+cont:
+  %add = add nsw i32 1, %invoke
+  ret i32 %add
+
+lpad:
+  %lp = landingpad i32 cleanup
+  resume i32 %lp
+}
+
+define i32 @outer4() {
+entry:
+; CHECK-LABEL: define i32 @outer4(
+; CHECK: invoke i32 @a()
+  %call = call i32 @inner4() returns_twice
+  %add = add nsw i32 1, %call
+  ret i32 %add
+}

Added: llvm/trunk/test/Transforms/Inline/inline_ssp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_ssp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_ssp.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_ssp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,161 @@
+; RUN: opt -inline %s -S | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' %s -S | FileCheck %s
+; Ensure SSP attributes are propagated correctly when inlining.
+
+ at .str = private unnamed_addr constant [11 x i8] c"fun_nossp\0A\00", align 1
+ at .str1 = private unnamed_addr constant [9 x i8] c"fun_ssp\0A\00", align 1
+ at .str2 = private unnamed_addr constant [15 x i8] c"fun_sspstrong\0A\00", align 1
+ at .str3 = private unnamed_addr constant [12 x i8] c"fun_sspreq\0A\00", align 1
+
+; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp)
+; are used by the remaining functions to ensure that the SSP attributes are
+; propagated correctly.  The caller should have its SSP attribute set as:
+; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as:
+;  sspreq > sspstrong > ssp > [no ssp]
+define internal void @fun_sspreq() nounwind sspreq uwtable {
+entry:
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0))
+  ret void
+}
+
+define internal void @fun_sspstrong() nounwind sspstrong uwtable {
+entry:
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0))
+  ret void
+}
+
+define internal void @fun_ssp() nounwind ssp uwtable {
+entry:
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i32 0, i32 0))
+  ret void
+}
+
+define internal void @fun_nossp() nounwind uwtable {
+entry:
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0))
+  ret void
+}
+
+; Tests start below 
+
+define void @inline_req_req() nounwind sspreq uwtable {
+entry:
+; CHECK: @inline_req_req() #0
+  call void @fun_sspreq()
+  ret void
+}
+
+define void @inline_req_strong() nounwind sspstrong uwtable {
+entry:
+; CHECK: @inline_req_strong() #0
+  call void @fun_sspreq()
+  ret void
+}
+
+define void @inline_req_ssp() nounwind ssp uwtable {
+entry:
+; CHECK: @inline_req_ssp() #0
+  call void @fun_sspreq()
+  ret void
+}
+
+define void @inline_req_nossp() nounwind uwtable {
+entry:
+; CHECK: @inline_req_nossp() #0
+  call void @fun_sspreq()
+  ret void
+}
+
+define void @inline_strong_req() nounwind sspreq uwtable {
+entry:
+; CHECK: @inline_strong_req() #0
+  call void @fun_sspstrong()
+  ret void
+}
+
+
+define void @inline_strong_strong() nounwind sspstrong uwtable {
+entry:
+; CHECK: @inline_strong_strong() #1
+  call void @fun_sspstrong()
+  ret void
+}
+
+define void @inline_strong_ssp() nounwind ssp uwtable {
+entry:
+; CHECK: @inline_strong_ssp() #1
+  call void @fun_sspstrong()
+  ret void
+}
+
+define void @inline_strong_nossp() nounwind uwtable {
+entry:
+; CHECK: @inline_strong_nossp() #1
+  call void @fun_sspstrong()
+  ret void
+}
+
+define void @inline_ssp_req() nounwind sspreq uwtable {
+entry:
+; CHECK: @inline_ssp_req() #0
+  call void @fun_ssp()
+  ret void
+}
+
+
+define void @inline_ssp_strong() nounwind sspstrong uwtable {
+entry:
+; CHECK: @inline_ssp_strong() #1
+  call void @fun_ssp()
+  ret void
+}
+
+define void @inline_ssp_ssp() nounwind ssp uwtable {
+entry:
+; CHECK: @inline_ssp_ssp() #2
+  call void @fun_ssp()
+  ret void
+}
+
+define void @inline_ssp_nossp() nounwind uwtable {
+entry:
+; CHECK: @inline_ssp_nossp() #2
+  call void @fun_ssp()
+  ret void
+}
+
+define void @inline_nossp_req() nounwind uwtable sspreq {
+entry:
+; CHECK: @inline_nossp_req() #0
+  call void @fun_nossp()
+  ret void
+}
+
+
+define void @inline_nossp_strong() nounwind sspstrong uwtable {
+entry:
+; CHECK: @inline_nossp_strong() #1
+  call void @fun_nossp()
+  ret void
+}
+
+define void @inline_nossp_ssp() nounwind ssp uwtable {
+entry:
+; CHECK: @inline_nossp_ssp() #2
+  call void @fun_nossp()
+  ret void
+}
+
+define void @inline_nossp_nossp() nounwind uwtable {
+entry:
+; CHECK: @inline_nossp_nossp() #3
+  call void @fun_nossp()
+  ret void
+}
+
+declare i32 @printf(i8*, ...)
+
+; CHECK: attributes #0 = { nounwind sspreq uwtable }
+; CHECK: attributes #1 = { nounwind sspstrong uwtable }
+; CHECK: attributes #2 = { nounwind ssp uwtable }
+; CHECK: attributes #3 = { nounwind uwtable }

Added: llvm/trunk/test/Transforms/Inline/inline_stats.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_stats.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_stats.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_stats.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,95 @@
+; First with legacy PM
+; RUN: opt -S -inline -inliner-function-import-stats=basic < %s 2>&1 | FileCheck %s -check-prefix=CHECK-BASIC -check-prefix=CHECK
+; RUN: opt -S -inline -inliner-function-import-stats=verbose < %s 2>&1 | FileCheck %s -check-prefix="CHECK-VERBOSE" -check-prefix=CHECK
+
+; Do again with new PM
+; RUN: opt -S -passes=inline -inliner-function-import-stats=basic < %s 2>&1 | FileCheck %s -check-prefix=CHECK-BASIC -check-prefix=CHECK
+; RUN: opt -S -passes=inline -inliner-function-import-stats=verbose < %s 2>&1 | FileCheck %s -check-prefix="CHECK-VERBOSE" -check-prefix=CHECK
+
+; CHECK: ------- Dumping inliner stats for [<stdin>] -------
+; CHECK-BASIC-NOT: -- List of inlined functions:
+; CHECK-BASIC-NOT: -- Inlined not imported function
+; CHECK-VERBOSE: -- List of inlined functions:
+; CHECK-VERBOSE: Inlined not imported function [internal2]: #inlines = 6, #inlines_to_importing_module = 2
+; CHECK-VERBOSE: Inlined imported function [external2]: #inlines = 4, #inlines_to_importing_module = 1
+; CHECK-VERBOSE: Inlined imported function [external1]: #inlines = 3, #inlines_to_importing_module = 2
+; CHECK-VERBOSE: Inlined imported function [external5]: #inlines = 1, #inlines_to_importing_module = 1
+; CHECK-VERBOSE: Inlined imported function [external3]: #inlines = 1, #inlines_to_importing_module = 0
+
+; CHECK: -- Summary:
+; CHECK: All functions: 10, imported functions: 7
+; CHECK: inlined functions: 5 [50% of all functions]
+; CHECK: imported functions inlined anywhere: 4 [57.14% of imported functions]
+; CHECK: imported functions inlined into importing module: 3 [42.86% of imported functions], remaining: 4 [57.14% of imported functions]
+; CHECK: non-imported functions inlined anywhere: 1 [33.33% of non-imported functions]
+; CHECK: non-imported functions inlined into importing module: 1 [33.33% of non-imported functions]
+
+define void @internal() {
+    call fastcc void @external1()
+    call fastcc void @internal2()
+    call coldcc void @external_big()
+    ret void
+}
+
+define void @internal2() alwaysinline {
+    ret void
+}
+
+define void @internal3() {
+    call fastcc void @external1()
+    call fastcc void @external5()
+    ret void
+}
+
+declare void @external_decl()
+
+define void @external1() alwaysinline !thinlto_src_module !0 {
+    call fastcc void @internal2()
+    call fastcc void @external2();
+    call void @external_decl();
+    ret void
+}
+
+define void @external2() alwaysinline !thinlto_src_module !1 {
+    ret void
+}
+
+define void @external3() alwaysinline !thinlto_src_module !1 {
+    ret void
+}
+
+define void @external4() !thinlto_src_module !1 {
+    call fastcc void @external1()
+    call fastcc void @external2()
+    ret void
+}
+
+define void @external5() !thinlto_src_module !1 {
+    ret void
+}
+
+; Assume big piece of code here. This function won't be inlined, so all the
+; inlined function it will have won't affect real inlines.
+define void @external_big() noinline !thinlto_src_module !1 {
+; CHECK-NOT: call fastcc void @internal2()
+    call fastcc void @internal2()
+    call fastcc void @internal2()
+    call fastcc void @internal2()
+    call fastcc void @internal2()
+
+; CHECK-NOT: call fastcc void @external2()
+    call fastcc void @external2()
+    call fastcc void @external2()
+; CHECK-NOT: call fastcc void @external3()
+    call fastcc void @external3()
+    ret void
+}
+
+; It should not be imported, but it should not break anything.
+define void @external_notcalled() !thinlto_src_module !0 {
+    call void @external_notcalled()
+    ret void
+}
+
+!0 = !{!"file.cc"}
+!1 = !{!"other.cc"}

Added: llvm/trunk/test/Transforms/Inline/inline_unreachable-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_unreachable-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_unreachable-2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_unreachable-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; CHECK-LABEL: caller
+; CHECK: call void @callee
+define void @caller(i32 %a, i1 %b) #0 {
+  call void @callee(i32 %a, i1 %b)
+  unreachable
+}
+
+define void @callee(i32 %a, i1 %b) {
+  call void @extern()
+  call void asm sideeffect "", ""()
+  br i1 %b, label %bb1, label %bb2
+bb1:
+  call void asm sideeffect "", ""()
+  ret void
+bb2:
+  call void asm sideeffect "", ""()
+  ret void
+}
+
+declare void @extern()

Added: llvm/trunk/test/Transforms/Inline/inline_unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_unreachable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_unreachable.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_unreachable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,131 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+ at a = global i32 4
+ at _ZTIi = external global i8*
+
+; CHECK-LABEL: callSimpleFunction
+; CHECK: call i32 @simpleFunction
+define i32 @callSimpleFunction(i32 %idx, i32 %limit) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %s = call i32 @simpleFunction(i32 %idx)
+  store i32 %s, i32* @a
+  unreachable
+
+if.end:
+  ret i32 %idx
+}
+
+; CHECK-LABEL: callSmallFunction
+; CHECK-NOT: call i32 @smallFunction
+define i32 @callSmallFunction(i32 %idx, i32 %limit) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %s = call i32 @smallFunction(i32 %idx)
+  store i32 %s, i32* @a
+  unreachable
+
+if.end:
+  ret i32 %idx
+}
+
+; CHECK-LABEL: throwSimpleException
+; CHECK: invoke i32 @simpleFunction
+define i32 @throwSimpleException(i32 %idx, i32 %limit) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %exception = call i8* @__cxa_allocate_exception(i64 1) #0
+  invoke i32 @simpleFunction(i32 %idx)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %if.then
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi  to i8*), i8* null) #1
+  unreachable
+
+lpad:                                             ; preds = %if.then
+  %ll = landingpad { i8*, i32 }
+          cleanup
+  ret i32 %idx
+
+if.end:                                           ; preds = %entry
+  ret i32 %idx
+}
+
+; CHECK-LABEL: throwSmallException
+; CHECK-NOT: invoke i32 @smallFunction
+define i32 @throwSmallException(i32 %idx, i32 %limit) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %exception = call i8* @__cxa_allocate_exception(i64 1) #0
+  invoke i32 @smallFunction(i32 %idx)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %if.then
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi  to i8*), i8* null) #1
+  unreachable
+
+lpad:                                             ; preds = %if.then
+  %ll = landingpad { i8*, i32 }
+          cleanup
+  ret i32 %idx
+
+if.end:                                           ; preds = %entry
+  ret i32 %idx
+}
+
+define i32 @simpleFunction(i32 %a) #0 {
+entry:
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %a2 = load volatile i32, i32* @a
+  %x2 = add i32 %x1, %a2
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %a5 = load volatile i32, i32* @a
+  %x5 = add i32 %x4, %a5
+  %a6 = load volatile i32, i32* @a
+  %x6 = add i32 %x5, %a6
+  %a7 = load volatile i32, i32* @a
+  %x7 = add i32 %x6, %a6
+  %a8 = load volatile i32, i32* @a
+  %x8 = add i32 %x7, %a8
+  %a9 = load volatile i32, i32* @a
+  %x9 = add i32 %x8, %a9
+  %a10 = load volatile i32, i32* @a
+  %x10 = add i32 %x9, %a10
+  %a11 = load volatile i32, i32* @a
+  %x11 = add i32 %x10, %a11
+  %a12 = load volatile i32, i32* @a
+  %x12 = add i32 %x11, %a12
+  %add = add i32 %x12, %a
+  ret i32 %add
+}
+
+define i32 @smallFunction(i32 %a) {
+entry:
+  %r = load volatile i32, i32* @a
+  ret i32 %r
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { noreturn }
+
+declare i8* @__cxa_allocate_exception(i64)
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_throw(i8*, i8*, i8*)
+

Added: llvm/trunk/test/Transforms/Inline/internal-scc-members.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/internal-scc-members.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/internal-scc-members.ll (added)
+++ llvm/trunk/test/Transforms/Inline/internal-scc-members.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; Test that the inliner can handle deleting functions within an SCC while still
+; processing the calls in that SCC.
+;
+; RUN: opt < %s -S -inline | FileCheck %s
+; RUN: opt < %s -S -passes=inline | FileCheck %s
+
+; CHECK-LABEL: define internal void @test1_scc0()
+; CHECK-NOT: call
+; CHECK: call void @test1_scc0()
+; CHECK-NOT: call
+; CHECK: ret
+define internal void @test1_scc0() {
+entry:
+  call void @test1_scc1()
+  ret void
+}
+
+; CHECK-NOT: @test1_scc1
+define internal void @test1_scc1() {
+entry:
+  call void @test1_scc0()
+  ret void
+}
+
+; CHECK-LABEL: define void @test1()
+; CHECK: call void @test1_scc0()
+define void @test1() {
+entry:
+  call void @test1_scc0() noinline
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/invoke-cleanup.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/invoke-cleanup.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/invoke-cleanup.ll (added)
+++ llvm/trunk/test/Transforms/Inline/invoke-cleanup.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt %s -inline -S | FileCheck %s
+; RUN: opt %s -passes='cgscc(inline)' -S | FileCheck %s
+
+declare void @external_func()
+
+ at exception_type1 = external global i8
+ at exception_type2 = external global i8
+
+
+define internal void @inner() personality i8* null {
+  invoke void @external_func()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_type1
+  resume i32 %lp
+}
+
+; Test that the "cleanup" clause is kept when inlining @inner() into
+; this call site (PR17872), otherwise C++ destructors will not be
+; called when they should be.
+
+define void @outer() personality i8* null {
+  invoke void @inner()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      cleanup
+      catch i8* @exception_type2
+  resume i32 %lp
+}
+; CHECK: define void @outer
+; CHECK: landingpad
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* @exception_type1
+; CHECK-NEXT: catch i8* @exception_type2

Added: llvm/trunk/test/Transforms/Inline/invoke-combine-clauses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/invoke-combine-clauses.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/invoke-combine-clauses.ll (added)
+++ llvm/trunk/test/Transforms/Inline/invoke-combine-clauses.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,117 @@
+; RUN: opt %s -passes='cgscc(inline)' -S | FileCheck %s
+
+declare void @external_func()
+declare void @abort()
+
+ at exception_inner = external global i8
+ at exception_outer = external global i8
+ at condition = external global i1
+
+
+; Check for a bug in which multiple "resume" instructions in the
+; inlined function caused "catch i8* @exception_outer" to appear
+; multiple times in the resulting landingpad.
+
+define internal void @inner_multiple_resume() personality i8* null {
+  invoke void @external_func()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_inner
+  %cond = load i1, i1* @condition
+  br i1 %cond, label %resume1, label %resume2
+resume1:
+  resume i32 1
+resume2:
+  resume i32 2
+}
+
+define void @outer_multiple_resume() personality i8* null {
+  invoke void @inner_multiple_resume()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_outer
+  resume i32 %lp
+}
+; CHECK: define void @outer_multiple_resume()
+; CHECK: %lp.i = landingpad
+; CHECK-NEXT: catch i8* @exception_inner
+; CHECK-NEXT: catch i8* @exception_outer
+; Check that there isn't another "catch" clause:
+; CHECK-NEXT: load
+
+
+; Check for a bug in which having a "resume" and a "call" in the
+; inlined function caused "catch i8* @exception_outer" to appear
+; multiple times in the resulting landingpad.
+
+define internal void @inner_resume_and_call() personality i8* null {
+  call void @external_func()
+  invoke void @external_func()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_inner
+  resume i32 %lp
+}
+
+define void @outer_resume_and_call() personality i8* null {
+  invoke void @inner_resume_and_call()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_outer
+  resume i32 %lp
+}
+; CHECK: define void @outer_resume_and_call()
+; CHECK: %lp.i = landingpad
+; CHECK-NEXT: catch i8* @exception_inner
+; CHECK-NEXT: catch i8* @exception_outer
+; Check that there isn't another "catch" clause:
+; CHECK-NEXT: br
+
+
+; Check what happens if the inlined function contains an "invoke" but
+; no "resume".  In this case, the inlined landingpad does not need to
+; include the "catch i8* @exception_outer" clause from the outer
+; function (since the outer function's landingpad will not be
+; reachable), but it's OK to include this clause.
+
+define internal void @inner_no_resume_or_call() personality i8* null {
+  invoke void @external_func()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_inner
+  ; A landingpad might have no "resume" if a C++ destructor aborts.
+  call void @abort() noreturn nounwind
+  unreachable
+}
+
+define void @outer_no_resume_or_call() personality i8* null {
+  invoke void @inner_no_resume_or_call()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32
+      catch i8* @exception_outer
+  resume i32 %lp
+}
+; CHECK: define void @outer_no_resume_or_call()
+; CHECK: %lp.i = landingpad
+; CHECK-NEXT: catch i8* @exception_inner
+; CHECK-NEXT: catch i8* @exception_outer
+; Check that there isn't another "catch" clause:
+; CHECK-NEXT: call void @abort()

Added: llvm/trunk/test/Transforms/Inline/invoke-cost.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/invoke-cost.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/invoke-cost.ll (added)
+++ llvm/trunk/test/Transforms/Inline/invoke-cost.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt -inline < %s -S -o - -inline-threshold=100 | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' < %s -S -o - -inline-threshold=100 | FileCheck %s
+
+target datalayout = "p:32:32"
+
+ at glbl = external global i32
+
+declare void @f()
+declare i32 @__gxx_personality_v0(...)
+declare i8* @__cxa_begin_catch(i8*)
+declare void @__cxa_end_catch()
+declare void @_ZSt9terminatev()
+
+define void @inner1() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @f() to label %cont1 unwind label %terminate.lpad
+
+cont1:
+  invoke void @f() to label %cont2 unwind label %terminate.lpad
+
+cont2:
+  invoke void @f() to label %cont3 unwind label %terminate.lpad
+
+cont3:
+  invoke void @f() to label %cont4 unwind label %terminate.lpad
+
+cont4:
+  ret void
+
+terminate.lpad:
+  landingpad {i8*, i32}
+            catch i8* null
+  call void @_ZSt9terminatev() noreturn nounwind
+  unreachable
+}
+
+define void @outer1() {
+; CHECK-LABEL: @outer1(
+;
+; This call should not get inlined because inner1 actually calls a function
+; many times, but it only does so through invoke as opposed to call.
+;
+; CHECK: call void @inner1
+  call void @inner1()
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/invoke_test-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/invoke_test-1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/invoke_test-1.ll (added)
+++ llvm/trunk/test/Transforms/Inline/invoke_test-1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; Test that we can inline a simple function, turning the calls in it into invoke
+; instructions
+
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+declare void @might_throw()
+
+define internal void @callee() {
+entry:
+  call void @might_throw()
+  ret void
+}
+
+; caller returns true if might_throw throws an exception...
+define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: define i32 @caller() personality i32 (...)* @__gxx_personality_v0
+entry:
+  invoke void @callee()
+      to label %cont unwind label %exc
+; CHECK-NOT: @callee
+; CHECK: invoke void @might_throw()
+
+cont:
+  ret i32 0
+
+exc:
+  %exn = landingpad {i8*, i32}
+         cleanup
+  ret i32 1
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/invoke_test-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/invoke_test-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/invoke_test-2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/invoke_test-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; Test that if an invoked function is inlined, and if that function cannot
+; throw, that the dead handler is now unreachable.
+
+; RUN: opt < %s -inline -simplifycfg -S | FileCheck %s
+
+declare void @might_throw()
+
+define internal i32 @callee() personality i32 (...)* @__gxx_personality_v0 {
+enrty:
+  invoke void @might_throw()
+      to label %cont unwind label %exc
+
+cont:
+  ret i32 0
+
+exc:
+  %exn = landingpad {i8*, i32}
+         cleanup
+  ret i32 1
+}
+
+; caller returns true if might_throw throws an exception... callee cannot throw.
+define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: define i32 @caller() personality i32 (...)* @__gxx_personality_v0
+enrty:
+  %X = invoke i32 @callee()
+           to label %cont unwind label %UnreachableExceptionHandler
+; CHECK-NOT: @callee
+; CHECK: invoke void @might_throw()
+; CHECK:     to label %[[C:.*]] unwind label %[[E:.*]]
+
+; CHECK: [[E]]:
+; CHECK:   landingpad
+; CHECK:      cleanup
+; CHECK:   br label %[[C]]
+
+cont:
+; CHECK: [[C]]:
+  ret i32 %X
+; CHECK:   %[[PHI:.*]] = phi i32
+; CHECK:   ret i32 %[[PHI]]
+
+UnreachableExceptionHandler:
+; CHECK-NOT: UnreachableExceptionHandler:
+  %exn = landingpad {i8*, i32}
+         cleanup
+  ret i32 -1
+; CHECK-NOT: ret i32 -1
+}
+; CHECK: }
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/invoke_test-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/invoke_test-3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/invoke_test-3.ll (added)
+++ llvm/trunk/test/Transforms/Inline/invoke_test-3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; Test that any rethrown exceptions in an inlined function are automatically
+; turned into branches to the invoke destination.
+
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+declare void @might_throw()
+
+define internal i32 @callee() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  invoke void @might_throw()
+      to label %cont unwind label %exc
+
+cont:
+  ret i32 0
+
+exc:
+ ; This just rethrows the exception!
+  %exn = landingpad {i8*, i32}
+         cleanup
+  resume { i8*, i32 } %exn
+}
+
+; caller returns true if might_throw throws an exception... which gets
+; propagated by callee.
+define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: define i32 @caller()
+entry:
+  %X = invoke i32 @callee()
+           to label %cont unwind label %Handler
+; CHECK-NOT: @callee
+; CHECK: invoke void @might_throw()
+; At this point we just check that the rest of the function does not 'resume'
+; at any point and instead the inlined resume is threaded into normal control
+; flow.
+; CHECK-NOT: resume
+
+cont:
+  ret i32 %X
+
+Handler:
+; This consumes an exception thrown by might_throw
+  %exn = landingpad {i8*, i32}
+         cleanup
+  ret i32 1
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/Inline/label-annotation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/label-annotation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/label-annotation.ll (added)
+++ llvm/trunk/test/Transforms/Inline/label-annotation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; Inlining should not clone label annotations.
+; Currently we block all duplication for simplicity.
+
+; RUN: opt < %s -S -inline | FileCheck %s
+
+ at the_global = global i32 0
+
+declare void @llvm.codeview.annotation(metadata)
+
+define void @inlinee() {
+entry:
+  store i32 42, i32* @the_global
+  call void @llvm.codeview.annotation(metadata !0)
+  ret void
+}
+
+define void @caller() {
+entry:
+  call void @inlinee()
+  ret void
+}
+
+!0 = !{!"annotation"}
+
+; CHECK-LABEL: define void @inlinee()
+; CHECK: store i32 42, i32* @the_global
+; CHECK: call void @llvm.codeview.annotation(metadata !0)
+; CHECK: ret void
+
+; CHECK-LABEL: define void @caller()
+;       MSVC can inline this. If we ever do, check for the store but make sure
+;       there is no annotation.
+; CHECK: call void @inlinee()
+; CHECK-NOT: call void @llvm.codeview.annotation
+; CHECK: ret void

Added: llvm/trunk/test/Transforms/Inline/last-call-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/last-call-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/last-call-bonus.ll (added)
+++ llvm/trunk/test/Transforms/Inline/last-call-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; The goal of this test is checking if LastCallToStaticBonus is applied
+; correctly while deciding inline deferral. For the test code below, when
+; inliner evaluates the callsite of bar->baz, it checks if inlining of bar->baz
+; prevents ininling of foo->bar, even when foo->bar inlining is more beneficial
+; than bar->baz inlining. As LastCallToStaticBonus has a massive value, and
+; both baz and bar has only one caller, the cost of foo->bar inlining and
+; bar->baz inlining should be non-trivial for inliner to compute that bar->baz
+; inlining can actaully prevent foo->bar inlining. To make the cost of these
+; callsites big enough, loop unrolling pass with very high threshold is used to
+; preprocess the test.
+
+; RUN: opt < %s -loop-unroll -inline -unroll-threshold=15000 -inline-threshold=250 -S | FileCheck %s
+; RUN: opt < %s -passes='function(require<opt-remark-emit>,unroll),require<profile-summary>,cgscc(inline)' -unroll-threshold=15000 -inline-threshold=250 -S | FileCheck %s
+; CHECK-LABEL: define internal i32 @bar()
+
+define internal i32 @baz() {
+entry:
+  br label %bb1
+
+bb1:
+  %ind = phi i32 [ 0, %entry ], [ %inc, %bb1 ]
+  call void @extern()
+  %inc = add nsw i32 %ind, 1
+  %cmp = icmp sgt i32 %inc, 510
+  br i1 %cmp, label %ret, label %bb1
+
+ret:
+  ret i32 0
+}
+
+define internal i32 @bar() {
+entry:
+  br label %bb1
+
+bb1:
+  %ind = phi i32 [ 0, %entry ], [ %inc, %bb1 ]
+  call void @extern()
+  %inc = add nsw i32 %ind, 1
+  %cmp = icmp sgt i32 %inc, 510
+  br i1 %cmp, label %ret, label %bb1
+
+ret:
+  call i32 @baz()
+  ret i32 0
+}
+
+define i32 @foo() {
+entry:
+  call i32 @bar()
+  ret i32 0
+}
+
+declare void @extern()

Added: llvm/trunk/test/Transforms/Inline/last-call-no-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/last-call-no-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/last-call-no-bonus.ll (added)
+++ llvm/trunk/test/Transforms/Inline/last-call-no-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,58 @@
+; This code is virtually identical to last-call-bonus.ll, but the callsites
+; to the internal functions are cold, thereby preventing the last call to
+; static bonus from being applied.
+
+; RUN: opt < %s -passes='function(require<opt-remark-emit>,unroll),require<profile-summary>,cgscc(inline)' -unroll-threshold=15000 -inline-threshold=250 -S | FileCheck %s
+
+; CHECK-LABEL: define internal i32 @baz
+define internal i32 @baz() {
+entry:
+  br label %bb1
+
+bb1:
+  %ind = phi i32 [ 0, %entry ], [ %inc, %bb1 ]
+  call void @extern()
+  %inc = add nsw i32 %ind, 1
+  %cmp = icmp sgt i32 %inc, 510
+  br i1 %cmp, label %ret, label %bb1
+
+ret:
+  ret i32 0
+}
+
+; CHECK-LABEL: define internal i32 @bar
+define internal i32 @bar(i1 %b) {
+entry:
+  br label %bb1
+
+bb1:
+  %ind = phi i32 [ 0, %entry ], [ %inc, %bb1 ]
+  call void @extern()
+  %inc = add nsw i32 %ind, 1
+  %cmp = icmp sgt i32 %inc, 510
+  br i1 %cmp, label %for.exit, label %bb1
+
+for.exit:
+  br i1 %b, label %bb2, label %ret, !prof !0
+bb2:
+; CHECK: call i32 @baz
+  call i32 @baz()
+  br label %ret
+ret:
+  ret i32 0
+}
+; CHECK-LABEL: define i32 @foo
+define i32 @foo(i1 %b) {
+entry:
+  br i1 %b, label %bb1, label %ret, !prof !0
+bb1:
+; CHECK: call i32 @bar
+  call i32 @bar(i1 %b)
+  br label %ret
+ret:
+  ret i32 0
+}
+
+declare void @extern()
+
+!0 = !{!"branch_weights", i32 1, i32 2500}

Added: llvm/trunk/test/Transforms/Inline/last-callsite.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/last-callsite.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/last-callsite.ll (added)
+++ llvm/trunk/test/Transforms/Inline/last-callsite.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,269 @@
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=0 -S | FileCheck %s
+
+; The 'test1_' prefixed functions test the basic 'last callsite' inline
+; threshold adjustment where we specifically inline the last call site of an
+; internal function regardless of cost.
+
+define internal void @test1_f() {
+entry:
+  %p = alloca i32
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  ret void
+}
+
+; Identical to @test1_f but doesn't get inlined because there is more than one
+; call. If this *does* get inlined, the body used both here and in @test1_f
+; isn't a good test for different threshold based on the last call.
+define internal void @test1_g() {
+entry:
+  %p = alloca i32
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  ret void
+}
+
+define void @test1() {
+; CHECK-LABEL: define void @test1()
+entry:
+  call void @test1_f()
+; CHECK-NOT: @test1_f
+
+  call void @test1_g()
+  call void @test1_g()
+; CHECK: call void @test1_g()
+; CHECK: call void @test1_g()
+
+  ret void
+}
+
+
+; The 'test2_' prefixed functions test that we can discover the last callsite
+; bonus after having inlined the prior call site. For this to work, we need
+; a callsite dependent cost so we have a trivial predicate guarding all the
+; cost, and set that in a particular direction.
+
+define internal void @test2_f(i1 %b) {
+entry:
+  %p = alloca i32
+  br i1 %b, label %then, label %exit
+
+then:
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Identical to @test2_f but doesn't get inlined because there is more than one
+; call. If this *does* get inlined, the body used both here and in @test2_f
+; isn't a good test for different threshold based on the last call.
+define internal void @test2_g(i1 %b) {
+entry:
+  %p = alloca i32
+  br i1 %b, label %then, label %exit
+
+then:
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test2() {
+; CHECK-LABEL: define void @test2()
+entry:
+  ; The first call is trivial to inline due to the argument.
+  call void @test2_f(i1 false)
+; CHECK-NOT: @test2_f
+
+  ; The second call is too expensive to inline unless we update the number of
+  ; calls after inlining the second.
+  call void @test2_f(i1 true)
+; CHECK-NOT: @test2_f
+
+  ; Sanity check that two calls with the hard predicate remain uninlined.
+  call void @test2_g(i1 true)
+  call void @test2_g(i1 true)
+; CHECK: call void @test2_g(i1 true)
+; CHECK: call void @test2_g(i1 true)
+
+  ret void
+}
+
+
+; The 'test3_' prefixed functions are similar to the 'test2_' functions but the
+; relative order of the trivial and hard to inline callsites is reversed. This
+; checks that the order of calls isn't significant to whether we observe the
+; "last callsite" threshold difference because the next-to-last gets inlined.
+; FIXME: We don't currently catch this case.
+
+define internal void @test3_f(i1 %b) {
+entry:
+  %p = alloca i32
+  br i1 %b, label %then, label %exit
+
+then:
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Identical to @test3_f but doesn't get inlined because there is more than one
+; call. If this *does* get inlined, the body used both here and in @test3_f
+; isn't a good test for different threshold based on the last call.
+define internal void @test3_g(i1 %b) {
+entry:
+  %p = alloca i32
+  br i1 %b, label %then, label %exit
+
+then:
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test3() {
+; CHECK-LABEL: define void @test3()
+entry:
+  ; The first call is too expensive to inline unless we update the number of
+  ; calls after inlining the second.
+  call void @test3_f(i1 true)
+; FIXME: We should inline this call without iteration.
+; CHECK: call void @test3_f(i1 true)
+
+  ; But the second call is trivial to inline due to the argument.
+  call void @test3_f(i1 false)
+; CHECK-NOT: @test3_f
+
+  ; Sanity check that two calls with the hard predicate remain uninlined.
+  call void @test3_g(i1 true)
+  call void @test3_g(i1 true)
+; CHECK: call void @test3_g(i1 true)
+; CHECK: call void @test3_g(i1 true)
+
+  ret void
+}
+
+
+; The 'test4_' prefixed functions are similar to the 'test2_' prefixed
+; functions but include unusual constant expressions that make discovering that
+; a function is dead harder.
+
+define internal void @test4_f(i1 %b) {
+entry:
+  %p = alloca i32
+  br i1 %b, label %then, label %exit
+
+then:
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Identical to @test4_f but doesn't get inlined because there is more than one
+; call. If this *does* get inlined, the body used both here and in @test4_f
+; isn't a good test for different threshold based on the last call.
+define internal void @test4_g(i1 %b) {
+entry:
+  %p = alloca i32
+  br i1 %b, label %then, label %exit
+
+then:
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  store volatile i32 0, i32* %p
+  br label %exit
+
+exit:
+  ret void
+}
+
+define void @test4() {
+; CHECK-LABEL: define void @test4()
+entry:
+  ; The first call is trivial to inline due to the argument. However this
+  ; argument also uses the function being called as part of a complex
+  ; constant expression. Merely inlining and deleting the call isn't enough to
+  ; drop the use count here, we need to GC the dead constant expression as
+  ; well.
+  call void @test4_f(i1 icmp ne (i64 ptrtoint (void (i1)* @test4_f to i64), i64 ptrtoint(void (i1)* @test4_f to i64)))
+; CHECK-NOT: @test4_f
+
+  ; The second call is too expensive to inline unless we update the number of
+  ; calls after inlining the second.
+  call void @test4_f(i1 true)
+; CHECK-NOT: @test4_f
+
+  ; And check that a single call to a function which is used by a complex
+  ; constant expression cannot be inlined because the constant expression forms
+  ; a second use. If this part starts failing we need to use more complex
+  ; constant expressions to reference a particular function with them.
+  %sink = alloca i1
+  store volatile i1 icmp ne (i64 ptrtoint (void (i1)* @test4_g to i64), i64 ptrtoint(void (i1)* @test4_g to i64)), i1* %sink
+  call void @test4_g(i1 true)
+; CHECK: store volatile i1 false
+; CHECK: call void @test4_g(i1 true)
+
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/launder.invariant.group.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/launder.invariant.group.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/launder.invariant.group.ll (added)
+++ llvm/trunk/test/Transforms/Inline/launder.invariant.group.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -S -inline < %s | FileCheck %s
+; RUN: opt -S -O3 < %s | FileCheck %s
+; RUN: opt -S -inline -inline-threshold=1 < %s | FileCheck %s
+
+%struct.A = type <{ i32 (...)**, i32, [4 x i8] }>
+
+; This test checks if value returned from the launder is considered aliasing
+; with its argument.  Due to bug caused by handling launder in capture tracking
+; sometimes it would be considered noalias.
+; CHECK-LABEL: define i32 @bar(%struct.A* noalias
+define i32 @bar(%struct.A* noalias) {
+; CHECK-NOT: noalias
+  %2 = bitcast %struct.A* %0 to i8*
+  %3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %2)
+  %4 = getelementptr inbounds i8, i8* %3, i64 8
+  %5 = bitcast i8* %4 to i32*
+  store i32 42, i32* %5, align 8
+  %6 = getelementptr inbounds %struct.A, %struct.A* %0, i64 0, i32 1
+  %7 = load i32, i32* %6, align 8
+  ret i32 %7
+}
+
+; CHECK-LABEL: define i32 @foo(%struct.A* noalias
+define i32 @foo(%struct.A* noalias)  {
+  ; CHECK-NOT: call i32 @bar(
+  ; CHECK-NOT: noalias
+  %2 = tail call i32 @bar(%struct.A* %0)
+  ret i32 %2
+}
+
+
+; This test checks if invariant group intrinsics have zero cost for inlining.
+; CHECK-LABEL: define i8* @caller(i8*
+define i8* @caller(i8* %p) {
+; CHECK-NOT: call i8* @lot_of_launders_and_strips
+  %a1 = call i8* @lot_of_launders_and_strips(i8* %p)
+  %a2 = call i8* @lot_of_launders_and_strips(i8* %a1)
+  %a3 = call i8* @lot_of_launders_and_strips(i8* %a2)
+  %a4 = call i8* @lot_of_launders_and_strips(i8* %a3)
+  ret i8* %a4
+}
+
+define i8* @lot_of_launders_and_strips(i8* %p) {
+  %a1 = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
+  %a2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %a1)
+  %a3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %a2)
+  %a4 = call i8* @llvm.launder.invariant.group.p0i8(i8* %a3)
+
+  %s1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a4)
+  %s2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %s1)
+  %s3 = call i8* @llvm.strip.invariant.group.p0i8(i8* %s2)
+  %s4 = call i8* @llvm.strip.invariant.group.p0i8(i8* %s3)
+
+   ret i8* %s4
+}
+
+
+declare i8* @llvm.launder.invariant.group.p0i8(i8*)
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)

Added: llvm/trunk/test/Transforms/Inline/lifetime-no-datalayout.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/lifetime-no-datalayout.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/lifetime-no-datalayout.ll (added)
+++ llvm/trunk/test/Transforms/Inline/lifetime-no-datalayout.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+declare void @use(i8* %a)
+
+define void @helper() {
+  %a = alloca i8
+  call void @use(i8* %a)
+  ret void
+}
+
+; Size in llvm.lifetime.X should be 1 (default for i8).
+define void @test() {
+; CHECK-LABEL: @test(
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.start.p0i8(i64 1
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.end.p0i8(i64 1
+  call void @helper()
+; CHECK-NOT: lifetime
+; CHECK: ret void
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/lifetime.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/lifetime.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/lifetime.ll (added)
+++ llvm/trunk/test/Transforms/Inline/lifetime.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,118 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -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-S128"
+
+declare void @llvm.lifetime.start.p0i8(i64, i8*)
+declare void @llvm.lifetime.end.p0i8(i64, i8*)
+
+define void @helper_both_markers() {
+  %a = alloca i8
+  ; Size in llvm.lifetime.start / llvm.lifetime.end differs from
+  ; allocation size. We should use the former.
+  call void @llvm.lifetime.start.p0i8(i64 2, i8* %a)
+  call void @llvm.lifetime.end.p0i8(i64 2, i8* %a)
+  ret void
+}
+
+define void @test_both_markers() {
+; CHECK-LABEL: @test_both_markers(
+; CHECK: llvm.lifetime.start.p0i8(i64 2
+; CHECK-NEXT: llvm.lifetime.end.p0i8(i64 2
+  call void @helper_both_markers()
+; CHECK-NEXT: llvm.lifetime.start.p0i8(i64 2
+; CHECK-NEXT: llvm.lifetime.end.p0i8(i64 2
+  call void @helper_both_markers()
+; CHECK-NEXT: ret void
+  ret void
+}
+
+;; Without this, the inliner will simplify out @test_no_marker before adding
+;; any lifetime markers.
+declare void @use(i8* %a)
+
+define void @helper_no_markers() {
+  %a = alloca i8 ; Allocation size is 1 byte.
+  call void @use(i8* %a)
+  ret void
+}
+
+;; We can't use CHECK-NEXT because there's an extra call void @use in between.
+;; Instead, we use CHECK-NOT to verify that there are no other lifetime calls.
+define void @test_no_marker() {
+; CHECK-LABEL: @test_no_marker(
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.start.p0i8(i64 1
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.end.p0i8(i64 1
+  call void @helper_no_markers()
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.start.p0i8(i64 1
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.end.p0i8(i64 1
+  call void @helper_no_markers()
+; CHECK-NOT: lifetime
+; CHECK: ret void
+  ret void
+}
+
+define void @helper_two_casts() {
+  %a = alloca i32
+  %b = bitcast i32* %a to i8*
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* %b)
+  %c = bitcast i32* %a to i8*
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* %c)
+  ret void
+}
+
+define void @test_two_casts() {
+; CHECK-LABEL: @test_two_casts(
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.start.p0i8(i64 4
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.end.p0i8(i64 4
+  call void @helper_two_casts()
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.start.p0i8(i64 4
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.end.p0i8(i64 4
+  call void @helper_two_casts()
+; CHECK-NOT: lifetime
+; CHECK: ret void
+  ret void
+}
+
+define void @helper_arrays_alloca() {
+  %a = alloca [10 x i32], align 16
+  %1 = bitcast [10 x i32]* %a to i8*
+  call void @use(i8* %1)
+  ret void
+}
+
+define void @test_arrays_alloca() {
+; CHECK-LABEL: @test_arrays_alloca(
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.start.p0i8(i64 40,
+; CHECK-NOT: lifetime
+; CHECK: llvm.lifetime.end.p0i8(i64 40,
+  call void @helper_arrays_alloca()
+; CHECK-NOT: lifetime
+; CHECK: ret void
+  ret void
+}
+
+%swift.error = type opaque
+
+define void @helper_swifterror_alloca() {
+entry:
+  %swifterror = alloca swifterror %swift.error*, align 8
+  store %swift.error* null, %swift.error** %swifterror, align 8
+  ret void
+}
+
+define void @test_swifterror_alloca() {
+; CHECK-LABEL: @test_swifterror_alloca(
+; CHECK-NOT: lifetime
+  call void @helper_swifterror_alloca()
+; CHECK: ret void
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/local-as-metadata-undominated-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/local-as-metadata-undominated-use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/local-as-metadata-undominated-use.ll (added)
+++ llvm/trunk/test/Transforms/Inline/local-as-metadata-undominated-use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+; Make sure the inliner doesn't crash when a metadata-bridged SSA operand is an
+; undominated use.
+;
+; If we ever add a verifier check to prevent the scenario in this file, it's
+; fine to delete this testcase.  However, we would need a bitcode upgrade since
+; such historical IR exists in practice.
+
+define i32 @foo(i32 %i) !dbg !4 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 %add, metadata !8, metadata !10), !dbg !11
+  %add = add nsw i32 1, %i, !dbg !12
+  ret i32 %add, !dbg !13
+}
+
+; CHECK-LABEL: define i32 @caller(
+define i32 @caller(i32 %i) {
+; CHECK-NEXT: entry:
+entry:
+; Although the inliner shouldn't crash, it can't be expected to get the
+; "correct" SSA value since its assumptions have been violated.
+; CHECK-NEXT:   tail call void @llvm.dbg.value(metadata ![[EMPTY:[0-9]+]],
+; CHECK-NEXT:   %{{.*}} = add nsw
+  %call = tail call i32 @foo(i32 %i)
+  ret i32 %call
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 265634) (llvm/trunk 265637)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "t.c", directory: "/path/to/tests")
+
+; CHECK: ![[EMPTY]] = !{}
+!2 = !{}
+!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7, !7}
+!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !DILocalVariable(name: "add", arg: 1, scope: !4, file: !1, line: 2, type: !7)
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !DIExpression()
+!11 = !DILocation(line: 2, column: 13, scope: !4)
+!12 = !DILocation(line: 2, column: 27, scope: !4)
+!13 = !DILocation(line: 2, column: 18, scope: !4)

Added: llvm/trunk/test/Transforms/Inline/monster_scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/monster_scc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/monster_scc.ll (added)
+++ llvm/trunk/test/Transforms/Inline/monster_scc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,432 @@
+; This test creates a monster SCC with a very pernicious call graph. It builds
+; a cycle of cross-connected pairs of functions with interesting inlining
+; decisions throughout, but ultimately trivial code complexity.
+;
+; Typically, a greedy approach to inlining works well for bottom-up inliners
+; such as LLVM's. However, there is no way to be bottom-up over an SCC: it's
+; a cycle! Greedily inlining as much as possible into each function of this
+; *SCC* will have the disasterous effect of inlining all N-1 functions into the
+; first one visited, N-2 functions into the second one visited, N-3 into the
+; third, and so on. This is because until inlining occurs, each function in
+; isolation appears to be an excellent inline candidate.
+;
+; Note that the exact number of calls in each function doesn't really matter.
+; It is mostly a function of cost thresholds and visit order. Because this is an
+; SCC there is no "right" or "wrong" answer here as long as no function blows up
+; to be *huge*. The specific concerning pattern is if one or more functions get
+; more than 16 calls in them.
+;
+; This test is extracted from the following C++ program compiled with Clang.
+; The IR is simplified with SROA, instcombine, and simplify-cfg. Then C++
+; linkage stuff, attributes, target specific things, metadata and comments were
+; removed. The order of the fuctions is also made more predictable than Clang's
+; output order.
+;
+;   void g(int);
+;
+;   template <bool K, int N> void f(bool *B, bool *E) {
+;     if (K)
+;       g(N);
+;     if (B == E)
+;       return;
+;     if (*B)
+;       f<true, N + 1>(B + 1, E);
+;     else
+;       f<false, N + 1>(B + 1, E);
+;   }
+;   template <> void f<false, MAX>(bool *B, bool *E) { return f<false, 0>(B, E); }
+;   template <> void f<true, MAX>(bool *B, bool *E) { return f<true, 0>(B, E); }
+;
+;   void test(bool *B, bool *E) { f<false, 0>(B, E); }
+;
+; RUN: opt -S < %s -inline -inline-threshold=150 | FileCheck %s --check-prefixes=CHECK,OLD
+; RUN: opt -S < %s -passes=inline -inline-threshold=150 | FileCheck %s --check-prefixes=CHECK,NEW
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+declare void @_Z1gi(i32)
+
+; CHECK-LABEL: define void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi1EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi2EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi2EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi2EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi2EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb0ELi0EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi1EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi1EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi1EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi1EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi2EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi2EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb1ELi0EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1gi(i32 0)
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi1EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi1EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb0ELi1EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi2EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi2EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi3EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi3EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb0ELi1EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi2EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi2EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb1ELi1EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi2EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi3EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi3EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi3EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi3EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb1ELi1EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1gi(i32 1)
+  %cmp = icmp eq i8* %B, %E
+; CHECK-NOT: call
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi2EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi2EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb0ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi0EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi0EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi4EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi4EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb0ELi2EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi3EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi3EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb1ELi2EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1gi(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi4EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi4EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi4EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi4EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb1ELi2EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1gi(i32 2)
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi3EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi3EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb0ELi3EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb0ELi0EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi1EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi1EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi0EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb0ELi3EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi4EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi4EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb1ELi3EEvPbS0_(
+; CHECK-NOT: call
+; CHECK: call void @_Z1gi(
+; CHECK-NOT: call
+; CHECK: call void @_Z1fILb1ELi0EEvPbS0_(
+; CHECK-NOT: call
+; CHECK: call void @_Z1fILb0ELi0EEvPbS0_(
+; CHECK-NOT: call
+define void @_Z1fILb1ELi3EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1gi(i32 3)
+  %cmp = icmp eq i8* %B, %E
+  br i1 %cmp, label %if.end3, label %if.end
+
+if.end:
+  %0 = load i8, i8* %B, align 1
+  %tobool = icmp eq i8 %0, 0
+  %add.ptr2 = getelementptr inbounds i8, i8* %B, i64 1
+  br i1 %tobool, label %if.else, label %if.then1
+
+if.then1:
+  call void @_Z1fILb1ELi4EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.else:
+  call void @_Z1fILb0ELi4EEvPbS0_(i8* %add.ptr2, i8* %E)
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb0ELi4EEvPbS0_(
+; CHECK-NOT: call
+; CHECK: call void @_Z1fILb0ELi0EEvPbS0_(
+; CHECK-NOT: call
+define void @_Z1fILb0ELi4EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1fILb0ELi0EEvPbS0_(i8* %B, i8* %E)
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z1fILb1ELi4EEvPbS0_(
+; OLD-NOT: call
+; OLD: call void @_Z1fILb1ELi0EEvPbS0_(
+; OLD-NOT: call
+; NEW-NOT: call
+; NEW: call void @_Z1gi(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb1ELi1EEvPbS0_(
+; NEW-NOT: call
+; NEW: call void @_Z1fILb0ELi1EEvPbS0_(
+; NEW-NOT: call
+define void @_Z1fILb1ELi4EEvPbS0_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1fILb1ELi0EEvPbS0_(i8* %B, i8* %E)
+  ret void
+}
+
+; CHECK-LABEL: define void @_Z4testPbS_(
+; CHECK: call
+; CHECK-NOT: call
+define void @_Z4testPbS_(i8* %B, i8* %E) {
+entry:
+  call void @_Z1fILb0ELi0EEvPbS0_(i8* %B, i8* %E)
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/nested-inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/nested-inline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/nested-inline.ll (added)
+++ llvm/trunk/test/Transforms/Inline/nested-inline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+; Test that bar and bar2 are both inlined throughout and removed.
+ at A = weak global i32 0		; <i32*> [#uses=1]
+ at B = weak global i32 0		; <i32*> [#uses=1]
+ at C = weak global i32 0		; <i32*> [#uses=1]
+
+define fastcc void @foo(i32 %X) {
+entry:
+; CHECK-LABEL: @foo(
+	%ALL = alloca i32, align 4		; <i32*> [#uses=1]
+	%tmp1 = and i32 %X, 1		; <i32> [#uses=1]
+	%tmp1.upgrd.1 = icmp eq i32 %tmp1, 0		; <i1> [#uses=1]
+	br i1 %tmp1.upgrd.1, label %cond_next, label %cond_true
+
+cond_true:		; preds = %entry
+	store i32 1, i32* @A
+	br label %cond_next
+
+cond_next:		; preds = %cond_true, %entry
+	%tmp4 = and i32 %X, 2		; <i32> [#uses=1]
+	%tmp4.upgrd.2 = icmp eq i32 %tmp4, 0		; <i1> [#uses=1]
+	br i1 %tmp4.upgrd.2, label %cond_next7, label %cond_true5
+
+cond_true5:		; preds = %cond_next
+	store i32 1, i32* @B
+	br label %cond_next7
+
+cond_next7:		; preds = %cond_true5, %cond_next
+	%tmp10 = and i32 %X, 4		; <i32> [#uses=1]
+	%tmp10.upgrd.3 = icmp eq i32 %tmp10, 0		; <i1> [#uses=1]
+	br i1 %tmp10.upgrd.3, label %cond_next13, label %cond_true11
+
+cond_true11:		; preds = %cond_next7
+	store i32 1, i32* @C
+	br label %cond_next13
+
+cond_next13:		; preds = %cond_true11, %cond_next7
+	%tmp16 = and i32 %X, 8		; <i32> [#uses=1]
+	%tmp16.upgrd.4 = icmp eq i32 %tmp16, 0		; <i1> [#uses=1]
+	br i1 %tmp16.upgrd.4, label %UnifiedReturnBlock, label %cond_true17
+
+cond_true17:		; preds = %cond_next13
+	call void @ext( i32* %ALL )
+	ret void
+
+UnifiedReturnBlock:		; preds = %cond_next13
+	ret void
+}
+
+; CHECK-NOT: @bar(
+define internal fastcc void @bar(i32 %X) {
+entry:
+	%ALL = alloca i32, align 4		; <i32*> [#uses=1]
+	%tmp1 = and i32 %X, 1		; <i32> [#uses=1]
+	%tmp1.upgrd.1 = icmp eq i32 %tmp1, 0		; <i1> [#uses=1]
+	br i1 %tmp1.upgrd.1, label %cond_next, label %cond_true
+
+cond_true:		; preds = %entry
+	store i32 1, i32* @A
+	br label %cond_next
+
+cond_next:		; preds = %cond_true, %entry
+	%tmp4 = and i32 %X, 2		; <i32> [#uses=1]
+	%tmp4.upgrd.2 = icmp eq i32 %tmp4, 0		; <i1> [#uses=1]
+	br i1 %tmp4.upgrd.2, label %cond_next7, label %cond_true5
+
+cond_true5:		; preds = %cond_next
+	store i32 1, i32* @B
+	br label %cond_next7
+
+cond_next7:		; preds = %cond_true5, %cond_next
+	%tmp10 = and i32 %X, 4		; <i32> [#uses=1]
+	%tmp10.upgrd.3 = icmp eq i32 %tmp10, 0		; <i1> [#uses=1]
+	br i1 %tmp10.upgrd.3, label %cond_next13, label %cond_true11
+
+cond_true11:		; preds = %cond_next7
+	store i32 1, i32* @C
+	br label %cond_next13
+
+cond_next13:		; preds = %cond_true11, %cond_next7
+	%tmp16 = and i32 %X, 8		; <i32> [#uses=1]
+	%tmp16.upgrd.4 = icmp eq i32 %tmp16, 0		; <i1> [#uses=1]
+	br i1 %tmp16.upgrd.4, label %UnifiedReturnBlock, label %cond_true17
+
+cond_true17:		; preds = %cond_next13
+	call void @foo( i32 %X )
+	ret void
+
+UnifiedReturnBlock:		; preds = %cond_next13
+	ret void
+}
+
+define internal fastcc void @bar2(i32 %X) {
+entry:
+	call void @foo( i32 %X )
+	ret void
+}
+
+declare void @ext(i32*)
+
+define void @test(i32 %X) {
+entry:
+; CHECK: test
+; CHECK-NOT: @bar(
+	tail call fastcc void @bar( i32 %X )
+	tail call fastcc void @bar( i32 %X )
+	tail call fastcc void @bar2( i32 %X )
+	tail call fastcc void @bar2( i32 %X )
+	ret void
+; CHECK: ret
+}

Added: llvm/trunk/test/Transforms/Inline/noalias-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noalias-calls.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/noalias-calls.ll (added)
+++ llvm/trunk/test/Transforms/Inline/noalias-calls.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -basicaa -inline -enable-noalias-to-md-conversion -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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) #0
+declare void @hey() #0
+
+define void @hello(i8* noalias nocapture %a, i8* noalias nocapture readonly %c, i8* nocapture %b) #1 {
+entry:
+  %l = alloca i8, i32 512, align 1
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %b, i64 16, i1 0)
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %b, i8* align 16 %c, i64 16, i1 0)
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %c, i64 16, i1 0)
+  call void @hey()
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %l, i8* align 16 %c, i64 16, i1 0)
+  ret void
+}
+
+define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 {
+entry:
+  tail call void @hello(i8* %a, i8* %c, i8* %b)
+  ret void
+}
+
+; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 {
+; CHECK: entry:
+; CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %b, i64 16, i1 false) #1, !noalias !0
+; CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %b, i8* align 16 %c, i64 16, i1 false) #1, !noalias !3
+; CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %c, i64 16, i1 false) #1, !alias.scope !5
+; CHECK:   call void @hey() #1, !noalias !5
+; CHECK:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %{{.*}}, i8* align 16 %c, i64 16, i1 false) #1, !noalias !3
+; CHECK:   ret void
+; CHECK: }
+
+attributes #0 = { nounwind argmemonly }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind uwtable }
+
+; CHECK: !0 = !{!1}
+; CHECK: !1 = distinct !{!1, !2, !"hello: %c"}
+; CHECK: !2 = distinct !{!2, !"hello"}
+; CHECK: !3 = !{!4}
+; CHECK: !4 = distinct !{!4, !2, !"hello: %a"}
+; CHECK: !5 = !{!4, !1}
+

Added: llvm/trunk/test/Transforms/Inline/noalias-cs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noalias-cs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/noalias-cs.ll (added)
+++ llvm/trunk/test/Transforms/Inline/noalias-cs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,84 @@
+; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s
+target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4, !noalias !3
+  %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+  store float %0, float* %arrayidx.i, align 4, !alias.scope !7, !noalias !8
+  %arrayidx1.i = getelementptr inbounds float, float* %b, i64 8
+  store float %0, float* %arrayidx1.i, align 4, !alias.scope !8, !noalias !7
+  %1 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %1, float* %arrayidx, align 4
+  ret void
+}
+
+define void @foo(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  call void @foo2(float* %a, float* %b, float* %c), !noalias !0
+  call void @foo2(float* %b, float* %b, float* %a), !alias.scope !0
+  ret void
+}
+
+; CHECK: define void @foo(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %0 = load float, float* %c, align 4, !noalias !6
+; CHECK:   %arrayidx.i.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i.i, align 4, !alias.scope !12, !noalias !13
+; CHECK:   %arrayidx1.i.i = getelementptr inbounds float, float* %b, i64 8
+; CHECK:   store float %0, float* %arrayidx1.i.i, align 4, !alias.scope !14, !noalias !15
+; CHECK:   %1 = load float, float* %c, align 4, !noalias !16
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx.i, align 4, !noalias !16
+; CHECK:   %2 = load float, float* %a, align 4, !alias.scope !16, !noalias !17
+; CHECK:   %arrayidx.i.i1 = getelementptr inbounds float, float* %b, i64 5
+; CHECK:   store float %2, float* %arrayidx.i.i1, align 4, !alias.scope !21, !noalias !22
+; CHECK:   %arrayidx1.i.i2 = getelementptr inbounds float, float* %b, i64 8
+; CHECK:   store float %2, float* %arrayidx1.i.i2, align 4, !alias.scope !23, !noalias !24
+; CHECK:   %3 = load float, float* %a, align 4, !alias.scope !16
+; CHECK:   %arrayidx.i3 = getelementptr inbounds float, float* %b, i64 7
+; CHECK:   store float %3, float* %arrayidx.i3, align 4, !alias.scope !16
+; CHECK:   ret void
+; CHECK: }
+
+attributes #0 = { nounwind uwtable }
+
+!0 = !{!1}
+!1 = distinct !{!1, !2, !"hello: %a"}
+!2 = distinct !{!2, !"hello"}
+!3 = !{!4, !6}
+!4 = distinct !{!4, !5, !"hello2: %a"}
+!5 = distinct !{!5, !"hello2"}
+!6 = distinct !{!6, !5, !"hello2: %b"}
+!7 = !{!4}
+!8 = !{!6}
+
+; CHECK: !0 = !{!1, !3}
+; CHECK: !1 = distinct !{!1, !2, !"hello2: %a"}
+; CHECK: !2 = distinct !{!2, !"hello2"}
+; CHECK: !3 = distinct !{!3, !2, !"hello2: %b"}
+; CHECK: !4 = !{!1}
+; CHECK: !5 = !{!3}
+; CHECK: !6 = !{!7, !9, !10}
+; CHECK: !7 = distinct !{!7, !8, !"hello2: %a"}
+; CHECK: !8 = distinct !{!8, !"hello2"}
+; CHECK: !9 = distinct !{!9, !8, !"hello2: %b"}
+; CHECK: !10 = distinct !{!10, !11, !"hello: %a"}
+; CHECK: !11 = distinct !{!11, !"hello"}
+; CHECK: !12 = !{!7}
+; CHECK: !13 = !{!9, !10}
+; CHECK: !14 = !{!9}
+; CHECK: !15 = !{!7, !10}
+; CHECK: !16 = !{!10}
+; CHECK: !17 = !{!18, !20}
+; CHECK: !18 = distinct !{!18, !19, !"hello2: %a"}
+; CHECK: !19 = distinct !{!19, !"hello2"}
+; CHECK: !20 = distinct !{!20, !19, !"hello2: %b"}
+; CHECK: !21 = !{!18, !10}
+; CHECK: !22 = !{!20}
+; CHECK: !23 = !{!20, !10}
+; CHECK: !24 = !{!18}
+

Added: llvm/trunk/test/Transforms/Inline/noalias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noalias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/noalias.ll (added)
+++ llvm/trunk/test/Transforms/Inline/noalias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,76 @@
+; RUN: opt -inline -enable-noalias-to-md-conversion -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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @hello(float* noalias nocapture %a, float* nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 5
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 {
+entry:
+  tail call void @hello(float* %a, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %0 = load float, float* %c, align 4, !noalias !0
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i, align 4, !alias.scope !0
+; CHECK:   %1 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 5
+  store float %0, float* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds float, float* %b, i64 8
+  store float %0, float* %arrayidx1, align 4
+  ret void
+}
+
+define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  tail call void @hello2(float* %a, float* %b, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %0 = load float, float* %c, align 4, !noalias !3
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i, align 4, !alias.scope !7, !noalias !8
+; CHECK:   %arrayidx1.i = getelementptr inbounds float, float* %b, i64 8
+; CHECK:   store float %0, float* %arrayidx1.i, align 4, !alias.scope !8, !noalias !7
+; CHECK:   %1 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+attributes #0 = { nounwind uwtable }
+
+; CHECK: !0 = !{!1}
+; CHECK: !1 = distinct !{!1, !2, !"hello: %a"}
+; CHECK: !2 = distinct !{!2, !"hello"}
+; CHECK: !3 = !{!4, !6}
+; CHECK: !4 = distinct !{!4, !5, !"hello2: %a"}
+; CHECK: !5 = distinct !{!5, !"hello2"}
+; CHECK: !6 = distinct !{!6, !5, !"hello2: %b"}
+; CHECK: !7 = !{!4}
+; CHECK: !8 = !{!6}
+

Added: llvm/trunk/test/Transforms/Inline/noalias2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noalias2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/noalias2.ll (added)
+++ llvm/trunk/test/Transforms/Inline/noalias2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,97 @@
+; RUN: opt -inline -enable-noalias-to-md-conversion -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-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @hello(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 5
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 {
+entry:
+  tail call void @hello(float* %a, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %0 = load float, float* %c, align 4, !alias.scope !0, !noalias !3
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i, align 4, !alias.scope !3, !noalias !0
+; CHECK:   %1 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 6
+  store float %0, float* %arrayidx, align 4
+  %arrayidx1 = getelementptr inbounds float, float* %b, i64 8
+  store float %0, float* %arrayidx1, align 4
+  ret void
+}
+
+; Check that when hello() is inlined into foo(), and then foo() is inlined into
+; foo2(), the noalias scopes are properly concatenated.
+define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+entry:
+  tail call void @foo(float* %a, float* %c)
+  tail call void @hello2(float* %a, float* %b, float* %c)
+  %0 = load float, float* %c, align 4
+  %arrayidx = getelementptr inbounds float, float* %a, i64 7
+  store float %0, float* %arrayidx, align 4
+  ret void
+}
+
+; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
+; CHECK: entry:
+; CHECK:   %0 = load float, float* %c, align 4, !alias.scope !5, !noalias !10
+; CHECK:   %arrayidx.i.i = getelementptr inbounds float, float* %a, i64 5
+; CHECK:   store float %0, float* %arrayidx.i.i, align 4, !alias.scope !10, !noalias !5
+; CHECK:   %1 = load float, float* %c, align 4, !alias.scope !13, !noalias !14
+; CHECK:   %arrayidx.i = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %1, float* %arrayidx.i, align 4, !alias.scope !14, !noalias !13
+; CHECK:   %2 = load float, float* %c, align 4, !noalias !15
+; CHECK:   %arrayidx.i1 = getelementptr inbounds float, float* %a, i64 6
+; CHECK:   store float %2, float* %arrayidx.i1, align 4, !alias.scope !19, !noalias !20
+; CHECK:   %arrayidx1.i = getelementptr inbounds float, float* %b, i64 8
+; CHECK:   store float %2, float* %arrayidx1.i, align 4, !alias.scope !20, !noalias !19
+; CHECK:   %3 = load float, float* %c, align 4
+; CHECK:   %arrayidx = getelementptr inbounds float, float* %a, i64 7
+; CHECK:   store float %3, float* %arrayidx, align 4
+; CHECK:   ret void
+; CHECK: }
+
+; CHECK: !0 = !{!1}
+; CHECK: !1 = distinct !{!1, !2, !"hello: %c"}
+; CHECK: !2 = distinct !{!2, !"hello"}
+; CHECK: !3 = !{!4}
+; CHECK: !4 = distinct !{!4, !2, !"hello: %a"}
+; CHECK: !5 = !{!6, !8}
+; CHECK: !6 = distinct !{!6, !7, !"hello: %c"}
+; CHECK: !7 = distinct !{!7, !"hello"}
+; CHECK: !8 = distinct !{!8, !9, !"foo: %c"}
+; CHECK: !9 = distinct !{!9, !"foo"}
+; CHECK: !10 = !{!11, !12}
+; CHECK: !11 = distinct !{!11, !7, !"hello: %a"}
+; CHECK: !12 = distinct !{!12, !9, !"foo: %a"}
+; CHECK: !13 = !{!8}
+; CHECK: !14 = !{!12}
+; CHECK: !15 = !{!16, !18}
+; CHECK: !16 = distinct !{!16, !17, !"hello2: %a"}
+; CHECK: !17 = distinct !{!17, !"hello2"}
+; CHECK: !18 = distinct !{!18, !17, !"hello2: %b"}
+; CHECK: !19 = !{!16}
+; CHECK: !20 = !{!18}
+
+attributes #0 = { nounwind uwtable }
+

Added: llvm/trunk/test/Transforms/Inline/noinline-recursive-fn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noinline-recursive-fn.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/noinline-recursive-fn.ll (added)
+++ llvm/trunk/test/Transforms/Inline/noinline-recursive-fn.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,111 @@
+; The inliner should never inline recursive functions into other functions.
+; This effectively is just peeling off the first iteration of a loop, and the
+; inliner heuristics are not set up for this.
+
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -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.3"
+
+ at g = common global i32 0                          ; <i32*> [#uses=1]
+
+define internal void @foo(i32 %x) nounwind ssp {
+entry:
+  %0 = icmp slt i32 %x, 0                         ; <i1> [#uses=1]
+  br i1 %0, label %return, label %bb
+
+bb:                                               ; preds = %entry
+  %1 = sub nsw i32 %x, 1                          ; <i32> [#uses=1]
+  call void @foo(i32 %1) nounwind ssp
+  store volatile i32 1, i32* @g, align 4
+  ret void
+
+return:                                           ; preds = %entry
+  ret void
+}
+
+
+;; CHECK-LABEL: @bonk(
+;; CHECK: call void @foo(i32 42)
+define void @bonk() nounwind ssp {
+entry:
+  call void @foo(i32 42) nounwind ssp
+  ret void
+}
+
+
+
+;; Here is an indirect case that should not be infinitely inlined.
+
+define internal void @f1(i32 %x, i8* %Foo, i8* %Bar) nounwind ssp {
+entry:
+  %0 = bitcast i8* %Bar to void (i32, i8*, i8*)*
+  %1 = sub nsw i32 %x, 1
+  call void %0(i32 %1, i8* %Foo, i8* %Bar) nounwind
+  store volatile i32 42, i32* @g, align 4
+  ret void
+}
+
+define internal void @f2(i32 %x, i8* %Foo, i8* %Bar) nounwind ssp {
+entry:
+  %0 = icmp slt i32 %x, 0                         ; <i1> [#uses=1]
+  br i1 %0, label %return, label %bb
+
+bb:                                               ; preds = %entry
+  %1 = bitcast i8* %Foo to void (i32, i8*, i8*)*  ; <void (i32, i8*, i8*)*> [#uses=1]
+  call void %1(i32 %x, i8* %Foo, i8* %Bar) nounwind
+  store volatile i32 13, i32* @g, align 4
+  ret void
+
+return:                                           ; preds = %entry
+  ret void
+}
+
+
+; CHECK-LABEL: @top_level(
+; CHECK: call void @f2(i32 122
+; Here we inline one instance of the cycle, but we don't want to completely
+; unroll it.
+define void @top_level() nounwind ssp {
+entry:
+  call void @f2(i32 123, i8* bitcast (void (i32, i8*, i8*)* @f1 to i8*), i8* bitcast (void (i32, i8*, i8*)* @f2 to i8*)) nounwind ssp
+  ret void
+}
+
+
+; Check that a recursive function, when called with a constant that makes the
+; recursive path dead code can actually be inlined.
+define i32 @fib(i32 %i) {
+entry:
+  %is.zero = icmp eq i32 %i, 0
+  br i1 %is.zero, label %zero.then, label %zero.else
+
+zero.then:
+  ret i32 0
+
+zero.else:
+  %is.one = icmp eq i32 %i, 1
+  br i1 %is.one, label %one.then, label %one.else
+
+one.then:
+  ret i32 1
+
+one.else:
+  %i1 = sub i32 %i, 1
+  %f1 = call i32 @fib(i32 %i1)
+  %i2 = sub i32 %i, 2
+  %f2 = call i32 @fib(i32 %i2)
+  %f = add i32 %f1, %f2
+  ret i32 %f
+}
+
+define i32 @fib_caller() {
+; CHECK-LABEL: @fib_caller(
+; CHECK-NOT: call
+; CHECK: ret
+  %f1 = call i32 @fib(i32 0)
+  %f2 = call i32 @fib(i32 1)
+  %result = add i32 %f1, %f2
+  ret i32 %result
+}

Added: llvm/trunk/test/Transforms/Inline/noinline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/noinline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/noinline.ll (added)
+++ llvm/trunk/test/Transforms/Inline/noinline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -inline -S < %s | FileCheck %s
+; PR6682
+declare void @foo() nounwind
+
+define void @bar() nounwind {
+entry:
+    tail call void @foo() nounwind
+    ret void
+}
+
+define void @bazz() nounwind {
+entry:
+    tail call void @bar() nounwind noinline
+    ret void
+}
+
+; CHECK: define void @bazz()
+; CHECK: call void @bar()

Added: llvm/trunk/test/Transforms/Inline/nonnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/nonnull.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/nonnull.ll (added)
+++ llvm/trunk/test/Transforms/Inline/nonnull.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt -S -inline %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' %s | FileCheck %s
+
+declare void @foo()
+declare void @bar()
+
+define void @callee(i8* %arg) {
+  %cmp = icmp eq i8* %arg, null
+  br i1 %cmp, label %expensive, label %done
+
+; This block is designed to be too expensive to inline.  We can only inline
+; callee if this block is known to be dead.
+expensive:
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  call void @foo()
+  ret void
+
+done:
+  call void @bar()
+  ret void
+}
+
+; Positive test - arg is known non null
+define void @caller(i8* nonnull %arg) {
+; CHECK-LABEL: @caller
+; CHECK: call void @bar()
+  call void @callee(i8* nonnull %arg)
+  ret void
+}
+
+; Negative test - arg is not known to be non null
+define void @caller2(i8* %arg) {
+; CHECK-LABEL: @caller2
+; CHECK: call void @callee(
+  call void @callee(i8* %arg)
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/Inline/null-function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/null-function.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/null-function.ll (added)
+++ llvm/trunk/test/Transforms/Inline/null-function.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt -print-before=always-inline -always-inline < %s -o /dev/null 2>&1 | FileCheck %s
+
+define i32 @main() #0 {
+entry:
+  ret i32 0
+}
+
+; CHECK: *** IR Dump Before Inliner for always_inline functions ***
+; CHECK: Printing <null> Function

Added: llvm/trunk/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll (added)
+++ llvm/trunk/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt < %s -S -inline -pass-remarks=inline \
+; RUN:    -pass-remarks-with-hotness 2>&1 | FileCheck %s
+
+; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t -pass-remarks=inline \
+; RUN:    -pass-remarks-with-hotness -pass-remarks-hotness-threshold=1 2>&1 | \
+; RUN:    FileCheck -allow-empty -check-prefix=THRESHOLD %s
+
+; Check that when any threshold is specified we ignore remarks with no
+; hotness -- these are blocks that have not been executed during training.
+
+;  1     int foo() { return 1; }
+;  2
+;  3     int bar() {
+;  4       return foo();
+;  5     }
+
+; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with (cost={{[0-9\-]+}}, threshold={{[0-9]+}})
+; THRESHOLD-NOT: remark
+
+; ModuleID = '/tmp/s.c'
+source_filename = "/tmp/s.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @foo() #0 !dbg !7 {
+entry:
+  ret i32 1, !dbg !9
+}
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @bar() #0 !dbg !10 {
+entry:
+  %call = call i32 @foo(), !dbg !11
+  ret i32 %call, !dbg !12
+}
+
+attributes #0 = { nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 1, column: 13, scope: !7)
+!10 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, retainedNodes: !2)
+!11 = !DILocation(line: 4, column: 10, scope: !10)
+!12 = !DILocation(line: 4, column: 3, scope: !10)

Added: llvm/trunk/test/Transforms/Inline/optimization-remarks-passed-yaml.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/optimization-remarks-passed-yaml.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/optimization-remarks-passed-yaml.ll (added)
+++ llvm/trunk/test/Transforms/Inline/optimization-remarks-passed-yaml.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; RUN: opt < %s -S -inline -pass-remarks-output=%t -pass-remarks=inline \
+; RUN:    -pass-remarks-missed=inline -pass-remarks-analysis=inline \
+; RUN:    -pass-remarks-with-hotness 2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+
+; RUN: opt < %s -S -passes=inline -pass-remarks-output=%t -pass-remarks=inline \
+; RUN:    -pass-remarks-missed=inline -pass-remarks-analysis=inline \
+; RUN:    -pass-remarks-with-hotness 2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+
+; Check the YAML file for inliner-generated passed and analysis remarks.  This
+; is the input:
+
+;  1     int foo() { return 1; }
+;  2
+;  3     int bar() {
+;  4       return foo();
+;  5     }
+
+; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with (cost={{[0-9\-]+}}, threshold={{[0-9]+}}) (hotness: 30)
+
+; YAML:      --- !Passed
+; YAML-NEXT: Pass:            inline
+; YAML-NEXT: Name:            Inlined
+; YAML-NEXT: DebugLoc:        { File: '/tmp/s.c', Line: 4, Column: 10 }
+; YAML-NEXT: Function:        bar
+; YAML-NEXT: Hotness:         30
+; YAML-NEXT: Args:
+; YAML-NEXT:   - Callee: foo
+; YAML-NEXT:     DebugLoc:        { File: '/tmp/s.c', Line: 1, Column: 0 }
+; YAML-NEXT:   - String: ' inlined into '
+; YAML-NEXT:   - Caller: bar
+; YAML-NEXT:     DebugLoc:        { File: '/tmp/s.c', Line: 3, Column: 0 }
+; YAML-NEXT:   - String: ' with '
+; YAML-NEXT:   - String: '(cost='
+; YAML-NEXT:   - Cost: '{{[0-9\-]+}}'
+; YAML-NEXT:   - String: ', threshold='
+; YAML-NEXT:   - Threshold: '{{[0-9]+}}'
+; YAML-NEXT:   - String: ')'
+; YAML-NEXT: ...
+
+; ModuleID = '/tmp/s.c'
+source_filename = "/tmp/s.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @foo() #0 !dbg !7 {
+entry:
+  ret i32 1, !dbg !9
+}
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @bar() #0 !dbg !10 !prof !13 {
+entry:
+  %call = call i32 @foo(), !dbg !11
+  ret i32 %call, !dbg !12
+}
+
+attributes #0 = { nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 1, column: 13, scope: !7)
+!10 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, retainedNodes: !2)
+!11 = !DILocation(line: 4, column: 10, scope: !10)
+!12 = !DILocation(line: 4, column: 3, scope: !10)
+!13 = !{!"function_entry_count", i64 30}

Added: llvm/trunk/test/Transforms/Inline/optimization-remarks-with-hotness.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/optimization-remarks-with-hotness.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/optimization-remarks-with-hotness.ll (added)
+++ llvm/trunk/test/Transforms/Inline/optimization-remarks-with-hotness.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline \
+; RUN:     -pass-remarks-analysis=inline -pass-remarks-with-hotness -S 2>&1 \
+; RUN:     | FileCheck %s
+; RUN: opt < %s -passes=inline -pass-remarks=inline -pass-remarks-missed=inline \
+; RUN:     -pass-remarks-analysis=inline -pass-remarks-with-hotness -S 2>&1 \
+; RUN:     | FileCheck %s
+
+; CHECK: foo inlined into bar with (cost=always): always inline attribute (hotness: 30)
+; CHECK: foz not inlined into bar because it should never be inlined (cost=never): noinline function attribute (hotness: 30)
+
+; Function Attrs: alwaysinline nounwind uwtable
+define i32 @foo() #0 !prof !1 {
+entry:
+  ret i32 4
+}
+
+; Function Attrs: noinline nounwind uwtable
+define i32 @foz() #1 !prof !2 {
+entry:
+  ret i32 2
+}
+
+; Function Attrs: nounwind uwtable
+define i32 @bar() !prof !3 {
+entry:
+  %call = call i32 @foo()
+  %call2 = call i32 @foz()
+  %mul = mul i32 %call, %call2
+  ret i32 %mul
+}
+
+attributes #0 = { alwaysinline }
+attributes #1 = { noinline }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.5.0 "}
+!1 = !{!"function_entry_count", i64 10}
+!2 = !{!"function_entry_count", i64 20}
+!3 = !{!"function_entry_count", i64 30}

Added: llvm/trunk/test/Transforms/Inline/optimization-remarks-yaml.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/optimization-remarks-yaml.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/optimization-remarks-yaml.ll (added)
+++ llvm/trunk/test/Transforms/Inline/optimization-remarks-yaml.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,118 @@
+; RUN: opt < %s -S -inline -pass-remarks-missed=inline \
+; RUN:     -pass-remarks-with-hotness -pass-remarks-hotness-threshold 15 \
+; RUN:     -pass-remarks-output=%t 2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+; RUN: opt < %s -S -inline -pass-remarks-with-hotness -pass-remarks-output=%t
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+;
+; Verify that remarks that don't meet the hotness threshold are not output.
+; RUN: opt < %s -S -inline -pass-remarks-missed=inline \
+; RUN:     -pass-remarks-with-hotness -pass-remarks-hotness-threshold 100 \
+; RUN:     -pass-remarks-output=%t.threshold 2>&1 | \
+; RUN:     FileCheck -check-prefix=THRESHOLD %s
+; RUN: test ! -s %t.threshold
+; RUN: opt < %s -S -inline \
+; RUN:     -pass-remarks-with-hotness -pass-remarks-hotness-threshold 100 \
+; RUN:     -pass-remarks-output=%t.threshold
+; The remarks output file should be empty.
+; RUN: test ! -s %t.threshold
+
+; NewPM:
+; RUN: opt < %s -S -passes=inline -pass-remarks-missed=inline \
+; RUN:     -pass-remarks-with-hotness -pass-remarks-hotness-threshold 15 \
+; RUN:     -pass-remarks-output=%t 2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+; RUN: opt < %s -S -passes=inline -pass-remarks-with-hotness -pass-remarks-output=%t
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+;
+; Verify that remarks that don't meet the hotness threshold are not output.
+; RUN: opt < %s -S -passes=inline -pass-remarks-missed=inline \
+; RUN:     -pass-remarks-with-hotness -pass-remarks-hotness-threshold 100 \
+; RUN:     -pass-remarks-output=%t.threshold 2>&1 | \
+; RUN:     FileCheck -check-prefix=THRESHOLD %s
+; RUN: test ! -s %t.threshold
+; RUN: opt < %s -S -passes=inline \
+; RUN:     -pass-remarks-with-hotness -pass-remarks-hotness-threshold 100 \
+; RUN:     -pass-remarks-output=%t.threshold
+; The remarks output file should be empty.
+; RUN: test ! -s %t.threshold
+
+; Check the YAML file generated for inliner remarks for this program:
+;
+;   1  int foo();
+;   2  int bar();
+;   3
+;   4  int baz() {
+;   5    return foo() + bar();
+;   6  }
+
+; CHECK:      remark: /tmp/s.c:5:10: foo will not be inlined into baz because its definition is unavailable (hotness: 30)
+; CHECK-NEXT: remark: /tmp/s.c:5:18: bar will not be inlined into baz because its definition is unavailable (hotness: 30)
+
+; YAML:      --- !Missed
+; YAML-NEXT: Pass:            inline
+; YAML-NEXT: Name:            NoDefinition
+; YAML-NEXT: DebugLoc:        { File: '/tmp/s.c', Line: 5, Column: 10 }
+; YAML-NEXT: Function:        baz
+; YAML-NEXT: Hotness:         30
+; YAML-NEXT: Args:
+; YAML-NEXT:   - Callee: foo
+; YAML-NEXT:   - String: ' will not be inlined into '
+; YAML-NEXT:   - Caller: baz
+; YAML-NEXT:     DebugLoc:        { File: '/tmp/s.c', Line: 4, Column: 0 }
+; YAML-NEXT:   - String: ' because its definition is unavailable'
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Missed
+; YAML-NEXT: Pass:            inline
+; YAML-NEXT: Name:            NoDefinition
+; YAML-NEXT: DebugLoc:        { File: '/tmp/s.c', Line: 5, Column: 18 }
+; YAML-NEXT: Function:        baz
+; YAML-NEXT: Hotness:         30
+; YAML-NEXT: Args:
+; YAML-NEXT:   - Callee: bar
+; YAML-NEXT:   - String: ' will not be inlined into '
+; YAML-NEXT:   - Caller: baz
+; YAML-NEXT:     DebugLoc:        { File: '/tmp/s.c', Line: 4, Column: 0 }
+; YAML-NEXT:   - String: ' because its definition is unavailable'
+; YAML-NEXT: ...
+
+; No remarks should be output, since none meet the threshold.
+; THRESHOLD-NOT: remark
+
+; ModuleID = '/tmp/s.c'
+source_filename = "/tmp/s.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @"\01baz"() !dbg !7 !prof !14 {
+entry:
+  %call = call i32 (...) @foo(), !dbg !9
+  %call1 = call i32 (...) @"\01bar"(), !dbg !10
+  %add = add nsw i32 %call, %call1, !dbg !12
+  ret i32 %add, !dbg !13
+}
+
+declare i32 @foo(...)
+
+declare i32 @"\01bar"(...)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 281293) (llvm/trunk 281290)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 4.0.0 (trunk 281293) (llvm/trunk 281290)"}
+!7 = distinct !DISubprogram(name: "baz", scope: !1, file: !1, line: 4, type: !8, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 5, column: 10, scope: !7)
+!10 = !DILocation(line: 5, column: 18, scope: !11)
+!11 = !DILexicalBlockFile(scope: !7, file: !1, discriminator: 1)
+!12 = !DILocation(line: 5, column: 16, scope: !7)
+!13 = !DILocation(line: 5, column: 3, scope: !7)
+!14 = !{!"function_entry_count", i64 30}

Added: llvm/trunk/test/Transforms/Inline/optimization-remarks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/optimization-remarks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/optimization-remarks.ll (added)
+++ llvm/trunk/test/Transforms/Inline/optimization-remarks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline \
+; RUN:       -pass-remarks-analysis=inline -S 2>&1 | \
+; RUN:       FileCheck -check-prefix=CHECK -check-prefix=NO_HOTNESS %s
+; RUN: opt < %s -inline -pass-remarks=inline -pass-remarks-missed=inline \
+; RUN:       -pass-remarks-analysis=inline -pass-remarks-with-hotness -S 2>&1 | \
+; RUN:       FileCheck -check-prefix=CHECK -check-prefix=HOTNESS %s
+
+; RUN: opt < %s -passes=inline -pass-remarks=inline -pass-remarks-missed=inline \
+; RUN:       -pass-remarks-analysis=inline -S 2>&1 | \
+; RUN:       FileCheck -check-prefix=CHECK -check-prefix=NO_HOTNESS %s
+; RUN: opt < %s -passes=inline -pass-remarks=inline -pass-remarks-missed=inline \
+; RUN:       -pass-remarks-analysis=inline -pass-remarks-with-hotness -S 2>&1 | \
+; RUN:       FileCheck -check-prefix=CHECK -check-prefix=HOTNESS %s
+
+; HOTNESS: fox will not be inlined into bar because its definition is unavailable
+; NO_HOTNESS-NOT: fox will not be inlined into bar because its definition is unavailable
+; CHECK: foo inlined into bar with (cost=always): always inline attribute
+; CHECK: foz not inlined into bar because it should never be inlined (cost=never): noinline function attribute
+
+; Function Attrs: alwaysinline nounwind uwtable
+define i32 @foo(i32 %x, i32 %y) #0 !prof !1 {
+entry:
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  store i32 %y, i32* %y.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  %1 = load i32, i32* %y.addr, align 4
+  %add = add nsw i32 %0, %1
+  ret i32 %add
+}
+
+; Function Attrs: noinline nounwind uwtable
+define float @foz(i32 %x, i32 %y) #1 !prof !1 {
+entry:
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  store i32 %y, i32* %y.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  %1 = load i32, i32* %y.addr, align 4
+  %mul = mul nsw i32 %0, %1
+  %conv = sitofp i32 %mul to float
+  ret float %conv
+}
+
+declare i32 @fox()
+
+; Function Attrs: nounwind uwtable
+define i32 @bar(i32 %j) #2 !prof !1 {
+entry:
+  %j.addr = alloca i32, align 4
+  store i32 %j, i32* %j.addr, align 4
+  %0 = load i32, i32* %j.addr, align 4
+  %1 = load i32, i32* %j.addr, align 4
+  %sub = sub nsw i32 %1, 2
+  %call = call i32 @foo(i32 %0, i32 %sub)
+  %conv = sitofp i32 %call to float
+  %2 = load i32, i32* %j.addr, align 4
+  %sub1 = sub nsw i32 %2, 2
+  %3 = load i32, i32* %j.addr, align 4
+  %call2 = call float @foz(i32 %sub1, i32 %3)
+  %mul = fmul float %conv, %call2
+  %conv3 = fptosi float %mul to i32
+  %call3 = call i32 @fox()
+  %add = add i32 %conv3, %call 
+  ret i32 %add
+}
+
+attributes #0 = { alwaysinline nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noinline nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 3.5.0 "}
+!1 = !{!"function_entry_count", i64 10}

Added: llvm/trunk/test/Transforms/Inline/parallel-loop-md-callee.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/parallel-loop-md-callee.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/parallel-loop-md-callee.ll (added)
+++ llvm/trunk/test/Transforms/Inline/parallel-loop-md-callee.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -S -inline < %s | FileCheck %s
+;
+; Check that the !llvm.access.group is still present after inlining.
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @Body(i32* nocapture %res, i32* nocapture readnone %c, i32* nocapture readonly %d, i32* nocapture readonly %p, i32 %i) {
+entry:
+  %idxprom = sext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %p, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4, !llvm.access.group !0
+  %cmp = icmp eq i32 %0, 0
+  %arrayidx2 = getelementptr inbounds i32, i32* %res, i64 %idxprom
+  %1 = load i32, i32* %arrayidx2, align 4, !llvm.access.group !0
+  br i1 %cmp, label %cond.end, label %cond.false
+
+cond.false:
+  %arrayidx6 = getelementptr inbounds i32, i32* %d, i64 %idxprom
+  %2 = load i32, i32* %arrayidx6, align 4, !llvm.access.group !0
+  %add = add nsw i32 %2, %1
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %add, %cond.false ], [ %1, %entry ]
+  store i32 %cond, i32* %arrayidx2, align 4
+  ret void
+}
+
+define void @Test(i32* %res, i32* %c, i32* %d, i32* %p, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i32 %i.0, 1600
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  call void @Body(i32* %res, i32* undef, i32* %d, i32* %p, i32 %i.0), !llvm.access.group !0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond, !llvm.loop !1
+
+for.end:
+  ret void
+}
+
+!0 = distinct !{}                                          ; access group
+!1 = distinct !{!1, !{!"llvm.loop.parallel_accesses", !0}} ; LoopID
+
+
+; CHECK-LABEL: @Test
+; CHECK: load i32,{{.*}}, !llvm.access.group !0
+; CHECK: load i32,{{.*}}, !llvm.access.group !0
+; CHECK: load i32,{{.*}}, !llvm.access.group !0
+; CHECK: store i32 {{.*}}, !llvm.access.group !0
+; CHECK: br label %for.cond, !llvm.loop !1

Added: llvm/trunk/test/Transforms/Inline/parallel-loop-md-merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/parallel-loop-md-merge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/parallel-loop-md-merge.ll (added)
+++ llvm/trunk/test/Transforms/Inline/parallel-loop-md-merge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,78 @@
+; RUN: opt -always-inline -globalopt -S < %s | FileCheck %s
+;
+; static void __attribute__((always_inline)) callee(long n, double A[static const restrict n], long i) {
+;   for (long j = 0; j < n; j += 1)
+;     A[i * n + j] = 42;
+; }
+;
+; void caller(long n, double A[static const restrict n]) {
+;   for (long i = 0; i < n; i += 1)
+;     callee(n, A, i);
+; }
+;
+; Check that the access groups (llvm.access.group) are correctly merged.
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define internal void @callee(i64 %n, double* noalias nonnull %A, i64 %i) #0 {
+entry:
+  br label %for.cond
+
+for.cond:
+  %j.0 = phi i64 [ 0, %entry ], [ %add1, %for.body ]
+  %cmp = icmp slt i64 %j.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %mul = mul nsw i64 %i, %n
+  %add = add nsw i64 %mul, %j.0
+  %arrayidx = getelementptr inbounds double, double* %A, i64 %add
+  store double 4.200000e+01, double* %arrayidx, align 8, !llvm.access.group !6
+  %add1 = add nuw nsw i64 %j.0, 1
+  br label %for.cond, !llvm.loop !7
+
+for.end:
+  ret void
+}
+
+attributes #0 = { alwaysinline }
+
+!6 = distinct !{}       ; access group
+!7 = distinct !{!7, !9} ; LoopID
+!9 = !{!"llvm.loop.parallel_accesses", !6}
+
+
+define void @caller(i64 %n, double* noalias nonnull %A) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i64 [ 0, %entry ], [ %add, %for.body ]
+  %cmp = icmp slt i64 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  call void @callee(i64 %n, double* %A, i64 %i.0), !llvm.access.group !10
+  %add = add nuw nsw i64 %i.0, 1
+  br label %for.cond, !llvm.loop !11
+
+for.end:
+  ret void
+}
+
+!10 = distinct !{}         ; access group
+!11 = distinct !{!11, !12} ; LoopID
+!12 = !{!"llvm.loop.parallel_accesses", !10}
+
+
+; CHECK: store double 4.200000e+01, {{.*}} !llvm.access.group ![[ACCESS_GROUP_LIST_3:[0-9]+]]
+; CHECK: br label %for.cond.i, !llvm.loop ![[LOOP_INNER:[0-9]+]]
+; CHECK: br label %for.cond, !llvm.loop ![[LOOP_OUTER:[0-9]+]]
+
+; CHECK: ![[ACCESS_GROUP_LIST_3]] = !{![[ACCESS_GROUP_INNER:[0-9]+]], ![[ACCESS_GROUP_OUTER:[0-9]+]]}
+; CHECK: ![[ACCESS_GROUP_INNER]] = distinct !{}
+; CHECK: ![[ACCESS_GROUP_OUTER]] = distinct !{}
+; CHECK: ![[LOOP_INNER]] = distinct !{![[LOOP_INNER]], ![[ACCESSES_INNER:[0-9]+]]}
+; CHECK: ![[ACCESSES_INNER]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_INNER]]}
+; CHECK: ![[LOOP_OUTER]] = distinct !{![[LOOP_OUTER]], ![[ACCESSES_OUTER:[0-9]+]]}
+; CHECK: ![[ACCESSES_OUTER]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_OUTER]]}

Added: llvm/trunk/test/Transforms/Inline/parallel-loop-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/parallel-loop-md.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/parallel-loop-md.ll (added)
+++ llvm/trunk/test/Transforms/Inline/parallel-loop-md.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,58 @@
+; RUN: opt -S -inline < %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: norecurse nounwind uwtable
+define void @Body(i32* nocapture %res, i32* nocapture readnone %c, i32* nocapture readonly %d, i32* nocapture readonly %p, i32 %i) #0 {
+entry:
+  %idxprom = sext i32 %i to i64
+  %arrayidx = getelementptr inbounds i32, i32* %p, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %cmp = icmp eq i32 %0, 0
+  %arrayidx2 = getelementptr inbounds i32, i32* %res, i64 %idxprom
+  %1 = load i32, i32* %arrayidx2, align 4
+  br i1 %cmp, label %cond.end, label %cond.false
+
+cond.false:                                       ; preds = %entry
+  %arrayidx6 = getelementptr inbounds i32, i32* %d, i64 %idxprom
+  %2 = load i32, i32* %arrayidx6, align 4
+  %add = add nsw i32 %2, %1
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.false
+  %cond = phi i32 [ %add, %cond.false ], [ %1, %entry ]
+  store i32 %cond, i32* %arrayidx2, align 4
+  ret void
+}
+
+; Function Attrs: nounwind uwtable
+define void @Test(i32* %res, i32* %c, i32* %d, i32* %p, i32 %n) #1 {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %cmp = icmp slt i32 %i.0, 1600
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  call void @Body(i32* %res, i32* undef, i32* %d, i32* %p, i32 %i.0), !llvm.access.group !0
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond, !llvm.loop !1
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+; CHECK-LABEL: @Test
+; CHECK: load i32,{{.*}}, !llvm.access.group !0
+; CHECK: load i32,{{.*}}, !llvm.access.group !0
+; CHECK: load i32,{{.*}}, !llvm.access.group !0
+; CHECK: store i32{{.*}}, !llvm.access.group !0
+; CHECK: br label %for.cond, !llvm.loop !1
+
+attributes #0 = { norecurse nounwind uwtable }
+
+!0 = distinct !{}
+!1 = distinct !{!0, !{!"llvm.loop.parallel_accesses", !0}}

Added: llvm/trunk/test/Transforms/Inline/partial-inline-act.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/partial-inline-act.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/partial-inline-act.ll (added)
+++ llvm/trunk/test/Transforms/Inline/partial-inline-act.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -disable-output
+; This testcase tests the assumption cache
+
+define internal i32 @inlinedFunc(i1 %cond, i32* align 4 %align.val) {
+entry:
+  br i1 %cond, label %if.then, label %return
+if.then:
+  ; Dummy store to have more than 0 uses
+  store i32 10, i32* %align.val, align 4
+  br label %return
+return:             ; preds = %entry
+  ret i32 0
+}
+
+define internal i32 @dummyCaller(i1 %cond, i32* align 2 %align.val) {
+entry:
+  %val = call i32 @inlinedFunc(i1 %cond, i32* %align.val)
+  ret i32 %val
+}
+

Added: llvm/trunk/test/Transforms/Inline/pr21206.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr21206.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/pr21206.ll (added)
+++ llvm/trunk/test/Transforms/Inline/pr21206.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -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() comdat($c)
+
+define linkonce_odr void @bar() comdat($c) {
+  ret void
+}
+; CHECK: define linkonce_odr void @bar() comdat($c)
+
+define void()* @zed()  {
+  ret void()* @foo
+}

Added: llvm/trunk/test/Transforms/Inline/pr22285.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr22285.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/pr22285.ll (added)
+++ llvm/trunk/test/Transforms/Inline/pr22285.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline),globaldce' -S | FileCheck %s
+
+$f1 = comdat any
+; CHECK-NOT: $f1 = comdat any
+
+define void @f2() {
+  call void @f1()
+  ret void
+}
+; CHECK-LABEL: define void @f2
+
+define linkonce_odr void @f1() comdat {
+  ret void
+}
+; CHECK-NOT: define linkonce_odr void @f1() comdat

Added: llvm/trunk/test/Transforms/Inline/pr26698.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr26698.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/pr26698.ll (added)
+++ llvm/trunk/test/Transforms/Inline/pr26698.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,66 @@
+; RUN: opt -S -inline -inline-threshold=100 -inline-cold-callsite-threshold=100 < %s | FileCheck %s
+; RUN: opt -S -passes='cgscc(inline)' -inline-threshold=100 -inline-cold-callsite-threshold=100 < %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-msvc18.0.0"
+
+declare void @g(i32)
+
+define void @f() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @g(i32 0)
+          to label %invoke.cont unwind label %cs.bb
+
+invoke.cont:
+  ret void
+
+cs.bb:
+  %cs = catchswitch within none [label %cp.bb] unwind label %cleanup.bb
+
+cp.bb:
+  %cpouter1 = catchpad within %cs [i8* null, i32 0, i8* null]
+  call void @dtor() #1 [ "funclet"(token %cpouter1) ]
+  catchret from %cpouter1 to label %invoke.cont
+
+cleanup.bb:
+  %cpouter2 = cleanuppad within none []
+  call void @g(i32 1) [ "funclet"(token %cpouter2) ]
+  cleanupret from %cpouter2 unwind to caller
+}
+
+declare i32 @__CxxFrameHandler3(...)
+
+; Function Attrs: nounwind
+define internal void @dtor() #1 personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @g(i32 2)
+          to label %invoke.cont unwind label %ehcleanup1
+
+invoke.cont:
+  ret void
+
+ehcleanup1:
+  %cpinner1 = cleanuppad within none []
+  invoke void @g(i32 3) [ "funclet" (token %cpinner1) ]
+          to label %done unwind label %ehcleanup2
+done:
+  unreachable
+
+ehcleanup2:
+  %cpinner2 = cleanuppad within %cpinner1 []
+  call void @g(i32 4) [ "funclet" (token %cpinner2) ]
+  cleanupret from %cpinner2 unwind to caller
+}
+
+; CHECK-LABEL: define void @f(
+
+; CHECK:      %[[cs:.*]] = catchswitch within none
+
+; CHECK:      %[[cpouter1:.*]] = catchpad within %[[cs]]
+
+; CHECK:      %[[cpinner1:.*]] = cleanuppad within %[[cpouter1]]
+
+; CHECK:      %[[cpinner2:.*]] = cleanuppad within %[[cpinner1]]
+; CHECK-NEXT: call void @g(i32 4) #0 [ "funclet"(token %[[cpinner2]]) ]
+; CHECK-NEXT: unreachable
+
+attributes #1 = { nounwind }

Added: llvm/trunk/test/Transforms/Inline/pr28298.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr28298.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/pr28298.ll (added)
+++ llvm/trunk/test/Transforms/Inline/pr28298.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt -S -passes='cgscc(inline)' < %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() {
+entry:
+  call void @test2()
+  ret void
+}
+
+define internal void @test2() {
+entry:
+  call void undef()
+  ret void
+}
+
+; CHECK-LABEL: define void @test1(
+; CHECK: call void undef(
+; CHECK: ret void

Added: llvm/trunk/test/Transforms/Inline/pr33637.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr33637.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/pr33637.ll (added)
+++ llvm/trunk/test/Transforms/Inline/pr33637.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -inline < %s
+
+define void @patatino() {
+for.cond:
+  br label %for.body
+
+for.body:
+  %tobool = icmp eq i32 5, 0
+  %sel = select i1 %tobool, i32 0, i32 2
+  br i1 undef, label %cleanup1.thread, label %cleanup1
+
+cleanup1.thread:
+  ret void
+
+cleanup1:
+  %cleanup.dest2 = phi i32 [ %sel, %for.body ]
+  %switch = icmp ult i32 %cleanup.dest2, 1
+  ret void
+}
+
+define void @main() {
+entry:
+  call void @patatino()
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/prof-update-instr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/prof-update-instr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/prof-update-instr.ll (added)
+++ llvm/trunk/test/Transforms/Inline/prof-update-instr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S | FileCheck %s
+; Checks if inliner updates VP metadata for indrect call instructions
+; with instrumentation based profile.
+
+ at func = global void ()* null
+ at func2 = global void ()* null
+
+; CHECK: define void @callee(i32 %n) !prof ![[ENTRY_COUNT:[0-9]*]]
+define void  @callee(i32 %n) !prof !15 {
+  %cond = icmp sle i32 %n, 10
+  br i1 %cond, label %cond_true, label %cond_false, !prof !20
+cond_true:
+; f2 is optimized away, thus not updated.
+  %f2 = load void ()*, void ()** @func2
+; CHECK: call void %f2(), !prof ![[COUNT_IND_CALLEE1:[0-9]*]]
+  call void %f2(), !prof !19
+  ret void
+cond_false:
+  %f = load void ()*, void ()** @func
+; CHECK: call void %f(), !prof ![[COUNT_IND_CALLEE:[0-9]*]]
+  call void %f(), !prof !18
+  ret void
+}
+
+; CHECK: define void @caller()
+define void @caller() !prof !21 {
+; CHECK: call void %f.i(), !prof ![[COUNT_IND_CALLER:[0-9]*]]
+  call void @callee(i32 15)
+  ret void
+}
+
+!llvm.module.flags = !{!1}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 10}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 2000}
+!8 = !{!"NumCounts", i64 2}
+!9 = !{!"NumFunctions", i64 2}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}
+!15 = !{!"function_entry_count", i64 1000}
+!16 = !{!"branch_weights", i64 2000}
+!18 = !{!"VP", i32 0, i64 140, i64 111, i64 80, i64 222, i64 40, i64 333, i64 20}
+!19 = !{!"VP", i32 0, i64 200, i64 111, i64 100, i64 222, i64 60, i64 333, i64 40}
+!20 = !{!"branch_weights", i32 1000, i32 1000}
+!21 = !{!"function_entry_count", i64 400}
+attributes #0 = { alwaysinline }
+; CHECK: ![[ENTRY_COUNT]] = !{!"function_entry_count", i64 600}
+; CHECK: ![[COUNT_IND_CALLEE1]] = !{!"VP", i32 0, i64 200, i64 111, i64 100, i64 222, i64 60, i64 333, i64 40}
+; CHECK: ![[COUNT_IND_CALLEE]] = !{!"VP", i32 0, i64 84, i64 111, i64 48, i64 222, i64 24, i64 333, i64 12}
+; CHECK: ![[COUNT_IND_CALLER]] = !{!"VP", i32 0, i64 56, i64 111, i64 32, i64 222, i64 16, i64 333, i64 8}

Added: llvm/trunk/test/Transforms/Inline/prof-update-sample.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/prof-update-sample.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/prof-update-sample.ll (added)
+++ llvm/trunk/test/Transforms/Inline/prof-update-sample.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; Checks if inliner updates branch_weights annotation for call instructions.
+
+declare void @ext();
+declare void @ext1();
+ at func = global void ()* null
+
+; CHECK: define void @callee(i32 %n) !prof ![[ENTRY_COUNT:[0-9]*]]
+define void  @callee(i32 %n) !prof !15 {
+  %cond = icmp sle i32 %n, 10
+  br i1 %cond, label %cond_true, label %cond_false
+cond_true:
+; ext1 is optimized away, thus not updated.
+; CHECK: call void @ext1(), !prof ![[COUNT_CALLEE1:[0-9]*]]
+  call void @ext1(), !prof !16
+  ret void
+cond_false:
+; ext is cloned and updated.
+; CHECK: call void @ext(), !prof ![[COUNT_CALLEE:[0-9]*]]
+  call void @ext(), !prof !16
+  %f = load void ()*, void ()** @func
+; CHECK: call void %f(), !prof ![[COUNT_IND_CALLEE:[0-9]*]] 
+  call void %f(), !prof !18
+  ret void
+}
+
+; CHECK: define void @caller()
+define void @caller() {
+; CHECK: call void @ext(), !prof ![[COUNT_CALLER:[0-9]*]]
+; CHECK: call void %f.i(), !prof ![[COUNT_IND_CALLER:[0-9]*]]
+  call void @callee(i32 15), !prof !17
+  ret void
+}
+
+!llvm.module.flags = !{!1}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"SampleProfile"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 10}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 2000}
+!8 = !{!"NumCounts", i64 2}
+!9 = !{!"NumFunctions", i64 2}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}
+!15 = !{!"function_entry_count", i64 1000}
+!16 = !{!"branch_weights", i64 2000}
+!17 = !{!"branch_weights", i64 400}
+!18 = !{!"VP", i32 0, i64 140, i64 111, i64 80, i64 222, i64 40, i64 333, i64 20}
+attributes #0 = { alwaysinline }
+; CHECK: ![[ENTRY_COUNT]] = !{!"function_entry_count", i64 600}
+; CHECK: ![[COUNT_CALLEE1]] = !{!"branch_weights", i64 2000}
+; CHECK: ![[COUNT_CALLEE]] = !{!"branch_weights", i64 1200}
+; CHECK: ![[COUNT_IND_CALLEE]] = !{!"VP", i32 0, i64 84, i64 111, i64 48, i64 222, i64 24, i64 333, i64 12}
+; CHECK: ![[COUNT_CALLER]] = !{!"branch_weights", i64 800}
+; CHECK: ![[COUNT_IND_CALLER]] = !{!"VP", i32 0, i64 56, i64 111, i64 32, i64 222, i64 16, i64 333, i64 8}

Added: llvm/trunk/test/Transforms/Inline/profile-meta.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/profile-meta.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/profile-meta.ll (added)
+++ llvm/trunk/test/Transforms/Inline/profile-meta.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -S -inline | FileCheck %s
+; RUN: opt < %s -S -passes='cgscc(inline)' | FileCheck %s
+
+; Make sure that profile and unpredictable  metadata is preserved when cloning a select.
+
+define i32 @callee_with_select(i1 %c, i32 %a, i32 %b) {
+  %sel = select i1 %c, i32 %a, i32 %b, !prof !0, !unpredictable !1
+  ret i32 %sel
+}
+
+define i32 @caller_of_select(i1 %C, i32 %A, i32 %B) {
+  %ret = call i32 @callee_with_select(i1 %C, i32 %A, i32 %B)
+  ret i32 %ret
+
+; CHECK-LABEL: @caller_of_select(
+; CHECK-NEXT:  [[SEL:%.*]] = select i1 %C, i32 %A, i32 %B, !prof !0, !unpredictable !1
+; CHECK-NEXT:  ret i32 [[SEL]]
+}
+
+; Make sure that profile and unpredictable metadata is preserved when cloning a branch.
+
+define i32 @callee_with_branch(i1 %c) {
+  br i1 %c, label %if, label %else, !unpredictable !1, !prof !2
+if:
+  ret i32 1
+else:
+  ret i32 2
+}
+
+define i32 @caller_of_branch(i1 %C) {
+  %ret = call i32 @callee_with_branch(i1 %C)
+  ret i32 %ret
+
+; CHECK-LABEL: @caller_of_branch(
+; CHECK-NEXT:  br i1 %C, label %{{.*}}, label %{{.*}}, !prof !2, !unpredictable !1
+}
+
+!0 = !{!"branch_weights", i32 1, i32 2}
+!1 = !{}
+!2 = !{!"branch_weights", i32 3, i32 4}
+
+; CHECK: !0 = !{!"branch_weights", i32 1, i32 2}
+; CHECK: !1 = !{}
+; CHECK: !2 = !{!"branch_weights", i32 3, i32 4}
+

Added: llvm/trunk/test/Transforms/Inline/ptr-diff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/ptr-diff.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/ptr-diff.ll (added)
+++ llvm/trunk/test/Transforms/Inline/ptr-diff.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,157 @@
+; RUN: opt -inline < %s -S -o - -inline-threshold=10 | FileCheck %s
+
+target datalayout = "p:32:32-p1:64:64-p2:16:16-n16:32:64"
+
+define i32 @outer1() {
+; CHECK-LABEL: @outer1(
+; CHECK-NOT: call i32
+; CHECK: ret i32
+
+  %ptr = alloca i32
+  %ptr1 = getelementptr inbounds i32, i32* %ptr, i32 0
+  %ptr2 = getelementptr inbounds i32, i32* %ptr, i32 42
+  %result = call i32 @inner1(i32* %ptr1, i32* %ptr2)
+  ret i32 %result
+}
+
+define i32 @inner1(i32* %begin, i32* %end) {
+  call void @extern()
+  %begin.i = ptrtoint i32* %begin to i32
+  %end.i = ptrtoint i32* %end to i32
+  %distance = sub i32 %end.i, %begin.i
+  %icmp = icmp sle i32 %distance, 42
+  br i1 %icmp, label %then, label %else
+
+then:
+  ret i32 3
+
+else:
+  %t = load i32, i32* %begin
+  ret i32 %t
+}
+
+define i32 @outer1_as1(i32 addrspace(1)* %ptr) {
+; CHECK-LABEL: @outer1_as1(
+; CHECK-NOT: call
+; CHECK: ret i32
+  %ptr1 = getelementptr inbounds i32, i32 addrspace(1)* %ptr, i32 0
+  %ptr2 = getelementptr inbounds i32, i32 addrspace(1)* %ptr, i32 42
+  %result = call i32 @inner1_as1(i32 addrspace(1)* %ptr1, i32 addrspace(1)* %ptr2)
+  ret i32 %result
+}
+
+; Make sure that the address space's larger size makes the ptrtoints
+; not no-ops preventing inlining
+define i32 @inner1_as1(i32 addrspace(1)* %begin, i32 addrspace(1)* %end) {
+  %begin.i = ptrtoint i32 addrspace(1)* %begin to i32
+  %end.i = ptrtoint i32 addrspace(1)* %end to i32
+  %distance = sub i32 %end.i, %begin.i
+  %icmp = icmp sle i32 %distance, 42
+  br i1 %icmp, label %then, label %else
+
+then:
+  ret i32 3
+
+else:
+  %t = load i32, i32 addrspace(1)* %begin
+  ret i32 %t
+}
+
+define i32 @outer2(i32* %ptr) {
+; Test that an inbounds GEP disables this -- it isn't safe in general as
+; wrapping changes the behavior of lessthan and greaterthan comparisons.
+; CHECK-LABEL: @outer2(
+; CHECK: call i32 @inner2
+; CHECK: ret i32
+
+  %ptr1 = getelementptr i32, i32* %ptr, i32 0
+  %ptr2 = getelementptr i32, i32* %ptr, i32 42
+  %result = call i32 @inner2(i32* %ptr1, i32* %ptr2)
+  ret i32 %result
+}
+
+define i32 @inner2(i32* %begin, i32* %end) {
+  call void @extern()
+  %begin.i = ptrtoint i32* %begin to i32
+  %end.i = ptrtoint i32* %end to i32
+  %distance = sub i32 %end.i, %begin.i
+  %icmp = icmp sle i32 %distance, 42
+  br i1 %icmp, label %then, label %else
+
+then:
+  ret i32 3
+
+else:
+  %t = load i32, i32* %begin
+  ret i32 %t
+}
+
+define i32 @outer3(i16* addrspace(1)* %ptr) {
+; CHECK-LABEL: @outer3(
+; CHECK-NOT: call i32
+; CHECK: ret i32 3
+; CHECK-LABEL: @inner3(
+  %result = call i32 @inner3(i16* addrspace(1)* %ptr)
+  ret i32 %result
+}
+
+define i32 @inner3(i16* addrspace(1)* %ptr) {
+  call void @extern()
+  %ptr.i = ptrtoint i16* addrspace(1)* %ptr to i64
+  %distance = sub i64 %ptr.i, %ptr.i
+  %icmp = icmp eq i64 %distance, 0
+  br i1 %icmp, label %then, label %else
+
+then:
+  ret i32 3
+
+else:
+  ret i32 5
+}
+
+
+; The inttoptrs are free since it is a smaller integer to a larger
+; pointer size
+define i32 @inttoptr_free_cost(i32 %a, i32 %b, i32 %c) {
+  call void @extern()
+  %p1 = inttoptr i32 %a to i32 addrspace(1)*
+  %p2 = inttoptr i32 %b to i32 addrspace(1)*
+  %p3 = inttoptr i32 %c to i32 addrspace(1)*
+  %t1 = load i32, i32 addrspace(1)* %p1
+  %t2 = load i32, i32 addrspace(1)* %p2
+  %t3 = load i32, i32 addrspace(1)* %p3
+  %s = add i32 %t1, %t2
+  %s1 = add i32 %s, %t3
+  ret i32 %s1
+}
+
+define i32 @inttoptr_free_cost_user(i32 %begin, i32 %end) {
+; CHECK-LABEL: @inttoptr_free_cost_user(
+; CHECK-NOT: call i32
+  %x = call i32 @inttoptr_free_cost(i32 %begin, i32 %end, i32 9)
+  ret i32 %x
+}
+
+; The inttoptrs have a cost since it is a larger integer to a smaller
+; pointer size
+define i32 @inttoptr_cost_smaller_ptr(i32 %a, i32 %b, i32 %c) {
+  call void @extern()
+  %p1 = inttoptr i32 %a to i32 addrspace(2)*
+  %p2 = inttoptr i32 %b to i32 addrspace(2)*
+  %p3 = inttoptr i32 %c to i32 addrspace(2)*
+  %t1 = load i32, i32 addrspace(2)* %p1
+  %t2 = load i32, i32 addrspace(2)* %p2
+  %t3 = load i32, i32 addrspace(2)* %p3
+  %s = add i32 %t1, %t2
+  %s1 = add i32 %s, %t3
+  ret i32 %s1
+}
+
+define i32 @inttoptr_cost_smaller_ptr_user(i32 %begin, i32 %end) {
+; CHECK-LABEL: @inttoptr_cost_smaller_ptr_user(
+; CHECK: call i32
+  %x = call i32 @inttoptr_cost_smaller_ptr(i32 %begin, i32 %end, i32 9)
+  ret i32 %x
+}
+
+declare void @extern()
\ No newline at end of file

Added: llvm/trunk/test/Transforms/Inline/recursive.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/recursive.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/recursive.ll (added)
+++ llvm/trunk/test/Transforms/Inline/recursive.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,73 @@
+; Inlining in the presence of recursion presents special challenges that we
+; test here.
+;
+; RUN: opt -inline -S < %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S < %s | FileCheck %s
+
+define i32 @large_stack_callee(i32 %param) {
+; CHECK-LABEL: define i32 @large_stack_callee(
+entry:
+ %yyy = alloca [100000 x i8]
+ %r = bitcast [100000 x i8]* %yyy to i8*
+ call void @bar(i8* %r)
+ ret i32 4
+}
+
+; Test a recursive function which calls another function with a large stack. In
+; addition to not inlining the recursive call, we should also not inline the
+; large stack allocation into a potentially recursive frame.
+define i32 @large_stack_recursive_caller(i32 %param) {
+; CHECK-LABEL: define i32 @large_stack_recursive_caller(
+entry:
+; CHECK-NEXT: entry:
+; CHECK-NOT: alloca
+  %t = call i32 @foo(i32 %param)
+  %cmp = icmp eq i32 %t, -1
+  br i1 %cmp, label %exit, label %cont
+
+cont:
+  %r = call i32 @large_stack_recursive_caller(i32 %t)
+; CHECK: call i32 @large_stack_recursive_caller
+  %f = call i32 @large_stack_callee(i32 %r)
+; CHECK: call i32 @large_stack_callee
+  br label %exit
+
+exit:
+  ret i32 4
+}
+
+declare void @bar(i8* %in)
+
+declare i32 @foo(i32 %param)
+
+; Check that when inlining a non-recursive path into a function's own body that
+; we get the re-mapping of instructions correct.
+define i32 @test_recursive_inlining_remapping(i1 %init, i8* %addr) {
+; CHECK-LABEL: define i32 @test_recursive_inlining_remapping(
+bb:
+  %n = alloca i32
+  br i1 %init, label %store, label %load
+; CHECK-NOT:     alloca
+;
+; CHECK:         %[[N:.*]] = alloca i32
+; CHECK-NEXT:    br i1 %init,
+
+store:
+  store i32 0, i32* %n
+  %cast = bitcast i32* %n to i8*
+  %v = call i32 @test_recursive_inlining_remapping(i1 false, i8* %cast)
+  ret i32 %v
+; CHECK-NOT:     call
+;
+; CHECK:         store i32 0, i32* %[[N]]
+; CHECK-NEXT:    %[[CAST:.*]] = bitcast i32* %[[N]] to i8*
+; CHECK-NEXT:    %[[INLINED_LOAD:.*]] = load i32, i32* %[[N]]
+; CHECK-NEXT:    ret i32 %[[INLINED_LOAD]]
+;
+; CHECK-NOT:     call
+
+load:
+  %castback = bitcast i8* %addr to i32*
+  %n.load = load i32, i32* %castback
+  ret i32 %n.load
+}

Added: llvm/trunk/test/Transforms/Inline/redundant-loads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/redundant-loads.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/redundant-loads.ll (added)
+++ llvm/trunk/test/Transforms/Inline/redundant-loads.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,204 @@
+; RUN: opt -inline < %s -S -o - -inline-threshold=3  | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @pad() readnone
+
+define void @outer1(i32* %a) {
+; CHECK-LABEL: @outer1(
+; CHECK-NOT: call void @inner1
+  %b = alloca i32
+  call void @inner1(i32* %a, i32* %b)
+  ret void
+}
+
+define void @inner1(i32* %a, i32* %b) {
+  %1 = load i32, i32* %a
+  store i32 %1, i32 * %b ; This store does not clobber the first load.
+  %2 = load i32, i32* %a
+  call void @pad()
+  %3 = load i32, i32* %a
+  ret void
+}
+
+
+define void @outer2(i32* %a, i32* %b) {
+; CHECK-LABEL: @outer2(
+; CHECK: call void @inner2
+  call void @inner2(i32* %a, i32* %b)
+  ret void
+}
+
+define void @inner2(i32* %a, i32* %b) {
+  %1 = load i32, i32* %a
+  store i32 %1, i32 * %b ; This store clobbers the first load.
+  %2 = load i32, i32* %a
+  call void @pad()
+  ret void
+}
+
+
+define void @outer3(i32* %a) {
+; CHECK-LABEL: @outer3(
+; CHECK: call void @inner3
+  call void @inner3(i32* %a)
+  ret void
+}
+
+declare void @ext()
+
+define void @inner3(i32* %a) {
+  %1 = load i32, i32* %a
+  call void @ext() ; This call clobbers the first load.
+  %2 = load i32, i32* %a
+  ret void
+}
+
+
+define void @outer4(i32* %a, i32* %b, i32* %c) {
+; CHECK-LABEL: @outer4(
+; CHECK-NOT: call void @inner4
+  call void @inner4(i32* %a, i32* %b, i1 false)
+  ret void
+}
+
+define void @inner4(i32* %a, i32* %b, i1 %pred) {
+  %1 = load i32, i32* %a
+  br i1 %pred, label %cond_true, label %cond_false
+
+cond_true:
+  store i32 %1, i32 * %b ; This store does not clobber the first load.
+  br label %cond_false
+
+cond_false:
+  %2 = load i32, i32* %a
+  call void @pad()
+  %3 = load i32, i32* %a
+  %4 = load i32, i32* %a
+  ret void
+}
+
+
+define void @outer5(i32* %a, double %b) {
+; CHECK-LABEL: @outer5(
+; CHECK-NOT: call void @inner5
+  call void @inner5(i32* %a, double %b)
+  ret void
+}
+
+declare double @llvm.fabs.f64(double) nounwind readnone
+
+define void @inner5(i32* %a, double %b) {
+  %1 = load i32, i32* %a
+  %2 = call double @llvm.fabs.f64(double %b) ; This intrinsic does not clobber the first load.
+  %3 = load i32, i32* %a
+  call void @pad()
+  ret void
+}
+
+define void @outer6(i32* %a, i8* %ptr) {
+; CHECK-LABEL: @outer6(
+; CHECK-NOT: call void @inner6
+  call void @inner6(i32* %a, i8* %ptr)
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) argmemonly nounwind
+
+define void @inner6(i32* %a, i8* %ptr) {
+  %1 = load i32, i32* %a
+  call void @llvm.lifetime.start.p0i8(i64 32, i8* %ptr) ; This intrinsic does not clobber the first load.
+  %2 = load i32, i32* %a
+  call void @pad()
+  %3 = load i32, i32* %a
+  ret void
+}
+
+define void @outer7(i32* %a) {
+; CHECK-LABEL: @outer7(
+; CHECK-NOT: call void @inner7
+  call void @inner7(i32* %a)
+  ret void
+}
+
+declare void @ext2() readnone
+
+define void @inner7(i32* %a) {
+  %1 = load i32, i32* %a
+  call void @ext2() ; This call does not clobber the first load.
+  %2 = load i32, i32* %a
+  ret void
+}
+
+
+define void @outer8(i32* %a) {
+; CHECK-LABEL: @outer8(
+; CHECK-NOT: call void @inner8
+  call void @inner8(i32* %a, void ()* @ext2)
+  ret void
+}
+
+define void @inner8(i32* %a, void ()* %f) {
+  %1 = load i32, i32* %a
+  call void %f() ; This indirect call does not clobber the first load.
+  %2 = load i32, i32* %a
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  ret void
+}
+
+
+define void @outer9(i32* %a) {
+; CHECK-LABEL: @outer9(
+; CHECK: call void @inner9
+  call void @inner9(i32* %a, void ()* @ext)
+  ret void
+}
+
+define void @inner9(i32* %a, void ()* %f) {
+  %1 = load i32, i32* %a
+  call void %f() ; This indirect call clobbers the first load.
+  %2 = load i32, i32* %a
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  call void @pad()
+  ret void
+}
+
+
+define void @outer10(i32* %a) {
+; CHECK-LABEL: @outer10(
+; CHECK: call void @inner10
+  %b = alloca i32
+  call void @inner10(i32* %a, i32* %b)
+  ret void
+}
+
+define void @inner10(i32* %a, i32* %b) {
+  %1 = load i32, i32* %a
+  store i32 %1, i32 * %b
+  %2 = load volatile i32, i32* %a ; volatile load should be kept.
+  call void @pad()
+  %3 = load volatile i32, i32* %a ; Same as the above.
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/store-sroa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/store-sroa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/store-sroa.ll (added)
+++ llvm/trunk/test/Transforms/Inline/store-sroa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt -S -O2 -inline-threshold=1 < %s | FileCheck %s
+
+%class.A = type { i32 }
+
+define void @_Z3barP1A(%class.A* %a) #0 {
+entry:
+  %a1 = getelementptr inbounds %class.A, %class.A* %a, i64 0, i32 0
+  %0 = load i32, i32* %a1, align 4
+  %add = add nsw i32 %0, 10
+  store i32 %add, i32* %a1, align 4
+  ret void
+}
+
+define void @_Z3foov() #0 {
+; CHECK-LABEL: @_Z3foov(
+; CHECK-NOT: call void @_Z3barP1A
+; CHECK: ret
+entry:
+  %a = alloca %class.A, align 4
+  call void @_Z3barP1A(%class.A* %a)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Inline/switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/switch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/switch.ll (added)
+++ llvm/trunk/test/Transforms/Inline/switch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; RUN: opt < %s -inline -inline-threshold=20 -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S | FileCheck %s
+
+define i32 @callee(i32 %a) {
+  switch i32 %a, label %sw.default [
+    i32 0, label %sw.bb0
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+    i32 4, label %sw.bb4
+    i32 5, label %sw.bb5
+    i32 6, label %sw.bb6
+    i32 7, label %sw.bb7
+    i32 8, label %sw.bb8
+    i32 9, label %sw.bb9
+  ]
+
+sw.default:
+  br label %return
+
+sw.bb0:
+  br label %return
+
+sw.bb1:
+  br label %return
+
+sw.bb2:
+  br label %return
+
+sw.bb3:
+  br label %return
+
+sw.bb4:
+  br label %return
+
+sw.bb5:
+  br label %return
+
+sw.bb6:
+  br label %return
+
+sw.bb7:
+  br label %return
+
+sw.bb8:
+  br label %return
+
+sw.bb9:
+  br label %return
+
+return:
+  ret i32 42
+}
+
+define i32 @caller(i32 %a) {
+; CHECK-LABEL: @caller(
+; CHECK: call i32 @callee(
+
+  %result = call i32 @callee(i32 %a)
+  ret i32 %result
+}

Added: llvm/trunk/test/Transforms/Inline/vector-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/vector-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/vector-bonus.ll (added)
+++ llvm/trunk/test/Transforms/Inline/vector-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -inline -inline-threshold=35  -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=35  -S | FileCheck %s
+
+define i32 @bar(<4 x i32> %v, i32 %i) #0 {
+entry:
+  %cmp = icmp sgt i32 %i, 4
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %mul1 = mul nsw i32 %i, %i
+  br label %return
+
+if.else:                                          ; preds = %entry
+  %add1 = add nsw i32 %i, %i
+  %add2 = add nsw i32 %i, %i
+  %add3 = add nsw i32 %i, %i
+  %add4 = add nsw i32 %i, %i
+  %add5 = add nsw i32 %i, %i
+  %add6 = add nsw i32 %i, %i
+  %vecext = extractelement <4 x i32> %v, i32 0
+  %vecext7 = extractelement <4 x i32> %v, i32 1
+  %add7 = add nsw i32 %vecext, %vecext7
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ %mul1, %if.then ], [ %add7, %if.else ]
+  ret i32 %retval.0
+}
+
+define i32 @foo(<4 x i32> %v, i32 %a) #1 {
+; CHECK-LABEL: @foo(
+; CHECK-NOT: call i32 @bar
+; CHECK: ret
+entry:
+  %call = call i32 @bar(<4 x i32> %v, i32 %a)
+  ret i32 %call
+}
+

Added: llvm/trunk/test/Transforms/Inline/vector-no-bonus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/vector-no-bonus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/vector-no-bonus.ll (added)
+++ llvm/trunk/test/Transforms/Inline/vector-no-bonus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; The code in this test is very similar to vector-bonus.ll except for
+; the fact that the call to bar is cold thereby preventing the application of
+; the vector bonus.
+; RUN: opt < %s -inline -inline-threshold=35  -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=35  -S | FileCheck %s
+
+define i32 @bar(<4 x i32> %v, i32 %i) #0 {
+entry:
+  %cmp = icmp sgt i32 %i, 4
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %mul1 = mul nsw i32 %i, %i
+  br label %return
+
+if.else:                                          ; preds = %entry
+  %add1 = add nsw i32 %i, %i
+  %add2 = add nsw i32 %i, %i
+  %add3 = add nsw i32 %i, %i
+  %add4 = add nsw i32 %i, %i
+  %add5 = add nsw i32 %i, %i
+  %add6 = add nsw i32 %i, %i
+  %vecext = extractelement <4 x i32> %v, i32 0
+  %vecext7 = extractelement <4 x i32> %v, i32 1
+  %add7 = add nsw i32 %vecext, %vecext7
+  br label %return
+
+return:                                           ; preds = %if.else, %if.then
+  %retval.0 = phi i32 [ %mul1, %if.then ], [ %add7, %if.else ]
+  ret i32 %retval.0
+}
+
+define i32 @foo(<4 x i32> %v, i32 %a) #1 {
+; CHECK-LABEL: @foo(
+; CHECK-NOT: call i32 @bar
+; CHECK: ret
+entry:
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %callbb, label %ret
+callbb:
+  %call = call i32 @bar(<4 x i32> %v, i32 %a)
+  br label %ret
+ret:
+  %call1 = phi i32 [%call, %callbb], [0, %entry]
+  ret i32 %call1
+}
+

Added: llvm/trunk/test/Transforms/Inline/zero-cost.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/zero-cost.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/zero-cost.ll (added)
+++ llvm/trunk/test/Transforms/Inline/zero-cost.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -inline -S %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' -S %s | FileCheck %s
+
+define void @f() {
+entry:
+  tail call void @g()
+  unreachable
+
+; CHECK-LABEL: @f
+; CHECK-NOT: call
+; CHECK: unreachable
+}
+
+define void @g() {
+entry:
+  unreachable
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2003-05-26-CastMiscompile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-05-26-CastMiscompile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-05-26-CastMiscompile.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-05-26-CastMiscompile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+; RUN: opt < %s -instcombine -S | grep 4294967295
+
+define i64 @test(i64 %Val) {
+        %tmp.3 = trunc i64 %Val to i32          ; <i32> [#uses=1]
+        %tmp.8 = zext i32 %tmp.3 to i64         ; <i64> [#uses=1]
+        ret i64 %tmp.8
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -instcombine -disable-output
+
+ at X = global i32 5               ; <i32*> [#uses=1]
+
+define i64 @test() {
+        %C = add i64 1, 2               ; <i64> [#uses=1]
+        %V = add i64 ptrtoint (i32* @X to i64), %C              ; <i64> [#uses=1]
+        ret i64 %V
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2003-06-05-BranchInvertInfLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-06-05-BranchInvertInfLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-06-05-BranchInvertInfLoop.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-06-05-BranchInvertInfLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; This testcase causes an infinite loop in the instruction combiner,
+; because it things that the constant value is a not expression... and 
+; constantly inverts the branch back and forth.
+;
+; RUN: opt < %s -instcombine -disable-output
+
+define i8 @test19(i1 %c) {
+        br i1 true, label %True, label %False
+
+True:           ; preds = %0
+        ret i8 1
+
+False:          ; preds = %0
+        ret i8 3
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2003-07-21-ExternalConstant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-07-21-ExternalConstant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-07-21-ExternalConstant.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-07-21-ExternalConstant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+;
+; Test: ExternalConstant
+;
+; Description:
+;	This regression test helps check whether the instruction combining
+;	optimization pass correctly handles global variables which are marked
+;	as external and constant.
+;
+;	If a problem occurs, we should die on an assert().  Otherwise, we
+;	should pass through the optimizer without failure.
+;
+; Extra code:
+; RUN: opt < %s -instcombine
+; END.
+
+target datalayout = "e-p:32:32"
+ at silly = external constant i32          ; <i32*> [#uses=1]
+
+declare void @bzero(i8*, i32)
+
+declare void @bcopy(i8*, i8*, i32)
+
+declare i32 @bcmp(i8*, i8*, i32)
+
+declare i32 @fputs(i8*, i8*)
+
+declare i32 @fputs_unlocked(i8*, i8*)
+
+define i32 @function(i32 %a.1) {
+entry:
+        %a.0 = alloca i32               ; <i32*> [#uses=2]
+        %result = alloca i32            ; <i32*> [#uses=2]
+        store i32 %a.1, i32* %a.0
+        %tmp.0 = load i32, i32* %a.0         ; <i32> [#uses=1]
+        %tmp.1 = load i32, i32* @silly               ; <i32> [#uses=1]
+        %tmp.2 = add i32 %tmp.0, %tmp.1         ; <i32> [#uses=1]
+        store i32 %tmp.2, i32* %result
+        br label %return
+
+return:         ; preds = %entry
+        %tmp.3 = load i32, i32* %result              ; <i32> [#uses=1]
+        ret i32 %tmp.3
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; This testcase can be simplified by "realizing" that alloca can never return
+; null.
+; RUN: opt < %s -instcombine -simplifycfg -S | FileCheck %s
+; CHECK-NOT: br
+
+declare i32 @bitmap_clear(...)
+
+define i32 @oof() {
+entry:
+        %live_head = alloca i32         ; <i32*> [#uses=2]
+        %tmp.1 = icmp ne i32* %live_head, null          ; <i1> [#uses=1]
+        br i1 %tmp.1, label %then, label %UnifiedExitNode
+
+then:           ; preds = %entry
+        %tmp.4 = call i32 (...) @bitmap_clear( i32* %live_head )               ; <i32> [#uses=0]
+        br label %UnifiedExitNode
+
+UnifiedExitNode:                ; preds = %then, %entry
+        ret i32 0
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,7 @@
+; RUN: opt < %s -instcombine -S | grep load
+
+define void @test(i32* %P) {
+        ; Dead but not deletable!
+        %X = load volatile i32, i32* %P              ; <i32> [#uses=0]
+        ret void
+}

Added: llvm/trunk/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -instcombine -disable-output
+
+declare i32* @bar()
+
+define float* @foo() personality i32 (...)* @__gxx_personality_v0 {
+        %tmp.11 = invoke float* bitcast (i32* ()* @bar to float* ()*)( )
+                        to label %invoke_cont unwind label %X           ; <float*> [#uses=1]
+
+invoke_cont:            ; preds = %0
+        ret float* %tmp.11
+
+X:              ; preds = %0
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        ret float* null
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; The cast in this testcase is not eliminable on a 32-bit target!
+; RUN: opt < %s -instcombine -S | grep inttoptr
+
+target datalayout = "e-p:32:32"
+
+declare void @foo(...)
+
+define void @test(i64 %X) {
+        %Y = inttoptr i64 %X to i32*            ; <i32*> [#uses=1]
+        call void (...) @foo( i32* %Y )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; Test for a problem afflicting several C++ programs in the testsuite.  The 
+; instcombine pass is trying to get rid of the cast in the invoke instruction, 
+; inserting a cast of the return value after the PHI instruction, but which is
+; used by the PHI instruction.  This is bad: because of the semantics of the
+; invoke instruction, we really cannot perform this transformation at all at
+; least without splitting the critical edge.
+;
+; RUN: opt < %s -instcombine -disable-output
+
+declare i8* @test()
+
+define i32 @foo() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+        br i1 true, label %cont, label %call
+
+call:           ; preds = %entry
+        %P = invoke i32* bitcast (i8* ()* @test to i32* ()*)( )
+                        to label %cont unwind label %N          ; <i32*> [#uses=1]
+
+cont:           ; preds = %call, %entry
+        %P2 = phi i32* [ %P, %call ], [ null, %entry ]          ; <i32*> [#uses=1]
+        %V = load i32, i32* %P2              ; <i32> [#uses=1]
+        ret i32 %V
+
+N:              ; preds = %call
+        %exn = landingpad {i8*, i32}
+                 cleanup
+        ret i32 0
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/InstCombine/2004-02-23-ShiftShiftOverflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-02-23-ShiftShiftOverflow.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-02-23-ShiftShiftOverflow.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-02-23-ShiftShiftOverflow.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -instcombine -S | not grep 34
+
+define i32 @test(i32 %X) {
+        ; Do not fold into shr X, 34, as this uses undefined behavior!
+        %Y = ashr i32 %X, 17            ; <i32> [#uses=1]
+        %Z = ashr i32 %Y, 17            ; <i32> [#uses=1]
+        ret i32 %Z
+}
+
+define i32 @test2(i32 %X) {
+        ; Do not fold into shl X, 34, as this uses undefined behavior!
+        %Y = shl i32 %X, 17             ; <i32> [#uses=1]
+        %Z = shl i32 %Y, 17             ; <i32> [#uses=1]
+        ret i32 %Z
+}

Added: llvm/trunk/test/Transforms/InstCombine/2004-03-13-InstCombineInfLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-03-13-InstCombineInfLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-03-13-InstCombineInfLoop.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-03-13-InstCombineInfLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; This testcase caused the combiner to go into an infinite loop, moving the 
+; cast back and forth, changing the seteq to operate on int vs uint and back.
+
+; RUN: opt < %s -instcombine -disable-output
+
+define i1 @test(i32 %A, i32 %B) {
+        %C = sub i32 0, %A              ; <i32> [#uses=1]
+        %Cc = bitcast i32 %C to i32             ; <i32> [#uses=1]
+        %D = sub i32 0, %B              ; <i32> [#uses=1]
+        %E = icmp eq i32 %Cc, %D                ; <i1> [#uses=1]
+        ret i1 %E
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-04-04-InstCombineReplaceAllUsesWith.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-04-04-InstCombineReplaceAllUsesWith.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-04-04-InstCombineReplaceAllUsesWith.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-04-04-InstCombineReplaceAllUsesWith.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -instcombine -disable-output
+
+define i32 @test() {
+        ret i32 0
+
+Loop:           ; preds = %Loop
+        %X = add i32 %X, 1              ; <i32> [#uses=1]
+        br label %Loop
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-05-07-UnsizedCastLoad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-05-07-UnsizedCastLoad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-05-07-UnsizedCastLoad.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-05-07-UnsizedCastLoad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -instcombine -disable-output
+
+%Ty = type opaque
+
+define i32 @test(%Ty* %X) {
+        %Y = bitcast %Ty* %X to i32*            ; <i32*> [#uses=1]
+        %Z = load i32, i32* %Y               ; <i32> [#uses=1]
+        ret i32 %Z
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-07-27-ConstantExprMul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-07-27-ConstantExprMul.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-07-27-ConstantExprMul.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-07-27-ConstantExprMul.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt < %s -instcombine -disable-output
+
+ at p = weak global i32 0          ; <i32*> [#uses=1]
+
+define i32 @test(i32 %x) {
+        %y = mul i32 %x, ptrtoint (i32* @p to i32)              ; <i32> [#uses=1]
+        ret i32 %y
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-08-09-RemInfLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-08-09-RemInfLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-08-09-RemInfLoop.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-08-09-RemInfLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt < %s -instcombine
+
+; This testcase should not send the instcombiner into an infinite loop!
+
+define i32 @test(i32 %X) {
+        %Y = srem i32 %X, 0             ; <i32> [#uses=1]
+        ret i32 %Y
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-08-10-BoolSetCC.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-08-10-BoolSetCC.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-08-10-BoolSetCC.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-08-10-BoolSetCC.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+; RUN: opt < %s -instcombine -S | \
+; RUN:    grep "ret i1 false"
+
+define i1 @test(i1 %V) {
+        %Y = icmp ult i1 %V, false              ; <i1> [#uses=1]
+        ret i1 %Y
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -instcombine -mem2reg -S | \
+; RUN:   not grep "i32 1"
+
+; When propagating the load through the select, make sure that the load is
+; inserted where the original load was, not where the select is.  Not doing
+; so could produce incorrect results!
+
+define i32 @test(i1 %C) {
+        %X = alloca i32         ; <i32*> [#uses=3]
+        %X2 = alloca i32                ; <i32*> [#uses=2]
+        store i32 1, i32* %X
+        store i32 2, i32* %X2
+        %Y = select i1 %C, i32* %X, i32* %X2            ; <i32*> [#uses=1]
+        store i32 3, i32* %X
+        %Z = load i32, i32* %Y               ; <i32> [#uses=1]
+        ret i32 %Z
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine2.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-09-20-BadLoadCombine2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -instcombine -mem2reg -simplifycfg | \
+; RUN:   llvm-dis | grep -v store | not grep "i32 1"
+
+; Test to make sure that instcombine does not accidentally propagate the load
+; into the PHI, which would break the program.
+
+define i32 @test(i1 %C) {
+entry:
+        %X = alloca i32         ; <i32*> [#uses=3]
+        %X2 = alloca i32                ; <i32*> [#uses=2]
+        store i32 1, i32* %X
+        store i32 2, i32* %X2
+        br i1 %C, label %cond_true.i, label %cond_continue.i
+
+cond_true.i:            ; preds = %entry
+        br label %cond_continue.i
+
+cond_continue.i:                ; preds = %cond_true.i, %entry
+        %mem_tmp.i.0 = phi i32* [ %X, %cond_true.i ], [ %X2, %entry ]           ; <i32*> [#uses=1]
+        store i32 3, i32* %X
+        %tmp.3 = load i32, i32* %mem_tmp.i.0         ; <i32> [#uses=1]
+        ret i32 %tmp.3
+}
+
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-09-28-BadShiftAndSetCC.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-09-28-BadShiftAndSetCC.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-09-28-BadShiftAndSetCC.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-09-28-BadShiftAndSetCC.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt < %s -instcombine -S | not grep -- -65536
+
+define i1 @test(i32 %tmp.124) {
+        %tmp.125 = shl i32 %tmp.124, 8          ; <i32> [#uses=1]
+        %tmp.126.mask = and i32 %tmp.125, -16777216             ; <i32> [#uses=1]
+        %tmp.128 = icmp eq i32 %tmp.126.mask, 167772160         ; <i1> [#uses=1]
+        ret i1 %tmp.128
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-11-22-Missed-and-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-11-22-Missed-and-fold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-11-22-Missed-and-fold.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-11-22-Missed-and-fold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -instcombine -S | not grep and
+
+define i8 @test21(i8 %A) {
+        ;; sign extend
+        %C = ashr i8 %A, 7              ; <i8> [#uses=1]
+        ;; chop off sign
+        %D = and i8 %C, 1               ; <i8> [#uses=1]
+        ret i8 %D
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,269 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; This test case tests the InstructionCombining optimization that
+; reduces things like:
+;   %Y = sext i8 %X to i32
+;   %C = icmp ult i32 %Y, 1024
+; to
+;   %C = i1 true
+; It includes test cases for different constant values, signedness of the
+; cast operands, and types of setCC operators. In all cases, the cast should
+; be eliminated. In many cases the setCC is also eliminated based on the
+; constant value and the range of the casted value.
+;
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+define i1 @lt_signed_to_large_unsigned(i8 %SB) {
+; CHECK-LABEL: @lt_signed_to_large_unsigned(
+; CHECK-NEXT:    [[C1:%.*]] = icmp sgt i8 %SB, -1
+; CHECK-NEXT:    ret i1 [[C1]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp ult i32 %Y, 1024
+  ret i1 %C
+}
+
+; PR28011 - https://llvm.org/bugs/show_bug.cgi?id=28011
+; The above transform only applies to scalar integers; it shouldn't be attempted for constant expressions or vectors.
+
+ at a = common global i32** null
+ at b = common global [1 x i32] zeroinitializer
+
+define i1 @PR28011(i16 %a) {
+; CHECK-LABEL: @PR28011(
+; CHECK-NEXT:    [[CONV:%.*]] = sext i16 %a to i32
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[CONV]], or (i32 zext (i1 icmp ne (i32*** bitcast ([1 x i32]* @b to i32***), i32*** @a) to i32), i32 1)
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %conv = sext i16 %a to i32
+  %cmp = icmp ne i32 %conv, or (i32 zext (i1 icmp ne (i32*** bitcast ([1 x i32]* @b to i32***), i32*** @a) to i32), i32 1)
+  ret i1 %cmp
+}
+
+define <2 x i1> @lt_signed_to_large_unsigned_vec(<2 x i8> %SB) {
+; CHECK-LABEL: @lt_signed_to_large_unsigned_vec(
+; CHECK-NEXT:    [[Y:%.*]] = sext <2 x i8> %SB to <2 x i32>
+; CHECK-NEXT:    [[C:%.*]] = icmp ult <2 x i32> [[Y]], <i32 1024, i32 2>
+; CHECK-NEXT:    ret <2 x i1> [[C]]
+;
+  %Y = sext <2 x i8> %SB to <2 x i32>
+  %C = icmp ult <2 x i32> %Y, <i32 1024, i32 2>
+  ret <2 x i1> %C
+}
+
+define i1 @lt_signed_to_large_signed(i8 %SB) {
+; CHECK-LABEL: @lt_signed_to_large_signed(
+; CHECK-NEXT:    ret i1 true
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp slt i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @lt_signed_to_large_negative(i8 %SB) {
+; CHECK-LABEL: @lt_signed_to_large_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp slt i32 %Y, -1024
+  ret i1 %C
+}
+
+define i1 @lt_signed_to_small_unsigned(i8 %SB) {
+; CHECK-LABEL: @lt_signed_to_small_unsigned(
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp ult i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @lt_signed_to_small_signed(i8 %SB) {
+; CHECK-LABEL: @lt_signed_to_small_signed(
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp slt i32 %Y, 17
+  ret i1 %C
+}
+define i1 @lt_signed_to_small_negative(i8 %SB) {
+; CHECK-LABEL: @lt_signed_to_small_negative(
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 %SB, -17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp slt i32 %Y, -17
+  ret i1 %C
+}
+
+define i1 @lt_unsigned_to_large_unsigned(i8 %SB) {
+; CHECK-LABEL: @lt_unsigned_to_large_unsigned(
+; CHECK-NEXT:    ret i1 true
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp ult i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @lt_unsigned_to_large_signed(i8 %SB) {
+; CHECK-LABEL: @lt_unsigned_to_large_signed(
+; CHECK-NEXT:    ret i1 true
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp slt i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @lt_unsigned_to_large_negative(i8 %SB) {
+; CHECK-LABEL: @lt_unsigned_to_large_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp slt i32 %Y, -1024
+  ret i1 %C
+}
+
+define i1 @lt_unsigned_to_small_unsigned(i8 %SB) {
+; CHECK-LABEL: @lt_unsigned_to_small_unsigned(
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp ult i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @lt_unsigned_to_small_signed(i8 %SB) {
+; CHECK-LABEL: @lt_unsigned_to_small_signed(
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp slt i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @lt_unsigned_to_small_negative(i8 %SB) {
+; CHECK-LABEL: @lt_unsigned_to_small_negative(
+; CHECK-NEXT:    ret i1 false
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp slt i32 %Y, -17
+  ret i1 %C
+}
+
+define i1 @gt_signed_to_large_unsigned(i8 %SB) {
+; CHECK-LABEL: @gt_signed_to_large_unsigned(
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i8 %SB, 0
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp ugt i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @gt_signed_to_large_signed(i8 %SB) {
+; CHECK-LABEL: @gt_signed_to_large_signed(
+; CHECK-NEXT:    ret i1 false
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp sgt i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @gt_signed_to_large_negative(i8 %SB) {
+; CHECK-LABEL: @gt_signed_to_large_negative(
+; CHECK-NEXT:    ret i1 true
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp sgt i32 %Y, -1024
+  ret i1 %C
+}
+
+define i1 @gt_signed_to_small_unsigned(i8 %SB) {
+; CHECK-LABEL: @gt_signed_to_small_unsigned(
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp ugt i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @gt_signed_to_small_signed(i8 %SB) {
+; CHECK-LABEL: @gt_signed_to_small_signed(
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp sgt i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @gt_signed_to_small_negative(i8 %SB) {
+; CHECK-LABEL: @gt_signed_to_small_negative(
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i8 %SB, -17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = sext i8 %SB to i32
+  %C = icmp sgt i32 %Y, -17
+  ret i1 %C
+}
+
+define i1 @gt_unsigned_to_large_unsigned(i8 %SB) {
+; CHECK-LABEL: @gt_unsigned_to_large_unsigned(
+; CHECK-NEXT:    ret i1 false
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp ugt i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @gt_unsigned_to_large_signed(i8 %SB) {
+; CHECK-LABEL: @gt_unsigned_to_large_signed(
+; CHECK-NEXT:    ret i1 false
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp sgt i32 %Y, 1024
+  ret i1 %C
+}
+
+define i1 @gt_unsigned_to_large_negative(i8 %SB) {
+; CHECK-LABEL: @gt_unsigned_to_large_negative(
+; CHECK-NEXT:    ret i1 true
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp sgt i32 %Y, -1024
+  ret i1 %C
+}
+
+define i1 @gt_unsigned_to_small_unsigned(i8 %SB) {
+; CHECK-LABEL: @gt_unsigned_to_small_unsigned(
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp ugt i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @gt_unsigned_to_small_signed(i8 %SB) {
+; CHECK-LABEL: @gt_unsigned_to_small_signed(
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i8 %SB, 17
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp sgt i32 %Y, 17
+  ret i1 %C
+}
+
+define i1 @gt_unsigned_to_small_negative(i8 %SB) {
+; CHECK-LABEL: @gt_unsigned_to_small_negative(
+; CHECK-NEXT:    ret i1 true
+;
+  %Y = zext i8 %SB to i32
+  %C = icmp sgt i32 %Y, -17
+  ret i1 %C
+}
+

Added: llvm/trunk/test/Transforms/InstCombine/2004-12-08-RemInfiniteLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2004-12-08-RemInfiniteLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2004-12-08-RemInfiniteLoop.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2004-12-08-RemInfiniteLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,7 @@
+; RUN: opt < %s -instcombine
+
+define i32 @test(i32 %X) {
+        %Y = srem i32 %X, undef         ; <i32> [#uses=1]
+        ret i32 %Y
+}
+




More information about the llvm-commits mailing list