[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/NewGVN/cyclic-phi-handling.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/cyclic-phi-handling.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/cyclic-phi-handling.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/cyclic-phi-handling.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo(i32 %arg, i32 %arg1, i32 (i32, i32)* %arg2) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label %bb3
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ %arg1, %bb ], [ [[TMP:%.*]]4, %bb7 ]
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ %arg, %bb ], [ [[TMP]], %bb7 ]
+; CHECK-NEXT:    [[TMP5:%.*]] = call i32 %arg2(i32 [[TMP4]], i32 [[TMP]])
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label %bb7, label %bb8
+; CHECK:       bb7:
+; CHECK-NEXT:    br label %bb3
+; CHECK:       bb8:
+; CHECK-NEXT:    ret void
+;
+bb:
+  br label %bb3
+
+;; While non-standard, llvm allows mutually dependent phi nodes
+;; Ensure we do not infinite loop trying to process them
+bb3:                                              ; preds = %bb7, %bb
+  %tmp = phi i32 [ %arg1, %bb ], [ %tmp4, %bb7 ]
+  %tmp4 = phi i32 [ %arg, %bb ], [ %tmp, %bb7 ]
+  %tmp5 = call i32 %arg2(i32 %tmp4, i32 %tmp)
+  %tmp6 = icmp ne i32 %tmp5, 0
+  br i1 %tmp6, label %bb7, label %bb8
+
+bb7:                                              ; preds = %bb3
+  br label %bb3
+
+bb8:                                              ; preds = %bb3
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/dbg-redundant-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/dbg-redundant-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/dbg-redundant-load.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/dbg-redundant-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+; Check that the redundant load from %if.then is removed.
+; Also, check that the debug location associated to load %0 still refers to
+; line 3 and not line 6.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; CHECK: @test_redundant_load(
+; CHECK-LABEL: entry:
+; CHECK-NEXT: load i32, i32* %Y, align 4, !dbg ![[LOC:[0-9]+]]
+; CHECK-LABEL: if.then:
+; CHECK-NOT: load
+; CHECK-LABEL: if.end:
+; CHECK: ![[LOC]] = !DILocation(line: 3, scope: !{{.*}})
+
+define i32 @test_redundant_load(i32 %X, i32* %Y) !dbg !6 {
+entry:
+  %0 = load i32, i32* %Y, align 4, !dbg !8
+  %cmp = icmp sgt i32 %X, -1, !dbg !9
+  br i1 %cmp, label %if.then, label %if.end, !dbg !9
+
+if.then:                                          ; preds = %entry
+  %1 = load i32, i32* %Y, align 4, !dbg !10
+  %add = add nsw i32 %0, %1, !dbg !10
+  call void @foo(), !dbg !11
+  br label %if.end, !dbg !12
+
+if.end:                                           ; preds = %if.then, %entry
+  %Result.0 = phi i32 [ %add, %if.then ], [ %0, %entry ]
+  ret i32 %Result.0, !dbg !13
+}
+
+declare void @foo()
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "test.cpp", directory: "")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = distinct !DISubprogram(name: "test_redundant_load", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!7 = !DISubroutineType(types: !2)
+!8 = !DILocation(line: 3, scope: !6)
+!9 = !DILocation(line: 5, scope: !6)
+!10 = !DILocation(line: 6, scope: !6)
+!11 = !DILocation(line: 7, scope: !6)
+!12 = !DILocation(line: 8, scope: !6)
+!13 = !DILocation(line: 10, scope: !6)

Added: llvm/trunk/test/Transforms/NewGVN/deadstore.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/deadstore.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/deadstore.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/deadstore.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+;; Most of these are borrowed from transforms/DSE/simple.ll
+;; NewGVN should be able to eliminate any stores of the same value that are actually redundnat.
+
+;; tmp5 is store of the same value to the same location as the load.
+define void @test12({ i32, i32 }* %x) nounwind  {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[X:%.*]], i32 0, i32 0
+; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP4]], align 4
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[X]], i32 0, i32 1
+; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[TMP7]], align 4
+; CHECK-NEXT:    [[TMP17:%.*]] = sub i32 0, [[TMP8]]
+; CHECK-NEXT:    store i32 [[TMP17]], i32* [[TMP7]], align 4
+; CHECK-NEXT:    ret void
+;
+  %tmp4 = getelementptr { i32, i32 }, { i32, i32 }* %x, i32 0, i32 0
+  %tmp5 = load i32, i32* %tmp4, align 4
+  %tmp7 = getelementptr { i32, i32 }, { i32, i32 }* %x, i32 0, i32 1
+  %tmp8 = load i32, i32* %tmp7, align 4
+  %tmp17 = sub i32 0, %tmp8
+  store i32 %tmp5, i32* %tmp4, align 4
+  store i32 %tmp17, i32* %tmp7, align 4
+  ret void
+}
+; Remove redundant store if loaded value is in another block.
+define i32 @test26(i1 %c, i32* %p) {
+; CHECK-LABEL: @test26(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[V:%.*]] = load i32, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %v = load i32, i32* %p, align 4
+  br i1 %c, label %bb1, label %bb2
+bb1:
+  br label %bb3
+bb2:
+  store i32 %v, i32* %p, align 4
+  br label %bb3
+bb3:
+  ret i32 0
+}
+
+declare void @unknown_func()
+; Remove redundant store, which is in the same loop as the load.
+define i32 @test33(i1 %c, i32* %p, i32 %i) {
+; CHECK-LABEL: @test33(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[V:%.*]] = load i32, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    call void @unknown_func()
+; CHECK-NEXT:    br i1 undef, label [[BB1]], label [[BB3:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %bb1
+bb1:
+  %v = load i32, i32* %p, align 4
+  br label %bb2
+bb2:
+  store i32 %v, i32* %p, align 4
+  ; Might read and overwrite value at %p, but doesn't matter.
+  call void @unknown_func()
+  br i1 undef, label %bb1, label %bb3
+bb3:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/NewGVN/debugloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/debugloc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/debugloc.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/debugloc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,78 @@
+; XFAIL: *
+; RUN: opt < %s -newgvn -S | FileCheck %s
+; CHECK: {{^}}for.body:
+; CHECK-NEXT: [[VREG1:%[^ ]+]] = phi{{.*}}[[VREG2:%[^ ]+]],{{.*}}%.sink,
+; CHECK-NOT: !dbg
+; CHECK-SAME: {{$}}
+; CHECK: {{^}}for.inc:
+; CHECK-NEXT: [[VREG2]] = phi{{.*}}%inc,{{.*}}[[VREG1]]
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at g = external local_unnamed_addr global i32, align 4
+
+; Function Attrs: nounwind uwtable
+define void @foo(i32 %x, i32 %y, i32 %z) local_unnamed_addr #0 !dbg !4 {
+entry:
+  %not.tobool = icmp eq i32 %x, 0, !dbg !8
+  %.sink = zext i1 %not.tobool to i32, !dbg !8
+  store i32 %.sink, i32* @g, align 4, !tbaa !9
+  %cmp8 = icmp sgt i32 %y, 0, !dbg !13
+  br i1 %cmp8, label %for.body.preheader, label %for.end, !dbg !17
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body, !dbg !19
+
+for.body:                                         ; preds = %for.body.preheader, %for.inc
+  %i.09 = phi i32 [ %inc4, %for.inc ], [ 0, %for.body.preheader ]
+  %cmp1 = icmp sgt i32 %i.09, %z, !dbg !19
+  br i1 %cmp1, label %if.then2, label %for.inc, !dbg !21
+
+if.then2:                                         ; preds = %for.body
+  %0 = load i32, i32* @g, align 4, !dbg !22, !tbaa !9
+  %inc = add nsw i32 %0, 1, !dbg !22
+  store i32 %inc, i32* @g, align 4, !dbg !22, !tbaa !9
+  br label %for.inc, !dbg !23
+
+for.inc:                                          ; preds = %for.body, %if.then2
+  %inc4 = add nuw nsw i32 %i.09, 1, !dbg !24
+  %exitcond = icmp ne i32 %inc4, %y, !dbg !13
+  br i1 %exitcond, label %for.body, label %for.end.loopexit, !dbg !17
+
+for.end.loopexit:                                 ; preds = %for.inc
+  br label %for.end, !dbg !26
+
+for.end:                                          ; preds = %for.end.loopexit, %entry
+  ret void, !dbg !26
+}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
+!1 = !DIFile(filename: "foo.c", directory: "b/")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null, !7, !7, !7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !DILocation(line: 4, column: 7, scope: !4)
+!9 = !{!10, !10, i64 0}
+!10 = !{!"int", !11, i64 0}
+!11 = !{!"omnipotent char", !12, i64 0}
+!12 = !{!"Simple C/C++ TBAA"}
+!13 = !DILocation(line: 10, column: 13, scope: !14)
+!14 = !DILexicalBlockFile(scope: !15, file: !1, discriminator: 1)
+!15 = distinct !DILexicalBlock(scope: !16, file: !1, line: 10, column: 3)
+!16 = distinct !DILexicalBlock(scope: !4, file: !1, line: 10, column: 3)
+!17 = !DILocation(line: 10, column: 3, scope: !18)
+!18 = !DILexicalBlockFile(scope: !16, file: !1, discriminator: 1)
+!19 = !DILocation(line: 11, column: 11, scope: !20)
+!20 = distinct !DILexicalBlock(scope: !15, file: !1, line: 11, column: 9)
+!21 = !DILocation(line: 11, column: 9, scope: !15)
+!22 = !DILocation(line: 12, column: 8, scope: !20)
+!23 = !DILocation(line: 12, column: 7, scope: !20)
+!24 = !DILocation(line: 10, column: 20, scope: !25)
+!25 = !DILexicalBlockFile(scope: !15, file: !1, discriminator: 2)
+!26 = !DILocation(line: 13, column: 1, scope: !4)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}

Added: llvm/trunk/test/Transforms/NewGVN/edge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/edge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/edge.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/edge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,170 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+define i32 @f1(i32 %x) {
+  ; CHECK-LABEL: define i32 @f1(
+bb0:
+  %cmp = icmp eq i32 %x, 0
+  br i1 %cmp, label %bb2, label %bb1
+bb1:
+  br label %bb2
+bb2:
+  %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+  %foo = add i32 %cond, %x
+  ret i32 %foo
+  ; CHECK: bb2:
+  ; CHECK: ret i32 %x
+}
+
+define i32 @f2(i32 %x) {
+  ; CHECK-LABEL: define i32 @f2(
+bb0:
+  %cmp = icmp ne i32 %x, 0
+  br i1 %cmp, label %bb1, label %bb2
+bb1:
+  br label %bb2
+bb2:
+  %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+  %foo = add i32 %cond, %x
+  ret i32 %foo
+  ; CHECK: bb2:
+  ; CHECK: ret i32 %x
+}
+
+define i32 @f3(i32 %x) {
+  ; CHECK-LABEL: define i32 @f3(
+bb0:
+  switch i32 %x, label %bb1 [ i32 0, label %bb2]
+bb1:
+  br label %bb2
+bb2:
+  %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
+  %foo = add i32 %cond, %x
+  ret i32 %foo
+  ; CHECK: bb2:
+  ; CHECK: ret i32 %x
+}
+
+declare void @g(i1)
+define void @f4(i8 * %x)  {
+; CHECK-LABEL: define void @f4(
+bb0:
+  %y = icmp eq i8* null, %x
+  br i1 %y, label %bb2, label %bb1
+bb1:
+  br label %bb2
+bb2:
+  %zed = icmp eq i8* null, %x
+  call void @g(i1 %zed)
+; CHECK: call void @g(i1 %y)
+  ret void
+}
+
+define double @fcmp_oeq_not_zero(double %x, double %y) {
+entry:
+  %cmp = fcmp oeq double %y, 2.0
+  br i1 %cmp, label %if, label %return
+
+if:
+  %div = fdiv double %x, %y
+  br label %return
+
+return:
+  %retval = phi double [ %div, %if ], [ %x, %entry ]
+  ret double %retval
+
+; CHECK-LABEL: define double @fcmp_oeq_not_zero(
+; CHECK: %div = fdiv double %x, 2.0
+}
+
+define double @fcmp_une_not_zero(double %x, double %y) {
+entry:
+  %cmp = fcmp une double %y, 2.0
+  br i1 %cmp, label %return, label %else
+
+else:
+  %div = fdiv double %x, %y
+  br label %return
+
+return:
+  %retval = phi double [ %div, %else ], [ %x, %entry ]
+  ret double %retval
+
+; CHECK-LABEL: define double @fcmp_une_not_zero(
+; CHECK: %div = fdiv double %x, 2.0
+}
+
+; PR22376 - We can't propagate zero constants because -0.0 
+; compares equal to 0.0. If %y is -0.0 in this test case,
+; we would produce the wrong sign on the infinity return value.
+define double @fcmp_oeq_zero(double %x, double %y) {
+entry:
+  %cmp = fcmp oeq double %y, 0.0
+  br i1 %cmp, label %if, label %return
+
+if:
+  %div = fdiv double %x, %y
+  br label %return
+
+return:
+  %retval = phi double [ %div, %if ], [ %x, %entry ]
+  ret double %retval
+
+; CHECK-LABEL: define double @fcmp_oeq_zero(
+; CHECK: %div = fdiv double %x, %y
+}
+
+define double @fcmp_une_zero(double %x, double %y) {
+entry:
+  %cmp = fcmp une double %y, -0.0
+  br i1 %cmp, label %return, label %else
+
+else:
+  %div = fdiv double %x, %y
+  br label %return
+
+return:
+  %retval = phi double [ %div, %else ], [ %x, %entry ]
+  ret double %retval
+
+; CHECK-LABEL: define double @fcmp_une_zero(
+; CHECK: %div = fdiv double %x, %y
+}
+
+; We also cannot propagate a value if it's not a constant.
+; This is because the value could be 0.0 or -0.0.
+
+define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
+entry:
+ %z = fadd double %z1, %z2
+ %cmp = fcmp oeq double %y, %z
+ br i1 %cmp, label %if, label %return
+
+if:
+ %div = fdiv double %x, %z
+ br label %return
+
+return:
+ %retval = phi double [ %div, %if ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_oeq_maybe_zero(
+; CHECK: %div = fdiv double %x, %z
+}
+
+define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
+entry:
+ %z = fadd double %z1, %z2
+ %cmp = fcmp une double %y, %z
+ br i1 %cmp, label %return, label %else
+
+else:
+ %div = fdiv double %x, %z
+ br label %return
+
+return:
+ %retval = phi double [ %div, %else ], [ %x, %entry ]
+ ret double %retval
+
+; CHECK-LABEL: define double @fcmp_une_maybe_zero(
+; CHECK: %div = fdiv double %x, %z
+}

Added: llvm/trunk/test/Transforms/NewGVN/eliminate-callsite-inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/eliminate-callsite-inline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/eliminate-callsite-inline.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/eliminate-callsite-inline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -inline -newgvn -S < %s | FileCheck %s
+
+; CHECK-LABEL: @f2()
+; CHECK-NEXT:    ret void
+; CHECK-NOT: @f1
+
+define void @f2() {
+  call void @f1()
+  call void @f1()
+  ret void
+}
+
+define internal void @f1() #1 {
+entry:
+  ret void
+}
+
+attributes #1 = { noinline nounwind readnone }

Added: llvm/trunk/test/Transforms/NewGVN/eliminate-ssacopy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/eliminate-ssacopy.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/eliminate-ssacopy.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/eliminate-ssacopy.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+; Make sure the created ssa copies are cleaned up. See PR38804.
+
+; CHECK-NOT: ssa_copy
+
+ at b = external dso_local local_unnamed_addr global i32, align 4
+ at a = external dso_local local_unnamed_addr global i8, align 1
+ at f = external dso_local local_unnamed_addr global i16, align 2
+
+define void @g() {
+; CHECK-LABEL: @g(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 undef, label [[FOR_COND1THREAD_PRE_SPLIT:%.*]], label [[FOR_COND_PREHEADER:%.*]]
+; CHECK:       for.cond.preheader:
+; CHECK-NEXT:    unreachable
+; CHECK:       for.cond1thread-pre-split:
+; CHECK-NEXT:    br label [[FOR_END4_SPLIT:%.*]]
+; CHECK:       for.end4.split:
+; CHECK-NEXT:    br i1 true, label [[FOR_COND6_PREHEADER:%.*]], label [[IF_END11:%.*]]
+; CHECK:       for.cond6.preheader:
+; CHECK-NEXT:    br i1 undef, label [[FOR_COND6_PREHEADER3:%.*]], label [[IF_END11_LOOPEXIT:%.*]]
+; CHECK:       for.cond6.preheader3:
+; CHECK-NEXT:    br label [[IF_END11_LOOPEXIT]]
+; CHECK:       if.end11.loopexit:
+; CHECK-NEXT:    [[STOREMERGE_LCSSA:%.*]] = phi i32 [ 0, [[FOR_COND6_PREHEADER]] ], [ 1, [[FOR_COND6_PREHEADER3]] ]
+; CHECK-NEXT:    store i32 [[STOREMERGE_LCSSA]], i32* @b, align 4
+; CHECK-NEXT:    br label [[IF_END11]]
+; CHECK:       if.end11:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @b, align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = load i8, i8* @a, align 1
+; CHECK-NEXT:    [[CONV:%.*]] = sext i8 [[TMP1]] to i32
+; CHECK-NEXT:    [[CMP12:%.*]] = icmp eq i32 [[TMP0]], [[CONV]]
+; CHECK-NEXT:    br i1 [[CMP12]], label [[IF_THEN14:%.*]], label [[IF_END16:%.*]]
+; CHECK:       if.then14:
+; CHECK-NEXT:    [[CONV15:%.*]] = trunc i32 [[TMP0]] to i16
+; CHECK-NEXT:    store i16 [[CONV15]], i16* @f, align 2
+; CHECK-NEXT:    unreachable
+; CHECK:       if.end16:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %tobool = icmp eq i32 undef, 0
+  br i1 %tobool, label %for.cond1thread-pre-split, label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %entry
+  unreachable
+
+for.cond1thread-pre-split:                        ; preds = %entry
+  br label %for.end4.split
+
+for.end4.split:                                   ; preds = %for.cond1thread-pre-split
+  br i1 %tobool, label %for.cond6.preheader, label %if.end11
+
+for.cond6.preheader:                              ; preds = %for.end4.split
+  br i1 undef, label %for.cond6.preheader3, label %if.end11.loopexit
+
+for.cond6.preheader3:                             ; preds = %for.cond6.preheader
+  br label %if.end11.loopexit
+
+if.end11.loopexit:                                ; preds = %for.cond6.preheader3, %for.cond6.preheader
+  %storemerge.lcssa = phi i32 [ 0, %for.cond6.preheader ], [ 1, %for.cond6.preheader3 ]
+  store i32 %storemerge.lcssa, i32* @b, align 4
+  br label %if.end11
+
+if.end11:                                         ; preds = %if.end11.loopexit, %for.end4.split
+  %0 = load i32, i32* @b, align 4
+  %1 = load i8, i8* @a, align 1
+  %conv = sext i8 %1 to i32
+  %cmp12 = icmp eq i32 %0, %conv
+  br i1 %cmp12, label %if.then14, label %if.end16
+
+if.then14:                                        ; preds = %if.end11
+  %conv15 = trunc i32 %0 to i16
+  store i16 %conv15, i16* @f, align 2
+  unreachable
+
+if.end16:                                         ; preds = %if.end11
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/equivalent-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/equivalent-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/equivalent-phi.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/equivalent-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+ at global = common global [1024 x i32] zeroinitializer, align 16
+
+;; We should be able to prove the equivalence of two of the phis, and then use that to eliminate
+;; one set of indexing calculations and a load
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @bar(i32 %arg, i32 %arg1, i32 %arg2) #0 {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label %bb3
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ %arg, %bb ], [ [[TMP:%.*]]15, %bb17 ]
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ %arg2, %bb ], [ [[TMP18:%.*]], %bb17 ]
+; CHECK-NEXT:    [[TMP6:%.*]] = phi i32 [ 0, %bb ], [ [[TMP14:%.*]], %bb17 ]
+; CHECK-NEXT:    [[TMP7:%.*]] = sext i32 [[TMP]] to i64
+; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [1024 x i32], [1024 x i32]* @global, i64 0, i64 [[TMP7]]
+; CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[TMP8]], align 4
+; CHECK-NEXT:    [[TMP10:%.*]] = add nsw i32 [[TMP6]], [[TMP9]]
+; CHECK-NEXT:    [[TMP14]] = add nsw i32 [[TMP10]], [[TMP9]]
+; CHECK-NEXT:    [[TMP15:%.*]] = add nsw i32 [[TMP]], %arg1
+; CHECK-NEXT:    br label %bb17
+; CHECK:       bb17:
+; CHECK-NEXT:    [[TMP18]] = add i32 [[TMP4]], -1
+; CHECK-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP4]], 0
+; CHECK-NEXT:    br i1 [[TMP19]], label %bb3, label %bb20
+; CHECK:       bb20:
+; CHECK-NEXT:    ret i32 [[TMP14]]
+;
+bb:
+  br label %bb3
+
+bb3:                                              ; preds = %bb17, %bb
+  %tmp = phi i32 [ %arg, %bb ], [ %tmp15, %bb17 ]
+  %tmp4 = phi i32 [ %arg2, %bb ], [ %tmp18, %bb17 ]
+  %tmp5 = phi i32 [ %arg, %bb ], [ %tmp16, %bb17 ]
+  %tmp6 = phi i32 [ 0, %bb ], [ %tmp14, %bb17 ]
+  %tmp7 = sext i32 %tmp to i64
+  %tmp8 = getelementptr inbounds [1024 x i32], [1024 x i32]* @global, i64 0, i64 %tmp7
+  %tmp9 = load i32, i32* %tmp8, align 4
+  %tmp10 = add nsw i32 %tmp6, %tmp9
+  %tmp11 = sext i32 %tmp5 to i64
+  %tmp12 = getelementptr inbounds [1024 x i32], [1024 x i32]* @global, i64 0, i64 %tmp11
+  %tmp13 = load i32, i32* %tmp12, align 4
+  %tmp14 = add nsw i32 %tmp10, %tmp13
+  %tmp15 = add nsw i32 %tmp, %arg1
+  %tmp16 = add nsw i32 %tmp5, %arg1
+  br label %bb17
+
+bb17:                                             ; preds = %bb3
+  %tmp18 = add i32 %tmp4, -1
+  %tmp19 = icmp ne i32 %tmp4, 0
+  br i1 %tmp19, label %bb3, label %bb20
+
+bb20:                                             ; preds = %bb17
+  ret i32 %tmp14
+}
+
+attributes #0 = { nounwind ssp 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"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"PIC Level", i32 2}
+!1 = !{!"Apple LLVM version 8.0.0 (clang-800.0.42.1)"}

Added: llvm/trunk/test/Transforms/NewGVN/fence.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/fence.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/fence.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/fence.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,90 @@
+; XFAIL: *
+; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s
+
+ at a = external constant i32
+; We can value forward across the fence since we can (semantically) 
+; reorder the following load before the fence.
+define i32 @test(i32* %addr.i) {
+; CHECK-LABEL: @test
+; CHECK: store
+; CHECK: fence
+; CHECK-NOT: load
+; CHECK: ret
+  store i32 5, i32* %addr.i, align 4
+  fence release
+  %a = load i32, i32* %addr.i, align 4
+  ret i32 %a
+}
+
+; Same as above
+define i32 @test2(i32* %addr.i) {
+; CHECK-LABEL: @test2
+; CHECK-NEXT: fence
+; CHECK-NOT: load
+; CHECK: ret
+  %a = load i32, i32* %addr.i, align 4
+  fence release
+  %a2 = load i32, i32* %addr.i, align 4
+  %res = sub i32 %a, %a2
+  ret i32 %res
+}
+
+; We can not value forward across an acquire barrier since we might
+; be syncronizing with another thread storing to the same variable
+; followed by a release fence.  This is not so much enforcing an
+; ordering property (though it is that too), but a liveness 
+; property.  We expect to eventually see the value of store by
+; another thread when spinning on that location.  
+define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) {
+; CHECK-LABEL: @test3
+; CHECK: load
+; CHECK: fence
+; CHECK: load
+; CHECK: ret i32 %res
+  ; the following code is intented to model the unrolling of
+  ; two iterations in a spin loop of the form:
+  ;   do { fence acquire: tmp = *%addr.i; ) while (!tmp);
+  ; It's hopefully clear that allowing PRE to turn this into:
+  ;   if (!*%addr.i) while(true) {} would be unfortunate
+  fence acquire
+  %a = load i32, i32* %addr.i, align 4
+  fence acquire
+  %a2 = load i32, i32* %addr.i, align 4
+  %res = sub i32 %a, %a2
+  ret i32 %res
+}
+
+; We can forward the value forward the load
+; across both the fences, because the load is from
+; a constant memory location.
+define i32 @test4(i32* %addr) {
+; CHECK-LABEL: @test4
+; CHECK-NOT: load
+; CHECK: fence release
+; CHECK: store
+; CHECK: fence seq_cst
+; CHECK: ret i32 0
+  %var = load i32, i32* @a
+  fence release
+  store i32 42, i32* %addr, align 8
+  fence seq_cst
+  %var2 = load i32, i32* @a
+  %var3 = sub i32 %var, %var2
+  ret i32 %var3
+}
+
+; Another example of why forwarding across an acquire fence is problematic
+; can be seen in a normal locking operation.  Say we had:
+; *p = 5; unlock(l); lock(l); use(p);
+; forwarding the store to p would be invalid.  A reasonable implementation
+; of unlock and lock might be:
+; unlock() { atomicrmw sub %l, 1 unordered; fence release }
+; lock() { 
+;   do {
+;     %res = cmpxchg %p, 0, 1, monotonic monotonic
+;   } while(!%res.success)
+;   fence acquire;
+; }
+; Given we chose to forward across the release fence, we clearly can't forward
+; across the acquire fence as well.
+

Added: llvm/trunk/test/Transforms/NewGVN/flags-simplify.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/flags-simplify.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/flags-simplify.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/flags-simplify.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -newgvn < %s | FileCheck %s
+
+; Check that we do not use keywords only available for some members of a
+; congruence class when simplifying.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at f = external global i64, align 8
+ at b = external global i1, align 8
+
+define i64 @ashr_lsh_nsw(i64 %tmp) {
+; CHECK-LABEL: @ashr_lsh_nsw(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV3:%.*]] = shl i64 [[TMP:%.*]], 32
+; CHECK-NEXT:    store i64 [[CONV3]], i64* @f, align 8
+; CHECK-NEXT:    [[CONV7:%.*]] = ashr exact i64 [[CONV3]], 32
+; CHECK-NEXT:    ret i64 [[CONV7]]
+;
+entry:                                          ; preds = %if.then
+  %conv3 = shl nsw i64 %tmp, 32
+  store i64 %conv3, i64* @f, align 8
+  %sext = shl i64 %tmp, 32
+  %conv7 = ashr exact i64 %sext, 32
+  ret i64 %conv7
+}
+
+define i64 @ashr_lsh_nuw(i64 %tmp) {
+; CHECK-LABEL: @ashr_lsh_nuw(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CONV3:%.*]] = shl i64 [[TMP:%.*]], 32
+; CHECK-NEXT:    store i64 [[CONV3]], i64* @f, align 8
+; CHECK-NEXT:    [[CONV7:%.*]] = ashr exact i64 [[CONV3]], 32
+; CHECK-NEXT:    ret i64 [[CONV7]]
+;
+entry:                                          ; preds = %if.then
+  %conv3 = shl nuw i64 %tmp, 32
+  store i64 %conv3, i64* @f, align 8
+  %sext = shl i64 %tmp, 32
+  %conv7 = ashr exact i64 %sext, 32
+  ret i64 %conv7
+}
+
+define i32 @udiv_exact_mul(i32 %x, i32 %y, i1 %arg2) {
+; CHECK-LABEL: @udiv_exact_mul(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[S1:%.*]] = udiv exact i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[S2:%.*]] = mul i32 [[S1]], [[Y]]
+; CHECK-NEXT:    ret i32 [[S2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[S1_2:%.*]] = udiv i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[S2_2:%.*]] = mul i32 [[S1_2]], [[Y]]
+; CHECK-NEXT:    ret i32 [[S2_2]]
+;
+  br i1 %arg2, label %bb2, label %bb1
+bb1:
+  %s1 = udiv exact i32 %x, %y
+  %s2 = mul i32 %s1, %y
+  ret i32 %s2
+
+bb2:
+  %s1.2 = udiv i32 %x, %y
+  %s2.2 = mul i32 %s1.2, %y
+  ret i32 %s2.2
+}
+
+define i1 @add_nuw_icmp(i32 %x, i32 %y, i1 %arg2) {
+; CHECK-LABEL: @add_nuw_icmp(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[Z:%.*]] = add i32 [[Y:%.*]], 1
+; CHECK-NEXT:    [[S1:%.*]] = add i32 [[X:%.*]], [[Z]]
+; CHECK-NEXT:    [[S2:%.*]] = add i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ugt i32 [[S1]], [[S2]]
+; CHECK-NEXT:    ret i1 [[C]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[Z_2:%.*]] = add nuw i32 [[Y]], 1
+; CHECK-NEXT:    [[S1_2:%.*]] = add nuw i32 [[X]], [[Z_2]]
+; CHECK-NEXT:    [[S2_2:%.*]] = add nuw i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i32 [[S1_2]], [[S2_2]]
+; CHECK-NEXT:    ret i1 [[C_2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %z = add i32 %y, 1
+  %s1 = add i32 %x, %z
+  %s2 = add i32 %x, %y
+  %c = icmp ugt i32 %s1, %s2
+  ret i1 %c
+
+bb2:
+  %z.2 = add nuw i32 %y, 1
+  %s1.2 = add nuw i32 %x, %z.2
+  %s2.2 = add nuw i32 %x, %y
+  %c.2 = icmp ugt i32 %s1.2, %s2.2
+  ret i1 %c.2
+}

Added: llvm/trunk/test/Transforms/NewGVN/flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/flags.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/flags.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/flags.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @test1(float %x, float %y) {
+entry:
+  %cmp1 = fcmp nnan oeq float %y, %x
+  %cmp2 = fcmp oeq float %x, %y
+  call void @use(i1 %cmp1)
+  call void @use(i1 %cmp2)
+  ret void
+}
+
+; CHECK-LABEL: define void @test1(
+; CHECK: %[[cmp:.*]] = fcmp oeq float %y, %x
+; CHECK-NEXT: call void @use(i1 %[[cmp]])
+; CHECK-NEXT: call void @use(i1 %[[cmp]])
+; CHECK-NEXT: ret void

Added: llvm/trunk/test/Transforms/NewGVN/fold-const-expr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/fold-const-expr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/fold-const-expr.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/fold-const-expr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,98 @@
+; GVN failed to do constant expression folding and expanded
+; them unfolded in many places, producing exponentially large const
+; expressions. As a result, the compilation never fisished.
+; This test checks that we are folding constant expression
+; PR 28418
+; RUN: opt -newgvn -S < %s | FileCheck %s
+%2 = type { i32, i32, i32, i32, i32 }
+define i32 @_Z16vector3util_mainv(i32 %x, i32 %y)  {
+  %tmp1 = alloca %2, align 4
+  %tmp114 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+  %tmp115 = bitcast i32* %tmp114 to <4 x i32>*
+  store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, <4 x i32>* %tmp115, align 4
+  %tmp1683 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+  %tmp1688 = load i32, i32* %tmp1683, align 4
+  %tmp1693 = shl i32 %tmp1688, 5
+  %tmp1694 = xor i32 %tmp1693, %tmp1688
+  %tmp1695 = lshr i32 %tmp1694, 7
+  %tmp1696 = xor i32 %tmp1695, %tmp1694
+  %tmp1697 = shl i32 %tmp1696, 22
+  %tmp1698 = xor i32 %tmp1697, %tmp1696
+  %tmp1707 = shl i32 %tmp1698, 5
+  %tmp1708 = xor i32 %tmp1707, %tmp1698
+  %tmp1709 = lshr i32 %tmp1708, 7
+  %tmp1710 = xor i32 %tmp1709, %tmp1708
+  %tmp1711 = shl i32 %tmp1710, 22
+  %tmp1712 = xor i32 %tmp1711, %tmp1710
+  %tmp1721 = shl i32 %tmp1712, 5
+  %tmp1722 = xor i32 %tmp1721, %tmp1712
+  %tmp1723 = lshr i32 %tmp1722, 7
+  %tmp1724 = xor i32 %tmp1723, %tmp1722
+  %tmp1725 = shl i32 %tmp1724, 22
+  %tmp1726 = xor i32 %tmp1725, %tmp1724
+  %tmp1735 = shl i32 %tmp1726, 5
+  %tmp1736 = xor i32 %tmp1735, %tmp1726
+  %tmp1737 = lshr i32 %tmp1736, 7
+  %tmp1738 = xor i32 %tmp1737, %tmp1736
+  %tmp1739 = shl i32 %tmp1738, 22
+  %tmp1740 = xor i32 %tmp1739, %tmp1738
+  store i32 %tmp1740, i32* %tmp1683, align 4
+; CHECK: store i32 310393545, i32* %tmp114, align 4
+  %tmp1756 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+  %tmp1761 = load i32, i32* %tmp1756, align 4
+  %tmp1766 = shl i32 %tmp1761, 5
+  %tmp1767 = xor i32 %tmp1766, %tmp1761
+  %tmp1768 = lshr i32 %tmp1767, 7
+  %tmp1769 = xor i32 %tmp1768, %tmp1767
+  %tmp1770 = shl i32 %tmp1769, 22
+  %tmp1771 = xor i32 %tmp1770, %tmp1769
+  %tmp1780 = shl i32 %tmp1771, 5
+  %tmp1781 = xor i32 %tmp1780, %tmp1771
+  %tmp1782 = lshr i32 %tmp1781, 7
+  %tmp1783 = xor i32 %tmp1782, %tmp1781
+  %tmp1784 = shl i32 %tmp1783, 22
+  %tmp1785 = xor i32 %tmp1784, %tmp1783
+  %tmp1794 = shl i32 %tmp1785, 5
+  %tmp1795 = xor i32 %tmp1794, %tmp1785
+  %tmp1796 = lshr i32 %tmp1795, 7
+  %tmp1797 = xor i32 %tmp1796, %tmp1795
+  %tmp1798 = shl i32 %tmp1797, 22
+  %tmp1799 = xor i32 %tmp1798, %tmp1797
+  %tmp1808 = shl i32 %tmp1799, 5
+  %tmp1809 = xor i32 %tmp1808, %tmp1799
+  %tmp1810 = lshr i32 %tmp1809, 7
+  %tmp1811 = xor i32 %tmp1810, %tmp1809
+  %tmp1812 = shl i32 %tmp1811, 22
+  %tmp1813 = xor i32 %tmp1812, %tmp1811
+  store i32 %tmp1813, i32* %tmp1756, align 4
+; CHECK: store i32 -383584258, i32* %tmp114, align 4
+  %tmp2645 = getelementptr inbounds %2, %2* %tmp1, i64 0, i32 1
+  %tmp2650 = load i32, i32* %tmp2645, align 4
+  %tmp2655 = shl i32 %tmp2650, 5
+  %tmp2656 = xor i32 %tmp2655, %tmp2650
+  %tmp2657 = lshr i32 %tmp2656, 7
+  %tmp2658 = xor i32 %tmp2657, %tmp2656
+  %tmp2659 = shl i32 %tmp2658, 22
+  %tmp2660 = xor i32 %tmp2659, %tmp2658
+  %tmp2669 = shl i32 %tmp2660, 5
+  %tmp2670 = xor i32 %tmp2669, %tmp2660
+  %tmp2671 = lshr i32 %tmp2670, 7
+  %tmp2672 = xor i32 %tmp2671, %tmp2670
+  %tmp2673 = shl i32 %tmp2672, 22
+  %tmp2674 = xor i32 %tmp2673, %tmp2672
+  %tmp2683 = shl i32 %tmp2674, 5
+  %tmp2684 = xor i32 %tmp2683, %tmp2674
+  %tmp2685 = lshr i32 %tmp2684, 7
+  %tmp2686 = xor i32 %tmp2685, %tmp2684
+  %tmp2687 = shl i32 %tmp2686, 22
+  %tmp2688 = xor i32 %tmp2687, %tmp2686
+  %tmp2697 = shl i32 %tmp2688, 5
+  %tmp2698 = xor i32 %tmp2697, %tmp2688
+  %tmp2699 = lshr i32 %tmp2698, 7
+  %tmp2700 = xor i32 %tmp2699, %tmp2698
+  %tmp2701 = shl i32 %tmp2700, 22
+  %tmp2702 = xor i32 %tmp2701, %tmp2700
+  store i32 %tmp2702, i32* %tmp2645, align 4
+; CHECK: store i32 -57163022, i32* %tmp114, align 4
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/NewGVN/fpmath.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/fpmath.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/fpmath.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/fpmath.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+define double @test1(double %x, double %y) {
+; CHECK: @test1(double %x, double %y)
+; CHECK: %add1 = fadd double %x, %y
+; CHECK-NOT: fpmath
+; CHECK: %foo = fadd double %add1, %add1
+  %add1 = fadd double %x, %y, !fpmath !0
+  %add2 = fadd double %x, %y
+  %foo = fadd double %add1, %add2
+  ret double %foo
+}
+
+define double @test2(double %x, double %y) {
+; CHECK: @test2(double %x, double %y)
+; CHECK: %add1 = fadd double %x, %y, !fpmath !0
+; CHECK: %foo = fadd double %add1, %add1
+  %add1 = fadd double %x, %y, !fpmath !0
+  %add2 = fadd double %x, %y, !fpmath !0
+  %foo = fadd double %add1, %add2
+  ret double %foo
+}
+
+define double @test3(double %x, double %y) {
+; CHECK: @test3(double %x, double %y)
+; CHECK: %add1 = fadd double %x, %y, !fpmath !1
+; CHECK: %foo = fadd double %add1, %add1
+  %add1 = fadd double %x, %y, !fpmath !1
+  %add2 = fadd double %x, %y, !fpmath !0
+  %foo = fadd double %add1, %add2
+  ret double %foo
+}
+
+define double @test4(double %x, double %y) {
+; CHECK: @test4(double %x, double %y)
+; CHECK: %add1 = fadd double %x, %y, !fpmath !1
+; CHECK: %foo = fadd double %add1, %add1
+  %add1 = fadd double %x, %y, !fpmath !0
+  %add2 = fadd double %x, %y, !fpmath !1
+  %foo = fadd double %add1, %add2
+  ret double %foo
+}
+
+!0 = !{ float 5.0 }
+!1 = !{ float 2.5 }

Added: llvm/trunk/test/Transforms/NewGVN/funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/funclet.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/funclet.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/funclet.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc"
+
+%eh.ThrowInfo = type { i32, i8*, i8*, i8* }
+%struct.A = type { i32* }
+
+@"_TI1?AUA@@" = external constant %eh.ThrowInfo
+
+define i8 @f() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  %b = alloca i8
+  %c = alloca i8
+  store i8 42, i8* %b
+  store i8 13, i8* %c
+  invoke void @_CxxThrowException(i8* %b, %eh.ThrowInfo* nonnull @"_TI1?AUA@@")
+          to label %unreachable unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %catchpad = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  store i8 5, i8* %b
+  catchret from %catchpad to label %try.cont
+
+try.cont:                                         ; preds = %catch
+  %load_b = load i8, i8* %b
+  %load_c = load i8, i8* %c
+  %add = add i8 %load_b, %load_c
+  ret i8 %add
+
+unreachable:                                      ; preds = %entry
+  unreachable
+}
+; CHECK-LABEL: define i8 @f(
+; CHECK:       %[[load_b:.*]] = load i8, i8* %b
+; CHECK-NEXT:  %[[load_c:.*]] = load i8, i8* %c
+; CHECK-NEXT:  %[[add:.*]] = add i8 %[[load_b]], %[[load_c]]
+; CHECK-NEXT:  ret i8 %[[add]]
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*)

Added: llvm/trunk/test/Transforms/NewGVN/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/int_sideeffect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/int_sideeffect.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/int_sideeffect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -S < %s -newgvn | FileCheck %s
+
+declare void @llvm.sideeffect()
+
+; Store-to-load forwarding across a @llvm.sideeffect.
+
+; CHECK-LABEL: s2l
+; CHECK-NOT: load
+define float @s2l(float* %p) {
+    store float 0.0, float* %p
+    call void @llvm.sideeffect()
+    %t = load float, float* %p
+    ret float %t
+}
+
+; Redundant load elimination across a @llvm.sideeffect.
+
+; CHECK-LABEL: rle
+; CHECK: load
+; CHECK-NOT: load
+define float @rle(float* %p) {
+    %r = load float, float* %p
+    call void @llvm.sideeffect()
+    %s = load float, float* %p
+    %t = fadd float %r, %s
+    ret float %t
+}

Added: llvm/trunk/test/Transforms/NewGVN/invariant.group.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/invariant.group.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/invariant.group.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/invariant.group.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,460 @@
+; XFAIL: *
+; RUN: opt < %s -newgvn -S | FileCheck %s
+
+%struct.A = type { i32 (...)** }
+ at _ZTV1A = available_externally unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 8
+ at _ZTI1A = external constant i8*
+
+ at unknownPtr = external global i8
+
+; CHECK-LABEL: define i8 @simple() {
+define i8 @simple() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    call void @foo(i8* %ptr)
+
+    %a = load i8, i8* %ptr, !invariant.group !0
+    %b = load i8, i8* %ptr, !invariant.group !0
+    %c = load i8, i8* %ptr, !invariant.group !0
+; CHECK: ret i8 42
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @optimizable1() {
+define i8 @optimizable1() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
+    %a = load i8, i8* %ptr, !invariant.group !0
+    
+    call void @foo(i8* %ptr2); call to use %ptr2
+; CHECK: ret i8 42
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @optimizable2() {
+define i8 @optimizable2() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    call void @foo(i8* %ptr)
+    
+    store i8 13, i8* %ptr ; can't use this store with invariant.group
+    %a = load i8, i8* %ptr 
+    call void @bar(i8 %a) ; call to use %a
+    
+    call void @foo(i8* %ptr)
+    %b = load i8, i8* %ptr, !invariant.group !0
+    
+; CHECK: ret i8 42
+    ret i8 %b
+}
+
+; CHECK-LABEL: define i1 @proveEqualityForStrip(
+define i1 @proveEqualityForStrip(i8* %a) {
+; FIXME: The first call could be also removed by GVN. Right now
+; DCE removes it. The second call is CSE'd with the first one.
+; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+; CHECK-NOT: llvm.strip.invariant.group
+  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
+  %r = icmp eq i8* %b1, %b2
+; CHECK: ret i1 true
+  ret i1 %r
+}
+
+; CHECK-LABEL: define i8 @unoptimizable1() {
+define i8 @unoptimizable1() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr
+    call void @foo(i8* %ptr)
+    %a = load i8, i8* %ptr, !invariant.group !0
+; CHECK: ret i8 %a
+    ret i8 %a
+}
+
+; CHECK-LABEL: define void @indirectLoads() {
+define void @indirectLoads() {
+entry:
+  %a = alloca %struct.A*, align 8
+  %0 = bitcast %struct.A** %a to i8*
+  
+  %call = call i8* @getPointer(i8* null) 
+  %1 = bitcast i8* %call to %struct.A*
+  call void @_ZN1AC1Ev(%struct.A* %1)
+  %2 = bitcast %struct.A* %1 to i8***
+  
+; CHECK: %vtable = load {{.*}} !invariant.group
+  %vtable = load i8**, i8*** %2, align 8, !invariant.group !0
+  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
+  call void @llvm.assume(i1 %cmp.vtables)
+  
+  store %struct.A* %1, %struct.A** %a, align 8
+  %3 = load %struct.A*, %struct.A** %a, align 8
+  %4 = bitcast %struct.A* %3 to void (%struct.A*)***
+
+; CHECK: call void @_ZN1A3fooEv(
+  %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !0
+  %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
+  %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
+  call void %5(%struct.A* %3)
+  %6 = load %struct.A*, %struct.A** %a, align 8
+  %7 = bitcast %struct.A* %6 to void (%struct.A*)***
+
+; CHECK: call void @_ZN1A3fooEv(
+  %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !0
+  %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0
+  %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8
+  
+  call void %8(%struct.A* %6)
+  %9 = load %struct.A*, %struct.A** %a, align 8
+  %10 = bitcast %struct.A* %9 to void (%struct.A*)***
+  
+  %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !0
+  %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0
+  %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8
+; CHECK: call void @_ZN1A3fooEv(
+  call void %11(%struct.A* %9)
+ 
+  %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !0
+  %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0
+  %12 = bitcast i8** %vfn6 to void (%struct.A*)**
+  %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8
+; CHECK: call void @_ZN1A3fooEv(
+  call void %13(%struct.A* %9)
+  
+  ret void
+}
+
+; CHECK-LABEL: define void @combiningBitCastWithLoad() {
+define void @combiningBitCastWithLoad() {
+entry:
+  %a = alloca %struct.A*, align 8
+  %0 = bitcast %struct.A** %a to i8*
+  
+  %call = call i8* @getPointer(i8* null) 
+  %1 = bitcast i8* %call to %struct.A*
+  call void @_ZN1AC1Ev(%struct.A* %1)
+  %2 = bitcast %struct.A* %1 to i8***
+  
+; CHECK: %vtable = load {{.*}} !invariant.group
+  %vtable = load i8**, i8*** %2, align 8, !invariant.group !0
+  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
+  
+  store %struct.A* %1, %struct.A** %a, align 8
+; CHECK-NOT: !invariant.group
+  %3 = load %struct.A*, %struct.A** %a, align 8
+  %4 = bitcast %struct.A* %3 to void (%struct.A*)***
+
+  %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !0
+  %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
+  %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
+  call void %5(%struct.A* %3)
+
+  ret void
+}
+
+; CHECK-LABEL:define void @loadCombine() {
+define void @loadCombine() {
+enter:
+  %ptr = alloca i8
+  store i8 42, i8* %ptr
+  call void @foo(i8* %ptr)
+; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group
+  %a = load i8, i8* %ptr, !invariant.group !0
+; CHECK-NOT: load
+  %b = load i8, i8* %ptr, !invariant.group !0
+; CHECK: call void @bar(i8 %[[A]])
+  call void @bar(i8 %a)
+; CHECK: call void @bar(i8 %[[A]])
+  call void @bar(i8 %b)
+  ret void
+}
+
+; CHECK-LABEL: define void @loadCombine1() {
+define void @loadCombine1() {
+enter:
+  %ptr = alloca i8
+  store i8 42, i8* %ptr
+  call void @foo(i8* %ptr)
+; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group
+  %c = load i8, i8* %ptr
+; CHECK-NOT: load
+  %d = load i8, i8* %ptr, !invariant.group !0
+; CHECK: call void @bar(i8 %[[D]])
+  call void @bar(i8 %c)
+; CHECK: call void @bar(i8 %[[D]])
+  call void @bar(i8 %d)
+  ret void
+}
+
+; CHECK-LABEL: define void @loadCombine2() {    
+define void @loadCombine2() {
+enter:
+  %ptr = alloca i8
+  store i8 42, i8* %ptr
+  call void @foo(i8* %ptr)
+; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
+  %e = load i8, i8* %ptr, !invariant.group !0
+; CHECK-NOT: load
+  %f = load i8, i8* %ptr
+; CHECK: call void @bar(i8 %[[E]])
+  call void @bar(i8 %e)
+; CHECK: call void @bar(i8 %[[E]])
+  call void @bar(i8 %f)
+  ret void
+}
+
+; CHECK-LABEL: define void @loadCombine3() {
+define void @loadCombine3() {
+enter:
+  %ptr = alloca i8
+  store i8 42, i8* %ptr
+  call void @foo(i8* %ptr)
+; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
+  %e = load i8, i8* %ptr, !invariant.group !0
+; CHECK-NOT: load
+  %f = load i8, i8* %ptr, !invariant.group !0
+; CHECK: call void @bar(i8 %[[E]])
+  call void @bar(i8 %e)
+; CHECK: call void @bar(i8 %[[E]])
+  call void @bar(i8 %f)
+  ret void
+}
+
+; CHECK-LABEL: define i8 @unoptimizable2() {
+define i8 @unoptimizable2() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr
+    call void @foo(i8* %ptr)
+    %a = load i8, i8* %ptr
+    call void @foo(i8* %ptr)
+    %b = load i8, i8* %ptr, !invariant.group !0
+    
+; CHECK: ret i8 %a
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @unoptimizable3() {
+define i8 @unoptimizable3() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    %ptr2 = call i8* @getPointer(i8* %ptr)
+    %a = load i8, i8* %ptr2, !invariant.group !0
+    
+; CHECK: ret i8 %a
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @optimizable4() {
+define i8 @optimizable4() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
+; CHECK-NOT: load
+    %a = load i8, i8* %ptr2, !invariant.group !0
+    
+; CHECK: ret i8 42
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @volatile1() {
+define i8 @volatile1() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    call void @foo(i8* %ptr)
+    %a = load i8, i8* %ptr, !invariant.group !0
+    %b = load volatile i8, i8* %ptr
+; CHECK: call void @bar(i8 %b)
+    call void @bar(i8 %b)
+
+    %c = load volatile i8, i8* %ptr, !invariant.group !0
+; FIXME: we could change %c to 42, preserving volatile load
+; CHECK: call void @bar(i8 %c)
+    call void @bar(i8 %c)
+; CHECK: ret i8 42
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @volatile2() {
+define i8 @volatile2() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    call void @foo(i8* %ptr)
+    %a = load i8, i8* %ptr, !invariant.group !0
+    %b = load volatile i8, i8* %ptr
+; CHECK: call void @bar(i8 %b)
+    call void @bar(i8 %b)
+
+    %c = load volatile i8, i8* %ptr, !invariant.group !0
+; FIXME: we could change %c to 42, preserving volatile load
+; CHECK: call void @bar(i8 %c)
+    call void @bar(i8 %c)
+; CHECK: ret i8 42
+    ret i8 %a
+}
+
+; CHECK-LABEL: define i8 @fun() {
+define i8 @fun() {
+entry:
+    %ptr = alloca i8
+    store i8 42, i8* %ptr, !invariant.group !0
+    call void @foo(i8* %ptr)
+
+    %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
+; CHECK: call void @bar(i8 42)
+    call void @bar(i8 %a)
+
+    %newPtr = call i8* @getPointer(i8* %ptr) 
+    %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr
+; CHECK: call void @bar(i8 %c)
+    call void @bar(i8 %c)
+    
+    %unknownValue = load i8, i8* @unknownPtr
+; FIXME: Can assume that %unknownValue == 42
+; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0
+    store i8 %unknownValue, i8* %ptr, !invariant.group !0 
+
+    %newPtr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
+; CHECK-NOT: load
+    %d = load i8, i8* %newPtr2, !invariant.group !0
+; CHECK: ret i8 %unknownValue
+    ret i8 %d
+}
+
+; This test checks if invariant.group understands gep with zeros
+; CHECK-LABEL: define void @testGEP0() {
+define void @testGEP0() {
+  %a = alloca %struct.A, align 8
+  %1 = bitcast %struct.A* %a to i8*
+  %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 0
+  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**), i32 (...)*** %2, align 8, !invariant.group !0
+; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull dereferenceable(8) %a)
+  call void @_ZN1A3fooEv(%struct.A* nonnull dereferenceable(8) %a) ; This call may change vptr
+  %3 = load i8, i8* @unknownPtr, align 4
+  %4 = icmp eq i8 %3, 0
+  br i1 %4, label %_Z1gR1A.exit, label %5
+
+; This should be devirtualized by invariant.group
+  %6 = bitcast %struct.A* %a to void (%struct.A*)***
+  %7 = load void (%struct.A*)**, void (%struct.A*)*** %6, align 8, !invariant.group !0
+  %8 = load void (%struct.A*)*, void (%struct.A*)** %7, align 8
+; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull %a)
+  call void %8(%struct.A* nonnull %a)
+  br label %_Z1gR1A.exit
+
+_Z1gR1A.exit:                                     ; preds = %0, %5
+  ret void
+}
+
+; Check if no optimizations are performed with global pointers.
+; FIXME: we could do the optimizations if we would check if dependency comes
+; from the same function.
+; CHECK-LABEL: define void @testGlobal() {
+define void @testGlobal() {
+; CHECK:  %a = load i8, i8* @unknownPtr, !invariant.group !0
+   %a = load i8, i8* @unknownPtr, !invariant.group !0
+   call void @foo2(i8* @unknownPtr, i8 %a)
+; CHECK:  %1 = load i8, i8* @unknownPtr, !invariant.group !0
+   %1 = load i8, i8* @unknownPtr, !invariant.group !0
+   call void @bar(i8 %1)
+
+   %b0 = bitcast i8* @unknownPtr to i1*
+   call void @fooBit(i1* %b0, i1 1)
+; Adding regex because of canonicalization of bitcasts
+; CHECK: %2 = load i1, i1* {{.*}}, !invariant.group !0
+   %2 = load i1, i1* %b0, !invariant.group !0
+   call void @fooBit(i1* %b0, i1 %2)
+; CHECK:  %3 = load i1, i1* {{.*}}, !invariant.group !0
+   %3 = load i1, i1* %b0, !invariant.group !0
+   call void @fooBit(i1* %b0, i1 %3)
+   ret void
+}
+; And in the case it is not global
+; CHECK-LABEL: define void @testNotGlobal() {
+define void @testNotGlobal() {
+   %a = alloca i8
+   call void @foo(i8* %a)
+; CHECK:  %b = load i8, i8* %a, !invariant.group !0
+   %b = load i8, i8* %a, !invariant.group !0
+   call void @foo2(i8* %a, i8 %b)
+
+   %1 = load i8, i8* %a, !invariant.group !0
+; CHECK: call void @bar(i8 %b)
+   call void @bar(i8 %1)
+
+   %b0 = bitcast i8* %a to i1*
+   call void @fooBit(i1* %b0, i1 1)
+; CHECK: %1 = trunc i8 %b to i1
+   %2 = load i1, i1* %b0, !invariant.group !0
+; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %1)
+   call void @fooBit(i1* %b0, i1 %2)
+   %3 = load i1, i1* %b0, !invariant.group !0
+; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %1)
+   call void @fooBit(i1* %b0, i1 %3)
+   ret void
+}
+
+; CHECK-LABEL: define void @handling_loops()
+define void @handling_loops() {
+  %a = alloca %struct.A, align 8
+  %1 = bitcast %struct.A* %a to i8*
+  %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 0
+  store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**), i32 (...)*** %2, align 8, !invariant.group !0
+  %3 = load i8, i8* @unknownPtr, align 4
+  %4 = icmp sgt i8 %3, 0
+  br i1 %4, label %.lr.ph.i, label %_Z2g2R1A.exit
+
+.lr.ph.i:                                         ; preds = %0
+  %5 = bitcast %struct.A* %a to void (%struct.A*)***
+  %6 = load i8, i8* @unknownPtr, align 4
+  %7 = icmp sgt i8 %6, 1
+  br i1 %7, label %._crit_edge.preheader, label %_Z2g2R1A.exit
+
+._crit_edge.preheader:                            ; preds = %.lr.ph.i
+  br label %._crit_edge
+
+._crit_edge:                                      ; preds = %._crit_edge.preheader, %._crit_edge
+  %8 = phi i8 [ %10, %._crit_edge ], [ 1, %._crit_edge.preheader ]
+  %.pre = load void (%struct.A*)**, void (%struct.A*)*** %5, align 8, !invariant.group !0
+  %9 = load void (%struct.A*)*, void (%struct.A*)** %.pre, align 8
+  ; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull %a)
+  call void %9(%struct.A* nonnull %a) #3
+  ; CHECK-NOT: call void %
+  %10 = add nuw nsw i8 %8, 1
+  %11 = load i8, i8* @unknownPtr, align 4
+  %12 = icmp slt i8 %10, %11
+  br i1 %12, label %._crit_edge, label %_Z2g2R1A.exit.loopexit
+
+_Z2g2R1A.exit.loopexit:                           ; preds = %._crit_edge
+  br label %_Z2g2R1A.exit
+
+_Z2g2R1A.exit:                                    ; preds = %_Z2g2R1A.exit.loopexit, %.lr.ph.i, %0
+  ret void
+}
+
+
+declare void @foo(i8*)
+declare void @foo2(i8*, i8)
+declare void @bar(i8)
+declare i8* @getPointer(i8*)
+declare void @_ZN1A3fooEv(%struct.A*)
+declare void @_ZN1AC1Ev(%struct.A*)
+declare void @fooBit(i1*, i1)
+
+declare i8* @llvm.launder.invariant.group.p0i8(i8*)
+
+; Function Attrs: nounwind
+declare void @llvm.assume(i1 %cmp.vtables) #0
+
+
+attributes #0 = { nounwind }
+!0 = !{}
\ No newline at end of file

Added: llvm/trunk/test/Transforms/NewGVN/invariant.start.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/invariant.start.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/invariant.start.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/invariant.start.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; Test to make sure llvm.invariant.start calls are not treated as clobbers.
+; RUN: opt < %s -newgvn -S | FileCheck %s
+
+
+declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) nounwind readonly
+declare void @llvm.invariant.end.p0i8({}*, i64, i8* nocapture) nounwind
+
+; We forward store to the load across the invariant.start intrinsic
+define i8 @forward_store() {
+; CHECK-LABEL: @forward_store
+; CHECK: call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
+; CHECK-NOT: load
+; CHECK: ret i8 0
+  %a = alloca i8
+  store i8 0, i8* %a
+  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
+  %r = load i8, i8* %a
+  ret i8 %r
+}
+
+declare i8 @dummy(i8* nocapture) nounwind readonly
+
+; We forward store to the load in the non-local analysis case,
+; i.e. invariant.start is in another basic block.
+define i8 @forward_store_nonlocal(i1 %cond) {
+; CHECK-LABEL: forward_store_nonlocal
+; CHECK: call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
+; CHECK: ret i8 0
+; CHECK: ret i8 %val
+  %a = alloca i8
+  store i8 0, i8* %a
+  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
+  br i1 %cond, label %loadblock, label %exit
+
+loadblock:
+  %r = load i8, i8* %a
+  ret i8 %r
+
+exit:
+  %val = call i8 @dummy(i8* %a)
+  ret i8 %val
+}
+
+; We should not value forward %foo to the invariant.end corresponding to %bar.
+define i8 @forward_store1() {
+; CHECK-LABEL: forward_store1
+; CHECK: %foo = call {}* @llvm.invariant.start.p0i8
+; CHECK-NOT: load
+; CHECK: %bar = call {}* @llvm.invariant.start.p0i8
+; CHECK: call void @llvm.invariant.end.p0i8({}* %bar, i64 1, i8* %a)
+; CHECK: ret i8 0
+  %a = alloca i8
+  store i8 0, i8* %a
+  %foo = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
+  %r = load i8, i8* %a
+  %bar = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %a)
+  call void @llvm.invariant.end.p0i8({}* %bar, i64 1, i8* %a)
+  ret i8 %r
+}

Added: llvm/trunk/test/Transforms/NewGVN/lifetime-simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/lifetime-simple.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/lifetime-simple.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/lifetime-simple.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+define i8 @test(i8* %P) nounwind {
+; CHECK: lifetime.start
+; CHECK-NOT: load
+; CHECK: lifetime.end
+entry:
+  call void @llvm.lifetime.start.p0i8(i64 32, i8* %P)
+  %0 = load i8, i8* %P
+  store i8 1, i8* %P
+  call void @llvm.lifetime.end.p0i8(i64 32, i8* %P)
+  %1 = load i8, i8* %P
+  ret i8 %1
+}
+
+declare void @llvm.lifetime.start.p0i8(i64 %S, i8* nocapture %P) readonly
+declare void @llvm.lifetime.end.p0i8(i64 %S, i8* nocapture %P)

Added: llvm/trunk/test/Transforms/NewGVN/load-constant-mem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/load-constant-mem.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/load-constant-mem.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/load-constant-mem.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+; PR4189
+ at G = external constant [4 x i32]
+
+define i32 @test(i8* %p, i32 %i) nounwind {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[P:%.*]] = getelementptr [4 x i32], [4 x i32]* @G, i32 0, i32 [[I:%.*]]
+; CHECK-NEXT:    store i8 4, i8* [[P:%.*]]
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %P = getelementptr [4 x i32], [4 x i32]* @G, i32 0, i32 %i
+  %A = load i32, i32* %P
+  store i8 4, i8* %p
+  %B = load i32, i32* %P
+  %C = sub i32 %A, %B
+  ret i32 %C
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+; Check that an unreachable predecessor to a PHI node doesn't cause a crash.
+; PR21625.
+
+define i32 @f(i32** %f) {
+; CHECK: bb0:
+; Load should be removed, since it's ignored.
+; CHECK-NEXT: br label
+bb0:
+  %bar = load i32*, i32** %f
+  br label %bb2
+bb1:
+  %zed = load i32*, i32** %f
+  br i1 false, label %bb1, label %bb2
+bb2:
+  %foo = phi i32* [ null, %bb0 ], [ %zed, %bb1 ]
+  %storemerge = load i32, i32* %foo
+  ret i32 %storemerge
+}

Added: llvm/trunk/test/Transforms/NewGVN/loadforward.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/loadforward.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/loadforward.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/loadforward.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 -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%rec11 = type { i16, i16, i16 }
+
+ at str = global %rec11 { i16 1, i16 2, i16 3 }
+
+;; Test that we forward the first store to the second load
+define i16 @bazinga() {
+; CHECK-LABEL: @bazinga(
+; CHECK-NEXT:    [[_TMP10:%.*]] = load i16, i16* getelementptr inbounds (%rec11, %rec11* @str, i64 0, i32 1)
+; CHECK-NEXT:    store i16 [[_TMP10]], i16* getelementptr inbounds (%rec11, %rec11* @str, i64 0, i32 0)
+; CHECK-NEXT:    [[_TMP15:%.*]] = icmp eq i16 [[_TMP10]], 3
+; CHECK-NEXT:    [[_TMP16:%.*]] = select i1 [[_TMP15]], i16 1, i16 0
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    ret i16 [[_TMP16]]
+;
+  %_tmp9 = getelementptr %rec11, %rec11* @str, i16 0, i32 1
+  %_tmp10 = load i16, i16* %_tmp9
+  %_tmp12 = getelementptr %rec11, %rec11* @str, i16 0, i32 0
+  store i16 %_tmp10, i16* %_tmp12
+  %_tmp13 = getelementptr %rec11, %rec11* @str, i16 0, i32 0
+  %_tmp14 = load i16, i16* %_tmp13
+  %_tmp15 = icmp eq i16 %_tmp14, 3
+  %_tmp16 = select i1 %_tmp15, i16 1, i16 0
+  br label %bb1
+
+bb1:
+  ret i16 %_tmp16
+}

Added: llvm/trunk/test/Transforms/NewGVN/malloc-load-removal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/malloc-load-removal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/malloc-load-removal.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/malloc-load-removal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -S -basicaa -newgvn < %s | FileCheck %s
+; RUN: opt -S -basicaa -newgvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS
+; PR13694
+
+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"
+
+declare i8* @malloc(i64) nounwind
+
+define noalias i8* @test1() nounwind uwtable ssp {
+entry:
+  %call = tail call i8* @malloc(i64 100) nounwind
+  %0 = load i8, i8* %call, align 1
+  %tobool = icmp eq i8 %0, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  store i8 0, i8* %call, align 1
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  ret i8* %call
+
+; CHECK-LABEL: @test1(
+; CHECK-NOT: load
+; CHECK-NOT: icmp
+
+; CHECK_NO_LIBCALLS-LABEL: @test1(
+; CHECK_NO_LIBCALLS: load
+; CHECK_NO_LIBCALLS: icmp
+}
+
+declare i8* @_Znwm(i64) nounwind
+
+define noalias i8* @test2() nounwind uwtable ssp {
+entry:
+  %call = tail call i8* @_Znwm(i64 100) nounwind
+  %0 = load i8, i8* %call, align 1
+  %tobool = icmp eq i8 %0, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  store i8 0, i8* %call, align 1
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  ret i8* %call
+
+; CHECK-LABEL: @test2(
+; CHECK-NOT: load
+; CHECK-NOT: icmp
+
+; CHECK_NO_LIBCALLS-LABEL: @test2(
+; CHECK_NO_LIBCALLS: load
+; CHECK_NO_LIBCALLS: icmp
+}

Added: llvm/trunk/test/Transforms/NewGVN/memory-handling.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/memory-handling.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/memory-handling.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/memory-handling.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,195 @@
+;; This test is really dependent on propagating a lot of memory info around, but in the end, not
+;; screwing up a single add.
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.Letter = type { i32, i32, i32, i32 }
+
+ at alPhrase = external local_unnamed_addr global [26 x %struct.Letter], align 16
+ at aqMainMask = external local_unnamed_addr global [2 x i64], align 16
+ at aqMainSign = external local_unnamed_addr global [2 x i64], align 16
+ at cchPhraseLength = external local_unnamed_addr global i32, align 4
+ at auGlobalFrequency = external local_unnamed_addr global [26 x i32], align 16
+ at .str.7 = external hidden unnamed_addr constant [28 x i8], align 1
+
+; Function Attrs: nounwind uwtable
+declare void @Fatal(i8*, i32) local_unnamed_addr #0
+
+; Function Attrs: nounwind readnone
+declare i16** @__ctype_b_loc() local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define void @BuildMask(i8* nocapture readonly) local_unnamed_addr #0 {
+  tail call void @llvm.memset.p0i8.i64(i8* align 16 bitcast ([26 x %struct.Letter]* @alPhrase to i8*), i8 0, i64 416, i1 false)
+  tail call void @llvm.memset.p0i8.i64(i8* align 16 bitcast ([2 x i64]* @aqMainMask to i8*), i8 0, i64 16, i1 false)
+  tail call void @llvm.memset.p0i8.i64(i8* align 16 bitcast ([2 x i64]* @aqMainSign to i8*), i8 0, i64 16, i1 false)
+  br label %.sink.split
+
+.sink.split:                                      ; preds = %14, %1
+  %.0 = phi i8* [ %0, %1 ], [ %.lcssa67, %14 ]
+  %.sink = phi i32 [ 0, %1 ], [ %23, %14 ]
+  store i32 %.sink, i32* @cchPhraseLength, align 4, !tbaa !1
+  br label %2
+
+; <label>:2:                                      ; preds = %6, %.sink.split
+  %.1 = phi i8* [ %.0, %.sink.split ], [ %3, %6 ]
+  %3 = getelementptr inbounds i8, i8* %.1, i64 1
+  %4 = load i8, i8* %.1, align 1, !tbaa !5
+  %5 = icmp eq i8 %4, 0
+  br i1 %5, label %.preheader.preheader, label %6
+
+.preheader.preheader:                             ; preds = %2
+  br label %.preheader
+
+; <label>:6:                                      ; preds = %2
+  %7 = tail call i16** @__ctype_b_loc() #4
+  %8 = load i16*, i16** %7, align 8, !tbaa !6
+  %9 = sext i8 %4 to i64
+  %10 = getelementptr inbounds i16, i16* %8, i64 %9
+  %11 = load i16, i16* %10, align 2, !tbaa !8
+  %12 = and i16 %11, 1024
+  %13 = icmp eq i16 %12, 0
+  br i1 %13, label %2, label %14
+
+; <label>:14:                                     ; preds = %6
+  %.lcssa67 = phi i8* [ %3, %6 ]
+  %.lcssa65 = phi i8 [ %4, %6 ]
+  %15 = sext i8 %.lcssa65 to i32
+  %16 = tail call i32 @tolower(i32 %15) #5
+  %17 = add nsw i32 %16, -97
+  %18 = sext i32 %17 to i64
+  %19 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %18, i32 0
+  %20 = load i32, i32* %19, align 16, !tbaa !10
+  %21 = add i32 %20, 1
+  store i32 %21, i32* %19, align 16, !tbaa !10
+  %22 = load i32, i32* @cchPhraseLength, align 4, !tbaa !1
+  %23 = add nsw i32 %22, 1
+  br label %.sink.split
+
+.preheader:                                       ; preds = %58, %.preheader.preheader
+  %indvars.iv = phi i64 [ 0, %.preheader.preheader ], [ %indvars.iv.next, %58 ]
+  %.04961 = phi i32 [ %.2, %58 ], [ 0, %.preheader.preheader ]
+  %.05160 = phi i32 [ %.253, %58 ], [ 0, %.preheader.preheader ]
+  %24 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 0
+  %25 = load i32, i32* %24, align 16, !tbaa !10
+  %26 = icmp eq i32 %25, 0
+  %27 = getelementptr inbounds [26 x i32], [26 x i32]* @auGlobalFrequency, i64 0, i64 %indvars.iv
+  br i1 %26, label %28, label %29
+
+; <label>:28:                                     ; preds = %.preheader
+  store i32 -1, i32* %27, align 4, !tbaa !1
+  br label %58
+
+; <label>:29:                                     ; preds = %.preheader
+  store i32 0, i32* %27, align 4, !tbaa !1
+  %30 = zext i32 %25 to i64
+  br i1 false, label %._crit_edge, label %.lr.ph.preheader
+
+.lr.ph.preheader:                                 ; preds = %29
+  br label %.lr.ph
+
+.lr.ph:                                           ; preds = %.lr.ph, %.lr.ph.preheader
+  %.04658 = phi i64 [ %32, %.lr.ph ], [ 1, %.lr.ph.preheader ]
+  %.04857 = phi i32 [ %31, %.lr.ph ], [ 1, %.lr.ph.preheader ]
+  %31 = add nuw nsw i32 %.04857, 1
+  %32 = shl i64 %.04658, 1
+  %33 = icmp ult i64 %30, %32
+  br i1 %33, label %._crit_edge.loopexit, label %.lr.ph
+
+._crit_edge.loopexit:                             ; preds = %.lr.ph
+  %.lcssa63 = phi i32 [ %31, %.lr.ph ]
+  %.lcssa = phi i64 [ %32, %.lr.ph ]
+  br label %._crit_edge
+
+._crit_edge:                                      ; preds = %._crit_edge.loopexit, %29
+  %.048.lcssa = phi i32 [ 1, %29 ], [ %.lcssa63, %._crit_edge.loopexit ]
+  %.046.lcssa = phi i64 [ 1, %29 ], [ %.lcssa, %._crit_edge.loopexit ]
+  %34 = add nsw i32 %.048.lcssa, %.04961
+  %35 = icmp ugt i32 %34, 64
+  br i1 %35, label %36, label %40
+
+; <label>:36:                                     ; preds = %._crit_edge
+; This testcase essentially comes down to this little add.
+; If we screw up the revisitation of the users of store of %sink above
+; we will end up propagating and simplifying this to 1 in the final output
+; because we keep an optimistic assumption we should not.
+; CHECK:  add i32 %.05160, 1
+  %37 = add i32 %.05160, 1
+  %38 = icmp ugt i32 %37, 1
+  br i1 %38, label %39, label %40
+
+; <label>:39:                                     ; preds = %36
+  tail call void @Fatal(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.7, i64 0, i64 0), i32 0)
+  br label %40
+
+; <label>:40:                                     ; preds = %39, %36, %._crit_edge
+  %.152 = phi i32 [ %.05160, %._crit_edge ], [ %37, %39 ], [ %37, %36 ]
+  %.150 = phi i32 [ %.04961, %._crit_edge ], [ 0, %39 ], [ 0, %36 ]
+  %41 = add i64 %.046.lcssa, 4294967295
+  %42 = trunc i64 %41 to i32
+  %43 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 2
+  store i32 %42, i32* %43, align 8, !tbaa !12
+  %44 = zext i32 %.150 to i64
+  %.046. = shl i64 %.046.lcssa, %44
+  %45 = zext i32 %.152 to i64
+  %46 = getelementptr inbounds [2 x i64], [2 x i64]* @aqMainSign, i64 0, i64 %45
+  %47 = load i64, i64* %46, align 8, !tbaa !13
+  %48 = or i64 %47, %.046.
+  store i64 %48, i64* %46, align 8, !tbaa !13
+  %49 = load i32, i32* %24, align 16, !tbaa !10
+  %50 = zext i32 %49 to i64
+  %51 = shl i64 %50, %44
+  %52 = getelementptr inbounds [2 x i64], [2 x i64]* @aqMainMask, i64 0, i64 %45
+  %53 = load i64, i64* %52, align 8, !tbaa !13
+  %54 = or i64 %51, %53
+  store i64 %54, i64* %52, align 8, !tbaa !13
+  %55 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 1
+  store i32 %.150, i32* %55, align 4, !tbaa !15
+  %56 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 3
+  store i32 %.152, i32* %56, align 4, !tbaa !16
+  %57 = add nsw i32 %.150, %.048.lcssa
+  br label %58
+
+; <label>:58:                                     ; preds = %40, %28
+  %.253 = phi i32 [ %.05160, %28 ], [ %.152, %40 ]
+  %.2 = phi i32 [ %.04961, %28 ], [ %57, %40 ]
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp ne i64 %indvars.iv.next, 26
+  br i1 %exitcond, label %.preheader, label %59
+
+; <label>:59:                                     ; preds = %58
+  ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #2
+
+; Function Attrs: inlinehint nounwind readonly uwtable
+declare i32 @tolower(i32) local_unnamed_addr #3
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { argmemonly nounwind }
+attributes #3 = { inlinehint nounwind readonly uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind readnone }
+attributes #5 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 4.0.0"}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"int", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!3, !3, i64 0}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"any pointer", !3, i64 0}
+!8 = !{!9, !9, i64 0}
+!9 = !{!"short", !3, i64 0}
+!10 = !{!11, !2, i64 0}
+!11 = !{!"", !2, i64 0, !2, i64 4, !2, i64 8, !2, i64 12}
+!12 = !{!11, !2, i64 8}
+!13 = !{!14, !14, i64 0}
+!14 = !{!"long", !3, i64 0}
+!15 = !{!11, !2, i64 4}
+!16 = !{!11, !2, i64 12}

Added: llvm/trunk/test/Transforms/NewGVN/metadata-nonnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/metadata-nonnull.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/metadata-nonnull.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/metadata-nonnull.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,178 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+
+; RUN: opt %s -newgvn -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* @test1(i8** %v0, i8** %v1) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    [[V2:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]], !nonnull !0
+; CHECK-NEXT:    store i8* [[V2]], i8** [[V1:%.*]]
+; CHECK-NEXT:    ret i8* [[V2]]
+;
+top:
+  %v2 = load i8*, i8** %v0, !nonnull !0
+  store i8* %v2, i8** %v1
+  %v3 = load i8*, i8** %v1
+  ret i8* %v3
+}
+
+; FIXME: could propagate nonnull to first load?
+define i8* @test2(i8** %v0, i8** %v1) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    [[V2:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    store i8* [[V2]], i8** [[V1:%.*]]
+; CHECK-NEXT:    ret i8* [[V2]]
+;
+top:
+  %v2 = load i8*, i8** %v0
+  store i8* %v2, i8** %v1
+  %v3 = load i8*, i8** %v1, !nonnull !0
+  ret i8* %v3
+}
+
+declare void @use1(i8* %a) readonly
+
+define i8* @test3(i8** %v0) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    [[V1:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    call void @use1(i8* [[V1]])
+; CHECK-NEXT:    br i1 undef, label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    ret i8* [[V1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    ret i8* [[V1]]
+;
+top:
+  %v1 = load i8*, i8** %v0
+  call void @use1(i8* %v1)
+  br i1 undef, label %bb1, label %bb2
+
+bb1:
+  %v2 = load i8*, i8** %v0, !nonnull !0
+  ret i8* %v2
+
+bb2:
+  %v3 = load i8*, i8** %v0
+  ret i8* %v3
+}
+
+define i8* @test4(i8** %v0) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    [[V1:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    call void @use1(i8* [[V1]])
+; CHECK-NEXT:    br i1 undef, label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    ret i8* [[V1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    ret i8* [[V1]]
+;
+top:
+  %v1 = load i8*, i8** %v0
+  call void @use1(i8* %v1)
+  br i1 undef, label %bb1, label %bb2
+
+bb1:
+  %v2 = load i8*, i8** %v0
+  ret i8* %v2
+
+bb2:
+  %v3 = load i8*, i8** %v0, !nonnull !0
+  ret i8* %v3
+}
+
+define i8* @test5(i8** %v0) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    [[V1:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]], !nonnull !0
+; CHECK-NEXT:    call void @use1(i8* [[V1]])
+; CHECK-NEXT:    br i1 undef, label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    ret i8* [[V1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    ret i8* [[V1]]
+;
+top:
+  %v1 = load i8*, i8** %v0, !nonnull !0
+  call void @use1(i8* %v1)
+  br i1 undef, label %bb1, label %bb2
+
+bb1:
+  %v2 = load i8*, i8** %v0
+  ret i8* %v2
+
+bb2:
+  %v3 = load i8*, i8** %v0
+  ret i8* %v3
+}
+
+define i8* @test6(i8** %v0, i8** %v1) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    br i1 undef, label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[V2:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]], !nonnull !0
+; CHECK-NEXT:    store i8* [[V2]], i8** [[V1:%.*]]
+; CHECK-NEXT:    ret i8* [[V2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[V4:%.*]] = load i8*, i8** [[V0]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    store i8* [[V4]], i8** [[V1]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    ret i8* [[V4]]
+;
+top:
+  br i1 undef, label %bb1, label %bb2
+
+bb1:
+  %v2 = load i8*, i8** %v0, !nonnull !0
+  store i8* %v2, i8** %v1
+  %v3 = load i8*, i8** %v1
+  ret i8* %v3
+
+bb2:
+  %v4 = load i8*, i8** %v0
+  store i8* %v4, i8** %v1
+  %v5 = load i8*, i8** %v1, !nonnull !0
+  ret i8* %v5
+}
+
+declare void @use2(i8* %a)
+
+define i8* @test7(i8** %v0) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    [[V1:%.*]] = load i8*, i8** [[V0:%[a-z0-9]+]], !nonnull !0
+; CHECK-NEXT:    call void @use2(i8* [[V1]])
+; CHECK-NEXT:    br i1 undef, label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[V2:%.*]] = load i8*, i8** [[V0]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    ret i8* [[V2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[V3:%.*]] = load i8*, i8** [[V0]]
+; CHECK-NOT:     !nonnull
+; CHECK-NEXT:    ret i8* [[V3]]
+;
+top:
+  %v1 = load i8*, i8** %v0, !nonnull !0
+  call void @use2(i8* %v1)
+  br i1 undef, label %bb1, label %bb2
+
+bb1:
+  %v2 = load i8*, i8** %v0
+  ret i8* %v2
+
+bb2:
+  %v3 = load i8*, i8** %v0
+  ret i8* %v3
+}
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/NewGVN/metadata-simplify.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/metadata-simplify.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/metadata-simplify.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/metadata-simplify.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,160 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+
+; The tests in this file check that we do not simplify based on metadata that is
+; not available on all code paths.
+
+; RUN: opt < %s -S -newgvn | FileCheck %s
+
+define i1 @test1(i32** %arg, i1 %arg2) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32*, i32** [[ARG:%.*]], !nonnull !0
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32* [[LOAD1]], null
+; CHECK-NEXT:    ret i1 [[CMP1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load i32*, i32** [[ARG]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32* [[LOAD2]], null
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %load1 = load i32*, i32** %arg, !nonnull !0
+  %cmp1 = icmp eq i32* %load1, null
+  ret i1 %cmp1
+
+bb2:
+  %load2 = load i32*, i32** %arg
+  %cmp2 = icmp eq i32* %load2, null
+  ret i1 %cmp2
+}
+
+define i1 @test2(i32** %arg, i1 %arg2) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32*, i32** [[ARG:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32* [[LOAD1]], null
+; CHECK-NEXT:    ret i1 [[CMP1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load i32*, i32** [[ARG]], !nonnull !0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32* [[LOAD2]], null
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %load1 = load i32*, i32** %arg
+  %cmp1 = icmp eq i32* %load1, null
+  ret i1 %cmp1
+
+bb2:
+  %load2 = load i32*, i32** %arg, !nonnull !0
+  %cmp2 = icmp eq i32* %load2, null
+  ret i1 %cmp2
+}
+
+
+define i1 @test3(i32* %ptr, i1 %arg2) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]], !range !1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[LOAD1]], 999
+; CHECK-NEXT:    ret i1 [[CMP1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load i32, i32* [[PTR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[LOAD2]], 999
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %load1 = load i32, i32* %ptr, !range !1
+  %cmp1 = icmp ne i32 %load1, 999
+  ret i1 %cmp1
+
+bb2:
+  %load2 = load i32, i32* %ptr
+  %cmp2 = icmp ne i32 %load2, 999
+  ret i1 %cmp2
+}
+
+define i1 @test4(i32* %ptr, i1 %arg2) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[LOAD1]], 999
+; CHECK-NEXT:    ret i1 [[CMP1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load i32, i32* [[PTR]], !range !1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[LOAD2]], 999
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %load1 = load i32, i32* %ptr
+  %cmp1 = icmp ne i32 %load1, 999
+  ret i1 %cmp1
+
+bb2:
+  %load2 = load i32, i32* %ptr, !range !1
+  %cmp2 = icmp ne i32 %load2, 999
+  ret i1 %cmp2
+}
+
+define i1 @test5(i32* %ptr, i1 %arg2) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]], !range !1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[LOAD1]], 999
+; CHECK-NEXT:    ret i1 [[CMP1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load i32, i32* [[PTR]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[LOAD2]], 999
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %load1 = load i32, i32* %ptr, !range !1
+  %cmp1 = icmp slt i32 %load1, 999
+  ret i1 %cmp1
+
+bb2:
+  %load2 = load i32, i32* %ptr
+  %cmp2 = icmp slt i32 %load2, 999
+  ret i1 %cmp2
+}
+
+define i1 @test6(i32* %ptr, i1 %arg2) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[LOAD1:%.*]] = load i32, i32* [[PTR:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[LOAD1]], 999
+; CHECK-NEXT:    ret i1 [[CMP1]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[LOAD2:%.*]] = load i32, i32* [[PTR]], !range !1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[LOAD2]], 999
+; CHECK-NEXT:    ret i1 [[CMP2]]
+;
+  br i1 %arg2, label %bb1, label %bb2
+
+bb1:
+  %load1 = load i32, i32* %ptr
+  %cmp1 = icmp slt i32 %load1, 999
+  ret i1 %cmp1
+
+bb2:
+  %load2 = load i32, i32* %ptr, !range !1
+  %cmp2 = icmp slt i32 %load2, 999
+  ret i1 %cmp2
+}
+
+!0 = !{}
+!1 = !{ i32 10, i32 20 }

Added: llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/no_speculative_loads_with_asan.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt -O3 -S %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+declare noalias i8* @_Znam(i64) #1
+
+define i32 @TestNoAsan() {
+  %1 = tail call noalias i8* @_Znam(i64 2)
+  %2 = getelementptr inbounds i8, i8* %1, i64 1
+  store i8 0, i8* %2, align 1
+  store i8 0, i8* %1, align 1
+  %3 = bitcast i8* %1 to i16*
+  %4 = load i16, i16* %3, align 4
+  %5 = icmp eq i16 %4, 0
+  br i1 %5, label %11, label %6
+
+; <label>:6                                       ; preds = %0
+  %7 = getelementptr inbounds i8, i8* %1, i64 2
+  %8 = bitcast i8* %7 to i16*
+  %9 = load i16, i16* %8, align 2
+  %10 = sext i16 %9 to i32
+  br label %11
+
+; <label>:11                                      ; preds = %0, %6
+  %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
+  ret i32 %12
+}
+
+; CHECK-LABEL: @TestNoAsan
+; CHECK: ret i32 0
+
+define i32 @TestAsan() sanitize_address {
+  %1 = tail call noalias i8* @_Znam(i64 2)
+  %2 = getelementptr inbounds i8, i8* %1, i64 1
+  store i8 0, i8* %2, align 1
+  store i8 0, i8* %1, align 1
+  %3 = bitcast i8* %1 to i16*
+  %4 = load i16, i16* %3, align 4
+  %5 = icmp eq i16 %4, 0
+  br i1 %5, label %11, label %6
+
+; <label>:6                                       ; preds = %0
+  %7 = getelementptr inbounds i8, i8* %1, i64 2
+  %8 = bitcast i8* %7 to i16*
+  %9 = load i16, i16* %8, align 2
+  %10 = sext i16 %9 to i32
+  br label %11
+
+; <label>:11                                      ; preds = %0, %6
+  %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
+  ret i32 %12
+}
+
+; CHECK-LABEL: @TestAsan
+; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
+; CHECK: {{.*}} = phi
+
+define i32 @TestHWAsan() sanitize_hwaddress {
+  %1 = tail call noalias i8* @_Znam(i64 2)
+  %2 = getelementptr inbounds i8, i8* %1, i64 1
+  store i8 0, i8* %2, align 1
+  store i8 0, i8* %1, align 1
+  %3 = bitcast i8* %1 to i16*
+  %4 = load i16, i16* %3, align 4
+  %5 = icmp eq i16 %4, 0
+  br i1 %5, label %11, label %6
+
+; <label>:6                                       ; preds = %0
+  %7 = getelementptr inbounds i8, i8* %1, i64 2
+  %8 = bitcast i8* %7 to i16*
+  %9 = load i16, i16* %8, align 2
+  %10 = sext i16 %9 to i32
+  br label %11
+
+; <label>:11                                      ; preds = %0, %6
+  %12 = phi i32 [ %10, %6 ], [ 0, %0 ]
+  ret i32 %12
+}
+
+; CHECK-LABEL: @TestHWAsan
+; CHECK-NOT: %[[LOAD:[^ ]+]] = load i32
+; CHECK: {{.*}} = phi
+

Added: llvm/trunk/test/Transforms/NewGVN/noalias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/noalias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/noalias.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/noalias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -scoped-noalias -basicaa -newgvn -S < %s | FileCheck %s
+
+define i32 @test1(i32* %p, i32* %q) {
+; CHECK-LABEL: @test1(i32* %p, i32* %q)
+; CHECK: load i32, i32* %p
+; CHECK-NOT: noalias
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !noalias !0
+  %b = load i32, i32* %p
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test2(i32* %p, i32* %q) {
+; CHECK-LABEL: @test2(i32* %p, i32* %q)
+; CHECK: load i32, i32* %p, !alias.scope !0
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !alias.scope !0
+  %b = load i32, i32* %p, !alias.scope !0
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+; FIXME: In this case we can do better than intersecting the scopes, and can
+; concatenate them instead. Both loads are in the same basic block, the first
+; makes the second safe to speculatively execute, and there are no calls that may
+; throw in between.
+define i32 @test3(i32* %p, i32* %q) {
+; CHECK-LABEL: @test3(i32* %p, i32* %q)
+; CHECK: load i32, i32* %p, !alias.scope !1
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !alias.scope !1
+  %b = load i32, i32* %p, !alias.scope !2
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+declare i32 @foo(i32*) readonly
+
+!0 = !{!0}
+!1 = !{!1}
+!2 = !{!0, !1}
+

Added: llvm/trunk/test/Transforms/NewGVN/non-integral-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/non-integral-pointers.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/non-integral-pointers.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/non-integral-pointers.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) {
+; CHECK-LABEL: @f0(
+; CHECK-NOT: inttoptr
+; CHECK-NOT: ptrtoint
+ entry:
+  store i64 %val, i64* %loc
+  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
+
+ neverTaken:
+  %loc.bc = bitcast i64* %loc to i8 addrspace(4)**
+  %ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc
+  store i8 5, i8 addrspace(4)* %ptr
+  ret void
+
+ alwaysTaken:
+  ret void
+}
+
+define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) {
+; CHECK-LABEL: @f1(
+; CHECK-NOT: inttoptr
+; CHECK-NOT: ptrtoint
+ entry:
+  store i8 addrspace(4)* %val, i8 addrspace(4)** %loc
+  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
+
+ neverTaken:
+  %loc.bc = bitcast i8 addrspace(4)** %loc to i64*
+  %int = load i64, i64* %loc.bc
+  ret i64 %int
+
+ alwaysTaken:
+  ret i64 42
+}

Added: llvm/trunk/test/Transforms/NewGVN/non-local-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/non-local-offset.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/non-local-offset.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/non-local-offset.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+; GVN should ignore the store to p[1] to see that the load from p[0] is
+; fully redundant.
+
+; CHECK-LABEL: @yes(
+; CHECK: if.then:
+; CHECK-NEXT: store i32 0, i32* %q
+; CHECK-NEXT: ret void
+
+define void @yes(i1 %c, i32* %p, i32* %q) nounwind {
+entry:
+  store i32 0, i32* %p
+  %p1 = getelementptr inbounds i32, i32* %p, i64 1
+  store i32 1, i32* %p1
+  br i1 %c, label %if.else, label %if.then
+
+if.then:
+  %t = load i32, i32* %p
+  store i32 %t, i32* %q
+  ret void
+
+if.else:
+  ret void
+}
+
+; GVN should ignore the store to p[1] to see that the first load from p[0] is
+; fully redundant. However, the second load is larger, so it's not a simple
+; redundancy.
+
+; CHECK-LABEL: @watch_out_for_size_change(
+; CHECK: if.then:
+; CHECK-NEXT: store i32 0, i32* %q
+; CHECK-NEXT: ret void
+; CHECK: if.else:
+; CHECK: load i64, i64* %pc
+; CHECK: store i64
+
+define void @watch_out_for_size_change(i1 %c, i32* %p, i32* %q) nounwind {
+entry:
+  store i32 0, i32* %p
+  %p1 = getelementptr inbounds i32, i32* %p, i64 1
+  store i32 1, i32* %p1
+  br i1 %c, label %if.else, label %if.then
+
+if.then:
+  %t = load i32, i32* %p
+  store i32 %t, i32* %q
+  ret void
+
+if.else:
+  %pc = bitcast i32* %p to i64*
+  %qc = bitcast i32* %q to i64*
+  %t64 = load i64, i64* %pc
+  store i64 %t64, i64* %qc
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/nonescaping-malloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/nonescaping-malloc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/nonescaping-malloc.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/nonescaping-malloc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; XFAIL: *
+; REQUIRES: asserts
+; RUN: opt < %s -basicaa -newgvn -stats -disable-output 2>&1 | FileCheck %s
+; rdar://7363102
+
+; CHECK: Number of loads deleted
+
+; GVN should be able to eliminate load %tmp22.i, because it is redundant with
+; load %tmp8.i. This requires being able to prove that %tmp7.i doesn't
+; alias the malloc'd value %tmp.i20.i.i, which it can do since %tmp7.i
+; is derived from %tmp5.i which is computed from a load, and %tmp.i20.i.i
+; is never stored and does not escape.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin10.0"
+
+%"struct.llvm::MallocAllocator" = type <{ i8 }>
+%"struct.llvm::StringMap<void*,llvm::MallocAllocator>" = type { %"struct.llvm::StringMapImpl", %"struct.llvm::MallocAllocator" }
+%"struct.llvm::StringMapEntry<void*>" = type { %"struct.llvm::StringMapEntryBase", i8* }
+%"struct.llvm::StringMapEntryBase" = type { i32 }
+%"struct.llvm::StringMapImpl" = type { %"struct.llvm::StringMapImpl::ItemBucket"*, i32, i32, i32, i32 }
+%"struct.llvm::StringMapImpl::ItemBucket" = type { i32, %"struct.llvm::StringMapEntryBase"* }
+%"struct.llvm::StringRef" = type { i8*, i64 }
+
+define %"struct.llvm::StringMapEntry<void*>"* @_Z3fooRN4llvm9StringMapIPvNS_15MallocAllocatorEEEPKc(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %X, i8* %P) ssp {
+entry:
+  %tmp = alloca %"struct.llvm::StringRef", align 8
+  %tmp.i = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %tmp, i64 0, i32 0
+  store i8* %P, i8** %tmp.i, align 8
+  %tmp1.i = call i64 @strlen(i8* %P) nounwind readonly
+  %tmp2.i = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %tmp, i64 0, i32 1
+  store i64 %tmp1.i, i64* %tmp2.i, align 8
+  %tmp1 = call %"struct.llvm::StringMapEntry<void*>"* @_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueERKNS_9StringRefE(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %X, %"struct.llvm::StringRef"* %tmp) ssp
+  ret %"struct.llvm::StringMapEntry<void*>"* %tmp1
+}
+
+declare i64 @strlen(i8* nocapture) nounwind readonly
+
+declare noalias i8* @malloc(i64) nounwind
+
+declare i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"*, i64, i64)
+
+define linkonce_odr %"struct.llvm::StringMapEntry<void*>"* @_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueERKNS_9StringRefE(%"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, %"struct.llvm::StringRef"* nocapture %Key) ssp align 2 {
+entry:
+  %elt = bitcast %"struct.llvm::StringRef"* %Key to i64*
+  %val = load i64, i64* %elt
+  %tmp = getelementptr inbounds %"struct.llvm::StringRef", %"struct.llvm::StringRef"* %Key, i64 0, i32 1
+  %val2 = load i64, i64* %tmp
+  %tmp2.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0
+  %tmp3.i = tail call i32 @_ZN4llvm13StringMapImpl15LookupBucketForENS_9StringRefE(%"struct.llvm::StringMapImpl"* %tmp2.i, i64 %val, i64 %val2)
+  %tmp4.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 0
+  %tmp5.i = load %"struct.llvm::StringMapImpl::ItemBucket"*, %"struct.llvm::StringMapImpl::ItemBucket"** %tmp4.i, align 8
+  %tmp6.i = zext i32 %tmp3.i to i64
+  %tmp7.i = getelementptr inbounds %"struct.llvm::StringMapImpl::ItemBucket", %"struct.llvm::StringMapImpl::ItemBucket"* %tmp5.i, i64 %tmp6.i, i32 1
+  %tmp8.i = load %"struct.llvm::StringMapEntryBase"*, %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8
+  %tmp9.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, null
+  %tmp13.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp8.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*)
+  %or.cond.i = or i1 %tmp9.i, %tmp13.i
+  br i1 %or.cond.i, label %bb4.i, label %bb6.i
+
+bb4.i:                                            ; preds = %entry
+  %tmp41.i = inttoptr i64 %val to i8*
+  %tmp4.i35.i = getelementptr inbounds i8, i8* %tmp41.i, i64 %val2
+  %tmp.i.i = ptrtoint i8* %tmp4.i35.i to i64
+  %tmp1.i.i = trunc i64 %tmp.i.i to i32
+  %tmp3.i.i = trunc i64 %val to i32
+  %tmp4.i.i = sub i32 %tmp1.i.i, %tmp3.i.i
+  %tmp5.i.i = add i32 %tmp4.i.i, 17
+  %tmp8.i.i = zext i32 %tmp5.i.i to i64
+  %tmp.i20.i.i = tail call noalias i8* @malloc(i64 %tmp8.i.i) nounwind
+  %tmp10.i.i = bitcast i8* %tmp.i20.i.i to %"struct.llvm::StringMapEntry<void*>"*
+  %tmp12.i.i = icmp eq i8* %tmp.i20.i.i, null
+  br i1 %tmp12.i.i, label %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i, label %bb.i.i
+
+bb.i.i:                                           ; preds = %bb4.i
+  %tmp.i.i.i.i = bitcast i8* %tmp.i20.i.i to i32*
+  store i32 %tmp4.i.i, i32* %tmp.i.i.i.i, align 4
+  %tmp1.i19.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 8
+  %0 = bitcast i8* %tmp1.i19.i.i to i8**
+  store i8* null, i8** %0, align 8
+  br label %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i
+
+_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i: ; preds = %bb.i.i, %bb4.i
+  %tmp.i18.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 16
+  %tmp15.i.i = zext i32 %tmp4.i.i to i64
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp.i18.i.i, i8* %tmp41.i, i64 %tmp15.i.i, i1 false)
+  %tmp.i18.sum.i.i = add i64 %tmp15.i.i, 16
+  %tmp17.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 %tmp.i18.sum.i.i
+  store i8 0, i8* %tmp17.i.i, align 1
+  %tmp.i.i.i = getelementptr inbounds i8, i8* %tmp.i20.i.i, i64 8
+  %1 = bitcast i8* %tmp.i.i.i to i8**
+  store i8* null, i8** %1, align 8
+  %tmp22.i = load %"struct.llvm::StringMapEntryBase"*, %"struct.llvm::StringMapEntryBase"** %tmp7.i, align 8
+  %tmp24.i = icmp eq %"struct.llvm::StringMapEntryBase"* %tmp22.i, inttoptr (i64 -1 to %"struct.llvm::StringMapEntryBase"*)
+  br i1 %tmp24.i, label %bb9.i, label %_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringMapEntryIS1_EENS_9StringRefET_.exit
+
+bb6.i:                                            ; preds = %entry
+  %tmp16.i = bitcast %"struct.llvm::StringMapEntryBase"* %tmp8.i to %"struct.llvm::StringMapEntry<void*>"*
+  ret %"struct.llvm::StringMapEntry<void*>"* %tmp16.i
+
+bb9.i:                                            ; preds = %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i
+  %tmp25.i = getelementptr inbounds %"struct.llvm::StringMap<void*,llvm::MallocAllocator>", %"struct.llvm::StringMap<void*,llvm::MallocAllocator>"* %this, i64 0, i32 0, i32 3
+  %tmp26.i = load i32, i32* %tmp25.i, align 8
+  %tmp27.i = add i32 %tmp26.i, -1
+  store i32 %tmp27.i, i32* %tmp25.i, align 8
+  ret %"struct.llvm::StringMapEntry<void*>"* %tmp10.i.i
+
+_ZN4llvm9StringMapIPvNS_15MallocAllocatorEE16GetOrCreateValueIS1_EERNS_14StringMapEntryIS1_EENS_9StringRefET_.exit: ; preds = %_ZN4llvm14StringMapEntryIPvE6CreateINS_15MallocAllocatorES1_EEPS2_PKcS7_RT_T0_.exit.i
+  ret %"struct.llvm::StringMapEntry<void*>"* %tmp10.i.i
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind

Added: llvm/trunk/test/Transforms/NewGVN/null-aliases-nothing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/null-aliases-nothing.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/null-aliases-nothing.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/null-aliases-nothing.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+%t = type { i32 }
+declare void @test1f(i8*)
+
+define void @test1(%t* noalias %stuff ) {
+    %p = getelementptr inbounds %t, %t* %stuff, i32 0, i32 0
+    %before = load i32, i32* %p
+
+    call void @test1f(i8* null)
+
+    %after = load i32, i32* %p ; <--- This should be a dead load
+    %sum = add i32 %before, %after
+
+    store i32 %sum, i32* %p
+    ret void
+; CHECK: load
+; CHECK-NOT: load
+; CHECK: ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/opt-remarks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/opt-remarks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/opt-remarks.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/opt-remarks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,113 @@
+; XFAIL: *
+; RUN: opt < %s -newgvn -o /dev/null  -pass-remarks-output=%t -S -pass-remarks=gvn \
+; RUN:     2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+; RUN: opt < %s -passes=newgvn -o /dev/null  -pass-remarks-output=%t -S -pass-remarks=gvn \
+; RUN:     2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+
+
+; CHECK:      remark: <unknown>:0:0: load of type i32 eliminated{{$}}
+; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
+; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
+; CHECK-NOT:  remark:
+
+; YAML:      --- !Passed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadElim
+; YAML-NEXT: Function:        arg
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - InfavorOfValue:  i
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Passed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadElim
+; YAML-NEXT: Function:        const
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - InfavorOfValue:  '4'
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Passed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadElim
+; YAML-NEXT: Function:        inst
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - InfavorOfValue:  load
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Missed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadClobbered
+; YAML-NEXT: DebugLoc:        { File: /tmp/s.c, Line: 3, Column: 3 }
+; YAML-NEXT: Function:        may_alias
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' not eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - OtherAccess:     load
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 1, Column: 13 }
+; YAML-NEXT:   - String:          ' because it is clobbered by '
+; YAML-NEXT:   - ClobberedBy:     store
+; YAML-NEXT:     DebugLoc:        { File: /tmp/s.c, Line: 2, Column: 10 }
+; YAML-NEXT: ...
+
+define i32 @arg(i32* %p, i32 %i) {
+entry:
+  store i32 %i, i32* %p
+  %load = load i32, i32* %p
+  ret i32 %load
+}
+
+define i32 @const(i32* %p) {
+entry:
+  store i32 4, i32* %p
+  %load = load i32, i32* %p
+  ret i32 %load
+}
+
+define i32 @inst(i32* %p) {
+entry:
+  %load1 = load i32, i32* %p
+  %load = load i32, i32* %p
+  %add = add i32 %load1, %load
+  ret i32 %add
+}
+
+define i32 @may_alias(i32* %p, i32* %r) !dbg !7 {
+entry:
+  %load1 = load i32, i32* %p, !tbaa !13, !dbg !9
+  store i32 4, i32* %r, !tbaa !13, !dbg !10
+  %load = load i32, i32* %p, !tbaa !13, !dbg !11
+  %add = add i32 %load1, %load
+  ret i32 %add
+}
+!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: "may_alias", 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 = !DILocation(line: 2, column: 10, scope: !7)
+!11 = !DILocation(line: 3, column: 3, scope: !7)
+
+!12 = !{ !"tbaa root" }
+!13 = !{ !"int", !12 }

Added: llvm/trunk/test/Transforms/NewGVN/pair_jumpthread.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pair_jumpthread.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pair_jumpthread.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pair_jumpthread.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,120 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -newgvn -S | FileCheck %s
+; RUN: opt < %s -newgvn -jump-threading -S | FileCheck --check-prefix=CHECK-JT %s
+
+define signext i32 @testBI(i32 signext %v) {
+; Test with std::pair<bool, int>
+; based on the following C++ code
+; std::pair<bool, int> callee(int v) {
+;   int a = dummy(v);
+;   if (a) return std::make_pair(true, dummy(a));
+;   else return std::make_pair(v < 0, v);
+; }
+; int func(int v) {
+;   std::pair<bool, int> rc = callee(v);
+;   if (rc.first) dummy(0);
+;   return rc.second;
+; }
+; CHECK-LABEL: @testBI(
+; CHECK:  _ZL6calleei.exit:
+; CHECK:    [[PHIOFOPS:%.*]] = phi i64 [ 1, %if.then.i ], [ {{%.*}}, %if.else.i ]
+; CHECK:    [[TOBOOL:%.*]] = icmp eq i64 [[PHIOFOPS]], 0
+;
+; CHECK-JT-LABEL: @testBI(
+; CHECK-JT:       _ZL6calleei.exit.thread:
+;
+
+entry:
+  %call.i = call signext i32 @dummy(i32 signext %v)
+  %tobool.i = icmp eq i32 %call.i, 0
+  br i1 %tobool.i, label %if.else.i, label %if.then.i
+
+if.then.i:                                        ; preds = %entry
+  %call2.i = call signext i32 @dummy(i32 signext %call.i)
+  %retval.sroa.22.0.insert.ext.i.i = zext i32 %call2.i to i64
+  %retval.sroa.22.0.insert.shift.i.i = shl nuw i64 %retval.sroa.22.0.insert.ext.i.i, 32
+  %retval.sroa.0.0.insert.insert.i.i = or i64 %retval.sroa.22.0.insert.shift.i.i, 1
+  br label %_ZL6calleei.exit
+
+if.else.i:                                        ; preds = %entry
+  %.lobit.i = lshr i32 %v, 31
+  %0 = zext i32 %.lobit.i to i64
+  %retval.sroa.22.0.insert.ext.i8.i = zext i32 %v to i64
+  %retval.sroa.22.0.insert.shift.i9.i = shl nuw i64 %retval.sroa.22.0.insert.ext.i8.i, 32
+  %retval.sroa.0.0.insert.insert.i11.i = or i64 %retval.sroa.22.0.insert.shift.i9.i, %0
+  br label %_ZL6calleei.exit
+
+_ZL6calleei.exit:                                 ; preds = %if.then.i, %if.else.i
+  %retval.sroa.0.0.i = phi i64 [ %retval.sroa.0.0.insert.insert.i.i, %if.then.i ], [ %retval.sroa.0.0.insert.insert.i11.i, %if.else.i ]
+  %rc.sroa.43.0.extract.shift = lshr i64 %retval.sroa.0.0.i, 32
+  %rc.sroa.43.0.extract.trunc = trunc i64 %rc.sroa.43.0.extract.shift to i32
+  %1 = and i64 %retval.sroa.0.0.i, 1
+  %tobool = icmp eq i64 %1, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %_ZL6calleei.exit
+  %call1 = call signext i32 @dummy(i32 signext 0)
+  br label %if.end
+
+if.end:                                           ; preds = %_ZL6calleei.exit, %if.then
+  ret i32 %rc.sroa.43.0.extract.trunc
+}
+
+
+define signext i32 @testIB(i32 signext %v) {
+; Test with std::pair<int, bool>
+; based on the following C++ code
+; std::pair<int, bool> callee(int v) {
+;   int a = dummy(v);
+;   if (a) return std::make_pair(dummy(v), true);
+;   else return std::make_pair(v, v < 0);
+; }
+; int func(int v) {
+;   std::pair<int, bool> rc = callee(v);
+;   if (rc.second) dummy(0);
+;   return rc.first;
+; }
+; CHECK-LABEL: @testIB(
+; CHECK:  _ZL6calleei.exit:
+; CHECK:     [[PHIOFOPS:%.*]] = phi i64 [ 4294967296, %if.then.i ], [ {{%.*}}, %if.else.i ]
+; CHECK:     [[TOBOOL:%.*]] = icmp eq i64 [[PHIOFOPS]], 0
+;
+; CHECK-JT-LABEL: @testIB(
+; CHECK-JT:       _ZL6calleei.exit.thread:
+;
+
+entry:
+  %call.i = call signext i32 @dummy(i32 signext %v)
+  %tobool.i = icmp eq i32 %call.i, 0
+  br i1 %tobool.i, label %if.else.i, label %if.then.i
+
+if.then.i:                                        ; preds = %entry
+  %call1.i = call signext i32 @dummy(i32 signext %v)
+  %retval.sroa.0.0.insert.ext.i.i = zext i32 %call1.i to i64
+  %retval.sroa.0.0.insert.insert.i.i = or i64 %retval.sroa.0.0.insert.ext.i.i, 4294967296
+  br label %_ZL6calleei.exit
+
+if.else.i:                                        ; preds = %entry
+  %.lobit.i = lshr i32 %v, 31
+  %0 = zext i32 %.lobit.i to i64
+  %retval.sroa.2.0.insert.shift.i8.i = shl nuw nsw i64 %0, 32
+  %retval.sroa.0.0.insert.ext.i9.i = zext i32 %v to i64
+  %retval.sroa.0.0.insert.insert.i10.i = or i64 %retval.sroa.2.0.insert.shift.i8.i, %retval.sroa.0.0.insert.ext.i9.i
+  br label %_ZL6calleei.exit
+
+_ZL6calleei.exit:                                 ; preds = %if.then.i, %if.else.i
+  %retval.sroa.0.0.i = phi i64 [ %retval.sroa.0.0.insert.insert.i.i, %if.then.i ], [ %retval.sroa.0.0.insert.insert.i10.i, %if.else.i ]
+  %rc.sroa.0.0.extract.trunc = trunc i64 %retval.sroa.0.0.i to i32
+  %1 = and i64 %retval.sroa.0.0.i, 4294967296
+  %tobool = icmp eq i64 %1, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %_ZL6calleei.exit
+  %call1 = call signext i32 @dummy(i32 signext 0)
+  br label %if.end
+
+if.end:                                           ; preds = %_ZL6calleei.exit, %if.then
+  ret i32 %rc.sroa.0.0.extract.trunc
+}
+
+declare signext i32 @dummy(i32 signext %v)

Added: llvm/trunk/test/Transforms/NewGVN/phi-edge-handling.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/phi-edge-handling.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/phi-edge-handling.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/phi-edge-handling.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -newgvn -S | FileCheck %s
+
+
+;; Block 6 is reachable, but edge 6->4 is not
+;; This means the phi value is undef, not 0
+; Function Attrs: ssp uwtable
+define i16 @hoge() local_unnamed_addr #0 align 2 {
+; CHECK-LABEL: @hoge(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    switch i8 undef, label [[BB7:%.*]] [
+; CHECK-NEXT:    i8 0, label [[BB1:%.*]]
+; CHECK-NEXT:    i8 12, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB6:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    unreachable
+; CHECK:       bb4:
+; CHECK-NEXT:    ret i16 undef
+; CHECK:       bb6:
+; CHECK-NEXT:    br i1 true, label [[BB3:%.*]], label [[BB4]], !llvm.loop !1
+; CHECK:       bb7:
+; CHECK-NEXT:    unreachable
+;
+bb:
+  switch i8 undef, label %bb7 [
+  i8 0, label %bb1
+  i8 12, label %bb2
+  ]
+
+bb1:                                              ; preds = %bb
+  br label %bb6
+
+bb2:                                              ; preds = %bb
+  br label %bb4
+
+bb3:                                              ; preds = %bb6
+  unreachable
+
+bb4:                                              ; preds = %bb6, %bb2
+  %tmp = phi i16 [ 0, %bb6 ], [ undef, %bb2 ]
+  ret i16 %tmp
+
+bb6:                                              ; preds = %bb4
+  br i1 true, label %bb3, label %bb4, !llvm.loop !1
+
+bb7:                                              ; preds = %bb
+  unreachable
+}
+
+attributes #0 = { 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"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 5.0.0"}
+!1 = distinct !{!1, !2}
+!2 = !{!"llvm.loop.unroll.disable"}

Added: llvm/trunk/test/Transforms/NewGVN/phi-of-ops-move-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/phi-of-ops-move-block.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/phi-of-ops-move-block.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/phi-of-ops-move-block.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,107 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -newgvn -S | FileCheck %s
+
+ at g_20 = external global i32, align 4
+
+define void @test() {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1:%.*]], [[CRITEDGE:%.*]] ]
+; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @g_20, align 4
+; CHECK-NEXT:    [[CMP0:%.*]] = icmp eq i32 [[STOREMERGE]], 0
+; CHECK-NEXT:    br i1 [[CMP0]], label [[LR_PH:%.*]], label [[CRITEDGE]]
+; CHECK:       lr.ph:
+; CHECK-NEXT:    [[LV:%.*]] = load i64, i64* inttoptr (i64 16 to i64*), align 16
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i64 [[LV]], 0
+; CHECK-NEXT:    br i1 [[CMP1]], label [[PREHEADER_SPLIT:%.*]], label [[CRITEDGE]]
+; CHECK:       preheader.split:
+; CHECK-NEXT:    br label [[PREHEADER_SPLIT]]
+; CHECK:       critedge:
+; CHECK-NEXT:    [[PHIOFOPS1:%.*]] = phi i1 [ false, [[BB1]] ], [ true, [[LR_PH]] ]
+; CHECK-NEXT:    [[PHIOFOPS:%.*]] = phi i1 [ [[CMP0]], [[BB1]] ], [ true, [[LR_PH]] ]
+; CHECK-NEXT:    [[DOT05_LCSSA:%.*]] = phi i32 [ 0, [[BB1]] ], [ -1, [[LR_PH]] ]
+; CHECK-NEXT:    [[ADD1]] = add nsw i32 [[STOREMERGE]], -1
+; CHECK-NEXT:    br i1 [[PHIOFOPS]], label [[BB1]], label [[END:%.*]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %bb1
+
+bb1:                                      ; preds = %critedge, %entry
+  %storemerge = phi i32 [ 0, %entry ], [ %add1, %critedge ]
+  store i32 %storemerge, i32* @g_20, align 4
+  %cmp0 = icmp eq i32 %storemerge, 0
+  br i1 %cmp0, label %lr.ph, label %critedge
+
+lr.ph:                                           ; preds = %bb1
+  %lv = load i64, i64* inttoptr (i64 16 to i64*), align 16
+  %cmp1 = icmp eq i64 %lv, 0
+  br i1 %cmp1, label %preheader.split, label %critedge
+
+preheader.split:                                 ; preds = %lr.ph, %preheader.split
+  br label %preheader.split
+
+critedge:                                        ; preds = %lr.ph, %bb1
+  %.05.lcssa = phi i32 [ 0, %bb1 ], [ -1, %lr.ph ]
+  %cmp2 = icmp ne i32 %.05.lcssa, 0
+  %brmerge = or i1 %cmp0, %cmp2
+  %add1 = add nsw i32 %storemerge, -1
+  br i1 %brmerge, label %bb1, label %end
+
+end:
+  ret void
+}
+
+; In this test case a temporary PhiOfOps node gets moved to BB with more
+; predecessors, so a new one needs to be created.
+define void @test2() {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[ADD:%.*]], [[CRITEDGE:%.*]] ]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[STOREMERGE]], 0
+; CHECK-NEXT:    br i1 [[CMP1]], label [[LR_PH:%.*]], label [[CRITEDGE]]
+; CHECK:       lr.ph:
+; CHECK-NEXT:    br i1 undef, label [[SPLIT1:%.*]], label [[SPLIT2:%.*]]
+; CHECK:       split1:
+; CHECK-NEXT:    br label [[CRITEDGE]]
+; CHECK:       split2:
+; CHECK-NEXT:    br label [[CRITEDGE]]
+; CHECK:       critedge:
+; CHECK-NEXT:    [[PHIOFOPS1:%.*]] = phi i1 [ false, [[BB1]] ], [ true, [[SPLIT2]] ], [ true, [[SPLIT1]] ]
+; CHECK-NEXT:    [[PHIOFOPS:%.*]] = phi i1 [ [[CMP1]], [[BB1]] ], [ true, [[SPLIT2]] ], [ true, [[SPLIT1]] ]
+; CHECK-NEXT:    [[LCSSA:%.*]] = phi i32 [ 0, [[BB1]] ], [ -1, [[SPLIT1]] ], [ -1, [[SPLIT2]] ]
+; CHECK-NEXT:    [[ADD]] = add nsw i32 [[STOREMERGE]], -1
+; CHECK-NEXT:    br i1 [[PHIOFOPS]], label [[BB1]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+  br label %bb1
+
+bb1:                                      ; preds = %critedge, %0
+  %storemerge = phi i32 [ 0, %0 ], [ %add, %critedge ]
+  %cmp1 = icmp eq i32 %storemerge, 0
+  br i1 %cmp1, label %lr.ph, label %critedge
+
+lr.ph:                                           ; preds = %bb1
+  br i1 undef, label %split1, label %split2
+
+split1:                                     ; preds = %lr.ph
+  br label %critedge
+
+split2:                                     ; preds = %lr.ph
+  br label %critedge
+
+critedge:                                        ; preds = %split1, %split2, %bb1
+  %lcssa = phi i32 [ 0, %bb1 ], [ -1, %split1 ], [ -1, %split2 ]
+  %cmp2 = icmp ne i32 %lcssa, 0
+  %brmerge = or i1 %cmp1, %cmp2
+  %add = add nsw i32 %storemerge, -1
+  br i1 %brmerge, label %bb1, label %exit
+
+exit:                                      ; preds = %critedge
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/phi-translate-partial-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/phi-translate-partial-alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/phi-translate-partial-alias.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/phi-translate-partial-alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -basicaa -newgvn -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-f128:128:128-n8:16:32:64"
+
+; GVN shouldn't PRE the load around the loop backedge because it's
+; not actually redundant around the loop backedge, despite appearances
+; if phi-translation is ignored.
+
+; CHECK: define void @test0(i8* %begin)
+; CHECK: loop:
+; CHECK:   %l0 = load i8, i8* %phi
+; CHECK:   call void @bar(i8 %l0)
+; CHECK:   %l1 = load i8, i8* %phi
+define void @test0(i8* %begin) {
+entry:
+  br label %loop
+
+loop:
+  %phi = phi i8* [ %begin, %entry ], [ %next, %loop ]
+  %l0 = load i8, i8* %phi
+  call void @bar(i8 %l0)
+  %l1 = load i8, i8* %phi
+  %next = getelementptr inbounds i8, i8* %phi, i8 %l1
+  br label %loop
+}
+
+declare void @bar(i8)

Added: llvm/trunk/test/Transforms/NewGVN/pr10820.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr10820.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr10820.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr10820.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; XFAIL: *
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+; NewGVN fails this due to missing load coercion
+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-f128:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at g = external global i31
+
+define void @main() nounwind uwtable {
+entry:
+; CHECK: store i32
+  store i32 402662078, i32* bitcast (i31* @g to i32*), align 8
+; CHECK-NOT: load i31
+  %0 = load i31, i31* @g, align 8
+; CHECK: store i31
+  store i31 %0, i31* undef, align 1
+  unreachable
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr12979.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr12979.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr12979.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr12979.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,93 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+define i32 @test1(i32 %x, i32 %y) {
+; CHECK: @test1(i32 %x, i32 %y)
+; CHECK: %add1 = add i32 %x, %y
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add nsw i32 %x, %y
+  %add2 = add     i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+define i32 @test2(i32 %x, i32 %y) {
+; CHECK: @test2(i32 %x, i32 %y)
+; CHECK: %add1 = add i32 %x, %y
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add nuw i32 %x, %y
+  %add2 = add     i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+define i32 @test3(i32 %x, i32 %y) {
+; CHECK: @test3(i32 %x, i32 %y)
+; CHECK: %add1 = add i32 %x, %y
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add nuw nsw i32 %x, %y
+  %add2 = add     i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+define i32 @test4(i32 %x, i32 %y) {
+; CHECK: @test4(i32 %x, i32 %y)
+; CHECK: %add1 = add nsw i32 %x, %y
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add nsw i32 %x, %y
+  %add2 = add nsw i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+define i32 @test5(i32 %x, i32 %y) {
+; CHECK: @test5(i32 %x, i32 %y)
+; CHECK: %add1 = add i32 %x, %y
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add nuw i32 %x, %y
+  %add2 = add nsw i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+define i32 @test6(i32 %x, i32 %y) {
+; CHECK: @test6(i32 %x, i32 %y)
+; CHECK: %add1 = add nsw i32 %x, %y
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add nuw nsw i32 %x, %y
+  %add2 = add nsw i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+define i32 @test7(i32 %x, i32 %y) {
+; CHECK: @test7(i32 %x, i32 %y)
+; CHECK: %add1 = add i32 %x, %y
+; CHECK-NOT: what_is_this
+; CHECK: %foo = add i32 %add1, %add1
+
+  %add1 = add i32 %x, %y, !what_is_this !{}
+  %add2 = add i32 %x, %y
+  %foo = add i32 %add1, %add2
+  ret i32 %foo
+}
+
+declare void @mumble(i2, i2)
+
+define void @test8(i2 %x) {
+; CHECK-LABEL: @test8(
+; CHECK:      %[[ashr:.*]] = ashr i2 %x, 1
+; CHECK-NEXT: call void @mumble(i2 %[[ashr]], i2 %[[ashr]])
+; CHECK-NEXT: ret void
+
+  %ashr0 = ashr exact i2 %x, 1
+  %ashr1 = ashr i2 %x, 1
+  call void @mumble(i2 %ashr0, i2 %ashr1)
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr14166.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr14166.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr14166.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr14166.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; XFAIL: *
+; RUN: opt -disable-basicaa -newgvn -S < %s | FileCheck %s
+; NewGVN fails this due to missing load coercion
+target datalayout = "e-p:32:32:32"
+target triple = "i386-pc-linux-gnu"
+define <2 x i32> @test1() {
+  %v1 = alloca <2 x i32>
+  call void @anything(<2 x i32>* %v1)
+  %v2 = load <2 x i32>, <2 x i32>* %v1
+  %v3 = inttoptr <2 x i32> %v2 to <2 x i8*>
+  %v4 = bitcast <2 x i32>* %v1 to <2 x i8*>*
+  store <2 x i8*> %v3, <2 x i8*>* %v4
+  %v5 = load <2 x i32>, <2 x i32>* %v1
+  ret <2 x i32> %v5
+; CHECK-LABEL: @test1(
+; CHECK: %v1 = alloca <2 x i32>
+; CHECK: call void @anything(<2 x i32>* %v1)
+; CHECK: %v2 = load <2 x i32>, <2 x i32>* %v1
+; CHECK: %v3 = inttoptr <2 x i32> %v2 to <2 x i8*>
+; CHECK: %v4 = bitcast <2 x i32>* %v1 to <2 x i8*>*
+; CHECK: store <2 x i8*> %v3, <2 x i8*>* %v4
+; CHECK: ret <2 x i32> %v2
+}
+
+declare void @anything(<2 x i32>*)
+

Added: llvm/trunk/test/Transforms/NewGVN/pr17732.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr17732.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr17732.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr17732.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -newgvn -S -o - < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.with_array = type { [2 x i8], i32, i8 }
+%struct.with_vector = type { <2 x i8>, i32, i8 }
+
+ at main.obj_with_array = private unnamed_addr constant { [2 x i8], i32, i8, [3 x i8] } { [2 x i8] zeroinitializer, i32 0, i8 1, [3 x i8] undef }, align 4
+ at array_with_zeroinit = common global %struct.with_array zeroinitializer, align 4
+
+ at main.obj_with_vector = private unnamed_addr constant { <2 x i8>, i32, i8, [3 x i8] } { <2 x i8> zeroinitializer, i32 0, i8 1, [3 x i8] undef }, align 4
+ at vector_with_zeroinit = common global %struct.with_vector zeroinitializer, align 4
+
+define i32 @main() {
+entry:
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 getelementptr inbounds (%struct.with_array, %struct.with_array* @array_with_zeroinit, i64 0, i32 0, i64 0), i8* align 4 getelementptr inbounds ({ [2 x i8], i32, i8, [3 x i8] }, { [2 x i8], i32, i8, [3 x i8] }* @main.obj_with_array, i64 0, i32 0, i64 0), i64 12, i1 false)
+  %0 = load i8, i8* getelementptr inbounds (%struct.with_array, %struct.with_array* @array_with_zeroinit, i64 0, i32 2), align 4
+
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 getelementptr inbounds (%struct.with_vector, %struct.with_vector* @vector_with_zeroinit, i64 0, i32 0, i64 0), i8* align 4 getelementptr inbounds ({ <2 x i8>, i32, i8, [3 x i8] }, { <2 x i8>, i32, i8, [3 x i8] }* @main.obj_with_vector, i64 0, i32 0, i64 0), i64 12, i1 false)
+  %1 = load i8, i8* getelementptr inbounds (%struct.with_vector, %struct.with_vector* @vector_with_zeroinit, i64 0, i32 2), align 4
+  %conv0 = sext i8 %0 to i32
+  %conv1 = sext i8 %1 to i32
+  %and = and i32 %conv0, %conv1
+  ret i32 %and
+; CHECK-LABEL: define i32 @main(
+; CHECK: ret i32 1
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1)

Added: llvm/trunk/test/Transforms/NewGVN/pr17852.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr17852.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr17852.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr17852.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,66 @@
+; RUN: opt < %s -basicaa -newgvn
+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"
+%struct.S0 = type { [2 x i8], [2 x i8], [4 x i8], [2 x i8], i32, i32, i32, i32 }
+define void @fn1(%struct.S0* byval align 8 %p1) {
+  br label %for.cond
+for.cond:                                         ; preds = %1, %0
+  br label %for.end
+  %f2 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
+  %f9 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 7
+  br label %for.cond
+for.end:                                          ; preds = %for.cond
+  br i1 true, label %if.else, label %if.then
+if.then:                                          ; preds = %for.end
+  %f22 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
+  %f7 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 5
+  %tmp7 = load i32, i32* %f7, align 8
+  br label %if.end40
+if.else:                                          ; preds = %for.end
+  br i1 false, label %for.cond18, label %if.then6
+if.then6:                                         ; preds = %if.else
+  %f3 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
+  %tmp10 = bitcast %struct.S0* %p1 to i16*
+  %f5 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
+  %tmp11 = bitcast [2 x i8]* %f5 to i16*
+  %bf.load13 = load i16, i16* %tmp11, align 8
+  br label %if.end36
+for.cond18:                                       ; preds = %if.else
+  call void @fn4()
+  br i1 true, label %if.end, label %if.end36
+if.end:                                           ; preds = %for.cond18
+  %f321 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 2
+  %f925 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 7
+  %f526 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
+  %tmp15 = bitcast [2 x i8]* %f526 to i16*
+  %bf.load27 = load i16, i16* %tmp15, align 8
+  %tmp16 = bitcast %struct.S0* %p1 to i16*
+  br label %if.end36
+if.end36:                                         ; preds = %if.end, %for.cond18, %if.then6
+  %f537 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
+  %tmp17 = bitcast [2 x i8]* %f537 to i16*
+  %bf.load38 = load i16, i16* %tmp17, align 8
+  %bf.clear39 = and i16 %bf.load38, -16384
+  br label %if.end40
+if.end40:                                         ; preds = %if.end36, %if.then
+  %f6 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 4
+  %tmp18 = load i32, i32* %f6, align 4
+  call void @fn2(i32 %tmp18)
+  %f8 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 6
+  %tmp19 = load i32, i32* %f8, align 4
+  %tobool41 = icmp eq i32 %tmp19, 0
+  br i1 true, label %if.end50, label %if.then42
+if.then42:                                        ; preds = %if.end40
+  %tmp20 = bitcast %struct.S0* %p1 to i16*
+  %f547 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
+  %tmp21 = bitcast [2 x i8]* %f547 to i16*
+  %bf.load48 = load i16, i16* %tmp21, align 8
+  br label %if.end50
+if.end50:                                         ; preds = %if.then42, %if.end40
+  %f551 = getelementptr inbounds %struct.S0, %struct.S0* %p1, i64 0, i32 3
+  %tmp22 = bitcast [2 x i8]* %f551 to i16*
+  %bf.load52 = load i16, i16* %tmp22, align 8
+  %bf.clear53 = and i16 %bf.load52, -16384
+  ret void
+}
+declare void @fn2(i32)
+declare void @fn4()

Added: llvm/trunk/test/Transforms/NewGVN/pr24397.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr24397.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr24397.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr24397.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -basicaa -newgvn -disable-output < %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define i64 @foo(i64** %arrayidx) {
+entry:
+  %p = load i64*, i64** %arrayidx, align 8
+  %cmpnull = icmp eq i64* %p, null
+  br label %BB2
+
+entry2:                                           ; No predecessors!
+  br label %BB2
+
+BB2:                                              ; preds = %entry2, %entry
+  %bc = bitcast i64** %arrayidx to i64*
+  %load = load i64, i64* %bc, align 8
+  ret i64 %load
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr24426.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr24426.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr24426.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr24426.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -memcpyopt -mldst-motion -newgvn -S | FileCheck %s
+
+declare void @check(i8)
+
+declare void @write(i8* %res)
+
+define void @test1() {
+  %1 = alloca [10 x i8]
+  %2 = bitcast [10 x i8]* %1 to i8*
+  call void @write(i8* %2)
+  %3 = load i8, i8* %2
+
+; CHECK-NOT: undef
+  call void @check(i8 %3)
+
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/pr25440.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr25440.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr25440.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr25440.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,108 @@
+;RUN: opt -newgvn -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64"
+target triple = "thumbv7--linux-gnueabi"
+
+%struct.a = type { i16, i16, [1 x %union.a] }
+%union.a = type { i32 }
+
+ at length = external global [0 x i32], align 4
+
+; Function Attrs: nounwind
+define fastcc void @foo(%struct.a* nocapture readonly %x) {
+;CHECK-LABEL: foo
+entry:
+  br label %bb0
+
+bb0:                                      ; preds = %land.lhs.true, %entry
+;CHECK: bb0:
+  %x.tr = phi %struct.a* [ %x, %entry ], [ null, %land.lhs.true ]
+  %code1 = getelementptr inbounds %struct.a, %struct.a* %x.tr, i32 0, i32 0
+  %0 = load i16, i16* %code1, align 4
+; CHECK: load i16, i16*
+  %conv = zext i16 %0 to i32
+  switch i32 %conv, label %if.end.50 [
+    i32 43, label %cleanup
+    i32 52, label %if.then.5
+  ]
+
+if.then.5:                                        ; preds = %bb0
+  br i1 undef, label %land.lhs.true, label %if.then.26
+
+land.lhs.true:                                    ; preds = %if.then.5
+  br i1 undef, label %cleanup, label %bb0
+
+if.then.26:                                       ; preds = %if.then.5
+  %x.tr.lcssa163 = phi %struct.a* [ %x.tr, %if.then.5 ]
+  br i1 undef, label %cond.end, label %cond.false
+
+cond.false:                                       ; preds = %if.then.26
+; CHECK: cond.false:
+; CHECK: load i16
+  %mode = getelementptr inbounds %struct.a, %struct.a* %x.tr.lcssa163, i32 0, i32 1
+  %bf.load = load i16, i16* %mode, align 2
+  %bf.shl = shl i16 %bf.load, 8
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %if.then.26
+  br i1 undef, label %if.then.44, label %cleanup
+
+if.then.44:                                       ; preds = %cond.end
+  unreachable
+
+if.end.50:                                        ; preds = %bb0
+;%CHECK: if.end.50:
+  %conv.lcssa = phi i32 [ %conv, %bb0 ]
+  %arrayidx52 = getelementptr inbounds [0 x i32], [0 x i32]* @length, i32 0, i32 %conv.lcssa
+  %1 = load i32, i32* %arrayidx52, align 4
+  br i1 undef, label %for.body.57, label %cleanup
+
+for.body.57:                                      ; preds = %if.end.50
+  %i.2157 = add nsw i32 %1, -1
+  unreachable
+
+cleanup:                                          ; preds = %if.end.50, %cond.end, %land.lhs.true, %bb0
+  ret void
+}
+
+ at yy_c_buf_p = external unnamed_addr global i8*, align 4
+ at dfg_text = external global i8*, align 4
+
+define void @dfg_lex() {
+;CHECK-LABEL: dfg_lex
+entry:
+  br label %while.bodythread-pre-split
+
+while.bodythread-pre-split:                       ; preds = %while.end, %while.end, %entry
+  br i1 undef, label %if.then.14, label %if.end.15
+
+if.then.14:                                       ; preds = %while.end, %while.bodythread-pre-split
+  %v1 = load i32, i32* bitcast (i8** @dfg_text to i32*), align 4
+  %sub.ptr.sub = sub i32 undef, %v1
+  br label %if.end.15
+
+if.end.15:                                        ; preds = %if.then.14, %while.bodythread-pre-split
+  %v2 = load i8*, i8** @yy_c_buf_p, align 4
+  br label %while.cond.16
+
+while.cond.16:                                    ; preds = %while.cond.16, %if.end.15
+  br i1 undef, label %while.cond.16, label %while.end
+
+while.end:                                        ; preds = %while.cond.16
+  %add.ptr = getelementptr inbounds i8, i8* %v2, i32 undef
+  store i8* %add.ptr, i8** @dfg_text, align 4
+  %sub.ptr.rhs.cast25 = ptrtoint i8* %add.ptr to i32
+  %sub.ptr.sub26 = sub i32 0, %sub.ptr.rhs.cast25
+  switch i32 undef, label %sw.default [
+    i32 65, label %while.bodythread-pre-split
+    i32 3, label %return
+    i32 57, label %while.bodythread-pre-split
+    i32 60, label %if.then.14
+  ]
+
+sw.default:                                       ; preds = %while.end
+  unreachable
+
+return:                                           ; preds = %while.end
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr28562.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr28562.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr28562.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr28562.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt -S -newgvn < %s | FileCheck %s
+define i32* @test1(i32* %a) {
+  %x1 = getelementptr inbounds i32, i32* %a, i32 10
+  %x2 = getelementptr i32, i32* %a, i32 10
+  ret i32* %x2
+; CHECK-LABEL: @test1(
+; CHECK: %[[x:.*]] = getelementptr i32, i32* %a, i32 10
+; CHECK: ret i32* %[[x]]
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr31472.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31472.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31472.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31472.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+;; Ensure the invoke does not accidentally get deleted as unused, just because the value is not used.
+
+; Function Attrs: norecurse ssp uwtable
+define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*){
+; CHECK-LABEL: @main(
+; CHECK-NEXT:    [[TMP1:%.*]] = invoke i32 @foo()
+; CHECK-NEXT:    to label %good unwind label %bad
+; CHECK:       good:
+; CHECK-NEXT:    ret i32 5
+; CHECK:       bad:
+; CHECK-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32
+;
+  %1 = invoke i32 @foo()
+  to label %good unwind label %bad
+
+good:
+; <label>:15:                                     ; preds = %.preheader
+  ret i32 5
+
+
+bad:
+; <label>:20:                                     ; preds = %15, %.preheader
+  %2 = landingpad { i8*, i32 }
+  cleanup
+  resume { i8*, i32 } %2
+}
+
+declare i32 @foo()
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/NewGVN/pr31483.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31483.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31483.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31483.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,106 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "E-m:e-i64:64-n32:64"
+
+ at global = external hidden unnamed_addr constant [11 x i8], align 1
+;; Ensure we do not believe the indexing increments are unreachable due to incorrect memory
+;; equivalence detection.  In PR31483, we were deleting those blocks as unreachable
+; Function Attrs: nounwind
+define signext i32 @ham(i8* %arg, i8* %arg1) #0 {
+; CHECK-LABEL: @ham(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = alloca i8*, align 8
+; CHECK-NEXT:    store i8* %arg1, i8** [[TMP]], align 8
+; CHECK-NEXT:    br label %bb2
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP3:%.*]] = phi i8* [ %arg, %bb ], [ %tmp7, %bb22 ]
+; CHECK-NEXT:    [[TMP4:%.*]] = load i8, i8* [[TMP3]], align 1
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i8 [[TMP4]], 0
+; CHECK-NEXT:    br i1 [[TMP5]], label %bb6, label %bb23
+; CHECK:       bb6:
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds i8, i8* [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP9:%.*]] = zext i8 [[TMP4]] to i32
+; CHECK-NEXT:    switch i32 [[TMP9]], label %bb22 [
+; CHECK-NEXT:    i32 115, label %bb10
+; CHECK-NEXT:    i32 105, label %bb16
+; CHECK-NEXT:    i32 99, label %bb16
+; CHECK-NEXT:    ]
+; CHECK:       bb10:
+; CHECK-NEXT:    [[TMP11:%.*]] = load i8*, i8** [[TMP]], align 8
+; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds i8, i8* [[TMP11]], i64 8
+; CHECK-NEXT:    store i8* [[TMP12]], i8** [[TMP]], align 8
+; CHECK-NEXT:    [[TMP13:%.*]] = bitcast i8* [[TMP11]] to i8**
+; CHECK-NEXT:    [[TMP14:%.*]] = load i8*, i8** [[TMP13]], align 8
+; CHECK-NEXT:    [[TMP15:%.*]] = call signext i32 (i8*, ...) @zot(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @global, i32 0, i32 0), i8* [[TMP14]])
+; CHECK-NEXT:    br label %bb22
+; CHECK:       bb16:
+; CHECK-NEXT:    [[TMP17:%.*]] = load i8*, i8** [[TMP]], align 8
+; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 8
+; CHECK-NEXT:    store i8* [[TMP18]], i8** [[TMP]], align 8
+; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 4
+; CHECK-NEXT:    [[TMP20:%.*]] = bitcast i8* [[TMP19]] to i32*
+; CHECK-NEXT:    br label %bb22
+; CHECK:       bb22:
+; CHECK-NEXT:    br label %bb2
+; CHECK:       bb23:
+; CHECK-NEXT:    [[TMP24:%.*]] = bitcast i8** [[TMP]] to i8*
+; CHECK-NEXT:    call void @llvm.va_end(i8* [[TMP24]])
+; CHECK-NEXT:    ret i32 undef
+;
+bb:
+  %tmp = alloca i8*, align 8
+  store i8* %arg1, i8** %tmp, align 8
+  br label %bb2
+
+bb2:                                              ; preds = %bb22, %bb
+  %tmp3 = phi i8* [ %arg, %bb ], [ %tmp7, %bb22 ]
+  %tmp4 = load i8, i8* %tmp3, align 1
+  %tmp5 = icmp ne i8 %tmp4, 0
+  br i1 %tmp5, label %bb6, label %bb23
+
+bb6:                                              ; preds = %bb2
+  %tmp7 = getelementptr inbounds i8, i8* %tmp3, i32 1
+  %tmp8 = load i8, i8* %tmp3, align 1
+  %tmp9 = zext i8 %tmp8 to i32
+  switch i32 %tmp9, label %bb22 [
+  i32 115, label %bb10
+  i32 105, label %bb16
+  i32 99, label %bb16
+  ]
+
+bb10:                                             ; preds = %bb6
+  %tmp11 = load i8*, i8** %tmp, align 8
+  %tmp12 = getelementptr inbounds i8, i8* %tmp11, i64 8
+  store i8* %tmp12, i8** %tmp, align 8
+  %tmp13 = bitcast i8* %tmp11 to i8**
+  %tmp14 = load i8*, i8** %tmp13, align 8
+  %tmp15 = call signext i32 (i8*, ...) @zot(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @global, i32 0, i32 0), i8* %tmp14)
+  br label %bb22
+
+bb16:                                             ; preds = %bb6, %bb6
+  %tmp17 = load i8*, i8** %tmp, align 8
+  %tmp18 = getelementptr inbounds i8, i8* %tmp17, i64 8
+  store i8* %tmp18, i8** %tmp, align 8
+  %tmp19 = getelementptr inbounds i8, i8* %tmp17, i64 4
+  %tmp20 = bitcast i8* %tmp19 to i32*
+  %tmp21 = load i32, i32* %tmp20, align 4
+  br label %bb22
+
+bb22:                                             ; preds = %bb16, %bb10, %bb6
+  br label %bb2
+
+bb23:                                             ; preds = %bb2
+  %tmp24 = bitcast i8** %tmp to i8*
+  call void @llvm.va_end(i8* %tmp24)
+  ret i32 undef
+}
+
+declare signext i32 @zot(i8*, ...) #1
+
+; Function Attrs: nounwind
+declare void @llvm.va_end(i8*) #2
+
+attributes #0 = { nounwind "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"="ppc64" "target-features"="+altivec,-bpermd,-crypto,-direct-move,-extdiv,-power8-vector,-qpx,-vsx" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "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"="ppc64" "target-features"="+altivec,-bpermd,-crypto,-direct-move,-extdiv,-power8-vector,-qpx,-vsx" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+

Added: llvm/trunk/test/Transforms/NewGVN/pr31491.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31491.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31491.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31491.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+;; Test that we do not infinite loop on this testcase, and that we do not try
+;; to replace the phi node argument with the result of the phi node.
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define internal i32 @pr31491() {
+; CHECK-LABEL: @pr31491(
+; CHECK-NEXT:  bb5:
+; CHECK-NEXT:    br label %bb7
+; CHECK:       bb7:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i8* [ [[TMP:%.*]]11, %bb10 ], [ undef, %bb5 ]
+; CHECK-NEXT:    br label %bb10
+; CHECK:       bb10:
+; CHECK-NEXT:    [[TMP11:%.*]] = tail call i8* @patatino(i8* [[TMP]])
+; CHECK-NEXT:    br label %bb7
+;
+bb5:
+  br label %bb7
+
+bb7:                                              ; preds = %bb10, %bb5
+  %tmp = phi i8* [ %tmp11, %bb10 ], [ undef, %bb5 ]
+  br label %bb10
+
+bb10:                                             ; preds = %bb7
+  %tmp11 = tail call i8* @patatino(i8* %tmp)
+  br label %bb7
+}
+
+declare i8* @patatino(i8*)

Added: llvm/trunk/test/Transforms/NewGVN/pr31501.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31501.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31501.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31501.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,136 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.foo = type { %struct.wombat.28*, %struct.zot, %struct.wombat.28* }
+%struct.zot = type { i64 }
+%struct.barney = type <{ %struct.wombat.28*, %struct.wibble, %struct.snork, %struct.quux.4, %struct.snork.10, %struct.ham.16*, %struct.wobble.23*, i32, i8, i8, [2 x i8] }>
+%struct.wibble = type { %struct.pluto, %struct.bar }
+%struct.pluto = type { %struct.quux }
+%struct.quux = type { %struct.eggs }
+%struct.eggs = type { %struct.zot.0, %struct.widget }
+%struct.zot.0 = type { i8*, i8*, i8* }
+%struct.widget = type { %struct.barney.1 }
+%struct.barney.1 = type { [8 x i8] }
+%struct.bar = type { [3 x %struct.widget] }
+%struct.snork = type <{ %struct.wobble, %struct.bar.3, [7 x i8] }>
+%struct.wobble = type { %struct.wombat }
+%struct.wombat = type { %struct.zot.2 }
+%struct.zot.2 = type { %struct.zot.0, %struct.ham }
+%struct.ham = type { %struct.barney.1 }
+%struct.bar.3 = type { i8 }
+%struct.quux.4 = type <{ %struct.quux.5, %struct.snork.9, [7 x i8] }>
+%struct.quux.5 = type { %struct.widget.6 }
+%struct.widget.6 = type { %struct.spam }
+%struct.spam = type { %struct.zot.0, %struct.ham.7 }
+%struct.ham.7 = type { %struct.barney.8 }
+%struct.barney.8 = type { [24 x i8] }
+%struct.snork.9 = type { i8 }
+%struct.snork.10 = type <{ %struct.foo.11, %struct.spam.15, [7 x i8] }>
+%struct.foo.11 = type { %struct.snork.12 }
+%struct.snork.12 = type { %struct.wombat.13 }
+%struct.wombat.13 = type { %struct.zot.0, %struct.wibble.14 }
+%struct.wibble.14 = type { %struct.barney.8 }
+%struct.spam.15 = type { i8 }
+%struct.ham.16 = type { %struct.pluto.17, %struct.pluto.17 }
+%struct.pluto.17 = type { %struct.bar.18 }
+%struct.bar.18 = type { %struct.baz*, %struct.zot.20, %struct.barney.22 }
+%struct.baz = type { %struct.wibble.19* }
+%struct.wibble.19 = type <{ %struct.baz, %struct.wibble.19*, %struct.baz*, i8, [7 x i8] }>
+%struct.zot.20 = type { %struct.ham.21 }
+%struct.ham.21 = type { %struct.baz }
+%struct.barney.22 = type { %struct.blam }
+%struct.blam = type { i64 }
+%struct.wobble.23 = type { %struct.spam.24, %struct.barney* }
+%struct.spam.24 = type { %struct.bar.25, %struct.zot.26* }
+%struct.bar.25 = type <{ i32 (...)**, i8, i8 }>
+%struct.zot.26 = type { i32 (...)**, i32, %struct.widget.27* }
+%struct.widget.27 = type { %struct.zot.26, %struct.zot.26* }
+%struct.wombat.28 = type <{ i32 (...)**, i8, i8, [6 x i8] }>
+
+; Function Attrs: norecurse nounwind ssp uwtable
+define weak_odr hidden %struct.foo* @quux(%struct.barney* %arg, %struct.wombat.28* %arg1) local_unnamed_addr #0 align 2 {
+; CHECK-LABEL: @quux(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0
+; CHECK-NEXT:    [[TMP2:%.*]] = bitcast %struct.spam* [[TMP]] to %struct.foo**
+; CHECK-NEXT:    [[TMP3:%.*]] = load %struct.foo*, %struct.foo** [[TMP2]], align 8, !tbaa !2
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0, i32 0, i32 1
+; CHECK-NEXT:    [[TMP5:%.*]] = bitcast i8** [[TMP4]] to %struct.foo**
+; CHECK-NEXT:    [[TMP6:%.*]] = load %struct.foo*, %struct.foo** [[TMP5]], align 8, !tbaa !7
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq %struct.foo* [[TMP3]], [[TMP6]]
+; CHECK-NEXT:    br i1 [[TMP7]], label %bb21, label %bb8
+; CHECK:       bb8:
+; CHECK-NEXT:    br label %bb11
+; CHECK:       bb9:
+; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq %struct.foo* [[TMP18:%.*]], [[TMP6]]
+; CHECK-NEXT:    br i1 [[TMP10]], label %bb19, label %bb11
+; CHECK:       bb11:
+; CHECK-NEXT:    [[TMP12:%.*]] = phi %struct.foo* [ [[TMP17:%.*]], %bb9 ], [ undef, %bb8 ]
+; CHECK-NEXT:    [[TMP13:%.*]] = phi %struct.foo* [ [[TMP18]], %bb9 ], [ [[TMP3]], %bb8 ]
+; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds %struct.foo, %struct.foo* [[TMP13]], i64 0, i32 0
+; CHECK-NEXT:    [[TMP15:%.*]] = load %struct.wombat.28*, %struct.wombat.28** [[TMP14]], align 8, !tbaa !8
+; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq %struct.wombat.28* [[TMP15]], %arg1
+; CHECK-NEXT:    [[TMP17]] = select i1 [[TMP16]], %struct.foo* [[TMP13]], %struct.foo* [[TMP12]]
+; CHECK-NEXT:    [[TMP18]] = getelementptr inbounds %struct.foo, %struct.foo* [[TMP13]], i64 1
+; CHECK-NEXT:    br i1 [[TMP16]], label %bb19, label %bb9
+; CHECK:       bb19:
+; CHECK-NEXT:    [[TMP20:%.*]] = phi %struct.foo* [ null, %bb9 ], [ [[TMP17]], %bb11 ]
+; CHECK-NEXT:    br label %bb21
+; CHECK:       bb21:
+; CHECK-NEXT:    [[TMP22:%.*]] = phi %struct.foo* [ null, %bb ], [ [[TMP20]], %bb19 ]
+; CHECK-NEXT:    ret %struct.foo* [[TMP22]]
+;
+bb:
+  %tmp = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0
+  %tmp2 = bitcast %struct.spam* %tmp to %struct.foo**
+  %tmp3 = load %struct.foo*, %struct.foo** %tmp2, align 8, !tbaa !2
+  %tmp4 = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0, i32 0, i32 1
+  %tmp5 = bitcast i8** %tmp4 to %struct.foo**
+  %tmp6 = load %struct.foo*, %struct.foo** %tmp5, align 8, !tbaa !7
+  %tmp7 = icmp eq %struct.foo* %tmp3, %tmp6
+  br i1 %tmp7, label %bb21, label %bb8
+
+bb8:                                              ; preds = %bb
+  br label %bb11
+
+bb9:                                              ; preds = %bb11
+  %tmp10 = icmp eq %struct.foo* %tmp18, %tmp6
+  br i1 %tmp10, label %bb19, label %bb11
+
+bb11:                                             ; preds = %bb9, %bb8
+  %tmp12 = phi %struct.foo* [ %tmp17, %bb9 ], [ undef, %bb8 ]
+  %tmp13 = phi %struct.foo* [ %tmp18, %bb9 ], [ %tmp3, %bb8 ]
+  %tmp14 = getelementptr inbounds %struct.foo, %struct.foo* %tmp13, i64 0, i32 0
+  %tmp15 = load %struct.wombat.28*, %struct.wombat.28** %tmp14, align 8, !tbaa !8
+  %tmp16 = icmp eq %struct.wombat.28* %tmp15, %arg1
+  %tmp17 = select i1 %tmp16, %struct.foo* %tmp13, %struct.foo* %tmp12
+  %tmp18 = getelementptr inbounds %struct.foo, %struct.foo* %tmp13, i64 1
+  br i1 %tmp16, label %bb19, label %bb9
+
+bb19:                                             ; preds = %bb11, %bb9
+  %tmp20 = phi %struct.foo* [ null, %bb9 ], [ %tmp17, %bb11 ]
+  br label %bb21
+
+bb21:                                             ; preds = %bb19, %bb
+  %tmp22 = phi %struct.foo* [ null, %bb ], [ %tmp20, %bb19 ]
+  ret %struct.foo* %tmp22
+}
+
+attributes #0 = { norecurse 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"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"PIC Level", i32 2}
+!1 = !{!"clang version 4.0.0"}
+!2 = !{!3, !4, i64 0}
+!3 = !{!"_ZTSN4llvm15SmallVectorBaseE", !4, i64 0, !4, i64 8, !4, i64 16}
+!4 = !{!"any pointer", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple C++ TBAA"}
+!7 = !{!3, !4, i64 8}
+!8 = !{!9, !4, i64 0}
+!9 = !{!"_ZTSN4llvm9RecordValE", !4, i64 0, !10, i64 8, !4, i64 16}
+!10 = !{!"_ZTSN4llvm14PointerIntPairIPNS_5RecTyELj1EbNS_21PointerLikeTypeTraitsIS2_EENS_18PointerIntPairInfoIS2_Lj1ES4_EEEE", !11, i64 0}
+!11 = !{!"long", !5, i64 0}

Added: llvm/trunk/test/Transforms/NewGVN/pr31573.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31573.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31573.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31573.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @patatino(i8* %blah) {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[MEH:%.*]] = phi i8* [ [[BLAH:%.*]], [[ENTRY:%.*]] ], [ null, [[WHILE_BODY:%.*]] ]
+; CHECK-NEXT:    switch i32 undef, label [[WHILE_BODY]] [
+; CHECK-NEXT:    i32 666, label [[WHILE_END:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       while.body:
+; CHECK-NEXT:    br label [[WHILE_COND]]
+; CHECK:       while.end:
+; CHECK-NEXT:    store i8 0, i8* [[MEH]], align 1
+; CHECK-NEXT:    store i8 0, i8* [[BLAH]], align 1
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %while.cond
+
+while.cond:
+  %meh = phi i8* [ %blah, %entry ], [ null, %while.body ]
+  switch i32 undef, label %while.body [
+  i32 666, label %while.end
+  ]
+
+while.body:
+  br label %while.cond
+
+while.end:
+;; These two stores will initially be considered equivalent, but then proven not.
+;; the second store would previously end up deciding it's equivalent to a previous
+;; store, but it was really just finding an optimistic version of itself
+;; in the congruence class.
+  store i8 0, i8* %meh, align 1
+  store i8 0, i8* %blah, align 1
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr31594.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31594.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31594.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31594.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,122 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define i1 @patatino(i8* %blah, i32 %choice) {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[FOO:%.*]] = phi i8* [ [[BLAH:%.*]], [[ENTRY:%.*]] ], [ null, [[WHILE_BODY:%.*]] ]
+; CHECK-NEXT:    switch i32 [[CHOICE:%.*]], label [[WHILE_BODY]] [
+; CHECK-NEXT:    i32 -1, label [[WHILE_END:%.*]]
+; CHECK-NEXT:    i32 40, label [[LAND_END:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       land.end:
+; CHECK-NEXT:    br label [[WHILE_END]]
+; CHECK:       while.body:
+; CHECK-NEXT:    br label [[WHILE_COND]]
+; CHECK:       while.end:
+; CHECK-NEXT:    store i8 0, i8* [[FOO]], align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, i8* [[BLAH]], align 1
+; CHECK-NEXT:    [[LOADED:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    store i8 0, i8* [[BLAH]], align 1
+; CHECK-NEXT:    ret i1 [[LOADED]]
+;
+entry:
+  br label %while.cond
+
+while.cond:
+  %foo = phi i8* [ %blah, %entry ], [ null, %while.body ]
+  switch i32 %choice, label %while.body [
+  i32 -1, label %while.end
+  i32 40, label %land.end
+  ]
+
+land.end:
+  br label %while.end
+
+while.body:
+  br label %while.cond
+
+while.end:
+  %foo.lcssa = phi i8* [ %foo, %land.end ], [ %foo, %while.cond ]
+;; These two stores will initially be considered equivalent, but then proven not.
+;; the second store would previously end up deciding it's equivalent to a previous
+;; store, but it was really just finding an optimistic version of itself
+;; in the congruence class.
+  store i8 0, i8* %foo.lcssa, align 1
+  %0 = load i8, i8* %blah, align 1
+  %loaded = icmp eq i8 %0, 0
+  store i8 0, i8* %blah, align 1
+  ret i1 %loaded
+}
+
+
+;; This is an example of a case where the memory states are equivalent solely due to unreachability,
+;; but the stores are not equal.
+define void @foo(i8* %arg) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i8* [ [[ARG:%.*]], [[BB:%.*]] ], [ null, [[BB2:%.*]] ]
+; CHECK-NEXT:    br i1 undef, label [[BB3:%.*]], label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb3:
+; CHECK-NEXT:    store i8 0, i8* [[TMP]], !g !0
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    br label [[BB6:%.*]]
+; CHECK:       bb6:
+; CHECK-NEXT:    br i1 undef, label [[BB9:%.*]], label [[BB7:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    switch i8 0, label [[BB6]] [
+; CHECK-NEXT:    i8 6, label [[BB8:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb8:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb9:
+; CHECK-NEXT:    store i8 0, i8* [[ARG]], !g !0
+; CHECK-NEXT:    unreachable
+;
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb2, %bb
+  %tmp = phi i8* [ %arg, %bb ], [ null, %bb2 ]
+  br i1 undef, label %bb3, label %bb2
+
+bb2:                                              ; preds = %bb1
+  br label %bb1
+
+bb3:                                              ; preds = %bb1
+  store i8 0, i8* %tmp, !g !0
+  br label %bb4
+
+bb4:                                              ; preds = %bb8, %bb3
+  %tmp5 = phi i8* [ null, %bb8 ], [ %arg, %bb3 ]
+  br label %bb6
+
+bb6:                                              ; preds = %bb7, %bb4
+  br i1 undef, label %bb9, label %bb7
+
+bb7:                                              ; preds = %bb6
+  switch i8 0, label %bb6 [
+  i8 6, label %bb8
+  ]
+
+bb8:                                              ; preds = %bb7
+  store i8 undef, i8* %tmp5, !g !0
+  br label %bb4
+
+bb9:                                              ; preds = %bb6
+  %tmp10 = phi i8* [ %tmp5, %bb6 ]
+  store i8 0, i8* %tmp10, !g !0
+  unreachable
+}
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/NewGVN/pr31613.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31613.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31613.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31613.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,135 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -enable-store-refinement -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+;; Both of these tests are tests of phi nodes that end up all equivalent to each other
+;; Without proper leader ordering, we will end up cycling the leader between all of them and never converge.
+
+define void @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ 1, [[BB18:%.*]] ]
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    br i1 undef, label [[BB18]], label [[BB7:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    br label [[BB9:%.*]]
+; CHECK:       bb9:
+; CHECK-NEXT:    br i1 undef, label [[BB2]], label [[BB11:%.*]]
+; CHECK:       bb11:
+; CHECK-NEXT:    br i1 undef, label [[BB16:%.*]], label [[BB14:%.*]]
+; CHECK:       bb14:
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb16:
+; CHECK-NEXT:    br label [[BB7]]
+; CHECK:       bb18:
+; CHECK-NEXT:    br label [[BB1]]
+;
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb18, %bb
+  %tmp = phi i32 [ 0, %bb ], [ 1, %bb18 ]
+  br label %bb2
+
+bb2:                                              ; preds = %bb9, %bb1
+  %tmp3 = phi i32 [ %tmp, %bb1 ], [ %tmp8, %bb9 ]
+  br label %bb4
+
+bb4:                                              ; preds = %bb14, %bb2
+  %tmp5 = phi i32 [ %tmp3, %bb2 ], [ %tmp15, %bb14 ]
+  br i1 undef, label %bb18, label %bb7
+
+bb7:                                              ; preds = %bb16, %bb4
+  %tmp8 = phi i32 [ %tmp17, %bb16 ], [ %tmp5, %bb4 ]
+  br label %bb9
+
+bb9:                                              ; preds = %bb7
+  br i1 undef, label %bb2, label %bb11
+
+bb11:                                             ; preds = %bb9
+  br i1 undef, label %bb16, label %bb14
+
+bb14:                                             ; preds = %bb11
+  %tmp15 = phi i32 [ %tmp8, %bb11 ]
+  br label %bb4
+
+bb16:                                             ; preds = %bb11
+  %tmp17 = phi i32 [ %tmp8, %bb11 ]
+  br label %bb7
+
+bb18:                                             ; preds = %bb4
+  br label %bb1
+}
+
+%struct.a = type {}
+%struct.b = type {}
+
+declare void @c.d.p(i64, i8*)
+
+define void @e(i32 %a0, i32 %a1, %struct.a** %p2) {
+; CHECK-LABEL: @e(
+; CHECK-NEXT:    [[F:%.*]] = alloca i32
+; CHECK-NEXT:    store i32 [[A0:%.*]], i32* [[F]], !g !0
+; CHECK-NEXT:    br label [[H:%.*]]
+; CHECK:       h:
+; CHECK-NEXT:    call void @c.d.p(i64 8, i8* undef)
+; CHECK-NEXT:    [[I:%.*]] = load i32, i32* [[F]]
+; CHECK-NEXT:    [[J:%.*]] = load i32, i32* null
+; CHECK-NEXT:    [[K:%.*]] = icmp eq i32 [[I]], [[J]]
+; CHECK-NEXT:    br i1 [[K]], label [[L:%.*]], label [[Q:%.*]]
+; CHECK:       l:
+; CHECK-NEXT:    br label [[R:%.*]]
+; CHECK:       q:
+; CHECK-NEXT:    [[M:%.*]] = load %struct.a*, %struct.a** null
+; CHECK-NEXT:    br label [[R]]
+; CHECK:       r:
+; CHECK-NEXT:    switch i32 undef, label [[N:%.*]] [
+; CHECK-NEXT:    i32 0, label [[S:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       s:
+; CHECK-NEXT:    store i32 [[A1:%.*]], i32* [[F]], !g !0
+; CHECK-NEXT:    br label [[H]]
+; CHECK:       n:
+; CHECK-NEXT:    [[O:%.*]] = load %struct.a*, %struct.a** [[P2:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %f = alloca i32
+  store i32 %a0, i32* %f, !g !0
+  br label %h
+
+h:                                                ; preds = %s, %0
+  call void @c.d.p(i64 8, i8* undef)
+  %i = load i32, i32* %f
+  %j = load i32, i32* null
+  %k = icmp eq i32 %i, %j
+  br i1 %k, label %l, label %q
+
+l:                                                ; preds = %h
+  br label %r
+
+q:                                                ; preds = %h
+  %m = load %struct.a*, %struct.a** null
+  %1 = bitcast %struct.a* %m to %struct.b*
+  br label %r
+
+r:                                                ; preds = %q, %l
+  switch i32 undef, label %n [
+  i32 0, label %s
+  ]
+
+s:                                                ; preds = %r
+  store i32 %a1, i32* %f, !g !0
+  br label %h
+
+n:                                                ; preds = %r
+  %o = load %struct.a*, %struct.a** %p2
+  %2 = bitcast %struct.a* %o to %struct.b*
+  ret void
+}
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/NewGVN/pr31682.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31682.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31682.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31682.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.foo = type { i32, i32, [2 x [4 x [6 x [6 x i16]]]] }
+
+ at global = external global %struct.foo*
+
+define void @bar() {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = load %struct.foo*, %struct.foo** @global
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 undef, label [[BB2]], label [[BB7:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    br label [[BB10:%.*]]
+; CHECK:       bb10:
+; CHECK-NEXT:    br label [[BB10]]
+;
+bb:
+  %tmp = load %struct.foo*, %struct.foo** @global
+  %tmp1 = getelementptr %struct.foo, %struct.foo* %tmp
+  br label %bb2
+
+bb2:                                              ; preds = %bb2, %bb
+  %tmp3 = phi %struct.foo* [ undef, %bb ], [ %tmp6, %bb2 ]
+  %tmp4 = getelementptr %struct.foo, %struct.foo* %tmp3, i64 0, i32 1
+  %tmp5 = load i32, i32* %tmp4
+  %tmp6 = load %struct.foo*, %struct.foo** @global
+  br i1 undef, label %bb2, label %bb7
+
+bb7:                                              ; preds = %bb2
+  %tmp8 = phi %struct.foo* [ %tmp6, %bb2 ]
+  %tmp9 = getelementptr %struct.foo, %struct.foo* %tmp8, i64 0, i32 1
+  br label %bb10
+
+bb10:                                             ; preds = %bb10, %bb7
+  %tmp11 = load i32, i32* %tmp9
+  br label %bb10
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr31758.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr31758.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr31758.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr31758.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn %s -S -o - | FileCheck %s
+
+%struct.dipsy = type {}
+%struct.fluttershy = type { %struct.dipsy* }
+%struct.patatino = type {}
+
+define void @tinkywinky() {
+; CHECK-LABEL: @tinkywinky(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB90:%.*]]
+; CHECK:       bb90:
+; CHECK-NEXT:    br label [[BB90]]
+; CHECK:       bb138:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    br label [[BB138:%.*]]
+;
+bb:
+  br label %bb90
+
+bb90:
+  %tmp = getelementptr inbounds %struct.fluttershy, %struct.fluttershy* undef, i64 0, i32 0
+  %tmp91 = bitcast %struct.dipsy** %tmp to %struct.patatino**
+  %tmp92 = load %struct.patatino*, %struct.patatino** %tmp91, align 8
+  %tmp99 = getelementptr inbounds %struct.patatino, %struct.patatino* %tmp92
+  %tmp134 = getelementptr inbounds %struct.fluttershy, %struct.fluttershy* undef, i64 0, i32 0
+  %tmp135 = bitcast %struct.dipsy** %tmp134 to %struct.patatino**
+  %tmp136 = load %struct.patatino*, %struct.patatino** %tmp135, align 8
+  br label %bb90
+
+bb138:
+  %tmp139 = getelementptr inbounds %struct.patatino, %struct.patatino* %tmp136
+  br label %bb138
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr32403.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32403.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32403.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32403.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;RUN: opt -newgvn -S < %s | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+; Function Attrs: nounwind ssp uwtable
+define void @reorder_ref_pic_list() local_unnamed_addr {
+; CHECK-LABEL: @reorder_ref_pic_list(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 undef, label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]
+; CHECK:       for.body.preheader:
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[REFIDXLX_0:%.*]] = phi i32 [ [[INC_I51:%.*]], [[IF_ELSE58:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT:    br i1 undef, label [[IF_THEN13:%.*]], label [[IF_ELSE58]]
+; CHECK:       if.then13:
+; CHECK-NEXT:    [[INC_I:%.*]] = add nsw i32 [[REFIDXLX_0]], 1
+; CHECK-NEXT:    br label [[FOR_BODY8_I:%.*]]
+; CHECK:       for.body8.i:
+; CHECK-NEXT:    br i1 undef, label [[FOR_INC24_I:%.*]], label [[IF_THEN17_I:%.*]]
+; CHECK:       if.then17.i:
+; CHECK-NEXT:    br label [[FOR_INC24_I]]
+; CHECK:       for.inc24.i:
+; CHECK-NEXT:    br label [[FOR_BODY8_I]]
+; CHECK:       if.else58:
+; CHECK-NEXT:    [[INC_I51]] = add nsw i32 [[REFIDXLX_0]], 1
+; CHECK-NEXT:    br label [[FOR_BODY]]
+; CHECK:       for.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 undef, label %for.end, label %for.body.preheader
+
+for.body.preheader:                               ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %if.else58, %for.body.preheader
+  %refIdxLX.0 = phi i32 [ %inc.i51, %if.else58 ], [ 0, %for.body.preheader ]
+  br i1 undef, label %if.then13, label %if.else58
+
+if.then13:                                        ; preds = %for.body
+  %inc.i = add nsw i32 %refIdxLX.0, 1
+  br label %for.body8.i
+
+for.body8.i:                                      ; preds = %for.inc24.i, %if.then13
+  %nIdx.052.i = phi i32 [ %inc.i, %if.then13 ], [ %nIdx.1.i, %for.inc24.i ]
+  br i1 undef, label %for.inc24.i, label %if.then17.i
+
+if.then17.i:                                      ; preds = %for.body8.i
+  br label %for.inc24.i
+
+for.inc24.i:                                      ; preds = %if.then17.i, %for.body8.i
+  %nIdx.1.i = phi i32 [ undef, %if.then17.i ], [ %nIdx.052.i, %for.body8.i ]
+  br label %for.body8.i
+
+if.else58:                                        ; preds = %for.body
+  %inc.i51 = add nsw i32 %refIdxLX.0, 1
+  br label %for.body
+
+for.end:                                          ; preds = %entry
+  ret void
+}
+
+
+

Added: llvm/trunk/test/Transforms/NewGVN/pr32607.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32607.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32607.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32607.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn %s -S -o - | FileCheck %s
+define hidden void @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  top:
+; CHECK-NEXT:    br label [[IF:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[TMP0:%.*]] = phi double [ [[TMP1:%.*]], [[IF]] ], [ undef, [[TOP:%.*]] ]
+; CHECK-NEXT:    [[TMP1]] = fadd double [[TMP0]], 1.000000e+00
+; CHECK-NEXT:    br i1 false, label [[L50:%.*]], label [[IF]]
+; CHECK:       L50:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    ret void
+;
+top:
+  %.promoted = load double, double* undef, align 8
+  br label %if
+
+;; This is really a multi-valued phi, because the phi is defined by an expression of the phi.
+;; This means that we can't propagate the value over the backedge, because we'll just cycle
+;; through every value.
+
+if:                                               ; preds = %if, %top
+  %0 = phi double [ %1, %if ], [ %.promoted, %top ]
+  %1 = fadd double %0, 1.0
+  br i1 false, label %L50, label %if
+
+L50:                                              ; preds = %if
+  %.lcssa = phi double [ %1, %if ]
+  store double %.lcssa, double* undef, align 8
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/pr32836.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32836.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32836.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32836.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+%struct.anon = type { i32 }
+ at b = external global %struct.anon
+define void @tinkywinky(i1 %patatino) {
+; CHECK-LABEL: @tinkywinky(
+; CHECK-NEXT:    store i32 8, i32* null
+; CHECK-NEXT:    br i1 [[PATATINO:%.*]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br label [[L:%.*]]
+; CHECK:       L:
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* null
+; CHECK-NEXT:    [[BF_LOAD1:%.*]] = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @b, i64 0, i32 0)
+; CHECK-NEXT:    [[BF_VALUE:%.*]] = and i32 [[TMP1]], 536870911
+; CHECK-NEXT:    [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], -536870912
+; CHECK-NEXT:    [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_VALUE]]
+; CHECK-NEXT:    store i32 [[BF_SET]], i32* getelementptr inbounds (%struct.anon, %struct.anon* @b, i64 0, i32 0)
+; CHECK-NEXT:    br label [[LOR_END:%.*]]
+; CHECK:       lor.end:
+; CHECK-NEXT:    br label [[L]]
+;
+  store i32 8, i32* null
+  br i1 %patatino, label %if.end, label %if.then
+if.then:
+  store i32 8, i32* null
+  br label %L
+L:
+  br label %if.end
+if.end:
+  %tmp1 = load i32, i32* null
+  %bf.load1 = load i32, i32* getelementptr (%struct.anon, %struct.anon* @b, i64 0, i32 0)
+  %bf.value = and i32 %tmp1, 536870911
+  %bf.clear = and i32 %bf.load1, -536870912
+  %bf.set = or i32 %bf.clear, %bf.value
+  store i32 %bf.set, i32* getelementptr (%struct.anon, %struct.anon* @b, i64 0, i32 0)
+  br label %lor.end
+lor.end:
+  %bf.load4 = load i32, i32* getelementptr (%struct.anon, %struct.anon* @b, i64 0, i32 0)
+  %tmp4 = and i32 %bf.load4, 536870911
+  %or = or i32 0, %tmp4
+  br label %L
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr32838.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32838.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32838.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32838.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;RUN: opt -newgvn -S < %s | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+;; Ensure we don't infinite loop when all phi arguments are really unreachable or self-defined
+define void @fn1(i64 %arg) {
+; CHECK-LABEL: @fn1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 undef, label [[IF_THEN:%.*]], label [[COND_TRUE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]]
+; CHECK:       firstphiblock:
+; CHECK-NEXT:    br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK:%.*]]
+; CHECK:       secondphiblock:
+; CHECK-NEXT:    [[SECONDPHI:%.*]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ undef, [[FIRSTPHIBLOCK]] ]
+; CHECK-NEXT:    br i1 undef, label [[FIRSTPHIBLOCK]], label [[THIRDPHIBLOCK]]
+; CHECK:       thirdphiblock:
+; CHECK-NEXT:    [[THIRDPHI]] = phi i64 [ [[SECONDPHI]], [[SECONDPHIBLOCK]] ], [ [[DIV:%.*]], [[COND_TRUE]] ]
+; CHECK-NEXT:    br label [[SECONDPHIBLOCK]]
+; CHECK:       for.cond17thread-pre-split:
+; CHECK-NEXT:    br label [[COND_TRUE]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    [[DIV]] = sdiv i64 [[ARG:%.*]], 4
+; CHECK-NEXT:    br label [[THIRDPHIBLOCK]]
+; CHECK:       temp:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 undef, label %if.then, label %cond.true
+if.then:
+  br i1 false, label %firstphiblock, label %temp
+firstphiblock:
+  %firstphi = phi i64 [ %arg, %if.then ], [ undef, %secondphiblock ]
+  br i1 undef, label %for.cond17thread-pre-split, label %secondphiblock
+secondphiblock:
+  %secondphi = phi i64 [ %thirdphi, %thirdphiblock ], [ %firstphi, %firstphiblock ]
+  br i1 undef, label %firstphiblock, label %thirdphiblock
+thirdphiblock:
+  %thirdphi = phi i64 [ %secondphi, %secondphiblock ], [ %div, %cond.true ]
+  br label %secondphiblock
+for.cond17thread-pre-split:
+  br label %cond.true
+cond.true:
+  %fourthphi = phi i64 [ %arg, %entry ], [ %firstphi, %for.cond17thread-pre-split ]
+  %div = sdiv i64 %fourthphi, 4
+  br label %thirdphiblock
+temp:
+  ret void
+}
+define void @fn2(i64 %arg) {
+; CHECK-LABEL: @fn2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 undef, label [[IF_THEN:%.*]], label [[COND_TRUE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]]
+; CHECK:       firstphiblock:
+; CHECK-NEXT:    [[FIRSTPHI:%.*]] = phi i64 [ undef, [[IF_THEN]] ], [ [[SECONDPHI:%.*]], [[SECONDPHIBLOCK:%.*]] ]
+; CHECK-NEXT:    br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK]]
+; CHECK:       secondphiblock:
+; CHECK-NEXT:    [[SECONDPHI]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ [[FIRSTPHI]], [[FIRSTPHIBLOCK]] ]
+; CHECK-NEXT:    br i1 undef, label [[FIRSTPHIBLOCK]], label [[THIRDPHIBLOCK]]
+; CHECK:       thirdphiblock:
+; CHECK-NEXT:    [[THIRDPHI]] = phi i64 [ [[SECONDPHI]], [[SECONDPHIBLOCK]] ], [ [[DIV:%.*]], [[COND_TRUE]] ]
+; CHECK-NEXT:    br label [[SECONDPHIBLOCK]]
+; CHECK:       for.cond17thread-pre-split:
+; CHECK-NEXT:    br label [[COND_TRUE]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    [[FOURTHPHI:%.*]] = phi i64 [ [[ARG:%.*]], [[ENTRY:%.*]] ], [ [[FIRSTPHI]], %for.cond17thread-pre-split ]
+; CHECK-NEXT:    [[DIV]] = sdiv i64 [[FOURTHPHI]], 4
+; CHECK-NEXT:    br label [[THIRDPHIBLOCK]]
+; CHECK:       temp:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 undef, label %if.then, label %cond.true
+if.then:
+  br i1 false, label %firstphiblock, label %temp
+firstphiblock:
+  %firstphi = phi i64 [ %arg, %if.then ], [ %secondphi, %secondphiblock ]
+  br i1 undef, label %for.cond17thread-pre-split, label %secondphiblock
+secondphiblock:
+  %secondphi = phi i64 [ %thirdphi, %thirdphiblock ], [ %firstphi, %firstphiblock ]
+  br i1 undef, label %firstphiblock, label %thirdphiblock
+thirdphiblock:
+  %thirdphi = phi i64 [ %secondphi, %secondphiblock ], [ %div, %cond.true ]
+  br label %secondphiblock
+for.cond17thread-pre-split:
+  br label %cond.true
+cond.true:
+  %fourthphi = phi i64 [ %arg, %entry ], [ %firstphi, %for.cond17thread-pre-split ]
+  %div = sdiv i64 %fourthphi, 4
+  br label %thirdphiblock
+temp:
+  ret void
+}
+ at b = external global i32, align 4
+ at a = external global i32, align 4
+define void @fn3() {
+; CHECK-LABEL: @fn3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[L1:%.*]]
+; CHECK:       l1.loopexit:
+; CHECK-NEXT:    br label [[L1]]
+; CHECK:       l1:
+; CHECK-NEXT:    [[F_0:%.*]] = phi i32* [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ]
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond.loopexit:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]]
+; CHECK:       for.cond1.preheader:
+; CHECK-NEXT:    br label [[FOR_BODY3:%.*]]
+; CHECK:       for.cond1:
+; CHECK-NEXT:    br label [[L2:%.*]]
+; CHECK:       for.body3:
+; CHECK-NEXT:    br i1 undef, label [[FOR_COND1:%.*]], label [[L1_LOOPEXIT]]
+; CHECK:       l2:
+; CHECK-NEXT:    [[G_4:%.*]] = phi i32* [ @b, [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT:    [[F_2:%.*]] = phi i32* [ [[F_0]], [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT:    br label [[FOR_INC:%.*]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    br i1 false, label [[FOR_COND_LOOPEXIT:%.*]], label [[FOR_INC]]
+; CHECK:       for.end14:
+; CHECK-NEXT:    br label [[L2]]
+;
+entry:
+  br label %l1
+l1.loopexit:
+  %g.223.lcssa = phi i32* [ @b, %for.body3 ]
+  br label %l1
+l1:
+  %g.0 = phi i32* [ undef, %entry ], [ %g.223.lcssa, %l1.loopexit ]
+  %f.0 = phi i32* [ @b, %entry ], [ @a, %l1.loopexit ]
+  br label %for.cond
+for.cond.loopexit:
+  br label %for.cond
+for.cond:
+  %g.1 = phi i32* [ %g.0, %l1 ], [ %g.4, %for.cond.loopexit ]
+  %f.1 = phi i32* [ %f.0, %l1 ], [ %f.2, %for.cond.loopexit ]
+  br i1 undef, label %for.end14, label %for.cond1.preheader
+for.cond1.preheader:
+  br label %for.body3
+for.cond1:
+  br label %l2
+for.body3:
+  br i1 undef, label %for.cond1, label %l1.loopexit
+l2:
+  %g.4 = phi i32* [ %g.1, %for.end14 ], [ @a, %for.cond1 ]
+  %f.2 = phi i32* [ %f.1, %for.end14 ], [ @a, %for.cond1 ]
+  br label %for.inc
+for.inc:
+  br i1 false, label %for.cond.loopexit, label %for.inc
+for.end14:
+  br label %l2
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/pr32845.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32845.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32845.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32845.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn %s -S | FileCheck %s
+
+ at b = external global i32, align 4
+ at a = external global i32, align 4
+define void @tinkywinky() {
+; CHECK-LABEL: @tinkywinky(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[L1:%.*]]
+; CHECK:       l1.loopexit:
+; CHECK-NEXT:    br label [[L1]]
+; CHECK:       l1:
+; CHECK-NEXT:    [[F_0:%.*]] = phi i32* [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ]
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond.loopexit:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]]
+; CHECK:       for.cond1.preheader:
+; CHECK-NEXT:    br label [[FOR_BODY3:%.*]]
+; CHECK:       for.cond1:
+; CHECK-NEXT:    br label [[L2:%.*]]
+; CHECK:       for.body3:
+; CHECK-NEXT:    br i1 undef, label [[FOR_COND1:%.*]], label [[L1_LOOPEXIT]]
+; CHECK:       l2:
+; CHECK-NEXT:    [[G_4:%.*]] = phi i32* [ @b, [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT:    [[F_2:%.*]] = phi i32* [ [[F_0]], [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT:    br label [[FOR_INC:%.*]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    br i1 false, label [[FOR_COND_LOOPEXIT:%.*]], label [[FOR_INC]]
+; CHECK:       for.end14:
+; CHECK-NEXT:    br label [[L2]]
+;
+entry:
+  br label %l1
+l1.loopexit:
+  %g.223.lcssa = phi i32* [ @b, %for.body3 ]
+  br label %l1
+l1:
+  %g.0 = phi i32* [ undef, %entry ], [ %g.223.lcssa, %l1.loopexit ]
+  %f.0 = phi i32* [ @b, %entry ], [ @a, %l1.loopexit ]
+  br label %for.cond
+for.cond.loopexit:
+  br label %for.cond
+for.cond:
+  %g.1 = phi i32* [ %g.0, %l1 ], [ %g.4, %for.cond.loopexit ]
+  %f.1 = phi i32* [ %f.0, %l1 ], [ %f.2, %for.cond.loopexit ]
+  br i1 undef, label %for.end14, label %for.cond1.preheader
+for.cond1.preheader:
+  br label %for.body3
+for.cond1:
+  br label %l2
+for.body3:
+  br i1 undef, label %for.cond1, label %l1.loopexit
+l2:
+  %g.4 = phi i32* [ %g.1, %for.end14 ], [ @a, %for.cond1 ]
+  %f.2 = phi i32* [ %f.1, %for.end14 ], [ @a, %for.cond1 ]
+  br label %for.inc
+for.inc:
+  br i1 false, label %for.cond.loopexit, label %for.inc
+for.end14:
+  br label %l2
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr32852.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32852.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32852.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32852.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; Make sure GVN doesn't incorrectly think the branch terminating
+; bb2 has a constant condition.
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+ at a = common global i32 0
+ at patatino = private unnamed_addr constant [3 x i8] c"0\0A\00"
+
+define void @tinkywinky() {
+bb:
+  %tmp = load i32, i32* @a
+  %tmp1 = icmp sge i32 %tmp, 0
+  br i1 %tmp1, label %bb2, label %bb7
+bb2:
+  %tmp4 = icmp sgt i32 %tmp, 0
+; CHECK: br i1 %tmp4, label %bb5, label %bb7
+  br i1 %tmp4, label %bb5, label %bb7
+bb5:
+  %tmp6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @patatino, i32 0, i32 0))
+  br label %bb7
+bb7:
+  ret void
+}
+
+declare i32 @printf(i8*, ...)

Added: llvm/trunk/test/Transforms/NewGVN/pr32897.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32897.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32897.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32897.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+define void @tinkywinky(i64* %b) {
+; CHECK-LABEL: @tinkywinky(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[BODY:%.*]]
+; CHECK:       body:
+; CHECK-NEXT:    store i64 undef, i64* [[B:%.*]]
+; CHECK-NEXT:    br i1 undef, label [[BODY]], label [[END:%.*]]
+; CHECK:       end:
+; CHECK-NEXT:    br label [[BODY]]
+;
+entry:
+  br label %body
+body:
+  %d.1 = phi i64* [ undef, %entry ], [ %d.1, %body ], [ %b, %end ]
+  store i64 undef, i64* %d.1
+  %b2 = load i64, i64* %b
+  %or = or i64 %b2, 0
+  store i64 %or, i64* %b
+  br i1 undef, label %body, label %end
+end:
+  br label %body
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr32934.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32934.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32934.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32934.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+; CHECK: define void @tinkywinky() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %d = alloca i32, align 4
+; CHECK-NEXT:   store i32 0, i32* null, align 4
+; CHECK-NEXT:   br label %for.cond
+; CHECK: for.cond:                                         ; preds = %if.end, %entry
+; CHECK-NEXT:   %0 = load i32, i32* null, align 4
+; CHECK-NEXT:   %cmp = icmp slt i32 %0, 1
+; CHECK-NEXT:   br i1 %cmp, label %for.body, label %while.cond
+; CHECK: for.body:                                         ; preds = %for.cond
+; CHECK-NEXT:   %1 = load i32, i32* @a, align 4
+; CHECK-NEXT:   store i32 %1, i32* %d, align 4
+; CHECK-NEXT:   br label %L
+; CHECK: L:                                                ; preds = %if.then, %for.body
+; CHECK-NEXT:   %tobool = icmp ne i32 %1, 0
+; CHECK-NEXT:   br i1 %tobool, label %if.then, label %if.end
+; CHECK: if.then:                                          ; preds = %L
+; CHECK-NEXT:   call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @patatino, i32 0, i32 0))
+; CHECK-NEXT:   br label %L
+; CHECK: if.end:                                           ; preds = %L
+; CHECK-NEXT:   br label %for.cond
+; CHECK: while.cond:                                       ; preds = %while.body, %for.cond
+; CHECK-NEXT:   br i1 undef, label %while.body, label %while.end
+; CHECK: while.body:                                       ; preds = %while.cond
+; CHECK-NEXT:   call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @patatino, i32 0, i32 0))
+; CHECK-NEXT:   br label %while.cond
+; CHECK: while.end:
+; CHECK-NEXT:   %2 = load i32, i32* @a, align 4
+; CHECK-NEXT:   store i32 %2, i32* undef, align 4
+; CHECK-NEXT:   ret void
+
+ at a = external global i32, align 4
+ at patatino = external unnamed_addr constant [2 x i8], align 1
+define void @tinkywinky() {
+entry:
+  %d = alloca i32, align 4
+  store i32 0, i32* null, align 4
+  br label %for.cond
+for.cond:
+  %0 = load i32, i32* null, align 4
+  %cmp = icmp slt i32 %0, 1
+  br i1 %cmp, label %for.body, label %while.cond
+for.body:
+  %1 = load i32, i32* @a, align 4
+  store i32 %1, i32* %d, align 4
+  br label %L
+L:
+  %2 = load i32, i32* %d, align 4
+  %tobool = icmp ne i32 %2, 0
+  br i1 %tobool, label %if.then, label %if.end
+if.then:
+  call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @patatino, i32 0, i32 0))
+  br label %L
+if.end:
+  br label %for.cond
+while.cond:
+  br i1 undef, label %while.body, label %while.end
+while.body:
+  call void (i8*, ...) @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @patatino, i32 0, i32 0))
+  br label %while.cond
+while.end:
+  %3 = load i32, i32* @a, align 4
+  store i32 %3, i32* undef, align 4
+  ret void
+}
+declare void @printf(i8*, ...) #1

Added: llvm/trunk/test/Transforms/NewGVN/pr32945.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32945.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32945.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32945.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -S -newgvn %s | FileCheck %s
+; CHECK-NOT: call i32 @llvm.ssa.copy
+
+ at d = external global i32
+ at e = external global i32
+define void @tinkywinky() {
+  br i1 true, label %lor.lhs.false, label %cond.true
+lor.lhs.false:
+  %tmp = load i32, i32* @d, align 4
+  %patatino = load i32, i32* null, align 4
+  %or = or i32 %tmp, %patatino
+  store i32 %or, i32* @d, align 4
+  br label %cond.true
+cond.true:
+  %tmp1 = load i32, i32* @e, align 4
+  %tmp2 = load i32, i32* @d, align 4
+  %cmp = icmp eq i32 %tmp1, %tmp2
+  br i1 %cmp, label %cond.true6, label %cond.false
+cond.true6:
+  %cmp7 = icmp slt i32 %tmp1, 0
+  br i1 %cmp7, label %cond.false, label %cond.false
+cond.false:
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr32952.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr32952.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr32952.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr32952.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; PR32952: Don't erroneously consider congruent two phi nodes which
+; have the same arguments but different incoming edges.
+; RUN: opt -newgvn -S %s | FileCheck %s
+
+ at a = common global i16 0, align 2
+ at .str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+
+define i32 @tinkywinky() {
+entry:
+  %0 = load i16, i16* @a, align 2
+  %conv = sext i16 %0 to i32
+  %neg = xor i32 %conv, -1
+  %conv1 = trunc i32 %neg to i16
+  %conv3 = zext i16 %conv1 to i32
+  %cmp = icmp slt i32 %conv, %conv3
+  br i1 %cmp, label %tinky, label %winky
+
+tinky:
+  store i16 2, i16* @a, align 2
+  br label %patatino
+
+winky:
+  br label %patatino
+
+patatino:
+; CHECK: %meh = phi i16 [ %0, %winky ], [ %conv1, %tinky ]
+; CHECK: %banana = phi i16 [ %0, %tinky ], [ %conv1, %winky ]
+  %meh = phi i16 [ %0, %winky ], [ %conv1, %tinky ]
+  %banana = phi i16 [ %0, %tinky ], [ %conv1, %winky ]
+  br label %end
+
+end:
+; CHECK: %promoted = zext i16 %banana to i32
+; CHECK: %other = zext i16 %meh to i32
+  %promoted = zext i16 %banana to i32
+  %other = zext i16 %meh to i32
+  %first = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %promoted)
+  %second = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %other)
+  ret i32 0
+}
+
+declare i32 @printf(i8*, ...)

Added: llvm/trunk/test/Transforms/NewGVN/pr33014.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33014.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33014.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33014.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; Make sure we don't end up in an infinite recursion in singleReachablePHIPath().
+; REQUIRES: asserts
+; RUN: opt -newgvn -S %s | FileCheck %s
+
+ at c = external global i64, align 8
+
+; CHECK-LABEL: define void @tinkywinky() {
+; CHECK: entry:
+; CHECK-NEXT:   br i1 undef, label %l2, label %if.then
+; CHECK: if.then:                                          ; preds = %entry
+; CHECK-NEXT:   br label %for.body
+; CHECK: ph:                                               ; preds = %back, %ontrue
+; CHECK-NEXT:   br label %for.body
+; CHECK: for.body:                                         ; preds = %ph, %if.then
+; CHECK-NEXT:   br i1 undef, label %ontrue, label %onfalse
+; CHECK: onfalse:                                          ; preds = %for.body
+; CHECK-NEXT:   %patatino = load i64, i64* @c
+; CHECK-NEXT:   ret void
+; CHECK: ontrue:                                           ; preds = %for.body
+; CHECK-NEXT:   %dipsy = load i64, i64* @c
+; CHECK-NEXT:   br label %ph
+; CHECK: back:                                             ; preds = %l2
+; CHECK-NEXT:   store i8 undef, i8* null
+; CHECK-NEXT:   br label %ph
+; CHECK: end:                                              ; preds = %l2
+; CHECK-NEXT:   ret void
+; CHECK: l2:                                               ; preds = %entry
+; CHECK-NEXT:   br i1 false, label %back, label %end
+; CHECK-NEXT: }
+
+define void @tinkywinky() {
+entry:
+  br i1 undef, label %l2, label %if.then
+if.then:
+  br label %for.body
+ph:
+  br label %for.body
+for.body:
+  br i1 undef, label %ontrue, label %onfalse
+onfalse:
+  %patatino = load i64, i64* @c
+  store i64 %patatino, i64* @c
+  ret void
+ontrue:
+  %dipsy = load i64, i64* @c
+  store i64 %dipsy, i64* @c
+  br label %ph
+back:
+  br label %ph
+end:
+  ret void
+l2:
+  br i1 false, label %back, label %end
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr33086.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33086.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33086.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33086.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -newgvn -S %s | FileCheck %s
+; REQUIRES: asserts
+
+; CHECK-LABEL: define void @tinkywinky() {
+; CHECK: entry:
+; CHECK-NEXT:   br i1 undef, label %for.cond18, label %for.cond.preheader
+; CHECK: for.cond.preheader:
+; CHECK-NEXT:   br label %for.cond2thread-pre-split
+; CHECK: for.cond2thread-pre-split:
+; CHECK-NEXT:   %conv24 = phi i32 [ 0, %for.cond.preheader ], [ %conv, %for.inc.split ]
+; CHECK-NEXT:   br label %for.inc.split
+; CHECK: for.inc.split:
+; CHECK-NEXT:   %add = shl nsw i32 %conv24, 16
+; CHECK-NEXT:   %sext23 = add i32 %add, 65536
+; CHECK-NEXT:   %conv = ashr exact i32 %sext23, 16
+; CHECK-NEXT:   %cmp = icmp slt i32 %sext23, 3604480
+; CHECK-NEXT:   br i1 %cmp, label %for.cond2thread-pre-split, label %l1.loopexit
+; CHECK: l1.loopexit:
+; CHECK-NEXT:   br label %l1
+; CHECK: l1:
+; CHECK-NEXT:   %0 = load i16, i16* null, align 2
+; CHECK-NEXT:   %g.0.g.0..pr = load i16, i16* null, align 2
+; CHECK-NEXT:   ret void
+; CHECK: for.cond18:
+; CHECK-NEXT:   br label %l1
+; CHECK-NEXT: }
+
+define void @tinkywinky() {
+entry:
+  br i1 undef, label %for.cond18, label %for.cond.preheader
+
+for.cond.preheader:
+  br label %for.cond2thread-pre-split
+
+for.cond2thread-pre-split:
+  %conv24 = phi i32 [ 0, %for.cond.preheader ], [ %conv, %for.inc.split ]
+  br label %for.inc.split
+
+for.inc.split:
+  %add = shl nsw i32 %conv24, 16
+  %sext23 = add i32 %add, 65536
+  %conv = ashr exact i32 %sext23, 16
+  %cmp = icmp slt i32 %sext23, 3604480
+  br i1 %cmp, label %for.cond2thread-pre-split, label %l1.loopexit
+
+l1.loopexit:
+  br label %l1
+
+l1:
+  %h.0 = phi i16* [ undef, %for.cond18 ], [ null, %l1.loopexit ]
+  %0 = load i16, i16* %h.0, align 2
+  store i16 %0, i16* null, align 2
+  %g.0.g.0..pr = load i16, i16* null, align 2
+  %tobool15 = icmp eq i16 %g.0.g.0..pr, 0
+  ret void
+
+for.cond18:
+  br label %l1
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr33116.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33116.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33116.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33116.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+ at a = external global i32
+
+define void @b() {
+; CHECK-LABEL: @b(
+; CHECK-NEXT:    br i1 false, label [[C:%.*]], label [[WHILE_D:%.*]]
+; CHECK:       while.d:
+; CHECK-NEXT:    br label [[F:%.*]]
+; CHECK:       f:
+; CHECK-NEXT:    br i1 undef, label [[IF_E:%.*]], label [[C]]
+; CHECK:       c:
+; CHECK-NEXT:    br i1 undef, label [[IF_G:%.*]], label [[IF_E]]
+; CHECK:       if.g:
+; CHECK-NEXT:    store i32 undef, i32* @a
+; CHECK-NEXT:    br label [[WHILE_D]]
+; CHECK:       if.e:
+; CHECK-NEXT:    br label [[F]]
+;
+  br i1 false, label %c, label %while.d
+
+while.d:                                          ; preds = %if.g, %0
+  br label %f
+
+f:                                                ; preds = %if.e, %while.d
+  br i1 undef, label %if.e, label %c
+
+c:                                                ; preds = %f, %0
+  br i1 undef, label %if.g, label %if.e
+
+if.g:                                             ; preds = %c
+  store i32 undef, i32* @a
+  br label %while.d
+
+if.e:                                             ; preds = %c, %f
+  br label %f
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/pr33185.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33185.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33185.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33185.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,120 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+
+ at a = local_unnamed_addr global i32 9, align 4
+ at .str4 = private unnamed_addr constant [6 x i8] c"D:%d\0A\00", align 1
+
+define i32 @test1() local_unnamed_addr {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[CMP1_I:%.*]] = icmp ne i32 [[TMP]], 0
+; CHECK-NEXT:    br label [[FOR_BODY_I:%.*]]
+; CHECK:       for.body.i:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[COND_END_I:%.*]] ]
+; CHECK-NEXT:    [[F_08_I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[COND_END_I]] ]
+; CHECK-NEXT:    [[MUL_I:%.*]] = select i1 [[CMP1_I]], i32 [[F_08_I]], i32 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[COND_END_I]], label [[COND_TRUE_I:%.*]]
+; CHECK:       cond.true.i:
+; CHECK-NEXT:    [[DIV_I:%.*]] = udiv i32 [[MUL_I]], [[F_08_I]]
+; CHECK-NEXT:    br label [[COND_END_I]]
+; CHECK:       cond.end.i:
+; CHECK-NEXT:    [[COND_I:%.*]] = phi i32 [ [[DIV_I]], [[COND_TRUE_I]] ], [ 0, [[FOR_BODY_I]] ]
+; CHECK-NEXT:    [[INC_I]] = add nuw nsw i32 [[F_08_I]], 1
+; CHECK-NEXT:    [[EXITCOND_I:%.*]] = icmp eq i32 [[INC_I]], 4
+; CHECK-NEXT:    br i1 [[EXITCOND_I]], label [[FN1_EXIT:%.*]], label [[FOR_BODY_I]]
+; CHECK:       fn1.exit:
+; CHECK-NEXT:    [[CALL4:%.*]] = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), i32 [[COND_I]])
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %tmp = load i32, i32* @a, align 4
+  %cmp1.i = icmp ne i32 %tmp, 0
+  br label %for.body.i
+
+for.body.i:
+  %tmp1 = phi i1 [ true, %entry ], [ false, %cond.end.i ]
+  %f.08.i = phi i32 [ 0, %entry ], [ %inc.i, %cond.end.i ]
+  %mul.i = select i1 %cmp1.i, i32 %f.08.i, i32 0
+  br i1 %tmp1, label %cond.end.i, label %cond.true.i
+
+cond.true.i:
+  ;; Ensure we don't replace this divide with a phi of ops that merges the wrong loop iteration value
+  %div.i = udiv i32 %mul.i, %f.08.i
+  br label %cond.end.i
+
+cond.end.i:
+  %cond.i = phi i32 [ %div.i, %cond.true.i ], [ 0, %for.body.i ]
+  %inc.i = add nuw nsw i32 %f.08.i, 1
+  %exitcond.i = icmp eq i32 %inc.i, 4
+  br i1 %exitcond.i, label %fn1.exit, label %for.body.i
+
+fn1.exit:
+  %cond.i.lcssa = phi i32 [ %cond.i, %cond.end.i ]
+  %call4= tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), i32 %cond.i.lcssa)
+  ret i32 0
+}
+
+declare i32 @printf(i8* nocapture readonly, ...)
+
+;; Variant of the above where we have made the udiv available in each predecessor with the wrong values.
+;; In the entry block, it is always 0, so we don't try to create a leader there, only in %cond.end.i.
+;; We should not create a phi of ops for it using these leaders.
+;; A correct phi of ops for this udiv would be phi(0, 1), which we are not smart enough to figure out.
+;; If we reuse the incorrect leaders, we will get phi(0, 0).
+define i32 @test2() local_unnamed_addr {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[CMP1_I:%.*]] = icmp ne i32 [[TMP]], 0
+; CHECK-NEXT:    br label [[FOR_BODY_I:%.*]]
+; CHECK:       for.body.i:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[COND_END_I:%.*]] ]
+; CHECK-NEXT:    [[F_08_I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[COND_END_I]] ]
+; CHECK-NEXT:    [[MUL_I:%.*]] = select i1 [[CMP1_I]], i32 [[F_08_I]], i32 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[COND_END_I]], label [[COND_TRUE_I:%.*]]
+; CHECK:       cond.true.i:
+; CHECK-NEXT:    [[DIV_I:%.*]] = udiv i32 [[MUL_I]], [[F_08_I]]
+; CHECK-NEXT:    br label [[COND_END_I]]
+; CHECK:       cond.end.i:
+; CHECK-NEXT:    [[COND_I:%.*]] = phi i32 [ [[DIV_I]], [[COND_TRUE_I]] ], [ 0, [[FOR_BODY_I]] ]
+; CHECK-NEXT:    [[INC_I]] = add nuw nsw i32 [[F_08_I]], 1
+; CHECK-NEXT:    [[TEST:%.*]] = udiv i32 [[MUL_I]], [[INC_I]]
+; CHECK-NEXT:    [[CALL5:%.*]] = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), i32 [[TEST]])
+; CHECK-NEXT:    [[EXITCOND_I:%.*]] = icmp eq i32 [[INC_I]], 4
+; CHECK-NEXT:    br i1 [[EXITCOND_I]], label [[FN1_EXIT:%.*]], label [[FOR_BODY_I]]
+; CHECK:       fn1.exit:
+; CHECK-NEXT:    [[CALL4:%.*]] = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), i32 [[COND_I]])
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %tmp = load i32, i32* @a, align 4
+  %cmp1.i = icmp ne i32 %tmp, 0
+  br label %for.body.i
+
+for.body.i:
+  %tmp1 = phi i1 [ true, %entry ], [ false, %cond.end.i ]
+  %f.08.i = phi i32 [ 0, %entry ], [ %inc.i, %cond.end.i ]
+  %mul.i = select i1 %cmp1.i, i32 %f.08.i, i32 0
+  br i1 %tmp1, label %cond.end.i, label %cond.true.i
+
+cond.true.i:
+  ;; Ensure we don't replace this divide with a phi of ops that merges the wrong loop iteration value
+  %div.i = udiv i32 %mul.i, %f.08.i
+  br label %cond.end.i
+
+cond.end.i:
+  %cond.i = phi i32 [ %div.i, %cond.true.i ], [ 0, %for.body.i ]
+  %inc.i = add nuw nsw i32 %f.08.i, 1
+  %test = udiv i32 %mul.i, %inc.i
+  %call5= tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), i32 %test)
+  %exitcond.i = icmp eq i32 %inc.i, 4
+  br i1 %exitcond.i, label %fn1.exit, label %for.body.i
+
+fn1.exit:
+  %cond.i.lcssa = phi i32 [ %cond.i, %cond.end.i ]
+  %call4= tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), i32 %cond.i.lcssa)
+  ret i32 0
+}
+
+

Added: llvm/trunk/test/Transforms/NewGVN/pr33187.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33187.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33187.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33187.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,148 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;; Ensure we don't change after value numbering by accidentally deleting the wrong expression.
+; RUN: opt -newgvn -S %s | FileCheck %s
+define void @fn1() local_unnamed_addr #0 {
+; CHECK-LABEL: @fn1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND_PREHEADER:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    br label [[FOR_COND_PREHEADER]]
+; CHECK:       for.cond.preheader:
+; CHECK-NEXT:    [[H_031:%.*]] = phi i32 [ 5, [[ENTRY:%.*]] ], [ [[H_127:%.*]], [[WHILE_COND:%.*]] ]
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[H_128:%.*]] = phi i32 [ [[H_031]], [[FOR_COND_PREHEADER]] ], [ [[H_2:%.*]], [[FOR_INC:%.*]] ]
+; CHECK-NEXT:    br label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br i1 false, label [[L_LOOPEXIT:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    br i1 undef, label [[FOR_INC]], label [[IF_END9:%.*]]
+; CHECK:       if.end9:
+; CHECK-NEXT:    br label [[FOR_INC]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[H_2]] = phi i32 [ [[H_128]], [[IF_END]] ], [ 0, [[IF_END9]] ]
+; CHECK-NEXT:    br i1 undef, label [[WHILE_COND10_LOOPEXIT:%.*]], label [[FOR_BODY]]
+; CHECK:       while.cond10.loopexit:
+; CHECK-NEXT:    br label [[WHILE_COND10:%.*]]
+; CHECK:       while.cond10:
+; CHECK-NEXT:    [[H_127]] = phi i32 [ [[H_126:%.*]], [[IF_END18:%.*]] ], [ [[H_125:%.*]], [[L:%.*]] ], [ [[H_2]], [[WHILE_COND10_LOOPEXIT]] ]
+; CHECK-NEXT:    br i1 undef, label [[WHILE_COND]], label [[WHILE_BODY12:%.*]]
+; CHECK:       while.body12:
+; CHECK-NEXT:    br i1 undef, label [[IF_END18]], label [[L]]
+; CHECK:       L.loopexit:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    br label [[L]]
+; CHECK:       L:
+; CHECK-NEXT:    [[H_125]] = phi i32 [ [[H_127]], [[WHILE_BODY12]] ], [ undef, [[L_LOOPEXIT]] ]
+; CHECK-NEXT:    br i1 undef, label [[WHILE_COND10]], label [[IF_END18]]
+; CHECK:       if.end18:
+; CHECK-NEXT:    [[H_126]] = phi i32 [ [[H_125]], [[L]] ], [ [[H_127]], [[WHILE_BODY12]] ]
+; CHECK-NEXT:    br label [[WHILE_COND10]]
+;
+entry:
+  br label %for.cond.preheader
+
+while.cond:                                       ; preds = %while.cond10
+  br label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %while.cond, %entry
+  %h.031 = phi i32 [ 5, %entry ], [ %h.127, %while.cond ]
+  br label %for.body
+
+for.body:                                         ; preds = %for.inc, %for.cond.preheader
+  %h.128 = phi i32 [ %h.031, %for.cond.preheader ], [ %h.2, %for.inc ]
+  br label %if.then
+
+if.then:                                          ; preds = %for.body
+  br i1 false, label %L.loopexit, label %if.end
+
+if.end:                                           ; preds = %if.then
+  br i1 undef, label %for.inc, label %if.end9
+
+if.end9:                                          ; preds = %if.end
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end9, %if.end
+  %h.2 = phi i32 [ %h.128, %if.end ], [ 0, %if.end9 ]
+  br i1 undef, label %while.cond10.loopexit, label %for.body
+
+while.cond10.loopexit:                            ; preds = %for.inc
+  %h.2.lcssa = phi i32 [ %h.2, %for.inc ]
+  br label %while.cond10
+
+while.cond10:                                     ; preds = %if.end18, %L, %while.cond10.loopexit
+  %h.127 = phi i32 [ %h.126, %if.end18 ], [ %h.125, %L ], [ %h.2.lcssa, %while.cond10.loopexit ]
+  br i1 undef, label %while.cond, label %while.body12
+
+while.body12:                                     ; preds = %while.cond10
+  br i1 undef, label %if.end18, label %L
+
+L.loopexit:                                       ; preds = %if.then
+  br label %L
+
+L:                                                ; preds = %L.loopexit, %while.body12
+  %h.125 = phi i32 [ %h.127, %while.body12 ], [ undef, %L.loopexit ]
+  br i1 undef, label %while.cond10, label %if.end18
+
+if.end18:                                         ; preds = %L, %while.body12
+  %h.126 = phi i32 [ %h.125, %L ], [ %h.127, %while.body12 ]
+  br label %while.cond10
+}
+
+
+define void @hoge() local_unnamed_addr #0 {
+; CHECK-LABEL: @hoge(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i64 [ 0, [[BB:%.*]] ], [ [[TMP2:%.*]], [[BB1]] ]
+; CHECK-NEXT:    [[TMP2]] = add nuw nsw i64 [[TMP]], 1
+; CHECK-NEXT:    br label [[BB1]]
+;
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb1, %bb
+  %tmp = phi i64 [ 0, %bb ], [ %tmp2, %bb1 ]
+  %tmp2 = add nuw nsw i64 %tmp, 1
+  br label %bb1
+}
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "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"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+
+source_filename = "pr33187-c.ll"
+
+define void @a() {
+; CHECK-LABEL: @a(
+; CHECK-NEXT:  b:
+; CHECK-NEXT:    store i8* null, i8** null
+; CHECK-NEXT:    br label [[D:%.*]]
+; CHECK:       d:
+; CHECK-NEXT:    [[I:%.*]] = phi i8* [ null, [[B:%.*]] ], [ [[E:%.*]], [[F:%.*]] ]
+; CHECK-NEXT:    br i1 undef, label [[F]], label [[G:%.*]]
+; CHECK:       g:
+; CHECK-NEXT:    store i8* [[I]], i8** null
+; CHECK-NEXT:    unreachable
+; CHECK:       f:
+; CHECK-NEXT:    [[E]] = getelementptr i8, i8* [[I]], i64 1
+; CHECK-NEXT:    br label [[D]]
+;
+b:
+  store i8* null, i8** null
+  br label %d
+
+d:                                                ; preds = %f, %b
+  %i = phi i8* [ null, %b ], [ %e, %f ]
+  br i1 undef, label %f, label %g
+
+g:                                                ; preds = %d
+  %h = phi i8* [ %i, %d ]
+  store i8* %h, i8** null
+  unreachable
+
+f:                                                ; preds = %d
+  %e = getelementptr i8, i8* %i, i64 1
+  br label %d
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/pr33196.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33196.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33196.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33196.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,72 @@
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+; CHECK: define i32 @main() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %tmp = load i32, i32* @d, align 4
+; CHECK-NEXT:   %tmp1 = load i32, i32* @c, align 4
+; CHECK-NEXT:   %tobool = icmp eq i32 %tmp1, -1
+; CHECK-NEXT:   br i1 %tobool, label %if.end, label %if.then
+; CHECK: if.then:
+; CHECK-NEXT:   br label %L
+; CHECK: L:
+; CHECK-NEXT:   %e.0 = phi i32 [ 0, %if.then ], [ %e.1, %if.then4 ]
+; CHECK-NEXT:   br label %if.end
+; CHECK: if.end:
+; CHECK-NEXT:   %e.1 = phi i32 [ %e.0, %L ], [ %tmp, %entry ]
+; CHECK-NEXT:   store i32 %e.1, i32* @a, align 4
+; CHECK-NEXT:   %tmp2 = load i32, i32* @b, align 4
+; CHECK-NEXT:   store i32 0, i32* @b, align 4
+; CHECK-NEXT:   %sext = shl i32 %tmp2, 16
+; CHECK-NEXT:   %conv1 = ashr exact i32 %sext, 16
+; CHECK-NEXT:   %add = add nsw i32 %conv1, %tmp1
+; CHECK-NEXT:   %add2 = add nsw i32 %add, %e.1
+; CHECK-NEXT:   store i32 %add2, i32* @a, align 4
+; CHECK-NEXT:   %tobool3 = icmp eq i32 %add2, 0
+; CHECK-NEXT:   br i1 %tobool3, label %if.end5, label %if.then4
+; CHECK: if.then4:
+; CHECK-NEXT:   br label %L
+; CHECK: if.end5:
+; CHECK-NEXT:   ret i32 0
+; CHECK-NEXT: }
+
+ at d = global i32 1, align 4
+ at c = common global i32 0, align 4
+ at a = common global i32 0, align 4
+ at b = common global i32 0, align 4
+
+define i32 @main() {
+entry:
+  %tmp = load i32, i32* @d, align 4
+  %tmp1 = load i32, i32* @c, align 4
+  %tobool = icmp eq i32 %tmp1, -1
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  br label %L
+
+L:                                                ; preds = %if.then4, %if.then
+  %e.0 = phi i32 [ 0, %if.then ], [ %e.1, %if.then4 ]
+  br label %if.end
+
+if.end:                                           ; preds = %L, %entry
+  %e.1 = phi i32 [ %e.0, %L ], [ %tmp, %entry ]
+  store i32 %e.1, i32* @a, align 4
+  %tmp2 = load i32, i32* @b, align 4
+  store i32 0, i32* @b, align 4
+  %sext = shl i32 %tmp2, 16
+  %conv1 = ashr exact i32 %sext, 16
+  %tmp3 = load i32, i32* @c, align 4
+  %add = add nsw i32 %conv1, %tmp3
+  %tmp4 = load i32, i32* @a, align 4
+  %and = and i32 %tmp4, %e.1
+  %add2 = add nsw i32 %add, %and
+  store i32 %add2, i32* @a, align 4
+  %tobool3 = icmp eq i32 %add2, 0
+  br i1 %tobool3, label %if.end5, label %if.then4
+
+if.then4:                                         ; preds = %if.end
+  br label %L
+
+if.end5:                                          ; preds = %if.end
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr33204.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33204.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33204.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33204.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+; Ensure that loads that bypass memory def-use chains get added as users of the new
+; MemoryDef.  Otherwise this test will not pass memory verification because the value
+; of the load will not be reprocessed until verification.
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+source_filename = "bugpoint-output-f242c4f.bc"
+target triple = "x86_64-apple-darwin16.7.0"
+
+ at global = external global i32 #0
+ at global.1 = external global i32 #0
+
+define void @hoge(i32 %arg) {
+; CHECK-LABEL: @hoge(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[ARG:%.*]], [[BB:%.*]] ]
+; CHECK-NEXT:    br label [[BB6:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* @global, !h !0
+; CHECK-NEXT:    unreachable
+; CHECK:       bb6:
+; CHECK-NEXT:    store i32 [[TMP]], i32* @global.1, !h !0
+; CHECK-NEXT:    br i1 undef, label [[BB7:%.*]], label [[BB1]]
+; CHECK:       bb7:
+; CHECK-NEXT:    br i1 undef, label [[BB10:%.*]], label [[BB8:%.*]]
+; CHECK:       bb8:
+; CHECK-NEXT:    br i1 false, label [[BB9:%.*]], label [[BB3:%.*]]
+; CHECK:       bb9:
+; CHECK-NEXT:    store i8 undef, i8* null
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb10:
+; CHECK-NEXT:    store i32 0, i32* @global, !h !0
+; CHECK-NEXT:    br label [[BB7]]
+;
+bb:
+  br label %bb2
+
+bb1:                                              ; preds = %bb6
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb
+  %tmp = phi i32 [ 0, %bb1 ], [ %arg, %bb ]
+  br label %bb6
+
+bb3:                                              ; preds = %bb9, %bb8
+  %tmp4 = load i32, i32* @global, !h !0
+  %tmp5 = icmp eq i32 %tmp4, 0
+  unreachable
+
+bb6:                                              ; preds = %bb2
+  store i32 %tmp, i32* @global.1, !h !0
+  br i1 undef, label %bb7, label %bb1
+
+bb7:                                              ; preds = %bb10, %bb6
+  br i1 undef, label %bb10, label %bb8
+
+bb8:                                              ; preds = %bb7
+  br i1 false, label %bb9, label %bb3
+
+bb9:                                              ; preds = %bb8
+  call void @widget()
+  br label %bb3
+
+bb10:                                             ; preds = %bb7
+  store i32 0, i32* @global, !h !0
+  br label %bb7
+}
+
+declare void @widget()
+
+attributes #0 = { align=4 }
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/NewGVN/pr33305.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33305.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33305.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33305.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,185 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+; Ensure we do not incorrect do phi of ops
+source_filename = "/Users/dannyb/sources/llvm-clean/debug-build/pr33305.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+ at a = common global i32 0, align 4
+ at b = local_unnamed_addr global i32* @a, align 8
+ at e = local_unnamed_addr global i32 -1, align 4
+ at g = local_unnamed_addr global i32 1, align 4
+ at c = common local_unnamed_addr global i32 0, align 4
+ at f = common local_unnamed_addr global i32 0, align 4
+ at h = common local_unnamed_addr global i32 0, align 4
+ at str = private unnamed_addr constant [5 x i8] c"fine\00"
+ at str.2 = private unnamed_addr constant [8 x i8] c"Screwed\00"
+
+; Function Attrs: nounwind optsize ssp uwtable
+define i32 @main() local_unnamed_addr #0 {
+; CHECK-LABEL: @main(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DOTPR_I:%.*]] = load i32, i32* @c, align 4, !tbaa !3
+; CHECK-NEXT:    [[CMP13_I:%.*]] = icmp slt i32 [[DOTPR_I]], 1
+; CHECK-NEXT:    br i1 [[CMP13_I]], label [[FOR_COND1_PREHEADER_LR_PH_I:%.*]], label [[ENTRY_FOR_END9_I_CRIT_EDGE:%.*]]
+; CHECK:       entry.for.end9.i_crit_edge:
+; CHECK-NEXT:    [[DOTPRE:%.*]] = load i32, i32* @h, align 4, !tbaa !3
+; CHECK-NEXT:    br label [[FOR_END9_I:%.*]]
+; CHECK:       for.cond1.preheader.lr.ph.i:
+; CHECK-NEXT:    [[G_PROMOTED14_I:%.*]] = load i32, i32* @g, align 4, !tbaa !3
+; CHECK-NEXT:    br label [[FOR_COND1_PREHEADER_I:%.*]]
+; CHECK:       for.cond1.preheader.i:
+; CHECK-NEXT:    [[INC816_I:%.*]] = phi i32 [ [[DOTPR_I]], [[FOR_COND1_PREHEADER_LR_PH_I]] ], [ [[INC8_I:%.*]], [[FOR_INC7_I:%.*]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ [[G_PROMOTED14_I]], [[FOR_COND1_PREHEADER_LR_PH_I]] ], [ 0, [[FOR_INC7_I]] ]
+; CHECK-NEXT:    br label [[FOR_BODY3_I:%.*]]
+; CHECK:       for.body3.i:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ false, [[FOR_COND1_PREHEADER_I]] ], [ true, [[LOR_END_I:%.*]] ]
+; CHECK-NEXT:    [[INC12_I:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_I]] ], [ [[INC_I:%.*]], [[LOR_END_I]] ]
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[TMP0]], [[FOR_COND1_PREHEADER_I]] ], [ 0, [[LOR_END_I]] ]
+; CHECK-NEXT:    [[TOBOOL_I:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[OR_COND_I:%.*]] = and i1 [[TMP1]], [[TOBOOL_I]]
+; CHECK-NEXT:    br i1 [[OR_COND_I]], label [[LOR_END_I]], label [[LOR_RHS_I:%.*]]
+; CHECK:       lor.rhs.i:
+; CHECK-NEXT:    [[LNOT_I:%.*]] = xor i1 [[TOBOOL_I]], true
+; CHECK-NEXT:    [[LNOT_EXT_I:%.*]] = zext i1 [[LNOT_I]] to i32
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* @e, align 4, !tbaa !3
+; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[TMP3]], [[LNOT_EXT_I]]
+; CHECK-NEXT:    store i32 [[XOR_I]], i32* @e, align 4, !tbaa !3
+; CHECK-NEXT:    br label [[LOR_END_I]]
+; CHECK:       lor.end.i:
+; CHECK-NEXT:    [[INC_I]] = add nuw nsw i32 [[INC12_I]], 1
+; CHECK-NEXT:    [[EXITCOND_I:%.*]] = icmp eq i32 [[INC_I]], 2
+; CHECK-NEXT:    br i1 [[EXITCOND_I]], label [[FOR_INC7_I]], label [[FOR_BODY3_I]]
+; CHECK:       for.inc7.i:
+; CHECK-NEXT:    [[INC8_I]] = add nsw i32 [[INC816_I]], 1
+; CHECK-NEXT:    [[CMP_I:%.*]] = icmp slt i32 [[INC816_I]], 0
+; CHECK-NEXT:    br i1 [[CMP_I]], label [[FOR_COND1_PREHEADER_I]], label [[FOR_COND_FOR_END9_CRIT_EDGE_I:%.*]]
+; CHECK:       for.cond.for.end9_crit_edge.i:
+; CHECK-NEXT:    store i32 0, i32* @g, align 4, !tbaa !3
+; CHECK-NEXT:    store i32 2, i32* @h, align 4, !tbaa !3
+; CHECK-NEXT:    store i32 [[INC8_I]], i32* @c, align 4, !tbaa !3
+; CHECK-NEXT:    br label [[FOR_END9_I]]
+; CHECK:       for.end9.i:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[DOTPRE]], [[ENTRY_FOR_END9_I_CRIT_EDGE]] ], [ 2, [[FOR_COND_FOR_END9_CRIT_EDGE_I]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = load i32*, i32** @b, align 8, !tbaa !7
+; CHECK-NEXT:    store i32 [[TMP4]], i32* [[TMP5]], align 4, !tbaa !3
+; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* @e, align 4, !tbaa !3
+; CHECK-NEXT:    [[CMP10_I:%.*]] = icmp slt i32 [[TMP6]], -1
+; CHECK-NEXT:    br i1 [[CMP10_I]], label [[IF_THEN_I:%.*]], label [[FN1_EXIT:%.*]]
+; CHECK:       if.then.i:
+; CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* @f, align 4, !tbaa !3
+; CHECK-NEXT:    store i32 [[TMP7]], i32* [[TMP5]], align 4, !tbaa !3
+; CHECK-NEXT:    br label [[FN1_EXIT]]
+; CHECK:       fn1.exit:
+; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* @a, align 4, !tbaa !3
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP8]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[PUTS2:%.*]] = tail call i32 @puts(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str.2, i64 0, i64 0))
+; CHECK-NEXT:    tail call void @abort()
+; CHECK-NEXT:    unreachable
+; CHECK:       if.end:
+; CHECK-NEXT:    [[PUTS:%.*]] = tail call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i64 0, i64 0))
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %.pr.i = load i32, i32* @c, align 4, !tbaa !3
+  %cmp13.i = icmp slt i32 %.pr.i, 1
+  br i1 %cmp13.i, label %for.cond1.preheader.lr.ph.i, label %entry.for.end9.i_crit_edge
+
+entry.for.end9.i_crit_edge:                       ; preds = %entry
+  %.pre = load i32, i32* @h, align 4, !tbaa !3
+  br label %for.end9.i
+
+for.cond1.preheader.lr.ph.i:                      ; preds = %entry
+  %g.promoted14.i = load i32, i32* @g, align 4, !tbaa !3
+  br label %for.cond1.preheader.i
+
+for.cond1.preheader.i:                            ; preds = %for.inc7.i, %for.cond1.preheader.lr.ph.i
+  %inc816.i = phi i32 [ %.pr.i, %for.cond1.preheader.lr.ph.i ], [ %inc8.i, %for.inc7.i ]
+  %0 = phi i32 [ %g.promoted14.i, %for.cond1.preheader.lr.ph.i ], [ 0, %for.inc7.i ]
+  br label %for.body3.i
+
+for.body3.i:                                      ; preds = %lor.end.i, %for.cond1.preheader.i
+  %1 = phi i1 [ false, %for.cond1.preheader.i ], [ true, %lor.end.i ]
+  %inc12.i = phi i32 [ 0, %for.cond1.preheader.i ], [ %inc.i, %lor.end.i ]
+  %2 = phi i32 [ %0, %for.cond1.preheader.i ], [ 0, %lor.end.i ]
+  %tobool.i = icmp ne i32 %2, 0
+  %or.cond.i = and i1 %1, %tobool.i
+  br i1 %or.cond.i, label %lor.end.i, label %lor.rhs.i
+
+lor.rhs.i:                                        ; preds = %for.body3.i
+  %lnot.i = xor i1 %tobool.i, true
+  %lnot.ext.i = zext i1 %lnot.i to i32
+  %3 = load i32, i32* @e, align 4, !tbaa !3
+  %xor.i = xor i32 %3, %lnot.ext.i
+  store i32 %xor.i, i32* @e, align 4, !tbaa !3
+  br label %lor.end.i
+
+lor.end.i:                                        ; preds = %lor.rhs.i, %for.body3.i
+  %inc.i = add nuw nsw i32 %inc12.i, 1
+  %exitcond.i = icmp eq i32 %inc.i, 2
+  br i1 %exitcond.i, label %for.inc7.i, label %for.body3.i
+
+for.inc7.i:                                       ; preds = %lor.end.i
+  %inc8.i = add nsw i32 %inc816.i, 1
+  %cmp.i = icmp slt i32 %inc816.i, 0
+  br i1 %cmp.i, label %for.cond1.preheader.i, label %for.cond.for.end9_crit_edge.i
+
+for.cond.for.end9_crit_edge.i:                    ; preds = %for.inc7.i
+  store i32 0, i32* @g, align 4, !tbaa !3
+  store i32 2, i32* @h, align 4, !tbaa !3
+  store i32 %inc8.i, i32* @c, align 4, !tbaa !3
+  br label %for.end9.i
+
+for.end9.i:                                       ; preds = %entry.for.end9.i_crit_edge, %for.cond.for.end9_crit_edge.i
+  %4 = phi i32 [ %.pre, %entry.for.end9.i_crit_edge ], [ 2, %for.cond.for.end9_crit_edge.i ]
+  %5 = load i32*, i32** @b, align 8, !tbaa !7
+  store i32 %4, i32* %5, align 4, !tbaa !3
+  %6 = load i32, i32* @e, align 4, !tbaa !3
+  %cmp10.i = icmp slt i32 %6, -1
+  br i1 %cmp10.i, label %if.then.i, label %fn1.exit
+
+if.then.i:                                        ; preds = %for.end9.i
+  %7 = load i32, i32* @f, align 4, !tbaa !3
+  store i32 %7, i32* %5, align 4, !tbaa !3
+  br label %fn1.exit
+
+fn1.exit:                                         ; preds = %if.then.i, %for.end9.i
+  %8 = load i32, i32* @a, align 4, !tbaa !3
+  %tobool = icmp eq i32 %8, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %fn1.exit
+  %puts2 = tail call i32 @puts(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @str.2, i64 0, i64 0))
+  tail call void @abort() #3
+  unreachable
+
+if.end:                                           ; preds = %fn1.exit
+  %puts = tail call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @str, i64 0, i64 0))
+  ret i32 0
+}
+
+; Function Attrs: noreturn nounwind optsize
+declare void @abort() local_unnamed_addr #1
+
+; Function Attrs: nounwind
+declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #2
+
+attributes #0 = { nounwind optsize 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"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noreturn nounwind optsize "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-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+attributes #3 = { noreturn nounwind optsize }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"PIC Level", i32 2}
+!2 = !{!"clang version 5.0.0"}
+!3 = !{!4, !4, i64 0}
+!4 = !{!"int", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple C/C++ TBAA"}
+!7 = !{!8, !8, i64 0}
+!8 = !{!"any pointer", !5, i64 0}

Added: llvm/trunk/test/Transforms/NewGVN/pr33367.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33367.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33367.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33367.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,137 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+; Verify that we don't accidentally delete intrinsics that aren't SSA copies
+%DS_struct = type { [32 x i64*], i8, [32 x i16] }
+%MNR_struct = type { i64, i64, %DS_struct* }
+
+declare i64 @llvm.x86.bmi.bextr.64(i64, i64) #3
+
+define %MNR_struct @f000316011717_2(%DS_struct* %pDS, [64 x i64]* %pCG) #2 {
+; CHECK-LABEL: @f000316011717_2(
+; CHECK-NEXT:  Entry:
+; CHECK-NEXT:    [[RESTART:%.*]] = alloca [[MNR_STRUCT:%.*]]
+; CHECK-NEXT:    [[PCARRY:%.*]] = getelementptr [[DS_STRUCT:%.*]], %DS_struct* [[PDS:%.*]], i32 0, i32 1
+; CHECK-NEXT:    [[PBRBASE:%.*]] = getelementptr [[DS_STRUCT]], %DS_struct* [[PDS]], i32 0, i32 0
+; CHECK-NEXT:    [[PBASE:%.*]] = getelementptr [32 x i64*], [32 x i64*]* [[PBRBASE]], i64 0, i64 0
+; CHECK-NEXT:    [[BASE:%.*]] = load i64*, i64** [[PBASE]], !tbaa !14
+; CHECK-NEXT:    [[ABSADDR:%.*]] = getelementptr i64, i64* [[BASE]], i64 9
+; CHECK-NEXT:    [[EXTARGET:%.*]] = load i64, i64* [[ABSADDR]], align 8, !tbaa !4
+; CHECK-NEXT:    [[TEMPLATE:%.*]] = icmp eq i64 [[EXTARGET]], 8593987412
+; CHECK-NEXT:    br i1 [[TEMPLATE]], label %"BB3.000316011731#1", label [[BB2_000316011731_5:%.*]]
+; CHECK:       "BB3.000316011731#1":
+; CHECK-NEXT:    [[PBASE8:%.*]] = getelementptr [32 x i64*], [32 x i64*]* [[PBRBASE]], i64 0, i64 29
+; CHECK-NEXT:    [[BASE9:%.*]] = load i64*, i64** [[PBASE8]], !tbaa !14
+; CHECK-NEXT:    [[ABSADDR1:%.*]] = getelementptr i64, i64* [[BASE9]], i64 7
+; CHECK-NEXT:    [[RMEM:%.*]] = load i64, i64* [[ABSADDR1]], align 8, !tbaa !4
+; CHECK-NEXT:    [[PWT:%.*]] = getelementptr [[DS_STRUCT]], %DS_struct* [[PDS]], i32 0, i32 2
+; CHECK-NEXT:    [[PWTE:%.*]] = getelementptr [32 x i16], [32 x i16]* [[PWT]], i64 0, i64 8593987412
+; CHECK-NEXT:    [[SHIFTS:%.*]] = load i16, i16* [[PWTE]], align 2, !tbaa !18, !invariant.load !20
+; CHECK-NEXT:    [[SLOWJ:%.*]] = icmp eq i16 [[SHIFTS]], 0
+; CHECK-NEXT:    br i1 [[SLOWJ]], label [[BB2_000316011731_5]], label %"BB3.000316011731#1.1"
+; CHECK:       BB2.000316011731.5:
+; CHECK-NEXT:    [[EXTARGET1:%.*]] = and i64 [[EXTARGET]], 137438953471
+; CHECK-NEXT:    switch i64 [[EXTARGET1]], label [[EXIT:%.*]] [
+; CHECK-NEXT:    ]
+; CHECK:       "BB3.000316011731#1.1":
+; CHECK-NEXT:    [[SHIFTS1:%.*]] = zext i16 [[SHIFTS]] to i64
+; CHECK-NEXT:    [[VAL:%.*]] = call i64 @llvm.x86.bmi.bextr.64(i64 [[RMEM]], i64 [[SHIFTS1]])
+; CHECK-NEXT:    [[PREG:%.*]] = getelementptr [64 x i64], [64 x i64]* [[PCG:%.*]], i64 0, i64 12
+; CHECK-NEXT:    store i64 [[VAL]], i64* [[PREG]], align 32, !tbaa !10
+; CHECK-NEXT:    [[PREG2:%.*]] = getelementptr [64 x i64], [64 x i64]* [[PCG]], i64 0, i64 14
+; CHECK-NEXT:    [[REG:%.*]] = load i64, i64* [[PREG2]], align 16, !tbaa !12
+; CHECK-NEXT:    [[BASE2:%.*]] = load i64*, i64** [[PBASE8]], !tbaa !14
+; CHECK-NEXT:    [[ABSADDR2:%.*]] = getelementptr i64, i64* [[BASE2]], i64 [[REG]]
+; CHECK-NEXT:    [[RMEM2:%.*]] = load i64, i64* [[ABSADDR2]], align 8, !tbaa !1
+; CHECK-NEXT:    [[PREG7:%.*]] = getelementptr [64 x i64], [64 x i64]* [[PCG]], i64 0, i64 9
+; CHECK-NEXT:    store i64 [[RMEM2]], i64* [[PREG7]], align 8, !tbaa !8
+; CHECK-NEXT:    [[ADD2C279:%.*]] = add i64 [[RMEM2]], [[VAL]]
+; CHECK-NEXT:    [[CCHK:%.*]] = icmp sge i64 [[ADD2C279]], 0
+; CHECK-NEXT:    [[CFL:%.*]] = zext i1 [[CCHK]] to i8
+; CHECK-NEXT:    store i8 [[CFL]], i8* [[PCARRY]], align 1, !tbaa !16
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       Exit:
+; CHECK-NEXT:    [[RESTART378:%.*]] = load [[MNR_STRUCT]], %MNR_struct* [[RESTART]]
+; CHECK-NEXT:    ret [[MNR_STRUCT]] %restart378
+;
+Entry:
+  %restart = alloca %MNR_struct
+  %pCarry = getelementptr %DS_struct, %DS_struct* %pDS, i32 0, i32 1
+  %pBRBase = getelementptr  %DS_struct, %DS_struct* %pDS, i32 0, i32 0
+  %pbase = getelementptr  [32 x i64*], [32 x i64*]* %pBRBase, i64 0, i64 0
+  %base = load i64*, i64** %pbase, !tbaa !142
+  %absaddr = getelementptr  i64, i64* %base, i64 9
+  %extarget = load i64, i64* %absaddr, align 8, !tbaa !4
+  %template = icmp eq i64 %extarget, 8593987412
+  br i1 %template, label %"BB3.000316011731#1", label %BB2.000316011731.5
+
+"BB3.000316011731#1":
+  %pBRBase7 = getelementptr  %DS_struct, %DS_struct* %pDS, i32 0, i32 0
+  %pbase8 = getelementptr  [32 x i64*], [32 x i64*]* %pBRBase7, i64 0, i64 29
+  %base9 = load i64*, i64** %pbase8, !tbaa !142
+  %absaddr1 = getelementptr  i64, i64* %base9, i64 7
+  %rmem = load i64, i64* %absaddr1, align 8, !tbaa !4
+  %pwt = getelementptr  %DS_struct, %DS_struct* %pDS, i32 0, i32 2
+  %pwte = getelementptr  [32 x i16], [32 x i16]* %pwt, i64 0, i64 %extarget
+  %shifts = load i16, i16* %pwte, align 2, !tbaa !175, !invariant.load !181
+  %slowj = icmp eq i16 %shifts, 0
+  br i1 %slowj, label %BB2.000316011731.5, label %"BB3.000316011731#1.1"
+
+BB2.000316011731.5:
+  %extarget1 = and i64 %extarget, 137438953471
+  switch i64 %extarget1, label %Exit [
+  ]
+
+"BB3.000316011731#1.1":
+  %shifts1 = zext i16 %shifts to i64
+  %val = call i64 @llvm.x86.bmi.bextr.64(i64 %rmem, i64 %shifts1)
+  %preg = getelementptr  [64 x i64], [64 x i64]* %pCG, i64 0, i64 12
+  store i64 %val, i64* %preg, align 32, !tbaa !32
+  %preg2 = getelementptr  [64 x i64], [64 x i64]* %pCG, i64 0, i64 14
+  %reg = load i64, i64* %preg2, align 16, !tbaa !36
+  %pBRBase2 = getelementptr  %DS_struct, %DS_struct* %pDS, i32 0, i32 0
+  %pbase2 = getelementptr  [32 x i64*], [32 x i64*]* %pBRBase2, i64 0, i64 29
+  %base2 = load i64*, i64** %pbase2, !tbaa !142
+  %absaddr2 = getelementptr  i64, i64* %base2, i64 %reg
+  %rmem2 = load i64, i64* %absaddr2, align 8, !tbaa !4
+  %preg7 = getelementptr  [64 x i64], [64 x i64]* %pCG, i64 0, i64 9
+  store i64 %rmem2, i64* %preg7, align 8, !tbaa !26
+  %reg7 = load i64, i64* %preg7, align 8, !tbaa !26
+  %preg3 = getelementptr  [64 x i64], [64 x i64]* %pCG, i64 0, i64 12
+  %reg4 = load i64, i64* %preg3, align 32, !tbaa !32
+  %add2c279 = add i64 %reg7, %reg4
+  %cchk = icmp sge i64 %add2c279, 0
+  %cfl = zext i1 %cchk to i8
+  store i8 %cfl, i8* %pCarry, align 1, !tbaa !156
+  br label %Exit
+
+Exit:
+  %restart378 = load %MNR_struct, %MNR_struct* %restart
+  ret %MNR_struct %restart378
+}
+
+attributes #2 = { nounwind }
+attributes #3 = { nounwind readnone }
+
+!tbaa = !{!0, !1, !3, !4, !6, !26, !32, !36, !142, !156, !175}
+
+!0 = !{!"tbaa2200"}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"data", !0}
+!3 = !{!"ctrl", !0}
+!4 = !{!5, !5, i64 0}
+!5 = !{!"mem", !2}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"grs", !2}
+!26 = !{!27, !27, i64 0}
+!27 = !{!"X9", !7}
+!32 = !{!33, !33, i64 0}
+!33 = !{!"A0", !7}
+!36 = !{!37, !37, i64 0}
+!37 = !{!"A2", !7}
+!142 = !{!143, !143, i64 0}
+!143 = !{!"breg", !3}
+!156 = !{!157, !157, i64 0}
+!157 = !{!"carry", !3}
+!175 = !{!176, !176, i64 0, i32 1}
+!176 = !{!"const", !3}
+!181 = !{}

Added: llvm/trunk/test/Transforms/NewGVN/pr33432.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33432.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33432.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33432.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+; Ensure we do not incorrect do phi of ops
+ at d = external local_unnamed_addr global i32, align 4
+
+define void @patatino() {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @d, align 4
+; CHECK-NEXT:    br label [[FOR_END10:%.*]]
+; CHECK:       for.end10:
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[TMP0]], 8
+; CHECK-NEXT:    br i1 undef, label [[IF_END:%.*]], label [[FOR_END10]]
+; CHECK:       if.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* @d, align 4
+  br label %for.end10
+
+for.end10:
+  %f.0 = phi i32 [ undef, %entry ], [ 8, %for.end10 ]
+  %or = or i32 %0, %f.0
+  %mul12 = mul nsw i32 %or, undef
+  br i1 undef, label %if.end, label %for.end10
+
+if.end:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/pr33461.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33461.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33461.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33461.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;; Ensure the store verifier is not overzealous
+; RUN: opt -newgvn -enable-phi-of-ops=true -S %s | FileCheck %s
+ at b = external global i16, align 2
+
+define void @patatino() {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 false, label [[FOR_COND1:%.*]], label [[FOR_INC:%.*]]
+; CHECK:       for.cond1:
+; CHECK-NEXT:    [[PHIOFOPS:%.*]] = phi i16 [ undef, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC]] ]
+; CHECK-NEXT:    store i16 [[PHIOFOPS]], i16* @b, align 2
+; CHECK-NEXT:    br label [[FOR_INC]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i16, i16* @b, align 2
+; CHECK-NEXT:    [[INC]] = add i16 [[TMP0]], 1
+; CHECK-NEXT:    store i16 [[INC]], i16* @b, align 2
+; CHECK-NEXT:    br label [[FOR_COND1]]
+;
+entry:
+  br i1 false, label %for.cond1, label %for.inc
+
+for.cond1:
+  %e.0 = phi i16* [ %e.1, %for.inc ], [ null, %entry ]
+  %0 = load i16, i16* %e.0, align 2
+  %add = add i16 %0, 0
+  store i16 %add, i16* %e.0, align 2
+  br label %for.inc
+
+for.inc:
+  %e.1 = phi i16* [ %e.0, %for.cond1 ], [ @b, %entry ]
+  %1 = load i16, i16* @b, align 2
+  %inc = add i16 %1, 1
+  store i16 %inc, i16* @b, align 2
+  br label %for.cond1
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr33720.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr33720.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr33720.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr33720.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,91 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+
+ at f = external local_unnamed_addr global i64
+ at b = external local_unnamed_addr global i64
+ at e = external local_unnamed_addr global i64
+
+define void @patatino() {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 undef, label [[IF_END24:%.*]], label [[FOR_COND16:%.*]]
+; CHECK:       for.cond2thread-pre-split:
+; CHECK-NEXT:    br i1 false, label [[FOR_BODY:%.*]], label [[FOR_COND8_PREHEADER:%.*]]
+; CHECK:       for.cond8.preheader:
+; CHECK-NEXT:    br i1 undef, label [[L1:%.*]], label %for.cond11thread-pre-split.lr.ph
+; CHECK:       for.cond11thread-pre-split.lr.ph:
+; CHECK-NEXT:    br label [[L1]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp ne i64 [[K_2:%.*]], 3
+; CHECK-NEXT:    [[CONV4:%.*]] = zext i1 [[CMP3]] to i64
+; CHECK-NEXT:    [[TMP0:%.*]] = load i64, i64* @f
+; CHECK-NEXT:    [[OR:%.*]] = or i64 [[TMP0]], [[CONV4]]
+; CHECK-NEXT:    store i64 [[OR]], i64* @f
+; CHECK-NEXT:    [[TOBOOL7:%.*]] = icmp ne i64 [[K_2]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL7]], label %for.cond2thread-pre-split, label [[LOR_RHS:%.*]]
+; CHECK:       lor.rhs:
+; CHECK-NEXT:    store i64 1, i64* @b, align 8
+; CHECK-NEXT:    br label %for.cond2thread-pre-split
+; CHECK:       l1:
+; CHECK-NEXT:    [[K_2]] = phi i64 [ undef, [[L1_PREHEADER:%.*]] ], [ 15, [[FOR_COND8_PREHEADER]] ], [ 5, %for.cond11thread-pre-split.lr.ph ]
+; CHECK-NEXT:    store i64 7, i64* [[J_3:%.*]]
+; CHECK-NEXT:    br label [[FOR_BODY]]
+; CHECK:       for.cond16:
+; CHECK-NEXT:    [[J_0:%.*]] = phi i64* [ @f, [[ENTRY:%.*]] ], [ undef, [[FOR_COND20:%.*]] ], [ @e, [[FOR_COND16]] ]
+; CHECK-NEXT:    br i1 undef, label [[FOR_COND20]], label [[FOR_COND16]]
+; CHECK:       for.cond20:
+; CHECK-NEXT:    [[J_2:%.*]] = phi i64* [ [[J_0]], [[FOR_COND16]] ], [ undef, [[IF_END24]] ]
+; CHECK-NEXT:    br i1 true, label [[IF_END24]], label [[FOR_COND16]]
+; CHECK:       if.end24:
+; CHECK-NEXT:    [[J_3]] = phi i64* [ [[J_2]], [[FOR_COND20]] ], [ undef, [[ENTRY]] ]
+; CHECK-NEXT:    br i1 false, label [[FOR_COND20]], label [[L1_PREHEADER]]
+; CHECK:       l1.preheader:
+; CHECK-NEXT:    br label [[L1]]
+;
+entry:
+  br i1 undef, label %if.end24, label %for.cond16
+
+for.cond2thread-pre-split:
+  br i1 false, label %for.body, label %for.cond8.preheader
+
+for.cond8.preheader:
+  br i1 undef, label %l1, label %for.cond11thread-pre-split.lr.ph
+
+for.cond11thread-pre-split.lr.ph:
+  br label %l1
+
+for.body:
+  %k.031 = phi i64 [ %k.2, %l1 ], [ 15, %for.cond2thread-pre-split ]
+  %cmp3 = icmp ne i64 %k.031, 3
+  %conv4 = zext i1 %cmp3 to i64
+  %0 = load i64, i64* @f
+  %or = or i64 %0, %conv4
+  store i64 %or, i64* @f
+  %tobool7 = icmp ne i64 %k.031, 0
+  %or.cond = or i1 %tobool7, false
+  br i1 %or.cond, label %for.cond2thread-pre-split, label %lor.rhs
+
+lor.rhs:
+  store i64 1, i64* @b, align 8
+  br label %for.cond2thread-pre-split
+
+l1:
+  %k.2 = phi i64 [ undef, %l1.preheader ], [ 15, %for.cond8.preheader ], [ 5, %for.cond11thread-pre-split.lr.ph ]
+  store i64 7, i64* %j.3
+  br label %for.body
+
+for.cond16:
+  %j.0 = phi i64* [ @f, %entry ], [ %j.2, %for.cond20 ], [ @e, %for.cond16 ]
+  br i1 undef, label %for.cond20, label %for.cond16
+
+for.cond20:
+  %j.2 = phi i64* [ %j.0, %for.cond16 ], [ %j.3, %if.end24 ]
+  br i1 true, label %if.end24, label %for.cond16
+
+if.end24:
+  %j.3 = phi i64* [ %j.2, %for.cond20 ], [ undef, %entry ]
+  br i1 false, label %for.cond20, label %l1.preheader
+
+l1.preheader:
+  br label %l1
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr34135.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr34135.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr34135.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr34135.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -newgvn -enable-phi-of-ops=true -S | FileCheck %s
+;; Make sure we don't incorrectly use predicateinfo to simplify phi of ops cases
+source_filename = "pr34135.ll"
+
+define void @snork(i32 %arg) {
+; CHECK-LABEL: @snork(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = sext i32 [[ARG:%.*]] to i64
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i64 [ 0, [[BB:%.*]] ], [ [[TMP3:%.*]], [[BB1]] ]
+; CHECK-NEXT:    [[TMP3]] = add i64 [[TMP2]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i64 [[TMP3]], [[TMP]]
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1]], label [[BB7:%.*]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp sgt i64 [[TMP]], 1
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB7]], label [[BB9:%.*]]
+; CHECK:       bb7:
+; CHECK-NEXT:    br label [[BB5:%.*]]
+; CHECK:       bb9:
+; CHECK-NEXT:    unreachable
+;
+bb:
+  %tmp = sext i32 %arg to i64
+  br label %bb1
+
+bb1:                                              ; preds = %bb1, %bb
+  %tmp2 = phi i64 [ 0, %bb ], [ %tmp3, %bb1 ]
+  %tmp3 = add i64 %tmp2, 1
+  %tmp4 = icmp slt i64 %tmp3, %tmp
+  br i1 %tmp4, label %bb1, label %bb7
+
+bb5:                                              ; preds = %bb7
+  %tmp6 = icmp sgt i64 %tmp8, 1
+  br i1 %tmp6, label %bb7, label %bb9
+
+bb7:                                              ; preds = %bb5, %bb1
+  %tmp8 = phi i64 [ undef, %bb5 ], [ %tmp, %bb1 ]
+  br label %bb5
+
+bb9:                                              ; preds = %bb5
+  unreachable
+}

Added: llvm/trunk/test/Transforms/NewGVN/pr34430.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr34430.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr34430.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr34430.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+; RUN: opt < %s -newgvn -S | FileCheck %s
+source_filename = "bugpoint-output-e4c7d0f.bc"
+
+;  Make sure we still properly resolve phi cycles when they involve predicateinfo copies of phis.
+define void @hoge() local_unnamed_addr #0 {
+; CHECK-LABEL: @hoge(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br i1 undef, label [[BB6:%.*]], label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB6]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 true, label [[BB3:%.*]], label [[BB6]]
+; CHECK:       bb3:
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    br i1 undef, label [[BB2:%.*]], label [[BB6]]
+; CHECK:       bb6:
+; CHECK-NEXT:    br label [[BB4]]
+;
+bb:
+  br i1 undef, label %bb6, label %bb1
+
+bb1:                                              ; preds = %bb
+  br label %bb6
+
+bb2:                                              ; preds = %bb4
+  %tmp = icmp slt i8 %tmp5, 7
+  br i1 %tmp, label %bb3, label %bb6
+
+bb3:                                              ; preds = %bb2
+  br label %bb4
+
+bb4:                                              ; preds = %bb6, %bb3
+  %tmp5 = phi i8 [ %tmp5, %bb3 ], [ %tmp7, %bb6 ]
+  br i1 undef, label %bb2, label %bb6
+
+bb6:                                              ; preds = %bb4, %bb2, %bb1, %bb
+  %tmp7 = phi i8 [ %tmp5, %bb4 ], [ %tmp5, %bb2 ], [ 5, %bb1 ], [ undef, %bb ]
+  br label %bb4
+}
+
+attributes #0 = { norecurse noreturn 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"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 6.0.0"}

Added: llvm/trunk/test/Transforms/NewGVN/pr34452.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr34452.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr34452.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr34452.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S < %s | FileCheck %s
+;; Ensure we don't crash when simplifying aggregate value expressions
+source_filename = "bugpoint-output-09f7a24.bc"
+
+ at WHOLELINE = external local_unnamed_addr global i32, align 4
+
+; Function Attrs: nounwind uwtable
+define void @sgrep() local_unnamed_addr #0 {
+; CHECK-LABEL: @sgrep(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @WHOLELINE, align 4, !tbaa !1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL]], i32 2048, i32 2047
+; CHECK-NEXT:    br label [[WHILE_BODY_US:%.*]]
+; CHECK:       while.body.us:
+; CHECK-NEXT:    [[START_1230_US:%.*]] = phi i32 [ [[DOT]], [[ENTRY:%.*]] ], [ 0, [[WHILE_BODY_US]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[START_1230_US]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 0, i64 [[TMP1]])
+; CHECK-NEXT:    br label [[WHILE_BODY_US]]
+;
+entry:
+  %0 = load i32, i32* @WHOLELINE, align 4, !tbaa !1
+  %tobool = icmp eq i32 %0, 0
+  %. = select i1 %tobool, i32 2048, i32 2047
+  br label %while.body.us
+
+while.body.us:                                    ; preds = %while.body.us, %entry
+  %start.1230.us = phi i32 [ %., %entry ], [ 0, %while.body.us ]
+  %1 = sext i32 %start.1230.us to i64
+  %2 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 0, i64 %1)
+  %.res302 = extractvalue { i64, i1 } %2, 0
+  %3 = icmp sge i64 undef, %.res302
+  br label %while.body.us
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64) #1
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "polly-optimized" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 6.0.0 (trunk 311664) (llvm/trunk 311666)"}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"int", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}

Added: llvm/trunk/test/Transforms/NewGVN/pr35074.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr35074.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr35074.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr35074.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 -newgvn -S | FileCheck %s
+
+define void @sort(i64 %.16) {
+; CHECK-LABEL: @sort(
+; CHECK-NEXT:  Entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = extractvalue { i64, i1 } undef, 0
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 2
+; CHECK-NEXT:    br i1 undef, label [[DIVZEROFAIL2_I:%.*]], label [[WHILEBODY_LR_PH:%.*]]
+; CHECK:       DivZeroFail2.i:
+; CHECK-NEXT:    unreachable
+; CHECK:       WhileBody.lr.ph:
+; CHECK-NEXT:    [[TMP2:%.*]] = udiv i64 [[DOT16:%.*]], [[TMP1]]
+; CHECK-NEXT:    br label [[WHILEBODY:%.*]]
+; CHECK:       WhileBody:
+; CHECK-NEXT:    [[ITERATOR:%.*]] = phi i64 [ 0, [[WHILEBODY_LR_PH]] ], [ [[TMP6:%.*]], [[BOUNDSCHECKOK276:%.*]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[ITERATOR]], i64 [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = extractvalue { i64, i1 } [[TMP3]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[TMP4]], i64 1)
+; CHECK-NEXT:    [[TMP6]] = extractvalue { i64, i1 } [[TMP5]], 0
+; CHECK-NEXT:    br i1 false, label [[BOUNDSCHECKFAIL275:%.*]], label [[BOUNDSCHECKOK276]]
+; CHECK:       WhileEnd:
+; CHECK-NEXT:    ret void
+; CHECK:       BoundsCheckFail275:
+; CHECK-NEXT:    unreachable
+; CHECK:       BoundsCheckOk276:
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i64 [[TMP6]], [[DOT16]]
+; CHECK-NEXT:    br i1 [[TMP7]], label [[WHILEBODY]], label [[WHILEEND:%.*]]
+;
+Entry:
+  %0 = extractvalue { i64, i1 } undef, 0
+  %1 = lshr i64 %0, 2
+  br i1 undef, label %DivZeroFail2.i, label %WhileBody.lr.ph
+
+DivZeroFail2.i:                                   ; preds = %Entry
+  unreachable
+
+WhileBody.lr.ph:                                  ; preds = %Entry
+  %2 = udiv i64 %.16, %1
+  br label %WhileBody
+
+WhileBody:                                        ; preds = %BoundsCheckOk276, %WhileBody.lr.ph
+  %iterator = phi i64 [ 0, %WhileBody.lr.ph ], [ %6, %BoundsCheckOk276 ]
+  %3 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %iterator, i64 %2)
+  %4 = extractvalue { i64, i1 } %3, 0
+  %5 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %4, i64 1)
+  %6 = extractvalue { i64, i1 } %5, 0
+  %7 = icmp ugt i64 %iterator, %.16
+  br i1 %7, label %BoundsCheckFail275, label %BoundsCheckOk276
+
+WhileEnd:                                         ; preds = %BoundsCheckOk276
+  ret void
+
+BoundsCheckFail275:                               ; preds = %WhileBody
+  unreachable
+
+BoundsCheckOk276:                                 ; preds = %WhileBody
+  %8 = icmp ult i64 %6, %.16
+  br i1 %8, label %WhileBody, label %WhileEnd
+}
+
+declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64)

Added: llvm/trunk/test/Transforms/NewGVN/pr35125.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pr35125.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pr35125.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pr35125.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -S %s | FileCheck %s
+
+ at a = common global i32 0, align 4
+ at .str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+define i32 @main() #0 {
+; CHECK-LABEL: @main(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[TMP0]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP0]], -1
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[PHIOFOPS:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[NEG]], [[IF_THEN]] ]
+; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[NEG]], [[ENTRY]] ]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 [[STOREMERGE]], [[PHIOFOPS]]
+; CHECK-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then3:
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[STOREMERGE]], -1
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[LOR_RHS:%.*]], label [[LOR_END:%.*]]
+; CHECK:       lor.rhs:
+; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp ne i32 [[TMP0]], 0
+; CHECK-NEXT:    [[PHITMP:%.*]] = zext i1 [[TOBOOL5]] to i32
+; CHECK-NEXT:    br label [[LOR_END]]
+; CHECK:       lor.end:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ 1, [[IF_THEN3]] ], [ [[PHITMP]], [[LOR_RHS]] ]
+; CHECK-NEXT:    store i32 [[TMP1]], i32* @a, align 4
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 [[TMP2]])
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %0 = load i32, i32* @a, align 4
+  %neg = xor i32 %0, -1
+  %cmp = icmp sgt i32 %0, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  br label %if.end
+
+if.end:
+  %storemerge = phi i32 [ %0, %if.then ], [ %neg, %entry ]
+  %neg1 = xor i32 %storemerge, -1
+  %cmp2 = icmp ult i32 %storemerge, %neg1
+  br i1 %cmp2, label %if.then3, label %if.end6
+
+if.then3:
+  %tobool = icmp eq i32 %storemerge, -1
+  br i1 %tobool, label %lor.rhs, label %lor.end
+
+lor.rhs:
+  %tobool5 = icmp ne i32 %0, 0
+  %phitmp = zext i1 %tobool5 to i32
+  br label %lor.end
+
+lor.end:
+  %1 = phi i32 [ 1, %if.then3 ], [ %phitmp, %lor.rhs ]
+  store i32 %1, i32* @a, align 4
+  br label %if.end6
+
+if.end6:
+  %2 = load i32, i32* @a, align 4
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %2) #3
+  ret i32 0
+}
+declare i32 @printf(i8*, ...) #2

Added: llvm/trunk/test/Transforms/NewGVN/pre-compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pre-compare.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pre-compare.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pre-compare.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt -newgvn -S < %s | FileCheck %s
+
+; C source:
+;
+;   void f(int x) {
+;     if (x != 1)
+;       puts (x == 2 ? "a" : "b");
+;     for (;;) {
+;       puts("step 1");
+;       if (x == 2)
+;         continue;
+;       printf("step 2: %d\n", x);
+;     }
+;   }
+;
+; If we PRE %cmp3, CodeGenPrepare won't be able to sink the compare down to its
+; uses, and we are forced to keep both %x and %cmp3 in registers in the loop.
+;
+; It is just as cheap to recompute the icmp against %x as it is to compare a
+; GPR against 0. On x86-64, the br i1 %cmp3 becomes:
+;
+;   testb %r12b, %r12b
+;   jne	LBB0_3
+;
+; The sunk icmp is:
+;
+;   cmpl $2, %ebx
+;   je	LBB0_3
+;
+; This is just as good, and it doesn't require a separate register.
+;
+; CHECK-NOT: phi i1
+
+ at .str = private unnamed_addr constant [2 x i8] c"a\00", align 1
+ at .str1 = private unnamed_addr constant [2 x i8] c"b\00", align 1
+ at .str2 = private unnamed_addr constant [7 x i8] c"step 1\00", align 1
+ at .str3 = private unnamed_addr constant [12 x i8] c"step 2: %d\0A\00", align 1
+
+define void @f(i32 %x) noreturn nounwind uwtable ssp {
+entry:
+  %cmp = icmp eq i32 %x, 1
+  br i1 %cmp, label %for.cond.preheader, label %if.then
+
+if.then:                                          ; preds = %entry
+  %cmp1 = icmp eq i32 %x, 2
+  %cond = select i1 %cmp1, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str1, i64 0, i64 0)
+  %call = tail call i32 @puts(i8* %cond) nounwind
+  br label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %entry, %if.then
+  %cmp3 = icmp eq i32 %x, 2
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond.backedge, %for.cond.preheader
+  %call2 = tail call i32 @puts(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str2, i64 0, i64 0)) nounwind
+  br i1 %cmp3, label %for.cond.backedge, label %if.end5
+
+if.end5:                                          ; preds = %for.cond
+  %call6 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i64 0, i64 0), i32 %x) nounwind
+  br label %for.cond.backedge
+
+for.cond.backedge:                                ; preds = %if.end5, %for.cond
+  br label %for.cond
+}
+
+declare i32 @puts(i8* nocapture) nounwind
+
+declare i32 @printf(i8* nocapture, ...) nounwind

Added: llvm/trunk/test/Transforms/NewGVN/pre-new-inst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/pre-new-inst.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/pre-new-inst.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/pre-new-inst.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; XFAIL: *
+; RUN: opt -basicaa -newgvn -S %s | FileCheck %s
+
+%MyStruct = type { i32, i32 }
+define i8 @foo(i64 %in, i8* %arr) {
+  %addr = alloca %MyStruct
+  %dead = trunc i64 %in to i32
+  br i1 undef, label %next, label %tmp
+
+tmp:
+  call void @bar()
+  br label %next
+
+next:
+  %addr64 = bitcast %MyStruct* %addr to i64*
+  store i64 %in, i64* %addr64
+  br label %final
+
+final:
+  %addr32 = getelementptr %MyStruct, %MyStruct* %addr, i32 0, i32 0
+  %idx32 = load i32, i32* %addr32
+
+; CHECK: %resptr = getelementptr i8, i8* %arr, i32 %dead
+  %resptr = getelementptr i8, i8* %arr, i32 %idx32
+  %res = load i8, i8* %resptr
+
+  ret i8 %res
+}
+
+declare void @bar()

Added: llvm/trunk/test/Transforms/NewGVN/predicates.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/predicates.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/predicates.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/predicates.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,111 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
+
+; Function Attrs: noinline norecurse nounwind readonly ssp uwtable
+define i32 @mp_unsgn_cmp(i32 %n, i32* nocapture readonly %in1, i32* nocapture readonly %in2) local_unnamed_addr {
+; CHECK-LABEL: @mp_unsgn_cmp(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], -1
+; CHECK-NEXT:    br i1 [[CMP11]], label [[FOR_INC_PREHEADER:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       for.inc.preheader:
+; CHECK-NEXT:    br label [[FOR_INC:%.*]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[STOREMERGE2:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_INC]] ], [ 0, [[FOR_INC_PREHEADER]] ]
+; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[STOREMERGE2]] to i64
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[IN1:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, i32* [[IN2:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX4]], align 4
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[INC]] = add nsw i32 [[STOREMERGE2]], 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[STOREMERGE2]], [[N]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[SUB]], 0
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[CMP2]], [[CMP1]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[FOR_INC]], label [[FOR_END:%.*]]
+; CHECK:       for.end:
+; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[SUB]], 0
+; CHECK-NEXT:    br i1 [[CMP5]], label [[IF_END8:%.*]], label [[IF_ELSE]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[SUB1_LCSSA4:%.*]] = phi i32 [ [[SUB]], [[FOR_END]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[CMP6:%.*]] = icmp slt i32 [[SUB1_LCSSA4]], 0
+; CHECK-NEXT:    [[DOTSUB1_LCSSA:%.*]] = select i1 [[CMP6]], i32 -1, i32 [[SUB1_LCSSA4]]
+; CHECK-NEXT:    ret i32 [[DOTSUB1_LCSSA]]
+; CHECK:       if.end8:
+; CHECK-NEXT:    ret i32 1
+;
+entry:
+  %cmp11 = icmp sgt i32 %n, -1
+  br i1 %cmp11, label %for.inc.preheader, label %if.else
+
+for.inc.preheader:                                ; preds = %entry
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.inc.preheader, %for.inc
+  %storemerge2 = phi i32 [ %inc, %for.inc ], [ 0, %for.inc.preheader ]
+  %idxprom = sext i32 %storemerge2 to i64
+  %arrayidx = getelementptr inbounds i32, i32* %in1, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %arrayidx4 = getelementptr inbounds i32, i32* %in2, i64 %idxprom
+  %1 = load i32, i32* %arrayidx4, align 4
+  %sub = sub nsw i32 %0, %1
+  %inc = add nsw i32 %storemerge2, 1
+  %cmp1 = icmp slt i32 %storemerge2, %n
+  %cmp2 = icmp eq i32 %sub, 0
+  %or.cond = and i1 %cmp2, %cmp1
+;; This is a self-critical edge to for.inc. If we insert predicate info on it, we will insert
+;; predicateinfo at the end of this block, and think it dominates everthing using only dfs
+;; numbers, instead of proper edge dominance.  We would then proceed to propagate the true value
+;; of sub == 0 everywhere, making this function only ever return 0.
+  br i1 %or.cond, label %for.inc, label %for.end
+
+for.end:                                          ; preds = %for.inc
+  %sub.lcssa = phi i32 [ %sub, %for.inc ]
+  %cmp5 = icmp sgt i32 %sub.lcssa, 0
+  br i1 %cmp5, label %if.end8, label %if.else
+
+if.else:                                          ; preds = %entry, %for.end
+  %sub1.lcssa4 = phi i32 [ %sub.lcssa, %for.end ], [ 0, %entry ]
+  %cmp6 = icmp slt i32 %sub1.lcssa4, 0
+  %.sub1.lcssa = select i1 %cmp6, i32 -1, i32 %sub1.lcssa4
+  ret i32 %.sub1.lcssa
+
+if.end8:                                          ; preds = %for.end
+  ret i32 1
+}
+
+
+;; This test will generate a copy of a copy of predicateinfo to the multiple uses
+;; of branch conditions below.  Make sure we don't try to extract operand info.
+; Function Attrs: uwtable
+define fastcc void @barney() {
+; CHECK-LABEL: @barney(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB22:%.*]]
+; CHECK:       bb22:
+; CHECK-NEXT:    br i1 undef, label [[BB29:%.*]], label [[BB35:%.*]]
+; CHECK:       bb29:
+; CHECK-NEXT:    br i1 true, label [[BB33:%.*]], label [[BB35]]
+; CHECK:       bb33:
+; CHECK-NEXT:    br i1 true, label [[BB35]], label [[BB35]]
+; CHECK:       bb35:
+; CHECK-NEXT:    unreachable
+;
+bb:
+  br label %bb22
+bb22:                                             ; preds = %bb21
+  %tmp23 = icmp eq i32 undef, 2
+  br i1 %tmp23, label %bb29, label %bb35
+
+
+bb29:                                             ; preds = %bb28
+  br i1 %tmp23, label %bb33, label %bb35
+
+
+bb33:                                             ; preds = %bb31
+  br i1 %tmp23, label %bb35, label %bb35
+
+
+bb35:                                             ; preds = %bb33, %bb29, %bb22
+  unreachable
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/propagate-ir-flags.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/propagate-ir-flags.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/propagate-ir-flags.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/propagate-ir-flags.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -newgvn -S | FileCheck %s
+
+; CHECK-LABEL: func_fast
+; CHECK:       fadd fast double
+; CHECK-NEXT:  store
+; CHECK-NEXT:  ret
+define double @func_fast(double %a, double %b) {
+entry:
+  %a.addr = alloca double, align 8
+  %add = fadd fast double %b, 3.000000e+00
+  store double %add, double* %a.addr, align 8
+  %load_add = load double, double* %a.addr, align 8
+  ret double %load_add
+}
+
+; CHECK-LABEL: func_no_fast
+; CHECK:       fadd double
+; CHECK-NEXT:  store
+; CHECK-NEXT:  ret
+define double @func_no_fast(double %a, double %b) {
+entry:
+  %a.addr = alloca double, align 8
+  %add = fadd fast double %b, 3.000000e+00
+  store double %add, double* %a.addr, align 8
+  %duplicated_add = fadd double %b, 3.000000e+00
+  ret double %duplicated_add
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/range.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/range.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/range.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/range.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; RUN: opt -basicaa -newgvn -S < %s | FileCheck %s
+
+define i32 @test1(i32* %p) {
+; CHECK-LABEL: @test1(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE0:[0-9]+]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !0
+  %b = load i32, i32* %p, !range !0
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test2(i32* %p) {
+; CHECK-LABEL: @test2(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE0]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !0
+  %b = load i32, i32* %p
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test3(i32* %p) {
+; CHECK-LABEL: @test3(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE0]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !0
+  %b = load i32, i32* %p, !range !1
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test4(i32* %p) {
+; CHECK-LABEL: @test4(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE0]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !0
+  %b = load i32, i32* %p, !range !2
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test5(i32* %p) {
+; CHECK-LABEL: @test5(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE3:[0-9]+]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !3
+  %b = load i32, i32* %p, !range !4
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test6(i32* %p) {
+; CHECK-LABEL: @test6(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE5:[0-9]+]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !5
+  %b = load i32, i32* %p, !range !6
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test7(i32* %p) {
+; CHECK-LABEL: @test7(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE7:[0-9]+]]
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !7
+  %b = load i32, i32* %p, !range !8
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test8(i32* %p) {
+; CHECK-LABEL: @test8(i32* %p)
+; CHECK: %a = load i32, i32* %p, !range ![[RANGE9:[0-9]+]]
+; CHECK-NOT: range
+; CHECK: %c = add i32 %a, %a
+  %a = load i32, i32* %p, !range !9
+  %b = load i32, i32* %p, !range !10
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+; CHECK: ![[RANGE0]] = !{i32 0, i32 2}
+; CHECK: ![[RANGE3]] = !{i32 -5, i32 -2}
+; CHECK: ![[RANGE5]] = !{i32 10, i32 1}
+; CHECK: ![[RANGE7]] = !{i32 1, i32 2, i32 3, i32 4}
+; CHECK: ![[RANGE9]] = !{i32 1, i32 5}
+
+!0 = !{i32 0, i32 2}
+!1 = !{i32 3, i32 5}
+!2 = !{i32 2, i32 5}
+!3 = !{i32 -5, i32 -2}
+!4 = !{i32 1, i32 5}
+!5 = !{i32 10, i32 1}
+!6 = !{i32 12, i32 16}
+!7 = !{i32 1, i32 2, i32 3, i32 4}
+!8 = !{i32 5, i32 1}
+!9 = !{i32 1, i32 5}
+!10 = !{i32 5, i32 1}

Added: llvm/trunk/test/Transforms/NewGVN/readattrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/readattrs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/readattrs.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/readattrs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt -newgvn -S -o - < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @use(i8* readonly nocapture)
+
+define i8 @test() {
+  %a = alloca i8
+  store i8 1, i8* %a
+  call void @use(i8* %a)
+  %b = load i8, i8* %a
+  ret i8 %b
+; CHECK-LABEL: define i8 @test(
+; CHECK: call void @use(i8* %a)
+; CHECK-NEXT: ret i8 1
+}

Added: llvm/trunk/test/Transforms/NewGVN/refine-stores.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/refine-stores.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/refine-stores.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/refine-stores.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,189 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+;; Now that we do store refinement, we have to verify that we add fake uses
+;; when we skip existing stores.
+;; We also are testing that various variations that cause stores to move classes
+;; have the right class movement happen
+;; All of these tests result in verification failures if it does not.
+%struct.eggs = type {}
+
+define void @spam(i32 *%a) {
+; CHECK-LABEL: @spam(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[FOO:%.*]] = bitcast i32* [[A:%.*]] to %struct.eggs**
+; CHECK-NEXT:    store %struct.eggs* null, %struct.eggs** [[FOO]]
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br i1 undef, label [[BB3:%.*]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    call void @baz()
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb3:
+; CHECK-NEXT:    store i32 0, i32* undef
+; CHECK-NEXT:    store %struct.eggs* null, %struct.eggs** [[FOO]]
+; CHECK-NEXT:    unreachable
+;
+bb:
+  %foo = bitcast i32 *%a to %struct.eggs**
+  store %struct.eggs* null, %struct.eggs** %foo
+  br label %bb1
+
+bb1:                                              ; preds = %bb2, %bb
+  br i1 undef, label %bb3, label %bb2
+
+bb2:                                              ; preds = %bb1
+  call void @baz()
+  br label %bb1
+
+bb3:                                              ; preds = %bb1
+  store i32 0, i32* undef
+;; This store is defined by a memoryphi of the call and the first store
+;; At first, we will prove it equivalent to the first store above.
+;; Then the call will become reachable, and the equivalence will be removed
+;; Without it being a use of the first store, we will not update the store
+;; to reflect this.
+  store %struct.eggs* null, %struct.eggs** %foo
+  unreachable
+}
+
+declare void @baz()
+
+
+define void @a() {
+; CHECK-LABEL: @a(
+; CHECK-NEXT:  b:
+; CHECK-NEXT:    br label [[C:%.*]]
+; CHECK:       c:
+; CHECK-NEXT:    store i64 undef, i64* null
+; CHECK-NEXT:    br label [[E:%.*]]
+; CHECK:       e:
+; CHECK-NEXT:    [[G:%.*]] = load i64*, i64** null
+; CHECK-NEXT:    store i64* undef, i64** null
+; CHECK-NEXT:    br i1 undef, label [[C]], label [[E]]
+;
+b:
+  br label %c
+
+c:                                                ; preds = %e, %b
+  %d = phi i64* [ undef, %b ], [ null, %e ]
+  store i64 undef, i64* %d
+  br label %e
+
+e:                                                ; preds = %e, %c
+;; The memory for this load starts out equivalent to just the store in c, we later discover the store after us, and
+;; need to make sure the right set of values get marked as changed after memory leaders change
+  %g = load i64*, i64** null
+  %0 = bitcast i64* %g to i64*
+  store i64* undef, i64** null
+  br i1 undef, label %c, label %e
+}
+
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+source_filename = "bugpoint-output-daef094.bc"
+target triple = "x86_64-apple-darwin16.5.0"
+
+%struct.hoge = type {}
+
+define void @widget(%struct.hoge* %arg) {
+; CHECK-LABEL: @widget(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP:%.*]] = phi %struct.hoge* [ [[ARG:%.*]], [[BB:%.*]] ], [ null, [[BB1]] ]
+; CHECK-NEXT:    store %struct.hoge* [[TMP]], %struct.hoge** undef
+; CHECK-NEXT:    br i1 undef, label [[BB1]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP3:%.*]] = phi i64 [ [[TMP8:%.*]], [[BB7:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB7]], label [[BB5:%.*]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[TMP6:%.*]] = load i64, i64* null
+; CHECK-NEXT:    call void @quux()
+; CHECK-NEXT:    store i64 [[TMP6]], i64* undef
+; CHECK-NEXT:    br label [[BB7]]
+; CHECK:       bb7:
+; CHECK-NEXT:    [[TMP8]] = add i64 [[TMP3]], 1
+; CHECK-NEXT:    br label [[BB2]]
+;
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb1, %bb
+  %tmp = phi %struct.hoge* [ %arg, %bb ], [ null, %bb1 ]
+  store %struct.hoge* %tmp, %struct.hoge** undef
+  br i1 undef, label %bb1, label %bb2
+
+bb2:                                              ; preds = %bb7, %bb1
+  %tmp3 = phi i64 [ %tmp8, %bb7 ], [ 0, %bb1 ]
+  %tmp4 = icmp eq i64 %tmp3, 0
+  br i1 %tmp4, label %bb7, label %bb5
+
+bb5:                                              ; preds = %bb2
+  ;; Originally thought equal to the store that comes after it until the phi edges
+  ;; are completely traversed
+  %tmp6 = load i64, i64* null
+  call void @quux()
+  store i64 %tmp6, i64* undef
+  br label %bb7
+
+bb7:                                              ; preds = %bb5, %bb2
+  %tmp8 = add i64 %tmp3, 1
+  br label %bb2
+}
+
+declare void @quux()
+; ModuleID = 'short.ll'
+source_filename = "short.ll"
+
+%struct.a = type {}
+
+define void @b() {
+; CHECK-LABEL: @b(
+; CHECK-NEXT:    [[C:%.*]] = alloca [[STRUCT_A:%.*]]
+; CHECK-NEXT:    br label [[D:%.*]]
+; CHECK:       m:
+; CHECK-NEXT:    unreachable
+; CHECK:       d:
+; CHECK-NEXT:    [[G:%.*]] = bitcast %struct.a* [[C]] to i8*
+; CHECK-NEXT:    [[F:%.*]] = bitcast i8* [[G]] to i32*
+; CHECK-NEXT:    [[E:%.*]] = load i32, i32* [[F]]
+; CHECK-NEXT:    br i1 undef, label [[I:%.*]], label [[J:%.*]]
+; CHECK:       i:
+; CHECK-NEXT:    br i1 undef, label [[K:%.*]], label [[M:%.*]]
+; CHECK:       k:
+; CHECK-NEXT:    br label [[L:%.*]]
+; CHECK:       l:
+; CHECK-NEXT:    unreachable
+; CHECK:       j:
+; CHECK-NEXT:    br label [[M]]
+;
+  %c = alloca %struct.a
+  br label %d
+
+m:                                                ; preds = %j, %i
+  store i32 %e, i32* %f
+  unreachable
+
+d:                                                ; preds = %0
+  %g = bitcast %struct.a* %c to i8*
+  %h = getelementptr i8, i8* %g
+  %f = bitcast i8* %h to i32*
+  %e = load i32, i32* %f
+  br i1 undef, label %i, label %j
+
+i:                                                ; preds = %d
+  br i1 undef, label %k, label %m
+
+k:                                                ; preds = %i
+  br label %l
+
+l:                                                ; preds = %k
+  %n = phi i32 [ %e, %k ]
+  ;; Becomes equal and then not equal to the other store, and
+  ;; along the way, the load.
+  store i32 %n, i32* %f
+  unreachable
+
+j:                                                ; preds = %d
+  br label %m
+}

Added: llvm/trunk/test/Transforms/NewGVN/rle-must-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/rle-must-alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/rle-must-alias.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/rle-must-alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; XFAIL: *
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+; GVN should eliminate the fully redundant %9 GEP which 
+; allows DEAD to be removed.  This is PR3198.
+
+; The %7 and %4 loads combine to make %DEAD unneeded.
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+ at H = common global [100 x i32] zeroinitializer, align 32		; <[100 x i32]*> [#uses=3]
+ at G = common global i32 0		; <i32*> [#uses=2]
+
+define i32 @test(i32 %i) nounwind {
+entry:
+	%0 = tail call i32 (...) @foo() nounwind		; <i32> [#uses=1]
+	%1 = icmp eq i32 %0, 0		; <i1> [#uses=1]
+	br i1 %1, label %bb1, label %bb
+
+bb:		; preds = %entry
+	%2 = tail call i32 (...) @bar() nounwind		; <i32> [#uses=0]
+	%3 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i		; <i32*> [#uses=1]
+	%4 = load i32, i32* %3, align 4		; <i32> [#uses=1]
+	store i32 %4, i32* @G, align 4
+	br label %bb3
+
+bb1:		; preds = %entry
+	%5 = tail call i32 (...) @baz() nounwind		; <i32> [#uses=0]
+	%6 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i		; <i32*> [#uses=1]
+	%7 = load i32, i32* %6, align 4		; <i32> [#uses=2]
+	store i32 %7, i32* @G, align 4
+	%8 = icmp eq i32 %7, 0		; <i1> [#uses=1]
+	br i1 %8, label %bb3, label %bb4
+
+bb3:		; preds = %bb1, %bb
+	%9 = getelementptr [100 x i32], [100 x i32]* @H, i32 0, i32 %i		; <i32*> [#uses=1]
+	%DEAD = load i32, i32* %9, align 4		; <i32> [#uses=1]
+; CHECK: %DEAD = phi i32 [ 0, %bb1 ], [ %4, %bb ]
+	ret i32 %DEAD
+
+bb4:		; preds = %bb1
+	ret i32 0
+}
+
+declare i32 @foo(...)
+
+declare i32 @bar(...)
+
+declare i32 @baz(...)

Added: llvm/trunk/test/Transforms/NewGVN/rle-no-phi-translate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/rle-no-phi-translate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/rle-no-phi-translate.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/rle-no-phi-translate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -newgvn -S | FileCheck %s
+; XFAIL: *
+; FIXME: This should be promotable, but memdep/gvn don't track values
+; path/edge sensitively enough.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+define i32 @g(i32* %b, i32* %c) nounwind {
+entry:
+        store i32 1, i32* %b
+        store i32 2, i32* %c
+        
+	%t1 = icmp eq i32* %b, null		; <i1> [#uses=1]
+	br i1 %t1, label %bb, label %bb2
+
+bb:		; preds = %entry
+	br label %bb2
+
+bb2:		; preds = %bb1, %bb
+	%c_addr.0 = phi i32* [ %b, %entry ], [ %c, %bb ]		; <i32*> [#uses=1]
+	%cv = load i32, i32* %c_addr.0, align 4		; <i32> [#uses=1]
+	ret i32 %cv
+; CHECK: bb2:
+; CHECK-NOT: load i32
+; CHECK: ret i32 
+}
+

Added: llvm/trunk/test/Transforms/NewGVN/rle-nonlocal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/rle-nonlocal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/rle-nonlocal.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/rle-nonlocal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+define i32 @main(i32** %p, i32 %x, i32 %y) {
+; CHECK-LABEL: @main(
+; CHECK-NEXT:  block1:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]]
+; CHECK:       block2:
+; CHECK-NEXT:    [[A:%.*]] = load i32*, i32** [[P:%.*]]
+; CHECK-NEXT:    br label [[BLOCK4:%.*]]
+; CHECK:       block3:
+; CHECK-NEXT:    [[B:%.*]] = load i32*, i32** [[P]]
+; CHECK-NEXT:    br label [[BLOCK4]]
+; CHECK:       block4:
+; CHECK-NEXT:    [[EXISTINGPHI:%.*]] = phi i32* [ [[A]], [[BLOCK2]] ], [ [[B]], [[BLOCK3]] ]
+; CHECK-NEXT:    [[C:%.*]] = load i32, i32* [[EXISTINGPHI]]
+; CHECK-NEXT:    [[E:%.*]] = add i32 [[C]], [[C]]
+; CHECK-NEXT:    ret i32 [[E]]
+;
+block1:
+  %cmp = icmp eq i32 %x, %y
+  br i1 %cmp , label %block2, label %block3
+
+block2:
+  %a = load i32*, i32** %p
+  br label %block4
+
+block3:
+  %b = load i32*, i32** %p
+  br label %block4
+
+block4:
+  %existingPHI = phi i32* [ %a, %block2 ], [ %b, %block3 ]
+  %DEAD = load i32*, i32** %p
+  %c = load i32, i32* %DEAD
+  %d = load i32, i32* %existingPHI
+  %e = add i32 %c, %d
+  ret i32 %e
+}

Added: llvm/trunk/test/Transforms/NewGVN/rle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/rle.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/rle.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/rle.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt < %s -data-layout="e-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-n8:16:32" -basicaa -newgvn -S -die | FileCheck %s
+; RUN: opt < %s -data-layout="E-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-n32"      -basicaa -newgvn -S -die | FileCheck %s
+; memset -> i16 forwarding.
+define signext i16 @memset_to_i16_local(i16* %A) nounwind ssp {
+entry:
+  %conv = bitcast i16* %A to i8*
+  tail call void @llvm.memset.p0i8.i64(i8* %conv, i8 1, i64 200, i1 false)
+  %arrayidx = getelementptr inbounds i16, i16* %A, i64 42
+  %tmp2 = load i16, i16* %arrayidx
+  ret i16 %tmp2
+; CHECK-LABEL: @memset_to_i16_local(
+; CHECK-NOT: load
+; CHECK: ret i16 257
+}
+
+ at GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 }
+ at GCst_as1 = addrspace(1) constant {i32, float, i32 } { i32 42, float 14., i32 97 }
+
+; memset -> float forwarding.
+define float @memcpy_to_float_local(float* %A) nounwind ssp {
+entry:
+  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %conv, i8* bitcast ({i32, float, i32 }* @GCst to i8*), i64 12, i1 false)
+  %arrayidx = getelementptr inbounds float, float* %A, i64 1 ; <float*> [#uses=1]
+  %tmp2 = load float, float* %arrayidx                   ; <float> [#uses=1]
+  ret float %tmp2
+; CHECK-LABEL: @memcpy_to_float_local(
+; CHECK-NOT: load
+; CHECK: ret float 1.400000e+01
+}
+; memcpy from address space 1
+define float @memcpy_to_float_local_as1(float* %A) nounwind ssp {
+entry:
+  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
+  tail call void @llvm.memcpy.p0i8.p1i8.i64(i8* %conv, i8 addrspace(1)* bitcast ({i32, float, i32 } addrspace(1)* @GCst_as1 to i8 addrspace(1)*), i64 12, i1 false)
+  %arrayidx = getelementptr inbounds float, float* %A, i64 1 ; <float*> [#uses=1]
+  %tmp2 = load float, float* %arrayidx                   ; <float> [#uses=1]
+  ret float %tmp2
+; CHECK-LABEL: @memcpy_to_float_local_as1(
+; CHECK-NOT: load
+; CHECK: ret float 1.400000e+01
+}
+
+; PR6642
+define i32 @memset_to_load() nounwind readnone {
+entry:
+  %x = alloca [256 x i32], align 4                ; <[256 x i32]*> [#uses=2]
+  %tmp = bitcast [256 x i32]* %x to i8*           ; <i8*> [#uses=1]
+  call void @llvm.memset.p0i8.i64(i8* align 4 %tmp, i8 0, i64 1024, i1 false)
+  %arraydecay = getelementptr inbounds [256 x i32], [256 x i32]* %x, i32 0, i32 0 ; <i32*>
+  %tmp1 = load i32, i32* %arraydecay                   ; <i32> [#uses=1]
+  ret i32 %tmp1
+; CHECK-LABEL: @memset_to_load(
+; CHECK: ret i32 0
+}
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
+declare void @llvm.memcpy.p0i8.p1i8.i64(i8* nocapture, i8 addrspace(1)* nocapture, i64, i1) nounwind

Added: llvm/trunk/test/Transforms/NewGVN/simp-to-self.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/simp-to-self.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/simp-to-self.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/simp-to-self.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -S < %s -newgvn | FileCheck %s
+
+; CHECK-LABEL: for.cond:
+; CHECK-NEXT:    %lv = load i32, i32* bitcast (i64* @a to i32*)
+; CHECK-NEXT:    %bf.clear = and i32 %lv, -131072
+; CHECK-NEXT:    %bf.set = or i32 1, %bf.clear
+; CHECK-NEXT:    br i1 %bc, label %for.cond, label %exit
+ at a = external global i64
+
+define void @fn1(i1 %bc) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.cond1.1, %entry
+  %tmp = phi i1 [ undef, %entry ], [ 1, %for.cond ]
+  %conv = zext i1 %tmp to i32
+  %lv = load i32, i32* bitcast (i64* @a to i32*)
+  %bf.clear = and i32 %lv, -131072
+  %bf.set = or i32 %conv, %bf.clear
+  %bf.clear.1 = and i32 %bf.set, -131072
+  %bf.set.1 = or i32 1, %bf.clear.1
+  br i1 %bc, label %for.cond, label %exit
+
+exit:                              ; preds = %for.cond1
+  store i32 %bf.set.1, i32* bitcast (i64* @a to i32*)
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/stale-loop-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/stale-loop-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/stale-loop-info.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/stale-loop-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -loops -newgvn -S < %s | FileCheck %s
+
+; This used to fail with ASAN enabled and if for some reason LoopInfo remained
+; available during GVN.  In this case BasicAA will use LI but
+; MergeBlockIntoPredecessor in GVN failed to update LI.
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.wibble.1028 = type { i32, i32, %struct.barney.881 }
+%struct.barney.881 = type { %struct.zot.882 }
+%struct.zot.882 = type { [64 x i8] }
+
+; Function Attrs: argmemonly
+declare void @snork.1(i8*) local_unnamed_addr #0
+
+define hidden zeroext i1 @eggs(%struct.wibble.1028* %arg, i1 %arg2) unnamed_addr align 2 {
+bb:
+  br i1 %arg2, label %bb14, label %bb3
+
+bb3:                                              ; preds = %bb
+  %tmp = getelementptr inbounds %struct.wibble.1028, %struct.wibble.1028* %arg, i64 0, i32 2, i32 0, i32 0, i64 0
+  %tmp5 = bitcast i8* %tmp to %struct.wibble.1028**
+  br label %bb6
+
+bb6:                                              ; preds = %bb12, %bb3
+  br label %bb7
+
+bb7:                                              ; preds = %bb6
+  br i1 undef, label %bb11, label %bb8
+
+bb8:                                              ; preds = %bb7
+  %tmp9 = load %struct.wibble.1028*, %struct.wibble.1028** %tmp5, align 8
+; CHECK: %tmp9 = load %struct.wibble.1028*, %struct.wibble.1028** %tmp5, align 8
+  %tmp10 = bitcast %struct.wibble.1028* %tmp9 to i8*
+  br label %bb12
+
+bb11:                                             ; preds = %bb7
+  br label %bb12
+
+bb12:                                             ; preds = %bb11, %bb8
+  %tmp13 = phi i8* [ %tmp, %bb11 ], [ %tmp10, %bb8 ]
+  call void @snork.1(i8* %tmp13) #1
+  br label %bb6
+
+bb14:                                             ; preds = %bb
+  ret i1 false
+}
+
+attributes #0 = { argmemonly }
+attributes #1 = { nounwind }

Added: llvm/trunk/test/Transforms/NewGVN/storeoverstore.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/storeoverstore.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/storeoverstore.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/storeoverstore.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,90 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn -enable-phi-of-ops=true -S < %s | FileCheck %s
+; RUN: opt -passes=newgvn -enable-phi-of-ops=true -S -o - %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+;; All the loads in this testcase are useless, but it requires understanding that repeated
+;; stores of the same value do not change the memory state to eliminate them.
+
+define i32 @foo(i32*, i32)  {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:    store i32 5, i32* [[TMP0:%.*]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
+; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
+; CHECK:         br label [[TMP5]]
+; CHECK:         [[PHIOFOPS:%.*]] = phi i32 [ 10, [[TMP2:%.*]] ], [ 15, [[TMP4]] ]
+; CHECK-NEXT:    [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP2]] ]
+; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP6:%.*]], label [[TMP7:%.*]]
+; CHECK:         br label [[TMP7]]
+; CHECK:         [[DOT1:%.*]] = phi i32 [ [[PHIOFOPS]], [[TMP6]] ], [ [[DOT0]], [[TMP5]] ]
+; CHECK-NEXT:    ret i32 [[DOT1]]
+;
+  store i32 5, i32* %0, align 4
+  %3 = icmp ne i32 %1, 0
+  br i1 %3, label %4, label %7
+
+; <label>:4:                                      ; preds = %2
+  %5 = load i32, i32* %0, align 4
+  %6 = add nsw i32 5, %5
+  br label %7
+
+; <label>:7:                                      ; preds = %4, %2
+  %.0 = phi i32 [ %6, %4 ], [ 5, %2 ]
+  store i32 5, i32* %0, align 4
+  %8 = icmp ne i32 %1, 0
+  br i1 %8, label %9, label %12
+
+; <label>:9:                                      ; preds = %7
+  %10 = load i32, i32* %0, align 4
+  %11 = add nsw i32 %.0, %10
+  br label %12
+
+; <label>:12:                                     ; preds = %9, %7
+  %.1 = phi i32 [ %11, %9 ], [ %.0, %7 ]
+  ret i32 %.1
+}
+
+;; This is similar to the above, but it is a conditional store of the same value
+;; which requires value numbering MemoryPhi properly to resolve.
+define i32 @foo2(i32*, i32)  {
+; CHECK-LABEL: @foo2(
+; CHECK-NEXT:    store i32 5, i32* [[TMP0:%.*]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
+; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
+; CHECK:         br label [[TMP6:%.*]]
+; CHECK:         br label [[TMP6]]
+; CHECK:         [[PHIOFOPS:%.*]] = phi i32 [ 10, [[TMP5]] ], [ 15, [[TMP4]] ]
+; CHECK-NEXT:    [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP5]] ]
+; CHECK-NEXT:    br i1 [[TMP3]], label [[TMP7:%.*]], label [[TMP8:%.*]]
+; CHECK:         br label [[TMP8]]
+; CHECK:         [[DOT1:%.*]] = phi i32 [ [[PHIOFOPS]], [[TMP7]] ], [ [[DOT0]], [[TMP6]] ]
+; CHECK-NEXT:    ret i32 [[DOT1]]
+;
+  store i32 5, i32* %0, align 4
+  %3 = icmp ne i32 %1, 0
+  br i1 %3, label %4, label %7
+
+; <label>:4:                                      ; preds = %2
+  %5 = load i32, i32* %0, align 4
+  %6 = add nsw i32 5, %5
+  br label %8
+
+; <label>:7:                                      ; preds = %2
+  store i32 5, i32* %0, align 4
+  br label %8
+
+; <label>:8:                                      ; preds = %7, %4
+  %.0 = phi i32 [ %6, %4 ], [ 5, %7 ]
+  %9 = icmp ne i32 %1, 0
+  br i1 %9, label %10, label %13
+
+; <label>:10:                                     ; preds = %8
+  %11 = load i32, i32* %0, align 4
+  %12 = add nsw i32 %.0, %11
+  br label %13
+
+; <label>:13:                                     ; preds = %10, %8
+  %.1 = phi i32 [ %12, %10 ], [ %.0, %8 ]
+  ret i32 %.1
+}

Added: llvm/trunk/test/Transforms/NewGVN/tbaa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/tbaa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/tbaa.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/tbaa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,148 @@
+; RUN: opt -tbaa -basicaa -newgvn -S < %s | FileCheck %s
+
+define i32 @test1(i8* %p, i8* %q) {
+; CHECK-LABEL: @test1(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p)
+; CHECK-NOT: tbaa
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !0
+  %b = call i32 @foo(i8* %p)
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test2(i8* %p, i8* %q) {
+; CHECK-LABEL: @test2(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGC:!.*]]
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !0
+  %b = call i32 @foo(i8* %p), !tbaa !0
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test3(i8* %p, i8* %q) {
+; CHECK-LABEL: @test3(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGB:!.*]]
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !3
+  %b = call i32 @foo(i8* %p), !tbaa !3
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test4(i8* %p, i8* %q) {
+; CHECK-LABEL: @test4(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA:!.*]]
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !1
+  %b = call i32 @foo(i8* %p), !tbaa !0
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test5(i8* %p, i8* %q) {
+; CHECK-LABEL: @test5(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA]]
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !0
+  %b = call i32 @foo(i8* %p), !tbaa !1
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test6(i8* %p, i8* %q) {
+; CHECK-LABEL: @test6(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p), !tbaa [[TAGA]]
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !0
+  %b = call i32 @foo(i8* %p), !tbaa !3
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test7(i8* %p, i8* %q) {
+; CHECK-LABEL: @test7(i8* %p, i8* %q)
+; CHECK: call i32 @foo(i8* %p)
+; CHECK-NOT: tbaa
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !4
+  %b = call i32 @foo(i8* %p), !tbaa !3
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test8(i32* %p, i32* %q) {
+; CHECK-LABEL: @test8
+; CHECK-NEXT: store i32 15, i32* %p
+; CHECK-NEXT: ret i32 0
+; Since we know the location is invariant, we can forward the
+; load across the potentially aliasing store.
+
+  %a = load i32, i32* %q, !tbaa !10
+  store i32 15, i32* %p
+  %b = load i32, i32* %q, !tbaa !10
+  %c = sub i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test9(i32* %p, i32* %q) {
+; CHECK-LABEL: @test9
+; CHECK-NEXT: call void @clobber()
+; CHECK-NEXT: ret i32 0
+; Since we know the location is invariant, we can forward the
+; load across the potentially aliasing store (within the call).
+
+  %a = load i32, i32* %q, !tbaa !10
+  call void @clobber()
+  %b = load i32, i32* %q, !tbaa !10
+  %c = sub i32 %a, %b
+  ret i32 %c
+}
+
+define i32 @test10(i8* %p, i8* %q) {
+; If one access encloses the other, then the merged access is the enclosed one
+; and not just the common final access type.
+; CHECK-LABEL: @test10
+; CHECK: call i32 @foo(i8* %p), !tbaa [[TAG_X_i:!.*]]
+; CHECK: %c = add i32 %a, %a
+  %a = call i32 @foo(i8* %p), !tbaa !15  ; TAG_X_i
+  %b = call i32 @foo(i8* %p), !tbaa !19  ; TAG_Y_x_i
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+declare void @clobber()
+declare i32 @foo(i8*) readonly
+
+; CHECK-DAG: [[TAGC]] = !{[[TYPEC:!.*]], [[TYPEC]], i64 0}
+; CHECK-DAG: [[TYPEC]] = !{!"C", [[TYPEA:!.*]]}
+; CHECK-DAG: [[TYPEA]] = !{!"A", !{{.*}}}
+; CHECK-DAG: [[TAGB]] = !{[[TYPEB:!.*]], [[TYPEB]], i64 0}
+; CHECK-DAG: [[TYPEB]] = !{!"B", [[TYPEA]]}
+; CHECK-DAG: [[TAGA]] = !{[[TYPEA]], [[TYPEA]], i64 0}
+!0 = !{!5, !5, i64 0}
+!1 = !{!6, !6, i64 0}
+!2 = !{!"tbaa root"}
+!3 = !{!7, !7, i64 0}
+!4 = !{!11, !11, i64 0}
+!5 = !{!"C", !6}
+!6 = !{!"A", !2}
+!7 = !{!"B", !6}
+!8 = !{!"another root"}
+!11 = !{!"scalar type", !8}
+
+; CHECK-DAG: [[TAG_X_i]] = !{[[TYPE_X:!.*]], [[TYPE_int:!.*]], i64 0}
+; CHECK-DAG: [[TYPE_X:!.*]] = !{!"struct X", [[TYPE_int]], i64 0}
+; CHECK-DAG: [[TYPE_int]] = !{!"int", {{!.*}}, i64 0}
+!15 = !{!16, !17, i64 0}            ; TAG_X_i
+!16 = !{!"struct X", !17, i64 0}    ; struct X { int i; };
+!17 = !{!"int", !18, i64 0}
+!18 = !{!"char", !2, i64 0}
+
+!19 = !{!20, !17, i64 0}            ; TAG_Y_x_i
+!20 = !{!"struct Y", !16, i64 0}    ; struct Y { struct X x; };
+
+; A TBAA structure who's only point is to have a constant location.
+!9 = !{!"yet another root"}
+!10 = !{!"node", !9, i64 1}

Added: llvm/trunk/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -memdep -newgvn -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.0"
+
+define i32 @test2() nounwind ssp {
+entry:
+    ret i32 0
+
+unreachable_block:
+    %a = add i32 %a, 1
+    ret i32 %a
+}
+
+define i32 @pr23096_test0() {
+entry:
+  br label %bb0
+
+bb1:
+  %ptr1 = ptrtoint i32* %ptr2 to i64
+  %ptr2 = inttoptr i64 %ptr1 to i32*
+  br i1 undef, label %bb0, label %bb1
+
+bb0:
+  %phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ]
+  %load = load i32, i32* %phi
+  ret i32 %load
+}
+
+define i32 @pr23096_test1() {
+entry:
+  br label %bb0
+
+bb1:
+  %ptr1 = getelementptr i32, i32* %ptr2, i32 0
+  %ptr2 = getelementptr i32, i32* %ptr1, i32 0
+  br i1 undef, label %bb0, label %bb1
+
+bb0:
+  %phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ]
+  %load = load i32, i32* %phi
+  ret i32 %load
+}

Added: llvm/trunk/test/Transforms/NewGVN/verify-memoryphi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/verify-memoryphi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/verify-memoryphi.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/verify-memoryphi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; Skip dead MemoryPhis when performing memory congruency verification
+; in NewGVN.
+; RUN: opt -S -newgvn %s | FileCheck %s
+; REQUIRES: asserts
+
+; CHECK: define void @tinkywinky() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   br i1 false, label %body, label %end
+; CHECK:      body:
+; CHECK-NEXT:   store i8 undef, i8* null
+; CHECK-NEXT:   br label %end
+; CHECK:      end:
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+define void @tinkywinky() {
+entry:
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* undef)
+  br i1 false, label %body, label %end
+
+body:
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* undef)
+  br label %end
+
+end:
+  ret void
+}

Added: llvm/trunk/test/Transforms/NewGVN/volatile-nonvolatile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/volatile-nonvolatile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/volatile-nonvolatile.ll (added)
+++ llvm/trunk/test/Transforms/NewGVN/volatile-nonvolatile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; RUN: opt -tbaa -newgvn -S < %s | FileCheck %s
+
+%struct.t = type { i32* }
+
+; The loaded address and the location of the address itself are not aliased,
+; so the second reload is not necessary. Check that it can be eliminated.
+; CHECK-LABEL: test1
+; CHECK: load
+; CHECK-NOT: load
+define void @test1(%struct.t* nocapture readonly %p, i32 %v) #0 {
+entry:
+  %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
+  %0 = load i32*, i32** %m, align 4, !tbaa !1
+  store volatile i32 %v, i32* %0, align 4, !tbaa !6
+  %1 = load i32*, i32** %m, align 4, !tbaa !1
+  store volatile i32 %v, i32* %1, align 4, !tbaa !6
+  ret void
+}
+
+; The store via the loaded address may overwrite the address itself.
+; Make sure that both loads remain.
+; CHECK-LABEL: test2
+; CHECK: load
+; CHECK: store
+; CHECK: load
+define void @test2(%struct.t* nocapture readonly %p, i32 %v) #0 {
+entry:
+  %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
+  %0 = load i32*, i32** %m, align 4, !tbaa !1
+  store volatile i32 %v, i32* %0, align 4, !tbaa !1
+  %1 = load i32*, i32** %m, align 4, !tbaa !1
+  store volatile i32 %v, i32* %1, align 4, !tbaa !1
+  ret void
+}
+
+; The loads are ordered and non-monotonic. Although they are not aliased to
+; the stores, make sure both are preserved.
+; CHECK-LABEL: test3
+; CHECK: load
+; CHECK: store
+; CHECK: load
+define void @test3(%struct.t* nocapture readonly %p, i32 %v) #0 {
+entry:
+  %m = getelementptr inbounds %struct.t, %struct.t* %p, i32 0, i32 0
+  %0 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1
+  store volatile i32 %v, i32* %0, align 4, !tbaa !6
+  %1 = load atomic i32*, i32** %m acquire, align 4, !tbaa !1
+  store volatile i32 %v, i32* %1, align 4, !tbaa !6
+  ret void
+}
+
+attributes #0 = { norecurse nounwind }
+
+!1 = !{!2, !3, i64 0}
+!2 = !{!"", !3, i64 0}
+!3 = !{!"any pointer", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"int", !4, i64 0}
+

Added: llvm/trunk/test/Transforms/ObjCARC/allocas.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/allocas.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/allocas.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/allocas.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,500 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+declare i8* @llvm.objc.retain(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare void @llvm.objc.autoreleasePoolPop(i8*)
+declare i8* @llvm.objc.autoreleasePoolPush()
+declare i8* @llvm.objc.retainBlock(i8*)
+
+declare i8* @objc_retainedObject(i8*)
+declare i8* @objc_unretainedObject(i8*)
+declare i8* @objc_unretainedPointer(i8*)
+
+declare void @use_pointer(i8*)
+declare void @callee()
+declare void @callee_fnptr(void ()*)
+declare void @invokee()
+declare i8* @returner()
+declare i8* @returner1()
+declare i8* @returner2()
+declare void @bar(i32 ()*)
+declare void @use_alloca(i8**)
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+
+
+; In the presence of allocas, unconditionally remove retain/release pairs only
+; if they are known safe in both directions. This prevents matching up an inner
+; retain with the boundary guarding release in the following situation:
+; 
+; %A = alloca
+; retain(%x)
+; retain(%x) <--- Inner Retain
+; store %x, %A
+; %y = load %A
+; ... DO STUFF ...
+; release(%y)
+; release(%x) <--- Guarding Release
+;
+; rdar://13750319
+
+; CHECK: define void @test1a(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test1a(i8* %x) {
+entry:
+  %A = alloca i8*
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  store i8* %x, i8** %A, align 8
+  %y = load i8*, i8** %A
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: define void @test1b(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test1b(i8* %x) {
+entry:
+  %A = alloca i8*
+  %gep = getelementptr i8*, i8** %A, i32 0
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  store i8* %x, i8** %gep, align 8
+  %y = load i8*, i8** %A
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+
+; CHECK: define void @test1c(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test1c(i8* %x) {
+entry:
+  %A = alloca i8*, i32 3
+  %gep = getelementptr i8*, i8** %A, i32 2
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  store i8* %x, i8** %gep, align 8
+  %y = load i8*, i8** %gep
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+
+; CHECK: define void @test1d(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test1d(i8* %x) {
+entry:
+  br i1 undef, label %use_allocaA, label %use_allocaB
+
+use_allocaA:
+  %allocaA = alloca i8*
+  br label %exit
+
+use_allocaB:
+  %allocaB = alloca i8*
+  br label %exit
+
+exit:
+  %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]
+  %gep = getelementptr i8*, i8** %A, i32 0
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  store i8* %x, i8** %gep, align 8
+  %y = load i8*, i8** %gep
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: define void @test1e(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test1e(i8* %x) {
+entry:
+  br i1 undef, label %use_allocaA, label %use_allocaB
+
+use_allocaA:
+  %allocaA = alloca i8*, i32 4
+  br label %exit
+
+use_allocaB:
+  %allocaB = alloca i8*, i32 4
+  br label %exit
+
+exit:
+  %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]
+  %gep = getelementptr i8*, i8** %A, i32 2
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  store i8* %x, i8** %gep, align 8
+  %y = load i8*, i8** %gep
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: define void @test1f(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test1f(i8* %x) {
+entry:
+  %allocaOne = alloca i8*
+  %allocaTwo = alloca i8*
+  %A = select i1 undef, i8** %allocaOne, i8** %allocaTwo
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  store i8* %x, i8** %A, align 8
+  %y = load i8*, i8** %A
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; Make sure that if a store is in a different basic block we handle known safe
+; conservatively.
+
+
+; CHECK: define void @test2a(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test2a(i8* %x) {
+entry:
+  %A = alloca i8*
+  store i8* %x, i8** %A, align 8
+  %y = load i8*, i8** %A
+  br label %bb1
+
+bb1:
+  br label %bb2
+
+bb2:
+  br label %bb3
+
+bb3:
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: define void @test2b(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test2b(i8* %x) {
+entry:
+  %A = alloca i8*
+  %gep1 = getelementptr i8*, i8** %A, i32 0
+  store i8* %x, i8** %gep1, align 8
+  %gep2 = getelementptr i8*, i8** %A, i32 0
+  %y = load i8*, i8** %gep2
+  br label %bb1
+
+bb1:
+  br label %bb2
+
+bb2:
+  br label %bb3
+
+bb3:
+  tail call i8* @llvm.objc.retain(i8* %x)
+  tail call i8* @llvm.objc.retain(i8* %x)
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: define void @test2c(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test2c(i8* %x) {
+entry:
+  %A = alloca i8*, i32 3
+  %gep1 = getelementptr i8*, i8** %A, i32 2
+  store i8* %x, i8** %gep1, align 8
+  %gep2 = getelementptr i8*, i8** %A, i32 2
+  %y = load i8*, i8** %gep2
+  tail call i8* @llvm.objc.retain(i8* %x)
+  br label %bb1
+
+bb1:
+  br label %bb2
+
+bb2:
+  br label %bb3
+
+bb3:
+  tail call i8* @llvm.objc.retain(i8* %x)
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: define void @test2d(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %y)
+; CHECK: @llvm.objc.release(i8* %x)
+; CHECK: ret void
+; CHECK: }
+define void @test2d(i8* %x) {
+entry:
+  tail call i8* @llvm.objc.retain(i8* %x)
+  br label %bb1
+
+bb1:
+  %Abb1 = alloca i8*, i32 3
+  %gepbb11 = getelementptr i8*, i8** %Abb1, i32 2
+  store i8* %x, i8** %gepbb11, align 8
+  %gepbb12 = getelementptr i8*, i8** %Abb1, i32 2
+  %ybb1 = load i8*, i8** %gepbb12
+  br label %bb3
+
+bb2:
+  %Abb2 = alloca i8*, i32 4
+  %gepbb21 = getelementptr i8*, i8** %Abb2, i32 2
+  store i8* %x, i8** %gepbb21, align 8
+  %gepbb22 = getelementptr i8*, i8** %Abb2, i32 2
+  %ybb2 = load i8*, i8** %gepbb22
+  br label %bb3
+
+bb3:
+  %A = phi i8** [ %Abb1, %bb1 ], [ %Abb2, %bb2 ]
+  %y = phi i8* [ %ybb1, %bb1 ], [ %ybb2, %bb2 ]
+  tail call i8* @llvm.objc.retain(i8* %x)
+  call void @use_alloca(i8** %A)
+  call void @llvm.objc.release(i8* %y), !clang.imprecise_release !0
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+; Make sure in the presence of allocas, if we find a cfghazard we do not perform
+; code motion even if we are known safe. These two concepts are separate and
+; should be treated as such.
+;
+; rdar://13949644
+
+; CHECK: define void @test3a() {
+; CHECK: entry:
+; CHECK:   @llvm.objc.retainAutoreleasedReturnValue
+; CHECK:   @llvm.objc.retain
+; CHECK:   @llvm.objc.retain
+; CHECK:   @llvm.objc.retain
+; CHECK:   @llvm.objc.retain
+; CHECK: arraydestroy.body:
+; CHECK:   @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: arraydestroy.done:
+; CHECK-NOT: @llvm.objc.release
+; CHECK: arraydestroy.body1:
+; CHECK:   @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: arraydestroy.done1:
+; CHECK: @llvm.objc.release
+; CHECK: ret void
+; CHECK: }
+define void @test3a() {
+entry:
+  %keys = alloca [2 x i8*], align 16
+  %objs = alloca [2 x i8*], align 16
+  
+  %call1 = call i8* @returner()
+  %tmp0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1)
+
+  %objs.begin = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 0
+  tail call i8* @llvm.objc.retain(i8* %call1)
+  store i8* %call1, i8** %objs.begin, align 8
+  %objs.elt = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 1
+  tail call i8* @llvm.objc.retain(i8* %call1)
+  store i8* %call1, i8** %objs.elt
+
+  %call2 = call i8* @returner1()
+  %call3 = call i8* @returner2()
+  %keys.begin = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 0
+  tail call i8* @llvm.objc.retain(i8* %call2)
+  store i8* %call2, i8** %keys.begin, align 8
+  %keys.elt = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 1
+  tail call i8* @llvm.objc.retain(i8* %call3)
+  store i8* %call3, i8** %keys.elt  
+  
+  %gep = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 2
+  br label %arraydestroy.body
+
+arraydestroy.body:
+  %arraydestroy.elementPast = phi i8** [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]
+  %arraydestroy.element = getelementptr inbounds i8*, i8** %arraydestroy.elementPast, i64 -1
+  %destroy_tmp = load i8*, i8** %arraydestroy.element, align 8
+  call void @llvm.objc.release(i8* %destroy_tmp), !clang.imprecise_release !0
+  %objs_ptr = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 0
+  %arraydestroy.cmp = icmp eq i8** %arraydestroy.element, %objs_ptr
+  br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body
+
+arraydestroy.done:
+  %gep1 = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 2
+  br label %arraydestroy.body1
+
+arraydestroy.body1:
+  %arraydestroy.elementPast1 = phi i8** [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]
+  %arraydestroy.element1 = getelementptr inbounds i8*, i8** %arraydestroy.elementPast1, i64 -1
+  %destroy_tmp1 = load i8*, i8** %arraydestroy.element1, align 8
+  call void @llvm.objc.release(i8* %destroy_tmp1), !clang.imprecise_release !0
+  %keys_ptr = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 0
+  %arraydestroy.cmp1 = icmp eq i8** %arraydestroy.element1, %keys_ptr
+  br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1
+
+arraydestroy.done1:
+  call void @llvm.objc.release(i8* %call1), !clang.imprecise_release !0
+  ret void
+}
+
+; Make sure that even though we stop said code motion we still allow for
+; pointers to be removed if we are known safe in both directions.
+;
+; rdar://13949644
+
+; CHECK: define void @test3b() {
+; CHECK: entry:
+; CHECK:   @llvm.objc.retainAutoreleasedReturnValue
+; CHECK:   @llvm.objc.retain
+; CHECK:   @llvm.objc.retain
+; CHECK:   @llvm.objc.retain
+; CHECK:   @llvm.objc.retain
+; CHECK: arraydestroy.body:
+; CHECK:   @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: arraydestroy.done:
+; CHECK-NOT: @llvm.objc.release
+; CHECK: arraydestroy.body1:
+; CHECK:   @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: arraydestroy.done1:
+; CHECK: @llvm.objc.release
+; CHECK: ret void
+; CHECK: }
+define void @test3b() {
+entry:
+  %keys = alloca [2 x i8*], align 16
+  %objs = alloca [2 x i8*], align 16
+  
+  %call1 = call i8* @returner()
+  %tmp0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1)
+  %tmp1 = tail call i8* @llvm.objc.retain(i8* %call1)
+
+  %objs.begin = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 0
+  tail call i8* @llvm.objc.retain(i8* %call1)
+  store i8* %call1, i8** %objs.begin, align 8
+  %objs.elt = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 1
+  tail call i8* @llvm.objc.retain(i8* %call1)
+  store i8* %call1, i8** %objs.elt
+
+  %call2 = call i8* @returner1()
+  %call3 = call i8* @returner2()
+  %keys.begin = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 0
+  tail call i8* @llvm.objc.retain(i8* %call2)
+  store i8* %call2, i8** %keys.begin, align 8
+  %keys.elt = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 1
+  tail call i8* @llvm.objc.retain(i8* %call3)
+  store i8* %call3, i8** %keys.elt  
+  
+  %gep = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 2
+  br label %arraydestroy.body
+
+arraydestroy.body:
+  %arraydestroy.elementPast = phi i8** [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]
+  %arraydestroy.element = getelementptr inbounds i8*, i8** %arraydestroy.elementPast, i64 -1
+  %destroy_tmp = load i8*, i8** %arraydestroy.element, align 8
+  call void @llvm.objc.release(i8* %destroy_tmp), !clang.imprecise_release !0
+  %objs_ptr = getelementptr inbounds [2 x i8*], [2 x i8*]* %objs, i64 0, i64 0
+  %arraydestroy.cmp = icmp eq i8** %arraydestroy.element, %objs_ptr
+  br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body
+
+arraydestroy.done:
+  %gep1 = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 2
+  br label %arraydestroy.body1
+
+arraydestroy.body1:
+  %arraydestroy.elementPast1 = phi i8** [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]
+  %arraydestroy.element1 = getelementptr inbounds i8*, i8** %arraydestroy.elementPast1, i64 -1
+  %destroy_tmp1 = load i8*, i8** %arraydestroy.element1, align 8
+  call void @llvm.objc.release(i8* %destroy_tmp1), !clang.imprecise_release !0
+  %keys_ptr = getelementptr inbounds [2 x i8*], [2 x i8*]* %keys, i64 0, i64 0
+  %arraydestroy.cmp1 = icmp eq i8** %arraydestroy.element1, %keys_ptr
+  br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1
+
+arraydestroy.done1:
+  call void @llvm.objc.release(i8* %call1), !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %call1), !clang.imprecise_release !0
+  ret void
+}
+
+!0 = !{}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/ObjCARC/apelim.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/apelim.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/apelim.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/apelim.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt -S -objc-arc-apelim < %s | FileCheck %s
+; rdar://10227311
+
+ at llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }]
+
+ at x = global i32 0
+
+declare i32 @bar() nounwind
+
+define i32 @foo() nounwind {
+entry:
+  ret i32 5
+}
+
+define internal void @__cxx_global_var_init() {
+entry:
+  %call = call i32 @foo()
+  store i32 %call, i32* @x, align 4
+  ret void
+}
+
+define internal void @__dxx_global_var_init() {
+entry:
+  %call = call i32 @bar()
+  store i32 %call, i32* @x, align 4
+  ret void
+}
+
+; CHECK: define internal void @_GLOBAL__I_x() {
+; CHECK-NOT: @objc
+; CHECK: }
+define internal void @_GLOBAL__I_x() {
+entry:
+  %0 = call i8* @llvm.objc.autoreleasePoolPush() nounwind
+  call void @__cxx_global_var_init()
+  call void @llvm.objc.autoreleasePoolPop(i8* %0) nounwind
+  ret void
+}
+
+; CHECK: define internal void @_GLOBAL__I_y() {
+; CHECK: %0 = call i8* @llvm.objc.autoreleasePoolPush() [[NUW:#[0-9]+]]
+; CHECK: call void @llvm.objc.autoreleasePoolPop(i8* %0) [[NUW]]
+; CHECK: }
+define internal void @_GLOBAL__I_y() {
+entry:
+  %0 = call i8* @llvm.objc.autoreleasePoolPush() nounwind
+  call void @__dxx_global_var_init()
+  call void @llvm.objc.autoreleasePoolPop(i8* %0) nounwind
+  ret void
+}
+
+declare i8* @llvm.objc.autoreleasePoolPush()
+declare void @llvm.objc.autoreleasePoolPop(i8*)
+
+; CHECK: attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/basic.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,3074 @@
+; RUN: opt -basicaa -objc-arc -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+declare i8* @llvm.objc.retain(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare void @llvm.objc.autoreleasePoolPop(i8*)
+declare i8* @llvm.objc.autoreleasePoolPush()
+declare i8* @llvm.objc.retainBlock(i8*)
+
+declare i8* @llvm.objc.retainedObject(i8*)
+declare i8* @llvm.objc.unretainedObject(i8*)
+declare i8* @llvm.objc.unretainedPointer(i8*)
+
+declare void @use_pointer(i8*)
+declare void @callee()
+declare void @callee_fnptr(void ()*)
+declare void @invokee()
+declare i8* @returner()
+declare void @bar(i32 ()*)
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+
+; Simple retain+release pair deletion, with some intervening control
+; flow and harmless instructions.
+
+; CHECK: define void @test0_precise(i32* %x, i1 %p) [[NUW:#[0-9]+]] {
+; CHECK: @llvm.objc.retain
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test0_precise(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+}
+
+; CHECK: define void @test0_imprecise(i32* %x, i1 %p) [[NUW]] {
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test0_imprecise(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Like test0 but the release isn't always executed when the retain is,
+; so the optimization is not safe.
+
+; TODO: Make the llvm.objc.release's argument be %0.
+
+; CHECK: define void @test1_precise(i32* %x, i1 %p, i1 %q) [[NUW]] {
+; CHECK: @llvm.objc.retain(i8* %a)
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test1_precise(i32* %x, i1 %p, i1 %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @callee()
+  br i1 %q, label %return, label %alt_return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+
+alt_return:
+  ret void
+}
+
+; CHECK: define void @test1_imprecise(i32* %x, i1 %p, i1 %q) [[NUW]] {
+; CHECK: @llvm.objc.retain(i8* %a)
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test1_imprecise(i32* %x, i1 %p, i1 %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @callee()
+  br i1 %q, label %return, label %alt_return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  ret void
+
+alt_return:
+  ret void
+}
+
+
+; Don't do partial elimination into two different CFG diamonds.
+
+; CHECK: define void @test1b_precise(i8* %x, i1 %p, i1 %q) {
+; CHECK: entry:
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK-NOT: @llvm.objc.
+; CHECK: if.end5:
+; CHECK:   tail call void @llvm.objc.release(i8* %x) [[NUW]]
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test1b_precise(i8* %x, i1 %p, i1 %q) {
+entry:
+  tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  br i1 %p, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  tail call void @callee()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  br i1 %q, label %if.then3, label %if.end5
+
+if.then3:                                         ; preds = %if.end
+  tail call void @use_pointer(i8* %x)
+  br label %if.end5
+
+if.end5:                                          ; preds = %if.then3, %if.end
+  tail call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test1b_imprecise(
+; CHECK: entry:
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %x) [[NUW:#[0-9]+]]
+; CHECK-NOT: @llvm.objc.
+; CHECK: if.end5:
+; CHECK:   tail call void @llvm.objc.release(i8* %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]]
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test1b_imprecise(i8* %x, i1 %p, i1 %q) {
+entry:
+  tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  br i1 %p, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  tail call void @callee()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  br i1 %q, label %if.then3, label %if.end5
+
+if.then3:                                         ; preds = %if.end
+  tail call void @use_pointer(i8* %x)
+  br label %if.end5
+
+if.end5:                                          ; preds = %if.then3, %if.end
+  tail call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+
+; Like test0 but the pointer is passed to an intervening call,
+; so the optimization is not safe.
+
+; CHECK-LABEL: define void @test2_precise(
+; CHECK: @llvm.objc.retain(i8* %a)
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test2_precise(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @use_pointer(i8* %0)
+  %d = bitcast i32* %x to float*
+  store float 3.0, float* %d
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test2_imprecise(
+; CHECK: @llvm.objc.retain(i8* %a)
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test2_imprecise(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @use_pointer(i8* %0)
+  %d = bitcast i32* %x to float*
+  store float 3.0, float* %d
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Like test0 but the release is in a loop,
+; so the optimization is not safe.
+
+; TODO: For now, assume this can't happen.
+
+; CHECK-LABEL: define void @test3_precise(
+; TODO: @llvm.objc.retain(i8* %a)
+; TODO: @llvm.objc.release
+; CHECK: }
+define void @test3_precise(i32* %x, i1* %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  %j = load volatile i1, i1* %q
+  br i1 %j, label %loop, label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test3_imprecise(
+; TODO: @llvm.objc.retain(i8* %a)
+; TODO: @llvm.objc.release
+; CHECK: }
+define void @test3_imprecise(i32* %x, i1* %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  %j = load volatile i1, i1* %q
+  br i1 %j, label %loop, label %return
+
+return:
+  ret void
+}
+
+
+; TODO: For now, assume this can't happen.
+
+; Like test0 but the retain is in a loop,
+; so the optimization is not safe.
+
+; CHECK-LABEL: define void @test4_precise(
+; TODO: @llvm.objc.retain(i8* %a)
+; TODO: @llvm.objc.release
+; CHECK: }
+define void @test4_precise(i32* %x, i1* %q) nounwind {
+entry:
+  br label %loop
+
+loop:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %j = load volatile i1, i1* %q
+  br i1 %j, label %loop, label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test4_imprecise(
+; TODO: @llvm.objc.retain(i8* %a)
+; TODO: @llvm.objc.release
+; CHECK: }
+define void @test4_imprecise(i32* %x, i1* %q) nounwind {
+entry:
+  br label %loop
+
+loop:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %j = load volatile i1, i1* %q
+  br i1 %j, label %loop, label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+
+; Like test0 but the pointer is conditionally passed to an intervening call,
+; so the optimization is not safe.
+
+; CHECK-LABEL: define void @test5a(
+; CHECK: @llvm.objc.retain(i8*
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test5a(i32* %x, i1 %q, i8* %y) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %s = select i1 %q, i8* %y, i8* %0
+  call void @use_pointer(i8* %s)
+  store i32 7, i32* %x
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test5b(
+; CHECK: @llvm.objc.retain(i8*
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test5b(i32* %x, i1 %q, i8* %y) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %s = select i1 %q, i8* %y, i8* %0
+  call void @use_pointer(i8* %s)
+  store i32 7, i32* %x
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+
+; retain+release pair deletion, where the release happens on two different
+; flow paths.
+
+; CHECK-LABEL: define void @test6a(
+; CHECK: entry:
+; CHECK:   tail call i8* @llvm.objc.retain
+; CHECK: t:
+; CHECK:   call void @llvm.objc.release
+; CHECK: f:
+; CHECK:   call void @llvm.objc.release
+; CHECK: return:
+; CHECK: }
+define void @test6a(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  %ct = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %ct) nounwind
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @callee()
+  %cf = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cf) nounwind
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test6b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test6b(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  %ct = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %ct) nounwind, !clang.imprecise_release !0
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @callee()
+  %cf = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cf) nounwind, !clang.imprecise_release !0
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test6c(
+; CHECK: entry:
+; CHECK:   tail call i8* @llvm.objc.retain
+; CHECK: t:
+; CHECK:   call void @llvm.objc.release
+; CHECK: f:
+; CHECK:   call void @llvm.objc.release
+; CHECK: return:
+; CHECK: }
+define void @test6c(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  %ct = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %ct) nounwind
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @callee()
+  %cf = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cf) nounwind, !clang.imprecise_release !0
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test6d(
+; CHECK: entry:
+; CHECK:   tail call i8* @llvm.objc.retain
+; CHECK: t:
+; CHECK:   call void @llvm.objc.release
+; CHECK: f:
+; CHECK:   call void @llvm.objc.release
+; CHECK: return:
+; CHECK: }
+define void @test6d(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br i1 %p, label %t, label %f
+
+t:
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  %ct = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %ct) nounwind, !clang.imprecise_release !0
+  br label %return
+
+f:
+  store i32 7, i32* %x
+  call void @callee()
+  %cf = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cf) nounwind
+  br label %return
+
+return:
+  ret void
+}
+
+
+; retain+release pair deletion, where the retain happens on two different
+; flow paths.
+
+; CHECK-LABEL:     define void @test7(
+; CHECK:     entry:
+; CHECK-NOT:   llvm.objc.
+; CHECK:     t:
+; CHECK:       call i8* @llvm.objc.retain
+; CHECK:     f:
+; CHECK:       call i8* @llvm.objc.retain
+; CHECK:     return:
+; CHECK:       call void @llvm.objc.release
+; CHECK: }
+define void @test7(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  call void @callee()
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test7b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test7b(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  call void @callee()
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Like test7, but there's a retain/retainBlock mismatch. Don't delete!
+
+; CHECK-LABEL: define void @test7c(
+; CHECK: t:
+; CHECK:   call i8* @llvm.objc.retainBlock
+; CHECK: f:
+; CHECK:   call i8* @llvm.objc.retain
+; CHECK: return:
+; CHECK:   call void @llvm.objc.release
+; CHECK: }
+define void @test7c(i32* %x, i1 %p) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retainBlock(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %return
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  call void @callee()
+  br label %return
+
+return:
+  %c = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %c) nounwind
+  ret void
+}
+
+; retain+release pair deletion, where the retain and release both happen on
+; different flow paths. Wild!
+
+; CHECK-LABEL: define void @test8a(
+; CHECK: entry:
+; CHECK: t:
+; CHECK:   @llvm.objc.retain
+; CHECK: f:
+; CHECK:   @llvm.objc.retain
+; CHECK: mid:
+; CHECK: u:
+; CHECK:   @llvm.objc.release
+; CHECK: g:
+; CHECK:   @llvm.objc.release
+; CHECK: return:
+; CHECK: }
+define void @test8a(i32* %x, i1 %p, i1 %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %mid
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  br label %mid
+
+mid:
+  br i1 %q, label %u, label %g
+
+u:
+  call void @callee()
+  %cu = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cu) nounwind
+  br label %return
+
+g:
+  %cg = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cg) nounwind
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test8b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test8b(i32* %x, i1 %p, i1 %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %mid
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  br label %mid
+
+mid:
+  br i1 %q, label %u, label %g
+
+u:
+  call void @callee()
+  %cu = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cu) nounwind, !clang.imprecise_release !0
+  br label %return
+
+g:
+  %cg = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cg) nounwind, !clang.imprecise_release !0
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test8c(
+; CHECK: entry:
+; CHECK: t:
+; CHECK:   @llvm.objc.retain
+; CHECK: f:
+; CHECK:   @llvm.objc.retain
+; CHECK: mid:
+; CHECK: u:
+; CHECK:   @llvm.objc.release
+; CHECK: g:
+; CHECK:   @llvm.objc.release
+; CHECK: return:
+; CHECK: }
+define void @test8c(i32* %x, i1 %p, i1 %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %mid
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  br label %mid
+
+mid:
+  br i1 %q, label %u, label %g
+
+u:
+  call void @callee()
+  %cu = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cu) nounwind
+  br label %return
+
+g:
+  %cg = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cg) nounwind, !clang.imprecise_release !0
+  br label %return
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @test8d(
+; CHECK: entry:
+; CHECK: t:
+; CHECK:   @llvm.objc.retain
+; CHECK: f:
+; CHECK:   @llvm.objc.retain
+; CHECK: mid:
+; CHECK: u:
+; CHECK:   @llvm.objc.release
+; CHECK: g:
+; CHECK:   @llvm.objc.release
+; CHECK: return:
+; CHECK: }
+define void @test8d(i32* %x, i1 %p, i1 %q) nounwind {
+entry:
+  %a = bitcast i32* %x to i8*
+  br i1 %p, label %t, label %f
+
+t:
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8 3, i8* %a
+  %b = bitcast i32* %x to float*
+  store float 2.0, float* %b
+  br label %mid
+
+f:
+  %1 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i32 7, i32* %x
+  br label %mid
+
+mid:
+  br i1 %q, label %u, label %g
+
+u:
+  call void @callee()
+  %cu = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cu) nounwind, !clang.imprecise_release !0
+  br label %return
+
+g:
+  %cg = bitcast i32* %x to i8*
+  call void @llvm.objc.release(i8* %cg) nounwind
+  br label %return
+
+return:
+  ret void
+}
+
+; Trivial retain+release pair deletion.
+
+; CHECK-LABEL: define void @test9(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test9(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind
+  ret void
+}
+
+; Retain+release pair, but on an unknown pointer relationship. Don't delete!
+
+; CHECK-LABEL: define void @test9b(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.release(i8* %s)
+; CHECK: }
+define void @test9b(i8* %x, i1 %j, i8* %p) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  %s = select i1 %j, i8* %x, i8* %p
+  call void @llvm.objc.release(i8* %s) nounwind
+  ret void
+}
+
+; Trivial retain+release pair with intervening calls - don't delete!
+
+; CHECK-LABEL: define void @test10(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @callee
+; CHECK: @use_pointer
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test10(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @callee()
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %0) nounwind
+  ret void
+}
+
+; Trivial retain+autoreleaserelease pair. Don't delete!
+; Also, add a tail keyword, since llvm.objc.retain can never be passed
+; a stack argument.
+
+; CHECK-LABEL: define void @test11(
+; CHECK: tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK: call i8* @llvm.objc.autorelease(i8* %0) [[NUW]]
+; CHECK: }
+define void @test11(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autorelease(i8* %0) nounwind
+  call void @use_pointer(i8* %x)
+  ret void
+}
+
+; Same as test11 but with no use_pointer call. Delete the pair!
+
+; CHECK-LABEL: define void @test11a(
+; CHECK: entry:
+; CHECK-NEXT: ret void
+; CHECK: }
+define void @test11a(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autorelease(i8* %0) nounwind
+  ret void
+}
+
+; Same as test11 but the value is returned. Do not perform an RV optimization
+; since if the frontend emitted code for an __autoreleasing variable, we may
+; want it to be in the autorelease pool.
+
+; CHECK-LABEL: define i8* @test11b(
+; CHECK: tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK: call i8* @llvm.objc.autorelease(i8* %0) [[NUW]]
+; CHECK: }
+define i8* @test11b(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autorelease(i8* %0) nounwind
+  ret i8* %x
+}
+
+; We can not delete this retain, release since we do not have a post-dominating
+; use of the release.
+
+; CHECK-LABEL: define void @test12(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retain(i8* %x)
+; CHECK-NEXT: @llvm.objc.retain
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test12(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Trivial retain,autorelease pair. Don't delete!
+
+; CHECK-LABEL: define void @test13(
+; CHECK: tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK: tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK: @use_pointer(i8* %x)
+; CHECK: call i8* @llvm.objc.autorelease(i8* %x) [[NUW]]
+; CHECK: }
+define void @test13(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  ret void
+}
+
+; Delete the retain+release pair.
+
+; CHECK-LABEL: define void @test13b(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retain(i8* %x)
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test13b(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Don't delete the retain+release pair because there's an
+; autoreleasePoolPop in the way.
+
+; CHECK-LABEL: define void @test13c(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc.autoreleasePoolPop
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @use_pointer
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test13c(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @llvm.objc.autoreleasePoolPop(i8* undef)
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Like test13c, but there's an autoreleasePoolPush in the way, but that
+; doesn't matter.
+
+; CHECK-LABEL: define void @test13d(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retain(i8* %x)
+; CHECK-NEXT: @llvm.objc.autoreleasePoolPush
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test13d(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autoreleasePoolPush()
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Trivial retain,release pair with intervening call, and it's post-dominated by
+; another release. But it is not known safe in the top down direction. We can
+; not eliminate it.
+
+; CHECK-LABEL: define void @test14(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retain
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test14(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Trivial retain,autorelease pair with intervening call, but it's post-dominated
+; by another release. Don't delete anything.
+
+; CHECK-LABEL: define void @test15(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retain(i8* %x)
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @llvm.objc.autorelease(i8* %x)
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test15(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Trivial retain,autorelease pair, post-dominated
+; by another release. Delete the retain and release.
+
+; CHECK-LABEL: define void @test15b(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retain
+; CHECK-NEXT: @llvm.objc.autorelease
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test15b(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test15c(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.autorelease
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test15c(i8* %x, i64 %n) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Retain+release pairs in diamonds, all dominated by a retain.
+
+; CHECK-LABEL: define void @test16a(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK-NOT: @objc
+; CHECK: purple:
+; CHECK: @use_pointer
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test16a(i1 %a, i1 %b, i8* %x) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br i1 %a, label %red, label %orange
+
+red:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+orange:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+yellow:
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  br i1 %b, label %green, label %blue
+
+green:
+  call void @llvm.objc.release(i8* %x) nounwind
+  br label %purple
+
+blue:
+  call void @llvm.objc.release(i8* %x) nounwind
+  br label %purple
+
+purple:
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test16b(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK-NOT: @objc
+; CHECK: purple:
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @llvm.objc.release
+; CHECK: }
+define void @test16b(i1 %a, i1 %b, i8* %x) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br i1 %a, label %red, label %orange
+
+red:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+orange:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+yellow:
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  br i1 %b, label %green, label %blue
+
+green:
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  br label %purple
+
+blue:
+  call void @llvm.objc.release(i8* %x) nounwind
+  br label %purple
+
+purple:
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test16c(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK-NOT: @objc
+; CHECK: purple:
+; CHECK: @use_pointer
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test16c(i1 %a, i1 %b, i8* %x) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br i1 %a, label %red, label %orange
+
+red:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+orange:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+yellow:
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  br i1 %b, label %green, label %blue
+
+green:
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  br label %purple
+
+blue:
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  br label %purple
+
+purple:
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK-LABEL: define void @test16d(
+; CHECK: @llvm.objc.retain(i8* %x)
+; CHECK: @llvm.objc
+; CHECK: }
+define void @test16d(i1 %a, i1 %b, i8* %x) {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br i1 %a, label %red, label %orange
+
+red:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+orange:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  br label %yellow
+
+yellow:
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  br i1 %b, label %green, label %blue
+
+green:
+  call void @llvm.objc.release(i8* %x) nounwind
+  br label %purple
+
+blue:
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  br label %purple
+
+purple:
+  ret void
+}
+
+; Delete no-ops.
+
+; CHECK-LABEL: define void @test18(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test18() {
+  call i8* @llvm.objc.retain(i8* null)
+  call void @llvm.objc.release(i8* null)
+  call i8* @llvm.objc.autorelease(i8* null)
+  ret void
+}
+
+; Delete no-ops where undef can be assumed to be null.
+
+; CHECK-LABEL: define void @test18b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test18b() {
+  call i8* @llvm.objc.retain(i8* undef)
+  call void @llvm.objc.release(i8* undef)
+  call i8* @llvm.objc.autorelease(i8* undef)
+  ret void
+}
+
+; Replace uses of arguments with uses of return values, to reduce
+; register pressure.
+
+; CHECK: define void @test19(i32* %y) {
+; CHECK:   %z = bitcast i32* %y to i8*
+; CHECK:   %0 = bitcast i32* %y to i8*
+; CHECK:   %1 = tail call i8* @llvm.objc.retain(i8* %0)
+; CHECK:   call void @use_pointer(i8* %z)
+; CHECK:   call void @use_pointer(i8* %z)
+; CHECK:   %2 = bitcast i32* %y to i8*
+; CHECK:   call void @llvm.objc.release(i8* %2)
+; CHECK:   ret void
+; CHECK: }
+define void @test19(i32* %y) {
+entry:
+  %x = bitcast i32* %y to i8*
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  %z = bitcast i32* %y to i8*
+  call void @use_pointer(i8* %z)
+  call void @use_pointer(i8* %z)
+  call void @llvm.objc.release(i8* %x)
+  ret void
+}
+
+; Bitcast insertion
+
+; CHECK-LABEL: define void @test20(
+; CHECK: %tmp1 = tail call i8* @llvm.objc.retain(i8* %tmp) [[NUW]]
+; CHECK-NEXT: invoke
+; CHECK: }
+define void @test20(double* %self) personality i32 (...)* @__gxx_personality_v0 {
+if.then12:
+  %tmp = bitcast double* %self to i8*
+  %tmp1 = call i8* @llvm.objc.retain(i8* %tmp) nounwind
+  invoke void @invokee()
+          to label %invoke.cont23 unwind label %lpad20
+
+invoke.cont23:                                    ; preds = %if.then12
+  invoke void @invokee()
+          to label %if.end unwind label %lpad20
+
+lpad20:                                           ; preds = %invoke.cont23, %if.then12
+  %tmp502 = phi double* [ undef, %invoke.cont23 ], [ %self, %if.then12 ]
+  %exn = landingpad {i8*, i32}
+           cleanup
+  unreachable
+
+if.end:                                           ; preds = %invoke.cont23
+  ret void
+}
+
+; Delete a redundant retain,autorelease when forwaring a call result
+; directly to a return value.
+
+; CHECK-LABEL: define i8* @test21(
+; CHECK: call i8* @returner()
+; CHECK-NEXT: ret i8* %call
+; CHECK-NEXT: }
+define i8* @test21() {
+entry:
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retain(i8* %call) nounwind
+  %1 = call i8* @llvm.objc.autorelease(i8* %0) nounwind
+  ret i8* %1
+}
+
+; Move an objc call up through a phi that has null operands.
+
+; CHECK-LABEL: define void @test22(
+; CHECK: B:
+; CHECK:   %1 = bitcast double* %p to i8*
+; CHECK:   call void @llvm.objc.release(i8* %1)
+; CHECK:   br label %C
+; CHECK: C:                                                ; preds = %B, %A
+; CHECK-NOT: @llvm.objc.release
+; CHECK: }
+define void @test22(double* %p, i1 %a) {
+  br i1 %a, label %A, label %B
+A:
+  br label %C
+B:
+  br label %C
+C:
+  %h = phi double* [ null, %A ], [ %p, %B ]
+  %c = bitcast double* %h to i8*
+  call void @llvm.objc.release(i8* %c), !clang.imprecise_release !0
+  ret void
+}
+
+; Do not move an llvm.objc.release that doesn't have the clang.imprecise_release tag.
+
+; CHECK-LABEL: define void @test22_precise(
+; CHECK: %[[P0:.*]] = phi double*
+; CHECK: %[[V0:.*]] = bitcast double* %[[P0]] to i8*
+; CHECK: call void @llvm.objc.release(i8* %[[V0]])
+; CHECK: ret void
+define void @test22_precise(double* %p, i1 %a) {
+  br i1 %a, label %A, label %B
+A:
+  br label %C
+B:
+  br label %C
+C:
+  %h = phi double* [ null, %A ], [ %p, %B ]
+  %c = bitcast double* %h to i8*
+  call void @llvm.objc.release(i8* %c)
+  ret void
+}
+
+; Any call can decrement a retain count.
+
+; CHECK-LABEL: define void @test24(
+; CHECK: @llvm.objc.retain(i8* %a)
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test24(i8* %r, i8* %a) {
+  call i8* @llvm.objc.retain(i8* %a)
+  call void @use_pointer(i8* %r)
+  %q = load i8, i8* %a
+  call void @llvm.objc.release(i8* %a)
+  ret void
+}
+
+; Don't move a retain/release pair if the release can be moved
+; but the retain can't be moved to balance it.
+
+; CHECK-LABEL: define void @test25(
+; CHECK: entry:
+; CHECK:   call i8* @llvm.objc.retain(i8* %p)
+; CHECK: true:
+; CHECK: done:
+; CHECK:   call void @llvm.objc.release(i8* %p)
+; CHECK: }
+define void @test25(i8* %p, i1 %x) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  br i1 %x, label %true, label %done
+
+true:
+  store i8 0, i8* %p
+  br label %done
+
+done:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Don't move a retain/release pair if the retain can be moved
+; but the release can't be moved to balance it.
+
+; CHECK-LABEL: define void @test26(
+; CHECK: entry:
+; CHECK:   call i8* @llvm.objc.retain(i8* %p)
+; CHECK: true:
+; CHECK: done:
+; CHECK:   call void @llvm.objc.release(i8* %p)
+; CHECK: }
+define void @test26(i8* %p, i1 %x) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  br label %done
+
+done:
+  store i8 0, i8* %p
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Don't sink the retain,release into the loop.
+
+; CHECK-LABEL: define void @test27(
+; CHECK: entry:
+; CHECK: call i8* @llvm.objc.retain(i8* %p)
+; CHECK: loop:
+; CHECK-NOT: @llvm.objc.
+; CHECK: done:
+; CHECK: call void @llvm.objc.release
+; CHECK: }
+define void @test27(i8* %p, i1 %x, i1 %y) {
+entry: 
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %loop, label %done
+
+loop:
+  call void @callee()
+  store i8 0, i8* %p
+  br i1 %y, label %done, label %loop
+  
+done: 
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Trivial code motion case: Triangle.
+
+; CHECK-LABEL: define void @test28(
+; CHECK-NOT: @llvm.objc.
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: store
+; CHECK: call void @llvm.objc.release
+; CHECK: done:
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test28(i8* %p, i1 %x) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  store i8 0, i8* %p
+  br label %done
+
+done:
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+; Trivial code motion case: Triangle, but no metadata. Don't move past
+; unrelated memory references!
+
+; CHECK-LABEL: define void @test28b(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: true:
+; CHECK-NOT: @llvm.objc.
+; CHECK: call void @callee()
+; CHECK-NOT: @llvm.objc.
+; CHECK: store
+; CHECK-NOT: @llvm.objc.
+; CHECK: done:
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test28b(i8* %p, i1 %x, i8* noalias %t) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  store i8 0, i8* %p
+  br label %done
+
+done:
+  store i8 0, i8* %t
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Trivial code motion case: Triangle, with metadata. Do move past
+; unrelated memory references! And preserve the metadata.
+
+; CHECK-LABEL: define void @test28c(
+; CHECK-NOT: @llvm.objc.
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: store
+; CHECK: call void @llvm.objc.release(i8* %p) [[NUW]], !clang.imprecise_release
+; CHECK: done:
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test28c(i8* %p, i1 %x, i8* noalias %t) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  store i8 0, i8* %p
+  br label %done
+
+done:
+  store i8 0, i8* %t
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+; Like test28. but with two releases.
+
+; CHECK-LABEL: define void @test29(
+; CHECK-NOT: @llvm.objc.
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: store
+; CHECK: call void @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: done:
+; CHECK-NOT: @llvm.objc.
+; CHECK: ohno:
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test29(i8* %p, i1 %x, i1 %y) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  store i8 0, i8* %p
+  br i1 %y, label %done, label %ohno
+
+done:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+
+ohno:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Basic case with the use and call in a diamond
+; with an extra release.
+
+; CHECK-LABEL: define void @test30(
+; CHECK-NOT: @llvm.objc.
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: store
+; CHECK: call void @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: false:
+; CHECK-NOT: @llvm.objc.
+; CHECK: done:
+; CHECK-NOT: @llvm.objc.
+; CHECK: ohno:
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test30(i8* %p, i1 %x, i1 %y, i1 %z) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %false
+
+true:
+  call void @callee()
+  store i8 0, i8* %p
+  br i1 %y, label %done, label %ohno
+
+false:
+  br i1 %z, label %done, label %ohno
+
+done:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+
+ohno:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Basic case with a mergeable release.
+
+; CHECK-LABEL: define void @test31(
+; CHECK: call i8* @llvm.objc.retain(i8* %p)
+; CHECK: call void @callee()
+; CHECK: store
+; CHECK: call void @llvm.objc.release
+; CHECK-NOT: @llvm.objc.release
+; CHECK: true:
+; CHECK-NOT: @llvm.objc.release
+; CHECK: false:
+; CHECK-NOT: @llvm.objc.release
+; CHECK: ret void
+; CHECK-NOT: @llvm.objc.release
+; CHECK: }
+define void @test31(i8* %p, i1 %x) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  store i8 0, i8* %p
+  br i1 %x, label %true, label %false
+true:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+false:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Don't consider bitcasts or getelementptrs direct uses.
+
+; CHECK-LABEL: define void @test32(
+; CHECK-NOT: @llvm.objc.
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: store
+; CHECK: call void @llvm.objc.release
+; CHECK: done:
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test32(i8* %p, i1 %x) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  store i8 0, i8* %p
+  br label %done
+
+done:
+  %g = bitcast i8* %p to i8*
+  %h = getelementptr i8, i8* %g, i64 0
+  call void @llvm.objc.release(i8* %g)
+  ret void
+}
+
+; Do consider icmps to be direct uses.
+
+; CHECK-LABEL: define void @test33(
+; CHECK-NOT: @llvm.objc.
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: icmp
+; CHECK: call void @llvm.objc.release
+; CHECK: done:
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test33(i8* %p, i1 %x, i8* %y) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  %v = icmp eq i8* %p, %y
+  br label %done
+
+done:
+  %g = bitcast i8* %p to i8*
+  %h = getelementptr i8, i8* %g, i64 0
+  call void @llvm.objc.release(i8* %g)
+  ret void
+}
+
+; Delete retain,release if there's just a possible dec and we have imprecise
+; releases.
+
+; CHECK-LABEL: define void @test34a(
+; CHECK:   call i8* @llvm.objc.retain
+; CHECK: true:
+; CHECK: done:
+; CHECK: call void @llvm.objc.release
+; CHECK: }
+define void @test34a(i8* %p, i1 %x, i8* %y) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  br label %done
+
+done:
+  %g = bitcast i8* %p to i8*
+  %h = getelementptr i8, i8* %g, i64 0
+  call void @llvm.objc.release(i8* %g)
+  ret void
+}
+
+; CHECK-LABEL: define void @test34b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test34b(i8* %p, i1 %x, i8* %y) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  call void @callee()
+  br label %done
+
+done:
+  %g = bitcast i8* %p to i8*
+  %h = getelementptr i8, i8* %g, i64 0
+  call void @llvm.objc.release(i8* %g), !clang.imprecise_release !0
+  ret void
+}
+
+
+; Delete retain,release if there's just a use and we do not have a precise
+; release.
+
+; Precise.
+; CHECK-LABEL: define void @test35a(
+; CHECK: entry:
+; CHECK:   call i8* @llvm.objc.retain
+; CHECK: true:
+; CHECK: done:
+; CHECK:   call void @llvm.objc.release
+; CHECK: }
+define void @test35a(i8* %p, i1 %x, i8* %y) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  %v = icmp eq i8* %p, %y
+  br label %done
+
+done:
+  %g = bitcast i8* %p to i8*
+  %h = getelementptr i8, i8* %g, i64 0
+  call void @llvm.objc.release(i8* %g)
+  ret void
+}
+
+; Imprecise.
+; CHECK-LABEL: define void @test35b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test35b(i8* %p, i1 %x, i8* %y) {
+entry:
+  %f0 = call i8* @llvm.objc.retain(i8* %p)
+  br i1 %x, label %true, label %done
+
+true:
+  %v = icmp eq i8* %p, %y
+  br label %done
+
+done:
+  %g = bitcast i8* %p to i8*
+  %h = getelementptr i8, i8* %g, i64 0
+  call void @llvm.objc.release(i8* %g), !clang.imprecise_release !0
+  ret void
+}
+
+; Delete a retain,release if there's no actual use and we have precise release.
+
+; CHECK-LABEL: define void @test36a(
+; CHECK: @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK-NOT: @llvm.objc.
+; CHECK: call void @callee()
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test36a(i8* %p) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  call void @callee()
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Like test36, but with metadata.
+
+; CHECK-LABEL: define void @test36b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test36b(i8* %p) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  call void @callee()
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+; Be aggressive about analyzing phis to eliminate possible uses.
+
+; CHECK-LABEL: define void @test38(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test38(i8* %p, i1 %u, i1 %m, i8* %z, i8* %y, i8* %x, i8* %w) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  br i1 %u, label %true, label %false
+true:
+  br i1 %m, label %a, label %b
+false:
+  br i1 %m, label %c, label %d
+a:
+  br label %e
+b:
+  br label %e
+c:
+  br label %f
+d:
+  br label %f
+e:
+  %j = phi i8* [ %z, %a ], [ %y, %b ]
+  br label %g
+f:
+  %k = phi i8* [ %w, %c ], [ %x, %d ]
+  br label %g
+g:
+  %h = phi i8* [ %j, %e ], [ %k, %f ]
+  call void @use_pointer(i8* %h)
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+; Delete retain,release pairs around loops.
+
+; CHECK-LABEL: define void @test39(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test39(i8* %p) {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %p)
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  br i1 undef, label %loop, label %exit
+
+exit:                                             ; preds = %loop
+  call void @llvm.objc.release(i8* %0), !clang.imprecise_release !0
+  ret void
+}
+
+; Delete retain,release pairs around loops containing uses.
+
+; CHECK-LABEL: define void @test39b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test39b(i8* %p) {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %p)
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  store i8 0, i8* %0
+  br i1 undef, label %loop, label %exit
+
+exit:                                             ; preds = %loop
+  call void @llvm.objc.release(i8* %0), !clang.imprecise_release !0
+  ret void
+}
+
+; Delete retain,release pairs around loops containing potential decrements.
+
+; CHECK-LABEL: define void @test39c(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test39c(i8* %p) {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %p)
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  call void @use_pointer(i8* %0)
+  br i1 undef, label %loop, label %exit
+
+exit:                                             ; preds = %loop
+  call void @llvm.objc.release(i8* %0), !clang.imprecise_release !0
+  ret void
+}
+
+; Delete retain,release pairs around loops even if
+; the successors are in a different order.
+
+; CHECK-LABEL: define void @test40(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test40(i8* %p) {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %p)
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  call void @use_pointer(i8* %0)
+  br i1 undef, label %exit, label %loop
+
+exit:                                             ; preds = %loop
+  call void @llvm.objc.release(i8* %0), !clang.imprecise_release !0
+  ret void
+}
+
+; Do the known-incremented retain+release elimination even if the pointer
+; is also autoreleased.
+
+; CHECK-LABEL: define void @test42(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @llvm.objc.release(i8* %p)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test42(i8* %p) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  call i8* @llvm.objc.autorelease(i8* %p)
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @llvm.objc.release(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Don't the known-incremented retain+release elimination if the pointer is
+; autoreleased and there's an autoreleasePoolPop.
+
+; CHECK-LABEL: define void @test43(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.retain
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @llvm.objc.autoreleasePoolPop(i8* undef)
+; CHECK-NEXT: call void @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test43(i8* %p) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  call i8* @llvm.objc.autorelease(i8* %p)
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @llvm.objc.autoreleasePoolPop(i8* undef)
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Do the known-incremented retain+release elimination if the pointer is
+; autoreleased and there's an autoreleasePoolPush.
+
+; CHECK-LABEL: define void @test43b(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.autoreleasePoolPush()
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK-NEXT: call void @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test43b(i8* %p) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  call i8* @llvm.objc.autorelease(i8* %p)
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @use_pointer(i8* %p)
+  call i8* @llvm.objc.autoreleasePoolPush()
+  call void @llvm.objc.release(i8* %p)
+  call void @use_pointer(i8* %p)
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Do retain+release elimination for non-provenance pointers.
+
+; CHECK-LABEL: define void @test44(
+; CHECK-NOT: llvm.objc.
+; CHECK: }
+define void @test44(i8** %pp) {
+  %p = load i8*, i8** %pp
+  %q = call i8* @llvm.objc.retain(i8* %p)
+  call void @llvm.objc.release(i8* %q)
+  ret void
+}
+
+; Don't delete retain+release with an unknown-provenance
+; may-alias llvm.objc.release between them.
+
+; CHECK-LABEL: define void @test45(
+; CHECK: call i8* @llvm.objc.retain(i8* %p)
+; CHECK: call void @llvm.objc.release(i8* %q)
+; CHECK: call void @use_pointer(i8* %p)
+; CHECK: call void @llvm.objc.release(i8* %p)
+; CHECK: }
+define void @test45(i8** %pp, i8** %qq) {
+  %p = load i8*, i8** %pp
+  %q = load i8*, i8** %qq
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @llvm.objc.release(i8* %q)
+  call void @use_pointer(i8* %p)
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Don't delete retain and autorelease here.
+
+; CHECK-LABEL: define void @test46(
+; CHECK: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
+; CHECK: }
+define void @test46(i8* %p, i1 %a) {
+entry:
+  call i8* @llvm.objc.retain(i8* %p)
+  br i1 %a, label %true, label %false
+
+true:
+  call i8* @llvm.objc.autorelease(i8* %p)
+  call void @use_pointer(i8* %p)
+  ret void
+
+false:
+  ret void
+}
+
+; Delete no-op cast calls.
+
+; CHECK-LABEL: define i8* @test47(
+; CHECK-NOT: call
+; CHECK: ret i8* %p
+; CHECK: }
+define i8* @test47(i8* %p) nounwind {
+  %x = call i8* @llvm.objc.retainedObject(i8* %p)
+  ret i8* %x
+}
+
+; Delete no-op cast calls.
+
+; CHECK-LABEL: define i8* @test48(
+; CHECK-NOT: call
+; CHECK: ret i8* %p
+; CHECK: }
+define i8* @test48(i8* %p) nounwind {
+  %x = call i8* @llvm.objc.unretainedObject(i8* %p)
+  ret i8* %x
+}
+
+; Delete no-op cast calls.
+
+; CHECK-LABEL: define i8* @test49(
+; CHECK-NOT: call
+; CHECK: ret i8* %p
+; CHECK: }
+define i8* @test49(i8* %p) nounwind {
+  %x = call i8* @llvm.objc.unretainedPointer(i8* %p)
+  ret i8* %x
+}
+
+; Do delete retain+release with intervening stores of the address value if we
+; have imprecise release attached to llvm.objc.release.
+
+; CHECK-LABEL:      define void @test50a(
+; CHECK-NEXT:   call i8* @llvm.objc.retain
+; CHECK-NEXT:   call void @callee
+; CHECK-NEXT:   store
+; CHECK-NEXT:   call void @llvm.objc.release
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test50a(i8* %p, i8** %pp) {
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  store i8* %p, i8** %pp
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; CHECK-LABEL: define void @test50b(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test50b(i8* %p, i8** %pp) {
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  store i8* %p, i8** %pp
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+
+; Don't delete retain+release with intervening stores through the
+; address value.
+
+; CHECK-LABEL: define void @test51a(
+; CHECK: call i8* @llvm.objc.retain(i8* %p)
+; CHECK: call void @llvm.objc.release(i8* %p)
+; CHECK: ret void
+; CHECK: }
+define void @test51a(i8* %p) {
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  store i8 0, i8* %p
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; CHECK-LABEL: define void @test51b(
+; CHECK: call i8* @llvm.objc.retain(i8* %p)
+; CHECK: call void @llvm.objc.release(i8* %p)
+; CHECK: ret void
+; CHECK: }
+define void @test51b(i8* %p) {
+  call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  store i8 0, i8* %p
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+; Don't delete retain+release with intervening use of a pointer of
+; unknown provenance.
+
+; CHECK-LABEL: define void @test52a(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: call void @use_pointer(i8* %z)
+; CHECK: call void @llvm.objc.release
+; CHECK: ret void
+; CHECK: }
+define void @test52a(i8** %zz, i8** %pp) {
+  %p = load i8*, i8** %pp
+  %1 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  %z = load i8*, i8** %zz
+  call void @use_pointer(i8* %z)
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; CHECK-LABEL: define void @test52b(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @callee()
+; CHECK: call void @use_pointer(i8* %z)
+; CHECK: call void @llvm.objc.release
+; CHECK: ret void
+; CHECK: }
+define void @test52b(i8** %zz, i8** %pp) {
+  %p = load i8*, i8** %pp
+  %1 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  %z = load i8*, i8** %zz
+  call void @use_pointer(i8* %z)
+  call void @llvm.objc.release(i8* %p), !clang.imprecise_release !0
+  ret void
+}
+
+; Like test52, but the pointer has function type, so it's assumed to
+; be not reference counted.
+; Oops. That's wrong. Clang sometimes uses function types gratuitously.
+; See rdar://10551239.
+
+; CHECK-LABEL: define void @test53(
+; CHECK: @llvm.objc.
+; CHECK: }
+define void @test53(void ()** %zz, i8** %pp) {
+  %p = load i8*, i8** %pp
+  %1 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  %z = load void ()*, void ()** %zz
+  call void @callee_fnptr(void ()* %z)
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Convert autorelease to release if the value is unused.
+
+; CHECK-LABEL: define void @test54(
+; CHECK: call i8* @returner()
+; CHECK-NEXT: call void @llvm.objc.release(i8* %t) [[NUW]], !clang.imprecise_release ![[RELEASE]]
+; CHECK-NEXT: ret void
+; CHECK: }
+define void @test54() {
+  %t = call i8* @returner()
+  call i8* @llvm.objc.autorelease(i8* %t)
+  ret void
+}
+
+; Nested retain+release pairs. Delete them both.
+
+; CHECK-LABEL: define void @test55(
+; CHECK-NOT: @objc
+; CHECK: }
+define void @test55(i8* %x) { 
+entry: 
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind 
+  %1 = call i8* @llvm.objc.retain(i8* %x) nounwind 
+  call void @llvm.objc.release(i8* %x) nounwind 
+  call void @llvm.objc.release(i8* %x) nounwind 
+  ret void 
+}
+
+; Nested retain+release pairs where the inner pair depends
+; on the outer pair to be removed, and then the outer pair
+; can be partially eliminated. Plus an extra outer pair to
+; eliminate, for fun.
+
+; CHECK-LABEL: define void @test56(
+; CHECK-NOT: @objc
+; CHECK: if.then:
+; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK-NEXT: tail call void @use_pointer(i8* %x)
+; CHECK-NEXT: tail call void @use_pointer(i8* %x)
+; CHECK-NEXT: tail call void @llvm.objc.release(i8* %x) [[NUW]], !clang.imprecise_release ![[RELEASE]]
+; CHECK-NEXT: br label %if.end
+; CHECK-NOT: @objc
+; CHECK: }
+define void @test56(i8* %x, i32 %n) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  %1 = tail call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tobool = icmp eq i32 %n, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %2 = tail call i8* @llvm.objc.retain(i8* %1) nounwind
+  tail call void @use_pointer(i8* %2)
+  tail call void @use_pointer(i8* %2)
+  tail call void @llvm.objc.release(i8* %2) nounwind, !clang.imprecise_release !0
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  tail call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  tail call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; When there are adjacent retain+release pairs, the first one is known
+; unnecessary because the presence of the second one means that the first one
+; won't be deleting the object.
+
+; CHECK-LABEL:      define void @test57(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %x) [[NUW]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test57(i8* %x) nounwind {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; An adjacent retain+release pair is sufficient even if it will be
+; removed itself.
+
+; CHECK-LABEL:      define void @test58(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   @llvm.objc.retain
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test58(i8* %x) nounwind {
+entry:
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Don't delete the second retain+release pair in an adjacent set.
+
+; CHECK-LABEL:      define void @test59(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %x) [[NUW]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test59(i8* %x) nounwind {
+entry:
+  %a = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind
+  %b = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call void @use_pointer(i8* %x)
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Constant pointers to objects don't need reference counting.
+
+ at constptr = external constant i8*
+ at something = external global i8*
+
+; We have a precise lifetime retain/release here. We can not remove them since
+; @something is not constant.
+
+; CHECK-LABEL: define void @test60a(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void @llvm.objc.release
+; CHECK: }
+define void @test60a() {
+  %t = load i8*, i8** @constptr
+  %s = load i8*, i8** @something
+  call i8* @llvm.objc.retain(i8* %s)
+  call void @callee()
+  call void @use_pointer(i8* %t)
+  call void @llvm.objc.release(i8* %s)
+  ret void
+}
+
+; CHECK-LABEL: define void @test60b(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK-NOT: call i8* @llvm.objc.retain
+; CHECK-NOT: call i8* @llvm.objc.release
+; CHECK: }
+define void @test60b() {
+  %t = load i8*, i8** @constptr
+  %s = load i8*, i8** @something
+  call i8* @llvm.objc.retain(i8* %t)
+  call i8* @llvm.objc.retain(i8* %t)
+  call void @callee()
+  call void @use_pointer(i8* %s)
+  call void @llvm.objc.release(i8* %t)
+  ret void
+}
+
+; CHECK-LABEL: define void @test60c(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test60c() {
+  %t = load i8*, i8** @constptr
+  %s = load i8*, i8** @something
+  call i8* @llvm.objc.retain(i8* %t)
+  call void @callee()
+  call void @use_pointer(i8* %s)
+  call void @llvm.objc.release(i8* %t), !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK-LABEL: define void @test60d(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test60d() {
+  %t = load i8*, i8** @constptr
+  %s = load i8*, i8** @something
+  call i8* @llvm.objc.retain(i8* %t)
+  call void @callee()
+  call void @use_pointer(i8* %s)
+  call void @llvm.objc.release(i8* %t)
+  ret void
+}
+
+; CHECK-LABEL: define void @test60e(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test60e() {
+  %t = load i8*, i8** @constptr
+  %s = load i8*, i8** @something
+  call i8* @llvm.objc.retain(i8* %t)
+  call void @callee()
+  call void @use_pointer(i8* %s)
+  call void @llvm.objc.release(i8* %t), !clang.imprecise_release !0
+  ret void
+}
+
+; Constant pointers to objects don't need to be considered related to other
+; pointers.
+
+; CHECK-LABEL: define void @test61(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test61() {
+  %t = load i8*, i8** @constptr
+  call i8* @llvm.objc.retain(i8* %t)
+  call void @callee()
+  call void @use_pointer(i8* %t)
+  call void @llvm.objc.release(i8* %t)
+  ret void
+}
+
+; Delete a retain matched by releases when one is inside the loop and the
+; other is outside the loop.
+
+; CHECK-LABEL: define void @test62(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test62(i8* %x, i1* %p) nounwind {
+entry:
+  br label %loop
+
+loop:
+  call i8* @llvm.objc.retain(i8* %x)
+  %q = load i1, i1* %p
+  br i1 %q, label %loop.more, label %exit
+
+loop.more:
+  call void @llvm.objc.release(i8* %x)
+  br label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %x)
+  ret void
+}
+
+; Like test62 but with no release in exit.
+; Don't delete anything!
+
+; CHECK-LABEL: define void @test63(
+; CHECK: loop:
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %x)
+; CHECK: loop.more:
+; CHECK:   call void @llvm.objc.release(i8* %x)
+; CHECK: }
+define void @test63(i8* %x, i1* %p) nounwind {
+entry:
+  br label %loop
+
+loop:
+  call i8* @llvm.objc.retain(i8* %x)
+  %q = load i1, i1* %p
+  br i1 %q, label %loop.more, label %exit
+
+loop.more:
+  call void @llvm.objc.release(i8* %x)
+  br label %loop
+
+exit:
+  ret void
+}
+
+; Like test62 but with no release in loop.more.
+; Don't delete anything!
+
+; CHECK-LABEL: define void @test64(
+; CHECK: loop:
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %x)
+; CHECK: exit:
+; CHECK:   call void @llvm.objc.release(i8* %x)
+; CHECK: }
+define void @test64(i8* %x, i1* %p) nounwind {
+entry:
+  br label %loop
+
+loop:
+  call i8* @llvm.objc.retain(i8* %x)
+  %q = load i1, i1* %p
+  br i1 %q, label %loop.more, label %exit
+
+loop.more:
+  br label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %x)
+  ret void
+}
+
+; Move an autorelease past a phi with a null.
+
+; CHECK-LABEL: define i8* @test65(
+; CHECK: if.then:
+; CHECK:   call i8* @llvm.objc.autorelease(
+; CHECK: return:
+; CHECK-NOT: @llvm.objc.autorelease
+; CHECK: }
+define i8* @test65(i1 %x) {
+entry:
+  br i1 %x, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %c = call i8* @returner()
+  %s = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %c) nounwind
+  br label %return
+
+return:                                           ; preds = %if.then, %entry
+  %retval = phi i8* [ %s, %if.then ], [ null, %entry ]
+  %q = call i8* @llvm.objc.autorelease(i8* %retval) nounwind
+  ret i8* %retval
+}
+
+; Don't move an autorelease past an autorelease pool boundary.
+
+; CHECK-LABEL: define i8* @test65b(
+; CHECK: if.then:
+; CHECK-NOT: @llvm.objc.autorelease
+; CHECK: return:
+; CHECK:   call i8* @llvm.objc.autorelease(
+; CHECK: }
+define i8* @test65b(i1 %x) {
+entry:
+  %t = call i8* @llvm.objc.autoreleasePoolPush()
+  br i1 %x, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %c = call i8* @returner()
+  %s = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %c) nounwind
+  br label %return
+
+return:                                           ; preds = %if.then, %entry
+  %retval = phi i8* [ %s, %if.then ], [ null, %entry ]
+  call void @llvm.objc.autoreleasePoolPop(i8* %t)
+  %q = call i8* @llvm.objc.autorelease(i8* %retval) nounwind
+  ret i8* %retval
+}
+
+; Don't move an autoreleaseReuturnValue, which would break
+; the RV optimization.
+
+; CHECK-LABEL: define i8* @test65c(
+; CHECK: if.then:
+; CHECK-NOT: @llvm.objc.autorelease
+; CHECK: return:
+; CHECK:   call i8* @llvm.objc.autoreleaseReturnValue(
+; CHECK: }
+define i8* @test65c(i1 %x) {
+entry:
+  br i1 %x, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %c = call i8* @returner()
+  %s = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %c) nounwind
+  br label %return
+
+return:                                           ; preds = %if.then, %entry
+  %retval = phi i8* [ %s, %if.then ], [ null, %entry ]
+  %q = call i8* @llvm.objc.autoreleaseReturnValue(i8* %retval) nounwind
+  ret i8* %retval
+}
+
+; CHECK-LABEL: define i8* @test65d(
+; CHECK: if.then:
+; CHECK-NOT: @llvm.objc.autorelease
+; CHECK: return:
+; CHECK:   call i8* @llvm.objc.autoreleaseReturnValue(
+; CHECK: }
+define i8* @test65d(i1 %x) {
+entry:
+  br i1 %x, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %c = call i8* @returner()
+  %s = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %c) nounwind
+  br label %return
+
+return:                                           ; preds = %if.then, %entry
+  %retval = phi i8* [ %s, %if.then ], [ null, %entry ]
+  %q = call i8* @llvm.objc.autoreleaseReturnValue(i8* %retval) nounwind
+  ret i8* %retval
+}
+
+; An llvm.objc.retain can serve as a may-use for a different pointer.
+; rdar://11931823
+
+; CHECK-LABEL: define void @test66a(
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %cond) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %call) [[NUW]]
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %tmp8) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %cond) [[NUW]]
+; CHECK: }
+define void @test66a(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) {
+entry:
+  br i1 %tobool, label %cond.true, label %cond.end
+
+cond.true:
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.true, %entry
+  %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ]
+  %tmp7 = tail call i8* @llvm.objc.retain(i8* %cond) nounwind
+  tail call void @llvm.objc.release(i8* %call) nounwind
+  %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar
+  %tmp9 = tail call i8* @llvm.objc.retain(i8* %tmp8) nounwind
+  tail call void @llvm.objc.release(i8* %cond) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test66b(
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %cond) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %call) [[NUW]]
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %tmp8) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %cond) [[NUW]]
+; CHECK: }
+define void @test66b(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) {
+entry:
+  br i1 %tobool, label %cond.true, label %cond.end
+
+cond.true:
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.true, %entry
+  %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ]
+  %tmp7 = tail call i8* @llvm.objc.retain(i8* %cond) nounwind
+  tail call void @llvm.objc.release(i8* %call) nounwind, !clang.imprecise_release !0
+  %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar
+  %tmp9 = tail call i8* @llvm.objc.retain(i8* %tmp8) nounwind
+  tail call void @llvm.objc.release(i8* %cond) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test66c(
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %cond) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %call) [[NUW]]
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %tmp8) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %cond) [[NUW]]
+; CHECK: }
+define void @test66c(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) {
+entry:
+  br i1 %tobool, label %cond.true, label %cond.end
+
+cond.true:
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.true, %entry
+  %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ]
+  %tmp7 = tail call i8* @llvm.objc.retain(i8* %cond) nounwind
+  tail call void @llvm.objc.release(i8* %call) nounwind
+  %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar
+  %tmp9 = tail call i8* @llvm.objc.retain(i8* %tmp8) nounwind, !clang.imprecise_release !0
+  tail call void @llvm.objc.release(i8* %cond) nounwind
+  ret void
+}
+
+; CHECK-LABEL: define void @test66d(
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %cond) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %call) [[NUW]]
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %tmp8) [[NUW]]
+; CHECK:   tail call void @llvm.objc.release(i8* %cond) [[NUW]]
+; CHECK: }
+define void @test66d(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) {
+entry:
+  br i1 %tobool, label %cond.true, label %cond.end
+
+cond.true:
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.true, %entry
+  %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ]
+  %tmp7 = tail call i8* @llvm.objc.retain(i8* %cond) nounwind
+  tail call void @llvm.objc.release(i8* %call) nounwind, !clang.imprecise_release !0
+  %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar
+  %tmp9 = tail call i8* @llvm.objc.retain(i8* %tmp8) nounwind
+  tail call void @llvm.objc.release(i8* %cond) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; A few real-world testcases.
+
+ at .str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00"
+@"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8
+declare i32 @printf(i8* nocapture, ...) nounwind
+declare i32 @puts(i8* nocapture) nounwind
+ at str = internal constant [16 x i8] c"-[ Top0 _getX ]\00"
+
+; CHECK: define { <2 x float>, <2 x float> } @"\01-[A z]"({}* %self, i8* nocapture %_cmd) [[NUW]] {
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+
+define {<2 x float>, <2 x float>} @"\01-[A z]"({}* %self, i8* nocapture %_cmd) nounwind {
+invoke.cont:
+  %0 = bitcast {}* %self to i8*
+  %1 = tail call i8* @llvm.objc.retain(i8* %0) nounwind
+  tail call void @llvm.dbg.value(metadata {}* %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)
+  tail call void @llvm.dbg.value(metadata {}* %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)
+  %ivar = load i64, i64* @"OBJC_IVAR_$_A.myZ", align 8
+  %add.ptr = getelementptr i8, i8* %0, i64 %ivar
+  %tmp1 = bitcast i8* %add.ptr to float*
+  %tmp2 = load float, float* %tmp1, align 4
+  %conv = fpext float %tmp2 to double
+  %add.ptr.sum = add i64 %ivar, 4
+  %tmp6 = getelementptr inbounds i8, i8* %0, i64 %add.ptr.sum
+  %2 = bitcast i8* %tmp6 to float*
+  %tmp7 = load float, float* %2, align 4
+  %conv8 = fpext float %tmp7 to double
+  %add.ptr.sum36 = add i64 %ivar, 8
+  %tmp12 = getelementptr inbounds i8, i8* %0, i64 %add.ptr.sum36
+  %arrayidx = bitcast i8* %tmp12 to float*
+  %tmp13 = load float, float* %arrayidx, align 4
+  %conv14 = fpext float %tmp13 to double
+  %tmp12.sum = add i64 %ivar, 12
+  %arrayidx19 = getelementptr inbounds i8, i8* %0, i64 %tmp12.sum
+  %3 = bitcast i8* %arrayidx19 to float*
+  %tmp20 = load float, float* %3, align 4
+  %conv21 = fpext float %tmp20 to double
+  %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str4, i64 0, i64 0), double %conv, double %conv8, double %conv14, double %conv21)
+  %ivar23 = load i64, i64* @"OBJC_IVAR_$_A.myZ", align 8
+  %add.ptr24 = getelementptr i8, i8* %0, i64 %ivar23
+  %4 = bitcast i8* %add.ptr24 to i128*
+  %srcval = load i128, i128* %4, align 4
+  tail call void @llvm.objc.release(i8* %0) nounwind
+  %tmp29 = trunc i128 %srcval to i64
+  %tmp30 = bitcast i64 %tmp29 to <2 x float>
+  %tmp31 = insertvalue {<2 x float>, <2 x float>} undef, <2 x float> %tmp30, 0
+  %tmp32 = lshr i128 %srcval, 64
+  %tmp33 = trunc i128 %tmp32 to i64
+  %tmp34 = bitcast i64 %tmp33 to <2 x float>
+  %tmp35 = insertvalue {<2 x float>, <2 x float>} %tmp31, <2 x float> %tmp34, 1
+  ret {<2 x float>, <2 x float>} %tmp35
+}
+
+; CHECK: @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) [[NUW]] {
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+
+define i32 @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) nounwind {
+invoke.cont:
+  %0 = bitcast {}* %self to i8*
+  %1 = tail call i8* @llvm.objc.retain(i8* %0) nounwind
+  %puts = tail call i32 @puts(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0))
+  tail call void @llvm.objc.release(i8* %0) nounwind
+  ret i32 0
+}
+
+@"\01L_OBJC_METH_VAR_NAME_" = internal global [5 x i8] c"frob\00", section "__TEXT,__cstring,cstring_literals", align 1@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
+ at llvm.used = appending global [3 x i8*] [i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_" to i8*), i8* bitcast ([2 x i32]* @"\01L_OBJC_IMAGE_INFO" to i8*)], section "llvm.metadata"
+
+; A simple loop. Eliminate the retain and release inside of it!
+
+; CHECK: define void @loop(i8* %x, i64 %n) {
+; CHECK: for.body:
+; CHECK-NOT: @llvm.objc.
+; CHECK: @llvm.objc.msgSend
+; CHECK-NOT: @llvm.objc.
+; CHECK: for.end:
+; CHECK: }
+define void @loop(i8* %x, i64 %n) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  %cmp9 = icmp sgt i64 %n, 0
+  br i1 %cmp9, label %for.body, label %for.end
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
+  %1 = tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call = tail call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %1, i8* %tmp5)
+  tail call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  %inc = add nsw i64 %i.010, 1
+  %exitcond = icmp eq i64 %inc, %n
+  br i1 %exitcond, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %entry
+  tail call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; ObjCARCOpt can delete the retain,release on self.
+
+; CHECK: define void @TextEditTest(%2* %self, %3* %pboard) {
+; CHECK-NOT: call i8* @llvm.objc.retain(i8* %tmp7)
+; CHECK: }
+
+%0 = type { i8* (i8*, %struct._message_ref_t*, ...)*, i8* }
+%1 = type opaque
+%2 = type opaque
+%3 = type opaque
+%4 = type opaque
+%5 = type opaque
+%struct.NSConstantString = type { i32*, i32, i8*, i64 }
+%struct._NSRange = type { i64, i64 }
+%struct.__CFString = type opaque
+%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
+%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* }
+%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* }
+%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }
+%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 }
+%struct._message_ref_t = type { i8*, i8* }
+%struct._objc_cache = type opaque
+%struct._objc_method = type { i8*, i8*, i8* }
+%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] }
+%struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] }
+%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32 }
+
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+ at kUTTypePlainText = external constant %struct.__CFString*
+@"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+ at _unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring"
+@"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+ at NSCocoaErrorDomain = external constant %1*
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+ at NSFilePathErrorKey = external constant %1*
+@"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+
+declare %1* @truncatedString(%1*, i64)
+define void @TextEditTest(%2* %self, %3* %pboard) {
+entry:
+  %err = alloca %4*, align 8
+  %tmp7 = bitcast %2* %self to i8*
+  %tmp8 = call i8* @llvm.objc.retain(i8* %tmp7) nounwind
+  store %4* null, %4** %err, align 8
+  %tmp1 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8
+  %tmp2 = load %struct.__CFString*, %struct.__CFString** @kUTTypePlainText, align 8
+  %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8
+  %tmp4 = bitcast %struct._class_t* %tmp1 to i8*
+  %call5 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp4, i8* %tmp3, %struct.__CFString* %tmp2)
+  %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8
+  %tmp6 = bitcast %3* %pboard to i8*
+  %call76 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp6, i8* %tmp5, i8* %call5)
+  %tmp9 = call i8* @llvm.objc.retain(i8* %call76) nounwind
+  %tobool = icmp eq i8* %tmp9, null
+  br i1 %tobool, label %end, label %land.lhs.true
+
+land.lhs.true:                                    ; preds = %entry
+  %tmp11 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8
+  %call137 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp6, i8* %tmp11, i8* %tmp9)
+  %tmp = bitcast i8* %call137 to %1*
+  %tmp10 = call i8* @llvm.objc.retain(i8* %call137) nounwind
+  call void @llvm.objc.release(i8* null) nounwind
+  %tmp12 = call i8* @llvm.objc.retain(i8* %call137) nounwind
+  call void @llvm.objc.release(i8* null) nounwind
+  %tobool16 = icmp eq i8* %call137, null
+  br i1 %tobool16, label %end, label %if.then
+
+if.then:                                          ; preds = %land.lhs.true
+  %tmp19 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
+  %call21 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*)*)(i8* %call137, i8* %tmp19)
+  %tobool22 = icmp eq i8 %call21, 0
+  br i1 %tobool22, label %if.then44, label %land.lhs.true23
+
+land.lhs.true23:                                  ; preds = %if.then
+  %tmp24 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
+  %tmp26 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
+  %tmp27 = bitcast %struct._class_t* %tmp24 to i8*
+  %call2822 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp27, i8* %tmp26, i8* %call137)
+  %tmp13 = bitcast i8* %call2822 to %5*
+  %tmp14 = call i8* @llvm.objc.retain(i8* %call2822) nounwind
+  call void @llvm.objc.release(i8* null) nounwind
+  %tobool30 = icmp eq i8* %call2822, null
+  br i1 %tobool30, label %if.then44, label %if.end
+
+if.end:                                           ; preds = %land.lhs.true23
+  %tmp32 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
+  %tmp33 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
+  %tmp34 = bitcast %struct._class_t* %tmp32 to i8*
+  %call35 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp34, i8* %tmp33)
+  %tmp37 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
+  %call3923 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %call35, i8* %tmp37, i8* %call2822, i32 signext 1, %4** %err)
+  %cmp = icmp eq i8* %call3923, null
+  br i1 %cmp, label %if.then44, label %end
+
+if.then44:                                        ; preds = %if.end, %land.lhs.true23, %if.then
+  %url.025 = phi %5* [ %tmp13, %if.end ], [ %tmp13, %land.lhs.true23 ], [ null, %if.then ]
+  %tmp49 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8
+  %call51 = call %struct._NSRange bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %struct._NSRange (i8*, i8*, i64, i64)*)(i8* %call137, i8* %tmp49, i64 0, i64 0)
+  %call513 = extractvalue %struct._NSRange %call51, 0
+  %call514 = extractvalue %struct._NSRange %call51, 1
+  %tmp52 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8
+  %call548 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %call137, i8* %tmp52, i64 %call513, i64 %call514)
+  %tmp55 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8
+  %tmp56 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8
+  %tmp57 = bitcast %struct._class_t* %tmp55 to i8*
+  %call58 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp57, i8* %tmp56)
+  %tmp59 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8
+  %call6110 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %call548, i8* %tmp59, i8* %call58)
+  %tmp15 = call i8* @llvm.objc.retain(i8* %call6110) nounwind
+  call void @llvm.objc.release(i8* %call137) nounwind
+  %tmp64 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8
+  %call66 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, %1*)*)(i8* %call6110, i8* %tmp64, %1* bitcast (%struct.NSConstantString* @_unnamed_cfstring_44 to %1*))
+  %tobool67 = icmp eq i8 %call66, 0
+  br i1 %tobool67, label %if.end74, label %if.then68
+
+if.then68:                                        ; preds = %if.then44
+  %tmp70 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8
+  %call7220 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %call6110, i8* %tmp70)
+  %tmp16 = call i8* @llvm.objc.retain(i8* %call7220) nounwind
+  call void @llvm.objc.release(i8* %call6110) nounwind
+  br label %if.end74
+
+if.end74:                                         ; preds = %if.then68, %if.then44
+  %filename.0.in = phi i8* [ %call7220, %if.then68 ], [ %call6110, %if.then44 ]
+  %filename.0 = bitcast i8* %filename.0.in to %1*
+  %tmp17 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to i8**), align 16
+  %tmp18 = bitcast i8* %tmp17 to i8 (i8*, %struct._message_ref_t*, i8*, ...)*
+  %call78 = call signext i8 (i8*, %struct._message_ref_t*, i8*, ...) %tmp18(i8* %call137, %struct._message_ref_t* bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to %struct._message_ref_t*), i8* %filename.0.in)
+  %tobool79 = icmp eq i8 %call78, 0
+  br i1 %tobool79, label %land.lhs.true80, label %if.then109
+
+land.lhs.true80:                                  ; preds = %if.end74
+  %tmp82 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
+  %call84 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*)*)(i8* %filename.0.in, i8* %tmp82)
+  %tobool86 = icmp eq i8 %call84, 0
+  br i1 %tobool86, label %if.then109, label %if.end106
+
+if.end106:                                        ; preds = %land.lhs.true80
+  %tmp88 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
+  %tmp90 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
+  %tmp91 = bitcast %struct._class_t* %tmp88 to i8*
+  %call9218 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp91, i8* %tmp90, i8* %filename.0.in)
+  %tmp20 = bitcast i8* %call9218 to %5*
+  %tmp21 = call i8* @llvm.objc.retain(i8* %call9218) nounwind
+  %tmp22 = bitcast %5* %url.025 to i8*
+  call void @llvm.objc.release(i8* %tmp22) nounwind
+  %tmp94 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
+  %tmp95 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
+  %tmp96 = bitcast %struct._class_t* %tmp94 to i8*
+  %call97 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp96, i8* %tmp95)
+  %tmp99 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
+  %call10119 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %call97, i8* %tmp99, i8* %call9218, i32 signext 1, %4** %err)
+  %phitmp = icmp eq i8* %call10119, null
+  br i1 %phitmp, label %if.then109, label %end
+
+if.then109:                                       ; preds = %if.end106, %land.lhs.true80, %if.end74
+  %url.129 = phi %5* [ %tmp20, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ]
+  %tmp110 = load %4*, %4** %err, align 8
+  %tobool111 = icmp eq %4* %tmp110, null
+  br i1 %tobool111, label %if.then112, label %if.end125
+
+if.then112:                                       ; preds = %if.then109
+  %tmp113 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8
+  %tmp114 = load %1*, %1** @NSCocoaErrorDomain, align 8
+  %tmp115 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8
+  %call117 = call %1* @truncatedString(%1* %filename.0, i64 1034)
+  %tmp118 = load %1*, %1** @NSFilePathErrorKey, align 8
+  %tmp119 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8
+  %tmp120 = bitcast %struct._class_t* %tmp115 to i8*
+  %call12113 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp120, i8* %tmp119, %1* %call117, %1* %tmp118, i8* null)
+  %tmp122 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8
+  %tmp123 = bitcast %struct._class_t* %tmp113 to i8*
+  %call12414 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp123, i8* %tmp122, %1* %tmp114, i64 258, i8* %call12113)
+  %tmp23 = call i8* @llvm.objc.retain(i8* %call12414) nounwind
+  %tmp25 = call i8* @llvm.objc.autorelease(i8* %tmp23) nounwind
+  %tmp28 = bitcast i8* %tmp25 to %4*
+  store %4* %tmp28, %4** %err, align 8
+  br label %if.end125
+
+if.end125:                                        ; preds = %if.then112, %if.then109
+  %tmp127 = phi %4* [ %tmp110, %if.then109 ], [ %tmp28, %if.then112 ]
+  %tmp126 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8
+  %tmp128 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8
+  %tmp129 = bitcast %struct._class_t* %tmp126 to i8*
+  %call13015 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %tmp129, i8* %tmp128, %4* %tmp127)
+  %tmp131 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8
+  %call13317 = call i8* (i8*, i8*, ...) @llvm.objc.msgSend(i8* %call13015, i8* %tmp131)
+  br label %end
+
+end:                                              ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry
+  %filename.2 = phi %1* [ %filename.0, %if.end106 ], [ %filename.0, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ]
+  %origFilename.0 = phi %1* [ %tmp, %if.end106 ], [ %tmp, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ]
+  %url.2 = phi %5* [ %tmp20, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %tmp13, %if.end ]
+  call void @llvm.objc.release(i8* %tmp9) nounwind, !clang.imprecise_release !0
+  %tmp29 = bitcast %5* %url.2 to i8*
+  call void @llvm.objc.release(i8* %tmp29) nounwind, !clang.imprecise_release !0
+  %tmp30 = bitcast %1* %origFilename.0 to i8*
+  call void @llvm.objc.release(i8* %tmp30) nounwind, !clang.imprecise_release !0
+  %tmp31 = bitcast %1* %filename.2 to i8*
+  call void @llvm.objc.release(i8* %tmp31) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %tmp7) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i32 @llvm.objc.sync.enter(i8*)
+declare i32 @llvm.objc.sync.exit(i8*)
+
+; Make sure that we understand that objc_sync_{enter,exit} are IC_User not
+; IC_Call/IC_CallOrUser.
+
+; CHECK-LABEL:      define void @test67(
+; CHECK-NEXT:   call i32 @llvm.objc.sync.enter(i8* %x)
+; CHECK-NEXT:   call i32 @llvm.objc.sync.exit(i8* %x)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test67(i8* %x) {
+  call i8* @llvm.objc.retain(i8* %x)
+  call i32 @llvm.objc.sync.enter(i8* %x)
+  call i32 @llvm.objc.sync.exit(i8* %x)
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0
+  ret void
+}
+
+!llvm.module.flags = !{!1}
+!llvm.dbg.cu = !{!3}
+
+!0 = !{}
+!1 = !{i32 1, !"Debug Info Version", i32 3}
+!2 = distinct !DISubprogram(unit: !3)
+!3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
+                             file: !4,
+                             isOptimized: true, flags: "-O2",
+                             splitDebugFilename: "abc.debug", emissionKind: 2)
+!4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+
+; CHECK: attributes [[NUW]] = { nounwind }
+; CHECK: attributes #1 = { nounwind readnone speculatable }
+; CHECK: ![[RELEASE]] = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,435 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+; rdar://9503416
+
+; Detect loop boundaries and don't move retains and releases
+; across them.
+
+declare void @use_pointer(i8*)
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
+declare void @callee()
+declare void @block_callee(void ()*)
+
+; CHECK-LABEL: define void @test0(
+; CHECK:   call i8* @llvm.objc.retain
+; CHECK: for.body:
+; CHECK-NOT: @objc
+; CHECK: for.end:
+; CHECK:   call void @llvm.objc.release
+; CHECK: }
+define void @test0(i8* %digits) {
+entry:
+  %tmp1 = call i8* @llvm.objc.retain(i8* %digits) nounwind
+  call void @use_pointer(i8* %digits)
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
+  call void @use_pointer(i8* %digits)
+  %inc = add i64 %upcDigitIndex.01, 1
+  %cmp = icmp ult i64 %inc, 12
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  call void @llvm.objc.release(i8* %digits) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK-LABEL: define void @test1(
+; CHECK:   call i8* @llvm.objc.retain
+; CHECK: for.body:
+; CHECK-NOT: @objc
+; CHECK: for.end:
+; CHECK:   void @llvm.objc.release
+; CHECK: }
+define void @test1(i8* %digits) {
+entry:
+  %tmp1 = call i8* @llvm.objc.retain(i8* %digits) nounwind
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
+  call void @use_pointer(i8* %digits)
+  call void @use_pointer(i8* %digits)
+  %inc = add i64 %upcDigitIndex.01, 1
+  %cmp = icmp ult i64 %inc, 12
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  call void @llvm.objc.release(i8* %digits) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK-LABEL: define void @test2(
+; CHECK:   call i8* @llvm.objc.retain
+; CHECK: for.body:
+; CHECK-NOT: @objc
+; CHECK: for.end:
+; CHECK:   void @llvm.objc.release
+; CHECK: }
+define void @test2(i8* %digits) {
+entry:
+  %tmp1 = call i8* @llvm.objc.retain(i8* %digits) nounwind
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %entry
+  %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
+  call void @use_pointer(i8* %digits)
+  %inc = add i64 %upcDigitIndex.01, 1
+  %cmp = icmp ult i64 %inc, 12
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:                                          ; preds = %for.body
+  call void @use_pointer(i8* %digits)
+  call void @llvm.objc.release(i8* %digits) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Delete nested retain+release pairs around loops.
+
+;      CHECK: define void @test3(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW:#[0-9]+]]
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %a)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test3(i8* %a) nounwind {
+entry:
+  %outer = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  call void @callee()
+  store i8 0, i8* %a
+  br i1 undef, label %loop, label %exit
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test4(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %a)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test4(i8* %a) nounwind {
+entry:
+  %outer = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br label %more
+
+more:
+  call void @callee()
+  call void @callee()
+  store i8 0, i8* %a
+  br i1 undef, label %loop, label %exit
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test5(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   call void @callee()
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   call void @use_pointer(i8* %a)
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %a)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test5(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  call void @callee()
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @use_pointer(i8* %a)
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test6(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   call void @use_pointer(i8* %a)
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %a)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test6(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  call void @callee()
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @use_pointer(i8* %a)
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test7(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   call void @callee()
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %a)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test7(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  call void @callee()
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  call void @use_pointer(i8* %a)
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test8(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   call void @llvm.objc.release(i8* %a)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test8(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  call void @callee()
+  call void @use_pointer(i8* %a)
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test9(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test9(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  call void @use_pointer(i8* %a)
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test10(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test10(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  call void @callee()
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+;      CHECK: define void @test11(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test11(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  br label %more
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Don't delete anything if they're not balanced.
+
+;      CHECK: define void @test12(i8* %a) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %outer = tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   %inner = tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK-NEXT:   br label %loop
+;  CHECK-NOT:   @llvm.objc.
+;      CHECK: exit:
+; CHECK-NEXT: call void @llvm.objc.release(i8* %a) [[NUW]]
+; CHECK-NEXT: call void @llvm.objc.release(i8* %a) [[NUW]], !clang.imprecise_release !0
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test12(i8* %a) nounwind {
+entry:
+  %outer = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  %inner = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  br i1 undef, label %true, label %more
+
+true:
+  ret void
+
+more:
+  br i1 undef, label %exit, label %loop
+
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Do not improperly pair retains in a for loop with releases outside of a for
+; loop when the proper pairing is disguised by a separate provenance represented
+; by an alloca.
+; rdar://12969722
+
+; CHECK: define void @test13(i8* %a) [[NUW]] {
+; CHECK: entry:
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK: loop:
+; CHECK:   tail call i8* @llvm.objc.retain(i8* %a) [[NUW]]
+; CHECK:   call void @block_callee
+; CHECK:   call void @llvm.objc.release(i8* %reloaded_a) [[NUW]]
+; CHECK: exit:
+; CHECK:   call void @llvm.objc.release(i8* %a) [[NUW]]
+; CHECK: }
+define void @test13(i8* %a) nounwind {
+entry:
+  %block = alloca i8*
+  %a1 = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  br label %loop
+
+loop:
+  %a2 = tail call i8* @llvm.objc.retain(i8* %a) nounwind
+  store i8* %a, i8** %block, align 8
+  %casted_block = bitcast i8** %block to void ()*
+  call void @block_callee(void ()* %casted_block)
+  %reloaded_a = load i8*, i8** %block, align 8
+  call void @llvm.objc.release(i8* %reloaded_a) nounwind, !clang.imprecise_release !0
+  br i1 undef, label %loop, label %exit
+  
+exit:
+  call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; CHECK: attributes [[NUW]] = { nounwind }
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/clang-arc-use-barrier.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/clang-arc-use-barrier.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/clang-arc-use-barrier.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/clang-arc-use-barrier.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -objc-arc -S %s | FileCheck %s
+
+%0 = type opaque
+
+; Make sure ARC optimizer doesn't sink @obj_retain past @llvm.objc.clang.arc.use.
+
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void (...) @llvm.objc.clang.arc.use(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: call void (...) @llvm.objc.clang.arc.use(
+
+define void @runTest() local_unnamed_addr {
+  %1 = alloca %0*, align 8
+  %2 = alloca %0*, align 8
+  %3 = tail call %0* @foo0()
+  %4 = bitcast %0* %3 to i8*
+  %5 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %4)
+  store %0* %3, %0** %1, align 8
+  call void @foo1(%0** nonnull %1)
+  %6 = load %0*, %0** %1, align 8
+  %7 = bitcast %0* %6 to i8*
+  %8 = call i8* @llvm.objc.retain(i8* %7)
+  call void (...) @llvm.objc.clang.arc.use(%0* %3)
+  call void @llvm.objc.release(i8* %4)
+  store %0* %6, %0** %2, align 8
+  call void @foo1(%0** nonnull %2)
+  %9 = load %0*, %0** %2, align 8
+  %10 = bitcast %0* %9 to i8*
+  %11 = call i8* @llvm.objc.retain(i8* %10)
+  call void (...) @llvm.objc.clang.arc.use(%0* %6)
+  %tmp1 = load %0*, %0** %2, align 8
+  call void @llvm.objc.release(i8* %7)
+  call void @foo2(%0* %9)
+  call void @llvm.objc.release(i8* %10)
+  ret void
+}
+
+declare %0* @foo0() local_unnamed_addr
+declare void @foo1(%0**) local_unnamed_addr
+declare void @foo2(%0*) local_unnamed_addr
+
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) local_unnamed_addr
+declare i8* @llvm.objc.retain(i8*) local_unnamed_addr
+declare void @llvm.objc.clang.arc.use(...) local_unnamed_addr
+declare void @llvm.objc.release(i8*) local_unnamed_addr

Added: llvm/trunk/test/Transforms/ObjCARC/comdat-ipo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/comdat-ipo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/comdat-ipo.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/comdat-ipo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; RUN: opt -S -objc-arc-apelim < %s | FileCheck %s
+
+; See PR26774
+
+ at llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_x }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_y }]
+
+ at x = global i32 0
+
+declare i32 @bar() nounwind
+
+define linkonce_odr i32 @foo() nounwind {
+entry:
+  ret i32 5
+}
+
+define internal void @__cxx_global_var_init() {
+entry:
+  %call = call i32 @foo()
+  store i32 %call, i32* @x, align 4
+  ret void
+}
+
+define internal void @__dxx_global_var_init() {
+entry:
+  %call = call i32 @bar()
+  store i32 %call, i32* @x, align 4
+  ret void
+}
+
+; CHECK-LABEL: define internal void @_GLOBAL__I_x() {
+define internal void @_GLOBAL__I_x() {
+entry:
+; CHECK:  call i8* @llvm.objc.autoreleasePoolPush()
+; CHECK-NEXT:  call void @__cxx_global_var_init()
+; CHECK-NEXT:  call void @llvm.objc.autoreleasePoolPop(i8* %0)
+; CHECK-NEXT:  ret void
+
+  %0 = call i8* @llvm.objc.autoreleasePoolPush() nounwind
+  call void @__cxx_global_var_init()
+  call void @llvm.objc.autoreleasePoolPop(i8* %0) nounwind
+  ret void
+}
+
+define internal void @_GLOBAL__I_y() {
+entry:
+  %0 = call i8* @llvm.objc.autoreleasePoolPush() nounwind
+  call void @__dxx_global_var_init()
+  call void @llvm.objc.autoreleasePoolPop(i8* %0) nounwind
+  ret void
+}
+
+declare i8* @llvm.objc.autoreleasePoolPush()
+declare void @llvm.objc.autoreleasePoolPop(i8*)

Added: llvm/trunk/test/Transforms/ObjCARC/contract-catchswitch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-catchswitch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-catchswitch.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-catchswitch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt -S -objc-arc-contract < %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--windows-msvc19.11.0"
+
+%0 = type opaque
+
+declare i32 @__CxxFrameHandler3(...)
+declare dllimport void @llvm.objc.release(i8*) local_unnamed_addr
+declare dllimport i8* @llvm.objc.retain(i8* returned) local_unnamed_addr
+
+ at p = global i8* null, align 4
+
+declare void @f() local_unnamed_addr
+
+define void @g() local_unnamed_addr personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %tmp = load i8*, i8** @p, align 4
+  %cast = bitcast i8* %tmp to %0*
+  %tmp1 = tail call i8* @llvm.objc.retain(i8* %tmp) #0
+  ; Split the basic block to ensure bitcast ends up in entry.split.
+  br label %entry.split
+
+entry.split:
+  invoke void @f()
+          to label %invoke.cont unwind label %catch.dispatch
+
+; Dummy nested catchswitch to test looping through the dominator tree.
+catch.dispatch:
+  %tmp2 = catchswitch within none [label %catch] unwind label %catch.dispatch1
+
+catch:
+  %tmp3 = catchpad within %tmp2 [i8* null, i32 64, i8* null]
+  catchret from %tmp3 to label %invoke.cont
+
+catch.dispatch1:
+  %tmp4 = catchswitch within none [label %catch1] unwind label %ehcleanup
+
+catch1:
+  %tmp5 = catchpad within %tmp4 [i8 *null, i32 64, i8* null]
+  catchret from %tmp5 to label %invoke.cont
+
+invoke.cont:
+  %tmp6 = load i8*, i8** @p, align 4
+  %cast1 = bitcast i8* %tmp6 to %0*
+  %tmp7 = tail call i8* @llvm.objc.retain(i8* %tmp6) #0
+  call void @llvm.objc.release(i8* %tmp) #0, !clang.imprecise_release !0
+  ; Split the basic block to ensure bitcast ends up in invoke.cont.split.
+  br label %invoke.cont.split
+
+invoke.cont.split:
+  invoke void @f()
+          to label %invoke.cont1 unwind label %ehcleanup
+
+invoke.cont1:
+  ret void
+
+ehcleanup:
+  %tmp8 = phi %0* [ %cast, %catch.dispatch1 ], [ %cast1, %invoke.cont.split ]
+  %tmp9 = cleanuppad within none []
+  %tmp10 = bitcast %0* %tmp8 to i8*
+  call void @llvm.objc.release(i8* %tmp10) #0 [ "funclet"(token %tmp9) ]
+  cleanupret from %tmp9 unwind to caller
+}
+
+; CHECK-LABEL: entry.split:
+; CHECK-NEXT:    %0 = bitcast i8* %tmp1 to %0*
+; CHECK-NEXT:    invoke void @f()
+; CHECK-NEXT:            to label %invoke.cont unwind label %catch.dispatch
+
+; CHECK-LABEL: invoke.cont.split:
+; CHECK-NEXT:    %1 = bitcast i8* %tmp7 to %0*
+; CHECK-NEXT:    invoke void @f()
+; CHECK-NEXT:            to label %invoke.cont1 unwind label %ehcleanup
+
+; CHECK-LABEL: ehcleanup:
+; CHECK-NEXT:    %tmp8 = phi %0* [ %0, %catch.dispatch1 ], [ %1, %invoke.cont.split ]
+
+attributes #0 = { nounwind }
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/contract-end-of-use-list.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-end-of-use-list.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-end-of-use-list.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-end-of-use-list.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -S < %s -objc-arc-expand -objc-arc-contract | FileCheck %s
+; Don't crash.  Reproducer for a use_iterator bug from r203364.
+; rdar://problem/16333235
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-darwin13.2.0"
+
+%struct = type { i8*, i8* }
+
+; CHECK-LABEL: @foo() {
+define internal i8* @foo() {
+entry:
+  %call = call i8* @bar()
+; CHECK: %retained1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call)
+  %retained1 = call i8* @llvm.objc.retain(i8* %call)
+  %isnull = icmp eq i8* %retained1, null
+  br i1 %isnull, label %cleanup, label %if.end
+
+if.end:
+; CHECK: %retained2 = call i8* @llvm.objc.retain(i8* %retained1)
+  %retained2 = call i8* @llvm.objc.retain(i8* %retained1)
+  br label %cleanup
+
+cleanup:
+  %retval = phi i8* [ %retained2, %if.end ], [ null, %entry ]
+  ret i8* %retval
+}
+
+declare i8* @bar()
+
+declare extern_weak i8* @llvm.objc.retain(i8*)

Added: llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,62 @@
+; RUN: opt -mtriple=i686-unknown-windows-msvc -objc-arc-contract -S -o - %s | FileCheck %s
+
+; Generated (and lightly modified and cleaned up) from the following source:
+; id f();
+; void g() {
+;   try {
+;     f();
+;   } catch (...) {
+;     f();
+;   }
+; }
+
+define void @"\01?g@@YAXXZ"() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %call = invoke i8* @"\01?f@@YAPAUobjc_object@@XZ"()
+          to label %invoke.cont unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %0 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %0 [i8* null, i32 64, i8* null]
+  %call1 = call i8* @"\01?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
+  %2 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1) [ "funclet"(token %1) ]
+  call void @llvm.objc.release(i8* %2) [ "funclet"(token %1) ]
+  br label %catch.1
+
+catch.1:                                          ; preds = %catch
+  %call2 = call i8* @"\01?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
+  %3 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call2) [ "funclet"(token %1) ]
+  call void @llvm.objc.release(i8* %3) [ "funclet"(token %1) ]
+  catchret from %1 to label %catchret.dest
+
+catchret.dest:                                    ; preds = %catch.1
+  ret void
+
+invoke.cont:                                      ; preds = %entry
+  %4 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call)
+  call void @llvm.objc.release(i8* %4)
+  ret void
+}
+
+declare i8* @"\01?f@@YAPAUobjc_object@@XZ"()
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare dllimport i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+
+declare dllimport void @llvm.objc.release(i8*)
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"movl\09%ebp, %ebp\09\09// marker for objc_retainAutoreleaseReturnValue"}
+
+; CHECK-LABEL: catch
+; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
+
+; CHECK-LABEL: catch.1
+; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
+
+; CHECK-LABEL: invoke.cont
+; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}}

Added: llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-marker.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -S -objc-arc-contract < %s | FileCheck %s
+
+; CHECK-LABEL: define void @foo() {
+; CHECK:      %call = tail call i32* @qux()
+; CHECK-NEXT: %tcall = bitcast i32* %call to i8*
+; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for return value optimization", ""()
+; CHECK-NEXT: %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
+; CHECK: }
+
+define void @foo() {
+entry:
+  %call = tail call i32* @qux()
+  %tcall = bitcast i32* %call to i8*
+  %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %tcall) nounwind
+  tail call void @bar(i8* %0)
+  ret void
+}
+
+; CHECK-LABEL: define void @foo2() {
+; CHECK:      %call = tail call i32* @qux()
+; CHECK-NEXT: %tcall = bitcast i32* %call to i8*
+; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for return value optimization", ""()
+; CHECK-NEXT: %0 = tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %tcall) [[NUW:#[0-9]+]]
+; CHECK: }
+
+define void @foo2() {
+entry:
+  %call = tail call i32* @qux()
+  %tcall = bitcast i32* %call to i8*
+  %0 = tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %tcall) nounwind
+  tail call void @bar(i8* %0)
+  ret void
+}
+
+
+declare i32* @qux()
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
+declare void @bar(i8*)
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov\09r7, r7\09\09@ marker for return value optimization"}
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/contract-replace-arg-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-replace-arg-use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-replace-arg-use.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-replace-arg-use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @foo1()
+
+; Check that ARC contraction replaces the function return with the value
+; returned by @llvm.objc.autoreleaseReturnValue.
+
+; CHECK-LABEL: define i32* @autoreleaseRVTailCall(
+; CHECK: %[[V0:[0-9]+]] = tail call i8* @llvm.objc.autoreleaseReturnValue(
+; CHECK: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to i32*
+; CHECK: ret i32* %[[V1]]
+
+define i32* @autoreleaseRVTailCall() {
+  %1 = call i8* @foo1()
+  %2 = bitcast i8* %1 to i32*
+  %3 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %1)
+  ret i32* %2
+}
+
+declare i32* @foo2(i32);
+
+; CHECK-LABEL: define i32* @autoreleaseRVTailCallPhi(
+; CHECK: %[[PHIVAL:.*]] = phi i8* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
+; CHECK: %[[RETVAL:.*]] = phi i32* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
+; CHECK: %[[V4:.*]] = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[PHIVAL]])
+; CHECK: %[[V0:.*]] = bitcast i8* %[[V4]] to i32*
+; CHECK: ret i32* %[[V0]]
+
+define i32* @autoreleaseRVTailCallPhi(i1 %cond) {
+entry:
+  br i1 %cond, label %bb1, label %bb2
+bb1:
+  %v0 = call i32* @foo2(i32 1)
+  %v1 = bitcast i32* %v0 to i8*
+  br label %bb3
+bb2:
+  %v2 = call i32* @foo2(i32 2)
+  %v3 = bitcast i32* %v2 to i8*
+  br label %bb3
+bb3:
+  %phival = phi i8* [ %v1, %bb1 ], [ %v3, %bb2 ]
+  %retval = phi i32* [ %v0, %bb1 ], [ %v2, %bb2 ]
+  %v4 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %phival)
+  ret i32* %retval
+}

Added: llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-funclet.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-funclet.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-funclet.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -mtriple=i686-unknown-windows-msvc -objc-arc-contract -S -o - %s | FileCheck %s
+
+declare void @f()
+declare i32 @__CxxFrameHandler3(...)
+declare dllimport i8* @llvm.objc.retain(i8*)
+declare dllimport i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare dllimport void @llvm.objc.release(i8*)
+
+ at x = external global i8*
+
+define void @g(i8* %p) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+  invoke void @f() to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:
+  %call = tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  %tmp = load i8*, i8** @x, align 4
+  store i8* %call, i8** @x, align 4
+  tail call void @llvm.objc.release(i8* %tmp) nounwind
+  ret void
+
+ehcleanup:
+  %1 = cleanuppad within none []
+  %call1 = tail call i8* @llvm.objc.retain(i8* %p) nounwind [ "funclet"(token %1) ]
+  %tmp1 = load i8*, i8** @x, align 4
+  store i8* %call1, i8** @x, align 4
+  tail call void @llvm.objc.release(i8* %tmp1) nounwind [ "funclet"(token %1) ]
+  cleanupret from %1 unwind to caller
+}
+
+; CHECK-LABEL: invoke.cont:
+; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) #0{{$}}
+; CHECK: ret void
+
+; CHECK-LABEL: ehcleanup:
+; CHECK: %1 = cleanuppad within none []
+; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) #0 [ "funclet"(token %1) ]
+; CHECK: cleanupret from %1 unwind to caller

Added: llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-ivar.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-ivar.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-ivar.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-storestrong-ivar.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+
+; CHECK: tail call void @llvm.objc.storeStrong(i8**
+
+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.0"
+
+%0 = type opaque
+%1 = type opaque
+
+@"OBJC_IVAR_$_Controller.preferencesController" = external global i64, section "__DATA, __objc_const", align 8
+
+declare i8* @llvm.objc.retain(i8*)
+
+declare void @llvm.objc.release(i8*)
+
+define hidden void @y(%0* nocapture %self, %1* %preferencesController) nounwind {
+entry:
+  %ivar = load i64, i64* @"OBJC_IVAR_$_Controller.preferencesController", align 8
+  %tmp = bitcast %0* %self to i8*
+  %add.ptr = getelementptr inbounds i8, i8* %tmp, i64 %ivar
+  %tmp1 = bitcast i8* %add.ptr to %1**
+  %tmp2 = load %1*, %1** %tmp1, align 8
+  %tmp3 = bitcast %1* %preferencesController to i8*
+  %tmp4 = tail call i8* @llvm.objc.retain(i8* %tmp3) nounwind
+  %tmp5 = bitcast %1* %tmp2 to i8*
+  tail call void @llvm.objc.release(i8* %tmp5) nounwind
+  %tmp6 = bitcast i8* %tmp4 to %1*
+  store %1* %tmp6, %1** %tmp1, align 8
+  ret void
+}

Added: llvm/trunk/test/Transforms/ObjCARC/contract-storestrong.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-storestrong.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-storestrong.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-storestrong.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,261 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
+declare void @use_pointer(i8*)
+
+ at x = external global i8*
+
+; CHECK-LABEL: define void @test0(
+; CHECK: entry:
+; CHECK-NEXT: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) [[NUW:#[0-9]+]]
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test0(i8* %p) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  %tmp = load i8*, i8** @x, align 8
+  store i8* %0, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %tmp) nounwind
+  ret void
+}
+
+; Don't do this if the load is volatile.
+
+; CHECK-LABEL: define void @test1(i8* %p) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK-NEXT:   %tmp = load volatile i8*, i8** @x, align 8
+; CHECK-NEXT:   store i8* %0, i8** @x, align 8
+; CHECK-NEXT:   tail call void @llvm.objc.release(i8* %tmp) [[NUW]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test1(i8* %p) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  %tmp = load volatile i8*, i8** @x, align 8
+  store i8* %0, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %tmp) nounwind
+  ret void
+}
+
+; Don't do this if the store is volatile.
+
+; CHECK-LABEL: define void @test2(i8* %p) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK-NEXT:   %tmp = load i8*, i8** @x, align 8
+; CHECK-NEXT:   store volatile i8* %0, i8** @x, align 8
+; CHECK-NEXT:   tail call void @llvm.objc.release(i8* %tmp) [[NUW]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test2(i8* %p) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  %tmp = load i8*, i8** @x, align 8
+  store volatile i8* %0, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %tmp) nounwind
+  ret void
+}
+
+; Don't do this if there's a use of the old pointer value between the store
+; and the release.
+
+; CHECK-LABEL: define void @test3(i8* %newValue) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) [[NUW]]
+; CHECK-NEXT:    %x1 = load i8*, i8** @x, align 8
+; CHECK-NEXT:    store i8* %x0, i8** @x, align 8
+; CHECK-NEXT:    tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0
+; CHECK-NEXT:    tail call void @llvm.objc.release(i8* %x1) [[NUW]], !clang.imprecise_release !0
+; CHECK-NEXT:    ret void
+; CHECK-NEXT:  }
+define void @test3(i8* %newValue) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  %x1 = load i8*, i8** @x, align 8
+  store i8* %newValue, i8** @x, align 8
+  tail call void @use_pointer(i8* %x1), !clang.arc.no_objc_arc_exceptions !0
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Like test3, but with an icmp use instead of a call, for good measure.
+
+; CHECK-LABEL:  define i1 @test4(i8* %newValue, i8* %foo) {
+; CHECK-NEXT:   entry:
+; CHECK-NEXT:     %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) [[NUW]]
+; CHECK-NEXT:     %x1 = load i8*, i8** @x, align 8
+; CHECK-NEXT:     store i8* %x0, i8** @x, align 8
+; CHECK-NEXT:     %t = icmp eq i8* %x1, %foo
+; CHECK-NEXT:     tail call void @llvm.objc.release(i8* %x1) [[NUW]], !clang.imprecise_release !0
+; CHECK-NEXT:     ret i1 %t
+; CHECK-NEXT:   }
+define i1 @test4(i8* %newValue, i8* %foo) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  %x1 = load i8*, i8** @x, align 8
+  store i8* %newValue, i8** @x, align 8
+  %t = icmp eq i8* %x1, %foo
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  ret i1 %t
+}
+
+; Do form an llvm.objc.storeStrong here, because the use is before the store.
+
+; CHECK-LABEL: define i1 @test5(i8* %newValue, i8* %foo) {
+; CHECK: %t = icmp eq i8* %x1, %foo
+; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %newValue) [[NUW]]
+; CHECK: }
+define i1 @test5(i8* %newValue, i8* %foo) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  %x1 = load i8*, i8** @x, align 8
+  %t = icmp eq i8* %x1, %foo
+  store i8* %newValue, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  ret i1 %t
+}
+
+; Like test5, but the release is before the store.
+
+; CHECK-LABEL: define i1 @test6(i8* %newValue, i8* %foo) {
+; CHECK: %t = icmp eq i8* %x1, %foo
+; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %newValue) [[NUW]]
+; CHECK: }
+define i1 @test6(i8* %newValue, i8* %foo) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  %x1 = load i8*, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  %t = icmp eq i8* %x1, %foo
+  store i8* %newValue, i8** @x, align 8
+  ret i1 %t
+}
+
+; Like test0, but there's no store, so don't form an llvm.objc.storeStrong.
+
+; CHECK-LABEL: define void @test7(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK-NEXT:   %tmp = load i8*, i8** @x, align 8
+; CHECK-NEXT:   tail call void @llvm.objc.release(i8* %tmp) [[NUW]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test7(i8* %p) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  %tmp = load i8*, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %tmp) nounwind
+  ret void
+}
+
+; Like test0, but there's no retain, so don't form an llvm.objc.storeStrong.
+
+; CHECK-LABEL: define void @test8(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %tmp = load i8*, i8** @x, align 8
+; CHECK-NEXT:   store i8* %p, i8** @x, align 8
+; CHECK-NEXT:   tail call void @llvm.objc.release(i8* %tmp) [[NUW]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test8(i8* %p) {
+entry:
+  %tmp = load i8*, i8** @x, align 8
+  store i8* %p, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %tmp) nounwind
+  ret void
+}
+
+; Make sure that we properly handle release that *may* release our new
+; value in between the retain and the store. We need to be sure that
+; this we can safely move the retain to the store. This specific test
+; makes sure that we properly handled a release of an unrelated
+; pointer.
+;
+; CHECK-LABEL: define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
+; CHECK-NOT: llvm.objc.storeStrong
+define i1 @test9(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  tail call void @llvm.objc.release(i8* %unrelated_ptr) nounwind, !clang.imprecise_release !0
+  %x1 = load i8*, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  %t = icmp eq i8* %x1, %foo
+  store i8* %newValue, i8** @x, align 8
+  ret i1 %t  
+}
+
+; Make sure that we don't perform the optimization when we just have a call.
+;
+; CHECK-LABEL: define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
+; CHECK-NOT: llvm.objc.storeStrong
+define i1 @test10(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  call void @use_pointer(i8* %unrelated_ptr)
+  %x1 = load i8*, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  %t = icmp eq i8* %x1, %foo
+  store i8* %newValue, i8** @x, align 8
+  ret i1 %t
+}
+
+; Make sure we form the store strong if the use in between the retain
+; and the store does not touch reference counts.
+; CHECK-LABEL: define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
+; CHECK: llvm.objc.storeStrong
+define i1 @test11(i8* %newValue, i8* %foo, i8* %unrelated_ptr) {
+entry:
+  %x0 = tail call i8* @llvm.objc.retain(i8* %newValue) nounwind
+  %t = icmp eq i8* %newValue, %foo
+  %x1 = load i8*, i8** @x, align 8
+  tail call void @llvm.objc.release(i8* %x1) nounwind, !clang.imprecise_release !0
+  store i8* %newValue, i8** @x, align 8
+  ret i1 %t
+}
+
+; Make sure that we form the store strong even if there are bitcasts on
+; the pointers.
+; CHECK-LABEL: define void @test12(
+; CHECK: entry:
+; CHECK-NEXT: %p16 = bitcast i8** @x to i16**
+; CHECK-NEXT: %tmp16 = load i16*, i16** %p16, align 8
+; CHECK-NEXT: %tmp8 = bitcast i16* %tmp16 to i8*
+; CHECK-NEXT: %p32 = bitcast i8** @x to i32**
+; CHECK-NEXT: %v32 = bitcast i8* %p to i32*
+; CHECK-NEXT: %0 = bitcast i16** %p16 to i8**
+; CHECK-NEXT: tail call void @llvm.objc.storeStrong(i8** %0, i8* %p)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test12(i8* %p) {
+entry:
+  %retain = tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  %p16 = bitcast i8** @x to i16**
+  %tmp16 = load i16*, i16** %p16, align 8
+  %tmp8 = bitcast i16* %tmp16 to i8*
+  %p32 = bitcast i8** @x to i32**
+  %v32 = bitcast i8* %retain to i32*
+  store i32* %v32, i32** %p32, align 8
+  tail call void @llvm.objc.release(i8* %tmp8) nounwind
+  ret void
+}
+
+; This used to crash.
+; CHECK-LABEL: define i8* @test13(
+; CHECK: tail call void @llvm.objc.storeStrong(i8** %{{.*}}, i8* %[[NEW:.*]])
+; CHECK-NEXT: ret i8* %[[NEW]]
+
+define i8* @test13(i8* %a0, i8* %a1, i8** %addr, i8* %new) {
+  %old = load i8*, i8** %addr, align 8
+  call void @llvm.objc.release(i8* %old)
+  %retained = call i8* @llvm.objc.retain(i8* %new)
+  store i8* %retained, i8** %addr, align 8
+  ret i8* %retained
+}
+
+!0 = !{}
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/contract-testcases.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-testcases.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-testcases.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-testcases.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,95 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+; rdar://9511608
+
+%0 = type opaque
+%1 = type opaque
+%2 = type { i64, i64 }
+%4 = type opaque
+
+declare %0* @"\01-[NSAttributedString(Terminal) pathAtIndex:effectiveRange:]"(%1*, i8* nocapture, i64, %2*) optsize
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.msgSend_fixup(i8*, i8*, ...)
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+declare void @llvm.objc.release(i8*)
+declare %2 @NSUnionRange(i64, i64, i64, i64) optsize
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+declare i32 @__gxx_personality_sj0(...)
+
+; Don't get in trouble on bugpointed code.
+
+; CHECK-LABEL: define void @test0(
+define void @test0() {
+bb:
+  %tmp = bitcast %4* undef to i8*
+  %tmp1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %tmp) nounwind
+  br label %bb3
+
+bb3:                                              ; preds = %bb2
+  br i1 undef, label %bb6, label %bb4
+
+bb4:                                              ; preds = %bb3
+  switch i64 undef, label %bb5 [
+    i64 9223372036854775807, label %bb6
+    i64 0, label %bb6
+  ]
+
+bb5:                                              ; preds = %bb4
+  br label %bb6
+
+bb6:                                              ; preds = %bb5, %bb4, %bb4, %bb3
+  %tmp7 = phi %4* [ undef, %bb5 ], [ undef, %bb4 ], [ undef, %bb3 ], [ undef, %bb4 ]
+  unreachable
+}
+
+; When rewriting operands for a phi which has multiple operands
+; for the same block, use the exactly same value in each block.
+
+; CHECK-LABEL: define void @test1(
+; CHECK: %0 = bitcast i8* %tmp3 to %0* 
+; CHECK: br i1 undef, label %bb7, label %bb7
+; CHECK: bb7:
+; CHECK: %tmp8 = phi %0* [ %0, %bb ], [ %0, %bb ]
+; CHECK: }
+define void @test1() {
+bb:
+  %tmp = tail call %0* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %0* ()*)()
+  %tmp2 = bitcast %0* %tmp to i8*
+  %tmp3 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %tmp2) nounwind
+  br i1 undef, label %bb7, label %bb7
+
+bb7:                                              ; preds = %bb6, %bb6, %bb5
+  %tmp8 = phi %0* [ %tmp, %bb ], [ %tmp, %bb ]
+  unreachable
+}
+
+; When looking for the defining instruction for an objc_retainAutoreleasedReturnValue
+; call, handle the case where it's an invoke in a different basic block.
+; rdar://11714057
+
+; CHECK: define void @_Z6doTestP8NSString() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
+; CHECK: invoke.cont:                                      ; preds = %entry
+; CHECK-NEXT: call void asm sideeffect "mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue", ""()
+; CHECK-NEXT: %tmp = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) [[NUW:#[0-9]+]]
+; CHECK: }
+define void @_Z6doTestP8NSString() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
+entry:
+  %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* ()*)()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %entry
+  %tmp = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  unreachable
+
+lpad:                                             ; preds = %entry
+  %tmp1 = landingpad { i8*, i32 }
+          cleanup
+  resume { i8*, i32 } undef
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov\09r7, r7\09\09@ marker for objc_retainAutoreleaseReturnValue"}
+
+; CHECK: attributes #0 = { optsize }
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/contract.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,232 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+
+declare void @use_pointer(i8*)
+declare i8* @returner()
+declare void @callee()
+
+; CHECK-LABEL: define void @test0(
+; CHECK: call void @use_pointer(i8* %0)
+; CHECK: }
+define void @test0(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  ret void
+}
+
+; CHECK-LABEL: define void @test1(
+; CHECK: call void @use_pointer(i8* %0)
+; CHECK: }
+define void @test1(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  ret void
+}
+
+; Merge objc_retain and objc_autorelease into objc_retainAutorelease.
+
+; CHECK-LABEL: define void @test2(
+; CHECK: tail call i8* @llvm.objc.retainAutorelease(i8* %x) [[NUW:#[0-9]+]]
+; CHECK: }
+define void @test2(i8* %x) nounwind {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  call i8* @llvm.objc.autorelease(i8* %0) nounwind
+  call void @use_pointer(i8* %x)
+  ret void
+}
+
+; Same as test2 but the value is returned. Do an RV optimization.
+
+; CHECK-LABEL: define i8* @test2b(
+; CHECK: tail call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %x) [[NUW]]
+; CHECK: }
+define i8* @test2b(i8* %x) nounwind {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
+  ret i8* %x
+}
+
+; Merge a retain,autorelease pair around a call.
+
+; CHECK-LABEL: define void @test3(
+; CHECK: tail call i8* @llvm.objc.retainAutorelease(i8* %x) [[NUW]]
+; CHECK: @use_pointer(i8* %0)
+; CHECK: }
+define void @test3(i8* %x, i64 %n) {
+entry:
+  tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  ret void
+}
+
+; Trivial retain,autorelease pair with intervening call, but it's post-dominated
+; by another release. The retain and autorelease can be merged.
+
+; CHECK-LABEL: define void @test4(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: @llvm.objc.retainAutorelease(i8* %x) [[NUW]]
+; CHECK-NEXT: @use_pointer
+; CHECK-NEXT: @llvm.objc.release
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test4(i8* %x, i64 %n) {
+entry:
+  tail call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %x)
+  call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  tail call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Don't merge retain and autorelease if they're not control-equivalent.
+
+; CHECK-LABEL: define void @test5(
+; CHECK: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK: true:
+; CHECK: call i8* @llvm.objc.autorelease(i8* %0) [[NUW]]
+; CHECK: }
+define void @test5(i8* %p, i1 %a) {
+entry:
+  tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  br i1 %a, label %true, label %false
+
+true:
+  call i8* @llvm.objc.autorelease(i8* %p) nounwind
+  call void @use_pointer(i8* %p)
+  ret void
+
+false:
+  ret void
+}
+
+; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
+; an objc_autorelease.
+; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
+; objc_retainAutoreleasedReturnValueAutorelease and merge
+; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
+; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
+; Those entrypoints don't exist yet though.
+
+; CHECK-LABEL: define i8* @test6(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p) [[NUW]]
+; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %1) [[NUW]]
+; CHECK: }
+define i8* @test6() {
+  %p = call i8* @returner()
+  tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p) nounwind
+  %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p) nounwind
+  call void @use_pointer(i8* %t)
+  ret i8* %t
+}
+
+; Don't spoil the RV optimization.
+
+; CHECK: define i8* @test7(i8* %p)
+; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
+; CHECK: call void @use_pointer(i8* %1)
+; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %1)
+; CHECK: ret i8* %2
+; CHECK-NEXT: }
+define i8* @test7(i8* %p) {
+  %1 = tail call i8* @llvm.objc.retain(i8* %p)
+  call void @use_pointer(i8* %p)
+  %2 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  ret i8* %p
+}
+
+; Do the return value substitution for PHI nodes too.
+
+; CHECK-LABEL: define i8* @test8(
+; CHECK: %retval = phi i8* [ %p, %if.then ], [ null, %entry ]
+; CHECK: }
+define i8* @test8(i1 %x, i8* %c) {
+entry:
+  br i1 %x, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %p = call i8* @llvm.objc.retain(i8* %c) nounwind
+  br label %return
+
+return:                                           ; preds = %if.then, %entry
+  %retval = phi i8* [ %c, %if.then ], [ null, %entry ]
+  ret i8* %retval
+}
+
+; Kill calls to @llvm.objc.clang.arc.use(...)
+; CHECK-LABEL: define void @test9(
+; CHECK-NOT: clang.arc.use
+; CHECK: }
+define void @test9(i8* %a, i8* %b) {
+  call void (...) @llvm.objc.clang.arc.use(i8* %a, i8* %b) nounwind
+  ret void
+}
+
+
+; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand
+; is a return value.
+
+; CHECK: define void @test10()
+; CHECK: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+define void @test10() {
+  %p = call i8* @returner()
+  tail call i8* @llvm.objc.retain(i8* %p) nounwind
+  ret void
+}
+
+; Convert objc_retain to objc_retainAutoreleasedReturnValue if its
+; argument is a return value.
+
+; CHECK-LABEL: define void @test11(
+; CHECK-NEXT: %y = call i8* @returner()
+; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y) [[NUW]]
+; CHECK-NEXT: ret void
+define void @test11() {
+  %y = call i8* @returner()
+  tail call i8* @llvm.objc.retain(i8* %y) nounwind
+  ret void
+}
+
+; Don't convert objc_retain to objc_retainAutoreleasedReturnValue if its
+; argument is not a return value.
+
+; CHECK-LABEL: define void @test12(
+; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %y) [[NUW]]
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test12(i8* %y) {
+  tail call i8* @llvm.objc.retain(i8* %y) nounwind
+  ret void
+}
+
+; Don't Convert objc_retain to objc_retainAutoreleasedReturnValue if it
+; isn't next to the call providing its return value.
+
+; CHECK-LABEL: define void @test13(
+; CHECK-NEXT: %y = call i8* @returner()
+; CHECK-NEXT: call void @callee()
+; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %y) [[NUW]]
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test13() {
+  %y = call i8* @returner()
+  call void @callee()
+  tail call i8* @llvm.objc.retain(i8* %y) nounwind
+  ret void
+}
+
+
+declare void @llvm.objc.clang.arc.use(...) nounwind
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/empty-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/empty-block.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/empty-block.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/empty-block.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+; rdar://10210274
+
+%0 = type opaque
+
+declare i8* @llvm.objc.retain(i8*)
+
+declare void @llvm.objc.release(i8*)
+
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+
+; Don't delete the autorelease.
+
+; CHECK-LABEL: define %0* @test0(
+; CHECK:   @llvm.objc.retain
+; CHECK: .lr.ph:
+; CHECK-NOT: @llvm.objc.r
+; CHECK: @llvm.objc.autoreleaseReturnValue
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define %0* @test0(%0* %buffer) nounwind {
+  %1 = bitcast %0* %buffer to i8*
+  %2 = tail call i8* @llvm.objc.retain(i8* %1) nounwind
+  br i1 undef, label %.lr.ph, label %._crit_edge
+
+.lr.ph:                                           ; preds = %.lr.ph, %0
+  br i1 false, label %.lr.ph, label %._crit_edge
+
+._crit_edge:                                      ; preds = %.lr.ph, %0
+  %3 = tail call i8* @llvm.objc.retain(i8* %1) nounwind
+  tail call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  %4 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %1) nounwind
+  ret %0* %buffer
+}
+
+; Do delete the autorelease, even with the retain in a different block.
+
+; CHECK-LABEL: define %0* @test1(
+; CHECK-NOT: @objc
+; CHECK: }
+define %0* @test1() nounwind {
+  %buffer = call %0* @foo()
+  %1 = bitcast %0* %buffer to i8*
+  %2 = tail call i8* @llvm.objc.retain(i8* %1) nounwind
+  br i1 undef, label %.lr.ph, label %._crit_edge
+
+.lr.ph:                                           ; preds = %.lr.ph, %0
+  br i1 false, label %.lr.ph, label %._crit_edge
+
+._crit_edge:                                      ; preds = %.lr.ph, %0
+  %3 = tail call i8* @llvm.objc.retain(i8* %1) nounwind
+  tail call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  %4 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %1) nounwind
+  ret %0* %buffer
+}
+
+declare %0* @foo()
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,171 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+; rdar://11744105
+; bugzilla://14584
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.9.0"
+
+%0 = type opaque
+%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* }
+%struct._objc_cache = type opaque
+%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* }
+%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }
+%struct._objc_method = type { i8*, i8*, i8* }
+%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] }
+%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32, i8** }
+%struct._prop_list_t = type { i32, i32, [0 x %struct._prop_t] }
+%struct._prop_t = type { i8*, i8* }
+%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }
+%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 }
+%struct.NSConstantString = type { i32*, i32, i8*, i64 }
+
+@"OBJC_CLASS_$_NSObject" = external global %struct._class_t
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_" = internal global %struct._class_t* @"OBJC_CLASS_$_NSObject", section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_METH_VAR_NAME_" = internal global [4 x i8] c"new\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+ at __CFConstantStringClassReference = external global [0 x i32]
+ at .str = private unnamed_addr constant [11 x i8] c"Failed: %@\00", align 1
+ at _unnamed_cfstring_ = private constant %struct.NSConstantString { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i64 10 }, section "__DATA,__cfstring"
+@"OBJC_CLASS_$_NSException" = external global %struct._class_t
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_1" = internal global %struct._class_t* @"OBJC_CLASS_$_NSException", section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+ at .str2 = private unnamed_addr constant [4 x i8] c"Foo\00", align 1
+ at _unnamed_cfstring_3 = private constant %struct.NSConstantString { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring"
+@"\01L_OBJC_METH_VAR_NAME_4" = internal global [14 x i8] c"raise:format:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+@"\01L_OBJC_SELECTOR_REFERENCES_5" = internal global i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_OBJC_METH_VAR_NAME_4", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+ at llvm.used = appending global [6 x i8*] [i8* bitcast (%struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_" to i8*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_" to i8*), i8* bitcast (%struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_1" to i8*), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_OBJC_METH_VAR_NAME_4", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_5" to i8*)], section "llvm.metadata"
+
+define i32 @main() uwtable ssp personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) !dbg !5 {
+entry:
+  %tmp = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_", align 8, !dbg !37
+  %tmp1 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8, !dbg !37, !invariant.load !38
+  %tmp2 = bitcast %struct._class_t* %tmp to i8*, !dbg !37
+; CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %tmp2, i8* %tmp1)
+  %call = call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %tmp2, i8* %tmp1), !dbg !37, !clang.arc.no_objc_arc_exceptions !38
+  call void @llvm.dbg.value(metadata i8* %call, metadata !25, metadata !DIExpression()), !dbg !37
+; CHECK: call i8* @llvm.objc.retain(i8* %call) [[NUW:#[0-9]+]]
+  %tmp3 = call i8* @llvm.objc.retain(i8* %call) nounwind, !dbg !39
+  call void @llvm.dbg.value(metadata i8* %call, metadata !25, metadata !DIExpression()), !dbg !39
+  invoke fastcc void @ThrowFunc(i8* %call)
+          to label %eh.cont unwind label %lpad, !dbg !40, !clang.arc.no_objc_arc_exceptions !38
+
+eh.cont:                                          ; preds = %entry
+; CHECK: call void @llvm.objc.release(i8* %call)
+  call void @llvm.objc.release(i8* %call) nounwind, !dbg !42, !clang.imprecise_release !38
+  br label %if.end, !dbg !43
+
+lpad:                                             ; preds = %entry
+  %tmp4 = landingpad { i8*, i32 }
+          catch i8* null, !dbg !40
+  %tmp5 = extractvalue { i8*, i32 } %tmp4, 0, !dbg !40
+  %exn.adjusted = call i8* @llvm.objc.begin_catch(i8* %tmp5) nounwind, !dbg !44
+  call void @llvm.dbg.value(metadata i8 0, metadata !21, metadata !DIExpression()), !dbg !46
+  call void @llvm.objc.end_catch(), !dbg !49, !clang.arc.no_objc_arc_exceptions !38
+; CHECK: call void @llvm.objc.release(i8* %call)
+  call void @llvm.objc.release(i8* %call) nounwind, !dbg !42, !clang.imprecise_release !38
+  call void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i8* %call), !dbg !50, !clang.arc.no_objc_arc_exceptions !38
+  br label %if.end, !dbg !52
+
+if.end:                                           ; preds = %lpad, %eh.cont
+  call void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i8* %call), !dbg !53, !clang.arc.no_objc_arc_exceptions !38
+; CHECK: call void @llvm.objc.release(i8* %call)
+  call void @llvm.objc.release(i8* %call) nounwind, !dbg !54, !clang.imprecise_release !38
+  ret i32 0, !dbg !54
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
+
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...) nonlazybind
+
+declare i8* @llvm.objc.retain(i8*) nonlazybind
+
+declare i8* @llvm.objc.begin_catch(i8*)
+
+declare void @llvm.objc.end_catch()
+
+declare void @llvm.objc.exception_rethrow()
+
+define internal fastcc void @ThrowFunc(i8* %obj) uwtable noinline ssp !dbg !27 {
+entry:
+  %tmp = call i8* @llvm.objc.retain(i8* %obj) nounwind
+  call void @llvm.dbg.value(metadata i8* %obj, metadata !32, metadata !DIExpression()), !dbg !55
+  %tmp1 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_1", align 8, !dbg !56
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_5", align 8, !dbg !56, !invariant.load !38
+  %tmp3 = bitcast %struct._class_t* %tmp1 to i8*, !dbg !56
+  call void (i8*, i8*, %0*, %0*, ...) bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, %0*, %0*, ...)*)(i8* %tmp3, i8* %tmp2, %0* bitcast (%struct.NSConstantString* @_unnamed_cfstring_3 to %0*), %0* bitcast (%struct.NSConstantString* @_unnamed_cfstring_3 to %0*)), !dbg !56, !clang.arc.no_objc_arc_exceptions !38
+  call void @llvm.objc.release(i8* %obj) nounwind, !dbg !58, !clang.imprecise_release !38
+  ret void, !dbg !58
+}
+
+declare i32 @__objc_personality_v0(...)
+
+declare void @llvm.objc.release(i8*) nonlazybind
+
+declare void @NSLog(i8*, ...)
+
+declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
+
+; CHECK: attributes #0 = { ssp uwtable }
+; CHECK: attributes #1 = { nounwind readnone speculatable }
+; CHECK: attributes #2 = { nonlazybind }
+; CHECK: attributes [[NUW]] = { nounwind }
+; CHECK: attributes #4 = { noinline ssp uwtable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!33, !34, !35, !36, !61}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, producer: "clang version 3.3 ", isOptimized: true, runtimeVersion: 2, emissionKind: FullDebug, file: !60, enums: !1, retainedTypes: !1, globals: !1)
+!1 = !{}
+!5 = distinct !DISubprogram(name: "main", line: 9, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0, scopeLine: 10, file: !60, scope: !6, type: !7, retainedNodes: !11)
+!6 = !DIFile(filename: "test.m", directory: "/Volumes/Files/gottesmmcab/Radar/12906997")
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9}
+!9 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!11 = !{!12, !21, !25}
+!12 = !DILocalVariable(name: "obj", line: 11, scope: !13, file: !6, type: !14)
+!13 = distinct !DILexicalBlock(line: 10, column: 0, file: !60, scope: !5)
+!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "id", line: 11, file: !60, baseType: !15)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, file: !60, baseType: !16)
+!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_object", file: !60, elements: !17)
+!17 = !{!18}
+!18 = !DIDerivedType(tag: DW_TAG_member, name: "isa", size: 64, file: !60, scope: !16, baseType: !19)
+!19 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, baseType: !20)
+!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "objc_class", flags: DIFlagFwdDecl, file: !60)
+!21 = !DILocalVariable(name: "ok", line: 13, scope: !22, file: !6, type: !23)
+!22 = distinct !DILexicalBlock(line: 12, column: 0, file: !60, scope: !13)
+!23 = !DIDerivedType(tag: DW_TAG_typedef, name: "BOOL", line: 62, file: !60, baseType: !24)
+!24 = !DIBasicType(tag: DW_TAG_base_type, name: "signed char", size: 8, align: 8, encoding: DW_ATE_signed_char)
+!25 = !DILocalVariable(name: "obj2", line: 15, scope: !26, file: !6, type: !14)
+!26 = distinct !DILexicalBlock(line: 14, column: 0, file: !60, scope: !22)
+!27 = distinct !DISubprogram(name: "ThrowFunc", line: 4, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 5, file: !60, scope: !6, type: !28, retainedNodes: !31)
+!28 = !DISubroutineType(types: !29)
+!29 = !{null, !14}
+!31 = !{!32}
+!32 = !DILocalVariable(name: "obj", line: 4, arg: 1, scope: !27, file: !6, type: !14)
+!33 = !{i32 1, !"Objective-C Version", i32 2}
+!34 = !{i32 1, !"Objective-C Image Info Version", i32 0}
+!35 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
+!36 = !{i32 4, !"Objective-C Garbage Collection", i32 0}
+!37 = !DILocation(line: 11, scope: !13)
+!38 = !{}
+!39 = !DILocation(line: 15, scope: !26)
+!40 = !DILocation(line: 17, scope: !41)
+!41 = distinct !DILexicalBlock(line: 16, column: 0, file: !60, scope: !26)
+!42 = !DILocation(line: 22, scope: !26)
+!43 = !DILocation(line: 23, scope: !22)
+!44 = !DILocation(line: 19, scope: !41)
+!45 = !{i8 0}
+!46 = !DILocation(line: 20, scope: !47)
+!47 = distinct !DILexicalBlock(line: 19, column: 0, file: !60, scope: !48)
+!48 = distinct !DILexicalBlock(line: 19, column: 0, file: !60, scope: !26)
+!49 = !DILocation(line: 21, scope: !47)
+!50 = !DILocation(line: 24, scope: !51)
+!51 = distinct !DILexicalBlock(line: 23, column: 0, file: !60, scope: !22)
+!52 = !DILocation(line: 25, scope: !51)
+!53 = !DILocation(line: 27, scope: !13)
+!54 = !DILocation(line: 28, scope: !13)
+!55 = !DILocation(line: 4, scope: !27)
+!56 = !DILocation(line: 6, scope: !57)
+!57 = distinct !DILexicalBlock(line: 5, column: 0, file: !60, scope: !27)
+!58 = !DILocation(line: 7, scope: !57)
+!60 = !DIFile(filename: "test.m", directory: "/Volumes/Files/gottesmmcab/Radar/12906997")
+!61 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/ObjCARC/escape.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/escape.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/escape.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/escape.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,134 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+; rdar://11229925
+
+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"
+
+%struct.__block_byref_weakLogNTimes = type { i8*, %struct.__block_byref_weakLogNTimes*, i32, i32, i8*, i8*, void (...)* }
+%struct.__block_descriptor = type { i64, i64 }
+
+; Don't optimize away the retainBlock, because the object's address "escapes"
+; with the objc_storeWeak call.
+
+; CHECK-LABEL: define void @test0(
+; CHECK: %tmp7 = call i8* @llvm.objc.retainBlock(i8* %tmp6) [[NUW:#[0-9]+]], !clang.arc.copy_on_escape !0
+; CHECK: call void @llvm.objc.release(i8* %tmp7) [[NUW]], !clang.imprecise_release !0
+; CHECK: }
+define void @test0() nounwind {
+entry:
+  %weakLogNTimes = alloca %struct.__block_byref_weakLogNTimes, align 8
+  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
+  %byref.isa = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 0
+  store i8* null, i8** %byref.isa, align 8
+  %byref.forwarding = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 1
+  store %struct.__block_byref_weakLogNTimes* %weakLogNTimes, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
+  %byref.flags = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 2
+  store i32 33554432, i32* %byref.flags, align 8
+  %byref.size = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 3
+  store i32 48, i32* %byref.size, align 4
+  %tmp1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 4
+  store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_ to i8*), i8** %tmp1, align 8
+  %tmp2 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 5
+  store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_ to i8*), i8** %tmp2, align 8
+  %weakLogNTimes1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 6
+  %tmp3 = bitcast void (...)** %weakLogNTimes1 to i8**
+  %tmp4 = call i8* @llvm.objc.initWeak(i8** %tmp3, i8* null) nounwind
+  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 0
+  store i8* null, i8** %block.isa, align 8
+  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 1
+  store i32 1107296256, i32* %block.flags, align 8
+  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 2
+  store i32 0, i32* %block.reserved, align 4
+  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 3
+  store i8* bitcast (void (i8*, i32)* @__main_block_invoke_0 to i8*), i8** %block.invoke, align 8
+  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 4
+  store %struct.__block_descriptor* null, %struct.__block_descriptor** %block.descriptor, align 8
+  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 5
+  %tmp5 = bitcast %struct.__block_byref_weakLogNTimes* %weakLogNTimes to i8*
+  store i8* %tmp5, i8** %block.captured, align 8
+  %tmp6 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block to i8*
+  %tmp7 = call i8* @llvm.objc.retainBlock(i8* %tmp6) nounwind, !clang.arc.copy_on_escape !0
+  %tmp8 = load %struct.__block_byref_weakLogNTimes*, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
+  %weakLogNTimes3 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %tmp8, i64 0, i32 6
+  %tmp9 = bitcast void (...)** %weakLogNTimes3 to i8**
+  %tmp10 = call i8* @llvm.objc.storeWeak(i8** %tmp9, i8* %tmp7) nounwind
+  %tmp11 = getelementptr inbounds i8, i8* %tmp7, i64 16
+  %tmp12 = bitcast i8* %tmp11 to i8**
+  %tmp13 = load i8*, i8** %tmp12, align 8
+  %tmp14 = bitcast i8* %tmp13 to void (i8*, i32)*
+  call void %tmp14(i8* %tmp7, i32 10) nounwind, !clang.arc.no_objc_arc_exceptions !0
+  call void @llvm.objc.release(i8* %tmp7) nounwind, !clang.imprecise_release !0
+  call void @_Block_object_dispose(i8* %tmp5, i32 8) nounwind
+  call void @llvm.objc.destroyWeak(i8** %tmp3) nounwind
+  ret void
+}
+
+; Like test0, but it makes a regular call instead of a storeWeak call,
+; so the optimization is valid.
+
+; CHECK-LABEL: define void @test1(
+; CHECK-NOT: @llvm.objc.retainBlock
+; CHECK: }
+define void @test1() nounwind {
+entry:
+  %weakLogNTimes = alloca %struct.__block_byref_weakLogNTimes, align 8
+  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
+  %byref.isa = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 0
+  store i8* null, i8** %byref.isa, align 8
+  %byref.forwarding = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 1
+  store %struct.__block_byref_weakLogNTimes* %weakLogNTimes, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
+  %byref.flags = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 2
+  store i32 33554432, i32* %byref.flags, align 8
+  %byref.size = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 3
+  store i32 48, i32* %byref.size, align 4
+  %tmp1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 4
+  store i8* bitcast (void (i8*, i8*)* @__Block_byref_object_copy_ to i8*), i8** %tmp1, align 8
+  %tmp2 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 5
+  store i8* bitcast (void (i8*)* @__Block_byref_object_dispose_ to i8*), i8** %tmp2, align 8
+  %weakLogNTimes1 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %weakLogNTimes, i64 0, i32 6
+  %tmp3 = bitcast void (...)** %weakLogNTimes1 to i8**
+  %tmp4 = call i8* @llvm.objc.initWeak(i8** %tmp3, i8* null) nounwind
+  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 0
+  store i8* null, i8** %block.isa, align 8
+  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 1
+  store i32 1107296256, i32* %block.flags, align 8
+  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 2
+  store i32 0, i32* %block.reserved, align 4
+  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 3
+  store i8* bitcast (void (i8*, i32)* @__main_block_invoke_0 to i8*), i8** %block.invoke, align 8
+  %block.descriptor = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 4
+  store %struct.__block_descriptor* null, %struct.__block_descriptor** %block.descriptor, align 8
+  %block.captured = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block, i64 0, i32 5
+  %tmp5 = bitcast %struct.__block_byref_weakLogNTimes* %weakLogNTimes to i8*
+  store i8* %tmp5, i8** %block.captured, align 8
+  %tmp6 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>* %block to i8*
+  %tmp7 = call i8* @llvm.objc.retainBlock(i8* %tmp6) nounwind, !clang.arc.copy_on_escape !0
+  %tmp8 = load %struct.__block_byref_weakLogNTimes*, %struct.__block_byref_weakLogNTimes** %byref.forwarding, align 8
+  %weakLogNTimes3 = getelementptr inbounds %struct.__block_byref_weakLogNTimes, %struct.__block_byref_weakLogNTimes* %tmp8, i64 0, i32 6
+  %tmp9 = bitcast void (...)** %weakLogNTimes3 to i8**
+  %tmp10 = call i8* @not_really_objc_storeWeak(i8** %tmp9, i8* %tmp7) nounwind
+  %tmp11 = getelementptr inbounds i8, i8* %tmp7, i64 16
+  %tmp12 = bitcast i8* %tmp11 to i8**
+  %tmp13 = load i8*, i8** %tmp12, align 8
+  %tmp14 = bitcast i8* %tmp13 to void (i8*, i32)*
+  call void %tmp14(i8* %tmp7, i32 10) nounwind, !clang.arc.no_objc_arc_exceptions !0
+  call void @llvm.objc.release(i8* %tmp7) nounwind, !clang.imprecise_release !0
+  call void @_Block_object_dispose(i8* %tmp5, i32 8) nounwind
+  call void @llvm.objc.destroyWeak(i8** %tmp3) nounwind
+  ret void
+}
+
+declare void @__Block_byref_object_copy_(i8*, i8*) nounwind
+declare void @__Block_byref_object_dispose_(i8*) nounwind
+declare void @llvm.objc.destroyWeak(i8**)
+declare i8* @llvm.objc.initWeak(i8**, i8*)
+declare void @__main_block_invoke_0(i8* nocapture, i32) nounwind ssp
+declare void @_Block_object_dispose(i8*, i32)
+declare i8* @llvm.objc.retainBlock(i8*)
+declare i8* @llvm.objc.storeWeak(i8**, i8*)
+declare i8* @not_really_objc_storeWeak(i8**, i8*)
+declare void @llvm.objc.release(i8*)
+
+!0 = !{}
+
+; CHECK: attributes [[NUW]] = { nounwind }
+; CHECK: attributes #1 = { nounwind ssp }

Added: llvm/trunk/test/Transforms/ObjCARC/expand.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/expand.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/expand.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/expand.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,94 @@
+; RUN: opt -objc-arc-expand -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+declare i8* @llvm.objc.retain(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.retainAutorelease(i8*)
+declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.retainBlock(i8*)
+
+declare void @use_pointer(i8*)
+
+; CHECK: define void @test_retain(i8* %x) [[NUW:#[0-9]+]] {
+; CHECK: call i8* @llvm.objc.retain(i8* %x)
+; CHECK: call void @use_pointer(i8* %x)
+; CHECK: }
+define void @test_retain(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}
+
+; CHECK: define void @test_retainAutoreleasedReturnValue(i8* %x) [[NUW]] {
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x)
+; CHECK: call void @use_pointer(i8* %x)
+; CHECK: }
+define void @test_retainAutoreleasedReturnValue(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}
+
+; CHECK: define void @test_retainAutorelease(i8* %x) [[NUW]] {
+; CHECK: call i8* @llvm.objc.retainAutorelease(i8* %x)
+; CHECK: call void @use_pointer(i8* %x)
+; CHECK: }
+define void @test_retainAutorelease(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retainAutorelease(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}
+
+; CHECK: define void @test_retainAutoreleaseReturnValue(i8* %x) [[NUW]] {
+; CHECK: call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %x)
+; CHECK: call void @use_pointer(i8* %x)
+; CHECK: }
+define void @test_retainAutoreleaseReturnValue(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}
+
+; CHECK: define void @test_autorelease(i8* %x) [[NUW]] {
+; CHECK: call i8* @llvm.objc.autorelease(i8* %x)
+; CHECK: call void @use_pointer(i8* %x)
+; CHECK: }
+define void @test_autorelease(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}
+
+; CHECK: define void @test_autoreleaseReturnValue(i8* %x) [[NUW]] {
+; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %x)
+; CHECK: call void @use_pointer(i8* %x)
+; CHECK: }
+define void @test_autoreleaseReturnValue(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; RetainBlock is not strictly forwarding. Do not touch it. ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; CHECK: define void @test_retainBlock(i8* %x) [[NUW]] {
+; CHECK: call i8* @llvm.objc.retainBlock(i8* %x)
+; CHECK: call void @use_pointer(i8* %0)
+; CHECK: }
+define void @test_retainBlock(i8* %x) nounwind {
+entry:
+  %0 = call i8* @llvm.objc.retainBlock(i8* %x) nounwind
+  call void @use_pointer(i8* %0)
+  ret void
+}

Added: llvm/trunk/test/Transforms/ObjCARC/funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/funclet.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/funclet.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/funclet.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; RUN: opt -mtriple x86_64-unknown-windows-msvc -objc-arc -S -o - %s | FileCheck %s
+
+; bool g();
+; id h();
+;
+; void f() {
+;   id a = nullptr;
+;   if (g())
+;     a = h();
+;   id b = nullptr;
+;   g();
+; }
+
+declare zeroext i1 @"\01?g@@YA_NXZ"() local_unnamed_addr
+declare i8* @"\01?h@@YAPEAUobjc_object@@XZ"() local_unnamed_addr
+
+declare dllimport void @llvm.objc.release(i8*) local_unnamed_addr
+declare dllimport i8* @llvm.objc.retainAutoreleasedReturnValue(i8* returned) local_unnamed_addr
+
+declare i32 @__CxxFrameHandler3(...)
+
+define void @"\01?f@@YAXXZ"() local_unnamed_addr personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %call = invoke zeroext i1 @"\01?g@@YA_NXZ"()
+          to label %invoke.cont unwind label %ehcleanup6
+
+invoke.cont:                                      ; preds = %entry
+  br i1 %call, label %if.then, label %if.end
+
+if.then:                                          ; preds = %invoke.cont
+  %call2 = invoke i8* @"\01?h@@YAPEAUobjc_object@@XZ"()
+          to label %invoke.cont1 unwind label %ehcleanup6
+
+invoke.cont1:                                     ; preds = %if.then
+  %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call2)
+  tail call void @llvm.objc.release(i8* null), !clang.imprecise_release !1
+  br label %if.end
+
+if.end:                                           ; preds = %invoke.cont1, %invoke.cont
+  %a.0 = phi i8* [ %call2, %invoke.cont1 ], [ null, %invoke.cont ]
+  %call4 = invoke zeroext i1 @"\01?g@@YA_NXZ"()
+          to label %invoke.cont3 unwind label %ehcleanup
+
+invoke.cont3:                                     ; preds = %if.end
+  tail call void @llvm.objc.release(i8* null), !clang.imprecise_release !1
+  tail call void @llvm.objc.release(i8* %a.0), !clang.imprecise_release !1
+  ret void
+
+ehcleanup:                                        ; preds = %if.end
+  %1 = cleanuppad within none []
+  call void @llvm.objc.release(i8* null) [ "funclet"(token %1) ], !clang.imprecise_release !1
+  cleanupret from %1 unwind label %ehcleanup6
+
+ehcleanup6:                                       ; preds = %ehcleanup, %if.then, %entry
+  %a.1 = phi i8* [ %a.0, %ehcleanup ], [ null, %if.then ], [ null, %entry ]
+  %2 = cleanuppad within none []
+  call void @llvm.objc.release(i8* %a.1) [ "funclet"(token %2) ], !clang.imprecise_release !1
+  cleanupret from %2 unwind to caller
+}
+
+; CHECK-LABEL: ?f@@YAXXZ
+; CHECK: call void @llvm.objc.release(i8* {{.*}}) {{.*}}[ "funclet"(token %1) ]
+; CHECK-NOT: call void @llvm.objc.release(i8* {{.*}}) {{.*}}[ "funclet"(token %2) ]
+
+define void @"\01?i@@YAXXZ"() local_unnamed_addr personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %call = invoke zeroext i1 @"\01?g@@YA_NXZ"()
+          to label %invoke.cont unwind label %ehcleanup6
+
+invoke.cont:                                      ; preds = %entry
+  br i1 %call, label %if.then, label %if.end
+
+if.then:                                          ; preds = %invoke.cont
+  %call2 = invoke i8* @"\01?h@@YAPEAUobjc_object@@XZ"()
+          to label %invoke.cont1 unwind label %ehcleanup6
+
+invoke.cont1:                                     ; preds = %if.then
+  %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call2)
+  tail call void @llvm.objc.release(i8* null), !clang.imprecise_release !1
+  br label %if.end
+
+if.end:                                           ; preds = %invoke.cont1, %invoke.cont
+  %a.0 = phi i8* [ %call2, %invoke.cont1 ], [ null, %invoke.cont ]
+  %call4 = invoke zeroext i1 @"\01?g@@YA_NXZ"()
+          to label %invoke.cont3 unwind label %ehcleanup
+
+invoke.cont3:                                     ; preds = %if.end
+  tail call void @llvm.objc.release(i8* null), !clang.imprecise_release !1
+  tail call void @llvm.objc.release(i8* %a.0), !clang.imprecise_release !1
+  ret void
+
+ehcleanup:                                        ; preds = %if.end
+  %1 = cleanuppad within none []
+  call void @llvm.objc.release(i8* null) [ "funclet"(token %1) ], !clang.imprecise_release !1
+  br label %ehcleanup.1
+
+ehcleanup.1:
+  cleanupret from %1 unwind label %ehcleanup6
+
+ehcleanup6:                                       ; preds = %ehcleanup, %if.then, %entry
+  %a.1 = phi i8* [ %a.0, %ehcleanup.1 ], [ null, %if.then ], [ null, %entry ]
+  %2 = cleanuppad within none []
+  call void @llvm.objc.release(i8* %a.1) [ "funclet"(token %2) ], !clang.imprecise_release !1
+  cleanupret from %2 unwind to caller
+}
+
+; CHECK-LABEL: ?i@@YAXXZ
+; CHECK: call void @llvm.objc.release(i8* {{.*}}) {{.*}}[ "funclet"(token %1) ]
+; CHECK-NOT: call void @llvm.objc.release(i8* {{.*}}) {{.*}}[ "funclet"(token %2) ]
+
+!1 = !{}
+

Added: llvm/trunk/test/Transforms/ObjCARC/gvn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/gvn.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/gvn.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/gvn.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt -S -basicaa -objc-arc-aa -gvn < %s | FileCheck %s
+
+ at x = common global i8* null, align 8
+
+declare i8* @llvm.objc.retain(i8*)
+declare i32 @llvm.objc.sync.enter(i8*)
+declare i32 @llvm.objc.sync.exit(i8*)
+
+; GVN should be able to eliminate this redundant load, with ARC-specific
+; alias analysis.
+
+; CHECK: define i8* @test0(i32 %n)
+; CHECK-NEXT: entry:
+; CHECK-NEXT: %s = load i8*, i8** @x
+; CHECK-NOT: load
+; CHECK: ret i8* %s
+; CHECK-NEXT: }
+define i8* @test0(i32 %n) nounwind {
+entry:
+  %s = load i8*, i8** @x
+  %0 = tail call i8* @llvm.objc.retain(i8* %s) nounwind
+  %t = load i8*, i8** @x
+  ret i8* %t
+}
+
+; GVN should not be able to eliminate this redundant load, with ARC-specific
+; alias analysis.
+
+; CHECK-LABEL: define i8* @test1(
+; CHECK: load
+; CHECK: load
+; CHECK: ret i8* %t
+; CHECK: }
+define i8* @test1(i32 %n) nounwind {
+entry:
+  %s = load i8*, i8** @x
+  %0 = call i32 @llvm.objc.sync.enter(i8* %s)
+  %t = load i8*, i8** @x
+  %1 = call i32 @llvm.objc.sync.exit(i8* %s)
+  ret i8* %t
+}

Added: llvm/trunk/test/Transforms/ObjCARC/intrinsic-use-isolated.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/intrinsic-use-isolated.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/intrinsic-use-isolated.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/intrinsic-use-isolated.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+
+; This file makes sure that clang.arc.used is removed even if no other ARC
+; interesting calls are in the module.
+
+declare void @llvm.objc.clang.arc.use(...) nounwind
+
+; Kill calls to @llvm.objc.clang.arc.use(...)
+; CHECK-LABEL: define void @test0(
+; CHECK-NOT: clang.arc.use
+; CHECK: }
+define void @test0(i8* %a, i8* %b) {
+  call void (...) @llvm.objc.clang.arc.use(i8* %a, i8* %b) nounwind
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/ObjCARC/intrinsic-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/intrinsic-use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/intrinsic-use.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/intrinsic-use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,113 @@
+; RUN: opt -basicaa -objc-arc -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+declare i8* @llvm.objc.retain(i8*)
+declare i8* @llvm.objc.retainAutorelease(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+
+declare void @llvm.objc.clang.arc.use(...)
+
+declare void @test0_helper(i8*, i8**)
+
+; Ensure that we honor clang.arc.use as a use and don't miscompile
+; the reduced test case from <rdar://13195034>.
+;
+; CHECK-LABEL:      define void @test0(
+; CHECK:        @llvm.objc.retain(i8* %x)
+; CHECK-NEXT:   store i8* %y, i8** %temp0
+; CHECK-NEXT:   @llvm.objc.retain(i8* %y)
+; CHECK-NEXT:   call void @test0_helper
+; CHECK-NEXT:   [[VAL1:%.*]] = load i8*, i8** %temp0
+; CHECK-NEXT:   @llvm.objc.retain(i8* [[VAL1]])
+; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(i8* %y)
+; CHECK-NEXT:   @llvm.objc.release(i8* %y)
+; CHECK-NEXT:   store i8* [[VAL1]], i8** %temp1
+; CHECK-NEXT:   call void @test0_helper
+; CHECK-NEXT:   [[VAL2:%.*]] = load i8*, i8** %temp1
+; CHECK-NEXT:   @llvm.objc.retain(i8* [[VAL2]])
+; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(i8* [[VAL1]])
+; CHECK-NEXT:   @llvm.objc.release(i8* [[VAL1]])
+; CHECK-NEXT:   @llvm.objc.autorelease(i8* %x)
+; CHECK-NEXT:   store i8* %x, i8** %out
+; CHECK-NEXT:   @llvm.objc.retain(i8* %x)
+; CHECK-NEXT:   @llvm.objc.release(i8* [[VAL2]])
+; CHECK-NEXT:   @llvm.objc.release(i8* %x)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test0(i8** %out, i8* %x, i8* %y) {
+entry:
+  %temp0 = alloca i8*, align 8
+  %temp1 = alloca i8*, align 8
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  %1 = call i8* @llvm.objc.retain(i8* %y) nounwind
+  store i8* %y, i8** %temp0
+  call void @test0_helper(i8* %x, i8** %temp0)
+  %val1 = load i8*, i8** %temp0
+  %2 = call i8* @llvm.objc.retain(i8* %val1) nounwind
+  call void (...) @llvm.objc.clang.arc.use(i8* %y) nounwind
+  call void @llvm.objc.release(i8* %y) nounwind
+  store i8* %val1, i8** %temp1
+  call void @test0_helper(i8* %x, i8** %temp1)
+  %val2 = load i8*, i8** %temp1
+  %3 = call i8* @llvm.objc.retain(i8* %val2) nounwind
+  call void (...) @llvm.objc.clang.arc.use(i8* %val1) nounwind
+  call void @llvm.objc.release(i8* %val1) nounwind
+  %4 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  %5 = call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  store i8* %x, i8** %out
+  call void @llvm.objc.release(i8* %val2) nounwind
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; CHECK-LABEL:      define void @test0a(
+; CHECK:        @llvm.objc.retain(i8* %x)
+; CHECK-NEXT:   store i8* %y, i8** %temp0
+; CHECK-NEXT:   @llvm.objc.retain(i8* %y)
+; CHECK-NEXT:   call void @test0_helper
+; CHECK-NEXT:   [[VAL1:%.*]] = load i8*, i8** %temp0
+; CHECK-NEXT:   @llvm.objc.retain(i8* [[VAL1]])
+; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(i8* %y)
+; CHECK-NEXT:   @llvm.objc.release(i8* %y)
+; CHECK-NEXT:   store i8* [[VAL1]], i8** %temp1
+; CHECK-NEXT:   call void @test0_helper
+; CHECK-NEXT:   [[VAL2:%.*]] = load i8*, i8** %temp1
+; CHECK-NEXT:   @llvm.objc.retain(i8* [[VAL2]])
+; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(i8* [[VAL1]])
+; CHECK-NEXT:   @llvm.objc.release(i8* [[VAL1]])
+; CHECK-NEXT:   @llvm.objc.autorelease(i8* %x)
+; CHECK-NEXT:   @llvm.objc.release(i8* [[VAL2]])
+; CHECK-NEXT:   store i8* %x, i8** %out
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test0a(i8** %out, i8* %x, i8* %y) {
+entry:
+  %temp0 = alloca i8*, align 8
+  %temp1 = alloca i8*, align 8
+  %0 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  %1 = call i8* @llvm.objc.retain(i8* %y) nounwind
+  store i8* %y, i8** %temp0
+  call void @test0_helper(i8* %x, i8** %temp0)
+  %val1 = load i8*, i8** %temp0
+  %2 = call i8* @llvm.objc.retain(i8* %val1) nounwind
+  call void (...) @llvm.objc.clang.arc.use(i8* %y) nounwind
+  call void @llvm.objc.release(i8* %y) nounwind, !clang.imprecise_release !0
+  store i8* %val1, i8** %temp1
+  call void @test0_helper(i8* %x, i8** %temp1)
+  %val2 = load i8*, i8** %temp1
+  %3 = call i8* @llvm.objc.retain(i8* %val2) nounwind
+  call void (...) @llvm.objc.clang.arc.use(i8* %val1) nounwind
+  call void @llvm.objc.release(i8* %val1) nounwind, !clang.imprecise_release !0
+  %4 = call i8* @llvm.objc.retain(i8* %x) nounwind
+  %5 = call i8* @llvm.objc.autorelease(i8* %x) nounwind
+  store i8* %x, i8** %out
+  call void @llvm.objc.release(i8* %val2) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %x) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+
+!0 = !{}
+

Added: llvm/trunk/test/Transforms/ObjCARC/invoke-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/invoke-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/invoke-2.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/invoke-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt -mtriple x86_64-unknown-windows-msvc -objc-arc -o - %s | llvm-dis -o - - | FileCheck %s
+
+target triple = "x86_64-unknown-windows-msvc"
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare dllimport i8* @llvm.objc.msgSend(i8*, i8*, ...) local_unnamed_addr
+
+declare dllimport i8* @llvm.objc.retain(i8* returned) local_unnamed_addr
+declare dllimport void @llvm.objc.release(i8*) local_unnamed_addr
+declare dllimport i8* @llvm.objc.retainAutoreleasedReturnValue(i8* returned) local_unnamed_addr
+
+declare dllimport i8* @llvm.objc.begin_catch(i8*) local_unnamed_addr
+declare dllimport void @llvm.objc.end_catch() local_unnamed_addr
+
+ at llvm.objc.METH_VAR_NAME_ = private unnamed_addr constant [2 x i8] c"m\00", align 1
+ at llvm.objc.SELECTOR_REFERENCES_ = private externally_initialized global i8* getelementptr inbounds ([2 x i8], [2 x i8]* @llvm.objc.METH_VAR_NAME_, i64 0, i64 0), section ".objc_selrefs$B", align 8
+
+define void @f(i8* %i) local_unnamed_addr personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %i)
+  %1 = load i8*, i8** @llvm.objc.SELECTOR_REFERENCES_, align 8, !invariant.load !0
+  %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %0, i8* %1)
+          to label %invoke.cont unwind label %catch.dispatch, !clang.arc.no_objc_arc_exceptions !0
+
+catch.dispatch:                                   ; preds = %entry
+  %2 = catchswitch within none [label %catch] unwind to caller
+
+invoke.cont:                                      ; preds = %entry
+  %3 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call)
+  tail call void @llvm.objc.release(i8* %3) #0, !clang.imprecise_release !0
+  br label %eh.cont
+
+eh.cont:                                          ; preds = %invoke.cont, %catch
+  tail call void @llvm.objc.release(i8* %0) #0, !clang.imprecise_release !0
+  ret void
+
+catch:                                            ; preds = %catch.dispatch
+  %4 = catchpad within %2 [i8* null, i32 0, i8* null]
+  %exn.adjusted = tail call i8* @llvm.objc.begin_catch(i8* undef)
+  tail call void @llvm.objc.end_catch(), !clang.arc.no_objc_arc_exceptions !0
+  br label %eh.cont
+}
+
+; CHECK-LABEL: @f
+
+; CHECK-NOT: tail call i8* @llvm.objc.retain(i8* %i)
+; CHECK: load i8*, i8** @llvm.objc.SELECTOR_REFERENCES_, align 8
+
+; CHECK: eh.cont:
+; CHECK-NOT: call void @llvm.objc.release(i8*
+; CHECK: ret void
+
+attributes #0 = { nounwind }
+
+!0 = !{}
+

Added: llvm/trunk/test/Transforms/ObjCARC/invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/invoke.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/invoke.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/invoke.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,224 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+declare void @use_pointer(i8*)
+declare void @callee()
+declare i8* @returner()
+
+; ARCOpt shouldn't try to move the releases to the block containing the invoke.
+
+; CHECK-LABEL: define void @test0(
+; CHECK: invoke.cont:
+; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW:#[0-9]+]], !clang.imprecise_release !0
+; CHECK:   ret void
+; CHECK: lpad:
+; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
+; CHECK:   ret void
+; CHECK-NEXT: }
+define void @test0(i8* %zipFile) personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  call i8* @llvm.objc.retain(i8* %zipFile) nounwind
+  call void @use_pointer(i8* %zipFile)
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*)*)(i8* %zipFile) 
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %entry
+  call void @llvm.objc.release(i8* %zipFile) nounwind, !clang.imprecise_release !0
+  ret void
+
+lpad:                                             ; preds = %entry
+  %exn = landingpad {i8*, i32}
+           cleanup
+  call void @llvm.objc.release(i8* %zipFile) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; ARCOpt should move the release before the callee calls.
+
+; CHECK-LABEL: define void @test1(
+; CHECK: invoke.cont:
+; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
+; CHECK:   call void @callee()
+; CHECK:   br label %done
+; CHECK: lpad:
+; CHECK:   call void @llvm.objc.release(i8* %zipFile) [[NUW]], !clang.imprecise_release !0
+; CHECK:   call void @callee()
+; CHECK:   br label %done
+; CHECK: done:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test1(i8* %zipFile) personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  call i8* @llvm.objc.retain(i8* %zipFile) nounwind
+  call void @use_pointer(i8* %zipFile)
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*)*)(i8* %zipFile)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %entry
+  call void @callee()
+  br label %done
+
+lpad:                                             ; preds = %entry
+  %exn = landingpad {i8*, i32}
+           cleanup
+  call void @callee()
+  br label %done
+
+done:
+  call void @llvm.objc.release(i8* %zipFile) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; The optimizer should ignore invoke unwind paths consistently.
+; PR12265
+
+; CHECK: define void @test2() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+; CHECK: invoke.cont:
+; CHECK-NEXT: call i8* @llvm.objc.retain
+; CHECK-NOT: @llvm.objc.r
+; CHECK: finally.cont:
+; CHECK-NEXT: call void @llvm.objc.release
+; CHECK-NOT: @objc
+; CHECK: finally.rethrow:
+; CHECK-NOT: @objc
+; CHECK: }
+define void @test2() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  %call = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* ()*)()
+          to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
+
+invoke.cont:                                      ; preds = %entry
+  %tmp1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void ()*)(), !clang.arc.no_objc_arc_exceptions !0
+  invoke void @use_pointer(i8* %call)
+          to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
+
+finally.cont:                                     ; preds = %invoke.cont
+  tail call void @llvm.objc.release(i8* %call) nounwind, !clang.imprecise_release !0
+  ret void
+
+finally.rethrow:                                  ; preds = %invoke.cont, %entry
+  %tmp2 = landingpad { i8*, i32 }
+          catch i8* null
+  unreachable
+}
+
+; Don't try to place code on invoke critical edges.
+
+; CHECK-LABEL: define void @test3(
+; CHECK: if.end:
+; CHECK-NEXT: call void @llvm.objc.release(i8* %p) [[NUW]]
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test3(i8* %p, i1 %b) personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  br i1 %b, label %if.else, label %if.then
+
+if.then:
+  invoke void @use_pointer(i8* %p)
+          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+
+if.else:
+  invoke void @use_pointer(i8* %p)
+          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+
+lpad:
+  %r = landingpad { i8*, i32 }
+       cleanup
+  ret void
+
+if.end:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Like test3, but with ARC-relevant exception handling.
+
+; CHECK-LABEL: define void @test4(
+; CHECK: lpad:
+; CHECK-NEXT: %r = landingpad { i8*, i32 }
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: call void @llvm.objc.release(i8* %p) [[NUW]]
+; CHECK-NEXT: ret void
+; CHECK: if.end:
+; CHECK-NEXT: call void @llvm.objc.release(i8* %p) [[NUW]]
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test4(i8* %p, i1 %b) personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  %0 = call i8* @llvm.objc.retain(i8* %p)
+  call void @callee()
+  br i1 %b, label %if.else, label %if.then
+
+if.then:
+  invoke void @use_pointer(i8* %p)
+          to label %if.end unwind label %lpad
+
+if.else:
+  invoke void @use_pointer(i8* %p)
+          to label %if.end unwind label %lpad
+
+lpad:
+  %r = landingpad { i8*, i32 }
+       cleanup
+  call void @llvm.objc.release(i8* %p)
+  ret void
+
+if.end:
+  call void @llvm.objc.release(i8* %p)
+  ret void
+}
+
+; Don't turn the retainAutoreleaseReturnValue into retain, because it's
+; for an invoke which we can assume codegen will put immediately prior.
+
+; CHECK-LABEL: define void @test5(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
+; CHECK: }
+define void @test5() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  %z = invoke i8* @returner()
+          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+
+lpad:
+  %r13 = landingpad { i8*, i32 }
+          cleanup
+  ret void
+
+if.end:
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
+  ret void
+}
+
+; Like test5, but there's intervening code.
+
+; CHECK-LABEL: define void @test6(
+; CHECK: call i8* @llvm.objc.retain(i8* %z)
+; CHECK: }
+define void @test6() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  %z = invoke i8* @returner()
+          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+
+lpad:
+  %r13 = landingpad { i8*, i32 }
+          cleanup
+  ret void
+
+if.end:
+  call void @callee()
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
+  ret void
+}
+
+declare i32 @__gxx_personality_v0(...)
+declare i32 @__objc_personality_v0(...)
+
+; CHECK: attributes [[NUW]] = { nounwind }
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/move-and-form-retain-autorelease.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/move-and-form-retain-autorelease.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/move-and-form-retain-autorelease.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/move-and-form-retain-autorelease.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,223 @@
+; RUN: opt -S -objc-arc-contract < %s | FileCheck %s
+
+; The optimizer should be able to move the autorelease past a control triangle
+; and various scary looking things and fold it into an objc_retainAutorelease.
+
+; CHECK: bb57:
+; CHECK: tail call i8* @llvm.objc.retainAutorelease(i8* %tmp71x) [[NUW:#[0-9]+]]
+; CHECK: bb99:
+
+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.0"
+
+%0 = type { i8* (i8*, %1*, ...)*, i8* }
+%1 = type { i8*, i8* }
+%2 = type { %2*, %2*, %3*, i8* (i8*, i8*)**, %4* }
+%3 = type opaque
+%4 = type { i32, i32, i32, i8*, i8*, %5*, %7*, %10*, i8*, %9* }
+%5 = type { i32, i32, [0 x %6] }
+%6 = type { i8*, i8*, i8* }
+%7 = type { i64, [0 x %8*] }
+%8 = type { i8*, i8*, %7*, %5*, %5*, %5*, %5*, %9*, i32, i32 }
+%9 = type { i32, i32, [0 x %1] }
+%10 = type { i32, i32, [0 x %11] }
+%11 = type { i64*, i8*, i8*, i32, i32 }
+%12 = type { i32*, i32, i8*, i64 }
+%13 = type opaque
+%14 = type opaque
+%15 = type opaque
+%16 = type opaque
+%17 = type opaque
+%18 = type opaque
+%19 = type opaque
+%20 = type opaque
+%21 = type opaque
+%22 = type opaque
+%23 = type opaque
+%24 = type opaque
+%25 = type opaque
+
+@"\01l_objc_msgSend_fixup_alloc" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16
+@"\01L_OBJC_SELECTOR_REFERENCES_8" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_3725" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_40" = external hidden global %2*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_4227" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_4631" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_70" = external hidden global %2*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_148" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_159" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_188" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_328" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01l_objc_msgSend_fixup_objectAtIndex_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16
+ at _unnamed_cfstring_386 = external hidden constant %12, section "__DATA,__cfstring"
+@"\01l_objc_msgSend_fixup_count" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16
+@"\01L_OBJC_SELECTOR_REFERENCES_389" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_391" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_393" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+ at NSPrintHeaderAndFooter = external constant %13*
+@"\01L_OBJC_SELECTOR_REFERENCES_395" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_396" = external hidden global %2*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_398" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_400" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_402" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_404" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_406" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_408" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_CLASSLIST_REFERENCES_$_409" = external hidden global %2*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8
+@"\01L_OBJC_SELECTOR_REFERENCES_411" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_413" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_415" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+
+declare i8* @llvm.objc.retain(i8*)
+
+declare void @llvm.objc.release(i8*)
+
+declare i8* @llvm.objc.autorelease(i8*)
+
+declare i8* @llvm.objc.explicit_autorelease(i8*)
+
+define hidden %14* @foo(%15* %arg, %16* %arg2) {
+bb:
+  %tmp = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_3725", align 8
+  %tmp4 = bitcast %15* %arg to i8*
+  %tmp5 = tail call %18* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %18* (i8*, i8*)*)(i8* %tmp4, i8* %tmp)
+  %tmp6 = bitcast %18* %tmp5 to i8*
+  %tmp7 = tail call i8* @llvm.objc.retain(i8* %tmp6) nounwind
+  %tmp8 = load %2*, %2** @"\01L_OBJC_CLASSLIST_REFERENCES_$_40", align 8
+  %tmp9 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_4227", align 8
+  %tmp10 = bitcast %2* %tmp8 to i8*
+  %tmp11 = tail call %19* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %19* (i8*, i8*)*)(i8* %tmp10, i8* %tmp9)
+  %tmp12 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_4631", align 8
+  %tmp13 = bitcast %19* %tmp11 to i8*
+  %tmp14 = tail call signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, %13*)*)(i8* %tmp13, i8* %tmp12, %13* bitcast (%12* @_unnamed_cfstring_386 to %13*))
+  %tmp15 = bitcast %16* %arg2 to i8*
+  %tmp16 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_count" to i8**), align 16
+  %tmp17 = bitcast i8* %tmp16 to i64 (i8*, %1*)*
+  %tmp18 = tail call i64 %tmp17(i8* %tmp15, %1* bitcast (%0* @"\01l_objc_msgSend_fixup_count" to %1*))
+  %tmp19 = icmp eq i64 %tmp18, 0
+  br i1 %tmp19, label %bb22, label %bb20
+
+bb20:                                             ; preds = %bb
+  %tmp21 = icmp eq i8 %tmp14, 0
+  br label %bb25
+
+bb22:                                             ; preds = %bb
+  %tmp23 = bitcast i8* %tmp7 to %18*
+  %tmp24 = icmp eq i8 %tmp14, 0
+  br i1 %tmp24, label %bb46, label %bb25
+
+bb25:                                             ; preds = %bb22, %bb20
+  %tmp26 = phi i1 [ %tmp21, %bb20 ], [ false, %bb22 ]
+  %tmp27 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_188", align 8
+  %tmp28 = tail call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %tmp7, i8* %tmp27)
+  %tmp29 = tail call i8* @llvm.objc.explicit_autorelease(i8* %tmp28) nounwind
+  %tmp30 = bitcast i8* %tmp29 to %18*
+  tail call void @llvm.objc.release(i8* %tmp7) nounwind
+  %tmp31 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_389", align 8
+  %tmp32 = tail call %20* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %20* (i8*, i8*)*)(i8* %tmp29, i8* %tmp31)
+  %tmp33 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_391", align 8
+  %tmp34 = bitcast %20* %tmp32 to i8*
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, %16*)*)(i8* %tmp34, i8* %tmp33, %16* %arg2)
+  br i1 %tmp26, label %bb46, label %bb35
+
+bb35:                                             ; preds = %bb25
+  %tmp36 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_389", align 8
+  %tmp37 = tail call %20* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %20* (i8*, i8*)*)(i8* %tmp29, i8* %tmp36)
+  %tmp38 = load %2*, %2** @"\01L_OBJC_CLASSLIST_REFERENCES_$_70", align 8
+  %tmp39 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_393", align 8
+  %tmp40 = bitcast %2* %tmp38 to i8*
+  %tmp41 = tail call %21* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %21* (i8*, i8*, i8)*)(i8* %tmp40, i8* %tmp39, i8 signext 1)
+  %tmp42 = bitcast %21* %tmp41 to i8*
+  %tmp43 = load %13*, %13** @NSPrintHeaderAndFooter, align 8
+  %tmp44 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_159", align 8
+  %tmp45 = bitcast %20* %tmp37 to i8*
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, %13*)*)(i8* %tmp45, i8* %tmp44, i8* %tmp42, %13* %tmp43)
+  br label %bb46
+
+bb46:                                             ; preds = %bb35, %bb25, %bb22
+  %tmp47 = phi %18* [ %tmp30, %bb35 ], [ %tmp30, %bb25 ], [ %tmp23, %bb22 ]
+  %tmp48 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_328", align 8
+  %tmp49 = tail call %22* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %22* (i8*, i8*)*)(i8* %tmp4, i8* %tmp48)
+  %tmp50 = bitcast %22* %tmp49 to i8*
+  %tmp51 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_count" to i8**), align 16
+  %tmp52 = bitcast i8* %tmp51 to i64 (i8*, %1*)*
+  %tmp53 = tail call i64 %tmp52(i8* %tmp50, %1* bitcast (%0* @"\01l_objc_msgSend_fixup_count" to %1*))
+  %tmp54 = icmp eq i64 %tmp53, 0
+  br i1 %tmp54, label %bb55, label %bb57
+
+bb55:                                             ; preds = %bb46
+  %tmp56 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_395", align 8
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*)*)(i8* %tmp4, i8* %tmp56)
+  br label %bb57
+
+bb57:                                             ; preds = %bb55, %bb46
+  %tmp58 = load %2*, %2** @"\01L_OBJC_CLASSLIST_REFERENCES_$_396", align 8
+  %tmp59 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_328", align 8
+  %tmp60 = tail call %22* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %22* (i8*, i8*)*)(i8* %tmp4, i8* %tmp59)
+  %tmp61 = bitcast %22* %tmp60 to i8*
+  %tmp62 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_objectAtIndex_" to i8**), align 16
+  %tmp63 = bitcast i8* %tmp62 to i8* (i8*, %1*, i64)*
+  %tmp64 = tail call i8* %tmp63(i8* %tmp61, %1* bitcast (%0* @"\01l_objc_msgSend_fixup_objectAtIndex_" to %1*), i64 0)
+  %tmp65 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_398", align 8
+  %tmp66 = tail call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %tmp64, i8* %tmp65)
+  %tmp67 = bitcast i8* %tmp66 to %23*
+  %tmp68 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_400", align 8
+  %tmp69 = bitcast %2* %tmp58 to i8*
+  %tmp70 = tail call %14* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %14* (i8*, i8*, %23*, %18*)*)(i8* %tmp69, i8* %tmp68, %23* %tmp67, %18* %tmp47)
+  %tmp71 = bitcast %14* %tmp70 to i8*
+  ; hack to prevent the optimize from using objc_retainAutoreleasedReturnValue.
+  %tmp71x = getelementptr i8, i8* %tmp71, i64 1
+  %tmp72 = tail call i8* @llvm.objc.retain(i8* %tmp71x) nounwind
+  %tmp73 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_402", align 8
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8)*)(i8* %tmp72, i8* %tmp73, i8 signext 1)
+  %tmp74 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_404", align 8
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8)*)(i8* %tmp72, i8* %tmp74, i8 signext 1)
+  %tmp75 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_328", align 8
+  %tmp76 = tail call %22* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %22* (i8*, i8*)*)(i8* %tmp4, i8* %tmp75)
+  %tmp77 = bitcast %22* %tmp76 to i8*
+  %tmp78 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_objectAtIndex_" to i8**), align 16
+  %tmp79 = bitcast i8* %tmp78 to i8* (i8*, %1*, i64)*
+  %tmp80 = tail call i8* %tmp79(i8* %tmp77, %1* bitcast (%0* @"\01l_objc_msgSend_fixup_objectAtIndex_" to %1*), i64 0)
+  %tmp81 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_406", align 8
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i64)*)(i8* %tmp80, i8* %tmp81, i64 9223372036854775807)
+  %tmp82 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_408", align 8
+  %tmp83 = tail call %24* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %24* (i8*, i8*)*)(i8* %tmp72, i8* %tmp82)
+  %tmp84 = bitcast %24* %tmp83 to i8*
+  %tmp85 = tail call i8* @llvm.objc.retain(i8* %tmp84) nounwind
+  %tmp86 = load %2*, %2** @"\01L_OBJC_CLASSLIST_REFERENCES_$_409", align 8
+  %tmp87 = bitcast %2* %tmp86 to i8*
+  %tmp88 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_alloc" to i8**), align 16
+  %tmp89 = bitcast i8* %tmp88 to i8* (i8*, %1*)*
+  %tmp90 = tail call i8* %tmp89(i8* %tmp87, %1* bitcast (%0* @"\01l_objc_msgSend_fixup_alloc" to %1*))
+  %tmp91 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_8", align 8
+  %tmp92 = tail call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %tmp90, i8* %tmp91)
+  %tmp93 = tail call i8* @llvm.objc.explicit_autorelease(i8* %tmp92) nounwind
+  %tmp94 = bitcast i8* %tmp93 to %25*
+  %tmp95 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_411", align 8
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, %25*)*)(i8* %tmp85, i8* %tmp95, %25* %tmp94)
+  tail call void @llvm.objc.release(i8* %tmp93) nounwind
+  %tmp96 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_148", align 8
+  %tmp97 = tail call signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*)*)(i8* %tmp4, i8* %tmp96)
+  %tmp98 = icmp eq i8 %tmp97, 0
+  br i1 %tmp98, label %bb99, label %bb104
+
+bb99:                                             ; preds = %bb57
+  %tmp100 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_413", align 8
+  %tmp101 = tail call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*)*)(i8* %tmp85, i8* %tmp100)
+  %tmp102 = or i64 %tmp101, 12
+  %tmp103 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_415", align 8
+  tail call void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i64)*)(i8* %tmp85, i8* %tmp103, i64 %tmp102)
+  br label %bb104
+
+bb104:                                            ; preds = %bb99, %bb57
+  %tmp105 = call i8* @llvm.objc.autorelease(i8* %tmp72) nounwind
+  %tmp106 = bitcast i8* %tmp105 to %14*
+  tail call void @llvm.objc.release(i8* %tmp85) nounwind
+  %tmp107 = bitcast %18* %tmp47 to i8*
+  tail call void @llvm.objc.release(i8* %tmp107) nounwind
+  ret %14* %tmp106
+}
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/move-and-merge-autorelease.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/move-and-merge-autorelease.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/move-and-merge-autorelease.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/move-and-merge-autorelease.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,108 @@
+; RUN: opt -S -objc-arc -objc-arc-contract < %s | FileCheck %s
+
+; The optimizer should be able to move the autorelease past two phi nodes
+; and fold it with the release in bb65.
+
+; CHECK: bb65:
+; CHECK: call i8* @llvm.objc.retainAutorelease
+; CHECK: br label %bb76
+
+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.0"
+
+%0 = type opaque
+%1 = type opaque
+%2 = type opaque
+%3 = type opaque
+%4 = type opaque
+%5 = type opaque
+
+@"\01L_OBJC_SELECTOR_REFERENCES_11" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_421455" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_598" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_620" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_622" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_624" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+@"\01L_OBJC_SELECTOR_REFERENCES_626" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+
+declare i8* @llvm.objc.retain(i8*)
+
+declare void @llvm.objc.release(i8*)
+
+declare i8* @llvm.objc.autorelease(i8*)
+
+define hidden %0* @foo(%1* %arg, %3* %arg3) {
+bb:
+  %tmp16 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_620", align 8
+  %tmp17 = bitcast %3* %arg3 to i8*
+  %tmp18 = call %4* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %4* (i8*, i8*)*)(i8* %tmp17, i8* %tmp16)
+  %tmp19 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_622", align 8
+  %tmp20 = bitcast %4* %tmp18 to i8*
+  %tmp21 = call %5* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %5* (i8*, i8*)*)(i8* %tmp20, i8* %tmp19)
+  %tmp22 = bitcast %5* %tmp21 to i8*
+  %tmp23 = call i8* @llvm.objc.retain(i8* %tmp22) nounwind
+  %tmp24 = bitcast i8* %tmp23 to %5*
+  %tmp26 = icmp eq i8* %tmp23, null
+  br i1 %tmp26, label %bb81, label %bb27
+
+bb27:                                             ; preds = %bb
+  %tmp29 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_11", align 8
+  %tmp30 = bitcast %1* %arg to i8*
+  %tmp31 = call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* %tmp30, i8* %tmp29)
+  %tmp34 = call i8* @llvm.objc.retain(i8* %tmp31) nounwind
+  %tmp37 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_421455", align 8
+  %tmp39 = call %0* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %0* (i8*, i8*)*)(i8* %tmp34, i8* %tmp37)
+  %tmp40 = bitcast %0* %tmp39 to i8*
+  %tmp41 = call i8* @llvm.objc.retain(i8* %tmp40) nounwind
+  %tmp42 = bitcast i8* %tmp41 to %0*
+  %tmp44 = icmp eq i8* %tmp41, null
+  br i1 %tmp44, label %bb45, label %bb55
+
+bb45:                                             ; preds = %bb27
+  %tmp47 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_624", align 8
+  %tmp49 = call %0* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %0* (i8*, i8*)*)(i8* %tmp34, i8* %tmp47)
+  %tmp51 = bitcast %0* %tmp49 to i8*
+  %tmp52 = call i8* @llvm.objc.retain(i8* %tmp51) nounwind
+  call void @llvm.objc.release(i8* %tmp41) nounwind
+  br label %bb55
+
+bb55:                                             ; preds = %bb27, %bb45
+  %tmp13.0 = phi %0* [ %tmp42, %bb27 ], [ %tmp49, %bb45 ]
+  %tmp57 = icmp eq %0* %tmp13.0, null
+  br i1 %tmp57, label %bb76, label %bb58
+
+bb58:                                             ; preds = %bb55
+  %tmp60 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_598", align 8
+  %tmp61 = bitcast %0* %tmp13.0 to i8*
+  %tmp62 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*)*)(i8* %tmp61, i8* %tmp60)
+  %tmp64 = icmp eq i8 %tmp62, 0
+  br i1 %tmp64, label %bb76, label %bb65
+
+bb65:                                             ; preds = %bb58
+  %tmp68 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_626", align 8
+  %tmp69 = bitcast %0* %tmp13.0 to i8*
+  %tmp70 = call %0* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to %0* (i8*, i8*, %5*)*)(i8* %tmp69, i8* %tmp68, %5* %tmp24)
+  %tmp72 = bitcast %0* %tmp70 to i8*
+  %tmp73 = call i8* @llvm.objc.retain(i8* %tmp72) nounwind
+  br label %bb76
+
+bb76:                                             ; preds = %bb58, %bb55, %bb65
+  %tmp10.0 = phi %0* [ %tmp70, %bb65 ], [ null, %bb58 ], [ null, %bb55 ]
+  %tmp78 = bitcast %0* %tmp13.0 to i8*
+  call void @llvm.objc.release(i8* %tmp78) nounwind
+  call void @llvm.objc.release(i8* %tmp34) nounwind
+  br label %bb81
+
+bb81:                                             ; preds = %bb, %bb76
+  %tmp10.1 = phi %0* [ %tmp10.0, %bb76 ], [ null, %bb ]
+  %tmp83 = bitcast %0* %tmp10.1 to i8*
+  %tmp84 = call i8* @llvm.objc.retain(i8* %tmp83) nounwind
+  call void @llvm.objc.release(i8* %tmp23) nounwind
+  %tmp87 = call i8* @llvm.objc.autorelease(i8* %tmp84) nounwind
+  %tmp88 = bitcast i8* %tmp87 to %0*
+  %tmp92 = bitcast %0* %tmp10.1 to i8*
+  call void @llvm.objc.release(i8* %tmp92) nounwind
+  ret %0* %tmp88
+}

Added: llvm/trunk/test/Transforms/ObjCARC/nested.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/nested.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/nested.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/nested.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,825 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+%struct.__objcFastEnumerationState = type { i64, i8**, i64*, [5 x i64] }
+
+@"\01L_OBJC_METH_VAR_NAME_" = internal global [43 x i8] c"countByEnumeratingWithState:objects:count:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([43 x i8], [43 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"
+ at g = common global i8* null, align 8
+@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
+
+declare void @callee()
+declare i8* @returner()
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.enumerationMutation(i8*)
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...) nonlazybind
+declare void @use(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @def()
+declare void @__crasher_block_invoke(i8* nocapture)
+declare i8* @llvm.objc.retainBlock(i8*)
+declare void @__crasher_block_invoke1(i8* nocapture)
+
+!0 = !{}
+
+; Delete a nested retain+release pair.
+
+; CHECK-LABEL: define void @test0(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK-NOT: @llvm.objc.retain
+; CHECK: }
+define void @test0(i8* %a) nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %0 = call i8* @llvm.objc.retain(i8* %a) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call6, %forcoll.refetch ]
+  %tmp7 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp7, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+  %mutationsptr3 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr3, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  call void @use(i8* %3)
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call6 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp5, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call6, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK-LABEL: define void @test2(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK-NOT: @llvm.objc.retain
+; CHECK: }
+define void @test2() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call3, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+  %mutationsptr4 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr4, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  call void @use(i8* %3)
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call7, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK-LABEL: define void @test4(
+; CHECK: call i8* @llvm.objc.retain
+; CHECK-NOT: @llvm.objc.retain
+; CHECK: }
+define void @test4() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %tmp = load i8*, i8** @g, align 8
+  %0 = call i8* @llvm.objc.retain(i8* %tmp) nounwind
+  %tmp2 = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp2, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp4 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp4, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call, %forcoll.loopinit ], [ %call8, %forcoll.refetch ]
+  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+  %mutationsptr5 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr5, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  call void @use(i8* %3)
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp7 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call8 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp7, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call8, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK-LABEL: define void @test5(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK-NOT: @llvm.objc.retain
+; CHECK: }
+define void @test5() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call3, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+  %mutationsptr4 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr4, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  call void @use(i8* %3)
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call7, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; We handle this now due to the fact that a release just needs a post dominating
+; use.
+;
+; CHECK-LABEL: define void @test6(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK-NOT: @llvm.objc.retain
+; CHECK: }
+define void @test6() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call3, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+  %mutationsptr4 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr4, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  call void @use(i8* %3)
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call7, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @callee()
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; TODO: Delete a nested retain+release pair.
+; The optimizer currently can't do this, because isn't isn't sophisticated enough in
+; reasnoning about nesting.
+
+; CHECK-LABEL: define void @test7(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: @llvm.objc.retain
+; CHECK: }
+define void @test7() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  call void @callee()
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call3, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.notmutated ]
+  %mutationsptr4 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr4, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  call void @use(i8* %3)
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call7, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @callee()
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Delete a nested retain+release pair.
+
+; CHECK-LABEL: define void @test8(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK-NOT: @llvm.objc.retain
+; CHECK: }
+define void @test8() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp2 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call3 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp2, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call3, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  %stateitems.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 1
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call3, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp8 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp8, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ 0, %forcoll.loopbody.outer ], [ %4, %forcoll.next ]
+  %mutationsptr4 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr4, align 8
+  %2 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %2, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %1)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %stateitems = load i8**, i8*** %stateitems.ptr, align 8
+  %currentitem.ptr = getelementptr i8*, i8** %stateitems, i64 %forcoll.index
+  %3 = load i8*, i8** %currentitem.ptr, align 8
+  %tobool = icmp eq i8* %3, null
+  br i1 %tobool, label %forcoll.next, label %if.then
+
+if.then:
+  call void @callee()
+  br label %forcoll.next
+
+forcoll.next:
+  %4 = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %4, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %1, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %5 = icmp eq i64 %call7, 0
+  br i1 %5, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %1) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; TODO: Delete a nested retain+release pair.
+; The optimizer currently can't do this, because of a split loop backedge.
+; See test9b for the same testcase without a split backedge.
+
+; CHECK-LABEL: define void @test9(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: }
+define void @test9() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %call1 = call i8* @returner()
+  %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %2 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call4, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]
+  %mutationsptr5 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr5, align 8
+  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %2)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %exitcond = icmp eq i64 %forcoll.index, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge
+
+forcoll.notmutated.forcoll.loopbody_crit_edge:
+  %phitmp = add i64 %forcoll.index, 1
+  br label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %4 = icmp eq i64 %call7, 0
+  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %2) nounwind
+  call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Like test9, but without a split backedge. TODO: optimize this.
+
+; CHECK-LABEL: define void @test9b(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: @llvm.objc.retain
+; CHECK: }
+define void @test9b() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %call1 = call i8* @returner()
+  %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1) nounwind
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %2 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call4, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated ], [ 0, %forcoll.loopbody.outer ]
+  %mutationsptr5 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr5, align 8
+  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %2)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %phitmp = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %phitmp, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %4 = icmp eq i64 %call7, 0
+  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %2) nounwind
+  call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; TODO: Delete a nested retain+release pair.
+; The optimizer currently can't do this, because of a split loop backedge.
+; See test10b for the same testcase without a split backedge.
+
+; CHECK-LABEL: define void @test10(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: call i8* @llvm.objc.retain
+; CHECK: }
+define void @test10() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %call1 = call i8* @returner()
+  %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1) nounwind
+  call void @callee()
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %2 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call4, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated.forcoll.loopbody_crit_edge ], [ 1, %forcoll.loopbody.outer ]
+  %mutationsptr5 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr5, align 8
+  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %2)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %exitcond = icmp eq i64 %forcoll.index, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.notmutated.forcoll.loopbody_crit_edge
+
+forcoll.notmutated.forcoll.loopbody_crit_edge:
+  %phitmp = add i64 %forcoll.index, 1
+  br label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %4 = icmp eq i64 %call7, 0
+  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %2) nounwind
+  call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Like test10, but without a split backedge. TODO: optimize this.
+
+; CHECK-LABEL: define void @test10b(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue
+; CHECK: @llvm.objc.retain
+; CHECK: }
+define void @test10b() nounwind {
+entry:
+  %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
+  %items.ptr = alloca [16 x i8*], align 8
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %call1 = call i8* @returner()
+  %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call1) nounwind
+  call void @callee()
+  %tmp = bitcast %struct.__objcFastEnumerationState* %state.ptr to i8*
+  call void @llvm.memset.p0i8.i64(i8* align 8 %tmp, i8 0, i64 64, i1 false)
+  %2 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call4 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp3, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %iszero = icmp eq i64 %call4, 0
+  br i1 %iszero, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:
+  %mutationsptr.ptr = getelementptr inbounds %struct.__objcFastEnumerationState, %struct.__objcFastEnumerationState* %state.ptr, i64 0, i32 2
+  %mutationsptr = load i64*, i64** %mutationsptr.ptr, align 8
+  %forcoll.initial-mutations = load i64, i64* %mutationsptr, align 8
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:
+  %forcoll.count.ph = phi i64 [ %call4, %forcoll.loopinit ], [ %call7, %forcoll.refetch ]
+  %tmp9 = icmp ugt i64 %forcoll.count.ph, 1
+  %umax = select i1 %tmp9, i64 %forcoll.count.ph, i64 1
+  br label %forcoll.loopbody
+
+forcoll.loopbody:
+  %forcoll.index = phi i64 [ %phitmp, %forcoll.notmutated ], [ 0, %forcoll.loopbody.outer ]
+  %mutationsptr5 = load i64*, i64** %mutationsptr.ptr, align 8
+  %statemutations = load i64, i64* %mutationsptr5, align 8
+  %3 = icmp eq i64 %statemutations, %forcoll.initial-mutations
+  br i1 %3, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:
+  call void @llvm.objc.enumerationMutation(i8* %2)
+  br label %forcoll.notmutated
+
+forcoll.notmutated:
+  %phitmp = add i64 %forcoll.index, 1
+  %exitcond = icmp eq i64 %phitmp, %umax
+  br i1 %exitcond, label %forcoll.refetch, label %forcoll.loopbody
+
+forcoll.refetch:
+  %tmp6 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+  %call7 = call i64 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i64 (i8*, i8*, %struct.__objcFastEnumerationState*, [16 x i8*]*, i64)*)(i8* %2, i8* %tmp6, %struct.__objcFastEnumerationState* %state.ptr, [16 x i8*]* %items.ptr, i64 16)
+  %4 = icmp eq i64 %call7, 0
+  br i1 %4, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:
+  call void @llvm.objc.release(i8* %2) nounwind
+  call void @llvm.objc.release(i8* %1) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Pointers to strong pointers can obscure provenance relationships. Be conservative
+; in the face of escaping pointers. rdar://12150909.
+
+%struct.__block_d = type { i64, i64 }
+
+ at _NSConcreteStackBlock = external global i8*
+ at __block_d_tmp = external hidden constant { i64, i64, i8*, i8*, i8*, i8* }
+ at __block_d_tmp5 = external hidden constant { i64, i64, i8*, i8*, i8*, i8* }
+
+; CHECK-LABEL: define void @test11(
+; CHECK: tail call i8* @llvm.objc.retain(i8* %call) [[NUW:#[0-9]+]]
+; CHECK: tail call i8* @llvm.objc.retain(i8* %call) [[NUW]]
+; CHECK: call void @llvm.objc.release(i8* %call) [[NUW]], !clang.imprecise_release !0
+; CHECK: }
+define void @test11() {
+entry:
+  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, align 8
+  %block9 = alloca <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, align 8
+  %call = call i8* @def(), !clang.arc.no_objc_arc_exceptions !0
+  %foo = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block, i64 0, i32 5
+  %block.isa = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block, i64 0, i32 0
+  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
+  %block.flags = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block, i64 0, i32 1
+  store i32 1107296256, i32* %block.flags, align 8
+  %block.reserved = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block, i64 0, i32 2
+  store i32 0, i32* %block.reserved, align 4
+  %block.invoke = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block, i64 0, i32 3
+  store i8* bitcast (void (i8*)* @__crasher_block_invoke to i8*), i8** %block.invoke, align 8
+  %block.d = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block, i64 0, i32 4
+  store %struct.__block_d* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_d_tmp to %struct.__block_d*), %struct.__block_d** %block.d, align 8
+  %foo2 = tail call i8* @llvm.objc.retain(i8* %call) nounwind
+  store i8* %foo2, i8** %foo, align 8
+  %foo4 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block to i8*
+  %foo5 = call i8* @llvm.objc.retainBlock(i8* %foo4) nounwind
+  call void @use(i8* %foo5), !clang.arc.no_objc_arc_exceptions !0
+  call void @llvm.objc.release(i8* %foo5) nounwind
+  %strongdestroy = load i8*, i8** %foo, align 8
+  call void @llvm.objc.release(i8* %strongdestroy) nounwind, !clang.imprecise_release !0
+  %foo10 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9, i64 0, i32 5
+  %block.isa11 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9, i64 0, i32 0
+  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa11, align 8
+  %block.flags12 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9, i64 0, i32 1
+  store i32 1107296256, i32* %block.flags12, align 8
+  %block.reserved13 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9, i64 0, i32 2
+  store i32 0, i32* %block.reserved13, align 4
+  %block.invoke14 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9, i64 0, i32 3
+  store i8* bitcast (void (i8*)* @__crasher_block_invoke1 to i8*), i8** %block.invoke14, align 8
+  %block.d15 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9, i64 0, i32 4
+  store %struct.__block_d* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @__block_d_tmp5 to %struct.__block_d*), %struct.__block_d** %block.d15, align 8
+  %foo18 = call i8* @llvm.objc.retain(i8* %call) nounwind
+  store i8* %call, i8** %foo10, align 8
+  %foo20 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_d*, i8* }>* %block9 to i8*
+  %foo21 = call i8* @llvm.objc.retainBlock(i8* %foo20) nounwind
+  call void @use(i8* %foo21), !clang.arc.no_objc_arc_exceptions !0
+  call void @llvm.objc.release(i8* %foo21) nounwind
+  %strongdestroy25 = load i8*, i8** %foo10, align 8
+  call void @llvm.objc.release(i8* %strongdestroy25) nounwind, !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %call) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+
+; CHECK: attributes [[NUW]] = { nounwind }
+; CHECK: attributes #1 = { argmemonly nounwind }
+; CHECK: attributes #2 = { nonlazybind }

Added: llvm/trunk/test/Transforms/ObjCARC/opt-catchswitch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/opt-catchswitch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/opt-catchswitch.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/opt-catchswitch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt -S -objc-arc < %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--windows-msvc"
+
+declare i8* @f(i8*, i8*)
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare dllimport i8* @llvm.objc.autoreleaseReturnValue(i8* returned)
+declare dllimport i8* @llvm.objc.retain(i8* returned)
+declare dllimport i8* @llvm.objc.retainAutoreleasedReturnValue(i8* returned)
+declare dllimport void @llvm.objc.release(i8*)
+
+define i8* @g(i8* %p, i8* %q) local_unnamed_addr personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %p) #0
+  %1 = tail call i8* @llvm.objc.retain(i8* %q) #0
+  %call = invoke i8* @f(i8* %p, i8* %q)
+          to label %invoke.cont unwind label %catch.dispatch, !clang.arc.no_objc_arc_exceptions !0
+
+catch.dispatch:
+  %2 = catchswitch within none [label %catch] unwind to caller
+
+catch:
+  %3 = catchpad within %2 [i8* null, i32 64, i8* null]
+  catchret from %3 to label %cleanup
+
+invoke.cont:
+  %4 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) #0
+  br label %cleanup
+
+cleanup:
+  %retval.0 = phi i8* [ %call, %invoke.cont ], [ null, %catch ]
+  tail call void @llvm.objc.release(i8* %q) #0, !clang.imprecise_release !0
+  tail call void @llvm.objc.release(i8* %p) #0, !clang.imprecise_release !0
+  %5 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %retval.0) #0
+  ret i8* %retval.0
+}
+
+; CHECK-LABEL: entry:
+; CHECK-NEXT:    %0 = tail call i8* @llvm.objc.retain(i8* %p) #0
+; CHECK-NEXT:    %call = invoke i8* @f(i8* %p, i8* %q)
+; CHECK-NEXT:            to label %invoke.cont unwind label %catch.dispatch
+
+; CHECK-LABEL: catch.dispatch:
+; CHECK-NEXT:    %1 = catchswitch within none [label %catch] unwind to caller
+
+; CHECK-LABEL: cleanup:
+; CHECK:         tail call void @llvm.objc.release(i8* %p) #0
+
+attributes #0 = { nounwind }
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/path-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/path-overflow.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/path-overflow.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/path-overflow.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,2193 @@
+; RUN: opt -objc-arc -S < %s
+; rdar://12277446
+; rdar://12480535
+; rdar://14590914
+; rdar://15377890
+
+; The total number of paths grows exponentially with the number of branches, and a
+; computation of this number can overflow any reasonable fixed-sized
+; integer. This can occur in both the addition phase when we are adding up the
+; total bottomup/topdown paths and when we multiply them together at the end.
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32"
+target triple = "thumbv7-apple-ios5.0.0"
+
+%struct.NSConstantString = type { i32*, i32, i8*, i32 }
+%struct.CGPoint = type { float, float }
+
+ at _unnamed_cfstring = external constant %struct.NSConstantString, section "__DATA,__cfstring"
+ at _unnamed_cfstring_2 = external constant %struct.NSConstantString, section "__DATA,__cfstring"
+
+declare i8* @llvm.objc.retain(i8*) nonlazybind
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*) nonlazybind
+declare void @llvm.objc.release(i8*) nonlazybind
+declare i8* @returner()
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...) nonlazybind
+declare void @NSLog(i8*, ...)
+declare void @llvm.objc.msgSend_stret(i8*, i8*, ...)
+declare i32 @__gxx_personality_sj0(...)
+declare i32 @__objc_personality_v0(...)
+
+
+define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
+entry:
+  br i1 undef, label %msgSend.nullinit, label %msgSend.call
+
+msgSend.call:                                     ; preds = %entry
+  br label %msgSend.cont
+
+msgSend.nullinit:                                 ; preds = %entry
+  br label %msgSend.cont
+
+msgSend.cont:                                     ; preds = %msgSend.nullinit, %msgSend.call
+  %0 = bitcast %struct.NSConstantString* @_unnamed_cfstring to i8*
+  %1 = call i8* @llvm.objc.retain(i8* %0) nounwind
+  br i1 undef, label %msgSend.nullinit33, label %msgSend.call32
+
+msgSend.call32:                                   ; preds = %if.end10
+  br label %msgSend.cont34
+
+msgSend.nullinit33:                               ; preds = %if.end10
+  br label %msgSend.cont34
+
+msgSend.cont34:                                   ; preds = %msgSend.nullinit33, %msgSend.call32
+  br i1 undef, label %msgSend.nullinit38, label %msgSend.call37
+
+msgSend.call37:                                   ; preds = %msgSend.cont34
+  br label %msgSend.cont39
+
+msgSend.nullinit38:                               ; preds = %msgSend.cont34
+  br label %msgSend.cont39
+
+msgSend.cont39:                                   ; preds = %msgSend.nullinit38, %msgSend.call37
+  br i1 undef, label %msgSend.nullinit49, label %msgSend.call48
+
+msgSend.call48:                                   ; preds = %msgSend.cont39
+  br label %msgSend.cont50
+
+msgSend.nullinit49:                               ; preds = %msgSend.cont39
+  br label %msgSend.cont50
+
+msgSend.cont50:                                   ; preds = %msgSend.nullinit49, %msgSend.call48
+  br i1 undef, label %msgSend.nullinit61, label %msgSend.call60
+
+msgSend.call60:                                   ; preds = %msgSend.cont50
+  br label %msgSend.cont62
+
+msgSend.nullinit61:                               ; preds = %msgSend.cont50
+  br label %msgSend.cont62
+
+msgSend.cont62:                                   ; preds = %msgSend.nullinit61, %msgSend.call60
+  br i1 undef, label %msgSend.nullinit67, label %msgSend.call66
+
+msgSend.call66:                                   ; preds = %msgSend.cont62
+  br label %msgSend.cont68
+
+msgSend.nullinit67:                               ; preds = %msgSend.cont62
+  br label %msgSend.cont68
+
+msgSend.cont68:                                   ; preds = %msgSend.nullinit67, %msgSend.call66
+  br i1 undef, label %msgSend.nullinit84, label %msgSend.call83
+
+msgSend.call83:                                   ; preds = %msgSend.cont68
+  br label %msgSend.cont85
+
+msgSend.nullinit84:                               ; preds = %msgSend.cont68
+  br label %msgSend.cont85
+
+msgSend.cont85:                                   ; preds = %msgSend.nullinit84, %msgSend.call83
+  br i1 undef, label %msgSend.nullinit90, label %msgSend.call89
+
+msgSend.call89:                                   ; preds = %msgSend.cont85
+  br label %msgSend.cont91
+
+msgSend.nullinit90:                               ; preds = %msgSend.cont85
+  br label %msgSend.cont91
+
+msgSend.cont91:                                   ; preds = %msgSend.nullinit90, %msgSend.call89
+  br i1 undef, label %msgSend.nullinit104, label %msgSend.call103
+
+msgSend.call103:                                  ; preds = %msgSend.cont91
+  br label %msgSend.cont105
+
+msgSend.nullinit104:                              ; preds = %msgSend.cont91
+  br label %msgSend.cont105
+
+msgSend.cont105:                                  ; preds = %msgSend.nullinit104, %msgSend.call103
+  br i1 undef, label %land.lhs.true, label %if.end123
+
+land.lhs.true:                                    ; preds = %msgSend.cont105
+  br i1 undef, label %if.then117, label %if.end123
+
+if.then117:                                       ; preds = %land.lhs.true
+  br label %if.end123
+
+if.end123:                                        ; preds = %if.then117, %land.lhs.true, %msgSend.cont105
+  br i1 undef, label %msgSend.nullinit132, label %msgSend.call131
+
+msgSend.call131:                                  ; preds = %if.end123
+  br label %msgSend.cont133
+
+msgSend.nullinit132:                              ; preds = %if.end123
+  br label %msgSend.cont133
+
+msgSend.cont133:                                  ; preds = %msgSend.nullinit132, %msgSend.call131
+  br i1 undef, label %msgSend.nullinit139, label %msgSend.call138
+
+msgSend.call138:                                  ; preds = %msgSend.cont133
+  br label %msgSend.cont140
+
+msgSend.nullinit139:                              ; preds = %msgSend.cont133
+  br label %msgSend.cont140
+
+msgSend.cont140:                                  ; preds = %msgSend.nullinit139, %msgSend.call138
+  br i1 undef, label %if.then151, label %if.end157
+
+if.then151:                                       ; preds = %msgSend.cont140
+  br label %if.end157
+
+if.end157:                                        ; preds = %if.then151, %msgSend.cont140
+  br i1 undef, label %msgSend.nullinit164, label %msgSend.call163
+
+msgSend.call163:                                  ; preds = %if.end157
+  br label %msgSend.cont165
+
+msgSend.nullinit164:                              ; preds = %if.end157
+  br label %msgSend.cont165
+
+msgSend.cont165:                                  ; preds = %msgSend.nullinit164, %msgSend.call163
+  br i1 undef, label %msgSend.nullinit176, label %msgSend.call175
+
+msgSend.call175:                                  ; preds = %msgSend.cont165
+  br label %msgSend.cont177
+
+msgSend.nullinit176:                              ; preds = %msgSend.cont165
+  br label %msgSend.cont177
+
+msgSend.cont177:                                  ; preds = %msgSend.nullinit176, %msgSend.call175
+  br i1 undef, label %land.lhs.true181, label %if.end202
+
+land.lhs.true181:                                 ; preds = %msgSend.cont177
+  br i1 undef, label %if.then187, label %if.end202
+
+if.then187:                                       ; preds = %land.lhs.true181
+  br i1 undef, label %msgSend.nullinit199, label %msgSend.call198
+
+msgSend.call198:                                  ; preds = %if.then187
+  br label %msgSend.cont200
+
+msgSend.nullinit199:                              ; preds = %if.then187
+  br label %msgSend.cont200
+
+msgSend.cont200:                                  ; preds = %msgSend.nullinit199, %msgSend.call198
+  br label %if.end202
+
+if.end202:                                        ; preds = %msgSend.cont200, %land.lhs.true181, %msgSend.cont177
+  br i1 undef, label %msgSend.nullinit236, label %msgSend.call235
+
+msgSend.call235:                                  ; preds = %if.end202
+  br label %msgSend.cont237
+
+msgSend.nullinit236:                              ; preds = %if.end202
+  br label %msgSend.cont237
+
+msgSend.cont237:                                  ; preds = %msgSend.nullinit236, %msgSend.call235
+  br i1 undef, label %msgSend.nullinit254, label %msgSend.call253
+
+msgSend.call253:                                  ; preds = %msgSend.cont237
+  br label %msgSend.cont255
+
+msgSend.nullinit254:                              ; preds = %msgSend.cont237
+  br label %msgSend.cont255
+
+msgSend.cont255:                                  ; preds = %msgSend.nullinit254, %msgSend.call253
+  br i1 undef, label %msgSend.nullinit269, label %msgSend.call268
+
+msgSend.call268:                                  ; preds = %msgSend.cont255
+  br label %msgSend.cont270
+
+msgSend.nullinit269:                              ; preds = %msgSend.cont255
+  br label %msgSend.cont270
+
+msgSend.cont270:                                  ; preds = %msgSend.nullinit269, %msgSend.call268
+  br i1 undef, label %msgSend.nullinit281, label %msgSend.call280
+
+msgSend.call280:                                  ; preds = %msgSend.cont270
+  br label %msgSend.cont282
+
+msgSend.nullinit281:                              ; preds = %msgSend.cont270
+  br label %msgSend.cont282
+
+msgSend.cont282:                                  ; preds = %msgSend.nullinit281, %msgSend.call280
+  br i1 undef, label %msgSend.nullinit287, label %msgSend.call286
+
+msgSend.call286:                                  ; preds = %msgSend.cont282
+  br label %msgSend.cont288
+
+msgSend.nullinit287:                              ; preds = %msgSend.cont282
+  br label %msgSend.cont288
+
+msgSend.cont288:                                  ; preds = %msgSend.nullinit287, %msgSend.call286
+  br i1 undef, label %msgSend.nullinit303, label %msgSend.call302
+
+msgSend.call302:                                  ; preds = %msgSend.cont288
+  br label %msgSend.cont304
+
+msgSend.nullinit303:                              ; preds = %msgSend.cont288
+  br label %msgSend.cont304
+
+msgSend.cont304:                                  ; preds = %msgSend.nullinit303, %msgSend.call302
+  br i1 undef, label %msgSend.nullinit344, label %msgSend.call343
+
+msgSend.call343:                                  ; preds = %msgSend.cont304
+  br label %msgSend.cont345
+
+msgSend.nullinit344:                              ; preds = %msgSend.cont304
+  br label %msgSend.cont345
+
+msgSend.cont345:                                  ; preds = %msgSend.nullinit344, %msgSend.call343
+  br i1 undef, label %msgSend.nullinit350, label %msgSend.call349
+
+msgSend.call349:                                  ; preds = %msgSend.cont345
+  br label %msgSend.cont351
+
+msgSend.nullinit350:                              ; preds = %msgSend.cont345
+  br label %msgSend.cont351
+
+msgSend.cont351:                                  ; preds = %msgSend.nullinit350, %msgSend.call349
+  br i1 undef, label %msgSend.nullinit366, label %msgSend.call365
+
+msgSend.call365:                                  ; preds = %msgSend.cont351
+  br label %msgSend.cont367
+
+msgSend.nullinit366:                              ; preds = %msgSend.cont351
+  br label %msgSend.cont367
+
+msgSend.cont367:                                  ; preds = %msgSend.nullinit366, %msgSend.call365
+  br i1 undef, label %msgSend.nullinit376, label %msgSend.call375
+
+msgSend.call375:                                  ; preds = %msgSend.cont367
+  br label %msgSend.cont377
+
+msgSend.nullinit376:                              ; preds = %msgSend.cont367
+  br label %msgSend.cont377
+
+msgSend.cont377:                                  ; preds = %msgSend.nullinit376, %msgSend.call375
+  br i1 undef, label %if.then384, label %if.else401
+
+if.then384:                                       ; preds = %msgSend.cont377
+  br i1 undef, label %msgSend.nullinit392, label %msgSend.call391
+
+msgSend.call391:                                  ; preds = %if.then384
+  br label %msgSend.cont393
+
+msgSend.nullinit392:                              ; preds = %if.then384
+  br label %msgSend.cont393
+
+msgSend.cont393:                                  ; preds = %msgSend.nullinit392, %msgSend.call391
+  br label %if.end418
+
+if.else401:                                       ; preds = %msgSend.cont377
+  br i1 undef, label %msgSend.nullinit409, label %msgSend.call408
+
+msgSend.call408:                                  ; preds = %if.else401
+  br label %msgSend.cont410
+
+msgSend.nullinit409:                              ; preds = %if.else401
+  br label %msgSend.cont410
+
+msgSend.cont410:                                  ; preds = %msgSend.nullinit409, %msgSend.call408
+  br label %if.end418
+
+if.end418:                                        ; preds = %msgSend.cont410, %msgSend.cont393
+  br i1 undef, label %msgSend.nullinit470, label %msgSend.call469
+
+msgSend.call469:                                  ; preds = %if.end418
+  br label %msgSend.cont471
+
+msgSend.nullinit470:                              ; preds = %if.end418
+  br label %msgSend.cont471
+
+msgSend.cont471:                                  ; preds = %msgSend.nullinit470, %msgSend.call469
+  br i1 undef, label %msgSend.nullinit484, label %msgSend.call483
+
+msgSend.call483:                                  ; preds = %msgSend.cont471
+  br label %msgSend.cont485
+
+msgSend.nullinit484:                              ; preds = %msgSend.cont471
+  br label %msgSend.cont485
+
+msgSend.cont485:                                  ; preds = %msgSend.nullinit484, %msgSend.call483
+  br i1 undef, label %msgSend.nullinit500, label %msgSend.call499
+
+msgSend.call499:                                  ; preds = %msgSend.cont485
+  br label %msgSend.cont501
+
+msgSend.nullinit500:                              ; preds = %msgSend.cont485
+  br label %msgSend.cont501
+
+msgSend.cont501:                                  ; preds = %msgSend.nullinit500, %msgSend.call499
+  br i1 undef, label %msgSend.nullinit506, label %msgSend.call505
+
+msgSend.call505:                                  ; preds = %msgSend.cont501
+  br label %msgSend.cont507
+
+msgSend.nullinit506:                              ; preds = %msgSend.cont501
+  br label %msgSend.cont507
+
+msgSend.cont507:                                  ; preds = %msgSend.nullinit506, %msgSend.call505
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+; Function Attrs: optsize ssp uwtable
+define void @test2() unnamed_addr align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
+bb:
+  br i1 undef, label %bb3, label %bb2
+
+bb2:                                              ; preds = %bb
+  br label %bb3
+
+bb3:                                              ; preds = %bb2, %bb
+  br i1 undef, label %bb5, label %bb4
+
+bb4:                                              ; preds = %bb3
+  br label %bb5
+
+bb5:                                              ; preds = %bb4, %bb3
+  br i1 undef, label %bb7, label %bb6
+
+bb6:                                              ; preds = %bb5
+  br label %bb7
+
+bb7:                                              ; preds = %bb6, %bb5
+  br i1 undef, label %bb9, label %bb8
+
+bb8:                                              ; preds = %bb7
+  unreachable
+
+bb9:                                              ; preds = %bb7
+  br i1 undef, label %bb11, label %bb10
+
+bb10:                                             ; preds = %bb9
+  br label %bb11
+
+bb11:                                             ; preds = %bb10, %bb9
+  br i1 undef, label %bb13, label %bb12
+
+bb12:                                             ; preds = %bb11
+  br label %bb13
+
+bb13:                                             ; preds = %bb12, %bb11
+  br i1 undef, label %bb15, label %bb14
+
+bb14:                                             ; preds = %bb13
+  br label %bb15
+
+bb15:                                             ; preds = %bb14, %bb13
+  br i1 undef, label %bb17, label %bb16
+
+bb16:                                             ; preds = %bb15
+  br label %bb17
+
+bb17:                                             ; preds = %bb16, %bb15
+  br i1 undef, label %bb19, label %bb18
+
+bb18:                                             ; preds = %bb17
+  br label %bb19
+
+bb19:                                             ; preds = %bb18, %bb17
+  br i1 undef, label %bb222, label %bb20
+
+bb20:                                             ; preds = %bb19
+  br i1 undef, label %bb222, label %bb21
+
+bb21:                                             ; preds = %bb20
+  br i1 undef, label %bb22, label %bb30
+
+bb22:                                             ; preds = %bb21
+  br i1 undef, label %bb23, label %bb32
+
+bb23:                                             ; preds = %bb22
+  br i1 undef, label %bb24, label %bb34
+
+bb24:                                             ; preds = %bb23
+  br i1 undef, label %bb26, label %bb25
+
+bb25:                                             ; preds = %bb24
+  br label %bb27
+
+bb26:                                             ; preds = %bb24
+  br label %bb27
+
+bb27:                                             ; preds = %bb26, %bb25
+  br i1 undef, label %bb28, label %bb42
+
+bb28:                                             ; preds = %bb27
+  br i1 undef, label %bb36, label %bb29
+
+bb29:                                             ; preds = %bb28
+  br label %bb36
+
+bb30:                                             ; preds = %bb210, %bb207, %bb203, %bb199, %bb182, %bb176, %bb174, %bb171, %bb136, %bb132, %bb21
+  br label %bb213
+
+bb32:                                             ; preds = %bb22
+  unreachable
+
+bb34:                                             ; preds = %bb23
+  unreachable
+
+bb36:                                             ; preds = %bb29, %bb28
+  br i1 undef, label %bb38, label %bb37
+
+bb37:                                             ; preds = %bb36
+  br label %bb39
+
+bb38:                                             ; preds = %bb36
+  br label %bb39
+
+bb39:                                             ; preds = %bb38, %bb37
+  br i1 undef, label %bb41, label %bb40
+
+bb40:                                             ; preds = %bb39
+  unreachable
+
+bb41:                                             ; preds = %bb39
+  br label %bb42
+
+bb42:                                             ; preds = %bb41, %bb27
+  br i1 undef, label %bb43, label %bb214
+
+bb43:                                             ; preds = %bb42
+  br i1 undef, label %bb47, label %bb45
+
+bb45:                                             ; preds = %bb130, %bb128, %bb126, %bb124, %bb122, %bb120, %bb118, %bb116, %bb114, %bb112, %bb110, %bb108, %bb105, %bb102, %bb100, %bb96, %bb94, %bb90, %bb88, %bb84, %bb82, %bb78, %bb76, %bb72, %bb70, %bb66, %bb64, %bb60, %bb58, %bb54, %bb51, %bb43
+  unreachable
+
+bb47:                                             ; preds = %bb43
+  br i1 undef, label %bb48, label %bb106
+
+bb48:                                             ; preds = %bb47
+  br i1 undef, label %bb50, label %bb49
+
+bb49:                                             ; preds = %bb48
+  br label %bb51
+
+bb50:                                             ; preds = %bb48
+  br label %bb51
+
+bb51:                                             ; preds = %bb50, %bb49
+  br i1 undef, label %bb53, label %bb45
+
+bb53:                                             ; preds = %bb51
+  br i1 undef, label %bb54, label %bb134
+
+bb54:                                             ; preds = %bb53
+  br i1 undef, label %bb55, label %bb45
+
+bb55:                                             ; preds = %bb54
+  br i1 undef, label %bb57, label %bb56
+
+bb56:                                             ; preds = %bb55
+  br label %bb58
+
+bb57:                                             ; preds = %bb55
+  br label %bb58
+
+bb58:                                             ; preds = %bb57, %bb56
+  br i1 undef, label %bb60, label %bb45
+
+bb60:                                             ; preds = %bb58
+  br i1 undef, label %bb61, label %bb45
+
+bb61:                                             ; preds = %bb60
+  br i1 undef, label %bb63, label %bb62
+
+bb62:                                             ; preds = %bb61
+  br label %bb64
+
+bb63:                                             ; preds = %bb61
+  br label %bb64
+
+bb64:                                             ; preds = %bb63, %bb62
+  br i1 undef, label %bb66, label %bb45
+
+bb66:                                             ; preds = %bb64
+  br i1 undef, label %bb67, label %bb45
+
+bb67:                                             ; preds = %bb66
+  br i1 undef, label %bb69, label %bb68
+
+bb68:                                             ; preds = %bb67
+  br label %bb70
+
+bb69:                                             ; preds = %bb67
+  br label %bb70
+
+bb70:                                             ; preds = %bb69, %bb68
+  br i1 undef, label %bb72, label %bb45
+
+bb72:                                             ; preds = %bb70
+  br i1 undef, label %bb73, label %bb45
+
+bb73:                                             ; preds = %bb72
+  br i1 undef, label %bb75, label %bb74
+
+bb74:                                             ; preds = %bb73
+  br label %bb76
+
+bb75:                                             ; preds = %bb73
+  br label %bb76
+
+bb76:                                             ; preds = %bb75, %bb74
+  br i1 undef, label %bb78, label %bb45
+
+bb78:                                             ; preds = %bb76
+  br i1 undef, label %bb79, label %bb45
+
+bb79:                                             ; preds = %bb78
+  br i1 undef, label %bb81, label %bb80
+
+bb80:                                             ; preds = %bb79
+  br label %bb82
+
+bb81:                                             ; preds = %bb79
+  br label %bb82
+
+bb82:                                             ; preds = %bb81, %bb80
+  br i1 undef, label %bb84, label %bb45
+
+bb84:                                             ; preds = %bb82
+  br i1 undef, label %bb85, label %bb45
+
+bb85:                                             ; preds = %bb84
+  br i1 undef, label %bb87, label %bb86
+
+bb86:                                             ; preds = %bb85
+  br label %bb88
+
+bb87:                                             ; preds = %bb85
+  br label %bb88
+
+bb88:                                             ; preds = %bb87, %bb86
+  br i1 undef, label %bb90, label %bb45
+
+bb90:                                             ; preds = %bb88
+  br i1 undef, label %bb91, label %bb45
+
+bb91:                                             ; preds = %bb90
+  br i1 undef, label %bb93, label %bb92
+
+bb92:                                             ; preds = %bb91
+  br label %bb94
+
+bb93:                                             ; preds = %bb91
+  br label %bb94
+
+bb94:                                             ; preds = %bb93, %bb92
+  br i1 undef, label %bb96, label %bb45
+
+bb96:                                             ; preds = %bb94
+  br i1 undef, label %bb97, label %bb45
+
+bb97:                                             ; preds = %bb96
+  br i1 undef, label %bb99, label %bb98
+
+bb98:                                             ; preds = %bb97
+  br label %bb100
+
+bb99:                                             ; preds = %bb97
+  br label %bb100
+
+bb100:                                            ; preds = %bb99, %bb98
+  br i1 undef, label %bb102, label %bb45
+
+bb102:                                            ; preds = %bb100
+  br i1 undef, label %bb104, label %bb45
+
+bb104:                                            ; preds = %bb102
+  br i1 undef, label %bb108, label %bb105
+
+bb105:                                            ; preds = %bb104
+  br i1 undef, label %bb108, label %bb45
+
+bb106:                                            ; preds = %bb47
+  unreachable
+
+bb108:                                            ; preds = %bb105, %bb104
+  br i1 undef, label %bb110, label %bb45
+
+bb110:                                            ; preds = %bb108
+  br i1 undef, label %bb112, label %bb45
+
+bb112:                                            ; preds = %bb110
+  br i1 undef, label %bb114, label %bb45
+
+bb114:                                            ; preds = %bb112
+  br i1 undef, label %bb116, label %bb45
+
+bb116:                                            ; preds = %bb114
+  br i1 undef, label %bb118, label %bb45
+
+bb118:                                            ; preds = %bb116
+  br i1 undef, label %bb120, label %bb45
+
+bb120:                                            ; preds = %bb118
+  br i1 undef, label %bb122, label %bb45
+
+bb122:                                            ; preds = %bb120
+  br i1 undef, label %bb124, label %bb45
+
+bb124:                                            ; preds = %bb122
+  br i1 undef, label %bb126, label %bb45
+
+bb126:                                            ; preds = %bb124
+  br i1 undef, label %bb128, label %bb45
+
+bb128:                                            ; preds = %bb126
+  br i1 undef, label %bb130, label %bb45
+
+bb130:                                            ; preds = %bb128
+  br i1 undef, label %bb132, label %bb45
+
+bb132:                                            ; preds = %bb130
+  br i1 undef, label %bb135, label %bb30
+
+bb134:                                            ; preds = %bb53
+  unreachable
+
+bb135:                                            ; preds = %bb132
+  br i1 undef, label %bb139, label %bb136
+
+bb136:                                            ; preds = %bb135
+  br i1 undef, label %bb138, label %bb30
+
+bb138:                                            ; preds = %bb136
+  br label %bb139
+
+bb139:                                            ; preds = %bb138, %bb135
+  br i1 undef, label %bb140, label %bb141
+
+bb140:                                            ; preds = %bb139
+  unreachable
+
+bb141:                                            ; preds = %bb139
+  br i1 undef, label %bb142, label %bb215
+
+bb142:                                            ; preds = %bb141
+  br i1 undef, label %bb144, label %bb143
+
+bb143:                                            ; preds = %bb142
+  br label %bb145
+
+bb144:                                            ; preds = %bb142
+  br label %bb145
+
+bb145:                                            ; preds = %bb144, %bb143
+  br i1 undef, label %bb146, label %bb151
+
+bb146:                                            ; preds = %bb145
+  br i1 undef, label %bb148, label %bb153
+
+bb148:                                            ; preds = %bb146
+  br i1 undef, label %bb155, label %bb149
+
+bb149:                                            ; preds = %bb148
+  br i1 undef, label %bb150, label %bb153
+
+bb150:                                            ; preds = %bb149
+  br label %bb155
+
+bb151:                                            ; preds = %bb145
+  unreachable
+
+bb153:                                            ; preds = %bb158, %bb149, %bb146
+  unreachable
+
+bb155:                                            ; preds = %bb150, %bb148
+  br i1 undef, label %bb157, label %bb156
+
+bb156:                                            ; preds = %bb155
+  br label %bb158
+
+bb157:                                            ; preds = %bb155
+  br label %bb158
+
+bb158:                                            ; preds = %bb157, %bb156
+  br i1 undef, label %bb160, label %bb153
+
+bb160:                                            ; preds = %bb158
+  br i1 undef, label %bb162, label %bb161
+
+bb161:                                            ; preds = %bb160
+  br label %bb163
+
+bb162:                                            ; preds = %bb160
+  br label %bb163
+
+bb163:                                            ; preds = %bb162, %bb161
+  br i1 undef, label %bb165, label %bb164
+
+bb164:                                            ; preds = %bb163
+  br label %bb165
+
+bb165:                                            ; preds = %bb164, %bb163
+  br i1 undef, label %bb170, label %bb166
+
+bb166:                                            ; preds = %bb165
+  br i1 undef, label %bb167, label %bb168
+
+bb167:                                            ; preds = %bb166
+  unreachable
+
+bb168:                                            ; preds = %bb166
+  unreachable
+
+bb170:                                            ; preds = %bb165
+  br i1 undef, label %bb215, label %bb171
+
+bb171:                                            ; preds = %bb170
+  br i1 undef, label %bb173, label %bb30
+
+bb173:                                            ; preds = %bb171
+  br i1 undef, label %bb174, label %bb215
+
+bb174:                                            ; preds = %bb173
+  br i1 undef, label %bb176, label %bb30
+
+bb176:                                            ; preds = %bb174
+  br i1 undef, label %bb178, label %bb30
+
+bb178:                                            ; preds = %bb176
+  br i1 undef, label %bb179, label %bb193
+
+bb179:                                            ; preds = %bb178
+  br i1 undef, label %bb181, label %bb180
+
+bb180:                                            ; preds = %bb179
+  br label %bb182
+
+bb181:                                            ; preds = %bb179
+  br label %bb182
+
+bb182:                                            ; preds = %bb181, %bb180
+  br i1 undef, label %bb184, label %bb30
+
+bb184:                                            ; preds = %bb182
+  %tmp185 = call i8* @returner()
+  br i1 undef, label %bb186, label %bb195
+
+bb186:                                            ; preds = %bb184
+  %tmp188 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %tmp185)
+  %tmp189 = call i8* @llvm.objc.retain(i8* %tmp188)
+  call void @llvm.objc.release(i8* %tmp189), !clang.imprecise_release !0
+  br i1 undef, label %bb197, label %bb190
+
+bb190:                                            ; preds = %bb186
+  br i1 undef, label %bb192, label %bb195
+
+bb192:                                            ; preds = %bb190
+  br i1 undef, label %bb197, label %bb195
+
+bb193:                                            ; preds = %bb178
+  br label %bb213
+
+bb195:                                            ; preds = %bb192, %bb190, %bb184
+  unreachable
+
+bb197:                                            ; preds = %bb192, %bb186
+  br i1 undef, label %bb198, label %bb215
+
+bb198:                                            ; preds = %bb197
+  br i1 undef, label %bb202, label %bb199
+
+bb199:                                            ; preds = %bb198
+  br i1 undef, label %bb201, label %bb30
+
+bb201:                                            ; preds = %bb199
+  br label %bb202
+
+bb202:                                            ; preds = %bb201, %bb198
+  br i1 undef, label %bb206, label %bb203
+
+bb203:                                            ; preds = %bb202
+  br i1 undef, label %bb205, label %bb30
+
+bb205:                                            ; preds = %bb203
+  br label %bb206
+
+bb206:                                            ; preds = %bb205, %bb202
+  br i1 undef, label %bb210, label %bb207
+
+bb207:                                            ; preds = %bb206
+  br i1 undef, label %bb209, label %bb30
+
+bb209:                                            ; preds = %bb207
+  br label %bb210
+
+bb210:                                            ; preds = %bb209, %bb206
+  br i1 undef, label %bb212, label %bb30
+
+bb212:                                            ; preds = %bb210
+  unreachable
+
+bb213:                                            ; preds = %bb193, %bb30
+  resume { i8*, i32 } undef
+
+bb214:                                            ; preds = %bb42
+  br label %bb219
+
+bb215:                                            ; preds = %bb197, %bb173, %bb170, %bb141
+  br i1 undef, label %bb217, label %bb216
+
+bb216:                                            ; preds = %bb215
+  br label %bb217
+
+bb217:                                            ; preds = %bb216, %bb215
+  br i1 undef, label %bb219, label %bb218
+
+bb218:                                            ; preds = %bb217
+  br label %bb219
+
+bb219:                                            ; preds = %bb218, %bb217, %bb214
+  br i1 undef, label %bb221, label %bb220
+
+bb220:                                            ; preds = %bb219
+  unreachable
+
+bb221:                                            ; preds = %bb219
+  unreachable
+
+bb222:                                            ; preds = %bb20, %bb19
+  ret void
+}
+
+; Function Attrs: ssp
+define void @test3() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) {
+entry:
+  %call2 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %entry
+  %call5 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont4 unwind label %lpad3
+
+invoke.cont4:                                     ; preds = %invoke.cont
+  br i1 undef, label %land.end, label %land.rhs
+
+land.rhs:                                         ; preds = %invoke.cont4
+  %call7 = invoke i32 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %land.end unwind label %lpad3
+
+land.end:                                         ; preds = %land.rhs, %invoke.cont4
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i unwind label %lpad.i
+
+invoke.cont.i:                                    ; preds = %land.end
+  br i1 undef, label %invoke.cont8, label %if.then.i
+
+if.then.i:                                        ; preds = %invoke.cont.i
+  br label %invoke.cont8
+
+lpad.i:                                           ; preds = %land.end
+  %tmp13 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont8:                                     ; preds = %if.then.i, %invoke.cont.i
+  %call18 = invoke i8* (i8*, i8*, i8*, ...) bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*, ...)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef)
+          to label %invoke.cont17 unwind label %lpad16
+
+invoke.cont17:                                    ; preds = %invoke.cont8
+  %call22 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont21 unwind label %lpad20
+
+invoke.cont21:                                    ; preds = %invoke.cont17
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i1980 unwind label %lpad.i1982
+
+invoke.cont.i1980:                                ; preds = %invoke.cont21
+  br i1 undef, label %invoke.cont24, label %if.then.i1981
+
+if.then.i1981:                                    ; preds = %invoke.cont.i1980
+  br label %invoke.cont24
+
+lpad.i1982:                                       ; preds = %invoke.cont21
+  %tmp28 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont24:                                    ; preds = %if.then.i1981, %invoke.cont.i1980
+  %call37 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont36 unwind label %lpad35
+
+invoke.cont36:                                    ; preds = %invoke.cont24
+  br i1 undef, label %land.end43, label %land.rhs39
+
+land.rhs39:                                       ; preds = %invoke.cont36
+  %call41 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %land.end43 unwind label %lpad35
+
+land.end43:                                       ; preds = %land.rhs39, %invoke.cont36
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i1986 unwind label %lpad.i1988
+
+invoke.cont.i1986:                                ; preds = %land.end43
+  br i1 undef, label %invoke.cont44, label %if.then.i1987
+
+if.then.i1987:                                    ; preds = %invoke.cont.i1986
+  br label %invoke.cont44
+
+lpad.i1988:                                       ; preds = %land.end43
+  %tmp42 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont44:                                    ; preds = %if.then.i1987, %invoke.cont.i1986
+  %call53 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont52 unwind label %lpad51
+
+invoke.cont52:                                    ; preds = %invoke.cont44
+  br i1 undef, label %land.end70, label %land.rhs58
+
+land.rhs58:                                       ; preds = %invoke.cont52
+  %call63 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 42)
+          to label %invoke.cont62 unwind label %lpad61
+
+invoke.cont62:                                    ; preds = %land.rhs58
+  %call68 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef)
+          to label %land.end70 unwind label %lpad66.body.thread
+
+land.end70:                                       ; preds = %invoke.cont62, %invoke.cont52
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i1992 unwind label %lpad66.body
+
+invoke.cont.i1992:                                ; preds = %land.end70
+  br i1 undef, label %invoke.cont71, label %if.then.i1993
+
+if.then.i1993:                                    ; preds = %invoke.cont.i1992
+  br label %invoke.cont71
+
+invoke.cont71:                                    ; preds = %if.then.i1993, %invoke.cont.i1992
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i1998 unwind label %lpad.i2000
+
+invoke.cont.i1998:                                ; preds = %invoke.cont71
+  br i1 undef, label %invoke.cont91, label %if.then.i1999
+
+if.then.i1999:                                    ; preds = %invoke.cont.i1998
+  br label %invoke.cont91
+
+lpad.i2000:                                       ; preds = %invoke.cont71
+  %tmp74 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup102
+
+invoke.cont91:                                    ; preds = %if.then.i1999, %invoke.cont.i1998
+  %call96 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont95 unwind label %lpad94
+
+invoke.cont95:                                    ; preds = %invoke.cont91
+  %call98 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* %call96)
+          to label %invoke.cont97 unwind label %lpad94
+
+invoke.cont97:                                    ; preds = %invoke.cont95
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2004 unwind label %lpad.i2006
+
+invoke.cont.i2004:                                ; preds = %invoke.cont97
+  br i1 undef, label %invoke.cont100, label %if.then.i2005
+
+if.then.i2005:                                    ; preds = %invoke.cont.i2004
+  br label %invoke.cont100
+
+lpad.i2006:                                       ; preds = %invoke.cont97
+  %tmp82 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont100:                                   ; preds = %if.then.i2005, %invoke.cont.i2004
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont110 unwind label %lpad109
+
+invoke.cont110:                                   ; preds = %invoke.cont100
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2010 unwind label %lpad.i2012
+
+invoke.cont.i2010:                                ; preds = %invoke.cont110
+  br i1 undef, label %invoke.cont117, label %if.then.i2011
+
+if.then.i2011:                                    ; preds = %invoke.cont.i2010
+  br label %invoke.cont117
+
+lpad.i2012:                                       ; preds = %invoke.cont110
+  %tmp98 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont117:                                   ; preds = %if.then.i2011, %invoke.cont.i2010
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2022 unwind label %lpad156.body
+
+lpad:                                             ; preds = %entry
+  %tmp118 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup
+
+lpad3:                                            ; preds = %land.rhs, %invoke.cont
+  %tmp119 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup
+
+ehcleanup:                                        ; preds = %lpad3, %lpad
+  unreachable
+
+lpad16:                                           ; preds = %invoke.cont8
+  %tmp121 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup26
+
+lpad20:                                           ; preds = %invoke.cont17
+  %tmp122 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup26
+
+ehcleanup26:                                      ; preds = %lpad20, %lpad16
+  unreachable
+
+lpad35:                                           ; preds = %land.rhs39, %invoke.cont24
+  %tmp124 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad51:                                           ; preds = %invoke.cont44
+  %tmp125 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad61:                                           ; preds = %land.rhs58
+  %tmp127 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad66.body.thread:                               ; preds = %invoke.cont62
+  %tmp128 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad66.body:                                      ; preds = %land.end70
+  %tmp129 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad94:                                           ; preds = %invoke.cont95, %invoke.cont91
+  %tmp133 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup102
+
+ehcleanup102:                                     ; preds = %lpad94, %lpad.i2000
+  unreachable
+
+lpad109:                                          ; preds = %invoke.cont100
+  %tmp134 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont.i2022:                                ; preds = %invoke.cont117
+  br i1 undef, label %invoke.cont157, label %if.then.i2023
+
+if.then.i2023:                                    ; preds = %invoke.cont.i2022
+  br label %invoke.cont157
+
+invoke.cont157:                                   ; preds = %if.then.i2023, %invoke.cont.i2022
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2028 unwind label %lpad164.body
+
+invoke.cont.i2028:                                ; preds = %invoke.cont157
+  br i1 undef, label %invoke.cont165, label %if.then.i2029
+
+if.then.i2029:                                    ; preds = %invoke.cont.i2028
+  br label %invoke.cont165
+
+invoke.cont165:                                   ; preds = %if.then.i2029, %invoke.cont.i2028
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, void (i8*, i8*)*)*)(i8* undef, i8* undef, void (i8*, i8*)* undef)
+          to label %invoke.cont184 unwind label %lpad183
+
+invoke.cont184:                                   ; preds = %invoke.cont165
+  %call186 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont185 unwind label %lpad183
+
+invoke.cont185:                                   ; preds = %invoke.cont184
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2034 unwind label %lpad.i2036
+
+invoke.cont.i2034:                                ; preds = %invoke.cont185
+  br i1 undef, label %invoke.cont190, label %if.then.i2035
+
+if.then.i2035:                                    ; preds = %invoke.cont.i2034
+  br label %invoke.cont190
+
+lpad.i2036:                                       ; preds = %invoke.cont185
+  %tmp168 = landingpad { i8*, i32 }
+          cleanup
+  br label %lpad183.body
+
+invoke.cont190:                                   ; preds = %if.then.i2035, %invoke.cont.i2034
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont197 unwind label %lpad196
+
+invoke.cont197:                                   ; preds = %invoke.cont190
+  %call202 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont201 unwind label %lpad200
+
+invoke.cont201:                                   ; preds = %invoke.cont197
+  %call205 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont204 unwind label %lpad203
+
+invoke.cont204:                                   ; preds = %invoke.cont201
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2040 unwind label %lpad.i2042
+
+invoke.cont.i2040:                                ; preds = %invoke.cont204
+  br i1 undef, label %invoke.cont207, label %if.then.i2041
+
+if.then.i2041:                                    ; preds = %invoke.cont.i2040
+  br label %invoke.cont207
+
+lpad.i2042:                                       ; preds = %invoke.cont204
+  %tmp181 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont207:                                   ; preds = %if.then.i2041, %invoke.cont.i2040
+  %call209 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont208 unwind label %lpad203
+
+invoke.cont208:                                   ; preds = %invoke.cont207
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2046 unwind label %lpad212.body
+
+invoke.cont.i2046:                                ; preds = %invoke.cont208
+  br i1 undef, label %invoke.cont213, label %if.then.i2047
+
+if.then.i2047:                                    ; preds = %invoke.cont.i2046
+  br label %invoke.cont213
+
+invoke.cont213:                                   ; preds = %if.then.i2047, %invoke.cont.i2046
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont221 unwind label %lpad220
+
+invoke.cont221:                                   ; preds = %invoke.cont213
+  %call229 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont228 unwind label %lpad227
+
+invoke.cont228:                                   ; preds = %invoke.cont221
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2052 unwind label %lpad.i2054
+
+invoke.cont.i2052:                                ; preds = %invoke.cont228
+  br i1 undef, label %invoke.cont231, label %if.then.i2053
+
+if.then.i2053:                                    ; preds = %invoke.cont.i2052
+  br label %invoke.cont231
+
+lpad.i2054:                                       ; preds = %invoke.cont228
+  %tmp198 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont231:                                   ; preds = %if.then.i2053, %invoke.cont.i2052
+  %call233 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont232 unwind label %lpad227
+
+invoke.cont232:                                   ; preds = %invoke.cont231
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2058 unwind label %lpad236.body
+
+invoke.cont.i2058:                                ; preds = %invoke.cont232
+  br i1 undef, label %invoke.cont237, label %if.then.i2059
+
+if.then.i2059:                                    ; preds = %invoke.cont.i2058
+  br label %invoke.cont237
+
+invoke.cont237:                                   ; preds = %if.then.i2059, %invoke.cont.i2058
+  %call246 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont245 unwind label %lpad244
+
+invoke.cont245:                                   ; preds = %invoke.cont237
+  %call248 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 13)
+          to label %invoke.cont247 unwind label %lpad244
+
+invoke.cont247:                                   ; preds = %invoke.cont245
+  %call251 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 2)
+          to label %invoke.cont250 unwind label %lpad249
+
+invoke.cont250:                                   ; preds = %invoke.cont247
+  %call254 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 7)
+          to label %invoke.cont253 unwind label %lpad252
+
+invoke.cont253:                                   ; preds = %invoke.cont250
+  %call257 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8**, i32)*)(i8* undef, i8* undef, i8** undef, i32 3)
+          to label %invoke.cont256 unwind label %lpad255
+
+invoke.cont256:                                   ; preds = %invoke.cont253
+  %call260 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* undef)
+          to label %invoke.cont259 unwind label %lpad258
+
+invoke.cont259:                                   ; preds = %invoke.cont256
+  %call267 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont266 unwind label %lpad265
+
+invoke.cont266:                                   ; preds = %invoke.cont259
+  %call275 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef)
+          to label %invoke.cont274 unwind label %lpad273
+
+invoke.cont274:                                   ; preds = %invoke.cont266
+  %call279 = invoke i32 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont278 unwind label %lpad277
+
+invoke.cont278:                                   ; preds = %invoke.cont274
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2064 unwind label %lpad.i2066
+
+invoke.cont.i2064:                                ; preds = %invoke.cont278
+  br i1 undef, label %invoke.cont281, label %if.then.i2065
+
+if.then.i2065:                                    ; preds = %invoke.cont.i2064
+  br label %invoke.cont281
+
+lpad.i2066:                                       ; preds = %invoke.cont278
+  %tmp253 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont281:                                   ; preds = %if.then.i2065, %invoke.cont.i2064
+  %call291 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont290 unwind label %lpad289
+
+invoke.cont290:                                   ; preds = %invoke.cont281
+  %call303 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 8)
+          to label %invoke.cont302 unwind label %lpad301
+
+invoke.cont302:                                   ; preds = %invoke.cont290
+  %call310 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, double)*)(i8* undef, i8* undef, double 5.000000e-01)
+          to label %invoke.cont309 unwind label %lpad308
+
+invoke.cont309:                                   ; preds = %invoke.cont302
+  %call313 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 42)
+          to label %invoke.cont312 unwind label %lpad311
+
+invoke.cont312:                                   ; preds = %invoke.cont309
+  %call316 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8**, i8**, i32)*)(i8* undef, i8* undef, i8** undef, i8** undef, i32 2)
+          to label %invoke.cont315 unwind label %lpad314
+
+invoke.cont315:                                   ; preds = %invoke.cont312
+  %call322 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef)
+          to label %invoke.cont321 unwind label %lpad320
+
+invoke.cont321:                                   ; preds = %invoke.cont315
+  br i1 undef, label %land.end344, label %land.rhs335
+
+land.rhs335:                                      ; preds = %invoke.cont321
+  %call342 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %land.end344 unwind label %lpad340.body.thread
+
+land.end344:                                      ; preds = %land.rhs335, %invoke.cont321
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2070 unwind label %lpad340.body
+
+invoke.cont.i2070:                                ; preds = %land.end344
+  br i1 undef, label %invoke.cont345, label %if.then.i2071
+
+if.then.i2071:                                    ; preds = %invoke.cont.i2070
+  br label %invoke.cont345
+
+invoke.cont345:                                   ; preds = %if.then.i2071, %invoke.cont.i2070
+  %call362 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef)
+          to label %invoke.cont361 unwind label %lpad360
+
+invoke.cont361:                                   ; preds = %invoke.cont345
+  %call365 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont364 unwind label %lpad363
+
+invoke.cont364:                                   ; preds = %invoke.cont361
+  %call371 = invoke i32 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont370 unwind label %lpad369
+
+invoke.cont370:                                   ; preds = %invoke.cont364
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2076 unwind label %lpad.i2078
+
+invoke.cont.i2076:                                ; preds = %invoke.cont370
+  br i1 undef, label %invoke.cont373, label %if.then.i2077
+
+if.then.i2077:                                    ; preds = %invoke.cont.i2076
+  br label %invoke.cont373
+
+lpad.i2078:                                       ; preds = %invoke.cont370
+  %tmp340 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont373:                                   ; preds = %if.then.i2077, %invoke.cont.i2076
+  %call377 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32, i8*)*)(i8* undef, i8* undef, i32 42, i8* undef)
+          to label %invoke.cont376 unwind label %lpad363
+
+invoke.cont376:                                   ; preds = %invoke.cont373
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i32)*)(i8* undef, i8* undef, i8* undef, i32 5)
+          to label %invoke.cont382 unwind label %lpad381
+
+invoke.cont382:                                   ; preds = %invoke.cont376
+  %call384 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont383 unwind label %lpad381
+
+invoke.cont383:                                   ; preds = %invoke.cont382
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2082 unwind label %lpad.i2084
+
+invoke.cont.i2082:                                ; preds = %invoke.cont383
+  br i1 undef, label %invoke.cont392, label %if.then.i2083
+
+if.then.i2083:                                    ; preds = %invoke.cont.i2082
+  br label %invoke.cont392
+
+lpad.i2084:                                       ; preds = %invoke.cont383
+  %tmp360 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont392:                                   ; preds = %if.then.i2083, %invoke.cont.i2082
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i32)*)(i8* undef, i8* undef, i8* undef, i32 -2)
+          to label %invoke.cont395 unwind label %lpad381
+
+invoke.cont395:                                   ; preds = %invoke.cont392
+  %call397 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont396 unwind label %lpad381
+
+invoke.cont396:                                   ; preds = %invoke.cont395
+  %call400 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont399 unwind label %lpad398
+
+invoke.cont399:                                   ; preds = %invoke.cont396
+  %call403 = invoke i32 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont402 unwind label %lpad401
+
+invoke.cont402:                                   ; preds = %invoke.cont399
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2088 unwind label %lpad.i2090
+
+invoke.cont.i2088:                                ; preds = %invoke.cont402
+  br i1 undef, label %invoke.cont405, label %if.then.i2089
+
+if.then.i2089:                                    ; preds = %invoke.cont.i2088
+  br label %invoke.cont405
+
+lpad.i2090:                                       ; preds = %invoke.cont402
+  %tmp370 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont405:                                   ; preds = %if.then.i2089, %invoke.cont.i2088
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i32)*)(i8* undef, i8* undef, i8* undef, i32 -1)
+          to label %invoke.cont408 unwind label %lpad381
+
+invoke.cont408:                                   ; preds = %invoke.cont405
+  %call410 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont409 unwind label %lpad381
+
+invoke.cont409:                                   ; preds = %invoke.cont408
+  %call413 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont412 unwind label %lpad411
+
+invoke.cont412:                                   ; preds = %invoke.cont409
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2094 unwind label %lpad.i2096
+
+invoke.cont.i2094:                                ; preds = %invoke.cont412
+  br i1 undef, label %invoke.cont418, label %if.then.i2095
+
+if.then.i2095:                                    ; preds = %invoke.cont.i2094
+  br label %invoke.cont418
+
+lpad.i2096:                                       ; preds = %invoke.cont412
+  %tmp380 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont418:                                   ; preds = %if.then.i2095, %invoke.cont.i2094
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i32)*)(i8* undef, i8* undef, i8* undef, i32 0)
+          to label %invoke.cont422 unwind label %lpad381
+
+invoke.cont422:                                   ; preds = %invoke.cont418
+  %call424 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont423 unwind label %lpad381
+
+invoke.cont423:                                   ; preds = %invoke.cont422
+  %call427 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont426 unwind label %lpad425
+
+invoke.cont426:                                   ; preds = %invoke.cont423
+  %call430 = invoke i32 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont429 unwind label %lpad428
+
+invoke.cont429:                                   ; preds = %invoke.cont426
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2100 unwind label %lpad.i2102
+
+invoke.cont.i2100:                                ; preds = %invoke.cont429
+  br i1 undef, label %invoke.cont432, label %if.then.i2101
+
+if.then.i2101:                                    ; preds = %invoke.cont.i2100
+  br label %invoke.cont432
+
+lpad.i2102:                                       ; preds = %invoke.cont429
+  %tmp390 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont432:                                   ; preds = %if.then.i2101, %invoke.cont.i2100
+  %call436 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 0)
+          to label %invoke.cont435 unwind label %lpad381
+
+invoke.cont435:                                   ; preds = %invoke.cont432
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2106 unwind label %lpad.i2108
+
+invoke.cont.i2106:                                ; preds = %invoke.cont435
+  %call444 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 5)
+          to label %invoke.cont443 unwind label %lpad381
+
+lpad.i2108:                                       ; preds = %invoke.cont435
+  %tmp396 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont443:                                   ; preds = %invoke.cont.i2106
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2112 unwind label %lpad.i2114
+
+invoke.cont.i2112:                                ; preds = %invoke.cont443
+  br i1 undef, label %invoke.cont449, label %if.then.i2113
+
+if.then.i2113:                                    ; preds = %invoke.cont.i2112
+  br label %invoke.cont449
+
+lpad.i2114:                                       ; preds = %invoke.cont443
+  %tmp402 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont449:                                   ; preds = %if.then.i2113, %invoke.cont.i2112
+  %call453 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 -2)
+          to label %invoke.cont452 unwind label %lpad381
+
+invoke.cont452:                                   ; preds = %invoke.cont449
+  %call456 = invoke i32 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i32 (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont455 unwind label %lpad454
+
+invoke.cont455:                                   ; preds = %invoke.cont452
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2118 unwind label %lpad.i2120
+
+invoke.cont.i2118:                                ; preds = %invoke.cont455
+  br i1 undef, label %invoke.cont458, label %if.then.i2119
+
+if.then.i2119:                                    ; preds = %invoke.cont.i2118
+  br label %invoke.cont458
+
+lpad.i2120:                                       ; preds = %invoke.cont455
+  %tmp408 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont458:                                   ; preds = %if.then.i2119, %invoke.cont.i2118
+  %call461 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 -1)
+          to label %invoke.cont460 unwind label %lpad381
+
+invoke.cont460:                                   ; preds = %invoke.cont458
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2124 unwind label %lpad.i2126
+
+invoke.cont.i2124:                                ; preds = %invoke.cont460
+  br i1 undef, label %invoke.cont466, label %if.then.i2125
+
+if.then.i2125:                                    ; preds = %invoke.cont.i2124
+  br label %invoke.cont466
+
+lpad.i2126:                                       ; preds = %invoke.cont460
+  %tmp414 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup477
+
+invoke.cont466:                                   ; preds = %if.then.i2125, %invoke.cont.i2124
+  %call470 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 0)
+          to label %invoke.cont469 unwind label %lpad381
+
+invoke.cont469:                                   ; preds = %invoke.cont466
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2130 unwind label %lpad.i2132
+
+invoke.cont.i2130:                                ; preds = %invoke.cont469
+  br i1 undef, label %invoke.cont475, label %if.then.i2131
+
+if.then.i2131:                                    ; preds = %invoke.cont.i2130
+  br label %invoke.cont475
+
+lpad.i2132:                                       ; preds = %invoke.cont469
+  %tmp420 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup477
+
+invoke.cont475:                                   ; preds = %if.then.i2131, %invoke.cont.i2130
+  %call491 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 1)
+          to label %invoke.cont490 unwind label %lpad489
+
+invoke.cont490:                                   ; preds = %invoke.cont475
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont499 unwind label %lpad498
+
+invoke.cont499:                                   ; preds = %invoke.cont490
+  %call504 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont503 unwind label %lpad489
+
+invoke.cont503:                                   ; preds = %invoke.cont499
+  %call507 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* undef, i8* undef, i32 3)
+          to label %invoke.cont506 unwind label %lpad505
+
+invoke.cont506:                                   ; preds = %invoke.cont503
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont509 unwind label %lpad508
+
+invoke.cont509:                                   ; preds = %invoke.cont506
+  %call513 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont512 unwind label %lpad489
+
+invoke.cont512:                                   ; preds = %invoke.cont509
+  br i1 undef, label %msgSend.null-receiver, label %msgSend.call
+
+msgSend.call:                                     ; preds = %invoke.cont512
+  invoke void bitcast (void (i8*, i8*, ...)* @llvm.objc.msgSend_stret to void (%struct.CGPoint*, i8*, i8*)*)(%struct.CGPoint* sret undef, i8* undef, i8* undef)
+          to label %msgSend.cont unwind label %lpad514
+
+msgSend.null-receiver:                            ; preds = %invoke.cont512
+  br label %msgSend.cont
+
+msgSend.cont:                                     ; preds = %msgSend.null-receiver, %msgSend.call
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2136 unwind label %lpad.i2138
+
+invoke.cont.i2136:                                ; preds = %msgSend.cont
+  br i1 undef, label %invoke.cont521, label %if.then.i2137
+
+if.then.i2137:                                    ; preds = %invoke.cont.i2136
+  br label %invoke.cont521
+
+lpad.i2138:                                       ; preds = %msgSend.cont
+  %tmp468 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont521:                                   ; preds = %if.then.i2137, %invoke.cont.i2136
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef)
+          to label %invoke.cont528 unwind label %lpad527
+
+invoke.cont528:                                   ; preds = %invoke.cont521
+  %call532 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont531 unwind label %lpad489
+
+invoke.cont531:                                   ; preds = %invoke.cont528
+  %call535 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont534 unwind label %lpad533
+
+invoke.cont534:                                   ; preds = %invoke.cont531
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2142 unwind label %lpad.i2144
+
+invoke.cont.i2142:                                ; preds = %invoke.cont534
+  br i1 undef, label %invoke.cont540, label %if.then.i2143
+
+if.then.i2143:                                    ; preds = %invoke.cont.i2142
+  br label %invoke.cont540
+
+lpad.i2144:                                       ; preds = %invoke.cont534
+  %tmp486 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+invoke.cont540:                                   ; preds = %if.then.i2143, %invoke.cont.i2142
+  %call544 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i32)*)(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef, i32 3)
+          to label %invoke.cont543 unwind label %lpad489
+
+invoke.cont543:                                   ; preds = %invoke.cont540
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* undef)
+          to label %invoke.cont546 unwind label %lpad545
+
+invoke.cont546:                                   ; preds = %invoke.cont543
+  %call549 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont548 unwind label %lpad489
+
+invoke.cont548:                                   ; preds = %invoke.cont546
+  %call555 = invoke signext i8 bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8 (i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont554 unwind label %lpad553
+
+invoke.cont554:                                   ; preds = %invoke.cont548
+  %tmp499 = call i8* @llvm.objc.retain(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*)) #3
+  invoke void (i8*, ...) @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i8* %tmp499, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont.i2148 unwind label %lpad.i2150
+
+invoke.cont.i2148:                                ; preds = %invoke.cont554
+  call void @llvm.objc.release(i8* %tmp499) #3, !clang.imprecise_release !0
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont566 unwind label %lpad565
+
+lpad.i2150:                                       ; preds = %invoke.cont554
+  %tmp500 = landingpad { i8*, i32 }
+          cleanup
+  call void @llvm.objc.release(i8* %tmp499) #3, !clang.imprecise_release !0
+  unreachable
+
+invoke.cont566:                                   ; preds = %invoke.cont.i2148
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*, i8*, i8*)*)(i8* undef, i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*))
+          to label %invoke.cont572 unwind label %lpad571
+
+invoke.cont572:                                   ; preds = %invoke.cont566
+  %call582 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %invoke.cont581 unwind label %lpad580
+
+invoke.cont581:                                   ; preds = %invoke.cont572
+  unreachable
+
+lpad156.body:                                     ; preds = %invoke.cont117
+  %tmp1157 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad164.body:                                     ; preds = %invoke.cont157
+  %tmp1158 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad183:                                          ; preds = %invoke.cont184, %invoke.cont165
+  %tmp1159 = landingpad { i8*, i32 }
+          cleanup
+  br label %lpad183.body
+
+lpad183.body:                                     ; preds = %lpad183, %lpad.i2036
+  unreachable
+
+lpad196:                                          ; preds = %invoke.cont190
+  %tmp1160 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad200:                                          ; preds = %invoke.cont197
+  %tmp1161 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad203:                                          ; preds = %invoke.cont207, %invoke.cont201
+  %tmp1162 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad212.body:                                     ; preds = %invoke.cont208
+  %tmp1163 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad220:                                          ; preds = %invoke.cont213
+  %tmp1164 = landingpad { i8*, i32 }
+          cleanup
+  br label %eh.resume
+
+lpad227:                                          ; preds = %invoke.cont231, %invoke.cont221
+  %tmp1166 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup239
+
+lpad236.body:                                     ; preds = %invoke.cont232
+  %tmp1167 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup239
+
+ehcleanup239:                                     ; preds = %lpad236.body, %lpad227
+  unreachable
+
+lpad244:                                          ; preds = %invoke.cont245, %invoke.cont237
+  %tmp1168 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad249:                                          ; preds = %invoke.cont247
+  %tmp1169 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad252:                                          ; preds = %invoke.cont250
+  %tmp1170 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup263
+
+lpad255:                                          ; preds = %invoke.cont253
+  %tmp1171 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup263
+
+lpad258:                                          ; preds = %invoke.cont256
+  %tmp1172 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+ehcleanup263:                                     ; preds = %lpad255, %lpad252
+  unreachable
+
+lpad265:                                          ; preds = %invoke.cont259
+  %tmp1173 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad273:                                          ; preds = %invoke.cont266
+  %tmp1175 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad277:                                          ; preds = %invoke.cont274
+  %tmp1176 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad289:                                          ; preds = %invoke.cont281
+  %tmp1177 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad301:                                          ; preds = %invoke.cont290
+  %tmp1180 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad308:                                          ; preds = %invoke.cont302
+  %tmp1182 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad311:                                          ; preds = %invoke.cont309
+  %tmp1183 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad314:                                          ; preds = %invoke.cont312
+  %tmp1184 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad320:                                          ; preds = %invoke.cont315
+  %tmp1186 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad340.body.thread:                              ; preds = %land.rhs335
+  %tmp1188 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad340.body:                                     ; preds = %land.end344
+  %tmp1189 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad360:                                          ; preds = %invoke.cont345
+  %tmp1191 = landingpad { i8*, i32 }
+          cleanup
+  br label %eh.resume
+
+lpad363:                                          ; preds = %invoke.cont373, %invoke.cont361
+  %tmp1192 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad369:                                          ; preds = %invoke.cont364
+  %tmp1194 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad381:                                          ; preds = %invoke.cont466, %invoke.cont458, %invoke.cont449, %invoke.cont.i2106, %invoke.cont432, %invoke.cont422, %invoke.cont418, %invoke.cont408, %invoke.cont405, %invoke.cont395, %invoke.cont392, %invoke.cont382, %invoke.cont376
+  %tmp1196 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup477
+
+lpad398:                                          ; preds = %invoke.cont396
+  %tmp1199 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad401:                                          ; preds = %invoke.cont399
+  %tmp1200 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad411:                                          ; preds = %invoke.cont409
+  %tmp1201 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad425:                                          ; preds = %invoke.cont423
+  %tmp1203 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup477
+
+lpad428:                                          ; preds = %invoke.cont426
+  %tmp1204 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad454:                                          ; preds = %invoke.cont452
+  %tmp1207 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+ehcleanup477:                                     ; preds = %lpad425, %lpad381, %lpad.i2132, %lpad.i2126
+  unreachable
+
+lpad489:                                          ; preds = %invoke.cont546, %invoke.cont540, %invoke.cont528, %invoke.cont509, %invoke.cont499, %invoke.cont475
+  %tmp1211 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup560
+
+lpad498:                                          ; preds = %invoke.cont490
+  %tmp1214 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad505:                                          ; preds = %invoke.cont503
+  %tmp1215 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad508:                                          ; preds = %invoke.cont506
+  %tmp1216 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad514:                                          ; preds = %msgSend.call
+  %tmp1217 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad527:                                          ; preds = %invoke.cont521
+  %tmp1219 = landingpad { i8*, i32 }
+          cleanup
+  br label %ehcleanup560
+
+lpad533:                                          ; preds = %invoke.cont531
+  %tmp1220 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad545:                                          ; preds = %invoke.cont543
+  %tmp1222 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad553:                                          ; preds = %invoke.cont548
+  %tmp1224 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+ehcleanup560:                                     ; preds = %lpad527, %lpad489
+  br label %eh.resume
+
+lpad565:                                          ; preds = %invoke.cont.i2148
+  %tmp1225 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad571:                                          ; preds = %invoke.cont566
+  %tmp1227 = landingpad { i8*, i32 }
+          cleanup
+  unreachable
+
+lpad580:                                          ; preds = %invoke.cont572
+  %tmp1228 = landingpad { i8*, i32 }
+          cleanup
+  br label %eh.resume
+
+eh.resume:                                        ; preds = %lpad580, %ehcleanup560, %lpad360, %lpad220
+  resume { i8*, i32 } undef
+}
+
+@"OBJC_EHTYPE_$_NSException" = external global i8
+
+define void @test4() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  br i1 undef, label %if.end13, label %if.then10
+
+if.then10:                                        ; preds = %entry
+  br label %if.end13
+
+if.end13:                                         ; preds = %if.then10, %entry
+  %0 = call i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*, i8*, i8*, i64, i8*, i8)*)(i8* undef, i8* undef, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring to i8*), i64 2, i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_2 to i8*), i8 signext 0), !clang.arc.no_objc_arc_exceptions !0
+  br i1 undef, label %if.then17, label %if.end18
+
+if.then17:                                        ; preds = %if.end13
+  br label %if.end18
+
+if.end18:                                         ; preds = %if.then17, %if.end13
+  br i1 undef, label %if.then64, label %if.end73
+
+if.then64:                                        ; preds = %if.end18
+  br i1 undef, label %cond.end71, label %cond.true68
+
+cond.true68:                                      ; preds = %if.then64
+  br label %cond.end71
+
+cond.end71:                                       ; preds = %cond.true68, %if.then64
+  br i1 undef, label %cleanup.action, label %cleanup.done
+
+cleanup.action:                                   ; preds = %cond.end71
+  br label %cleanup.done
+
+cleanup.done:                                     ; preds = %cleanup.action, %cond.end71
+  br label %if.end73
+
+if.end73:                                         ; preds = %cleanup.done, %if.end18
+  br i1 undef, label %forcoll.empty, label %forcoll.loopinit
+
+forcoll.loopinit:                                 ; preds = %if.end73
+  br label %forcoll.loopbody.outer
+
+forcoll.loopbody.outer:                           ; preds = %forcoll.refetch, %forcoll.loopinit
+  br label %forcoll.loopbody
+
+forcoll.loopbody:                                 ; preds = %forcoll.notmutated, %forcoll.loopbody.outer
+  br i1 undef, label %forcoll.notmutated, label %forcoll.mutated
+
+forcoll.mutated:                                  ; preds = %forcoll.loopbody
+  br label %forcoll.notmutated
+
+forcoll.notmutated:                               ; preds = %forcoll.mutated, %forcoll.loopbody
+  br i1 undef, label %forcoll.loopbody, label %forcoll.refetch
+
+forcoll.refetch:                                  ; preds = %forcoll.notmutated
+  br i1 undef, label %forcoll.empty, label %forcoll.loopbody.outer
+
+forcoll.empty:                                    ; preds = %forcoll.refetch, %if.end73
+  br i1 undef, label %if.end85, label %if.then82
+
+if.then82:                                        ; preds = %forcoll.empty
+  br label %if.end85
+
+if.end85:                                         ; preds = %if.then82, %forcoll.empty
+  br i1 undef, label %if.then87, label %if.end102
+
+if.then87:                                        ; preds = %if.end85
+  br i1 undef, label %if.end94, label %if.then91
+
+if.then91:                                        ; preds = %if.then87
+  br label %if.end94
+
+if.end94:                                         ; preds = %if.then91, %if.then87
+  br i1 undef, label %if.end101, label %if.then98
+
+if.then98:                                        ; preds = %if.end94
+  br label %if.end101
+
+if.end101:                                        ; preds = %if.then98, %if.end94
+  br label %if.end102
+
+if.end102:                                        ; preds = %if.end101, %if.end85
+  br i1 undef, label %do.body113, label %if.then107
+
+if.then107:                                       ; preds = %if.end102
+  br label %do.body113
+
+do.body113:                                       ; preds = %if.then107, %if.end102
+  br i1 undef, label %if.then116, label %if.end117
+
+if.then116:                                       ; preds = %do.body113
+  br label %if.end117
+
+if.end117:                                        ; preds = %if.then116, %do.body113
+  br i1 undef, label %if.then125, label %if.end126
+
+if.then125:                                       ; preds = %if.end117
+  br label %if.end126
+
+if.end126:                                        ; preds = %if.then125, %if.end117
+  br i1 undef, label %do.end166, label %cond.true132
+
+cond.true132:                                     ; preds = %if.end126
+  br i1 undef, label %do.body148, label %cond.true151
+
+do.body148:                                       ; preds = %cond.true132
+  br i1 undef, label %do.end166, label %cond.true151
+
+cond.true151:                                     ; preds = %do.body148, %cond.true132
+  br i1 undef, label %if.then162, label %do.end166
+
+if.then162:                                       ; preds = %cond.true151
+  br label %do.end166
+
+do.end166:                                        ; preds = %if.then162, %cond.true151, %do.body148, %if.end126
+  br i1 undef, label %if.then304, label %if.then170
+
+if.then170:                                       ; preds = %do.end166
+  br i1 undef, label %do.end193, label %cond.true179
+
+cond.true179:                                     ; preds = %if.then170
+  br i1 undef, label %if.then190, label %do.end193
+
+if.then190:                                       ; preds = %cond.true179
+  br label %do.end193
+
+do.end193:                                        ; preds = %if.then190, %cond.true179, %if.then170
+  br i1 undef, label %do.body200, label %do.body283
+
+do.body200:                                       ; preds = %do.end193
+  br i1 undef, label %do.end254, label %cond.true203
+
+cond.true203:                                     ; preds = %do.body200
+  br i1 undef, label %do.body218, label %cond.true221
+
+do.body218:                                       ; preds = %cond.true203
+  br i1 undef, label %do.end254, label %cond.true221
+
+cond.true221:                                     ; preds = %do.body218, %cond.true203
+  br i1 undef, label %if.then232, label %do.body236
+
+if.then232:                                       ; preds = %cond.true221
+  br label %do.body236
+
+do.body236:                                       ; preds = %if.then232, %cond.true221
+  br i1 undef, label %do.end254, label %cond.true239
+
+cond.true239:                                     ; preds = %do.body236
+  br i1 undef, label %if.then250, label %do.end254
+
+if.then250:                                       ; preds = %cond.true239
+  br label %do.end254
+
+do.end254:                                        ; preds = %if.then250, %cond.true239, %do.body236, %do.body218, %do.body200
+  br i1 undef, label %do.end277, label %cond.true263
+
+cond.true263:                                     ; preds = %do.end254
+  br i1 undef, label %if.then274, label %do.end277
+
+if.then274:                                       ; preds = %cond.true263
+  unreachable
+
+do.end277:                                        ; preds = %cond.true263, %do.end254
+  br i1 undef, label %if.then280, label %do.body283
+
+if.then280:                                       ; preds = %do.end277
+  br label %do.body283
+
+do.body283:                                       ; preds = %if.then280, %do.end277, %do.end193
+  br i1 undef, label %if.end301, label %cond.true286
+
+cond.true286:                                     ; preds = %do.body283
+  br i1 undef, label %if.then297, label %if.end301
+
+if.then297:                                       ; preds = %cond.true286
+  br label %if.end301
+
+if.end301:                                        ; preds = %if.then297, %cond.true286, %do.body283
+  br i1 undef, label %if.then304, label %do.body351
+
+if.then304:                                       ; preds = %if.end301, %do.end166
+  br i1 undef, label %do.body309.lr.ph, label %do.body351
+
+do.body309.lr.ph:                                 ; preds = %if.then304
+  br label %do.body309
+
+do.body309:                                       ; preds = %for.cond.backedge, %do.body309.lr.ph
+  br i1 undef, label %do.end328, label %cond.true312
+
+cond.true312:                                     ; preds = %do.body309
+  br i1 undef, label %if.then323, label %do.end328
+
+if.then323:                                       ; preds = %cond.true312
+  br label %do.end328
+
+do.end328:                                        ; preds = %if.then323, %cond.true312, %do.body309
+  br i1 undef, label %for.cond.backedge, label %cond.true335
+
+for.cond.backedge:                                ; preds = %if.then346, %cond.true335, %do.end328
+  br i1 undef, label %do.body309, label %do.body351
+
+cond.true335:                                     ; preds = %do.end328
+  br i1 undef, label %if.then346, label %for.cond.backedge
+
+if.then346:                                       ; preds = %cond.true335
+  br label %for.cond.backedge
+
+do.body351:                                       ; preds = %for.cond.backedge, %if.then304, %if.end301
+  br i1 undef, label %if.then354, label %if.end355
+
+if.then354:                                       ; preds = %do.body351
+  br label %if.end355
+
+if.end355:                                        ; preds = %if.then354, %do.body351
+  br i1 undef, label %if.else, label %if.then364
+
+if.then364:                                       ; preds = %if.end355
+  br label %do.body366
+
+if.else:                                          ; preds = %if.end355
+  br label %do.body366
+
+do.body366:                                       ; preds = %if.else, %if.then364
+  br i1 undef, label %if.then369, label %if.end377.critedge
+
+if.then369:                                       ; preds = %do.body366
+  br label %if.end377
+
+if.end377.critedge:                               ; preds = %do.body366
+  br label %if.end377
+
+if.end377:                                        ; preds = %if.end377.critedge, %if.then369
+  br i1 undef, label %if.then383, label %if.end392.critedge
+
+if.then383:                                       ; preds = %if.end377
+  br label %if.end392
+
+if.end392.critedge:                               ; preds = %if.end377
+  br label %if.end392
+
+if.end392:                                        ; preds = %if.end392.critedge, %if.then383
+  br i1 undef, label %if.then398, label %if.end399
+
+if.then398:                                       ; preds = %if.end392
+  br label %if.end399
+
+if.end399:                                        ; preds = %if.then398, %if.end392
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*, i8*)*)(i8* undef, i8* undef)
+          to label %eh.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+
+eh.cont:                                          ; preds = %if.end399
+  br i1 undef, label %if.then430, label %if.end439.critedge
+
+if.then430:                                       ; preds = %eh.cont
+  %1 = call i8* @llvm.objc.retain(i8* %0)
+  br label %if.end439
+
+lpad:                                             ; preds = %if.end399
+  %2 = landingpad { i8*, i32 }
+          catch i8* @"OBJC_EHTYPE_$_NSException"
+  unreachable
+
+if.end439.critedge:                               ; preds = %eh.cont
+  %3 = call i8* @llvm.objc.retain(i8* %0)
+  br label %if.end439
+
+if.end439:                                        ; preds = %if.end439.critedge, %if.then430
+  call void @llvm.objc.release(i8* %0), !clang.imprecise_release !0
+  unreachable
+
+return:                                           ; No predecessors!
+  ret void
+}
+
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/pointer-types.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/pointer-types.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/pointer-types.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/pointer-types.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+; Don't hoist @llvm.objc.release past a use of its pointer, even
+; if the use has function type, because clang uses function types
+; in dubious ways.
+; rdar://10551239
+
+; CHECK-LABEL: define void @test0(
+; CHECK: %otherBlock = phi void ()* [ %b1, %if.then ], [ null, %entry ]
+; CHECK-NEXT: call void @use_fptr(void ()* %otherBlock)
+; CHECK-NEXT: %tmp11 = bitcast void ()* %otherBlock to i8*
+; CHECK-NEXT: call void @llvm.objc.release(i8* %tmp11)
+
+define void @test0(i1 %tobool, void ()* %b1) {
+entry:
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %otherBlock = phi void ()* [ %b1, %if.then ], [ null, %entry ]
+  call void @use_fptr(void ()* %otherBlock)
+  %tmp11 = bitcast void ()* %otherBlock to i8*
+  call void @llvm.objc.release(i8* %tmp11) nounwind
+  ret void
+}
+
+declare void @use_fptr(void ()*)
+declare void @llvm.objc.release(i8*)
+

Added: llvm/trunk/test/Transforms/ObjCARC/post-inlining.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/post-inlining.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/post-inlining.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/post-inlining.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+
+declare void @use_pointer(i8*)
+declare i8* @returner()
+declare i8* @llvm.objc.retain(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+
+; Clean up residue left behind after inlining.
+
+; CHECK-LABEL: define void @test0(
+; CHECK: entry:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test0(i8* %call.i) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %call.i) nounwind
+  %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
+  ret void
+}
+
+; Same as test0, but with slightly different use arrangements.
+
+; CHECK-LABEL: define void @test1(
+; CHECK: entry:
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test1(i8* %call.i) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %call.i) nounwind
+  %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
+  ret void
+}
+
+; Delete a retainRV+autoreleaseRV even if the pointer is used.
+
+; CHECK-LABEL: define void @test24(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   call void @use_pointer(i8* %p)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test24(i8* %p) {
+entry:
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* %p) nounwind
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p) nounwind
+  call void @use_pointer(i8* %p)
+  ret void
+}

Added: llvm/trunk/test/Transforms/ObjCARC/pr12270.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/pr12270.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/pr12270.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/pr12270.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt -disable-output -objc-arc-contract < %s
+; test that we don't crash on unreachable code
+%2 = type opaque
+
+define void @_i_Test__foo(%2 *%x) {
+entry:
+  unreachable
+
+return:                                           ; No predecessors!
+  %bar = bitcast %2* %x to i8*
+  %foo = call i8* @llvm.objc.autoreleaseReturnValue(i8* %bar) nounwind
+  call void @callee()
+  call void @use_pointer(i8* %foo)
+  call void @llvm.objc.release(i8* %foo) nounwind
+  ret void
+}
+
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare void @llvm.objc.release(i8*)
+declare void @callee()
+declare void @use_pointer(i8*)

Added: llvm/trunk/test/Transforms/ObjCARC/provenance.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/provenance.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/provenance.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/provenance.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt -disable-output -disable-basicaa -pa-eval %s 2>&1 | FileCheck %s
+
+@"\01l_objc_msgSend_fixup_" = global i8 0
+ at g1 = global i8 0, section "__OBJC,__message_refs,literal_pointers,no_dead_strip"
+ at g2 = global i8 0, section "__DATA, __objc_classrefs, regular, no_dead_strip"
+ at g3 = global i8 0, section "__DATA, __objc_superrefs, regular, no_dead_strip"
+ at g4 = global i8 0, section "__TEXT,__objc_methname,cstring_literals"
+ at g5 = global i8 0, section "__TEXT,__cstring,cstring_literals"
+
+declare void @g(i8)
+
+define void @f(i8* %a, i8** %b, i8** %c) {
+  %y1 = load i8, i8* %a
+  call void @g(i8 %y1)
+
+  %y2 = load i8*, i8** %b
+  %y3 = load i8*, i8** %c
+
+  %x0 = load i8, i8* @"\01l_objc_msgSend_fixup_"
+  call void @g(i8 %x0)
+
+  %x1 = load i8, i8* @g1
+  call void @g(i8 %x1)
+
+  %x2 = load i8, i8* @g2
+  call void @g(i8 %x2)
+
+  %x3 = load i8, i8* @g3
+  call void @g(i8 %x3)
+
+  %x4 = load i8, i8* @g4
+  call void @g(i8 %x4)
+
+  %x5 = load i8, i8* @g5
+  call void @g(i8 %x5)
+  ret void
+}
+
+; CHECK: y1 and y2 are related.
+; CHECK: y1 and y3 are related.
+; CHECK: y2 and y3 are related.
+; CHECK: x0 and y1 are not related.
+; CHECK: x0 and y2 are not related.
+; CHECK: x0 and y3 are not related.
+; CHECK: l_objc_msgSend_fixup_ and y1 are not related.
+; CHECK: l_objc_msgSend_fixup_ and y2 are not related.
+; CHECK: l_objc_msgSend_fixup_ and y3 are not related.
+; CHECK: x1 and y1 are not related.
+; CHECK: x2 and y1 are not related.
+; CHECK: x3 and y1 are not related.
+; CHECK: x4 and y1 are not related.
+; CHECK: x5 and y1 are not related.

Added: llvm/trunk/test/Transforms/ObjCARC/retain-block-side-effects.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/retain-block-side-effects.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/retain-block-side-effects.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/retain-block-side-effects.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -S -objc-arc-aa -basicaa -gvn < %s | FileCheck %s
+; rdar://10050579
+
+; objc_retainBlock stores into %repeater so the load from after the
+; call isn't forwardable from the store before the call.
+
+; CHECK: %tmp16 = call i8* @llvm.objc.retainBlock(i8* %tmp15) [[NUW:#[0-9]+]]
+; CHECK: %tmp17 = bitcast i8* %tmp16 to void ()*
+; CHECK: %tmp18 = load %struct.__block_byref_repeater*, %struct.__block_byref_repeater** %byref.forwarding, align 8
+; CHECK: %repeater12 = getelementptr inbounds %struct.__block_byref_repeater, %struct.__block_byref_repeater* %tmp18, i64 0, i32 6
+; CHECK: store void ()* %tmp17, void ()** %repeater12, align 8
+
+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"
+
+%0 = type opaque
+%struct.__block_byref_repeater = type { i8*, %struct.__block_byref_repeater*, i32, i32, i8*, i8*, void ()* }
+%struct.__block_descriptor = type { i64, i64 }
+
+define void @foo() noreturn {
+entry:
+  %repeater = alloca %struct.__block_byref_repeater, align 8
+  %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>, align 8
+  %byref.forwarding = getelementptr inbounds %struct.__block_byref_repeater, %struct.__block_byref_repeater* %repeater, i64 0, i32 1
+  %tmp10 = getelementptr inbounds %struct.__block_byref_repeater, %struct.__block_byref_repeater* %repeater, i64 0, i32 6
+  store void ()* null, void ()** %tmp10, align 8
+  %block.captured11 = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>* %block, i64 0, i32 6
+  %tmp14 = bitcast %struct.__block_byref_repeater* %repeater to i8*
+  store i8* %tmp14, i8** %block.captured11, align 8
+  %tmp15 = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0*, i8* }>* %block to i8*
+  %tmp16 = call i8* @llvm.objc.retainBlock(i8* %tmp15) nounwind
+  %tmp17 = bitcast i8* %tmp16 to void ()*
+  %tmp18 = load %struct.__block_byref_repeater*, %struct.__block_byref_repeater** %byref.forwarding, align 8
+  %repeater12 = getelementptr inbounds %struct.__block_byref_repeater, %struct.__block_byref_repeater* %tmp18, i64 0, i32 6
+  %tmp13 = load void ()*, void ()** %repeater12, align 8
+  store void ()* %tmp17, void ()** %repeater12, align 8
+  ret void
+}
+
+declare i8* @llvm.objc.retainBlock(i8*)
+
+; CHECK: attributes #0 = { noreturn }
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/retain-not-declared.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/retain-not-declared.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/retain-not-declared.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/retain-not-declared.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -S -objc-arc -objc-arc-contract < %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"
+declare i8* @llvm.objc.unretainedObject(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.msgSend(i8*, i8*, ...)
+declare void @llvm.objc.release(i8*)
+
+; Test that the optimizer can create an objc_retainAutoreleaseReturnValue
+; declaration even if no objc_retain declaration exists.
+; rdar://9401303
+
+; CHECK:      define i8* @test0(i8* %p) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %p) [[NUW:#[0-9]+]]
+; CHECK-NEXT:   ret i8* %0
+; CHECK-NEXT: }
+
+define i8* @test0(i8* %p) {
+entry:
+  %call = tail call i8* @llvm.objc.unretainedObject(i8* %p)
+  %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call) nounwind
+  ret i8* %call
+}
+
+; Properly create the @llvm.objc.retain declaration when it doesn't already exist.
+; rdar://9825114
+
+; CHECK-LABEL: @test1(
+; CHECK: @llvm.objc.retain
+; CHECK: @llvm.objc.retainAutoreleasedReturnValue(
+; CHECK: @llvm.objc.release
+; CHECK: @llvm.objc.release
+; CHECK: }
+define void @test1(i8* %call88) nounwind personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  %tmp1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call88) nounwind
+  %call94 = invoke i8* bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to i8* (i8*)*)(i8* %tmp1)
+          to label %invoke.cont93 unwind label %lpad91
+
+invoke.cont93:                                    ; preds = %entry
+  %tmp2 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call94) nounwind
+  call void @llvm.objc.release(i8* %tmp1) nounwind
+  invoke void bitcast (i8* (i8*, i8*, ...)* @llvm.objc.msgSend to void (i8*)*)(i8* %tmp2)
+          to label %invoke.cont102 unwind label %lpad100
+
+invoke.cont102:                                   ; preds = %invoke.cont93
+  call void @llvm.objc.release(i8* %tmp2) nounwind, !clang.imprecise_release !0
+  unreachable
+
+lpad91:                                           ; preds = %entry
+  %exn91 = landingpad {i8*, i32}
+              cleanup
+  unreachable
+
+lpad100:                                          ; preds = %invoke.cont93
+  %exn100 = landingpad {i8*, i32}
+              cleanup
+  call void @llvm.objc.release(i8* %tmp2) nounwind, !clang.imprecise_release !0
+  unreachable
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+!0 = !{}
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/rle-s2l.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/rle-s2l.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/rle-s2l.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/rle-s2l.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,138 @@
+; RUN: opt -S -basicaa -objc-arc < %s | FileCheck %s
+
+declare i8* @llvm.objc.loadWeak(i8**)
+declare i8* @llvm.objc.loadWeakRetained(i8**)
+declare i8* @llvm.objc.storeWeak(i8**, i8*)
+declare i8* @llvm.objc.initWeak(i8**, i8*)
+declare void @use_pointer(i8*)
+declare void @callee()
+
+; Basic redundant @llvm.objc.loadWeak elimination.
+
+; CHECK:      define void @test0(i8** %p) {
+; CHECK-NEXT:   %y = call i8* @llvm.objc.loadWeak(i8** %p)
+; CHECK-NEXT:   call void @use_pointer(i8* %y)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test0(i8** %p) {
+  %x = call i8* @llvm.objc.loadWeak(i8** %p)
+  %y = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; DCE the @llvm.objc.loadWeak.
+
+; CHECK:      define void @test1(i8** %p) {
+; CHECK-NEXT:   %y = call i8* @llvm.objc.loadWeakRetained(i8** %p)
+; CHECK-NEXT:   call void @use_pointer(i8* %y)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test1(i8** %p) {
+  %x = call i8* @llvm.objc.loadWeak(i8** %p)
+  %y = call i8* @llvm.objc.loadWeakRetained(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; Basic redundant @llvm.objc.loadWeakRetained elimination.
+
+; CHECK:      define void @test2(i8** %p) {
+; CHECK-NEXT:   %x = call i8* @llvm.objc.loadWeak(i8** %p)
+; CHECK-NEXT:   store i8 3, i8* %x
+; CHECK-NEXT:   %1 = tail call i8* @llvm.objc.retain(i8* %x)
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test2(i8** %p) {
+  %x = call i8* @llvm.objc.loadWeak(i8** %p)
+  store i8 3, i8* %x
+  %y = call i8* @llvm.objc.loadWeakRetained(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; Basic redundant @llvm.objc.loadWeakRetained elimination, this time
+; with a readonly call instead of a store.
+
+; CHECK:      define void @test3(i8** %p) {
+; CHECK-NEXT:   %x = call i8* @llvm.objc.loadWeak(i8** %p)
+; CHECK-NEXT:   call void @use_pointer(i8* %x) [[RO:#[0-9]+]]
+; CHECK-NEXT:   %1 = tail call i8* @llvm.objc.retain(i8* %x)
+; CHECK-NEXT:   call void @use_pointer(i8* %x)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test3(i8** %p) {
+  %x = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %x) readonly
+  %y = call i8* @llvm.objc.loadWeakRetained(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; A regular call blocks redundant weak load elimination.
+
+; CHECK:      define void @test4(i8** %p) {
+; CHECK-NEXT:   %x = call i8* @llvm.objc.loadWeak(i8** %p)
+; CHECK-NEXT:   call void @use_pointer(i8* %x) [[RO]]
+; CHECK-NEXT:   call void @callee()
+; CHECK-NEXT:   %y = call i8* @llvm.objc.loadWeak(i8** %p)
+; CHECK-NEXT:   call void @use_pointer(i8* %y)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test4(i8** %p) {
+  %x = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %x) readonly
+  call void @callee()
+  %y = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; Store to load forwarding.
+
+; CHECK:      define void @test5(i8** %p, i8* %n) {
+; CHECK-NEXT:   %1 = call i8* @llvm.objc.storeWeak(i8** %p, i8* %n)
+; CHECK-NEXT:   call void @use_pointer(i8* %n)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test5(i8** %p, i8* %n) {
+  call i8* @llvm.objc.storeWeak(i8** %p, i8* %n)
+  %y = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; Store to load forwarding with objc_initWeak.
+
+; CHECK:      define void @test6(i8** %p, i8* %n) {
+; CHECK-NEXT:   %1 = call i8* @llvm.objc.initWeak(i8** %p, i8* %n)
+; CHECK-NEXT:   call void @use_pointer(i8* %n)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test6(i8** %p, i8* %n) {
+  call i8* @llvm.objc.initWeak(i8** %p, i8* %n)
+  %y = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; Don't forward if there's a may-alias store in the way.
+
+; CHECK:      define void @test7(i8** %p, i8* %n, i8** %q, i8* %m) {
+; CHECK-NEXT:   call i8* @llvm.objc.initWeak(i8** %p, i8* %n)
+; CHECK-NEXT:   call i8* @llvm.objc.storeWeak(i8** %q, i8* %m)
+; CHECK-NEXT:   %y = call i8* @llvm.objc.loadWeak(i8** %p)
+; CHECK-NEXT:   call void @use_pointer(i8* %y)
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @test7(i8** %p, i8* %n, i8** %q, i8* %m) {
+  call i8* @llvm.objc.initWeak(i8** %p, i8* %n)
+  call i8* @llvm.objc.storeWeak(i8** %q, i8* %m)
+  %y = call i8* @llvm.objc.loadWeak(i8** %p)
+  call void @use_pointer(i8* %y)
+  ret void
+}
+
+; CHECK: attributes #0 = { nounwind }
+; CHECK: attributes [[RO]] = { readonly }

Added: llvm/trunk/test/Transforms/ObjCARC/rv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/rv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/rv.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/rv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,392 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+declare i8* @llvm.objc.retain(i8*)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.autorelease(i8*)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*)
+declare void @llvm.objc.autoreleasePoolPop(i8*)
+declare void @llvm.objc.autoreleasePoolPush()
+declare i8* @llvm.objc.retainBlock(i8*)
+
+declare i8* @objc_retainedObject(i8*)
+declare i8* @objc_unretainedObject(i8*)
+declare i8* @objc_unretainedPointer(i8*)
+
+declare void @use_pointer(i8*)
+declare void @callee()
+declare void @callee_fnptr(void ()*)
+declare void @invokee()
+declare i8* @returner()
+
+; Test that retain+release elimination is suppressed when the
+; retain is an objc_retainAutoreleasedReturnValue, since it's
+; better to do the RV optimization.
+
+; CHECK-LABEL:      define void @test0(
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %x = call i8* @returner
+; CHECK-NEXT:   %0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x) [[NUW:#[0-9]+]]
+; CHECK: t:
+; CHECK-NOT: @llvm.objc.
+; CHECK: return:
+; CHECK-NEXT: call void @llvm.objc.release(i8* %x)
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+define void @test0(i1 %p) nounwind {
+entry:
+  %x = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x)
+  br i1 %p, label %t, label %return
+
+t:
+  call void @use_pointer(i8* %x)
+  store i8 0, i8* %x
+  br label %return
+
+return:
+  call void @llvm.objc.release(i8* %x) nounwind
+  ret void
+}
+
+; Delete no-ops.
+
+; CHECK-LABEL: define void @test2(
+; CHECK-NOT: @llvm.objc.
+; CHECK: }
+define void @test2() {
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* null)
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* null)
+  ; call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* null) ; TODO
+  %bitcast = bitcast i32* null to i8*
+  %rb = call i8* @llvm.objc.retainBlock(i8* %bitcast)
+  call void @use_pointer(i8* %rb)
+  %rb2 = call i8* @llvm.objc.retainBlock(i8* undef)
+  call void @use_pointer(i8* %rb2)
+  ret void
+}
+
+; Delete a redundant retainRV,autoreleaseRV when forwaring a call result
+; directly to a return value.
+
+; CHECK-LABEL: define i8* @test3(
+; CHECK: call i8* @returner()
+; CHECK-NEXT: ret i8* %call
+define i8* @test3() {
+entry:
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call) nounwind
+  %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
+  ret i8* %1
+}
+
+; Delete a redundant retain,autoreleaseRV when forwaring a call result
+; directly to a return value.
+
+; CHECK-LABEL: define i8* @test4(
+; CHECK: call i8* @returner()
+; CHECK-NEXT: ret i8* %call
+define i8* @test4() {
+entry:
+  %call = call i8* @returner()
+  %0 = call i8* @llvm.objc.retain(i8* %call) nounwind
+  %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
+  ret i8* %1
+}
+
+; Delete a redundant fused retain+autoreleaseRV when forwaring a call result
+; directly to a return value.
+
+; TODO
+; HECK: define i8* @test5
+; HECK: call i8* @returner()
+; HECK-NEXT: ret i8* %call
+;define i8* @test5() {
+;entry:
+;  %call = call i8* @returner()
+;  %0 = call i8* @llvm.objc.retainAutoreleaseReturnValue(i8* %call) nounwind
+;  ret i8* %0
+;}
+
+; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into
+; an objc_autorelease.
+; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into
+; objc_retainAutoreleasedReturnValueAutorelease and merge
+; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue
+; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?
+; Those entrypoints don't exist yet though.
+
+; CHECK-LABEL: define i8* @test7(
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+define i8* @test7() {
+  %p = call i8* @returner()
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+  %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  call void @use_pointer(i8* %p)
+  ret i8* %t
+}
+
+; CHECK-LABEL: define i8* @test7b(
+; CHECK: call i8* @llvm.objc.retain(i8* %p)
+; CHECK: %t = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+define i8* @test7b() {
+  %p = call i8* @returner()
+  call void @use_pointer(i8* %p)
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+  %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  ret i8* %p
+}
+
+; Don't apply the RV optimization to autorelease if there's no retain.
+
+; CHECK: define i8* @test9(i8* %p)
+; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
+define i8* @test9(i8* %p) {
+  call i8* @llvm.objc.autorelease(i8* %p)
+  ret i8* %p
+}
+
+; Do not apply the RV optimization.
+
+; CHECK: define i8* @test10(i8* %p)
+; CHECK: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
+; CHECK-NEXT: ret i8* %p
+define i8* @test10(i8* %p) {
+  %1 = call i8* @llvm.objc.retain(i8* %p)
+  %2 = call i8* @llvm.objc.autorelease(i8* %p)
+  ret i8* %p
+}
+
+; Don't do the autoreleaseRV optimization because @use_pointer
+; could undo the retain.
+
+; CHECK: define i8* @test11(i8* %p)
+; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: call void @use_pointer(i8* %p)
+; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK-NEXT: ret i8* %p
+define i8* @test11(i8* %p) {
+  %1 = call i8* @llvm.objc.retain(i8* %p)
+  call void @use_pointer(i8* %p)
+  %2 = call i8* @llvm.objc.autorelease(i8* %p)
+  ret i8* %p
+}
+
+; Don't spoil the RV optimization.
+
+; CHECK: define i8* @test12(i8* %p)
+; CHECK: tail call i8* @llvm.objc.retain(i8* %p)
+; CHECK: call void @use_pointer(i8* %p)
+; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+; CHECK: ret i8* %p
+define i8* @test12(i8* %p) {
+  %1 = call i8* @llvm.objc.retain(i8* %p)
+  call void @use_pointer(i8* %p)
+  %2 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  ret i8* %p
+}
+
+; Don't zap the objc_retainAutoreleasedReturnValue.
+
+; CHECK-LABEL: define i8* @test13(
+; CHECK: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+; CHECK: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK: ret i8* %p
+define i8* @test13() {
+  %p = call i8* @returner()
+  %1 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+  call void @callee()
+  %2 = call i8* @llvm.objc.autorelease(i8* %p)
+  ret i8* %p
+}
+
+; Convert objc_retainAutoreleasedReturnValue to objc_retain if its
+; argument is not a return value.
+
+; CHECK-LABEL: define void @test14(
+; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %p) [[NUW]]
+; CHECK-NEXT: ret void
+define void @test14(i8* %p) {
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+  ret void
+}
+
+; Don't convert objc_retainAutoreleasedReturnValue to objc_retain if its
+; argument is a return value.
+
+; CHECK-LABEL: define void @test15(
+; CHECK-NEXT: %y = call i8* @returner()
+; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y) [[NUW]]
+; CHECK-NEXT: ret void
+define void @test15() {
+  %y = call i8* @returner()
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y)
+  ret void
+}
+
+; Delete autoreleaseRV+retainRV pairs.
+
+; CHECK: define i8* @test19(i8* %p) {
+; CHECK-NEXT: ret i8* %p
+define i8* @test19(i8* %p) {
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+  ret i8* %p
+}
+
+; Delete autoreleaseRV+retainRV pairs when they have equivalent PHIs as inputs
+
+; CHECK: define i8* @test19phi(i8* %p) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label %test19bb
+; CHECK: test19bb:
+; CHECK-NEXT: ret i8* %p
+define i8* @test19phi(i8* %p) {
+entry:
+  br label %test19bb
+test19bb:
+  %phi1 = phi i8* [ %p, %entry ]
+  %phi2 = phi i8* [ %p, %entry ]
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* %phi1)
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %phi2)
+  ret i8* %p
+}
+
+; Like test19 but with plain autorelease.
+
+; CHECK: define i8* @test20(i8* %p) {
+; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: ret i8* %p
+define i8* @test20(i8* %p) {
+  call i8* @llvm.objc.autorelease(i8* %p)
+  call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p)
+  ret i8* %p
+}
+
+; Like test19 but with plain retain.
+
+; CHECK: define i8* @test21(i8* %p) {
+; CHECK-NEXT: call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: ret i8* %p
+define i8* @test21(i8* %p) {
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  call i8* @llvm.objc.retain(i8* %p)
+  ret i8* %p
+}
+
+; Like test19 but with plain retain and autorelease.
+
+; CHECK: define i8* @test22(i8* %p) {
+; CHECK-NEXT: call i8* @llvm.objc.autorelease(i8* %p)
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: ret i8* %p
+define i8* @test22(i8* %p) {
+  call i8* @llvm.objc.autorelease(i8* %p)
+  call i8* @llvm.objc.retain(i8* %p)
+  ret i8* %p
+}
+
+; Convert autoreleaseRV to autorelease.
+
+; CHECK-LABEL: define void @test23(
+; CHECK: call i8* @llvm.objc.autorelease(i8* %p) [[NUW]]
+define void @test23(i8* %p) {
+  store i8 0, i8* %p
+  call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  ret void
+}
+
+; Don't convert autoreleaseRV to autorelease if the result is returned,
+; even through a bitcast.
+
+; CHECK-LABEL: define {}* @test24(
+; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+define {}* @test24(i8* %p) {
+  %t = call i8* @llvm.objc.autoreleaseReturnValue(i8* %p)
+  %s = bitcast i8* %p to {}*
+  ret {}* %s
+}
+
+declare i8* @first_test25();
+declare i8* @second_test25(i8*);
+declare void @somecall_test25();
+
+; ARC optimizer used to move the last release between the call to second_test25
+; and the call to objc_retainAutoreleasedReturnValue, causing %second to be
+; released prematurely when %first and %second were pointing to the same object.
+
+; CHECK-LABEL: define void @test25(
+; CHECK: %[[CALL1:.*]] = call i8* @second_test25(
+; CHECK-NEXT: tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL1]])
+
+define void @test25() {
+  %first = call i8* @first_test25()
+  %v0 = call i8* @llvm.objc.retain(i8* %first)
+  call void @somecall_test25()
+  %second = call i8* @second_test25(i8* %first)
+  %call2 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %second)
+  call void @llvm.objc.release(i8* %second), !clang.imprecise_release !0
+  call void @llvm.objc.release(i8* %first), !clang.imprecise_release !0
+  ret void
+}
+
+; Check that ObjCARCOpt::OptimizeReturns removes the redundant calls even when
+; they are not in the same basic block. This code used to cause an assertion
+; failure.
+
+; CHECK-LABEL: define i8* @test26()
+; CHECK: call i8* @returner()
+; CHECK-NOT:  call
+define i8* @test26() {
+bb0:
+  %v0 = call i8* @returner()
+  %v1 = tail call i8* @llvm.objc.retain(i8* %v0)
+  br label %bb1
+bb1:
+  %v2 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %v1)
+  br label %bb2
+bb2:
+  ret i8* %v2
+}
+
+declare i32* @func27(i32);
+
+; Check that ObjCARCOpt::OptimizeAutoreleaseRVCall doesn't turn a call to
+; @llvm.objc.autoreleaseReturnValue into a call to @llvm.objc.autorelease when a return
+; instruction uses a value equivalent to @llvm.objc.autoreleaseReturnValue's operand.
+; In the code below, %phival and %retval are considered equivalent.
+
+; CHECK-LABEL: define i32* @test27(
+; CHECK: %[[PHIVAL:.*]] = phi i8* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
+; CHECK: %[[RETVAL:.*]] = phi i32* [ %{{.*}}, %bb1 ], [ %{{.*}}, %bb2 ]
+; CHECK: tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[PHIVAL]])
+; CHECK: ret i32* %[[RETVAL]]
+
+define i32* @test27(i1 %cond) {
+entry:
+  br i1 %cond, label %bb1, label %bb2
+bb1:
+  %v0 = call i32* @func27(i32 1)
+  %v1 = bitcast i32* %v0 to i8*
+  br label %bb3
+bb2:
+  %v2 = call i32* @func27(i32 2)
+  %v3 = bitcast i32* %v2 to i8*
+  br label %bb3
+bb3:
+  %phival = phi i8* [ %v1, %bb1 ], [ %v3, %bb2 ]
+  %retval = phi i32* [ %v0, %bb1 ], [ %v2, %bb2 ]
+  %v4 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %phival)
+  ret i32* %retval
+}
+
+!0 = !{}
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/split-backedge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/split-backedge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/split-backedge.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/split-backedge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -S -objc-arc < %s | FileCheck %s
+
+; Handle a retain+release pair entirely contained within a split loop backedge.
+; rdar://11256239
+
+; CHECK-LABEL: define void @test0(
+; CHECK: call i8* @llvm.objc.retain(i8* %call) [[NUW:#[0-9]+]]
+; CHECK: call i8* @llvm.objc.retain(i8* %call) [[NUW]]
+; CHECK: call i8* @llvm.objc.retain(i8* %cond) [[NUW]]
+; CHECK: call void @llvm.objc.release(i8* %call) [[NUW]]
+; CHECK: call void @llvm.objc.release(i8* %call) [[NUW]]
+; CHECK: call void @llvm.objc.release(i8* %cond) [[NUW]]
+define void @test0() personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) {
+entry:
+  br label %while.body
+
+while.body:                                       ; preds = %while.cond
+  %call = invoke i8* @returner()
+          to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+
+invoke.cont:                                      ; preds = %while.body
+  %t0 = call i8* @llvm.objc.retain(i8* %call) nounwind
+  %t1 = call i8* @llvm.objc.retain(i8* %call) nounwind
+  %call.i1 = invoke i8* @returner()
+          to label %invoke.cont1 unwind label %lpad
+
+invoke.cont1:                                     ; preds = %invoke.cont
+  %cond = select i1 undef, i8* null, i8* %call
+  %t2 = call i8* @llvm.objc.retain(i8* %cond) nounwind
+  call void @llvm.objc.release(i8* %call) nounwind
+  call void @llvm.objc.release(i8* %call) nounwind
+  call void @use_pointer(i8* %cond)
+  call void @llvm.objc.release(i8* %cond) nounwind
+  br label %while.body
+
+lpad:                                             ; preds = %invoke.cont, %while.body
+  %t4 = landingpad { i8*, i32 }
+          catch i8* null
+  ret void
+}
+
+declare i8* @returner()
+declare i32 @__objc_personality_v0(...)
+declare void @llvm.objc.release(i8*)
+declare i8* @llvm.objc.retain(i8*)
+declare void @use_pointer(i8*)
+
+!0 = !{}
+
+; CHECK: attributes [[NUW]] = { nounwind }

Added: llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/tail-call-invariant-enforcement.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,108 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+declare void @llvm.objc.release(i8* %x)
+declare i8* @llvm.objc.retain(i8* %x)
+declare i8* @llvm.objc.autorelease(i8* %x)
+declare i8* @llvm.objc.autoreleaseReturnValue(i8* %x)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %x)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %x)
+declare i8* @tmp(i8*)
+
+; Never tail call objc_autorelease.
+
+; CHECK: define i8* @test0(i8* %x) [[NUW:#[0-9]+]] {
+; CHECK: %tmp0 = call i8* @llvm.objc.autorelease(i8* %x) [[NUW]]
+; CHECK: %tmp1 = call i8* @llvm.objc.autorelease(i8* %x) [[NUW]]
+; CHECK: }
+define i8* @test0(i8* %x) nounwind {
+entry:
+  %tmp0 = call i8* @llvm.objc.autorelease(i8* %x)
+  %tmp1 = tail call i8* @llvm.objc.autorelease(i8* %x)
+
+  ret i8* %x
+}
+
+; Always tail call autoreleaseReturnValue.
+
+; CHECK: define i8* @test1(i8* %x) [[NUW]] {
+; CHECK: %tmp0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %x) [[NUW]]
+; CHECK: %tmp1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %x) [[NUW]]
+; CHECK: }
+define i8* @test1(i8* %x) nounwind {
+entry:
+  %tmp0 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %x)
+  %tmp1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %x)
+  ret i8* %x
+}
+
+; Always tail call objc_retain.
+
+; CHECK: define i8* @test2(i8* %x) [[NUW]] {
+; CHECK: %tmp0 = tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK: %tmp1 = tail call i8* @llvm.objc.retain(i8* %x) [[NUW]]
+; CHECK: }
+define i8* @test2(i8* %x) nounwind {
+entry:
+  %tmp0 = call i8* @llvm.objc.retain(i8* %x)
+  %tmp1 = tail call i8* @llvm.objc.retain(i8* %x)
+  ret i8* %x
+}
+
+; Always tail call objc_retainAutoreleasedReturnValue unless it's annotated with
+; notail.
+; CHECK: define i8* @test3(i8* %x) [[NUW]] {
+; CHECK: %tmp0 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y) [[NUW]]
+; CHECK: %tmp1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z) [[NUW]]
+; CHECK: %tmp2 = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z2) [[NUW]]
+; CHECK: }
+define i8* @test3(i8* %x) nounwind {
+entry:
+  %y = call i8* @tmp(i8* %x)
+  %tmp0 = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %y)
+  %z = call i8* @tmp(i8* %x)
+  %tmp1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z)
+  %z2 = call i8* @tmp(i8* %x)
+  %tmp2 = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %z2)
+  ret i8* %x
+}
+
+; By itself, we should never change whether or not objc_release is tail called.
+
+; CHECK: define void @test4(i8* %x) [[NUW]] {
+; CHECK: call void @llvm.objc.release(i8* %x) [[NUW]]
+; CHECK: tail call void @llvm.objc.release(i8* %x) [[NUW]]
+; CHECK: }
+define void @test4(i8* %x) nounwind {
+entry:
+  call void @llvm.objc.release(i8* %x)
+  tail call void @llvm.objc.release(i8* %x)
+  ret void
+}
+
+; If we convert a tail called @llvm.objc.autoreleaseReturnValue to an
+; @llvm.objc.autorelease, ensure that the tail call is removed.
+; CHECK: define i8* @test5(i8* %x) [[NUW]] {
+; CHECK: %tmp0 = call i8* @llvm.objc.autorelease(i8* %x) [[NUW]]
+; CHECK: }
+define i8* @test5(i8* %x) nounwind {
+entry:
+  %tmp0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %x)
+  ret i8* %tmp0
+}
+
+; Always tail call llvm.objc.unsafeClaimAutoreleasedReturnValue.
+; CHECK: define i8* @test6(i8* %x) [[NUW]] {
+; CHECK: %tmp0 = tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %y) [[NUW]]
+; CHECK: %tmp1 = tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %z) [[NUW]]
+; CHECK: }
+define i8* @test6(i8* %x) nounwind {
+entry:
+  %y = call i8* @tmp(i8* %x)
+  %tmp0 = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %y)
+  %z = call i8* @tmp(i8* %x)
+  %tmp1 = tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %z)
+  ret i8* %x
+}
+
+; CHECK: attributes [[NUW]] = { nounwind }
+

Added: llvm/trunk/test/Transforms/ObjCARC/unsafe-claim-rv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/unsafe-claim-rv.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/unsafe-claim-rv.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/unsafe-claim-rv.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+; Generated by compiling:
+;
+; id baz(void *X) { return (__bridge_transfer id)X; }
+; 
+; void foo(id X) {
+; void *Y = 0;
+; if (X)
+;   Y = (__bridge_retained void *)X;
+; baz(Y);
+; }
+;
+; clang -x objective-c -mllvm -enable-objc-arc-opts=0 -fobjc-arc -S -emit-llvm test.m
+;
+; And then hand-reduced further. 
+
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
+
+define void @foo(i8* %X) {
+entry:
+  %0 = tail call i8* @llvm.objc.retain(i8* %X) 
+  %tobool = icmp eq i8* %0, null
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %1 = tail call i8* @llvm.objc.retain(i8* nonnull %0)
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %Y.0 = phi i8* [ %1, %if.then ], [ null, %entry ]
+  %2 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %Y.0)
+  %3 = tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %2)
+  tail call void @llvm.objc.release(i8* %0) 
+  ret void
+}
+
+; CHECK: if.then
+; CHECK: tail call i8* @llvm.objc.retain
+; CHECK-NEXT: call i8* @llvm.objc.autorelease
+; CHECK: %Y.0 = phi
+; CHECK-NEXT: tail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %Y.0)
+; CHECK-NEXT: tail call void @llvm.objc.release
+

Added: llvm/trunk/test/Transforms/ObjCARC/weak-contract.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/weak-contract.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/weak-contract.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/weak-contract.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s
+
+declare i8* @llvm.objc.initWeak(i8**, i8*)
+
+; Convert objc_initWeak(p, null) to *p = null.
+
+; CHECK:      define i8* @test0(i8** %p) {
+; CHECK-NEXT:   store i8* null, i8** %p
+; CHECK-NEXT:   ret i8* null
+; CHECK-NEXT: }
+define i8* @test0(i8** %p) {
+  %t = call i8* @llvm.objc.initWeak(i8** %p, i8* null)
+  ret i8* %t
+}

Added: llvm/trunk/test/Transforms/ObjCARC/weak-copies.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/weak-copies.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/weak-copies.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/weak-copies.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,89 @@
+; RUN: opt -S -basicaa -objc-arc < %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-darwin11.0.0"
+
+%0 = type { i64, i64, i8*, i8*, i8*, i8* }
+%1 = type <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>
+%struct.__block_descriptor = type { i64, i64 }
+
+ at _NSConcreteStackBlock = external global i8*
+ at .str = private unnamed_addr constant [6 x i8] c"v8@?0\00"
+@"\01L_OBJC_CLASS_NAME_" = internal global [3 x i8] c"\01@\00", section "__TEXT,__objc_classname,cstring_literals", align 1
+ at __block_descriptor_tmp = internal constant %0 { i64 0, i64 40, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_ to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_ to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"\01L_OBJC_CLASS_NAME_", i32 0, i32 0) }
+@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
+ at llvm.used = appending global [2 x i8*] [i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"\01L_OBJC_CLASS_NAME_", i32 0, i32 0), i8* bitcast ([2 x i32]* @"\01L_OBJC_IMAGE_INFO" to i8*)], section "llvm.metadata"
+
+; Eliminate unnecessary weak pointer copies.
+
+; CHECK:      define void @foo() {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %call = call i8* @bar()
+; CHECK-NEXT:   call void @use(i8* %call) [[NUW:#[0-9]+]]
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: }
+define void @foo() {
+entry:
+  %w = alloca i8*, align 8
+  %x = alloca i8*, align 8
+  %call = call i8* @bar()
+  %0 = call i8* @llvm.objc.initWeak(i8** %w, i8* %call) nounwind
+  %1 = call i8* @llvm.objc.loadWeak(i8** %w) nounwind
+  %2 = call i8* @llvm.objc.initWeak(i8** %x, i8* %1) nounwind
+  %3 = call i8* @llvm.objc.loadWeak(i8** %x) nounwind
+  call void @use(i8* %3) nounwind
+  call void @llvm.objc.destroyWeak(i8** %x) nounwind
+  call void @llvm.objc.destroyWeak(i8** %w) nounwind
+  ret void
+}
+
+; Eliminate unnecessary weak pointer copies in a block initialization.
+
+; CHECK:      define void @qux(i8* %me) #0 {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %block = alloca %1, align 8
+; CHECK-NOT:    alloca
+; CHECK:      }
+define void @qux(i8* %me) nounwind {
+entry:
+  %w = alloca i8*, align 8
+  %block = alloca %1, align 8
+  %0 = call i8* @llvm.objc.retain(i8* %me) nounwind
+  %1 = call i8* @llvm.objc.initWeak(i8** %w, i8* %0) nounwind
+  %block.isa = getelementptr inbounds %1, %1* %block, i64 0, i32 0
+  store i8* bitcast (i8** @_NSConcreteStackBlock to i8*), i8** %block.isa, align 8
+  %block.flags = getelementptr inbounds %1, %1* %block, i64 0, i32 1
+  store i32 1107296256, i32* %block.flags, align 8
+  %block.reserved = getelementptr inbounds %1, %1* %block, i64 0, i32 2
+  store i32 0, i32* %block.reserved, align 4
+  %block.invoke = getelementptr inbounds %1, %1* %block, i64 0, i32 3
+  store i8* bitcast (void (i8*)* @__qux_block_invoke_0 to i8*), i8** %block.invoke, align 8
+  %block.descriptor = getelementptr inbounds %1, %1* %block, i64 0, i32 4
+  store %struct.__block_descriptor* bitcast (%0* @__block_descriptor_tmp to %struct.__block_descriptor*), %struct.__block_descriptor** %block.descriptor, align 8
+  %block.captured = getelementptr inbounds %1, %1* %block, i64 0, i32 5
+  %2 = call i8* @llvm.objc.loadWeak(i8** %w) nounwind
+  %3 = call i8* @llvm.objc.initWeak(i8** %block.captured, i8* %2) nounwind
+  %4 = bitcast %1* %block to void ()*
+  call void @use_block(void ()* %4) nounwind
+  call void @llvm.objc.destroyWeak(i8** %block.captured) nounwind
+  call void @llvm.objc.destroyWeak(i8** %w) nounwind
+  call void @llvm.objc.release(i8* %0) nounwind, !clang.imprecise_release !0
+  ret void
+}
+
+declare i8* @llvm.objc.retain(i8*)
+declare void @use_block(void ()*) nounwind
+declare void @__qux_block_invoke_0(i8* %.block_descriptor) nounwind
+declare void @__copy_helper_block_(i8*, i8*) nounwind
+declare void @llvm.objc.copyWeak(i8**, i8**)
+declare void @__destroy_helper_block_(i8*) nounwind
+declare void @llvm.objc.release(i8*)
+declare i8* @bar()
+declare i8* @llvm.objc.initWeak(i8**, i8*)
+declare i8* @llvm.objc.loadWeak(i8**)
+declare void @use(i8*) nounwind
+declare void @llvm.objc.destroyWeak(i8**)
+
+; CHECK: attributes [[NUW]] = { nounwind }
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/ObjCARC/weak-dce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/weak-dce.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/weak-dce.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/weak-dce.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt -S -basicaa -objc-arc < %s | FileCheck %s
+; rdar://11434915
+
+; Delete the weak calls and replace them with just the net retain.
+
+;      CHECK: define void @test0(i8* %p) {
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: ret void
+
+define void @test0(i8* %p) {
+  %weakBlock = alloca i8*, align 8
+  %tmp7 = call i8* @llvm.objc.initWeak(i8** %weakBlock, i8* %p) nounwind
+  %tmp26 = call i8* @llvm.objc.loadWeakRetained(i8** %weakBlock) nounwind
+  call void @llvm.objc.destroyWeak(i8** %weakBlock) nounwind
+  ret void
+}
+
+;      CHECK: define i8* @test1(i8* %p) {
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %p)
+; CHECK-NEXT: ret i8* %p
+
+define i8* @test1(i8* %p) {
+  %weakBlock = alloca i8*, align 8
+  %tmp7 = call i8* @llvm.objc.initWeak(i8** %weakBlock, i8* %p) nounwind
+  %tmp26 = call i8* @llvm.objc.loadWeakRetained(i8** %weakBlock) nounwind
+  call void @llvm.objc.destroyWeak(i8** %weakBlock) nounwind
+  ret i8* %tmp26
+}
+
+;      CHECK: define i8* @test2(i8* %p, i8* %q) {
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %q)
+; CHECK-NEXT: ret i8* %q
+
+define i8* @test2(i8* %p, i8* %q) {
+  %weakBlock = alloca i8*, align 8
+  %tmp7 = call i8* @llvm.objc.initWeak(i8** %weakBlock, i8* %p) nounwind
+  %tmp19 = call i8* @llvm.objc.storeWeak(i8** %weakBlock, i8* %q) nounwind
+  %tmp26 = call i8* @llvm.objc.loadWeakRetained(i8** %weakBlock) nounwind
+  call void @llvm.objc.destroyWeak(i8** %weakBlock) nounwind
+  ret i8* %tmp26
+}
+
+declare i8* @llvm.objc.initWeak(i8**, i8*)
+declare void @llvm.objc.destroyWeak(i8**)
+declare i8* @llvm.objc.loadWeakRetained(i8**)
+declare i8* @llvm.objc.storeWeak(i8** %weakBlock, i8* %q)

Added: llvm/trunk/test/Transforms/ObjCARC/weak.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/weak.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/weak.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/weak.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt -objc-arc -S < %s | FileCheck %s
+
+declare i8* @llvm.objc.initWeak(i8**, i8*)
+declare i8* @llvm.objc.storeWeak(i8**, i8*)
+declare i8* @llvm.objc.loadWeak(i8**)
+declare void @llvm.objc.destroyWeak(i8**)
+declare i8* @llvm.objc.loadWeakRetained(i8**)
+declare void @llvm.objc.moveWeak(i8**, i8**)
+declare void @llvm.objc.copyWeak(i8**, i8**)
+
+; If the pointer-to-weak-pointer is null, it's undefined behavior.
+
+; CHECK-LABEL: define void @test0(
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: store i8* undef, i8** null
+; CHECK: ret void
+define void @test0(i8* %p, i8** %q) {
+entry:
+  call i8* @llvm.objc.storeWeak(i8** null, i8* %p)
+  call i8* @llvm.objc.storeWeak(i8** undef, i8* %p)
+  call i8* @llvm.objc.loadWeakRetained(i8** null)
+  call i8* @llvm.objc.loadWeakRetained(i8** undef)
+  call i8* @llvm.objc.loadWeak(i8** null)
+  call i8* @llvm.objc.loadWeak(i8** undef)
+  call i8* @llvm.objc.initWeak(i8** null, i8* %p)
+  call i8* @llvm.objc.initWeak(i8** undef, i8* %p)
+  call void @llvm.objc.destroyWeak(i8** null)
+  call void @llvm.objc.destroyWeak(i8** undef)
+
+  call void @llvm.objc.copyWeak(i8** null, i8** %q)
+  call void @llvm.objc.copyWeak(i8** undef, i8** %q)
+  call void @llvm.objc.copyWeak(i8** %q, i8** null)
+  call void @llvm.objc.copyWeak(i8** %q, i8** undef)
+
+  call void @llvm.objc.moveWeak(i8** null, i8** %q)
+  call void @llvm.objc.moveWeak(i8** undef, i8** %q)
+  call void @llvm.objc.moveWeak(i8** %q, i8** null)
+  call void @llvm.objc.moveWeak(i8** %q, i8** undef)
+
+  ret void
+}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/PR28219.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/PR28219.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/PR28219.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/PR28219.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+ at bar
+256
+1
+2
+ at foo
+512
+1
+3

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_br_1
+25571299074
+2
+3
+2
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1_large_count.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1_large_count.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1_large_count.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/branch1_large_count.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_br_1
+25571299074
+2
+12884901888
+8589934592
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/branch2.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/branch2.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/branch2.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/branch2.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_br_2
+29667547796
+2
+1
+1
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/criticaledge.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/criticaledge.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/criticaledge.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/criticaledge.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_criticalEdge
+82323253069
+8
+2
+1
+2
+2
+0
+1
+2
+1
+
+<stdin>:bar
+12884901887
+1
+7
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/cspgo.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/cspgo.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/cspgo.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/cspgo.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,151 @@
+# CSIR level Instrumentation Flag
+:csir
+bar_m
+# Func Hash:
+29667547796
+# Num Counters:
+2
+# Counter Values:
+99949
+51
+
+bar_m
+# Func Hash:
+1224979111529676799
+# Num Counters:
+2
+# Counter Values:
+100000
+99949
+
+csfdo_plain.c:cond
+# Func Hash:
+1152921517491748863
+# Num Counters:
+1
+# Counter Values:
+200000
+
+csfdo_plain.c:cond
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+200000
+
+bar_m2
+# Func Hash:
+1152921534274394772
+# Num Counters:
+2
+# Counter Values:
+99938
+62
+
+bar_m2
+# Func Hash:
+29667547796
+# Num Counters:
+2
+# Counter Values:
+99938
+62
+
+foo
+# Func Hash:
+1152921640672869708
+# Num Counters:
+10
+# Counter Values:
+100000
+100000
+0
+66666
+66666
+0
+100000
+66667
+100000
+1
+
+foo
+# Func Hash:
+29212902728
+# Num Counters:
+2
+# Counter Values:
+100000
+1
+
+bar
+# Func Hash:
+1152921569533132113
+# Num Counters:
+5
+# Counter Values:
+0
+0
+0
+0
+0
+
+bar
+# Func Hash:
+56228292833
+# Num Counters:
+4
+# Counter Values:
+800000
+399999
+100000
+100000
+
+main
+# Func Hash:
+1152921517491748863
+# Num Counters:
+1
+# Counter Values:
+1
+
+main
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+1
+
+csfdo_plain.c:barbar
+# Func Hash:
+1152921517491748863
+# Num Counters:
+1
+# Counter Values:
+100000
+
+csfdo_plain.c:barbar
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+100000
+
+goo
+# Func Hash:
+1152921517491748863
+# Num Counters:
+1
+# Counter Values:
+100000
+
+goo
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+100000
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/diag.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/diag.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/diag.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/diag.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,7 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+foo
+12884999999
+1
+1
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/diag_FE.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/diag_FE.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/diag_FE.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/diag_FE.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5 @@
+foo
+12884999999
+1
+1
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/func_entry.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/func_entry.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/func_entry.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/func_entry.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+9999
+
+bar
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+0

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/indirect_call.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/indirect_call.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/indirect_call.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/indirect_call.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+:ir
+bar
+# Func Hash:
+281487861612543
+# Num Counters:
+1
+# Counter Values:
+140
+# Num Value Kinds:
+1
+# ValueKind = IPVK_IndirectCallTarget:
+0
+# NumValueSites:
+1
+3
+func2:80
+func1:40
+func3:20
+
+func1
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+40
+
+func2
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+80
+
+func3
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+20
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/indirectbr.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/indirectbr.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/indirectbr.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/indirectbr.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+47485104005
+# Num Counters:
+4
+# Counter Values:
+139
+20
+5
+63

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/irreducible.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/irreducible.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/irreducible.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/irreducible.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+:ir
+_Z11irreducibleii
+# Func Hash:
+64451410787
+# Num Counters:
+6
+# Counter Values:
+1000
+950
+100
+373
+1
+0
+
+_Z11irreduciblePh
+# Func Hash:
+104649601521
+# Num Counters:
+9
+# Counter Values:
+100
+300
+99
+300
+201
+1
+1
+0
+0

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/landingpad.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/landingpad.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/landingpad.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/landingpad.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+foo
+59130013419
+4
+3
+1
+2
+0
+
+bar
+24868915205
+2
+3
+2
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/large_count_remarks.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/large_count_remarks.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/large_count_remarks.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/large_count_remarks.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test
+25571299074
+2
+40000000000
+20000000000
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/loop1.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/loop1.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/loop1.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/loop1.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_simple_for
+34137660316
+2
+96
+4
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/loop2.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/loop2.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/loop2.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/loop2.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_nested_for
+53929068288
+3
+33
+10
+6
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/memop_size_annotation.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/memop_size_annotation.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/memop_size_annotation.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/memop_size_annotation.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+53929068288
+# Num Counters:
+3
+# Counter Values:
+556
+20
+1
+# Num Value Kinds:
+1
+# ValueKind = IPVK_MemOPSize:
+1
+# NumValueSites:
+1
+9
+7:33
+2:88
+9:72
+4:66
+1:99
+5:55
+6:44
+3:77
+8:22

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/multiple_hash_profile.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/multiple_hash_profile.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/multiple_hash_profile.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/multiple_hash_profile.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+# IR level Instrumentation Flag
+:ir
+_Z3fooi
+# Func Hash:
+72057606922829823
+# Num Counters:
+2
+# Counter Values:
+18
+12
+
+_Z3fooi
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+0
+
+_Z3bari
+# Func Hash:
+72057606922829823
+# Num Counters:
+2
+# Counter Values:
+0
+0
+
+_Z4m2f1v
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+1
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/noreturncall.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/noreturncall.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/noreturncall.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/noreturncall.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+36496524737
+# Num Counters:
+3
+# Counter Values:
+21
+21
+0

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.map
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.map?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.map (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.map Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# foo:: and foo::detail:: are equivalent
+name 3foo N3foo6detailE
+
+# foo::qux and foo::quux are equivalent
+type N3foo3quxE N3foo4quuxE
+
+# N::X and M::X are equivalent
+name N1N1XE N1M1XE

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/remap.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+_ZN3foo3barERKN1N1XINS_4quuxEEE
+25571299074
+2
+3
+2
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/select1.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/select1.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/select1.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/select1.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+:ir
+test_br_2
+72057623705475732
+3
+4
+1
+1
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/select2.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/select2.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/select2.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/select2.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+72057628175588252
+# Num Counters:
+3
+# Counter Values:
+800
+3
+300

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/select_hash_conflict.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/select_hash_conflict.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/select_hash_conflict.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/select_hash_conflict.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+1
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/switch.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/switch.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/switch.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/switch.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+# :ir is the flag to indicate this is IR level profile.
+:ir
+test_switch
+46200943743
+4
+0
+5
+2
+3
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cs.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cs.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cs.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cs.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,72 @@
+# CSIR level Instrumentation Flag
+:csir
+cond.llvm.11253644763537639171
+# Func Hash:
+1152921517491748863
+# Num Counters:
+1
+# Counter Values:
+200000
+
+foo
+# Func Hash:
+29212902728
+# Num Counters:
+2
+# Counter Values:
+100000
+1
+
+bar
+# Func Hash:
+1152921534274394772
+# Num Counters:
+2
+# Counter Values:
+0
+0
+
+bar
+# Func Hash:
+29667547796
+# Num Counters:
+2
+# Counter Values:
+100000
+100000
+
+main
+# Func Hash:
+1152921517491748863
+# Num Counters:
+1
+# Counter Values:
+1
+
+main
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+1
+
+cspgo.c:foo
+# Func Hash:
+1152921563228422740
+# Num Counters:
+4
+# Counter Values:
+100000
+100000
+0
+1
+
+cspgo_bar.c:cond
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+200000
+

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_gen.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_gen.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_gen.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_gen.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$__llvm_profile_filename = comdat any
+$__llvm_profile_raw_version = comdat any
+
+ at odd = common dso_local global i32 0, align 4
+ at even = common dso_local global i32 0, align 4
+ at __llvm_profile_filename = constant [25 x i8] c"pass2/default_%m.profraw\00", comdat
+ at __llvm_profile_raw_version = constant i64 216172782113783812, comdat
+
+define dso_local void @bar(i32 %n) !prof !29 {
+entry:
+  %call = tail call fastcc i32 @cond(i32 %n)
+  %tobool = icmp eq i32 %call, 0
+  br i1 %tobool, label %if.else, label %if.then, !prof !30
+
+if.then:
+  %0 = load i32, i32* @odd, align 4
+  %inc = add i32 %0, 1
+  store i32 %inc, i32* @odd, align 4
+  br label %if.end
+
+if.else:
+  %1 = load i32, i32* @even, align 4
+  %inc1 = add i32 %1, 1
+  store i32 %inc1, i32* @even, align 4
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define internal fastcc i32 @cond(i32 %i) #1 !prof !29 !PGOFuncName !35 {
+entry:
+  %rem = srem i32 %i, 2
+  ret i32 %rem
+}
+
+attributes #1 = { inlinehint noinline }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 500002}
+!5 = !{!"MaxCount", i64 200000}
+!6 = !{!"MaxInternalCount", i64 100000}
+!7 = !{!"MaxFunctionCount", i64 200000}
+!8 = !{!"NumCounts", i64 6}
+!9 = !{!"NumFunctions", i64 4}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27}
+!12 = !{i32 10000, i64 200000, i32 1}
+!13 = !{i32 100000, i64 200000, i32 1}
+!14 = !{i32 200000, i64 200000, i32 1}
+!15 = !{i32 300000, i64 200000, i32 1}
+!16 = !{i32 400000, i64 200000, i32 1}
+!17 = !{i32 500000, i64 100000, i32 4}
+!18 = !{i32 600000, i64 100000, i32 4}
+!19 = !{i32 700000, i64 100000, i32 4}
+!20 = !{i32 800000, i64 100000, i32 4}
+!21 = !{i32 900000, i64 100000, i32 4}
+!22 = !{i32 950000, i64 100000, i32 4}
+!23 = !{i32 990000, i64 100000, i32 4}
+!24 = !{i32 999000, i64 100000, i32 4}
+!25 = !{i32 999900, i64 100000, i32 4}
+!26 = !{i32 999990, i64 100000, i32 4}
+!27 = !{i32 999999, i64 1, i32 6}
+!29 = !{!"function_entry_count", i64 200000}
+!30 = !{!"branch_weights", i32 100000, i32 100000}
+!35 = !{!"cspgo_bar.c:cond"}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_use.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_cspgo_bar_use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at odd = common dso_local global i32 0, align 4
+ at even = common dso_local global i32 0, align 4
+
+define dso_local void @bar(i32 %n) #0 !prof !29 {
+entry:
+  %call = tail call fastcc i32 @cond(i32 %n)
+  %tobool = icmp eq i32 %call, 0
+  br i1 %tobool, label %if.else, label %if.then, !prof !30
+
+if.then:
+  %0 = load i32, i32* @odd, align 4
+  %inc = add i32 %0, 1
+  store i32 %inc, i32* @odd, align 4
+  br label %if.end
+
+if.else:
+  %1 = load i32, i32* @even, align 4
+  %inc1 = add i32 %1, 1
+  store i32 %inc1, i32* @even, align 4
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+define internal fastcc i32 @cond(i32 %i) #1 !prof !29 !PGOFuncName !35 {
+entry:
+  %rem = srem i32 %i, 2
+  ret i32 %rem
+}
+
+attributes #0 = { "target-cpu"="x86-64" }
+attributes #1 = { inlinehint noinline }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 500002}
+!5 = !{!"MaxCount", i64 200000}
+!6 = !{!"MaxInternalCount", i64 100000}
+!7 = !{!"MaxFunctionCount", i64 200000}
+!8 = !{!"NumCounts", i64 6}
+!9 = !{!"NumFunctions", i64 4}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27}
+!12 = !{i32 10000, i64 200000, i32 1}
+!13 = !{i32 100000, i64 200000, i32 1}
+!14 = !{i32 200000, i64 200000, i32 1}
+!15 = !{i32 300000, i64 200000, i32 1}
+!16 = !{i32 400000, i64 200000, i32 1}
+!17 = !{i32 500000, i64 100000, i32 4}
+!18 = !{i32 600000, i64 100000, i32 4}
+!19 = !{i32 700000, i64 100000, i32 4}
+!20 = !{i32 800000, i64 100000, i32 4}
+!21 = !{i32 900000, i64 100000, i32 4}
+!22 = !{i32 950000, i64 100000, i32 4}
+!23 = !{i32 990000, i64 100000, i32 4}
+!24 = !{i32 999000, i64 100000, i32 4}
+!25 = !{i32 999900, i64 100000, i32 4}
+!26 = !{i32 999990, i64 100000, i32 4}
+!27 = !{i32 999999, i64 1, i32 6}
+!29 = !{!"function_entry_count", i64 200000}
+!30 = !{!"branch_weights", i32 100000, i32 100000}
+!35 = !{!"cspgo_bar.c:cond"}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_indirect_call_promotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_indirect_call_promotion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_indirect_call_promotion.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_indirect_call_promotion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+source_filename = "thinlto_indirect_call_promotion.c"
+
+define void @a() {
+entry:
+  ret void
+}
+
+define internal void @c() !PGOFuncName !1 {
+entry:
+  ret void
+}
+
+!1 = !{!"thinlto_indirect_call_promotion.c:c"}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fptr = external local_unnamed_addr global void ()*, align 8
+
+; Function Attrs: norecurse nounwind uwtable
+define void @_Z6updatei(i32 %i) local_unnamed_addr #0 {
+entry:
+  store void ()* @_ZL3foov, void ()** @fptr, align 8
+  ret void
+}
+
+; Function Attrs: norecurse nounwind readnone uwtable
+define internal void @_ZL3foov() #1 {
+entry:
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "b.cc", directory: "/ssd/llvm/abc/small")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2a.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2a.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2a.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2a.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+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 readnone uwtable
+define internal void @_ZL3foov() #1 {
+entry:
+  call void @_ZL3barv()
+  ret void
+}
+
+declare void @_ZL3barv()
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "b.cc", directory: "/ssd/llvm/abc/small")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2b.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2b.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2b.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp2b.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @_ZL3barv() #1 {
+entry:
+  call void @dummy()
+  call void @dummy()
+  call void @dummy()
+  call void @dummy()
+  call void @dummy()
+  call void @dummy()
+  ret void
+}
+
+define internal void @dummy() {
+entry:
+    ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "c.cc", directory: "/ssd/llvm/abc/small")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp3.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/thinlto_samplepgo_icp3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fptr = external local_unnamed_addr global void ()*, align 8
+
+; Function Attrs: norecurse nounwind uwtable
+define void @_Z6updatei(i32 %i) local_unnamed_addr #0 {
+entry:
+  store void ()* @_ZL3foov, void ()** @fptr, align 8
+  ret void
+}
+
+; Function Attrs: nounwind readnone uwtable
+define internal void @_ZL3foov() !prof !34 {
+entry:
+  %0 = load void ()*, void ()** @fptr, align 8
+  tail call void %0(), !prof !40
+  ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "b.cc", directory: "/ssd/llvm/abc/small")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}
+!34 = !{!"function_entry_count", i64 1}
+!40 = !{!"VP", i32 0, i64 3000, i64 -8789629626369651636, i64 3000}

Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/unreachable_bb.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/unreachable_bb.proftext?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/unreachable_bb.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/unreachable_bb.proftext Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+# IR level Instrumentation Flag
+:ir
+foo
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+0

Added: llvm/trunk/test/Transforms/PGOProfile/PR28219.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/PR28219.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/PR28219.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/PR28219.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; Test that we annotate entire program's summary and not just this module's
+; RUN: llvm-profdata merge %S/Inputs/PR28219.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s
+
+define i32 @bar() {
+entry:
+  ret i32 1
+}
+; CHECK-DAG: {{![0-9]+}} = !{i32 1, !"ProfileSummary", {{![0-9]+}}}
+; CHECK-DAG: {{![0-9]+}} = !{!"NumFunctions", i64 2}
+; CHECK-DAG: {{![0-9]+}} = !{!"MaxFunctionCount", i64 3}
+

Added: llvm/trunk/test/Transforms/PGOProfile/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/PGOProfile/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/PGOProfile/X86/macho.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/X86/macho.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/X86/macho.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/X86/macho.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -pgo-instr-gen -instrprof -S | llc | FileCheck %s --check-prefix=MACHO-DIRECTIVE
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+; MACHO-DIRECTIVE: .weak_definition        ___llvm_profile_raw_version
+define i32 @test_macho(i32 %i) {
+entry:
+  ret i32 %i
+}

Added: llvm/trunk/test/Transforms/PGOProfile/branch1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/branch1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/branch1.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/branch1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,62 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN --check-prefix=GEN-COMDAT
+; RUN: opt < %s -mtriple=x86_64-apple-darwin -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN --check-prefix=GEN-DARWIN-LINKONCE
+
+; New PM
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN --check-prefix=GEN-COMDAT
+; RUN: opt < %s -mtriple=x86_64-apple-darwin -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN --check-prefix=GEN-DARWIN-LINKONCE
+
+; RUN: llvm-profdata merge %S/Inputs/branch1.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+
+; RUN: llvm-profdata merge %S/Inputs/branch1_large_count.proftext -o %t.l.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.l.profdata -S | FileCheck %s --check-prefix=USE-LARGE
+
+; New PM
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.l.profdata -S | FileCheck %s --check-prefix=USE-LARGE
+
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -pass-remarks=pgo-instrumentation -pgo-emit-branch-prob -S 2>&1| FileCheck %s --check-prefix=ANALYSIS
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -pass-remarks=pgo-instrumentation -pgo-emit-branch-prob -S 2>&1| FileCheck %s --check-prefix=ANALYSIS
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+; GEN-DARWIN-LINKONCE: target triple = "x86_64-apple-darwin"
+
+; GEN-COMDAT: $__llvm_profile_raw_version = comdat any
+; GEN-COMDAT: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN-LINKONCE: @__llvm_profile_raw_version = linkonce constant i64 {{[0-9]+}}
+; GEN: @__profn_test_br_1 = private constant [9 x i8] c"test_br_1"
+
+define i32 @test_br_1(i32 %i) {
+; USE-LABEL: @test_br_1
+; USE-SAME: !prof ![[FUNC_ENTRY_COUNT:[0-9]+]]
+entry:
+; GEN: entry:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @__profn_test_br_1, i32 0, i32 0), i64 25571299074, i32 2, i32 0)
+  %cmp = icmp sgt i32 %i, 0
+  br i1 %cmp, label %if.then, label %if.end
+; USE: br i1 %cmp, label %if.then, label %if.end
+; USE-SAME: !prof ![[BW_ENTRY:[0-9]+]]
+; USE-DAG: ![[BW_ENTRY]] = !{!"branch_weights", i32 2, i32 1}
+; USE-LARGE: br i1 %cmp, label %if.then, label %if.end
+; USE-LARGE-SAME: !prof ![[BW_L_ENTRY:[0-9]+]]
+; USE-LARGE-DAG: ![[BW_L_ENTRY]] = !{!"branch_weights", i32 -1431655766, i32 1431655765}
+
+if.then:
+; GEN: if.then:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @__profn_test_br_1, i32 0, i32 0), i64 25571299074, i32 2, i32 1)
+  %add = add nsw i32 %i, 2
+  br label %if.end
+
+if.end:
+; GEN: if.end:
+; GEN-NOT: llvm.instrprof.increment
+; GEN: ret i32
+  %retv = phi i32 [ %add, %if.then ], [ %i, %entry ]
+  ret i32 %retv
+}
+; USE-DAG: {{![0-9]+}} = !{i32 1, !"ProfileSummary", {{![0-9]+}}}
+; USE-DAG: {{![0-9]+}} = !{!"DetailedSummary", {{![0-9]+}}}
+; USE-DAG: ![[FUNC_ENTRY_COUNT]] = !{!"function_entry_count", i64 3}
+
+; ANALYSIS:remark: <unknown>:0:0: sgt_i32_Zero {{.*}}66.67% (total count : 3)

Added: llvm/trunk/test/Transforms/PGOProfile/branch2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/branch2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/branch2.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/branch2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: llvm-profdata merge %S/Inputs/branch2.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_test_br_2 = private constant [9 x i8] c"test_br_2"
+
+define i32 @test_br_2(i32 %i) {
+entry:
+; GEN: entry:
+; GEN-NOT: llvm.instrprof.increment
+  %cmp = icmp sgt i32 %i, 0
+  br i1 %cmp, label %if.then, label %if.else
+; USE: br i1 %cmp, label %if.then, label %if.else
+; USE-SAME: !prof ![[BW_ENTRY:[0-9]+]]
+; USE: ![[BW_ENTRY]] = !{!"branch_weights", i32 1, i32 1}
+
+if.then:
+; GEN: if.then:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @__profn_test_br_2, i32 0, i32 0), i64 29667547796, i32 2, i32 0)
+  %add = add nsw i32 %i, 2
+  br label %if.end
+
+if.else:
+; GEN: if.else:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @__profn_test_br_2, i32 0, i32 0), i64 29667547796, i32 2, i32 1)
+  %sub = sub nsw i32 %i, 2
+  br label %if.end
+
+if.end:
+; GEN: if.end:
+; GEN-NOT: llvm.instrprof.increment
+  %retv = phi i32 [ %add, %if.then ], [ %sub, %if.else ]
+  ret i32 %retv
+; GEN: ret
+}

Added: llvm/trunk/test/Transforms/PGOProfile/chr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/chr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/chr.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/chr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1912 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -chr -instcombine -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -passes='require<profile-summary>,function(chr,instcombine,simplify-cfg)' -S | FileCheck %s
+
+declare void @foo()
+declare void @bar()
+
+; Simple case.
+; Roughly,
+; t0 = *i
+; if ((t0 & 1) != 0) // Likely true
+;   foo()
+; if ((t0 & 2) != 0) // Likely true
+;   foo()
+; ->
+; t0 = *i
+; if ((t0 & 3) != 0) { // Likely true
+;   foo()
+;   foo()
+; } else {
+;   if ((t0 & 1) != 0)
+;     foo()
+;   if ((t0 & 2) != 0)
+;     foo()
+; }
+define void @test_chr_1(i32* %i) !prof !14 {
+; CHECK-LABEL: @test_chr_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %3 = and i32 %0, 2
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb3, label %bb2, !prof !15
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  ret void
+}
+
+; Simple case with a cold block.
+; Roughly,
+; t0 = *i
+; if ((t0 & 1) != 0) // Likely true
+;   foo()
+; if ((t0 & 2) == 0) // Likely false
+;   bar()
+; if ((t0 & 4) != 0) // Likely true
+;   foo()
+; ->
+; t0 = *i
+; if ((t0 & 7) == 7) { // Likely true
+;   foo()
+;   foo()
+; } else {
+;   if ((t0 & 1) != 0)
+;     foo()
+;   if ((t0 & 2) == 0)
+;     bar()
+;   if ((t0 & 4) != 0)
+;     foo()
+; }
+define void @test_chr_1_1(i32* %i) !prof !14 {
+; CHECK-LABEL: @test_chr_1_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 7
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 7
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB5:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB2_NONCHR:%.*]], label [[BB3_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[BB3_NONCHR]]
+; CHECK:       bb3.nonchr:
+; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 4
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    br i1 [[TMP8]], label [[BB5]], label [[BB4_NONCHR:%.*]], !prof !16
+; CHECK:       bb4.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB5]]
+; CHECK:       bb5:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %3 = and i32 %0, 2
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb2, label %bb3, !prof !15
+
+bb2:
+  call void @bar()
+  br label %bb3
+
+bb3:
+  %5 = and i32 %0, 4
+  %6 = icmp eq i32 %5, 0
+  br i1 %6, label %bb5, label %bb4, !prof !15
+
+bb4:
+  call void @foo()
+  br label %bb5
+
+bb5:
+  ret void
+}
+
+; With an aggregate bit check.
+; Roughly,
+; t0 = *i
+; if ((t0 & 255) != 0) // Likely true
+;   if ((t0 & 1) != 0) // Likely true
+;     foo()
+;   if ((t0 & 2) != 0) // Likely true
+;     foo()
+; ->
+; t0 = *i
+; if ((t0 & 3) != 0) { // Likely true
+;   foo()
+;   foo()
+; } else if ((t0 & 255) != 0)
+;   if ((t0 & 1) != 0)
+;     foo()
+;   if ((t0 & 2) != 0)
+;     foo()
+; }
+define void @test_chr_2(i32* %i) !prof !14 {
+; CHECK-LABEL: @test_chr_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB1:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb1:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 255
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB4]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB2_NONCHR:%.*]], label [[BB1_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    br i1 [[TMP8]], label [[BB4]], label [[BB3_NONCHR:%.*]], !prof !16
+; CHECK:       bb3.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB2_NONCHR]]
+; CHECK:       bb4:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 255
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb4, label %bb0, !prof !15
+
+bb0:
+  %3 = and i32 %0, 1
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb2, label %bb1, !prof !15
+
+bb1:
+  call void @foo()
+  br label %bb2
+
+bb2:
+  %5 = and i32 %0, 2
+  %6 = icmp eq i32 %5, 0
+  br i1 %6, label %bb4, label %bb3, !prof !15
+
+bb3:
+  call void @foo()
+  br label %bb4
+
+bb4:
+  ret void
+}
+
+; Split case.
+; Roughly,
+; t1 = *i
+; if ((t1 & 1) != 0) // Likely true
+;   foo()
+; if ((t1 & 2) != 0) // Likely true
+;   foo()
+; t2 = *i
+; if ((t2 & 4) != 0) // Likely true
+;   foo()
+; if ((t2 & 8) != 0) // Likely true
+;   foo()
+; ->
+; t1 = *i
+; if ((t1 & 3) != 0) { // Likely true
+;   foo()
+;   foo()
+; } else {
+;   if ((t1 & 1) != 0)
+;     foo()
+;   if ((t1 & 2) != 0)
+;     foo()
+; }
+; t2 = *i
+; if ((t2 & 12) != 0) { // Likely true
+;   foo()
+;   foo()
+; } else {
+;   if ((t2 & 4) != 0)
+;     foo()
+;   if ((t2 & 8) != 0)
+;     foo()
+; }
+define void @test_chr_3(i32* %i) !prof !14 {
+; CHECK-LABEL: @test_chr_3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* [[I]], align 4
+; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP7]], 12
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 12
+; CHECK-NEXT:    br i1 [[TMP9]], label [[BB4:%.*]], label [[BB3_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB7:%.*]]
+; CHECK:       bb3.split.nonchr:
+; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP7]], 4
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT:    br i1 [[TMP11]], label [[BB5_NONCHR:%.*]], label [[BB4_NONCHR:%.*]], !prof !16
+; CHECK:       bb4.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB5_NONCHR]]
+; CHECK:       bb5.nonchr:
+; CHECK-NEXT:    [[TMP12:%.*]] = and i32 [[TMP7]], 8
+; CHECK-NEXT:    [[TMP13:%.*]] = icmp eq i32 [[TMP12]], 0
+; CHECK-NEXT:    br i1 [[TMP13]], label [[BB7]], label [[BB6_NONCHR:%.*]], !prof !16
+; CHECK:       bb6.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB7]]
+; CHECK:       bb7:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %3 = and i32 %0, 2
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb3, label %bb2, !prof !15
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  %5 = load i32, i32* %i
+  %6 = and i32 %5, 4
+  %7 = icmp eq i32 %6, 0
+  br i1 %7, label %bb5, label %bb4, !prof !15
+
+bb4:
+  call void @foo()
+  br label %bb5
+
+bb5:
+  %8 = and i32 %5, 8
+  %9 = icmp eq i32 %8, 0
+  br i1 %9, label %bb7, label %bb6, !prof !15
+
+bb6:
+  call void @foo()
+  br label %bb7
+
+bb7:
+  ret void
+}
+
+; Selects.
+; Roughly,
+; t0 = *i
+; sum1 = (t0 & 1) ? sum0 : (sum0 + 42) // Likely false
+; sum2 = (t0 & 2) ? sum1 : (sum1 + 43) // Likely false
+; return sum2
+; ->
+; t0 = *i
+; if ((t0 & 3) == 3)
+;   return sum0 + 85
+; else {
+;   sum1 = (t0 & 1) ? sum0 : (sum0 + 42)
+;   sum2 = (t0 & 2) ? sum1 : (sum1 + 43)
+;   return sum2
+; }
+define i32 @test_chr_4(i32* %i, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       entry.split:
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85
+; CHECK-NEXT:    ret i32 [[TMP3]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[SUM0]], 42
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    [[SUM1_NONCHR:%.*]] = select i1 [[TMP6]], i32 [[SUM0]], i32 [[TMP4]], !prof !16
+; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    [[TMP9:%.*]] = add i32 [[SUM1_NONCHR]], 43
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP8]], i32 [[SUM1_NONCHR]], i32 [[TMP9]], !prof !16
+; CHECK-NEXT:    ret i32 [[SUM2_NONCHR]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  %3 = add i32 %sum0, 42
+  %sum1 = select i1 %2, i32 %sum0, i32 %3, !prof !15
+  %4 = and i32 %0, 2
+  %5 = icmp eq i32 %4, 0
+  %6 = add i32 %sum1, 43
+  %sum2 = select i1 %5, i32 %sum1, i32 %6, !prof !15
+  ret i32 %sum2
+}
+
+; Selects + Brs
+; Roughly,
+; t0 = *i
+; if ((t0 & 255) != 0) { // Likely true
+;   sum = (t0 & 1) ? sum0 : (sum0 + 42) // Likely false
+;   sum = (t0 & 2) ? sum : (sum + 43) // Likely false
+;   if ((t0 & 4) != 0) { // Likely true
+;     sum3 = sum + 44
+;     sum = (t0 & 8) ? sum3 : (sum3 + 44) // Likely false
+;   }
+; }
+; return sum
+; ->
+; t0 = *i
+; if ((t0 & 15) != 15) { // Likely true
+;   sum = sum0 + 173
+; } else if ((t0 & 255) != 0) {
+;   sum = (t0 & 1) ? sum0 : (sum0 + 42)
+;   sum = (t0 & 2) ? sum : (sum + 43)
+;   if ((t0 & 4) != 0) {
+;     sum3 = sum + 44
+;     sum = (t0 & 8) ? sum3 : (sum3 + 44)
+;   }
+; }
+; return sum
+define i32 @test_chr_5(i32* %i, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 15
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 15
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85
+; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[SUM0]], 173
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 255
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    [[TMP9:%.*]] = add i32 [[SUM0]], 42
+; CHECK-NEXT:    [[SUM1_NONCHR:%.*]] = select i1 [[TMP8]], i32 [[SUM0]], i32 [[TMP9]], !prof !16
+; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT:    [[TMP12:%.*]] = add i32 [[SUM1_NONCHR]], 43
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP11]], i32 [[SUM1_NONCHR]], i32 [[TMP12]], !prof !16
+; CHECK-NEXT:    [[TMP13:%.*]] = and i32 [[TMP0]], 4
+; CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i32 [[TMP13]], 0
+; CHECK-NEXT:    br i1 [[TMP14]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP15:%.*]] = and i32 [[TMP0]], 8
+; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
+; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP16]], i32 44, i32 88, !prof !16
+; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[TMP4]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    ret i32 [[SUM6]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 255
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb3, label %bb0, !prof !15
+
+bb0:
+  %3 = and i32 %0, 1
+  %4 = icmp eq i32 %3, 0
+  %5 = add i32 %sum0, 42
+  %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15
+  %6 = and i32 %0, 2
+  %7 = icmp eq i32 %6, 0
+  %8 = add i32 %sum1, 43
+  %sum2 = select i1 %7, i32 %sum1, i32 %8, !prof !15
+  %9 = and i32 %0, 4
+  %10 = icmp eq i32 %9, 0
+  br i1 %10, label %bb2, label %bb1, !prof !15
+
+bb1:
+  %sum3 = add i32 %sum2, 44
+  %11 = and i32 %0, 8
+  %12 = icmp eq i32 %11, 0
+  %13 = add i32 %sum3, 44
+  %sum4 = select i1 %12, i32 %sum3, i32 %13, !prof !15
+  br label %bb2
+
+bb2:
+  %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ]
+  br label %bb3
+
+bb3:
+  %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ]
+  ret i32 %sum6
+}
+
+; Selects + Brs with a scope split in the middle
+; Roughly,
+; t0 = *i
+; if ((t0 & 255) != 0) { // Likely true
+;   sum = (t0 & 1) ? sum0 : (sum0 + 42) // Likely false
+;   sum = (t0 & 2) ? sum : (sum + 43) // Likely false
+;   if ((sum0 & 4) != 0) { // Likely true. The condition doesn't use v.
+;     sum3 = sum + 44
+;     sum = (t0 & 8) ? sum3 : (sum3 + 44) // Likely false
+;   }
+; }
+; return sum
+; ->
+; t0 = *i
+; if ((sum0 & 4) != 0 & (t0 & 11) != 11) { // Likely true
+;   sum = sum0 + 173
+; } else if ((t0 & 255) != 0) {
+;   sum = (t0 & 1) ? sum0 : (sum0 + 42)
+;   sum = (t0 & 2) ? sum : (sum + 43)
+;   if ((sum0 & 4) != 0) {
+;     sum3 = sum + 44
+;     sum = (t0 & 8) ? sum3 : (sum3 + 44)
+;   }
+; }
+; return sum
+define i32 @test_chr_5_1(i32* %i, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_5_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[SUM0:%.*]], 4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 11
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 11
+; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP2]]
+; CHECK-NEXT:    br i1 [[TMP5]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[SUM0]], 85
+; CHECK-NEXT:    [[TMP7:%.*]] = add i32 [[SUM0]], 173
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP8:%.*]] = and i32 [[TMP0]], 255
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0
+; CHECK-NEXT:    br i1 [[TMP9]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT:    [[TMP12:%.*]] = add i32 [[SUM0]], 42
+; CHECK-NEXT:    [[SUM1_NONCHR:%.*]] = select i1 [[TMP11]], i32 [[SUM0]], i32 [[TMP12]], !prof !16
+; CHECK-NEXT:    [[TMP13:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i32 [[TMP13]], 0
+; CHECK-NEXT:    [[TMP15:%.*]] = add i32 [[SUM1_NONCHR]], 43
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP14]], i32 [[SUM1_NONCHR]], i32 [[TMP15]], !prof !16
+; CHECK-NEXT:    [[TMP16:%.*]] = and i32 [[SUM0]], 4
+; CHECK-NEXT:    [[TMP17:%.*]] = icmp eq i32 [[TMP16]], 0
+; CHECK-NEXT:    br i1 [[TMP17]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP18:%.*]] = and i32 [[TMP0]], 8
+; CHECK-NEXT:    [[TMP19:%.*]] = icmp eq i32 [[TMP18]], 0
+; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP19]], i32 44, i32 88, !prof !16
+; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[TMP7]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    ret i32 [[SUM6]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 255
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb3, label %bb0, !prof !15
+
+bb0:
+  %3 = and i32 %0, 1
+  %4 = icmp eq i32 %3, 0
+  %5 = add i32 %sum0, 42
+  %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15
+  %6 = and i32 %0, 2
+  %7 = icmp eq i32 %6, 0
+  %8 = add i32 %sum1, 43
+  %sum2 = select i1 %7, i32 %sum1, i32 %8, !prof !15
+  %9 = and i32 %sum0, 4                              ; Split
+  %10 = icmp eq i32 %9, 0
+  br i1 %10, label %bb2, label %bb1, !prof !15
+
+bb1:
+  %sum3 = add i32 %sum2, 44
+  %11 = and i32 %0, 8
+  %12 = icmp eq i32 %11, 0
+  %13 = add i32 %sum3, 44
+  %sum4 = select i1 %12, i32 %sum3, i32 %13, !prof !15
+  br label %bb2
+
+bb2:
+  %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ]
+  br label %bb3
+
+bb3:
+  %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ]
+  ret i32 %sum6
+}
+
+; Selects + Brs, non-matching bases
+; Roughly,
+; i0 = *i
+; j0 = *j
+; if ((i0 & 255) != 0) { // Likely true
+;   sum = (i0 & 2) ? sum0 : (sum0 + 43) // Likely false
+;   if ((j0 & 4) != 0) { // Likely true. The condition uses j0, not i0.
+;     sum3 = sum + 44
+;     sum = (i0 & 8) ? sum3 : (sum3 + 44) // Likely false
+;   }
+; }
+; return sum
+; ->
+; i0 = *i
+; j0 = *j
+; if ((j0 & 4) != 0 & (i0 & 10) != 10) { // Likely true
+;   sum = sum0 + 131
+; } else if ((i0 & 255) != 0) {
+;   sum = (i0 & 2) ? sum0 : (sum0 + 43)
+;   if ((j0 & 4) != 0) {
+;     sum3 = sum + 44
+;     sum = (i0 & 8) ? sum3 : (sum3 + 44)
+;   }
+; }
+; return sum
+define i32 @test_chr_6(i32* %i, i32* %j, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_6(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    [[V9:%.*]] = and i32 [[J0]], 4
+; CHECK-NEXT:    [[V10:%.*]] = icmp ne i32 [[V9]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[I0]], 10
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 10
+; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[V10]]
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    [[V8:%.*]] = add i32 [[SUM0:%.*]], 43
+; CHECK-NEXT:    [[V13:%.*]] = add i32 [[SUM0]], 131
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[V1:%.*]] = and i32 [[I0]], 255
+; CHECK-NEXT:    [[V2:%.*]] = icmp eq i32 [[V1]], 0
+; CHECK-NEXT:    br i1 [[V2]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    [[V3_NONCHR:%.*]] = and i32 [[I0]], 2
+; CHECK-NEXT:    [[V4_NONCHR:%.*]] = icmp eq i32 [[V3_NONCHR]], 0
+; CHECK-NEXT:    [[V8_NONCHR:%.*]] = add i32 [[SUM0]], 43
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[V4_NONCHR]], i32 [[SUM0]], i32 [[V8_NONCHR]], !prof !16
+; CHECK-NEXT:    [[V9_NONCHR:%.*]] = and i32 [[J0]], 4
+; CHECK-NEXT:    [[V10_NONCHR:%.*]] = icmp eq i32 [[V9_NONCHR]], 0
+; CHECK-NEXT:    br i1 [[V10_NONCHR]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[V11_NONCHR:%.*]] = and i32 [[I0]], 8
+; CHECK-NEXT:    [[V12_NONCHR:%.*]] = icmp eq i32 [[V11_NONCHR]], 0
+; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[V12_NONCHR]], i32 44, i32 88, !prof !16
+; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[V13]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    ret i32 [[SUM6]]
+;
+entry:
+  %i0 = load i32, i32* %i
+  %j0 = load i32, i32* %j
+  %v1 = and i32 %i0, 255
+  %v2 = icmp eq i32 %v1, 0
+  br i1 %v2, label %bb3, label %bb0, !prof !15
+
+bb0:
+  %v3 = and i32 %i0, 2
+  %v4 = icmp eq i32 %v3, 0
+  %v8 = add i32 %sum0, 43
+  %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15
+  %v9 = and i32 %j0, 4
+  %v10 = icmp eq i32 %v9, 0
+  br i1 %v10, label %bb2, label %bb1, !prof !15
+
+bb1:
+  %sum3 = add i32 %sum2, 44
+  %v11 = and i32 %i0, 8
+  %v12 = icmp eq i32 %v11, 0
+  %v13 = add i32 %sum3, 44
+  %sum4 = select i1 %v12, i32 %sum3, i32 %v13, !prof !15
+  br label %bb2
+
+bb2:
+  %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ]
+  br label %bb3
+
+bb3:
+  %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ]
+  ret i32 %sum6
+}
+
+; Selects + Brs, the branch condition can't be hoisted to be merged with a
+; select. No CHR happens.
+; Roughly,
+; i0 = *i
+; sum = ((i0 & 2) == 0) ? sum0 : (sum0 + 43)  // Likely false
+; foo();
+; j0 = *j
+; if ((j0 & 4) != 0) { // Likely true
+;   foo();
+;   sum = sum + 44
+; }
+; return sum
+; ->
+; (no change)
+define i32 @test_chr_7(i32* %i, i32* %j, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_7(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[V3:%.*]] = and i32 [[I0]], 2
+; CHECK-NEXT:    [[V4:%.*]] = icmp eq i32 [[V3]], 0
+; CHECK-NEXT:    [[V8:%.*]] = add i32 [[SUM0:%.*]], 43
+; CHECK-NEXT:    [[SUM2:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof !16
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    [[V9:%.*]] = and i32 [[J0]], 4
+; CHECK-NEXT:    [[V10:%.*]] = icmp eq i32 [[V9]], 0
+; CHECK-NEXT:    br i1 [[V10]], label [[BB2:%.*]], label [[BB1:%.*]], !prof !16
+; CHECK:       bb1:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[SUM4:%.*]] = add i32 [[SUM2]], 44
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[SUM5:%.*]] = phi i32 [ [[SUM2]], [[ENTRY:%.*]] ], [ [[SUM4]], [[BB1]] ]
+; CHECK-NEXT:    ret i32 [[SUM5]]
+;
+entry:
+  %i0 = load i32, i32* %i
+  %v3 = and i32 %i0, 2
+  %v4 = icmp eq i32 %v3, 0
+  %v8 = add i32 %sum0, 43
+  %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15
+  call void @foo()
+  %j0 = load i32, i32* %j
+  %v9 = and i32 %j0, 4
+  %v10 = icmp eq i32 %v9, 0
+  br i1 %v10, label %bb2, label %bb1, !prof !15    ; %v10 can't be hoisted above the above select
+
+bb1:
+  call void @foo()
+  %sum4 = add i32 %sum2, 44
+  br label %bb2
+
+bb2:
+  %sum5 = phi i32 [ %sum2, %entry ], [ %sum4, %bb1 ]
+  ret i32 %sum5
+}
+
+; Selects + Brs, the branch condition can't be hoisted to be merged with the
+; selects. Dropping the select.
+; Roughly,
+; i0 = *i
+; sum = ((i0 & 2) == 0) ? sum0 : (sum0 + 43)  // Likely false
+; foo();
+; j0 = *j
+; if ((j0 & 4) != 0) // Likely true
+;   foo()
+; if ((j0 & 8) != 0) // Likely true
+;   foo()
+; return sum
+; ->
+; i0 = *i
+; sum = ((i0 & 2) == 0) ? sum0 : (sum0 + 43)  // Likely false
+; foo();
+; j0 = *j
+; if ((j0 & 12) != 12) { // Likely true
+;   foo()
+;   foo()
+; } else {
+;   if ((j0 & 4) != 0)
+;     foo()
+;   if ((j0 & 8) != 0)
+;     foo()
+; }
+; return sum
+define i32 @test_chr_7_1(i32* %i, i32* %j, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_7_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[V3:%.*]] = and i32 [[I0]], 2
+; CHECK-NEXT:    [[V4:%.*]] = icmp eq i32 [[V3]], 0
+; CHECK-NEXT:    [[V8:%.*]] = add i32 [[SUM0:%.*]], 43
+; CHECK-NEXT:    [[SUM2:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof !16
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[J0]], 12
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 12
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[V9:%.*]] = and i32 [[J0]], 4
+; CHECK-NEXT:    [[V10:%.*]] = icmp eq i32 [[V9]], 0
+; CHECK-NEXT:    br i1 [[V10]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[V11_NONCHR:%.*]] = and i32 [[J0]], 8
+; CHECK-NEXT:    [[V12_NONCHR:%.*]] = icmp eq i32 [[V11_NONCHR]], 0
+; CHECK-NEXT:    br i1 [[V12_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i32 [[SUM2]]
+;
+entry:
+  %i0 = load i32, i32* %i
+  %v3 = and i32 %i0, 2
+  %v4 = icmp eq i32 %v3, 0
+  %v8 = add i32 %sum0, 43
+  %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15
+  call void @foo()
+  %j0 = load i32, i32* %j
+  %v9 = and i32 %j0, 4
+  %v10 = icmp eq i32 %v9, 0
+  br i1 %v10, label %bb1, label %bb0, !prof !15    ; %v10 can't be hoisted above the above select
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %v11 = and i32 %j0, 8
+  %v12 = icmp eq i32 %v11, 0
+  br i1 %v12, label %bb3, label %bb2, !prof !15
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  ret i32 %sum2
+}
+
+; Branches aren't biased enough. No CHR happens.
+; Roughly,
+; t0 = *i
+; if ((t0 & 1) != 0) // Not biased
+;   foo()
+; if ((t0 & 2) != 0) // Not biased
+;   foo()
+; ->
+; (no change)
+define void @test_chr_8(i32* %i) !prof !14 {
+; CHECK-LABEL: @test_chr_8(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB1:%.*]], label [[BB0:%.*]], !prof !17
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB3:%.*]], label [[BB2:%.*]], !prof !17
+; CHECK:       bb2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !16
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %3 = and i32 %0, 2
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb3, label %bb2, !prof !16
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  ret void
+}
+
+; With an existing phi at the exit.
+; Roughly,
+; t = *i
+; if ((t0 & 1) != 0) // Likely true
+;   foo()
+; if ((t0 & 2) != 0) { // Likely true
+;   t = *j
+;   foo()
+; }
+; // There's a phi for t here.
+; return t
+; ->
+; t = *i
+; if ((t & 3) == 3) { // Likely true
+;   foo()
+;   t = *j
+;   foo()
+; } else {
+;   if ((t & 1) != 0)
+;     foo()
+;   if ((t & 2) != 0) {
+;     t = *j
+;     foo()
+;   }
+; }
+; // There's a phi for t here.
+; return t
+define i32 @test_chr_9(i32* %i, i32* %j) !prof !14 {
+; CHECK-LABEL: @test_chr_9(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0
+; CHECK-NEXT:    br i1 [[TMP5]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP6:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0
+; CHECK-NEXT:    br i1 [[TMP7]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[J]], align 4
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP0]], [[BB1_NONCHR]] ], [ [[TMP8]], [[BB2_NONCHR]] ]
+; CHECK-NEXT:    ret i32 [[TMP9]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %3 = and i32 %0, 2
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb3, label %bb2, !prof !15
+
+bb2:
+  %5 = load i32, i32* %j
+  call void @foo()
+  br label %bb3
+
+bb3:
+  %6 = phi i32 [ %0, %bb1 ], [ %5, %bb2 ]
+  ret i32 %6
+}
+
+; With no phi at the exit, but the exit needs a phi inserted after CHR.
+; Roughly,
+; t0 = *i
+; if ((t0 & 1) != 0) // Likely true
+;   foo()
+; t1 = *j
+; if ((t1 & 2) != 0) // Likely true
+;   foo()
+; return (t1 * 42) - (t1 - 99)
+; ->
+; t0 = *i
+; if ((t0 & 3) == 3) { // Likely true
+;   foo()
+;   t1 = *j
+;   foo()
+; } else {
+;   if ((t0 & 1) != 0)
+;     foo()
+;   if ((t0 & 2) != 0) {
+;     t1 = *j
+;     foo()
+;   }
+; }
+; // A new phi for t1 is inserted here.
+; return (t1 * 42) - (t1 - 99)
+define i32 @test_chr_10(i32* %i, i32* %j) !prof !14 {
+; CHECK-LABEL: @test_chr_10(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP4:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0
+; CHECK-NEXT:    br i1 [[TMP5]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* [[J]], align 4
+; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    br i1 [[TMP8]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP9:%.*]] = phi i32 [ [[TMP3]], [[BB0]] ], [ [[TMP6]], [[BB2_NONCHR]] ], [ [[TMP6]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    [[TMP10:%.*]] = mul i32 [[TMP9]], 42
+; CHECK-NEXT:    [[TMP11:%.*]] = add i32 [[TMP9]], -99
+; CHECK-NEXT:    [[TMP12:%.*]] = add i32 [[TMP10]], [[TMP11]]
+; CHECK-NEXT:    ret i32 [[TMP12]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %3 = load i32, i32* %j
+  %4 = and i32 %0, 2
+  %5 = icmp eq i32 %4, 0
+  br i1 %5, label %bb3, label %bb2, !prof !15
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  %6 = mul i32 %3, 42
+  %7 = sub i32 %3, 99
+  %8 = add i32 %6, %7
+  ret i32 %8
+}
+
+; Test a case where there are two use-def chain paths to the same value (t0)
+; from the branch condition. This is a regression test for an old bug that
+; caused a bad hoisting that moves (hoists) a value (%conv) twice to the end of
+; the %entry block (once for %div and once for %mul16) and put a use ahead of
+; its definition like:
+; %entry:
+;   ...
+;   %div = fdiv double 1.000000e+00, %conv
+;   %conv = sitofp i32 %0 to double
+;   %mul16 = fmul double %div, %conv
+;
+; Roughly,
+; t0 = *i
+; if ((t0 & 1) != 0) // Likely true
+;   foo()
+; // there are two use-def paths from the branch condition to t0.
+; if ((1.0 / t0) * t0 < 1) // Likely true
+;   foo()
+; ->
+; t0 = *i
+; if ((t0 & 1) != 0 & (1.0 / t0) * t0 > 0) { // Likely true
+;   foo()
+;   foo()
+; } else {
+;   if ((t0 & 1) != 0)
+;     foo()
+;   if ((1.0 / t0) * t0 < 1) // Likely true
+;     foo()
+; }
+define void @test_chr_11(i32* %i, i32 %x) !prof !14 {
+; CHECK-LABEL: @test_chr_11(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = sitofp i32 [[TMP0]] to double
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double 1.000000e+00, [[CONV]]
+; CHECK-NEXT:    [[MUL16:%.*]] = fmul double [[DIV]], [[CONV]]
+; CHECK-NEXT:    [[CONV717:%.*]] = fptosi double [[MUL16]] to i32
+; CHECK-NEXT:    [[CMP18:%.*]] = icmp sgt i32 [[CONV717]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[CMP18]]
+; CHECK-NEXT:    br i1 [[TMP3]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0_NONCHR:%.*]], label [[BB1_NONCHR:%.*]], !prof !18
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[CONV_NONCHR:%.*]] = sitofp i32 [[TMP0]] to double
+; CHECK-NEXT:    [[DIV_NONCHR:%.*]] = fdiv double 1.000000e+00, [[CONV_NONCHR]]
+; CHECK-NEXT:    [[MUL16_NONCHR:%.*]] = fmul double [[DIV_NONCHR]], [[CONV_NONCHR]]
+; CHECK-NEXT:    [[CONV717_NONCHR:%.*]] = fptosi double [[MUL16_NONCHR]] to i32
+; CHECK-NEXT:    [[CMP18_NONCHR:%.*]] = icmp slt i32 [[CONV717_NONCHR]], 1
+; CHECK-NEXT:    br i1 [[CMP18_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %conv = sitofp i32 %0 to double
+  %div = fdiv double 1.000000e+00, %conv
+  %mul16 = fmul double %div, %conv
+  %conv717 = fptosi double %mul16 to i32
+  %cmp18 = icmp slt i32 %conv717, 1
+  br i1 %cmp18, label %bb3, label %bb2, !prof !15
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  ret void
+}
+
+; Selects + unrelated br only
+define i32 @test_chr_12(i32* %i, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_12(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 255
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB3:%.*]], label [[BB0:%.*]], !prof !16
+; CHECK:       bb0:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[SUM0:%.*]], 42
+; CHECK-NEXT:    [[SUM1:%.*]] = select i1 [[TMP4]], i32 [[SUM0]], i32 [[TMP5]], !prof !16
+; CHECK-NEXT:    [[TMP6:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0
+; CHECK-NEXT:    [[TMP8:%.*]] = add i32 [[SUM1]], 43
+; CHECK-NEXT:    [[SUM2:%.*]] = select i1 [[TMP7]], i32 [[SUM1]], i32 [[TMP8]], !prof !16
+; CHECK-NEXT:    [[TMP9:%.*]] = load i32, i32* [[I]], align 4
+; CHECK-NEXT:    [[TMP10:%.*]] = icmp ne i32 [[TMP9]], 0
+; CHECK-NEXT:    [[TMP11:%.*]] = and i32 [[TMP0]], 8
+; CHECK-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
+; CHECK-NEXT:    [[TMP13:%.*]] = and i1 [[TMP10]], [[TMP12]]
+; CHECK-NEXT:    br i1 [[TMP13]], label [[BB1:%.*]], label [[BB0_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP14:%.*]] = add i32 [[SUM2]], 88
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb0.split.nonchr:
+; CHECK-NEXT:    br i1 [[TMP10]], label [[BB1_NONCHR:%.*]], label [[BB3]], !prof !18
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP15:%.*]] = and i32 [[TMP0]], 8
+; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
+; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP16]], i32 44, i32 88, !prof !16
+; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2]], [[SUM4_NONCHR_V]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[SUM0]], [[ENTRY:%.*]] ], [ [[TMP14]], [[BB1]] ], [ [[SUM2]], [[BB0_SPLIT_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    ret i32 [[SUM6]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 255
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb3, label %bb0, !prof !15
+
+bb0:
+  %3 = and i32 %0, 1
+  %4 = icmp eq i32 %3, 0
+  %5 = add i32 %sum0, 42
+  %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15
+  %6 = and i32 %0, 2
+  %7 = icmp eq i32 %6, 0
+  %8 = add i32 %sum1, 43
+  %sum2 = select i1 %7, i32 %sum1, i32 %8, !prof !15
+  %9 = load i32, i32* %i
+  %10 = icmp eq i32 %9, 0
+  br i1 %10, label %bb2, label %bb1, !prof !15
+
+bb1:
+  %sum3 = add i32 %sum2, 44
+  %11 = and i32 %0, 8
+  %12 = icmp eq i32 %11, 0
+  %13 = add i32 %sum3, 44
+  %sum4 = select i1 %12, i32 %sum3, i32 %13, !prof !15
+  br label %bb2
+
+bb2:
+  %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ]
+  br label %bb3
+
+bb3:
+  %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ]
+  ret i32 %sum6
+}
+
+; In the second CHR, a condition value depends on a trivial phi that's inserted
+; by the first CHR.
+; Roughly,
+; i0 = *i
+; v2 = (z != 1) ? pred : true  // Likely false
+; if (z == 0 & pred)  // Likely false
+;   foo()
+; j0 = *j
+; sum2 = ((i0 & 2) == j0) ? sum0 : (sum0 + 43) // Likely false
+; sum3 = ((i0 == j0) ? sum0 : (sum0 + 43) // Likely false
+; foo()
+; if ((i0 & 4) == 0) // Unbiased
+;   foo()
+; return i0 + sum3
+; ->
+; i0 = *i
+; if (z != 1 & (z == 0 & pred)) // First CHR
+;   foo()
+; // A trivial phi for i0 is inserted here by the first CHR (which gets removed
+; // later) and the subsequent branch condition (for the second CHR) uses it.
+; j0 = *j
+; if ((i0 & 2) != j0 & i0 != j0) {  // Second CHR
+;   sum3 = sum0 + 43
+;   foo()
+;   if (i0 & 4) == 0)
+;     foo()
+; } else {
+;   sum3 = (i0 == j0) ? sum0 : (sum0 + 43)
+;   foo()
+;   if (i0 & 4) == 0)
+;     foo()
+; }
+; return i0 + sum3
+define i32 @test_chr_14(i32* %i, i32* %j, i32 %sum0, i1 %pred, i32 %z) !prof !14 {
+; CHECK-LABEL: @test_chr_14(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[V1:%.*]] = icmp ne i32 [[Z:%.*]], 1
+; CHECK-NEXT:    [[V0:%.*]] = icmp eq i32 [[Z]], 0
+; CHECK-NEXT:    [[V3_NONCHR:%.*]] = and i1 [[V0]], [[PRED:%.*]]
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[V1]], [[V3_NONCHR]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[BB0_NONCHR:%.*]], label [[BB1:%.*]], !prof !19
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    [[V6:%.*]] = and i32 [[I0]], 2
+; CHECK-NEXT:    [[V4:%.*]] = icmp ne i32 [[V6]], [[J0]]
+; CHECK-NEXT:    [[V8:%.*]] = add i32 [[SUM0:%.*]], 43
+; CHECK-NEXT:    [[V5:%.*]] = icmp ne i32 [[I0]], [[J0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[V4]], [[V5]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB1_SPLIT:%.*]], label [[BB1_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb1.split:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[V9:%.*]] = and i32 [[I0]], 4
+; CHECK-NEXT:    [[V10:%.*]] = icmp eq i32 [[V9]], 0
+; CHECK-NEXT:    br i1 [[V10]], label [[BB3:%.*]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb1.split.nonchr:
+; CHECK-NEXT:    [[V5_NONCHR:%.*]] = icmp eq i32 [[I0]], [[J0]]
+; CHECK-NEXT:    [[SUM3_NONCHR:%.*]] = select i1 [[V5_NONCHR]], i32 [[SUM0]], i32 [[V8]], !prof !16
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[V9_NONCHR:%.*]] = and i32 [[I0]], 4
+; CHECK-NEXT:    [[V10_NONCHR:%.*]] = icmp eq i32 [[V9_NONCHR]], 0
+; CHECK-NEXT:    br i1 [[V10_NONCHR]], label [[BB3]], label [[BB2_NONCHR:%.*]]
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[V8]], [[BB2]] ], [ [[V8]], [[BB1_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB2_NONCHR]] ], [ [[SUM3_NONCHR]], [[BB1_SPLIT_NONCHR]] ]
+; CHECK-NEXT:    [[V11:%.*]] = add i32 [[I0]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[V11]]
+;
+entry:
+  %i0 = load i32, i32* %i
+  %v0 = icmp eq i32 %z, 0
+  %v1 = icmp ne i32 %z, 1
+  %v2 = select i1 %v1, i1 %pred, i1 true, !prof !15
+  %v3 = and i1 %v0, %pred
+  br i1 %v3, label %bb0, label %bb1, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %j0 = load i32, i32* %j
+  %v6 = and i32 %i0, 2
+  %v4 = icmp eq i32 %v6, %j0
+  %v8 = add i32 %sum0, 43
+  %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15
+  %v5 = icmp eq i32 %i0, %j0
+  %sum3 = select i1 %v5, i32 %sum0, i32 %v8, !prof !15
+  call void @foo()
+  %v9 = and i32 %i0, 4
+  %v10 = icmp eq i32 %v9, 0
+  br i1 %v10, label %bb3, label %bb2
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  %v11 = add i32 %i0, %sum3
+  ret i32 %v11
+}
+
+; Branch or selects depends on another select. No CHR happens.
+; Roughly,
+; i0 = *i
+; if (z == 0 & ((z != 1) ? pred : true)) { // Likely false
+;   foo()
+; j0 = *j
+; sum2 = ((i0 & 2) == j0) ? sum0 : (sum0 + 43) // Likely false
+; sum3 = (i0 == sum2) ? sum2 : (sum0 + 43) // Likely false. This depends on the
+;                                          // previous select.
+; foo()
+; if ((i0 & 4) == 0) // Unbiased
+;   foo()
+; return i0 + sum3
+; ->
+; (no change)
+define i32 @test_chr_15(i32* %i, i32* %j, i32 %sum0, i1 %pred, i32 %z) !prof !14 {
+; CHECK-LABEL: @test_chr_15(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[V0:%.*]] = icmp eq i32 [[Z:%.*]], 0
+; CHECK-NEXT:    [[V3:%.*]] = and i1 [[V0]], [[PRED:%.*]]
+; CHECK-NEXT:    br i1 [[V3]], label [[BB0:%.*]], label [[BB1:%.*]], !prof !16
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[J0:%.*]] = load i32, i32* [[J:%.*]], align 4
+; CHECK-NEXT:    [[V6:%.*]] = and i32 [[I0]], 2
+; CHECK-NEXT:    [[V4:%.*]] = icmp eq i32 [[V6]], [[J0]]
+; CHECK-NEXT:    [[V8:%.*]] = add i32 [[SUM0:%.*]], 43
+; CHECK-NEXT:    [[SUM2:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof !16
+; CHECK-NEXT:    [[V5:%.*]] = icmp eq i32 [[I0]], [[SUM2]]
+; CHECK-NEXT:    [[SUM3:%.*]] = select i1 [[V5]], i32 [[SUM2]], i32 [[V8]], !prof !16
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[V9:%.*]] = and i32 [[I0]], 4
+; CHECK-NEXT:    [[V10:%.*]] = icmp eq i32 [[V9]], 0
+; CHECK-NEXT:    br i1 [[V10]], label [[BB3:%.*]], label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[V11:%.*]] = add i32 [[I0]], [[SUM3]]
+; CHECK-NEXT:    ret i32 [[V11]]
+;
+entry:
+  %i0 = load i32, i32* %i
+  %v0 = icmp eq i32 %z, 0
+  %v1 = icmp ne i32 %z, 1
+  %v2 = select i1 %v1, i1 %pred, i1 true, !prof !15
+  %v3 = and i1 %v0, %v2
+  br i1 %v3, label %bb0, label %bb1, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %j0 = load i32, i32* %j
+  %v6 = and i32 %i0, 2
+  %v4 = icmp eq i32 %v6, %j0
+  %v8 = add i32 %sum0, 43
+  %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15
+  %v5 = icmp eq i32 %i0, %sum2
+  %sum3 = select i1 %v5, i32 %sum2, i32 %v8, !prof !15
+  call void @foo()
+  %v9 = and i32 %i0, 4
+  %v10 = icmp eq i32 %v9, 0
+  br i1 %v10, label %bb3, label %bb2
+
+bb2:
+  call void @foo()
+  br label %bb3
+
+bb3:
+  %v11 = add i32 %i0, %sum3
+  ret i32 %v11
+}
+
+; With an existing phi at the exit but a value (%v40) is both alive and is an
+; operand to a phi at the exit block.
+; Roughly,
+; t0 = *i
+; if ((t0 & 1) != 0) // Likely true
+;   foo()
+; v40 = t0 + 44
+; if ((t0 & 2) != 0) // Likely true
+;   v41 = t0 + 99
+;   foo()
+; }
+; v42 = phi v40, v41
+; return v42 + v40
+; ->
+; t0 = *i
+; if ((t0 & 3) == 3) // Likely true
+;   foo()
+;   v40 = t0 + 44
+;   v41 = t0 + 99
+;   foo()
+; } else {
+;   if ((t0 & 1) != 0) // Likely true
+;     foo()
+;   v40_nc = t0 + 44
+;   if ((t0 & 2) != 0) // Likely true
+;     v41_nc = t0 + 99
+;     foo()
+;   }
+; }
+; t7 = phi v40, v40_nc
+; v42 = phi v41, v41_nc
+; v43 = v42 + t7
+; return v43
+define i32 @test_chr_16(i32* %i) !prof !14 {
+; CHECK-LABEL: @test_chr_16(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 3
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[V40:%.*]] = add i32 [[TMP0]], 44
+; CHECK-NEXT:    [[V41:%.*]] = add i32 [[TMP0]], 99
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label [[BB1_NONCHR:%.*]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB1_NONCHR]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[V40_NONCHR:%.*]] = add i32 [[TMP0]], 44
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 2
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB2_NONCHR:%.*]], !prof !16
+; CHECK:       bb2.nonchr:
+; CHECK-NEXT:    [[V41_NONCHR:%.*]] = add i32 [[TMP0]], 99
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP7:%.*]] = phi i32 [ [[V40]], [[BB0]] ], [ [[V40_NONCHR]], [[BB2_NONCHR]] ], [ [[V40_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    [[V42:%.*]] = phi i32 [ [[V41]], [[BB0]] ], [ [[V41_NONCHR]], [[BB2_NONCHR]] ], [ [[V40_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    [[V43:%.*]] = add i32 [[V42]], [[TMP7]]
+; CHECK-NEXT:    ret i32 [[V43]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 1
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  br label %bb1
+
+bb1:
+  %v40 = add i32 %0, 44
+  %3 = and i32 %0, 2
+  %4 = icmp eq i32 %3, 0
+  br i1 %4, label %bb3, label %bb2, !prof !15
+
+bb2:
+  %v41 = add i32 %0, 99
+  call void @foo()
+  br label %bb3
+
+bb3:
+  %v42 = phi i32 [ %v41, %bb2 ], [ %v40, %bb1 ]
+  %v43 = add i32 %v42, %v40
+  ret i32 %v43
+}
+
+; Two consecutive regions have an entry in the middle of them. No CHR happens.
+; Roughly,
+; if ((i & 4) == 0) {
+;   if (!j)
+;     goto bb1
+; } else {
+;   t0 = (i & 1)
+;   if (t0 != 0) // Likely true
+;     foo()
+;     s = (i & 1) + i
+;   }
+;  bb1:
+;   p = phi i, t0, s
+;   if ((i & 2) != 0) // Likely true
+;     foo()
+;     q = p + 2
+; }
+; r = phi p, q, i
+; return r
+; ->
+; (no change)
+define i32 @test_chr_17(i32 %i, i1 %j) !prof !14 {
+; CHECK-LABEL: @test_chr_17(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[V0:%.*]] = and i32 [[I:%.*]], 4
+; CHECK-NEXT:    [[V1:%.*]] = icmp eq i32 [[V0]], 0
+; CHECK-NEXT:    br i1 [[V1]], label [[BBE:%.*]], label [[BBQ:%.*]]
+; CHECK:       bbq:
+; CHECK-NEXT:    br i1 [[J:%.*]], label [[BB3:%.*]], label [[BB1:%.*]]
+; CHECK:       bbe:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[I]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB1]], label [[BB0:%.*]], !prof !16
+; CHECK:       bb0:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[S:%.*]] = add i32 [[TMP0]], [[I]]
+; CHECK-NEXT:    br label [[BB1]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[I]], [[BBQ]] ], [ [[TMP0]], [[BBE]] ], [ [[S]], [[BB0]] ]
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[I]], 2
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0
+; CHECK-NEXT:    br i1 [[TMP3]], label [[BB3]], label [[BB2:%.*]], !prof !16
+; CHECK:       bb2:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    [[Q:%.*]] = add i32 [[P]], [[TMP2]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[P]], [[BB1]] ], [ [[Q]], [[BB2]] ], [ [[I]], [[BBQ]] ]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+entry:
+  %v0 = and i32 %i, 4
+  %v1 = icmp eq i32 %v0, 0
+  br i1 %v1, label %bbe, label %bbq
+
+bbq:
+  br i1 %j, label %bb3, label %bb1
+
+bbe:
+  %0 = and i32 %i, 1
+  %1 = icmp eq i32 %0, 0
+  br i1 %1, label %bb1, label %bb0, !prof !15
+
+bb0:
+  call void @foo()
+  %s = add i32 %0, %i
+  br label %bb1
+
+bb1:
+  %p = phi i32 [ %i, %bbq ], [ %0, %bbe ], [ %s, %bb0 ]
+  %2 = and i32 %i, 2
+  %3 = icmp eq i32 %2, 0
+  br i1 %3, label %bb3, label %bb2, !prof !15
+
+bb2:
+  call void @foo()
+  %q = add i32 %p, %2
+  br label %bb3
+
+bb3:
+  %r = phi i32 [ %p, %bb1 ], [ %q, %bb2 ], [ %i, %bbq ]
+  ret i32 %r
+}
+
+; Select + br, there's a loop and we need to update the user of an inserted phi
+; at the entry block. This is a regression test for a bug that's fixed.
+; Roughly,
+; do {
+;   inc1 = phi inc2, 0
+;   li = *i
+;   sum1 = sum0 + 42
+;   sum2 = ((li & 1) == 0) ? sum0 : sum1  // Likely false
+;   inc2 = inc1 + 1
+;   if ((li & 4) != 0) // Likely true
+;     sum3 = sum2 + 44
+;   sum4 = phi sum1, sum3
+; } while (inc2 != 100)  // Likely true (loop back)
+; return sum4
+; ->
+; do {
+;   inc1 = phi tmp2, 0  // The first operand needed to be updated
+;   li = *i
+;   sum1 = sum0 + 42
+;   if ((li & 5) == 5) { // Likely true
+;     inc2 = inc1 + 1
+;     sum3 = sum0 + 86
+;   } else {
+;     inc2_nc = inc1 + 1
+;     if ((li & 4) == 0)
+;       sum2_nc = ((li & 1) == 0) ? sum0 : sum1
+;       sum3_nc = sum2_nc + 44
+;     }
+;   tmp2 = phi inc2, in2c_nc
+;   sum4 = phi sum3, sum3_nc, sum1
+; } while (tmp2 != 100)
+; return sum4
+define i32 @test_chr_18(i32* %i, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_18(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[BB0:%.*]]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[INC1:%.*]] = phi i32 [ [[TMP2:%.*]], [[BB2:%.*]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[LI:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[SUM1:%.*]] = add i32 [[SUM0:%.*]], 42
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[LI]], 5
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 5
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB0_SPLIT:%.*]], label [[BB0_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0.split:
+; CHECK-NEXT:    [[INC2:%.*]] = add i32 [[INC1]], 1
+; CHECK-NEXT:    [[SUM3:%.*]] = add i32 [[SUM0]], 86
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb0.split.nonchr:
+; CHECK-NEXT:    [[A4_NONCHR:%.*]] = and i32 [[LI]], 4
+; CHECK-NEXT:    [[CMP4_NONCHR:%.*]] = icmp eq i32 [[A4_NONCHR]], 0
+; CHECK-NEXT:    [[INC2_NONCHR:%.*]] = add i32 [[INC1]], 1
+; CHECK-NEXT:    br i1 [[CMP4_NONCHR]], label [[BB2]], label [[BB1_NONCHR:%.*]], !prof !16
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[A1:%.*]] = and i32 [[LI]], 1
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A1]], 0
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[CMP1]], i32 [[SUM0]], i32 [[SUM1]], !prof !16
+; CHECK-NEXT:    [[SUM3_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], 44
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP2]] = phi i32 [ [[INC2]], [[BB0_SPLIT]] ], [ [[INC2_NONCHR]], [[BB1_NONCHR]] ], [ [[INC2_NONCHR]], [[BB0_SPLIT_NONCHR]] ]
+; CHECK-NEXT:    [[SUM4:%.*]] = phi i32 [ [[SUM3]], [[BB0_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB1_NONCHR]] ], [ [[SUM1]], [[BB0_SPLIT_NONCHR]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP2]], 100
+; CHECK-NEXT:    br i1 [[CMP]], label [[BB3:%.*]], label [[BB0]], !prof !16
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i32 [[SUM4]]
+;
+entry:
+  br label %bb0
+
+bb0:
+  %inc1 = phi i32 [ %inc2, %bb2 ], [ 0, %entry ]
+  %li = load i32, i32* %i
+  %a1 = and i32 %li, 1
+  %cmp1 = icmp eq i32 %a1, 0
+  %sum1 = add i32 %sum0, 42
+  %sum2 = select i1 %cmp1, i32 %sum0, i32 %sum1, !prof !15
+  %a4 = and i32 %li, 4
+  %cmp4 = icmp eq i32 %a4, 0
+  %inc2 = add i32 %inc1, 1
+  br i1 %cmp4, label %bb2, label %bb1, !prof !15
+
+bb1:
+  %sum3 = add i32 %sum2, 44
+  br label %bb2
+
+bb2:
+  %sum4 = phi i32 [ %sum1, %bb0 ], [ %sum3, %bb1 ]
+  %cmp = icmp eq i32 %inc2, 100
+  br i1 %cmp, label %bb3, label %bb0, !prof !15
+
+bb3:
+  ret i32 %sum4
+}
+
+
+; Selects + Brs. Those share the condition value, which causes the
+; targets/operands of the branch/select to be flipped.
+; Roughly,
+; t0 = *i
+; if ((t0 & 255) != 0) {  // Likely true
+;   sum1 = ((t0 & 1) == 0) ? sum0 : (sum0 + 42)  // Likely false
+;   sum2 = ((t0 & 1) == 0) ? sum1 : (sum1 + 42)  // Likely false
+;   if ((t0 & 1) != 0) { // Likely true
+;     sum3 = sum2 + 44
+;     sum4 = ((t0 & 8) == 0) ? sum3 : (sum3 + 44) // Likely false
+;   }
+;   sum5 = phi sum2, sum4
+; }
+; sum6 = phi sum0, sum5
+; return sum6
+; ->
+; t0 = *i
+; if ((t0 & 9) == 9) { // Likely true
+;   tmp3 = sum0 + 85  // Dead
+;   tmp4 = sum0 + 173
+; } else {
+;   if ((t0 & 255) != 0) {
+;     sum2_nc = ((t0 & 1) == 0) ? sum0 : (sum0 + 85)
+;     sum4_nc_v = ((t0 & 8) == 0) ? 44 : 88
+;     sum4_nc = add sum2_nc + sum4_nc_v
+;   }
+; }
+; sum6 = phi tmp4, sum0, sum2_nc, sum4_nc
+; return sum6
+define i32 @test_chr_19(i32* %i, i32 %sum0) !prof !14 {
+; CHECK-LABEL: @test_chr_19(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[TMP0]], 9
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 9
+; CHECK-NEXT:    br i1 [[TMP2]], label [[BB0:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       bb0:
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85
+; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[SUM0]], 173
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0]], 255
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB3]], label [[BB0_NONCHR:%.*]], !prof !16
+; CHECK:       bb0.nonchr:
+; CHECK-NEXT:    [[TMP7:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    [[TMP9:%.*]] = add i32 [[SUM0]], 85
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[TMP8]], i32 [[SUM0]], i32 [[TMP9]], !prof !16
+; CHECK-NEXT:    br i1 [[TMP8]], label [[BB3]], label [[BB1_NONCHR:%.*]], !prof !16
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    [[TMP10:%.*]] = and i32 [[TMP0]], 8
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT:    [[SUM4_NONCHR_V:%.*]] = select i1 [[TMP11]], i32 44, i32 88, !prof !16
+; CHECK-NEXT:    [[SUM4_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], [[SUM4_NONCHR_V]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[SUM6:%.*]] = phi i32 [ [[TMP4]], [[BB0]] ], [ [[SUM0]], [[ENTRY_SPLIT_NONCHR]] ], [ [[SUM2_NONCHR]], [[BB0_NONCHR]] ], [ [[SUM4_NONCHR]], [[BB1_NONCHR]] ]
+; CHECK-NEXT:    ret i32 [[SUM6]]
+;
+entry:
+  %0 = load i32, i32* %i
+  %1 = and i32 %0, 255
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %bb3, label %bb0, !prof !15
+
+bb0:
+  %3 = and i32 %0, 1
+  %4 = icmp eq i32 %3, 0
+  %5 = add i32 %sum0, 42
+  %sum1 = select i1 %4, i32 %sum0, i32 %5, !prof !15
+  %6 = add i32 %sum1, 43
+  %sum2 = select i1 %4, i32 %sum1, i32 %6, !prof !15
+  br i1 %4, label %bb2, label %bb1, !prof !15
+
+bb1:
+  %sum3 = add i32 %sum2, 44
+  %7 = and i32 %0, 8
+  %8 = icmp eq i32 %7, 0
+  %9 = add i32 %sum3, 44
+  %sum4 = select i1 %8, i32 %sum3, i32 %9, !prof !15
+  br label %bb2
+
+bb2:
+  %sum5 = phi i32 [ %sum2, %bb0 ], [ %sum4, %bb1 ]
+  br label %bb3
+
+bb3:
+  %sum6 = phi i32 [ %sum0, %entry ], [ %sum5, %bb2 ]
+  ret i32 %sum6
+}
+
+; Selects. The exit block, which belongs to the top-level region, has a select
+; and causes the top-level region to be the outermost CHR scope with the
+; subscope that includes the entry block with two selects. The outermost CHR
+; scope doesn't see the selects in the entry block as the entry block is in the
+; subscope and incorrectly sets the CHR hoist point to the branch rather than
+; the first select in the entry block and causes the CHR'ed selects ("select i1
+; false...") to incorrectly position above the CHR branch. This is testing
+; against a quirk of how the region analysis handles the entry block.
+; Roughly,
+; i0 = *i
+; sum2 = ((i0 & 2) == 0) ? sum0 : (sum0 + 43) // Likely false
+; sum3 = ((i0 & 4) == 0) ? sum2 : (sum2 + 44) // Likely false
+; if (j)
+;   foo()
+; i5 = *i
+; v13 = (i5 == 44) ? i5 : sum3
+; return v13
+; ->
+; i0 = *i
+; if ((i0 & 6) != 6) { // Likely true
+;   v9 = sum0 + 87
+;   if (j)
+;     foo()
+; } else {
+;   sum2.nc = ((i0 & 2) == 0) ? sum0 : (sum0 + 43)
+;   sum3.nc = ((i0 & 4) == 0) ? sum2.nc : (sum2.nc + 44)
+;   if (j)
+;     foo()
+; }
+; t2 = phi v9, sum3.nc
+; i5 = *i
+; v13 = (i5 == 44) ? 44 : t2
+; return v13
+define i32 @test_chr_20(i32* %i, i32 %sum0, i1 %j) !prof !14 {
+; CHECK-LABEL: @test_chr_20(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[I0:%.*]] = load i32, i32* [[I:%.*]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[I0]], 6
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 6
+; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof !15
+; CHECK:       entry.split:
+; CHECK-NEXT:    [[V9:%.*]] = add i32 [[SUM0:%.*]], 87
+; CHECK-NEXT:    br i1 [[J:%.*]], label [[BB1:%.*]], label [[BB4:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       entry.split.nonchr:
+; CHECK-NEXT:    [[V8:%.*]] = add i32 [[SUM0]], 43
+; CHECK-NEXT:    [[V3:%.*]] = and i32 [[I0]], 2
+; CHECK-NEXT:    [[V4:%.*]] = icmp eq i32 [[V3]], 0
+; CHECK-NEXT:    [[SUM2_NONCHR:%.*]] = select i1 [[V4]], i32 [[SUM0]], i32 [[V8]], !prof !16
+; CHECK-NEXT:    [[V6_NONCHR:%.*]] = and i32 [[I0]], 4
+; CHECK-NEXT:    [[V5_NONCHR:%.*]] = icmp eq i32 [[V6_NONCHR]], 0
+; CHECK-NEXT:    [[V9_NONCHR:%.*]] = add i32 [[SUM2_NONCHR]], 44
+; CHECK-NEXT:    [[SUM3_NONCHR:%.*]] = select i1 [[V5_NONCHR]], i32 [[SUM2_NONCHR]], i32 [[V9_NONCHR]], !prof !16
+; CHECK-NEXT:    br i1 [[J]], label [[BB1_NONCHR:%.*]], label [[BB4]]
+; CHECK:       bb1.nonchr:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb4:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i32 [ [[V9]], [[BB1]] ], [ [[V9]], [[ENTRY_SPLIT]] ], [ [[SUM3_NONCHR]], [[BB1_NONCHR]] ], [ [[SUM3_NONCHR]], [[ENTRY_SPLIT_NONCHR]] ]
+; CHECK-NEXT:    [[I5:%.*]] = load i32, i32* [[I]], align 4
+; CHECK-NEXT:    [[V12:%.*]] = icmp eq i32 [[I5]], 44
+; CHECK-NEXT:    [[V13:%.*]] = select i1 [[V12]], i32 44, i32 [[TMP2]], !prof !16
+; CHECK-NEXT:    ret i32 [[V13]]
+;
+entry:
+  %i0 = load i32, i32* %i
+  %v3 = and i32 %i0, 2
+  %v4 = icmp eq i32 %v3, 0
+  %v8 = add i32 %sum0, 43
+  %sum2 = select i1 %v4, i32 %sum0, i32 %v8, !prof !15
+  %v6 = and i32 %i0, 4
+  %v5 = icmp eq i32 %v6, 0
+  %v9 = add i32 %sum2, 44
+  %sum3 = select i1 %v5, i32 %sum2, i32 %v9, !prof !15
+  br i1 %j, label %bb1, label %bb4
+
+bb1:
+  call void @foo()
+  br label %bb4
+
+bb4:
+  %i5 = load i32, i32* %i
+  %v12 = icmp eq i32 %i5, 44
+  %v13 = select i1 %v12, i32 %i5, i32 %sum3, !prof !15
+  ret i32 %v13
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 10000}
+!4 = !{!"MaxCount", i64 10}
+!5 = !{!"MaxInternalCount", i64 1}
+!6 = !{!"MaxFunctionCount", i64 1000}
+!7 = !{!"NumCounts", i64 3}
+!8 = !{!"NumFunctions", i64 3}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11, !12, !13}
+!11 = !{i32 10000, i64 100, i32 1}
+!12 = !{i32 999000, i64 100, i32 1}
+!13 = !{i32 999999, i64 1, i32 2}
+
+!14 = !{!"function_entry_count", i64 100}
+!15 = !{!"branch_weights", i32 0, i32 1}
+!16 = !{!"branch_weights", i32 1, i32 1}
+; CHECK: !15 = !{!"branch_weights", i32 1000, i32 0}
+; CHECK: !16 = !{!"branch_weights", i32 0, i32 1}
+; CHECK: !17 = !{!"branch_weights", i32 1, i32 1}
+; CHECK: !18 = !{!"branch_weights", i32 1, i32 0}
+; CHECK: !19 = !{!"branch_weights", i32 0, i32 1000}

Added: llvm/trunk/test/Transforms/PGOProfile/comdat_internal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/comdat_internal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/comdat_internal.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/comdat_internal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -pgo-instr-gen -instrprof -S | FileCheck %s
+; RUN: opt < %s -passes=pgo-instr-gen,instrprof -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$foo = comdat any
+; CHECK: $foo = comdat any
+
+; CHECK: $__llvm_profile_raw_version = comdat any
+; CHECK: $__profv__stdin__foo.[[FOO_HASH:[0-9]+]] = comdat any
+
+ at bar = global i32 ()* @foo, align 8
+
+; CHECK: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; CHECK-NOT: __profn__stdin__foo
+; CHECK: @__profc__stdin__foo.[[FOO_HASH]] = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat($__profv__stdin__foo.[[FOO_HASH]]), align 8
+; CHECK: @__profd__stdin__foo.[[FOO_HASH]] = private global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 -5640069336071256030, i64 [[FOO_HASH]], i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__stdin__foo.[[FOO_HASH]], i32 0, i32 0), i8* null
+; CHECK-NOT: bitcast (i32 ()* @foo to i8*)
+; CHECK-SAME: , i8* null, i32 1, [2 x i16] zeroinitializer }, section "__llvm_prf_data", comdat($__profv__stdin__foo.[[FOO_HASH]]), align 8
+; CHECK: @__llvm_prf_nm
+; CHECK: @llvm.used
+
+define internal i32 @foo() comdat {
+entry:
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/PGOProfile/comdat_rename.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/comdat_rename.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/comdat_rename.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/comdat_rename.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt < %s -mtriple=x86_64-unknown-linux -pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s
+; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s
+; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s
+; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s
+
+; Rename Comdat group and its function.
+$f = comdat any
+; CHECK: $f.[[SINGLEBB_HASH:[0-9]+]] = comdat any
+define linkonce_odr void @f() comdat($f) {
+  ret void
+}
+
+; Not rename Comdat with right linkage.
+$nf = comdat any
+; CHECK: $nf = comdat any
+define void @nf() comdat($nf) {
+  ret void
+}
+
+; Not rename Comdat with variable members.
+$f_with_var = comdat any
+; CHECK: $f_with_var = comdat any
+ at var = global i32 0, comdat($f_with_var)
+define linkonce_odr void @f_with_var() comdat($f_with_var) {
+  %tmp = load i32, i32* @var, align 4
+  %inc = add nsw i32 %tmp, 1
+  store i32 %inc, i32* @var, align 4
+  ret void
+}
+
+; Not rename Comdat with multiple functions.
+$tf = comdat any
+; CHECK: $tf = comdat any
+define linkonce void @tf() comdat($tf) {
+  ret void
+}
+define linkonce void @tf2() comdat($tf) {
+  ret void
+}
+
+; Rename AvailableExternallyLinkage functions
+; CHECK-DAG: $aef.[[SINGLEBB_HASH]] = comdat any
+
+; CHECK: @f = weak alias void (), void ()* @f.[[SINGLEBB_HASH]]
+; CHECK: @aef = weak alias void (), void ()* @aef.[[SINGLEBB_HASH]]
+
+define available_externally void @aef() {
+; CHECK: define linkonce_odr void @aef.[[SINGLEBB_HASH]]() comdat {
+  ret void
+}
+
+

Added: llvm/trunk/test/Transforms/PGOProfile/counter_promo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/counter_promo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/counter_promo.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/counter_promo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt < %s -pgo-instr-gen -instrprof -do-counter-promotion=true -S | FileCheck --check-prefix=PROMO --check-prefix=NONATOMIC_PROMO %s
+; RUN: opt < %s --passes=pgo-instr-gen,instrprof -do-counter-promotion=true -S | FileCheck --check-prefix=PROMO --check-prefix=NONATOMIC_PROMO %s 
+; RUN: opt < %s -pgo-instr-gen -instrprof -do-counter-promotion=true -atomic-counter-update-promoted -S | FileCheck --check-prefix=PROMO --check-prefix=ATOMIC_PROMO %s
+; RUN: opt < %s --passes=pgo-instr-gen,instrprof -do-counter-promotion=true -atomic-counter-update-promoted -S | FileCheck --check-prefix=PROMO --check-prefix=ATOMIC_PROMO %s 
+
+define void @foo(i32 %n, i32 %N) {
+; PROMO-LABEL: @foo
+; PROMO: {{.*}} = load {{.*}} @__profc_foo{{.*}} 3)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}3)
+bb:
+  %tmp = add nsw i32 %n, 1
+  %tmp1 = add nsw i32 %n, -1
+  br label %bb2
+
+bb2:                                              ; preds = %bb9, %bb
+; PROMO: phi {{.*}}
+; PROMO-NEXT: phi {{.*}}
+; PROMO-NEXT: phi {{.*}}
+; PROMO-NEXT: phi {{.*}}
+  %i.0 = phi i32 [ 0, %bb ], [ %tmp10, %bb9 ]
+  %tmp3 = icmp slt i32 %i.0, %tmp
+  br i1 %tmp3, label %bb4, label %bb5
+
+bb4:                                              ; preds = %bb2
+  tail call void @bar(i32 1)
+  br label %bb9
+
+bb5:                                              ; preds = %bb2
+  %tmp6 = icmp slt i32 %i.0, %tmp1
+  br i1 %tmp6, label %bb7, label %bb8
+
+bb7:                                              ; preds = %bb5
+  tail call void @bar(i32 2)
+  br label %bb9
+
+bb8:                                              ; preds = %bb5
+  tail call void @bar(i32 3)
+  br label %bb9
+
+bb9:                                              ; preds = %bb8, %bb7, %bb4
+; PROMO: %[[LIVEOUT3:[a-z0-9]+]] = phi {{.*}}
+; PROMO-NEXT: %[[LIVEOUT2:[a-z0-9]+]] = phi {{.*}}
+; PROMO-NEXT: %[[LIVEOUT1:[a-z0-9]+]] = phi {{.*}}
+  %tmp10 = add nsw i32 %i.0, 1
+  %tmp11 = icmp slt i32 %tmp10, %N
+  br i1 %tmp11, label %bb2, label %bb12
+
+bb12:                                             ; preds = %bb9
+  ret void
+; NONATOMIC_PROMO: %[[PROMO1:[a-z0-9.]+]] = load {{.*}} @__profc_foo{{.*}} 0)
+; NONATOMIC_PROMO-NEXT: add {{.*}} %[[PROMO1]], %[[LIVEOUT1]] 
+; NONATOMIC_PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}0)
+; NONATOMIC_PROMO-NEXT: %[[PROMO2:[a-z0-9.]+]] = load {{.*}} @__profc_foo{{.*}} 1)
+; NONATOMIC_PROMO-NEXT: add {{.*}} %[[PROMO2]], %[[LIVEOUT2]]
+; NONATOMIC_PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}1)
+; NONATOMIC_PROMO-NEXT: %[[PROMO3:[a-z0-9.]+]] = load {{.*}} @__profc_foo{{.*}} 2)
+; NONATOMIC_PROMO-NEXT: add {{.*}} %[[PROMO3]], %[[LIVEOUT3]]
+; NONATOMIC_PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}2)
+; ATOMIC_PROMO: atomicrmw add {{.*}} @__profc_foo{{.*}}0), i64 %[[LIVEOUT1]] seq_cst
+; ATOMIC_PROMO-NEXT: atomicrmw add {{.*}} @__profc_foo{{.*}}1), i64 %[[LIVEOUT2]] seq_cst
+; ATOMIC_PROMO-NEXT: atomicrmw add {{.*}} @__profc_foo{{.*}}2), i64 %[[LIVEOUT3]] seq_cst
+; PROMO-NOT: @__profc_foo
+
+
+}
+
+declare void @bar(i32)

Added: llvm/trunk/test/Transforms/PGOProfile/counter_promo_exit_merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/counter_promo_exit_merge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/counter_promo_exit_merge.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/counter_promo_exit_merge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; RUN: opt < %s -instrprof -do-counter-promotion=true -speculative-counter-promotion-max-exiting=3 -S | FileCheck --check-prefix=PROMO %s
+; RUN: opt < %s --passes=instrprof -do-counter-promotion=true -speculative-counter-promotion-max-exiting=3 -S | FileCheck --check-prefix=PROMO %s
+
+$__llvm_profile_raw_version = comdat any
+
+ at g = common local_unnamed_addr global i32 0, align 4
+ at __llvm_profile_raw_version = constant i64 72057594037927940, comdat
+ at __profn_foo = private constant [3 x i8] c"foo"
+
+define void @foo(i32 %arg) local_unnamed_addr {
+bb:
+  %tmp = add nsw i32 %arg, -1
+  br label %bb1
+
+bb1:                                              ; preds = %bb11, %bb
+  %tmp2 = phi i32 [ 0, %bb ], [ %tmp12, %bb11 ]
+  %tmp3 = icmp sgt i32 %tmp2, %arg
+  br i1 %tmp3, label %bb7, label %bb4
+
+bb4:                                              ; preds = %bb1
+  call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 63969943867, i32 5, i32 1)
+  tail call void @bar(i32 1)
+  %tmp5 = load i32, i32* @g, align 4
+  %tmp6 = icmp sgt i32 %tmp5, 100
+  br i1 %tmp6, label %bb14, label %bb11
+
+bb7:                                              ; preds = %bb1
+  %tmp8 = icmp slt i32 %tmp2, %tmp
+  br i1 %tmp8, label %bb9, label %bb10
+
+bb9:                                              ; preds = %bb7
+  call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 63969943867, i32 5, i32 2)
+  tail call void @bar(i32 2)
+  br label %bb11
+
+bb10:                                             ; preds = %bb7
+  call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 63969943867, i32 5, i32 3)
+  tail call void @bar(i32 3)
+  br label %bb11
+
+bb11:                                             ; preds = %bb10, %bb9, %bb4
+  %tmp12 = add nuw nsw i32 %tmp2, 1
+  %tmp13 = icmp slt i32 %tmp2, 99
+  br i1 %tmp13, label %bb1, label %bb14
+
+bb14:                                             ; preds = %bb4.bb14_crit_edge, %bb11
+  tail call void @bar(i32 0)
+  br label %bb15
+; PROMO-LABEL: bb14:
+; PROMO: %[[MERGE1:[a-z0-9]+]] = phi {{.*}}
+; PROMO-NEXT: %[[MERGE2:[a-z0-9.]+]] = phi {{.*}}
+; PROMO-NEXT: %[[MERGE3:[a-z0-9.]+]] = phi {{.*}}
+; PROMO-NEXT: %[[PROMO3:[a-z0-9.]+]] = load{{.*}}@__profc_foo{{.*}}1)
+; PROMO-NEXT: {{.*}} = add {{.*}}%[[PROMO3]], %[[MERGE3]]
+; PROMO-NEXT: store{{.*}}@__profc_foo{{.*}}1)
+; PROMO-NEXT: %[[PROMO2:[a-z0-9.]+]] = load{{.*}}@__profc_foo{{.*}}2)
+; PROMO-NEXT: {{.*}} = add {{.*}}%[[PROMO2]], %[[MERGE2]]
+; PROMO-NEXT: store{{.*}}@__profc_foo{{.*}}2)
+; PROMO-NEXT: %[[PROMO1:[a-z0-9.]+]] = load{{.*}}@__profc_foo{{.*}}3)
+; PROMO-NEXT: {{.*}} = add {{.*}}%[[PROMO1]], %[[MERGE1]]
+; PROMO-NEXT: store{{.*}}@__profc_foo{{.*}}3)
+
+bb15:                                             ; preds = %bb14
+  call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 63969943867, i32 5, i32 4)
+  tail call void @bar(i32 1)
+  ret void
+}
+
+declare void @bar(i32) local_unnamed_addr
+
+; Function Attrs: nounwind
+declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #0
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/PGOProfile/counter_promo_mexits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/counter_promo_mexits.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/counter_promo_mexits.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/counter_promo_mexits.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,80 @@
+; RUN: opt < %s -pgo-instr-gen -instrprof -do-counter-promotion=true -speculative-counter-promotion-max-exiting=3 -S | FileCheck --check-prefix=PROMO %s
+; RUN: opt < %s --passes=pgo-instr-gen,instrprof -do-counter-promotion=true -speculative-counter-promotion-max-exiting=3 -S | FileCheck --check-prefix=PROMO %s
+
+ at g = common local_unnamed_addr global i32 0, align 4
+
+define void @foo(i32 %arg) local_unnamed_addr {
+; PROMO-LABEL: @foo
+bb:
+  %tmp = add nsw i32 %arg, -1
+  br label %bb1
+bb1:                                              ; preds = %bb11, %bb
+  %tmp2 = phi i32 [ 0, %bb ], [ %tmp12, %bb11 ]
+  %tmp3 = icmp sgt i32 %tmp2, %arg
+  br i1 %tmp3, label %bb7, label %bb4
+
+bb4:                                              ; preds = %bb1
+  tail call void @bar(i32 1)
+  %tmp5 = load i32, i32* @g, align 4
+  %tmp6 = icmp sgt i32 %tmp5, 100
+  br i1 %tmp6, label %bb15_0, label %bb11
+
+bb7:                                              ; preds = %bb1
+  %tmp8 = icmp slt i32 %tmp2, %tmp
+  br i1 %tmp8, label %bb9, label %bb10
+
+bb9:                                              ; preds = %bb7
+  tail call void @bar(i32 2)
+  br label %bb11
+
+bb10:                                             ; preds = %bb7
+  tail call void @bar(i32 3)
+  br label %bb11
+
+bb11:                                             ; preds = %bb10, %bb9, %bb4
+  %tmp12 = add nuw nsw i32 %tmp2, 1
+  %tmp13 = icmp slt i32 %tmp2, 99
+  br i1 %tmp13, label %bb1, label %bb14
+
+bb14:                                             ; preds = %bb11
+; PROMO-LABEL: bb14:
+  tail call void @bar(i32 0)
+  br label %bb15
+; PROMO:  %pgocount.promoted{{.*}} = load {{.*}} @__profc_foo{{.*}} 0)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}0)
+; PROMO-NEXT:  %pgocount.promoted{{.*}} = load {{.*}} @__profc_foo{{.*}} 1)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}1)
+; PROMO-NEXT:  %pgocount.promoted{{.*}} = load {{.*}} @__profc_foo{{.*}} 2)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}2)
+; PROMO-NEXT:  %pgocount{{.*}} = load {{.*}} @__profc_foo{{.*}} 3)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}3)
+
+
+bb15_0:                                             ; preds = %bb11
+; PROMO-LABEL: bb15_0:
+  br label %bb15
+; PROMO:  %pgocount.promoted{{.*}} = load {{.*}} @__profc_foo{{.*}} 0)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}0)
+; PROMO-NEXT:  %pgocount.promoted{{.*}} = load {{.*}} @__profc_foo{{.*}} 1)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}1)
+; PROMO-NEXT:  %pgocount.promoted{{.*}} = load {{.*}} @__profc_foo{{.*}} 2)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}2)
+; PROMO-NEXT:  %pgocount{{.*}} = load {{.*}} @__profc_foo{{.*}} 4)
+; PROMO-NEXT: add 
+; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}4)
+; PROMO-NOT: @__profc_foo
+
+
+bb15:                                             ; preds = %bb14, %bb4
+  tail call void @bar(i32 1)
+  ret void
+}
+
+declare void @bar(i32) local_unnamed_addr

Added: llvm/trunk/test/Transforms/PGOProfile/counter_promo_nest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/counter_promo_nest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/counter_promo_nest.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/counter_promo_nest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,165 @@
+; TEST that counter updates are promoted outside the whole loop nest
+; RUN: opt < %s -pgo-instr-gen -instrprof -do-counter-promotion=true -S | FileCheck --check-prefix=PROMO  %s
+; RUN: opt < %s --passes=pgo-instr-gen,instrprof -do-counter-promotion=true -S | FileCheck --check-prefix=PROMO  %s 
+
+ at g = common local_unnamed_addr global i32 0, align 4
+ at c = local_unnamed_addr global i32 10, align 4
+
+; Function Attrs: noinline norecurse nounwind uwtable
+define void @bar() local_unnamed_addr #0 {
+bb:
+  %tmp2 = load i32, i32* @g, align 4, !tbaa !2
+  %tmp3 = add nsw i32 %tmp2, 1
+  store i32 %tmp3, i32* @g, align 4, !tbaa !2
+  ret void
+}
+
+; Function Attrs: norecurse nounwind uwtable
+define i32 @main() local_unnamed_addr #1 {
+bb:
+  store i32 0, i32* @g, align 4, !tbaa !2
+  %tmp = load i32, i32* @c, align 4, !tbaa !2
+  %tmp1 = icmp sgt i32 %tmp, 0
+  br i1 %tmp1, label %bb2_1, label %bb84
+
+bb2_1:
+  br label %bb2
+
+bb2:                                              ; preds = %bb39, %bb
+  %tmp3 = phi i32 [ %tmp40, %bb39 ], [ %tmp, %bb2_1 ]
+  %tmp5 = phi i32 [ %tmp43, %bb39 ], [ 0, %bb2_1 ]
+  %tmp7 = icmp sgt i32 %tmp3, 0
+  br i1 %tmp7, label %bb14_1, label %bb39
+
+bb8:                                              ; preds = %bb39
+; PROMO-LABEL: bb8
+; PROMO: load {{.*}} @__profc_main{{.*}}
+; PROMO-NEXT: add
+; PROMO-NEXT: store {{.*}}@__profc_main{{.*}}
+; PROMO-NEXT: load {{.*}} @__profc_main{{.*}}
+; PROMO-NEXT: add
+; PROMO-NEXT: store {{.*}}@__profc_main{{.*}}
+; PROMO-NEXT: load {{.*}} @__profc_main{{.*}}
+; PROMO-NEXT: add
+; PROMO-NEXT: store {{.*}}@__profc_main{{.*}}
+; PROMO-NEXT: load {{.*}} @__profc_main{{.*}}
+; PROMO-NEXT: add
+; PROMO-NEXT: store {{.*}}@__profc_main{{.*}}
+; PROMO-NEXT: load {{.*}} @__profc_main{{.*}}
+; PROMO-NEXT: add
+; PROMO-NEXT: store {{.*}}@__profc_main{{.*}}
+
+  %tmp13 = icmp sgt i32 %tmp40, 0
+  br i1 %tmp13, label %bb45, label %bb84
+
+bb14_1:
+  br label %bb14
+
+bb14:                                             ; preds = %bb29, %bb2
+  %tmp15 = phi i32 [ %tmp30, %bb29 ], [ %tmp3, %bb14_1 ]
+  %tmp16 = phi i64 [ %tmp31, %bb29 ], [ 0, %bb14_1 ]
+  %tmp17 = phi i64 [ %tmp32, %bb29 ], [ 0, %bb14_1 ]
+  %tmp18 = phi i32 [ %tmp33, %bb29 ], [ 0, %bb14_1 ]
+  %tmp19 = icmp sgt i32 %tmp15, 0
+  br i1 %tmp19, label %bb20_split, label %bb29
+
+bb20_split:                                             
+ br label %bb20
+
+bb20:                                             ; preds = %bb20, %bb14
+  %tmp21 = phi i64 [ %tmp23, %bb20 ], [ 0, %bb20_split ]
+  %tmp22 = phi i32 [ %tmp24, %bb20 ], [ 0, %bb20_split ]
+  %tmp23 = add nuw i64 %tmp21, 1
+  tail call void @bar()
+  %tmp24 = add nuw nsw i32 %tmp22, 1
+  %tmp25 = load i32, i32* @c, align 4, !tbaa !2
+  %tmp26 = icmp slt i32 %tmp24, %tmp25
+  br i1 %tmp26, label %bb20, label %bb27
+
+bb27:                                             ; preds = %bb20
+  %tmp28 = add i64 %tmp23, %tmp16
+  br label %bb29
+
+bb29:                                             ; preds = %bb27, %bb14
+  %tmp30 = phi i32 [ %tmp25, %bb27 ], [ %tmp15, %bb14 ]
+  %tmp31 = phi i64 [ %tmp28, %bb27 ], [ %tmp16, %bb14 ]
+  %tmp32 = add nuw i64 %tmp17, 1
+  %tmp33 = add nuw nsw i32 %tmp18, 1
+  %tmp34 = icmp slt i32 %tmp33, %tmp30
+  br i1 %tmp34, label %bb14, label %bb35
+
+bb35:                                             ; preds = %bb29
+  %tmp36 = insertelement <2 x i64> undef, i64 %tmp31, i32 0
+  br label %bb39
+
+bb39:                                             ; preds = %bb35, %bb2
+  %tmp40 = phi i32 [ %tmp30, %bb35 ], [ %tmp3, %bb2 ]
+  %tmp43 = add nuw nsw i32 %tmp5, 1
+  %tmp44 = icmp slt i32 %tmp43, %tmp40
+  br i1 %tmp44, label %bb2, label %bb8
+
+bb45:                                             ; preds = %bb67, %bb8
+  %tmp46 = phi i32 [ %tmp68, %bb67 ], [ %tmp40, %bb8 ]
+  %tmp47 = phi i64 [ %tmp69, %bb67 ], [ 0, %bb8 ]
+  %tmp48 = phi i64 [ %tmp70, %bb67 ], [ 0, %bb8 ]
+  %tmp49 = phi i32 [ %tmp71, %bb67 ], [ 0, %bb8 ]
+  %tmp50 = icmp sgt i32 %tmp46, 0
+  br i1 %tmp50, label %bb57, label %bb67
+
+bb51:                                             ; preds = %bb67
+  %tmp56 = icmp sgt i32 %tmp68, 0
+  br i1 %tmp56, label %bb73, label %bb84
+
+bb57:                                             ; preds = %bb57, %bb45
+  %tmp58 = phi i64 [ %tmp60, %bb57 ], [ 0, %bb45 ]
+  %tmp59 = phi i32 [ %tmp61, %bb57 ], [ 0, %bb45 ]
+  %tmp60 = add nuw i64 %tmp58, 1
+  tail call void @bar()
+  %tmp61 = add nuw nsw i32 %tmp59, 1
+  %tmp62 = load i32, i32* @c, align 4, !tbaa !2
+  %tmp63 = mul nsw i32 %tmp62, 10
+  %tmp64 = icmp slt i32 %tmp61, %tmp63
+  br i1 %tmp64, label %bb57, label %bb65
+
+bb65:                                             ; preds = %bb57
+  %tmp66 = add i64 %tmp60, %tmp47
+  br label %bb67
+
+bb67:                                             ; preds = %bb65, %bb45
+  %tmp68 = phi i32 [ %tmp62, %bb65 ], [ %tmp46, %bb45 ]
+  %tmp69 = phi i64 [ %tmp66, %bb65 ], [ %tmp47, %bb45 ]
+  %tmp70 = add nuw i64 %tmp48, 1
+  %tmp71 = add nuw nsw i32 %tmp49, 1
+  %tmp72 = icmp slt i32 %tmp71, %tmp68
+  br i1 %tmp72, label %bb45, label %bb51
+
+bb73:                                             ; preds = %bb73, %bb51
+  %tmp74 = phi i64 [ %tmp76, %bb73 ], [ 0, %bb51 ]
+  %tmp75 = phi i32 [ %tmp77, %bb73 ], [ 0, %bb51 ]
+  %tmp76 = add nuw i64 %tmp74, 1
+  tail call void @bar()
+  %tmp77 = add nuw nsw i32 %tmp75, 1
+  %tmp78 = load i32, i32* @c, align 4, !tbaa !2
+  %tmp79 = mul nsw i32 %tmp78, 100
+  %tmp80 = icmp slt i32 %tmp77, %tmp79
+  br i1 %tmp80, label %bb73, label %bb81
+
+bb81:                                             ; preds = %bb73
+  br label %bb84
+
+bb84:                                             ; preds = %bb81, %bb51, %bb8, %bb
+  ret i32 0
+}
+
+attributes #0 = { noinline }
+attributes #1 = { norecurse nounwind uwtable } 
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 307355)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}

Added: llvm/trunk/test/Transforms/PGOProfile/criticaledge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/criticaledge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/criticaledge.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/criticaledge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: llvm-profdata merge %S/Inputs/criticaledge.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_test_criticalEdge = private constant [17 x i8] c"test_criticalEdge"
+; GEN: @__profn__stdin__bar = private constant [11 x i8] c"<stdin>:bar"
+
+define i32 @test_criticalEdge(i32 %i, i32 %j) {
+entry:
+; CHECK: entry:
+; GEN-NOT: call void @llvm.instrprof.increment
+  switch i32 %i, label %sw.default [
+    i32 1, label %sw.bb
+    i32 2, label %sw.bb1
+    i32 3, label %sw.bb2
+    i32 4, label %sw.bb2
+; CHECK:    i32 3, label %entry.sw.bb2_crit_edge
+; CHECK:    i32 4, label %entry.sw.bb2_crit_edge1
+    i32 5, label %sw.bb2
+  ]
+; USE: ]
+; USE-SAME: !prof ![[BW_SWITCH:[0-9]+]]
+
+; CHECK: entry.sw.bb2_crit_edge1:
+; GEN:   call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 1)
+; CHECK:   br label %sw.bb2
+
+; CHECK: entry.sw.bb2_crit_edge:
+; GEN:   call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 0)
+; CHECK:   br label %sw.bb2
+
+sw.bb:
+; GEN: sw.bb:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 5)
+  %call = call i32 @bar(i32 2)
+  br label %sw.epilog
+
+sw.bb1:
+; GEN: sw.bb1:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 4)
+  %call2 = call i32 @bar(i32 1024)
+  br label %sw.epilog
+
+sw.bb2:
+; GEN: sw.bb2:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %cmp = icmp eq i32 %j, 2
+  br i1 %cmp, label %if.then, label %if.end
+; USE: br i1 %cmp, label %if.then, label %if.end
+; USE-SAME: !prof ![[BW_SW_BB2:[0-9]+]]
+
+if.then:
+; GEN: if.then:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 2)
+  %call4 = call i32 @bar(i32 4)
+  br label %return
+
+if.end:
+; GEN: if.end:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 3)
+  %call5 = call i32 @bar(i32 8)
+  br label %sw.epilog
+
+sw.default:
+; GEN: sw.default:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %call6 = call i32 @bar(i32 32)
+  %cmp7 = icmp sgt i32 %j, 10
+  br i1 %cmp7, label %if.then8, label %if.end9
+; USE: br i1 %cmp7, label %if.then8, label %if.end9
+; USE-SAME: !prof ![[BW_SW_DEFAULT:[0-9]+]]
+
+if.then8:
+; GEN: if.then8:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 7)
+  %add = add nsw i32 %call6, 10
+  br label %if.end9
+
+if.end9:
+; GEN: if.end9:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @__profn_test_criticalEdge, i32 0, i32 0), i64 82323253069, i32 8, i32 6)
+  %res.0 = phi i32 [ %add, %if.then8 ], [ %call6, %sw.default ]
+  br label %sw.epilog
+
+sw.epilog:
+; GEN: sw.epilog:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %res.1 = phi i32 [ %res.0, %if.end9 ], [ %call5, %if.end ], [ %call2, %sw.bb1 ], [ %call, %sw.bb ]
+  br label %return
+
+return:
+; GEN: return:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %retval = phi i32 [ %res.1, %sw.epilog ], [ %call4, %if.then ]
+  ret i32 %retval
+}
+
+define internal i32 @bar(i32 %i) {
+entry:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__profn__stdin__bar, i32 0, i32 0), i64 12884901887, i32 1, i32 0)
+  ret i32 %i
+}
+
+; USE: ![[BW_SWITCH]] = !{!"branch_weights", i32 2, i32 1, i32 0, i32 2, i32 1, i32 1}
+; USE: ![[BW_SW_BB2]] = !{!"branch_weights", i32 2, i32 2}
+; USE: ![[BW_SW_DEFAULT]] = !{!"branch_weights", i32 1, i32 1}

Added: llvm/trunk/test/Transforms/PGOProfile/cspgo_profile_summary.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/cspgo_profile_summary.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/cspgo_profile_summary.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/cspgo_profile_summary.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,155 @@
+; Test the profile summary for context sensitive PGO (CSPGO)
+
+; RUN: llvm-profdata merge %S/Inputs/cspgo.proftext -o %t.profdata
+; RUN: opt < %s -O2 -disable-preinline -pgo-kind=pgo-instr-use-pipeline -profile-file=%t.profdata -S | FileCheck %s --check-prefix=PGOSUMMARY
+; RUN: opt < %s -O2 -disable-preinline -pgo-kind=pgo-instr-use-pipeline -profile-file=%t.profdata -S -cspgo-kind=cspgo-instr-use-pipeline| FileCheck %s --check-prefix=CSPGOSUMMARY
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at odd = common dso_local global i32 0, align 4
+ at even = common dso_local global i32 0, align 4
+ at not_six = common dso_local global i32 0, align 4
+
+define dso_local i32 @goo(i32 %n) {
+entry:
+  %i = alloca i32, align 4
+  %i.0..sroa_cast = bitcast i32* %i to i8*
+  store volatile i32 %n, i32* %i, align 4
+  %i.0. = load volatile i32, i32* %i, align 4
+  ret i32 %i.0.
+}
+
+define dso_local void @bar(i32 %n) {
+entry:
+  %call = call fastcc i32 @cond(i32 %n)
+  %tobool = icmp eq i32 %call, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:
+  %0 = load i32, i32* @odd, align 4
+  %inc = add i32 %0, 1
+  store i32 %inc, i32* @odd, align 4
+  br label %if.end
+
+if.else:
+  %1 = load i32, i32* @even, align 4
+  %inc1 = add i32 %1, 1
+  store i32 %inc1, i32* @even, align 4
+  br label %if.end
+
+if.end:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %if.end ], [ %inc6, %for.inc ]
+  %cmp = icmp ult i32 %i.0, 4
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %mul = mul nsw i32 %i.0, %n
+  %rem = srem i32 %mul, 6
+  %tobool2 = icmp eq i32 %rem, 0
+  br i1 %tobool2, label %for.inc, label %if.then3
+
+if.then3:
+  %2 = load i32, i32* @not_six, align 4
+  %inc4 = add i32 %2, 1
+  store i32 %inc4, i32* @not_six, align 4
+  br label %for.inc
+
+for.inc:
+  %inc6 = add nuw nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  ret void
+}
+; PGOSUMMARY-LABEL: @bar
+; PGOSUMMARY: %odd.sink = select i1 %tobool, i32* @even, i32* @odd
+; PGOSUMMARY-SAME: !prof ![[BW_PGO_BAR:[0-9]+]]
+; CSPGOSUMMARY-LABEL: @bar
+; CSPGOSUMMARY: %odd.sink = select i1 %tobool, i32* @even, i32* @odd
+; CSPGOSUMMARY-SAME: !prof ![[BW_CSPGO_BAR:[0-9]+]]
+
+define internal fastcc i32 @cond(i32 %i) {
+entry:
+  %rem = srem i32 %i, 2
+  ret i32 %rem
+}
+
+define dso_local void @foo() {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %add4, %for.body ]
+  %cmp = icmp slt i32 %i.0, 200000
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:
+  %call = call i32 @goo(i32 %i.0)
+  call void @bar(i32 %call)
+  %add = add nsw i32 %call, 1
+  call void @bar(i32 %add)
+  %call1 = call i32 @bar_m(i32 %call) #4
+  %call3 = call i32 @bar_m2(i32 %add) #4
+  call fastcc void @barbar()
+  %add4 = add nsw i32 %call, 2
+  br label %for.cond
+
+for.end:
+  ret void
+}
+; CSPGOSUMMARY-LABEL: @foo
+; CSPGOSUMMARY: %even.sink{{[0-9]*}} = select i1 %tobool.i{{[0-9]*}}, i32* @even, i32* @odd
+; CSPGOSUMMARY-SAME: !prof ![[BW1_CSPGO_FOO:[0-9]+]]
+; CSPGOSUMMARY: %even.sink{{[0-9]*}} = select i1 %tobool.i{{[0-9]*}}, i32* @even, i32* @odd
+; CSPGOSUMMARY-SAME: !prof ![[BW2_CSPGO_FOO:[0-9]+]]
+
+declare dso_local i32 @bar_m(i32)
+declare dso_local i32 @bar_m2(i32)
+
+define internal fastcc void @barbar() {
+entry:
+  %0 = load i32, i32* @odd, align 4
+  %inc = add i32 %0, 1
+  store i32 %inc, i32* @odd, align 4
+  ret void
+}
+
+define dso_local i32 @main() {
+entry:
+  call void @foo()
+  ret i32 0
+}
+
+; PGOSUMMARY: {{![0-9]+}} = !{i32 1, !"ProfileSummary", !{{[0-9]+}}}
+; PGOSUMMARY: {{![0-9]+}} = !{!"ProfileFormat", !"InstrProf"}
+; PGOSUMMARY: {{![0-9]+}} = !{!"TotalCount", i64 2100001}
+; PGOSUMMARY: {{![0-9]+}} = !{!"MaxCount", i64 800000}
+; PGOSUMMARY: {{![0-9]+}} = !{!"MaxInternalCount", i64 399999}
+; PGOSUMMARY: {{![0-9]+}} = !{!"MaxFunctionCount", i64 800000}
+; PGOSUMMARY: {{![0-9]+}} = !{!"NumCounts", i64 14}
+; PGOSUMMARY: {{![0-9]+}} = !{!"NumFunctions", i64 8}
+; PGOSUMMARY-DAG: ![[BW_PGO_BAR]] = !{!"branch_weights", i32 100000, i32 100000}
+
+; CSPGOSUMMARY: {{![0-9]+}} = !{i32 1, !"ProfileSummary", !1}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"ProfileFormat", !"InstrProf"}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"TotalCount", i64 2100001}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"MaxCount", i64 800000}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"MaxInternalCount", i64 399999}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"MaxFunctionCount", i64 800000}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"NumCounts", i64 14}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"NumFunctions", i64 8}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"DetailedSummary", !10}
+; CSPGOSUMMARY: {{![0-9]+}} = !{i32 1, !"CSProfileSummary", !{{[0-9]+}}}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"ProfileFormat", !"CSInstrProf"}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"TotalCount", i64 1299950}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"MaxCount", i64 200000}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"MaxInternalCount", i64 100000}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"MaxFunctionCount", i64 200000}
+; CSPGOSUMMARY: {{![0-9]+}} = !{!"NumCounts", i64 23}
+; CSPGOSUMMARY-DAG: ![[BW_CSPGO_BAR]] = !{!"branch_weights", i32 100000, i32 100000}
+; CSPGOSUMMARY-DAG: ![[BW1_CSPGO_FOO]] = !{!"branch_weights", i32 100000, i32 0}
+; CSPGOSUMMARY-DAG: ![[BW2_CSPGO_FOO]] = !{!"branch_weights", i32 0, i32 100000}

Added: llvm/trunk/test/Transforms/PGOProfile/diag_FE_profile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/diag_FE_profile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/diag_FE_profile.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/diag_FE_profile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: llvm-profdata merge %S/Inputs/diag_FE.proftext -o %t.profdata
+; RUN: not opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S  2>&1 | FileCheck %s
+; RUN: not opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S  2>&1 | FileCheck %s
+
+; CHECK: Not an IR level instrumentation profile
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @foo() {
+entry:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/PGOProfile/diag_mismatch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/diag_mismatch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/diag_mismatch.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/diag_mismatch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: llvm-profdata merge %S/Inputs/diag.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s
+
+; CHECK: Function control flow change detected (hash mismatch) foo
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @foo() {
+entry:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/PGOProfile/diag_no_funcprofdata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/diag_no_funcprofdata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/diag_no_funcprofdata.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/diag_no_funcprofdata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: llvm-profdata merge %S/Inputs/diag.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-warn-missing-function=true -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s
+; RUN: opt < %s -passes=pgo-instr-use -pgo-warn-missing-function=true -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s
+
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DEFAULT
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DEFAULT
+
+; CHECK: No profile data available for function bar
+; DEFAULT-NOT: No profile data available for function bar
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @bar() {
+entry:
+  ret i32 0 
+}

Added: llvm/trunk/test/Transforms/PGOProfile/diag_no_profile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/diag_no_profile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/diag_no_profile.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/diag_no_profile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: not opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S  2>&1
+; RUN: not opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S  2>&1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @foo() {
+entry:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/PGOProfile/do-not-instrument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/do-not-instrument.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/do-not-instrument.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/do-not-instrument.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+define i32 @f1() {
+; CHECK-LABEL: @f1
+entry:
+; CHECK: call void @llvm.instrprof.increment
+; CHECK-NOT: ptrtoint void (i8*)* asm sideeffect
+; CHECK-NOT: call void @llvm.instrprof.value.profile
+; CHECK: tail call void asm sideeffect 
+  tail call void asm sideeffect "", "imr,~{memory},~{dirflag},~{fpsr},~{flags}"(i8* undef) #0
+  ret i32 0
+}
+
+define i32 @f2() {
+entry:
+; CHECK: call void @llvm.instrprof.increment
+; CHECK-NOT: call void @llvm.instrprof.value.profile
+  call void (i32, ...) bitcast (void (...)* @foo to void (i32, ...)*)(i32 21)
+  ret i32 0
+}
+
+declare void @foo(...) #0
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/PGOProfile/func_entry.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/func_entry.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/func_entry.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/func_entry.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: llvm-profdata merge %S/Inputs/func_entry.proftext -o %t.profdata
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -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 s = common dso_local local_unnamed_addr global i32 0, align 4
+
+define void @bar() {
+; CHECK-LABEL: @bar
+; CHECK-SAME: !prof ![[FUNC_ENTRY_COUNT_ZERO:[0-9]+]]
+
+entry:
+  store i32 1, i32* @s, align 4
+  ret void
+}
+
+define void @foo() {
+; CHECK-LABEL: @foo
+; CHECK-SAME: !prof ![[FUNC_ENTRY_COUNT_NON_ZERO:[0-9]+]]
+entry:
+  %0 = load i32, i32* @s, align 4
+  %add = add nsw i32 %0, 4
+  store i32 %add, i32* @s, align 4
+  ret void
+}
+
+; CHECK-DAG: ![[FUNC_ENTRY_COUNT_ZERO]] = !{!"function_entry_count", i64 0}
+; CHECK-DAG: ![[FUNC_ENTRY_COUNT_NON_ZERO]] = !{!"function_entry_count", i64 9999}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_covariant_call_return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_covariant_call_return.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_covariant_call_return.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_covariant_call_return.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt < %s -passes=pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.D = type { %struct.B }
+%struct.B = type { i32 (...)** }
+%struct.Base = type { i8 }
+%struct.Derived = type { i8 }
+
+declare noalias i8* @_Znwm(i64)
+declare void @_ZN1DC2Ev(%struct.D*);
+declare %struct.Derived* @_ZN1D4funcEv(%struct.D*);
+
+define %struct.Base* @bar() {
+entry:
+  %call = call noalias i8* @_Znwm(i64 8)
+  %tmp = bitcast i8* %call to %struct.D*
+  call void @_ZN1DC2Ev(%struct.D* %tmp)
+  %tmp1 = bitcast %struct.D* %tmp to %struct.B*
+  %tmp2 = bitcast %struct.B* %tmp1 to %struct.Base* (%struct.B*)***
+  %vtable = load %struct.Base* (%struct.B*)**, %struct.Base* (%struct.B*)*** %tmp2, align 8
+  %vfn = getelementptr inbounds %struct.Base* (%struct.B*)*, %struct.Base* (%struct.B*)** %vtable, i64 0
+  %tmp3 = load %struct.Base* (%struct.B*)*, %struct.Base* (%struct.B*)** %vfn, align 8
+; ICALL-PROM:  [[CMP:%[0-9]+]] = icmp eq %struct.Base* (%struct.B*)* %tmp3, bitcast (%struct.Derived* (%struct.D*)* @_ZN1D4funcEv to %struct.Base* (%struct.B*)*)
+; ICALL-PROM:  br i1 [[CMP]], label %if.true.direct_targ, label %if.false.orig_indirect, !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICALL-PROM:if.true.direct_targ:
+; ICALL-PROM:  [[ARG_BITCAST:%[0-9]+]] = bitcast %struct.B* %tmp1 to %struct.D*
+; ICALL-PROM:  [[DIRCALL_RET:%[0-9]+]] = call %struct.Derived* @_ZN1D4funcEv(%struct.D* [[ARG_BITCAST]])
+; ICALL-PROM:  [[DIRCALL_RET_CAST:%[0-9]+]] = bitcast %struct.Derived* [[DIRCALL_RET]] to %struct.Base*
+; ICALL-PROM:  br label %if.end.icp 
+; ICALL-PROM:if.false.orig_indirect:
+; ICALL-PROM:  %call1 = call %struct.Base* %tmp3(%struct.B* %tmp1)
+; ICALL-PROM:  br label %if.end.icp
+; ICALL-PROM:if.end.icp:
+; ICALL-PROM:  [[PHI_RET:%[0-9]+]] = phi %struct.Base* [ %call1, %if.false.orig_indirect ], [ [[DIRCALL_RET_CAST]], %if.true.direct_targ ]
+  %call1 = call %struct.Base* %tmp3(%struct.B* %tmp1), !prof !1
+  ret %struct.Base* %call1
+}
+
+!1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}
+; ICALL-PROM-NOT: !1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}
+; ICALL-PROM: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 12345, i32 0}
+; ICALL-PROM-NOT: !1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_covariant_invoke_return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_covariant_invoke_return.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_covariant_invoke_return.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_covariant_invoke_return.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; RUN: opt < %s -pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt < %s -passes=pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+%struct.D = type { %struct.B }
+%struct.B = type { i32 (...)** }
+%struct.Derived = type { %struct.Base, i32 }
+%struct.Base = type { i32 }
+
+ at _ZTIi = external constant i8*
+declare i8* @_Znwm(i64)
+declare void @_ZN1DC2Ev(%struct.D*)
+declare %struct.Derived* @_ZN1D4funcEv(%struct.D*)
+declare void @_ZN1DD0Ev(%struct.D*)
+declare void @_ZdlPv(i8*)
+declare i32 @__gxx_personality_v0(...)
+declare i32 @llvm.eh.typeid.for(i8*)
+declare i8* @__cxa_begin_catch(i8*)
+declare void @__cxa_end_catch()
+
+
+define i32 @foo() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %call = invoke i8* @_Znwm(i64 8)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  %tmp = bitcast i8* %call to %struct.D*
+  call void @_ZN1DC2Ev(%struct.D* %tmp)
+  %tmp1 = bitcast %struct.D* %tmp to %struct.B*
+  %tmp2 = bitcast %struct.B* %tmp1 to %struct.Base* (%struct.B*)***
+  %vtable = load %struct.Base* (%struct.B*)**, %struct.Base* (%struct.B*)*** %tmp2, align 8
+  %vfn = getelementptr inbounds %struct.Base* (%struct.B*)*, %struct.Base* (%struct.B*)** %vtable, i64 0
+  %tmp3 = load %struct.Base* (%struct.B*)*, %struct.Base* (%struct.B*)** %vfn, align 8
+; ICALL-PROM:  [[CMP:%[0-9]+]] = icmp eq %struct.Base* (%struct.B*)* %tmp3, bitcast (%struct.Derived* (%struct.D*)* @_ZN1D4funcEv to %struct.Base* (%struct.B*)*)
+; ICALL-PROM:  br i1 [[CMP]], label %if.true.direct_targ, label %if.false.orig_indirect, !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICALL-PROM:if.true.direct_targ:
+; ICALL-PROM:  [[ARG_BITCAST:%[0-9]+]] = bitcast %struct.B* %tmp1 to %struct.D*
+; ICALL-PROM:  [[DIRCALL_RET:%[0-9]+]] = invoke %struct.Derived* @_ZN1D4funcEv(%struct.D* [[ARG_BITCAST]])
+; ICALL-PROM:          to label %if.true.direct_targ.if.end.icp_crit_edge unwind label %lpad
+; ICALL-PROM:if.true.direct_targ.if.end.icp_crit_edge:
+; ICALL-PROM:  [[DIRCALL_RET_CAST:%[0-9]+]] = bitcast %struct.Derived* [[DIRCALL_RET]] to %struct.Base*
+; ICALL-PROM:  br label %if.end.icp
+; ICALL-PROM:if.false.orig_indirect:
+; ICAll-PROM:  %call2 = invoke %struct.Base* %tmp3(%struct.B* %tmp1)
+; ICAll-PROM:          to label %invoke.cont1 unwind label %lpad
+; ICALL-PROM:if.end.icp:
+; ICALL-PROM:  br label %invoke.cont1
+  %call2 = invoke %struct.Base* %tmp3(%struct.B* %tmp1)
+          to label %invoke.cont1 unwind label %lpad, !prof !1
+
+invoke.cont1:
+; ICAll-PROM:  [[PHI_RET:%[0-9]+]] = phi %struct.Base* [ %call2, %if.false.orig_indirect ], [ [[DIRCALL_RET_CAST]], %if.end.icp ]
+; ICAll-PROM:  %isnull = icmp eq %struct.Base* [[PHI_RET]], null
+  %isnull = icmp eq %struct.Base* %call2, null
+  br i1 %isnull, label %delete.end, label %delete.notnull
+
+delete.notnull:
+  %tmp4 = bitcast %struct.Base* %call2 to i8*
+  call void @_ZdlPv(i8* %tmp4)
+  br label %delete.end
+
+delete.end:
+  %isnull3 = icmp eq %struct.B* %tmp1, null
+  br i1 %isnull3, label %delete.end8, label %delete.notnull4
+
+delete.notnull4:
+  %tmp5 = bitcast %struct.B* %tmp1 to void (%struct.B*)***
+  %vtable5 = load void (%struct.B*)**, void (%struct.B*)*** %tmp5, align 8
+  %vfn6 = getelementptr inbounds void (%struct.B*)*, void (%struct.B*)** %vtable5, i64 2
+  %tmp6 = load void (%struct.B*)*, void (%struct.B*)** %vfn6, align 8
+  invoke void %tmp6(%struct.B* %tmp1)
+          to label %invoke.cont7 unwind label %lpad
+
+invoke.cont7:
+  br label %delete.end8
+
+delete.end8:
+  br label %try.cont
+
+lpad:
+  %tmp7 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %tmp8 = extractvalue { i8*, i32 } %tmp7, 0
+  %tmp9 = extractvalue { i8*, i32 } %tmp7, 1
+  br label %catch.dispatch
+
+catch.dispatch:
+  %tmp10 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
+  %matches = icmp eq i32 %tmp9, %tmp10
+  br i1 %matches, label %catch, label %eh.resume
+
+catch:
+  %tmp11 = call i8* @__cxa_begin_catch(i8* %tmp8)
+  %tmp12 = bitcast i8* %tmp11 to i32*
+  %tmp13 = load i32, i32* %tmp12, align 4
+  call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  ret i32 0
+
+eh.resume:
+  %lpad.val = insertvalue { i8*, i32 } undef, i8* %tmp8, 0
+  %lpad.val11 = insertvalue { i8*, i32 } %lpad.val, i32 %tmp9, 1
+  resume { i8*, i32 } %lpad.val11
+}
+
+!1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}
+; ICALL-PROM-NOT: !1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}
+; ICALL-PROM: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 12345, i32 0}
+; ICALL-PROM-NOT: !1 = !{!"VP", i32 0, i64 12345, i64 -3913987384944532146, i64 12345}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_invoke.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_invoke.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_invoke.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,106 @@
+; RUN: opt < %s -icp-lto -pgo-icall-prom -S | FileCheck %s --check-prefix=ICP
+; RUN: opt < %s -icp-lto -passes=pgo-icall-prom -S | FileCheck %s --check-prefix=ICP
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo1 = global void ()* null, align 8
+ at foo2 = global i32 ()* null, align 8
+ at _ZTIi = external constant i8*
+
+define internal void @_ZL4bar1v() !PGOFuncName !0 {
+entry:
+  ret void
+}
+
+define internal i32 @_ZL4bar2v() !PGOFuncName !1 {
+entry:
+  ret i32 100
+}
+
+define i32 @_Z3goov() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %tmp = load void ()*, void ()** @foo1, align 8
+; ICP:  [[CMP_IC1:%[0-9]+]] = icmp eq void ()* %tmp, @_ZL4bar1v
+; ICP:  br i1 [[CMP_IC1]], label %[[TRUE_LABEL_IC1:.*]], label %[[FALSE_LABEL_IC1:.*]], !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICP:[[TRUE_LABEL_IC1]]:
+; ICP:  invoke void @_ZL4bar1v()
+; ICP:          to label %[[DCALL_NORMAL_DEST_IC1:.*]] unwind label %lpad
+; ICP:[[FALSE_LABEL_IC1]]:
+  invoke void %tmp()
+          to label %try.cont unwind label %lpad, !prof !2
+
+; ICP:[[DCALL_NORMAL_DEST_IC1]]:
+; ICP:  br label %try.cont
+
+lpad:
+  %tmp1 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %tmp2 = extractvalue { i8*, i32 } %tmp1, 0
+  %tmp3 = extractvalue { i8*, i32 } %tmp1, 1
+  %tmp4 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
+  %matches = icmp eq i32 %tmp3, %tmp4
+  br i1 %matches, label %catch, label %eh.resume
+
+catch:
+  %tmp5 = tail call i8* @__cxa_begin_catch(i8* %tmp2)
+  tail call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+  %tmp6 = load i32 ()*, i32 ()** @foo2, align 8
+; ICP:  [[CMP_IC2:%[0-9]+]] = icmp eq i32 ()* %tmp6, @_ZL4bar2v
+; ICP:  br i1 [[CMP_IC2]], label %[[TRUE_LABEL_IC2:.*]], label %[[FALSE_LABEL_IC2:.*]], !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICP:[[TRUE_LABEL_IC2]]:
+; ICP:  [[RESULT_IC2_0:%[0-9]+]] = invoke i32 @_ZL4bar2v()
+; ICP:          to label %[[MERGE_BB:.*]] unwind label %lpad1
+; ICP:[[FALSE_LABEL_IC2]]:
+; ICP:  [[RESULT_IC2_1:%.+]] = invoke i32 %tmp6()
+; ICP:          to label %[[MERGE_BB]] unwind label %lpad1
+  %call = invoke i32 %tmp6()
+          to label %try.cont8 unwind label %lpad1, !prof !3
+
+; ICP:[[MERGE_BB]]:
+; ICP:  [[MERGE_PHI:%.+]] = phi i32 [ [[RESULT_IC2_1]], %[[FALSE_LABEL_IC2]] ], [ [[RESULT_IC2_0]], %[[TRUE_LABEL_IC2]] ]
+; ICP:  br label %try.cont8
+lpad1:
+  %tmp7 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %tmp8 = extractvalue { i8*, i32 } %tmp7, 0
+  %tmp9 = extractvalue { i8*, i32 } %tmp7, 1
+  %tmp10 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
+  %matches5 = icmp eq i32 %tmp9, %tmp10
+  br i1 %matches5, label %catch6, label %eh.resume
+
+catch6:
+  %tmp11 = tail call i8* @__cxa_begin_catch(i8* %tmp8)
+  tail call void @__cxa_end_catch()
+  br label %try.cont8
+
+try.cont8:
+  %i.0 = phi i32 [ undef, %catch6 ], [ %call, %try.cont ]
+; ICP:  %i.0 = phi i32 [ undef, %catch6 ], [ [[MERGE_PHI]], %[[MERGE_BB]] ]
+  ret i32 %i.0
+
+eh.resume:
+  %ehselector.slot.0 = phi i32 [ %tmp9, %lpad1 ], [ %tmp3, %lpad ]
+  %exn.slot.0 = phi i8* [ %tmp8, %lpad1 ], [ %tmp2, %lpad ]
+  %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0
+  %lpad.val11 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1
+  resume { i8*, i32 } %lpad.val11
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i32 @llvm.eh.typeid.for(i8*)
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()
+
+!0 = !{!"invoke.ll:_ZL4bar1v"}
+!1 = !{!"invoke.ll:_ZL4bar2v"}
+!2 = !{!"VP", i32 0, i64 1, i64 -2732222848796217051, i64 1}
+!3 = !{!"VP", i32 0, i64 1, i64 -6116256810522035449, i64 1}
+; ICP-NOT !3 = !{!"VP", i32 0, i64 1, i64 -2732222848796217051, i64 1}
+; ICP-NOT !4 = !{!"VP", i32 0, i64 1, i64 -6116256810522035449, i64 1}
+; ICP: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1, i32 0}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_invoke_nouse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_invoke_nouse.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_invoke_nouse.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_invoke_nouse.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt < %s -icp-lto -pgo-icall-prom -S | FileCheck %s --check-prefix=ICP
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at _ZTISt9exception = external constant i8*
+ at pfptr = global i32()* null, align 8
+
+define internal i32 @_ZL4bar1v() !PGOFuncName !0 {
+entry:
+  ret i32 100 
+}
+
+; Function Attrs: uwtable
+define i32 @_Z3fooi(i32 %x) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %tobool = icmp eq i32 %x, 0
+  br i1 %tobool, label %if.end, label %cleanup
+
+if.end:                                           ; preds = %entry
+  %fptr = load i32 ()*, i32 ()** @pfptr, align 8
+; ICP:  [[CMP_IC1:%[0-9]+]] = icmp eq i32 ()* %fptr, @_ZL4bar1v
+; ICP:  br i1 [[CMP_IC1]], label %[[TRUE_LABEL_IC1:.*]], label %[[FALSE_LABEL_IC1:.*]], !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICP:[[TRUE_LABEL_IC1]]:
+; ICP:  invoke i32 @_ZL4bar1v()
+; ICP:          to label %[[DCALL_NORMAL_DEST_IC1:.*]] unwind label %lpad
+; ICP:[[FALSE_LABEL_IC1]]:
+  %call = invoke i32 %fptr()
+          to label %cleanup unwind label %lpad, !prof !1
+
+; ICP:[[DCALL_NORMAL_DEST_IC1]]:
+; ICP:  br label %cleanup
+
+lpad:                                             ; preds = %if.end
+  %0 = landingpad { i8*, i32 }
+          cleanup
+          catch i8* bitcast (i8** @_ZTISt9exception to i8*)
+  %1 = extractvalue { i8*, i32 } %0, 1
+  %2 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTISt9exception to i8*))
+  %matches = icmp eq i32 %1, %2
+  br i1 %matches, label %catch, label %ehcleanup
+
+catch:                                            ; preds = %lpad
+  %3 = extractvalue { i8*, i32 } %0, 0
+  %4 = tail call i8* @__cxa_begin_catch(i8* %3)
+  tail call void @__cxa_end_catch()
+  br label %cleanup
+
+cleanup:                                          ; preds = %catch, %if.end, %entry
+; ICP-NOT: %[0-9]+ = phi 
+  ret i32 0
+
+ehcleanup:                                        ; preds = %lpad
+  resume { i8*, i32 } %0
+}
+
+declare i32 @_Z3barv() local_unnamed_addr
+
+declare i32 @__gxx_personality_v0(...)
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.typeid.for(i8*)
+
+declare i8* @__cxa_begin_catch(i8*) local_unnamed_addr
+
+declare void @__cxa_end_catch() local_unnamed_addr
+
+!0 = !{!"invoke.ll:_ZL4bar1v"}
+!1 = !{!"VP", i32 0, i64 10000, i64 -2732222848796217051, i64 10000}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_mismatch_msg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_mismatch_msg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_mismatch_msg.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_mismatch_msg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -pgo-icall-prom -pass-remarks-missed=pgo-icall-prom -S 2>& 1 | FileCheck %s
+; RUN: opt < %s -passes=pgo-icall-prom -pass-remarks-missed=pgo-icall-prom -S 2>& 1 | FileCheck %s
+
+; CHECK: remark: <unknown>:0:0: Cannot promote indirect call to func4 with count of 1234: The number of arguments mismatch
+; CHECK: remark: <unknown>:0:0: Cannot promote indirect call: target with md5sum{{.*}} not found
+; CHECK: remark: <unknown>:0:0: Cannot promote indirect call to func2 with count of 7890: Return type mismatch
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = common global i32 ()* null, align 8
+ at foo2 = common global i32 ()* null, align 8
+ at foo3 = common global i32 ()* null, align 8
+
+define i32 @func4(i32 %i) {
+entry:
+  ret i32 %i
+}
+
+define void @func2() {
+entry:
+  ret void
+}
+
+define i32 @bar() {
+entry:
+  %tmp = load i32 ()*, i32 ()** @foo, align 8
+  %call = call i32 %tmp(), !prof !1
+  %tmp2 = load i32 ()*, i32 ()** @foo2, align 8
+  %call1 = call i32 %tmp2(), !prof !2
+  %add = add nsw i32 %call1, %call
+  %tmp3 = load i32 ()*, i32 ()** @foo3, align 8
+  %call2 = call i32 %tmp3(), !prof !3
+  %add2 = add nsw i32 %add, %call2
+  ret i32 %add2
+}
+
+!1 = !{!"VP", i32 0, i64 1801, i64 7651369219802541373, i64 1234, i64 -4377547752858689819, i64 567}
+!2 = !{!"VP", i32 0, i64 3023, i64 -6929281286627296573, i64 2345, i64 -4377547752858689819, i64 678}
+!3 = !{!"VP", i32 0, i64 7890,  i64 -4377547752858689819, i64 7890}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_sample.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_sample.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_sample.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_sample.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt -pgo-icall-prom -icp-samplepgo -S < %s | FileCheck %s
+
+define i32* @_Z3fooPi(i32* readnone returned) {
+  ret i32* %0
+}
+
+; CHECK-LABEL: _Z3barPFPiS_E
+; CHECK: if.true.direct_targ
+; CHECK:   call i32* @_Z3fooPi
+define i32* @_Z3barPFPiS_E(i32* (i32*)* nocapture) {
+  %2 = tail call i32* %0(i32* null), !prof !33
+  ret i32* %2
+}
+
+!llvm.module.flags = !{!3}
+
+!3 = !{i32 1, !"ProfileSummary", !4}
+!4 = !{!5, !6, !7, !8, !9, !10, !11, !12}
+!5 = !{!"ProfileFormat", !"SampleProfile"}
+!6 = !{!"TotalCount", i64 0}
+!7 = !{!"MaxCount", i64 0}
+!8 = !{!"MaxInternalCount", i64 0}
+!9 = !{!"MaxFunctionCount", i64 0}
+!10 = !{!"NumCounts", i64 1}
+!11 = !{!"NumFunctions", i64 1}
+!12 = !{!"DetailedSummary", !13}
+!13 = !{!14, !15, !16, !17, !18, !19, !19, !20, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29}
+!14 = !{i32 10000, i64 0, i32 0}
+!15 = !{i32 100000, i64 0, i32 0}
+!16 = !{i32 200000, i64 0, i32 0}
+!17 = !{i32 300000, i64 0, i32 0}
+!18 = !{i32 400000, i64 0, i32 0}
+!19 = !{i32 500000, i64 0, i32 0}
+!20 = !{i32 600000, i64 0, i32 0}
+!21 = !{i32 700000, i64 0, i32 0}
+!22 = !{i32 800000, i64 0, i32 0}
+!23 = !{i32 900000, i64 0, i32 0}
+!24 = !{i32 950000, i64 0, i32 0}
+!25 = !{i32 990000, i64 0, i32 0}
+!26 = !{i32 999000, i64 0, i32 0}
+!27 = !{i32 999900, i64 0, i32 0}
+!28 = !{i32 999990, i64 0, i32 0}
+!29 = !{i32 999999, i64 0, i32 0}
+!33 = !{!"VP", i32 0, i64 100, i64 8400159624858369790, i64 100}

Added: llvm/trunk/test/Transforms/PGOProfile/icp_vararg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/icp_vararg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/icp_vararg.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/icp_vararg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt < %s -passes=pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = common global i32 (i32, ...)* null, align 8
+
+define i32 @va_func(i32 %num, ...) {
+entry:
+  ret i32 0
+}
+
+define i32 @bar() #1 {
+entry:
+  %tmp = load i32 (i32, ...)*, i32 (i32, ...)** @foo, align 8
+; ICALL-PROM:  [[CMP:%[0-9]+]] = icmp eq i32 (i32, ...)* %tmp, @va_func
+; ICALL-PROM:  br i1 [[CMP]], label %if.true.direct_targ, label %if.false.orig_indirect, !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICALL-PROM:if.true.direct_targ:
+; ICALL-PROM:  [[DIRCALL_RET:%[0-9]+]] = call i32 (i32, ...) @va_func(i32 3, i32 12, i32 22, i32 4)
+; ICALL-PROM:  br label %if.end.icp
+  %call = call i32 (i32, ...) %tmp(i32 3, i32 12, i32 22, i32 4), !prof !1
+; ICALL-PROM:if.false.orig_indirect:
+; ICALL-PROM:  %call = call i32 (i32, ...) %tmp(i32 3, i32 12, i32 22, i32 4)
+; ICALL-PROM:  br label %if.end.icp
+  ret i32 %call
+; ICALL-PROM:if.end.icp:
+; ICALL-PROM:  [[PHI_RET:%[0-9]+]] = phi i32 [ %call, %if.false.orig_indirect ], [ [[DIRCALL_RET]], %if.true.direct_targ ]
+; ICALL-PROM:  ret i32 [[PHI_RET]] 
+
+}
+
+!1 = !{!"VP", i32 0, i64 12345, i64 989055279648259519, i64 12345}
+; ICALL-PROM: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 12345, i32 0}

Added: llvm/trunk/test/Transforms/PGOProfile/indirect_call_annotation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/indirect_call_annotation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/indirect_call_annotation.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/indirect_call_annotation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: llvm-profdata merge %S/Inputs/indirect_call.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=VP-ANNOTATION
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=VP-ANNOTATION
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = common global i32 (i32)* null, align 8
+
+define i32 @func1(i32 %x) {
+entry:
+  ret i32 %x
+}
+
+define i32 @func2(i32 %x) {
+entry:
+  %add = add nsw i32 %x, 1
+  ret i32 %add
+}
+
+define i32 @func3(i32 %x) {
+entry:
+  %add = add nsw i32 %x, 3
+  ret i32 %add
+}
+
+define i32 @bar(i32 %i) {
+entry:
+  %tmp = load i32 (i32)*, i32 (i32)** @foo, align 8
+  %call = call i32 %tmp(i32 %i)
+; VP-ANNOTATION: %call = call i32 %tmp(i32 %i)
+; VP-ANNOTATION-SAME: !prof ![[VP:[0-9]+]]
+; VP-ANNOTATION: ![[VP]] = !{!"VP", i32 0, i64 140, i64 -4377547752858689819, i64 80, i64 -2545542355363006406, i64 40, i64 -6929281286627296573, i64 20}
+  ret i32 %call
+}
+
+

Added: llvm/trunk/test/Transforms/PGOProfile/indirect_call_profile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/indirect_call_profile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/indirect_call_profile.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/indirect_call_profile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen,instrprof -S | FileCheck %s --check-prefix=LOWER
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$foo3 = comdat any
+
+ at bar = external global void ()*, align 8
+; GEN: @__profn_foo = private constant [3 x i8] c"foo"
+
+define void @foo() {
+entry:
+; GEN: entry:
+; GEN-NEXT: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 [[FOO_HASH:[0-9]+]], i32 1, i32 0)
+  %tmp = load void ()*, void ()** @bar, align 8
+; GEN: [[ICALL_TARGET:%[0-9]+]] = ptrtoint void ()* %tmp to i64
+; GEN-NEXT: call void @llvm.instrprof.value.profile(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 [[FOO_HASH]], i64 [[ICALL_TARGET]], i32 0, i32 0)
+  call void %tmp()
+  ret void
+}
+
+ at bar2 = global void ()* null, align 8
+ at _ZTIi = external constant i8*
+
+define i32 @foo2(i32 %arg, i8** nocapture readnone %arg1) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+bb:
+  %tmp2 = load void ()*, void ()** @bar2, align 8
+  invoke void %tmp2()
+          to label %bb10 unwind label %bb2
+; GEN: [[ICALL_TARGET2:%[0-9]+]] = ptrtoint void ()* %tmp2 to i64
+; GEN-NEXT: call void @llvm.instrprof.value.profile(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @__profn_foo2, i32 0, i32 0), i64 [[FOO2_HASH:[0-9]+]], i64 [[ICALL_TARGET2]], i32 0, i32 0)
+
+bb2:                                              ; preds = %bb
+  %tmp3 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %tmp4 = extractvalue { i8*, i32 } %tmp3, 1
+  %tmp5 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
+  %tmp6 = icmp eq i32 %tmp4, %tmp5
+  br i1 %tmp6, label %bb7, label %bb11
+
+bb7:                                              ; preds = %bb2
+  %tmp8 = extractvalue { i8*, i32 } %tmp3, 0
+  %tmp9 = tail call i8* @__cxa_begin_catch(i8* %tmp8)
+  tail call void @__cxa_end_catch()
+  br label %bb10
+
+bb10:                                             ; preds = %bb7, %bb
+  ret i32 0
+
+bb11:                                             ; preds = %bb2
+  resume { i8*, i32 } %tmp3
+}
+
+; Test that comdat function's address is recorded.
+; LOWER: @__profd_foo3.[[FOO3_HASH:[0-9]+]] = linkonce_odr{{.*}}@__profc_foo3.[[FOO3_HASH]]
+; Function Attrs: nounwind uwtable
+define linkonce_odr i32 @foo3()  comdat  {
+  ret i32 1
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.typeid.for(i8*) #0
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()
+

Added: llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; RUN: opt < %s -pgo-icall-prom -S -icp-total-percent-threshold=50 | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt < %s -pgo-icall-prom -S -icp-samplepgo -icp-total-percent-threshold=50 | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt < %s -passes=pgo-icall-prom -S -icp-total-percent-threshold=50 | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt < %s -pgo-icall-prom -S -pass-remarks=pgo-icall-prom -icp-remaining-percent-threshold=0 -icp-total-percent-threshold=0 -icp-max-prom=4 2>&1 | FileCheck %s --check-prefix=PASS-REMARK
+; RUN: opt < %s -passes=pgo-icall-prom -S -pass-remarks=pgo-icall-prom -icp-remaining-percent-threshold=0 -icp-total-percent-threshold=0 -icp-max-prom=4 2>&1 | FileCheck %s --check-prefix=PASS-REMARK
+; RUN: opt < %s -passes=pgo-icall-prom -S -pass-remarks=pgo-icall-prom -icp-remaining-percent-threshold=0 -icp-total-percent-threshold=20 -icp-max-prom=4 2>&1 | FileCheck %s --check-prefix=PASS2-REMARK
+
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func4 with count 1030 out of 1600
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func2 with count 410 out of 570
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func3 with count 150 out of 160
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func1 with count 10 out of 10
+
+; PASS2-REMARK: remark: <unknown>:0:0: Promote indirect call to func4 with count 1030 out of 1600
+; PASS2-REMARK: remark: <unknown>:0:0: Promote indirect call to func2 with count 410 out of 570
+; PASS2-REMARK-NOT: remark: <unknown>:0:0: Promote indirect call to func3
+; PASS2-REMARK-NOT: remark: <unknown>:0:0: Promote indirect call to func1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = common global i32 ()* null, align 8
+
+define i32 @func1() {
+entry:
+  ret i32 0
+}
+
+define i32 @func2() {
+entry:
+  ret i32 1
+}
+
+define i32 @func3() {
+entry:
+  ret i32 2
+}
+
+define i32 @func4() {
+entry:
+  ret i32 3
+}
+
+define i32 @bar() {
+entry:
+  %tmp = load i32 ()*, i32 ()** @foo, align 8
+; ICALL-PROM:   [[CMP:%[0-9]+]] = icmp eq i32 ()* %tmp, @func4
+; ICALL-PROM:   br i1 [[CMP]], label %if.true.direct_targ, label %if.false.orig_indirect, !prof [[BRANCH_WEIGHT:![0-9]+]]
+; ICALL-PROM: if.true.direct_targ:
+; ICALL-PROM:   [[DIRCALL_RET:%[0-9]+]] = call i32 @func4()
+; ICALL-PROM-SAMPLEPGO: call i32 @func4(), !prof [[CALL_METADATA:![0-9]+]]
+; ICALL-PROM:   br label %if.end.icp
+  %call = call i32 %tmp(), !prof !1
+; ICALL-PROM: if.false.orig_indirect:
+; ICALL-PROM:   %call = call i32 %tmp(), !prof [[NEW_VP_METADATA:![0-9]+]]
+  ret i32 %call
+; ICALL-PROM: if.end.icp:
+; ICALL-PROM:   [[PHI_RET:%[0-9]+]] = phi i32 [ %call, %if.false.orig_indirect ], [ [[DIRCALL_RET]], %if.true.direct_targ ]
+; ICALL-PROM:   ret i32 [[PHI_RET]]
+}
+
+!1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410, i64 -6929281286627296573, i64 150, i64 -2545542355363006406, i64 10}
+
+; ICALL-PROM: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1030, i32 570}
+; ICALL-PROM: [[NEW_VP_METADATA]] = !{!"VP", i32 0, i64 570, i64 -4377547752858689819, i64 410}
+; ICALL-PROM-SAMPLEPGO: [[CALL_METADATA]] = !{!"branch_weights", i32 1030}

Added: llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion_vla.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion_vla.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion_vla.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/indirect_call_promotion_vla.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -pgo-icall-prom -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.A = type { i8 }
+%struct.B = type { i8 }
+ at foo = common global i32 (%struct.A*, ...)* null, align 8
+
+define i32 @func1(%struct.B* %x, ...) {
+entry:
+  ret i32 0
+}
+
+define i32 @bar(%struct.A* %x) {
+entry:
+  %tmp = load i32 (%struct.A*, ...)*, i32 (%struct.A*, ...)** @foo, align 8
+; CHECK:   [[CMP:%[0-9]+]] = icmp eq i32 (%struct.A*, ...)* %tmp, bitcast (i32 (%struct.B*, ...)* @func1 to i32 (%struct.A*, ...)*)
+; CHECK:   br i1 [[CMP]], label %if.true.direct_targ, label %if.false.orig_indirect, !prof [[BRANCH_WEIGHT:![0-9]+]]
+; CHECK: if.true.direct_targ:
+; CHECK:   [[DIRCALL_RET:%[0-9]+]] = call i32 (%struct.B*, ...) @func1
+; CHECK:   br label %if.end.icp
+  %call = call i32 (%struct.A*, ...) %tmp(%struct.A* %x, i32 0), !prof !1
+  ret i32 %call
+}
+
+; CHECK: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1500, i32 100}
+!1 = !{!"VP", i32 0, i64 1600, i64 -2545542355363006406, i64 1500}

Added: llvm/trunk/test/Transforms/PGOProfile/indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/indirectbr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/indirectbr.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/indirectbr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: llvm-profdata merge %S/Inputs/indirectbr.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; New PM
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | opt -S -analyze -branch-prob | FileCheck %s --check-prefix=BRANCHPROB
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo.table = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@foo, %return), i8* blockaddress(@foo, %label2), i8* blockaddress(@foo, %label3)], align 16
+
+define i32 @foo(i32 %i) {
+entry:
+  %cmp = icmp ult i32 %i, 3
+  br i1 %cmp, label %if.then, label %return
+
+if.then:
+  %idxprom = zext i32 %i to i64
+  %arrayidx = getelementptr inbounds [3 x i8*], [3 x i8*]* @foo.table, i64 0, i64 %idxprom
+  %0 = load i8*, i8** %arrayidx, align 8
+  indirectbr i8* %0, [label %return, label %label2, label %label3]
+; USE:  indirectbr i8* %0, [label %return, label %label2, label %label3]
+; USE-SAME: !prof ![[BW_INDBR:[0-9]+]]
+; USE: ![[BW_INDBR]] = !{!"branch_weights", i32 63, i32 20, i32 5}
+
+label2:
+  br label %return
+
+label3:
+  br label %return
+
+return:
+  %retval.0 = phi i32 [ 3, %label3 ], [ 2, %label2 ], [ 0, %entry ], [ 1, %if.then ]
+  ret i32 %retval.0
+}
+
+; BRANCHPROB: Printing analysis 'Branch Probability Analysis' for function 'foo':
+; BRANCHPROB:---- Branch Probabilities ----
+; BRANCHPROB:  edge entry -> if.then probability is 0x37c32b17 / 0x80000000 = 43.56%
+; BRANCHPROB:  edge entry -> return.clone probability is 0x483cd4e9 / 0x80000000 = 56.44%
+; BRANCHPROB:  edge if.then -> return probability is 0x5ba2e8ba / 0x80000000 = 71.59%
+; BRANCHPROB:  edge if.then -> label2 probability is 0x1d1745d1 / 0x80000000 = 22.73%
+; BRANCHPROB:  edge if.then -> label3 probability is 0x0745d174 / 0x80000000 = 5.68%
+; BRANCHPROB:  edge label2 -> return.clone probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+; BRANCHPROB:  edge label3 -> return.clone probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+; BRANCHPROB:  edge return -> .split probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+; BRANCHPROB:  edge return.clone -> .split probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+
+

Added: llvm/trunk/test/Transforms/PGOProfile/infinite_loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/infinite_loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/infinite_loop.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/infinite_loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -instrprof -S -o - -do-counter-promotion=1  | FileCheck %s
+; CHECK: store
+
+ at __profn_foo = private constant [3 x i8] c"foo"
+
+define void @foo() {
+entry:
+  br label %while.body
+
+  while.body:                                       ; preds = %entry, %while.body
+    call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 14813359968, i32 1, i32 0)
+    call void (...) @bar() #2
+    br label %while.body
+}
+
+declare void @bar(...)
+
+declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #0
+
+attributes #0 = { nounwind }
+

Added: llvm/trunk/test/Transforms/PGOProfile/infinite_loop_gen.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/infinite_loop_gen.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/infinite_loop_gen.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/infinite_loop_gen.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -pgo-instr-gen -S -o -   | FileCheck %s
+
+define void @foo() {
+entry:
+  br label %while.body
+  ; CHECK: llvm.instrprof.increment
+
+    while.body:                                       ; preds = %entry, %while.body
+    ; CHECK: llvm.instrprof.increment
+        call void (...) @bar() #2
+    br label %while.body
+}
+
+declare void @bar(...)
+
+attributes #0 = { nounwind }
+

Added: llvm/trunk/test/Transforms/PGOProfile/irreducible.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/irreducible.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/irreducible.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/irreducible.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,139 @@
+; RUN: llvm-profdata merge %S/Inputs/irreducible.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+
+; GEN: $__llvm_profile_raw_version = comdat any
+
+; Function Attrs: noinline norecurse nounwind readnone uwtable
+define i32 @_Z11irreducibleii(i32 %iter_outer, i32 %iter_inner) local_unnamed_addr #0 {
+entry:
+  %cmp24 = icmp sgt i32 %iter_outer, 0
+  br i1 %cmp24, label %for.body, label %entry.for.cond.cleanup_crit_edge
+
+entry.for.cond.cleanup_crit_edge:                 ; preds = %entry
+  br label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %entry.for.cond.cleanup_crit_edge, %for.end
+  %sum.0.lcssa = phi i32 [ 0, %entry.for.cond.cleanup_crit_edge ], [ %sum.1, %for.end ]
+  ret i32 %sum.0.lcssa
+
+for.body:                                         ; preds = %entry, %for.end
+  %k.026 = phi i32 [ %inc12, %for.end ], [ 0, %entry ]
+  %sum.025 = phi i32 [ %sum.1, %for.end ], [ 0, %entry ]
+  %rem23 = and i32 %k.026, 1
+  %cmp1 = icmp eq i32 %rem23, 0
+  br i1 %cmp1, label %entry8, label %for.cond2
+
+for.cond2:                                        ; preds = %for.body, %if.end9
+  %sum.1 = phi i32 [ %add10, %if.end9 ], [ %sum.025, %for.body ]
+  %i.0 = phi i32 [ %inc, %if.end9 ], [ 0, %for.body ]
+  %cmp3 = icmp slt i32 %i.0, %iter_inner
+  br i1 %cmp3, label %for.body4, label %for.end
+; USE: br i1 %cmp3, label %for.body4, label %for.end, !prof !{{[0-9]+}},
+; USE-SAME: !irr_loop ![[FOR_COND2_IRR_LOOP:[0-9]+]]
+
+for.body4:                                        ; preds = %for.cond2
+  %rem5 = srem i32 %k.026, 3
+  %cmp6 = icmp eq i32 %rem5, 0
+  br i1 %cmp6, label %entry8, label %if.end9
+
+entry8:                                           ; preds = %for.body4, %for.body
+  %sum.2 = phi i32 [ %sum.025, %for.body ], [ %sum.1, %for.body4 ]
+  %i.1 = phi i32 [ 0, %for.body ], [ %i.0, %for.body4 ]
+  %add = add nsw i32 %sum.2, 4
+  br label %if.end9
+; USE: br label %if.end9,
+; USE-SAME: !irr_loop ![[ENTRY8_IRR_LOOP:[0-9]+]]
+
+if.end9:                                          ; preds = %entry8, %for.body4
+  %sum.3 = phi i32 [ %add, %entry8 ], [ %sum.1, %for.body4 ]
+  %i.2 = phi i32 [ %i.1, %entry8 ], [ %i.0, %for.body4 ]
+  %add10 = add nsw i32 %sum.3, 1
+  %inc = add nsw i32 %i.2, 1
+  br label %for.cond2
+; USE: br label %for.cond2,
+; USE-SAME: !irr_loop ![[IF_END9_IRR_LOOP:[0-9]+]]
+
+for.end:                                          ; preds = %for.cond2
+  %inc12 = add nuw nsw i32 %k.026, 1
+  %exitcond = icmp eq i32 %inc12, %iter_outer
+  br i1 %exitcond, label %for.cond.cleanup, label %for.body
+}
+
+
+
+ at targets = local_unnamed_addr global [256 x i8*] zeroinitializer, align 16
+ at tracing = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: noinline norecurse nounwind uwtable
+define i32 @_Z11irreduciblePh(i8* nocapture readonly %p) {
+entry:
+  %0 = load i32, i32* @tracing, align 4
+  %1 = trunc i32 %0 to i8
+  %tobool = icmp eq i32 %0, 0
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %sw.default, %entry
+  br label %dispatch_op
+
+dispatch_op:                                      ; preds = %sw.bb6, %for.cond1
+  switch i8 %1, label %sw.default [
+    i8 0, label %sw.bb
+    i8 1, label %dispatch_op.sw.bb6_crit_edge
+    i8 2, label %sw.bb15
+  ]
+
+dispatch_op.sw.bb6_crit_edge:                     ; preds = %dispatch_op
+  br label %sw.bb6
+
+sw.bb:                                            ; preds = %indirectgoto, %dispatch_op
+  br label %exit
+
+TARGET_1:                                         ; preds = %indirectgoto
+  br label %sw.bb6
+; USE: br label %sw.bb6, !irr_loop {{.*}}
+
+sw.bb6:                                           ; preds = %TARGET_1, %dispatch_op.sw.bb6_crit_edge
+  br i1 %tobool, label %dispatch_op, label %if.then
+; USE: br i1 %tobool, label %dispatch_op, label %if.then, !prof !{{[0-9]+}},
+; USE-SAME: !irr_loop ![[SW_BB6_IRR_LOOP:[0-9]+]]
+
+if.then:                                          ; preds = %sw.bb6
+  br label %indirectgoto
+
+TARGET_2:                                         ; preds = %indirectgoto
+  br label %sw.bb15
+; USE: br label %sw.bb15, !irr_loop {{.*}}
+
+sw.bb15:                                          ; preds = %TARGET_2, %dispatch_op
+  br i1 %tobool, label %if.then18, label %exit
+; USE: br i1 %tobool, label %if.then18, label %exit, !prof !{{[0-9]+}},
+; USE-SAME: !irr_loop ![[SW_BB15_IRR_LOOP:[0-9]+]]
+
+if.then18:                                        ; preds = %sw.bb15
+  br label %indirectgoto
+
+unknown_op:                                       ; preds = %indirectgoto
+  br label %sw.default
+
+sw.default:                                       ; preds = %unknown_op, %dispatch_op
+  br label %for.cond1
+
+exit:                                             ; preds = %sw.bb15, %sw.bb
+  ret i32 0
+
+indirectgoto:                                     ; preds = %if.then18, %if.then
+  %idxprom21 = zext i32 %0 to i64
+  %arrayidx22 = getelementptr inbounds [256 x i8*], [256 x i8*]* @targets, i64 0, i64 %idxprom21
+  %target = load i8*, i8** %arrayidx22, align 8
+  indirectbr i8* %target, [label %unknown_op, label %sw.bb, label %TARGET_1, label %TARGET_2]
+; USE: indirectbr i8* %target, [label %unknown_op, label %sw.bb, label %TARGET_1, label %TARGET_2], !prof !{{[0-9]+}},
+; USE-SAME: !irr_loop ![[INDIRECTGOTO_IRR_LOOP:[0-9]+]]
+}
+
+; USE: ![[FOR_COND2_IRR_LOOP]] = !{!"loop_header_weight", i64 1050}
+; USE: ![[ENTRY8_IRR_LOOP]] = !{!"loop_header_weight", i64 373}
+; USE: ![[IF_END9_IRR_LOOP]] = !{!"loop_header_weight", i64 1000}
+; USE: ![[SW_BB6_IRR_LOOP]] = !{!"loop_header_weight", i64 501}
+; USE: ![[SW_BB15_IRR_LOOP]] = !{!"loop_header_weight", i64 100}
+; USE: ![[INDIRECTGOTO_IRR_LOOP]] = !{!"loop_header_weight", i64 400}

Added: llvm/trunk/test/Transforms/PGOProfile/landingpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/landingpad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/landingpad.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/landingpad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,129 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: llvm-profdata merge %S/Inputs/landingpad.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at val = global i32 0, align 4
+ at _ZTIi = external constant i8*
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_bar = private constant [3 x i8] c"bar"
+; GEN: @__profn_foo = private constant [3 x i8] c"foo"
+
+define i32 @bar(i32 %i) {
+entry:
+; GEN: entry:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_bar, i32 0, i32 0), i64 24868915205, i32 2, i32 0)
+  %rem = srem i32 %i, 3
+  %tobool = icmp ne i32 %rem, 0
+  br i1 %tobool, label %if.then, label %if.end
+; USE: br i1 %tobool, label %if.then, label %if.end
+; USE-SAME: !prof ![[BW_BAR_ENTRY:[0-9]+]]
+
+if.then:
+; GEN: if.then:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_bar, i32 0, i32 0), i64 24868915205, i32 2, i32 1)
+  %exception = call i8* @__cxa_allocate_exception(i64 4)
+  %tmp = bitcast i8* %exception to i32*
+  store i32 %i, i32* %tmp, align 16
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+  unreachable
+
+if.end:
+; GEN: if.end:
+; GEN-NOT: call void @llvm.instrprof.increment
+; GEN: ret i32
+  ret i32 0
+}
+
+declare i8* @__cxa_allocate_exception(i64)
+
+declare void @__cxa_throw(i8*, i8*, i8*)
+
+define i32 @foo(i32 %i) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+; GEN: entry:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %rem = srem i32 %i, 2
+  %tobool = icmp ne i32 %rem, 0
+  br i1 %tobool, label %if.then, label %if.end
+; USE: br i1 %tobool, label %if.then, label %if.end
+; USE-SAME: !prof ![[BW_FOO_ENTRY:[0-9]+]]
+
+if.then:
+; GEN: if.then:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %mul = mul nsw i32 %i, 7
+  %call = invoke i32 @bar(i32 %mul)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+; GEN: invoke.cont:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 59130013419, i32 4, i32 1)
+  br label %if.end
+
+lpad:
+; GEN: lpad:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %tmp = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+  %tmp1 = extractvalue { i8*, i32 } %tmp, 0
+  %tmp2 = extractvalue { i8*, i32 } %tmp, 1
+  br label %catch.dispatch
+
+catch.dispatch:
+; GEN: catch.dispatch:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %tmp3 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
+  %matches = icmp eq i32 %tmp2, %tmp3
+  br i1 %matches, label %catch, label %eh.resume
+; USE: br i1 %matches, label %catch, label %eh.resume
+; USE-SAME: !prof ![[BW_CATCH_DISPATCH:[0-9]+]]
+
+catch:
+; GEN: catch:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 59130013419, i32 4, i32 2)
+  %tmp4 = call i8* @__cxa_begin_catch(i8* %tmp1)
+  %tmp5 = bitcast i8* %tmp4 to i32*
+  %tmp6 = load i32, i32* %tmp5, align 4
+  %tmp7 = load i32, i32* @val, align 4
+  %sub = sub nsw i32 %tmp7, %tmp6
+  store i32 %sub, i32* @val, align 4
+  call void @__cxa_end_catch()
+  br label %try.cont
+
+try.cont:
+; GEN: try.cont:
+; GEN-NOT: call void @llvm.instrprof.increment
+  ret i32 -1
+
+if.end:
+; GEN: if.end:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 59130013419, i32 4, i32 0)
+  %tmp8 = load i32, i32* @val, align 4
+  %add = add nsw i32 %tmp8, %i
+  store i32 %add, i32* @val, align 4
+  br label %try.cont
+
+eh.resume:
+; GEN: eh.resume:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 59130013419, i32 4, i32 3)
+  %lpad.val = insertvalue { i8*, i32 } undef, i8* %tmp1, 0
+  %lpad.val3 = insertvalue { i8*, i32 } %lpad.val, i32 %tmp2, 1
+  resume { i8*, i32 } %lpad.val3
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare i32 @llvm.eh.typeid.for(i8*)
+
+declare i8* @__cxa_begin_catch(i8*)
+
+declare void @__cxa_end_catch()
+
+; USE: ![[BW_BAR_ENTRY]] = !{!"branch_weights", i32 2, i32 1}
+; USE: ![[BW_FOO_ENTRY]] = !{!"branch_weights", i32 3, i32 2}
+; USE: ![[BW_CATCH_DISPATCH]] = !{!"branch_weights", i32 2, i32 0}

Added: llvm/trunk/test/Transforms/PGOProfile/large_count_remarks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/large_count_remarks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/large_count_remarks.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/large_count_remarks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: llvm-profdata merge %S/Inputs/large_count_remarks.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -pass-remarks=pgo-instrumentation -pgo-emit-branch-prob -S 2>&1| FileCheck %s --check-prefix=ANALYSIS
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -pass-remarks=pgo-instrumentation -pgo-emit-branch-prob -S 2>&1| FileCheck %s --check-prefix=ANALYSIS
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @test(i32 %i) {
+entry:
+  %cmp = icmp sgt i32 %i, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %add = add nsw i32 %i, 2
+  br label %if.end
+
+if.end:
+  %retv = phi i32 [ %add, %if.then ], [ %i, %entry ]
+  ret i32 %retv
+}
+
+; ANALYSIS:remark: <unknown>:0:0: sgt_i32_Zero {{.*}}50.00% (total count : 40000000000)

Added: llvm/trunk/test/Transforms/PGOProfile/loop1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/loop1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/loop1.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/loop1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: llvm-profdata merge %S/Inputs/loop1.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_test_simple_for = private constant [15 x i8] c"test_simple_for"
+
+define i32 @test_simple_for(i32 %n) {
+entry:
+; GEN: entry:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @__profn_test_simple_for, i32 0, i32 0), i64 34137660316, i32 2, i32 1)
+  br label %for.cond
+
+for.cond:
+; GEN: for.cond:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %i = phi i32 [ 0, %entry ], [ %inc1, %for.inc ]
+  %sum = phi i32 [ 1, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp slt i32 %i, %n
+  br i1 %cmp, label %for.body, label %for.end
+; USE: br i1 %cmp, label %for.body, label %for.end
+; USE-SAME: !prof ![[BW_FOR_COND:[0-9]+]]
+; USE: ![[BW_FOR_COND]] = !{!"branch_weights", i32 96, i32 4}
+
+for.body:
+; GEN: for.body:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %inc = add nsw i32 %sum, 1
+  br label %for.inc
+
+for.inc:
+; GEN: for.inc:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @__profn_test_simple_for, i32 0, i32 0), i64 34137660316, i32 2, i32 0)
+  %inc1 = add nsw i32 %i, 1
+  br label %for.cond
+
+for.end:
+; GEN: for.end:
+; GEN-NOT: call void @llvm.instrprof.increment
+; GEN: ret i32
+  ret i32 %sum
+}

Added: llvm/trunk/test/Transforms/PGOProfile/loop2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/loop2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/loop2.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/loop2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: llvm-profdata merge %S/Inputs/loop2.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_test_nested_for = private constant [15 x i8] c"test_nested_for"
+
+define i32 @test_nested_for(i32 %r, i32 %s) {
+entry:
+; GEN: entry:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @__profn_test_nested_for, i32 0, i32 0), i64 53929068288, i32 3, i32 2)
+  br label %for.cond.outer
+
+for.cond.outer:
+; GEN: for.cond.outer:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %i.0 = phi i32 [ 0, %entry ], [ %inc.2, %for.inc.outer ]
+  %sum.0 = phi i32 [ 1, %entry ], [ %sum.1, %for.inc.outer ]
+  %cmp = icmp slt i32 %i.0, %r
+  br i1 %cmp, label %for.body.outer, label %for.end.outer
+; USE: br i1 %cmp, label %for.body.outer, label %for.end.outer
+; USE-SAME: !prof ![[BW_FOR_COND_OUTER:[0-9]+]]
+
+for.body.outer:
+; GEN: for.body.outer:
+; GEN-NOT: call void @llvm.instrprof.increment
+  br label %for.cond.inner
+
+for.cond.inner:
+; GEN: for.cond.inner:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %j.0 = phi i32 [ 0, %for.body.outer ], [ %inc.1, %for.inc.inner ]
+  %sum.1 = phi i32 [ %sum.0, %for.body.outer ], [ %inc, %for.inc.inner ]
+  %cmp2 = icmp slt i32 %j.0, %s
+  br i1 %cmp2, label %for.body.inner, label %for.end.inner
+; USE: br i1 %cmp2, label %for.body.inner, label %for.end.inner
+; USE-SAME: !prof ![[BW_FOR_COND_INNER:[0-9]+]]
+
+for.body.inner:
+; GEN: for.body.inner:
+; GEN-NOT: call void @llvm.instrprof.increment
+  %inc = add nsw i32 %sum.1, 1
+  br label %for.inc.inner
+
+for.inc.inner:
+; GEN: for.inc.inner:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @__profn_test_nested_for, i32 0, i32 0), i64 53929068288, i32 3, i32 0)
+  %inc.1 = add nsw i32 %j.0, 1
+  br label %for.cond.inner
+
+for.end.inner:
+; GEN: for.end.inner:
+  br label %for.inc.outer
+
+for.inc.outer:
+; GEN: for.inc.outer:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @__profn_test_nested_for, i32 0, i32 0), i64 53929068288, i32 3, i32 1)
+  %inc.2 = add nsw i32 %i.0, 1
+  br label %for.cond.outer
+
+for.end.outer:
+; GEN: for.end.outer:
+; GEN-NOT: call void @llvm.instrprof.increment
+; GEN: ret i32
+  ret i32 %sum.0
+}
+
+; USE-DAG: ![[BW_FOR_COND_OUTER]] = !{!"branch_weights", i32 10, i32 6}
+; USE-DAG: ![[BW_FOR_COND_INNER]] = !{!"branch_weights", i32 33, i32 10}
+

Added: llvm/trunk/test/Transforms/PGOProfile/memcpy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/memcpy.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/memcpy.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/memcpy.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -pgo-instr-gen -instrprof -S | FileCheck %s
+; RUN: opt <%s -passes=pgo-instr-gen,instrprof -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 @foo(i8* %dst, i8* %src, i32* %a, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %add, %for.cond1 ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.cond1, label %for.end6
+
+for.cond1:
+  %j.0 = phi i32 [ %inc, %for.body3 ], [ 0, %for.cond ]
+  %idx.ext = sext i32 %i.0 to i64
+  %add.ptr = getelementptr inbounds i32, i32* %a, i64 %idx.ext
+  %0 = load i32, i32* %add.ptr, align 4
+  %cmp2 = icmp slt i32 %j.0, %0
+  %add = add nsw i32 %i.0, 1
+  br i1 %cmp2, label %for.body3, label %for.cond
+
+for.body3:
+  %conv = sext i32 %add to i64
+; CHECK: call void @__llvm_profile_instrument_range(i64 %conv, i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_foo to i8*), i32 0, i64 0, i64 8, i64 8192)
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false)
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end6:
+  ret void
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)

Added: llvm/trunk/test/Transforms/PGOProfile/memop_clone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/memop_clone.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/memop_clone.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/memop_clone.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -pgo-memop-opt -verify-dom-info -S | FileCheck %s
+
+define i32 @test(i8* %a, i8* %b) !prof !1 {
+; CHECK_LABEL: test
+; CHECK: MemOP.Case.3:
+; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* undef, i8* %a, i32 3, i1 false)
+; CHECK: MemOP.Case.2:
+; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* undef, i8* %a, i32 2, i1 false)
+; CHECK: MemOP.Default:
+; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* undef, i8* %a, i32 undef, i1 false)
+; CHECK: MemOP.Case.33:
+; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* undef, i8* %b, i64 3, i1 false)
+; CHECK  MemOP.Case.24:
+; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* undef, i8* %b, i64 2, i1 false)
+; CHECK: MemOP.Default2:
+; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* undef, i8* %b, i64 undef, i1 false)
+  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* undef, i8* %a, i32 undef, i1 false), !prof !2
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* undef, i8* %b, i64 undef, i1 false), !prof !2
+  unreachable
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1)
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)
+
+!1 = !{!"function_entry_count", i64 5170}
+!2 = !{!"VP", i32 1, i64 2585, i64 3, i64 1802, i64 2, i64 783}
+

Added: llvm/trunk/test/Transforms/PGOProfile/memop_size_annotation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/memop_size_annotation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/memop_size_annotation.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/memop_size_annotation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: llvm-profdata merge %S/Inputs/memop_size_annotation.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -memop-max-annotations=9 -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefixes=MEMOP_ANNOTATION,MEMOP_ANNOTATION9
+; RUN: opt < %s -passes=pgo-instr-use -memop-max-annotations=9 -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefixes=MEMOP_ANNOTATION,MEMOP_ANNOTATION9
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefixes=MEMOP_ANNOTATION,MEMOP_ANNOTATION4
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefixes=MEMOP_ANNOTATION,MEMOP_ANNOTATION4
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i8* %dst, i8* %src, i32* %a, i32 %n) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:
+  br label %for.cond1
+
+for.cond1:
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %idx.ext = sext i32 %i.0 to i64
+  %add.ptr = getelementptr inbounds i32, i32* %a, i64 %idx.ext
+  %0 = load i32, i32* %add.ptr, align 4
+  %cmp2 = icmp slt i32 %j.0, %0
+  br i1 %cmp2, label %for.body3, label %for.end
+
+for.body3:
+  %add = add nsw i32 %i.0, 1
+  %conv = sext i32 %add to i64
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false)
+; MEMOP_ANNOTATION: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false)
+; MEMOP_ANNOTATION-SAME: !prof ![[MEMOP_VALUESITE:[0-9]+]]
+; MEMOP_ANNOTATION9: ![[MEMOP_VALUESITE]] = !{!"VP", i32 1, i64 556, i64 1, i64 99, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72, i64 4, i64 66, i64 5, i64 55, i64 6, i64 44, i64 7, i64 33, i64 8, i64 22}
+; MEMOP_ANNOTATION4: ![[MEMOP_VALUESITE]] = !{!"VP", i32 1, i64 556, i64 1, i64 99, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72}
+  br label %for.inc
+
+for.inc:
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:
+  br label %for.inc4
+
+for.inc4:
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:
+  ret void
+}
+
+declare void @llvm.lifetime.start(i64, i8* nocapture)
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)
+
+declare void @llvm.lifetime.end(i64, i8* nocapture)

Added: llvm/trunk/test/Transforms/PGOProfile/memop_size_from_strlen.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/memop_size_from_strlen.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/memop_size_from_strlen.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/memop_size_from_strlen.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture writeonly, i8* nocapture readonly, i32, i1)
+declare i32 @strlen(i8* nocapture)
+
+; CHECK_LABEL: test
+; CHECK: %1 = zext i32 %c to i64
+; CHECK:  call void @llvm.instrprof.value.profile(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @__profn_test, i32 0, i32 0), i64 12884901887, i64 %1, i32 1, i32 0)
+
+define void @test(i8* %a, i8* %p) {
+  %c = call i32 @strlen(i8* %p)
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %p, i32 %c, i1 false)
+  ret void
+}

Added: llvm/trunk/test/Transforms/PGOProfile/memop_size_opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/memop_size_opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/memop_size_opt.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/memop_size_opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,154 @@
+; RUN: opt < %s -pgo-memop-opt -verify-dom-info -pgo-memop-count-threshold=90 -pgo-memop-percent-threshold=15 -S | FileCheck %s --check-prefix=MEMOP_OPT
+; RUN: opt < %s -passes=pgo-memop-opt -verify-dom-info -pgo-memop-count-threshold=90 -pgo-memop-percent-threshold=15 -S | FileCheck %s --check-prefix=MEMOP_OPT
+; RUN: opt < %s -pgo-memop-opt -verify-dom-info -pgo-memop-count-threshold=90 -pgo-memop-percent-threshold=15 -pass-remarks-with-hotness -pass-remarks-output=%t.opt.yaml -S | FileCheck %s --check-prefix=MEMOP_OPT
+; RUN: FileCheck %s -input-file=%t.opt.yaml --check-prefix=YAML
+; RUN: opt < %s -passes=pgo-memop-opt -verify-dom-info -pgo-memop-count-threshold=90 -pgo-memop-percent-threshold=15 -pass-remarks-with-hotness -pass-remarks-output=%t.opt.yaml -S | FileCheck %s --check-prefix=MEMOP_OPT
+; RUN: FileCheck %s -input-file=%t.opt.yaml --check-prefix=YAML
+
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i8* %dst, i8* %src, i8* %dst2, i8* %src2, i32* %a, i32 %n) !prof !27 {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %inc5, %for.inc4 ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end6, !prof !28
+
+for.body:
+  br label %for.cond1
+
+for.cond1:
+  %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.inc ]
+  %idx.ext = sext i32 %i.0 to i64
+  %add.ptr = getelementptr inbounds i32, i32* %a, i64 %idx.ext
+  %0 = load i32, i32* %add.ptr, align 4
+  %cmp2 = icmp slt i32 %j.0, %0
+  br i1 %cmp2, label %for.body3, label %for.end, !prof !29
+
+for.body3:
+  %add = add nsw i32 %i.0, 1
+  %conv = sext i32 %add to i64
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false), !prof !30
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 %conv, i1 false), !prof !31
+  br label %for.inc
+
+; MEMOP_OPT:  switch i64 %conv, label %[[DEFAULT_LABEL:.*]] [
+; MEMOP_OPT:    i64 1, label %[[CASE_1_LABEL:.*]]
+; MEMOP_OPT:  ], !prof [[SWITCH_BW:![0-9]+]] 
+; MEMOP_OPT: [[CASE_1_LABEL]]:
+; MEMOP_OPT:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false)
+; MEMOP_OPT:   br label %[[MERGE_LABEL:.*]]
+; MEMOP_OPT: [[DEFAULT_LABEL]]:
+; MEMOP_OPT:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false), !prof [[NEWVP:![0-9]+]]
+; MEMOP_OPT:   br label %[[MERGE_LABEL]]
+; MEMOP_OPT: [[MERGE_LABEL]]:
+; MEMOP_OPT:  switch i64 %conv, label %[[DEFAULT_LABEL2:.*]] [
+; MEMOP_OPT:    i64 1, label %[[CASE_1_LABEL2:.*]]
+; MEMOP_OPT:  ], !prof [[SWITCH_BW:![0-9]+]] 
+; MEMOP_OPT: [[CASE_1_LABEL2]]:
+; MEMOP_OPT:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 1, i1 false)
+; MEMOP_OPT:   br label %[[MERGE_LABEL2:.*]]
+; MEMOP_OPT: [[DEFAULT_LABEL2]]:
+; MEMOP_OPT:   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 %conv, i1 false), !prof [[NEWVP]]
+; MEMOP_OPT:   br label %[[MERGE_LABEL2]]
+; MEMOP_OPT: [[MERGE_LABEL2]]:
+; MEMOP_OPT:   br label %for.inc
+; MEMOP_OPT: [[SWITCH_BW]] = !{!"branch_weights", i32 457, i32 99}
+; Should be 457 total left (original total count 556, minus 99 from specialized
+; value 1, which is removed from VP array. Also, we only end up with 5 total
+; values, since the default max number of promotions is 5 and therefore
+; the rest of the values are ignored when extracting the VP metadata.
+; MEMOP_OPT: [[NEWVP]] = !{!"VP", i32 1, i64 457, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72, i64 4, i64 66}
+
+for.inc:
+  %inc = add nsw i32 %j.0, 1
+  br label %for.cond1
+
+for.end:
+  br label %for.inc4
+
+for.inc4:
+  %inc5 = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end6:
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 579}
+!4 = !{!"MaxCount", i64 556}
+!5 = !{!"MaxInternalCount", i64 20}
+!6 = !{!"MaxFunctionCount", i64 556}
+!7 = !{!"NumCounts", i64 6}
+!8 = !{!"NumFunctions", i64 3}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11, !12, !13, !14, !15, !16, !16, !17, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26}
+!11 = !{i32 10000, i64 556, i32 1}
+!12 = !{i32 100000, i64 556, i32 1}
+!13 = !{i32 200000, i64 556, i32 1}
+!14 = !{i32 300000, i64 556, i32 1}
+!15 = !{i32 400000, i64 556, i32 1}
+!16 = !{i32 500000, i64 556, i32 1}
+!17 = !{i32 600000, i64 556, i32 1}
+!18 = !{i32 700000, i64 556, i32 1}
+!19 = !{i32 800000, i64 556, i32 1}
+!20 = !{i32 900000, i64 556, i32 1}
+!21 = !{i32 950000, i64 556, i32 1}
+!22 = !{i32 990000, i64 20, i32 2}
+!23 = !{i32 999000, i64 1, i32 5}
+!24 = !{i32 999900, i64 1, i32 5}
+!25 = !{i32 999990, i64 1, i32 5}
+!26 = !{i32 999999, i64 1, i32 5}
+!27 = !{!"function_entry_count", i64 1}
+!28 = !{!"branch_weights", i32 20, i32 1}
+!29 = !{!"branch_weights", i32 556, i32 20}
+!30 = !{!"VP", i32 1, i64 556, i64 1, i64 99, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72, i64 4, i64 66, i64 5, i64 55, i64 6, i64 44, i64 7, i64 33, i64 8, i64 22}
+!31 = !{!"VP", i32 1, i64 556, i64 1, i64 99, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72, i64 4, i64 66, i64 5, i64 55, i64 6, i64 44, i64 7, i64 33, i64 8, i64 22}
+
+declare void @llvm.lifetime.start(i64, i8* nocapture)
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)
+
+declare void @llvm.lifetime.end(i64, i8* nocapture)
+
+; YAML:      --- !Passed
+; YAML-NEXT: Pass:            pgo-memop-opt
+; YAML-NEXT: Name:            memopt-opt
+; YAML-NEXT: Function:        foo
+; YAML-NEXT: Hotness:         0
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'optimized '
+; YAML-NEXT:   - Intrinsic:       memcpy
+; YAML-NEXT:   - String:          ' with count '
+; YAML-NEXT:   - Count:           '99'
+; YAML-NEXT:   - String:          ' out of '
+; YAML-NEXT:   - Total:           '556'
+; YAML-NEXT:   - String:          ' for '
+; YAML-NEXT:   - Versions:        '1'
+; YAML-NEXT:   - String:          ' versions'
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Passed
+; YAML-NEXT: Pass:            pgo-memop-opt
+; YAML-NEXT: Name:            memopt-opt
+; YAML-NEXT: Function:        foo
+; YAML-NEXT: Hotness:         0
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'optimized '
+; YAML-NEXT:   - Intrinsic:       memcpy
+; YAML-NEXT:   - String:          ' with count '
+; YAML-NEXT:   - Count:           '99'
+; YAML-NEXT:   - String:          ' out of '
+; YAML-NEXT:   - Total:           '556'
+; YAML-NEXT:   - String:          ' for '
+; YAML-NEXT:   - Versions:        '1'
+; YAML-NEXT:   - String:          ' versions'
+; YAML-NEXT: ...

Added: llvm/trunk/test/Transforms/PGOProfile/memop_size_opt_zero.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/memop_size_opt_zero.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/memop_size_opt_zero.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/memop_size_opt_zero.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; Test to ensure the pgo memop optimization pass doesn't try to scale
+; up a value profile with a 0 count, which would lead to divide by 0.
+; RUN: opt < %s -passes=pgo-memop-opt -verify-dom-info -pgo-memop-count-threshold=1 -S | FileCheck %s --check-prefix=MEMOP_OPT
+; RUN: opt < %s -pgo-memop-opt -verify-dom-info -pgo-memop-count-threshold=1 -S | FileCheck %s --check-prefix=MEMOP_OPT
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo(i8* %dst, i8* %src, i64 %conv) !prof !0 {
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false), !prof !1
+  ret void
+}
+
+; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i1 false), !prof !1
+
+!0 = !{!"function_entry_count", i64 1}
+!1 = !{!"VP", i32 1, i64 0, i64 1, i64 0, i64 2, i64 0, i64 3, i64 0, i64 9, i64 0, i64 4, i64 0, i64 5, i64 0, i64 6, i64 0, i64 7, i64 0, i64 8, i64 0}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)

Added: llvm/trunk/test/Transforms/PGOProfile/multiple_hash_profile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/multiple_hash_profile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/multiple_hash_profile.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/multiple_hash_profile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: llvm-profdata merge %S/Inputs/multiple_hash_profile.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata  -S | FileCheck %s
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$_Z3fooi = comdat any
+
+ at g2 = local_unnamed_addr global i32 (i32)* null, align 8
+
+define i32 @_Z3bari(i32 %i) {
+entry:
+  %cmp = icmp sgt i32 %i, 2
+  %mul = select i1 %cmp, i32 1, i32 %i
+  %retval.0 = mul nsw i32 %mul, %i
+  ret i32 %retval.0
+}
+
+define void @_Z4m2f1v() {
+entry:
+  store i32 (i32)* @_Z3fooi, i32 (i32)** @g2, align 8
+  ret void
+}
+
+define linkonce_odr i32 @_Z3fooi(i32 %i) comdat {
+entry:
+  %cmp.i = icmp sgt i32 %i, 2
+  %mul.i = select i1 %cmp.i, i32 1, i32 %i
+; CHECK: %mul.i = select i1 %cmp.i, i32 1, i32 %i
+; CHECK-SAME: !prof ![[BW:[0-9]+]]
+; CHECK: ![[BW]] = !{!"branch_weights", i32 12, i32 6}
+  %retval.0.i = mul nsw i32 %mul.i, %i
+  ret i32 %retval.0.i
+}
+
+

Added: llvm/trunk/test/Transforms/PGOProfile/noreturncall.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/noreturncall.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/noreturncall.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/noreturncall.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: llvm-profdata merge %S/Inputs/noreturncall.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; REQUIRES: asserts
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @bar0(i32)
+
+define i32 @bar2(i32 %i) {
+entry:
+  unreachable
+}
+
+define i32 @foo(i32 %i, i32 %j, i32 %k) {
+entry:
+  %cmp = icmp slt i32 %i, 999
+  br i1 %cmp, label %if.then, label %if.end
+; USE: br i1 %cmp, label %if.then, label %if.end
+; USE-SAME: !prof ![[BW_ENTRY:[0-9]+]]
+
+if.then:
+  %call = call i32 @bar0(i32 %i)
+  br label %if.end
+
+if.end:
+  %ret.0 = phi i32 [ %call, %if.then ], [ 0, %entry ]
+  %cmp1 = icmp sgt i32 %j, 1000
+  %cmp3 = icmp sgt i32 %k, 99
+  %or.cond = and i1 %cmp1, %cmp3
+  br i1 %or.cond, label %if.then4, label %if.end7
+; USE: br i1 %or.cond, label %if.then4, label %if.end7
+; USE-SAME: !prof ![[BW_IF:[0-9]+]]
+
+if.then4:
+  %call5 = call i32 @bar2(i32 undef)
+  br label %if.end7
+
+if.end7:
+  %mul = mul nsw i32 %ret.0, %ret.0
+  ret i32 %mul
+}
+; USE: ![[BW_ENTRY]] = !{!"branch_weights", i32 21, i32 0}
+; USE: ![[BW_IF]] = !{!"branch_weights", i32 0, i32 21}

Added: llvm/trunk/test/Transforms/PGOProfile/preinline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/preinline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/preinline.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/preinline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -O2 -pgo-kind=pgo-instr-gen-pipeline -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -O2 -pgo-kind=pgo-instr-gen-pipeline -profile-file=default.profraw -S | FileCheck %s --check-prefix=GEN
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @foo(i32 %i) {
+entry:
+; GEN: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_foo
+; GEN-NOT: %pgocount.i = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__stdin__bar
+  %call = call i32 @bar()
+  %add = add nsw i32 %i, %call
+  ret i32 %add
+}
+
+define internal i32 @bar() {
+; check that bar is inlined into foo and eliminiated from IR.
+; GEN-NOT: define internal i32 @bar
+entry:
+  %call = call i32 (...) @bar1()
+  ret i32 %call
+}
+
+declare i32 @bar1(...)

Added: llvm/trunk/test/Transforms/PGOProfile/remap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/remap.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/remap.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/remap.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: llvm-profdata merge %S/Inputs/remap.proftext -o %t.profdata
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-test-profile-remapping-file=%S/Inputs/remap.map -S | FileCheck %s --check-prefix=USE
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @_ZN3foo3barERKN1M1XINS_6detail3quxEEE(i32 %i) {
+; USE-LABEL: @_ZN3foo3barERKN1M1XINS_6detail3quxEEE
+; USE-SAME: !prof ![[FUNC_ENTRY_COUNT:[0-9]+]]
+entry:
+  %cmp = icmp sgt i32 %i, 0
+  br i1 %cmp, label %if.then, label %if.end
+; USE: br i1 %cmp, label %if.then, label %if.end
+; USE-SAME: !prof ![[BW_ENTRY:[0-9]+]]
+
+if.then:
+  %add = add nsw i32 %i, 2
+  br label %if.end
+
+if.end:
+  %retv = phi i32 [ %add, %if.then ], [ %i, %entry ]
+  ret i32 %retv
+}
+
+; USE-DAG: {{![0-9]+}} = !{i32 1, !"ProfileSummary", {{![0-9]+}}}
+; USE-DAG: {{![0-9]+}} = !{!"DetailedSummary", {{![0-9]+}}}
+; USE-DAG: ![[FUNC_ENTRY_COUNT]] = !{!"function_entry_count", i64 3}
+; USE-DAG: ![[BW_ENTRY]] = !{!"branch_weights", i32 2, i32 1}

Added: llvm/trunk/test/Transforms/PGOProfile/select1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/select1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/select1.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/select1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt < %s -pgo-instr-gen -pgo-instr-select=true -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -pgo-instr-select=true -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -pgo-instr-gen -pgo-instr-select=false -S | FileCheck %s --check-prefix=NOSELECT
+; RUN: opt < %s -passes=pgo-instr-gen -pgo-instr-select=false -S | FileCheck %s --check-prefix=NOSELECT
+; RUN: llvm-profdata merge %S/Inputs/select1.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-instr-select=true -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-instr-select=true -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @test_br_2(i32 %i) {
+entry:
+  %cmp = icmp sgt i32 %i, 0
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %add = add nsw i32 %i, 2
+;GEN: %[[STEP:[0-9]+]] = zext i1 %cmp to i64
+;GEN: call void @llvm.instrprof.increment.step({{.*}} i32 3, i32 2, i64 %[[STEP]])
+;NOSELECT-NOT: call void @llvm.instrprof.increment.step
+  %s = select i1 %cmp, i32 %add, i32 0
+;USE: select i1 %cmp{{.*}}, !prof ![[BW_ENTRY:[0-9]+]]
+;USE: ![[BW_ENTRY]] = !{!"branch_weights", i32 1, i32 3}
+
+  br label %if.end
+
+if.else:
+  %sub = sub nsw i32 %i, 2
+  br label %if.end
+
+if.end:
+  %retv = phi i32 [ %add, %if.then ], [ %sub, %if.else ]
+  ret i32 %retv
+}

Added: llvm/trunk/test/Transforms/PGOProfile/select2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/select2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/select2.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/select2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: llvm-profdata merge %S/Inputs/select2.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-instr-select=true -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-instr-select=true -S | FileCheck %s --check-prefix=USE
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @foo(i32 %n) {
+;USE: define i32 @foo(i32 %n) !prof ![[ENTRY_COUNT:[0-9]+]] {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+;USE:  br i1 %cmp, label %for.body, label %for.end, !prof ![[BW_FOR_BR:[0-9]+]]
+
+for.body:
+  %cmp1 = icmp sgt i32 %sum.0, 10
+  %cond = select i1 %cmp1, i32 20, i32 -10
+;USE:  %cond = select i1 %cmp1, i32 20, i32 -10, !prof ![[BW_FOR_SELECT:[0-9]+]]
+  %add = add nsw i32 %sum.0, %cond
+  br label %for.inc
+
+for.inc:
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  ret i32 %sum.0
+}
+
+;USE: ![[ENTRY_COUNT]] = !{!"function_entry_count", i64 3}
+;USE: ![[BW_FOR_BR]] = !{!"branch_weights", i32 800, i32 3}
+;USE: ![[BW_FOR_SELECT]] = !{!"branch_weights", i32 300, i32 500}

Added: llvm/trunk/test/Transforms/PGOProfile/select_hash_conflict.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/select_hash_conflict.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/select_hash_conflict.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/select_hash_conflict.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,97 @@
+; RUN: llvm-profdata merge %S/Inputs/select_hash_conflict.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-instr-select=true -S | FileCheck %s
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -pgo-instr-select=true -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 a = common dso_local local_unnamed_addr global [16 x i32] zeroinitializer, align 16
+ at c0 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c1 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c2 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c3 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c4 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c5 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c6 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c7 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c8 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c9 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c10 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c11 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c12 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c13 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c14 = common dso_local local_unnamed_addr global i8 0, align 1
+ at c15 = common dso_local local_unnamed_addr global i8 0, align 1
+
+define i32 @foo(i32 %n) {
+entry:
+  %0 = load i8, i8* @c0, align 1
+  %tobool = icmp eq i8 %0, 0
+  %cond = select i1 %tobool, i32 2, i32 1
+  store i32 %cond, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 0), align 16
+  %1 = load i8, i8* @c1, align 1
+  %tobool2 = icmp eq i8 %1, 0
+  %cond3 = select i1 %tobool2, i32 2, i32 1
+  store i32 %cond3, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 1), align 4
+  %2 = load i8, i8* @c2, align 1
+  %tobool5 = icmp eq i8 %2, 0
+  %cond6 = select i1 %tobool5, i32 2, i32 1
+  store i32 %cond6, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 2), align 8
+  %3 = load i8, i8* @c3, align 1
+  %tobool8 = icmp eq i8 %3, 0
+  %cond9 = select i1 %tobool8, i32 2, i32 1
+  store i32 %cond9, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 3), align 4
+  %4 = load i8, i8* @c4, align 1
+  %tobool11 = icmp eq i8 %4, 0
+  %cond12 = select i1 %tobool11, i32 2, i32 1
+  store i32 %cond12, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 4), align 16
+  %5 = load i8, i8* @c5, align 1
+  %tobool14 = icmp eq i8 %5, 0
+  %cond15 = select i1 %tobool14, i32 2, i32 1
+  store i32 %cond15, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 5), align 4
+  %6 = load i8, i8* @c6, align 1
+  %tobool17 = icmp eq i8 %6, 0
+  %cond18 = select i1 %tobool17, i32 2, i32 1
+  store i32 %cond18, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 6), align 8
+  %7 = load i8, i8* @c7, align 1
+  %tobool20 = icmp eq i8 %7, 0
+  %cond21 = select i1 %tobool20, i32 2, i32 1
+  store i32 %cond21, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 7), align 4
+  %8 = load i8, i8* @c8, align 1
+  %tobool23 = icmp eq i8 %8, 0
+  %cond24 = select i1 %tobool23, i32 2, i32 1
+  store i32 %cond24, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 8), align 16
+  %9 = load i8, i8* @c9, align 1
+  %tobool26 = icmp eq i8 %9, 0
+  %cond27 = select i1 %tobool26, i32 2, i32 1
+  store i32 %cond27, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 9), align 4
+  %10 = load i8, i8* @c10, align 1
+  %tobool29 = icmp eq i8 %10, 0
+  %cond30 = select i1 %tobool29, i32 2, i32 1
+  store i32 %cond30, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 10), align 8
+  %11 = load i8, i8* @c11, align 1
+  %tobool32 = icmp eq i8 %11, 0
+  %cond33 = select i1 %tobool32, i32 2, i32 1
+  store i32 %cond33, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 11), align 4
+  %12 = load i8, i8* @c12, align 1
+  %tobool35 = icmp eq i8 %12, 0
+  %cond36 = select i1 %tobool35, i32 2, i32 1
+  store i32 %cond36, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 12), align 16
+  %13 = load i8, i8* @c13, align 1
+  %tobool38 = icmp eq i8 %13, 0
+  %cond39 = select i1 %tobool38, i32 2, i32 1
+  store i32 %cond39, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 13), align 4
+  %14 = load i8, i8* @c14, align 1
+  %tobool41 = icmp eq i8 %14, 0
+  %cond42 = select i1 %tobool41, i32 2, i32 1
+  store i32 %cond42, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 14), align 8
+  %15 = load i8, i8* @c15, align 1
+  %tobool44 = icmp eq i8 %15, 0
+  %cond45 = select i1 %tobool44, i32 2, i32 1
+  store i32 %cond45, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a, i64 0, i64 15), align 4
+  ret i32 %n
+}
+; CHECK-LABEL: define i32 @foo(i32 %n)
+; We should skip the profile.
+; CHECK-NOT: %{{.*}} = select i1 %{{.*}}, i32 2, i32 1, !prof
+

Added: llvm/trunk/test/Transforms/PGOProfile/single_bb.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/single_bb.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/single_bb.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/single_bb.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_single_bb = private constant [9 x i8] c"single_bb"
+
+define i32 @single_bb() {
+entry:
+; GEN: entry:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @__profn_single_bb, i32 0, i32 0), i64 12884901887, i32 1, i32 0)
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/PGOProfile/split-indirectbr-critical-edges.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/split-indirectbr-critical-edges.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/split-indirectbr-critical-edges.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/split-indirectbr-critical-edges.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s
+
+; Function Attrs: norecurse nounwind readnone uwtable
+define i32 @bar(i32 %v) local_unnamed_addr #0 {
+entry:
+  %mul = shl nsw i32 %v, 1
+  ret i32 %mul
+}
+
+; Function Attrs: norecurse nounwind readonly uwtable
+define i32 @foo(i8* nocapture readonly %p) #1 {
+entry:
+  %targets = alloca [256 x i8*], align 16
+  %arrayidx1 = getelementptr inbounds [256 x i8*], [256 x i8*]* %targets, i64 0, i64 93
+  store i8* blockaddress(@foo, %if.end), i8** %arrayidx1, align 8
+  br label %for.cond2
+
+for.cond2:                                        ; preds = %if.end, %for.cond2, %entry
+; CHECK: for.cond2:                                        ; preds = %.split1
+  %p.addr.0 = phi i8* [ %p, %entry ], [ %incdec.ptr5, %if.end ], [ %incdec.ptr, %for.cond2 ]
+  %incdec.ptr = getelementptr inbounds i8, i8* %p.addr.0, i64 1
+  %0 = load i8, i8* %p.addr.0, align 1
+  %cond = icmp eq i8 %0, 93
+  br i1 %cond, label %if.end.preheader, label %for.cond2
+
+if.end.preheader:                                 ; preds = %for.cond2
+  br label %if.end
+
+if.end:                                           ; preds = %if.end.preheader, %if.end
+; CHECK: if.end:                                           ; preds = %.split1
+  %p.addr.1 = phi i8* [ %incdec.ptr5, %if.end ], [ %incdec.ptr, %if.end.preheader ]
+  %incdec.ptr5 = getelementptr inbounds i8, i8* %p.addr.1, i64 1
+  %1 = load i8, i8* %p.addr.1, align 1
+  %idxprom6 = zext i8 %1 to i64
+  %arrayidx7 = getelementptr inbounds [256 x i8*], [256 x i8*]* %targets, i64 0, i64 %idxprom6
+  %2 = load i8*, i8** %arrayidx7, align 8
+  indirectbr i8* %2, [label %for.cond2, label %if.end]
+; CHECK: indirectbr i8* %2, [label %for.cond2, label %if.end]
+}

Added: llvm/trunk/test/Transforms/PGOProfile/statics_counter_naming.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/statics_counter_naming.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/statics_counter_naming.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/statics_counter_naming.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt %s -pgo-instr-gen -static-func-full-module-prefix=false -S | FileCheck %s --check-prefix=NOPATH
+; RUN: opt %s -passes=pgo-instr-gen -static-func-full-module-prefix=false -S | FileCheck %s --check-prefix=NOPATH
+; RUN: opt %s --pgo-instr-gen -static-func-strip-dirname-prefix=1000 -S | FileCheck %s --check-prefix=NOPATH
+; RUN: opt %s -passes=pgo-instr-gen -static-func-strip-dirname-prefix=1000 -S | FileCheck %s --check-prefix=NOPATH
+; RUN: opt %s --pgo-instr-gen -static-func-strip-dirname-prefix=1 -S | FileCheck %s --check-prefix=HASPATH
+; RUN: opt %s -passes=pgo-instr-gen -static-func-strip-dirname-prefix=1 -S | FileCheck %s --check-prefix=HASPATH
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; NOPATH: @__profn_statics_counter_naming.ll_func = private constant [30 x i8] c"statics_counter_naming.ll:func"
+; HASPATH-NOT: @__profn_statics_counter_naming.ll_func = private constant [30 x i8] c"statics_counter_naming.ll:func"
+
+define internal i32 @func() {
+entry:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/PGOProfile/switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/switch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/switch.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/switch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; RUN: opt < %s -pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefix=GEN
+; RUN: llvm-profdata merge %S/Inputs/switch.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; GEN: $__llvm_profile_raw_version = comdat any
+; GEN: @__llvm_profile_raw_version = constant i64 {{[0-9]+}}, comdat
+; GEN: @__profn_test_switch = private constant [11 x i8] c"test_switch"
+
+define void @test_switch(i32 %i) {
+entry:
+; GEN: entry:
+; GEN-NOT: call void @llvm.instrprof.increment
+  switch i32 %i, label %sw.default [
+    i32 1, label %sw.bb
+    i32 2, label %sw.bb1
+    i32 3, label %sw.bb2
+  ]
+; USE: ]
+; USE-SAME: !prof ![[BW_SWITCH:[0-9]+]]
+; USE: ![[BW_SWITCH]] = !{!"branch_weights", i32 3, i32 2, i32 0, i32 5}
+
+sw.bb:
+; GEN: sw.bb:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__profn_test_switch, i32 0, i32 0), i64 46200943743, i32 4, i32 2)
+  br label %sw.epilog
+
+sw.bb1:
+; GEN: sw.bb1:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__profn_test_switch, i32 0, i32 0), i64 46200943743, i32 4, i32 0)
+  br label %sw.epilog
+
+sw.bb2:
+; GEN: sw.bb2:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__profn_test_switch, i32 0, i32 0), i64 46200943743, i32 4, i32 1)
+  br label %sw.epilog
+
+sw.default:
+; GEN: sw.default:
+; GEN: call void @llvm.instrprof.increment(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__profn_test_switch, i32 0, i32 0), i64 46200943743, i32 4, i32 3)
+  br label %sw.epilog
+
+sw.epilog:
+; GEN: sw.epilog:
+; GEN-NOT: call void @llvm.instrprof.increment
+  ret void
+; GEN: ret void
+}

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_gen.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_gen.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_gen.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_gen.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,88 @@
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary %s -o %t1.bc
+; RUN: opt -module-summary %S/Inputs/thinlto_cspgo_bar_gen.ll -o %t2.bc
+; RUN: llvm-lto2 run -lto-cspgo-profile-file=alloc -lto-cspgo-gen -save-temps -o %t %t1.bc %t2.bc \
+; RUN:   -r=%t1.bc,foo,pl \
+; RUN:   -r=%t1.bc,bar,l \
+; RUN:   -r=%t1.bc,main,plx \
+; RUN:   -r=%t1.bc,__llvm_profile_filename,plx \
+; RUN:   -r=%t1.bc,__llvm_profile_raw_version,plx \
+; RUN:   -r=%t2.bc,bar,pl \
+; RUN:   -r=%t2.bc,odd,pl \
+; RUN:   -r=%t2.bc,even,pl \
+; RUN:   -r=%t2.bc,__llvm_profile_filename,x \
+; RUN:   -r=%t2.bc,__llvm_profile_raw_version,x
+; RUN: llvm-dis %t.1.4.opt.bc -o - | FileCheck %s --check-prefix=CSGEN
+
+; CSGEN: @__profc_
+; CSGEN: @__profd_
+
+source_filename = "cspgo.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+$__llvm_profile_filename = comdat any
+$__llvm_profile_raw_version = comdat any
+ at __llvm_profile_filename = constant [25 x i8] c"pass2/default_%m.profraw\00", comdat
+ at __llvm_profile_raw_version = constant i64 216172782113783812, comdat
+
+define dso_local void @foo() #0 !prof !29 {
+entry:
+  br label %for.body
+
+for.body:
+  %i.06 = phi i32 [ 0, %entry ], [ %add1, %for.body ]
+  tail call void @bar(i32 %i.06)
+  %add = or i32 %i.06, 1
+  tail call void @bar(i32 %add)
+  %add1 = add nuw nsw i32 %i.06, 2
+  %cmp = icmp ult i32 %add1, 200000
+  br i1 %cmp, label %for.body, label %for.end, !prof !30
+
+for.end:
+  ret void
+}
+
+declare dso_local void @bar(i32)
+
+define dso_local i32 @main() !prof !29 {
+entry:
+  tail call void @foo()
+  ret i32 0
+}
+
+attributes #0 = { "target-cpu"="x86-64" }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 500002}
+!5 = !{!"MaxCount", i64 200000}
+!6 = !{!"MaxInternalCount", i64 100000}
+!7 = !{!"MaxFunctionCount", i64 200000}
+!8 = !{!"NumCounts", i64 6}
+!9 = !{!"NumFunctions", i64 4}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27}
+!12 = !{i32 10000, i64 200000, i32 1}
+!13 = !{i32 100000, i64 200000, i32 1}
+!14 = !{i32 200000, i64 200000, i32 1}
+!15 = !{i32 300000, i64 200000, i32 1}
+!16 = !{i32 400000, i64 200000, i32 1}
+!17 = !{i32 500000, i64 100000, i32 4}
+!18 = !{i32 600000, i64 100000, i32 4}
+!19 = !{i32 700000, i64 100000, i32 4}
+!20 = !{i32 800000, i64 100000, i32 4}
+!21 = !{i32 900000, i64 100000, i32 4}
+!22 = !{i32 950000, i64 100000, i32 4}
+!23 = !{i32 990000, i64 100000, i32 4}
+!24 = !{i32 999000, i64 100000, i32 4}
+!25 = !{i32 999900, i64 100000, i32 4}
+!26 = !{i32 999990, i64 100000, i32 4}
+!27 = !{i32 999999, i64 1, i32 6}
+!29 = !{!"function_entry_count", i64 1}
+!30 = !{!"branch_weights", i32 100000, i32 1}

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_use.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_use.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_cspgo_use.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,82 @@
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary %s -o %t1.bc
+; RUN: opt -module-summary %S/Inputs/thinlto_cspgo_bar_use.ll -o %t2.bc
+; RUN: llvm-profdata merge %S/Inputs/thinlto_cs.proftext -o %t3.profdata
+; RUN: llvm-lto2 run -lto-cspgo-profile-file=%t3.profdata -save-temps -o %t %t1.bc %t2.bc \
+; RUN:   -r=%t1.bc,foo,pl \
+; RUN:   -r=%t1.bc,bar,l \
+; RUN:   -r=%t1.bc,main,plx \
+; RUN:   -r=%t2.bc,bar,pl \
+; RUN:   -r=%t2.bc,odd,pl \
+; RUN:   -r=%t2.bc,even,pl
+; RUN: llvm-dis %t.1.4.opt.bc -o - | FileCheck %s --check-prefix=CSUSE
+
+; CSUSE: {{![0-9]+}} = !{i32 1, !"ProfileSummary", {{![0-9]+}}}
+; CSUSE: {{![0-9]+}} = !{i32 1, !"CSProfileSummary", {{![0-9]+}}}
+; CSUSE-DAG: {{![0-9]+}} = !{!"branch_weights", i32 100000, i32 0}
+; CSUSE-DAG: {{![0-9]+}} = !{!"branch_weights", i32 0, i32 100000}
+
+source_filename = "cspgo.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define dso_local void @foo() #0 !prof !29 {
+entry:
+  br label %for.body
+
+for.body:
+  %i.06 = phi i32 [ 0, %entry ], [ %add1, %for.body ]
+  tail call void @bar(i32 %i.06)
+  %add = or i32 %i.06, 1
+  tail call void @bar(i32 %add)
+  %add1 = add nuw nsw i32 %i.06, 2
+  %cmp = icmp ult i32 %add1, 200000
+  br i1 %cmp, label %for.body, label %for.end, !prof !30
+
+for.end:
+  ret void
+}
+
+declare dso_local void @bar(i32)
+
+define dso_local i32 @main() !prof !29 {
+entry:
+  tail call void @foo()
+  ret i32 0
+}
+
+attributes #0 = { "target-cpu"="x86-64" }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 500002}
+!5 = !{!"MaxCount", i64 200000}
+!6 = !{!"MaxInternalCount", i64 100000}
+!7 = !{!"MaxFunctionCount", i64 200000}
+!8 = !{!"NumCounts", i64 6}
+!9 = !{!"NumFunctions", i64 4}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27}
+!12 = !{i32 10000, i64 200000, i32 1}
+!13 = !{i32 100000, i64 200000, i32 1}
+!14 = !{i32 200000, i64 200000, i32 1}
+!15 = !{i32 300000, i64 200000, i32 1}
+!16 = !{i32 400000, i64 200000, i32 1}
+!17 = !{i32 500000, i64 100000, i32 4}
+!18 = !{i32 600000, i64 100000, i32 4}
+!19 = !{i32 700000, i64 100000, i32 4}
+!20 = !{i32 800000, i64 100000, i32 4}
+!21 = !{i32 900000, i64 100000, i32 4}
+!22 = !{i32 950000, i64 100000, i32 4}
+!23 = !{i32 990000, i64 100000, i32 4}
+!24 = !{i32 999000, i64 100000, i32 4}
+!25 = !{i32 999900, i64 100000, i32 4}
+!26 = !{i32 999990, i64 100000, i32 4}
+!27 = !{i32 999999, i64 1, i32 6}
+!29 = !{!"function_entry_count", i64 1}
+!30 = !{!"branch_weights", i32 100000, i32 1}

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/thinlto_indirect_call_promotion.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -o %t4.bc -print-imports 2>&1 | FileCheck %s --check-prefix=IMPORTS
+; IMPORTS-DAG: Import a
+; IMPORTS-DAG: Import c
+
+; RUN: opt %t4.bc -icp-lto -pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+; RUN: opt %t4.bc -icp-lto -pgo-icall-prom -S -pass-remarks=pgo-icall-prom 2>&1 | FileCheck %s --check-prefix=PASS-REMARK
+; PASS-REMARK: Promote indirect call to a with count 1 out of 1
+; PASS-REMARK: Promote indirect call to c.llvm.0 with count 1 out of 1
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = external local_unnamed_addr global void ()*, align 8
+ at bar = external local_unnamed_addr global void ()*, align 8
+
+define i32 @main() local_unnamed_addr {
+entry:
+  %0 = load void ()*, void ()** @foo, align 8
+; ICALL-PROM:   br i1 %{{[0-9]+}}, label %if.true.direct_targ, label %if.false.orig_indirect, !prof [[BRANCH_WEIGHT:![0-9]+]]
+  tail call void %0(), !prof !1
+  %1 = load void ()*, void ()** @bar, align 8
+; ICALL-PROM:   br i1 %{{[0-9]+}}, label %if.true.direct_targ1, label %if.false.orig_indirect2, !prof [[BRANCH_WEIGHT:![0-9]+]]
+  tail call void %1(), !prof !2
+  ret i32 0
+}
+
+!1 = !{!"VP", i32 0, i64 1, i64 -6289574019528802036, i64 1}
+!2 = !{!"VP", i32 0, i64 1, i64 591260329866125152, i64 1}
+
+; Should not have a VP annotation on new indirect call (check before and after
+; branch_weights annotation).
+; ICALL-PROM-NOT: !"VP"
+; ICALL-PROM: [[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1, i32 0}
+; ICALL-PROM-NOT: !"VP"

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/thinlto_samplepgo_icp.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Checks if calls to static target functions are properly imported and promoted
+; by ICP. Note that the GUID in the profile is from the oroginal name.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -o %t4.bc -print-imports 2>&1 | FileCheck %s --check-prefix=IMPORTS
+; IMPORTS: Import _ZL3foov.llvm.0
+; RUN: opt %t4.bc -icp-lto -pgo-icall-prom -S | FileCheck %s --check-prefix=ICALL-PROM
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fptr = local_unnamed_addr global void ()* null, align 8
+
+; Function Attrs: norecurse uwtable
+define i32 @main() local_unnamed_addr #0 !prof !34 {
+entry:
+  %0 = load void ()*, void ()** @fptr, align 8
+; ICALL-PROM:   br i1 %{{[0-9]+}}, label %if.true.direct_targ, label %if.false.orig_indirect
+  tail call void %0(), !prof !40
+  ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3,!4}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "main.cc", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"ProfileSummary", !5}
+!5 = !{!6, !7, !8, !9, !10, !11, !12, !13}
+!6 = !{!"ProfileFormat", !"SampleProfile"}
+!7 = !{!"TotalCount", i64 3003}
+!8 = !{!"MaxCount", i64 3000}
+!9 = !{!"MaxInternalCount", i64 0}
+!10 = !{!"MaxFunctionCount", i64 0}
+!11 = !{!"NumCounts", i64 3}
+!12 = !{!"NumFunctions", i64 1}
+!13 = !{!"DetailedSummary", !14}
+!14 = !{!15, !16, !17, !18, !19, !20, !20, !21, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30}
+!15 = !{i32 10000, i64 3000, i32 1}
+!16 = !{i32 100000, i64 3000, i32 1}
+!17 = !{i32 200000, i64 3000, i32 1}
+!18 = !{i32 300000, i64 3000, i32 1}
+!19 = !{i32 400000, i64 3000, i32 1}
+!20 = !{i32 500000, i64 3000, i32 1}
+!21 = !{i32 600000, i64 3000, i32 1}
+!22 = !{i32 700000, i64 3000, i32 1}
+!23 = !{i32 800000, i64 3000, i32 1}
+!24 = !{i32 900000, i64 3000, i32 1}
+!25 = !{i32 950000, i64 3000, i32 1}
+!26 = !{i32 990000, i64 3000, i32 1}
+!27 = !{i32 999000, i64 3000, i32 1}
+!28 = !{i32 999900, i64 2, i32 2}
+!29 = !{i32 999990, i64 2, i32 2}
+!30 = !{i32 999999, i64 2, i32 2}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}
+!34 = !{!"function_entry_count", i64 1}
+!40 = !{!"VP", i32 0, i64 3000, i64 -8789629626369651636, i64 3000}

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp2.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,78 @@
+; Checks if indirect calls to static target functions that are actually
+; dead in the new binary target (due to a profile collected from a slightly
+; different binary) are properly traversed during ThinLTO liveness analysis.
+; If the liveness analysis is changed to ignore indirect edges and the
+; importer is changed to check liveness before importing, this test will
+; need adjustment (in that case _ZL3foov should not be imported/promoted,
+; and _ZL3barv can be internalized/removed).
+
+; REQUIRES: x86-registered-target
+
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/thinlto_samplepgo_icp2a.ll -o %t2a.bc
+; RUN: opt -module-summary %p/Inputs/thinlto_samplepgo_icp2b.ll -o %t2b.bc
+
+; Use -import-instr-limit=5 so that we don't import _ZL3barv, which would
+; hide the problem.
+; RUN: llvm-lto2 run -save-temps -import-instr-limit=5 -o %t3 %t.bc %t2a.bc %t2b.bc -r %t.bc,fptr,plx -r %t.bc,main,plx -r %t2a.bc,_ZL3barv,l -r %t2b.bc,_ZL3barv,pl -print-imports 2>&1 | FileCheck %s --check-prefix=IMPORTS2
+; IMPORTS2-NOT: Import _ZL3barv
+; IMPORTS2: Import _ZL3foov.llvm.0
+; IMPORTS2-NOT: Import _ZL3barv
+; RUN: llvm-nm %t3.2 | FileCheck %s --check-prefix=NM
+; NM: _ZL3barv
+; RUN: llvm-dis < %t3.3.2.internalize.bc | FileCheck %s --check-prefix=INTERNALIZE
+; INTERNALIZE: define dso_local void @_ZL3barv
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fptr = local_unnamed_addr global void ()* null, align 8
+
+; Function Attrs: norecurse uwtable
+define i32 @main() local_unnamed_addr #0 !prof !34 {
+entry:
+  %0 = load void ()*, void ()** @fptr, align 8
+; ICALL-PROM:   br i1 %{{[0-9]+}}, label %if.true.direct_targ, label %if.false.orig_indirect
+  tail call void %0(), !prof !40
+  ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3,!4}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "main.cc", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"ProfileSummary", !5}
+!5 = !{!6, !7, !8, !9, !10, !11, !12, !13}
+!6 = !{!"ProfileFormat", !"SampleProfile"}
+!7 = !{!"TotalCount", i64 3003}
+!8 = !{!"MaxCount", i64 3000}
+!9 = !{!"MaxInternalCount", i64 0}
+!10 = !{!"MaxFunctionCount", i64 0}
+!11 = !{!"NumCounts", i64 3}
+!12 = !{!"NumFunctions", i64 1}
+!13 = !{!"DetailedSummary", !14}
+!14 = !{!15, !16, !17, !18, !19, !20, !20, !21, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30}
+!15 = !{i32 10000, i64 3000, i32 1}
+!16 = !{i32 100000, i64 3000, i32 1}
+!17 = !{i32 200000, i64 3000, i32 1}
+!18 = !{i32 300000, i64 3000, i32 1}
+!19 = !{i32 400000, i64 3000, i32 1}
+!20 = !{i32 500000, i64 3000, i32 1}
+!21 = !{i32 600000, i64 3000, i32 1}
+!22 = !{i32 700000, i64 3000, i32 1}
+!23 = !{i32 800000, i64 3000, i32 1}
+!24 = !{i32 900000, i64 3000, i32 1}
+!25 = !{i32 950000, i64 3000, i32 1}
+!26 = !{i32 990000, i64 3000, i32 1}
+!27 = !{i32 999000, i64 3000, i32 1}
+!28 = !{i32 999900, i64 2, i32 2}
+!29 = !{i32 999990, i64 2, i32 2}
+!30 = !{i32 999999, i64 2, i32 2}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}
+!34 = !{!"function_entry_count", i64 1}
+!40 = !{!"VP", i32 0, i64 3000, i64 -8789629626369651636, i64 3000}

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp3.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; REQUIRES: x86-registered-target
+
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/thinlto_samplepgo_icp3.ll -o %t2.bc
+
+; Test to make sure importing and dead stripping works in the
+; case where the target is a local function that also indirectly calls itself.
+; RUN: llvm-lto2 run -thinlto-threads=1 -save-temps -o %t3 %t.bc %t2.bc -r %t.bc,fptr,plx -r %t.bc,main,plx -r %t2.bc,_Z6updatei,pl -r %t2.bc,fptr,l -print-imports 2>&1 | FileCheck %s --check-prefix=IMPORTS
+; Make sure we import the promted indirectly called target
+; IMPORTS: Import _ZL3foov.llvm.0
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fptr = local_unnamed_addr global void ()* null, align 8
+
+; Function Attrs: norecurse uwtable
+define i32 @main() local_unnamed_addr #0 !prof !34 {
+entry:
+  %0 = load void ()*, void ()** @fptr, align 8
+; ICALL-PROM:   br i1 %{{[0-9]+}}, label %if.true.direct_targ, label %if.false.orig_indirect
+  tail call void %0(), !prof !40
+  ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3,!4}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "main.cc", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"ProfileSummary", !5}
+!5 = !{!6, !7, !8, !9, !10, !11, !12, !13}
+!6 = !{!"ProfileFormat", !"SampleProfile"}
+!7 = !{!"TotalCount", i64 3003}
+!8 = !{!"MaxCount", i64 3000}
+!9 = !{!"MaxInternalCount", i64 0}
+!10 = !{!"MaxFunctionCount", i64 0}
+!11 = !{!"NumCounts", i64 3}
+!12 = !{!"NumFunctions", i64 1}
+!13 = !{!"DetailedSummary", !14}
+!14 = !{!15, !16, !17, !18, !19, !20, !20, !21, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30}
+!15 = !{i32 10000, i64 3000, i32 1}
+!16 = !{i32 100000, i64 3000, i32 1}
+!17 = !{i32 200000, i64 3000, i32 1}
+!18 = !{i32 300000, i64 3000, i32 1}
+!19 = !{i32 400000, i64 3000, i32 1}
+!20 = !{i32 500000, i64 3000, i32 1}
+!21 = !{i32 600000, i64 3000, i32 1}
+!22 = !{i32 700000, i64 3000, i32 1}
+!23 = !{i32 800000, i64 3000, i32 1}
+!24 = !{i32 900000, i64 3000, i32 1}
+!25 = !{i32 950000, i64 3000, i32 1}
+!26 = !{i32 990000, i64 3000, i32 1}
+!27 = !{i32 999000, i64 3000, i32 1}
+!28 = !{i32 999900, i64 2, i32 2}
+!29 = !{i32 999990, i64 2, i32 2}
+!30 = !{i32 999999, i64 2, i32 2}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}
+!34 = !{!"function_entry_count", i64 1}
+!40 = !{!"VP", i32 0, i64 3000, i64 -8789629626369651636, i64 3000}

Added: llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary %s -o %t.bc
+
+; Tests that with dead stripping in the thin link enabled (default), we do not
+; promote to target of the dropped dead symbol _ZL3foov. This can happen with a
+; sample profile collected for one binary used to  optimize for another binary.
+; RUN: llvm-lto2 run -save-temps -o %t2 %t.bc -r %t.bc,fptr,plx \
+; RUN:		-r %t.bc,main,plx -r %t.bc,_ZL3foov,l
+; RUN: llvm-dis < %t2.1.4.opt.bc | FileCheck %s --check-prefix=OPT
+; RUN: llvm-lto2 run -save-temps -o %t2 %t.bc -r %t.bc,fptr,plx \
+; RUN: 		-r %t.bc,main,plx -r %t.bc,_ZL3foov,l -compute-dead=false
+; RUN: llvm-dis < %t2.1.4.opt.bc | FileCheck %s --check-prefix=OPT-NODEAD
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at fptr = local_unnamed_addr global void ()* null, align 8
+
+define void @_ZL3foov() #1 {
+entry:
+  ret void
+}
+
+define i32 @main() local_unnamed_addr #0 !prof !34 {
+entry:
+  %0 = load void ()*, void ()** @fptr, align 8
+; OPT-NOT: label %if.false.orig_indirect
+; OPT-NODEAD: br i1 %{{[0-9]+}}, label %if.end.icp, label %if.false.orig_indirect
+  tail call void %0(), !prof !40
+  ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3,!4}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "main.cc", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"ProfileSummary", !5}
+!5 = !{!6, !7, !8, !9, !10, !11, !12, !13}
+!6 = !{!"ProfileFormat", !"SampleProfile"}
+!7 = !{!"TotalCount", i64 3003}
+!8 = !{!"MaxCount", i64 3000}
+!9 = !{!"MaxInternalCount", i64 0}
+!10 = !{!"MaxFunctionCount", i64 0}
+!11 = !{!"NumCounts", i64 3}
+!12 = !{!"NumFunctions", i64 1}
+!13 = !{!"DetailedSummary", !14}
+!14 = !{!15, !16, !17, !18, !19, !20, !20, !21, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30}
+!15 = !{i32 10000, i64 3000, i32 1}
+!16 = !{i32 100000, i64 3000, i32 1}
+!17 = !{i32 200000, i64 3000, i32 1}
+!18 = !{i32 300000, i64 3000, i32 1}
+!19 = !{i32 400000, i64 3000, i32 1}
+!20 = !{i32 500000, i64 3000, i32 1}
+!21 = !{i32 600000, i64 3000, i32 1}
+!22 = !{i32 700000, i64 3000, i32 1}
+!23 = !{i32 800000, i64 3000, i32 1}
+!24 = !{i32 900000, i64 3000, i32 1}
+!25 = !{i32 950000, i64 3000, i32 1}
+!26 = !{i32 990000, i64 3000, i32 1}
+!27 = !{i32 999000, i64 3000, i32 1}
+!28 = !{i32 999900, i64 2, i32 2}
+!29 = !{i32 999990, i64 2, i32 2}
+!30 = !{i32 999999, i64 2, i32 2}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}
+!34 = !{!"function_entry_count", i64 1}
+!40 = !{!"VP", i32 0, i64 3000, i64 -8789629626369651636, i64 3000}

Added: llvm/trunk/test/Transforms/PGOProfile/unreachable_bb.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/unreachable_bb.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/unreachable_bb.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/unreachable_bb.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: llvm-profdata merge %S/Inputs/unreachable_bb.proftext -o %t.profdata
+; RUN: opt < %s -pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+; RUN: opt < %s -passes=pgo-instr-use -pgo-test-profile-file=%t.profdata -S | FileCheck %s --check-prefix=USE
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @foo() {
+entry:
+  call void @bar()
+  unreachable
+return:
+  ret void
+}
+
+declare void @bar()
+
+;USE: !0 = !{i32 1, !"ProfileSummary", !1}
+;USE: !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+;USE: !2 = !{!"ProfileFormat", !"InstrProf"}
+;USE: !3 = !{!"TotalCount", i64 0}
+
+

Added: llvm/trunk/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll (added)
+++ llvm/trunk/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+
+define float @f(float %val) {
+; CHECK-LABEL: @f(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @sqrtf(float [[VAL:%.*]]) #0
+; CHECK-NEXT:    [[TMP0:%.*]] = fcmp oge float [[VAL]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[CALL_SQRT:%.*]]
+; CHECK:       call.sqrt:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call float @sqrtf(float [[VAL]])
+; CHECK-NEXT:    br label [[ENTRY_SPLIT]]
+; CHECK:       entry.split:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi float [ [[RES]], [[ENTRY:%.*]] ], [ [[TMP1]], [[CALL_SQRT]] ]
+; CHECK-NEXT:    ret float [[TMP2]]
+;
+entry:
+  %res = tail call float @sqrtf(float %val)
+  ret float %res
+}
+
+declare float @sqrtf(float)

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

Added: llvm/trunk/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll (added)
+++ llvm/trunk/test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -S -partially-inline-libcalls < %s | FileCheck %s
+; RUN: opt -S -passes=partially-inline-libcalls < %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @sqrt()
+declare float @sqrtf()
+
+; CHECK-LABEL: @foo
+define i32 @foo() {
+  ; CHECK: call{{.*}}@sqrt
+  ; CHECK-NOT: call{{.*}}@sqrt
+  %r = call i32 @sqrt()
+  ret i32 %r
+}
+
+; CHECK-LABEL: @bar
+define float @bar() {
+  ; CHECK: call{{.*}}@sqrtf
+  ; CHECK-NOT: call{{.*}}@sqrtf
+  %r = call float @sqrtf()
+  ret float %r
+}

Added: llvm/trunk/test/Transforms/PartiallyInlineLibCalls/nobuiltin.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PartiallyInlineLibCalls/nobuiltin.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PartiallyInlineLibCalls/nobuiltin.ll (added)
+++ llvm/trunk/test/Transforms/PartiallyInlineLibCalls/nobuiltin.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt -S -partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+
+define float @f(float %val) {
+; CHECK-LABEL: @f
+; CHECK: call{{.*}}@sqrtf
+; CHECK-NOT: call{{.*}}@sqrtf
+  %res = tail call float @sqrtf(float %val) nobuiltin
+  ret float %res
+}
+
+declare float @sqrtf(float)




More information about the llvm-commits mailing list