[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/SimplifyCFG/2011-09-05-TrivialLPad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/2011-09-05-TrivialLPad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; CHECK-NOT: invoke
+; CHECK-NOT: landingpad
+
+declare void @bar()
+
+define i32 @foo() personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 {
+entry:
+  invoke void @bar()
+          to label %return unwind label %lpad
+
+return:
+  ret i32 0
+
+lpad:
+  %lp = landingpad { i8*, i32 }
+          cleanup
+  resume { i8*, i32 } %lp
+}
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)

Added: llvm/trunk/test/Transforms/SimplifyCFG/AArch64/cttz-ctlz.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/AArch64/cttz-ctlz.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/AArch64/cttz-ctlz.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/AArch64/cttz-ctlz.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -S -simplifycfg -mtriple=aarch64 < %s | FileCheck %s
+
+define i32 @ctlz(i32 %A) {
+; CHECK-LABEL: @ctlz(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]]
+; CHECK-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+define i32 @cttz(i32 %A) {
+; CHECK-LABEL: @cttz(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]]
+; CHECK-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:
+  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+

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

Added: llvm/trunk/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/AArch64/prefer-fma.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,73 @@
+; RUN: opt < %s -mtriple=aarch64-linux-gnu -simplifycfg -enable-unsafe-fp-math -S >%t
+; RUN: FileCheck %s < %t
+; ModuleID = 't.cc'
+
+; Function Attrs: nounwind
+define double @_Z3fooRdS_S_S_(double* dereferenceable(8) %x, double* dereferenceable(8) %y, double* dereferenceable(8) %a) #0 {
+entry:
+  %0 = load double, double* %y, align 8
+  %cmp = fcmp oeq double %0, 0.000000e+00
+  %1 = load double, double* %x, align 8
+  br i1 %cmp, label %if.then, label %if.else
+
+; fadd (const, (fmul x, y))
+if.then:                                          ; preds = %entry
+; CHECK-LABEL: if.then:
+; CHECK:   %3 = fmul fast double %1, %2
+; CHECK-NEXT:   %mul = fadd fast double 1.000000e+00, %3
+  %2 = load double, double* %a, align 8
+  %3 = fmul fast double %1, %2
+  %mul = fadd fast double 1.000000e+00, %3
+  store double %mul, double* %y, align 8
+  br label %if.end
+
+; fsub ((fmul x, y), z)
+if.else:                                          ; preds = %entry
+; CHECK-LABEL: if.else:
+; CHECK:   %mul1 = fmul fast double %1, %2
+; CHECK-NEXT:   %sub1 = fsub fast double %mul1, %0
+  %4 = load double, double* %a, align 8
+  %mul1 = fmul fast double %1, %4
+  %sub1 = fsub fast double %mul1, %0
+  %gep1 = getelementptr double, double* %y, i32 1
+  store double %sub1, double* %gep1, align 8
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %5 = load double, double* %y, align 8
+  %cmp2 = fcmp oeq double %5, 2.000000e+00
+  %6 = load double, double* %x, align 8
+  br i1 %cmp2, label %if.then2, label %if.else2
+
+; fsub (x, (fmul y, z))
+if.then2:                                         ; preds = %entry
+; CHECK-LABEL: if.then2:
+; CHECK:   %7 = fmul fast double %5, 3.000000e+00
+; CHECK-NEXT:   %mul2 = fsub fast double %6, %7
+  %7 = load double, double* %a, align 8
+  %8 = fmul fast double %6, 3.0000000e+00
+  %mul2 = fsub fast double %7, %8
+  store double %mul2, double* %y, align 8
+  br label %if.end2
+
+; fsub (fneg((fmul x, y)), const)
+if.else2:                                         ; preds = %entry
+; CHECK-LABEL: if.else2:
+; CHECK:   %mul3 = fmul fast double %5, 3.000000e+00
+; CHECK-NEXT:   %neg = fsub fast double 0.000000e+00, %mul3
+; CHECK-NEXT:   %sub2 = fsub fast double %neg, 3.000000e+00
+  %mul3 = fmul fast double %6, 3.0000000e+00
+  %neg = fsub fast double 0.0000000e+00, %mul3
+  %sub2 = fsub fast double %neg, 3.0000000e+00
+  store double %sub2, double* %y, align 8
+  br label %if.end2
+
+if.end2:                                           ; preds = %if.else, %if.then
+  %9 = load double, double* %x, align 8
+  %10 = load double, double* %y, align 8
+  %add = fadd fast double %9, %10
+  %11 = load double, double* %a, align 8
+  %add2 = fadd fast double %add, %11
+  ret double %add2
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/AMDGPU/cttz-ctlz.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/AMDGPU/cttz-ctlz.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/AMDGPU/cttz-ctlz.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/AMDGPU/cttz-ctlz.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,249 @@
+; RUN: opt -S -simplifycfg -mtriple=amdgcn-unknown-unknown -mcpu=tahiti < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s
+; RUN: opt -S -simplifycfg -mtriple=amdgcn-unknown-unknown -mcpu=tonga < %s | FileCheck -check-prefix=SI -check-prefix=ALL %s
+
+
+define i64 @test1(i64 %A) {
+; ALL-LABEL: @test1(
+; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]]
+; SI-NEXT: ret i64 [[SEL]]
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
+  ret i64 %cond
+}
+
+
+define i32 @test2(i32 %A) {
+; ALL-LABEL: @test2(
+; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTLZ]]
+; SI-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+
+define signext i16 @test3(i16 signext %A) {
+; ALL-LABEL: @test3(
+; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
+; SI-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
+; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 16, i16 [[CTLZ]]
+; SI-NEXT: ret i16 [[SEL]]
+entry:
+  %tobool = icmp eq i16 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
+  ret i16 %cond
+}
+
+
+define i64 @test1b(i64 %A) {
+; ALL-LABEL: @test1b(
+; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTTZ]]
+; SI-NEXT: ret i64 [[SEL]]
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
+  ret i64 %cond
+}
+
+
+define i32 @test2b(i32 %A) {
+; ALL-LABEL: @test2b(
+; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTTZ]]
+; SI-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+
+define signext i16 @test3b(i16 signext %A) {
+; ALL-LABEL: @test3b(
+; SI: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
+; SI-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
+; SI-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 16, i16 [[CTTZ]]
+; SI-NEXT: ret i16 [[SEL]]
+entry:
+  %tobool = icmp eq i16 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
+  ret i16 %cond
+}
+
+
+define i64 @test1c(i64 %A) {
+; ALL-LABEL: @test1c(
+; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 63, i64 [[CTLZ]]
+; ALL-NEXT: ret i64 [[SEL]]
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
+  ret i64 %cond
+}
+
+define i32 @test2c(i32 %A) {
+; ALL-LABEL: @test2c(
+; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 31, i32 [[CTLZ]]
+; ALL-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
+  ret i32 %cond
+}
+
+
+define signext i16 @test3c(i16 signext %A) {
+; ALL-LABEL: @test3c(
+; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
+; ALL-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
+; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 15, i16 [[CTLZ]]
+; ALL-NEXT: ret i16 [[SEL]]
+entry:
+  %tobool = icmp eq i16 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
+  ret i16 %cond
+}
+
+
+define i64 @test1d(i64 %A) {
+; ALL-LABEL: @test1d(
+; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 63, i64 [[CTTZ]]
+; ALL-NEXT: ret i64 [[SEL]]
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ]
+  ret i64 %cond
+}
+
+
+define i32 @test2d(i32 %A) {
+; ALL-LABEL: @test2d(
+; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 31, i32 [[CTTZ]]
+; ALL-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ]
+  ret i32 %cond
+}
+
+
+define signext i16 @test3d(i16 signext %A) {
+; ALL-LABEL: @test3d(
+; ALL: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
+; ALL-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
+; ALL-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i16 15, i16 [[CTTZ]]
+; ALL-NEXT: ret i16 [[SEL]]
+entry:
+  %tobool = icmp eq i16 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ]
+  ret i16 %cond
+}
+
+
+declare i64 @llvm.ctlz.i64(i64, i1)
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i16 @llvm.ctlz.i16(i16, i1)
+declare i64 @llvm.cttz.i64(i64, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+declare i16 @llvm.cttz.i16(i16, i1)

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

Added: llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/ARM/cttz-ctlz.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -S -simplifycfg -mtriple=arm -mattr=+v6t2 < %s | FileCheck %s
+
+define i32 @ctlz(i32 %A) {
+; CHECK-LABEL: @ctlz(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]]
+; CHECK-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+define i32 @cttz(i32 %A) {
+; CHECK-LABEL: @cttz(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]]
+; CHECK-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:
+  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+

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

Added: llvm/trunk/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+;RUN: opt -S -simplifycfg -mtriple=arm < %s | FileCheck %s
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+; CHECK-LABEL: select_trunc_i64
+; CHECK-NOT: br
+; CHECK: select
+; CHECK: select
+define arm_aapcscc i32 @select_trunc_i64(i32 %a, i32 %b) {
+entry:
+  %conv = sext i32 %a to i64
+  %conv1 = sext i32 %b to i64
+  %add = add nsw i64 %conv1, %conv
+  %cmp = icmp sgt i64 %add, 2147483647
+  br i1 %cmp, label %cond.end7, label %cond.false
+
+cond.false:                                       ; preds = %entry
+  %0 = icmp sgt i64 %add, -2147483648
+  %cond = select i1 %0, i64 %add, i64 -2147483648
+  %extract.t = trunc i64 %cond to i32
+  br label %cond.end7
+
+cond.end7:                                        ; preds = %cond.false, %entry
+  %cond8.off0 = phi i32 [ 2147483647, %entry ], [ %extract.t, %cond.false ]
+  ret i32 %cond8.off0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table-constant-expr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "armv7a--none-eabi"
+
+; One of the phi node's values is too complex to be represented by a global
+; variable, so we can't convert to a lookup table.
+
+; CHECK-NOT: @switch.table
+; CHECK-NOT: load
+
+ at g1 = external global i32, align 4
+ at g2 = external global i32, align 4
+ at g3 = external global i32, align 4
+ at g4 = external thread_local global i32, align 4
+
+define i32* @test3(i32 %n) {
+entry:
+  switch i32 %n, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+  ]
+
+sw.bb:
+  br label %return
+
+sw.bb1:
+  br label %return
+
+sw.bb2:
+  br label %return
+
+sw.default:
+  br label %return
+
+return:
+  %retval.0 = phi i32* [ @g4, %sw.default ], [ getelementptr inbounds (i32, i32* inttoptr (i32 mul (i32 ptrtoint (i32* @g3 to i32), i32 2) to i32*), i32 1), %sw.bb2 ], [ @g2, %sw.bb1 ], [ @g1, %sw.bb ]
+  ret i32* %retval.0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/ARM/switch-to-lookup-table.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,138 @@
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=static    < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=pic       < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=ropi      < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=rwpi      < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -simplifycfg -switch-to-lookup -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' -mtriple=arm -relocation-model=static    < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' -mtriple=arm -relocation-model=pic       < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' -mtriple=arm -relocation-model=ropi      < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' -mtriple=arm -relocation-model=rwpi      < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' -mtriple=arm -relocation-model=ropi-rwpi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
+
+; CHECK:       @{{.*}} = private unnamed_addr constant [3 x i32] [i32 1234, i32 5678, i32 15532]
+; ENABLE:      @{{.*}} = private unnamed_addr constant [3 x i32*] [i32* @c1, i32* @c2, i32* @c3]
+; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x i32*] [i32* @c1, i32* @c2, i32* @c3]
+; ENABLE:      @{{.*}} = private unnamed_addr constant [3 x i32*] [i32* @g1, i32* @g2, i32* @g3]
+; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x i32*] [i32* @g1, i32* @g2, i32* @g3]
+; ENABLE:      @{{.*}} = private unnamed_addr constant [3 x i32 (i32, i32)*] [i32 (i32, i32)* @f1, i32 (i32, i32)* @f2, i32 (i32, i32)* @f3]
+; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [3 x i32 (i32, i32)*] [i32 (i32, i32)* @f1, i32 (i32, i32)* @f2, i32 (i32, i32)* @f3]
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "armv7a--none-eabi"
+
+define i32 @test1(i32 %n) {
+entry:
+  switch i32 %n, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+  ]
+
+sw.bb:
+  br label %return
+
+sw.bb1:
+  br label %return
+
+sw.bb2:
+  br label %return
+
+sw.default:
+  br label %return
+
+return:
+  %retval.0 = phi i32 [ 15498, %sw.default ], [ 15532, %sw.bb2 ], [ 5678, %sw.bb1 ], [ 1234, %sw.bb ]
+  ret i32 %retval.0
+}
+
+ at c1 = external constant i32, align 4
+ at c2 = external constant i32, align 4
+ at c3 = external constant i32, align 4
+ at c4 = external constant i32, align 4
+
+
+define i32* @test2(i32 %n) {
+entry:
+  switch i32 %n, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+  ]
+
+sw.bb:
+  br label %return
+
+sw.bb1:
+  br label %return
+
+sw.bb2:
+  br label %return
+
+sw.default:
+  br label %return
+
+return:
+  %retval.0 = phi i32* [ @c4, %sw.default ], [ @c3, %sw.bb2 ], [ @c2, %sw.bb1 ], [ @c1, %sw.bb ]
+  ret i32* %retval.0
+}
+
+ at g1 = external global i32, align 4
+ at g2 = external global i32, align 4
+ at g3 = external global i32, align 4
+ at g4 = external global i32, align 4
+
+define i32* @test3(i32 %n) {
+entry:
+  switch i32 %n, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+  ]
+
+sw.bb:
+  br label %return
+
+sw.bb1:
+  br label %return
+
+sw.bb2:
+  br label %return
+
+sw.default:
+  br label %return
+
+return:
+  %retval.0 = phi i32* [ @g4, %sw.default ], [ @g3, %sw.bb2 ], [ @g2, %sw.bb1 ], [ @g1, %sw.bb ]
+  ret i32* %retval.0
+}
+
+declare i32 @f1(i32, i32)
+declare i32 @f2(i32, i32)
+declare i32 @f3(i32, i32)
+declare i32 @f4(i32, i32)
+declare i32 @f5(i32, i32)
+
+define i32 @test4(i32 %a, i32 %b, i32 %c) {
+entry:
+  %cmp = icmp eq i32 %a, 1
+  br i1 %cmp, label %cond.end11, label %cond.false
+
+cond.false:
+  %cmp1 = icmp eq i32 %a, 2
+  br i1 %cmp1, label %cond.end11, label %cond.false3
+
+cond.false3:
+  %cmp4 = icmp eq i32 %a, 3
+  br i1 %cmp4, label %cond.end11, label %cond.false6
+
+cond.false6:
+  %cmp7 = icmp eq i32 %a, 4
+  %cond = select i1 %cmp7, i32 (i32, i32)* @f4, i32 (i32, i32)* @f5
+  br label %cond.end11
+
+cond.end11:
+  %cond12 = phi i32 (i32, i32)* [ @f1, %entry ], [ @f2, %cond.false ], [ %cond, %cond.false6 ], [ @f3, %cond.false3 ]
+  %call = call i32 %cond12(i32 %b, i32 %c) #2
+  ret i32 %call
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/BrUnwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/BrUnwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/BrUnwind.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/BrUnwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -simplifycfg -S | \
+; RUN: not grep "br label"
+
+define void @test(i1 %C) {
+        br i1 %C, label %A, label %B
+A:              ; preds = %0
+        call void @test( i1 %C )
+        br label %X
+B:              ; preds = %0
+        call void @test( i1 %C )
+        br label %X
+X:              ; preds = %B, %A
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,67 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+ at G = extern_weak global i32
+
+; PR3354
+; Do not merge bb1 into the entry block, it might trap.
+
+define i32 @admiral(i32 %a, i32 %b) {
+; CHECK-LABEL: @admiral(
+; CHECK-NEXT:    [[C:%.*]] = icmp sle i32 %a, %b
+; CHECK-NEXT:    br i1 [[C]], label %bb2, label %bb1
+; CHECK:       bb1:
+; CHECK-NEXT:    [[D:%.*]] = icmp sgt i32 sdiv (i32 -32768, i32 ptrtoint (i32* @G to i32)), 0
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[D]], i32 927, i32 42
+; CHECK-NEXT:    br label %bb2
+; CHECK:       bb2:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 42, %0 ], [ [[DOT]], %bb1 ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+;
+  %c = icmp sle i32 %a, %b
+  br i1 %c, label %bb2, label %bb1
+bb1:
+  %d = icmp sgt i32 sdiv (i32 -32768, i32 ptrtoint (i32* @G to i32)), 0
+  br i1 %d, label %bb6, label %bb2
+bb2:
+  ret i32 42
+bb6:
+  ret i32 927
+}
+
+define i32 @ackbar(i1 %c) {
+; CHECK-LABEL: @ackbar(
+; CHECK-NEXT:    br i1 %c, label %bb5, label %bb6
+; CHECK:       bb5:
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 icmp sgt (i32 sdiv (i32 32767, i32 ptrtoint (i32* @G to i32)), i32 0), i32 42, i32 927
+; CHECK-NEXT:    br label %bb6
+; CHECK:       bb6:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 42, %0 ], [ [[DOT]], %bb5 ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+;
+  br i1 %c, label %bb5, label %bb6
+bb5:
+  br i1 icmp sgt (i32 sdiv (i32 32767, i32 ptrtoint (i32* @G to i32)), i32 0), label %bb6, label %bb7
+bb6:
+  ret i32 42
+bb7:
+  ret i32 927
+}
+
+; FP ops don't trap by default, so this is safe to hoist.
+
+define i32 @tarp(i1 %c) {
+; CHECK-LABEL: @tarp(
+; CHECK-NEXT:  bb9:
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 fcmp oeq (float fdiv (float 3.000000e+00, float sitofp (i32 ptrtoint (i32* @G to i32) to float)), float 1.000000e+00), i32 42, i32 927
+; CHECK-NEXT:    [[MERGE:%.*]] = select i1 %c, i32 [[DOT]], i32 42
+; CHECK-NEXT:    ret i32 [[MERGE]]
+;
+  br i1 %c, label %bb8, label %bb9
+bb8:
+  br i1 fcmp oeq (float fdiv (float 3.0, float sitofp (i32 ptrtoint (i32* @G to i32) to float)), float 1.0), label %bb9, label %bb10
+bb9:
+  ret i32 42
+bb10:
+  ret i32 927
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/CoveredLookupTable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/CoveredLookupTable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/CoveredLookupTable.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/CoveredLookupTable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt -simplifycfg -switch-to-lookup -S %s | FileCheck %s
+; RUN: opt -passes='simplify-cfg<switch-to-lookup>' -S %s | FileCheck %s
+; rdar://15268442
+
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin12.0.0"
+
+; CHECK-LABEL: define i3 @coveredswitch_test(
+; CHECK: entry:
+; CHECK-NEXT: sub i3 %input, -4
+; CHECK-NEXT: zext i3 %switch.tableidx to i24
+; CHECK-NEXT: mul i24 %switch.cast, 3
+; CHECK-NEXT: lshr i24 7507338, %switch.shiftamt
+; CHECK-NEXT: trunc i24 %switch.downshift to i3
+; CHECK-NEXT: ret i3 %switch.masked
+
+define i3 @coveredswitch_test(i3 %input) {
+entry:
+  switch i3 %input, label %bb8 [
+    i3 0, label %bb7
+    i3 1, label %bb
+    i3 2, label %bb3
+    i3 3, label %bb4
+    i3 4, label %bb5
+    i3 5, label %bb6
+  ]
+
+bb:                                               ; preds = %entry
+  br label %bb8
+
+bb3:                                              ; preds = %entry
+  br label %bb8
+
+bb4:                                              ; preds = %entry
+  br label %bb8
+
+bb5:                                              ; preds = %entry
+  br label %bb8
+
+bb6:                                              ; preds = %entry
+  br label %bb8
+
+bb7:                                              ; preds = %entry
+  br label %bb8
+
+bb8:                                              ; preds = %bb7, %bb6, %bb5, %bb4, %bb3, %bb, %entry
+  %result = phi i3 [ 0, %bb7 ], [ 1, %bb6 ], [ 2, %bb5 ], [ 3, %bb4 ], [ 4, %bb3 ], [ 5, %bb ], [ 6, %entry ]
+  ret i3 %result
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/DeadSetCC.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/DeadSetCC.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/DeadSetCC.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/DeadSetCC.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -simplifycfg -S | \
+; RUN:   not grep "icmp eq"
+
+; Check that simplifycfg deletes a dead 'seteq' instruction when it
+; folds a conditional branch into a switch instruction.
+
+declare void @foo()
+
+declare void @bar()
+
+define void @testcfg(i32 %V) {
+        %C = icmp eq i32 %V, 18         ; <i1> [#uses=1]
+        %D = icmp eq i32 %V, 180                ; <i1> [#uses=1]
+        %E = or i1 %C, %D               ; <i1> [#uses=1]
+        br i1 %E, label %L1, label %Sw
+Sw:             ; preds = %0
+        switch i32 %V, label %L1 [
+                 i32 15, label %L2
+                 i32 16, label %L2
+        ]
+L1:             ; preds = %Sw, %0
+        call void @foo( )
+        ret void
+L2:             ; preds = %Sw, %Sw
+        call void @bar( )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/EmptyBlockMerge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/EmptyBlockMerge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/EmptyBlockMerge.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/EmptyBlockMerge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; Basic block #2 should not be merged into BB #3!
+;
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @foo()
+
+define void @cprop_test12(i32* %data) {
+bb0:
+	%reg108 = load i32, i32* %data		; <i32> [#uses=2]
+	%cond218 = icmp ne i32 %reg108, 5		; <i1> [#uses=1]
+	br i1 %cond218, label %bb3, label %bb2
+bb2:		; preds = %bb0
+	call void @foo( )
+; CHECK: br label %bb3
+	br label %bb3
+bb3:		; preds = %bb2, %bb0
+	%reg117 = phi i32 [ 110, %bb2 ], [ %reg108, %bb0 ]		; <i32> [#uses=1]
+	store i32 %reg117, i32* %data
+	ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,256 @@
+; Test merging of blocks with phi nodes.
+;
+; RUN: opt < %s -simplifycfg -S > %t
+; RUN: not grep N: %t
+; RUN: not grep X: %t
+; RUN: not grep 'switch i32[^U]+%U' %t
+; RUN: not grep "^BB.tomerge" %t
+; RUN: grep "^BB.nomerge" %t | count 4
+;
+
+; ModuleID = '<stdin>'
+declare i1 @foo()
+
+declare i1 @bar(i32)
+
+define i32 @test(i1 %a) {
+Q:
+        br i1 %a, label %N, label %M
+N:              ; preds = %Q
+        br label %M
+M:              ; preds = %N, %Q
+        ; It's ok to merge N and M because the incoming values for W are the
+        ; same for both cases...
+        %W = phi i32 [ 2, %N ], [ 2, %Q ]               ; <i32> [#uses=1]
+        %R = add i32 %W, 1              ; <i32> [#uses=1]
+        ret i32 %R
+}
+
+; Test merging of blocks with phi nodes where at least one incoming value
+; in the successor is undef.
+define i8 @testundef(i32 %u) {
+R:
+  switch i32 %u, label %U [
+    i32 0, label %S
+    i32 1, label %T
+    i32 2, label %T
+  ]
+
+S:                                            ; preds = %R
+  br label %U
+
+T:                                           ; preds = %R, %R
+  br label %U
+
+U:                                        ; preds = %T, %S, %R
+  ; We should be able to merge either the S or T block into U by rewriting
+  ; R's incoming value with the incoming value of that predecessor since
+  ; R's incoming value is undef and both of those predecessors are simple
+  ; unconditional branches.
+  %val.0 = phi i8 [ undef, %R ], [ 1, %T ], [ 0, %S ]
+  ret i8 %val.0
+}
+
+; Test merging of blocks with phi nodes where at least one incoming value
+; in the successor is undef.
+define i8 @testundef2(i32 %u, i32* %A) {
+V:
+  switch i32 %u, label %U [
+    i32 0, label %W
+    i32 1, label %X
+    i32 2, label %X
+    i32 3, label %Z
+  ]
+
+W:                                            ; preds = %V
+  br label %U
+
+Z:
+  store i32 0, i32* %A, align 4
+  br label %X
+
+X:                                           ; preds = %V, %V, %Z
+  br label %U
+
+U:                                        ; preds = %X, %W, %V
+  ; We should be able to merge either the W or X block into U by rewriting
+  ; V's incoming value with the incoming value of that predecessor since
+  ; V's incoming value is undef and both of those predecessors are simple
+  ; unconditional branches. Note that X has predecessors beyond
+  ; the direct predecessors of U.
+  %val.0 = phi i8 [ undef, %V ], [ 1, %X ], [ 1, %W ]
+  ret i8 %val.0
+}
+
+define i8 @testmergesome(i32 %u, i32* %A) {
+V:
+  switch i32 %u, label %Y [
+    i32 0, label %W
+    i32 1, label %X
+    i32 2, label %X
+    i32 3, label %Z
+  ]
+
+W:                                            ; preds = %V
+  store i32 1, i32* %A, align 4
+  br label %Y
+
+Z:
+  store i32 0, i32* %A, align 4
+  br label %X
+
+X:                                           ; preds = %V, %Z
+  br label %Y
+
+Y:                                        ; preds = %X, %W, %V
+  ; After merging X into Y, we should have 5 predecessors
+  ; and thus 5 incoming values to the phi.
+  %val.0 = phi i8 [ 1, %V ], [ 1, %X ], [ 2, %W ]
+  ret i8 %val.0
+}
+
+
+define i8 @testmergesome2(i32 %u, i32* %A) {
+V:
+  switch i32 %u, label %W [
+    i32 0, label %W
+    i32 1, label %Y
+    i32 2, label %X
+    i32 4, label %Y
+  ]
+
+W:                                            ; preds = %V
+  store i32 1, i32* %A, align 4
+  br label %Y
+
+X:                                           ; preds = %V, %Z
+  br label %Y
+
+Y:                                        ; preds = %X, %W, %V
+  ; Ensure that we deal with both undef inputs for V when we merge in X.
+  %val.0 = phi i8 [ undef, %V ], [ 1, %X ], [ 2, %W ], [ undef, %V ]
+  ret i8 %val.0
+}
+
+; This function can't be merged
+define void @a() {
+entry:
+	br label %BB.nomerge
+
+BB.nomerge:		; preds = %Common, %entry
+        ; This phi has a conflicting value (0) with below phi (2), so blocks
+        ; can't be merged.
+	%a = phi i32 [ 1, %entry ], [ 0, %Common ]		; <i32> [#uses=1]
+	br label %Succ
+
+Succ:		; preds = %Common, %BB.nomerge
+	%b = phi i32 [ %a, %BB.nomerge ], [ 2, %Common ]		; <i32> [#uses=0]
+	%conde = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %conde, label %Common, label %Exit
+
+Common:		; preds = %Succ
+	%cond = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %cond, label %BB.nomerge, label %Succ
+
+Exit:		; preds = %Succ
+	ret void
+}
+
+; This function can't be merged
+define void @b() {
+entry:
+	br label %BB.nomerge
+
+BB.nomerge:		; preds = %Common, %entry
+	br label %Succ
+
+Succ:		; preds = %Common, %BB.nomerge
+        ; This phi has confliction values for Common and (through BB) Common,
+        ; blocks can't be merged
+	%b = phi i32 [ 1, %BB.nomerge ], [ 2, %Common ]		; <i32> [#uses=0]
+	%conde = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %conde, label %Common, label %Exit
+
+Common:		; preds = %Succ
+	%cond = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %cond, label %BB.nomerge, label %Succ
+
+Exit:		; preds = %Succ
+	ret void
+}
+
+; This function can't be merged (for keeping canonical loop structures)
+define void @c() {
+entry:
+	br label %BB.nomerge
+
+BB.nomerge:		; preds = %Common, %entry
+	br label %Succ
+
+Succ:		; preds = %Common, %BB.tomerge, %Pre-Exit
+        ; This phi has identical values for Common and (through BB) Common,
+        ; blocks can't be merged
+	%b = phi i32 [ 1, %BB.nomerge ], [ 1, %Common ], [ 2, %Pre-Exit ]
+	%conde = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %conde, label %Common, label %Pre-Exit
+
+Common:		; preds = %Succ
+	%cond = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %cond, label %BB.nomerge, label %Succ
+
+Pre-Exit:       ; preds = %Succ
+        ; This adds a backedge, so the %b phi node gets a third branch and is
+        ; not completely trivial
+	%cond2 = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %cond2, label %Succ, label %Exit
+
+Exit:		; preds = %Pre-Exit
+	ret void
+}
+
+; This function can't be merged (for keeping canonical loop structures)
+define void @d() {
+entry:
+	br label %BB.nomerge
+
+BB.nomerge:		; preds = %Common, %entry
+        ; This phi has a matching value (0) with below phi (0), so blocks
+        ; can be merged.
+	%a = phi i32 [ 1, %entry ], [ 0, %Common ]		; <i32> [#uses=1]
+	br label %Succ
+
+Succ:		; preds = %Common, %BB.tomerge
+	%b = phi i32 [ %a, %BB.nomerge ], [ 0, %Common ]		; <i32> [#uses=0]
+	%conde = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %conde, label %Common, label %Exit
+
+Common:		; preds = %Succ
+	%cond = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %cond, label %BB.nomerge, label %Succ
+
+Exit:		; preds = %Succ
+	ret void
+}
+
+; This function can be merged
+define void @e() {
+entry:
+	br label %Succ
+
+Succ:		; preds = %Use, %entry
+        ; This phi is used somewhere else than Succ, but this should not prevent
+        ; merging this block
+	%a = phi i32 [ 1, %entry ], [ 0, %Use ]		; <i32> [#uses=1]
+	br label %BB.tomerge
+
+BB.tomerge:		; preds = %Succ
+	%conde = call i1 @foo( )		; <i1> [#uses=1]
+	br i1 %conde, label %Use, label %Exit
+
+Use:		; preds = %Succ
+	%cond = call i1 @bar( i32 %a )		; <i1> [#uses=1]
+	br i1 %cond, label %Succ, label %Exit
+
+Exit:		; preds = %Use, %Succ
+	ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,123 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -forward-switch-cond=false -S | FileCheck %s --check-prefix=NO_FWD
+; RUN: opt < %s -simplifycfg -forward-switch-cond=true  -S | FileCheck %s --check-prefix=FWD
+
+; RUN: opt < %s -passes='simplify-cfg<no-forward-switch-cond>' -S | FileCheck %s --check-prefix=NO_FWD
+; RUN: opt < %s -passes='simplify-cfg<forward-switch-cond>' -S | FileCheck %s --check-prefix=FWD
+
+; PR10131
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+define i32 @t(i32 %m) nounwind readnone {
+; NO_FWD-LABEL: @t(
+; NO_FWD-NEXT:  entry:
+; NO_FWD-NEXT:    switch i32 [[M:%.*]], label [[SW_BB4:%.*]] [
+; NO_FWD-NEXT:    i32 0, label [[RETURN:%.*]]
+; NO_FWD-NEXT:    i32 1, label [[SW_BB1:%.*]]
+; NO_FWD-NEXT:    i32 2, label [[SW_BB2:%.*]]
+; NO_FWD-NEXT:    i32 3, label [[SW_BB3:%.*]]
+; NO_FWD-NEXT:    ]
+; NO_FWD:       sw.bb1:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       sw.bb2:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       sw.bb3:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       sw.bb4:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       return:
+; NO_FWD-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 4, [[SW_BB4]] ], [ 3, [[SW_BB3]] ], [ 2, [[SW_BB2]] ], [ 1, [[SW_BB1]] ], [ 0, [[ENTRY:%.*]] ]
+; NO_FWD-NEXT:    ret i32 [[RETVAL_0]]
+;
+; FWD-LABEL: @t(
+; FWD-NEXT:  entry:
+; FWD-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[M:%.*]], 4
+; FWD-NEXT:    [[M_:%.*]] = select i1 [[SWITCH]], i32 [[M]], i32 4
+; FWD-NEXT:    ret i32 [[M_]]
+;
+entry:
+  switch i32 %m, label %sw.bb4 [
+  i32 0, label %sw.bb0
+  i32 1, label %sw.bb1
+  i32 2, label %sw.bb2
+  i32 3, label %sw.bb3
+  ]
+
+sw.bb0:                                           ; preds = %entry
+  br label %return
+
+sw.bb1:                                           ; preds = %entry
+  br label %return
+
+sw.bb2:                                           ; preds = %entry
+  br label %return
+
+sw.bb3:                                           ; preds = %entry
+  br label %return
+
+sw.bb4:                                           ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %entry, %sw.bb4, %sw.bb3, %sw.bb2, %sw.bb1
+  %retval.0 = phi i32 [ 4, %sw.bb4 ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %sw.bb0 ]
+  ret i32 %retval.0
+}
+
+; If 1 incoming phi value is a case constant of a switch, convert it to the switch condition:
+; https://bugs.llvm.org/show_bug.cgi?id=34471
+; This then subsequently should allow squashing of the other trivial case blocks.
+
+define i32 @PR34471(i32 %x) {
+; NO_FWD-LABEL: @PR34471(
+; NO_FWD-NEXT:  entry:
+; NO_FWD-NEXT:    switch i32 [[X:%.*]], label [[ELSE3:%.*]] [
+; NO_FWD-NEXT:    i32 17, label [[RETURN:%.*]]
+; NO_FWD-NEXT:    i32 19, label [[IF19:%.*]]
+; NO_FWD-NEXT:    i32 42, label [[IF42:%.*]]
+; NO_FWD-NEXT:    ]
+; NO_FWD:       if19:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       if42:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       else3:
+; NO_FWD-NEXT:    br label [[RETURN]]
+; NO_FWD:       return:
+; NO_FWD-NEXT:    [[R:%.*]] = phi i32 [ [[X]], [[IF19]] ], [ [[X]], [[IF42]] ], [ 0, [[ELSE3]] ], [ 17, [[ENTRY:%.*]] ]
+; NO_FWD-NEXT:    ret i32 [[R]]
+;
+; FWD-LABEL: @PR34471(
+; FWD-NEXT:  entry:
+; FWD-NEXT:    switch i32 [[X:%.*]], label [[ELSE3:%.*]] [
+; FWD-NEXT:    i32 17, label [[RETURN:%.*]]
+; FWD-NEXT:    i32 19, label [[RETURN]]
+; FWD-NEXT:    i32 42, label [[RETURN]]
+; FWD-NEXT:    ]
+; FWD:       else3:
+; FWD-NEXT:    br label [[RETURN]]
+; FWD:       return:
+; FWD-NEXT:    [[R:%.*]] = phi i32 [ 0, [[ELSE3]] ], [ [[X]], [[ENTRY:%.*]] ], [ [[X]], [[ENTRY]] ], [ [[X]], [[ENTRY]] ]
+; FWD-NEXT:    ret i32 [[R]]
+;
+entry:
+  switch i32 %x, label %else3 [
+  i32 17, label %return
+  i32 19, label %if19
+  i32 42, label %if42
+  ]
+
+if19:
+  br label %return
+
+if42:
+  br label %return
+
+else3:
+  br label %return
+
+return:
+  %r = phi i32 [ %x, %if19 ], [ %x, %if42 ], [ 0, %else3 ], [ 17, %entry ]
+  ret i32 %r
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/disable-lookup-table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/disable-lookup-table.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/disable-lookup-table.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/disable-lookup-table.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt -S -O2 < %s | FileCheck %s -check-prefix=DISABLE
+; RUN: opt -S -hexagon-emit-lookup-tables=true -O2 < %s | FileCheck %s -check-prefix=DISABLE
+; RUN: opt -S -hexagon-emit-lookup-tables=false -O2 < %s | FileCheck %s -check-prefix=DISABLE
+; The attribute "no-jump-tables"="true" disables the generation of switch generated lookup tables
+
+; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [6 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5]
+
+target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
+target triple = "hexagon-unknown--elf"
+
+; Function Attrs: noinline nounwind
+define i32 @foo(i32 %c) #0 {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+    i32 46, label %sw.bb4
+    i32 47, label %sw.bb5
+    i32 48, label %sw.bb6
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+}
+
+attributes #0 = { noinline nounwind "no-jump-tables"="true"}

Added: llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5 @@
+config.suffixes = ['.ll']
+
+targets = set(config.root.targets_to_build.split())
+if not 'Hexagon' in targets:
+    config.unsupported = True

Added: llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,62 @@
+; RUN: opt -S -O2 < %s | FileCheck %s -check-prefix=ENABLE
+; RUN: opt -S -hexagon-emit-lookup-tables=true -O2 < %s | FileCheck %s -check-prefix=ENABLE
+; RUN: opt -S -hexagon-emit-lookup-tables=false -O2 < %s | FileCheck %s -check-prefix=DISABLE
+
+
+; ENABLE: @{{.*}} = private unnamed_addr constant [6 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5]
+; DISABLE-NOT: @{{.*}} = private unnamed_addr constant [6 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5]
+; DISABLE : = phi i32 [ 19, %{{.*}} ], [ 5, %{{.*}} ], [ 12, %{{.*}} ], [ 22, %{{.*}} ], [ 14, %{{.*}} ], [ 20, %{{.*}} ], [ 9, %{{.*}} ]
+
+target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
+target triple = "hexagon-unknown--elf"
+
+; Function Attrs: noinline nounwind
+define i32 @foo(i32 %x) #0 section ".tcm_text" {
+entry:
+  %retval = alloca i32, align 4
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  switch i32 %0, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+    i32 4, label %sw.bb4
+    i32 5, label %sw.bb5
+  ]
+
+sw.bb:                                            ; preds = %entry
+  store i32 9, i32* %retval, align 4
+  br label %return
+
+sw.bb1:                                           ; preds = %entry
+  store i32 20, i32* %retval, align 4
+  br label %return
+
+sw.bb2:                                           ; preds = %entry
+  store i32 14, i32* %retval, align 4
+  br label %return
+
+sw.bb3:                                           ; preds = %entry
+  store i32 22, i32* %retval, align 4
+  br label %return
+
+sw.bb4:                                           ; preds = %entry
+  store i32 12, i32* %retval, align 4
+  br label %return
+
+sw.bb5:                                           ; preds = %entry
+  store i32 5, i32* %retval, align 4
+  br label %return
+
+sw.default:                                       ; preds = %entry
+  store i32 19, i32* %retval, align 4
+  br label %return
+
+return:                                           ; preds = %sw.default, %sw.bb5, %sw.bb4, %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb
+  %1 = load i32, i32* %retval, align 4
+  ret i32 %1
+}
+
+attributes #0 = { noinline nounwind "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"="hexagonv60" "target-features"="-hvx,-long-calls" "unsafe-fp-math"="false" "use-soft-float"="false" }

Added: llvm/trunk/test/Transforms/SimplifyCFG/HoistCode.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/HoistCode.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/HoistCode.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/HoistCode.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -simplifycfg -S | not grep br
+
+define void @foo(i1 %C, i32* %P) {
+        br i1 %C, label %T, label %F
+T:              ; preds = %0
+        store i32 7, i32* %P
+        ret void
+F:              ; preds = %0
+        store i32 7, i32* %P
+        ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/InfLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/InfLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/InfLoop.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/InfLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,101 @@
+; RUN: opt < %s -simplifycfg -disable-output
+; END.
+
+target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+target triple = "thumbv7-apple-ios9.0.0"
+
+%struct.anon = type { %struct.anon.0, i32, i32, %union.T1 }
+%struct.anon.0 = type { i32, [256 x i32], [256 x i8] }
+%union.T1 = type { %struct.F}
+%struct.F = type { i32 }
+
+ at U = internal global %struct.anon zeroinitializer, align 4
+
+define void @main() {
+entry:
+  %0 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @U, i32 0, i32 2), align 4
+  %cmp.i = icmp eq i32 %0, -1
+  br i1 %cmp.i, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %1 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @U, i32 0, i32 2), align 4
+  %bf.load = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @U, i32 0, i32 3, i32 0, i32 0), align 4
+  %cmp = icmp slt i32 %0, 0
+  br i1 %cmp, label %if.end7, label %cond.false
+
+cond.false:                                       ; preds = %if.end
+  %add = and i32 %bf.load, 30
+  %shl = add nuw nsw i32 %add, 2
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.end, %cond.false
+  %2 = icmp eq i32 %0, 1
+  br i1 %2, label %if.then9, label %if.else10
+
+if.then9:                                         ; preds = %if.end7
+  br label %if.end29
+
+if.else10:                                        ; preds = %if.end7
+  %cmp11 = icmp ugt i32 %0, 13
+  br i1 %cmp11, label %if.then12, label %if.else14
+
+if.then12:                                        ; preds = %if.else10
+  br label %if.end26
+
+if.else14:                                        ; preds = %if.else10
+  %tobool = icmp eq i1 %2, 0
+  br i1 %tobool, label %lor.rhs, label %if.then18
+
+lor.rhs:                                          ; preds = %if.else14
+  %tobool.not.i = icmp eq i1 %2, 0
+  br i1 %tobool.not.i, label %if.else21, label %if.end.i54
+
+if.end.i54:                                       ; preds = %lor.rhs
+  br label %for.cond.i
+
+for.cond.i:                                       ; preds = %if.end6.i, %if.end.i54
+  %ix.0.i = phi i32 [ 0, %if.end.i54 ], [ %inc.i55, %if.end6.i ]
+  %ret.0.off0.i = phi i1 [ false, %if.end.i54 ], [ %.ret.0.off0.i, %if.end6.i ]
+  %cmp2.i = icmp ult i32 %ix.0.i, 2
+  br i1 %cmp2.i, label %for.body.i, label %TmpSimpleNeedExt.exit
+
+for.body.i:                                       ; preds = %for.cond.i
+  %arrayidx.i = getelementptr inbounds %struct.anon, %struct.anon* @U, i32 0, i32 0, i32 2, i32 %ix.0.i
+  %elt = load i8, i8* %arrayidx.i, align 1
+  %cmp3.i = icmp sgt i8 %elt, 7
+  br i1 %cmp3.i, label %if.else21, label %if.end6.i
+
+if.end6.i:                                        ; preds = %for.body.i
+  %cmp10.i = icmp ugt i8 %elt, 59
+  %.ret.0.off0.i = or i1 %ret.0.off0.i, %cmp10.i
+  %inc.i55 = add i32 %ix.0.i, 1
+  br label %for.cond.i
+
+TmpSimpleNeedExt.exit:                            ; preds = %for.body.i
+  br i1 %ret.0.off0.i, label %if.then18, label %if.else21
+
+if.then18:                                        ; preds = %if.else14, %TmpSimpleNeedExt.exit
+  br label %if.end26
+
+if.else21:                                        ; preds = %for.body.i, %lor.rhs, %TmpSimpleNeedExt.exit
+  br label %if.end26
+
+if.end26:                                         ; preds = %if.then18, %if.else21, %if.then12
+  %cmp.i51 = icmp slt i32 %0, 7
+  br i1 %cmp.i51, label %if.then.i, label %if.end.i
+
+if.then.i:                                        ; preds = %if.end26
+  br label %if.end.i
+
+if.end.i:                                         ; preds = %if.then.i, %if.end26
+  br label %if.end29
+
+if.then2.i:                                       ; preds = %if.end.i
+  br label %if.end29
+
+if.end29:                                         ; preds = %if.end.i, %if.then2.i, %if.then9
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/MagicPointer.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/MagicPointer.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/MagicPointer.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/MagicPointer.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,149 @@
+; Test that simplifycfg can create switch instructions from constant pointers.
+;
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0.0"
+
+ at .str = private constant [5 x i8] c"null\00"      ; <[5 x i8]*> [#uses=2]
+ at .str1 = private constant [4 x i8] c"one\00"      ; <[4 x i8]*> [#uses=2]
+ at .str2 = private constant [4 x i8] c"two\00"      ; <[4 x i8]*> [#uses=2]
+ at .str3 = private constant [5 x i8] c"four\00"     ; <[5 x i8]*> [#uses=2]
+
+ at .str_as1 = private addrspace(1) constant [5 x i8] c"null\00"      ; <[5 x i8]*> [#uses=2]
+ at .str1_as1 = private addrspace(1) constant [4 x i8] c"one\00"      ; <[4 x i8]*> [#uses=2]
+ at .str2_as1 = private addrspace(1) constant [4 x i8] c"two\00"      ; <[4 x i8]*> [#uses=2]
+ at .str3_as1 = private addrspace(1) constant [5 x i8] c"four\00"     ; <[5 x i8]*> [#uses=2]
+
+declare i32 @puts(i8*)
+declare i32 @puts_as1(i8 addrspace(1)*)
+
+define void @f(i8* %x) nounwind ssp {
+; CHECK-LABEL: @f(
+; CHECK: switch i64 %magicptr
+; CHECK: i64 0, label
+; CHECK: i64 1, label
+; CHECK: i64 2, label
+; CHECK: i64 3, label
+; CHECK: i64 4, label
+; CHECK: }
+
+entry:
+  %tobool = icmp eq i8* %x, null                  ; <i1> [#uses=1]
+  br i1 %tobool, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end21
+
+if.else:                                          ; preds = %entry
+  %cmp = icmp eq i8* %x, inttoptr (i64 1 to i8*)  ; <i1> [#uses=1]
+  br i1 %cmp, label %if.then2, label %if.else4
+
+if.then2:                                         ; preds = %if.else
+  %call3 = call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end20
+
+if.else4:                                         ; preds = %if.else
+  %cmp6 = icmp eq i8* %x, inttoptr (i64 2 to i8*) ; <i1> [#uses=1]
+  br i1 %cmp6, label %if.then9, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %if.else4
+  %cmp8 = icmp eq i8* %x, inttoptr (i64 3 to i8*) ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then9, label %if.else11
+
+if.then9:                                         ; preds = %lor.lhs.false, %if.else4
+  %call10 = call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end19
+
+if.else11:                                        ; preds = %lor.lhs.false
+  %cmp13 = icmp eq i8* %x, inttoptr (i64 4 to i8*) ; <i1> [#uses=1]
+  br i1 %cmp13, label %if.then14, label %if.else16
+
+if.then14:                                        ; preds = %if.else11
+  %call15 = call i32 @puts(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str3, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end
+
+if.else16:                                        ; preds = %if.else11
+  %call18 = call i32 @puts(i8* %x) nounwind       ; <i32> [#uses=0]
+  br label %if.end
+
+if.end:                                           ; preds = %if.else16, %if.then14
+  br label %if.end19
+
+if.end19:                                         ; preds = %if.end, %if.then9
+  br label %if.end20
+
+if.end20:                                         ; preds = %if.end19, %if.then2
+  br label %if.end21
+
+if.end21:                                         ; preds = %if.end20, %if.then
+  ret void
+}
+
+; Is it useful to test a version where the ptrtoints are to the same
+; size?
+define void @f_as1(i8 addrspace(1)* %x) nounwind ssp {
+; CHECK-LABEL: @f_as1(
+; CHECK: ptrtoint i8 addrspace(1)* %x to i16
+; CHECK: switch i16 %magicptr
+; CHECK: i16 0, label
+; CHECK: i16 1, label
+; CHECK: i16 2, label
+; CHECK: i16 3, label
+; CHECK: i16 4, label
+; CHECK: }
+
+entry:
+  %tobool = icmp eq i8 addrspace(1)* %x, null                  ; <i1> [#uses=1]
+  br i1 %tobool, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %call = call i32 @puts_as1(i8 addrspace(1)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(1)* @.str_as1, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end21
+
+if.else:                                          ; preds = %entry
+  %cmp = icmp eq i8 addrspace(1)* %x, inttoptr (i64 1 to i8 addrspace(1)*)  ; <i1> [#uses=1]
+  br i1 %cmp, label %if.then2, label %if.else4
+
+if.then2:                                         ; preds = %if.else
+  %call3 = call i32 @puts_as1(i8 addrspace(1)* getelementptr inbounds ([4 x i8], [4 x i8] addrspace(1)* @.str1_as1, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end20
+
+if.else4:                                         ; preds = %if.else
+  %cmp6 = icmp eq i8 addrspace(1)* %x, inttoptr (i64 2 to i8 addrspace(1)*) ; <i1> [#uses=1]
+  br i1 %cmp6, label %if.then9, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %if.else4
+  %cmp8 = icmp eq i8 addrspace(1)* %x, inttoptr (i64 3 to i8 addrspace(1)*) ; <i1> [#uses=1]
+  br i1 %cmp8, label %if.then9, label %if.else11
+
+if.then9:                                         ; preds = %lor.lhs.false, %if.else4
+  %call10 = call i32 @puts_as1(i8 addrspace(1)* getelementptr inbounds ([4 x i8], [4 x i8] addrspace(1)* @.str2_as1, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end19
+
+if.else11:                                        ; preds = %lor.lhs.false
+  %cmp13 = icmp eq i8 addrspace(1)* %x, inttoptr (i64 4 to i8 addrspace(1)*) ; <i1> [#uses=1]
+  br i1 %cmp13, label %if.then14, label %if.else16
+
+if.then14:                                        ; preds = %if.else11
+  %call15 = call i32 @puts_as1(i8 addrspace(1)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(1)* @.str3_as1, i64 0, i64 0)) nounwind ; <i32> [#uses=0]
+  br label %if.end
+
+if.else16:                                        ; preds = %if.else11
+  %call18 = call i32 @puts_as1(i8 addrspace(1)* %x) nounwind       ; <i32> [#uses=0]
+  br label %if.end
+
+if.end:                                           ; preds = %if.else16, %if.then14
+  br label %if.end19
+
+if.end19:                                         ; preds = %if.end, %if.then9
+  br label %if.end20
+
+if.end20:                                         ; preds = %if.end19, %if.then2
+  br label %if.end21
+
+if.end21:                                         ; preds = %if.end20, %if.then
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/Mips/cttz-ctlz.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/Mips/cttz-ctlz.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/Mips/cttz-ctlz.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/Mips/cttz-ctlz.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -S -simplifycfg -mtriple=mips-linux-gnu < %s | FileCheck %s
+
+define i32 @ctlz(i32 %A) {
+; CHECK-LABEL: @ctlz(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]]
+; CHECK-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+define i32 @cttz(i32 %A) {
+; CHECK-LABEL: @cttz(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; CHECK-NEXT: [[CTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i32 32, i32 [[CTZ]]
+; CHECK-NEXT: ret i32 [[SEL]]
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:
+  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/Mips/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/Mips/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/Mips/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/Mips/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5 @@
+config.suffixes = ['.ll']
+
+targets = set(config.root.targets_to_build.split())
+if not 'Mips' in targets:
+    config.unsupported = True

Added: llvm/trunk/test/Transforms/SimplifyCFG/PHINode.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PHINode.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PHINode.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PHINode.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; -simplifycfg is not folding blocks if there is a PHI node involved.  This 
+; should be fixed eventually
+
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define i32 @main(i32 %argc) {
+; <label>:0
+; CHECK-NOT: br label %InlinedFunctionReturnNode
+	br label %InlinedFunctionReturnNode
+InlinedFunctionReturnNode:		; preds = %0
+	%X = phi i32 [ 7, %0 ]		; <i32> [#uses=1]
+	%Y = add i32 %X, %argc		; <i32> [#uses=1]
+	ret i32 %Y
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR16069.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR16069.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR16069.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR16069.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+ at b = extern_weak global i32
+
+define i32 @foo(i1 %y) {
+; CHECK-LABEL: @foo(
+; CHECK:         [[COND_I:%.*]] = phi i32 [ srem (i32 1, i32 zext (i1 icmp eq (i32* @b, i32* null) to i32)), %bb2 ], [ 0, %0 ]
+; CHECK-NEXT:    ret i32 [[COND_I]]
+;
+  br i1 %y, label %bb1, label %bb2
+bb1:
+  br label %bb3
+bb2:
+  br label %bb3
+bb3:
+  %cond.i = phi i32 [ 0, %bb1 ], [ srem (i32 1, i32 zext (i1 icmp eq (i32* @b, i32* null) to i32)), %bb2 ]
+  ret i32 %cond.i
+}
+
+define i32 @foo2(i1 %x) {
+; CHECK-LABEL: @foo2(
+; CHECK:         [[COND:%.*]] = phi i32 [ 0, %bb1 ], [ srem (i32 1, i32 zext (i1 icmp eq (i32* @b, i32* null) to i32)), %bb0 ]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+bb0:
+  br i1 %x, label %bb1, label %bb2
+bb1:
+  br label %bb2
+bb2:
+  %cond = phi i32 [ 0, %bb1 ], [ srem (i32 1, i32 zext (i1 icmp eq (i32* @b, i32* null) to i32)), %bb0 ]
+  ret i32 %cond
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR17073.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR17073.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR17073.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR17073.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,73 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; In PR17073 ( http://llvm.org/pr17073 ), we illegally hoisted an operation that can trap.
+; The first test confirms that we don't do that when the trapping op is reached by the current BB (block1).
+; The second test confirms that we don't do that when the trapping op is reached by the previous BB (entry).
+; The third test confirms that we can still do this optimization for an operation (add) that doesn't trap.
+; The tests must be complicated enough to prevent previous SimplifyCFG actions from optimizing away
+; the instructions that we're checking for.
+
+target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"
+target triple = "i386-apple-macosx10.9.0"
+
+ at a = common global i32 0, align 4
+ at b = common global i8 0, align 1
+
+; CHECK-LABEL: can_trap1 
+; CHECK-NOT: or i1 %tobool, icmp eq (i32* bitcast (i8* @b to i32*), i32* @a)
+; CHECK-NOT: select i1 %tobool, i32* null, i32* select (i1 icmp eq (i64 urem (i64 2, i64 zext (i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a) to i64)), i64 0), i32* null, i32* @a) 
+define i32* @can_trap1() {
+entry:
+  %0 = load i32, i32* @a, align 4
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %exit, label %block1
+
+block1:
+  br i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a), label %exit, label %block2
+
+block2:
+  br label %exit
+
+exit:
+  %storemerge = phi i32* [ null, %entry ],[ null, %block2 ], [ select (i1 icmp eq (i64 urem (i64 2, i64 zext (i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a) to i64)), i64 0), i32* null, i32* @a), %block1 ]
+  ret i32* %storemerge
+}
+
+; CHECK-LABEL: can_trap2 
+; CHECK-NOT: or i1 %tobool, icmp eq (i32* bitcast (i8* @b to i32*), i32* @a)
+; CHECK-NOT: select i1 %tobool, i32* select (i1 icmp eq (i64 urem (i64 2, i64 zext (i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a) to i64)), i64 0), i32* null, i32* @a), i32* null
+define i32* @can_trap2() {
+entry:
+  %0 = load i32, i32* @a, align 4
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %exit, label %block1
+
+block1:
+  br i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a), label %exit, label %block2
+
+block2:
+  br label %exit
+
+exit:
+  %storemerge = phi i32* [ select (i1 icmp eq (i64 urem (i64 2, i64 zext (i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a) to i64)), i64 0), i32* null, i32* @a), %entry ],[ null, %block2 ], [ null, %block1 ]
+  ret i32* %storemerge
+}
+
+; CHECK-LABEL: cannot_trap 
+; CHECK: select i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a), i32* select (i1 icmp eq (i64 add (i64 zext (i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a) to i64), i64 2), i64 0), i32* null, i32* @a), i32* null
+define i32* @cannot_trap() {
+entry:
+  %0 = load i32, i32* @a, align 4
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %exit, label %block1
+
+block1:
+  br i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a), label %exit, label %block2
+
+block2:
+  br label %exit
+
+exit:
+  %storemerge = phi i32* [ null, %entry ],[ null, %block2 ], [ select (i1 icmp eq (i64 add (i64 2, i64 zext (i1 icmp eq (i32* bitcast (i8* @b to i32*), i32* @a) to i64)), i64 0), i32* null, i32* @a), %block1 ]
+  ret i32* %storemerge
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR25267.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR25267.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR25267.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR25267.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define void @f() {
+entry:
+  br label %for.cond
+
+for.cond:
+  %phi = phi i1 [ false, %entry ], [ true, %for.body ]
+  %select = select i1 %phi, i32 1, i32 2
+  br label %for.body
+
+for.body:
+  switch i32 %select, label %for.cond [
+    i32 1, label %return
+    i32 2, label %for.body
+  ]
+
+return:
+  ret void
+}
+
+; CHECK-LABEL: define void @f(
+; CHECK: br label %[[LABEL:.*]]
+; CHECK: br label %[[LABEL]]

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR27615-simplify-cond-br.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR27615-simplify-cond-br.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR27615-simplify-cond-br.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR27615-simplify-cond-br.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt -S -simplifycfg -strip-debug < %s | FileCheck %s
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+; Test case for BUG-27615
+; Test that simplify cond branch produce same result for debug and non-debug builds
+; CHECK: select i1 %or.cond, i32 -1, i32 5
+; CHECK-NOT: bb1:
+
+; ModuleID = './csmith107.i.debug.ll'
+source_filename = "./csmith107.i.debug.ll"
+
+ at a = global i16 0, !dbg !0
+ at b = global i32 0, !dbg !4
+ at c = global i16* null, !dbg !9
+
+define i16 @fn1() !dbg !17 {
+bb2:
+  store i32 -1, i32* @b, align 1
+  %_tmp1.pre = load i16, i16* @a, align 1, !dbg !20
+  %_tmp2.pre = load i16*, i16** @c, align 1
+  tail call void @llvm.dbg.value(metadata i16 6, metadata !22, metadata !23), !dbg !24
+  tail call void @llvm.dbg.value(metadata i16 %_tmp1.pre, metadata !25, metadata !23), !dbg !20
+  %_tmp3 = load i16, i16* %_tmp2.pre, align 1
+  %_tmp4 = icmp ne i16 %_tmp3, 0
+  %_tmp6 = icmp ne i16 %_tmp1.pre, 0
+  %or.cond = and i1 %_tmp6, %_tmp4
+  br i1 %or.cond, label %bb5, label %bb1
+
+bb1:                                              ; preds = %bb2
+  store i32 5, i32* @b, align 1
+  br label %bb5
+
+bb5:                                              ; preds = %bb1, %bb2
+  ret i16 0
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!12}
+!llvm.module.flags = !{!15, !16}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 2, type: !3, isLocal: false, isDefinition: true)
+!2 = !DIFile(filename: "csmith107.i.c", directory: "/tmp")
+!3 = !DIBasicType(name: "int", size: 16, align: 16, encoding: DW_ATE_signed)
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = !DIGlobalVariable(name: "b", scope: null, file: !2, line: 3, type: !6, isLocal: false, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint32_t", file: !2, line: 1, baseType: !7)
+!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u32_t", file: !2, baseType: !8)
+!8 = !DIBasicType(name: "unsigned long", size: 32, align: 16, encoding: DW_ATE_unsigned)
+!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
+!10 = !DIGlobalVariable(name: "c", scope: null, file: !2, line: 4, type: !11, isLocal: false, isDefinition: true)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 16, align: 16)
+!12 = distinct !DICompileUnit(language: DW_LANG_C, file: !2, producer: "FlexC Compiler v6.36 (LLVM)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !13, retainedTypes: !13, globals: !14)
+!13 = !{}
+!14 = !{!0, !4, !9}
+!15 = !{i32 2, !"Dwarf Version", i32 4}
+!16 = !{i32 2, !"Debug Info Version", i32 3}
+!17 = distinct !DISubprogram(name: "fn1", scope: !2, file: !2, line: 5, type: !18, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: false, unit: !12, retainedNodes: !13)
+!18 = !DISubroutineType(types: !19)
+!19 = !{!3}
+!20 = !DILocation(line: 8, column: 16, scope: !21)
+!21 = !DILexicalBlock(scope: !17, file: !2, line: 7, column: 29)
+!22 = !DILocalVariable(name: "d", scope: !21, line: 8, type: !3)
+!23 = !DIExpression()
+!24 = !DILocation(line: 8, column: 9, scope: !21)
+!25 = !DILocalVariable(name: "e", scope: !21, line: 8, type: !3)
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR29163.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR29163.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR29163.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR29163.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -S -simplifycfg < %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 GV = external constant i64*
+
+define i64* @test1(i1 %cond, i8* %P) {
+entry:
+  br i1 %cond, label %if, label %then
+
+then:
+  %bc = bitcast i8* %P to i64*
+  br label %join
+
+if:
+  %load = load i64*, i64** @GV, align 8, !dereferenceable !0
+  br label %join
+
+join:
+  %phi = phi i64* [ %bc, %then ], [ %load, %if ]
+  ret i64* %phi
+}
+
+; CHECK-LABEL: define i64* @test1(
+; CHECK: %[[bc:.*]] = bitcast i8* %P to i64*
+; CHECK: %[[load:.*]] = load i64*, i64** @GV, align 8{{$}}
+; CHECK: %[[phi:.*]] = select i1 %cond, i64* %[[load]], i64* %[[bc]]
+; CHECK: ret i64* %[[phi]]
+
+
+!0 = !{i64 8}

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR30210.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR30210.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR30210.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR30210.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32* @fn1(i32* returned)
+
+define i32 @test1(i1 %B) {
+entry:
+  br label %for.cond.us
+
+for.cond.us:                                      ; preds = %for.cond.us, %entry
+  br i1 %B, label %for.cond4.preheader, label %for.cond.us
+
+for.cond4.preheader:                              ; preds = %for.cond.us
+  br i1 %B, label %for.cond4.preheader.split.us, label %for.cond4
+
+for.cond4.preheader.split.us:                     ; preds = %for.cond4.preheader
+  unreachable
+
+for.cond4:                                        ; preds = %for.end, %for.cond4.preheader
+  %phi = phi i32* [ %call, %for.end ], [ undef, %for.cond4.preheader ]
+  %call = call i32* @fn1(i32* %phi)
+  br label %for.cond5
+
+for.cond5:                                        ; preds = %for.cond5, %for.cond4
+  br i1 %B, label %for.cond5, label %for.end
+
+for.end:                                          ; preds = %for.cond5
+  %load = load i32, i32* %call, align 4
+  br label %for.cond4
+}
+
+; CHECK-LABEL: define i32 @test1(
+; CHECK: br label %[[LABEL:.*]]
+; CHECK: [[LABEL]]:
+; CHECK: br label %[[LABEL]]

Added: llvm/trunk/test/Transforms/SimplifyCFG/PR9946.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PR9946.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PR9946.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PR9946.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -simplifycfg -disable-output < %s
+
+ at foo = external constant i32
+
+define i32 @f() {
+entry:
+  br i1 icmp eq (i64 and (i64 ptrtoint (i32* @foo to i64), i64 15), i64 0), label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %storemerge = phi i32 [ 1, %if.end ], [ 0, %if.then ]
+  ret i32 %storemerge
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by update_test_checks.py
+; Test merging of blocks that only have PHI nodes in them
+;
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+;
+
+define i32 @test(i1 %a, i1 %b) {
+; CHECK-LABEL: @test(
+; CHECK:       M:
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 %b, i32 0, i32 1
+; CHECK-NEXT:    [[W:%.*]] = select i1 %a, i32 2, i32 [[DOT]]
+; CHECK-NEXT:    [[R:%.*]] = add i32 [[W]], 1
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  br i1 %a, label %M, label %O
+O:              ; preds = %0
+  br i1 %b, label %N, label %Q
+Q:              ; preds = %O
+  br label %N
+N:              ; preds = %Q, %O
+  ; This block should be foldable into M
+  %Wp = phi i32 [ 0, %O ], [ 1, %Q ]              ; <i32> [#uses=1]
+  br label %M
+M:              ; preds = %N, %0
+  %W = phi i32 [ %Wp, %N ], [ 2, %0 ]             ; <i32> [#uses=1]
+  %R = add i32 %W, 1              ; <i32> [#uses=1]
+  ret i32 %R
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge2.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PhiBlockMerge2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; Test merging of blocks that only have PHI nodes in them.  This tests the case
+; where the mergedinto block doesn't have any PHI nodes, and is in fact 
+; dominated by the block-to-be-eliminated
+;
+; RUN: opt < %s -simplifycfg -S | not grep N:
+;
+
+declare i1 @foo()
+
+define i32 @test(i1 %a, i1 %b) {
+        %c = call i1 @foo()
+	br i1 %c, label %N, label %P
+P:
+        %d = call i1 @foo()
+	br i1 %d, label %N, label %Q
+Q:
+	br label %N
+N:
+	%W = phi i32 [0, %0], [1, %Q], [2, %P]
+	; This block should be foldable into M
+	br label %M
+
+M:
+	%R = add i32 %W, 1
+	ret i32 %R
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; Test a bunch of cases where the cfg simplification code should
+; be able to fold PHI nodes into computation in common cases.  Folding the PHI
+; nodes away allows the branches to be eliminated, performing a simple form of
+; 'if conversion'.
+
+; RUN: opt < %s -simplifycfg -S > %t.xform
+; RUN:   not grep phi %t.xform 
+; RUN:   grep ret %t.xform
+
+declare void @use(i1)
+
+declare void @use.upgrd.1(i32)
+
+
+define void @test(i1 %c, i32 %V, i32 %V2) {
+; <label>:0
+        br i1 %c, label %T, label %F
+T:              ; preds = %0
+        br label %F
+F:              ; preds = %T, %0
+        %B1 = phi i1 [ true, %0 ], [ false, %T ]                ; <i1> [#uses=1]
+        %I6 = phi i32 [ %V, %0 ], [ 0, %T ]             ; <i32> [#uses=1]
+        call void @use( i1 %B1 )
+        call void @use.upgrd.1( i32 %I6 )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate2.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Use a select to make this a single BB.
+; Also, make sure the profile metadata is propagated to the select (PR26636).
+
+define i32 @FoldTwoEntryPHINode(i1 %C, i32 %V1, i32 %V2, i16 %V3) {
+entry:
+        br i1 %C, label %then, label %else, !prof !0, !unpredictable !1
+then:
+        %V4 = or i32 %V2, %V1
+        br label %Cont
+else:
+        %V5 = sext i16 %V3 to i32
+        br label %Cont
+Cont:
+        %V6 = phi i32 [ %V5, %else ], [ %V4, %then ]
+        call i32 @FoldTwoEntryPHINode( i1 false, i32 0, i32 0, i16 0 )
+        ret i32 %V1
+
+; CHECK-LABEL: @FoldTwoEntryPHINode(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:  %V5 = sext i16 %V3 to i32
+; CHECK-NEXT:  %V4 = or i32 %V2, %V1
+; CHECK-NEXT:  %V6 = select i1 %C, i32 %V4, i32 %V5, !prof !0, !unpredictable !1
+; CHECK-NEXT:  %0 = call i32 @FoldTwoEntryPHINode(i1 false, i32 0, i32 0, i16 0)
+; CHECK-NEXT:  ret i32 %V1
+}
+
+!0 = !{!"branch_weights", i32 3, i32 5}
+!1 = !{}
+
+; CHECK: !0 = !{!"branch_weights", i32 3, i32 5}
+; CHECK: !1 = !{}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate3.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PhiEliminate3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; Test merging of blocks containing complex expressions,
+; with various folding thresholds
+;
+; RUN: opt < %s -simplifycfg -S -phi-node-folding-threshold=1 | grep N:
+; RUN: opt < %s -simplifycfg -S -phi-node-folding-threshold=2 | not grep N:
+; RUN: opt < %s -simplifycfg -S -phi-node-folding-threshold=2 | grep M:
+; RUN: opt < %s -simplifycfg -S -phi-node-folding-threshold=7 | not grep M:
+;
+
+define i32 @test(i1 %a, i1 %b, i32 %i, i32 %j, i32 %k) {
+entry:
+        br i1 %a, label %M, label %O
+O:
+        br i1 %b, label %P, label %Q
+P:
+        %iaj = add i32 %i, %j
+        %iajak = add i32 %iaj, %k
+        br label %N
+Q:
+        %ixj = xor i32 %i, %j
+        %ixjxk = xor i32 %ixj, %k
+        br label %N
+N:
+        ; This phi should be foldable if threshold >= 2
+        %Wp = phi i32 [ %iajak, %P ], [ %ixjxk, %Q ]
+        %Wp2 = add i32 %Wp, %Wp
+        br label %M
+M:
+        ; This phi should be foldable if threshold >= 7
+        %W = phi i32 [ %Wp2, %N ], [ 2, %entry ]
+        %R = add i32 %W, 1
+        ret i32 %R
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/PhiNoEliminate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PhiNoEliminate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PhiNoEliminate.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PhiNoEliminate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -simplifycfg -S | \
+; RUN:   not grep select
+
+;; The PHI node in this example should not be turned into a select, as we are
+;; not able to ifcvt the entire block.  As such, converting to a select just 
+;; introduces inefficiency without saving copies.
+
+define i32 @bar(i1 %C) {
+entry:
+        br i1 %C, label %then, label %endif
+then:           ; preds = %entry
+        %tmp.3 = call i32 @qux( )               ; <i32> [#uses=0]
+        br label %endif
+endif:          ; preds = %then, %entry
+        %R = phi i32 [ 123, %entry ], [ 12312, %then ]          ; <i32> [#uses=1]
+        ;; stuff to disable tail duplication
+        call i32 @qux( )                ; <i32>:0 [#uses=0]
+        call i32 @qux( )                ; <i32>:1 [#uses=0]
+        call i32 @qux( )                ; <i32>:2 [#uses=0]
+        call i32 @qux( )                ; <i32>:3 [#uses=0]
+        call i32 @qux( )                ; <i32>:4 [#uses=0]
+        call i32 @qux( )                ; <i32>:5 [#uses=0]
+        call i32 @qux( )                ; <i32>:6 [#uses=0]
+        ret i32 %R
+}
+
+declare i32 @qux()

Added: llvm/trunk/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/PowerPC/cttz-ctlz-spec.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck -enable-var-scope %s
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+define i64 @test1(i64 %A) {
+; CHECK-LABEL: @test1(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; CHECK-NEXT: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTLZ]]
+; CHECK-NEXT: ret i64 [[SEL]]
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
+  ret i64 %cond
+}
+
+define i64 @test1b(i64 %A) {
+; CHECK-LABEL: @test1b(
+; CHECK: [[ICMP:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; CHECK-NEXT: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+; CHECK-NEXT: [[SEL:%[A-Za-z0-9.]+]] = select i1 [[ICMP]], i64 64, i64 [[CTTZ]]
+; CHECK-NEXT: ret i64 [[SEL]]
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
+  ret i64 %cond
+}
+
+declare i64 @llvm.ctlz.i64(i64, i1)
+declare i64 @llvm.cttz.i64(i64, i1)
+

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

Added: llvm/trunk/test/Transforms/SimplifyCFG/RISCV/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/RISCV/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/RISCV/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/RISCV/lit.local.cfg Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5 @@
+config.suffixes = ['.ll']
+
+targets = set(config.root.targets_to_build.split())
+if not 'RISCV' in targets:
+    config.unsupported = True

Added: llvm/trunk/test/Transforms/SimplifyCFG/RISCV/select-trunc-i64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/RISCV/select-trunc-i64.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/RISCV/select-trunc-i64.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/RISCV/select-trunc-i64.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+;RUN: opt -S -simplifycfg -mtriple=riscv32 < %s | FileCheck %s
+
+; Test case taken from test/Transforms/SimplifyCFG/ARM/select-trunc-i64.ll.
+; A correct implementation of isTruncateFree allows this test case to be
+; reduced to a single basic block.
+
+; CHECK-LABEL: select_trunc_i64
+; CHECK-NOT: br
+; CHECK: select
+; CHECK: select
+define i32 @select_trunc_i64(i32 %a, i32 %b) {
+entry:
+  %conv = sext i32 %a to i64
+  %conv1 = sext i32 %b to i64
+  %add = add nsw i64 %conv1, %conv
+  %cmp = icmp sgt i64 %add, 2147483647
+  br i1 %cmp, label %cond.end7, label %cond.false
+
+cond.false:                                       ; preds = %entry
+  %0 = icmp sgt i64 %add, -2147483648
+  %cond = select i1 %0, i64 %add, i64 -2147483648
+  %extract.t = trunc i64 %cond to i32
+  br label %cond.end7
+
+cond.end7:                                        ; preds = %cond.false, %entry
+  %cond8.off0 = phi i32 [ 2147483647, %entry ], [ %extract.t, %cond.false ]
+  ret i32 %cond8.off0
+}

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

Added: llvm/trunk/test/Transforms/SimplifyCFG/SPARC/switch_to_lookup_table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/SPARC/switch_to_lookup_table.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/SPARC/switch_to_lookup_table.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/SPARC/switch_to_lookup_table.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -simplifycfg -S -mtriple=sparc-unknown-unknown | FileCheck %s
+
+; Check that switches are not turned into lookup tables, as this is not
+; considered profitable on the target.
+
+define i32 @f(i32 %c) nounwind uwtable readnone {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+    i32 46, label %sw.bb4
+    i32 47, label %sw.bb5
+    i32 48, label %sw.bb6
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @f(
+; CHECK-NOT: getelementptr
+; CHECK: switch i32 %c
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/SpeculativeExec.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,121 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -phi-node-folding-threshold=2 -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @test1(i32 %a, i32 %b, i32 %c) nounwind  {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB1:%.*]], label [[BB3:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[C:%.*]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[A:%.*]], 1
+; CHECK-NEXT:    [[TMP3_A:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[A]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[TMP3_A]], [[BB1]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = sub i32 [[TMP4]], 1
+; CHECK-NEXT:    ret i32 [[TMP5]]
+;
+entry:
+  %tmp1 = icmp eq i32 %b, 0
+  br i1 %tmp1, label %bb1, label %bb3
+
+bb1:            ; preds = %entry
+  %tmp2 = icmp sgt i32 %c, 1
+  br i1 %tmp2, label %bb2, label %bb3
+
+bb2:		; preds = bb1
+  %tmp3 = add i32 %a, 1
+  br label %bb3
+
+bb3:		; preds = %bb2, %entry
+  %tmp4 = phi i32 [ %b, %entry ], [ %a, %bb1 ], [ %tmp3, %bb2 ]
+  %tmp5 = sub i32 %tmp4, 1
+  ret i32 %tmp5
+}
+
+define i8* @test4(i1* %dummy, i8* %a, i8* %b) {
+; Test that we don't speculate an arbitrarily large number of unfolded constant
+; expressions.
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND1:%.*]] = load volatile i1, i1* [[DUMMY:%.*]]
+; CHECK-NEXT:    br i1 [[COND1]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[COND2:%.*]] = load volatile i1, i1* [[DUMMY]]
+; CHECK-NEXT:    br i1 [[COND2]], label [[THEN:%.*]], label [[END]]
+; CHECK:       then:
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[X1:%.*]] = phi i8* [ [[A:%.*]], [[ENTRY:%.*]] ], [ [[B:%.*]], [[IF]] ], [ inttoptr (i64 1 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X2:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 2 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X3:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 3 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X4:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 4 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X5:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 5 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X6:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 6 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X7:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 7 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X8:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 8 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X9:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 9 to i8*), [[THEN]] ]
+; CHECK-NEXT:    [[X10:%.*]] = phi i8* [ [[A]], [[ENTRY]] ], [ [[B]], [[IF]] ], [ inttoptr (i64 10 to i8*), [[THEN]] ]
+; CHECK-NEXT:    ret i8* [[X10]]
+;
+
+entry:
+  %cond1 = load volatile i1, i1* %dummy
+  br i1 %cond1, label %if, label %end
+
+if:
+  %cond2 = load volatile i1, i1* %dummy
+  br i1 %cond2, label %then, label %end
+
+then:
+  br label %end
+
+end:
+  %x1 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 1 to i8*), %then ]
+  %x2 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 2 to i8*), %then ]
+  %x3 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 3 to i8*), %then ]
+  %x4 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 4 to i8*), %then ]
+  %x5 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 5 to i8*), %then ]
+  %x6 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 6 to i8*), %then ]
+  %x7 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 7 to i8*), %then ]
+  %x8 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 8 to i8*), %then ]
+  %x9 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 9 to i8*), %then ]
+  %x10 = phi i8* [ %a, %entry ], [ %b, %if ], [ inttoptr (i64 10 to i8*), %then ]
+
+  ret i8* %x10
+}
+
+define i32* @test5(i32 %a, i32 %b, i32 %c, i32* dereferenceable(10) %ptr1,
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB1:%.*]], label [[BB3:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[C:%.*]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = load i32*, i32** [[PTR3:%.*]]
+; CHECK-NEXT:    [[TMP3_PTR2:%.*]] = select i1 [[TMP2]], i32* [[TMP3]], i32* [[PTR2:%.*]]
+; CHECK-NEXT:    ret i32* [[TMP3_PTR2]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i32* [[PTR1:%.*]]
+;
+  i32* dereferenceable(10) %ptr2, i32** dereferenceable(10) %ptr3) nounwind {
+entry:
+  %tmp1 = icmp eq i32 %b, 0
+  br i1 %tmp1, label %bb1, label %bb3
+
+bb1:            ; preds = %entry
+  %tmp2 = icmp sgt i32 %c, 1
+  br i1 %tmp2, label %bb2, label %bb3
+
+bb2:		; preds = bb1
+  %tmp3 = load i32*, i32** %ptr3, !dereferenceable !{i64 10}
+  br label %bb3
+
+bb3:		; preds = %bb2, %entry
+  %tmp4 = phi i32* [ %ptr1, %entry ], [ %ptr2, %bb1 ], [ %tmp3, %bb2 ]
+  ret i32* %tmp4
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToHeader.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToHeader.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToHeader.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToHeader.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Check that we can get rid of empty block leading to header
+; if it does not introduce new edge.
+define i32 @test(i32 %c) {
+entry:
+  br label %header
+header:
+  %i = phi i32 [0, %entry], [%i.1, %backedge]
+  %i.1 = add i32 %i, 1
+  %cmp = icmp slt i32 %i.1, %c
+  br i1 %cmp, label %backedge, label %exit
+; CHECK-NOT: backedge:
+backedge:
+  br label %header
+exit:
+  ret i32 %i
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToReturn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToReturn.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToReturn.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/UncondBranchToReturn.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; The unify-function-exit-nodes pass often makes basic blocks that just contain
+; a PHI node and a return.  Make sure the simplify cfg can straighten out this
+; important case.  This is basically the most trivial form of tail-duplication.
+
+; RUN: opt < %s -simplifycfg -S | \
+; RUN:    not grep "br label"
+
+define i32 @test(i1 %B, i32 %A, i32 %B.upgrd.1) {
+        br i1 %B, label %T, label %F
+T:              ; preds = %0
+        br label %ret
+F:              ; preds = %0
+        br label %ret
+ret:            ; preds = %F, %T
+        %X = phi i32 [ %A, %F ], [ %B.upgrd.1, %T ]             ; <i32> [#uses=1]
+        ret i32 %X
+}
+
+
+; Make sure it's willing to move unconditional branches to return instructions
+; as well, even if the return block is shared and the source blocks are
+; non-empty.
+define i32 @test2(i1 %B, i32 %A, i32 %B.upgrd.2) {
+        br i1 %B, label %T, label %F
+T:              ; preds = %0
+        call i32 @test( i1 true, i32 5, i32 8 )         ; <i32>:1 [#uses=0]
+        br label %ret
+F:              ; preds = %0
+        call i32 @test( i1 true, i32 5, i32 8 )         ; <i32>:2 [#uses=0]
+        br label %ret
+ret:            ; preds = %F, %T
+        ret i32 %A
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/UnreachableEliminate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/UnreachableEliminate.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/UnreachableEliminate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,188 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define void @test1(i1 %C, i1* %BP) {
+; CHECK-LABEL: @test1(
+; CHECK: entry:
+; CHECK-NEXT: ret void
+entry:
+        br i1 %C, label %T, label %F
+T:
+        store i1 %C, i1* %BP
+        unreachable
+F:
+        ret void
+}
+
+define void @test2() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: @test2(
+; CHECK: entry:
+; CHECK-NEXT: call void @test2()
+; CHECK-NEXT: ret void
+entry:
+        invoke void @test2( )
+                        to label %N unwind label %U
+U:
+  %res = landingpad { i8* }
+          cleanup
+        unreachable
+N:
+        ret void
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+define i32 @test3(i32 %v) {
+; CHECK-LABEL: @test3(
+; CHECK: entry:
+; CHECK-NEXT: [[CMP:%[A-Za-z0-9]+]] = icmp eq i32 %v, 2
+; CHECK-NEXT: select i1 [[CMP]], i32 2, i32 1
+; CHECK-NEXT: ret
+entry:
+        switch i32 %v, label %default [
+                 i32 1, label %U
+                 i32 2, label %T
+        ]
+default:
+        ret i32 1
+U:
+        unreachable
+T:
+        ret i32 2
+}
+
+
+;; We can either convert the following control-flow to a select or remove the
+;; unreachable control flow because of the undef store of null. Make sure we do
+;; the latter.
+
+define void @test5(i1 %cond, i8* %ptr) {
+
+; CHECK-LABEL: test5
+; CHECK: entry:
+; CHECK-NOT: select
+; CHECK:  store i8 2, i8* %ptr
+; CHECK:  ret
+
+entry:
+  br i1 %cond, label %bb1, label %bb3
+
+bb3:
+ br label %bb2
+
+bb1:
+ br label %bb2
+
+bb2:
+  %ptr.2 = phi i8* [ %ptr, %bb3 ], [ null, %bb1 ]
+  store i8 2, i8* %ptr.2, align 8
+  ret void
+}
+
+define void @test5_no_null_opt(i1 %cond, i8* %ptr) #0 {
+
+; CHECK-LABEL: test5_no_null_opt
+; CHECK: entry:
+; CHECK: %[[SEL:.*]] = select i1 %cond, i8* null, i8* %ptr
+; CHECK: store i8 2, i8* %[[SEL]]
+
+entry:
+  br i1 %cond, label %bb1, label %bb3
+
+bb3:
+ br label %bb2
+
+bb1:
+ br label %bb2
+
+bb2:
+  %ptr.2 = phi i8* [ %ptr, %bb3 ], [ null, %bb1 ]
+  store i8 2, i8* %ptr.2, align 8
+  ret void
+}
+
+; CHECK-LABEL: test6
+; CHECK: entry:
+; CHECK-NOT: select
+; CHECK:  store i8 2, i8* %ptr
+; CHECK:  ret
+
+define void @test6(i1 %cond, i8* %ptr) {
+entry:
+  br i1 %cond, label %bb1, label %bb2
+
+bb1:
+  br label %bb2
+
+bb2:
+  %ptr.2 = phi i8* [ %ptr, %entry ], [ null, %bb1 ]
+  store i8 2, i8* %ptr.2, align 8
+  ret void
+}
+
+; CHECK-LABEL: test6_no_null_opt
+; CHECK: entry:
+; CHECK: %[[SEL:.*]] = select i1 %cond, i8* null, i8* %ptr
+; CHECK: store i8 2, i8* %[[SEL]]
+
+define void @test6_no_null_opt(i1 %cond, i8* %ptr) #0 {
+entry:
+  br i1 %cond, label %bb1, label %bb2
+
+bb1:
+  br label %bb2
+
+bb2:
+  %ptr.2 = phi i8* [ %ptr, %entry ], [ null, %bb1 ]
+  store i8 2, i8* %ptr.2, align 8
+  ret void
+}
+
+
+define i32 @test7(i1 %X) {
+entry:
+  br i1 %X, label %if, label %else
+
+if:
+  call void undef()
+  br label %else
+
+else:
+  %phi = phi i32 [ 0, %entry ], [ 1, %if ]
+  ret i32 %phi
+}
+; CHECK-LABEL: define i32 @test7(
+; CHECK-NOT: call
+; CHECK: ret i32 0
+
+define void @test8(i1 %X, void ()* %Y) {
+entry:
+  br i1 %X, label %if, label %else
+
+if:
+  br label %else
+
+else:
+  %phi = phi void ()* [ %Y, %entry ], [ null, %if ]
+  call void %phi()
+  ret void
+}
+; CHECK-LABEL: define void @test8(
+; CHECK: call void %Y(
+
+define void @test8_no_null_opt(i1 %X, void ()* %Y) #0 {
+entry:
+  br i1 %X, label %if, label %else
+
+if:
+  br label %else
+
+else:
+  %phi = phi void ()* [ %Y, %entry ], [ null, %if ]
+  call void %phi()
+  ret void
+}
+attributes #0 = { "null-pointer-is-valid"="true" }
+
+; CHECK-LABEL: define void @test8_no_null_opt(
+; CHECK: %[[SEL:.*]] = select i1 %X, void ()* null, void ()* %Y
+; CHECK: call void %[[SEL]]

Added: llvm/trunk/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/X86/disable-lookup-table.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,46 @@
+; RUN: opt < %s -simplifycfg -switch-to-lookup -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+; RUN: opt < %s -passes='simplify-cfg<switch-to-lookup>' -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+; In the presence of "-no-jump-tables"="true", simplifycfg should not convert switches to lookup tables.
+
+; CHECK: @switch.table.bar = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1]
+; CHECK-LABEL: foo
+; CHECK-NOT: @switch.table.foo = private unnamed_addr constant [4 x i32] [i32 55, i32 123, i32 0, i32 -1]
+
+define i32 @foo(i32 %c) "no-jump-tables"="true" {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ],  [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+}
+
+
+define i32 @bar(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ],  [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/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/SimplifyCFG/X86/speculate-cttz-ctlz.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/X86/speculate-cttz-ctlz.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,318 @@
+; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
+; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
+; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC
+
+
+define i64 @test1(i64 %A) {
+; ALL-LABEL: @test1(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]]
+; ALL: ret
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
+  ret i64 %cond
+}
+
+define i32 @test2(i32 %A) {
+; ALL-LABEL: @test2(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]]
+; ALL: ret
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+
+define signext i16 @test3(i16 signext %A) {
+; ALL-LABEL: @test3(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
+; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]]
+; ALL: ret
+entry:
+  %tobool = icmp eq i16 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
+  ret i16 %cond
+}
+
+
+define i64 @test1b(i64 %A) {
+; ALL-LABEL: @test1b(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]]
+; ALL: ret
+entry:
+  %tobool = icmp eq i64 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
+  ret i64 %cond
+}
+
+
+define i32 @test2b(i32 %A) {
+; ALL-LABEL: @test2b(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]]
+; ALL: ret
+entry:
+  %tobool = icmp eq i32 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
+  ret i32 %cond
+}
+
+
+define signext i16 @test3b(i16 signext %A) {
+; ALL-LABEL: @test3b(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
+; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]]
+; ALL: ret
+entry:
+  %tobool = icmp eq i16 %A, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
+  ret i16 %cond
+}
+
+; The following tests verify that calls to cttz/ctlz are speculated even if
+; basic block %cond.true has an extra zero extend/truncate which is "free"
+; for the target.
+
+define i64 @test1e(i32 %x) {
+; ALL-LABEL: @test1e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
+; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64
+; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
+; LZCNT-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i32 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %phitmp2 = zext i32 %0 to i64
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
+  ret i64 %cond
+}
+
+define i32 @test2e(i64 %x) {
+; ALL-LABEL: @test2e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
+; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32
+; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
+; LZCNT-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i64 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
+  %cast = trunc i64 %0 to i32
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
+  ret i32 %cond
+}
+
+define i64 @test3e(i32 %x) {
+; ALL-LABEL: @test3e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64
+; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
+; BMI-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i32 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+  %phitmp2 = zext i32 %0 to i64
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
+  ret i64 %cond
+}
+
+define i32 @test4e(i64 %x) {
+; ALL-LABEL: @test4e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32
+; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
+; BMI-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i64 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+  %cast = trunc i64 %0 to i32
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
+  ret i32 %cond
+}
+
+define i16 @test5e(i64 %x) {
+; ALL-LABEL: @test5e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16
+; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
+; BMI-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i64 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
+  %cast = trunc i64 %0 to i16
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
+  ret i16 %cond
+}
+
+define i16 @test6e(i32 %x) {
+; ALL-LABEL: @test6e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
+; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16
+; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
+; BMI-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i32 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
+  %cast = trunc i32 %0 to i16
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
+  ret i16 %cond
+}
+
+define i16 @test7e(i64 %x) {
+; ALL-LABEL: @test7e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
+; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16
+; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
+; LZCNT-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i64 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
+  %cast = trunc i64 %0 to i16
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
+  ret i16 %cond
+}
+
+define i16 @test8e(i32 %x) {
+; ALL-LABEL: @test8e(
+; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
+; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
+; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16
+; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
+; LZCNT-NOT: select
+; GENERIC-NOT: select
+; ALL: ret
+entry:
+  %tobool = icmp eq i32 %x, 0
+  br i1 %tobool, label %cond.end, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %cast = trunc i32 %0 to i16
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
+  ret i16 %cond
+}
+
+
+declare i64 @llvm.ctlz.i64(i64, i1)
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i16 @llvm.ctlz.i16(i16, i1)
+declare i64 @llvm.cttz.i64(i64, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+declare i16 @llvm.cttz.i16(i16, i1)

Added: llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt -S -simplifycfg -switch-to-lookup < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
+
+; rdar://17887153
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin12.0.0"
+
+; When we have a covered lookup table, make sure we don't delete PHINodes that
+; are cached in PHIs.
+; CHECK-LABEL: @test
+; CHECK: entry:
+; CHECK-NEXT: sub i3 %arg, -4
+; CHECK-NEXT: zext i3 %switch.tableidx to i4
+; CHECK-NEXT: getelementptr inbounds [8 x i64], [8 x i64]* @switch.table.test, i32 0, i4 %switch.tableidx.zext
+; CHECK-NEXT: load i64, i64* %switch.gep
+; CHECK-NEXT: add i64
+; CHECK-NEXT: ret i64
+define i64 @test(i3 %arg) {
+entry:
+  switch i3 %arg, label %Default [
+    i3 -2, label %Label6
+    i3 1, label %Label1
+    i3 2, label %Label2
+    i3 3, label %Label3
+    i3 -4, label %Label4
+    i3 -3, label %Label5
+  ]
+
+Default:
+  %v1 = phi i64 [ 7, %Label6 ], [ 11, %Label5 ], [ 6, %Label4 ], [ 13, %Label3 ], [ 9, %Label2 ], [ 15, %Label1 ], [ 8, %entry ]
+  %v2 = phi i64 [ 0, %Label6 ], [ 0, %Label5 ], [ 0, %Label4 ], [ 0, %Label3 ], [ 0, %Label2 ], [ 0, %Label1 ], [ 0, %entry ]
+  %v3 = add i64 %v1, %v2
+  ret i64 %v3
+
+Label1:
+  br label %Default
+
+Label2:
+  br label %Default
+
+Label3:
+  br label %Default
+
+Label4:
+  br label %Default
+
+Label5:
+  br label %Default
+
+Label6:
+  br label %Default
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/X86/switch-table-bug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -S -simplifycfg -switch-to-lookup < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
+; RUN: opt -S -passes='simplify-cfg<switch-to-lookup>' < %s -mtriple=x86_64-apple-darwin12.0.0 | FileCheck %s
+
+; rdar://17735071
+target datalayout = "e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin12.0.0"
+
+; When tableindex can't fit into i2, we should extend the type to i3.
+; CHECK-LABEL: @_TFO6reduce1E5toRawfS0_FT_Si
+; CHECK: entry:
+; CHECK-NEXT: sub i2 %0, -2
+; CHECK-NEXT: zext i2 %switch.tableidx to i3
+; CHECK-NEXT: getelementptr inbounds [4 x i64], [4 x i64]* @switch.table._TFO6reduce1E5toRawfS0_FT_Si, i32 0, i3 %switch.tableidx.zext
+; CHECK-NEXT: load i64, i64* %switch.gep
+; CHECK-NEXT: ret i64 %switch.load
+define i64 @_TFO6reduce1E5toRawfS0_FT_Si(i2) {
+entry:
+  switch i2 %0, label %1 [
+    i2 0, label %2
+    i2 1, label %3
+    i2 -2, label %4
+    i2 -1, label %5
+  ]
+
+; <label>:1                                       ; preds = %entry
+  unreachable
+
+; <label>:2                                       ; preds = %2
+  br label %6
+
+; <label>:3                                       ; preds = %4
+  br label %6
+
+; <label>:4                                       ; preds = %6
+  br label %6
+
+; <label>:5                                       ; preds = %8
+  br label %6
+
+; <label>:6                                      ; preds = %3, %5, %7, %9
+  %7 = phi i64 [ 3, %5 ], [ 2, %4 ], [ 1, %3 ], [ 0, %2 ]
+  ret i64 %7
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1452 @@
+; RUN: opt < %s -simplifycfg -switch-to-lookup=true -keep-loops=false -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+; RUN: opt < %s -passes='simplify-cfg<no-keep-loops;switch-to-lookup>' -S -mtriple=x86_64-unknown-linux-gnu | 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"
+
+; The table for @f
+; CHECK: @switch.table.f = private unnamed_addr constant [7 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 27, i32 62, i32 1], align 4
+
+; The char table for char
+; CHECK: @switch.table.char = private unnamed_addr constant [9 x i8] c"7{\00\FF\1B>\01!T", align 1
+
+; The float table for @h
+; CHECK: @switch.table.h = private unnamed_addr constant [4 x float] [float 0x40091EB860000000, float 0x3FF3BE76C0000000, float 0x4012449BA0000000, float 0x4001AE1480000000], align 4
+
+; The table for @foostring
+; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0)], align 8
+
+; The table for @earlyreturncrash
+; CHECK: @switch.table.earlyreturncrash = private unnamed_addr constant [4 x i32] [i32 42, i32 9, i32 88, i32 5], align 4
+
+; The table for @large
+; CHECK: @switch.table.large = private unnamed_addr constant [199 x i32] [i32 1, i32 4, i32 9,
+
+; The table for @cprop
+; CHECK: @switch.table.cprop = private unnamed_addr constant [7 x i32] [i32 5, i32 42, i32 126, i32 -452, i32 128, i32 6, i32 7], align 4
+
+; The table for @unreachable_case
+; CHECK: @switch.table.unreachable_case = private unnamed_addr constant [9 x i32] [i32 0, i32 0, i32 0, i32 2, i32 -1, i32 1, i32 1, i32 1, i32 1], align 4
+
+; A simple int-to-int selection switch.
+; It is dense enough to be replaced by table lookup.
+; The result is directly by a ret from an otherwise empty bb,
+; so we return early, directly from the lookup bb.
+
+define i32 @f(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+    i32 46, label %sw.bb4
+    i32 47, label %sw.bb5
+    i32 48, label %sw.bb6
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @f(
+; CHECK: entry:
+; CHECK-NEXT: %switch.tableidx = sub i32 %c, 42
+; CHECK-NEXT: %0 = icmp ult i32 %switch.tableidx, 7
+; CHECK-NEXT: br i1 %0, label %switch.lookup, label %return
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.gep = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i32 0, i32 %switch.tableidx
+; CHECK-NEXT: %switch.load = load i32, i32* %switch.gep
+; CHECK-NEXT: ret i32 %switch.load
+; CHECK: return:
+; CHECK-NEXT: ret i32 15
+}
+
+; Same thing, but with i8's
+
+define i8 @char(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+    i32 46, label %sw.bb4
+    i32 47, label %sw.bb5
+    i32 48, label %sw.bb6
+    i32 49, label %sw.bb7
+    i32 50, label %sw.bb8
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.bb7: br label %return
+sw.bb8: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i8 [ 15, %sw.default ], [ 84, %sw.bb8 ], [ 33, %sw.bb7 ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i8 %retval.0
+
+; CHECK-LABEL: @char(
+; CHECK: entry:
+; CHECK-NEXT: %switch.tableidx = sub i32 %c, 42
+; CHECK-NEXT: %0 = icmp ult i32 %switch.tableidx, 9
+; CHECK-NEXT: br i1 %0, label %switch.lookup, label %return
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.gep = getelementptr inbounds [9 x i8], [9 x i8]* @switch.table.char, i32 0, i32 %switch.tableidx
+; CHECK-NEXT: %switch.load = load i8, i8* %switch.gep
+; CHECK-NEXT: ret i8 %switch.load
+; CHECK: return:
+; CHECK-NEXT: ret i8 15
+}
+
+; A switch used to initialize two variables, an i8 and a float.
+
+declare void @dummy(i8 signext, float)
+define void @h(i32 %x) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.epilog
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+
+sw.epilog:
+  %a.0 = phi i8 [ 7, %sw.default ], [ 5, %sw.bb3 ], [ 88, %sw.bb2 ], [ 9, %sw.bb1 ], [ 42, %entry ]
+  %b.0 = phi float [ 0x4023FAE140000000, %sw.default ], [ 0x4001AE1480000000, %sw.bb3 ], [ 0x4012449BA0000000, %sw.bb2 ], [ 0x3FF3BE76C0000000, %sw.bb1 ], [ 0x40091EB860000000, %entry ]
+  call void @dummy(i8 signext %a.0, float %b.0)
+  ret void
+
+; CHECK-LABEL: @h(
+; CHECK: entry:
+; CHECK-NEXT: %0 = icmp ult i32 %x, 4
+; CHECK-NEXT: br i1 %0, label %switch.lookup, label %sw.epilog
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.shiftamt = mul i32 %x, 8
+; CHECK-NEXT: %switch.downshift = lshr i32 89655594, %switch.shiftamt
+; CHECK-NEXT: %switch.masked = trunc i32 %switch.downshift to i8
+; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x float], [4 x float]* @switch.table.h, i32 0, i32 %x
+; CHECK-NEXT: %switch.load = load float, float* %switch.gep
+; CHECK-NEXT: br label %sw.epilog
+; CHECK: sw.epilog:
+; CHECK-NEXT: %a.0 = phi i8 [ %switch.masked, %switch.lookup ], [ 7, %entry ]
+; CHECK-NEXT: %b.0 = phi float [ %switch.load, %switch.lookup ], [ 0x4023FAE140000000, %entry ]
+; CHECK-NEXT: call void @dummy(i8 signext %a.0, float %b.0)
+; CHECK-NEXT: ret void
+}
+
+
+; Switch used to return a string.
+
+ at .str = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+ at .str1 = private unnamed_addr constant [4 x i8] c"bar\00", align 1
+ at .str2 = private unnamed_addr constant [4 x i8] c"baz\00", align 1
+ at .str3 = private unnamed_addr constant [4 x i8] c"qux\00", align 1
+ at .str4 = private unnamed_addr constant [6 x i8] c"error\00", align 1
+
+define i8* @foostring(i32 %x)  {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %return
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+
+return:
+  %retval.0 = phi i8* [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), %sw.default ],
+                      [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0), %sw.bb3 ],
+                      [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), %sw.bb2 ],
+                      [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), %sw.bb1 ],
+                      [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), %entry ]
+  ret i8* %retval.0
+
+; CHECK-LABEL: @foostring(
+; CHECK: entry:
+; CHECK-NEXT: %0 = icmp ult i32 %x, 4
+; CHECK-NEXT: br i1 %0, label %switch.lookup, label %return
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i8*], [4 x i8*]* @switch.table.foostring, i32 0, i32 %x
+; CHECK-NEXT: %switch.load = load i8*, i8** %switch.gep
+; CHECK-NEXT: ret i8* %switch.load
+}
+
+; Switch used to initialize two values. The first value is returned, the second
+; value is not used. This used to make the transformation generate illegal code.
+
+define i32 @earlyreturncrash(i32 %x)  {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.epilog
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+
+sw.epilog:
+  %a.0 = phi i32 [ 7, %sw.default ], [ 5, %sw.bb3 ], [ 88, %sw.bb2 ], [ 9, %sw.bb1 ], [ 42, %entry ]
+  %b.0 = phi i32 [ 10, %sw.default ], [ 5, %sw.bb3 ], [ 1, %sw.bb2 ], [ 4, %sw.bb1 ], [ 3, %entry ]
+  ret i32 %a.0
+
+; CHECK-LABEL: @earlyreturncrash(
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.earlyreturncrash, i32 0, i32 %x
+; CHECK-NEXT: %switch.load = load i32, i32* %switch.gep
+; CHECK-NEXT: ret i32 %switch.load
+; CHECK: sw.epilog:
+; CHECK-NEXT: ret i32 7
+}
+
+
+; Example 7 from http://blog.regehr.org/archives/320
+; It is not dense enough for a regular table, but the results
+; can be packed into a bitmap.
+
+define i32 @crud(i8 zeroext %c)  {
+entry:
+  %cmp = icmp ult i8 %c, 33
+  br i1 %cmp, label %lor.end, label %switch.early.test
+
+switch.early.test:
+  switch i8 %c, label %lor.rhs [
+    i8 92, label %lor.end
+    i8 62, label %lor.end
+    i8 60, label %lor.end
+    i8 59, label %lor.end
+    i8 58, label %lor.end
+    i8 46, label %lor.end
+    i8 44, label %lor.end
+    i8 34, label %lor.end
+    i8 39, label %switch.edge
+  ]
+
+switch.edge: br label %lor.end
+lor.rhs: br label %lor.end
+
+lor.end:
+  %0 = phi i1 [ true, %switch.early.test ],
+              [ false, %lor.rhs ],
+              [ true, %entry ],
+              [ true, %switch.early.test ],
+              [ true, %switch.early.test ],
+              [ true, %switch.early.test ],
+              [ true, %switch.early.test ],
+              [ true, %switch.early.test ],
+              [ true, %switch.early.test ],
+              [ true, %switch.early.test ],
+              [ true, %switch.edge ]
+  %lor.ext = zext i1 %0 to i32
+  ret i32 %lor.ext
+
+; CHECK-LABEL: @crud(
+; CHECK: entry:
+; CHECK-NEXT: %cmp = icmp ult i8 %c, 33
+; CHECK-NEXT: br i1 %cmp, label %lor.end, label %switch.early.test
+; CHECK: switch.early.test:
+; CHECK-NEXT: %switch.tableidx = sub i8 %c, 34
+; CHECK-NEXT: %0 = icmp ult i8 %switch.tableidx, 59
+; CHECK-NEXT: br i1 %0, label %switch.lookup, label %lor.end
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.cast = zext i8 %switch.tableidx to i59
+; CHECK-NEXT: %switch.shiftamt = mul i59 %switch.cast, 1
+; CHECK-NEXT: %switch.downshift = lshr i59 -288230375765830623, %switch.shiftamt
+; CHECK-NEXT: %switch.masked = trunc i59 %switch.downshift to i1
+; CHECK-NEXT: br label %lor.end
+; CHECK: lor.end:
+; CHECK-NEXT: %1 = phi i1 [ true, %entry ], [ %switch.masked, %switch.lookup ], [ false, %switch.early.test ]
+; CHECK-NEXT: %lor.ext = zext i1 %1 to i32
+; CHECK-NEXT: ret i32 %lor.ext
+}
+
+; PR13946
+define i32 @overflow(i32 %type) {
+entry:
+  switch i32 %type, label %sw.default [
+    i32 -2147483648, label %sw.bb
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 -2147483645, label %sw.bb3
+    i32 3, label %sw.bb3
+  ]
+
+sw.bb: br label %if.end
+sw.bb1: br label %if.end
+sw.bb2: br label %if.end
+sw.bb3: br label %if.end
+sw.default: br label %if.end
+if.else: br label %if.end
+
+if.end:
+  %dirent_type.0 = phi i32 [ 3, %sw.default ], [ 6, %sw.bb3 ], [ 5, %sw.bb2 ], [ 0, %sw.bb1 ], [ 3, %sw.bb ], [ 0, %if.else ]
+  ret i32 %dirent_type.0
+; CHECK-LABEL: define i32 @overflow(
+; CHECK: switch
+; CHECK: phi
+}
+
+; PR13985
+define i1 @undef(i32 %tmp) {
+bb:
+  switch i32 %tmp, label %bb3 [
+    i32 0, label %bb1
+    i32 1, label %bb1
+    i32 7, label %bb2
+    i32 8, label %bb2
+  ]
+
+bb1: br label %bb3
+bb2: br label %bb3
+
+bb3:
+  %tmp4 = phi i1 [ undef, %bb ], [ false, %bb2 ], [ true, %bb1 ]
+  ret i1 %tmp4
+; CHECK-LABEL: define i1 @undef(
+; CHECK: %switch.cast = trunc i32 %tmp to i9
+; CHECK: %switch.downshift = lshr i9 3, %switch.shiftamt
+}
+
+; Also handle large switches that would be rejected by
+; isValueEqualityComparison()
+; CHECK: large
+; CHECK-NOT: switch i32
+define i32 @large(i32 %x) {
+entry:
+  %cmp = icmp slt i32 %x, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %mul = mul i32 %x, -10
+  br label %if.end
+
+if.end:
+  %x.addr.0 = phi i32 [ %mul, %if.then ], [ %x, %entry ]
+  switch i32 %x.addr.0, label %return [
+    i32 199, label %sw.bb203
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+    i32 4, label %sw.bb4
+    i32 5, label %sw.bb5
+    i32 6, label %sw.bb6
+    i32 7, label %sw.bb7
+    i32 8, label %sw.bb8
+    i32 9, label %sw.bb9
+    i32 10, label %sw.bb10
+    i32 11, label %sw.bb11
+    i32 12, label %sw.bb12
+    i32 13, label %sw.bb13
+    i32 14, label %sw.bb14
+    i32 15, label %sw.bb15
+    i32 16, label %sw.bb16
+    i32 17, label %sw.bb17
+    i32 18, label %sw.bb18
+    i32 19, label %sw.bb19
+    i32 20, label %sw.bb20
+    i32 21, label %sw.bb21
+    i32 22, label %sw.bb22
+    i32 23, label %sw.bb23
+    i32 24, label %sw.bb24
+    i32 25, label %sw.bb25
+    i32 26, label %sw.bb26
+    i32 27, label %sw.bb27
+    i32 28, label %sw.bb28
+    i32 29, label %sw.bb29
+    i32 30, label %sw.bb30
+    i32 31, label %sw.bb31
+    i32 32, label %sw.bb32
+    i32 33, label %sw.bb33
+    i32 34, label %sw.bb34
+    i32 35, label %sw.bb35
+    i32 36, label %sw.bb37
+    i32 37, label %sw.bb38
+    i32 38, label %sw.bb39
+    i32 39, label %sw.bb40
+    i32 40, label %sw.bb41
+    i32 41, label %sw.bb42
+    i32 42, label %sw.bb43
+    i32 43, label %sw.bb44
+    i32 44, label %sw.bb45
+    i32 45, label %sw.bb47
+    i32 46, label %sw.bb48
+    i32 47, label %sw.bb49
+    i32 48, label %sw.bb50
+    i32 49, label %sw.bb51
+    i32 50, label %sw.bb52
+    i32 51, label %sw.bb53
+    i32 52, label %sw.bb54
+    i32 53, label %sw.bb55
+    i32 54, label %sw.bb56
+    i32 55, label %sw.bb58
+    i32 56, label %sw.bb59
+    i32 57, label %sw.bb60
+    i32 58, label %sw.bb61
+    i32 59, label %sw.bb62
+    i32 60, label %sw.bb63
+    i32 61, label %sw.bb64
+    i32 62, label %sw.bb65
+    i32 63, label %sw.bb66
+    i32 64, label %sw.bb67
+    i32 65, label %sw.bb68
+    i32 66, label %sw.bb69
+    i32 67, label %sw.bb70
+    i32 68, label %sw.bb71
+    i32 69, label %sw.bb72
+    i32 70, label %sw.bb73
+    i32 71, label %sw.bb74
+    i32 72, label %sw.bb76
+    i32 73, label %sw.bb77
+    i32 74, label %sw.bb78
+    i32 75, label %sw.bb79
+    i32 76, label %sw.bb80
+    i32 77, label %sw.bb81
+    i32 78, label %sw.bb82
+    i32 79, label %sw.bb83
+    i32 80, label %sw.bb84
+    i32 81, label %sw.bb85
+    i32 82, label %sw.bb86
+    i32 83, label %sw.bb87
+    i32 84, label %sw.bb88
+    i32 85, label %sw.bb89
+    i32 86, label %sw.bb90
+    i32 87, label %sw.bb91
+    i32 88, label %sw.bb92
+    i32 89, label %sw.bb93
+    i32 90, label %sw.bb94
+    i32 91, label %sw.bb95
+    i32 92, label %sw.bb96
+    i32 93, label %sw.bb97
+    i32 94, label %sw.bb98
+    i32 95, label %sw.bb99
+    i32 96, label %sw.bb100
+    i32 97, label %sw.bb101
+    i32 98, label %sw.bb102
+    i32 99, label %sw.bb103
+    i32 100, label %sw.bb104
+    i32 101, label %sw.bb105
+    i32 102, label %sw.bb106
+    i32 103, label %sw.bb107
+    i32 104, label %sw.bb108
+    i32 105, label %sw.bb109
+    i32 106, label %sw.bb110
+    i32 107, label %sw.bb111
+    i32 108, label %sw.bb112
+    i32 109, label %sw.bb113
+    i32 110, label %sw.bb114
+    i32 111, label %sw.bb115
+    i32 112, label %sw.bb116
+    i32 113, label %sw.bb117
+    i32 114, label %sw.bb118
+    i32 115, label %sw.bb119
+    i32 116, label %sw.bb120
+    i32 117, label %sw.bb121
+    i32 118, label %sw.bb122
+    i32 119, label %sw.bb123
+    i32 120, label %sw.bb124
+    i32 121, label %sw.bb125
+    i32 122, label %sw.bb126
+    i32 123, label %sw.bb127
+    i32 124, label %sw.bb128
+    i32 125, label %sw.bb129
+    i32 126, label %sw.bb130
+    i32 127, label %sw.bb131
+    i32 128, label %sw.bb132
+    i32 129, label %sw.bb133
+    i32 130, label %sw.bb134
+    i32 131, label %sw.bb135
+    i32 132, label %sw.bb136
+    i32 133, label %sw.bb137
+    i32 134, label %sw.bb138
+    i32 135, label %sw.bb139
+    i32 136, label %sw.bb140
+    i32 137, label %sw.bb141
+    i32 138, label %sw.bb142
+    i32 139, label %sw.bb143
+    i32 140, label %sw.bb144
+    i32 141, label %sw.bb145
+    i32 142, label %sw.bb146
+    i32 143, label %sw.bb147
+    i32 144, label %sw.bb148
+    i32 145, label %sw.bb149
+    i32 146, label %sw.bb150
+    i32 147, label %sw.bb151
+    i32 148, label %sw.bb152
+    i32 149, label %sw.bb153
+    i32 150, label %sw.bb154
+    i32 151, label %sw.bb155
+    i32 152, label %sw.bb156
+    i32 153, label %sw.bb157
+    i32 154, label %sw.bb158
+    i32 155, label %sw.bb159
+    i32 156, label %sw.bb160
+    i32 157, label %sw.bb161
+    i32 158, label %sw.bb162
+    i32 159, label %sw.bb163
+    i32 160, label %sw.bb164
+    i32 161, label %sw.bb165
+    i32 162, label %sw.bb166
+    i32 163, label %sw.bb167
+    i32 164, label %sw.bb168
+    i32 165, label %sw.bb169
+    i32 166, label %sw.bb170
+    i32 167, label %sw.bb171
+    i32 168, label %sw.bb172
+    i32 169, label %sw.bb173
+    i32 170, label %sw.bb174
+    i32 171, label %sw.bb175
+    i32 172, label %sw.bb176
+    i32 173, label %sw.bb177
+    i32 174, label %sw.bb178
+    i32 175, label %sw.bb179
+    i32 176, label %sw.bb180
+    i32 177, label %sw.bb181
+    i32 178, label %sw.bb182
+    i32 179, label %sw.bb183
+    i32 180, label %sw.bb184
+    i32 181, label %sw.bb185
+    i32 182, label %sw.bb186
+    i32 183, label %sw.bb187
+    i32 184, label %sw.bb188
+    i32 185, label %sw.bb189
+    i32 186, label %sw.bb190
+    i32 187, label %sw.bb191
+    i32 188, label %sw.bb192
+    i32 189, label %sw.bb193
+    i32 190, label %sw.bb194
+    i32 191, label %sw.bb195
+    i32 192, label %sw.bb196
+    i32 193, label %sw.bb197
+    i32 194, label %sw.bb198
+    i32 195, label %sw.bb199
+    i32 196, label %sw.bb200
+    i32 197, label %sw.bb201
+    i32 198, label %sw.bb202
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.bb7: br label %return
+sw.bb8: br label %return
+sw.bb9: br label %return
+sw.bb10: br label %return
+sw.bb11: br label %return
+sw.bb12: br label %return
+sw.bb13: br label %return
+sw.bb14: br label %return
+sw.bb15: br label %return
+sw.bb16: br label %return
+sw.bb17: br label %return
+sw.bb18: br label %return
+sw.bb19: br label %return
+sw.bb20: br label %return
+sw.bb21: br label %return
+sw.bb22: br label %return
+sw.bb23: br label %return
+sw.bb24: br label %return
+sw.bb25: br label %return
+sw.bb26: br label %return
+sw.bb27: br label %return
+sw.bb28: br label %return
+sw.bb29: br label %return
+sw.bb30: br label %return
+sw.bb31: br label %return
+sw.bb32: br label %return
+sw.bb33: br label %return
+sw.bb34: br label %return
+sw.bb35: br label %return
+sw.bb37: br label %return
+sw.bb38: br label %return
+sw.bb39: br label %return
+sw.bb40: br label %return
+sw.bb41: br label %return
+sw.bb42: br label %return
+sw.bb43: br label %return
+sw.bb44: br label %return
+sw.bb45: br label %return
+sw.bb47: br label %return
+sw.bb48: br label %return
+sw.bb49: br label %return
+sw.bb50: br label %return
+sw.bb51: br label %return
+sw.bb52: br label %return
+sw.bb53: br label %return
+sw.bb54: br label %return
+sw.bb55: br label %return
+sw.bb56: br label %return
+sw.bb58: br label %return
+sw.bb59: br label %return
+sw.bb60: br label %return
+sw.bb61: br label %return
+sw.bb62: br label %return
+sw.bb63: br label %return
+sw.bb64: br label %return
+sw.bb65: br label %return
+sw.bb66: br label %return
+sw.bb67: br label %return
+sw.bb68: br label %return
+sw.bb69: br label %return
+sw.bb70: br label %return
+sw.bb71: br label %return
+sw.bb72: br label %return
+sw.bb73: br label %return
+sw.bb74: br label %return
+sw.bb76: br label %return
+sw.bb77: br label %return
+sw.bb78: br label %return
+sw.bb79: br label %return
+sw.bb80: br label %return
+sw.bb81: br label %return
+sw.bb82: br label %return
+sw.bb83: br label %return
+sw.bb84: br label %return
+sw.bb85: br label %return
+sw.bb86: br label %return
+sw.bb87: br label %return
+sw.bb88: br label %return
+sw.bb89: br label %return
+sw.bb90: br label %return
+sw.bb91: br label %return
+sw.bb92: br label %return
+sw.bb93: br label %return
+sw.bb94: br label %return
+sw.bb95: br label %return
+sw.bb96: br label %return
+sw.bb97: br label %return
+sw.bb98: br label %return
+sw.bb99: br label %return
+sw.bb100: br label %return
+sw.bb101: br label %return
+sw.bb102: br label %return
+sw.bb103: br label %return
+sw.bb104: br label %return
+sw.bb105: br label %return
+sw.bb106: br label %return
+sw.bb107: br label %return
+sw.bb108: br label %return
+sw.bb109: br label %return
+sw.bb110: br label %return
+sw.bb111: br label %return
+sw.bb112: br label %return
+sw.bb113: br label %return
+sw.bb114: br label %return
+sw.bb115: br label %return
+sw.bb116: br label %return
+sw.bb117: br label %return
+sw.bb118: br label %return
+sw.bb119: br label %return
+sw.bb120: br label %return
+sw.bb121: br label %return
+sw.bb122: br label %return
+sw.bb123: br label %return
+sw.bb124: br label %return
+sw.bb125: br label %return
+sw.bb126: br label %return
+sw.bb127: br label %return
+sw.bb128: br label %return
+sw.bb129: br label %return
+sw.bb130: br label %return
+sw.bb131: br label %return
+sw.bb132: br label %return
+sw.bb133: br label %return
+sw.bb134: br label %return
+sw.bb135: br label %return
+sw.bb136: br label %return
+sw.bb137: br label %return
+sw.bb138: br label %return
+sw.bb139: br label %return
+sw.bb140: br label %return
+sw.bb141: br label %return
+sw.bb142: br label %return
+sw.bb143: br label %return
+sw.bb144: br label %return
+sw.bb145: br label %return
+sw.bb146: br label %return
+sw.bb147: br label %return
+sw.bb148: br label %return
+sw.bb149: br label %return
+sw.bb150: br label %return
+sw.bb151: br label %return
+sw.bb152: br label %return
+sw.bb153: br label %return
+sw.bb154: br label %return
+sw.bb155: br label %return
+sw.bb156: br label %return
+sw.bb157: br label %return
+sw.bb158: br label %return
+sw.bb159: br label %return
+sw.bb160: br label %return
+sw.bb161: br label %return
+sw.bb162: br label %return
+sw.bb163: br label %return
+sw.bb164: br label %return
+sw.bb165: br label %return
+sw.bb166: br label %return
+sw.bb167: br label %return
+sw.bb168: br label %return
+sw.bb169: br label %return
+sw.bb170: br label %return
+sw.bb171: br label %return
+sw.bb172: br label %return
+sw.bb173: br label %return
+sw.bb174: br label %return
+sw.bb175: br label %return
+sw.bb176: br label %return
+sw.bb177: br label %return
+sw.bb178: br label %return
+sw.bb179: br label %return
+sw.bb180: br label %return
+sw.bb181: br label %return
+sw.bb182: br label %return
+sw.bb183: br label %return
+sw.bb184: br label %return
+sw.bb185: br label %return
+sw.bb186: br label %return
+sw.bb187: br label %return
+sw.bb188: br label %return
+sw.bb189: br label %return
+sw.bb190: br label %return
+sw.bb191: br label %return
+sw.bb192: br label %return
+sw.bb193: br label %return
+sw.bb194: br label %return
+sw.bb195: br label %return
+sw.bb196: br label %return
+sw.bb197: br label %return
+sw.bb198: br label %return
+sw.bb199: br label %return
+sw.bb200: br label %return
+sw.bb201: br label %return
+sw.bb202: br label %return
+sw.bb203: br label %return
+
+return:
+  %retval.0 = phi i32 [ 39204, %sw.bb202 ], [ 38809, %sw.bb201 ], [ 38416, %sw.bb200 ], [ 38025, %sw.bb199 ], [ 37636, %sw.bb198 ], [ 37249, %sw.bb197 ], [ 36864, %sw.bb196 ], [ 36481, %sw.bb195 ], [ 36100, %sw.bb194 ], [ 35721, %sw.bb193 ], [ 35344, %sw.bb192 ], [ 34969, %sw.bb191 ], [ 34596, %sw.bb190 ], [ 34225, %sw.bb189 ], [ 33856, %sw.bb188 ], [ 33489, %sw.bb187 ], [ 33124, %sw.bb186 ], [ 32761, %sw.bb185 ], [ 32400, %sw.bb184 ], [ 32041, %sw.bb183 ], [ 31684, %sw.bb182 ], [ 31329, %sw.bb181 ], [ 30976, %sw.bb180 ], [ 30625, %sw.bb179 ], [ 30276, %sw.bb178 ], [ 29929, %sw.bb177 ], [ 29584, %sw.bb176 ], [ 29241, %sw.bb175 ], [ 28900, %sw.bb174 ], [ 28561, %sw.bb173 ], [ 28224, %sw.bb172 ], [ 27889, %sw.bb171 ], [ 27556, %sw.bb170 ], [ 27225, %sw.bb169 ], [ 26896, %sw.bb168 ], [ 26569, %sw.bb167 ], [ 26244, %sw.bb166 ], [ 25921, %sw.bb165 ], [ 25600, %sw.bb164 ], [ 25281, %sw.bb163 ], [ 24964, %sw.bb162 ], [ 24649, %sw.bb161 ], [ 24336, %sw.bb160 ], [ 24025, %sw.bb159 ], [ 23716, %sw.bb158 ], [ 23409, %sw.bb157 ], [ 23104, %sw.bb156 ], [ 22801, %sw.bb155 ], [ 22500, %sw.bb154 ], [ 22201, %sw.bb153 ], [ 21904, %sw.bb152 ], [ 21609, %sw.bb151 ], [ 21316, %sw.bb150 ], [ 21025, %sw.bb149 ], [ 20736, %sw.bb148 ], [ 20449, %sw.bb147 ], [ 20164, %sw.bb146 ], [ 19881, %sw.bb145 ], [ 19600, %sw.bb144 ], [ 19321, %sw.bb143 ], [ 19044, %sw.bb142 ], [ 18769, %sw.bb141 ], [ 18496, %sw.bb140 ], [ 18225, %sw.bb139 ], [ 17956, %sw.bb138 ], [ 17689, %sw.bb137 ], [ 17424, %sw.bb136 ], [ 17161, %sw.bb135 ], [ 16900, %sw.bb134 ], [ 16641, %sw.bb133 ], [ 16384, %sw.bb132 ], [ 16129, %sw.bb131 ], [ 15876, %sw.bb130 ], [ 15625, %sw.bb129 ], [ 15376, %sw.bb128 ], [ 15129, %sw.bb127 ], [ 14884, %sw.bb126 ], [ 14641, %sw.bb125 ], [ 14400, %sw.bb124 ], [ 14161, %sw.bb123 ], [ 13924, %sw.bb122 ], [ 13689, %sw.bb121 ], [ 13456, %sw.bb120 ], [ 13225, %sw.bb119 ], [ 12996, %sw.bb118 ], [ 12769, %sw.bb117 ], [ 12544, %sw.bb116 ], [ 12321, %sw.bb115 ], [ 12100, %sw.bb114 ], [ 11881, %sw.bb113 ], [ 11664, %sw.bb112 ], [ 11449, %sw.bb111 ], [ 11236, %sw.bb110 ], [ 11025, %sw.bb109 ], [ 10816, %sw.bb108 ], [ 10609, %sw.bb107 ], [ 10404, %sw.bb106 ], [ 10201, %sw.bb105 ], [ 10000, %sw.bb104 ], [ 9801, %sw.bb103 ], [ 9604, %sw.bb102 ], [ 9409, %sw.bb101 ], [ 9216, %sw.bb100 ], [ 9025, %sw.bb99 ], [ 8836, %sw.bb98 ], [ 8649, %sw.bb97 ], [ 8464, %sw.bb96 ], [ 8281, %sw.bb95 ], [ 8100, %sw.bb94 ], [ 7921, %sw.bb93 ], [ 7744, %sw.bb92 ], [ 7569, %sw.bb91 ], [ 7396, %sw.bb90 ], [ 7225, %sw.bb89 ], [ 7056, %sw.bb88 ], [ 6889, %sw.bb87 ], [ 6724, %sw.bb86 ], [ 6561, %sw.bb85 ], [ 6400, %sw.bb84 ], [ 6241, %sw.bb83 ], [ 6084, %sw.bb82 ], [ 5929, %sw.bb81 ], [ 5776, %sw.bb80 ], [ 5625, %sw.bb79 ], [ 5476, %sw.bb78 ], [ 5329, %sw.bb77 ], [ 5184, %sw.bb76 ], [ 5112, %sw.bb74 ], [ 4900, %sw.bb73 ], [ 4761, %sw.bb72 ], [ 4624, %sw.bb71 ], [ 4489, %sw.bb70 ], [ 4356, %sw.bb69 ], [ 4225, %sw.bb68 ], [ 4096, %sw.bb67 ], [ 3969, %sw.bb66 ], [ 3844, %sw.bb65 ], [ 3721, %sw.bb64 ], [ 3600, %sw.bb63 ], [ 3481, %sw.bb62 ], [ 3364, %sw.bb61 ], [ 3249, %sw.bb60 ], [ 3136, %sw.bb59 ], [ 3025, %sw.bb58 ], [ 2970, %sw.bb56 ], [ 2809, %sw.bb55 ], [ 2704, %sw.bb54 ], [ 2601, %sw.bb53 ], [ 2500, %sw.bb52 ], [ 2401, %sw.bb51 ], [ 2304, %sw.bb50 ], [ 2209, %sw.bb49 ], [ 2116, %sw.bb48 ], [ 2025, %sw.bb47 ], [ 1980, %sw.bb45 ], [ 1849, %sw.bb44 ], [ 1764, %sw.bb43 ], [ 1681, %sw.bb42 ], [ 1600, %sw.bb41 ], [ 1521, %sw.bb40 ], [ 1444, %sw.bb39 ], [ 1369, %sw.bb38 ], [ 1296, %sw.bb37 ], [ 1260, %sw.bb35 ], [ 1156, %sw.bb34 ], [ 1089, %sw.bb33 ], [ 1024, %sw.bb32 ], [ 961, %sw.bb31 ], [ 900, %sw.bb30 ], [ 841, %sw.bb29 ], [ 784, %sw.bb28 ], [ 729, %sw.bb27 ], [ 676, %sw.bb26 ], [ 625, %sw.bb25 ], [ 576, %sw.bb24 ], [ 529, %sw.bb23 ], [ 484, %sw.bb22 ], [ 441, %sw.bb21 ], [ 400, %sw.bb20 ], [ 361, %sw.bb19 ], [ 342, %sw.bb18 ], [ 289, %sw.bb17 ], [ 256, %sw.bb16 ], [ 225, %sw.bb15 ], [ 196, %sw.bb14 ], [ 169, %sw.bb13 ], [ 144, %sw.bb12 ], [ 121, %sw.bb11 ], [ 100, %sw.bb10 ], [ 81, %sw.bb9 ], [ 64, %sw.bb8 ], [ 49, %sw.bb7 ], [ 36, %sw.bb6 ], [ 25, %sw.bb5 ], [ 16, %sw.bb4 ], [ 9, %sw.bb3 ], [ 4, %sw.bb2 ], [ 1, %sw.bb1 ], [ 39601, %sw.bb203 ], [ 0, %if.end ]
+  ret i32 %retval.0
+}
+
+define i32 @cprop(i32 %x, i32 %y) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 1, label %return
+    i32 2, label %sw.bb1
+    i32 3, label %sw.bb2
+    i32 4, label %sw.bb2
+    i32 5, label %sw.bb2
+    i32 6, label %sw.bb3
+    i32 7, label %sw.bb3
+  ]
+
+sw.bb1: br label %return
+
+sw.bb2:
+  %and = and i32 %x, 1
+  %and.ptr = inttoptr i32 %and to i8*
+  %tobool = icmp ne i8* %and.ptr, null
+  %cond = select i1 %tobool, i32 -123, i32 456
+  %sub = sub nsw i32 %x, %cond
+  br label %return
+
+sw.bb3:
+  %trunc = trunc i32 %x to i8
+  %sext = sext i8 %trunc to i32
+  %select.i = icmp sgt i32 %sext, 0
+  %select = select i1 %select.i, i32 %sext, i32 %y
+  br label %return
+
+sw.default:
+  br label %return
+
+return:
+  %retval.0 = phi i32 [ 123, %sw.default ], [ %select, %sw.bb3 ], [ %sub, %sw.bb2 ], [ 42, %sw.bb1 ], [ 5, %entry ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @cprop(
+; CHECK: switch.lookup:
+; CHECK: %switch.gep = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.cprop, i32 0, i32 %switch.tableidx
+}
+
+define i32 @unreachable_case(i32 %x)  {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb
+    i32 2, label %sw.bb
+    i32 3, label %sw.bb1
+    i32 4, label %sw.bb2
+    i32 5, label %sw.bb3
+    i32 6, label %sw.bb3
+    i32 7, label %sw.bb3
+    i32 8, label %sw.bb3
+  ]
+
+sw.bb: br label %return
+sw.bb1: unreachable
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+
+return:
+  %retval.0 = phi i32 [ 1, %sw.bb3 ], [ -1, %sw.bb2 ], [ 0, %sw.bb ], [ 2, %sw.default ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @unreachable_case(
+; CHECK: switch.lookup:
+; CHECK: getelementptr inbounds [9 x i32], [9 x i32]* @switch.table.unreachable_case, i32 0, i32 %x
+}
+
+define i32 @unreachable_default(i32 %x)  {
+entry:
+  switch i32 %x, label %default [
+    i32 0, label %bb0
+    i32 1, label %bb1
+    i32 2, label %bb2
+    i32 3, label %bb3
+  ]
+
+bb0: br label %return
+bb1: br label %return
+bb2: br label %return
+bb3: br label %return
+default: unreachable
+
+return:
+  %retval = phi i32 [ 42, %bb0 ], [ 52, %bb1 ], [ 1, %bb2 ], [ 2, %bb3 ]
+  ret i32 %retval
+
+; CHECK-LABEL: @unreachable_default(
+; CHECK: entry:
+; CHECK-NOT: icmp
+; CHECK-NOT: br 1i
+; CHECK-NEXT: %switch.gep = getelementptr inbounds [4 x i32], [4 x i32]* @switch.table.unreachable_default, i32 0, i32 %x
+; CHECK-NEXT: %switch.load = load i32, i32* %switch.gep
+; CHECK-NEXT: ret i32 %switch.load
+}
+
+; Don't create a table with illegal type
+define i96 @illegaltype(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 42, label %return
+    i32 43, label %sw.bb1
+    i32 44, label %sw.bb2
+    i32 45, label %sw.bb3
+    i32 46, label %sw.bb4
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i96 [ 15, %sw.default ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i96 %retval.0
+
+; CHECK-LABEL: @illegaltype(
+; CHECK-NOT: @switch.table
+; CHECK: switch i32 %c
+}
+
+; If we can build a lookup table without any holes, we don't need a default result.
+declare void @exit(i32)
+define i32 @nodefaultnoholes(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 0, label %return
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: call void @exit(i32 1)
+            unreachable
+return:
+  %x = phi i32 [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %x
+
+; CHECK-LABEL: @nodefaultnoholes(
+; CHECK: @switch.table
+; CHECK-NOT: switch i32
+}
+
+; This lookup table will have holes, so we need to test for the holes.
+define i32 @nodefaultwithholes(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 0, label %return
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+    i32 5, label %sw.bb3
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: call void @exit(i32 1)
+            unreachable
+return:
+  %x = phi i32 [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %x
+
+; CHECK-LABEL: @nodefaultwithholes(
+; CHECK: entry:
+; CHECK: br i1 %{{.*}}, label %switch.hole_check, label %sw.default
+; CHECK: switch.hole_check:
+; CHECK-NEXT: %switch.maskindex = trunc i32 %c to i8
+; CHECK-NEXT: %switch.shifted = lshr i8 47, %switch.maskindex
+; The mask is binary 101111.
+; CHECK-NEXT: %switch.lobit = trunc i8 %switch.shifted to i1
+; CHECK-NEXT: br i1 %switch.lobit, label %switch.lookup, label %sw.default
+; CHECK-NOT: switch i32
+}
+
+; We don't build lookup tables with holes for switches with less than four cases.
+define i32 @threecasesholes(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 0, label %return
+    i32 1, label %sw.bb1
+    i32 3, label %sw.bb2
+  ]
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.default: br label %return
+return:
+  %x = phi i32 [ %c, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 9, %entry ]
+  ret i32 %x
+; CHECK-LABEL: @threecasesholes(
+; CHECK: switch i32
+; CHECK-NOT: @switch.table
+}
+
+; We build lookup tables for switches with three or more cases.
+define i32 @threecases(i32 %c) {
+; CHECK-LABEL: @threecases(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 %c, 3
+; CHECK-NEXT:    br i1 [[TMP0]], label %switch.lookup, label %return
+; CHECK:       switch.lookup:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* @switch.table.threecases, i32 0, i32 %c
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]]
+; CHECK-NEXT:    ret i32 [[SWITCH_LOAD]]
+; CHECK:       return:
+; CHECK-NEXT:    ret i32 3
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 0, label %return
+  i32 1, label %sw.bb1
+  i32 2, label %sw.bb2
+  ]
+sw.bb1:
+  br label %return
+sw.bb2:
+  br label %return
+sw.default:
+  br label %return
+return:
+  %x = phi i32 [ 3, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 10, %entry ]
+  ret i32 %x
+}
+
+; We don't build tables for switches with two cases.
+define i32 @twocases(i32 %c) {
+; CHECK-LABEL: @twocases(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 %c, 1
+; CHECK-NEXT:    [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP:%.*]], i32 7, i32 3
+; CHECK-NEXT:    [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 %c, 0
+; CHECK-NEXT:    [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 9, i32 [[SWITCH_SELECT]]
+; CHECK-NEXT:    ret i32 [[SWITCH_SELECT2]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 0, label %return
+  i32 1, label %sw.bb1
+  ]
+sw.bb1:
+  br label %return
+sw.default:
+  br label %return
+return:
+  %x = phi i32 [ 3, %sw.default ], [ 7, %sw.bb1 ], [ 9, %entry ]
+  ret i32 %x
+}
+
+; Don't build tables for switches with TLS variables.
+ at tls_a = thread_local global i32 0
+ at tls_b = thread_local global i32 0
+ at tls_c = thread_local global i32 0
+ at tls_d = thread_local global i32 0
+define i32* @tls(i32 %x) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %return
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+  ]
+sw.bb1:
+  br label %return
+sw.bb2:
+  br label %return
+sw.default:
+  br label %return
+return:
+  %retval.0 = phi i32* [ @tls_d, %sw.default ], [ @tls_c, %sw.bb2 ], [ @tls_b, %sw.bb1 ], [ @tls_a, %entry ]
+  ret i32* %retval.0
+; CHECK-LABEL: @tls(
+; CHECK: switch i32
+; CHECK-NOT: @switch.table
+}
+
+; Don't build tables for switches with dllimport variables.
+ at dllimport_a = external dllimport global [3x i32]
+ at dllimport_b = external dllimport global [3x i32]
+ at dllimport_c = external dllimport global [3x i32]
+ at dllimport_d = external dllimport global [3x i32]
+define i32* @dllimport(i32 %x) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %return
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+  ]
+sw.bb1:
+  br label %return
+sw.bb2:
+  br label %return
+sw.default:
+  br label %return
+return:
+  %retval.0 = phi i32* [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_d, i32 0, i32 0), %sw.default ],
+                       [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_c, i32 0, i32 0), %sw.bb2 ],
+                       [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_b, i32 0, i32 0), %sw.bb1 ],
+                       [ getelementptr inbounds ([3 x i32], [3 x i32]* @dllimport_a, i32 0, i32 0), %entry ]
+  ret i32* %retval.0
+; CHECK-LABEL: @dllimport(
+; CHECK: switch i32
+; CHECK-NOT: @switch.table
+}
+
+; We can use linear mapping.
+define i8 @linearmap1(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 10, label %return
+    i32 11, label %sw.bb1
+    i32 12, label %sw.bb2
+    i32 13, label %sw.bb3
+  ]
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+return:
+  %x = phi i8 [ 3, %sw.default ], [ 3, %sw.bb3 ], [ 8, %sw.bb2 ], [ 13, %sw.bb1 ], [ 18, %entry ]
+  ret i8 %x
+; CHECK-LABEL: @linearmap1(
+; CHECK: entry:
+; CHECK-NEXT: %switch.tableidx = sub i32 %c, 10
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8
+; CHECK-NEXT: %switch.idx.mult = mul i8 %switch.idx.cast, -5
+; CHECK-NEXT: %switch.offset = add i8 %switch.idx.mult, 18
+; CHECK-NEXT: ret i8 %switch.offset
+}
+
+; Linear mapping in a different configuration.
+define i32 @linearmap2(i8 %c) {
+entry:
+  switch i8 %c, label %sw.default [
+    i8 -10, label %return
+    i8 -11, label %sw.bb1
+    i8 -12, label %sw.bb2
+    i8 -13, label %sw.bb3
+  ]
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+return:
+  %x = phi i32 [ 3, %sw.default ], [ 18, %sw.bb3 ], [ 19, %sw.bb2 ], [ 20, %sw.bb1 ], [ 21, %entry ]
+  ret i32 %x
+; CHECK-LABEL: @linearmap2(
+; CHECK: entry:
+; CHECK-NEXT: %switch.tableidx = sub i8 %c, -13
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.idx.cast = zext i8 %switch.tableidx to i32
+; CHECK-NEXT: %switch.offset = add i32 %switch.idx.cast, 18
+; CHECK-NEXT: ret i32 %switch.offset
+}
+
+; Linear mapping with overflows.
+define i8 @linearmap3(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 10, label %return
+    i32 11, label %sw.bb1
+    i32 12, label %sw.bb2
+    i32 13, label %sw.bb3
+  ]
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+return:
+  %x = phi i8 [ 3, %sw.default ], [ 44, %sw.bb3 ], [ -56, %sw.bb2 ], [ 100, %sw.bb1 ], [ 0, %entry ]
+  ret i8 %x
+; CHECK-LABEL: @linearmap3(
+; CHECK: entry:
+; CHECK-NEXT: %switch.tableidx = sub i32 %c, 10
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8
+; CHECK-NEXT: %switch.idx.mult = mul i8 %switch.idx.cast, 100
+; CHECK-NEXT: ret i8 %switch.idx.mult
+}
+
+; Linear mapping with with multiplier 1 and offset 0.
+define i8 @linearmap4(i32 %c) {
+entry:
+  switch i32 %c, label %sw.default [
+    i32 -2, label %return
+    i32 -1, label %sw.bb1
+    i32 0, label %sw.bb2
+    i32 1, label %sw.bb3
+  ]
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.default: br label %return
+return:
+  %x = phi i8 [ 3, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %entry ]
+  ret i8 %x
+; CHECK-LABEL: @linearmap4(
+; CHECK: entry:
+; CHECK-NEXT: %switch.tableidx = sub i32 %c, -2
+; CHECK: switch.lookup:
+; CHECK-NEXT: %switch.idx.cast = trunc i32 %switch.tableidx to i8
+; CHECK-NEXT: ret i8 %switch.idx.cast
+}
+
+; Reuse the inverted table range compare.
+define i32 @reuse_cmp1(i32 %x) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+sw.bb: br label %sw.epilog
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+sw.epilog:
+  %r.0 = phi i32 [ 0, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ]
+  %cmp = icmp eq i32 %r.0, 0       ; This compare can be "replaced".
+  br i1 %cmp, label %if.then, label %if.end
+if.then: br label %return
+if.end: br label %return
+return:
+  %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ]
+  ret i32 %retval.0
+; CHECK-LABEL: @reuse_cmp1(
+; CHECK: entry:
+; CHECK-NEXT: [[C:%.+]] = icmp ult i32 %x, 4
+; CHECK-NEXT: %inverted.cmp = xor i1 [[C]], true
+; CHECK:      [[R:%.+]] = select i1 %inverted.cmp, i32 100, i32 {{.*}}
+; CHECK-NEXT: ret i32 [[R]]
+}
+
+; Reuse the table range compare.
+define i32 @reuse_cmp2(i32 %x) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+sw.bb: br label %sw.epilog
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+sw.epilog:
+  %r.0 = phi i32 [ 4, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 1, %sw.bb1 ], [ 0, %sw.bb ]
+  %cmp = icmp ne i32 %r.0, 4       ; This compare can be "replaced".
+  br i1 %cmp, label %if.then, label %if.end
+if.then: br label %return
+if.end: br label %return
+return:
+  %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ]
+  ret i32 %retval.0
+; CHECK-LABEL: @reuse_cmp2(
+; CHECK: entry:
+; CHECK-NEXT: %0 = icmp ult i32 %x, 4
+; CHECK-NEXT: %x. = select i1 %0, i32 %x, i32 4
+; CHECK-NEXT: [[C:%.+]] = icmp ne i32 %x., 4
+; CHECK:      [[R:%.+]] = select i1 %0, i32 {{.*}}, i32 100
+; CHECK-NEXT: ret i32 [[R]]
+}
+
+; Cannot reuse the table range compare, because the default value is the same
+; as one of the case values.
+define i32 @no_reuse_cmp(i32 %x) {
+entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+sw.bb: br label %sw.epilog
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+sw.epilog:
+  %r.0 = phi i32 [ 12, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ]
+  %cmp = icmp ne i32 %r.0, 0
+  br i1 %cmp, label %if.then, label %if.end
+if.then: br label %return
+if.end: br label %return
+return:
+  %retval.0 = phi i32 [ %r.0, %if.then ], [ 100, %if.end ]
+  ret i32 %retval.0
+; CHECK-LABEL: @no_reuse_cmp(
+; CHECK:  [[S:%.+]] = select
+; CHECK-NEXT:  %cmp = icmp ne i32 [[S]], 0
+; CHECK-NEXT:  [[R:%.+]] = select i1 %cmp, i32 [[S]], i32 100
+; CHECK-NEXT:  ret i32 [[R]]
+}
+
+; Cannot reuse the table range compare, because the phi at the switch merge
+; point is not dominated by the switch.
+define i32 @no_reuse_cmp2(i32 %x, i32 %y) {
+entry:
+  %ec = icmp ne i32 %y, 0
+  br i1 %ec, label %switch.entry, label %sw.epilog
+switch.entry:
+  switch i32 %x, label %sw.default [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb1
+    i32 2, label %sw.bb2
+    i32 3, label %sw.bb3
+  ]
+sw.bb: br label %sw.epilog
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+sw.epilog:
+  %r.0 = phi i32 [100, %entry], [ 0, %sw.default ], [ 13, %sw.bb3 ], [ 12, %sw.bb2 ], [ 11, %sw.bb1 ], [ 10, %sw.bb ]
+  %cmp = icmp eq i32 %r.0, 0       ; This compare can be "replaced".
+  br i1 %cmp, label %if.then, label %if.end
+if.then: br label %return
+if.end: br label %return
+return:
+  %retval.0 = phi i32 [ 100, %if.then ], [ %r.0, %if.end ]
+  ret i32 %retval.0
+; CHECK-LABEL: @no_reuse_cmp2(
+; CHECK:  %r.0 = phi
+; CHECK-NEXT:  %cmp = icmp eq i32 %r.0, 0
+; CHECK-NEXT:  [[R:%.+]] = select i1 %cmp
+; CHECK-NEXT:  ret i32 [[R]]
+}
+
+define void @pr20210(i8 %x, i1 %y) {
+; %z has uses outside of its BB or the phi it feeds into,
+; so doing a table lookup and jumping directly to while.cond would
+; cause %z to cease dominating all its uses.
+
+entry:
+  br i1 %y, label %sw, label %intermediate
+
+sw:
+  switch i8 %x, label %end [
+    i8 7, label %intermediate
+    i8 3, label %intermediate
+    i8 2, label %intermediate
+    i8 1, label %intermediate
+    i8 0, label %intermediate
+  ]
+
+intermediate:
+  %z = zext i8 %x to i32
+  br label %while.cond
+
+while.cond:
+  %i = phi i32 [ %z, %intermediate ], [ %j, %while.body ]
+  %b = icmp ne i32 %i, 7
+  br i1 %b, label %while.body, label %while.end
+
+while.body:
+  %j = add i32 %i, 1
+  br label %while.cond
+
+while.end:
+  call void @exit(i32 %z)
+  unreachable
+
+end:
+  ret void
+; CHECK-LABEL: @pr20210
+; CHECK: switch i8 %x
+}
+
+; Make sure we do not crash due to trying to generate an unguarded
+; lookup (since i3 can only hold values in the range of explicit
+; values) and simultaneously trying to generate a branch to deal with
+; the fact that we have holes in the range.
+define i32 @covered_switch_with_bit_tests(i3) {
+entry:
+  switch i3 %0, label %l6 [
+    i3 -3, label %l5
+    i3 -4, label %l5
+    i3 3, label %l1
+    i3 2, label %l1
+  ]
+
+l1: br label %l2
+
+l2:
+  %x = phi i32 [ 1, %l1 ], [ 2, %l5 ]
+  br label %l6
+
+l5: br label %l2
+
+l6:
+  %r = phi i32 [ %x, %l2 ], [ 0, %entry ]
+  ret i32 %r
+; CHECK-LABEL: @covered_switch_with_bit_tests
+; CHECK: entry
+; CHECK-NEXT: switch
+}
+
+; Speculation depth must be limited to avoid a zero-cost instruction cycle.
+
+; CHECK-LABEL: @PR26308(
+; CHECK:       cleanup4:
+; CHECK-NEXT:  br label %cleanup4
+
+define i32 @PR26308(i1 %B, i64 %load) {
+entry:
+  br label %while.body
+
+while.body:
+  br label %cleanup
+
+cleanup:
+  %cleanup.dest.slot.0 = phi i1 [ false, %while.body ]
+  br i1 %cleanup.dest.slot.0, label %for.cond, label %cleanup4
+
+for.cond:
+  %e.0 = phi i64* [ undef, %cleanup ], [ %incdec.ptr, %for.cond2 ]
+  %pi = ptrtoint i64* %e.0 to i64
+  %incdec.ptr = getelementptr inbounds i64, i64* %e.0, i64 1
+  br label %for.cond2
+
+for.cond2:
+  %storemerge = phi i64 [ %pi, %for.cond ], [ %load, %for.cond2 ]
+  br i1 %B, label %for.cond2, label %for.cond
+
+cleanup4:
+  br label %while.body
+}
+
+declare void @throw(i1)
+
+define void @wineh_test(i64 %val) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @throw(i1 false)
+          to label %unreachable unwind label %cleanup1
+
+unreachable:
+  unreachable
+
+cleanup1:
+  %cleanuppad1 = cleanuppad within none []
+  switch i64 %val, label %cleanupdone2 [
+    i64 0, label %cleanupdone1
+    i64 1, label %cleanupdone1
+    i64 6, label %cleanupdone1
+  ]
+
+cleanupdone1:
+  cleanupret from %cleanuppad1 unwind label %cleanup2
+
+cleanupdone2:
+  cleanupret from %cleanuppad1 unwind label %cleanup2
+
+cleanup2:
+  %phi = phi i1 [ true, %cleanupdone1 ], [ false, %cleanupdone2 ]
+  %cleanuppad2 = cleanuppad within none []
+  call void @throw(i1 %phi) [ "funclet"(token %cleanuppad2) ]
+  unreachable
+}
+
+; CHECK-LABEL: @wineh_test(
+; CHECK: entry:
+; CHECK:   invoke void @throw(i1 false)
+; CHECK:           to label %[[unreachable:.*]] unwind label %[[cleanup1:.*]]
+
+; CHECK: [[unreachable]]:
+; CHECK:   unreachable
+
+; CHECK: [[cleanup1]]:
+; CHECK:   %[[cleanuppad1:.*]] = cleanuppad within none []
+; CHECK:   switch i64 %val, label %[[cleanupdone2:.*]] [
+; CHECK:     i64 0, label %[[cleanupdone1:.*]]
+; CHECK:     i64 1, label %[[cleanupdone1]]
+; CHECK:     i64 6, label %[[cleanupdone1]]
+; CHECK:   ]
+
+; CHECK: [[cleanupdone1]]:
+; CHECK:   cleanupret from %[[cleanuppad1]] unwind label %[[cleanup2:.*]]
+
+; CHECK: [[cleanupdone2]]:
+; CHECK:   cleanupret from %[[cleanuppad1]] unwind label %[[cleanup2]]
+
+; CHECK: [[cleanup2]]:
+; CHECK:   %[[phi:.*]] = phi i1 [ true, %[[cleanupdone1]] ], [ false, %[[cleanupdone2]] ]
+; CHECK:   %[[cleanuppad2:.*]] = cleanuppad within none []
+; CHECK:   call void @throw(i1 %[[phi]]) [ "funclet"(token %[[cleanuppad2]]) ]
+; CHECK:   unreachable
+
+declare i32 @__CxxFrameHandler3(...)

Added: llvm/trunk/test/Transforms/SimplifyCFG/assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/assume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/assume.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/assume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+define void @test1() {
+        call void @llvm.assume(i1 0)
+        ret void
+
+; CHECK-LABEL: @test1
+; CHECK-NOT: llvm.assume
+; CHECK: unreachable
+}
+
+define void @test2() {
+        call void @llvm.assume(i1 undef)
+        ret void
+
+; CHECK-LABEL: @test2
+; CHECK-NOT: llvm.assume
+; CHECK: unreachable
+}
+
+declare void @llvm.assume(i1) nounwind
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/attr-convergent.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/attr-convergent.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/attr-convergent.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/attr-convergent.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Checks that the SimplifyCFG pass won't duplicate a call to a function marked
+; convergent.
+;
+; CHECK: call void @barrier
+; CHECK-NOT: call void @barrier
+define void @check(i1 %cond, i32* %out) {
+entry:
+  br i1 %cond, label %if.then, label %if.end
+
+if.then:
+  store i32 5, i32* %out
+  br label %if.end
+
+if.end:
+  %x = phi i1 [ true, %entry ], [ false, %if.then ]
+  call void @barrier()
+  br i1 %x, label %cond.end, label %cond.false
+
+cond.false:
+  br label %cond.end
+
+cond.end:
+  ret void
+}
+
+declare void @barrier() convergent

Added: llvm/trunk/test/Transforms/SimplifyCFG/attr-noduplicate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/attr-noduplicate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/attr-noduplicate.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/attr-noduplicate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; This test checks that the SimplifyCFG pass won't duplicate a call to a
+; function marked noduplicate.
+;
+; CHECK-LABEL: @noduplicate
+; CHECK: call void @barrier
+; CHECK-NOT: call void @barrier
+define void @noduplicate(i32 %cond, i32* %out) {
+entry:
+  %out1 = getelementptr i32, i32* %out, i32 1
+  %out2 = getelementptr i32, i32* %out, i32 2
+  %cmp = icmp eq i32 %cond, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  store i32 5, i32* %out
+  br label %if.end
+
+if.end:
+  call void @barrier() #0
+  br i1 %cmp, label %cond.end, label %cond.false
+
+cond.false:
+  store i32 5, i32* %out1
+  br label %cond.end
+
+cond.end:
+  %value = phi i32 [ 1, %cond.false ], [ 0, %if.end ]
+  store i32 %value, i32* %out2
+  ret void
+}
+
+; Function Attrs: noduplicate nounwind
+declare void @barrier() #0
+
+attributes #0 = { noduplicate nounwind }

Added: llvm/trunk/test/Transforms/SimplifyCFG/basictest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/basictest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/basictest.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/basictest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,133 @@
+; Test CFG simplify removal of branch instructions.
+;
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -passes=simplify-cfg -S | FileCheck %s
+
+define void @test1() {
+        br label %1
+        ret void
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: ret void
+}
+
+define void @test2() {
+        ret void
+        ret void
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+}
+
+define void @test3(i1 %T) {
+        br i1 %T, label %1, label %1
+        ret void
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: ret void
+}
+
+; Folding branch to a common destination.
+; CHECK-LABEL: @test4_fold
+; CHECK: %cmp1 = icmp eq i32 %a, %b
+; CHECK: %cmp2 = icmp ugt i32 %a, 0
+; CHECK: %or.cond = and i1 %cmp1, %cmp2
+; CHECK: br i1 %or.cond, label %else, label %untaken
+; CHECK-NOT: taken:
+; CHECK: ret void
+define void @test4_fold(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, 0
+  br i1 %cmp2, label %else, label %untaken
+
+else:
+  call void @foo()
+  ret void
+
+untaken:
+  ret void
+}
+
+; Prefer a simplification based on a dominating condition rather than folding a
+; branch to a common destination.
+; CHECK-LABEL: @test4
+; CHECK-NOT: br
+; CHECK-NOT: br
+; CHECK-NOT: call
+; CHECK: ret void
+define void @test4_no_fold(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  br i1 %cmp2, label %else, label %untaken
+
+else:
+  call void @foo()
+  ret void
+
+untaken:
+  ret void
+}
+
+declare void @foo()
+
+; PR5795
+define void @test5(i32 %A) {
+  switch i32 %A, label %return [
+    i32 2, label %1
+    i32 10, label %2
+  ]
+
+  ret void
+
+  ret void
+
+return:                                           ; preds = %entry
+  ret void
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: ret void
+}
+
+
+; PR14893
+define i8 @test6f() {
+; CHECK-LABEL: @test6f
+; CHECK: alloca i8, align 1
+; CHECK-NEXT: call i8 @test6g
+; CHECK-NEXT: icmp eq i8 %tmp, 0
+; CHECK-NEXT: load i8, i8* %r, align 1, !dbg !{{[0-9]+$}}
+
+bb0:
+  %r = alloca i8, align 1
+  %tmp = call i8 @test6g(i8* %r)
+  %tmp1 = icmp eq i8 %tmp, 0
+  br i1 %tmp1, label %bb2, label %bb1
+bb1:
+  %tmp3 = load i8, i8* %r, align 1, !range !2, !tbaa !10, !dbg !5
+  %tmp4 = icmp eq i8 %tmp3, 1
+  br i1 %tmp4, label %bb2, label %bb3
+bb2:
+  br label %bb3
+bb3:
+  %tmp6 = phi i8 [ 0, %bb2 ], [ 1, %bb1 ]
+  ret i8 %tmp6
+}
+declare i8 @test6g(i8*)
+
+!llvm.dbg.cu = !{!3}
+!llvm.module.flags = !{!8, !9}
+
+!0 = !{!10, !10, i64 0}
+!1 = !{!"foo"}
+!2 = !{i8 0, i8 2}
+!3 = distinct !DICompileUnit(language: DW_LANG_C99, file: !7, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !4)
+!4 = !{}
+!5 = !DILocation(line: 23, scope: !6)
+!6 = distinct !DISubprogram(name: "foo", scope: !3, file: !7, line: 1, type: !DISubroutineType(types: !4), isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !3, retainedNodes: !4)
+!7 = !DIFile(filename: "foo.c", directory: "/")
+!8 = !{i32 2, !"Dwarf Version", i32 2}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{!"scalar type", !1}

Added: llvm/trunk/test/Transforms/SimplifyCFG/bbi-23595.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/bbi-23595.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/bbi-23595.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/bbi-23595.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt < %s -S -simplifycfg | FileCheck %s
+
+; In 'simplifycfg', during the flattening of a 'br', the instructions for the
+; 'true' and 'false' parts, are moved out from their respective basic blocks.
+; Their original debug locations (DILocations) and debug intrinsic instructions
+; (dbg.values) are removed.
+; As those basic blocks are now empty, their associated labels are removed.
+;
+; For the given test case, the labels 'W' and 'cleanup4' are removed.
+; We're expecting the dbg.label associated with 'W' to disappear, because
+; the 'W' label was removed.
+
+; CHECK-LABEL: _Z7test_itv()
+; CHECK:       entry:
+; CHECK-NEXT:    %retval.0 = select i1 undef, i16 1, i16 0
+; CHECK-NEXT:    ret i16 0
+
+define i16 @_Z7test_itv() {
+entry:
+  br label %sw.bb
+
+sw.bb:                                            ; preds = %entry
+  br i1 undef, label %W, label %cleanup4
+
+W:                                                ; preds = %sw.bb
+  call void @llvm.dbg.label(metadata !1), !dbg !8
+  br label %cleanup4
+
+cleanup4:                                         ; preds = %W, %sw.bb
+  %retval.0 = phi i16 [ 1, %W ], [ 0, %sw.bb ]
+  ret i16 0
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.label(metadata) #0
+
+attributes #0 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{}
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !DILabel(scope: !2, name: "W", file: !3, line: 47)
+!2 = distinct !DILexicalBlock(scope: !4, file: !3, line: 40, column: 3)
+!3 = !DIFile(filename: "foo.c", directory: "./")
+!4 = distinct !DISubprogram(name: "test_it", scope: !3, file: !3, line: 35, type: !5, scopeLine: 36, unit: !7)
+!5 = !DISubroutineType(types: !6)
+!6 = !{}
+!7 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+!8 = !DILocation(line: 47, column: 2, scope: !2)

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-merge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-merge.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-merge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -simplifycfg -instcombine \
+; RUN:   -simplifycfg -S | not grep call
+
+declare void @bar()
+
+define void @test(i32 %X, i32 %Y) {
+entry:
+        %tmp.2 = icmp ne i32 %X, %Y             ; <i1> [#uses=1]
+        br i1 %tmp.2, label %shortcirc_next, label %UnifiedReturnBlock
+shortcirc_next:         ; preds = %entry
+        %tmp.3 = icmp ne i32 %X, %Y             ; <i1> [#uses=1]
+        br i1 %tmp.3, label %UnifiedReturnBlock, label %then
+then:           ; preds = %shortcirc_next
+        call void @bar( )
+        ret void
+UnifiedReturnBlock:             ; preds = %shortcirc_next, %entry
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-prop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-prop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-prop.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-cond-prop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -simplifycfg -S | not grep call
+
+declare void @bar()
+
+define void @test(i32 %X, i32 %Y) {
+entry:
+        %tmp.2 = icmp slt i32 %X, %Y            ; <i1> [#uses=2]
+        br i1 %tmp.2, label %shortcirc_next, label %UnifiedReturnBlock
+shortcirc_next:         ; preds = %entry
+        br i1 %tmp.2, label %UnifiedReturnBlock, label %then
+then:           ; preds = %shortcirc_next
+        call void @bar( )
+        ret void
+UnifiedReturnBlock:             ; preds = %shortcirc_next, %entry
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-dbg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-dbg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-dbg.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-dbg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+%0 = type { i32*, i32* }
+
+ at 0 = external hidden constant [5 x %0], align 4
+
+define void @foo(i32) nounwind ssp !dbg !0 {
+Entry:
+  %1 = icmp slt i32 %0, 0, !dbg !5
+  br i1 %1, label %BB5, label %BB1, !dbg !5
+
+BB1:                                              ; preds = %Entry
+  %2 = icmp sgt i32 %0, 4, !dbg !5
+  br i1 %2, label %BB5, label %BB2, !dbg !5
+
+BB2:                                              ; preds = %BB1
+  %3 = shl i32 1, %0, !dbg !5
+  %4 = and i32 %3, 31, !dbg !5
+  %5 = icmp eq i32 %4, 0, !dbg !5
+  br i1 %5, label %BB5, label %BB3, !dbg !5
+
+;CHECK: icmp eq
+;CHECK-NEXT: getelementptr
+;CHECK-NEXT: icmp eq
+
+BB3:                                              ; preds = %BB2
+  %6 = getelementptr inbounds [5 x %0], [5 x %0]* @0, i32 0, i32 %0, !dbg !6
+  call void @llvm.dbg.value(metadata %0* %6, metadata !7, metadata !{}), !dbg !12
+  %7 = icmp eq %0* %6, null, !dbg !13
+  br i1 %7, label %BB5, label %BB4, !dbg !13
+
+BB4:                                              ; preds = %BB3
+  %8 = icmp slt i32 %0, 0, !dbg !5
+  ret void, !dbg !14
+
+BB5:                                              ; preds = %BB3, %BB2, %BB1, %Entry
+  ret void, !dbg !14
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
+
+!llvm.dbg.cu = !{!2}
+
+!0 = distinct !DISubprogram(name: "foo", line: 231, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !15, scope: !1, type: !3)
+!1 = !DIFile(filename: "a.c", directory: "/private/tmp")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang (trunk 129006)", isOptimized: true, emissionKind: FullDebug, file: !15, enums: !4, retainedTypes: !4)
+!3 = !DISubroutineType(types: !4)
+!4 = !{null}
+!5 = !DILocation(line: 131, column: 2, scope: !0)
+!6 = !DILocation(line: 134, column: 2, scope: !0)
+!7 = !DILocalVariable(name: "bar", line: 232, scope: !8, file: !1, type: !9)
+!8 = distinct !DILexicalBlock(line: 231, column: 1, file: !15, scope: !0)
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 32, align: 32, scope: !2, baseType: !10)
+!10 = !DIDerivedType(tag: DW_TAG_const_type, scope: !2, baseType: !11)
+!11 = !DIBasicType(tag: DW_TAG_base_type, name: "unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned)
+!12 = !DILocation(line: 232, column: 40, scope: !8)
+!13 = !DILocation(line: 234, column: 2, scope: !8)
+!14 = !DILocation(line: 274, column: 1, scope: !8)
+!15 = !DIFile(filename: "a.c", directory: "/private/tmp")

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-test.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-test.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-test.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-test.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; This test ensures that the simplifycfg pass continues to constant fold
+; terminator instructions.
+
+; RUN: opt < %s -simplifycfg -S | not grep br
+
+define i32 @test(i32 %A, i32 %B) {
+J:
+        %C = add i32 %A, 12             ; <i32> [#uses=2]
+        br i1 true, label %L, label %K
+L:              ; preds = %J
+        %D = add i32 %C, %B             ; <i32> [#uses=1]
+        ret i32 %D
+K:              ; preds = %J
+        %E = add i32 %C, %B             ; <i32> [#uses=1]
+        ret i32 %E
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-three.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-three.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-three.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-three.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,259 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; s >= t, s != t, s <= t
+define void @foo1(i32 %s, i32 %t) {
+; CHECK-LABEL: @foo1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[S:%.*]], [[T:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @bar1(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END6]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    call void @bar2(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END6]]
+; CHECK:       if.then4:
+; CHECK-NEXT:    call void @bar3(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp sge i32 %s, %t
+  br i1 %cmp, label %if.then, label %if.end6
+
+if.then:
+  call void @bar1(i32 %s, i32 %t)
+  %cmp1 = icmp ne i32 %s, %t
+  br i1 %cmp1, label %if.then2, label %if.end6
+
+if.then2:
+  call void @bar2(i32 %s, i32 %t)
+  %cmp3 = icmp sle i32 %s, %t
+  br i1 %cmp3, label %if.then4, label %if.end6
+
+if.then4:
+  call void @bar3(i32 %s, i32 %t)
+  br label %if.end6
+
+if.end6:
+  ret void
+}
+
+; s != t, s >= t, s <= t
+define void @foo11(i32 %s, i32 %t) {
+; CHECK-LABEL: @foo11(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[S:%.*]], [[T:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @bar1(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END6]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    call void @bar2(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END6]]
+; CHECK:       if.then4:
+; CHECK-NEXT:    call void @bar3(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp ne i32 %s, %t
+  br i1 %cmp, label %if.then, label %if.end6
+
+if.then:
+  call void @bar1(i32 %s, i32 %t)
+  %cmp1 = icmp sge i32 %s, %t
+  br i1 %cmp1, label %if.then2, label %if.end6
+
+if.then2:
+  call void @bar2(i32 %s, i32 %t)
+  %cmp3 = icmp sle i32 %s, %t
+  br i1 %cmp3, label %if.then4, label %if.end6
+
+if.then4:
+  call void @bar3(i32 %s, i32 %t)
+  br label %if.end6
+
+if.end6:
+  ret void
+}
+
+; s >= t, t != s, s <= t
+define void @foo2(i32 %s, i32 %t) {
+; CHECK-LABEL: @foo2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[S:%.*]], [[T:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @bar1(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[T]], [[S]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END6]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    call void @bar2(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END6]]
+; CHECK:       if.then4:
+; CHECK-NEXT:    call void @bar3(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp sge i32 %s, %t
+  br i1 %cmp, label %if.then, label %if.end6
+
+if.then:
+  call void @bar1(i32 %s, i32 %t)
+  %cmp1 = icmp ne i32 %t, %s
+  br i1 %cmp1, label %if.then2, label %if.end6
+
+if.then2:
+  call void @bar2(i32 %s, i32 %t)
+  %cmp3 = icmp sle i32 %s, %t
+  br i1 %cmp3, label %if.then4, label %if.end6
+
+if.then4:
+  call void @bar3(i32 %s, i32 %t)
+  br label %if.end6
+
+if.end6:
+  ret void
+}
+
+; s != t, t <= s, s <= t
+define void @foo21(i32 %s, i32 %t) {
+; CHECK-LABEL: @foo21(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[S:%.*]], [[T:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @bar1(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i32 [[T]], [[S]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END6]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    call void @bar2(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END6]]
+; CHECK:       if.then4:
+; CHECK-NEXT:    call void @bar3(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp ne i32 %s, %t
+  br i1 %cmp, label %if.then, label %if.end6
+
+if.then:
+  call void @bar1(i32 %s, i32 %t)
+  %cmp1 = icmp sle i32 %t, %s
+  br i1 %cmp1, label %if.then2, label %if.end6
+
+if.then2:
+  call void @bar2(i32 %s, i32 %t)
+  %cmp3 = icmp sle i32 %s, %t
+  br i1 %cmp3, label %if.then4, label %if.end6
+
+if.then4:
+  call void @bar3(i32 %s, i32 %t)
+  br label %if.end6
+
+if.end6:
+  ret void
+}
+
+; t <= s, t != s, s <= t
+define void @foo3(i32 %s, i32 %t) {
+; CHECK-LABEL: @foo3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[T:%.*]], [[S:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @bar1(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[T]], [[S]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END6]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    call void @bar2(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END6]]
+; CHECK:       if.then4:
+; CHECK-NEXT:    call void @bar3(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp sle i32 %t, %s
+  br i1 %cmp, label %if.then, label %if.end6
+
+if.then:
+  call void @bar1(i32 %s, i32 %t)
+  %cmp1 = icmp ne i32 %t, %s
+  br i1 %cmp1, label %if.then2, label %if.end6
+
+if.then2:
+  call void @bar2(i32 %s, i32 %t)
+  %cmp3 = icmp sle i32 %s, %t
+  br i1 %cmp3, label %if.then4, label %if.end6
+
+if.then4:
+  call void @bar3(i32 %s, i32 %t)
+  br label %if.end6
+
+if.end6:
+  ret void
+}
+
+; t != s, t <= s, s <= t
+define void @foo31(i32 %s, i32 %t) {
+; CHECK-LABEL: @foo31(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[T:%.*]], [[S:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END6:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @bar1(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sle i32 [[T]], [[S]]
+; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END6]]
+; CHECK:       if.then2:
+; CHECK-NEXT:    call void @bar2(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sle i32 [[S]], [[T]]
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END6]]
+; CHECK:       if.then4:
+; CHECK-NEXT:    call void @bar3(i32 [[S]], i32 [[T]])
+; CHECK-NEXT:    br label [[IF_END6]]
+; CHECK:       if.end6:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp ne i32 %t, %s
+  br i1 %cmp, label %if.then, label %if.end6
+
+if.then:
+  call void @bar1(i32 %s, i32 %t)
+  %cmp1 = icmp sle i32 %t, %s
+  br i1 %cmp1, label %if.then2, label %if.end6
+
+if.then2:
+  call void @bar2(i32 %s, i32 %t)
+  %cmp3 = icmp sle i32 %s, %t
+  br i1 %cmp3, label %if.then4, label %if.end6
+
+if.then4:
+  call void @bar3(i32 %s, i32 %t)
+  br label %if.end6
+
+if.end6:
+  ret void
+}
+
+declare void @bar1(i32, i32)
+declare void @bar2(i32, i32)
+declare void @bar3(i32, i32)
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-threshold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-threshold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-threshold.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-fold-threshold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,83 @@
+; RUN: opt %s -simplifycfg -S | FileCheck %s --check-prefix=NORMAL
+; RUN: opt %s -simplifycfg -S -bonus-inst-threshold=2 | FileCheck %s --check-prefix=AGGRESSIVE
+; RUN: opt %s -simplifycfg -S -bonus-inst-threshold=4 | FileCheck %s --check-prefix=WAYAGGRESSIVE
+; RUN: opt %s -passes=simplify-cfg -S | FileCheck %s --check-prefix=NORMAL
+; RUN: opt %s -passes='simplify-cfg<bonus-inst-threshold=2>' -S | FileCheck %s --check-prefix=AGGRESSIVE
+; RUN: opt %s -passes='simplify-cfg<bonus-inst-threshold=4>' -S | FileCheck %s --check-prefix=WAYAGGRESSIVE
+
+define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d, i32* %input) {
+; NORMAL-LABEL: @foo(
+; AGGRESSIVE-LABEL: @foo(
+entry:
+  %cmp = icmp sgt i32 %d, 3
+  br i1 %cmp, label %cond.end, label %lor.lhs.false
+; NORMAL: br i1
+; AGGRESSIVE: br i1
+
+lor.lhs.false:
+  %mul = shl i32 %c, 1
+  %add = add nsw i32 %mul, %a
+  %cmp1 = icmp slt i32 %add, %b
+  br i1 %cmp1, label %cond.false, label %cond.end
+; NORMAL: br i1
+; AGGRESSIVE-NOT: br i1
+
+cond.false:
+  %0 = load i32, i32* %input, align 4
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
+  ret i32 %cond
+}
+
+declare void @distinct_a();
+declare void @distinct_b();
+
+;; Like foo, but have to duplicate into multiple predecessors
+define i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d, i32* %input) {
+; NORMAL-LABEL: @bar(
+; AGGRESSIVE-LABEL: @bar(
+entry:
+  %cmp_split = icmp slt i32 %d, %b
+  %cmp = icmp sgt i32 %d, 3
+  br i1 %cmp_split, label %pred_a, label %pred_b
+pred_a:
+; NORMAL-LABEL: pred_a:
+; AGGRESSIVE-LABEL: pred_a:
+; WAYAGGRESSIVE-LABEL: pred_a:
+; NORMAL: br i1
+; AGGRESSIVE: br i1
+; WAYAGGRESSIVE: br i1
+  call void @distinct_a();
+  br i1 %cmp, label %cond.end, label %lor.lhs.false
+pred_b:
+; NORMAL-LABEL: pred_b:
+; AGGRESSIVE-LABEL: pred_b:
+; WAYAGGRESSIVE-LABEL: pred_b:
+; NORMAL: br i1
+; AGGRESSIVE: br i1
+; WAYAGGRESSIVE: br i1
+  call void @distinct_b();
+  br i1 %cmp, label %cond.end, label %lor.lhs.false
+
+lor.lhs.false:
+  %mul = shl i32 %c, 1
+  %add = add nsw i32 %mul, %a
+  %cmp1 = icmp slt i32 %add, %b
+  br i1 %cmp1, label %cond.false, label %cond.end
+; NORMAL-LABEL: lor.lhs.false:
+; AGGRESIVE-LABEL: lor.lhs.false:
+; WAYAGGRESIVE-LABEL: lor.lhs.false:
+; NORMAL: br i1
+; AGGRESSIVE: br i1
+; WAYAGGRESSIVE-NOT: br i1
+
+cond.false:
+  %0 = load i32, i32* %input, align 4
+  br label %cond.end
+
+cond.end:
+  %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ],[ 0, %pred_a ],[ 0, %pred_b ]
+  ret i32 %cond
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-fold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-fold.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-fold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define void @test(i32* %P, i32* %Q, i1 %A, i1 %B) {
+; CHECK: test
+; CHECK: br i1
+; CHECK-NOT: br i1
+; CHECK: ret
+; CHECK: ret
+
+entry:
+        br i1 %A, label %a, label %b
+a:
+        br i1 %B, label %b, label %c
+b:
+        store i32 123, i32* %P
+        ret void
+c:
+        ret void
+}
+
+; rdar://10554090
+define zeroext i1 @test2(i64 %i0, i64 %i1) nounwind uwtable readonly ssp {
+entry:
+; CHECK: test2
+; CHECK: br i1
+  %and.i.i = and i64 %i0, 281474976710655
+  %and.i11.i = and i64 %i1, 281474976710655
+  %or.cond = icmp eq i64 %and.i.i, %and.i11.i
+  br i1 %or.cond, label %c, label %a
+
+a:
+; CHECK: br
+  %shr.i4.i = lshr i64 %i0, 48
+  %and.i5.i = and i64 %shr.i4.i, 32767
+  %shr.i.i = lshr i64 %i1, 48
+  %and.i2.i = and i64 %shr.i.i, 32767
+  %cmp9.i = icmp ult i64 %and.i5.i, %and.i2.i
+  br i1 %cmp9.i, label %c, label %b
+
+b:
+; CHECK-NOT: br
+  %shr.i13.i9 = lshr i64 %i1, 48
+  %and.i14.i10 = and i64 %shr.i13.i9, 32767
+  %shr.i.i11 = lshr i64 %i0, 48
+  %and.i11.i12 = and i64 %shr.i.i11, 32767
+  %phitmp = icmp uge i64 %and.i14.i10, %and.i11.i12
+  br label %c
+
+c:
+  %o2 = phi i1 [ false, %a ], [ %phitmp, %b ], [ false, %entry ]
+  ret i1 %o2
+}
+
+; PR13180
+define void @pr13180(i8 %p) {
+entry:
+  %tobool = icmp eq i8 %p, 0
+  br i1 %tobool, label %cond.false, label %cond.true
+
+cond.true:                                        ; preds = %entry
+  br label %cond.end
+
+cond.false:                                       ; preds = %entry
+  %phitmp = icmp eq i8 %p, 0
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  %cond = phi i1 [ undef, %cond.true ], [ %phitmp, %cond.false ]
+  unreachable
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/branch-phi-thread.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/branch-phi-thread.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/branch-phi-thread.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/branch-phi-thread.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,66 @@
+; RUN: opt < %s -simplifycfg -adce -S | \
+; RUN:   not grep "call void @f1"
+; END.
+
+declare void @f1()
+
+declare void @f2()
+
+declare void @f3()
+
+declare void @f4()
+
+define i32 @test1(i32 %X, i1 %D) {
+E:
+	%C = icmp eq i32 %X, 0		; <i1> [#uses=2]
+	br i1 %C, label %T, label %F
+T:		; preds = %A, %E
+	br i1 %C, label %B, label %A
+A:		; preds = %T
+	call void @f1( )
+	br i1 %D, label %T, label %F
+B:		; preds = %T
+	call void @f2( )
+	ret i32 345
+F:		; preds = %A, %E
+	call void @f3( )
+	ret i32 123
+}
+
+define i32 @test2(i32 %X, i1 %D) {
+E:
+	%C = icmp eq i32 %X, 0		; <i1> [#uses=2]
+	br i1 %C, label %T, label %F
+T:		; preds = %A, %E
+	%P = phi i1 [ true, %E ], [ %C, %A ]		; <i1> [#uses=1]
+	br i1 %P, label %B, label %A
+A:		; preds = %T
+	call void @f1( )
+	br i1 %D, label %T, label %F
+B:		; preds = %T
+	call void @f2( )
+	ret i32 345
+F:		; preds = %A, %E
+	call void @f3( )
+	ret i32 123
+}
+
+define i32 @test3(i32 %X, i1 %D, i32* %AP, i32* %BP) {
+E:
+	%C = icmp eq i32 %X, 0		; <i1> [#uses=2]
+	br i1 %C, label %T, label %F
+T:		; preds = %A, %E
+	call void @f3( )
+	%XX = load i32, i32* %AP		; <i32> [#uses=1]
+	store i32 %XX, i32* %BP
+	br i1 %C, label %B, label %A
+A:		; preds = %T
+	call void @f1( )
+	br i1 %D, label %T, label %F
+B:		; preds = %T
+	call void @f2( )
+	ret i32 345
+F:		; preds = %A, %E
+	call void @f3( )
+	ret i32 123
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/bug-25299.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/bug-25299.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/bug-25299.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/bug-25299.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+;; Test case for bug 25299, contributed by David Majnemer.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f(i1 %B) personality i1 undef {
+entry:
+;CHECK: entry
+;CHECK-NEXT: call void @g()
+  invoke void @g()
+          to label %continue unwind label %unwind
+
+unwind:                                           ; preds = %entry
+  %tmp101 = landingpad { i8*, i32 }
+          cleanup
+  br i1 %B, label %resume, label %then
+
+then:                                             ; preds = %cleanup1
+  br label %resume
+
+resume:                                           ; preds = %cleanup2, %then, %cleanup1, %unwind
+  %tmp104 = phi { i8*, i32 } [ %tmp101, %then ], [ %tmp106, %cleanup2 ], [ %tmp101, %unwind ]
+;CHECK-NOT: resume { i8*, i32 } %tmp104
+  resume { i8*, i32 } %tmp104
+
+continue:                                         ; preds = %entry, %continue
+;CHECK: continue:                                         ; preds = %entry, %continue
+;CHECK-NEXT: call void @g()
+  invoke void @g()
+          to label %continue unwind label %cleanup2
+
+cleanup2:                                         ; preds = %continue
+  %tmp106 = landingpad { i8*, i32 }
+          cleanup
+  br label %resume
+}
+
+declare void @g()
\ No newline at end of file

Added: llvm/trunk/test/Transforms/SimplifyCFG/clamp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/clamp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/clamp.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/clamp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define float @clamp(float %a, float %b, float %c) {
+; CHECK-LABEL: @clamp
+; CHECK:  %cmp = fcmp ogt float %a, %c
+; CHECK:  %cmp1 = fcmp olt float %a, %b
+; CHECK:  %cond = select i1 %cmp1, float %b, float %a
+; CHECK:  %cond5 = select i1 %cmp, float %c, float %cond
+; CHECK:  ret float %cond5
+entry:
+  %cmp = fcmp ogt float %a, %c
+  br i1 %cmp, label %cond.end4, label %cond.false
+
+cond.false:                                       ; preds = %entry
+  %cmp1 = fcmp olt float %a, %b
+  %cond = select i1 %cmp1, float %b, float %a
+  br label %cond.end4
+
+cond.end4:                                        ; preds = %entry, %cond.false
+  %cond5 = phi float [ %cond, %cond.false ], [ %c, %entry ]
+  ret float %cond5
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/combine-parallel-mem-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/combine-parallel-mem-md.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/combine-parallel-mem-md.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/combine-parallel-mem-md.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: norecurse nounwind uwtable
+define void @Test(i32* nocapture %res, i32* nocapture readnone %c, i32* nocapture readonly %d, i32* nocapture readonly %p) #0 {
+entry:
+  br label %for.body
+
+; CHECK-LABEL: @Test
+; CHECK: load i32, i32* {{.*}}, align 4, !llvm.access.group !0
+; CHECK: load i32, i32* {{.*}}, align 4, !llvm.access.group !0
+; CHECK: store i32 {{.*}}, align 4, !llvm.access.group !0
+; CHECK-NOT: load
+; CHECK-NOT: store
+
+for.body:                                         ; preds = %cond.end, %entry
+  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %cond.end ]
+  %arrayidx = getelementptr inbounds i32, i32* %p, i64 %indvars.iv
+  %0 = load i32, i32* %arrayidx, align 4, !llvm.access.group !0
+  %cmp1 = icmp eq i32 %0, 0
+  br i1 %cmp1, label %cond.true, label %cond.false
+
+cond.false:                                       ; preds = %for.body
+  %arrayidx3 = getelementptr inbounds i32, i32* %res, i64 %indvars.iv
+  %v = load i32, i32* %arrayidx3, align 4, !llvm.access.group !0
+  %arrayidx7 = getelementptr inbounds i32, i32* %d, i64 %indvars.iv
+  %1 = load i32, i32* %arrayidx7, align 4, !llvm.access.group !0
+  %add = add nsw i32 %1, %v
+  br label %cond.end
+
+cond.true:                                       ; preds = %for.body
+  %arrayidx4 = getelementptr inbounds i32, i32* %res, i64 %indvars.iv
+  %w = load i32, i32* %arrayidx4, align 4, !llvm.access.group !0
+  %arrayidx8 = getelementptr inbounds i32, i32* %d, i64 %indvars.iv
+  %2 = load i32, i32* %arrayidx8, align 4, !llvm.access.group !0
+  %add2 = add nsw i32 %2, %w
+  br label %cond.end
+
+cond.end:                                         ; preds = %for.body, %cond.false
+  %cond = phi i32 [ %add, %cond.false ], [ %add2, %cond.true ]
+  %arrayidx9 = getelementptr inbounds i32, i32* %res, i64 %indvars.iv
+  store i32 %cond, i32* %arrayidx9, align 4, !llvm.access.group !0
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp eq i64 %indvars.iv.next, 16
+  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
+
+for.end:                                          ; preds = %cond.end
+  ret void
+}
+
+attributes #0 = { norecurse nounwind uwtable }
+
+!0 = distinct !{!0, !1, !{!"llvm.loop.parallel_accesses", !10}}
+!1 = !{!"llvm.loop.vectorize.enable", i1 true}
+!10 = distinct !{}

Added: llvm/trunk/test/Transforms/SimplifyCFG/common-dest-folding.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/common-dest-folding.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/common-dest-folding.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/common-dest-folding.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+;CHECK: @foo
+;CHECK: and i32 %c1, %k
+;CHECK: icmp eq i32
+;CHECK: and i32 %c2, %k
+;CHECK: icmp eq i32
+;CHECK: or i1
+;CHECK: ret
+define i32 @foo(i32 %k, i32 %c1, i32 %c2) {
+  %1 = and i32 %c1, %k
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %8, label %3
+
+; <label>:3                                       ; preds = %0
+  %4 = and i32 %c2, %k
+  %5 = icmp eq i32 %4, 0
+  br i1 %5, label %8, label %6
+
+; <label>:6                                       ; preds = %3
+  %7 = tail call i32 (...) @bar() nounwind
+  br label %8
+
+; <label>:8                                       ; preds = %3, %0, %6
+  ret i32 undef
+}
+
+;CHECK: @conduse
+;CHECK: shl i32 1, %c1
+;CHECK-NEXT: shl i32 1, %c2
+;CHECK-NEXT: and i32
+;CHECK-NEXT: icmp eq i32
+;CHECK-NEXT: and i32
+;CHECK-NEXT: icmp eq i32
+;CHECK: ret
+define i32 @conduse(i32 %k, i32 %c1, i32 %c2) #0 {
+bb:
+  %tmp = shl i32 1, %c1
+  %tmp4 = shl i32 1, %c2
+  %tmp1 = and i32 %tmp, %k
+  %tmp2 = icmp eq i32 %tmp1, 0
+  br i1 %tmp2, label %bb9, label %bb3
+
+bb3:                                              ; preds = %bb
+  %tmp5 = and i32 %tmp4, %k
+  %tmp6 = icmp eq i32 %tmp5, 0
+  br i1 %tmp6, label %bb9, label %bb7
+
+bb7:                                              ; preds = %bb3
+  %tmp8 = tail call i32 (...) @bar() #1
+  br label %bb9
+
+bb9:                                              ; preds = %bb7, %bb3, %bb
+  ret i32 undef
+}
+
+declare i32 @bar(...)

Added: llvm/trunk/test/Transforms/SimplifyCFG/critedge-assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/critedge-assume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/critedge-assume.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/critedge-assume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,83 @@
+; RUN: opt -o %t %s -instcombine -simplifycfg -thinlto-bc -verify-assumption-cache
+; RUN: llvm-dis -o - %t | FileCheck %s
+
+; Test that the simplifycfg pass correctly updates the assumption cache
+; when it clones the llvm.assume call as part of creating a critical
+; edge. To do that, we set up a pass pipeline such that (1) an assumption
+; cache is created for foo before simplifycfg updates it, and (2) foo's
+; assumption cache is verified after simplifycfg has run. To satisfy 1, we
+; run the instcombine pass first in our pipeline. To satisfy 2, we use the
+; ThinLTOBitcodeWriter pass to write bitcode (that pass uses the assumption
+; cache). That ensures that the pass manager does not call releaseMemory()
+; on the AssumptionCacheTracker before the end of the pipeline, which would
+; wipe out the bad assumption cache before it is verified.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%class.F = type { i8 }
+%class.B = type { i8 }
+%class.A = type { %class.C }
+%class.C = type { i32 (...)** }
+
+define void @foo(%class.F* %this, %class.B* %out) {
+entry:
+  %call = tail call i32 @_ZNK1F5beginEv(%class.F* %this)
+  %call2 = tail call i32 @_ZNK1F3endEv(%class.F* %this)
+  %cmp.i22 = icmp eq i32 %call, %call2
+  br i1 %cmp.i22, label %while.end, label %while.body.preheader
+
+while.body.preheader:
+  br label %while.body
+
+while.body:
+  %frame_node.sroa.0.023 = phi i32 [ %inc.i, %_ZN10unique_ptrD2Ev.exit ], [ %call, %while.body.preheader ]
+  %call8 = tail call i8* @_Znwm(i64 8)
+  %inc.i = add nsw i32 %frame_node.sroa.0.023, 1
+  %cmp = icmp eq i32 %inc.i, %call2
+  br i1 %cmp, label %_ZN10unique_ptrD2Ev.exit, label %if.then
+
+if.then:
+  tail call void @_ZN1B6appendEv(%class.B* %out)
+  br label %_ZN10unique_ptrD2Ev.exit
+
+_ZN10unique_ptrD2Ev.exit:
+  %x1 = bitcast i8* %call8 to void (%class.A*)***
+  %vtable.i.i = load void (%class.A*)**, void (%class.A*)*** %x1, align 8
+  %x2 = bitcast void (%class.A*)** %vtable.i.i to i8*
+  %x3 = tail call i1 @llvm.type.test(i8* %x2, metadata !"foo")
+  ; CHECK: call void @llvm.assume
+  ; CHECK: call void @llvm.assume
+  tail call void @llvm.assume(i1 %x3) #5
+  br i1 %cmp, label %while.end.loopexit, label %while.body
+
+while.end.loopexit:
+  br label %while.end
+
+while.end:
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare i32 @_ZNK1F5beginEv(%class.F*)
+
+declare i32 @_ZNK1F3endEv(%class.F*)
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)
+
+declare noalias nonnull i8* @_Znwm(i64)
+
+declare void @_ZN1B6appendEv(%class.B*)
+
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+declare i1 @llvm.type.test(i8*, metadata)
+
+declare void @llvm.assume(i1)
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"PIC Level", i32 2}
+!1 = !{!"clang version 5.0.0 "}

Added: llvm/trunk/test/Transforms/SimplifyCFG/dbginfo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/dbginfo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/dbginfo.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/dbginfo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt < %s -simplifycfg -S | not grep "br label"
+
+	%llvm.dbg.anchor.type = type { i32, i32 }
+	%llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 }
+	%llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8* }
+	%llvm.dbg.composite.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, { }* }
+	%llvm.dbg.derivedtype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }* }
+	%llvm.dbg.global_variable.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1, { }* }
+	%llvm.dbg.subprogram.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1 }
+	%llvm.dbg.subrange.type = type { i32, i64, i64 }
+	%struct.Group = type { %struct.Scene, %struct.Sphere, %"struct.std::list<Scene*,std::allocator<Scene*> >" }
+	%struct.Ray = type { %struct.Vec, %struct.Vec }
+	%struct.Scene = type { i32 (...)** }
+	%struct.Sphere = type { %struct.Scene, %struct.Vec, double }
+	%struct.Vec = type { double, double, double }
+	%struct.__class_type_info_pseudo = type { %struct.__type_info_pseudo }
+	%struct.__false_type = type <{ i8 }>
+	%"struct.__gnu_cxx::new_allocator<Scene*>" = type <{ i8 }>
+	%"struct.__gnu_cxx::new_allocator<std::_List_node<Scene*> >" = type <{ i8 }>
+	%struct.__si_class_type_info_pseudo = type { %struct.__type_info_pseudo, %"struct.std::type_info"* }
+	%struct.__type_info_pseudo = type { i8*, i8* }
+	%"struct.std::Hit" = type { double, %struct.Vec }
+	%"struct.std::_List_base<Scene*,std::allocator<Scene*> >" = type { %"struct.std::_List_base<Scene*,std::allocator<Scene*> >::_List_impl" }
+	%"struct.std::_List_base<Scene*,std::allocator<Scene*> >::_List_impl" = type { %"struct.std::_List_node_base" }
+	%"struct.std::_List_const_iterator<Scene*>" = type { %"struct.std::_List_node_base"* }
+	%"struct.std::_List_iterator<Scene*>" = type { %"struct.std::_List_node_base"* }
+	%"struct.std::_List_node<Scene*>" = type { %"struct.std::_List_node_base", %struct.Scene* }
+	%"struct.std::_List_node_base" = type { %"struct.std::_List_node_base"*, %"struct.std::_List_node_base"* }
+	%"struct.std::allocator<Scene*>" = type <{ i8 }>
+	%"struct.std::allocator<std::_List_node<Scene*> >" = type <{ i8 }>
+	%"struct.std::basic_ios<char,std::char_traits<char> >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream<char,std::char_traits<char> >"*, i8, i8, %"struct.std::basic_streambuf<char,std::char_traits<char> >"*, %"struct.std::ctype<char>"*, %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >"*, %"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >"* }
+	%"struct.std::basic_ostream<char,std::char_traits<char> >" = type { i32 (...)**, %"struct.std::basic_ios<char,std::char_traits<char> >" }
+	%"struct.std::basic_streambuf<char,std::char_traits<char> >" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"struct.std::locale" }
+	%"struct.std::ctype<char>" = type { %"struct.std::locale::facet", i32*, i8, i32*, i32*, i32*, i8, [256 x i8], [256 x i8], i8 }
+	%"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"struct.std::locale" }
+	%"struct.std::ios_base::Init" = type <{ i8 }>
+	%"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 }
+	%"struct.std::ios_base::_Words" = type { i8*, i32 }
+	%"struct.std::list<Scene*,std::allocator<Scene*> >" = type { %"struct.std::_List_base<Scene*,std::allocator<Scene*> >" }
+	%"struct.std::locale" = type { %"struct.std::locale::_Impl"* }
+	%"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** }
+	%"struct.std::locale::facet" = type { i32 (...)**, i32 }
+	%"struct.std::num_get<char,std::istreambuf_iterator<char, std::char_traits<char> > >" = type { %"struct.std::locale::facet" }
+	%"struct.std::num_put<char,std::ostreambuf_iterator<char, std::char_traits<char> > >" = type { %"struct.std::locale::facet" }
+	%"struct.std::numeric_limits<double>" = type <{ i8 }>
+	%"struct.std::type_info" = type { i32 (...)**, i8* }
+ at llvm.dbg.subprogram947 = external constant %llvm.dbg.subprogram.type		; <%llvm.dbg.subprogram.type*> [#uses=1]
+
+declare void @llvm.dbg.func.start({ }*) nounwind
+
+declare void @llvm.dbg.region.end({ }*) nounwind
+
+declare void @_ZN9__gnu_cxx13new_allocatorIP5SceneED2Ev(%struct.__false_type*) nounwind
+
+define void @_ZNSaIP5SceneED1Ev(%struct.__false_type* %this) nounwind {
+entry:
+	%this_addr = alloca %struct.__false_type*		; <%struct.__false_type**> [#uses=2]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	call void @llvm.dbg.func.start({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram947 to { }*))
+	store %struct.__false_type* %this, %struct.__false_type** %this_addr
+	%0 = load %struct.__false_type*, %struct.__false_type** %this_addr, align 4		; <%struct.__false_type*> [#uses=1]
+	call void @_ZN9__gnu_cxx13new_allocatorIP5SceneED2Ev(%struct.__false_type* %0) nounwind
+	br label %bb
+
+bb:		; preds = %entry
+	br label %return
+
+return:		; preds = %bb
+	call void @llvm.dbg.region.end({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram947 to { }*))
+	ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt -S <%s -simplifycfg | FileCheck %s
+
+define void @test_br(i32 %x) {
+entry:
+; CHECK-LABEL: @test_br(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret void
+  %cmp = icmp eq i32 %x, 10
+  br i1 %cmp, label %if.then, label %if.then
+
+if.then:                                          ; preds = %entry
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+
+define void @test_switch(i32 %x) nounwind {
+entry:
+; CHECK-LABEL: @test_switch(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret void
+  %rem = srem i32 %x, 3
+  switch i32 %rem, label %sw.bb [
+    i32 1, label %sw.bb
+    i32 10, label %sw.bb
+  ]
+
+sw.bb:                                            ; preds = %sw.default, %entry, %entry
+  br label %sw.epilog
+
+sw.epilog:                                        ; preds = %sw.bb
+  ret void
+}
+
+define void @test_indirectbr(i32 %x) {
+entry:
+; CHECK-LABEL: @test_indirectbr(
+; CHECK-NEXT: entry:
+; Ideally this should now check:
+;   CHK-NEXT: ret void
+; But that doesn't happen yet. Instead:
+; CHECK-NEXT: br label %L1
+
+  %label = bitcast i8* blockaddress(@test_indirectbr, %L1) to i8*
+  indirectbr i8* %label, [label %L1, label %L2]
+
+L1:                                               ; preds = %entry
+  ret void
+L2:                                               ; preds = %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/debug-info-thread-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/debug-info-thread-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/debug-info-thread-phi.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/debug-info-thread-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt %s -debugify -simplifycfg -S | FileCheck %s
+; Tests Bug 37966
+
+define void @bar(i32 %aa) {
+; CHECK-LABEL: @bar(
+; CHECK: if.end.1.critedge:
+; CHECK: br label %if.end.1, !dbg ![[DBG:[0-9]+]]
+entry:
+  %aa.addr = alloca i32, align 4
+  %bb = alloca i32, align 4
+  store i32 %aa, i32* %aa.addr, align 4
+  store i32 0, i32* %bb, align 4
+  %tobool = icmp ne i32 %aa, 0
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @foo()
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  store i32 1, i32* %bb, align 4
+  br i1 %tobool, label %if.then.1, label %if.end.1 ; "line 10" to -debugify
+
+if.then.1:                                        ; preds = %if.end
+  call void @foo()
+  br label %if.end.1
+
+if.end.1:                                         ; preds = %if.then.1, %if.end
+  store i32 2, i32* %bb, align 4
+  br label %for.end
+
+for.end:                                          ; preds = %if.end.1
+  ret void
+}
+
+declare void @foo()
+
+; CHECK: ![[DBG]] = !DILocation(line: 10,

Added: llvm/trunk/test/Transforms/SimplifyCFG/div-rem-pairs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/div-rem-pairs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/div-rem-pairs.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/div-rem-pairs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,114 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+; We could hoist the div/rem in these tests because it's safe to do so.
+; PR31028 - https://bugs.llvm.org/show_bug.cgi?id=31028
+; ...but since there's a separate pass for that, don't bother.
+
+define i32 @hoist_sdiv(i32 %a, i32 %b) {
+; CHECK-LABEL: @hoist_sdiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[REM]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+entry:
+  %rem = srem i32 %a, %b
+  %cmp = icmp eq i32 %rem, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %div = sdiv i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+define i64 @hoist_udiv(i64 %a, i64 %b) {
+; CHECK-LABEL: @hoist_udiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[REM:%.*]] = urem i64 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[REM]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i64 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i64 [ [[DIV]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i64 [[RET]]
+;
+entry:
+  %rem = urem i64 %a, %b
+  %cmp = icmp eq i64 %rem, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %div = udiv i64 %a, %b
+  br label %end
+
+end:
+  %ret = phi i64 [ %div, %if ], [ 3, %entry ]
+  ret i64 %ret
+}
+
+define i16 @hoist_srem(i16 %a, i16 %b) {
+; CHECK-LABEL: @hoist_srem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i16 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[DIV]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[REM:%.*]] = srem i16 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i16 [ [[REM]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i16 [[RET]]
+;
+entry:
+  %div = sdiv i16 %a, %b
+  %cmp = icmp eq i16 %div, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %rem = srem i16 %a, %b
+  br label %end
+
+end:
+  %ret = phi i16 [ %rem, %if ], [ 3, %entry ]
+  ret i16 %ret
+}
+
+define i8 @hoist_urem(i8 %a, i8 %b) {
+; CHECK-LABEL: @hoist_urem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i8 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[DIV]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[REM:%.*]] = urem i8 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i8 [ [[REM]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+entry:
+  %div = udiv i8 %a, %b
+  %cmp = icmp eq i8 %div, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %rem = urem i8 %a, %b
+  br label %end
+
+end:
+  %ret = phi i8 [ %rem, %if ], [ 3, %entry ]
+  ret i8 %ret
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/duplicate-landingpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/duplicate-landingpad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/duplicate-landingpad.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/duplicate-landingpad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,110 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+declare i32 @__gxx_personality_v0(...)
+declare void @fn()
+
+
+; CHECK-LABEL: @test1
+define void @test1() personality i32 (...)* @__gxx_personality_v0 {
+entry:
+; CHECK-LABEL: entry:
+; CHECK: to label %invoke2 unwind label %lpad2
+  invoke void @fn()
+    to label %invoke2 unwind label %lpad1
+
+invoke2:
+; CHECK-LABEL: invoke2:
+; CHECK: to label %invoke.cont unwind label %lpad2
+  invoke void @fn()
+    to label %invoke.cont unwind label %lpad2
+
+invoke.cont:
+  ret void
+
+lpad1:
+  %exn = landingpad {i8*, i32}
+         cleanup
+  br label %shared_resume
+
+lpad2:
+; CHECK-LABEL: lpad2:
+; CHECK: landingpad { i8*, i32 }
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: call void @fn()
+; CHECK-NEXT: ret void
+  %exn2 = landingpad {i8*, i32}
+          cleanup
+  br label %shared_resume
+
+shared_resume:
+  call void @fn()
+  ret void
+}
+
+; Don't trigger if blocks aren't the same/empty
+define void @neg1() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: @neg1
+entry:
+; CHECK-LABEL: entry:
+; CHECK: to label %invoke2 unwind label %lpad1
+  invoke void @fn()
+    to label %invoke2 unwind label %lpad1
+
+invoke2:
+; CHECK-LABEL: invoke2:
+; CHECK: to label %invoke.cont unwind label %lpad2
+  invoke void @fn()
+    to label %invoke.cont unwind label %lpad2
+
+invoke.cont:
+  ret void
+
+lpad1:
+  %exn = landingpad {i8*, i32}
+         filter [0 x i8*] zeroinitializer
+  call void @fn()
+  br label %shared_resume
+
+lpad2:
+  %exn2 = landingpad {i8*, i32}
+          cleanup
+  br label %shared_resume
+
+shared_resume:
+  call void @fn()
+  ret void
+}
+
+; Should not trigger when the landing pads are not the exact same
+define void @neg2() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: @neg2
+entry:
+; CHECK-LABEL: entry:
+; CHECK: to label %invoke2 unwind label %lpad1
+  invoke void @fn()
+    to label %invoke2 unwind label %lpad1
+
+invoke2:
+; CHECK-LABEL: invoke2:
+; CHECK: to label %invoke.cont unwind label %lpad2
+  invoke void @fn()
+    to label %invoke.cont unwind label %lpad2
+
+invoke.cont:
+  ret void
+
+lpad1:
+  %exn = landingpad {i8*, i32}
+         filter [0 x i8*] zeroinitializer
+  br label %shared_resume
+
+lpad2:
+  %exn2 = landingpad {i8*, i32}
+          cleanup
+  br label %shared_resume
+
+shared_resume:
+  call void @fn()
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/duplicate-phis.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/duplicate-phis.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/duplicate-phis.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/duplicate-phis.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -instcombine -simplifycfg -S | grep " = phi " | count 1
+
+; instcombine should sort the PHI operands so that simplifycfg can see the
+; duplicate and remove it.
+
+define i32 @foo(i1 %t) {
+entry:
+  call void @bar()
+  br i1 %t, label %true, label %false
+true:
+  call void @bar()
+  br label %false
+false:
+  %a = phi i32 [ 2, %true ], [ 5, %entry ]
+  %b = phi i32 [ 5, %entry ], [ 2, %true ]
+  call void @bar()
+  %c = add i32 %a, %b
+  ret i32 %c
+}
+
+declare void @bar()

Added: llvm/trunk/test/Transforms/SimplifyCFG/empty-catchpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/empty-catchpad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/empty-catchpad.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/empty-catchpad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,115 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @f()
+declare void @llvm.foo(i32) nounwind
+declare void @ProcessCLRException()
+
+define void @test1() personality void ()* @ProcessCLRException {
+entry:
+  invoke void @f()
+    to label %exit unwind label %exn.dispatch
+exn.dispatch:
+  %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller
+pad1:
+  %cp1 = catchpad within %cs [i32 1]
+  call void @llvm.foo(i32 1)
+  catchret from %cp1 to label %exit
+pad2:
+  %cp2 = catchpad within %cs [i32 2]
+  unreachable
+exit:
+  ret void
+}
+; Remove unreachble catch2, leave catch1 as-is
+; CHECK-LABEL: define void @test1()
+; CHECK: %cs = catchswitch within none [label %pad1] unwind to caller
+; CHECK-NOT: catchpad
+; CHECK: %cp1 = catchpad within %cs [i32 1]
+; CHECK-NOT: catchpad
+
+; Remove both catchpads and the catchswitch from exn.dispatch
+; CHECK-LABEL: define void @test2()
+define void @test2() personality void ()* @ProcessCLRException {
+entry:
+  invoke void @f()
+    to label %via.cleanup unwind label %exn.dispatch
+  ; CHECK-NOT: invoke
+  ; CHECK: call void @f()
+via.cleanup:
+  invoke void @f()
+    to label %via.catchswitch unwind label %cleanup.inner
+cleanup.inner:
+  %cp.inner = cleanuppad within none []
+  call void @llvm.foo(i32 0)
+  cleanupret from %cp.inner unwind label %exn.dispatch
+  ; CHECK: cleanupret from %cp.inner unwind to caller
+via.catchswitch:
+  invoke void @f()
+    to label %exit unwind label %dispatch.inner
+dispatch.inner:
+  %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch
+  ; CHECK: %cs.inner = catchswitch within none [label %pad.inner] unwind to caller
+pad.inner:
+  %catch.inner = catchpad within %cs.inner [i32 0]
+  ; CHECK: %catch.inner = catchpad within %cs.inner
+  call void @llvm.foo(i32 1)
+  catchret from %catch.inner to label %exit
+exn.dispatch:
+  %cs = catchswitch within none [label %pad1, label %pad2] unwind to caller
+  ; CHECK-NOT: catchswitch within
+  ; CHECK-NOT: catchpad
+pad1:
+  catchpad within %cs [i32 1]
+  unreachable
+pad2:
+  catchpad within %cs [i32 2]
+  unreachable
+exit:
+  ret void
+}
+
+; Same as @test2, but exn.dispatch catchswitch has an unwind dest that
+; preds need to be reidrected to
+; CHECK-LABEL: define void @test3()
+define void @test3() personality void ()* @ProcessCLRException {
+entry:
+  invoke void @f()
+    to label %via.cleanup unwind label %exn.dispatch
+  ; CHECK: invoke void @f()
+  ; CHECK-NEXT: to label %via.cleanup unwind label %cleanup
+via.cleanup:
+  invoke void @f()
+    to label %via.catchswitch unwind label %cleanup.inner
+cleanup.inner:
+  %cp.inner = cleanuppad within none []
+  call void @llvm.foo(i32 0)
+  cleanupret from %cp.inner unwind label %exn.dispatch
+  ; CHECK: cleanupret from %cp.inner unwind label %cleanup
+via.catchswitch:
+  invoke void @f()
+    to label %exit unwind label %dispatch.inner
+dispatch.inner:
+  %cs.inner = catchswitch within none [label %pad.inner] unwind label %exn.dispatch
+  ; CHECK: %cs.inner = catchswitch within none [label %pad.inner] unwind label %cleanup
+pad.inner:
+  %catch.inner = catchpad within %cs.inner [i32 0]
+  ; CHECK: %catch.inner = catchpad within %cs.inner
+  call void @llvm.foo(i32 1)
+  catchret from %catch.inner to label %exit
+exn.dispatch:
+  %cs = catchswitch within none [label %pad1, label %pad2] unwind label %cleanup
+  ; CHECK-NOT: catchswitch within
+  ; CHECK-NOT: catchpad
+pad1:
+  catchpad within %cs [i32 1]
+  unreachable
+pad2:
+  catchpad within %cs [i32 2]
+  unreachable
+cleanup:
+  %cp = cleanuppad within none []
+  call void @llvm.foo(i32 0)
+  cleanupret from %cp unwind to caller
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,470 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; ModuleID = 'cppeh-simplify.cpp'
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+
+; This case arises when two objects with empty destructors are cleaned up.
+;
+; void f1() { 
+;   S a;
+;   S b;
+;   g(); 
+; }
+;
+; In this case, both cleanup pads can be eliminated and the invoke can be
+; converted to a call.
+;
+; CHECK: define void @f1()
+; CHECK: entry:
+; CHECK:   call void @g()
+; CHECK:   ret void
+; CHECK-NOT: cleanuppad
+; CHECK: }
+;
+define void @f1() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  invoke void @g() to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  ret void
+
+ehcleanup:                                        ; preds = %entry
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %ehcleanup.1
+
+ehcleanup.1:                                      ; preds = %ehcleanup
+  %1 = cleanuppad within none []
+  cleanupret from %1 unwind to caller
+}
+
+
+; This case arises when an object with an empty destructor must be cleaned up
+; outside of a try-block and an object with a non-empty destructor must be
+; cleaned up within the try-block.
+;
+; void f2() { 
+;   S a;
+;   try {
+;     S2 b;
+;     g();
+;   } catch (...) {}
+; }
+;
+; In this case, the outermost cleanup pad can be eliminated and the catch block
+; should unwind to the caller (that is, exception handling continues with the
+; parent frame of the caller).
+;
+; CHECK: define void @f2()
+; CHECK: entry:
+; CHECK:   invoke void @g()
+; CHECK: ehcleanup:
+; CHECK:   cleanuppad within none
+; CHECK:   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %b)
+; CHECK:   cleanupret from %0 unwind label %catch.dispatch
+; CHECK: catch.dispatch:
+; CHECK:   catchswitch within none [label %catch] unwind to caller
+; CHECK: catch:
+; CHECK:   catchpad
+; CHECK:   catchret
+; CHECK-NOT: cleanuppad
+; CHECK: }
+;
+define void @f2() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %b = alloca %struct.S2, align 1
+  invoke void @g() to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  br label %try.cont
+
+ehcleanup:                                        ; preds = %entry
+  %0 = cleanuppad within none []
+  call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %b)
+  cleanupret from %0 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %ehcleanup
+  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %1 to label %catchret.dest
+
+catchret.dest:                                    ; preds = %catch
+  br label %try.cont
+
+try.cont:                                         ; preds = %catchret.dest, %invoke.cont
+  ret void
+
+ehcleanup.1:
+  %2 = cleanuppad within none []
+  cleanupret from %2 unwind to caller
+}
+
+
+; This case arises when an object with a non-empty destructor must be cleaned up
+; outside of a try-block and an object with an empty destructor must be cleaned
+; within the try-block.
+;
+; void f3() { 
+;   S2 a;
+;   try {
+;     S b;
+;     g();
+;   } catch (...) {}
+; }
+;
+; In this case the inner cleanup pad should be eliminated and the invoke of g()
+; should unwind directly to the catchpad.
+;
+; CHECK-LABEL: define void @f3()
+; CHECK: entry:
+; CHECK:   invoke void @g()
+; CHECK:           to label %try.cont unwind label %catch.dispatch
+; CHECK: catch.dispatch:
+; CHECK-NEXT: catchswitch within none [label %catch] unwind label %ehcleanup.1
+; CHECK: catch:
+; CHECK:   catchpad within %cs1 [i8* null, i32 64, i8* null]
+; CHECK:   catchret
+; CHECK: ehcleanup.1:
+; CHECK:   cleanuppad
+; CHECK:   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %a)
+; CHECK:   cleanupret from %cp3 unwind to caller
+; CHECK: }
+;
+define void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  %a = alloca %struct.S2, align 1
+  invoke void @g() to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  br label %try.cont
+
+ehcleanup:                                        ; preds = %entry
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %ehcleanup
+  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1
+
+catch:                                            ; preds = %catch.dispatch
+  %cp2 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %cp2 to label %catchret.dest
+
+catchret.dest:                                    ; preds = %catch
+  br label %try.cont
+
+try.cont:                                         ; preds = %catchret.dest, %invoke.cont
+  ret void
+
+ehcleanup.1:
+  %cp3 = cleanuppad within none []
+  call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %a)
+  cleanupret from %cp3 unwind to caller
+}
+
+
+; This case arises when an object with an empty destructor may require cleanup
+; from either inside or outside of a try-block.
+;
+; void f4() { 
+;   S a;
+;   g();
+;   try {
+;     g();
+;   } catch (...) {}
+; }
+;
+; In this case, the cleanuppad should be eliminated, the invoke outside of the
+; catch block should be converted to a call (that is, that is, exception
+; handling continues with the parent frame of the caller).)
+;
+; CHECK-LABEL: define void @f4()
+; CHECK: entry:
+; CHECK:   call void @g
+; Note: The cleanuppad simplification will insert an unconditional branch here
+;       but it will be eliminated, placing the following invoke in the entry BB. 
+; CHECK:   invoke void @g()
+; CHECK:           to label %try.cont unwind label %catch.dispatch
+; CHECK: catch.dispatch:
+; CHECK:   catchswitch within none [label %catch] unwind to caller
+; CHECK: catch:
+; CHECK:   catchpad
+; CHECK:   catchret
+; CHECK-NOT: cleanuppad
+; CHECK: }
+;
+define void @f4() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  invoke void @g()
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  invoke void @g()
+          to label %try.cont unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %invoke.cont
+  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup
+
+catch:                                            ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %0 to label %try.cont
+
+try.cont:                                         ; preds = %catch, %invoke.cont
+  ret void
+
+ehcleanup:
+  %cp2 = cleanuppad within none []
+  cleanupret from %cp2 unwind to caller
+}
+
+; This case tests simplification of an otherwise empty cleanup pad that contains
+; a PHI node.
+;
+; int f6() {
+;   int state = 1;
+;   try {
+;     S a;
+;     g();
+;     state = 2;
+;     g();
+;   } catch (...) {
+;     return state;
+;   }
+;   return 0;
+; }
+;
+; In this case, the cleanup pad should be eliminated and the PHI node in the
+; cleanup pad should be sunk into the catch dispatch block.
+;
+; CHECK-LABEL: define i32 @f6()
+; CHECK: entry:
+; CHECK:   invoke void @g()
+; CHECK: invoke.cont:
+; CHECK:   invoke void @g()
+; CHECK-NOT: ehcleanup:
+; CHECK-NOT:   cleanuppad
+; CHECK: catch.dispatch:
+; CHECK:   %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
+; CHECK: }
+define i32 @f6() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  invoke void @g()
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  invoke void @g()
+          to label %return unwind label %ehcleanup
+
+ehcleanup:                                        ; preds = %invoke.cont, %entry
+  %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %ehcleanup
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %1 to label %return
+
+return:                                           ; preds = %invoke.cont, %catch
+  %retval.0 = phi i32 [ %state.0, %catch ], [ 0, %invoke.cont ]
+  ret i32 %retval.0
+}
+
+; This case tests another variation of simplification of an otherwise empty
+; cleanup pad that contains a PHI node.
+;
+; int f7() {
+;   int state = 1;
+;   try {
+;     g();
+;     state = 2;
+;     S a;
+;     g();
+;     state = 3;
+;     g();
+;   } catch (...) {
+;     return state;
+;   }
+;   return 0;
+; }
+;
+; In this case, the cleanup pad should be eliminated and the PHI node in the
+; cleanup pad should be merged with the PHI node in the catch dispatch block.
+;
+; CHECK-LABEL: define i32 @f7()
+; CHECK: entry:
+; CHECK:   invoke void @g()
+; CHECK: invoke.cont:
+; CHECK:   invoke void @g()
+; CHECK: invoke.cont.1:
+; CHECK:   invoke void @g()
+; CHECK-NOT: ehcleanup:
+; CHECK-NOT:   cleanuppad
+; CHECK: catch.dispatch:
+; CHECK:   %state.1 = phi i32 [ 1, %entry ], [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
+; CHECK: }
+define i32 @f7() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  invoke void @g()
+          to label %invoke.cont unwind label %catch.dispatch
+
+invoke.cont:                                      ; preds = %entry
+  invoke void @g()
+          to label %invoke.cont.1 unwind label %ehcleanup
+
+invoke.cont.1:                                    ; preds = %invoke.cont
+  invoke void @g()
+          to label %return unwind label %ehcleanup
+
+ehcleanup:                                        ; preds = %invoke.cont.1, %invoke.cont
+  %state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %ehcleanup, %entry
+  %state.1 = phi i32 [ %state.0, %ehcleanup ], [ 1, %entry ]
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %1 to label %return
+
+return:                                           ; preds = %invoke.cont.1, %catch
+  %retval.0 = phi i32 [ %state.1, %catch ], [ 0, %invoke.cont.1 ]
+  ret i32 %retval.0
+}
+
+; This case tests a scenario where an empty cleanup pad is not dominated by all
+; of the predecessors of its successor, but the successor references a PHI node
+; in the empty cleanup pad.
+;
+; Conceptually, the case being modeled is something like this:
+;
+; int f8() {
+;   int x = 1;
+;   try {
+;     S a;
+;     g();
+;     x = 2;
+; retry:
+;     g();
+;     return
+;   } catch (...) {
+;     use_x(x);
+;   }
+;   goto retry;
+; }
+;
+; While that C++ syntax isn't legal, the IR below is.
+;
+; In this case, the PHI node that is sunk from ehcleanup to catch.dispatch
+; should have an incoming value entry for path from 'foo' that references the
+; PHI node itself.
+;
+; CHECK-LABEL: define void @f8()
+; CHECK: entry:
+; CHECK:   invoke void @g()
+; CHECK: invoke.cont:
+; CHECK:   invoke void @g()
+; CHECK-NOT: ehcleanup:
+; CHECK-NOT:   cleanuppad
+; CHECK: catch.dispatch:
+; CHECK:   %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ], [ %x, %catch.cont ] 
+; CHECK: }
+define void @f8() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+  invoke void @g()
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  invoke void @g()
+          to label %return unwind label %ehcleanup
+
+ehcleanup:                                        ; preds = %invoke.cont, %entry
+  %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %ehcleanup, %catch.cont
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  call void @use_x(i32 %x)
+  catchret from %1 to label %catch.cont
+
+catch.cont:                                       ; preds = %catch
+  invoke void @g()
+          to label %return unwind label %catch.dispatch
+
+return:                                           ; preds = %invoke.cont, %catch.cont
+  ret void
+}
+; CHECK-LABEL: define i32 @f9()
+; CHECK: entry:
+; CHECK:   invoke void @"\01??1S2@@QEAA at XZ"(
+; CHECK-NOT:   cleanuppad
+; CHECK: catch.dispatch:
+; CHECK: }
+define i32 @f9() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  %s = alloca i8, align 1
+  call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %s)
+  %bc = bitcast i8* %s to %struct.S2*
+  invoke void @"\01??1S2@@QEAA at XZ"(%struct.S2* %bc)
+          to label %try.cont unwind label %ehcleanup
+
+ehcleanup:
+  %cleanup.pad = cleanuppad within none []
+  call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %s)
+  cleanupret from %cleanup.pad unwind label %catch.dispatch
+
+catch.dispatch:
+  %catch.switch = catchswitch within none [label %catch] unwind to caller
+
+catch:
+  %catch.pad = catchpad within %catch.switch [i8* null, i32 0, i8* null]
+  catchret from %catch.pad to label %try.cont
+
+try.cont:
+  ret i32 0
+}
+
+; CHECK-LABEL: define void @f10(
+define void @f10(i32 %V) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @g()
+          to label %unreachable unwind label %cleanup
+; CHECK:       call void @g()
+; CHECK-NEXT:  unreachable
+
+unreachable:
+  unreachable
+
+cleanup:
+  %cp = cleanuppad within none []
+  switch i32 %V, label %cleanupret1 [
+    i32 0, label %cleanupret2
+  ]
+
+cleanupret1:
+  cleanupret from %cp unwind to caller
+
+cleanupret2:
+  cleanupret from %cp unwind to caller
+}
+
+%struct.S = type { i8 }
+%struct.S2 = type { i8 }
+declare void @"\01??1S2@@QEAA at XZ"(%struct.S2*)
+declare void @g()
+declare void @use_x(i32 %x)
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)

Added: llvm/trunk/test/Transforms/SimplifyCFG/extract-cost.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/extract-cost.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/extract-cost.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/extract-cost.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt -simplifycfg -S  < %s | FileCheck %s
+
+declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) #1
+
+define i32 @f(i32 %a, i32 %b) #0 {
+entry:
+  %uadd = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
+  %cmp = extractvalue { i32, i1 } %uadd, 1
+  br i1 %cmp, label %return, label %if.end
+
+if.end:                                           ; preds = %entry
+  %0 = extractvalue { i32, i1 } %uadd, 0
+  br label %return
+
+return:                                           ; preds = %entry, %if.end
+  %retval.0 = phi i32 [ %0, %if.end ], [ 0, %entry ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @f(
+; CHECK-NOT: phi
+; CHECK: select
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/fold-branch-debuginvariant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/fold-branch-debuginvariant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/fold-branch-debuginvariant.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/fold-branch-debuginvariant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -strip-debug -simplifycfg -S | FileCheck %s
+
+; Verify that the and.2 instruction is eliminated even in the presence of a
+; preceding debug intrinsic.
+
+; CHECK-LABEL: bb1:
+; CHECK: and i1 false, false
+; CHECK-LABEL: bb2:
+; CHECK-NOT: and i1 false, false
+
+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
+define void @foo() local_unnamed_addr #0 !dbg !4 {
+bb1:
+  %and.1 = and i1 false, false
+  %cmp = icmp eq i16 0, 0
+  br i1 %cmp, label %bb2, label %bb3
+
+bb2:                                              ; preds = %bb1
+  call void @llvm.dbg.value(metadata i16 0, metadata !8, metadata !DIExpression()), !dbg !9
+  %and.2 = and i1 false, false
+  br label %bb3
+
+bb3:                                              ; preds = %bb2, %bb1
+  ret void
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { norecurse nounwind }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "Foo", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2)
+!1 = !DIFile(filename: "foo.c", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 10, type: !5, isLocal: false, isDefinition: true, scopeLine: 10, isOptimized: false, unit: !0, retainedNodes: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null, !7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !DILocalVariable(name: "p_1", arg: 1, scope: !4, line: 4, type: !7)
+!9 = distinct !DILocation(line: 11, column: 3, scope: !4)

Added: llvm/trunk/test/Transforms/SimplifyCFG/fold-debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/fold-debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/fold-debug-info.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/fold-debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,102 @@
+;; Check that we don't crash. PR37300.
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+
+define void @patatino() {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret void
+;
+bb:
+  %tmp = icmp eq i32 7, 0
+  br label %bb3
+bb3:                                              ; preds = %bb2, %bb
+  br label %bb36
+bb5:                                              ; preds = %bb4
+  %tmp7 = icmp ne i32 7, 0
+  %tmp8 = and i1 true, %tmp7
+  br i1 %tmp8, label %bb16, label %bb14
+bb9:                                              ; preds = %bb33, %bb10
+  br label %bb18
+bb10:                                             ; preds = %bb19, %bb13
+  %tmp11 = add nsw i32 2, 1
+  %tmp12 = icmp eq i32 %tmp11, 0
+  br i1 %tmp12, label %bb17, label %bb9
+bb13:                                             ; preds = %bb18, %bb13
+  br label %bb10
+bb14:                                             ; preds = %bb17, %bb6, %bb5
+  br label %bb35
+bb16:                                             ; preds = %bb6
+  br label %bb31
+bb17:                                             ; preds = %bb32, %bb10
+  br label %bb14
+bb18:                                             ; preds = %bb9
+  br label %bb13
+bb21:                                             ; preds = %bb31, %bb23
+  %tmp22 = phi i32 [ 0, %bb23 ], [ 0, %bb31 ]
+  br label %bb27
+bb23:                                             ; preds = %bb29, %bb28, %bb26
+  %tmp24 = add nsw i32 %tmp22, 1
+  %tmp25 = icmp eq i32 %tmp24, 0
+  br i1 %tmp25, label %bb32, label %bb21
+bb27:                                             ; preds = %bb21
+  br label %bb30
+bb28:                                             ; preds = %bb30
+  br label %bb23
+bb30:                                             ; preds = %bb30, %bb27
+  br label %bb28
+bb31:                                             ; preds = %bb16
+  br label %bb21
+bb32:                                             ; preds = %bb23
+  br label %bb17
+bb35:                                             ; preds = %bb14
+  br label %bb3
+bb36:                                             ; preds = %bb3, %bb3
+  br label %bb37
+bb37:                                             ; preds = %bb36
+  %tmp39 = and i1 %tmp, true
+  br i1 %tmp39, label %bb40, label %bb67
+bb40:                                             ; preds = %bb38
+  br i1 %tmp, label %bb42, label %bb41
+bb41:                                             ; preds = %bb40
+  br label %bb43
+bb42:                                             ; preds = %bb40
+  br label %bb66
+bb43:                                             ; preds = %bb41
+  br label %bb44
+bb44:                                             ; preds = %bb61, %bb43
+  %tmp45 = phi i32 [ 0, %bb61 ], [ 0, %bb43 ]
+  %tmp46 = phi i32 [ %tmp62, %bb61 ], [ 0, %bb43 ]
+  br label %bb51
+bb48:                                             ; preds = %bb47
+  br label %bb49
+bb49:                                             ; preds = %bb48
+  %tmp50 = phi i32 [ 0, %bb48 ]
+  br label %bb61
+bb51:                                             ; preds = %bb44
+  br label %bb52
+bb52:                                             ; preds = %bb55, %bb51
+  %tmp53 = phi i32 [ %tmp46, %bb51 ], [ 0, %bb55 ]
+  br label %bb55
+bb54:                                             ; preds = %bb52
+  br label %bb55
+bb55:                                             ; preds = %bb54, %bb52
+  %tmp56 = phi i32 [ 0, %bb54 ], [ 0, %bb52 ]
+  %tmp57 = shl i32 %tmp56, 16
+  br i1 false, label %bb52, label %bb58
+bb58:                                             ; preds = %bb55
+  %tmp59 = phi i32 [ 0, %bb55 ]
+  %tmp60 = phi i32 [ %tmp53, %bb55 ]
+  br label %bb61
+bb61:                                             ; preds = %bb58, %bb49
+  %tmp62 = phi i32 [ %tmp59, %bb58 ], [ %tmp50, %bb49 ]
+  %tmp63 = add nsw i32 %tmp45, 1
+  %tmp64 = icmp eq i32 %tmp63, 0
+  br i1 %tmp64, label %bb65, label %bb44
+bb65:                                             ; preds = %bb61
+  br label %bb66
+bb66:                                             ; preds = %bb65, %bb42
+  br label %bb67
+bb67:                                             ; preds = %bb66, %bb38
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/gepcost.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/gepcost.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/gepcost.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/gepcost.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -simplifycfg | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "thumbv7m-none--eabi"
+
+ at glob = external unnamed_addr constant [16 x i8]
+
+define void @f() {
+; CHECK-LABEL: @f(
+; CHECK-NEXT:  entr:
+; CHECK-NEXT:    br i1 undef, label [[NEXT:%.*]], label [[EXIT:%.*]]
+; CHECK:       next:
+; CHECK-NEXT:    [[PAT:%.*]] = getelementptr [16 x i8], [16 x i8]* @glob
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entr:
+  br i1 undef, label %next, label %exit
+
+next:
+  %pat = getelementptr [16 x i8], [16 x i8]* @glob
+  br label %exit
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/guards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/guards.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/guards.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 -simplifycfg < %s | FileCheck %s
+
+declare void @llvm.experimental.guard(i1, ...)
+
+define i32 @f_0(i1 %c) {
+; CHECK-LABEL: @f_0(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+; CHECK-NEXT:    unreachable
+;
+entry:
+  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+  ret i32 10
+}
+
+define i32 @f_1(i1 %c) {
+; Demonstrate that we (intentionally) do not simplify a guard on undef
+; CHECK-LABEL: @f_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK:       true:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ]
+; CHECK-NEXT:    ret i32 10
+; CHECK:       false:
+; CHECK-NEXT:    ret i32 20
+;
+
+entry:
+  br i1 %c, label %true, label %false
+
+true:
+  call void(i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ]
+  ret i32 10
+
+false:
+  ret i32 20
+}
+
+define i32 @f_2(i1 %c, i32* %buf) {
+; CHECK-LABEL: @f_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]]
+; CHECK:       guard_block:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+; CHECK-NEXT:    unreachable
+; CHECK:       merge_block:
+; CHECK-NEXT:    ret i32 50
+;
+entry:
+  br i1 %c, label %guard_block, label %merge_block
+
+guard_block:
+  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+  %val = load i32, i32* %buf
+  br label %merge_block
+
+merge_block:
+  %to.return = phi i32 [ %val, %guard_block ], [ 50, %entry ]
+  ret i32 %to.return
+
+}
+
+define i32 @f_3(i1* %c, i32* %buf) {
+; CHECK-LABEL: @f_3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C0:%.*]] = load volatile i1, i1* [[C:%.*]]
+; CHECK-NEXT:    br i1 [[C0]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]]
+; CHECK:       guard_block:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+; CHECK-NEXT:    unreachable
+; CHECK:       merge_block:
+; CHECK-NEXT:    [[C1:%.*]] = load volatile i1, i1* [[C]]
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[C1]], i32 50, i32 100
+; CHECK-NEXT:    ret i32 [[DOT]]
+;
+entry:
+  %c0 = load volatile i1, i1* %c
+  br i1 %c0, label %guard_block, label %merge_block
+
+guard_block:
+  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+  %val = load i32, i32* %buf
+  %c2 = load volatile i1, i1* %c
+  br i1 %c2, label %left, label %right
+
+merge_block:
+  %c1 = load volatile i1, i1* %c
+  br i1 %c1, label %left, label %right
+
+left:
+  %val.left = phi i32 [ %val, %guard_block ], [ 50, %merge_block ]
+  ret i32 %val.left
+
+right:
+  %val.right = phi i32 [ %val, %guard_block ], [ 100, %merge_block ]
+  ret i32 %val.right
+
+
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/hoist-common-code.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/hoist-common-code.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/hoist-common-code.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/hoist-common-code.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -simplifycfg -S | not grep br
+
+declare void @bar(i32)
+
+define void @test(i1 %P, i32* %Q) {
+        br i1 %P, label %T, label %F
+T:              ; preds = %0
+        store i32 1, i32* %Q
+        %A = load i32, i32* %Q               ; <i32> [#uses=1]
+        call void @bar( i32 %A )
+        ret void
+F:              ; preds = %0
+        store i32 1, i32* %Q
+        %B = load i32, i32* %Q               ; <i32> [#uses=1]
+        call void @bar( i32 %B )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+; Verify that we don't crash due an invalid !dbg location on the hoisted llvm.dbg.value
+
+define i64 @caller(i64* %ptr, i64 %flag) !dbg !10 {
+init:
+  %v9 = icmp eq i64 %flag, 0
+  br i1 %v9, label %a, label %b
+
+; CHECK:  %vala = load i64, i64* %ptr
+; CHECK-NEXT:  call void @llvm.dbg.value(metadata i64 %vala, metadata [[MD:![0-9]*]]
+; CHECK-NEXT:  call void @llvm.dbg.value(metadata i64 %vala, metadata [[MD]]
+; CHECK-NEXT:  %valbmasked = and i64 %vala, 1
+
+a:                                              ; preds = %init
+  %vala = load i64, i64* %ptr, align 8
+  call void @llvm.dbg.value(metadata i64 %vala, metadata !8, metadata !DIExpression()), !dbg !12
+  br label %test.exit
+
+b:                                              ; preds = %init
+  %valb = load i64, i64* %ptr, align 8
+  call void @llvm.dbg.value(metadata i64 %valb, metadata !8, metadata !DIExpression()), !dbg !13
+  %valbmasked = and i64 %valb, 1
+  br label %test.exit
+
+test.exit:                                      ; preds = %a, %b
+  %retv = phi i64 [ %vala, %a ], [ %valbmasked, %b ]
+  ret i64 %retv
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+attributes #0 = { nounwind readnone speculatable }
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!1}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
+!2 = !DIFile(filename: "optbug", directory: "")
+!3 = !{}
+!4 = distinct !DISubprogram(name: "callee", scope: !2, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !1, retainedNodes: !7)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null}
+!7 = !{!8}
+!8 = !DILocalVariable(name: "var", scope: !4, file: !2, type: !9)
+!9 = !DIBasicType(name: "var_t", size: 64, encoding: DW_ATE_unsigned)
+!10 = distinct !DISubprogram(name: "caller", scope: !2, file: !2, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: false, unit: !1, retainedNodes: !3)
+!11 = distinct !DILocation(line: 6, scope: !10)
+!12 = !DILocation(line: 2, scope: !4, inlinedAt: !11)
+!13 = !DILocation(line: 3, scope: !4, inlinedAt: !11)

Added: llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+define i32 @foo(i32 %i) nounwind ssp !dbg !0 {
+  call void @llvm.dbg.value(metadata i32 %i, metadata !6, metadata !DIExpression()), !dbg !7
+  call void @llvm.dbg.value(metadata i32 0, metadata !9, metadata !DIExpression()), !dbg !11
+  %1 = icmp ne i32 %i, 0, !dbg !12
+;CHECK: call i32 (...) @bar()
+;CHECK-NEXT: llvm.dbg.value
+  br i1 %1, label %2, label %4, !dbg !12
+
+; <label>:2                                       ; preds = %0
+  %3 = call i32 (...) @bar(), !dbg !13
+  call void @llvm.dbg.value(metadata i32 %3, metadata !9, metadata !DIExpression()), !dbg !13
+  br label %6, !dbg !15
+
+; <label>:4                                       ; preds = %0
+  %5 = call i32 (...) @bar(), !dbg !16
+  call void @llvm.dbg.value(metadata i32 %5, metadata !9, metadata !DIExpression()), !dbg !16
+  br label %6, !dbg !18
+
+; <label>:6                                       ; preds = %4, %2
+  %k.0 = phi i32 [ %3, %2 ], [ %5, %4 ]
+  ret i32 %k.0, !dbg !19
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
+
+declare i32 @bar(...)
+
+declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
+
+!llvm.module.flags = !{!21}
+!llvm.dbg.cu = !{!2}
+
+!0 = distinct !DISubprogram(name: "foo", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !20, scope: !1, type: !3)
+!1 = !DIFile(filename: "b.c", directory: "/private/tmp")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang", isOptimized: true, emissionKind: FullDebug, file: !20)
+!3 = !DISubroutineType(types: !4)
+!4 = !{!5}
+!5 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!6 = !DILocalVariable(name: "i", line: 2, arg: 1, scope: !0, file: !1, type: !5)
+!7 = !DILocation(line: 2, column: 13, scope: !0)
+!9 = !DILocalVariable(name: "k", line: 3, scope: !10, file: !1, type: !5)
+!10 = distinct !DILexicalBlock(line: 2, column: 16, file: !20, scope: !0)
+!11 = !DILocation(line: 3, column: 12, scope: !10)
+!12 = !DILocation(line: 4, column: 3, scope: !10)
+!13 = !DILocation(line: 5, column: 5, scope: !14)
+!14 = distinct !DILexicalBlock(line: 4, column: 10, file: !20, scope: !10)
+!15 = !DILocation(line: 6, column: 3, scope: !14)
+!16 = !DILocation(line: 7, column: 5, scope: !17)
+!17 = distinct !DILexicalBlock(line: 6, column: 10, file: !20, scope: !10)
+!18 = !DILocation(line: 8, column: 3, scope: !17)
+!19 = !DILocation(line: 9, column: 3, scope: !10)
+!20 = !DIFile(filename: "b.c", directory: "/private/tmp")
+!21 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/SimplifyCFG/hoist-with-range.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/hoist-with-range.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/hoist-with-range.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/hoist-with-range.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define void @foo(i1 %c, i8* %p) {
+; CHECK: if:
+; CHECK-NEXT: load i8, i8* %p, !range !0
+; CHECK: !0 = !{i8 0, i8 1, i8 3, i8 5}
+if:
+  br i1 %c, label %then, label %else
+then:
+  %t = load i8, i8* %p, !range !0
+  br label %out
+else:
+  %e = load i8, i8* %p, !range !1
+  br label %out
+out:
+  ret void
+}
+
+!0 = !{ i8 0, i8 1 }
+!1 = !{ i8 3, i8 5 }

Added: llvm/trunk/test/Transforms/SimplifyCFG/implied-and-or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/implied-and-or.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/implied-and-or.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/implied-and-or.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,250 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -simplifycfg | FileCheck %s
+
+declare void @foo()
+declare void @bar()
+
+define void @test_and1(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_and1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp1 = icmp eq i32 %a, 0
+  %cmp2 = icmp eq i32 %b, 0
+  %and = and i1 %cmp1, %cmp2
+  br i1 %and, label %taken, label %end
+
+taken:
+  call void @bar()
+  %cmp3 = icmp eq i32 %a, 0  ;; <-- implied true
+  br i1 %cmp3, label %if.then, label %end
+
+if.then:
+  call void @foo()
+  br label %end
+
+end:
+  ret void
+}
+
+; We can't infer anything if the result of the 'and' is false
+
+define void @test_and2(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_and2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[END:%.*]], label [[TAKEN:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[A]], 0
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp1 = icmp eq i32 %a, 0
+  %cmp2 = icmp eq i32 %b, 0
+  %and = and i1 %cmp1, %cmp2
+  br i1 %and, label %end, label %taken
+
+taken:
+  call void @bar()
+  %cmp3 = icmp eq i32 %a, 0
+  br i1 %cmp3, label %if.then, label %end
+
+if.then:
+  call void @foo()
+  br label %end
+
+end:
+  ret void
+}
+
+define void @test_or1(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_or1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[OR]], label [[END:%.*]], label [[TAKEN:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp1 = icmp eq i32 %a, 0
+  %cmp2 = icmp eq i32 %b, 0
+  %or = or i1 %cmp1, %cmp2
+  br i1 %or, label %end, label %taken
+
+taken:
+  call void @bar()
+  %cmp3 = icmp ne i32 %a, 0   ;; <-- implied true
+  br i1 %cmp3, label %if.then, label %end
+
+if.then:
+  call void @foo()
+  br label %end
+
+end:
+  ret void
+}
+
+; We can't infer anything if the result of the 'or' is true
+
+define void @test_or2(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_or2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[OR]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[A]], 0
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp1 = icmp eq i32 %a, 0
+  %cmp2 = icmp eq i32 %b, 0
+  %or = or i1 %cmp1, %cmp2
+  br i1 %or, label %taken, label %end
+
+taken:
+  call void @bar()
+  %cmp3 = icmp eq i32 %a, 0
+  br i1 %cmp3, label %if.then, label %end
+
+if.then:
+  call void @foo()
+  br label %end
+
+end:
+  ret void
+}
+
+; We can recurse a tree of 'and' or 'or's.
+
+define void @test_and_recurse1(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @test_and_recurse1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMPA:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMPB:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[CMPC:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMPA]], [[CMPB]]
+; CHECK-NEXT:    [[AND2:%.*]] = and i1 [[AND1]], [[CMPC]]
+; CHECK-NEXT:    br i1 [[AND2]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmpa = icmp eq i32 %a, 0
+  %cmpb = icmp eq i32 %b, 0
+  %cmpc = icmp eq i32 %c, 0
+  %and1 = and i1 %cmpa, %cmpb
+  %and2 = and i1 %and1, %cmpc
+  br i1 %and2, label %taken, label %end
+
+taken:
+  call void @bar()
+  %cmp3 = icmp eq i32 %a, 0
+  br i1 %cmp3, label %if.then, label %end
+
+if.then:
+  call void @foo()
+  br label %end
+
+end:
+  ret void
+}
+
+; Check to make sure we don't recurse too deep.
+
+define void @test_and_recurse2(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
+; CHECK-LABEL: @test_and_recurse2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMPA:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[CMPB:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[CMPC:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    [[CMPD:%.*]] = icmp eq i32 [[D:%.*]], 0
+; CHECK-NEXT:    [[CMPE:%.*]] = icmp eq i32 [[E:%.*]], 0
+; CHECK-NEXT:    [[CMPF:%.*]] = icmp eq i32 [[F:%.*]], 0
+; CHECK-NEXT:    [[CMPG:%.*]] = icmp eq i32 [[G:%.*]], 0
+; CHECK-NEXT:    [[CMPH:%.*]] = icmp eq i32 [[H:%.*]], 0
+; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMPA]], [[CMPB]]
+; CHECK-NEXT:    [[AND2:%.*]] = and i1 [[AND1]], [[CMPC]]
+; CHECK-NEXT:    [[AND3:%.*]] = and i1 [[AND2]], [[CMPD]]
+; CHECK-NEXT:    [[AND4:%.*]] = and i1 [[AND3]], [[CMPE]]
+; CHECK-NEXT:    [[AND5:%.*]] = and i1 [[AND4]], [[CMPF]]
+; CHECK-NEXT:    [[AND6:%.*]] = and i1 [[AND5]], [[CMPG]]
+; CHECK-NEXT:    [[AND7:%.*]] = and i1 [[AND6]], [[CMPH]]
+; CHECK-NEXT:    br i1 [[AND7]], label [[TAKEN:%.*]], label [[END:%.*]]
+; CHECK:       taken:
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[A]], 0
+; CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+  i32 %g, i32 %h) {
+entry:
+  %cmpa = icmp eq i32 %a, 0
+  %cmpb = icmp eq i32 %b, 0
+  %cmpc = icmp eq i32 %c, 0
+  %cmpd = icmp eq i32 %d, 0
+  %cmpe = icmp eq i32 %e, 0
+  %cmpf = icmp eq i32 %f, 0
+  %cmpg = icmp eq i32 %g, 0
+  %cmph = icmp eq i32 %h, 0
+  %and1 = and i1 %cmpa, %cmpb
+  %and2 = and i1 %and1, %cmpc
+  %and3 = and i1 %and2, %cmpd
+  %and4 = and i1 %and3, %cmpe
+  %and5 = and i1 %and4, %cmpf
+  %and6 = and i1 %and5, %cmpg
+  %and7 = and i1 %and6, %cmph
+  br i1 %and7, label %taken, label %end
+
+taken:
+  call void @bar()
+  %cmp3 = icmp eq i32 %a, 0 ; <-- can be implied true
+  br i1 %cmp3, label %if.then, label %end
+
+if.then:
+  call void @foo()
+  br label %end
+
+end:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-false-dest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-false-dest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-false-dest.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-false-dest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,339 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+
+declare void @is(i1)
+
+; If A == B is false then A == B is implied false.
+; CHECK-LABEL: @test_eq_eq
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_eq_eq(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp eq i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A == B is false then A != B is implied true.
+; CHECK-LABEL: @test_eq_ne
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_eq_ne(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ne i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A != B is false then A != B is implied false.
+; CHECK-LABEL: @test_ne_ne
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_ne(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ne i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A != B is false then A >u B is implied false.
+; CHECK-LABEL: @test_ne_ugt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_ugt(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A != B is false then A >=u B is implied true.
+; CHECK-LABEL: @test_ne_uge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ne_uge(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp uge i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A != B is false then A <u B is implied false.
+; CHECK-LABEL: @test_ne_ult
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A != B is false then A <=u B is implied true.
+; CHECK-LABEL: @test_ne_ule
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ne_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A >u B is false then A >u B is implied false.
+; CHECK-LABEL: @test_ugt_ugt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ugt_ugt(i32 %a, i32 %b) {
+  %cmp1 = icmp ugt i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A >u B is false then A <=u B is implied true.
+; CHECK-LABEL: @test_ugt_ule
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ugt_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ugt i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A >=u B is false then A >=u B is implied false.
+; CHECK-LABEL: @test_uge_uge
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_uge_uge(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp uge i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A >=u B is false then A <u B is implied true.
+; CHECK-LABEL: @test_uge_ult
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_uge_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A >=u B is false then A <=u B is implied true.
+; CHECK-LABEL: @test_uge_ule
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_uge_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A <u B is false then A <u B is implied false.
+; CHECK-LABEL: @test_ult_ult
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ult_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp ult i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; If A <=u B is false then A <=u B is implied false.
+; CHECK-LABEL: @test_ule_ule
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ule_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ule i32 %a, %b
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-imm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-imm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-imm.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching-imm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,123 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+
+; cmp1 implies cmp2 is false
+; CHECK-LABEL: @test1
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test1(i32 %a) {
+  %cmp1 = icmp eq i32 %a, 0
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp eq i32 %a, 1
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; cmp1 implies cmp2 is false
+; CHECK-LABEL: @test2
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test2(i32 %a) {
+  %cmp1 = icmp ugt i32 %a, 5
+  br i1 %cmp1, label %untaken, label %taken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, 6
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; cmp1 implies cmp2 is false
+; CHECK-LABEL: @test3
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test3(i32 %a) {
+  %cmp1 = icmp ugt i32 %a, 1
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp eq i32 %a, 0
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; cmp1 implies cmp2 is true
+; CHECK-LABEL: @test4
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test4(i32 %a) {
+  %cmp1 = icmp sgt i32 %a, 1
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, 0
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; cmp1 implies cmp2 is true
+; CHECK-LABEL: @test5
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test5(i32 %a) {
+  %cmp1 = icmp sgt i32 %a, 5
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sgt i32 %a, -1
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+declare void @is(i1)

Added: llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/implied-cond-matching.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1029 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+
+declare void @dead()
+declare void @alive()
+declare void @is(i1)
+
+; Test same condition with swapped operands.
+; void test_swapped_ops(unsigned a, unsigned b) {
+;   if (a > b) {
+;     if (b > a) <- always false
+;       dead();
+;     alive();
+;   }
+; }
+;
+; CHECK-LABEL: @test_swapped_ops
+; CHECK-NOT: call void @dead()
+; CHECK: call void @alive()
+; CHECK: ret
+define void @test_swapped_ops(i32 %a, i32 %b) {
+entry:
+  %cmp = icmp ugt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end3
+
+if.then:
+  %cmp1 = icmp ugt i32 %b, %a
+  br i1 %cmp1, label %if.then2, label %if.end
+
+if.then2:
+  call void @dead()
+  br label %if.end
+
+if.end:
+  call void @alive()
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; void test_swapped_pred(unsigned a, unsigned b) {
+;   if (a > b) {
+;     alive();
+;     if (b < a) <- always true; remove branch
+;       alive();
+;   }
+; }
+;
+; CHECK-LABEL: @test_swapped_pred
+; CHECK: call void @alive()
+; CHECK-NEXT: call void @alive()
+; CHECK: ret
+define void @test_swapped_pred(i32 %a, i32 %b) {
+entry:
+  %cmp = icmp ugt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end3
+
+if.then:
+  call void @alive()
+  %cmp1 = icmp ult i32 %b, %a
+  br i1 %cmp1, label %if.then2, label %if.end3
+
+if.then2:
+  call void @alive()
+  br label %if.end3
+
+if.end3:
+  ret void
+}
+
+; A == B implies A == B is true.
+; CHECK-LABEL: @test_eq_eq
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_eq_eq(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp eq i32 %a, %b
+  br i1 %cmp2, label %eq_eq_istrue, label %eq_eq_isfalse
+
+eq_eq_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_eq_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A != B is false.
+; CHECK-LABEL: @test_eq_ne
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_eq_ne(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ne i32 %a, %b
+  br i1 %cmp2, label %eq_ne_istrue, label %eq_ne_isfalse
+
+eq_ne_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_ne_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A >u B is false.
+; CHECK-LABEL: @test_eq_ugt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_eq_ugt(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  br i1 %cmp2, label %eq_ugt_istrue, label %eq_ugt_isfalse
+
+eq_ugt_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_ugt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A >=u B is true.
+; CHECK-LABEL: @test_eq_uge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_eq_uge(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp uge i32 %a, %b
+  br i1 %cmp2, label %eq_uge_istrue, label %eq_uge_isfalse
+
+eq_uge_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_uge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A <u B is false.
+; CHECK-LABEL: @test_eq_ult
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_eq_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %eq_ult_istrue, label %eq_ult_isfalse
+
+eq_ult_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_ult_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A <=u B is true.
+; CHECK-LABEL: @test_eq_ule
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_eq_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %eq_ule_istrue, label %eq_ule_isfalse
+
+eq_ule_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_ule_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A >s B is false.
+; CHECK-LABEL: @test_eq_sgt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_eq_sgt(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sgt i32 %a, %b
+  br i1 %cmp2, label %eq_sgt_istrue, label %eq_sgt_isfalse
+
+eq_sgt_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_sgt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A >=s B is true.
+; CHECK-LABEL: @test_eq_sge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_eq_sge(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sge i32 %a, %b
+  br i1 %cmp2, label %eq_sge_istrue, label %eq_sge_isfalse
+
+eq_sge_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_sge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A <s B is false.
+; CHECK-LABEL: @test_eq_slt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_eq_slt(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %eq_slt_istrue, label %eq_slt_isfalse
+
+eq_slt_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_slt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A == B implies A <=s B is true.
+; CHECK-LABEL: @test_eq_sle
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_eq_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp eq i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %eq_sle_istrue, label %eq_sle_isfalse
+
+eq_sle_istrue:
+  call void @is(i1 true)
+  ret void
+
+eq_sle_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A != B is true.
+; CHECK-LABEL: @test_ne_ne
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ne_ne(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ne i32 %a, %b
+  br i1 %cmp2, label %ne_ne_istrue, label %ne_ne_isfalse
+
+ne_ne_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_ne_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A >u B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_ugt
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_ugt(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  br i1 %cmp2, label %ne_ugt_istrue, label %ne_ugt_isfalse
+
+ne_ugt_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_ugt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A >=u B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_uge
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_uge(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp uge i32 %a, %b
+  br i1 %cmp2, label %ne_uge_istrue, label %ne_uge_isfalse
+
+ne_uge_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_uge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A <u B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_ult
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %ne_ult_istrue, label %ne_ult_isfalse
+
+ne_ult_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_ult_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A <=u B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_ule
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %ne_ule_istrue, label %ne_ule_isfalse
+
+ne_ule_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_ule_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A >s B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_sgt
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_sgt(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sgt i32 %a, %b
+  br i1 %cmp2, label %ne_sgt_istrue, label %ne_sgt_isfalse
+
+ne_sgt_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_sgt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A >=s B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_sge
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_sge(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sge i32 %a, %b
+  br i1 %cmp2, label %ne_sge_istrue, label %ne_sge_isfalse
+
+ne_sge_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_sge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A <s B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_slt
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_slt(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %ne_slt_istrue, label %ne_slt_isfalse
+
+ne_slt_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_slt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A != B implies A <=s B is unknown to be true or false.
+; CHECK-LABEL: @test_ne_sle
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ne_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp ne i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %ne_sle_istrue, label %ne_sle_isfalse
+
+ne_sle_istrue:
+  call void @is(i1 true)
+  ret void
+
+ne_sle_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >u B implies A >u B is true.
+; CHECK-LABEL: @test_ugt_ugt
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ugt_ugt(i32 %a, i32 %b) {
+  %cmp1 = icmp ugt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ugt i32 %a, %b
+  br i1 %cmp2, label %ugt_ugt_istrue, label %ugt_ugt_isfalse
+
+ugt_ugt_istrue:
+  call void @is(i1 true)
+  ret void
+
+ugt_ugt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >u B implies A >=u B is true.
+; CHECK-LABEL: @test_ugt_uge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ugt_uge(i32 %a, i32 %b) {
+  %cmp1 = icmp ugt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp uge i32 %a, %b
+  br i1 %cmp2, label %ugt_uge_istrue, label %ugt_uge_isfalse
+
+ugt_uge_istrue:
+  call void @is(i1 true)
+  ret void
+
+ugt_uge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >u B implies A <u B is false.
+; CHECK-LABEL: @test_ugt_ult
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ugt_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp ugt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %ugt_ult_istrue, label %ugt_ult_isfalse
+
+ugt_ult_istrue:
+  call void @is(i1 true)
+  ret void
+
+ugt_ult_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >u B implies A <=u B is false.
+; CHECK-LABEL: @test_ugt_ule
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_ugt_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ugt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %ugt_ule_istrue, label %ugt_ule_isfalse
+
+ugt_ule_istrue:
+  call void @is(i1 true)
+  ret void
+
+ugt_ule_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=u B implies A >=u B is true.
+; CHECK-LABEL: @test_uge_uge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_uge_uge(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp uge i32 %a, %b
+  br i1 %cmp2, label %uge_uge_istrue, label %uge_uge_isfalse
+
+uge_uge_istrue:
+  call void @is(i1 true)
+  ret void
+
+uge_uge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=u B implies A <u B is false.
+; CHECK-LABEL: @test_uge_ult
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_uge_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %uge_ult_istrue, label %uge_ult_isfalse
+
+uge_ult_istrue:
+  call void @is(i1 true)
+  ret void
+
+uge_ult_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=u B implies A <=u B is unknown to be true or false.
+; CHECK-LABEL: @test_uge_ule
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_uge_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %uge_ule_istrue, label %uge_ule_isfalse
+
+uge_ule_istrue:
+  call void @is(i1 true)
+  ret void
+
+uge_ule_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A <u B implies A <u B is true.
+; CHECK-LABEL: @test_ult_ult
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ult_ult(i32 %a, i32 %b) {
+  %cmp1 = icmp ult i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ult i32 %a, %b
+  br i1 %cmp2, label %ult_ult_istrue, label %ult_ult_isfalse
+
+ult_ult_istrue:
+  call void @is(i1 true)
+  ret void
+
+ult_ult_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A <u B implies A <=u B is true.
+; CHECK-LABEL: @test_ult_ule
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ult_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ult i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %ult_ule_istrue, label %ult_ule_isfalse
+
+ult_ule_istrue:
+  call void @is(i1 true)
+  ret void
+
+ult_ule_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A <=u B implies A <=u B is true.
+; CHECK-LABEL: @test_ule_ule
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_ule_ule(i32 %a, i32 %b) {
+  %cmp1 = icmp ule i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ule i32 %a, %b
+  br i1 %cmp2, label %ule_ule_istrue, label %ule_ule_isfalse
+
+ule_ule_istrue:
+  call void @is(i1 true)
+  ret void
+
+ule_ule_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >s B implies A >s B is true.
+; CHECK-LABEL: @test_sgt_sgt
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_sgt_sgt(i32 %a, i32 %b) {
+  %cmp1 = icmp sgt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sgt i32 %a, %b
+  br i1 %cmp2, label %sgt_sgt_istrue, label %sgt_sgt_isfalse
+
+sgt_sgt_istrue:
+  call void @is(i1 true)
+  ret void
+
+sgt_sgt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >s B implies A >=s B is true.
+; CHECK-LABEL: @test_sgt_sge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_sgt_sge(i32 %a, i32 %b) {
+  %cmp1 = icmp sgt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sge i32 %a, %b
+  br i1 %cmp2, label %sgt_sge_istrue, label %sgt_sge_isfalse
+
+sgt_sge_istrue:
+  call void @is(i1 true)
+  ret void
+
+sgt_sge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >s B implies A <s B is false.
+; CHECK-LABEL: @test_sgt_slt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_sgt_slt(i32 %a, i32 %b) {
+  %cmp1 = icmp sgt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %sgt_slt_istrue, label %sgt_slt_isfalse
+
+sgt_slt_istrue:
+  call void @is(i1 true)
+  ret void
+
+sgt_slt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >s B implies A <=s B is false.
+; CHECK-LABEL: @test_sgt_sle
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_sgt_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp sgt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %sgt_sle_istrue, label %sgt_sle_isfalse
+
+sgt_sle_istrue:
+  call void @is(i1 true)
+  ret void
+
+sgt_sle_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=s B implies A >=s B is true.
+; CHECK-LABEL: @test_sge_sge
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_sge_sge(i32 %a, i32 %b) {
+  %cmp1 = icmp sge i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sge i32 %a, %b
+  br i1 %cmp2, label %sge_sge_istrue, label %sge_sge_isfalse
+
+sge_sge_istrue:
+  call void @is(i1 true)
+  ret void
+
+sge_sge_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=s B implies A <s B is false.
+; CHECK-LABEL: @test_sge_slt
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_sge_slt(i32 %a, i32 %b) {
+  %cmp1 = icmp sge i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %sge_slt_istrue, label %sge_slt_isfalse
+
+sge_slt_istrue:
+  call void @is(i1 true)
+  ret void
+
+sge_slt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=s B implies A <=s B is unknown to be true or false.
+; CHECK-LABEL: @test_sge_sle
+; CHECK: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_sge_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp sge i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %sge_sle_istrue, label %sge_sle_isfalse
+
+sge_sle_istrue:
+  call void @is(i1 true)
+  ret void
+
+sge_sle_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A <s B implies A <s B is true.
+; CHECK-LABEL: @test_slt_slt
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_slt_slt(i32 %a, i32 %b) {
+  %cmp1 = icmp slt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp slt i32 %a, %b
+  br i1 %cmp2, label %slt_slt_istrue, label %slt_slt_isfalse
+
+slt_slt_istrue:
+  call void @is(i1 true)
+  ret void
+
+slt_slt_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A <s B implies A <=s B is true.
+; CHECK-LABEL: @test_slt_sle
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_slt_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp slt i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %slt_sle_istrue, label %slt_sle_isfalse
+
+slt_sle_istrue:
+  call void @is(i1 true)
+  ret void
+
+slt_sle_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A <=s B implies A <=s B is true.
+; CHECK-LABEL: @test_sle_sle
+; CHECK: call void @is(i1 true)
+; CHECK-NOT: call void @is(i1 false)
+define void @test_sle_sle(i32 %a, i32 %b) {
+  %cmp1 = icmp sle i32 %a, %b
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp sle i32 %a, %b
+  br i1 %cmp2, label %sle_sle_istrue, label %sle_sle_isfalse
+
+sle_sle_istrue:
+  call void @is(i1 true)
+  ret void
+
+sle_sle_isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}
+
+; A >=u 5 implies A <u 5 is false.
+; CHECK-LABEL: @test_uge_ult_const
+; CHECK-NOT: call void @is(i1 true)
+; CHECK: call void @is(i1 false)
+define void @test_uge_ult_const(i32 %a, i32 %b) {
+  %cmp1 = icmp uge i32 %a, 5
+  br i1 %cmp1, label %taken, label %untaken
+
+taken:
+  %cmp2 = icmp ult i32 %a, 5
+  br i1 %cmp2, label %istrue, label %isfalse
+
+istrue:
+  call void @is(i1 true)
+  ret void
+
+isfalse:
+  call void @is(i1 false)
+  ret void
+
+untaken:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/implied-cond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/implied-cond.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/implied-cond.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/implied-cond.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+; Check for when one branch implies the value of a successors conditional and
+; it's not simply the same conditional repeated.
+
+define void @test(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test
+  %iplus1 = add nsw i32 %i, 1
+  %var29 = icmp slt i32 %iplus1, %length.i
+; CHECK: br i1 %var29, label %in_bounds, label %out_of_bounds
+  br i1 %var29, label %next, label %out_of_bounds
+
+next:
+; CHECK-LABEL: in_bounds:
+; CHECK-NEXT: ret void
+  %var30 = icmp slt i32 %i, %length.i
+  br i1 %var30, label %in_bounds, label %out_of_bounds2
+
+in_bounds:
+  ret void
+
+out_of_bounds:
+  call void @foo(i64 0)
+  unreachable
+
+out_of_bounds2:
+  call void @foo(i64 1)
+  unreachable
+}
+
+; If the add is not nsw, it's not safe to use the fact about i+1 to imply the
+; i condition since it could have overflowed.
+define void @test_neg(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test_neg
+  %iplus1 = add i32 %i, 1
+  %var29 = icmp slt i32 %iplus1, %length.i
+; CHECK: br i1 %var29, label %next, label %out_of_bounds
+  br i1 %var29, label %next, label %out_of_bounds
+
+next:
+  %var30 = icmp slt i32 %i, %length.i
+; CHECK: br i1 %var30, label %in_bounds, label %out_of_bounds2
+  br i1 %var30, label %in_bounds, label %out_of_bounds2
+
+in_bounds:
+  ret void
+
+out_of_bounds:
+  call void @foo(i64 0)
+  unreachable
+
+out_of_bounds2:
+  call void @foo(i64 1)
+  unreachable
+}
+
+
+define void @test2(i32 %length.i, i32 %i) {
+; CHECK-LABEL: @test2
+  %iplus100 = add nsw i32 %i, 100
+  %var29 = icmp slt i32 %iplus100, %length.i
+; CHECK: br i1 %var29, label %in_bounds, label %out_of_bounds
+  br i1 %var29, label %next, label %out_of_bounds
+
+next:
+  %var30 = icmp slt i32 %i, %length.i
+  br i1 %var30, label %in_bounds, label %out_of_bounds2
+
+in_bounds:
+  ret void
+
+out_of_bounds:
+  call void @foo(i64 0)
+  unreachable
+
+out_of_bounds2:
+  call void @foo(i64 1)
+  unreachable
+}
+
+declare void @foo(i64)
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/indirectbr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/indirectbr.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/indirectbr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,251 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+; SimplifyCFG should eliminate redundant indirectbr edges.
+
+; CHECK: indbrtest0
+; CHECK: indirectbr i8* %t, [label %BB0, label %BB1, label %BB2]
+; CHECK: %x = phi i32 [ 0, %BB0 ], [ 1, %entry ]
+
+declare void @foo()
+declare void @A()
+declare void @B(i32)
+declare void @C()
+
+define void @indbrtest0(i8** %P, i8** %Q) {
+entry:
+  store i8* blockaddress(@indbrtest0, %BB0), i8** %P
+  store i8* blockaddress(@indbrtest0, %BB1), i8** %P
+  store i8* blockaddress(@indbrtest0, %BB2), i8** %P
+  call void @foo()
+  %t = load i8*, i8** %Q
+  indirectbr i8* %t, [label %BB0, label %BB1, label %BB2, label %BB0, label %BB1, label %BB2]
+BB0:
+  call void @A()
+  br label %BB1
+BB1:
+  %x = phi i32 [ 0, %BB0 ], [ 1, %entry ], [ 1, %entry ]
+  call void @B(i32 %x)
+  ret void
+BB2:
+  call void @C()
+  ret void
+}
+
+; SimplifyCFG should convert the indirectbr into a directbr. It would be even
+; better if it removed the branch altogether, but simplifycfdg currently misses
+; that because the predecessor is the entry block.
+
+; CHECK: indbrtest1
+; CHECK: br label %BB0
+
+define void @indbrtest1(i8** %P, i8** %Q) {
+entry:
+  store i8* blockaddress(@indbrtest1, %BB0), i8** %P
+  call void @foo()
+  %t = load i8*, i8** %Q
+  indirectbr i8* %t, [label %BB0, label %BB0]
+BB0:
+  call void @A()
+  ret void
+}
+
+; SimplifyCFG should notice that BB0 does not have its address taken and
+; remove it from entry's successor list.
+
+; CHECK: indbrtest2
+; CHECK: entry:
+; CHECK-NEXT: unreachable
+
+define void @indbrtest2(i8* %t) {
+entry:
+  indirectbr i8* %t, [label %BB0, label %BB0]
+BB0:
+  ret void
+}
+
+
+; Make sure the blocks in the next few tests aren't trivially removable as
+; successors by taking their addresses.
+
+ at anchor = constant [13 x i8*] [
+  i8* blockaddress(@indbrtest3, %L1), i8* blockaddress(@indbrtest3, %L2), i8* blockaddress(@indbrtest3, %L3),
+  i8* blockaddress(@indbrtest4, %L1), i8* blockaddress(@indbrtest4, %L2), i8* blockaddress(@indbrtest4, %L3),
+  i8* blockaddress(@indbrtest5, %L1), i8* blockaddress(@indbrtest5, %L2), i8* blockaddress(@indbrtest5, %L3), i8* blockaddress(@indbrtest5, %L4),
+  i8* blockaddress(@indbrtest6, %L1), i8* blockaddress(@indbrtest6, %L2), i8* blockaddress(@indbrtest6, %L3)
+]
+
+; SimplifyCFG should turn the indirectbr into a conditional branch on the
+; condition of the select.
+
+; CHECK-LABEL: @indbrtest3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 %cond, label %L1, label %L2
+; CHECK-NOT: indirectbr
+; CHECK-NOT: br
+; CHECK-NOT: L3:
+define void @indbrtest3(i1 %cond, i8* %address) nounwind {
+entry:
+  %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest3, %L1), i8* blockaddress(@indbrtest3, %L2)
+  indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
+
+L1:
+  call void @A()
+  ret void
+L2:
+  call void @C()
+  ret void
+L3:
+  call void @foo()
+  ret void
+}
+
+; SimplifyCFG should turn the indirectbr into an unconditional branch to the
+; only possible destination.
+; As in @indbrtest1, it should really remove the branch entirely, but it doesn't
+; because it's in the entry block.
+
+; CHECK-LABEL: @indbrtest4(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label %L1
+define void @indbrtest4(i1 %cond) nounwind {
+entry:
+  %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest4, %L1), i8* blockaddress(@indbrtest4, %L1)
+  indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
+
+L1:
+  call void @A()
+  ret void
+L2:
+  call void @C()
+  ret void
+L3:
+  call void @foo()
+  ret void
+}
+
+; SimplifyCFG should turn the indirectbr into an unreachable because neither
+; destination is listed as a successor.
+
+; CHECK-LABEL: @indbrtest5(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: unreachable
+; CHECK-NEXT: }
+define void @indbrtest5(i1 %cond, i8* %anchor) nounwind {
+entry:
+  %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest5, %L1), i8* blockaddress(@indbrtest5, %L2)
+; This needs to have more than one successor for this test, otherwise it gets
+; replaced with an unconditional branch to the single successor.
+  indirectbr i8* %indirect.goto.dest, [label %L3, label %L4]
+
+L1:
+  call void @A()
+  ret void
+L2:
+  call void @C()
+  ret void
+L3:
+  call void @foo()
+  ret void
+L4:
+  call void @foo()
+
+; This keeps blockaddresses not otherwise listed as successors from being zapped
+; before SimplifyCFG even looks at the indirectbr.
+  indirectbr i8* %anchor, [label %L1, label %L2]
+}
+
+; The same as above, except the selected addresses are equal.
+
+; CHECK-LABEL: @indbrtest6(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: unreachable
+; CHECK-NEXT: }
+define void @indbrtest6(i1 %cond, i8* %anchor) nounwind {
+entry:
+  %indirect.goto.dest = select i1 %cond, i8* blockaddress(@indbrtest6, %L1), i8* blockaddress(@indbrtest6, %L1)
+; This needs to have more than one successor for this test, otherwise it gets
+; replaced with an unconditional branch to the single successor.
+  indirectbr i8* %indirect.goto.dest, [label %L2, label %L3]
+
+L1:
+  call void @A()
+  ret void
+L2:
+  call void @C()
+  ret void
+L3:
+  call void @foo()
+
+; This keeps blockaddresses not otherwise listed as successors from being zapped
+; before SimplifyCFG even looks at the indirectbr.
+  indirectbr i8* %anchor, [label %L1, label %L2]
+}
+
+; PR10072
+
+ at xblkx.bbs = internal unnamed_addr constant [9 x i8*] [i8* blockaddress(@indbrtest7, %xblkx.begin), i8* blockaddress(@indbrtest7, %xblkx.begin3), i8* blockaddress(@indbrtest7, %xblkx.begin4), i8* blockaddress(@indbrtest7, %xblkx.begin5), i8* blockaddress(@indbrtest7, %xblkx.begin6), i8* blockaddress(@indbrtest7, %xblkx.begin7), i8* blockaddress(@indbrtest7, %xblkx.begin8), i8* blockaddress(@indbrtest7, %xblkx.begin9), i8* blockaddress(@indbrtest7, %xblkx.end)]
+
+define void @indbrtest7() {
+escape-string.top:
+  %xval202x = call i32 @xfunc5x()
+  br label %xlab5x
+
+xlab8x:                                           ; preds = %xlab5x
+  %xvaluex = call i32 @xselectorx()
+  %xblkx.x = getelementptr [9 x i8*], [9 x i8*]* @xblkx.bbs, i32 0, i32 %xvaluex
+  %xblkx.load = load i8*, i8** %xblkx.x
+  indirectbr i8* %xblkx.load, [label %xblkx.begin, label %xblkx.begin3, label %xblkx.begin4, label %xblkx.begin5, label %xblkx.begin6, label %xblkx.begin7, label %xblkx.begin8, label %xblkx.begin9, label %xblkx.end]
+
+xblkx.begin:
+  br label %xblkx.end
+
+xblkx.begin3:
+  br label %xblkx.end
+
+xblkx.begin4:
+  br label %xblkx.end
+
+xblkx.begin5:
+  br label %xblkx.end
+
+xblkx.begin6:
+  br label %xblkx.end
+
+xblkx.begin7:
+  br label %xblkx.end
+
+xblkx.begin8:
+  br label %xblkx.end
+
+xblkx.begin9:
+  br label %xblkx.end
+
+xblkx.end:
+  %yes.0 = phi i1 [ false, %xblkx.begin ], [ true, %xlab8x ], [ false, %xblkx.begin9 ], [ false, %xblkx.begin8 ], [ false, %xblkx.begin7 ], [ false, %xblkx.begin6 ], [ false, %xblkx.begin5 ], [ true, %xblkx.begin4 ], [ false, %xblkx.begin3 ]
+  br i1 %yes.0, label %v2j, label %xlab17x
+
+v2j:
+; CHECK: %xunusedx = call i32 @xactionx()
+  %xunusedx = call i32 @xactionx()
+  br label %xlab4x
+
+xlab17x:
+  br label %xlab4x
+
+xlab4x:
+  %incr19 = add i32 %xval704x.0, 1
+  br label %xlab5x
+
+xlab5x:
+  %xval704x.0 = phi i32 [ 0, %escape-string.top ], [ %incr19, %xlab4x ]
+  %xval10x = icmp ult i32 %xval704x.0, %xval202x
+  br i1 %xval10x, label %xlab8x, label %xlab9x
+
+xlab9x:
+  ret void
+}
+
+declare i32 @xfunc5x()
+declare i8 @xfunc7x()
+declare i32 @xselectorx()
+declare i32 @xactionx()

Added: llvm/trunk/test/Transforms/SimplifyCFG/inline-asm-sink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/inline-asm-sink.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/inline-asm-sink.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/inline-asm-sink.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -mem2reg -simplifycfg -S | FileCheck -enable-var-scope %s
+
+define i32 @test(i32 %x) {
+; CHECK-LABEL: @test
+entry:
+  %y = alloca i32, align 4
+  %tobool = icmp ne i32 %x, 0
+  br i1 %tobool, label %if.then, label %if.else
+
+if.then:
+; CHECK: if.then:
+; CHECK: [[ASM1:%.*]] = call i32 asm "mov $0, #1", "=r"()
+  %tmp1 = call i32 asm "mov $0, #1", "=r"() nounwind readnone
+  store i32 %tmp1, i32* %y, align 4
+  br label %if.end
+
+if.else:
+; CHECK: if.else:
+; CHECK: [[ASM2:%.*]] = call i32 asm "mov $0, #2", "=r"()
+  %tmp2 = call i32 asm "mov $0, #2", "=r"() nounwind readnone
+  store i32 %tmp2, i32* %y, align 4
+  br label %if.end
+
+if.end:
+; CHECK: if.end:
+; CHECK: {{%.*}} = phi i32 [ [[ASM1]], %if.then ], [ [[ASM2]], %if.else ]
+  %tmp3 = load i32, i32* %y, align 4
+  ret i32 %tmp3
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,162 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_call_unexpected(i8*)
+declare void @purefn() nounwind readnone
+declare i32 @read_only() nounwind readonly
+declare i32 @nounwind_fn() nounwind
+declare i32 @fn()
+
+
+; CHECK-LABEL: @f1(
+define i8* @f1() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+; CHECK: call void @llvm.trap()
+; CHECK: unreachable
+  %call = invoke noalias i8* undef()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  ret i8* %call
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+  unreachable
+}
+
+; CHECK-LABEL: @f2(
+define i8* @f2() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+; CHECK: call void @llvm.trap()
+; CHECK: unreachable
+  %call = invoke noalias i8* null()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  ret i8* %call
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+  unreachable
+}
+
+; CHECK-LABEL: @f2_no_null_opt(
+define i8* @f2_no_null_opt() nounwind uwtable ssp #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+; CHECK: invoke noalias i8* null()
+  %call = invoke noalias i8* null()
+          to label %invoke.cont unwind label %lpad
+
+; CHECK: invoke.cont:
+; CHECK: ret i8* %call
+invoke.cont:
+  ret i8* %call
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+; CHECK: unreachable
+  unreachable
+}
+
+; CHECK-LABEL: @f3(
+define i32 @f3() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-NEXT: entry
+entry:
+; CHECK-NEXT: ret i32 3
+  %call = invoke i32 @read_only()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  ret i32 3
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+  unreachable
+}
+
+; CHECK-LABEL: @f4(
+define i32 @f4() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-NEXT: entry
+entry:
+; CHECK-NEXT: call i32 @read_only()
+  %call = invoke i32 @read_only()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+; CHECK-NEXT: ret i32 %call
+  ret i32 %call
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+  %1 = extractvalue { i8*, i32 } %0, 0
+  tail call void @__cxa_call_unexpected(i8* %1) noreturn nounwind
+  unreachable
+}
+
+; CHECK-LABEL: @f5(
+define i32 @f5(i1 %cond, i8* %a, i8* %b) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  br i1 %cond, label %x, label %y
+
+x:
+; CHECK: invoke i32 @fn()
+  %call = invoke i32 @fn()
+          to label %cont unwind label %lpad
+
+y:
+; CHECK: call i32 @nounwind_fn()
+  %call2 = invoke i32 @nounwind_fn()
+           to label %cont unwind label %lpad
+
+cont:
+; CHECK: phi i32
+; CHECK: ret i32 %phi
+  %phi = phi i32 [%call, %x], [%call2, %y]
+  ret i32 %phi
+
+lpad:
+; CHECK-NOT: phi
+  %phi2 = phi i8* [%a, %x], [%b, %y]
+  %0 = landingpad { i8*, i32 }
+          filter [0 x i8*] zeroinitializer
+; CHECK: __cxa_call_unexpected(i8* %a)
+  tail call void @__cxa_call_unexpected(i8* %phi2) noreturn nounwind
+  unreachable
+}
+
+; CHECK-LABEL: @f6(
+define void @f6() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  invoke void @purefn()
+          to label %invoke.cont1 unwind label %lpad
+
+invoke.cont1:
+  %foo = invoke i32 @fn()
+          to label %invoke.cont2 unwind label %lpad
+
+invoke.cont2:
+  ret void
+
+lpad:
+; CHECK-NOT: phi
+  %tmp = phi i8* [ null, %invoke.cont1 ], [ null, %entry ]
+  landingpad { i8*, i32 }
+          cleanup
+  ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/invoke_unwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @bar()
+
+; This testcase checks to see if the simplifycfg pass is converting invoke
+; instructions to call instructions if the handler just rethrows the exception.
+define i32 @test1() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: ret i32 0
+        invoke void @bar( )
+                        to label %1 unwind label %Rethrow
+        ret i32 0
+Rethrow:
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+        resume { i8*, i32 } %exn
+}
+
+define i32 @test2() personality i32 (...)* @__gxx_personality_v0 {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: call void @bar() [ "foo"(i32 100) ]
+; CHECK-NEXT: ret i32 0
+        invoke void @bar( ) [ "foo"(i32 100) ]
+                        to label %1 unwind label %Rethrow
+        ret i32 0
+Rethrow:
+        %exn = landingpad {i8*, i32}
+                 catch i8* null
+        resume { i8*, i32 } %exn
+}
+
+declare i64 @dummy1()
+declare i64 @dummy2()
+
+; This testcase checks to see if simplifycfg pass can convert two invoke 
+; instructions to call instructions if they share a common trivial unwind
+; block.
+define i64 @test3(i1 %cond) personality i32 (...)* @__gxx_personality_v0 {
+entry:
+; CHECK-LABEL: @test3(
+; CHECK: %call1 = call i64 @dummy1()
+; CHECK: %call2 = call i64 @dummy2()
+; CHECK-NOT: resume { i8*, i32 } %lp
+  br i1 %cond, label %br1, label %br2
+
+br1:
+  %call1 = invoke i64 @dummy1()
+          to label %invoke.cont unwind label %lpad1
+          
+br2: 
+  %call2 = invoke i64 @dummy2()
+          to label %invoke.cont unwind label %lpad2
+          
+invoke.cont:
+  %c = phi i64 [%call1, %br1], [%call2, %br2]
+  ret i64 %c 
+  
+  
+lpad1:
+  %0 = landingpad { i8*, i32 }
+          cleanup
+  br label %rethrow 
+
+rethrow:
+  %lp = phi { i8*, i32 } [%0, %lpad1], [%1, %lpad2]
+  resume { i8*, i32 } %lp
+  
+lpad2:
+  %1 = landingpad { i8*, i32 }
+          cleanup
+  br label %rethrow
+}
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/SimplifyCFG/iterative-simplify.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/iterative-simplify.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/iterative-simplify.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/iterative-simplify.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; RUN: opt < %s -simplifycfg -S | not grep bb17
+; PR1786
+
+define i32 @main() {
+entry:
+	%retval = alloca i32, align 4		; <i32*> [#uses=1]
+	%i = alloca i32, align 4		; <i32*> [#uses=7]
+	%z = alloca i32, align 4		; <i32*> [#uses=4]
+	%z16 = alloca i32, align 4		; <i32*> [#uses=4]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	store i32 0, i32* %i
+	%toBool = icmp ne i8 1, 0		; <i1> [#uses=1]
+	br i1 %toBool, label %cond_true, label %cond_false
+
+cond_true:		; preds = %entry
+	store i32 0, i32* %z
+	br label %bb
+
+bb:		; preds = %cond_next, %cond_true
+	%tmp = load i32, i32* %z		; <i32> [#uses=1]
+	%tmp1 = sub i32 %tmp, 16384		; <i32> [#uses=1]
+	store i32 %tmp1, i32* %z
+	%tmp2 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp3 = add i32 %tmp2, 1		; <i32> [#uses=1]
+	store i32 %tmp3, i32* %i
+	%tmp4 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp5 = icmp sgt i32 %tmp4, 262144		; <i1> [#uses=1]
+	%tmp56 = zext i1 %tmp5 to i8		; <i8> [#uses=1]
+	%toBool7 = icmp ne i8 %tmp56, 0		; <i1> [#uses=1]
+	br i1 %toBool7, label %cond_true8, label %cond_next
+
+cond_true8:		; preds = %bb
+	call void @abort( )
+	unreachable
+
+cond_next:		; preds = %bb
+	%tmp9 = load i32, i32* %z		; <i32> [#uses=1]
+	%tmp10 = icmp ne i32 %tmp9, 0		; <i1> [#uses=1]
+	%tmp1011 = zext i1 %tmp10 to i8		; <i8> [#uses=1]
+	%toBool12 = icmp ne i8 %tmp1011, 0		; <i1> [#uses=1]
+	br i1 %toBool12, label %bb, label %bb13
+
+bb13:		; preds = %cond_next
+	call void @exit( i32 0 )
+	unreachable
+
+cond_false:		; preds = %entry
+	%toBool14 = icmp ne i8 1, 0		; <i1> [#uses=1]
+	br i1 %toBool14, label %cond_true15, label %cond_false33
+
+cond_true15:		; preds = %cond_false
+	store i32 0, i32* %z16
+	br label %bb17
+
+bb17:		; preds = %cond_next27, %cond_true15
+	%tmp18 = load i32, i32* %z16		; <i32> [#uses=1]
+	%tmp19 = sub i32 %tmp18, 16384		; <i32> [#uses=1]
+	store i32 %tmp19, i32* %z16
+	%tmp20 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp21 = add i32 %tmp20, 1		; <i32> [#uses=1]
+	store i32 %tmp21, i32* %i
+	%tmp22 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp23 = icmp sgt i32 %tmp22, 262144		; <i1> [#uses=1]
+	%tmp2324 = zext i1 %tmp23 to i8		; <i8> [#uses=1]
+	%toBool25 = icmp ne i8 %tmp2324, 0		; <i1> [#uses=1]
+	br i1 %toBool25, label %cond_true26, label %cond_next27
+
+cond_true26:		; preds = %bb17
+	call void @abort( )
+	unreachable
+
+cond_next27:		; preds = %bb17
+	%tmp28 = load i32, i32* %z16		; <i32> [#uses=1]
+	%tmp29 = icmp ne i32 %tmp28, 0		; <i1> [#uses=1]
+	%tmp2930 = zext i1 %tmp29 to i8		; <i8> [#uses=1]
+	%toBool31 = icmp ne i8 %tmp2930, 0		; <i1> [#uses=1]
+	br i1 %toBool31, label %bb17, label %bb32
+
+bb32:		; preds = %cond_next27
+	call void @exit( i32 0 )
+	unreachable
+
+cond_false33:		; preds = %cond_false
+	call void @exit( i32 0 )
+	unreachable
+
+cond_next34:		; No predecessors!
+	br label %cond_next35
+
+cond_next35:		; preds = %cond_next34
+	br label %return
+
+return:		; preds = %cond_next35
+	%retval36 = load i32, i32* %retval		; <i32> [#uses=1]
+	ret i32 %retval36
+}
+
+declare void @abort()
+
+declare void @exit(i32)

Added: llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Test that a lifetime intrinsic isn't removed because that would change semantics
+
+; CHECK: foo
+; CHECK: entry:
+; CHECK: bb0:
+; CHECK: bb1:
+; CHECK: ret
+define void @foo(i1 %x) {
+entry:
+  %a = alloca i8
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) nounwind
+  br i1 %x, label %bb0, label %bb1
+
+bb0:
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %a) nounwind
+  br label %bb1
+
+bb1:
+  call void @f()
+  ret void
+}
+
+declare void @f()
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
+
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind

Added: llvm/trunk/test/Transforms/SimplifyCFG/merge-cleanuppads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/merge-cleanuppads.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/merge-cleanuppads.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/merge-cleanuppads.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+; Function Attrs: uwtable
+define void @test1() #0 personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @may_throw(i32 3)
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  tail call void @may_throw(i32 2) #2
+  tail call void @may_throw(i32 1) #2
+  ret void
+
+ehcleanup:                                        ; preds = %entry
+  %cp = cleanuppad within none []
+  tail call void @may_throw(i32 2) #2 [ "funclet"(token %cp) ]
+  cleanupret from %cp unwind label %ehcleanup2
+
+ehcleanup2:
+  %cp2 = cleanuppad within none []
+  tail call void @may_throw(i32 1) #2 [ "funclet"(token %cp2) ]
+  cleanupret from %cp2 unwind to caller
+}
+
+; CHECK-LABEL: define void @test1(
+; CHECK: %[[cp:.*]] = cleanuppad within none []
+; CHECK: tail call void @may_throw(i32 2) #2 [ "funclet"(token %[[cp]]) ]
+; CHECK: tail call void @may_throw(i32 1) #2 [ "funclet"(token %[[cp]]) ]
+; CHECK: cleanupret from %[[cp]] unwind to caller
+
+declare void @may_throw(i32) #1
+
+declare i32 @__CxxFrameHandler3(...)
+
+attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }

Added: llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores-2.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,321 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S < %s -simplifycfg -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=1 | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+target triple = "armv7--linux-gnueabihf"
+
+; This is a bit reversal that has been run through the early optimizer (-mem2reg -gvn -instcombine).
+; There should be no additional PHIs created at all. The store should be on its own in a predicated
+; block and there should be no PHIs.
+
+define i32 @f(i32* %b) {
+; CHECK-LABEL: @f(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[B:%.*]], align 4
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[TMP0]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[TMP0]], -2147483648
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[TOBOOL]], i32 [[TMP0]], i32 [[OR]]
+; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[TMP1]], 2
+; CHECK-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[AND1]], 0
+; CHECK-NEXT:    [[OR4:%.*]] = or i32 [[TMP1]], 1073741824
+; CHECK-NEXT:    [[DOTOR4:%.*]] = select i1 [[TOBOOL2]], i32 [[TMP1]], i32 [[OR4]]
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i1 [[TOBOOL]], true
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[TOBOOL2]], true
+; CHECK-NEXT:    [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    [[AND6:%.*]] = and i32 [[DOTOR4]], 4
+; CHECK-NEXT:    [[TOBOOL7:%.*]] = icmp eq i32 [[AND6]], 0
+; CHECK-NEXT:    [[OR9:%.*]] = or i32 [[DOTOR4]], 536870912
+; CHECK-NEXT:    [[DOTOR4_OR9:%.*]] = select i1 [[TOBOOL7]], i32 [[DOTOR4]], i32 [[OR9]]
+; CHECK-NEXT:    [[TMP5:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL7]], true
+; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TMP5]], true
+; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP7]], [[TMP6]]
+; CHECK-NEXT:    [[AND11:%.*]] = and i32 [[DOTOR4_OR9]], 8
+; CHECK-NEXT:    [[TOBOOL12:%.*]] = icmp eq i32 [[AND11]], 0
+; CHECK-NEXT:    [[OR14:%.*]] = or i32 [[DOTOR4_OR9]], 268435456
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14:%.*]] = select i1 [[TOBOOL12]], i32 [[DOTOR4_OR9]], i32 [[OR14]]
+; CHECK-NEXT:    [[TMP9:%.*]] = xor i1 [[TMP8]], true
+; CHECK-NEXT:    [[TMP10:%.*]] = xor i1 [[TOBOOL12]], true
+; CHECK-NEXT:    [[TMP11:%.*]] = xor i1 [[TMP9]], true
+; CHECK-NEXT:    [[TMP12:%.*]] = or i1 [[TMP11]], [[TMP10]]
+; CHECK-NEXT:    [[AND16:%.*]] = and i32 [[DOTOR4_OR9_OR14]], 16
+; CHECK-NEXT:    [[TOBOOL17:%.*]] = icmp eq i32 [[AND16]], 0
+; CHECK-NEXT:    [[OR19:%.*]] = or i32 [[DOTOR4_OR9_OR14]], 134217728
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19:%.*]] = select i1 [[TOBOOL17]], i32 [[DOTOR4_OR9_OR14]], i32 [[OR19]]
+; CHECK-NEXT:    [[TMP13:%.*]] = xor i1 [[TMP12]], true
+; CHECK-NEXT:    [[TMP14:%.*]] = xor i1 [[TOBOOL17]], true
+; CHECK-NEXT:    [[TMP15:%.*]] = xor i1 [[TMP13]], true
+; CHECK-NEXT:    [[TMP16:%.*]] = or i1 [[TMP15]], [[TMP14]]
+; CHECK-NEXT:    [[AND21:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19]], 32
+; CHECK-NEXT:    [[TOBOOL22:%.*]] = icmp eq i32 [[AND21]], 0
+; CHECK-NEXT:    [[OR24:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19]], 67108864
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24:%.*]] = select i1 [[TOBOOL22]], i32 [[DOTOR4_OR9_OR14_OR19]], i32 [[OR24]]
+; CHECK-NEXT:    [[TMP17:%.*]] = xor i1 [[TMP16]], true
+; CHECK-NEXT:    [[TMP18:%.*]] = xor i1 [[TOBOOL22]], true
+; CHECK-NEXT:    [[TMP19:%.*]] = xor i1 [[TMP17]], true
+; CHECK-NEXT:    [[TMP20:%.*]] = or i1 [[TMP19]], [[TMP18]]
+; CHECK-NEXT:    [[AND26:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24]], 64
+; CHECK-NEXT:    [[TOBOOL27:%.*]] = icmp eq i32 [[AND26]], 0
+; CHECK-NEXT:    [[OR29:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24]], 33554432
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29:%.*]] = select i1 [[TOBOOL27]], i32 [[DOTOR4_OR9_OR14_OR19_OR24]], i32 [[OR29]]
+; CHECK-NEXT:    [[TMP21:%.*]] = xor i1 [[TMP20]], true
+; CHECK-NEXT:    [[TMP22:%.*]] = xor i1 [[TOBOOL27]], true
+; CHECK-NEXT:    [[TMP23:%.*]] = xor i1 [[TMP21]], true
+; CHECK-NEXT:    [[TMP24:%.*]] = or i1 [[TMP23]], [[TMP22]]
+; CHECK-NEXT:    [[AND31:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29]], 256
+; CHECK-NEXT:    [[TOBOOL32:%.*]] = icmp eq i32 [[AND31]], 0
+; CHECK-NEXT:    [[OR34:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29]], 8388608
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34:%.*]] = select i1 [[TOBOOL32]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29]], i32 [[OR34]]
+; CHECK-NEXT:    [[TMP25:%.*]] = xor i1 [[TMP24]], true
+; CHECK-NEXT:    [[TMP26:%.*]] = xor i1 [[TOBOOL32]], true
+; CHECK-NEXT:    [[TMP27:%.*]] = xor i1 [[TMP25]], true
+; CHECK-NEXT:    [[TMP28:%.*]] = or i1 [[TMP27]], [[TMP26]]
+; CHECK-NEXT:    [[AND36:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34]], 512
+; CHECK-NEXT:    [[TOBOOL37:%.*]] = icmp eq i32 [[AND36]], 0
+; CHECK-NEXT:    [[OR39:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34]], 4194304
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39:%.*]] = select i1 [[TOBOOL37]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34]], i32 [[OR39]]
+; CHECK-NEXT:    [[TMP29:%.*]] = xor i1 [[TMP28]], true
+; CHECK-NEXT:    [[TMP30:%.*]] = xor i1 [[TOBOOL37]], true
+; CHECK-NEXT:    [[TMP31:%.*]] = xor i1 [[TMP29]], true
+; CHECK-NEXT:    [[TMP32:%.*]] = or i1 [[TMP31]], [[TMP30]]
+; CHECK-NEXT:    [[AND41:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39]], 1024
+; CHECK-NEXT:    [[TOBOOL42:%.*]] = icmp eq i32 [[AND41]], 0
+; CHECK-NEXT:    [[OR44:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39]], 2097152
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44:%.*]] = select i1 [[TOBOOL42]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39]], i32 [[OR44]]
+; CHECK-NEXT:    [[TMP33:%.*]] = xor i1 [[TMP32]], true
+; CHECK-NEXT:    [[TMP34:%.*]] = xor i1 [[TOBOOL42]], true
+; CHECK-NEXT:    [[TMP35:%.*]] = xor i1 [[TMP33]], true
+; CHECK-NEXT:    [[TMP36:%.*]] = or i1 [[TMP35]], [[TMP34]]
+; CHECK-NEXT:    [[AND46:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44]], 2048
+; CHECK-NEXT:    [[TOBOOL47:%.*]] = icmp eq i32 [[AND46]], 0
+; CHECK-NEXT:    [[OR49:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44]], 1048576
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49:%.*]] = select i1 [[TOBOOL47]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44]], i32 [[OR49]]
+; CHECK-NEXT:    [[TMP37:%.*]] = xor i1 [[TMP36]], true
+; CHECK-NEXT:    [[TMP38:%.*]] = xor i1 [[TOBOOL47]], true
+; CHECK-NEXT:    [[TMP39:%.*]] = xor i1 [[TMP37]], true
+; CHECK-NEXT:    [[TMP40:%.*]] = or i1 [[TMP39]], [[TMP38]]
+; CHECK-NEXT:    [[AND51:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49]], 4096
+; CHECK-NEXT:    [[TOBOOL52:%.*]] = icmp eq i32 [[AND51]], 0
+; CHECK-NEXT:    [[OR54:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49]], 524288
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54:%.*]] = select i1 [[TOBOOL52]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49]], i32 [[OR54]]
+; CHECK-NEXT:    [[TMP41:%.*]] = xor i1 [[TMP40]], true
+; CHECK-NEXT:    [[TMP42:%.*]] = xor i1 [[TOBOOL52]], true
+; CHECK-NEXT:    [[TMP43:%.*]] = xor i1 [[TMP41]], true
+; CHECK-NEXT:    [[TMP44:%.*]] = or i1 [[TMP43]], [[TMP42]]
+; CHECK-NEXT:    [[AND56:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54]], 8192
+; CHECK-NEXT:    [[TOBOOL57:%.*]] = icmp eq i32 [[AND56]], 0
+; CHECK-NEXT:    [[OR59:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54]], 262144
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59:%.*]] = select i1 [[TOBOOL57]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54]], i32 [[OR59]]
+; CHECK-NEXT:    [[TMP45:%.*]] = xor i1 [[TMP44]], true
+; CHECK-NEXT:    [[TMP46:%.*]] = xor i1 [[TOBOOL57]], true
+; CHECK-NEXT:    [[TMP47:%.*]] = xor i1 [[TMP45]], true
+; CHECK-NEXT:    [[TMP48:%.*]] = or i1 [[TMP47]], [[TMP46]]
+; CHECK-NEXT:    [[AND61:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59]], 16384
+; CHECK-NEXT:    [[TOBOOL62:%.*]] = icmp eq i32 [[AND61]], 0
+; CHECK-NEXT:    [[OR64:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59]], 131072
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64:%.*]] = select i1 [[TOBOOL62]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59]], i32 [[OR64]]
+; CHECK-NEXT:    [[TMP49:%.*]] = xor i1 [[TMP48]], true
+; CHECK-NEXT:    [[TMP50:%.*]] = xor i1 [[TOBOOL62]], true
+; CHECK-NEXT:    [[TMP51:%.*]] = xor i1 [[TMP49]], true
+; CHECK-NEXT:    [[TMP52:%.*]] = or i1 [[TMP51]], [[TMP50]]
+; CHECK-NEXT:    [[AND66:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64]], 32768
+; CHECK-NEXT:    [[TOBOOL67:%.*]] = icmp eq i32 [[AND66]], 0
+; CHECK-NEXT:    [[OR69:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64]], 65536
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64_OR69:%.*]] = select i1 [[TOBOOL67]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64]], i32 [[OR69]]
+; CHECK-NEXT:    [[TMP53:%.*]] = xor i1 [[TMP52]], true
+; CHECK-NEXT:    [[TMP54:%.*]] = xor i1 [[TOBOOL67]], true
+; CHECK-NEXT:    [[TMP55:%.*]] = xor i1 [[TMP53]], true
+; CHECK-NEXT:    [[TMP56:%.*]] = or i1 [[TMP55]], [[TMP54]]
+; CHECK-NEXT:    [[AND71:%.*]] = and i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64_OR69]], 128
+; CHECK-NEXT:    [[TOBOOL72:%.*]] = icmp eq i32 [[AND71]], 0
+; CHECK-NEXT:    [[OR74:%.*]] = or i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64_OR69]], 16777216
+; CHECK-NEXT:    [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64_OR69_OR74:%.*]] = select i1 [[TOBOOL72]], i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64_OR69]], i32 [[OR74]]
+; CHECK-NEXT:    [[TMP57:%.*]] = xor i1 [[TMP56]], true
+; CHECK-NEXT:    [[TMP58:%.*]] = xor i1 [[TOBOOL72]], true
+; CHECK-NEXT:    [[TMP59:%.*]] = xor i1 [[TMP57]], true
+; CHECK-NEXT:    [[TMP60:%.*]] = or i1 [[TMP59]], [[TMP58]]
+; CHECK-NEXT:    br i1 [[TMP60]], label [[TMP61:%.*]], label [[TMP62:%.*]]
+; CHECK:         store i32 [[DOTOR4_OR9_OR14_OR19_OR24_OR29_OR34_OR39_OR44_OR49_OR54_OR59_OR64_OR69_OR74]], i32* [[B]], align 4
+; CHECK-NEXT:    br label [[TMP62]]
+; CHECK:         ret i32 0
+;
+entry:
+  %0 = load i32, i32* %b, align 4
+  %and = and i32 %0, 1
+  %tobool = icmp eq i32 %and, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %or = or i32 %0, -2147483648
+  store i32 %or, i32* %b, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %1 = phi i32 [ %0, %entry ], [ %or, %if.then ]
+  %and1 = and i32 %1, 2
+  %tobool2 = icmp eq i32 %and1, 0
+  br i1 %tobool2, label %if.end5, label %if.then3
+
+if.then3:                                         ; preds = %if.end
+  %or4 = or i32 %1, 1073741824
+  store i32 %or4, i32* %b, align 4
+  br label %if.end5
+
+if.end5:                                          ; preds = %if.end, %if.then3
+  %2 = phi i32 [ %1, %if.end ], [ %or4, %if.then3 ]
+  %and6 = and i32 %2, 4
+  %tobool7 = icmp eq i32 %and6, 0
+  br i1 %tobool7, label %if.end10, label %if.then8
+
+if.then8:                                         ; preds = %if.end5
+  %or9 = or i32 %2, 536870912
+  store i32 %or9, i32* %b, align 4
+  br label %if.end10
+
+if.end10:                                         ; preds = %if.end5, %if.then8
+  %3 = phi i32 [ %2, %if.end5 ], [ %or9, %if.then8 ]
+  %and11 = and i32 %3, 8
+  %tobool12 = icmp eq i32 %and11, 0
+  br i1 %tobool12, label %if.end15, label %if.then13
+
+if.then13:                                        ; preds = %if.end10
+  %or14 = or i32 %3, 268435456
+  store i32 %or14, i32* %b, align 4
+  br label %if.end15
+
+if.end15:                                         ; preds = %if.end10, %if.then13
+  %4 = phi i32 [ %3, %if.end10 ], [ %or14, %if.then13 ]
+  %and16 = and i32 %4, 16
+  %tobool17 = icmp eq i32 %and16, 0
+  br i1 %tobool17, label %if.end20, label %if.then18
+
+if.then18:                                        ; preds = %if.end15
+  %or19 = or i32 %4, 134217728
+  store i32 %or19, i32* %b, align 4
+  br label %if.end20
+
+if.end20:                                         ; preds = %if.end15, %if.then18
+  %5 = phi i32 [ %4, %if.end15 ], [ %or19, %if.then18 ]
+  %and21 = and i32 %5, 32
+  %tobool22 = icmp eq i32 %and21, 0
+  br i1 %tobool22, label %if.end25, label %if.then23
+
+if.then23:                                        ; preds = %if.end20
+  %or24 = or i32 %5, 67108864
+  store i32 %or24, i32* %b, align 4
+  br label %if.end25
+
+if.end25:                                         ; preds = %if.end20, %if.then23
+  %6 = phi i32 [ %5, %if.end20 ], [ %or24, %if.then23 ]
+  %and26 = and i32 %6, 64
+  %tobool27 = icmp eq i32 %and26, 0
+  br i1 %tobool27, label %if.end30, label %if.then28
+
+if.then28:                                        ; preds = %if.end25
+  %or29 = or i32 %6, 33554432
+  store i32 %or29, i32* %b, align 4
+  br label %if.end30
+
+if.end30:                                         ; preds = %if.end25, %if.then28
+  %7 = phi i32 [ %6, %if.end25 ], [ %or29, %if.then28 ]
+  %and31 = and i32 %7, 256
+  %tobool32 = icmp eq i32 %and31, 0
+  br i1 %tobool32, label %if.end35, label %if.then33
+
+if.then33:                                        ; preds = %if.end30
+  %or34 = or i32 %7, 8388608
+  store i32 %or34, i32* %b, align 4
+  br label %if.end35
+
+if.end35:                                         ; preds = %if.end30, %if.then33
+  %8 = phi i32 [ %7, %if.end30 ], [ %or34, %if.then33 ]
+  %and36 = and i32 %8, 512
+  %tobool37 = icmp eq i32 %and36, 0
+  br i1 %tobool37, label %if.end40, label %if.then38
+
+if.then38:                                        ; preds = %if.end35
+  %or39 = or i32 %8, 4194304
+  store i32 %or39, i32* %b, align 4
+  br label %if.end40
+
+if.end40:                                         ; preds = %if.end35, %if.then38
+  %9 = phi i32 [ %8, %if.end35 ], [ %or39, %if.then38 ]
+  %and41 = and i32 %9, 1024
+  %tobool42 = icmp eq i32 %and41, 0
+  br i1 %tobool42, label %if.end45, label %if.then43
+
+if.then43:                                        ; preds = %if.end40
+  %or44 = or i32 %9, 2097152
+  store i32 %or44, i32* %b, align 4
+  br label %if.end45
+
+if.end45:                                         ; preds = %if.end40, %if.then43
+  %10 = phi i32 [ %9, %if.end40 ], [ %or44, %if.then43 ]
+  %and46 = and i32 %10, 2048
+  %tobool47 = icmp eq i32 %and46, 0
+  br i1 %tobool47, label %if.end50, label %if.then48
+
+if.then48:                                        ; preds = %if.end45
+  %or49 = or i32 %10, 1048576
+  store i32 %or49, i32* %b, align 4
+  br label %if.end50
+
+if.end50:                                         ; preds = %if.end45, %if.then48
+  %11 = phi i32 [ %10, %if.end45 ], [ %or49, %if.then48 ]
+  %and51 = and i32 %11, 4096
+  %tobool52 = icmp eq i32 %and51, 0
+  br i1 %tobool52, label %if.end55, label %if.then53
+
+if.then53:                                        ; preds = %if.end50
+  %or54 = or i32 %11, 524288
+  store i32 %or54, i32* %b, align 4
+  br label %if.end55
+
+if.end55:                                         ; preds = %if.end50, %if.then53
+  %12 = phi i32 [ %11, %if.end50 ], [ %or54, %if.then53 ]
+  %and56 = and i32 %12, 8192
+  %tobool57 = icmp eq i32 %and56, 0
+  br i1 %tobool57, label %if.end60, label %if.then58
+
+if.then58:                                        ; preds = %if.end55
+  %or59 = or i32 %12, 262144
+  store i32 %or59, i32* %b, align 4
+  br label %if.end60
+
+if.end60:                                         ; preds = %if.end55, %if.then58
+  %13 = phi i32 [ %12, %if.end55 ], [ %or59, %if.then58 ]
+  %and61 = and i32 %13, 16384
+  %tobool62 = icmp eq i32 %and61, 0
+  br i1 %tobool62, label %if.end65, label %if.then63
+
+if.then63:                                        ; preds = %if.end60
+  %or64 = or i32 %13, 131072
+  store i32 %or64, i32* %b, align 4
+  br label %if.end65
+
+if.end65:                                         ; preds = %if.end60, %if.then63
+  %14 = phi i32 [ %13, %if.end60 ], [ %or64, %if.then63 ]
+  %and66 = and i32 %14, 32768
+  %tobool67 = icmp eq i32 %and66, 0
+  br i1 %tobool67, label %if.end70, label %if.then68
+
+if.then68:                                        ; preds = %if.end65
+  %or69 = or i32 %14, 65536
+  store i32 %or69, i32* %b, align 4
+  br label %if.end70
+
+if.end70:                                         ; preds = %if.end65, %if.then68
+  %15 = phi i32 [ %14, %if.end65 ], [ %or69, %if.then68 ]
+  %and71 = and i32 %15, 128
+  %tobool72 = icmp eq i32 %and71, 0
+  br i1 %tobool72, label %if.end75, label %if.then73
+
+if.then73:                                        ; preds = %if.end70
+  %or74 = or i32 %15, 16777216
+  store i32 %or74, i32* %b, align 4
+  br label %if.end75
+
+if.end75:                                         ; preds = %if.end70, %if.then73
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/merge-cond-stores.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,408 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -simplifycfg -instcombine < %s -simplifycfg-merge-cond-stores=true -simplifycfg-merge-cond-stores-aggressively=false -phi-node-folding-threshold=2 -S | FileCheck %s
+
+; This test should succeed and end up if-converted.
+define void @test_simple(i32* %p, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_simple(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[X2]], true
+; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
+; CHECK:         [[NOT_X2:%.*]] = xor i1 [[X2]], true
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32
+; CHECK-NEXT:    store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[TMP3]]
+; CHECK:         ret void
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %fallthrough, label %yes1
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+fallthrough:
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %end, label %yes2
+
+yes2:
+  store i32 1, i32* %p
+  br label %end
+
+end:
+  ret void
+}
+
+; This is the same as test_simple, but the branch target order has been swapped
+define void @test_simple_commuted(i32* %p, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_simple_commuted(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[X1]], [[X2]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[TMP1:%.*]], label [[TMP2:%.*]]
+; CHECK:         [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
+; CHECK-NEXT:    store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[TMP2]]
+; CHECK:         ret void
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %yes1, label %fallthrough
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+fallthrough:
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %yes2, label %end
+
+yes2:
+  store i32 1, i32* %p
+  br label %end
+
+end:
+  ret void
+}
+
+; This test should entirely fold away, leaving one large basic block.
+define void @test_recursive(i32* %p, i32 %a, i32 %b, i32 %c, i32 %d) {
+; CHECK-LABEL: @test_recursive(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[X4:%.*]] = icmp eq i32 [[D:%.*]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[TMP0]], [[C:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[X4]], true
+; CHECK-NEXT:    [[TMP4:%.*]] = or i1 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
+; CHECK:         [[X3:%.*]] = icmp eq i32 [[C]], 0
+; CHECK-NEXT:    [[X2:%.*]] = icmp ne i32 [[B]], 0
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = zext i1 [[X2]] to i32
+; CHECK-NEXT:    [[SPEC_SELECT1:%.*]] = select i1 [[X3]], i32 [[SPEC_SELECT]], i32 2
+; CHECK-NEXT:    [[SPEC_SELECT2:%.*]] = select i1 [[X4]], i32 [[SPEC_SELECT1]], i32 3
+; CHECK-NEXT:    store i32 [[SPEC_SELECT2]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[TMP6]]
+; CHECK:         ret void
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %fallthrough, label %yes1
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+fallthrough:
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %next, label %yes2
+
+yes2:
+  store i32 1, i32* %p
+  br label %next
+
+next:
+  %x3 = icmp eq i32 %c, 0
+  br i1 %x3, label %fallthrough2, label %yes3
+
+yes3:
+  store i32 2, i32* %p
+  br label %fallthrough2
+
+fallthrough2:
+  %x4 = icmp eq i32 %d, 0
+  br i1 %x4, label %end, label %yes4
+
+yes4:
+  store i32 3, i32* %p
+  br label %end
+
+
+end:
+  ret void
+}
+
+; The code in each diamond is too large - it won't be if-converted so our
+; heuristics should say no.
+define void @test_not_ifconverted(i32* %p, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_not_ifconverted(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
+; CHECK:       yes1:
+; CHECK-NEXT:    [[Y1:%.*]] = or i32 [[B:%.*]], 55
+; CHECK-NEXT:    [[Y2:%.*]] = add i32 [[Y1]], 24
+; CHECK-NEXT:    [[Y3:%.*]] = and i32 [[Y2]], 67
+; CHECK-NEXT:    store i32 [[Y3]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[FALLTHROUGH]]
+; CHECK:       fallthrough:
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[B]], 0
+; CHECK-NEXT:    br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
+; CHECK:       yes2:
+; CHECK-NEXT:    [[Z1:%.*]] = or i32 [[A]], 55
+; CHECK-NEXT:    [[Z2:%.*]] = add i32 [[Z1]], 24
+; CHECK-NEXT:    [[Z3:%.*]] = and i32 [[Z2]], 67
+; CHECK-NEXT:    store i32 [[Z3]], i32* [[P]], align 4
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %fallthrough, label %yes1
+
+yes1:
+  %y1 = or i32 %b, 55
+  %y2 = add i32 %y1, 24
+  %y3 = and i32 %y2, 67
+  store i32 %y3, i32* %p
+  br label %fallthrough
+
+fallthrough:
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %end, label %yes2
+
+yes2:
+  %z1 = or i32 %a, 55
+  %z2 = add i32 %z1, 24
+  %z3 = and i32 %z2, 67
+  store i32 %z3, i32* %p
+  br label %end
+
+end:
+  ret void
+}
+
+; The store to %p clobbers the previous store, so if-converting this would
+; be illegal.
+define void @test_aliasing1(i32* %p, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_aliasing1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
+; CHECK:       yes1:
+; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[FALLTHROUGH]]
+; CHECK:       fallthrough:
+; CHECK-NEXT:    [[Y1:%.*]] = load i32, i32* [[P]], align 4
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[Y1]], 0
+; CHECK-NEXT:    br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
+; CHECK:       yes2:
+; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %fallthrough, label %yes1
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+fallthrough:
+  %y1 = load i32, i32* %p
+  %x2 = icmp eq i32 %y1, 0
+  br i1 %x2, label %end, label %yes2
+
+yes2:
+  store i32 1, i32* %p
+  br label %end
+
+end:
+  ret void
+}
+
+; The load from %q aliases with %p, so if-converting this would be illegal.
+define void @test_aliasing2(i32* %p, i32* %q, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_aliasing2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    br i1 [[X1]], label [[FALLTHROUGH:%.*]], label [[YES1:%.*]]
+; CHECK:       yes1:
+; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[FALLTHROUGH]]
+; CHECK:       fallthrough:
+; CHECK-NEXT:    [[Y1:%.*]] = load i32, i32* [[Q:%.*]], align 4
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[Y1]], 0
+; CHECK-NEXT:    br i1 [[X2]], label [[END:%.*]], label [[YES2:%.*]]
+; CHECK:       yes2:
+; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %fallthrough, label %yes1
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+fallthrough:
+  %y1 = load i32, i32* %q
+  %x2 = icmp eq i32 %y1, 0
+  br i1 %x2, label %end, label %yes2
+
+yes2:
+  store i32 1, i32* %p
+  br label %end
+
+end:
+  ret void
+}
+
+declare void @f()
+
+; This should get if-converted.
+define i32 @test_diamond_simple(i32* %p, i32* %q, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_diamond_simple(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[Z2:%.*]] = select i1 [[X1]], i32 [[B:%.*]], i32 0
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[B]], 0
+; CHECK-NEXT:    [[Z4:%.*]] = select i1 [[X2]], i32 [[Z2]], i32 3
+; CHECK-NEXT:    [[TMP0:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[TMP3:%.*]], label [[TMP2:%.*]]
+; CHECK:         [[SIMPLIFYCFG_MERGE:%.*]] = select i1 [[X2]], i32 [[Z2]], i32 1
+; CHECK-NEXT:    store i32 [[SIMPLIFYCFG_MERGE]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[TMP3]]
+; CHECK:         ret i32 [[Z4]]
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %no1, label %yes1
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+no1:
+  %z1 = add i32 %a, %b
+  br label %fallthrough
+
+fallthrough:
+  %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %no2, label %yes2
+
+yes2:
+  store i32 1, i32* %p
+  br label %end
+
+no2:
+  %z3 = sub i32 %z2, %b
+  br label %end
+
+end:
+  %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
+  ret i32 %z4
+}
+
+; Now there is a call to f() in the bottom branch. The store in the first
+; branch would now be reordered with respect to the call if we if-converted,
+; so we must not.
+define i32 @test_diamond_alias3(i32* %p, i32* %q, i32 %a, i32 %b) {
+; CHECK-LABEL: @test_diamond_alias3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X1:%.*]] = icmp eq i32 [[A:%.*]], 0
+; CHECK-NEXT:    br i1 [[X1]], label [[NO1:%.*]], label [[YES1:%.*]]
+; CHECK:       yes1:
+; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[FALLTHROUGH:%.*]]
+; CHECK:       no1:
+; CHECK-NEXT:    call void @f()
+; CHECK-NEXT:    [[Z1:%.*]] = add i32 [[A]], [[B:%.*]]
+; CHECK-NEXT:    br label [[FALLTHROUGH]]
+; CHECK:       fallthrough:
+; CHECK-NEXT:    [[Z2:%.*]] = phi i32 [ [[Z1]], [[NO1]] ], [ 0, [[YES1]] ]
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[B]], 0
+; CHECK-NEXT:    br i1 [[X2]], label [[NO2:%.*]], label [[YES2:%.*]]
+; CHECK:       yes2:
+; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       no2:
+; CHECK-NEXT:    call void @f()
+; CHECK-NEXT:    [[Z3:%.*]] = sub i32 [[Z2]], [[B]]
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[Z4:%.*]] = phi i32 [ [[Z3]], [[NO2]] ], [ 3, [[YES2]] ]
+; CHECK-NEXT:    ret i32 [[Z4]]
+;
+entry:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %no1, label %yes1
+
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+
+no1:
+  call void @f()
+  %z1 = add i32 %a, %b
+  br label %fallthrough
+
+fallthrough:
+  %z2 = phi i32 [ %z1, %no1 ], [ 0, %yes1 ]
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %no2, label %yes2
+
+yes2:
+  store i32 1, i32* %p
+  br label %end
+
+no2:
+  call void @f()
+  %z3 = sub i32 %z2, %b
+  br label %end
+
+end:
+  %z4 = phi i32 [ %z3, %no2 ], [ 3, %yes2 ]
+  ret i32 %z4
+}
+
+; This test has an outer if over the two triangles. This requires creating a new BB to hold the store.
+define void @test_outer_if(i32* %p, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @test_outer_if(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X3:%.*]] = icmp eq i32 [[C:%.*]], 0
+; CHECK-NEXT:    br i1 [[X3]], label [[END:%.*]], label [[CONTINUE:%.*]]
+; CHECK:       continue:
+; CHECK-NEXT:    [[X1:%.*]] = icmp ne i32 [[A:%.*]], 0
+; CHECK-NEXT:    [[X2:%.*]] = icmp eq i32 [[B:%.*]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[X2]], true
+; CHECK-NEXT:    [[TMP1:%.*]] = or i1 [[X1]], [[TMP0]]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[END]]
+; CHECK:         [[NOT_X2:%.*]] = xor i1 [[X2]], true
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = zext i1 [[NOT_X2]] to i32
+; CHECK-NEXT:    store i32 [[SPEC_SELECT]], i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x3 = icmp eq i32 %c, 0
+  br i1 %x3, label %end, label %continue
+continue:
+  %x1 = icmp eq i32 %a, 0
+  br i1 %x1, label %fallthrough, label %yes1
+yes1:
+  store i32 0, i32* %p
+  br label %fallthrough
+  fallthrough:
+  %x2 = icmp eq i32 %b, 0
+  br i1 %x2, label %end, label %yes2
+yes2:
+  store i32 1, i32* %p
+  br label %end
+end:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/multiple-phis.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/multiple-phis.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/multiple-phis.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/multiple-phis.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -simplifycfg -keep-loops=false -S < %s | FileCheck %s
+; RUN: opt -passes='simplify-cfg<no-keep-loops>' -S < %s | FileCheck %s
+
+; It's not worthwhile to if-convert one of the phi nodes and leave
+; the other behind, because that still requires a branch. If
+; SimplifyCFG if-converts one of the phis, it should do both.
+
+define i32 @upper_bound(i32* %r, i32 %high, i32 %k) nounwind {
+; CHECK-LABEL: @upper_bound(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[HIGH_ADDR_0:%.*]] = phi i32 [ [[HIGH:%.*]], [[ENTRY:%.*]] ], [ [[DIV_HIGH_ADDR_0:%.*]], [[WHILE_BODY:%.*]] ]
+; CHECK-NEXT:    [[LOW_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[LOW_0_ADD2:%.*]], [[WHILE_BODY]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[LOW_0]], [[HIGH_ADDR_0]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_END:%.*]]
+; CHECK:       while.body:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LOW_0]], [[HIGH_ADDR_0]]
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[ADD]], 2
+; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[DIV]] to i64
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[R:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[K:%.*]], [[TMP0]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[DIV]], 1
+; CHECK-NEXT:    [[DIV_HIGH_ADDR_0]] = select i1 [[CMP1]], i32 [[DIV]], i32 [[HIGH_ADDR_0]]
+; CHECK-NEXT:    [[LOW_0_ADD2]] = select i1 [[CMP1]], i32 [[LOW_0]], i32 [[ADD2]]
+; CHECK-NEXT:    br label [[WHILE_COND]]
+; CHECK:       while.end:
+; CHECK-NEXT:    ret i32 [[LOW_0]]
+;
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %if.then, %if.else, %entry
+  %high.addr.0 = phi i32 [ %high, %entry ], [ %div, %if.then ], [ %high.addr.0, %if.else ]
+  %low.0 = phi i32 [ 0, %entry ], [ %low.0, %if.then ], [ %add2, %if.else ]
+  %cmp = icmp ult i32 %low.0, %high.addr.0
+  br i1 %cmp, label %while.body, label %while.end
+
+while.body:                                       ; preds = %while.cond
+  %add = add i32 %low.0, %high.addr.0
+  %div = udiv i32 %add, 2
+  %idxprom = zext i32 %div to i64
+  %arrayidx = getelementptr inbounds i32, i32* %r, i64 %idxprom
+  %0 = load i32, i32* %arrayidx
+  %cmp1 = icmp ult i32 %k, %0
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:                                          ; preds = %while.body
+  br label %while.cond
+
+if.else:                                          ; preds = %while.body
+  %add2 = add i32 %div, 1
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  ret i32 %low.0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/no-md-sink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/no-md-sink.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/no-md-sink.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/no-md-sink.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt < %s -simplifycfg -sink-common-insts -S | FileCheck %s
+; RUN: opt < %s -passes='simplify-cfg<sink-common-insts>' -S | FileCheck %s
+
+define i1 @test1(i1 zeroext %flag, i8* %y) #0 {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %r = call i1 @llvm.type.test(i8* %y, metadata !0)
+  br label %if.end
+
+if.else:
+  %s = call i1 @llvm.type.test(i8* %y, metadata !1)
+  br label %if.end
+
+if.end:
+  %t = phi i1 [ %s, %if.else ], [ %r, %if.then ]
+  ret i1 %t
+}
+
+!0 = !{i32 0, !"typeid1"}
+!1 = !{i32 4, !"typeid1"}
+
+declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone
+
+; CHECK-LABEL: test1
+; CHECK: @llvm.type.test
+; CHECK: @llvm.type.test
+; CHECK: ret i1
+
+define i1 @test2(i1 zeroext %flag, i8* %y, i8* %z) #0 {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %r = call i1 @llvm.type.test(i8* %y, metadata !0)
+  br label %if.end
+
+if.else:
+  %s = call i1 @llvm.type.test(i8* %z, metadata !0)
+  br label %if.end
+
+if.end:
+  %t = phi i1 [ %s, %if.else ], [ %r, %if.then ]
+  ret i1 %t
+}
+
+; CHECK-LABEL: test2
+; CHECK: %[[S:[a-z0-9.]+]] = select i1 %flag, i8* %y, i8* %z
+; CHECK: %[[R:[a-z0-9.]+]] = call i1 @llvm.type.test(i8* %[[S]], metadata !0)
+; CHECK: ret i1 %[[R]]
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_asan.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,59 @@
+; RUN: opt -simplifycfg -S %s | FileCheck %s
+; Make sure we don't speculate loads under AddressSanitizer.
+ at g = global i32 0, align 4
+
+define i32 @TestNoAsan(i32 %cond) nounwind readonly uwtable {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* @g, align 4
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+; CHECK-LABEL: @TestNoAsan
+; CHECK: %[[LOAD:[^ ]*]] = load
+; CHECK: select{{.*}}[[LOAD]]
+; CHECK: ret i32
+}
+
+define i32 @TestAsan(i32 %cond) nounwind readonly uwtable sanitize_address {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* @g, align 4
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+; CHECK-LABEL: @TestAsan
+; CHECK: br i1
+; CHECK: load i32, i32* @g
+; CHECK: br label
+; CHECK: ret i32
+}
+
+define i32 @TestHWAsan(i32 %cond) nounwind readonly uwtable sanitize_hwaddress {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* @g, align 4
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+; CHECK-LABEL: @TestHWAsan
+; CHECK: br i1
+; CHECK: load i32, i32* @g
+; CHECK: br label
+; CHECK: ret i32
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_tsan.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_tsan.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_tsan.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/no_speculative_loads_with_tsan.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -simplifycfg -S %s | FileCheck %s
+; Make sure we don't speculate loads under ThreadSanitizer.
+ at g = global i32 0, align 4
+
+define i32 @TestNoTsan(i32 %cond) nounwind readonly uwtable {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* @g, align 4
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+; CHECK-LABEL: @TestNoTsan
+; CHECK: %[[LOAD:[^ ]*]] = load
+; CHECK: select{{.*}}[[LOAD]]
+; CHECK: ret i32
+}
+
+define i32 @TestTsan(i32 %cond) nounwind readonly uwtable sanitize_thread {
+entry:
+  %tobool = icmp eq i32 %cond, 0
+  br i1 %tobool, label %return, label %if.then
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* @g, align 4
+  br label %return
+
+return:                                           ; preds = %entry, %if.then
+  %retval = phi i32 [ %0, %if.then ], [ 0, %entry ]
+  ret i32 %retval
+; CHECK-LABEL: @TestTsan
+; CHECK: br i1
+; CHECK: load i32, i32* @g
+; CHECK: br label
+; CHECK: ret i32
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/noreturn-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/noreturn-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/noreturn-call.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/noreturn-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; PR1796
+
+declare void @Finisher(i32) noreturn
+
+; Make sure we optimize a sequence of two calls (second unreachable);
+define void @double_call(i32) {
+; CHECK-LABEL: @double_call(
+; CHECK-NEXT:    tail call void @Finisher(i32 %0) #0
+; CHECK-NEXT:    unreachable
+;
+  tail call void @Finisher(i32 %0) noreturn
+  tail call void @Finisher(i32 %0) noreturn
+  ret void
+}
+
+; Make sure we DON'T try to optimize a musttail call (the IR invariant
+; is that it must be followed by [optional bitcast then] ret).
+define void @must_tail(i32) {
+; CHECK-LABEL: @must_tail(
+; CHECK-NEXT:    musttail call void @Finisher(i32 %0) #0
+; CHECK-NEXT:    ret void
+;
+  musttail call void @Finisher(i32 %0) #0
+  ret void
+}
+
+; CHECK: attributes #0 = { noreturn }
+attributes #0 = { noreturn }

Added: llvm/trunk/test/Transforms/SimplifyCFG/opt-for-fuzzing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/opt-for-fuzzing.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/opt-for-fuzzing.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/opt-for-fuzzing.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define i32 @foo(i32 %x) optforfuzzing {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  %cmp = icmp sgt i32 %0, 16
+  br i1 %cmp, label %land.rhs, label %land.end
+
+land.rhs:
+  %1 = load i32, i32* %x.addr, align 4
+  %cmp1 = icmp slt i32 %1, 32
+  br label %land.end
+
+land.end:
+  %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ]
+  %conv = zext i1 %2 to i32
+  ret i32 %conv
+
+; CHECK-LABEL: define i32 @foo(i32 %x)
+; CHECK: br i1 %cmp, label %land.rhs, label %land.end
+; CHECK-LABEL: land.rhs:
+; CHECK: br label %land.end
+; CHECK-LABEL: land.end:
+; CHECK: phi {{.*}} %entry {{.*}} %land.rhs
+}
+
+define i32 @bar(i32 %x) {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  %cmp = icmp sgt i32 %0, 16
+  br i1 %cmp, label %land.rhs, label %land.end
+
+land.rhs:
+  %1 = load i32, i32* %x.addr, align 4
+  %cmp1 = icmp slt i32 %1, 32
+  br label %land.end
+
+land.end:
+  %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ]
+  %conv = zext i1 %2 to i32
+  ret i32 %conv
+
+; CHECK-LABEL: define i32 @bar(i32 %x)
+; CHECK-NOT: br
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/phi-undef-loadstore.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,239 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+declare void @bar() nounwind
+
+define i32 @test1(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ %c, %if.then4 ], [ null, %if.else ]
+  %tmp9 = load i32, i32* %x.0
+  ret i32 %tmp9
+
+; CHECK-LABEL: @test1(
+; CHECK: if.else:
+; CHECK: br label %if.end7
+
+; CHECK: phi i32* [ %a, %if.then ], [ %c, %if.else ]
+}
+
+define i32 @test1_no_null_opt(i32* %a, i32 %b, i32* %c, i32 %d) nounwind #0 {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ %c, %if.then4 ], [ null, %if.else ]
+  %tmp9 = load i32, i32* %x.0
+  ret i32 %tmp9
+
+; CHECK-LABEL: @test1_no_null_opt(
+; CHECK: if.then:
+; CHECK: if.else:
+; CHECK: if.then4:
+; CHECK: br label %if.end7
+; CHECK: if.end7:
+; CHECK-NEXT: phi i32* [ %a, %if.then ], [ %c, %if.then4 ], [ null, %if.else ]
+}
+
+define i32 @test2(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+  %tmp9 = load i32, i32* %x.0
+  ret i32 %tmp9
+; CHECK-LABEL: @test2(
+; CHECK: if.else:
+; CHECK: unreachable
+
+; CHECK-NOT: phi
+}
+
+define i32 @test2_no_null_opt(i32* %a, i32 %b, i32* %c, i32 %d) nounwind #0 {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+  %tmp9 = load i32, i32* %x.0
+  ret i32 %tmp9
+; CHECK-LABEL: @test2_no_null_opt(
+; CHECK: if.then:
+; CHECK: if.else:
+; CHECK: if.then4:
+; CHECK: if.end7:
+; CHECK-NEXT: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+}
+
+define i32 @test3(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+  tail call void @bar() nounwind
+  %tmp9 = load i32, i32* %x.0
+  ret i32 %tmp9
+; CHECK-LABEL: @test3(
+; CHECK: if.end7:
+; CHECK: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+}
+
+define i32 @test3_no_null_opt(i32* %a, i32 %b, i32* %c, i32 %d) nounwind #0 {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+  tail call void @bar() nounwind
+  %tmp9 = load i32, i32* %x.0
+  ret i32 %tmp9
+; CHECK-LABEL: @test3_no_null_opt(
+; CHECK: if.then:
+; CHECK: if.else:
+; CHECK: if.then4:
+; CHECK: if.end7:
+; CHECK-NEXT: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+}
+
+define i32 @test4(i32* %a, i32 %b, i32* %c, i32 %d) nounwind {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+  %gep = getelementptr i32, i32* %x.0, i32 10
+  %tmp9 = load i32, i32* %gep
+  %tmp10 = or i32 %tmp9, 1
+  store i32 %tmp10, i32* %gep
+  ret i32 %tmp9
+; CHECK-LABEL: @test4(
+; CHECK-NOT: phi
+}
+
+define i32 @test4_no_null_opt(i32* %a, i32 %b, i32* %c, i32 %d) nounwind #0 {
+entry:
+  %tobool = icmp eq i32 %b, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.else:                                          ; preds = %entry
+  %tobool3 = icmp eq i32 %d, 0
+  br i1 %tobool3, label %if.end7, label %if.then4
+
+if.then4:                                         ; preds = %if.else
+  tail call void @bar() nounwind
+  br label %if.end7
+
+if.end7:                                          ; preds = %if.else, %if.then4, %if.then
+  %x.0 = phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+  %gep = getelementptr i32, i32* %x.0, i32 10
+  %tmp9 = load i32, i32* %gep
+  %tmp10 = or i32 %tmp9, 1
+  store i32 %tmp10, i32* %gep
+  ret i32 %tmp9
+; CHECK-LABEL: @test4_no_null_opt(
+; CHECK: if.then:
+; CHECK: if.else:
+; CHECK: if.then4:
+; CHECK: if.end7:
+; CHECK-NEXT: phi i32* [ %a, %if.then ], [ null, %if.then4 ], [ null, %if.else ]
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/SimplifyCFG/pr33605.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/pr33605.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/pr33605.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/pr33605.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Skip simplifying unconditional branches from empty blocks in simplifyCFG,
+; when it can destroy canonical loop structure.
+
+; void foo();
+; bool test(int a, int b, int *c) {
+;   bool changed = false;
+;   for (unsigned int i = 2; i--;) {
+;     int r = a | b;
+;     if ( r != c[i]) {
+;       c[i] = r;
+;       foo();
+;       changed = true;
+;     }
+;   }
+;   return changed;
+; }
+
+; CHECK-LABEL: @test(
+; CHECK: for.cond:
+; CHECK-NEXT: %i.0 = phi i32 [ 2, %entry ], [ %dec, %if.end ]
+; CHECK: for.body:
+; CHECK: br i1 %cmp, label %if.end, label %if.then
+; CHECK-NOT: br i1 %cmp, label %for.cond, label %if.then
+; CHECK: if.then:
+; CHECK: br label %if.end
+; CHECK-NOT: br label %for.cond
+; CHECK: if.end:
+; CHECK br label %for.cond
+define i1 @test(i32 %a, i32 %b, i32* %c) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %if.end, %entry
+  %i.0 = phi i32 [ 2, %entry ], [ %dec, %if.end ]
+  %changed.0.off0 = phi i1 [ false, %entry ], [ %changed.1.off0, %if.end ]
+  %dec = add nsw i32 %i.0, -1
+  %tobool = icmp eq i32 %i.0, 0
+  br i1 %tobool, label %for.cond.cleanup, label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %changed.0.off0.lcssa = phi i1 [ %changed.0.off0, %for.cond ]
+  ret i1 %changed.0.off0.lcssa
+
+for.body:                                         ; preds = %for.cond
+  %or = or i32 %a, %b
+  %idxprom = sext i32 %dec to i64
+  %arrayidx = getelementptr inbounds i32, i32* %c, i64 %idxprom
+  %0 = load i32, i32* %arrayidx, align 4
+  %cmp = icmp eq i32 %or, %0
+  br i1 %cmp, label %if.end, label %if.then
+
+if.then:                                          ; preds = %for.body
+  store i32 %or, i32* %arrayidx, align 4
+  call void @foo()
+  br label %if.end
+
+if.end:                                           ; preds = %for.body, %if.then
+  %changed.1.off0 = phi i1 [ true, %if.then ], [ %changed.0.off0, %for.body ]
+  br label %for.cond
+}
+
+declare void @foo()

Added: llvm/trunk/test/Transforms/SimplifyCFG/pr34131.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/pr34131.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/pr34131.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/pr34131.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+; Just checking for lack of crash here, but we should be able to check the IR?
+; Earlier version using auto-generated checks from utils/update_test_checks.py
+; had bot problems though...
+
+define void @patatino() {
+
+; CHECK-LABEL: @patatino
+
+  br label %bb1
+bb1:                                              ; preds = %bb36, %0
+  br label %bb2
+bb2:                                              ; preds = %bb3, %bb1
+  br i1 undef, label %bb4, label %bb3
+bb3:                                              ; preds = %bb4, %bb2
+  br i1 undef, label %bb2, label %bb5
+bb4:                                              ; preds = %bb2
+  switch i32 undef, label %bb3 [
+  ]
+bb5:                                              ; preds = %bb3
+  br label %bb6
+bb6:                                              ; preds = %bb5
+  br i1 undef, label %bb7, label %bb9
+bb7:                                              ; preds = %bb6
+  %tmp = or i64 undef, 1
+  %tmp8 = icmp ult i64 %tmp, 0
+  br i1 %tmp8, label %bb12, label %bb9
+bb9:                                              ; preds = %bb35, %bb34, %bb33, %bb32, %bb31, %bb30, %bb27, %bb24, %bb21, %bb18, %bb16, %bb14, %bb12, %bb7, %bb6
+  br label %bb11
+bb10:                                             ; preds = %bb36
+  br label %bb11
+bb11:                                             ; preds = %bb10, %bb9
+  ret void
+bb12:                                             ; preds = %bb7
+  %tmp13 = icmp ult i64 0, 0
+  br i1 %tmp13, label %bb14, label %bb9
+bb14:                                             ; preds = %bb12
+  %tmp15 = icmp ult i64 undef, 0
+  br i1 %tmp15, label %bb16, label %bb9
+bb16:                                             ; preds = %bb14
+  %tmp17 = icmp ult i64 undef, 0
+  br i1 %tmp17, label %bb18, label %bb9
+bb18:                                             ; preds = %bb16
+  %tmp19 = or i64 undef, 5
+  %tmp20 = icmp ult i64 %tmp19, 0
+  br i1 %tmp20, label %bb21, label %bb9
+bb21:                                             ; preds = %bb18
+  %tmp22 = or i64 undef, 6
+  %tmp23 = icmp ult i64 %tmp22, 0
+  br i1 %tmp23, label %bb24, label %bb9
+bb24:                                             ; preds = %bb21
+  %tmp25 = or i64 undef, 7
+  %tmp26 = icmp ult i64 %tmp25, 0
+  br i1 %tmp26, label %bb27, label %bb9
+bb27:                                             ; preds = %bb24
+  %tmp28 = or i64 undef, 8
+  %tmp29 = icmp ult i64 %tmp28, 0
+  br i1 %tmp29, label %bb30, label %bb9
+bb30:                                             ; preds = %bb27
+  br i1 undef, label %bb31, label %bb9
+bb31:                                             ; preds = %bb30
+  br i1 undef, label %bb32, label %bb9
+bb32:                                             ; preds = %bb31
+  br i1 undef, label %bb33, label %bb9
+bb33:                                             ; preds = %bb32
+  br i1 undef, label %bb34, label %bb9
+bb34:                                             ; preds = %bb33
+  br i1 undef, label %bb35, label %bb9
+bb35:                                             ; preds = %bb34
+  br i1 undef, label %bb36, label %bb9
+bb36:                                             ; preds = %bb35
+  br i1 undef, label %bb1, label %bb10
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/pr35774.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -simplifycfg -S %s | FileCheck %s
+
+%foo = type { i32 (%foo)*, i32 }
+
+declare i32 @putchar(i32)
+
+define i32 @intercept(%foo %f) {
+; CHECK-LABEL: @intercept(
+; CHECK-NEXT:    [[FN:%.*]] = extractvalue [[FOO:%.*]] %f, 0
+; CHECK-NEXT:    [[X:%.*]] = extractvalue [[FOO]] %f, 1
+; CHECK-NEXT:    [[X0:%.*]] = icmp eq i32 [[X]], 0
+; CHECK-NEXT:    br i1 [[X0]], label [[ZERO:%.*]], label [[NONZERO:%.*]]
+; CHECK:       Zero:
+; CHECK-NEXT:    [[R0:%.*]] = musttail call i32 [[FN]](%foo [[F:%.*]])
+; CHECK-NEXT:    ret i32 [[R0]]
+; CHECK:       Nonzero:
+; CHECK-NEXT:    [[R1:%.*]] = tail call i32 [[FN]](%foo [[F]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @putchar(i32 [[R1]])
+; CHECK-NEXT:    ret i32 [[R1]]
+;
+  %fn = extractvalue %foo %f, 0
+  %x = extractvalue %foo %f, 1
+  %x0 = icmp eq i32 %x, 0
+  br i1 %x0, label %Zero, label %Nonzero
+
+Zero:
+  %r0 = musttail call i32 %fn(%foo %f)
+  ret i32 %r0
+
+Nonzero:
+  %r1 = tail call i32 %fn(%foo %f)
+  %1 = tail call i32 @putchar(i32 %r1)
+  ret i32 %r1
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/pr39807.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/pr39807.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/pr39807.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/pr39807.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+declare void @personality()
+
+define void @test(i1 %b) personality void()* @personality !dbg !1 {
+; CHECK:      invoke void @inlinable()
+; CHECK-NEXT:    to label %success unwind label %failure, !dbg ![[DBGLOC:[0-9]+]]
+    br i1 %b, label %if, label %else
+
+if:
+    invoke void @inlinable()
+        to label %success unwind label %failure, !dbg !2
+
+else:
+    invoke void @inlinable()
+        to label %success unwind label %failure, !dbg !8
+
+success:
+    ret void
+
+failure:
+    landingpad {}
+        cleanup
+    ret void
+}
+
+define internal void @inlinable() !dbg !7 {
+    ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!4, !5, !6}
+
+; CHECK: ![[DBGLOC]] = !DILocation(line: 0
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, runtimeVersion: 0, file: !3)
+!1 = distinct !DISubprogram(name: "test", unit: !0)
+!2 = !DILocation(line: 2, scope: !1)
+!3 = !DIFile(filename: "foo", directory: ".")
+!4 = !{i32 2, !"Dwarf Version", i32 4}
+!5 = !{i32 2, !"Debug Info Version", i32 3}
+!6 = !{i32 1, !"wchar_size", i32 4}
+!7 = distinct !DISubprogram(name: "inlinable", unit: !0)
+!8 = !DILocation(line: 3, scope: !1)

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-partial.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -simplifycfg -S -o - < %s | FileCheck %s
+
+; This test case was written to trigger an incorrect assert statement in
+; -simplifycfg.  Thus we don't actually want to check the output, just that
+; -simplifycfg ran successfully.  Thus we only check that the function still
+; exists, and that it still calls foo().
+;
+; NOTE: There are some obviously dead blocks and missing branch weight
+;       metadata.  Both of these features were key to triggering the assert.
+;       Additionally, the not-taken weight of the branch with a weight had to
+;       be 0 to trigger the assert.
+
+declare void @foo() nounwind uwtable
+
+define void @func(i32 %A) nounwind uwtable {
+; CHECK-LABEL: define void @func(
+entry:
+  %cmp11 = icmp eq i32 %A, 1
+  br i1 %cmp11, label %if.then, label %if.else, !prof !0
+
+if.then:
+  call void @foo()
+; CHECK: call void @foo()
+  br label %if.else
+
+if.else:
+  %cmp17 = icmp eq i32 %A, 2
+  br i1 %cmp17, label %if.then2, label %if.end
+
+if.then2:
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+!0 = !{!"branch_weights", i32 1, i32 0}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights-switch-create.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,140 @@
+; RUN: opt -simplifycfg -S -o - < %s | FileCheck %s
+
+declare void @func2(i32)
+declare void @func4(i32)
+declare void @func6(i32)
+declare void @func8(i32)
+
+;; test1 - create a switch with case 2 and case 4 from two branches: N == 2
+;; and N == 4.
+define void @test1(i32 %N) nounwind uwtable {
+entry:
+  %cmp = icmp eq i32 %N, 2
+  br i1 %cmp, label %if.then, label %if.else, !prof !0
+; CHECK: test1
+; CHECK: switch i32 %N
+; CHECK: ], !prof !0
+
+if.then:
+  call void @func2(i32 %N) nounwind
+  br label %if.end9
+
+if.else:
+  %cmp2 = icmp eq i32 %N, 4
+  br i1 %cmp2, label %if.then7, label %if.else8, !prof !1
+
+if.then7:
+  call void @func4(i32 %N) nounwind
+  br label %if.end
+
+if.else8:
+  call void @func8(i32 %N) nounwind
+  br label %if.end
+
+if.end:
+  br label %if.end9
+
+if.end9:
+  ret void
+}
+
+;; test2 - Merge two switches where PredDefault == BB.
+define void @test2(i32 %M, i32 %N) nounwind uwtable {
+entry:
+  %cmp = icmp sgt i32 %M, 2
+  br i1 %cmp, label %sw1, label %sw2
+
+sw1:
+  switch i32 %N, label %sw2 [
+    i32 2, label %sw.bb
+    i32 3, label %sw.bb1
+  ], !prof !2
+; CHECK: test2
+; CHECK: switch i32 %N, label %sw.epilog
+; CHECK: i32 2, label %sw.bb
+; CHECK: i32 3, label %sw.bb1
+; CHECK: i32 4, label %sw.bb5
+; CHECK: ], !prof !1
+
+sw.bb:
+  call void @func2(i32 %N) nounwind
+  br label %sw.epilog
+
+sw.bb1:
+  call void @func4(i32 %N) nounwind
+  br label %sw.epilog
+
+sw2:
+;; Here "case 2" is invalidated if control is transferred through default case
+;; of the first switch.
+  switch i32 %N, label %sw.epilog [
+    i32 2, label %sw.bb4
+    i32 4, label %sw.bb5
+  ], !prof !3
+
+sw.bb4:
+  call void @func6(i32 %N) nounwind
+  br label %sw.epilog
+
+sw.bb5:
+  call void @func8(i32 %N) nounwind
+  br label %sw.epilog
+
+sw.epilog:
+  ret void
+}
+
+;; test3 - Merge two switches where PredDefault != BB.
+define void @test3(i32 %M, i32 %N) nounwind uwtable {
+entry:
+  %cmp = icmp sgt i32 %M, 2
+  br i1 %cmp, label %sw1, label %sw2
+
+sw1:
+  switch i32 %N, label %sw.bb [
+    i32 2, label %sw2
+    i32 3, label %sw2
+    i32 1, label %sw.bb1
+  ], !prof !4
+; CHECK: test3
+; CHECK: switch i32 %N, label %sw.bb
+; CHECK: i32 1, label %sw.bb1
+; CHECK: i32 3, label %sw.bb4
+; CHECK: i32 2, label %sw.epilog
+; CHECK: ], !prof !3
+
+sw.bb:
+  call void @func2(i32 %N) nounwind
+  br label %sw.epilog
+
+sw.bb1:
+  call void @func4(i32 %N) nounwind
+  br label %sw.epilog
+
+sw2:
+  switch i32 %N, label %sw.epilog [
+    i32 3, label %sw.bb4
+    i32 4, label %sw.bb5
+  ], !prof !5
+
+sw.bb4:
+  call void @func6(i32 %N) nounwind
+  br label %sw.epilog
+
+sw.bb5:
+  call void @func8(i32 %N) nounwind
+  br label %sw.epilog
+
+sw.epilog:
+  ret void
+}
+
+!0 = !{!"branch_weights", i32 64, i32 4}
+!1 = !{!"branch_weights", i32 4, i32 64}
+; CHECK: !0 = !{!"branch_weights", i32 256, i32 4352, i32 16}
+!2 = !{!"branch_weights", i32 4, i32 4, i32 8}
+!3 = !{!"branch_weights", i32 8, i32 8, i32 4}
+; CHECK: !1 = !{!"branch_weights", i32 32, i32 48, i32 96, i32 16}
+!4 = !{!"branch_weights", i32 7, i32 6, i32 4, i32 3}
+!5 = !{!"branch_weights", i32 17, i32 13, i32 9}
+; CHECK: !3 = !{!"branch_weights", i32 7, i32 3, i32 4, i32 6}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-branchweights.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,675 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -simplifycfg -S -o - < %s | FileCheck %s
+
+declare void @helper(i32)
+
+define void @test1(i1 %a, i1 %b) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_NOT:%.*]] = xor i1 [[A:%.*]], true
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[A_NOT]], [[C]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof !0
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %a, label %Y, label %X, !prof !0
+
+X:
+  %c = or i1 %b, false
+  br i1 %c, label %Z, label %Y, !prof !1
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+; Make sure the metadata name string is "branch_weights" before propagating it.
+
+define void @fake_weights(i1 %a, i1 %b) {
+; CHECK-LABEL: @fake_weights(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_NOT:%.*]] = xor i1 [[A:%.*]], true
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[A_NOT]], [[C]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof !1
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %a, label %Y, label %X, !prof !12
+X:
+  %c = or i1 %b, false
+  br i1 %c, label %Z, label %Y, !prof !1
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+define void @test2(i1 %a, i1 %b) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[A:%.*]], [[C]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof !2
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %a, label %X, label %Y, !prof !1
+
+X:
+  %c = or i1 %b, false
+  br i1 %c, label %Z, label %Y, !prof !2
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+define void @test3(i1 %a, i1 %b) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[A:%.*]], [[C]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof !1
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %a, label %X, label %Y, !prof !1
+
+X:
+  %c = or i1 %b, false
+  br i1 %c, label %Z, label %Y
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+define void @test4(i1 %a, i1 %b) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[A:%.*]], [[C]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof !1
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %a, label %X, label %Y
+
+X:
+  %c = or i1 %b, false
+  br i1 %c, label %Z, label %Y, !prof !1
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+;; test5 - The case where it jumps to the default target will be removed.
+define void @test5(i32 %M, i32 %N) nounwind uwtable {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[N:%.*]], label [[SW2:%.*]] [
+; CHECK-NEXT:    i32 3, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 2, label [[SW_BB:%.*]]
+; CHECK-NEXT:    ], !prof !3
+; CHECK:       sw.bb:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    br label [[SW_EPILOG:%.*]]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw2:
+; CHECK-NEXT:    call void @helper(i32 2)
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.epilog:
+; CHECK-NEXT:    ret void
+;
+entry:
+  switch i32 %N, label %sw2 [
+  i32 1, label %sw2
+  i32 2, label %sw.bb
+  i32 3, label %sw.bb1
+  ], !prof !3
+
+sw.bb:
+  call void @helper(i32 0)
+  br label %sw.epilog
+
+sw.bb1:
+  call void @helper(i32 1)
+  br label %sw.epilog
+
+sw2:
+  call void @helper(i32 2)
+  br label %sw.epilog
+
+sw.epilog:
+  ret void
+}
+
+;; test6 - Some cases of the second switch are pruned during optimization.
+;; Then the second switch will be converted to a branch, finally, the first
+;; switch and the branch will be merged into a single switch.
+define void @test6(i32 %M, i32 %N) nounwind uwtable {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[N:%.*]], label [[SW_EPILOG:%.*]] [
+; CHECK-NEXT:    i32 3, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 2, label [[SW_BB:%.*]]
+; CHECK-NEXT:    i32 4, label [[SW_BB5:%.*]]
+; CHECK-NEXT:    ], !prof !4
+; CHECK:       sw.bb:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.bb5:
+; CHECK-NEXT:    call void @helper(i32 3)
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.epilog:
+; CHECK-NEXT:    ret void
+;
+entry:
+  switch i32 %N, label %sw2 [
+  i32 1, label %sw2
+  i32 2, label %sw.bb
+  i32 3, label %sw.bb1
+  ], !prof !4
+
+sw.bb:
+  call void @helper(i32 0)
+  br label %sw.epilog
+
+sw.bb1:
+  call void @helper(i32 1)
+  br label %sw.epilog
+
+sw2:
+;; Here "case 2" is invalidated since the default case of the first switch
+;; does not include "case 2".
+  switch i32 %N, label %sw.epilog [
+  i32 2, label %sw.bb4
+  i32 4, label %sw.bb5
+  ], !prof !5
+
+sw.bb4:
+  call void @helper(i32 2)
+  br label %sw.epilog
+
+sw.bb5:
+  call void @helper(i32 3)
+  br label %sw.epilog
+
+sw.epilog:
+  ret void
+}
+
+;; This test is based on test1 but swapped the targets of the second branch.
+define void @test1_swap(i1 %a, i1 %b) {
+; CHECK-LABEL: @test1_swap(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[A:%.*]], [[C]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[Y:%.*]], label [[Z:%.*]], !prof !5
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %a, label %Y, label %X, !prof !0
+
+X:
+  %c = or i1 %b, false
+  br i1 %c, label %Y, label %Z, !prof !1
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+define void @test7(i1 %a, i1 %b) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[C:%.*]] = or i1 [[B:%.*]], false
+; CHECK-NEXT:    [[BRMERGE:%.*]] = or i1 [[A:%.*]], [[C]]
+; CHECK-NEXT:    br i1 [[BRMERGE]], label [[Y:%.*]], label [[Z:%.*]], !prof !6
+; CHECK:       Y:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+; CHECK:       Z:
+; CHECK-NEXT:    call void @helper(i32 1)
+; CHECK-NEXT:    ret void
+;
+entry:
+  %c = or i1 %b, false
+  br i1 %a, label %Y, label %X, !prof !0
+
+X:
+  br i1 %c, label %Y, label %Z, !prof !6
+
+Y:
+  call void @helper(i32 0)
+  ret void
+
+Z:
+  call void @helper(i32 1)
+  ret void
+}
+
+; Test basic folding to a conditional branch.
+define void @test8(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LT:%.*]] = icmp slt i64 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    br i1 [[LT]], label [[A:%.*]], label [[B:%.*]], !prof !7
+; CHECK:       a:
+; CHECK-NEXT:    call void @helper(i32 0) #1
+; CHECK-NEXT:    ret void
+; CHECK:       b:
+; CHECK-NEXT:    call void @helper(i32 1) #1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %lt = icmp slt i64 %x, %y
+  %qux = select i1 %lt, i32 0, i32 2
+  switch i32 %qux, label %bees [
+  i32 0, label %a
+  i32 1, label %b
+  i32 2, label %b
+  ], !prof !7
+a:
+  call void @helper(i32 0) nounwind
+  ret void
+b:
+  call void @helper(i32 1) nounwind
+  ret void
+bees:
+  call void @helper(i32 2) nounwind
+  ret void
+}
+
+; Test edge splitting when the default target has icmp and unconditinal
+; branch
+define i1 @test9(i32 %x, i32 %y) nounwind {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[X:%.*]], label [[BEES:%.*]] [
+; CHECK-NEXT:    i32 0, label [[A:%.*]]
+; CHECK-NEXT:    i32 1, label [[END:%.*]]
+; CHECK-NEXT:    i32 2, label [[END]]
+; CHECK-NEXT:    i32 92, label [[END]]
+; CHECK-NEXT:    ], !prof !8
+; CHECK:       a:
+; CHECK-NEXT:    call void @helper(i32 0) #1
+; CHECK-NEXT:    [[RETA:%.*]] = icmp slt i32 [[X]], [[Y:%.*]]
+; CHECK-NEXT:    ret i1 [[RETA]]
+; CHECK:       bees:
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[BEES]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT:    call void @helper(i32 2) #1
+; CHECK-NEXT:    ret i1 [[RET]]
+;
+entry:
+  switch i32 %x, label %bees [
+  i32 0, label %a
+  i32 1, label %end
+  i32 2, label %end
+  ], !prof !7
+
+a:
+  call void @helper(i32 0) nounwind
+  %reta = icmp slt i32 %x, %y
+  ret i1 %reta
+
+bees:
+  %tmp = icmp eq i32 %x, 92
+  br label %end
+
+end:
+  %ret = phi i1 [ true, %entry ], [%tmp, %bees], [true, %entry]
+  call void @helper(i32 2) nounwind
+  ret i1 %ret
+}
+
+define void @test10(i32 %x) nounwind readnone ssp noredzone {
+; CHECK-LABEL: @test10(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
+; CHECK-NEXT:    br i1 [[SWITCH]], label [[LOR_END:%.*]], label [[LOR_RHS:%.*]], !prof !9
+; CHECK:       lor.rhs:
+; CHECK-NEXT:    call void @helper(i32 1) #1
+; CHECK-NEXT:    ret void
+; CHECK:       lor.end:
+; CHECK-NEXT:    call void @helper(i32 0) #1
+; CHECK-NEXT:    ret void
+;
+entry:
+  switch i32 %x, label %lor.rhs [
+  i32 2, label %lor.end
+  i32 1, label %lor.end
+  i32 3, label %lor.end
+  ], !prof !7
+
+lor.rhs:
+  call void @helper(i32 1) nounwind
+  ret void
+
+lor.end:
+  call void @helper(i32 0) nounwind
+  ret void
+
+}
+
+; Remove dead cases from the switch.
+define void @test11(i32 %x) nounwind {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT:    [[I:%.*]] = shl i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I]], 24
+; CHECK-NEXT:    br i1 [[COND]], label [[C:%.*]], label [[A:%.*]], !prof !10
+; CHECK:       a:
+; CHECK-NEXT:    call void @helper(i32 0) #1
+; CHECK-NEXT:    ret void
+; CHECK:       c:
+; CHECK-NEXT:    call void @helper(i32 2) #1
+; CHECK-NEXT:    ret void
+;
+  %i = shl i32 %x, 1
+  switch i32 %i, label %a [
+  i32 21, label %b
+  i32 24, label %c
+  ], !prof !8
+
+a:
+  call void @helper(i32 0) nounwind
+  ret void
+b:
+  call void @helper(i32 1) nounwind
+  ret void
+c:
+  call void @helper(i32 2) nounwind
+  ret void
+}
+
+;; test12 - Don't crash if the whole switch is removed
+define void @test12(i32 %M, i32 %N) nounwind uwtable {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void @helper(i32 0)
+; CHECK-NEXT:    ret void
+;
+entry:
+  switch i32 %N, label %sw.bb [
+  i32 1, label %sw.bb
+  ], !prof !9
+
+sw.bb:
+  call void @helper(i32 0)
+  br label %sw.epilog
+
+sw.epilog:
+  ret void
+}
+
+;; If every case is dead, make sure they are all removed. This used to
+;; crash trying to merge the metadata.
+define void @test13(i32 %x) nounwind {
+; CHECK-LABEL: @test13(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void @helper(i32 0) #1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %i = shl i32 %x, 1
+  switch i32 %i, label %a [
+  i32 21, label %b
+  i32 25, label %c
+  ], !prof !8
+
+a:
+  call void @helper(i32 0) nounwind
+  ret void
+b:
+  call void @helper(i32 1) nounwind
+  ret void
+c:
+  call void @helper(i32 2) nounwind
+  ret void
+}
+
+;; When folding branches to common destination, the updated branch weights
+;; can exceed uint32 by more than factor of 2. We should keep halving the
+;; weights until they can fit into uint32.
+ at max_regno = common global i32 0, align 4
+define void @test14(i32* %old, i32 %final) {
+; CHECK-LABEL: @test14(
+; CHECK-NEXT:  for.cond:
+; CHECK-NEXT:    br label [[FOR_COND2:%.*]]
+; CHECK:       for.cond2:
+; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[INC19:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_COND:%.*]] ]
+; CHECK-NEXT:    [[BIT_0:%.*]] = phi i32 [ [[SHL:%.*]], [[FOR_INC]] ], [ 1, [[FOR_COND]] ]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[BIT_0]], 0
+; CHECK-NEXT:    [[V3:%.*]] = load i32, i32* @max_regno, align 4
+; CHECK-NEXT:    [[CMP4:%.*]] = icmp eq i32 [[I_1]], [[V3]]
+; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[CMP4]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[FOR_EXIT:%.*]], label [[FOR_INC]], !prof !11
+; CHECK:       for.inc:
+; CHECK-NEXT:    [[SHL]] = shl i32 [[BIT_0]], 1
+; CHECK-NEXT:    [[INC19]] = add nsw i32 [[I_1]], 1
+; CHECK-NEXT:    br label [[FOR_COND2]]
+; CHECK:       for.exit:
+; CHECK-NEXT:    ret void
+;
+for.cond:
+  br label %for.cond2
+for.cond2:
+  %i.1 = phi i32 [ %inc19, %for.inc ], [ 0, %for.cond ]
+  %bit.0 = phi i32 [ %shl, %for.inc ], [ 1, %for.cond ]
+  %tobool = icmp eq i32 %bit.0, 0
+  br i1 %tobool, label %for.exit, label %for.body3, !prof !10
+for.body3:
+  %v3 = load i32, i32* @max_regno, align 4
+  %cmp4 = icmp eq i32 %i.1, %v3
+  br i1 %cmp4, label %for.exit, label %for.inc, !prof !11
+for.inc:
+  %shl = shl i32 %bit.0, 1
+  %inc19 = add nsw i32 %i.1, 1
+  br label %for.cond2
+for.exit:
+  ret void
+}
+
+; Don't drop the metadata.
+
+define i32 @HoistThenElseCodeToIf(i32 %n) {
+; CHECK-LABEL: @HoistThenElseCodeToIf(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[N:%.*]], 0
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL]], i32 1, i32 234, !prof !12
+; CHECK-NEXT:    ret i32 [[DOT]]
+;
+entry:
+  %tobool = icmp eq i32 %n, 0
+  br i1 %tobool, label %if, label %else, !prof !0
+
+if:
+  br label %return
+
+else:
+  br label %return
+
+return:
+  %retval.0 = phi i32 [ 1, %if ], [ 234, %else ]
+  ret i32 %retval.0
+}
+
+; The selects should have freshly calculated branch weights.
+
+define i32 @SimplifyCondBranchToCondBranch(i1 %cmpa, i1 %cmpb) {
+; CHECK-LABEL: @SimplifyCondBranchToCondBranch(
+; CHECK-NEXT:  block1:
+; CHECK-NEXT:    [[BRMERGE:%.*]] = or i1 [[CMPA:%.*]], [[CMPB:%.*]]
+; CHECK-NEXT:    [[DOTMUX:%.*]] = select i1 [[CMPA]], i32 0, i32 2, !prof !13
+; CHECK-NEXT:    [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof !14
+; CHECK-NEXT:    ret i32 [[OUTVAL]]
+;
+block1:
+  br i1 %cmpa, label %block3, label %block2, !prof !13
+
+block2:
+  br i1 %cmpb, label %block3, label %exit, !prof !14
+
+block3:
+  %cowval = phi i32 [ 2, %block2 ], [ 0, %block1 ]
+  br label %exit
+
+exit:
+  %outval = phi i32 [ %cowval, %block3 ], [ 1, %block2 ]
+  ret i32 %outval
+}
+
+; Swap the operands of the compares to verify that the weights update correctly.
+
+define i32 @SimplifyCondBranchToCondBranchSwap(i1 %cmpa, i1 %cmpb) {
+; CHECK-LABEL: @SimplifyCondBranchToCondBranchSwap(
+; CHECK-NEXT:  block1:
+; CHECK-NEXT:    [[CMPA_NOT:%.*]] = xor i1 [[CMPA:%.*]], true
+; CHECK-NEXT:    [[CMPB_NOT:%.*]] = xor i1 [[CMPB:%.*]], true
+; CHECK-NEXT:    [[BRMERGE:%.*]] = or i1 [[CMPA_NOT]], [[CMPB_NOT]]
+; CHECK-NEXT:    [[DOTMUX:%.*]] = select i1 [[CMPA_NOT]], i32 0, i32 2, !prof !15
+; CHECK-NEXT:    [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof !16
+; CHECK-NEXT:    ret i32 [[OUTVAL]]
+;
+block1:
+  br i1 %cmpa, label %block2, label %block3, !prof !13
+
+block2:
+  br i1 %cmpb, label %exit, label %block3, !prof !14
+
+block3:
+  %cowval = phi i32 [ 2, %block2 ], [ 0, %block1 ]
+  br label %exit
+
+exit:
+  %outval = phi i32 [ %cowval, %block3 ], [ 1, %block2 ]
+  ret i32 %outval
+}
+
+define i32 @SimplifyCondBranchToCondBranchSwapMissingWeight(i1 %cmpa, i1 %cmpb) {
+; CHECK-LABEL: @SimplifyCondBranchToCondBranchSwapMissingWeight(
+; CHECK-NEXT:  block1:
+; CHECK-NEXT:    [[CMPA_NOT:%.*]] = xor i1 [[CMPA:%.*]], true
+; CHECK-NEXT:    [[CMPB_NOT:%.*]] = xor i1 [[CMPB:%.*]], true
+; CHECK-NEXT:    [[BRMERGE:%.*]] = or i1 [[CMPA_NOT]], [[CMPB_NOT]]
+; CHECK-NEXT:    [[DOTMUX:%.*]] = select i1 [[CMPA_NOT]], i32 0, i32 2, !prof !17
+; CHECK-NEXT:    [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof !18
+; CHECK-NEXT:    ret i32 [[OUTVAL]]
+;
+block1:
+  br i1 %cmpa, label %block2, label %block3, !prof !13
+
+block2:
+  br i1 %cmpb, label %exit, label %block3
+
+block3:
+  %cowval = phi i32 [ 2, %block2 ], [ 0, %block1 ]
+  br label %exit
+
+exit:
+  %outval = phi i32 [ %cowval, %block3 ], [ 1, %block2 ]
+  ret i32 %outval
+}
+
+!0 = !{!"branch_weights", i32 3, i32 5}
+!1 = !{!"branch_weights", i32 1, i32 1}
+!2 = !{!"branch_weights", i32 1, i32 2}
+!3 = !{!"branch_weights", i32 4, i32 3, i32 2, i32 1}
+!4 = !{!"branch_weights", i32 4, i32 3, i32 2, i32 1}
+!5 = !{!"branch_weights", i32 7, i32 6, i32 5}
+!6 = !{!"branch_weights", i32 1, i32 3}
+!7 = !{!"branch_weights", i32 33, i32 9, i32 8, i32 7}
+!8 = !{!"branch_weights", i32 33, i32 9, i32 8}
+!9 = !{!"branch_weights", i32 7, i32 6}
+!10 = !{!"branch_weights", i32 672646, i32 21604207}
+!11 = !{!"branch_weights", i32 6960, i32 21597248}
+!12 = !{!"these_are_not_the_branch_weights_you_are_looking_for", i32 3, i32 5}
+!13 = !{!"branch_weights", i32 2, i32 3}
+!14 = !{!"branch_weights", i32 4, i32 7}
+
+; CHECK: !0 = !{!"branch_weights", i32 5, i32 11}
+; CHECK: !1 = !{!"branch_weights", i32 1, i32 3}
+; CHECK: !2 = !{!"branch_weights", i32 1, i32 5}
+; CHECK: !3 = !{!"branch_weights", i32 7, i32 1, i32 2}
+; CHECK: !4 = !{!"branch_weights", i32 49, i32 12, i32 24, i32 35}
+; CHECK: !5 = !{!"branch_weights", i32 11, i32 5}
+; CHECK: !6 = !{!"branch_weights", i32 17, i32 15}
+; CHECK: !7 = !{!"branch_weights", i32 9, i32 7}
+; CHECK: !8 = !{!"branch_weights", i32 17, i32 9, i32 8, i32 7, i32 17}
+; CHECK: !9 = !{!"branch_weights", i32 24, i32 33}
+; CHECK: !10 = !{!"branch_weights", i32 8, i32 33}
+;; The false weight prints out as a negative integer here, but inside llvm, we
+;; treat the weight as an unsigned integer.
+; CHECK: !11 = !{!"branch_weights", i32 112017436, i32 -735157296}
+; CHECK: !12 = !{!"branch_weights", i32 3, i32 5}
+; CHECK: !13 = !{!"branch_weights", i32 22, i32 12}
+; CHECK: !14 = !{!"branch_weights", i32 34, i32 21}
+; CHECK: !15 = !{!"branch_weights", i32 33, i32 14}
+; CHECK: !16 = !{!"branch_weights", i32 47, i32 8}
+; CHECK: !17 = !{!"branch_weights", i32 6, i32 2}
+; CHECK: !18 = !{!"branch_weights", i32 8, i32 2}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt -simplifycfg -keep-loops=false -S < %s | FileCheck %s
+; RUN: opt -passes='simplify-cfg<no-keep-loops>' -S < %s | FileCheck %s
+
+define void @test1(i32 %n) #0 {
+entry:
+  %n.addr = alloca i32, align 4
+  %count = alloca i32, align 4
+  store i32 %n, i32* %n.addr, align 4
+  %0 = bitcast i32* %count to i8*
+  store i32 0, i32* %count, align 4
+  br label %while.cond
+
+while.cond:                                       ; preds = %if.end, %entry
+  %1 = load i32, i32* %count, align 4
+  %2 = load i32, i32* %n.addr, align 4
+  %cmp = icmp ule i32 %1, %2
+  br i1 %cmp, label %while.body, label %while.end
+
+while.body:                                       ; preds = %while.cond
+  %3 = load i32, i32* %count, align 4
+  %rem = urem i32 %3, 2
+  %cmp1 = icmp eq i32 %rem, 0
+  br i1 %cmp1, label %if.then, label %if.else
+
+if.then:                                          ; preds = %while.body
+  %4 = load i32, i32* %count, align 4
+  %add = add i32 %4, 1
+  store i32 %add, i32* %count, align 4
+  br label %if.end
+
+; CHECK: if.then:
+; CHECK:  br label %while.cond, !llvm.loop !0
+
+if.else:                                          ; preds = %while.body
+  %5 = load i32, i32* %count, align 4
+  %add2 = add i32 %5, 2
+  store i32 %add2, i32* %count, align 4
+  br label %if.end
+
+; CHECK: if.else:
+; CHECK:  br label %while.cond, !llvm.loop !0
+
+if.end:                                           ; preds = %if.else, %if.then
+  br label %while.cond, !llvm.loop !0
+
+while.end:                                        ; preds = %while.cond
+  %6 = bitcast i32* %count to i8*
+  ret void
+}
+
+!0 = distinct !{!0, !1}
+!1 = !{!"llvm.loop.distribute.enable", i1 true}
+; CHECK: !0 = distinct !{!0, !1}
+; CHECK: !1 = !{!"llvm.loop.distribute.enable", i1 true}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-2.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @bar(i32*)
+declare void @baz(i32*)
+
+; CHECK-LABEL: @test_load_combine_metadata(
+; Check that dereferenceable metadata is combined
+; CHECK: load i32*, i32** %p
+; CHECK-SAME: !dereferenceable ![[DEREF:[0-9]+]]
+; CHECK: t:
+; CHECK: f:
+define void @test_load_combine_metadata(i1 %c, i32** %p) {
+  br i1 %c, label %t, label %f
+
+t:
+  %v1 = load i32*, i32** %p, !dereferenceable !0
+  call void @bar(i32* %v1)
+  br label %cont
+
+f:
+  %v2 = load i32*, i32** %p, !dereferenceable !1
+  call void @baz(i32* %v2)
+  br label %cont
+
+cont:
+  ret void
+}
+
+; CHECK: ![[DEREF]] = !{i64 8}
+
+!0 = !{i64 8}
+!1 = !{i64 16}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-3.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-3.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata-3.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @bar(i32*)
+declare void @baz(i32*)
+
+; CHECK-LABEL: @test_load_combine_metadata(
+; Check that dereferenceable_or_null metadata is combined
+; CHECK: load i32*, i32** %p
+; CHECK-SAME: !dereferenceable_or_null ![[DEREF:[0-9]+]]
+; CHECK: t:
+; CHECK: f:
+define void @test_load_combine_metadata(i1 %c, i32** %p) {
+  br i1 %c, label %t, label %f
+
+t:
+  %v1 = load i32*, i32** %p, !dereferenceable_or_null !0
+  call void @bar(i32* %v1)
+  br label %cont
+
+f:
+  %v2 = load i32*, i32** %p, !dereferenceable_or_null !1
+  call void @baz(i32* %v2)
+  br label %cont
+
+cont:
+  ret void
+}
+
+; CHECK: ![[DEREF]] = !{i64 8}
+
+!0 = !{i64 8}
+!1 = !{i64 16}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-load-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+declare void @bar(i32*)
+declare void @baz(i32*)
+
+; CHECK-LABEL: @test_load_combine_metadata(
+; Check that align metadata is combined
+; CHECK: load i32*, i32** %p
+; CHECK-SAME: !align ![[ALIGN:[0-9]+]]
+; CHECK: t:
+; CHECK: f:
+define void @test_load_combine_metadata(i1 %c, i32** %p) {
+  br i1 %c, label %t, label %f
+
+t:
+  %v1 = load i32*, i32** %p, !align !0
+  call void @bar(i32* %v1)
+  br label %cont
+
+f:
+  %v2 = load i32*, i32** %p, !align !1
+  call void @baz(i32* %v2)
+  br label %cont
+
+cont:
+  ret void
+}
+
+; CHECK: ![[ALIGN]] = !{i64 8}
+
+!0 = !{i64 8}
+!1 = !{i64 16}

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-make-implicit-on-switch-to-br.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-make-implicit-on-switch-to-br.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-make-implicit-on-switch-to-br.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-make-implicit-on-switch-to-br.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt %s -simplifycfg -S | FileCheck %s
+
+; ConstantFoldTerminator function can convert SwitchInst with one case (and default) to
+; a conditional BranchInst. This test checks the converted BranchInst preserve the 
+; make.implicit metadata.
+
+declare i32 @consume(i32*)
+declare void @trap()
+
+define i32 @copy-metadata(i32* %x) {
+
+entry:
+  %x.int = ptrtoint i32* %x to i64
+  
+; CHECK: br i1 %cond, label %is_null, label %default, !make.implicit !0
+  switch i64 %x.int, label %default [
+    i64 0, label %is_null
+  ], !make.implicit !0
+  
+default:
+  %0 = call i32 @consume(i32* %x)
+  ret i32 %0
+
+is_null:
+  call void @trap()
+  unreachable
+}
+
+!0 = !{}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/preserve-store-alignment.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/preserve-store-alignment.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/preserve-store-alignment.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/preserve-store-alignment.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,267 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+%struct.Counters = type { i64, i64, i64, [8 x i8] }
+
+ at m = global i64 3, align 8
+ at counters = global %struct.Counters zeroinitializer, align 16
+
+define i32 @align_both_equal() local_unnamed_addr {
+; CHECK-LABEL: @align_both_equal(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
+; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
+; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
+; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
+; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
+; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
+; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
+; CHECK:         store <2 x i64> [[DOT]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    br label [[TMP10]]
+; CHECK:         ret i32 0
+;
+entry:
+  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
+  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %2 = load i64, i64* @m, align 8
+  %and = and i64 %2, 1
+  %tobool = icmp eq i64 %and, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
+  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
+  %and4 = and i64 %2, 2
+  %tobool5 = icmp eq i64 %and4, 0
+  br i1 %tobool5, label %if.end9, label %if.then6
+
+if.then6:                                         ; preds = %if.end
+  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
+  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  br label %if.end9
+
+if.end9:                                          ; preds = %if.end, %if.then6
+  ret i32 0
+}
+
+define i32 @align_not_equal() local_unnamed_addr {
+; CHECK-LABEL: @align_not_equal(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
+; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
+; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
+; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
+; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
+; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
+; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
+; CHECK:         store <2 x i64> [[DOT]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    br label [[TMP10]]
+; CHECK:         ret i32 0
+;
+entry:
+  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
+  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %2 = load i64, i64* @m, align 8
+  %and = and i64 %2, 1
+  %tobool = icmp eq i64 %and, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
+  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 16
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
+  %and4 = and i64 %2, 2
+  %tobool5 = icmp eq i64 %and4, 0
+  br i1 %tobool5, label %if.end9, label %if.then6
+
+if.then6:                                         ; preds = %if.end
+  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
+  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  br label %if.end9
+
+if.end9:                                          ; preds = %if.end, %if.then6
+  ret i32 0
+}
+
+define i32 @align_single_zero() local_unnamed_addr {
+; CHECK-LABEL: @align_single_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
+; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
+; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
+; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
+; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
+; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
+; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
+; CHECK:         store <2 x i64> [[DOT]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    br label [[TMP10]]
+; CHECK:         ret i32 0
+;
+entry:
+  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
+  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %2 = load i64, i64* @m, align 8
+  %and = and i64 %2, 1
+  %tobool = icmp eq i64 %and, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
+  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
+  %and4 = and i64 %2, 2
+  %tobool5 = icmp eq i64 %and4, 0
+  br i1 %tobool5, label %if.end9, label %if.then6
+
+if.then6:                                         ; preds = %if.end
+  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
+  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  br label %if.end9
+
+if.end9:                                          ; preds = %if.end, %if.then6
+  ret i32 0
+}
+
+define i32 @align_single_zero_second_greater_default() local_unnamed_addr {
+; CHECK-LABEL: @align_single_zero_second_greater_default(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
+; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
+; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
+; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
+; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
+; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
+; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
+; CHECK:         store <2 x i64> [[DOT]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 16
+; CHECK-NEXT:    br label [[TMP10]]
+; CHECK:         ret i32 0
+;
+entry:
+  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
+  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %2 = load i64, i64* @m, align 8
+  %and = and i64 %2, 1
+  %tobool = icmp eq i64 %and, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
+  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 32
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
+  %and4 = and i64 %2, 2
+  %tobool5 = icmp eq i64 %and4, 0
+  br i1 %tobool5, label %if.end9, label %if.then6
+
+if.then6:                                         ; preds = %if.end
+  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
+  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
+  br label %if.end9
+
+if.end9:                                          ; preds = %if.end, %if.then6
+  ret i32 0
+}
+
+define i32 @align_both_zero() local_unnamed_addr {
+; CHECK-LABEL: @align_both_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 1, i64 1>
+; CHECK-NEXT:    store <2 x i64> [[TMP1]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64* @m, align 8
+; CHECK-NEXT:    [[AND:%.*]] = and i64 [[TMP2]], 1
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw <2 x i64> [[TMP0]], <i64 2, i64 2>
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TOBOOL]], <2 x i64> [[TMP1]], <2 x i64> [[TMP3]]
+; CHECK-NEXT:    [[AND4:%.*]] = and i64 [[TMP2]], 2
+; CHECK-NEXT:    [[TOBOOL5:%.*]] = icmp eq i64 [[AND4]], 0
+; CHECK-NEXT:    [[TMP5:%.*]] = add nsw <2 x i64> [[TMP4]], <i64 1, i64 1>
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[TOBOOL5]], <2 x i64> [[TMP4]], <2 x i64> [[TMP5]]
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[TOBOOL]], true
+; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TOBOOL5]], true
+; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP10:%.*]]
+; CHECK:         store <2 x i64> [[DOT]], <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 16
+; CHECK-NEXT:    br label [[TMP10]]
+; CHECK:         ret i32 0
+;
+entry:
+  %0 = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %1 = add nsw <2 x i64> %0, <i64 1, i64 1>
+  store <2 x i64> %1, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*), align 8
+  %2 = load i64, i64* @m, align 8
+  %and = and i64 %2, 1
+  %tobool = icmp eq i64 %and, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  %3 = add nsw <2 x i64> %0, <i64 2, i64 2>
+  store <2 x i64> %3, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
+  br label %if.end
+
+if.end:                                           ; preds = %entry, %if.then
+  %4 = phi <2 x i64> [ %1, %entry ], [ %3, %if.then ]
+  %and4 = and i64 %2, 2
+  %tobool5 = icmp eq i64 %and4, 0
+  br i1 %tobool5, label %if.end9, label %if.then6
+
+if.then6:                                         ; preds = %if.end
+  %5 = add nsw <2 x i64> %4, <i64 1, i64 1>
+  store <2 x i64> %5, <2 x i64>* bitcast (i64* getelementptr inbounds (%struct.Counters, %struct.Counters* @counters, i64 0, i32 1) to <2 x i64>*)
+  br label %if.end9
+
+if.end9:                                          ; preds = %if.end, %if.then6
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/rangereduce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/rangereduce.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/rangereduce.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/rangereduce.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,347 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -switch-to-lookup -S | FileCheck %s
+; RUN: opt < %s -passes='simplify-cfg<switch-to-lookup>' -S | FileCheck %s
+
+target datalayout = "e-n32"
+
+define i32 @test1(i32 %a) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], 97
+; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[TMP1]], 30
+; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    switch i32 [[TMP4]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 0, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 1, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 2, label [[THREE:%.*]]
+; CHECK-NEXT:    i32 3, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 97, label %one
+  i32 101, label %two
+  i32 105, label %three
+  i32 109, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+
+; Optimization shouldn't trigger; bitwidth > 64
+define i128 @test2(i128 %a) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    switch i128 [[A:%.*]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i128 97, label [[ONE:%.*]]
+; CHECK-NEXT:    i128 101, label [[TWO:%.*]]
+; CHECK-NEXT:    i128 105, label [[THREE:%.*]]
+; CHECK-NEXT:    i128 109, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i128 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i128 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i128 %a, label %def [
+  i128 97, label %one
+  i128 101, label %two
+  i128 105, label %three
+  i128 109, label %three
+  ]
+
+def:
+  ret i128 8867
+
+one:
+  ret i128 11984
+two:
+  ret i128 1143
+three:
+  ret i128 99783
+}
+
+; Optimization shouldn't trigger; no holes present
+define i32 @test3(i32 %a) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    switch i32 [[A:%.*]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 97, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 98, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 99, label [[THREE:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 97, label %one
+  i32 98, label %two
+  i32 99, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+
+; Optimization shouldn't trigger; not an arithmetic progression
+define i32 @test4(i32 %a) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    switch i32 [[A:%.*]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 97, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 102, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 105, label [[THREE:%.*]]
+; CHECK-NEXT:    i32 109, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 97, label %one
+  i32 102, label %two
+  i32 105, label %three
+  i32 109, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+
+; Optimization shouldn't trigger; not a power of two
+define i32 @test5(i32 %a) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    switch i32 [[A:%.*]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 97, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 102, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 107, label [[THREE:%.*]]
+; CHECK-NEXT:    i32 112, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 97, label %one
+  i32 102, label %two
+  i32 107, label %three
+  i32 112, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+
+define i32 @test6(i32 %a) optsize {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], -109
+; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[TMP1]], 30
+; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    switch i32 [[TMP4]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 3, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 2, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 1, label [[THREE:%.*]]
+; CHECK-NEXT:    i32 0, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 -97, label %one
+  i32 -101, label %two
+  i32 -105, label %three
+  i32 -109, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+
+define i8 @test7(i8 %a) optsize {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 [[A:%.*]], -36
+; CHECK-NEXT:    [[TMP2:%.*]] = lshr i8 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP3:%.*]] = shl i8 [[TMP1]], 6
+; CHECK-NEXT:    [[TMP4:%.*]] = or i8 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult i8 [[TMP4]], 4
+; CHECK-NEXT:    br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[DEF:%.*]]
+; CHECK:       switch.lookup:
+; CHECK-NEXT:    [[SWITCH_CAST:%.*]] = zext i8 [[TMP4]] to i32
+; CHECK-NEXT:    [[SWITCH_SHIFTAMT:%.*]] = mul i32 [[SWITCH_CAST]], 8
+; CHECK-NEXT:    [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 -943228976, [[SWITCH_SHIFTAMT]]
+; CHECK-NEXT:    [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8
+; CHECK-NEXT:    ret i8 [[SWITCH_MASKED]]
+; CHECK:       def:
+; CHECK-NEXT:    ret i8 -93
+;
+  switch i8 %a, label %def [
+  i8 220, label %one
+  i8 224, label %two
+  i8 228, label %three
+  i8 232, label %three
+  ]
+
+def:
+  ret i8 8867
+
+one:
+  ret i8 11984
+two:
+  ret i8 1143
+three:
+  ret i8 99783
+}
+
+define i32 @test8(i32 %a) optsize {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], 97
+; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[TMP1]], 30
+; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    switch i32 [[TMP4]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 0, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 1, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 2, label [[THREE:%.*]]
+; CHECK-NEXT:    i32 4, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 97, label %one
+  i32 101, label %two
+  i32 105, label %three
+  i32 113, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+
+define i32 @test9(i32 %a) {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[A:%.*]], 6
+; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[TMP1]], 31
+; CHECK-NEXT:    [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    switch i32 [[TMP4]], label [[DEF:%.*]] [
+; CHECK-NEXT:    i32 6, label [[ONE:%.*]]
+; CHECK-NEXT:    i32 7, label [[TWO:%.*]]
+; CHECK-NEXT:    i32 0, label [[THREE:%.*]]
+; CHECK-NEXT:    i32 2, label [[THREE]]
+; CHECK-NEXT:    ]
+; CHECK:       def:
+; CHECK-NEXT:    [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ]
+; CHECK-NEXT:    ret i32 [[MERGE]]
+; CHECK:       one:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       two:
+; CHECK-NEXT:    br label [[DEF]]
+; CHECK:       three:
+; CHECK-NEXT:    br label [[DEF]]
+;
+  switch i32 %a, label %def [
+  i32 18, label %one
+  i32 20, label %two
+  i32 6, label %three
+  i32 10, label %three
+  ]
+
+def:
+  ret i32 8867
+
+one:
+  ret i32 11984
+two:
+  ret i32 1143
+three:
+  ret i32 99783
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/remove-debug-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/remove-debug-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/remove-debug-2.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/remove-debug-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Check that the debug location for the hoisted store for "ret = 0" is a
+; line-0 location.
+;
+; int foo(int x) {
+;   int ret = 1;
+;   if (x)
+;     ret = 0;
+;   return ret;
+; }
+;
+; CHECK: store i32 1,{{.+}}!dbg ![[DLOC1:[0-9]+]]
+; CHECK: icmp ne {{.+}}!dbg ![[DLOC2:[0-9]+]]
+; CHECK: [[VREG:%[^ ]+]] = select
+; CHECK: store i32 [[VREG]],{{.*}} !dbg [[storeLoc:![0-9]+]]
+; CHECK: ret {{.+}}!dbg ![[DLOC3:[0-9]+]]
+; CHECK: ![[DLOC1]] = !DILocation(line: 2
+; CHECK: ![[DLOC2]] = !DILocation(line: 3
+; CHECK: [[storeLoc]] = !DILocation(line: 0
+; CHECK: ![[DLOC3]] = !DILocation(line: 5
+
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: noinline nounwind uwtable
+define i32 @foo(i32) !dbg !6 {
+  %2 = alloca i32, align 4
+  %3 = alloca i32, align 4
+  store i32 %0, i32* %2, align 4
+  store i32 1, i32* %3, align 4, !dbg !14
+  %4 = load i32, i32* %2, align 4, !dbg !15
+  %5 = icmp ne i32 %4, 0, !dbg !15
+  br i1 %5, label %6, label %7, !dbg !17
+
+; <label>:6:                                      ; preds = %1
+  store i32 0, i32* %3, align 4, !dbg !18
+  br label %7, !dbg !19
+
+; <label>:7:                                      ; preds = %6, %1
+  %8 = load i32, i32* %3, align 4, !dbg !20
+  ret i32 %8, !dbg !21
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
+!1 = !DIFile(filename: "foo.c", directory: "b/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{}
+!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !9}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DILocalVariable(name: "x", arg: 1, scope: !6, file: !1, line: 1, type: !9)
+!11 = !DIExpression()
+!12 = !DILocation(line: 1, column: 13, scope: !6)
+!13 = !DILocalVariable(name: "ret", scope: !6, file: !1, line: 2, type: !9)
+!14 = !DILocation(line: 2, column: 7, scope: !6)
+!15 = !DILocation(line: 3, column: 7, scope: !16)
+!16 = distinct !DILexicalBlock(scope: !6, file: !1, line: 3, column: 7)
+!17 = !DILocation(line: 3, column: 7, scope: !6)
+!18 = !DILocation(line: 4, column: 9, scope: !16)
+!19 = !DILocation(line: 4, column: 5, scope: !16)
+!20 = !DILocation(line: 5, column: 10, scope: !6)
+!21 = !DILocation(line: 5, column: 3, scope: !6)

Added: llvm/trunk/test/Transforms/SimplifyCFG/remove-debug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/remove-debug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/remove-debug.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/remove-debug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,88 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; TODO: Track the acutal DebugLoc of the hoisted instruction when no-line
+; DebugLoc is supported (https://reviews.llvm.org/D24180)
+
+; Checks if the debug info for hoisted "x = i" is removed and
+; the debug info for hoisted "bar()" is set as line 0
+; int x;
+; void bar();
+; void baz();
+;
+; void foo(int i) {
+;   if (i == 0) {
+;     x = i;
+;     bar();
+;   } else {
+;     x = i;
+;     bar();
+;     baz();
+;   }
+; }
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at x = global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3fooi(i32) #0 !dbg !6 {
+; CHECK: load i32, i32* %2, align 4, !dbg ![[LOAD:[0-9]+]], !tbaa
+; CHECK: store i32 %5, i32* @x, align 4, !dbg ![[BAR:[0-9]+]], !tbaa
+; CHECK: call void @_Z3barv(), !dbg ![[BAR]]
+; CHECK: call void @_Z3bazv(), !dbg ![[BAZ:[0-9]+]]
+  %2 = alloca i32, align 4
+  store i32 %0, i32* %2, align 4, !tbaa !8
+  %3 = load i32, i32* %2, align 4, !dbg !12, !tbaa !8
+  %4 = icmp eq i32 %3, 0, !dbg !13
+  br i1 %4, label %5, label %7, !dbg !12
+
+; <label>:5:
+  %6 = load i32, i32* %2, align 4, !dbg !14, !tbaa !8
+  store i32 %6, i32* @x, align 4, !dbg !15, !tbaa !8
+  call void @_Z3barv(), !dbg !16
+  br label %9, !dbg !17
+
+; <label>:7:
+  %8 = load i32, i32* %2, align 4, !dbg !18, !tbaa !8
+  store i32 %8, i32* @x, align 4, !dbg !19, !tbaa !8
+  call void @_Z3barv(), !dbg !20
+  call void @_Z3bazv(), !dbg !21
+  br label %9
+
+; <label>:9:
+  ret void, !dbg !21
+}
+
+declare void @_Z3barv() #1
+
+declare void @_Z3bazv() #1
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+; CHECK: ![[LOAD]] = !DILocation(line: 6, column: 7
+; CHECK: ![[BAR]] = !DILocation(line: 0
+; CHECK: ![[BAZ]] = !DILocation(line: 12, column: 5
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1)
+!1 = !DIFile(filename: "a", directory: "b/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{}
+!6 = distinct !DISubprogram(unit: !0)
+!7 = !DISubroutineType(types: !2)
+!8 = !{!9, !9, i64 0}
+!9 = !{!"int", !10, i64 0}
+!10 = !{!"omnipotent char", !11, i64 0}
+!11 = !{!"Simple C++ TBAA"}
+!12 = !DILocation(line: 6, column: 7, scope: !6)
+!13 = !DILocation(line: 6, column: 9, scope: !6)
+!14 = !DILocation(line: 7, column: 9, scope: !6)
+!15 = !DILocation(line: 7, column: 7, scope: !6)
+!16 = !DILocation(line: 8, column: 5, scope: !6)
+!17 = !DILocation(line: 9, column: 3, scope: !6)
+!18 = !DILocation(line: 10, column: 9, scope: !6)
+!19 = !DILocation(line: 10, column: 7, scope: !6)
+!20 = !DILocation(line: 11, column: 5, scope: !6)
+!21 = !DILocation(line: 12, column: 5, scope: !6)
+!22 = !DILocation(line: 14, column: 1, scope: !6)

Added: llvm/trunk/test/Transforms/SimplifyCFG/return-merge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/return-merge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/return-merge.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/return-merge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -simplifycfg -S | not grep br
+
+define i32 @test1(i1 %C) {
+entry:
+        br i1 %C, label %T, label %F
+T:              ; preds = %entry
+        ret i32 1
+F:              ; preds = %entry
+        ret i32 0
+}
+
+define void @test2(i1 %C) {
+        br i1 %C, label %T, label %F
+T:              ; preds = %0
+        ret void
+F:              ; preds = %0
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/seh-nounwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/seh-nounwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/seh-nounwind.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/seh-nounwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+; Don't remove invokes of nounwind functions if the personality handles async
+; exceptions. The @div function in this test can fault, even though it can't
+; throw a synchronous exception.
+
+define i32 @div(i32 %n, i32 %d) nounwind {
+entry:
+  %div = sdiv i32 %n, %d
+  ret i32 %div
+}
+
+define i32 @main() nounwind personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
+entry:
+  %call = invoke i32 @div(i32 10, i32 0)
+          to label %__try.cont unwind label %lpad
+
+lpad:
+  %0 = landingpad { i8*, i32 }
+          catch i8* null
+  br label %__try.cont
+
+__try.cont:
+  %retval.0 = phi i32 [ %call, %entry ], [ 0, %lpad ]
+  ret i32 %retval.0
+}
+
+; CHECK-LABEL: define i32 @main()
+; CHECK: invoke i32 @div(i32 10, i32 0)
+
+declare i32 @__C_specific_handler(...)

Added: llvm/trunk/test/Transforms/SimplifyCFG/select-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/select-gep.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/select-gep.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/select-gep.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+%ST = type { i8, i8 }
+
+define i8* @test1(%ST* %x, i8* %y) nounwind {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq %ST* [[X:%.*]], null
+; CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr [[ST:%.*]], %ST* [[X]], i32 0, i32 1
+; CHECK-NEXT:    [[INCDEC_PTR_Y:%.*]] = select i1 [[CMP]], i8* [[INCDEC_PTR]], i8* [[Y:%.*]]
+; CHECK-NEXT:    ret i8* [[INCDEC_PTR_Y]]
+;
+entry:
+  %cmp = icmp eq %ST* %x, null
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %incdec.ptr = getelementptr %ST, %ST* %x, i32 0, i32 1
+  br label %if.end
+
+if.end:
+  %x.addr = phi i8* [ %incdec.ptr, %if.then ], [ %y, %entry ]
+  ret i8* %x.addr
+
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/sink-common-code.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/sink-common-code.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/sink-common-code.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/sink-common-code.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,892 @@
+; RUN: opt < %s -simplifycfg -sink-common-insts -S | FileCheck -enable-var-scope %s
+; RUN: opt < %s -passes='simplify-cfg<sink-common-insts>' -S | FileCheck -enable-var-scope %s
+
+define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+; CHECK-LABEL: test1
+; CHECK: add
+; CHECK: select
+; CHECK: icmp
+; CHECK-NOT: br
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = zext i1 %cmp to i8
+  br label %if.end
+
+if.else:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = zext i1 %cmp2 to i8
+  br label %if.end
+
+if.end:
+  %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ]
+  %tobool4 = icmp ne i8 %obeys.0, 0
+  ret i1 %tobool4
+}
+
+define zeroext i1 @test2(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+; CHECK-LABEL: test2
+; CHECK: add
+; CHECK: select
+; CHECK: icmp
+; CHECK-NOT: br
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = zext i1 %cmp to i8
+  br label %if.end
+
+if.else:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp uge i32 %blksA, %add
+  %frombool3 = zext i1 %cmp2 to i8
+  br label %if.end
+
+if.end:
+  %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ]
+  %tobool4 = icmp ne i8 %obeys.0, 0
+  ret i1 %tobool4
+}
+
+declare i32 @foo(i32, i32) nounwind readnone
+
+define i32 @test3(i1 zeroext %flag, i32 %x, i32 %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone
+  %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone
+  br label %if.end
+
+if.else:
+  %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone
+  %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone
+  br label %if.end
+
+if.end:
+  %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ]
+  %yy = phi i32 [ %y0, %if.then ], [ %y1, %if.else ]
+  %ret = add i32 %xx, %yy
+  ret i32 %ret
+}
+
+; CHECK-LABEL: test3
+; CHECK: select
+; CHECK: call
+; CHECK: call
+; CHECK: add
+; CHECK-NOT: br
+
+define i32 @test4(i1 zeroext %flag, i32 %x, i32* %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %a = add i32 %x, 5
+  store i32 %a, i32* %y
+  br label %if.end
+
+if.else:
+  %b = add i32 %x, 7
+  store i32 %b, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test4
+; CHECK: select
+; CHECK: store
+; CHECK-NOT: store
+
+define i32 @test5(i1 zeroext %flag, i32 %x, i32* %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %a = add i32 %x, 5
+  store volatile i32 %a, i32* %y
+  br label %if.end
+
+if.else:
+  %b = add i32 %x, 7
+  store i32 %b, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test5
+; CHECK: store volatile
+; CHECK: store
+
+define i32 @test6(i1 zeroext %flag, i32 %x, i32* %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %a = add i32 %x, 5
+  store volatile i32 %a, i32* %y
+  br label %if.end
+
+if.else:
+  %b = add i32 %x, 7
+  store volatile i32 %b, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test6
+; CHECK: select
+; CHECK: store volatile
+; CHECK-NOT: store
+
+define i32 @test7(i1 zeroext %flag, i32 %x, i32* %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %z = load volatile i32, i32* %y
+  %a = add i32 %z, 5
+  store volatile i32 %a, i32* %y
+  br label %if.end
+
+if.else:
+  %w = load volatile i32, i32* %y
+  %b = add i32 %w, 7
+  store volatile i32 %b, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test7
+; CHECK-DAG: select
+; CHECK-DAG: load volatile
+; CHECK: store volatile
+; CHECK-NOT: load
+; CHECK-NOT: store
+
+; %z and %w are in different blocks. We shouldn't sink the add because
+; there may be intervening memory instructions.
+define i32 @test8(i1 zeroext %flag, i32 %x, i32* %y) {
+entry:
+  %z = load volatile i32, i32* %y
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %a = add i32 %z, 5
+  store volatile i32 %a, i32* %y
+  br label %if.end
+
+if.else:
+  %w = load volatile i32, i32* %y
+  %b = add i32 %w, 7
+  store volatile i32 %b, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test8
+; CHECK: add
+; CHECK: add
+
+; The extra store in %if.then means %z and %w are not equivalent.
+define i32 @test9(i1 zeroext %flag, i32 %x, i32* %y, i32* %p) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  store i32 7, i32* %p
+  %z = load volatile i32, i32* %y
+  store i32 6, i32* %p
+  %a = add i32 %z, 5
+  store volatile i32 %a, i32* %y
+  br label %if.end
+
+if.else:
+  %w = load volatile i32, i32* %y
+  %b = add i32 %w, 7
+  store volatile i32 %b, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test9
+; CHECK: add
+; CHECK: add
+
+%struct.anon = type { i32, i32 }
+
+; The GEP indexes a struct type so cannot have a variable last index.
+define i32 @test10(i1 zeroext %flag, i32 %x, i32* %y, %struct.anon* %s) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %dummy = add i32 %x, 5
+  %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 0
+  store volatile i32 %x, i32* %gepa
+  br label %if.end
+
+if.else:
+  %dummy1 = add i32 %x, 6
+  %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
+  store volatile i32 %x, i32* %gepb
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test10
+; CHECK: getelementptr
+; CHECK: getelementptr
+; CHECK: phi
+; CHECK: store volatile
+
+; The shufflevector's mask operand cannot be merged in a PHI.
+define i32 @test11(i1 zeroext %flag, i32 %w, <2 x i32> %x, <2 x i32> %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %dummy = add i32 %w, 5
+  %sv1 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 0, i32 1>
+  br label %if.end
+
+if.else:
+  %dummy1 = add i32 %w, 6
+  %sv2 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 1, i32 0>
+  br label %if.end
+
+if.end:
+  %p = phi <2 x i32> [ %sv1, %if.then ], [ %sv2, %if.else ]
+  ret i32 1
+}
+
+; CHECK-LABEL: test11
+; CHECK: shufflevector
+; CHECK: shufflevector
+
+; We can't common an intrinsic!
+define i32 @test12(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %dummy = add i32 %w, 5
+  %sv1 = call i32 @llvm.ctlz.i32(i32 %x)
+  br label %if.end
+
+if.else:
+  %dummy1 = add i32 %w, 6
+  %sv2 = call i32 @llvm.cttz.i32(i32 %x)
+  br label %if.end
+
+if.end:
+  %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ]
+  ret i32 1
+}
+
+declare i32 @llvm.ctlz.i32(i32 %x) readnone
+declare i32 @llvm.cttz.i32(i32 %x) readnone
+
+; CHECK-LABEL: test12
+; CHECK: call i32 @llvm.ctlz
+; CHECK: call i32 @llvm.cttz
+
+; The TBAA metadata should be properly combined.
+define i32 @test13(i1 zeroext %flag, i32 %x, i32* %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %z = load volatile i32, i32* %y
+  %a = add i32 %z, 5
+  store volatile i32 %a, i32* %y, !tbaa !3
+  br label %if.end
+
+if.else:
+  %w = load volatile i32, i32* %y
+  %b = add i32 %w, 7
+  store volatile i32 %b, i32* %y, !tbaa !4
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+!0 = !{ !"an example type tree" }
+!1 = !{ !"int", !0 }
+!2 = !{ !"float", !0 }
+!3 = !{ !"const float", !2, i64 0 }
+!4 = !{ !"special float", !2, i64 1 }
+
+; CHECK-LABEL: test13
+; CHECK-DAG: select
+; CHECK-DAG: load volatile
+; CHECK: store volatile {{.*}}, !tbaa ![[$TBAA:[0-9]]]
+; CHECK-NOT: load
+; CHECK-NOT: store
+
+; The call should be commoned.
+define i32 @test13a(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %sv1 = call i32 @bar(i32 %x)
+  br label %if.end
+
+if.else:
+  %sv2 = call i32 @bar(i32 %y)
+  br label %if.end
+
+if.end:
+  %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ]
+  ret i32 1
+}
+declare i32 @bar(i32)
+
+; CHECK-LABEL: test13a
+; CHECK: %[[x:.*]] = select i1 %flag
+; CHECK: call i32 @bar(i32 %[[x]])
+
+; The load should be commoned.
+define i32 @test14(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, %struct.anon* %s) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %dummy = add i32 %x, 1
+  %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
+  %sv1 = load i32, i32* %gepa
+  %cmp1 = icmp eq i32 %sv1, 56
+  br label %if.end
+
+if.else:
+  %dummy2 = add i32 %x, 4
+  %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
+  %sv2 = load i32, i32* %gepb
+  %cmp2 = icmp eq i32 %sv2, 57
+  call void @llvm.dbg.value(metadata i32 0, metadata !9, metadata !DIExpression()), !dbg !11
+  br label %if.end
+
+if.end:
+  %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ]
+  ret i32 1
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+!llvm.module.flags = !{!5, !6}
+!llvm.dbg.cu = !{!7}
+
+!5 = !{i32 2, !"Dwarf Version", i32 4}
+!6 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !10)
+!8 = distinct !DISubprogram(name: "foo", unit: !7)
+!9 = !DILocalVariable(name: "b", line: 1, arg: 2, scope: !8)
+!10 = !DIFile(filename: "a.c", directory: "a/b")
+!11 = !DILocation(line: 1, column: 14, scope: !8)
+
+; CHECK-LABEL: test14
+; CHECK: getelementptr
+; CHECK: load
+; CHECK-NOT: load
+
+; The load should be commoned.
+define i32 @test15(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, %struct.anon* %s) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %dummy = add i32 %x, 1
+  %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 0
+  %sv1 = load i32, i32* %gepa
+  %ext1 = zext i32 %sv1 to i64
+  %cmp1 = icmp eq i64 %ext1, 56
+  br label %if.end
+
+if.else:
+  %dummy2 = add i32 %x, 4
+  %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
+  %sv2 = load i32, i32* %gepb
+  %ext2 = zext i32 %sv2 to i64
+  %cmp2 = icmp eq i64 %ext2, 57
+  br label %if.end
+
+if.end:
+  %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ]
+  ret i32 1
+}
+
+; CHECK-LABEL: test15
+; CHECK: getelementptr
+; CHECK: load
+; CHECK-NOT: load
+
+define zeroext i1 @test_crash(i1 zeroext %flag, i32* %i4, i32* %m, i32* %n) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %tmp1 = load i32, i32* %i4
+  %tmp2 = add i32 %tmp1, -1
+  store i32 %tmp2, i32* %i4
+  br label %if.end
+
+if.else:
+  %tmp3 = load i32, i32* %m
+  %tmp4 = load i32, i32* %n
+  %tmp5 = add i32 %tmp3, %tmp4
+  store i32 %tmp5, i32* %i4
+  br label %if.end
+
+if.end:
+  ret i1 true
+}
+
+; CHECK-LABEL: test_crash
+; No checks for test_crash - just ensure it doesn't crash!
+
+define zeroext i1 @test16(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) {
+
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = zext i1 %cmp to i8
+  br label %if.end
+
+if.else:
+  br i1 %flag2, label %if.then2, label %if.end
+
+if.then2:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = zext i1 %cmp2 to i8
+  br label %if.end
+
+if.end:
+  %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %if.else ]
+  %tobool4 = icmp ne i8 %obeys.0, 0
+  ret i1 %tobool4
+}
+
+; CHECK-LABEL: test16
+; CHECK: zext
+; CHECK: zext
+
+define zeroext i1 @test16a(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks, i8* %p) {
+
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = zext i1 %cmp to i8
+  store i8 %frombool1, i8* %p
+  br label %if.end
+
+if.else:
+  br i1 %flag2, label %if.then2, label %if.end
+
+if.then2:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = zext i1 %cmp2 to i8
+  store i8 %frombool3, i8* %p
+  br label %if.end
+
+if.end:
+  ret i1 true
+}
+
+; CHECK-LABEL: test16a
+; CHECK: zext
+; CHECK-NOT: zext
+
+define zeroext i1 @test17(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
+entry:
+  switch i32 %flag, label %if.end [
+    i32 0, label %if.then
+    i32 1, label %if.then2
+  ]
+
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = call i8 @i1toi8(i1 %cmp)
+  br label %if.end
+
+if.then2:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = call i8 @i1toi8(i1 %cmp2)
+  br label %if.end
+
+if.end:
+  %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %entry ]
+  %tobool4 = icmp ne i8 %obeys.0, 0
+  ret i1 %tobool4
+}
+declare i8 @i1toi8(i1)
+
+; CHECK-LABEL: test17
+; CHECK: if.then:
+; CHECK-NEXT: icmp uge
+; CHECK-NEXT: br label %[[x:.*]]
+
+; CHECK: if.then2:
+; CHECK-NEXT: add
+; CHECK-NEXT: icmp ule
+; CHECK-NEXT: br label %[[x]]
+
+; CHECK: [[x]]:
+; CHECK-NEXT: %[[y:.*]] = phi i1 [ %cmp
+; CHECK-NEXT: %[[z:.*]] = call i8 @i1toi8(i1 %[[y]])
+; CHECK-NEXT: br label %if.end
+
+; CHECK: if.end:
+; CHECK-NEXT: phi i8
+; CHECK-DAG: [ %[[z]], %[[x]] ]
+; CHECK-DAG: [ 0, %entry ]
+
+define zeroext i1 @test18(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
+entry:
+  switch i32 %flag, label %if.then3 [
+    i32 0, label %if.then
+    i32 1, label %if.then2
+  ]
+
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = zext i1 %cmp to i8
+  br label %if.end
+
+if.then2:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = zext i1 %cmp2 to i8
+  br label %if.end
+
+if.then3:
+  %add2 = add i32 %nblks, %blksA
+  %cmp3 = icmp ule i32 %add2, %blksA
+  %frombool4 = zext i1 %cmp3 to i8
+  br label %if.end
+
+if.end:
+  %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ %frombool4, %if.then3 ]
+  %tobool4 = icmp ne i8 %obeys.0, 0
+  ret i1 %tobool4
+}
+
+; CHECK-LABEL: test18
+; CHECK: if.end:
+; CHECK-NEXT: %[[x:.*]] = phi i1
+; CHECK-DAG: [ %cmp, %if.then ]
+; CHECK-DAG: [ %cmp2, %if.then2 ]
+; CHECK-DAG: [ %cmp3, %if.then3 ]
+; CHECK-NEXT: zext i1 %[[x]] to i8
+
+define i32 @test_pr30188(i1 zeroext %flag, i32 %x) {
+entry:
+  %y = alloca i32
+  %z = alloca i32
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  store i32 %x, i32* %y
+  br label %if.end
+
+if.else:
+  store i32 %x, i32* %z
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test_pr30188
+; CHECK-NOT: select
+; CHECK: store
+; CHECK: store
+
+define i32 @test_pr30188a(i1 zeroext %flag, i32 %x) {
+entry:
+  %y = alloca i32
+  %z = alloca i32
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  call void @g()
+  %one = load i32, i32* %y
+  %two = add i32 %one, 2
+  store i32 %two, i32* %y
+  br label %if.end
+
+if.else:
+  %three = load i32, i32* %z
+  %four = add i32 %three, 2
+  store i32 %four, i32* %y
+  br label %if.end
+
+if.end:
+  ret i32 1
+}
+
+; CHECK-LABEL: test_pr30188a
+; CHECK-NOT: select
+; CHECK: load
+; CHECK: load
+; CHECK: store
+
+; The phi is confusing - both add instructions are used by it, but
+; not on their respective unconditional arcs. It should not be
+; optimized.
+define void @test_pr30292(i1 %cond, i1 %cond2, i32 %a, i32 %b) {
+entry:
+  %add1 = add i32 %a, 1
+  br label %succ
+
+one:
+  br i1 %cond, label %two, label %succ
+
+two:
+  call void @g()
+  %add2 = add i32 %a, 1
+  br label %succ
+
+succ:
+  %p = phi i32 [ 0, %entry ], [ %add1, %one ], [ %add2, %two ]
+  br label %one
+}
+declare void @g()
+
+; CHECK-LABEL: test_pr30292
+; CHECK: phi i32 [ 0, %entry ], [ %add1, %succ ], [ %add2, %two ]
+
+define zeroext i1 @test_pr30244(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) {
+
+entry:
+  %p = alloca i8
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %cmp = icmp uge i32 %blksA, %nblks
+  %frombool1 = zext i1 %cmp to i8
+  store i8 %frombool1, i8* %p
+  br label %if.end
+
+if.else:
+  br i1 %flag2, label %if.then2, label %if.end
+
+if.then2:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = zext i1 %cmp2 to i8
+  store i8 %frombool3, i8* %p
+  br label %if.end
+
+if.end:
+  ret i1 true
+}
+
+; CHECK-LABEL: @test_pr30244
+; CHECK: store
+; CHECK: store
+
+define i32 @test_pr30373a(i1 zeroext %flag, i32 %x, i32 %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone
+  %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone
+  %z0 = lshr i32 %y0, 8
+  br label %if.end
+
+if.else:
+  %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone
+  %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone
+  %z1 = lshr exact i32 %y1, 8
+  br label %if.end
+
+if.end:
+  %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ]
+  %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ]
+  %ret = add i32 %xx, %yy
+  ret i32 %ret
+}
+
+; CHECK-LABEL: test_pr30373a
+; CHECK: lshr
+; CHECK-NOT: exact
+; CHECK: }
+
+define i32 @test_pr30373b(i1 zeroext %flag, i32 %x, i32 %y) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone
+  %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone
+  %z0 = lshr exact i32 %y0, 8
+  br label %if.end
+
+if.else:
+  %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone
+  %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone
+  %z1 = lshr i32 %y1, 8
+  br label %if.end
+
+if.end:
+  %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ]
+  %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ]
+  %ret = add i32 %xx, %yy
+  ret i32 %ret
+}
+
+; CHECK-LABEL: test_pr30373b
+; CHECK: lshr
+; CHECK-NOT: exact
+; CHECK: }
+
+; Check that simplifycfg doesn't sink and merge inline-asm instructions.
+
+define i32 @test_inline_asm1(i32 %c, i32 %r6) {
+entry:
+  %tobool = icmp eq i32 %c, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:
+  %0 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8)
+  br label %if.end
+
+if.else:
+  %1 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6)
+  br label %if.end
+
+if.end:
+  %r6.addr.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
+  ret i32 %r6.addr.0
+}
+
+; CHECK-LABEL: @test_inline_asm1(
+; CHECK: call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8)
+; CHECK: call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6)
+
+declare i32 @call_target()
+
+define void @test_operand_bundles(i1 %cond, i32* %ptr) {
+entry:
+  br i1 %cond, label %left, label %right
+
+left:
+  %val0 = call i32 @call_target() [ "deopt"(i32 10) ]
+  store i32 %val0, i32* %ptr
+  br label %merge
+
+right:
+  %val1 = call i32 @call_target() [ "deopt"(i32 20) ]
+  store i32 %val1, i32* %ptr
+  br label %merge
+
+merge:
+  ret void
+}
+
+; CHECK-LABEL: @test_operand_bundles(
+; CHECK: left:
+; CHECK-NEXT:   %val0 = call i32 @call_target() [ "deopt"(i32 10) ]
+; CHECK: right:
+; CHECK-NEXT:   %val1 = call i32 @call_target() [ "deopt"(i32 20) ]
+
+%T = type {i32, i32}
+
+define i32 @test_insertvalue(i1 zeroext %flag, %T %P) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %t1 = insertvalue %T %P, i32 0, 0
+  br label %if.end
+
+if.else:
+  %t2 = insertvalue %T %P, i32 1, 0
+  br label %if.end
+
+if.end:
+  %t = phi %T [%t1, %if.then], [%t2, %if.else]
+  ret i32 1
+}
+
+; CHECK-LABEL: @test_insertvalue
+; CHECK: select
+; CHECK: insertvalue
+; CHECK-NOT: insertvalue
+
+
+declare void @baz(i32)
+
+define void @test_sink_void_calls(i32 %x) {
+entry:
+  switch i32 %x, label %default [
+    i32 0, label %bb0
+    i32 1, label %bb1
+    i32 2, label %bb2
+    i32 3, label %bb3
+    i32 4, label %bb4
+  ]
+bb0:
+  call void @baz(i32 12)
+  br label %return
+bb1:
+  call void @baz(i32 34)
+  br label %return
+bb2:
+  call void @baz(i32 56)
+  br label %return
+bb3:
+  call void @baz(i32 78)
+  br label %return
+bb4:
+  call void @baz(i32 90)
+  br label %return
+default:
+  unreachable
+return:
+  ret void
+
+; Check that the calls get sunk to the return block.
+; We would previously not sink calls without uses, see PR41259.
+; CHECK-LABEL: @test_sink_void_calls
+; CHECK-NOT: call
+; CHECK-LABEL: return:
+; CHECK: phi
+; CHECK: call
+; CHECK-NOT: call
+; CHECK: ret
+}
+
+
+; CHECK: ![[$TBAA]] = !{![[TYPE:[0-9]]], ![[TYPE]], i64 0}
+; CHECK: ![[TYPE]] = !{!"float", ![[TEXT:[0-9]]]}
+; CHECK: ![[TEXT]] = !{!"an example type tree"}

Added: llvm/trunk/test/Transforms/SimplifyCFG/speculate-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/speculate-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/speculate-call.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/speculate-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+; CHECK-LABEL: @speculatable_attribute
+; CHECK: select
+define i32 @speculatable_attribute(i32 %a) {
+entry:
+  %c = icmp sgt i32 %a, 64
+  br i1 %c, label %end, label %if
+
+if:
+  %val = call i32 @func() #0
+  br label %end
+
+end:
+  %ret = phi i32 [%val, %if], [0, %entry]
+  ret i32 %ret
+}
+
+define i32 @func() #0 {
+  ret i32 1
+}
+attributes #0 = { nounwind readnone speculatable }
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,83 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -simplifycfg | FileCheck %s
+
+; This test case was generated from speculate-dbgvalue.c:
+;
+;   int test1(int getdirt, int dirt) {
+;     int result = 100;
+;     if (getdirt != 0)
+;       result = dirt;
+;     return result;
+;   }
+;
+; using
+;   clang speculate-dbgvalue.c -S -emit-llvm -g -O3 -mllvm -disable-llvm-optzns -o - | opt -mem2reg -S
+
+
+; Function Attrs: nounwind uwtable
+define i32 @test1(i32 %getdirt, i32 %dirt) #0 !dbg !7 {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    call void @llvm.dbg.value(metadata i32 [[GETDIRT:%.*]], metadata !12, metadata !DIExpression()), !dbg !15
+; CHECK-NEXT:    call void @llvm.dbg.value(metadata i32 [[DIRT:%.*]], metadata !13, metadata !DIExpression()), !dbg !16
+; CHECK-NEXT:    call void @llvm.dbg.value(metadata i32 100, metadata !14, metadata !DIExpression()), !dbg !17
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[GETDIRT]], 0, !dbg !18
+; *** We used to get an incorrect "call void @llvm.dbg.value(metadata i32 [[DIRT]], metadata !14, metadata !DIExpression()), !dbg !17" here, before the select. ***
+; CHECK-NOT:     call void @llvm.dbg.value(metadata i32 [[DIRT]], metadata !14
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[CMP]], i32 [[DIRT]], i32 100, !dbg !20
+; CHECK-NEXT:    call void @llvm.dbg.value(metadata i32 [[RESULT]], metadata !14, metadata !DIExpression()), !dbg !17
+; CHECK-NEXT:    ret i32 [[RESULT]], !dbg !21
+; CHECK: !12 = !DILocalVariable(name: "getdirt"
+; CHECK: !13 = !DILocalVariable(name: "dirt"
+; CHECK: !14 = !DILocalVariable(name: "result"
+;
+entry:
+  call void @llvm.dbg.value(metadata i32 %getdirt, metadata !12, metadata !DIExpression()), !dbg !15
+  call void @llvm.dbg.value(metadata i32 %dirt, metadata !13, metadata !DIExpression()), !dbg !16
+  call void @llvm.dbg.value(metadata i32 100, metadata !14, metadata !DIExpression()), !dbg !17
+  %cmp = icmp ne i32 %getdirt, 0, !dbg !18
+  br i1 %cmp, label %if.then, label %if.end, !dbg !20
+
+if.then:                                          ; preds = %entry
+  call void @llvm.dbg.value(metadata i32 %dirt, metadata !14, metadata !DIExpression()), !dbg !17
+  br label %if.end, !dbg !21
+
+if.end:                                           ; preds = %if.then, %entry
+  %result.0 = phi i32 [ %dirt, %if.then ], [ 100, %entry ]
+  call void @llvm.dbg.value(metadata i32 %result.0, metadata !14, metadata !DIExpression()), !dbg !17
+  ret i32 %result.0, !dbg !22
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind readnone speculatable }
+
+!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 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "speculate-dbgvalue.c", directory: "/foo")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 6.0.0"}
+!7 = distinct !DISubprogram(name: "test1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!12, !13, !14}
+!12 = !DILocalVariable(name: "getdirt", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!13 = !DILocalVariable(name: "dirt", arg: 2, scope: !7, file: !1, line: 1, type: !10)
+!14 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 2, type: !10)
+!15 = !DILocation(line: 1, column: 15, scope: !7)
+!16 = !DILocation(line: 1, column: 28, scope: !7)
+!17 = !DILocation(line: 2, column: 7, scope: !7)
+!18 = !DILocation(line: 3, column: 15, scope: !19)
+!19 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 7)
+!20 = !DILocation(line: 3, column: 7, scope: !7)
+!21 = !DILocation(line: 4, column: 5, scope: !19)
+!22 = !DILocation(line: 5, column: 3, scope: !7)

Added: llvm/trunk/test/Transforms/SimplifyCFG/speculate-math.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/speculate-math.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/speculate-math.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/speculate-math.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,165 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s --check-prefix=EXPENSIVE --check-prefix=ALL
+; RUN: opt -S -simplifycfg -speculate-one-expensive-inst=false < %s | FileCheck %s --check-prefix=CHEAP --check-prefix=ALL
+
+declare float @llvm.sqrt.f32(float) nounwind readonly
+declare float @llvm.fma.f32(float, float, float) nounwind readonly
+declare float @llvm.fmuladd.f32(float, float, float) nounwind readonly
+declare float @llvm.fabs.f32(float) nounwind readonly
+declare float @llvm.minnum.f32(float, float) nounwind readonly
+declare float @llvm.maxnum.f32(float, float) nounwind readonly
+declare float @llvm.minimum.f32(float, float) nounwind readonly
+declare float @llvm.maximum.f32(float, float) nounwind readonly
+
+; ALL-LABEL: @fdiv_test(
+; EXPENSIVE: select i1 %cmp, double %div, double 0.0
+; CHEAP-NOT: select
+
+define double @fdiv_test(double %a, double %b) {
+entry:
+  %cmp = fcmp ogt double %a, 0.0
+  br i1 %cmp, label %cond.true, label %cond.end
+
+cond.true:
+  %div = fdiv double %b, %a
+  br label %cond.end
+
+cond.end:
+  %cond = phi double [ %div, %cond.true ], [ 0.0, %entry ]
+  ret double %cond
+}
+
+; ALL-LABEL: @sqrt_test(
+; ALL: select
+define void @sqrt_test(float addrspace(1)* noalias nocapture %out, float %a) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_sqrt.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.sqrt.f32(float %a) nounwind readnone
+  br label %test_sqrt.exit
+
+test_sqrt.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @fabs_test(
+; ALL: select
+define void @fabs_test(float addrspace(1)* noalias nocapture %out, float %a) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_fabs.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.fabs.f32(float %a) nounwind readnone
+  br label %test_fabs.exit
+
+test_fabs.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @fma_test(
+; ALL: select
+define void @fma_test(float addrspace(1)* noalias nocapture %out, float %a, float %b, float %c) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_fma.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.fma.f32(float %a, float %b, float %c) nounwind readnone
+  br label %test_fma.exit
+
+test_fma.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @fmuladd_test(
+; ALL: select
+define void @fmuladd_test(float addrspace(1)* noalias nocapture %out, float %a, float %b, float %c) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_fmuladd.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.fmuladd.f32(float %a, float %b, float %c) nounwind readnone
+  br label %test_fmuladd.exit
+
+test_fmuladd.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @minnum_test(
+; ALL: select
+define void @minnum_test(float addrspace(1)* noalias nocapture %out, float %a, float %b) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_minnum.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.minnum.f32(float %a, float %b) nounwind readnone
+  br label %test_minnum.exit
+
+test_minnum.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @maxnum_test(
+; ALL: select
+define void @maxnum_test(float addrspace(1)* noalias nocapture %out, float %a, float %b) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_maxnum.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.maxnum.f32(float %a, float %b) nounwind readnone
+  br label %test_maxnum.exit
+
+test_maxnum.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @minimum_test(
+; ALL: select
+define void @minimum_test(float addrspace(1)* noalias nocapture %out, float %a, float %b) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_minimum.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.minimum.f32(float %a, float %b) nounwind readnone
+  br label %test_minimum.exit
+
+test_minimum.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}
+
+; ALL-LABEL: @maximum_test(
+; ALL: select
+define void @maximum_test(float addrspace(1)* noalias nocapture %out, float %a, float %b) nounwind {
+entry:
+  %cmp.i = fcmp olt float %a, 0.000000e+00
+  br i1 %cmp.i, label %test_maximum.exit, label %cond.else.i
+
+cond.else.i:                                      ; preds = %entry
+  %0 = tail call float @llvm.maximum.f32(float %a, float %b) nounwind readnone
+  br label %test_maximum.exit
+
+test_maximum.exit:                                   ; preds = %cond.else.i, %entry
+  %cond.i = phi float [ %0, %cond.else.i ], [ 0x7FF8000000000000, %entry ]
+  store float %cond.i, float addrspace(1)* %out, align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/speculate-store.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/speculate-store.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/speculate-store.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/speculate-store.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,90 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+define void @ifconvertstore(i32* %A, i32 %B, i32 %C, i32 %D) {
+; CHECK-LABEL: @ifconvertstore(
+; CHECK:         store i32 %B, i32* %A
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 %D, 42
+; CHECK-NEXT:    [[C_B:%.*]] = select i1 [[CMP]], i32 %C, i32 %B, !prof !0
+; CHECK-NEXT:    store i32 [[C_B]], i32* %A
+; CHECK-NEXT:    ret void
+;
+entry:
+; First store to the location.
+  store i32 %B, i32* %A
+  %cmp = icmp sgt i32 %D, 42
+  br i1 %cmp, label %if.then, label %ret.end, !prof !0
+
+; Make sure we speculate stores like the following one. It is cheap compared to
+; a mispredicated branch.
+if.then:
+  store i32 %C, i32* %A
+  br label %ret.end
+
+ret.end:
+  ret void
+}
+
+; Store to a different location.
+
+define void @noifconvertstore1(i32* %A1, i32* %A2, i32 %B, i32 %C, i32 %D) {
+; CHECK-LABEL: @noifconvertstore1(
+; CHECK-NOT: select
+;
+entry:
+  store i32 %B, i32* %A1
+  %cmp = icmp sgt i32 %D, 42
+  br i1 %cmp, label %if.then, label %ret.end
+
+if.then:
+  store i32 %C, i32* %A2
+  br label %ret.end
+
+ret.end:
+  ret void
+}
+
+; This function could store to our address, so we can't repeat the first store a second time.
+declare void @unknown_fun()
+
+define void @noifconvertstore2(i32* %A, i32 %B, i32 %C, i32 %D) {
+; CHECK-LABEL: @noifconvertstore2(
+; CHECK-NOT: select
+;
+entry:
+; First store to the location.
+  store i32 %B, i32* %A
+  call void @unknown_fun()
+  %cmp6 = icmp sgt i32 %D, 42
+  br i1 %cmp6, label %if.then, label %ret.end
+
+if.then:
+  store i32 %C, i32* %A
+  br label %ret.end
+
+ret.end:
+  ret void
+}
+
+; Make sure we don't speculate volatile stores.
+
+define void @noifconvertstore_volatile(i32* %A, i32 %B, i32 %C, i32 %D) {
+; CHECK-LABEL: @noifconvertstore_volatile(
+; CHECK-NOT: select
+;
+entry:
+; First store to the location.
+  store i32 %B, i32* %A
+  %cmp6 = icmp sgt i32 %D, 42
+  br i1 %cmp6, label %if.then, label %ret.end
+
+if.then:
+  store volatile i32 %C, i32* %A
+  br label %ret.end
+
+ret.end:
+  ret void
+}
+
+; CHECK: !0 = !{!"branch_weights", i32 3, i32 5}
+!0 = !{!"branch_weights", i32 3, i32 5}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/speculate-vector-ops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/speculate-vector-ops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/speculate-vector-ops.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/speculate-vector-ops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+define i32 @speculate_vector_extract(i32 %d, <4 x i32> %v) #0 {
+; CHECK-LABEL: @speculate_vector_extract(
+; CHECK-NOT: br
+entry:
+  %conv = insertelement <4 x i32> undef, i32 %d, i32 0
+  %conv2 = insertelement <4 x i32> %conv, i32 %d, i32 1
+  %conv3 = insertelement <4 x i32> %conv2, i32 %d, i32 2
+  %conv4 = insertelement <4 x i32> %conv3, i32 %d, i32 3
+  %tmp6 = add nsw <4 x i32> %conv4, <i32 0, i32 -1, i32 -2, i32 -3>
+  %cmp = icmp eq <4 x i32> %tmp6, zeroinitializer
+  %cmp.ext = sext <4 x i1> %cmp to <4 x i32>
+  %tmp8 = extractelement <4 x i32> %cmp.ext, i32 0
+  %tobool = icmp eq i32 %tmp8, 0
+  br i1 %tobool, label %cond.else, label %cond.then
+
+return:                                           ; preds = %cond.end28
+  ret i32 %cond32
+
+cond.then:                                        ; preds = %entry
+  %tmp10 = extractelement <4 x i32> %v, i32 0
+  br label %cond.end
+
+cond.else:                                        ; preds = %entry
+  %tmp12 = extractelement <4 x i32> %v, i32 3
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.else, %cond.then
+  %cond = phi i32 [ %tmp10, %cond.then ], [ %tmp12, %cond.else ]
+  %tmp14 = extractelement <4 x i32> %cmp.ext, i32 1
+  %tobool15 = icmp eq i32 %tmp14, 0
+  br i1 %tobool15, label %cond.else17, label %cond.then16
+
+cond.then16:                                      ; preds = %cond.end
+  %tmp20 = extractelement <4 x i32> %v, i32 1
+  br label %cond.end18
+
+cond.else17:                                      ; preds = %cond.end
+  br label %cond.end18
+
+cond.end18:                                       ; preds = %cond.else17, %cond.then16
+  %cond22 = phi i32 [ %tmp20, %cond.then16 ], [ %cond, %cond.else17 ]
+  %tmp24 = extractelement <4 x i32> %cmp.ext, i32 2
+  %tobool25 = icmp eq i32 %tmp24, 0
+  br i1 %tobool25, label %cond.else27, label %cond.then26
+
+cond.then26:                                      ; preds = %cond.end18
+  %tmp30 = extractelement <4 x i32> %v, i32 2
+  br label %cond.end28
+
+cond.else27:                                      ; preds = %cond.end18
+  br label %cond.end28
+
+cond.end28:                                       ; preds = %cond.else27, %cond.then26
+  %cond32 = phi i32 [ %tmp30, %cond.then26 ], [ %cond22, %cond.else27 ]
+  br label %return
+}
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/SimplifyCFG/speculate-with-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/speculate-with-offset.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/speculate-with-offset.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/speculate-with-offset.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,94 @@
+; RUN: opt -simplifycfg -S < %s | FileCheck %s
+
+; This load is safe to speculate, as it's from a safe offset
+; within an alloca.
+
+; CHECK-LABEL: @yes(
+; CHECK-NOT: br
+
+define void @yes(i1 %c) nounwind {
+entry:
+  %a = alloca [4 x i64*], align 8
+  %__a.addr = getelementptr [4 x i64*], [4 x i64*]* %a, i64 0, i64 3
+  call void @frob(i64** %__a.addr)
+  br i1 %c, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %tmp5 = load i64*, i64** %__a.addr, align 8
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %storemerge = phi i64* [ undef, %if.then ], [ %tmp5, %if.end ]
+  ret void
+}
+
+; CHECK-LABEL: @no0(
+; CHECK: br i1 %c
+
+define void @no0(i1 %c) nounwind {
+entry:
+  %a = alloca [4 x i64*], align 8
+  %__a.addr = getelementptr [4 x i64*], [4 x i64*]* %a, i64 0, i64 4
+  call void @frob(i64** %__a.addr)
+  br i1 %c, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %tmp5 = load i64*, i64** %__a.addr, align 8
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %storemerge = phi i64* [ undef, %if.then ], [ %tmp5, %if.end ]
+  ret void
+}
+
+; CHECK-LABEL: @no1(
+; CHECK: br i1 %c
+
+define void @no1(i1 %c, i64 %n) nounwind {
+entry:
+  %a = alloca [4 x i64*], align 8
+  %__a.addr = getelementptr [4 x i64*], [4 x i64*]* %a, i64 0, i64 %n
+  call void @frob(i64** %__a.addr)
+  br i1 %c, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %tmp5 = load i64*, i64** %__a.addr, align 8
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %storemerge = phi i64* [ undef, %if.then ], [ %tmp5, %if.end ]
+  ret void
+}
+
+; CHECK-LABEL: @no2(
+; CHECK: br i1 %c
+
+define void @no2(i1 %c, i64 %n) nounwind {
+entry:
+  %a = alloca [4 x i64*], align 8
+  %__a.addr = getelementptr [4 x i64*], [4 x i64*]* %a, i64 1, i64 0
+  call void @frob(i64** %__a.addr)
+  br i1 %c, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %tmp5 = load i64*, i64** %__a.addr, align 8
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %storemerge = phi i64* [ undef, %if.then ], [ %tmp5, %if.end ]
+  ret void
+}
+
+declare void @frob(i64** nocapture %p)

Added: llvm/trunk/test/Transforms/SimplifyCFG/statepoint-invoke-unwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/statepoint-invoke-unwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/statepoint-invoke-unwind.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/statepoint-invoke-unwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; Test that statepoint intrinsic is marked with Throwable attribute and it is
+; not optimized into call
+
+declare i64 addrspace(1)* @gc_call()
+declare token @llvm.experimental.gc.statepoint.p0f_p1i64f(i64, i32, i64 addrspace(1)* ()*, i32, i32, ...)
+declare i32* @fake_personality_function()
+
+define i32 @test() gc "statepoint-example" personality i32* ()* @fake_personality_function {
+; CHECK-LABEL: test
+entry:
+  ; CHECK-LABEL: entry:
+  ; CHECK-NEXT: %sp = invoke token (i64, i32, i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f
+  %sp = invoke token (i64, i32, i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 0, i32 0, i64 addrspace(1)* ()* @gc_call, i32 0, i32 0, i32 0, i32 0)
+                to label %normal unwind label %exception
+
+exception:
+  %lpad = landingpad { i8*, i32 }
+          cleanup
+  ret i32 0
+
+normal:
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+; We're sign extending an 8-bit value.
+; The switch condition must be in the range [-128, 127], so any cases outside of that range must be dead.
+; Only the first case has a non-zero weight, but that gets eliminated. Note
+; that this shouldn't have been the case in the first place, but the test here
+; ensures that all-zero branch weights are not attached causing problems downstream.
+
+define i1 @repeated_signbits(i8 %condition) {
+; CHECK-LABEL: @repeated_signbits(
+; CHECK:         switch i32
+; CHECK-DAG:     i32 -128, label %a
+; CHECK-DAG:     i32 -1, label %a
+; CHECK-DAG:     i32  0, label %a
+; CHECK-DAG:     i32  127, label %a
+; CHECK-NEXT:    ]
+; CHECK-NOT:    , !prof
+;
+entry:
+  %sext = sext i8 %condition to i32
+  switch i32 %sext, label %default [
+  i32 -2147483648, label %a
+  i32 -129, label %a
+  i32 -128, label %a
+  i32 -1, label %a
+  i32  0, label %a
+  i32  127, label %a
+  i32  128, label %a
+  i32  2147483647, label %a
+  ], !prof !1
+
+a:
+  ret i1 1
+
+default:
+  ret i1 0
+}
+
+!1 = !{!"branch_weights", i32 0, i32 1, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-dead-default.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,179 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+declare void @foo(i32)
+
+define void @test(i1 %a) {
+; CHECK-LABEL: @test
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+  switch i1 %a, label %default [i1 1, label %true
+                                i1 0, label %false]
+true:
+  call void @foo(i32 1)
+  ret void
+false:
+  call void @foo(i32 3)
+  ret void
+default:
+  call void @foo(i32 2)
+  ret void
+}  
+
+define void @test2(i2 %a) {
+; CHECK-LABEL: @test2
+  switch i2 %a, label %default [i2 0, label %case0
+                                i2 1, label %case1
+                                i2 2, label %case2
+                                i2 3, label %case3]
+case0:
+  call void @foo(i32 0)
+  ret void
+case1:
+  call void @foo(i32 1)
+  ret void
+case2:
+  call void @foo(i32 2)
+  ret void
+case3:
+  call void @foo(i32 3)
+  ret void
+default:
+; CHECK-LABEL: default1:
+; CHECK-NEXT: unreachable
+  call void @foo(i32 4)
+  ret void
+}  
+
+; This one is a negative test - we know the value of the default,
+; but that's about it
+define void @test3(i2 %a) {
+; CHECK-LABEL: @test3
+  switch i2 %a, label %default [i2 0, label %case0
+                                i2 1, label %case1
+                                i2 2, label %case2]
+
+case0:
+  call void @foo(i32 0)
+  ret void
+case1:
+  call void @foo(i32 1)
+  ret void
+case2:
+  call void @foo(i32 2)
+  ret void
+default:
+; CHECK-LABEL: default:
+; CHECK-NEXT: call void @foo
+  call void @foo(i32 0)
+  ret void
+}  
+
+; Negative test - check for possible overflow when computing
+; number of possible cases.
+define void @test4(i128 %a) {
+; CHECK-LABEL: @test4
+  switch i128 %a, label %default [i128 0, label %case0
+                                  i128 1, label %case1]
+
+case0:
+  call void @foo(i32 0)
+  ret void
+case1:
+  call void @foo(i32 1)
+  ret void
+default:
+; CHECK-LABEL: default:
+; CHECK-NEXT: call void @foo
+  call void @foo(i32 0)
+  ret void
+}  
+
+; All but one bit known zero
+define void @test5(i8 %a) {
+; CHECK-LABEL: @test5
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+  %cmp = icmp ult i8 %a, 2 
+  call void @llvm.assume(i1 %cmp)
+  switch i8 %a, label %default [i8 1, label %true
+                                i8 0, label %false]
+true:
+  call void @foo(i32 1)
+  ret void
+false:
+  call void @foo(i32 3)
+  ret void
+default:
+  call void @foo(i32 2)
+  ret void
+} 
+
+;; All but one bit known one
+define void @test6(i8 %a) {
+; CHECK-LABEL: @test6
+; CHECK: @llvm.assume
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+  %and = and i8 %a, 254
+  %cmp = icmp eq i8 %and, 254 
+  call void @llvm.assume(i1 %cmp)
+  switch i8 %a, label %default [i8 255, label %true
+                                i8 254, label %false]
+true:
+  call void @foo(i32 1)
+  ret void
+false:
+  call void @foo(i32 3)
+  ret void
+default:
+  call void @foo(i32 2)
+  ret void
+}
+
+; Check that we can eliminate both dead cases and dead defaults
+; within a single run of simplify-cfg
+define void @test7(i8 %a) {
+; CHECK-LABEL: @test7
+; CHECK: @llvm.assume
+; CHECK: br i1 [[IGNORE:%.*]], label %true, label %false
+  %and = and i8 %a, 254
+  %cmp = icmp eq i8 %and, 254 
+  call void @llvm.assume(i1 %cmp)
+  switch i8 %a, label %default [i8 255, label %true
+                                i8 254, label %false
+                                i8 0, label %also_dead]
+true:
+  call void @foo(i32 1)
+  ret void
+false:
+  call void @foo(i32 3)
+  ret void
+also_dead:
+  call void @foo(i32 5)
+  ret void
+default:
+  call void @foo(i32 2)
+  ret void
+}
+
+;; All but one bit known undef
+;; Note: This is currently testing an optimization which doesn't trigger. The
+;; case this is protecting against is that a bit could be assumed both zero 
+;; *or* one given we know it's undef.  ValueTracking doesn't do this today,
+;; but it doesn't hurt to confirm.
+define void @test8(i8 %a) {
+; CHECK-LABEL: @test8(
+; CHECK: switch i8
+  %and = and i8 %a, 254
+  %cmp = icmp eq i8 %and, undef
+  call void @llvm.assume(i1 %cmp)
+  switch i8 %a, label %default [i8 255, label %true
+                                i8 254, label %false]
+true:
+  call void @foo(i32 1)
+  ret void
+false:
+  call void @foo(i32 3)
+  ret void
+default:
+  call void @foo(i32 2)
+  ret void
+}
+
+declare void @llvm.assume(i1)

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-masked-bits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-masked-bits.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-masked-bits.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-masked-bits.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 -S -simplifycfg < %s | FileCheck %s
+
+define i32 @test1(i32 %x) nounwind {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  a:
+; CHECK-NEXT:    [[I:%.*]] = shl i32 %x, 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I]], 24
+; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[COND]], i32 5, i32 0
+; CHECK-NEXT:    ret i32 [[DOT]]
+;
+  %i = shl i32 %x, 1
+  switch i32 %i, label %a [
+  i32 21, label %b
+  i32 24, label %c
+  ]
+
+a:
+  ret i32 0
+b:
+  ret i32 3
+c:
+  ret i32 5
+}
+
+
+define i32 @test2(i32 %x) nounwind {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  a:
+; CHECK-NEXT:    ret i32 0
+;
+  %i = shl i32 %x, 1
+  switch i32 %i, label %a [
+  i32 21, label %b
+  i32 23, label %c
+  ]
+
+a:
+  ret i32 0
+b:
+  ret i32 3
+c:
+  ret i32 5
+}
+
+; We're sign extending an 8-bit value.
+; The switch condition must be in the range [-128, 127], so any cases outside of that range must be dead.
+
+define i1 @repeated_signbits(i8 %condition) {
+; CHECK-LABEL: @repeated_signbits(
+; CHECK:         switch i32
+; CHECK-DAG:     i32 -128, label %a
+; CHECK-DAG:     i32 -1, label %a
+; CHECK-DAG:     i32  0, label %a
+; CHECK-DAG:     i32  127, label %a
+; CHECK-NEXT:    ]
+;
+entry:
+  %sext = sext i8 %condition to i32
+  switch i32 %sext, label %default [
+  i32 -2147483648, label %a
+  i32 -129, label %a
+  i32 -128, label %a
+  i32 -1, label %a
+  i32  0, label %a
+  i32  127, label %a
+  i32  128, label %a
+  i32  2147483647, label %a
+  ]
+
+a:
+  ret i1 1
+
+default:
+  ret i1 0
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-on-const-select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-on-const-select.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-on-const-select.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-on-const-select.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,141 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck -enable-var-scope %s
+
+; Test basic folding to a conditional branch.
+define i32 @foo(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @foo(
+entry:
+    %eq = icmp eq i64 %x, %y
+    br i1 %eq, label %b, label %switch
+switch:
+    %lt = icmp slt i64 %x, %y
+; CHECK: br i1 %lt, label %a, label %b
+    %qux = select i1 %lt, i32 0, i32 2
+    switch i32 %qux, label %bees [
+        i32 0, label %a
+        i32 1, label %b
+        i32 2, label %b
+    ]
+a:
+    tail call void @bees.a() nounwind
+    ret i32 1
+; CHECK: b:
+; CHECK-NEXT: %retval = phi i32 [ 0, %switch ], [ 2, %entry ]
+b:
+    %retval = phi i32 [0, %switch], [0, %switch], [2, %entry]
+    tail call void @bees.b() nounwind
+    ret i32 %retval
+; CHECK-NOT: bees:
+bees:
+    tail call void @llvm.trap() nounwind
+    unreachable
+}
+
+; Test basic folding to an unconditional branch.
+define i32 @bar(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @bar(
+entry:
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void @bees.a() [[$NUW:#[0-9]+]]
+; CHECK-NEXT: ret i32 0
+    %lt = icmp slt i64 %x, %y
+    %qux = select i1 %lt, i32 0, i32 2
+    switch i32 %qux, label %bees [
+        i32 0, label %a
+        i32 1, label %b
+        i32 2, label %a
+    ]
+a:
+    %retval = phi i32 [0, %entry], [0, %entry], [1, %b]
+    tail call void @bees.a() nounwind
+    ret i32 0
+b:
+    tail call void @bees.b() nounwind
+    br label %a
+bees:
+    tail call void @llvm.trap() nounwind
+    unreachable
+}
+
+; Test the edge case where both values from the select are the default case.
+define void @bazz(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @bazz(
+entry:
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void @bees.b() [[$NUW]]
+; CHECK-NEXT: ret void
+    %lt = icmp slt i64 %x, %y
+    %qux = select i1 %lt, i32 10, i32 12
+    switch i32 %qux, label %b [
+        i32 0, label %a
+        i32 1, label %bees
+        i32 2, label %bees
+    ]
+a:
+    tail call void @bees.a() nounwind
+    ret void
+b:
+    tail call void @bees.b() nounwind
+    ret void
+bees:
+    tail call void @llvm.trap()
+    unreachable
+}
+
+; Test the edge case where both values from the select are equal.
+define void @quux(i64 %x, i64 %y) nounwind {
+; CHECK-LABEL: @quux(
+entry:
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void @bees.a() [[$NUW]]
+; CHECK-NEXT: ret void
+    %lt = icmp slt i64 %x, %y
+    %qux = select i1 %lt, i32 0, i32 0
+    switch i32 %qux, label %b [
+        i32 0, label %a
+        i32 1, label %bees
+        i32 2, label %bees
+    ]
+a:
+    tail call void @bees.a() nounwind
+    ret void
+b:
+    tail call void @bees.b() nounwind
+    ret void
+bees:
+    tail call void @llvm.trap()
+    unreachable
+}
+
+; A final test, for phi node munging.
+define i32 @xyzzy(i64 %x, i64 %y) {
+; CHECK-LABEL: @xyzzy(
+entry:
+    %eq = icmp eq i64 %x, %y
+    br i1 %eq, label %r, label %cont
+cont:
+; CHECK: %lt = icmp slt i64 %x, %y
+    %lt = icmp slt i64 %x, %y
+; CHECK-NEXT: select i1 %lt, i32 -1, i32 1
+    %qux = select i1 %lt, i32 0, i32 2
+    switch i32 %qux, label %bees [
+        i32 0, label %a
+        i32 1, label %r
+        i32 2, label %r
+    ]
+r:
+    %val = phi i32 [0, %entry], [1, %cont], [1, %cont]
+    ret i32 %val
+a:
+    ret i32 -1
+; CHECK-NOT: bees:
+bees:
+    tail call void @llvm.trap()
+    unreachable
+}
+
+declare void @llvm.trap() nounwind noreturn
+declare void @bees.a() nounwind
+declare void @bees.b() nounwind
+
+; CHECK: attributes [[$NUW]] = { nounwind }
+; CHECK: attributes #1 = { cold noreturn nounwind }

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; RUN: opt %s -simplifycfg -S | FileCheck %s
+
+declare i32 @f(i32)
+
+define i32 @basic(i32 %x) {
+; CHECK-LABEL: @basic
+; CHECK: x.off = add i32 %x, -5
+; CHECK: %switch = icmp ult i32 %x.off, 3
+; CHECK: br i1 %switch, label %a, label %default
+
+entry:
+  switch i32 %x, label %default [
+    i32 5, label %a
+    i32 6, label %a
+    i32 7, label %a
+  ]
+default:
+  %0 = call i32 @f(i32 0)
+  ret i32 %0
+a:
+  %1 = call i32 @f(i32 1)
+  ret i32 %1
+}
+
+
+define i32 @unreachable(i32 %x) {
+; CHECK-LABEL: @unreachable
+; CHECK: x.off = add i32 %x, -5
+; CHECK: %switch = icmp ult i32 %x.off, 3
+; CHECK: br i1 %switch, label %a, label %b
+
+entry:
+  switch i32 %x, label %unreachable [
+    i32 5, label %a
+    i32 6, label %a
+    i32 7, label %a
+    i32 10, label %b
+    i32 20, label %b
+    i32 30, label %b
+    i32 40, label %b
+  ]
+unreachable:
+  unreachable
+a:
+  %0 = call i32 @f(i32 0)
+  ret i32 %0
+b:
+  %1 = call i32 @f(i32 1)
+  ret i32 %1
+}
+
+
+define i32 @unreachable2(i32 %x) {
+; CHECK-LABEL: @unreachable2
+; CHECK: x.off = add i32 %x, -5
+; CHECK: %switch = icmp ult i32 %x.off, 3
+; CHECK: br i1 %switch, label %a, label %b
+
+entry:
+  ; Note: folding the most popular case destination into the default
+  ; would prevent switch-to-icmp here.
+  switch i32 %x, label %unreachable [
+    i32 5, label %a
+    i32 6, label %a
+    i32 7, label %a
+    i32 10, label %b
+    i32 20, label %b
+  ]
+unreachable:
+  unreachable
+a:
+  %0 = call i32 @f(i32 0)
+  ret i32 %0
+b:
+  %1 = call i32 @f(i32 1)
+  ret i32 %1
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-simplify-crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-simplify-crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-simplify-crash.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-simplify-crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,108 @@
+; RUN: opt < %s -simplifycfg -disable-output
+
+define void @NewExtractNames() {
+entry:
+	br i1 false, label %endif.0, label %then.0
+then.0:		; preds = %entry
+	br i1 false, label %shortcirc_next.i, label %shortcirc_done.i
+shortcirc_next.i:		; preds = %then.0
+	br label %shortcirc_done.i
+shortcirc_done.i:		; preds = %shortcirc_next.i, %then.0
+	br i1 false, label %then.0.i, label %else.0.i
+then.0.i:		; preds = %shortcirc_done.i
+	br label %NewBase.exit
+else.0.i:		; preds = %shortcirc_done.i
+	br i1 false, label %endif.0.i, label %else.1.i
+else.1.i:		; preds = %else.0.i
+	br i1 false, label %endif.0.i, label %else.2.i
+else.2.i:		; preds = %else.1.i
+	br label %NewBase.exit
+endif.0.i:		; preds = %else.1.i, %else.0.i
+	br label %NewBase.exit
+NewBase.exit:		; preds = %endif.0.i, %else.2.i, %then.0.i
+	br label %endif.0
+endif.0:		; preds = %NewBase.exit, %entry
+	%tmp.32.mask = and i32 0, 31		; <i32> [#uses=1]
+	switch i32 %tmp.32.mask, label %label.9 [
+		 i32 16, label %loopentry.2
+		 i32 15, label %loopentry.2
+		 i32 14, label %loopentry.2
+		 i32 13, label %loopentry.2
+		 i32 10, label %loopentry.2
+		 i32 20, label %loopentry.1
+		 i32 19, label %loopentry.1
+		 i32 2, label %loopentry.0
+		 i32 0, label %switchexit
+	]
+loopentry.0:		; preds = %endif.1, %endif.0
+	br i1 false, label %no_exit.0, label %switchexit
+no_exit.0:		; preds = %loopentry.0
+	br i1 false, label %then.1, label %else.1
+then.1:		; preds = %no_exit.0
+	br label %endif.1
+else.1:		; preds = %no_exit.0
+	br i1 false, label %shortcirc_next.0, label %shortcirc_done.0
+shortcirc_next.0:		; preds = %else.1
+	br label %shortcirc_done.0
+shortcirc_done.0:		; preds = %shortcirc_next.0, %else.1
+	br i1 false, label %then.2, label %endif.2
+then.2:		; preds = %shortcirc_done.0
+	br label %endif.2
+endif.2:		; preds = %then.2, %shortcirc_done.0
+	br label %endif.1
+endif.1:		; preds = %endif.2, %then.1
+	br label %loopentry.0
+loopentry.1:		; preds = %endif.3, %endif.0, %endif.0
+	br i1 false, label %no_exit.1, label %switchexit
+no_exit.1:		; preds = %loopentry.1
+	br i1 false, label %then.3, label %else.2
+then.3:		; preds = %no_exit.1
+	br label %endif.3
+else.2:		; preds = %no_exit.1
+	br i1 false, label %shortcirc_next.1, label %shortcirc_done.1
+shortcirc_next.1:		; preds = %else.2
+	br label %shortcirc_done.1
+shortcirc_done.1:		; preds = %shortcirc_next.1, %else.2
+	br i1 false, label %then.4, label %endif.4
+then.4:		; preds = %shortcirc_done.1
+	br label %endif.4
+endif.4:		; preds = %then.4, %shortcirc_done.1
+	br label %endif.3
+endif.3:		; preds = %endif.4, %then.3
+	br label %loopentry.1
+loopentry.2:		; preds = %endif.5, %endif.0, %endif.0, %endif.0, %endif.0, %endif.0
+	%i.3 = phi i32 [ 0, %endif.5 ], [ 0, %endif.0 ], [ 0, %endif.0 ], [ 0, %endif.0 ], [ 0, %endif.0 ], [ 0, %endif.0 ]		; <i32> [#uses=1]
+	%tmp.158 = icmp slt i32 %i.3, 0		; <i1> [#uses=1]
+	br i1 %tmp.158, label %no_exit.2, label %switchexit
+no_exit.2:		; preds = %loopentry.2
+	br i1 false, label %shortcirc_next.2, label %shortcirc_done.2
+shortcirc_next.2:		; preds = %no_exit.2
+	br label %shortcirc_done.2
+shortcirc_done.2:		; preds = %shortcirc_next.2, %no_exit.2
+	br i1 false, label %then.5, label %endif.5
+then.5:		; preds = %shortcirc_done.2
+	br label %endif.5
+endif.5:		; preds = %then.5, %shortcirc_done.2
+	br label %loopentry.2
+label.9:		; preds = %endif.0
+	br i1 false, label %then.6, label %endif.6
+then.6:		; preds = %label.9
+	br label %endif.6
+endif.6:		; preds = %then.6, %label.9
+	store i32 0, i32* null
+	br label %switchexit
+switchexit:		; preds = %endif.6, %loopentry.2, %loopentry.1, %loopentry.0, %endif.0
+	br i1 false, label %endif.7, label %then.7
+then.7:		; preds = %switchexit
+	br i1 false, label %shortcirc_next.3, label %shortcirc_done.3
+shortcirc_next.3:		; preds = %then.7
+	br label %shortcirc_done.3
+shortcirc_done.3:		; preds = %shortcirc_next.3, %then.7
+	br i1 false, label %then.8, label %endif.8
+then.8:		; preds = %shortcirc_done.3
+	br label %endif.8
+endif.8:		; preds = %then.8, %shortcirc_done.3
+	br label %endif.7
+endif.7:		; preds = %endif.8, %switchexit
+	ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-to-br.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-to-br.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-to-br.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-to-br.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt %s -simplifycfg -S | FileCheck %s
+
+declare i32 @f(i32)
+
+define i32 @basic(i32 %x) {
+; CHECK-LABEL: @basic
+; CHECK-LABEL: entry:
+; CHECK-NEXT:  call i32 @f(i32 0)
+; CHECK-NEXT:  ret i32 %0
+
+entry:
+  switch i32 %x, label %default [
+    i32 5, label %default
+    i32 6, label %default
+    i32 7, label %default
+  ]
+default:
+  %0 = call i32 @f(i32 0)
+  ret i32 %0
+}
+
+
+define i32 @constant() {
+; CHECK-LABEL: @constant
+; CHECK-LABEL: entry:
+; CHECK-NEXT:  call i32 @f(i32 1)
+; CHECK-NEXT:  ret i32 %0
+
+entry:
+  switch i32 42, label %default [
+    i32 41, label %default
+    i32 42, label %a
+    i32 43, label %b
+  ]
+default:
+  %0 = call i32 @f(i32 0)
+  ret i32 %0
+a:
+  %1 = call i32 @f(i32 1)
+  ret i32 %1
+b:
+  %2 = call i32 @f(i32 2)
+  ret i32 %2
+}
+
+
+define i32 @unreachable(i32 %x) {
+; CHECK-LABEL: @unreachable
+; CHECK-LABEL: entry:
+; CHECK-NEXT:  call i32 @f(i32 0)
+; CHECK-NEXT:  ret i32 %0
+
+entry:
+  switch i32 %x, label %unreachable [
+    i32 5, label %a
+    i32 6, label %a
+    i32 7, label %a
+  ]
+unreachable:
+  unreachable
+a:
+  %0 = call i32 @f(i32 0)
+  ret i32 %0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-to-icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-to-icmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-to-icmp.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-to-icmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+define zeroext i1 @test1(i32 %x) nounwind readnone ssp noredzone {
+entry:
+ switch i32 %x, label %lor.rhs [
+   i32 2, label %lor.end
+   i32 1, label %lor.end
+   i32 3, label %lor.end
+ ]
+
+lor.rhs:
+ br label %lor.end
+
+lor.end:
+ %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ]
+ ret i1 %0
+
+; CHECK-LABEL: @test1(
+; CHECK: %x.off = add i32 %x, -1
+; CHECK: %switch = icmp ult i32 %x.off, 3
+}
+
+define zeroext i1 @test2(i32 %x) nounwind readnone ssp noredzone {
+entry:
+ switch i32 %x, label %lor.rhs [
+   i32 0, label %lor.end
+   i32 1, label %lor.end
+ ]
+
+lor.rhs:
+ br label %lor.end
+
+lor.end:
+ %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ]
+ ret i1 %0
+
+; CHECK-LABEL: @test2(
+; CHECK: %switch = icmp ult i32 %x, 2
+}
+
+define i32 @test3(i1 %flag) {
+entry:
+ switch i1 %flag, label %bad [
+   i1 true, label %good
+   i1 false, label %good
+ ]
+
+good:
+ ret i32 0
+
+bad:
+ ret i32 1
+
+; CHECK-LABEL: @test3(
+; CHECK: entry:
+; CHECK-NEXT: ret i32 0
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; a, b;
+; fn1() {
+;   if (b)
+;     if (a == 0 || a == 5)
+;       return a;
+;   return 0;
+; }
+
+; Checking that we handle correctly the case when we have a switch
+; branching multiple times to the same block
+
+ at b = common global i32 0, align 4
+ at a = common global i32 0, align 4
+
+; Function Attrs: nounwind
+define i32 @fn1() {
+; CHECK-LABEL: @fn1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @b, align 4
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %return, label %if.then
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP:%.*]], i32 0, i32 0
+; CHECK-NEXT:    [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[TMP1]], 5
+; CHECK-NEXT:    [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 5, i32 [[SWITCH_SELECT]]
+; CHECK-NEXT:    br label %return
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_SELECT2]], %if.then ], [ 0, %entry ]
+; CHECK-NEXT:    ret i32 [[RETVAL_0]]
+;
+entry:
+  %0 = load i32, i32* @b, align 4
+  %tobool = icmp eq i32 %0, 0
+  br i1 %tobool, label %if.end3, label %if.then
+
+if.then:
+  %1 = load i32, i32* @a, align 4
+  switch i32 %1, label %if.end3 [
+  i32 5, label %return
+  i32 0, label %return
+  ]
+
+if.end3:
+  br label %return
+
+return:
+  %retval.0 = phi i32 [ 0, %if.end3 ], [ %1, %if.then ], [ %1, %if.then ]
+  ret i32 %retval.0
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; int foo1_with_default(int a) {
+;   switch(a) {
+;     case 10:
+;       return 10;
+;     case 20:
+;       return 2;
+;   }
+;   return 4;
+; }
+
+define i32 @foo1_with_default(i32 %a) {
+; CHECK-LABEL: @foo1_with_default(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 %a, 20
+; CHECK-NEXT:    [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP:%.*]], i32 2, i32 4
+; CHECK-NEXT:    [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 %a, 10
+; CHECK-NEXT:    [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 10, i32 [[SWITCH_SELECT]]
+; CHECK-NEXT:    ret i32 [[SWITCH_SELECT2]]
+;
+entry:
+  switch i32 %a, label %sw.epilog [
+  i32 10, label %sw.bb
+  i32 20, label %sw.bb1
+  ]
+
+sw.bb:
+  br label %return
+
+sw.bb1:
+  br label %return
+
+sw.epilog:
+  br label %return
+
+return:
+  %retval.0 = phi i32 [ 4, %sw.epilog ], [ 2, %sw.bb1 ], [ 10, %sw.bb ]
+  ret i32 %retval.0
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,660 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+target datalayout="p:40:64:64:32"
+
+declare void @foo1()
+
+declare void @foo2()
+
+define void @test1(i32 %V) {
+        %C1 = icmp eq i32 %V, 4         ; <i1> [#uses=1]
+        %C2 = icmp eq i32 %V, 17                ; <i1> [#uses=1]
+        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test1(
+; CHECK:  switch i32 %V, label %F [
+; CHECK:    i32 17, label %T
+; CHECK:    i32 4, label %T
+; CHECK:  ]
+}
+
+define void @test1_ptr(i32* %V) {
+        %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*)
+        %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*)
+        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test1_ptr(
+; DL:  %magicptr = ptrtoint i32* %V to i32
+; DL:  switch i32 %magicptr, label %F [
+; DL:    i32 17, label %T
+; DL:    i32 4, label %T
+; DL:  ]
+}
+
+define void @test1_ptr_as1(i32 addrspace(1)* %V) {
+        %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*)
+        %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*)
+        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test1_ptr_as1(
+; DL:  %magicptr = ptrtoint i32 addrspace(1)* %V to i16
+; DL:  switch i16 %magicptr, label %F [
+; DL:    i16 17, label %T
+; DL:    i16 4, label %T
+; DL:  ]
+}
+
+define void @test2(i32 %V) {
+        %C1 = icmp ne i32 %V, 4         ; <i1> [#uses=1]
+        %C2 = icmp ne i32 %V, 17                ; <i1> [#uses=1]
+        %CN = and i1 %C1, %C2           ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test2(
+; CHECK:  switch i32 %V, label %T [
+; CHECK:    i32 17, label %F
+; CHECK:    i32 4, label %F
+; CHECK:  ]
+}
+
+define void @test3(i32 %V) {
+        %C1 = icmp eq i32 %V, 4         ; <i1> [#uses=1]
+        br i1 %C1, label %T, label %N
+N:              ; preds = %0
+        %C2 = icmp eq i32 %V, 17                ; <i1> [#uses=1]
+        br i1 %C2, label %T, label %F
+T:              ; preds = %N, %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %N
+        call void @foo2( )
+        ret void
+
+; CHECK-LABEL: @test3(
+; CHECK: switch i32 %V, label %F [
+; CHECK:     i32 4, label %T
+; CHECK:     i32 17, label %T
+; CHECK:   ]
+}
+
+
+
+define i32 @test4(i8 zeroext %c) nounwind ssp noredzone {
+entry:
+  %cmp = icmp eq i8 %c, 62
+  br i1 %cmp, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp4 = icmp eq i8 %c, 34
+  br i1 %cmp4, label %lor.end, label %lor.rhs
+
+lor.rhs:                                          ; preds = %lor.lhs.false
+  %cmp8 = icmp eq i8 %c, 92
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %lor.lhs.false, %entry
+  %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp8, %lor.rhs ]
+  %lor.ext = zext i1 %0 to i32
+  ret i32 %lor.ext
+
+; CHECK-LABEL: @test4(
+; CHECK:  switch i8 %c, label %lor.rhs [
+; CHECK:    i8 62, label %lor.end
+; CHECK:    i8 34, label %lor.end
+; CHECK:    i8 92, label %lor.end
+; CHECK:  ]
+}
+
+define i32 @test5(i8 zeroext %c) nounwind ssp noredzone {
+entry:
+  switch i8 %c, label %lor.rhs [
+    i8 62, label %lor.end
+    i8 34, label %lor.end
+    i8 92, label %lor.end
+  ]
+
+lor.rhs:                                          ; preds = %entry
+  %V = icmp eq i8 %c, 92
+  br label %lor.end
+
+lor.end:                                          ; preds = %entry, %entry, %entry, %lor.rhs
+  %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ]
+  %lor.ext = zext i1 %0 to i32
+  ret i32 %lor.ext
+; CHECK-LABEL: @test5(
+; CHECK:  switch i8 %c, label %lor.rhs [
+; CHECK:    i8 62, label %lor.end
+; CHECK:    i8 34, label %lor.end
+; CHECK:    i8 92, label %lor.end
+; CHECK:  ]
+}
+
+
+define i1 @test6({ i32, i32 }* %I) {
+entry:
+        %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1         ; <i32*> [#uses=1]
+        %tmp.2.i = load i32, i32* %tmp.1.i           ; <i32> [#uses=6]
+        %tmp.2 = icmp eq i32 %tmp.2.i, 14               ; <i1> [#uses=1]
+        br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0
+shortcirc_next.0:               ; preds = %entry
+        %tmp.6 = icmp eq i32 %tmp.2.i, 15               ; <i1> [#uses=1]
+        br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1
+shortcirc_next.1:               ; preds = %shortcirc_next.0
+        %tmp.11 = icmp eq i32 %tmp.2.i, 16              ; <i1> [#uses=1]
+        br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2
+shortcirc_next.2:               ; preds = %shortcirc_next.1
+        %tmp.16 = icmp eq i32 %tmp.2.i, 17              ; <i1> [#uses=1]
+        br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3
+shortcirc_next.3:               ; preds = %shortcirc_next.2
+        %tmp.21 = icmp eq i32 %tmp.2.i, 18              ; <i1> [#uses=1]
+        br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4
+shortcirc_next.4:               ; preds = %shortcirc_next.3
+        %tmp.26 = icmp eq i32 %tmp.2.i, 19              ; <i1> [#uses=1]
+        br label %UnifiedReturnBlock
+shortcirc_done.4:               ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry
+        br label %UnifiedReturnBlock
+UnifiedReturnBlock:             ; preds = %shortcirc_done.4, %shortcirc_next.4
+        %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ]             ; <i1> [#uses=1]
+        ret i1 %UnifiedRetVal
+
+; CHECK-LABEL: @test6(
+; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14
+; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6
+}
+
+define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ult i32 %x, 32
+  %cmp4 = icmp eq i8 %c, 97
+  %or.cond = or i1 %cmp, %cmp4
+  %cmp9 = icmp eq i8 %c, 99
+  %or.cond11 = or i1 %or.cond, %cmp9
+  br i1 %or.cond11, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  tail call void @foo1() nounwind noredzone
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+
+; CHECK-LABEL: @test7(
+; CHECK:   %cmp = icmp ult i32 %x, 32
+; CHECK:   br i1 %cmp, label %if.then, label %switch.early.test
+; CHECK: switch.early.test:
+; CHECK:   switch i8 %c, label %if.end [
+; CHECK:     i8 99, label %if.then
+; CHECK:     i8 97, label %if.then
+; CHECK:   ]
+}
+
+define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone {
+entry:
+  br i1 %C, label %N, label %if.then
+N:
+  %cmp = icmp ult i32 %x, 32
+  %cmp4 = icmp eq i8 %c, 97
+  %or.cond = or i1 %cmp, %cmp4
+  %cmp9 = icmp eq i8 %c, 99
+  %or.cond11 = or i1 %or.cond, %cmp9
+  br i1 %or.cond11, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %A = phi i32 [0, %entry], [42, %N]
+  tail call void @foo1() nounwind noredzone
+  ret i32 %A
+
+if.end:                                           ; preds = %entry
+  ret i32 0
+
+; CHECK-LABEL: @test8(
+; CHECK: switch.early.test:
+; CHECK:   switch i8 %c, label %if.end [
+; CHECK:     i8 99, label %if.then
+; CHECK:     i8 97, label %if.then
+; CHECK:   ]
+; CHECK:   %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ]
+}
+
+;; This is "Example 7" from http://blog.regehr.org/archives/320
+define i32 @test9(i8 zeroext %c) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ult i8 %c, 33
+  br i1 %cmp, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp4 = icmp eq i8 %c, 46
+  br i1 %cmp4, label %lor.end, label %lor.lhs.false6
+
+lor.lhs.false6:                                   ; preds = %lor.lhs.false
+  %cmp9 = icmp eq i8 %c, 44
+  br i1 %cmp9, label %lor.end, label %lor.lhs.false11
+
+lor.lhs.false11:                                  ; preds = %lor.lhs.false6
+  %cmp14 = icmp eq i8 %c, 58
+  br i1 %cmp14, label %lor.end, label %lor.lhs.false16
+
+lor.lhs.false16:                                  ; preds = %lor.lhs.false11
+  %cmp19 = icmp eq i8 %c, 59
+  br i1 %cmp19, label %lor.end, label %lor.lhs.false21
+
+lor.lhs.false21:                                  ; preds = %lor.lhs.false16
+  %cmp24 = icmp eq i8 %c, 60
+  br i1 %cmp24, label %lor.end, label %lor.lhs.false26
+
+lor.lhs.false26:                                  ; preds = %lor.lhs.false21
+  %cmp29 = icmp eq i8 %c, 62
+  br i1 %cmp29, label %lor.end, label %lor.lhs.false31
+
+lor.lhs.false31:                                  ; preds = %lor.lhs.false26
+  %cmp34 = icmp eq i8 %c, 34
+  br i1 %cmp34, label %lor.end, label %lor.lhs.false36
+
+lor.lhs.false36:                                  ; preds = %lor.lhs.false31
+  %cmp39 = icmp eq i8 %c, 92
+  br i1 %cmp39, label %lor.end, label %lor.rhs
+
+lor.rhs:                                          ; preds = %lor.lhs.false36
+  %cmp43 = icmp eq i8 %c, 39
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %lor.lhs.false36, %lor.lhs.false31, %lor.lhs.false26, %lor.lhs.false21, %lor.lhs.false16, %lor.lhs.false11, %lor.lhs.false6, %lor.lhs.false, %entry
+  %0 = phi i1 [ true, %lor.lhs.false36 ], [ true, %lor.lhs.false31 ], [ true, %lor.lhs.false26 ], [ true, %lor.lhs.false21 ], [ true, %lor.lhs.false16 ], [ true, %lor.lhs.false11 ], [ true, %lor.lhs.false6 ], [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp43, %lor.rhs ]
+  %conv46 = zext i1 %0 to i32
+  ret i32 %conv46
+
+; CHECK-LABEL: @test9(
+; CHECK:   %cmp = icmp ult i8 %c, 33
+; CHECK:   br i1 %cmp, label %lor.end, label %switch.early.test
+
+; CHECK: switch.early.test:
+; CHECK:   switch i8 %c, label %lor.rhs [
+; CHECK:     i8 92, label %lor.end
+; CHECK:     i8 62, label %lor.end
+; CHECK:     i8 60, label %lor.end
+; CHECK:     i8 59, label %lor.end
+; CHECK:     i8 58, label %lor.end
+; CHECK:     i8 46, label %lor.end
+; CHECK:     i8 44, label %lor.end
+; CHECK:     i8 34, label %lor.end
+; CHECK:     i8 39, label %lor.end
+; CHECK:   ]
+}
+
+define i32 @test10(i32 %mode, i1 %Cond) {
+  %A = icmp ne i32 %mode, 0
+  %B = icmp ne i32 %mode, 51
+  %C = and i1 %A, %B
+  %D = and i1 %C, %Cond
+  br i1 %D, label %T, label %F
+T:
+  ret i32 123
+F:
+  ret i32 324
+
+; CHECK-LABEL: @test10(
+; CHECK:  br i1 %Cond, label %switch.early.test, label %F
+; CHECK:switch.early.test:
+; CHECK:  switch i32 %mode, label %T [
+; CHECK:    i32 51, label %F
+; CHECK:    i32 0, label %F
+; CHECK:  ]
+}
+
+; PR8780
+define i32 @test11(i32 %bar) nounwind {
+entry:
+  %cmp = icmp eq i32 %bar, 4
+  %cmp2 = icmp eq i32 %bar, 35
+  %or.cond = or i1 %cmp, %cmp2
+  %cmp5 = icmp eq i32 %bar, 53
+  %or.cond1 = or i1 %or.cond, %cmp5
+  %cmp8 = icmp eq i32 %bar, 24
+  %or.cond2 = or i1 %or.cond1, %cmp8
+  %cmp11 = icmp eq i32 %bar, 23
+  %or.cond3 = or i1 %or.cond2, %cmp11
+  %cmp14 = icmp eq i32 %bar, 55
+  %or.cond4 = or i1 %or.cond3, %cmp14
+  %cmp17 = icmp eq i32 %bar, 12
+  %or.cond5 = or i1 %or.cond4, %cmp17
+  %cmp20 = icmp eq i32 %bar, 35
+  %or.cond6 = or i1 %or.cond5, %cmp20
+  br i1 %or.cond6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @test11(
+; CHECK: switch i32 %bar, label %if.end [
+; CHECK:   i32 55, label %return
+; CHECK:   i32 53, label %return
+; CHECK:   i32 35, label %return
+; CHECK:   i32 24, label %return
+; CHECK:   i32 23, label %return
+; CHECK:   i32 12, label %return
+; CHECK:   i32 4, label %return
+; CHECK: ]
+}
+
+define void @test12() nounwind {
+entry:
+  br label %bb49.us.us
+
+bb49.us.us:
+  %A = icmp eq i32 undef, undef
+  br i1 %A, label %bb55.us.us, label %malformed
+
+bb48.us.us:
+  %B = icmp ugt i32 undef, undef
+  br i1 %B, label %bb55.us.us, label %bb49.us.us
+
+bb55.us.us:
+  br label %bb48.us.us
+
+malformed:
+  ret void
+; CHECK-LABEL: @test12(
+
+}
+
+; test13 - handle switch formation with ult.
+define void @test13(i32 %x) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ult i32 %x, 2
+  br i1 %cmp, label %if.then, label %lor.lhs.false3
+
+lor.lhs.false3:                                   ; preds = %lor.lhs.false
+  %cmp5 = icmp eq i32 %x, 3
+  br i1 %cmp5, label %if.then, label %lor.lhs.false6
+
+lor.lhs.false6:                                   ; preds = %lor.lhs.false3
+  %cmp8 = icmp eq i32 %x, 4
+  br i1 %cmp8, label %if.then, label %lor.lhs.false9
+
+lor.lhs.false9:                                   ; preds = %lor.lhs.false6
+  %cmp11 = icmp eq i32 %x, 6
+  br i1 %cmp11, label %if.then, label %if.end
+
+if.then:                                          ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+  call void @foo1() noredzone
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %lor.lhs.false9
+  ret void
+; CHECK-LABEL: @test13(
+; CHECK:  switch i32 %x, label %if.end [
+; CHECK:     i32 6, label %if.then
+; CHECK:     i32 4, label %if.then
+; CHECK:     i32 3, label %if.then
+; CHECK:     i32 1, label %if.then
+; CHECK:     i32 0, label %if.then
+; CHECK:   ]
+}
+
+; test14 - handle switch formation with ult.
+define void @test14(i32 %x) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ugt i32 %x, 2
+  br i1 %cmp, label %lor.lhs.false3, label %if.then
+
+lor.lhs.false3:                                   ; preds = %lor.lhs.false
+  %cmp5 = icmp ne i32 %x, 3
+  br i1 %cmp5, label %lor.lhs.false6, label %if.then
+
+lor.lhs.false6:                                   ; preds = %lor.lhs.false3
+  %cmp8 = icmp ne i32 %x, 4
+  br i1 %cmp8, label %lor.lhs.false9, label %if.then
+
+lor.lhs.false9:                                   ; preds = %lor.lhs.false6
+  %cmp11 = icmp ne i32 %x, 6
+  br i1 %cmp11, label %if.end, label %if.then
+
+if.then:                                          ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+  call void @foo1() noredzone
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %lor.lhs.false9
+  ret void
+; CHECK-LABEL: @test14(
+; CHECK:  switch i32 %x, label %if.end [
+; CHECK:     i32 6, label %if.then
+; CHECK:     i32 4, label %if.then
+; CHECK:     i32 3, label %if.then
+; CHECK:     i32 1, label %if.then
+; CHECK:     i32 0, label %if.then
+; CHECK:   ]
+}
+
+; Don't crash on ginormous ranges.
+define void @test15(i128 %x) nounwind {
+  %cmp = icmp ugt i128 %x, 2
+  br i1 %cmp, label %if.end, label %lor.false
+
+lor.false:
+  %cmp2 = icmp ne i128 %x, 100000000000000000000
+  br i1 %cmp2, label %if.end, label %if.then
+
+if.then:
+  call void @foo1() noredzone
+  br label %if.end
+
+if.end:
+  ret void
+
+; CHECK-LABEL: @test15(
+; CHECK-NOT: switch
+; CHECK: ret void
+}
+
+; PR8675
+; rdar://5134905
+define zeroext i1 @test16(i32 %x) nounwind {
+entry:
+; CHECK-LABEL: @test16(
+; CHECK: %x.off = add i32 %x, -1
+; CHECK: %switch = icmp ult i32 %x.off, 3
+  %cmp.i = icmp eq i32 %x, 1
+  br i1 %cmp.i, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:
+  %cmp.i2 = icmp eq i32 %x, 2
+  br i1 %cmp.i2, label %lor.end, label %lor.rhs
+
+lor.rhs:
+  %cmp.i1 = icmp eq i32 %x, 3
+  br label %lor.end
+
+lor.end:
+  %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp.i1, %lor.rhs ]
+  ret i1 %0
+}
+
+; Check that we don't turn an icmp into a switch where it's not useful.
+define void @test17(i32 %x, i32 %y) {
+  %cmp = icmp ult i32 %x, 3
+  %switch = icmp ult i32 %y, 2
+  %or.cond775 = or i1 %cmp, %switch
+  br i1 %or.cond775, label %lor.lhs.false8, label %return
+
+lor.lhs.false8:
+  tail call void @foo1()
+  ret void
+
+return:
+  ret void
+
+; CHECK-LABEL: @test17(
+; CHECK-NOT: switch.early.test
+; CHECK-NOT: switch i32
+; CHECK: ret void
+}
+
+define void @test18(i32 %arg) {
+bb:
+  %tmp = and i32 %arg, -2
+  %tmp1 = icmp eq i32 %tmp, 8
+  %tmp2 = icmp eq i32 %arg, 10
+  %tmp3 = or i1 %tmp1, %tmp2
+  %tmp4 = icmp eq i32 %arg, 11
+  %tmp5 = or i1 %tmp3, %tmp4
+  %tmp6 = icmp eq i32 %arg, 12
+  %tmp7 = or i1 %tmp5, %tmp6
+  br i1 %tmp7, label %bb19, label %bb8
+
+bb8:                                              ; preds = %bb
+  %tmp9 = add i32 %arg, -13
+  %tmp10 = icmp ult i32 %tmp9, 2
+  %tmp11 = icmp eq i32 %arg, 16
+  %tmp12 = or i1 %tmp10, %tmp11
+  %tmp13 = icmp eq i32 %arg, 17
+  %tmp14 = or i1 %tmp12, %tmp13
+  %tmp15 = icmp eq i32 %arg, 18
+  %tmp16 = or i1 %tmp14, %tmp15
+  %tmp17 = icmp eq i32 %arg, 15
+  %tmp18 = or i1 %tmp16, %tmp17
+  br i1 %tmp18, label %bb19, label %bb20
+
+bb19:                                             ; preds = %bb8, %bb
+  tail call void @foo1()
+  br label %bb20
+
+bb20:                                             ; preds = %bb19, %bb8
+  ret void
+
+; CHECK-LABEL: @test18(
+; CHECK: %arg.off = add i32 %arg, -8
+; CHECK: icmp ult i32 %arg.off, 11
+}
+
+define void @PR26323(i1 %tobool23, i32 %tmp3) {
+entry:
+  %tobool5 = icmp ne i32 %tmp3, 0
+  %neg14 = and i32 %tmp3, -2
+  %cmp17 = icmp ne i32 %neg14, -1
+  %or.cond = and i1 %tobool5, %tobool23
+  %or.cond1 = and i1 %cmp17, %or.cond
+  br i1 %or.cond1, label %if.end29, label %if.then27
+
+if.then27:                                        ; preds = %entry
+  call void @foo1()
+  unreachable
+
+if.end29:                                         ; preds = %entry
+  ret void
+}
+
+; CHECK-LABEL: define void @PR26323(
+; CHECK:  %tobool5 = icmp ne i32 %tmp3, 0
+; CHECK:  %neg14 = and i32 %tmp3, -2
+; CHECK:  %cmp17 = icmp ne i32 %neg14, -1
+; CHECK:  %or.cond = and i1 %tobool5, %tobool23
+; CHECK:  %or.cond1 = and i1 %cmp17, %or.cond
+; CHECK:  br i1 %or.cond1, label %if.end29, label %if.then27
+
+; Form a switch when and'ing a negated power of two
+; CHECK-LABEL: define void @test19
+; CHECK: switch i32 %arg, label %else [
+; CHECK: i32 32, label %if
+; CHECK: i32 13, label %if
+; CHECK: i32 12, label %if
+define void @test19(i32 %arg) {
+  %and = and i32 %arg, -2
+  %cmp1 = icmp eq i32 %and, 12
+  %cmp2 = icmp eq i32 %arg, 32
+  %pred = or i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
+
+; Since %cmp1 is always false, a switch is never formed
+; CHECK-LABEL: define void @test20
+; CHECK-NOT: switch
+; CHECK: ret void
+define void @test20(i32 %arg) {
+  %and = and i32 %arg, -2
+  %cmp1 = icmp eq i32 %and, 13
+  %cmp2 = icmp eq i32 %arg, 32
+  %pred = or i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
+
+; Form a switch when or'ing a power of two
+; CHECK-LABEL: define void @test21
+; CHECK: i32 32, label %else
+; CHECK: i32 13, label %else
+; CHECK: i32 12, label %else
+define void @test21(i32 %arg) {
+  %and = or i32 %arg, 1
+  %cmp1 = icmp ne i32 %and, 13
+  %cmp2 = icmp ne i32 %arg, 32
+  %pred = and i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
+
+; Since %cmp1 is always false, a switch is never formed
+; CHECK-LABEL: define void @test22
+; CHECK-NOT: switch
+; CHECK: ret void
+define void @test22(i32 %arg) {
+  %and = or i32 %arg, 1
+  %cmp1 = icmp ne i32 %and, 12
+  %cmp2 = icmp ne i32 %arg, 32
+  %pred = and i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
\ No newline at end of file

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch_create.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch_create.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch_create.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch_create.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,660 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; RUN: opt -S -data-layout="p:32:32-p1:16:16" -simplifycfg < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s
+
+declare void @foo1()
+
+declare void @foo2()
+
+define void @test1(i32 %V) {
+        %C1 = icmp eq i32 %V, 4         ; <i1> [#uses=1]
+        %C2 = icmp eq i32 %V, 17                ; <i1> [#uses=1]
+        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test1(
+; CHECK:  switch i32 %V, label %F [
+; CHECK:    i32 17, label %T
+; CHECK:    i32 4, label %T
+; CHECK:  ]
+}
+
+define void @test1_ptr(i32* %V) {
+        %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*)
+        %C2 = icmp eq i32* %V, inttoptr (i32 17 to i32*)
+        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test1_ptr(
+; DL:  %magicptr = ptrtoint i32* %V to i32
+; DL:  switch i32 %magicptr, label %F [
+; DL:    i32 17, label %T
+; DL:    i32 4, label %T
+; DL:  ]
+}
+
+define void @test1_ptr_as1(i32 addrspace(1)* %V) {
+        %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*)
+        %C2 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 17 to i32 addrspace(1)*)
+        %CN = or i1 %C1, %C2            ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test1_ptr_as1(
+; DL:  %magicptr = ptrtoint i32 addrspace(1)* %V to i16
+; DL:  switch i16 %magicptr, label %F [
+; DL:    i16 17, label %T
+; DL:    i16 4, label %T
+; DL:  ]
+}
+
+define void @test2(i32 %V) {
+        %C1 = icmp ne i32 %V, 4         ; <i1> [#uses=1]
+        %C2 = icmp ne i32 %V, 17                ; <i1> [#uses=1]
+        %CN = and i1 %C1, %C2           ; <i1> [#uses=1]
+        br i1 %CN, label %T, label %F
+T:              ; preds = %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %0
+        call void @foo2( )
+        ret void
+; CHECK-LABEL: @test2(
+; CHECK:  switch i32 %V, label %T [
+; CHECK:    i32 17, label %F
+; CHECK:    i32 4, label %F
+; CHECK:  ]
+}
+
+define void @test3(i32 %V) {
+        %C1 = icmp eq i32 %V, 4         ; <i1> [#uses=1]
+        br i1 %C1, label %T, label %N
+N:              ; preds = %0
+        %C2 = icmp eq i32 %V, 17                ; <i1> [#uses=1]
+        br i1 %C2, label %T, label %F
+T:              ; preds = %N, %0
+        call void @foo1( )
+        ret void
+F:              ; preds = %N
+        call void @foo2( )
+        ret void
+
+; CHECK-LABEL: @test3(
+; CHECK: switch i32 %V, label %F [
+; CHECK:     i32 4, label %T
+; CHECK:     i32 17, label %T
+; CHECK:   ]
+}
+
+
+
+define i32 @test4(i8 zeroext %c) nounwind ssp noredzone {
+entry:
+  %cmp = icmp eq i8 %c, 62
+  br i1 %cmp, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp4 = icmp eq i8 %c, 34
+  br i1 %cmp4, label %lor.end, label %lor.rhs
+
+lor.rhs:                                          ; preds = %lor.lhs.false
+  %cmp8 = icmp eq i8 %c, 92
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %lor.lhs.false, %entry
+  %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp8, %lor.rhs ]
+  %lor.ext = zext i1 %0 to i32
+  ret i32 %lor.ext
+
+; CHECK-LABEL: @test4(
+; CHECK:  switch i8 %c, label %lor.rhs [
+; CHECK:    i8 62, label %lor.end
+; CHECK:    i8 34, label %lor.end
+; CHECK:    i8 92, label %lor.end
+; CHECK:  ]
+}
+
+define i32 @test5(i8 zeroext %c) nounwind ssp noredzone {
+entry:
+  switch i8 %c, label %lor.rhs [
+    i8 62, label %lor.end
+    i8 34, label %lor.end
+    i8 92, label %lor.end
+  ]
+
+lor.rhs:                                          ; preds = %entry
+  %V = icmp eq i8 %c, 92
+  br label %lor.end
+
+lor.end:                                          ; preds = %entry, %entry, %entry, %lor.rhs
+  %0 = phi i1 [ true, %entry ], [ %V, %lor.rhs ], [ true, %entry ], [ true, %entry ]
+  %lor.ext = zext i1 %0 to i32
+  ret i32 %lor.ext
+; CHECK-LABEL: @test5(
+; CHECK:  switch i8 %c, label %lor.rhs [
+; CHECK:    i8 62, label %lor.end
+; CHECK:    i8 34, label %lor.end
+; CHECK:    i8 92, label %lor.end
+; CHECK:  ]
+}
+
+
+define i1 @test6({ i32, i32 }* %I) {
+entry:
+        %tmp.1.i = getelementptr { i32, i32 }, { i32, i32 }* %I, i64 0, i32 1         ; <i32*> [#uses=1]
+        %tmp.2.i = load i32, i32* %tmp.1.i           ; <i32> [#uses=6]
+        %tmp.2 = icmp eq i32 %tmp.2.i, 14               ; <i1> [#uses=1]
+        br i1 %tmp.2, label %shortcirc_done.4, label %shortcirc_next.0
+shortcirc_next.0:               ; preds = %entry
+        %tmp.6 = icmp eq i32 %tmp.2.i, 15               ; <i1> [#uses=1]
+        br i1 %tmp.6, label %shortcirc_done.4, label %shortcirc_next.1
+shortcirc_next.1:               ; preds = %shortcirc_next.0
+        %tmp.11 = icmp eq i32 %tmp.2.i, 16              ; <i1> [#uses=1]
+        br i1 %tmp.11, label %shortcirc_done.4, label %shortcirc_next.2
+shortcirc_next.2:               ; preds = %shortcirc_next.1
+        %tmp.16 = icmp eq i32 %tmp.2.i, 17              ; <i1> [#uses=1]
+        br i1 %tmp.16, label %shortcirc_done.4, label %shortcirc_next.3
+shortcirc_next.3:               ; preds = %shortcirc_next.2
+        %tmp.21 = icmp eq i32 %tmp.2.i, 18              ; <i1> [#uses=1]
+        br i1 %tmp.21, label %shortcirc_done.4, label %shortcirc_next.4
+shortcirc_next.4:               ; preds = %shortcirc_next.3
+        %tmp.26 = icmp eq i32 %tmp.2.i, 19              ; <i1> [#uses=1]
+        br label %UnifiedReturnBlock
+shortcirc_done.4:               ; preds = %shortcirc_next.3, %shortcirc_next.2, %shortcirc_next.1, %shortcirc_next.0, %entry
+        br label %UnifiedReturnBlock
+UnifiedReturnBlock:             ; preds = %shortcirc_done.4, %shortcirc_next.4
+        %UnifiedRetVal = phi i1 [ %tmp.26, %shortcirc_next.4 ], [ true, %shortcirc_done.4 ]             ; <i1> [#uses=1]
+        ret i1 %UnifiedRetVal
+
+; CHECK-LABEL: @test6(
+; CHECK: %tmp.2.i.off = add i32 %tmp.2.i, -14
+; CHECK: %switch = icmp ult i32 %tmp.2.i.off, 6
+}
+
+define void @test7(i8 zeroext %c, i32 %x) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ult i32 %x, 32
+  %cmp4 = icmp eq i8 %c, 97
+  %or.cond = or i1 %cmp, %cmp4
+  %cmp9 = icmp eq i8 %c, 99
+  %or.cond11 = or i1 %or.cond, %cmp9
+  br i1 %or.cond11, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  tail call void @foo1() nounwind noredzone
+  ret void
+
+if.end:                                           ; preds = %entry
+  ret void
+
+; CHECK-LABEL: @test7(
+; CHECK:   %cmp = icmp ult i32 %x, 32
+; CHECK:   br i1 %cmp, label %if.then, label %switch.early.test
+; CHECK: switch.early.test:
+; CHECK:   switch i8 %c, label %if.end [
+; CHECK:     i8 99, label %if.then
+; CHECK:     i8 97, label %if.then
+; CHECK:   ]
+}
+
+define i32 @test8(i8 zeroext %c, i32 %x, i1 %C) nounwind ssp noredzone {
+entry:
+  br i1 %C, label %N, label %if.then
+N:
+  %cmp = icmp ult i32 %x, 32
+  %cmp4 = icmp eq i8 %c, 97
+  %or.cond = or i1 %cmp, %cmp4
+  %cmp9 = icmp eq i8 %c, 99
+  %or.cond11 = or i1 %or.cond, %cmp9
+  br i1 %or.cond11, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %A = phi i32 [0, %entry], [42, %N]
+  tail call void @foo1() nounwind noredzone
+  ret i32 %A
+
+if.end:                                           ; preds = %entry
+  ret i32 0
+
+; CHECK-LABEL: @test8(
+; CHECK: switch.early.test:
+; CHECK:   switch i8 %c, label %if.end [
+; CHECK:     i8 99, label %if.then
+; CHECK:     i8 97, label %if.then
+; CHECK:   ]
+; CHECK:   %A = phi i32 [ 0, %entry ], [ 42, %switch.early.test ], [ 42, %N ], [ 42, %switch.early.test ]
+}
+
+;; This is "Example 7" from http://blog.regehr.org/archives/320
+define i32 @test9(i8 zeroext %c) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ult i8 %c, 33
+  br i1 %cmp, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %entry
+  %cmp4 = icmp eq i8 %c, 46
+  br i1 %cmp4, label %lor.end, label %lor.lhs.false6
+
+lor.lhs.false6:                                   ; preds = %lor.lhs.false
+  %cmp9 = icmp eq i8 %c, 44
+  br i1 %cmp9, label %lor.end, label %lor.lhs.false11
+
+lor.lhs.false11:                                  ; preds = %lor.lhs.false6
+  %cmp14 = icmp eq i8 %c, 58
+  br i1 %cmp14, label %lor.end, label %lor.lhs.false16
+
+lor.lhs.false16:                                  ; preds = %lor.lhs.false11
+  %cmp19 = icmp eq i8 %c, 59
+  br i1 %cmp19, label %lor.end, label %lor.lhs.false21
+
+lor.lhs.false21:                                  ; preds = %lor.lhs.false16
+  %cmp24 = icmp eq i8 %c, 60
+  br i1 %cmp24, label %lor.end, label %lor.lhs.false26
+
+lor.lhs.false26:                                  ; preds = %lor.lhs.false21
+  %cmp29 = icmp eq i8 %c, 62
+  br i1 %cmp29, label %lor.end, label %lor.lhs.false31
+
+lor.lhs.false31:                                  ; preds = %lor.lhs.false26
+  %cmp34 = icmp eq i8 %c, 34
+  br i1 %cmp34, label %lor.end, label %lor.lhs.false36
+
+lor.lhs.false36:                                  ; preds = %lor.lhs.false31
+  %cmp39 = icmp eq i8 %c, 92
+  br i1 %cmp39, label %lor.end, label %lor.rhs
+
+lor.rhs:                                          ; preds = %lor.lhs.false36
+  %cmp43 = icmp eq i8 %c, 39
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %lor.lhs.false36, %lor.lhs.false31, %lor.lhs.false26, %lor.lhs.false21, %lor.lhs.false16, %lor.lhs.false11, %lor.lhs.false6, %lor.lhs.false, %entry
+  %0 = phi i1 [ true, %lor.lhs.false36 ], [ true, %lor.lhs.false31 ], [ true, %lor.lhs.false26 ], [ true, %lor.lhs.false21 ], [ true, %lor.lhs.false16 ], [ true, %lor.lhs.false11 ], [ true, %lor.lhs.false6 ], [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp43, %lor.rhs ]
+  %conv46 = zext i1 %0 to i32
+  ret i32 %conv46
+
+; CHECK-LABEL: @test9(
+; CHECK:   %cmp = icmp ult i8 %c, 33
+; CHECK:   br i1 %cmp, label %lor.end, label %switch.early.test
+
+; CHECK: switch.early.test:
+; CHECK:   switch i8 %c, label %lor.rhs [
+; CHECK:     i8 92, label %lor.end
+; CHECK:     i8 62, label %lor.end
+; CHECK:     i8 60, label %lor.end
+; CHECK:     i8 59, label %lor.end
+; CHECK:     i8 58, label %lor.end
+; CHECK:     i8 46, label %lor.end
+; CHECK:     i8 44, label %lor.end
+; CHECK:     i8 34, label %lor.end
+; CHECK:     i8 39, label %lor.end
+; CHECK:   ]
+}
+
+define i32 @test10(i32 %mode, i1 %Cond) {
+  %A = icmp ne i32 %mode, 0
+  %B = icmp ne i32 %mode, 51
+  %C = and i1 %A, %B
+  %D = and i1 %C, %Cond
+  br i1 %D, label %T, label %F
+T:
+  ret i32 123
+F:
+  ret i32 324
+
+; CHECK-LABEL: @test10(
+; CHECK:  br i1 %Cond, label %switch.early.test, label %F
+; CHECK:switch.early.test:
+; CHECK:  switch i32 %mode, label %T [
+; CHECK:    i32 51, label %F
+; CHECK:    i32 0, label %F
+; CHECK:  ]
+}
+
+; PR8780
+define i32 @test11(i32 %bar) nounwind {
+entry:
+  %cmp = icmp eq i32 %bar, 4
+  %cmp2 = icmp eq i32 %bar, 35
+  %or.cond = or i1 %cmp, %cmp2
+  %cmp5 = icmp eq i32 %bar, 53
+  %or.cond1 = or i1 %or.cond, %cmp5
+  %cmp8 = icmp eq i32 %bar, 24
+  %or.cond2 = or i1 %or.cond1, %cmp8
+  %cmp11 = icmp eq i32 %bar, 23
+  %or.cond3 = or i1 %or.cond2, %cmp11
+  %cmp14 = icmp eq i32 %bar, 55
+  %or.cond4 = or i1 %or.cond3, %cmp14
+  %cmp17 = icmp eq i32 %bar, 12
+  %or.cond5 = or i1 %or.cond4, %cmp17
+  %cmp20 = icmp eq i32 %bar, 35
+  %or.cond6 = or i1 %or.cond5, %cmp20
+  br i1 %or.cond6, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ 0, %if.end ]
+  ret i32 %retval.0
+
+; CHECK-LABEL: @test11(
+; CHECK: switch i32 %bar, label %if.end [
+; CHECK:   i32 55, label %return
+; CHECK:   i32 53, label %return
+; CHECK:   i32 35, label %return
+; CHECK:   i32 24, label %return
+; CHECK:   i32 23, label %return
+; CHECK:   i32 12, label %return
+; CHECK:   i32 4, label %return
+; CHECK: ]
+}
+
+define void @test12() nounwind {
+entry:
+  br label %bb49.us.us
+
+bb49.us.us:
+  %A = icmp eq i32 undef, undef
+  br i1 %A, label %bb55.us.us, label %malformed
+
+bb48.us.us:
+  %B = icmp ugt i32 undef, undef
+  br i1 %B, label %bb55.us.us, label %bb49.us.us
+
+bb55.us.us:
+  br label %bb48.us.us
+
+malformed:
+  ret void
+; CHECK-LABEL: @test12(
+
+}
+
+; test13 - handle switch formation with ult.
+define void @test13(i32 %x) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ult i32 %x, 2
+  br i1 %cmp, label %if.then, label %lor.lhs.false3
+
+lor.lhs.false3:                                   ; preds = %lor.lhs.false
+  %cmp5 = icmp eq i32 %x, 3
+  br i1 %cmp5, label %if.then, label %lor.lhs.false6
+
+lor.lhs.false6:                                   ; preds = %lor.lhs.false3
+  %cmp8 = icmp eq i32 %x, 4
+  br i1 %cmp8, label %if.then, label %lor.lhs.false9
+
+lor.lhs.false9:                                   ; preds = %lor.lhs.false6
+  %cmp11 = icmp eq i32 %x, 6
+  br i1 %cmp11, label %if.then, label %if.end
+
+if.then:                                          ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+  call void @foo1() noredzone
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %lor.lhs.false9
+  ret void
+; CHECK-LABEL: @test13(
+; CHECK:  switch i32 %x, label %if.end [
+; CHECK:     i32 6, label %if.then
+; CHECK:     i32 4, label %if.then
+; CHECK:     i32 3, label %if.then
+; CHECK:     i32 1, label %if.then
+; CHECK:     i32 0, label %if.then
+; CHECK:   ]
+}
+
+; test14 - handle switch formation with ult.
+define void @test14(i32 %x) nounwind ssp noredzone {
+entry:
+  %cmp = icmp ugt i32 %x, 2
+  br i1 %cmp, label %lor.lhs.false3, label %if.then
+
+lor.lhs.false3:                                   ; preds = %lor.lhs.false
+  %cmp5 = icmp ne i32 %x, 3
+  br i1 %cmp5, label %lor.lhs.false6, label %if.then
+
+lor.lhs.false6:                                   ; preds = %lor.lhs.false3
+  %cmp8 = icmp ne i32 %x, 4
+  br i1 %cmp8, label %lor.lhs.false9, label %if.then
+
+lor.lhs.false9:                                   ; preds = %lor.lhs.false6
+  %cmp11 = icmp ne i32 %x, 6
+  br i1 %cmp11, label %if.end, label %if.then
+
+if.then:                                          ; preds = %lor.lhs.false9, %lor.lhs.false6, %lor.lhs.false3, %lor.lhs.false, %entry
+  call void @foo1() noredzone
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %lor.lhs.false9
+  ret void
+; CHECK-LABEL: @test14(
+; CHECK:  switch i32 %x, label %if.end [
+; CHECK:     i32 6, label %if.then
+; CHECK:     i32 4, label %if.then
+; CHECK:     i32 3, label %if.then
+; CHECK:     i32 1, label %if.then
+; CHECK:     i32 0, label %if.then
+; CHECK:   ]
+}
+
+; Don't crash on ginormous ranges.
+define void @test15(i128 %x) nounwind {
+  %cmp = icmp ugt i128 %x, 2
+  br i1 %cmp, label %if.end, label %lor.false
+
+lor.false:
+  %cmp2 = icmp ne i128 %x, 100000000000000000000
+  br i1 %cmp2, label %if.end, label %if.then
+
+if.then:
+  call void @foo1() noredzone
+  br label %if.end
+
+if.end:
+  ret void
+
+; CHECK-LABEL: @test15(
+; CHECK-NOT: switch
+; CHECK: ret void
+}
+
+; PR8675
+; rdar://5134905
+define zeroext i1 @test16(i32 %x) nounwind {
+entry:
+; CHECK-LABEL: @test16(
+; CHECK: %x.off = add i32 %x, -1
+; CHECK: %switch = icmp ult i32 %x.off, 3
+  %cmp.i = icmp eq i32 %x, 1
+  br i1 %cmp.i, label %lor.end, label %lor.lhs.false
+
+lor.lhs.false:
+  %cmp.i2 = icmp eq i32 %x, 2
+  br i1 %cmp.i2, label %lor.end, label %lor.rhs
+
+lor.rhs:
+  %cmp.i1 = icmp eq i32 %x, 3
+  br label %lor.end
+
+lor.end:
+  %0 = phi i1 [ true, %lor.lhs.false ], [ true, %entry ], [ %cmp.i1, %lor.rhs ]
+  ret i1 %0
+}
+
+; Check that we don't turn an icmp into a switch where it's not useful.
+define void @test17(i32 %x, i32 %y) {
+  %cmp = icmp ult i32 %x, 3
+  %switch = icmp ult i32 %y, 2
+  %or.cond775 = or i1 %cmp, %switch
+  br i1 %or.cond775, label %lor.lhs.false8, label %return
+
+lor.lhs.false8:
+  tail call void @foo1()
+  ret void
+
+return:
+  ret void
+
+; CHECK-LABEL: @test17(
+; CHECK-NOT: switch.early.test
+; CHECK-NOT: switch i32
+; CHECK: ret void
+}
+
+define void @test18(i32 %arg) {
+bb:
+  %tmp = and i32 %arg, -2
+  %tmp1 = icmp eq i32 %tmp, 8
+  %tmp2 = icmp eq i32 %arg, 10
+  %tmp3 = or i1 %tmp1, %tmp2
+  %tmp4 = icmp eq i32 %arg, 11
+  %tmp5 = or i1 %tmp3, %tmp4
+  %tmp6 = icmp eq i32 %arg, 12
+  %tmp7 = or i1 %tmp5, %tmp6
+  br i1 %tmp7, label %bb19, label %bb8
+
+bb8:                                              ; preds = %bb
+  %tmp9 = add i32 %arg, -13
+  %tmp10 = icmp ult i32 %tmp9, 2
+  %tmp11 = icmp eq i32 %arg, 16
+  %tmp12 = or i1 %tmp10, %tmp11
+  %tmp13 = icmp eq i32 %arg, 17
+  %tmp14 = or i1 %tmp12, %tmp13
+  %tmp15 = icmp eq i32 %arg, 18
+  %tmp16 = or i1 %tmp14, %tmp15
+  %tmp17 = icmp eq i32 %arg, 15
+  %tmp18 = or i1 %tmp16, %tmp17
+  br i1 %tmp18, label %bb19, label %bb20
+
+bb19:                                             ; preds = %bb8, %bb
+  tail call void @foo1()
+  br label %bb20
+
+bb20:                                             ; preds = %bb19, %bb8
+  ret void
+
+; CHECK-LABEL: @test18(
+; CHECK: %arg.off = add i32 %arg, -8
+; CHECK: icmp ult i32 %arg.off, 11
+}
+
+define void @PR26323(i1 %tobool23, i32 %tmp3) {
+entry:
+  %tobool5 = icmp ne i32 %tmp3, 0
+  %neg14 = and i32 %tmp3, -2
+  %cmp17 = icmp ne i32 %neg14, -1
+  %or.cond = and i1 %tobool5, %tobool23
+  %or.cond1 = and i1 %cmp17, %or.cond
+  br i1 %or.cond1, label %if.end29, label %if.then27
+
+if.then27:                                        ; preds = %entry
+  call void @foo1()
+  unreachable
+
+if.end29:                                         ; preds = %entry
+  ret void
+}
+
+; CHECK-LABEL: define void @PR26323(
+; CHECK:  %tobool5 = icmp ne i32 %tmp3, 0
+; CHECK:  %neg14 = and i32 %tmp3, -2
+; CHECK:  %cmp17 = icmp ne i32 %neg14, -1
+; CHECK:  %or.cond = and i1 %tobool5, %tobool23
+; CHECK:  %or.cond1 = and i1 %cmp17, %or.cond
+; CHECK:  br i1 %or.cond1, label %if.end29, label %if.then27
+
+; Form a switch when and'ing a negated power of two
+; CHECK-LABEL: define void @test19
+; CHECK: switch i32 %arg, label %else [
+; CHECK: i32 32, label %if
+; CHECK: i32 13, label %if
+; CHECK: i32 12, label %if
+define void @test19(i32 %arg) {
+  %and = and i32 %arg, -2
+  %cmp1 = icmp eq i32 %and, 12
+  %cmp2 = icmp eq i32 %arg, 32
+  %pred = or i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
+
+; Since %cmp1 is always false, a switch is never formed
+; CHECK-LABEL: define void @test20
+; CHECK-NOT: switch
+; CHECK: ret void
+define void @test20(i32 %arg) {
+  %and = and i32 %arg, -2
+  %cmp1 = icmp eq i32 %and, 13
+  %cmp2 = icmp eq i32 %arg, 32
+  %pred = or i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
+
+; Form a switch when or'ing a power of two
+; CHECK-LABEL: define void @test21
+; CHECK: i32 32, label %else
+; CHECK: i32 13, label %else
+; CHECK: i32 12, label %else
+define void @test21(i32 %arg) {
+  %and = or i32 %arg, 1
+  %cmp1 = icmp ne i32 %and, 13
+  %cmp2 = icmp ne i32 %arg, 32
+  %pred = and i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
+
+; Since %cmp1 is always false, a switch is never formed
+; CHECK-LABEL: define void @test22
+; CHECK-NOT: switch
+; CHECK: ret void
+define void @test22(i32 %arg) {
+  %and = or i32 %arg, 1
+  %cmp1 = icmp ne i32 %and, 12
+  %cmp2 = icmp ne i32 %arg, 32
+  %pred = and i1 %cmp1, %cmp2
+  br i1 %pred, label %if, label %else
+
+if:
+  call void @foo1()
+  ret void
+
+else:
+  ret void
+}
\ No newline at end of file

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch_switch_fold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch_switch_fold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch_switch_fold.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch_switch_fold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,65 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Test that a switch going to a switch on the same value can be merged.
+; All three switches in this example can be merged into one big one.
+
+declare void @foo1()
+
+declare void @foo2()
+
+declare void @foo3()
+
+declare void @foo4()
+
+define void @test1(i32 %V) {
+        switch i32 %V, label %F [
+                 i32 4, label %T
+                 i32 17, label %T
+                 i32 5, label %T
+                 i32 1234, label %F
+        ]
+T:              ; preds = %0, %0, %0
+        switch i32 %V, label %F [
+                 i32 4, label %A
+                 i32 17, label %B
+                 i32 42, label %C
+        ]
+A:              ; preds = %T
+        call void @foo1( )
+        ret void
+B:              ; preds = %F, %F, %T
+        call void @foo2( )
+        ret void
+C:              ; preds = %T
+        call void @foo3( )
+        ret void
+F:              ; preds = %F, %T, %0, %0
+        switch i32 %V, label %F [
+                 i32 4, label %B
+                 i32 18, label %B
+                 i32 42, label %D
+        ]
+D:              ; preds = %F
+        call void @foo4( )
+        ret void
+
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    switch i32 %V, label %infloop [
+; CHECK-NEXT:    i32 4, label %A
+; CHECK-NEXT:    i32 17, label %B
+; CHECK-NEXT:    i32 18, label %B
+; CHECK-NEXT:    i32 42, label %D
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    ret void
+; CHECK:       B:
+; CHECK-NEXT:    call void @foo2()
+; CHECK-NEXT:    ret void
+; CHECK:       D:
+; CHECK-NEXT:    call void @foo4()
+; CHECK-NEXT:    ret void
+; CHECK:       infloop:
+; CHECK-NEXT:    br label %infloop
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch_thread.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch_thread.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch_thread.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch_thread.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,113 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+; Test that we can thread a simple known condition through switch statements.
+
+declare void @foo1()
+
+declare void @foo2()
+
+declare void @DEAD()
+
+define void @test1(i32 %V) {
+        switch i32 %V, label %A [
+                 i32 4, label %T
+                 i32 17, label %Done
+                 i32 1234, label %A
+        ]
+;; V == 4 if we get here.
+T:              ; preds = %0
+        call void @foo1( )
+        ;; This switch is always statically determined.
+        switch i32 %V, label %A2 [
+                 i32 4, label %B
+                 i32 17, label %C
+                 i32 42, label %C
+        ]
+A2:             ; preds = %T
+        call void @DEAD( )
+        call void @DEAD( )
+        ;; always true
+        %cond2 = icmp eq i32 %V, 4              ; <i1> [#uses=1]
+        br i1 %cond2, label %Done, label %C
+A:              ; preds = %0, %0
+        call void @foo1( )
+        ;; always true
+        %cond = icmp ne i32 %V, 4               ; <i1> [#uses=1]
+        br i1 %cond, label %Done, label %C
+Done:           ; preds = %B, %A, %A2, %0
+        ret void
+B:              ; preds = %T
+        call void @foo2( )
+        ;; always true
+        %cond3 = icmp eq i32 %V, 4              ; <i1> [#uses=1]
+        br i1 %cond3, label %Done, label %C
+C:              ; preds = %B, %A, %A2, %T, %T
+        call void @DEAD( )
+        ret void
+
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    switch i32 %V, label %A [
+; CHECK-NEXT:    i32 4, label %T
+; CHECK-NEXT:    i32 17, label %Done
+; CHECK-NEXT:    ]
+; CHECK:       T:
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    call void @foo2()
+; CHECK-NEXT:    br label %Done
+; CHECK:       A:
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    br label %Done
+; CHECK:       Done:
+; CHECK-NEXT:    ret void
+}
+
+define void @test2(i32 %V) {
+        switch i32 %V, label %A [
+                 i32 4, label %T
+                 i32 17, label %D
+                 i32 1234, label %E
+        ]
+;; V != 4, 17, 1234 here.
+A:              ; preds = %0
+        call void @foo1( )
+        ;; This switch is always statically determined.
+        switch i32 %V, label %E [
+                 i32 4, label %C
+                 i32 17, label %C
+                 i32 42, label %D
+        ]
+;; unreacahble.
+C:              ; preds = %A, %A
+        call void @DEAD( )
+        ret void
+T:              ; preds = %0
+        call void @foo1( )
+        call void @foo1( )
+        ret void
+D:              ; preds = %A, %0
+        call void @foo1( )
+        ret void
+E:              ; preds = %A, %0
+        ret void
+
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    switch i32 %V, label %A [
+; CHECK-NEXT:    i32 4, label %T
+; CHECK-NEXT:    i32 17, label %D
+; CHECK-NEXT:    i32 1234, label %E
+; CHECK-NEXT:    ]
+; CHECK:       A:
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 %V, 42
+; CHECK-NEXT:    br i1 [[COND]], label %D, label %E
+; CHECK:       T:
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    ret void
+; CHECK:       D:
+; CHECK-NEXT:    call void @foo1()
+; CHECK-NEXT:    ret void
+; CHECK:       E:
+; CHECK-NEXT:    ret void
+}
+

Added: llvm/trunk/test/Transforms/SimplifyCFG/switch_undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/switch_undef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/switch_undef.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/switch_undef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt %s -keep-loops=false -switch-to-lookup=true -simplifycfg -S | FileCheck %s
+; RUN: opt %s -passes='simplify-cfg<no-keep-loops;switch-to-lookup>' -S | FileCheck %s
+
+define void @f6() #0 {
+; CHECK-LABEL: entry:
+
+entry:
+  br label %for.cond.i
+
+for.cond.i:                                       ; preds = %f1.exit.i, %entry
+  switch i16 undef, label %f1.exit.i [
+    i16 -1, label %cond.false.i3.i
+    i16 1, label %cond.false.i3.i
+    i16 0, label %cond.false.i3.i
+  ]
+
+cond.false.i3.i:                                  ; preds = %for.cond.i, %for.cond.i, %for.cond.i
+  br label %f1.exit.i
+
+f1.exit.i:                                        ; preds = %cond.false.i3.i, %for.cond.i
+  %cond.i4.i = phi i16 [ undef, %cond.false.i3.i ], [ 1, %for.cond.i ]
+  %tobool7.i = icmp ne i16 %cond.i4.i, 0
+  br label %for.cond.i
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; Radar 9342286
+; Assign DebugLoc to trap instruction.
+define void @foo() nounwind ssp !dbg !0 {
+; CHECK: call void @llvm.trap(), !dbg
+  store i32 42, i32* null, !dbg !5
+  ret void, !dbg !7
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10}
+
+!0 = distinct !DISubprogram(name: "foo", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !8, scope: !1, type: !3)
+!1 = !DIFile(filename: "foo.c", directory: "/private/tmp")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)", isOptimized: true, emissionKind: FullDebug, file: !8, enums: !{}, retainedTypes: !{})
+!3 = !DISubroutineType(types: !4)
+!4 = !{null}
+!5 = !DILocation(line: 4, column: 2, scope: !6)
+!6 = distinct !DILexicalBlock(line: 3, column: 12, file: !8, scope: !0)
+!7 = !DILocation(line: 5, column: 1, scope: !6)
+!8 = !DIFile(filename: "foo.c", directory: "/private/tmp")
+!10 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/SimplifyCFG/trap-no-null-opt-debugloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trap-no-null-opt-debugloc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/trap-no-null-opt-debugloc.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/trap-no-null-opt-debugloc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+define void @foo() nounwind ssp #0 !dbg !0 {
+; CHECK: store i32 42, i32* null
+; CHECK-NOT: call void @llvm.trap()
+; CHECK: ret void
+  store i32 42, i32* null, !dbg !5
+  ret void, !dbg !7
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10}
+
+!0 = distinct !DISubprogram(name: "foo", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !8, scope: !1, type: !3)
+!1 = !DIFile(filename: "foo.c", directory: "/private/tmp")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)", isOptimized: true, emissionKind: FullDebug, file: !8, enums: !{}, retainedTypes: !{})
+!3 = !DISubroutineType(types: !4)
+!4 = !{null}
+!5 = !DILocation(line: 4, column: 2, scope: !6)
+!6 = distinct !DILexicalBlock(line: 3, column: 12, file: !8, scope: !0)
+!7 = !DILocation(line: 5, column: 1, scope: !6)
+!8 = !DIFile(filename: "foo.c", directory: "/private/tmp")
+!10 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,125 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; PR2967
+
+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"
+target triple = "i386-pc-linux-gnu"
+
+define void @test1(i32 %x) nounwind {
+entry:
+        %0 = icmp eq i32 %x, 0          ; <i1> [#uses=1]
+        br i1 %0, label %bb, label %return
+
+bb:             ; preds = %entry
+        %1 = load volatile i32, i32* null
+        unreachable
+        
+        br label %return
+return:         ; preds = %entry
+        ret void
+; CHECK-LABEL: @test1(
+; CHECK: load volatile
+}
+
+define void @test1_no_null_opt(i32 %x) nounwind #0 {
+entry:
+        %0 = icmp eq i32 %x, 0          ; <i1> [#uses=1]
+        br i1 %0, label %bb, label %return
+
+bb:             ; preds = %entry
+        %1 = load volatile i32, i32* null
+        unreachable
+
+        br label %return
+return:         ; preds = %entry
+        ret void
+; CHECK-LABEL: @test1_no_null_opt(
+; CHECK: load volatile
+; CHECK: unreachable
+}
+
+; rdar://7958343
+define void @test2() nounwind {
+entry:
+        store i32 4,i32* null
+        ret void
+
+; CHECK-LABEL: @test2(
+; CHECK: call void @llvm.trap
+; CHECK: unreachable
+}
+
+define void @test2_no_null_opt() nounwind #0 {
+entry:
+        store i32 4,i32* null
+        ret void
+; CHECK-LABEL: @test2_no_null_opt(
+; CHECK: store i32 4, i32* null
+; CHECK-NOT: call void @llvm.trap
+; CHECK: ret
+}
+
+; PR7369
+define void @test3() nounwind {
+entry:
+        store volatile i32 4, i32* null
+        ret void
+
+; CHECK-LABEL: @test3(
+; CHECK: store volatile i32 4, i32* null
+; CHECK: ret
+}
+
+define void @test3_no_null_opt() nounwind #0 {
+entry:
+        store volatile i32 4, i32* null
+        ret void
+
+; CHECK-LABEL: @test3_no_null_opt(
+; CHECK: store volatile i32 4, i32* null
+; CHECK: ret
+}
+
+; Check store before unreachable.
+define void @test4(i1 %C, i32* %P) {
+; CHECK-LABEL: @test4(
+; CHECK: entry:
+; CHECK-NEXT: br i1 %C
+entry:
+  br i1 %C, label %T, label %F
+T:
+  store volatile i32 0, i32* %P
+  unreachable
+F:
+  ret void
+}
+
+; Check cmpxchg before unreachable.
+define void @test5(i1 %C, i32* %P) {
+; CHECK-LABEL: @test5(
+; CHECK: entry:
+; CHECK-NEXT: br i1 %C
+entry:
+  br i1 %C, label %T, label %F
+T:
+  cmpxchg volatile i32* %P, i32 0, i32 1 seq_cst seq_cst
+  unreachable
+F:
+  ret void
+}
+
+; Check atomicrmw before unreachable.
+define void @test6(i1 %C, i32* %P) {
+; CHECK-LABEL: @test6(
+; CHECK: entry:
+; CHECK-NEXT: br i1 %C
+entry:
+  br i1 %C, label %T, label %F
+T:
+  atomicrmw volatile xchg i32* %P, i32 0 seq_cst
+  unreachable
+F:
+  ret void
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/SimplifyCFG/two-entry-phi-return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/two-entry-phi-return.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/two-entry-phi-return.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/two-entry-phi-return.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+
+define i1 @qux(i8* %m, i8* %n, i8* %o, i8* %p) nounwind  {
+; CHECK-LABEL: @qux(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i8* %m, %n
+; CHECK-NEXT:    [[TMP15:%.*]] = icmp eq i8* %o, %p
+; CHECK-NEXT:    [[TMP15_:%.*]] = select i1 [[TMP7]], i1 [[TMP15]], i1 false, !prof !0
+; CHECK-NEXT:    ret i1 [[TMP15_]]
+;
+entry:
+  %tmp7 = icmp eq i8* %m, %n
+  br i1 %tmp7, label %bb, label %UnifiedReturnBlock, !prof !0
+
+bb:
+  %tmp15 = icmp eq i8* %o, %p
+  br label %UnifiedReturnBlock
+
+UnifiedReturnBlock:
+  %result = phi i1 [ 0, %entry ], [ %tmp15, %bb ]
+  ret i1 %result
+
+}
+
+!0 = !{!"branch_weights", i32 4, i32 64}

Added: llvm/trunk/test/Transforms/SimplifyCFG/unreachable-blocks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/unreachable-blocks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/unreachable-blocks.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/unreachable-blocks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -simplifycfg < %s -disable-output
+
+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-pc-linux-gnu"
+
+; PR11825
+define void @test1() {
+entry:
+  br label %return
+
+while_block:                                      ; preds = %and_if_cont2, %and_if_cont
+  %newlen = sub i32 %newlen, 1
+  %newptr = getelementptr i8, i8* %newptr, i64 1
+  %test = icmp sgt i32 %newlen, 0
+  br i1 %test, label %and_if1, label %and_if_cont2
+
+and_if1:                                          ; preds = %while_block
+  %char = load i8, i8* %newptr
+  %test2 = icmp ule i8 %char, 32
+  br label %and_if_cont2
+
+and_if_cont2:                                     ; preds = %and_if1, %while_block
+  %a18 = phi i1 [ %test, %while_block ], [ %test2, %and_if1 ]
+  br i1 %a18, label %while_block, label %return
+
+return:                                           ; preds = %and_if_cont2, %and_if_cont
+  ret void
+}

Added: llvm/trunk/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/unreachable-cleanuppad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -simplifycfg -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-win32"
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare void @fn_2()
+
+define void @fn_1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  br i1 %B, label %__Ea.exit, label %lor.lhs.false.i.i
+
+lor.lhs.false.i.i:
+  br i1 %B, label %if.end.i.i, label %__Ea.exit
+
+if.end.i.i:
+  invoke void @fn_2()
+          to label %__Ea.exit unwind label %ehcleanup.i
+
+ehcleanup.i:
+  %t4 = cleanuppad within none []
+  br label %arraydestroy.body.i
+
+arraydestroy.body.i:
+  %gep = getelementptr i8, i8* null, i32 -1
+  br label %dtor.exit.i
+
+dtor.exit.i:
+  br i1 %B, label %arraydestroy.done3.i, label %arraydestroy.body.i
+
+arraydestroy.done3.i:
+  cleanupret from %t4 unwind to caller
+
+__Ea.exit:
+  ret void
+}
+
+; CHECK-LABEL: define void @fn_1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret void

Added: llvm/trunk/test/Transforms/SimplifyCFG/volatile-phioper.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/volatile-phioper.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/volatile-phioper.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/volatile-phioper.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,48 @@
+; RUN: opt < %s -simplifycfg -S | FileCheck %s
+;
+; rdar:13349374
+;
+; SimplifyCFG should not eliminate blocks with volatile stores.
+; Essentially, volatile needs to be backdoor that tells the optimizer
+; it can no longer use language standard as an excuse. The compiler
+; needs to expose the volatile access to the platform.
+;
+; CHECK-LABEL: @test(
+; CHECK: entry:
+; CHECK: @Trace
+; CHECK: while.body:
+; CHECK: store volatile
+; CHECK: end:
+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"
+
+define void @test(i8** nocapture %PeiServices) #0 {
+entry:
+  %call = tail call i32 (...) @Trace() #2
+  %tobool = icmp eq i32 %call, 0
+  br i1 %tobool, label %while.body, label %if.then
+
+if.then:                                          ; preds = %entry
+  %call1 = tail call i32 (...) @Trace() #2
+  br label %while.body
+
+while.body:                                       ; preds = %entry, %if.then, %while.body
+  %Addr.017 = phi i8* [ %incdec.ptr, %while.body ], [ null, %if.then ], [ null, %entry ]
+  %x.016 = phi i8 [ %inc, %while.body ], [ 0, %if.then ], [ 0, %entry ]
+  %inc = add i8 %x.016, 1
+  %incdec.ptr = getelementptr inbounds i8, i8* %Addr.017, i64 1
+  store volatile i8 %x.016, i8* %Addr.017, align 1
+  %0 = ptrtoint i8* %incdec.ptr to i64
+  %1 = trunc i64 %0 to i32
+  %cmp = icmp ult i32 %1, 4096
+  br i1 %cmp, label %while.body, label %end
+
+end:
+  ret void
+}
+declare i32 @Trace(...) #1
+
+attributes #0 = { nounwind ssp uwtable "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "relocation-model"="pic" "ssp-buffers-size"="8" }
+attributes #1 = { "fp-contract-model"="standard" "no-frame-pointer-elim" "no-frame-pointer-elim-non-leaf" "relocation-model"="pic" "ssp-buffers-size"="8" }
+attributes #2 = { nounwind }
+
+!0 = !{i32 1039}

Added: llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,167 @@
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+declare void @Personality()
+declare void @f()
+
+; CHECK-LABEL: define void @test1()
+define void @test1() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  ; CHECK: call void @f()
+  invoke void @f()
+    to label %exit unwind label %unreachable.unwind
+exit:
+  ret void
+unreachable.unwind:
+  cleanuppad within none []
+  unreachable  
+}
+
+; CHECK-LABEL: define void @test2()
+define void @test2() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+    to label %exit unwind label %catch.pad
+catch.pad:
+  %cs1 = catchswitch within none [label %catch.body] unwind label %unreachable.unwind
+  ; CHECK: catch.pad:
+  ; CHECK-NEXT: catchswitch within none [label %catch.body] unwind to caller
+catch.body:
+  ; CHECK:      catch.body:
+  ; CHECK-NEXT:   catchpad within %cs1
+  ; CHECK-NEXT:   call void @f()
+  ; CHECK-NEXT:   unreachable
+  %catch = catchpad within %cs1 []
+  call void @f()
+  catchret from %catch to label %unreachable
+exit:
+  ret void
+unreachable.unwind:
+  cleanuppad within none []
+  unreachable
+unreachable:
+  unreachable
+}
+
+; CHECK-LABEL: define void @test3()
+define void @test3() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+    to label %exit unwind label %cleanup.pad
+cleanup.pad:
+  ; CHECK: %cleanup = cleanuppad within none []
+  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: unreachable
+  %cleanup = cleanuppad within none []
+  invoke void @f()
+    to label %cleanup.ret unwind label %unreachable.unwind
+cleanup.ret:
+  ; This cleanupret should be rewritten to unreachable,
+  ; and merged into the pred block.
+  cleanupret from %cleanup unwind label %unreachable.unwind
+exit:
+  ret void
+unreachable.unwind:
+  cleanuppad within none []
+  unreachable
+}
+
+; CHECK-LABEL: define void @test5()
+define void @test5() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+          to label %exit unwind label %catch.pad
+
+catch.pad:
+  %cs1 = catchswitch within none [label %catch.body] unwind to caller
+
+catch.body:
+  %catch = catchpad within %cs1 []
+  catchret from %catch to label %exit
+
+exit:
+  unreachable
+}
+
+; CHECK-LABEL: define void @test6()
+define void @test6() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+          to label %exit unwind label %catch.pad
+
+catch.pad:
+  %cs1 = catchswitch within none [label %catch.body, label %catch.body] unwind to caller
+  ; CHECK: catchswitch within none [label %catch.body] unwind to caller
+
+catch.body:
+  %catch = catchpad within %cs1 [i8* null, i32 0, i8* null]
+  catchret from %catch to label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: define void @test7()
+define void @test7() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+          to label %exit unwind label %catch.pad
+
+catch.pad:
+  %cs1 = catchswitch within none [label %catch.body, label %catch.body2] unwind to caller
+  ; CHECK: catchswitch within none [label %catch.body] unwind to caller
+
+catch.body:
+  %catch = catchpad within %cs1 [i8* null, i32 0, i8* null]
+  catchret from %catch to label %exit
+
+catch.body2:
+  %catch2 = catchpad within %cs1 [i8* null, i32 0, i8* null]
+  catchret from %catch2 to label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: define void @test8()
+define void @test8() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+          to label %exit unwind label %catch.pad
+
+catch.pad:
+  %cs1 = catchswitch within none [label %catch.body, label %catch.body2] unwind to caller
+  ; CHECK: catchswitch within none [label %catch.body] unwind to caller
+
+catch.body2:
+  %catch2 = catchpad within %cs1 [i8* null, i32 0, i8* null]
+  catchret from %catch2 to label %exit
+
+catch.body:
+  %catch = catchpad within %cs1 [i8* null, i32 0, i8* null]
+  catchret from %catch to label %exit
+
+exit:
+  ret void
+}
+
+; CHECK-LABEL: define void @test9()
+define void @test9() personality i8* bitcast (void ()* @Personality to i8*) {
+entry:
+  invoke void @f()
+          to label %exit unwind label %catch.pad
+
+catch.pad:
+  %cs1 = catchswitch within none [label %catch.body, label %catch.body2] unwind to caller
+  ; CHECK: catchswitch within none [label %catch.body, label %catch.body2] unwind to caller
+
+catch.body:
+  %catch = catchpad within %cs1 [i8* null, i32 0, i8* null]
+  catchret from %catch to label %exit
+
+catch.body2:
+  %catch2 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  catchret from %catch2 to label %exit
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/Sink/badloadsink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/badloadsink.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/badloadsink.ll (added)
+++ llvm/trunk/test/Transforms/Sink/badloadsink.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -basicaa -sink -S | FileCheck %s
+declare void @foo(i64 *)
+declare i8* @llvm.load.relative.i32(i8* %ptr, i32 %offset) argmemonly nounwind readonly
+define i64 @sinkload(i1 %cmp, i8* %ptr, i32 %off) {
+; CHECK-LABEL: @sinkload
+top:
+    %a = alloca i64
+; CHECK: call void @foo(i64* %a)
+; CHECK-NEXT: %x = load i64, i64* %a
+; CHECK-NEXT: %y = call i8* @llvm.load.relative.i32(i8* %ptr, i32 %off)
+    call void @foo(i64* %a)
+    %x = load i64, i64* %a
+    %y = call i8* @llvm.load.relative.i32(i8* %ptr, i32 %off)
+    br i1 %cmp, label %A, label %B
+A:
+    store i64 0, i64 *%a
+    store i8 0, i8 *%ptr
+    br label %B
+B:
+; CHECK-NOT: load i64, i64 *%a
+; CHECK-NOT: call i8* @llvm.load.relative(i8* %ptr, i32 off)
+    %y2 = ptrtoint i8* %y to i64
+    %retval = add i64 %y2, %x
+    ret i64 %retval
+}
+

Added: llvm/trunk/test/Transforms/Sink/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/basic.ll (added)
+++ llvm/trunk/test/Transforms/Sink/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,144 @@
+; RUN: opt < %s -basicaa -sink -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline='basic-aa' -passes='sink' -S | FileCheck %s
+
+ at A = external global i32
+ at B = external global i32
+
+; Sink should sink the load past the store (which doesn't overlap) into
+; the block that uses it.
+
+;      CHECK-LABEL: @foo(
+;      CHECK: true:
+; CHECK-NEXT: %l = load i32, i32* @A
+; CHECK-NEXT: ret i32 %l
+
+define i32 @foo(i1 %z) {
+  %l = load i32, i32* @A
+  store i32 0, i32* @B
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; But don't sink load volatiles...
+
+;      CHECK-LABEL: @foo2(
+;      CHECK: load volatile
+; CHECK-NEXT: store i32
+
+define i32 @foo2(i1 %z) {
+  %l = load volatile i32, i32* @A
+  store i32 0, i32* @B
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; Sink to the nearest post-dominator
+
+;      CHECK-LABEL: @diamond(
+;      CHECK: X:
+; CHECK-NEXT: phi
+; CHECK-NEXT: mul nsw
+; CHECK-NEXT: sub
+
+define i32 @diamond(i32 %a, i32 %b, i32 %c) {
+  %1 = mul nsw i32 %c, %b
+  %2 = icmp sgt i32 %a, 0
+  br i1 %2, label %B0, label %B1
+
+B0:                                       ; preds = %0
+  br label %X
+
+B1:                                      ; preds = %0
+  br label %X
+
+X:                                     ; preds = %5, %3
+  %.01 = phi i32 [ %c, %B0 ], [ %a, %B1 ]
+  %R = sub i32 %1, %.01
+  ret i32 %R
+}
+
+; We shouldn't sink constant sized allocas from the entry block, since CodeGen
+; interprets allocas outside the entry block as dynamically sized stack objects.
+
+; CHECK-LABEL: @alloca_nosink
+; CHECK: entry:
+; CHECK-NEXT: alloca
+define i32 @alloca_nosink(i32 %a, i32 %b) {
+entry:
+  %0 = alloca i32
+  %1 = icmp ne i32 %a, 0
+  br i1 %1, label %if, label %endif
+
+if:
+  %2 = getelementptr i32, i32* %0, i32 1
+  store i32 0, i32* %0
+  store i32 1, i32* %2
+  %3 = getelementptr i32, i32* %0, i32 %b
+  %4 = load i32, i32* %3
+  ret i32 %4
+
+endif:
+  ret i32 0
+}
+
+; Make sure we sink dynamic sized allocas
+
+; CHECK-LABEL: @alloca_sink_dynamic
+; CHECK: entry:
+; CHECK-NOT: alloca
+; CHECK: if:
+; CHECK-NEXT: alloca
+define i32 @alloca_sink_dynamic(i32 %a, i32 %b, i32 %size) {
+entry:
+  %0 = alloca i32, i32 %size
+  %1 = icmp ne i32 %a, 0
+  br i1 %1, label %if, label %endif
+
+if:
+  %2 = getelementptr i32, i32* %0, i32 1
+  store i32 0, i32* %0
+  store i32 1, i32* %2
+  %3 = getelementptr i32, i32* %0, i32 %b
+  %4 = load i32, i32* %3
+  ret i32 %4
+
+endif:
+  ret i32 0
+}
+
+; We also want to sink allocas that are not in the entry block.  These
+; will already be considered as dynamically sized stack objects, so sinking
+; them does no further damage.
+
+; CHECK-LABEL: @alloca_sink_nonentry
+; CHECK: if0:
+; CHECK-NOT: alloca
+; CHECK: if:
+; CHECK-NEXT: alloca
+define i32 @alloca_sink_nonentry(i32 %a, i32 %b, i32 %c) {
+entry:
+  %cmp = icmp ne i32 %c, 0
+  br i1 %cmp, label %endif, label %if0
+
+if0:
+  %0 = alloca i32
+  %1 = icmp ne i32 %a, 0
+  br i1 %1, label %if, label %endif
+
+if:
+  %2 = getelementptr i32, i32* %0, i32 1
+  store i32 0, i32* %0
+  store i32 1, i32* %2
+  %3 = getelementptr i32, i32* %0, i32 %b
+  %4 = load i32, i32* %3
+  ret i32 %4
+
+endif:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/Sink/call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/call.ll (added)
+++ llvm/trunk/test/Transforms/Sink/call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; RUN: opt < %s -basicaa -sink -S | FileCheck %s
+
+declare i32 @f_load_global() nounwind readonly
+declare i32 @f_load_arg(i32*) nounwind readonly argmemonly
+declare void @f_store_global(i32) nounwind
+declare void @f_store_arg(i32*) nounwind argmemonly
+declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly
+declare i32 @f_readnone(i32) nounwind readnone
+
+ at A = external global i32
+ at B = external global i32
+
+; Sink readonly call if no stores are in the way.
+;
+; CHECK-LABEL: @test_sink_no_stores(
+; CHECK: true:
+; CHECK-NEXT: %l = call i32 @f_load_global
+; CHECK-NEXT: ret i32 %l
+define i32 @test_sink_no_stores(i1 %z) {
+  %l = call i32 @f_load_global()
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; CHECK-LABEL: @test_sink_argmem_store(
+; CHECK: true:
+; CHECK-NEXT: %l = call i32 @f_load_arg
+; CHECK-NEXT: ret i32 %l
+define i32 @test_sink_argmem_store(i1 %z) {
+  %l = call i32 @f_load_arg(i32* @A)
+  store i32 0, i32* @B
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; CHECK-LABEL: @test_sink_argmem_call(
+; CHECK: true:
+; CHECK-NEXT: %l = call i32 @f_load_arg
+; CHECK-NEXT: ret i32 %l
+define i32 @test_sink_argmem_call(i1 %z) {
+  %l = call i32 @f_load_arg(i32* @A)
+  call void @f_store_arg(i32* @B)
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; CHECK-LABEL: @test_sink_argmem_multiple(
+; CHECK: true:
+; CHECK-NEXT: %l = call i32 @f_load_arg
+; CHECK-NEXT: ret i32 %l
+define i32 @test_sink_argmem_multiple(i1 %z) {
+  %l = call i32 @f_load_arg(i32* @A)
+  call void @f_readonly_arg(i32* @A, i32* @B)
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; But don't sink if there is a store.
+;
+; CHECK-LABEL: @test_nosink_store(
+; CHECK: call i32 @f_load_global
+; CHECK-NEXT: store i32
+define i32 @test_nosink_store(i1 %z) {
+  %l = call i32 @f_load_global()
+  store i32 0, i32* @A
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; CHECK-LABEL: @test_nosink_call(
+; CHECK: call i32 @f_load_global
+; CHECK-NEXT: call void @f_store_global
+define i32 @test_nosink_call(i1 %z) {
+  %l = call i32 @f_load_global()
+  call void @f_store_global(i32 0)
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}
+
+; readnone calls are sunk across stores.
+;
+; CHECK-LABEL: @test_sink_readnone(
+; CHECK: true:
+; CHECK-NEXT: %l = call i32 @f_readnone(
+; CHECK-NEXT: ret i32 %l
+define i32 @test_sink_readnone(i1 %z) {
+  %l = call i32 @f_readnone(i32 0)
+  store i32 0, i32* @A
+  br i1 %z, label %true, label %false
+true:
+  ret i32 %l
+false:
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/Sink/catchswitch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/catchswitch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/catchswitch.ll (added)
+++ llvm/trunk/test/Transforms/Sink/catchswitch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -sink -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"
+
+define void @h() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  %call = call i32 @g(i32 1) readnone
+  invoke void @_CxxThrowException(i8* null, i8* null) noreturn
+          to label %unreachable unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %cs = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %cp = catchpad within %cs [i8* null, i32 64, i8* null]
+  catchret from %cp to label %try.cont
+
+try.cont:                                         ; preds = %catch
+  call void @k(i32 %call)
+  ret void
+
+unreachable:                                      ; preds = %entry
+  unreachable
+}
+
+declare x86_stdcallcc void @_CxxThrowException(i8*, i8*)
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare i32 @g(i32) readnone
+
+declare void @k(i32)
+
+; CHECK-LABEL: define void @h(
+; CHECK: call i32 @g(i32 1)
+; CHECK-NEXT: invoke void @_CxxThrowException(

Added: llvm/trunk/test/Transforms/Sink/convergent.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/convergent.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/convergent.ll (added)
+++ llvm/trunk/test/Transforms/Sink/convergent.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -sink -S < %s | FileCheck %s
+
+; Verify that IR sinking does not move convergent operations to
+; blocks that are not control equivalent.
+
+; CHECK: define i32 @foo
+; CHECK: entry
+; CHECK-NEXT: call i32 @bar
+; CHECK-NEXT: br i1 %arg
+
+define i32 @foo(i1 %arg) {
+entry:
+  %c = call i32 @bar() readonly convergent
+  br i1 %arg, label %then, label %end
+
+then:
+  ret i32 %c
+
+end:
+  ret i32 0
+}
+
+declare i32 @bar() readonly convergent

Added: llvm/trunk/test/Transforms/Sink/fence.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/fence.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/fence.ll (added)
+++ llvm/trunk/test/Transforms/Sink/fence.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -S -sink < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @test1(i32* ()*) {
+entry:
+  %1 = call i32* %0() #0
+  fence syncscope("singlethread") seq_cst
+  %2 = load i32, i32* %1, align 4
+  fence syncscope("singlethread") seq_cst
+  %3 = icmp eq i32 %2, 0
+  br i1 %3, label %fail, label %pass
+
+fail:                                             ; preds = %top
+  br label %pass
+
+pass:                                             ; preds = %fail, %top
+  ret void
+}
+
+; CHECK-LABEL: @test1(
+; CHECK:  %[[call:.*]] = call i32* %0()
+; CHECK:  fence syncscope("singlethread") seq_cst
+; CHECK:  load i32, i32* %[[call]], align 4
+; CHECK:  fence syncscope("singlethread") seq_cst
+
+
+attributes #0 = { nounwind readnone }

Added: llvm/trunk/test/Transforms/Sink/landingpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/landingpad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/landingpad.ll (added)
+++ llvm/trunk/test/Transforms/Sink/landingpad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; Test that we don't sink landingpads
+; RUN: opt -sink -S < %s | FileCheck %s
+
+declare hidden void @g()
+declare void @h()
+declare i32 @__gxx_personality_v0(...)
+
+define void @f() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  invoke void @g()
+          to label %invoke.cont.15 unwind label %lpad
+
+invoke.cont.15:
+  unreachable
+
+; CHECK: lpad:
+; CHECK: %0 = landingpad { i8*, i32 }
+lpad:
+  %0 = landingpad { i8*, i32 }
+          catch i8* null
+  invoke void @h()
+          to label %invoke.cont unwind label %lpad.1
+
+; CHECK: invoke.cont
+; CHECK-NOT: %0 = landingpad { i8*, i32 }
+invoke.cont:
+  ret void
+
+lpad.1:
+  %1 = landingpad { i8*, i32 }
+          cleanup
+  resume { i8*, i32 } %1
+}

Added: llvm/trunk/test/Transforms/SpeculateAroundPHIs/basic-x86.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculateAroundPHIs/basic-x86.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SpeculateAroundPHIs/basic-x86.ll (added)
+++ llvm/trunk/test/Transforms/SpeculateAroundPHIs/basic-x86.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,595 @@
+; Test the basic functionality of speculating around PHI nodes based on reduced
+; cost of the constant operands to the PHI nodes using the x86 cost model.
+;
+; REQUIRES: x86-registered-target
+; RUN: opt -S -passes=spec-phis < %s | FileCheck %s
+
+target triple = "x86_64-unknown-unknown"
+
+define i32 @test_basic(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_basic(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %arg, 7
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %arg, 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %sum = add i32 %arg, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+; Check that we handle commuted operands and get the constant onto the RHS.
+define i32 @test_commuted(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_commuted(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %arg, 7
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %arg, 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %sum = add i32 %p, %arg
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+define i32 @test_split_crit_edge(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_split_crit_edge(
+entry:
+  br i1 %flag, label %exit, label %a
+; CHECK:       entry:
+; CHECK-NEXT:    br i1 %flag, label %[[ENTRY_SPLIT:.*]], label %a
+;
+; CHECK:       [[ENTRY_SPLIT]]:
+; CHECK-NEXT:    %[[SUM_ENTRY_SPLIT:.*]] = add i32 %arg, 7
+; CHECK-NEXT:    br label %exit
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %arg, 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %entry ], [ 11, %a ]
+  %sum = add i32 %arg, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_ENTRY_SPLIT]], %[[ENTRY_SPLIT]] ], [ %[[SUM_A]], %a ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+define i32 @test_no_spec_dominating_inst(i1 %flag, i32* %ptr) {
+; CHECK-LABEL: define i32 @test_no_spec_dominating_inst(
+entry:
+  %load = load i32, i32* %ptr
+  br i1 %flag, label %a, label %b
+; CHECK:         %[[LOAD:.*]] = load i32, i32* %ptr
+; CHECK-NEXT:    br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %[[LOAD]], 7
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %[[LOAD]], 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %sum = add i32 %load, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+; We have special logic handling PHI nodes, make sure it doesn't get confused
+; by a dominating PHI.
+define i32 @test_no_spec_dominating_phi(i1 %flag1, i1 %flag2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_no_spec_dominating_phi(
+entry:
+  br i1 %flag1, label %x.block, label %y.block
+; CHECK:       entry:
+; CHECK-NEXT:    br i1 %flag1, label %x.block, label %y.block
+
+x.block:
+  br label %merge
+; CHECK:       x.block:
+; CHECK-NEXT:    br label %merge
+
+y.block:
+  br label %merge
+; CHECK:       y.block:
+; CHECK-NEXT:    br label %merge
+
+merge:
+  %xy.phi = phi i32 [ %x, %x.block ], [ %y, %y.block ]
+  br i1 %flag2, label %a, label %b
+; CHECK:       merge:
+; CHECK-NEXT:    %[[XY_PHI:.*]] = phi i32 [ %x, %x.block ], [ %y, %y.block ]
+; CHECK-NEXT:    br i1 %flag2, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %[[XY_PHI]], 7
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %[[XY_PHI]], 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %sum = add i32 %xy.phi, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[SUM_PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT:    ret i32 %[[SUM_PHI]]
+}
+
+; Ensure that we will speculate some number of "free" instructions on the given
+; architecture even though they are unrelated to the PHI itself.
+define i32 @test_speculate_free_insts(i1 %flag, i64 %arg) {
+; CHECK-LABEL: define i32 @test_speculate_free_insts(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[T1_A:.*]] = trunc i64 %arg to i48
+; CHECK-NEXT:    %[[T2_A:.*]] = trunc i48 %[[T1_A]] to i32
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %[[T2_A]], 7
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[T1_B:.*]] = trunc i64 %arg to i48
+; CHECK-NEXT:    %[[T2_B:.*]] = trunc i48 %[[T1_B]] to i32
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %[[T2_B]], 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %t1 = trunc i64 %arg to i48
+  %t2 = trunc i48 %t1 to i32
+  %sum = add i32 %t2, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+define i32 @test_speculate_free_phis(i1 %flag, i32 %arg1, i32 %arg2) {
+; CHECK-LABEL: define i32 @test_speculate_free_phis(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %arg1, 7
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %arg2, 11
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p1 = phi i32 [ 7, %a ], [ 11, %b ]
+  %p2 = phi i32 [ %arg1, %a ], [ %arg2, %b ]
+  %sum = add i32 %p2, %p1
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; We don't DCE the now unused PHI node...
+; CHECK-NEXT:    %{{.*}} = phi i32 [ %arg1, %a ], [ %arg2, %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+; We shouldn't speculate multiple uses even if each individually looks
+; profitable because of the total cost.
+define i32 @test_no_spec_multi_uses(i1 %flag, i32 %arg1, i32 %arg2, i32 %arg3) {
+; CHECK-LABEL: define i32 @test_no_spec_multi_uses(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %add1 = add i32 %arg1, %p
+  %add2 = add i32 %arg2, %p
+  %add3 = add i32 %arg3, %p
+  %sum1 = add i32 %add1, %add2
+  %sum2 = add i32 %sum1, %add3
+  ret i32 %sum2
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT:    %[[ADD1:.*]] = add i32 %arg1, %[[PHI]]
+; CHECK-NEXT:    %[[ADD2:.*]] = add i32 %arg2, %[[PHI]]
+; CHECK-NEXT:    %[[ADD3:.*]] = add i32 %arg3, %[[PHI]]
+; CHECK-NEXT:    %[[SUM1:.*]] = add i32 %[[ADD1]], %[[ADD2]]
+; CHECK-NEXT:    %[[SUM2:.*]] = add i32 %[[SUM1]], %[[ADD3]]
+; CHECK-NEXT:    ret i32 %[[SUM2]]
+}
+
+define i32 @test_multi_phis1(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_multi_phis1(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A1:.*]] = add i32 %arg, 1
+; CHECK-NEXT:    %[[SUM_A2:.*]] = add i32 %[[SUM_A1]], 3
+; CHECK-NEXT:    %[[SUM_A3:.*]] = add i32 %[[SUM_A2]], 5
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B1:.*]] = add i32 %arg, 2
+; CHECK-NEXT:    %[[SUM_B2:.*]] = add i32 %[[SUM_B1]], 4
+; CHECK-NEXT:    %[[SUM_B3:.*]] = add i32 %[[SUM_B2]], 6
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p1 = phi i32 [ 1, %a ], [ 2, %b ]
+  %p2 = phi i32 [ 3, %a ], [ 4, %b ]
+  %p3 = phi i32 [ 5, %a ], [ 6, %b ]
+  %sum1 = add i32 %arg, %p1
+  %sum2 = add i32 %sum1, %p2
+  %sum3 = add i32 %sum2, %p3
+  ret i32 %sum3
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A3]], %a ], [ %[[SUM_B3]], %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+; Check that the order of the PHIs doesn't impact the behavior.
+define i32 @test_multi_phis2(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_multi_phis2(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:         br i1 %flag, label %a, label %b
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A1:.*]] = add i32 %arg, 1
+; CHECK-NEXT:    %[[SUM_A2:.*]] = add i32 %[[SUM_A1]], 3
+; CHECK-NEXT:    %[[SUM_A3:.*]] = add i32 %[[SUM_A2]], 5
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B1:.*]] = add i32 %arg, 2
+; CHECK-NEXT:    %[[SUM_B2:.*]] = add i32 %[[SUM_B1]], 4
+; CHECK-NEXT:    %[[SUM_B3:.*]] = add i32 %[[SUM_B2]], 6
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p3 = phi i32 [ 5, %a ], [ 6, %b ]
+  %p2 = phi i32 [ 3, %a ], [ 4, %b ]
+  %p1 = phi i32 [ 1, %a ], [ 2, %b ]
+  %sum1 = add i32 %arg, %p1
+  %sum2 = add i32 %sum1, %p2
+  %sum3 = add i32 %sum2, %p3
+  ret i32 %sum3
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ %[[SUM_A3]], %a ], [ %[[SUM_B3]], %b ]
+; CHECK-NEXT:    ret i32 %[[PHI]]
+}
+
+define i32 @test_no_spec_indirectbr(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_no_spec_indirectbr(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:       entry:
+; CHECK-NEXT:    br i1 %flag, label %a, label %b
+
+a:
+  indirectbr i8* undef, [label %exit]
+; CHECK:       a:
+; CHECK-NEXT:    indirectbr i8* undef, [label %exit]
+
+b:
+  indirectbr i8* undef, [label %exit]
+; CHECK:       b:
+; CHECK-NEXT:    indirectbr i8* undef, [label %exit]
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %sum = add i32 %arg, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT:    %[[SUM:.*]] = add i32 %arg, %[[PHI]]
+; CHECK-NEXT:    ret i32 %[[SUM]]
+}
+
+declare void @g()
+
+declare i32 @__gxx_personality_v0(...)
+
+; FIXME: We should be able to handle this case -- only the exceptional edge is
+; impossible to split.
+define i32 @test_no_spec_invoke_continue(i1 %flag, i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: define i32 @test_no_spec_invoke_continue(
+entry:
+  br i1 %flag, label %a, label %b
+; CHECK:       entry:
+; CHECK-NEXT:    br i1 %flag, label %a, label %b
+
+a:
+  invoke void @g()
+          to label %exit unwind label %lpad
+; CHECK:       a:
+; CHECK-NEXT:    invoke void @g()
+; CHECK-NEXT:            to label %exit unwind label %lpad
+
+b:
+  invoke void @g()
+          to label %exit unwind label %lpad
+; CHECK:       b:
+; CHECK-NEXT:    invoke void @g()
+; CHECK-NEXT:            to label %exit unwind label %lpad
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %sum = add i32 %arg, %p
+  ret i32 %sum
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT:    %[[SUM:.*]] = add i32 %arg, %[[PHI]]
+; CHECK-NEXT:    ret i32 %[[SUM]]
+
+lpad:
+  %lp = landingpad { i8*, i32 }
+          cleanup
+  resume { i8*, i32 } undef
+}
+
+define i32 @test_no_spec_landingpad(i32 %arg, i32* %ptr) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK-LABEL: define i32 @test_no_spec_landingpad(
+entry:
+  invoke void @g()
+          to label %invoke.cont unwind label %lpad
+; CHECK:       entry:
+; CHECK-NEXT:    invoke void @g()
+; CHECK-NEXT:            to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  invoke void @g()
+          to label %exit unwind label %lpad
+; CHECK:       invoke.cont:
+; CHECK-NEXT:    invoke void @g()
+; CHECK-NEXT:            to label %exit unwind label %lpad
+
+lpad:
+  %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+  %lp = landingpad { i8*, i32 }
+          cleanup
+  %sum = add i32 %arg, %p
+  store i32 %sum, i32* %ptr
+  resume { i8*, i32 } undef
+; CHECK:       lpad:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+
+exit:
+  ret i32 0
+}
+
+declare i32 @__CxxFrameHandler3(...)
+
+define i32 @test_no_spec_cleanuppad(i32 %arg, i32* %ptr) personality i32 (...)* @__CxxFrameHandler3 {
+; CHECK-LABEL: define i32 @test_no_spec_cleanuppad(
+entry:
+  invoke void @g()
+          to label %invoke.cont unwind label %lpad
+; CHECK:       entry:
+; CHECK-NEXT:    invoke void @g()
+; CHECK-NEXT:            to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+  invoke void @g()
+          to label %exit unwind label %lpad
+; CHECK:       invoke.cont:
+; CHECK-NEXT:    invoke void @g()
+; CHECK-NEXT:            to label %exit unwind label %lpad
+
+lpad:
+  %p = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+  %cp = cleanuppad within none []
+  %sum = add i32 %arg, %p
+  store i32 %sum, i32* %ptr
+  cleanupret from %cp unwind to caller
+; CHECK:       lpad:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ 7, %entry ], [ 11, %invoke.cont ]
+
+exit:
+  ret i32 0
+}
+
+; Check that we don't fall over when confronted with seemingly reasonable code
+; for us to handle but in an unreachable region and with non-PHI use-def
+; cycles.
+define i32 @test_unreachable_non_phi_cycles(i1 %flag, i32 %arg) {
+; CHECK-LABEL: define i32 @test_unreachable_non_phi_cycles(
+entry:
+  ret i32 42
+; CHECK:       entry:
+; CHECK-NEXT:    ret i32 42
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i32 [ 7, %a ], [ 11, %b ]
+  %zext = zext i32 %sum to i64
+  %trunc = trunc i64 %zext to i32
+  %sum = add i32 %trunc, %p
+  br i1 %flag, label %a, label %b
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i32 [ 7, %a ], [ 11, %b ]
+; CHECK-NEXT:    %[[ZEXT:.*]] = zext i32 %[[SUM:.*]] to i64
+; CHECK-NEXT:    %[[TRUNC:.*]] = trunc i64 %[[ZEXT]] to i32
+; CHECK-NEXT:    %[[SUM]] = add i32 %[[TRUNC]], %[[PHI]]
+; CHECK-NEXT:    br i1 %flag, label %a, label %b
+}
+
+; Check that we don't speculate in the face of an expensive immediate. There
+; are two reasons this should never speculate. First, even a local analysis
+; should fail because it makes some paths (%a) potentially more expensive due
+; to multiple uses of the immediate. Additionally, when we go to speculate the
+; instructions, their cost will also be too high.
+; FIXME: The goal is really to test the first property, but there doesn't
+; happen to be any way to use free-to-speculate instructions here so that it
+; would be the only interesting property.
+define i64 @test_expensive_imm(i32 %flag, i64 %arg) {
+; CHECK-LABEL: define i64 @test_expensive_imm(
+entry:
+  switch i32 %flag, label %a [
+    i32 1, label %b
+    i32 2, label %c
+    i32 3, label %d
+  ]
+; CHECK:         switch i32 %flag, label %a [
+; CHECK-NEXT:      i32 1, label %b
+; CHECK-NEXT:      i32 2, label %c
+; CHECK-NEXT:      i32 3, label %d
+; CHECK-NEXT:    ]
+
+a:
+  br label %exit
+; CHECK:       a:
+; CHECK-NEXT:    br label %exit
+
+b:
+  br label %exit
+; CHECK:       b:
+; CHECK-NEXT:    br label %exit
+
+c:
+  br label %exit
+; CHECK:       c:
+; CHECK-NEXT:    br label %exit
+
+d:
+  br label %exit
+; CHECK:       d:
+; CHECK-NEXT:    br label %exit
+
+exit:
+  %p = phi i64 [ 4294967296, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
+  %sum1 = add i64 %arg, %p
+  %sum2 = add i64 %sum1, %p
+  ret i64 %sum2
+; CHECK:       exit:
+; CHECK-NEXT:    %[[PHI:.*]] = phi i64 [ {{[0-9]+}}, %a ], [ 1, %b ], [ 1, %c ], [ 1, %d ]
+; CHECK-NEXT:    %[[SUM1:.*]] = add i64 %arg, %[[PHI]]
+; CHECK-NEXT:    %[[SUM2:.*]] = add i64 %[[SUM1]], %[[PHI]]
+; CHECK-NEXT:    ret i64 %[[SUM2]]
+}
+
+define i32 @test_no_spec_non_postdominating_uses(i1 %flag1, i1 %flag2, i32 %arg) {
+; CHECK-LABEL: define i32 @test_no_spec_non_postdominating_uses(
+entry:
+  br i1 %flag1, label %a, label %b
+; CHECK:         br i1 %flag1, label %a, label %b
+
+a:
+  br label %merge
+; CHECK:       a:
+; CHECK-NEXT:    %[[SUM_A:.*]] = add i32 %arg, 7
+; CHECK-NEXT:    br label %merge
+
+b:
+  br label %merge
+; CHECK:       b:
+; CHECK-NEXT:    %[[SUM_B:.*]] = add i32 %arg, 11
+; CHECK-NEXT:    br label %merge
+
+merge:
+  %p1 = phi i32 [ 7, %a ], [ 11, %b ]
+  %p2 = phi i32 [ 13, %a ], [ 42, %b ]
+  %sum1 = add i32 %arg, %p1
+  br i1 %flag2, label %exit1, label %exit2
+; CHECK:       merge:
+; CHECK-NEXT:    %[[PHI1:.*]] = phi i32 [ %[[SUM_A]], %a ], [ %[[SUM_B]], %b ]
+; CHECK-NEXT:    %[[PHI2:.*]] = phi i32 [ 13, %a ], [ 42, %b ]
+; CHECK-NEXT:    br i1 %flag2, label %exit1, label %exit2
+
+exit1:
+  ret i32 %sum1
+; CHECK:       exit1:
+; CHECK-NEXT:    ret i32 %[[PHI1]]
+
+exit2:
+  %sum2 = add i32 %arg, %p2
+  ret i32 %sum2
+; CHECK:       exit2:
+; CHECK-NEXT:    %[[SUM2:.*]] = add i32 %arg, %[[PHI2]]
+; CHECK-NEXT:    ret i32 %[[SUM2]]
+}

Added: llvm/trunk/test/Transforms/SpeculativeExecution/spec-calls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec-calls.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SpeculativeExecution/spec-calls.ll (added)
+++ llvm/trunk/test/Transforms/SpeculativeExecution/spec-calls.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN:   | FileCheck %s
+
+declare float @llvm.fabs.f32(float) nounwind readnone
+declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
+
+declare float @unknown(float)
+declare float @unknown_readnone(float) nounwind readnone
+
+; CHECK-LABEL: @ifThen_fabs(
+; CHECK: call float @llvm.fabs.f32(
+; CHECK: br i1 true
+define void @ifThen_fabs() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = call float @llvm.fabs.f32(float 1.0)
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_ctlz(
+; CHECK: call i32 @llvm.ctlz.i32(
+; CHECK: br i1 true
+define void @ifThen_ctlz() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = call i32 @llvm.ctlz.i32(i32 0, i1 true)
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_call_sideeffects(
+; CHECK: br i1 true
+; CHECK: call float @unknown(
+define void @ifThen_call_sideeffects() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = call float @unknown(float 1.0)
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_call_readnone(
+; CHECK: br i1 true
+; CHECK: call float @unknown_readnone(
+define void @ifThen_call_readnone() {
+  br i1 true, label %a, label %b
+a:
+  %x = call float @unknown_readnone(float 1.0)
+  br label %b
+
+b:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SpeculativeExecution/spec-casts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec-casts.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SpeculativeExecution/spec-casts.ll (added)
+++ llvm/trunk/test/Transforms/SpeculativeExecution/spec-casts.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,136 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN:   | FileCheck %s
+
+; CHECK-LABEL: @ifThen_bitcast(
+; CHECK: bitcast
+; CHECK: br i1 true
+define void @ifThen_bitcast() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = bitcast i32 undef to float
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_ptrtoint(
+; CHECK: ptrtoint
+; CHECK: br i1 true
+define void @ifThen_ptrtoint() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = ptrtoint i32* undef to i64
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_inttoptr(
+; CHECK: inttoptr
+; CHECK: br i1 true
+define void @ifThen_inttoptr() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = inttoptr i64 undef to i32*
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_addrspacecast(
+; CHECK: addrspacecast
+; CHECK: br i1 true
+define void @ifThen_addrspacecast() {
+  br i1 true, label %a, label %b
+a:
+  %x = addrspacecast i32* undef to i32 addrspace(1)*
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fptoui(
+; CHECK: fptoui
+; CHECK: br i1 true
+define void @ifThen_fptoui() {
+  br i1 true, label %a, label %b
+a:
+  %x = fptoui float undef to i32
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fptosi(
+; CHECK: fptosi
+; CHECK: br i1 true
+define void @ifThen_fptosi() {
+  br i1 true, label %a, label %b
+a:
+  %x = fptosi float undef to i32
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_uitofp(
+; CHECK: uitofp
+; CHECK: br i1 true
+define void @ifThen_uitofp() {
+  br i1 true, label %a, label %b
+a:
+  %x = uitofp i32 undef to float
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_sitofp(
+; CHECK: sitofp
+; CHECK: br i1 true
+define void @ifThen_sitofp() {
+  br i1 true, label %a, label %b
+a:
+  %x = sitofp i32 undef to float
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fpext(
+; CHECK: fpext
+; CHECK: br i1 true
+define void @ifThen_fpext() {
+  br i1 true, label %a, label %b
+a:
+  %x = fpext float undef to double
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fptrunc(
+; CHECK: fptrunc
+; CHECK: br i1 true
+define void @ifThen_fptrunc() {
+  br i1 true, label %a, label %b
+a:
+  %x = fptrunc double undef to float
+  br label %b
+
+b:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SpeculativeExecution/spec-compares.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec-compares.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SpeculativeExecution/spec-compares.ll (added)
+++ llvm/trunk/test/Transforms/SpeculativeExecution/spec-compares.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN:   | FileCheck %s
+
+; CHECK-LABEL: @ifThen_icmp(
+; CHECK: icmp
+; CHECK: br i1 true
+define void @ifThen_icmp() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = icmp eq i32 undef, undef
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fcmp(
+; CHECK: fcmp
+; CHECK: br i1 true
+define void @ifThen_fcmp() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = fcmp oeq float undef, undef
+  br label %b
+
+b:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SpeculativeExecution/spec-fp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec-fp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SpeculativeExecution/spec-fp.ll (added)
+++ llvm/trunk/test/Transforms/SpeculativeExecution/spec-fp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN:   | FileCheck %s
+
+; CHECK-LABEL: @ifThen_fadd(
+; CHECK: fadd
+; CHECK: br i1 true
+define void @ifThen_fadd() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = fadd float undef, undef
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fsub(
+; CHECK: fsub
+; CHECK: br i1 true
+define void @ifThen_fsub() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = fsub float undef, undef
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fneg(
+; CHECK: fsub float -0.0
+; CHECK: br i1 true
+define void @ifThen_fneg() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = fsub float -0.0, undef
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fmul(
+; CHECK: fmul
+; CHECK: br i1 true
+define void @ifThen_fmul() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = fmul float undef, undef
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_fdiv(
+; CHECK: fdiv
+; CHECK: br i1 true
+define void @ifThen_fdiv() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = fdiv float undef, undef
+  br label %b
+
+b:
+  ret void
+}
+
+; CHECK-LABEL: @ifThen_frem(
+; CHECK: frem
+; CHECK: br i1 true
+define void @ifThen_frem() {
+  br i1 true, label %a, label %b
+
+a:
+  %x = frem float undef, undef
+  br label %b
+
+b:
+  ret void
+}

Added: llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll (added)
+++ llvm/trunk/test/Transforms/SpeculativeExecution/spec.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,198 @@
+; RUN: opt < %s -S -speculative-execution \
+; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN:   | FileCheck %s
+; RUN: opt < %s -S -passes='speculative-execution' \
+; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
+; RUN:   | FileCheck %s
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
+
+; Hoist in if-then pattern.
+define void @ifThen() {
+; CHECK-LABEL: @ifThen(
+; CHECK: %x = add i32 2, 3
+; CHECK: br i1 true
+  br i1 true, label %a, label %b
+; CHECK: a:
+a:
+  %x = add i32 2, 3
+; CHECK: br label
+  br label %b
+; CHECK: b:
+b:
+; CHECK: ret void
+  ret void
+}
+
+; Hoist in if-else pattern.
+define void @ifElse() {
+; CHECK-LABEL: @ifElse(
+; CHECK: %x = add i32 2, 3
+; CHECK: br i1 true
+  br i1 true, label %b, label %a
+; CHECK: a:
+a:
+  %x = add i32 2, 3
+; CHECK: br label
+  br label %b
+; CHECK: b:
+b:
+; CHECK: ret void
+  ret void
+}
+
+; Hoist in if-then-else pattern if it is equivalent to if-then.
+define void @ifElseThenAsIfThen() {
+; CHECK-LABEL: @ifElseThenAsIfThen(
+; CHECK: %x = add i32 2, 3
+; CHECK: br
+  br i1 true, label %a, label %b
+; CHECK: a:
+a:
+  %x = add i32 2, 3
+; CHECK: br label
+  br label %c
+; CHECK: b:
+b:
+  br label %c
+; CHECK: c
+c:
+  ret void
+}
+
+; Hoist in if-then-else pattern if it is equivalent to if-else.
+define void @ifElseThenAsIfElse() {
+; CHECK-LABEL: @ifElseThenAsIfElse(
+; CHECK: %x = add i32 2, 3
+; CHECK: br
+  br i1 true, label %b, label %a
+; CHECK: a:
+a:
+  %x = add i32 2, 3
+; CHECK: br label
+  br label %c
+; CHECK: b:
+b:
+  br label %c
+; CHECK: c
+c:
+  ret void
+}
+
+; Do not hoist if-then-else pattern if it is not equivalent to if-then
+; or if-else.
+define void @ifElseThen() {
+; CHECK-LABEL: @ifElseThen(
+; CHECK: br
+  br i1 true, label %a, label %b
+; CHECK: a:
+a:
+; CHECK: %x = add
+  %x = add i32 2, 3
+; CHECK: br label
+  br label %c
+; CHECK: b:
+b:
+; CHECK: %y = add
+  %y = add i32 2, 3
+  br label %c
+; CHECK: c
+c:
+  ret void
+}
+
+; Do not hoist loads and do not hoist an instruction past a definition of
+; an operand.
+define void @doNotHoistPastDef() {
+; CHECK-LABEL: @doNotHoistPastDef(
+  br i1 true, label %b, label %a
+; CHECK-NOT: load
+; CHECK-NOT: add
+; CHECK: a:
+a:
+; CHECK: %def = load
+  %def = load i32, i32* null
+; CHECK: %use = add
+  %use = add i32 %def, 0
+  br label %b
+; CHECK: b:
+b:
+  ret void
+}
+
+; Case with nothing to speculate.
+define void @nothingToSpeculate() {
+; CHECK-LABEL: @nothingToSpeculate(
+  br i1 true, label %b, label %a
+; CHECK: a:
+a:
+; CHECK: %def = load
+  %def = load i32, i32* null
+  br label %b
+; CHECK: b:
+b:
+  ret void
+}
+
+; Still hoist if an operand is defined before the block or is itself hoisted.
+define void @hoistIfNotPastDef() {
+; CHECK-LABEL: @hoistIfNotPastDef(
+; CHECK: %x = load
+  %x = load i32, i32* null
+; CHECK: %y = add i32 %x, 1
+; CHECK: %z = add i32 %y, 1
+; CHECK: br
+  br i1 true, label %b, label %a
+; CHECK: a:
+a:
+  %y = add i32 %x, 1
+  %z = add i32 %y, 1
+  br label %b
+; CHECK: b:
+b:
+  ret void
+}
+
+; Do not hoist if the speculation cost is too high.
+define void @costTooHigh() {
+; CHECK-LABEL: @costTooHigh(
+; CHECK: br
+  br i1 true, label %b, label %a
+; CHECK: a:
+a:
+; CHECK: %r1 = add
+  %r1 = add i32 1, 1
+; CHECK: %r2 = add
+  %r2 = add i32 1, 1
+; CHECK: %r3 = add
+  %r3 = add i32 1, 1
+; CHECK: %r4 = add
+  %r4 = add i32 1, 1
+; CHECK: %r5 = add
+  %r5 = add i32 1, 1
+  br label %b
+; CHECK: b:
+b:
+  ret void
+}
+
+; Do not hoist if too many instructions are left behind.
+define void @tooMuchLeftBehind() {
+; CHECK-LABEL: @tooMuchLeftBehind(
+; CHECK: br
+  br i1 true, label %b, label %a
+; CHECK: a:
+a:
+; CHECK: %x = load
+  %x = load i32, i32* null
+; CHECK: %r1 = add
+  %r1 = add i32 %x, 1
+; CHECK: %r2 = add
+  %r2 = add i32 %x, 1
+; CHECK: %r3 = add
+  %r3 = add i32 %x, 1
+  br label %b
+; CHECK: b:
+b:
+  ret void
+}

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

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/pr23975.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/pr23975.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/pr23975.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/pr23975.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -slsr -S | FileCheck %s
+
+target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"
+target triple = "amdgcn--"
+
+%struct.Matrix4x4 = type { [4 x [4 x float]] }
+
+; Function Attrs: nounwind
+define fastcc void @Accelerator_Intersect(%struct.Matrix4x4 addrspace(1)* nocapture readonly %leafTransformations) #0 {
+; CHECK-LABEL:  @Accelerator_Intersect(
+entry:
+  %tmp = sext i32 undef to i64
+  %arrayidx114 = getelementptr inbounds %struct.Matrix4x4, %struct.Matrix4x4 addrspace(1)* %leafTransformations, i64 %tmp
+  %tmp1 = getelementptr %struct.Matrix4x4, %struct.Matrix4x4 addrspace(1)* %leafTransformations, i64 %tmp, i32 0, i64 0, i64 0
+; CHECK: %tmp1 = getelementptr %struct.Matrix4x4, %struct.Matrix4x4 addrspace(1)* %leafTransformations, i64 %tmp, i32 0, i64 0, i64 0
+  %tmp2 = load <4 x float>, <4 x float> addrspace(1)* undef, align 4
+  ret void
+}
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "target-cpu"="tahiti" "unsafe-fp-math"="false" "use-soft-float"="false" }

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/reassociate-geps-and-slsr-addrspace.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/reassociate-geps-and-slsr-addrspace.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/reassociate-geps-and-slsr-addrspace.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/AMDGPU/reassociate-geps-and-slsr-addrspace.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,107 @@
+; RUN: opt -S -mtriple=amdgcn-- -separate-const-offset-from-gep -slsr -gvn < %s | FileCheck %s
+
+target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64"
+
+
+; CHECK-LABEL: @slsr_after_reassociate_global_geps_mubuf_max_offset(
+; CHECK: [[b1:%[0-9]+]] = getelementptr float, float addrspace(1)* %arr, i64 [[bump:%[0-9]+]]
+; CHECK: [[b2:%[0-9]+]] = getelementptr float, float addrspace(1)* [[b1]], i64 [[bump]]
+define amdgpu_kernel void @slsr_after_reassociate_global_geps_mubuf_max_offset(float addrspace(1)* %out, float addrspace(1)* noalias %arr, i32 %i) {
+bb:
+  %i2 = shl nsw i32 %i, 1
+  %j1 = add nsw i32 %i, 1023
+  %tmp = sext i32 %j1 to i64
+  %p1 = getelementptr inbounds float, float addrspace(1)* %arr, i64 %tmp
+  %tmp3 = bitcast float addrspace(1)* %p1 to i32 addrspace(1)*
+  %v11 = load i32, i32 addrspace(1)* %tmp3, align 4
+  %tmp4 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v11, i32 addrspace(1)* %tmp4, align 4
+
+  %j2 = add nsw i32 %i2, 1023
+  %tmp5 = sext i32 %j2 to i64
+  %p2 = getelementptr inbounds float, float addrspace(1)* %arr, i64 %tmp5
+  %tmp6 = bitcast float addrspace(1)* %p2 to i32 addrspace(1)*
+  %v22 = load i32, i32 addrspace(1)* %tmp6, align 4
+  %tmp7 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v22, i32 addrspace(1)* %tmp7, align 4
+
+  ret void
+}
+
+; CHECK-LABEL: @slsr_after_reassociate_global_geps_over_mubuf_max_offset(
+; CHECK: %j1 = add nsw i32 %i, 1024
+; CHECK: %tmp = sext i32 %j1 to i64
+; CHECK: getelementptr inbounds float, float addrspace(1)* %arr, i64 %tmp
+; CHECK: getelementptr inbounds float, float addrspace(1)* %arr, i64 %tmp5
+define amdgpu_kernel void @slsr_after_reassociate_global_geps_over_mubuf_max_offset(float addrspace(1)* %out, float addrspace(1)* noalias %arr, i32 %i) {
+bb:
+  %i2 = shl nsw i32 %i, 1
+  %j1 = add nsw i32 %i, 1024
+  %tmp = sext i32 %j1 to i64
+  %p1 = getelementptr inbounds float, float addrspace(1)* %arr, i64 %tmp
+  %tmp3 = bitcast float addrspace(1)* %p1 to i32 addrspace(1)*
+  %v11 = load i32, i32 addrspace(1)* %tmp3, align 4
+  %tmp4 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v11, i32 addrspace(1)* %tmp4, align 4
+
+  %j2 = add nsw i32 %i2, 1024
+  %tmp5 = sext i32 %j2 to i64
+  %p2 = getelementptr inbounds float, float addrspace(1)* %arr, i64 %tmp5
+  %tmp6 = bitcast float addrspace(1)* %p2 to i32 addrspace(1)*
+  %v22 = load i32, i32 addrspace(1)* %tmp6, align 4
+  %tmp7 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v22, i32 addrspace(1)* %tmp7, align 4
+
+  ret void
+}
+
+; CHECK-LABEL: @slsr_after_reassociate_lds_geps_ds_max_offset(
+; CHECK: [[B1:%[0-9]+]] = getelementptr float, float addrspace(3)* %arr, i32 %i
+; CHECK: getelementptr inbounds float, float addrspace(3)* [[B1]], i32 16383
+
+; CHECK: [[B2:%[0-9]+]] = getelementptr float, float addrspace(3)* [[B1]], i32 %i
+; CHECK: getelementptr inbounds float, float addrspace(3)* [[B2]], i32 16383
+define amdgpu_kernel void @slsr_after_reassociate_lds_geps_ds_max_offset(float addrspace(1)* %out, float addrspace(3)* noalias %arr, i32 %i) {
+bb:
+  %i2 = shl nsw i32 %i, 1
+  %j1 = add nsw i32 %i, 16383
+  %p1 = getelementptr inbounds float, float addrspace(3)* %arr, i32 %j1
+  %tmp3 = bitcast float addrspace(3)* %p1 to i32 addrspace(3)*
+  %v11 = load i32, i32 addrspace(3)* %tmp3, align 4
+  %tmp4 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v11, i32 addrspace(1)* %tmp4, align 4
+
+  %j2 = add nsw i32 %i2, 16383
+  %p2 = getelementptr inbounds float, float addrspace(3)* %arr, i32 %j2
+  %tmp6 = bitcast float addrspace(3)* %p2 to i32 addrspace(3)*
+  %v22 = load i32, i32 addrspace(3)* %tmp6, align 4
+  %tmp7 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v22, i32 addrspace(1)* %tmp7, align 4
+
+  ret void
+}
+
+; CHECK-LABEL: @slsr_after_reassociate_lds_geps_over_ds_max_offset(
+; CHECK: %j1 = add nsw i32 %i, 16384
+; CHECK: getelementptr inbounds float, float addrspace(3)* %arr, i32 %j1
+; CHECK: %j2 = add i32 %j1, %i
+; CHECK: getelementptr inbounds float, float addrspace(3)* %arr, i32 %j2
+define amdgpu_kernel void @slsr_after_reassociate_lds_geps_over_ds_max_offset(float addrspace(1)* %out, float addrspace(3)* noalias %arr, i32 %i) {
+bb:
+  %i2 = shl nsw i32 %i, 1
+  %j1 = add nsw i32 %i, 16384
+  %p1 = getelementptr inbounds float, float addrspace(3)* %arr, i32 %j1
+  %tmp3 = bitcast float addrspace(3)* %p1 to i32 addrspace(3)*
+  %v11 = load i32, i32 addrspace(3)* %tmp3, align 4
+  %tmp4 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v11, i32 addrspace(1)* %tmp4, align 4
+
+  %j2 = add nsw i32 %i2, 16384
+  %p2 = getelementptr inbounds float, float addrspace(3)* %arr, i32 %j2
+  %tmp6 = bitcast float addrspace(3)* %p2 to i32 addrspace(3)*
+  %v22 = load i32, i32 addrspace(3)* %tmp6, align 4
+  %tmp7 = bitcast float addrspace(1)* %out to i32 addrspace(1)*
+  store i32 %v22, i32 addrspace(1)* %tmp7, align 4
+
+  ret void
+}

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

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/reassociate-geps-and-slsr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/reassociate-geps-and-slsr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/reassociate-geps-and-slsr.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/reassociate-geps-and-slsr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; RUN: opt < %s -separate-const-offset-from-gep -slsr -gvn -S | FileCheck %s
+; RUN: llc < %s -march=nvptx64 -mcpu=sm_35 | FileCheck %s --check-prefix=PTX
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
+target triple = "nvptx64-unknown-unknown"
+
+; arr[i + 5]
+; arr[i * 2 + 5]
+; arr[i * 3 + 5]
+; arr[i * 4 + 5]
+;
+;   => reassociate-geps
+;
+; *(&arr[i] + 5)
+; *(&arr[i * 2] + 5)
+; *(&arr[i * 3] + 5)
+; *(&arr[i * 4] + 5)
+;
+;   => slsr
+;
+; p1 = &arr[i]
+; *(p1 + 5)
+; p2 = p1 + i
+; *(p2 + 5)
+; p3 = p2 + i
+; *(p3 + 5)
+; p4 = p3 + i
+; *(p4 + 5)
+define void @slsr_after_reassociate_geps(float* %arr, i32 %i) {
+; CHECK-LABEL: @slsr_after_reassociate_geps(
+; PTX-LABEL: .visible .func slsr_after_reassociate_geps(
+; PTX: ld.param.u64 [[arr:%rd[0-9]+]], [slsr_after_reassociate_geps_param_0];
+; PTX: ld.param.u32 [[i:%r[0-9]+]], [slsr_after_reassociate_geps_param_1];
+  %i2 = shl nsw i32 %i, 1
+  %i3 = mul nsw i32 %i, 3
+  %i4 = shl nsw i32 %i, 2
+
+  %j1 = add nsw i32 %i, 5
+  %p1 = getelementptr inbounds float, float* %arr, i32 %j1
+; CHECK: [[b1:%[0-9]+]] = getelementptr float, float* %arr, i64 [[bump:%[0-9]+]]
+; PTX: mul.wide.s32 [[i4:%rd[0-9]+]], [[i]], 4;
+; PTX: add.s64 [[base1:%rd[0-9]+]], [[arr]], [[i4]];
+  %v1 = load float, float* %p1, align 4
+; PTX: ld.f32 {{%f[0-9]+}}, {{\[}}[[base1]]+20];
+  call void @foo(float %v1)
+
+  %j2 = add nsw i32 %i2, 5
+  %p2 = getelementptr inbounds float, float* %arr, i32 %j2
+; CHECK: [[b2:%[0-9]+]] = getelementptr float, float* [[b1]], i64 [[bump]]
+; PTX: add.s64 [[base2:%rd[0-9]+]], [[base1]], [[i4]];
+  %v2 = load float, float* %p2, align 4
+; PTX: ld.f32 {{%f[0-9]+}}, {{\[}}[[base2]]+20];
+  call void @foo(float %v2)
+
+  %j3 = add nsw i32 %i3, 5
+  %p3 = getelementptr inbounds float, float* %arr, i32 %j3
+; CHECK: [[b3:%[0-9]+]] = getelementptr float, float* [[b2]], i64 [[bump]]
+; PTX: add.s64 [[base3:%rd[0-9]+]], [[base2]], [[i4]];
+  %v3 = load float, float* %p3, align 4
+; PTX: ld.f32 {{%f[0-9]+}}, {{\[}}[[base3]]+20];
+  call void @foo(float %v3)
+
+  %j4 = add nsw i32 %i4, 5
+  %p4 = getelementptr inbounds float, float* %arr, i32 %j4
+; CHECK: [[b4:%[0-9]+]] = getelementptr float, float* [[b3]], i64 [[bump]]
+; PTX: add.s64 [[base4:%rd[0-9]+]], [[base3]], [[i4]];
+  %v4 = load float, float* %p4, align 4
+; PTX: ld.f32 {{%f[0-9]+}}, {{\[}}[[base4]]+20];
+  call void @foo(float %v4)
+
+  ret void
+}
+
+declare void @foo(float)

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/speculative-slsr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/speculative-slsr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/speculative-slsr.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/NVPTX/speculative-slsr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: llc < %s -march=nvptx64 -mcpu=sm_35 | FileCheck %s
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
+target triple = "nvptx64-nvidia-cuda"
+
+; CUDA code
+; __global__ void foo(int b, int s) {
+;   #pragma unroll
+;   for (int i = 0; i < 4; ++i) {
+;     if (cond(i))
+;       use((b + i) * s);
+;   }
+; }
+define void @foo(i32 %b, i32 %s) {
+; CHECK-LABEL: .visible .entry foo(
+entry:
+; CHECK: ld.param.u32 [[s:%r[0-9]+]], [foo_param_1];
+; CHECK: ld.param.u32 [[b:%r[0-9]+]], [foo_param_0];
+  %call = tail call zeroext i1 @cond(i32 0)
+  br i1 %call, label %if.then, label %for.inc
+
+if.then:                                          ; preds = %entry
+  %mul = mul nsw i32 %b, %s
+; CHECK: mul.lo.s32 [[a0:%r[0-9]+]], [[b]], [[s]]
+  tail call void @use(i32 %mul)
+  br label %for.inc
+
+for.inc:                                          ; preds = %entry, %if.then
+  %call.1 = tail call zeroext i1 @cond(i32 1)
+  br i1 %call.1, label %if.then.1, label %for.inc.1
+
+if.then.1:                                        ; preds = %for.inc
+  %add.1 = add nsw i32 %b, 1
+  %mul.1 = mul nsw i32 %add.1, %s
+; CHECK: add.s32 [[a1:%r[0-9]+]], [[a0]], [[s]]
+  tail call void @use(i32 %mul.1)
+  br label %for.inc.1
+
+for.inc.1:                                        ; preds = %if.then.1, %for.inc
+  %call.2 = tail call zeroext i1 @cond(i32 2)
+  br i1 %call.2, label %if.then.2, label %for.inc.2
+
+if.then.2:                                        ; preds = %for.inc.1
+  %add.2 = add nsw i32 %b, 2
+  %mul.2 = mul nsw i32 %add.2, %s
+; CHECK: add.s32 [[a2:%r[0-9]+]], [[a1]], [[s]]
+  tail call void @use(i32 %mul.2)
+  br label %for.inc.2
+
+for.inc.2:                                        ; preds = %if.then.2, %for.inc.1
+  %call.3 = tail call zeroext i1 @cond(i32 3)
+  br i1 %call.3, label %if.then.3, label %for.inc.3
+
+if.then.3:                                        ; preds = %for.inc.2
+  %add.3 = add nsw i32 %b, 3
+  %mul.3 = mul nsw i32 %add.3, %s
+; CHECK: add.s32 [[a3:%r[0-9]+]], [[a2]], [[s]]
+  tail call void @use(i32 %mul.3)
+  br label %for.inc.3
+
+for.inc.3:                                        ; preds = %if.then.3, %for.inc.2
+  ret void
+}
+
+declare zeroext i1 @cond(i32)
+
+declare void @use(i32)
+
+!nvvm.annotations = !{!0}
+
+!0 = !{void (i32, i32)* @foo, !"kernel", i32 1}

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/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/StraightLineStrengthReduce/X86/no-slsr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/X86/no-slsr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/X86/no-slsr.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/X86/no-slsr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -slsr -gvn -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Do not perform SLSR on &input[s] and &input[s * 2] which fit into addressing
+; modes of X86.
+define i32 @no_slsr_gep(i32* %input, i64 %s) {
+; CHECK-LABEL: @no_slsr_gep(
+  ; v0 = input[0];
+  %p0 = getelementptr inbounds i32, i32* %input, i64 0
+  %v0 = load i32, i32* %p0
+
+  ; v1 = input[s];
+  %p1 = getelementptr inbounds i32, i32* %input, i64 %s
+; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %s
+  %v1 = load i32, i32* %p1
+
+  ; v2 = input[s * 2];
+  %s2 = mul nsw i64 %s, 2
+  %p2 = getelementptr inbounds i32, i32* %input, i64 %s2
+; CHECK: %p2 = getelementptr inbounds i32, i32* %input, i64 %s2
+  %v2 = load i32, i32* %p2
+
+  ; return v0 + v1 + v2;
+  %1 = add i32 %v0, %v1
+  %2 = add i32 %1, %v2
+  ret i32 %2
+}
+
+define void @no_slsr_add(i32 %b, i32 %s) {
+; CHECK-LABEL: @no_slsr_add(
+  %1 = add i32 %b, %s
+; CHECK: add i32 %b, %s
+  call void @foo(i32 %1)
+  %s2 = mul i32 %s, 2
+; CHECK: %s2 = mul i32 %s, 2
+  %2 = add i32 %b, %s2
+; CHECK: add i32 %b, %s2
+  call void @foo(i32 %2)
+  ret void
+}
+
+declare void @foo(i32 %a)

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-add.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-add.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-add.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,172 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -slsr -gvn -S | FileCheck %s
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
+
+define void @shl(i32 %b, i32 %s) {
+; CHECK-LABEL: @shl(
+; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S:%.*]]
+; CHECK-NEXT:    call void @foo(i32 [[T1]])
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], [[S]]
+; CHECK-NEXT:    call void @foo(i32 [[T2]])
+; CHECK-NEXT:    ret void
+;
+  %t1 = add i32 %b, %s
+  call void @foo(i32 %t1)
+  %s2 = shl i32 %s, 1
+  %t2 = add i32 %b, %s2
+  call void @foo(i32 %t2)
+  ret void
+}
+
+define void @stride_is_2s(i32 %b, i32 %s) {
+; CHECK-LABEL: @stride_is_2s(
+; CHECK-NEXT:    [[S2:%.*]] = shl i32 [[S:%.*]], 1
+; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S2]]
+; CHECK-NEXT:    call void @foo(i32 [[T1]])
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], [[S2]]
+; CHECK-NEXT:    call void @foo(i32 [[T2]])
+; CHECK-NEXT:    [[T3:%.*]] = add i32 [[T2]], [[S2]]
+; CHECK-NEXT:    call void @foo(i32 [[T3]])
+; CHECK-NEXT:    ret void
+;
+  %s2 = shl i32 %s, 1
+  %t1 = add i32 %b, %s2
+  call void @foo(i32 %t1)
+  %s4 = shl i32 %s, 2
+  %t2 = add i32 %b, %s4
+  call void @foo(i32 %t2)
+  %s6 = mul i32 %s, 6
+  %t3 = add i32 %b, %s6
+  call void @foo(i32 %t3)
+  ret void
+}
+
+define void @stride_is_3s(i32 %b, i32 %s) {
+; CHECK-LABEL: @stride_is_3s(
+; CHECK-NEXT:    [[T1:%.*]] = add i32 [[S:%.*]], [[B:%.*]]
+; CHECK-NEXT:    call void @foo(i32 [[T1]])
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[S]], 3
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], [[TMP1]]
+; CHECK-NEXT:    call void @foo(i32 [[T2]])
+; CHECK-NEXT:    [[T3:%.*]] = add i32 [[T2]], [[TMP1]]
+; CHECK-NEXT:    call void @foo(i32 [[T3]])
+; CHECK-NEXT:    ret void
+;
+  %t1 = add i32 %s, %b
+  call void @foo(i32 %t1)
+  %s4 = shl i32 %s, 2
+  %t2 = add i32 %s4, %b
+  call void @foo(i32 %t2)
+  %s7 = mul i32 %s, 7
+  %t3 = add i32 %s7, %b
+  call void @foo(i32 %t3)
+  ret void
+}
+
+; foo(b + 6 * s);
+; foo(b + 4 * s);
+; foo(b + 2 * s);
+;   =>
+; t1 = b + 6 * s;
+; foo(t1);
+; s2 = 2 * s;
+; t2 = t1 - s2;
+; foo(t2);
+; t3 = t2 - s2;
+; foo(t3);
+define void @stride_is_minus_2s(i32 %b, i32 %s) {
+; CHECK-LABEL: @stride_is_minus_2s(
+; CHECK-NEXT:    [[S6:%.*]] = mul i32 [[S:%.*]], 6
+; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S6]]
+; CHECK-NEXT:    call void @foo(i32 [[T1]])
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[S]], 1
+; CHECK-NEXT:    [[T2:%.*]] = sub i32 [[T1]], [[TMP1]]
+; CHECK-NEXT:    call void @foo(i32 [[T2]])
+; CHECK-NEXT:    [[T3:%.*]] = sub i32 [[T2]], [[TMP1]]
+; CHECK-NEXT:    call void @foo(i32 [[T3]])
+; CHECK-NEXT:    ret void
+;
+  %s6 = mul i32 %s, 6
+  %t1 = add i32 %b, %s6
+  call void @foo(i32 %t1)
+  %s4 = shl i32 %s, 2
+  %t2 = add i32 %b, %s4
+  call void @foo(i32 %t2)
+  %s2 = shl i32 %s, 1
+  %t3 = add i32 %b, %s2
+  call void @foo(i32 %t3)
+  ret void
+}
+
+; TODO: This pass is targeted at simple address-calcs, so it is artificially limited to
+; match scalar values. The code could be modified to handle vector types too.
+
+define void @stride_is_minus_2s_vec(<2 x i32> %b, <2 x i32> %s) {
+; CHECK-LABEL: @stride_is_minus_2s_vec(
+; CHECK-NEXT:    [[S6:%.*]] = mul <2 x i32> [[S:%.*]], <i32 6, i32 6>
+; CHECK-NEXT:    [[T1:%.*]] = add <2 x i32> [[B:%.*]], [[S6]]
+; CHECK-NEXT:    call void @voo(<2 x i32> [[T1]])
+; CHECK-NEXT:    [[S4:%.*]] = shl <2 x i32> [[S]], <i32 2, i32 2>
+; CHECK-NEXT:    [[T2:%.*]] = add <2 x i32> [[B]], [[S4]]
+; CHECK-NEXT:    call void @voo(<2 x i32> [[T2]])
+; CHECK-NEXT:    [[S2:%.*]] = shl <2 x i32> [[S]], <i32 1, i32 1>
+; CHECK-NEXT:    [[T3:%.*]] = add <2 x i32> [[B]], [[S2]]
+; CHECK-NEXT:    call void @voo(<2 x i32> [[T3]])
+; CHECK-NEXT:    ret void
+;
+  %s6 = mul <2 x i32> %s, <i32 6, i32 6>
+  %t1 = add <2 x i32> %b, %s6
+  call void @voo(<2 x i32> %t1)
+  %s4 = shl <2 x i32> %s, <i32 2, i32 2>
+  %t2 = add <2 x i32> %b, %s4
+  call void @voo(<2 x i32> %t2)
+  %s2 = shl <2 x i32> %s, <i32 1, i32 1>
+  %t3 = add <2 x i32> %b, %s2
+  call void @voo(<2 x i32> %t3)
+  ret void
+}
+
+; t = b + (s << 3);
+; foo(t);
+; foo(b + s);
+;
+; do not rewrite b + s to t - 7 * s because the latter is more complicated.
+define void @simple_enough(i32 %b, i32 %s) {
+; CHECK-LABEL: @simple_enough(
+; CHECK-NEXT:    [[S8:%.*]] = shl i32 [[S:%.*]], 3
+; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S8]]
+; CHECK-NEXT:    call void @foo(i32 [[T1]])
+; CHECK-NEXT:    [[T2:%.*]] = add i32 [[B]], [[S]]
+; CHECK-NEXT:    call void @foo(i32 [[T2]])
+; CHECK-NEXT:    ret void
+;
+  %s8 = shl i32 %s, 3
+  %t1 = add i32 %b, %s8
+  call void @foo(i32 %t1)
+  %t2 = add i32 %b, %s
+  call void @foo(i32 %t2)
+  ret void
+}
+
+define void @slsr_strided_add_128bit(i128 %b, i128 %s) {
+; CHECK-LABEL: @slsr_strided_add_128bit(
+; CHECK-NEXT:    [[S125:%.*]] = shl i128 [[S:%.*]], 125
+; CHECK-NEXT:    [[T1:%.*]] = add i128 [[B:%.*]], [[S125]]
+; CHECK-NEXT:    call void @bar(i128 [[T1]])
+; CHECK-NEXT:    [[T2:%.*]] = add i128 [[T1]], [[S125]]
+; CHECK-NEXT:    call void @bar(i128 [[T2]])
+; CHECK-NEXT:    ret void
+;
+  %s125 = shl i128 %s, 125
+  %s126 = shl i128 %s, 126
+  %t1 = add i128 %b, %s125
+  call void @bar(i128 %t1)
+  %t2 = add i128 %b, %s126
+  call void @bar(i128 %t2)
+  ret void
+}
+
+declare void @foo(i32)
+declare void @voo(<2 x i32>)
+declare void @bar(i128)

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-gep.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-gep.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-gep.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,191 @@
+; RUN: opt < %s -slsr -gvn -S | FileCheck %s
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64-p:64:64:64-p1:32:32:32"
+
+; foo(input[0]);
+; foo(input[s]);
+; foo(input[s * 2]);
+;   =>
+; p0 = &input[0];
+; foo(*p);
+; p1 = p0 + s;
+; foo(*p1);
+; p2 = p1 + s;
+; foo(*p2);
+define void @slsr_gep(i32* %input, i64 %s) {
+; CHECK-LABEL: @slsr_gep(
+  ; v0 = input[0];
+  %p0 = getelementptr inbounds i32, i32* %input, i64 0
+  call void @foo(i32* %p0)
+
+  ; v1 = input[s];
+  %p1 = getelementptr inbounds i32, i32* %input, i64 %s
+; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %s
+  call void @foo(i32* %p1)
+
+  ; v2 = input[s * 2];
+  %s2 = shl nsw i64 %s, 1
+  %p2 = getelementptr inbounds i32, i32* %input, i64 %s2
+; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %s
+  call void @foo(i32* %p2)
+
+  ret void
+}
+
+; foo(input[0]);
+; foo(input[(long)s]);
+; foo(input[(long)(s * 2)]);
+;   =>
+; p0 = &input[0];
+; foo(*p);
+; p1 = p0 + (long)s;
+; foo(*p1);
+; p2 = p1 + (long)s;
+; foo(*p2);
+define void @slsr_gep_sext(i32* %input, i32 %s) {
+; CHECK-LABEL: @slsr_gep_sext(
+  ; v0 = input[0];
+  %p0 = getelementptr inbounds i32, i32* %input, i64 0
+  call void @foo(i32* %p0)
+
+  ; v1 = input[s];
+  %t = sext i32 %s to i64
+  %p1 = getelementptr inbounds i32, i32* %input, i64 %t
+; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %t
+  call void @foo(i32* %p1)
+
+  ; v2 = input[s * 2];
+  %s2 = shl nsw i32 %s, 1
+  %t2 = sext i32 %s2 to i64
+  %p2 = getelementptr inbounds i32, i32* %input, i64 %t2
+; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %t
+  call void @foo(i32* %p2)
+
+  ret void
+}
+
+; int input[10][5];
+; foo(input[s][t]);
+; foo(input[s * 2][t]);
+; foo(input[s * 3][t]);
+;   =>
+; p0 = &input[s][t];
+; foo(*p0);
+; p1 = p0 + 5s;
+; foo(*p1);
+; p2 = p1 + 5s;
+; foo(*p2);
+define void @slsr_gep_2d([10 x [5 x i32]]* %input, i64 %s, i64 %t) {
+; CHECK-LABEL: @slsr_gep_2d(
+  ; v0 = input[s][t];
+  %p0 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s, i64 %t
+  call void @foo(i32* %p0)
+
+  ; v1 = input[s * 2][t];
+  %s2 = shl nsw i64 %s, 1
+; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 5
+  %p1 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s2, i64 %t
+; CHECK: %p1 = getelementptr inbounds i32, i32* %p0, i64 [[BUMP]]
+  call void @foo(i32* %p1)
+
+  ; v3 = input[s * 3][t];
+  %s3 = mul nsw i64 %s, 3
+  %p2 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s3, i64 %t
+; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 [[BUMP]]
+  call void @foo(i32* %p2)
+
+  ret void
+}
+
+%struct.S = type <{ i64, i32 }>
+
+; In this case, the bump
+;     = (char *)&input[s * 2][t].f1 - (char *)&input[s][t].f1
+;     = 60 * s
+; which may not be divisible by typeof(input[s][t].f1) = 8. Therefore, we
+; rewrite the candidates using byte offset instead of index offset as in
+; @slsr_gep_2d.
+define void @slsr_gep_uglygep([10 x [5 x %struct.S]]* %input, i64 %s, i64 %t) {
+; CHECK-LABEL: @slsr_gep_uglygep(
+  ; v0 = input[s][t].f1;
+  %p0 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s, i64 %t, i32 0
+  call void @bar(i64* %p0)
+
+  ; v1 = input[s * 2][t].f1;
+  %s2 = shl nsw i64 %s, 1
+; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 60
+  %p1 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s2, i64 %t, i32 0
+; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
+  call void @bar(i64* %p1)
+
+  ; v2 = input[s * 3][t].f1;
+  %s3 = mul nsw i64 %s, 3
+  %p2 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s3, i64 %t, i32 0
+; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
+  call void @bar(i64* %p2)
+
+  ret void
+}
+
+define void @slsr_out_of_bounds_gep(i32* %input, i32 %s) {
+; CHECK-LABEL: @slsr_out_of_bounds_gep(
+  ; v0 = input[0];
+  %p0 = getelementptr i32, i32* %input, i64 0
+  call void @foo(i32* %p0)
+
+  ; v1 = input[(long)s];
+  %t = sext i32 %s to i64
+  %p1 = getelementptr i32, i32* %input, i64 %t
+; CHECK: %p1 = getelementptr i32, i32* %input, i64 %t
+  call void @foo(i32* %p1)
+
+  ; v2 = input[(long)(s * 2)];
+  %s2 = shl nsw i32 %s, 1
+  %t2 = sext i32 %s2 to i64
+  %p2 = getelementptr i32, i32* %input, i64 %t2
+; CHECK: %p2 = getelementptr i32, i32* %p1, i64 %t
+  call void @foo(i32* %p2)
+
+  ret void
+}
+
+define void @slsr_gep_128bit_index(i32* %input, i128 %s) {
+; CHECK-LABEL: @slsr_gep_128bit_index(
+  ; p0 = &input[0]
+  %p0 = getelementptr inbounds i32, i32* %input, i128 0
+  call void @foo(i32* %p0)
+
+  ; p1 = &input[s << 125]
+  %s125 = shl nsw i128 %s, 125
+  %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
+; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
+  call void @foo(i32* %p1)
+
+  ; p2 = &input[s << 126]
+  %s126 = shl nsw i128 %s, 126
+  %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
+; CHECK: %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
+  call void @foo(i32* %p2)
+
+  ret void
+}
+
+define void @slsr_gep_32bit_pointer(i32 addrspace(1)* %input, i64 %s) {
+; CHECK-LABEL: @slsr_gep_32bit_pointer(
+  ; p1 = &input[s]
+  %p1 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s
+  call void @baz(i32 addrspace(1)* %p1)
+
+  ; p2 = &input[s * 2]
+  %s2 = mul nsw i64 %s, 2
+  %p2 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s2
+  ; %s2 is wider than the pointer size of addrspace(1), so do not factor it.
+; CHECK: %p2 = getelementptr inbounds i32, i32 addrspace(1)* %input, i64 %s2
+  call void @baz(i32 addrspace(1)* %p2)
+
+  ret void
+}
+
+declare void @foo(i32*)
+declare void @bar(i64*)
+declare void @baz(i32 addrspace(1)*)

Added: llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-mul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-mul.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-mul.ll (added)
+++ llvm/trunk/test/Transforms/StraightLineStrengthReduce/slsr-mul.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,147 @@
+; RUN: opt < %s -slsr -gvn -S | FileCheck %s
+
+target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
+
+define void @slsr1(i32 %b, i32 %s) {
+; CHECK-LABEL: @slsr1(
+  ; foo(b * s);
+  %mul0 = mul i32 %b, %s
+; CHECK: mul i32
+; CHECK-NOT: mul i32
+  call void @foo(i32 %mul0)
+
+  ; foo((b + 1) * s);
+  %b1 = add i32 %b, 1
+  %mul1 = mul i32 %b1, %s
+  call void @foo(i32 %mul1)
+
+  ; foo((b + 2) * s);
+  %b2 = add i32 %b, 2
+  %mul2 = mul i32 %b2, %s
+  call void @foo(i32 %mul2)
+
+  ret void
+}
+
+define void @non_canonicalized(i32 %b, i32 %s) {
+; CHECK-LABEL: @non_canonicalized(
+  ; foo(b * s);
+  %mul0 = mul i32 %b, %s
+; CHECK: mul i32
+; CHECK-NOT: mul i32
+  call void @foo(i32 %mul0)
+
+  ; foo((1 + b) * s);
+  %b1 = add i32 1, %b
+  %mul1 = mul i32 %b1, %s
+  call void @foo(i32 %mul1)
+
+  ; foo((2 + b) * s);
+  %b2 = add i32 2, %b
+  %mul2 = mul i32 %b2, %s
+  call void @foo(i32 %mul2)
+
+  ret void
+}
+
+define void @or(i32 %a, i32 %s) {
+  %b = shl i32 %a, 1
+; CHECK-LABEL: @or(
+  ; foo(b * s);
+  %mul0 = mul i32 %b, %s
+; CHECK: [[base:[^ ]+]] = mul i32
+  call void @foo(i32 %mul0)
+
+  ; foo((b | 1) * s);
+  %b1 = or i32 %b, 1
+  %mul1 = mul i32 %b1, %s
+; CHECK: add i32 [[base]], %s
+  call void @foo(i32 %mul1)
+
+  ; foo((b | 2) * s);
+  %b2 = or i32 %b, 2
+  %mul2 = mul i32 %b2, %s
+; CHECK: mul i32 %b2, %s
+  call void @foo(i32 %mul2)
+
+  ret void
+}
+
+; foo(a * b)
+; foo((a + 1) * b)
+; foo(a * (b + 1))
+; foo((a + 1) * (b + 1))
+define void @slsr2(i32 %a, i32 %b) {
+; CHECK-LABEL: @slsr2(
+  %a1 = add i32 %a, 1
+  %b1 = add i32 %b, 1
+  %mul0 = mul i32 %a, %b
+; CHECK: mul i32
+; CHECK-NOT: mul i32
+  %mul1 = mul i32 %a1, %b
+  %mul2 = mul i32 %a, %b1
+  %mul3 = mul i32 %a1, %b1
+
+  call void @foo(i32 %mul0)
+  call void @foo(i32 %mul1)
+  call void @foo(i32 %mul2)
+  call void @foo(i32 %mul3)
+
+  ret void
+}
+
+; The bump is a multiple of the stride.
+;
+; foo(b * s);
+; foo((b + 2) * s);
+; foo((b + 4) * s);
+;   =>
+; mul0 = b * s;
+; bump = s * 2;
+; mul1 = mul0 + bump; // GVN ensures mul1 and mul2 use the same bump.
+; mul2 = mul1 + bump;
+define void @slsr3(i32 %b, i32 %s) {
+; CHECK-LABEL: @slsr3(
+  %mul0 = mul i32 %b, %s
+; CHECK: mul i32
+  call void @foo(i32 %mul0)
+
+  %b1 = add i32 %b, 2
+  %mul1 = mul i32 %b1, %s
+; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = shl i32 %s, 1
+; CHECK: %mul1 = add i32 %mul0, [[BUMP]]
+  call void @foo(i32 %mul1)
+
+  %b2 = add i32 %b, 4
+  %mul2 = mul i32 %b2, %s
+; CHECK: %mul2 = add i32 %mul1, [[BUMP]]
+  call void @foo(i32 %mul2)
+
+  ret void
+}
+
+; Do not rewrite a candidate if its potential basis does not dominate it.
+;
+; if (cond)
+;   foo(a * b);
+; foo((a + 1) * b);
+define void @not_dominate(i1 %cond, i32 %a, i32 %b) {
+; CHECK-LABEL: @not_dominate(
+entry:
+  %a1 = add i32 %a, 1
+  br i1 %cond, label %then, label %merge
+
+then:
+  %mul0 = mul i32 %a, %b
+; CHECK: %mul0 = mul i32 %a, %b
+  call void @foo(i32 %mul0)
+  br label %merge
+
+merge:
+  %mul1 = mul i32 %a1, %b
+; CHECK: %mul1 = mul i32 %a1, %b
+  call void @foo(i32 %mul1)
+  ret void
+}
+
+declare void @foo(i32)

Added: llvm/trunk/test/Transforms/StripDeadPrototypes/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripDeadPrototypes/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripDeadPrototypes/basic.ll (added)
+++ llvm/trunk/test/Transforms/StripDeadPrototypes/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt -strip-dead-prototypes -S -o - < %s | FileCheck %s
+; RUN: opt -S -passes=strip-dead-prototypes < %s | FileCheck %s
+
+; CHECK: declare i32 @f
+declare i32 @f()
+; CHECK-NOT: declare i32 @g
+declare i32 @g()
+
+define i32 @foo() {
+  %call = call i32 @f()
+  ret i32 %call
+}

Added: llvm/trunk/test/Transforms/StripSymbols/2007-01-15-llvm.used.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripSymbols/2007-01-15-llvm.used.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripSymbols/2007-01-15-llvm.used.ll (added)
+++ llvm/trunk/test/Transforms/StripSymbols/2007-01-15-llvm.used.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -strip -S | FileCheck %s
+
+; CHECK: foo
+; CHECK: bar
+; CHECK: foo
+; CHECK: bar
+
+ at llvm.used = appending global [2 x i8*] [ i8* bitcast (i32* @foo to i8*), i8* bitcast (i32 ()* @bar to i8*) ], section "llvm.metadata"		; <[2 x i8*]*> [#uses=0]
+ at foo = internal constant i32 41		; <i32*> [#uses=1]
+
+define internal i32 @bar() nounwind  {
+entry:
+	ret i32 42
+}
+
+define i32 @main() nounwind  {
+entry:
+	ret i32 0
+}
+

Added: llvm/trunk/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll (added)
+++ llvm/trunk/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt -strip-debug < %s -S | FileCheck %s
+
+; CHECK-NOT: call void @llvm.dbg.value
+
+source_filename = "test/Transforms/StripSymbols/2010-06-30-StripDebug.ll"
+
+ at x = common global i32 0, !dbg !0
+
+; Function Attrs: nounwind optsize readnone ssp
+define void @foo() #0 !dbg !7 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 0, metadata !10, metadata !12), !dbg !13
+  ret void, !dbg !14
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind optsize readnone ssp }
+attributes #1 = { nounwind readnone }
+
+!llvm.module.flags = !{!4}
+!llvm.dbg.cu = !{!5}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "x", scope: !2, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true)
+!2 = !DIFile(filename: "b.c", directory: "/tmp")
+!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!4 = !{i32 1, !"Debug Info Version", i32 3}
+!5 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !6)
+!6 = !{!0}
+!7 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !2, file: !2, line: 2, type: !8, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !5)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null}!10 = !DILocalVariable(name: "y", scope: !11, file: !2, line: 3, type: !3)!11 = distinct !DILexicalBlock(scope: !7, file: !2, line: 2)!12 = !DIExpression()!13 = !DILocation(line: 3, scope: !11)!14 = !DILocation(line: 4, scope: !11)
\ No newline at end of file

Added: llvm/trunk/test/Transforms/StripSymbols/2010-08-25-crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripSymbols/2010-08-25-crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripSymbols/2010-08-25-crash.ll (added)
+++ llvm/trunk/test/Transforms/StripSymbols/2010-08-25-crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -strip-dead-debug-info -disable-output < %s
+source_filename = "test/Transforms/StripSymbols/2010-08-25-crash.ll"
+
+; Function Attrs: nounwind ssp
+define i32 @foo() #0 !dbg !9 {
+entry:
+  ret i32 0, !dbg !12
+}
+
+attributes #0 = { nounwind ssp }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 2.8 (trunk 112062)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !3)
+!1 = !DIFile(filename: "/tmp/a.c", directory: "/Volumes/Lalgate/clean/D.CW")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = !DIGlobalVariable(name: "i", linkageName: "i", scope: !1, file: !1, line: 2, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_const_type, scope: !1, file: !1, baseType: !7)
+!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !{i32 1, !"Debug Info Version", i32 3}
+!9 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 3, type: !10, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !0)
+!10 = !DISubroutineType(types: !11)
+!11 = !{!7}
+!12 = !DILocation(line: 3, column: 13, scope: !13)
+!13 = distinct !DILexicalBlock(scope: !9, file: !1, line: 3, column: 11)
+

Added: llvm/trunk/test/Transforms/StripSymbols/block-address.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripSymbols/block-address.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripSymbols/block-address.ll (added)
+++ llvm/trunk/test/Transforms/StripSymbols/block-address.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -strip -S < %s | FileCheck %s
+; PR10286
+
+ at main_addrs = constant [2 x i8*] [i8* blockaddress(@f, %FOO), i8* blockaddress(@f, %BAR)]
+; CHECK: @main_addrs = constant [2 x i8*] [i8* blockaddress(@f, %2), i8* blockaddress(@f, %3)]
+
+declare void @foo() nounwind
+declare void @bar() nounwind
+
+define void @f(i8* %indirect.goto.dest) nounwind uwtable ssp {
+entry:
+  indirectbr i8* %indirect.goto.dest, [label %FOO, label %BAR]
+
+  ; CHECK: indirectbr i8* %0, [label %2, label %3]
+
+FOO:
+  call void @foo()
+  ret void
+
+BAR:
+  call void @bar()
+  ret void
+}

Added: llvm/trunk/test/Transforms/StripSymbols/strip-cov.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripSymbols/strip-cov.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripSymbols/strip-cov.ll (added)
+++ llvm/trunk/test/Transforms/StripSymbols/strip-cov.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -S %s -strip -o - | FileCheck %s
+
+; CHECK-NOT: !llvm.dbg.cu
+; CHECK-NOT: !llvm.gcov
+
+; CHECK: !llvm.module.flags = !{!0}
+; CHECK: !0 = !{i32 2, !"Debug Info Version", i32 3}
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+!llvm.gcov = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 284352) (llvm/trunk 284353)", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "/dev/null", directory: "/home/davide/work/llvm/build/bin")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{!"/scratch/patatino/build/bin/null.gcno", !"/scratch/patatino/build/bin/null.gcda", !0}

Added: llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll (added)
+++ llvm/trunk/test/Transforms/StripSymbols/strip-dead-debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt -strip-dead-debug-info -verify %s -S | FileCheck %s
+
+; CHECK: ModuleID = '{{.*}}'
+; CHECK-NOT: "bar"
+; CHECK-NOT: "abcd"
+; CHECK-NOT: "GCC"
+; CHECK: "Globals"
+; CHECK: "abcd2"
+
+source_filename = "test/Transforms/StripSymbols/strip-dead-debug-info.ll"
+
+ at xyz = global i32 2, !dbg !0
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+; Function Attrs: nounwind readnone ssp
+define i32 @fn() #1 !dbg !10 {
+entry:
+  ret i32 0, !dbg !13
+}
+
+; Function Attrs: nounwind readonly ssp
+define i32 @foo(i32 %i) #2 !dbg !15 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32 %i, metadata !18, metadata !19), !dbg !20
+  %.0 = load i32, i32* @xyz, align 4, !dbg !30
+  ret i32 %.0, !dbg !21
+}
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind readnone ssp }
+attributes #2 = { nounwind readonly ssp }
+
+!llvm.dbg.cu = !{!4, !23, !24, !28}
+!llvm.module.flags = !{!9}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "xyz", scope: !2, file: !2, line: 3, type: !3, isLocal: false, isDefinition: true)
+!2 = !DIFile(filename: "g.c", directory: "/tmp/")
+!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!4 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6)
+!5 = !{}
+!6 = !{!7, !0}
+!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression())
+!8 = !DIGlobalVariable(name: "abcd", scope: !2, file: !2, line: 2, type: !3, isLocal: true, isDefinition: true)
+!9 = !{i32 1, !"Debug Info Version", i32 3}
+!10 = distinct !DISubprogram(name: "fn", linkageName: "fn", scope: null, file: !2, line: 6, type: !11, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !4)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!3}
+!13 = !DILocation(line: 6, scope: !14)
+!14 = distinct !DILexicalBlock(scope: !10, file: !2, line: 6)
+!15 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !2, line: 7, type: !16, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !4)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!3, !3}
+!18 = !DILocalVariable(name: "i", arg: 1, scope: !15, file: !2, line: 7, type: !3)
+!19 = !DIExpression()
+!20 = !DILocation(line: 7, scope: !15)
+!21 = !DILocation(line: 10, scope: !22)
+!22 = distinct !DILexicalBlock(scope: !15, file: !2, line: 7)
+!23 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "GCC", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !5)
+!24 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "Globals", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !25)
+!25 = !{!26}
+!26 = !DIGlobalVariableExpression(var: !27, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
+!27 = !DIGlobalVariable(name: "abcd2", scope: !2, file: !2, line: 2, type: !3, isLocal: true, isDefinition: true)
+!28 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "InlineTest", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !5)
+!29 = distinct !DISubprogram(name: "inlinefunc", linkageName: "inlinefunc", scope: null, file: !2, line: 7, type: !16, isLocal: false, isDefinition: true, isOptimized: true, unit: !28)
+!30 = !DILocation(line: 100, scope: !29, inlinedAt: !21)

Added: llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug-xfail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug-xfail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug-xfail.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug-xfail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; XFAIL: *
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -structurizecfg -verify-region-info %s
+
+; FIXME: Merge into backedge-id-bug
+; Variant which has an issue with region construction
+
+define amdgpu_kernel void @loop_backedge_misidentified_alt(i32 addrspace(1)* %arg0) #0 {
+entry:
+  %tmp = load volatile <2 x i32>, <2 x i32> addrspace(1)* undef, align 16
+  %load1 = load volatile <2 x float>, <2 x float> addrspace(1)* undef
+  %tid = call i32 @llvm.amdgcn.workitem.id.x()
+  %gep = getelementptr inbounds i32, i32 addrspace(1)* %arg0, i32 %tid
+  %i.initial = load volatile i32, i32 addrspace(1)* %gep, align 4
+  br label %LOOP.HEADER
+
+LOOP.HEADER:
+  %i = phi i32 [ %i.final, %END_ELSE_BLOCK ], [ %i.initial, %entry ]
+  call void asm sideeffect "s_nop 0x100b ; loop $0 ", "r,~{memory}"(i32 %i) #0
+  %tmp12 = zext i32 %i to i64
+  %tmp13 = getelementptr inbounds <4 x i32>, <4 x i32> addrspace(1)* null, i64 %tmp12
+  %tmp14 = load <4 x i32>, <4 x i32> addrspace(1)* %tmp13, align 16
+  %tmp15 = extractelement <4 x i32> %tmp14, i64 0
+  %tmp16 = and i32 %tmp15, 65535
+  %tmp17 = icmp eq i32 %tmp16, 1
+  br i1 %tmp17, label %bb18, label %bb62
+
+bb18:
+  %tmp19 = extractelement <2 x i32> %tmp, i64 0
+  %tmp22 = lshr i32 %tmp19, 16
+  %tmp24 = urem i32 %tmp22, 52
+  %tmp25 = mul nuw nsw i32 %tmp24, 52
+  br label %INNER_LOOP
+
+INNER_LOOP:
+  %inner.loop.j = phi i32 [ %tmp25, %bb18 ], [ %inner.loop.j.inc, %INNER_LOOP ]
+  call void asm sideeffect "; inner loop body", ""() #0
+  %inner.loop.j.inc = add nsw i32 %inner.loop.j, 1
+  %inner.loop.cmp = icmp eq i32 %inner.loop.j, 0
+  br i1 %inner.loop.cmp, label %INNER_LOOP_BREAK, label %INNER_LOOP
+
+INNER_LOOP_BREAK:
+  %tmp59 = extractelement <4 x i32> %tmp14, i64 2
+  call void asm sideeffect "s_nop 23 ", "~{memory}"() #0
+  br label %END_ELSE_BLOCK
+
+bb62:
+  %load13 = icmp ult i32 %tmp16, 271
+  ;br i1 %load13, label %bb64, label %INCREMENT_I
+  ; branching directly to the return avoids the bug
+  br i1 %load13, label %RETURN, label %INCREMENT_I
+
+
+bb64:
+  call void asm sideeffect "s_nop 42", "~{memory}"() #0
+  br label %RETURN
+
+INCREMENT_I:
+  %inc.i = add i32 %i, 1
+  call void asm sideeffect "s_nop 0x1336 ; increment $0", "v,~{memory}"(i32 %inc.i) #0
+  br label %END_ELSE_BLOCK
+
+END_ELSE_BLOCK:
+  %i.final = phi i32 [ %tmp59, %INNER_LOOP_BREAK ], [ %inc.i, %INCREMENT_I ]
+  call void asm sideeffect "s_nop 0x1337 ; end else block $0", "v,~{memory}"(i32 %i.final) #0
+  %cmp.end.else.block = icmp eq i32 %i.final, -1
+  br i1 %cmp.end.else.block, label %RETURN, label %LOOP.HEADER
+
+RETURN:
+  call void asm sideeffect "s_nop 0x99 ; ClosureEval return", "~{memory}"() #0
+  store volatile <2 x float> %load1, <2 x float> addrspace(1)* undef, align 8
+  ret void
+}
+
+declare i32 @llvm.amdgcn.workitem.id.x() #1
+
+attributes #0 = { convergent nounwind }
+attributes #1 = { convergent nounwind readnone }

Added: llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/backedge-id-bug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,164 @@
+; XFAIL: *
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -structurizecfg %s | FileCheck %s
+
+; StructurizeCFG::orderNodes used an arbitrary and nonsensical sorting
+; function which broke the basic backedge identification algorithm. It
+; would use RPO order, but then do a weird partial sort by the loop
+; depth assuming blocks are sorted by loop. However a block can appear
+; in between blocks of a loop that is not part of a loop, breaking the
+; assumption of the sort.
+;
+; The collectInfos must be done in RPO order. The actual
+; structurization order I think is less important, but unless the loop
+; headers are identified in RPO order, it finds the wrong set of back
+; edges.
+
+define amdgpu_kernel void @loop_backedge_misidentified(i32 addrspace(1)* %arg0) #0 {
+; CHECK-LABEL: @loop_backedge_misidentified(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP:%.*]] = load volatile <2 x i32>, <2 x i32> addrspace(1)* undef, align 16
+; CHECK-NEXT:    [[LOAD1:%.*]] = load volatile <2 x float>, <2 x float> addrspace(1)* undef
+; CHECK-NEXT:    [[TID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, i32 addrspace(1)* [[ARG0:%.*]], i32 [[TID]]
+; CHECK-NEXT:    [[I_INITIAL:%.*]] = load volatile i32, i32 addrspace(1)* [[GEP]], align 4
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       LOOP.HEADER:
+; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INITIAL]], [[ENTRY:%.*]] ], [ [[TMP10:%.*]], [[FLOW4:%.*]] ]
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x100b
+; CHECK-NEXT:    [[TMP12:%.*]] = zext i32 [[I]] to i64
+; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32> addrspace(1)* null, i64 [[TMP12]]
+; CHECK-NEXT:    [[TMP14:%.*]] = load <4 x i32>, <4 x i32> addrspace(1)* [[TMP13]], align 16
+; CHECK-NEXT:    [[TMP15:%.*]] = extractelement <4 x i32> [[TMP14]], i64 0
+; CHECK-NEXT:    [[TMP16:%.*]] = and i32 [[TMP15]], 65535
+; CHECK-NEXT:    [[TMP17:%.*]] = icmp eq i32 [[TMP16]], 1
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[TMP17]], true
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB62:%.*]], label [[FLOW:%.*]]
+; CHECK:       Flow2:
+; CHECK-NEXT:    br label [[FLOW]]
+; CHECK:       bb18:
+; CHECK-NEXT:    [[TMP19:%.*]] = extractelement <2 x i32> [[TMP]], i64 0
+; CHECK-NEXT:    [[TMP22:%.*]] = lshr i32 [[TMP19]], 16
+; CHECK-NEXT:    [[TMP24:%.*]] = urem i32 [[TMP22]], 52
+; CHECK-NEXT:    [[TMP25:%.*]] = mul nuw nsw i32 [[TMP24]], 52
+; CHECK-NEXT:    br label [[INNER_LOOP:%.*]]
+; CHECK:       Flow3:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[TMP59:%.*]], [[INNER_LOOP_BREAK:%.*]] ], [ [[TMP7:%.*]], [[FLOW]] ]
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i1 [ true, [[INNER_LOOP_BREAK]] ], [ [[TMP8:%.*]], [[FLOW]] ]
+; CHECK-NEXT:    br i1 [[TMP2]], label [[END_ELSE_BLOCK:%.*]], label [[FLOW4]]
+; CHECK:       INNER_LOOP:
+; CHECK-NEXT:    [[INNER_LOOP_J:%.*]] = phi i32 [ [[INNER_LOOP_J_INC:%.*]], [[INNER_LOOP]] ], [ [[TMP25]], [[BB18:%.*]] ]
+; CHECK-NEXT:    call void asm sideeffect "
+; CHECK-NEXT:    [[INNER_LOOP_J_INC]] = add nsw i32 [[INNER_LOOP_J]], 1
+; CHECK-NEXT:    [[INNER_LOOP_CMP:%.*]] = icmp eq i32 [[INNER_LOOP_J]], 0
+; CHECK-NEXT:    br i1 [[INNER_LOOP_CMP]], label [[INNER_LOOP_BREAK]], label [[INNER_LOOP]]
+; CHECK:       INNER_LOOP_BREAK:
+; CHECK-NEXT:    [[TMP59]] = extractelement <4 x i32> [[TMP14]], i64 2
+; CHECK-NEXT:    call void asm sideeffect "s_nop 23 ", "~{memory}"() #0
+; CHECK-NEXT:    br label [[FLOW3:%.*]]
+; CHECK:       bb62:
+; CHECK-NEXT:    [[LOAD13:%.*]] = icmp ult i32 [[TMP16]], 271
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i1 [[LOAD13]], true
+; CHECK-NEXT:    br i1 [[TMP3]], label [[INCREMENT_I:%.*]], label [[FLOW1:%.*]]
+; CHECK:       Flow1:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[INC_I:%.*]], [[INCREMENT_I]] ], [ undef, [[BB62]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = phi i1 [ true, [[INCREMENT_I]] ], [ false, [[BB62]] ]
+; CHECK-NEXT:    [[TMP6:%.*]] = phi i1 [ false, [[INCREMENT_I]] ], [ true, [[BB62]] ]
+; CHECK-NEXT:    br i1 [[TMP6]], label [[BB64:%.*]], label [[FLOW2:%.*]]
+; CHECK:       bb64:
+; CHECK-NEXT:    call void asm sideeffect "s_nop 42", "~{memory}"() #0
+; CHECK-NEXT:    br label [[FLOW2]]
+; CHECK:       Flow:
+; CHECK-NEXT:    [[TMP7]] = phi i32 [ [[TMP4]], [[FLOW2]] ], [ undef, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    [[TMP8]] = phi i1 [ [[TMP5]], [[FLOW2]] ], [ false, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = phi i1 [ false, [[FLOW2]] ], [ true, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    br i1 [[TMP9]], label [[BB18]], label [[FLOW3]]
+; CHECK:       INCREMENT_I:
+; CHECK-NEXT:    [[INC_I]] = add i32 [[I]], 1
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x1336
+; CHECK-NEXT:    br label [[FLOW1]]
+; CHECK:       END_ELSE_BLOCK:
+; CHECK-NEXT:    [[I_FINAL:%.*]] = phi i32 [ [[TMP1]], [[FLOW3]] ]
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x1337
+; CHECK-NEXT:    [[CMP_END_ELSE_BLOCK:%.*]] = icmp eq i32 [[I_FINAL]], -1
+; CHECK-NEXT:    br label [[FLOW4]]
+; CHECK:       Flow4:
+; CHECK-NEXT:    [[TMP10]] = phi i32 [ [[I_FINAL]], [[END_ELSE_BLOCK]] ], [ undef, [[FLOW3]] ]
+; CHECK-NEXT:    [[TMP11:%.*]] = phi i1 [ [[CMP_END_ELSE_BLOCK]], [[END_ELSE_BLOCK]] ], [ true, [[FLOW3]] ]
+; CHECK-NEXT:    br i1 [[TMP11]], label [[RETURN:%.*]], label [[LOOP_HEADER]]
+; CHECK:       RETURN:
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x99
+; CHECK-NEXT:    store volatile <2 x float> [[LOAD1]], <2 x float> addrspace(1)* undef, align 8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %tmp = load volatile <2 x i32>, <2 x i32> addrspace(1)* undef, align 16
+  %load1 = load volatile <2 x float>, <2 x float> addrspace(1)* undef
+  %tid = call i32 @llvm.amdgcn.workitem.id.x()
+  %gep = getelementptr inbounds i32, i32 addrspace(1)* %arg0, i32 %tid
+  %i.initial = load volatile i32, i32 addrspace(1)* %gep, align 4
+  br label %LOOP.HEADER
+
+LOOP.HEADER:
+  %i = phi i32 [ %i.final, %END_ELSE_BLOCK ], [ %i.initial, %entry ]
+  call void asm sideeffect "s_nop 0x100b ; loop $0 ", "r,~{memory}"(i32 %i) #0
+  %tmp12 = zext i32 %i to i64
+  %tmp13 = getelementptr inbounds <4 x i32>, <4 x i32> addrspace(1)* null, i64 %tmp12
+  %tmp14 = load <4 x i32>, <4 x i32> addrspace(1)* %tmp13, align 16
+  %tmp15 = extractelement <4 x i32> %tmp14, i64 0
+  %tmp16 = and i32 %tmp15, 65535
+  %tmp17 = icmp eq i32 %tmp16, 1
+  br i1 %tmp17, label %bb18, label %bb62
+
+bb18:
+  %tmp19 = extractelement <2 x i32> %tmp, i64 0
+  %tmp22 = lshr i32 %tmp19, 16
+  %tmp24 = urem i32 %tmp22, 52
+  %tmp25 = mul nuw nsw i32 %tmp24, 52
+  br label %INNER_LOOP
+
+INNER_LOOP:
+  %inner.loop.j = phi i32 [ %tmp25, %bb18 ], [ %inner.loop.j.inc, %INNER_LOOP ]
+  call void asm sideeffect "; inner loop body", ""() #0
+  %inner.loop.j.inc = add nsw i32 %inner.loop.j, 1
+  %inner.loop.cmp = icmp eq i32 %inner.loop.j, 0
+  br i1 %inner.loop.cmp, label %INNER_LOOP_BREAK, label %INNER_LOOP
+
+INNER_LOOP_BREAK:
+  %tmp59 = extractelement <4 x i32> %tmp14, i64 2
+  call void asm sideeffect "s_nop 23 ", "~{memory}"() #0
+  br label %END_ELSE_BLOCK
+
+bb62:
+  %load13 = icmp ult i32 %tmp16, 271
+  br i1 %load13, label %bb64, label %INCREMENT_I
+
+bb64:
+  call void asm sideeffect "s_nop 42", "~{memory}"() #0
+  br label %RETURN
+
+INCREMENT_I:
+  %inc.i = add i32 %i, 1
+  call void asm sideeffect "s_nop 0x1336 ; increment $0", "v,~{memory}"(i32 %inc.i) #0
+  br label %END_ELSE_BLOCK
+
+END_ELSE_BLOCK:
+  %i.final = phi i32 [ %tmp59, %INNER_LOOP_BREAK ], [ %inc.i, %INCREMENT_I ]
+  call void asm sideeffect "s_nop 0x1337 ; end else block $0", "v,~{memory}"(i32 %i.final) #0
+  %cmp.end.else.block = icmp eq i32 %i.final, -1
+  br i1 %cmp.end.else.block, label %RETURN, label %LOOP.HEADER
+
+RETURN:
+  call void asm sideeffect "s_nop 0x99 ; ClosureEval return", "~{memory}"() #0
+  store volatile <2 x float> %load1, <2 x float> addrspace(1)* undef, align 8
+  ret void
+}
+
+; The same function, except break to return block goes directly to the
+; return, which managed to hide the bug.
+; FIXME: Merge variant from backedge-id-bug-xfail
+
+declare i32 @llvm.amdgcn.workitem.id.x() #1
+
+attributes #0 = { convergent nounwind }
+attributes #1 = { convergent nounwind readnone }

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

Added: llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/loop-subregion-misordered.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/loop-subregion-misordered.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/loop-subregion-misordered.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/loop-subregion-misordered.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,165 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -S -structurizecfg %s | FileCheck %s
+;
+; StructurizeCFG::orderNodes basically uses a reverse post-order (RPO) traversal of the region
+; list to get the order. The only problem with it is that sometimes backedges
+; for outer loops will be visited before backedges for inner loops. To solve this problem,
+; a loop depth based approach has been used to make sure all blocks in this loop has been visited
+; before moving on to outer loop.
+;
+; However, we found a problem for a SubRegion which is a loop itself:
+;                   _
+;                  | |
+;                  V |
+;      --> BB1 --> BB2 --> BB3 -->
+;
+; In this case, BB2 is a SubRegion (loop), and thus its loopdepth is different than that of
+; BB1 and BB3. This fact will lead BB2 to be placed in the wrong order.
+;
+; In this work, we treat the SubRegion as a special case and use its exit block to determine
+; the loop and its depth to guard the sorting.
+define amdgpu_kernel void @loop_subregion_misordered(i32 addrspace(1)* %arg0) #0 {
+; CHECK-LABEL: @loop_subregion_misordered(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP:%.*]] = load volatile <2 x i32>, <2 x i32> addrspace(1)* undef, align 16
+; CHECK-NEXT:    [[LOAD1:%.*]] = load volatile <2 x float>, <2 x float> addrspace(1)* undef
+; CHECK-NEXT:    [[TID:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, i32 addrspace(1)* [[ARG0:%.*]], i32 [[TID]]
+; CHECK-NEXT:    [[I_INITIAL:%.*]] = load volatile i32, i32 addrspace(1)* [[GEP]], align 4
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       LOOP.HEADER:
+; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INITIAL]], [[ENTRY:%.*]] ], [ [[TMP7:%.*]], [[FLOW3:%.*]] ]
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x100b
+; CHECK-NEXT:    [[TMP12:%.*]] = zext i32 [[I]] to i64
+; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32> addrspace(1)* null, i64 [[TMP12]]
+; CHECK-NEXT:    [[TMP14:%.*]] = load <4 x i32>, <4 x i32> addrspace(1)* [[TMP13]], align 16
+; CHECK-NEXT:    [[TMP15:%.*]] = extractelement <4 x i32> [[TMP14]], i64 0
+; CHECK-NEXT:    [[TMP16:%.*]] = and i32 [[TMP15]], 65535
+; CHECK-NEXT:    [[TMP17:%.*]] = icmp eq i32 [[TMP16]], 1
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[TMP17]], true
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB62:%.*]], label [[FLOW:%.*]]
+; CHECK:       Flow1:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[INC_I:%.*]], [[INCREMENT_I:%.*]] ], [ undef, [[BB62]] ]
+; CHECK-NEXT:    [[TMP2:%.*]] = phi i1 [ false, [[INCREMENT_I]] ], [ true, [[BB62]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = phi i1 [ true, [[INCREMENT_I]] ], [ false, [[BB62]] ]
+; CHECK-NEXT:    br label [[FLOW]]
+; CHECK:       bb18:
+; CHECK-NEXT:    [[TMP19:%.*]] = extractelement <2 x i32> [[TMP]], i64 0
+; CHECK-NEXT:    [[TMP22:%.*]] = lshr i32 [[TMP19]], 16
+; CHECK-NEXT:    [[TMP24:%.*]] = urem i32 [[TMP22]], 52
+; CHECK-NEXT:    [[TMP25:%.*]] = mul nuw nsw i32 [[TMP24]], 52
+; CHECK-NEXT:    br label [[INNER_LOOP:%.*]]
+; CHECK:       Flow2:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i32 [ [[TMP59:%.*]], [[INNER_LOOP_BREAK:%.*]] ], [ [[TMP9:%.*]], [[FLOW]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = phi i1 [ true, [[INNER_LOOP_BREAK]] ], [ [[TMP11:%.*]], [[FLOW]] ]
+; CHECK-NEXT:    br i1 [[TMP5]], label [[END_ELSE_BLOCK:%.*]], label [[FLOW3]]
+; CHECK:       INNER_LOOP:
+; CHECK-NEXT:    [[INNER_LOOP_J:%.*]] = phi i32 [ [[INNER_LOOP_J_INC:%.*]], [[INNER_LOOP]] ], [ [[TMP25]], [[BB18:%.*]] ]
+; CHECK-NEXT:    call void asm sideeffect "
+; CHECK-NEXT:    [[INNER_LOOP_J_INC]] = add nsw i32 [[INNER_LOOP_J]], 1
+; CHECK-NEXT:    [[INNER_LOOP_CMP:%.*]] = icmp eq i32 [[INNER_LOOP_J]], 0
+; CHECK-NEXT:    br i1 [[INNER_LOOP_CMP]], label [[INNER_LOOP_BREAK]], label [[INNER_LOOP]]
+; CHECK:       INNER_LOOP_BREAK:
+; CHECK-NEXT:    [[TMP59]] = extractelement <4 x i32> [[TMP14]], i64 2
+; CHECK-NEXT:    call void asm sideeffect "s_nop 23 ", "~{memory}"() #0
+; CHECK-NEXT:    br label [[FLOW2:%.*]]
+; CHECK:       bb62:
+; CHECK-NEXT:    [[LOAD13:%.*]] = icmp ult i32 [[TMP16]], 271
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i1 [[LOAD13]], true
+; CHECK-NEXT:    br i1 [[TMP6]], label [[INCREMENT_I]], label [[FLOW1:%.*]]
+; CHECK:       Flow3:
+; CHECK-NEXT:    [[TMP7]] = phi i32 [ [[I_FINAL:%.*]], [[END_ELSE_BLOCK]] ], [ undef, [[FLOW2]] ]
+; CHECK-NEXT:    [[TMP8:%.*]] = phi i1 [ [[CMP_END_ELSE_BLOCK:%.*]], [[END_ELSE_BLOCK]] ], [ true, [[FLOW2]] ]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[FLOW4:%.*]], label [[LOOP_HEADER]]
+; CHECK:       Flow4:
+; CHECK-NEXT:    br i1 [[TMP10:%.*]], label [[BB64:%.*]], label [[RETURN:%.*]]
+; CHECK:       bb64:
+; CHECK-NEXT:    call void asm sideeffect "s_nop 42", "~{memory}"() #0
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       Flow:
+; CHECK-NEXT:    [[TMP9]] = phi i32 [ [[TMP1]], [[FLOW1]] ], [ undef, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    [[TMP10]] = phi i1 [ [[TMP2]], [[FLOW1]] ], [ false, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    [[TMP11]] = phi i1 [ [[TMP3]], [[FLOW1]] ], [ false, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    [[TMP12:%.*]] = phi i1 [ false, [[FLOW1]] ], [ true, [[LOOP_HEADER]] ]
+; CHECK-NEXT:    br i1 [[TMP12]], label [[BB18]], label [[FLOW2]]
+; CHECK:       INCREMENT_I:
+; CHECK-NEXT:    [[INC_I]] = add i32 [[I]], 1
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x1336
+; CHECK-NEXT:    br label [[FLOW1]]
+; CHECK:       END_ELSE_BLOCK:
+; CHECK-NEXT:    [[I_FINAL]] = phi i32 [ [[TMP4]], [[FLOW2]] ]
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x1337
+; CHECK-NEXT:    [[CMP_END_ELSE_BLOCK]] = icmp eq i32 [[I_FINAL]], -1
+; CHECK-NEXT:    br label [[FLOW3]]
+; CHECK:       RETURN:
+; CHECK-NEXT:    call void asm sideeffect "s_nop 0x99
+; CHECK-NEXT:    store volatile <2 x float> [[LOAD1]], <2 x float> addrspace(1)* undef, align 8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %tmp = load volatile <2 x i32>, <2 x i32> addrspace(1)* undef, align 16
+  %load1 = load volatile <2 x float>, <2 x float> addrspace(1)* undef
+  %tid = call i32 @llvm.amdgcn.workitem.id.x()
+  %gep = getelementptr inbounds i32, i32 addrspace(1)* %arg0, i32 %tid
+  %i.initial = load volatile i32, i32 addrspace(1)* %gep, align 4
+  br label %LOOP.HEADER
+
+LOOP.HEADER:
+  %i = phi i32 [ %i.final, %END_ELSE_BLOCK ], [ %i.initial, %entry ]
+  call void asm sideeffect "s_nop 0x100b ; loop $0 ", "r,~{memory}"(i32 %i) #0
+  %tmp12 = zext i32 %i to i64
+  %tmp13 = getelementptr inbounds <4 x i32>, <4 x i32> addrspace(1)* null, i64 %tmp12
+  %tmp14 = load <4 x i32>, <4 x i32> addrspace(1)* %tmp13, align 16
+  %tmp15 = extractelement <4 x i32> %tmp14, i64 0
+  %tmp16 = and i32 %tmp15, 65535
+  %tmp17 = icmp eq i32 %tmp16, 1
+  br i1 %tmp17, label %bb18, label %bb62
+
+bb18:
+  %tmp19 = extractelement <2 x i32> %tmp, i64 0
+  %tmp22 = lshr i32 %tmp19, 16
+  %tmp24 = urem i32 %tmp22, 52
+  %tmp25 = mul nuw nsw i32 %tmp24, 52
+  br label %INNER_LOOP
+
+INNER_LOOP:
+  %inner.loop.j = phi i32 [ %tmp25, %bb18 ], [ %inner.loop.j.inc, %INNER_LOOP ]
+  call void asm sideeffect "; inner loop body", ""() #0
+  %inner.loop.j.inc = add nsw i32 %inner.loop.j, 1
+  %inner.loop.cmp = icmp eq i32 %inner.loop.j, 0
+  br i1 %inner.loop.cmp, label %INNER_LOOP_BREAK, label %INNER_LOOP
+
+INNER_LOOP_BREAK:
+  %tmp59 = extractelement <4 x i32> %tmp14, i64 2
+  call void asm sideeffect "s_nop 23 ", "~{memory}"() #0
+  br label %END_ELSE_BLOCK
+
+bb62:
+  %load13 = icmp ult i32 %tmp16, 271
+  br i1 %load13, label %bb64, label %INCREMENT_I
+
+bb64:
+  call void asm sideeffect "s_nop 42", "~{memory}"() #0
+  br label %RETURN
+
+INCREMENT_I:
+  %inc.i = add i32 %i, 1
+  call void asm sideeffect "s_nop 0x1336 ; increment $0", "v,~{memory}"(i32 %inc.i) #0
+  br label %END_ELSE_BLOCK
+
+END_ELSE_BLOCK:
+  %i.final = phi i32 [ %tmp59, %INNER_LOOP_BREAK ], [ %inc.i, %INCREMENT_I ]
+  call void asm sideeffect "s_nop 0x1337 ; end else block $0", "v,~{memory}"(i32 %i.final) #0
+  %cmp.end.else.block = icmp eq i32 %i.final, -1
+  br i1 %cmp.end.else.block, label %RETURN, label %LOOP.HEADER
+
+RETURN:
+  call void asm sideeffect "s_nop 0x99 ; ClosureEval return", "~{memory}"() #0
+  store volatile <2 x float> %load1, <2 x float> addrspace(1)* undef, align 8
+  ret void
+}
+
+declare i32 @llvm.amdgcn.workitem.id.x() #1
+
+attributes #0 = { convergent nounwind }
+attributes #1 = { convergent nounwind readnone }

Added: llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,82 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -mtriple=amdgcn-- -S -o - -structurizecfg -structurizecfg-skip-uniform-regions < %s | FileCheck %s
+
+define amdgpu_cs void @uniform(i32 inreg %v) {
+; CHECK-LABEL: @uniform(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CC:%.*]] = icmp eq i32 [[V:%.*]], 0
+; CHECK-NEXT:    br i1 [[CC]], label [[IF:%.*]], label [[END:%.*]], !structurizecfg.uniform !0
+; CHECK:       if:
+; CHECK-NEXT:    br label [[END]], !structurizecfg.uniform !0
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cc = icmp eq i32 %v, 0
+  br i1 %cc, label %if, label %end
+
+if:
+  br label %end
+
+end:
+  ret void
+}
+
+define amdgpu_cs void @nonuniform(i32 addrspace(4)* %ptr) {
+; CHECK-LABEL: @nonuniform(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[FLOW:%.*]] ]
+; CHECK-NEXT:    [[CC:%.*]] = icmp ult i32 [[I]], 4
+; CHECK-NEXT:    br i1 [[CC]], label [[MID_LOOP:%.*]], label [[FLOW]]
+; CHECK:       mid.loop:
+; CHECK-NEXT:    [[V:%.*]] = call i32 @llvm.amdgcn.workitem.id.x()
+; CHECK-NEXT:    [[CC2:%.*]] = icmp eq i32 [[V]], 0
+; CHECK-NEXT:    br i1 [[CC2]], label [[END_LOOP:%.*]], label [[FLOW1:%.*]]
+; CHECK:       Flow:
+; CHECK-NEXT:    [[TMP0]] = phi i32 [ [[TMP2:%.*]], [[FLOW1]] ], [ undef, [[FOR_BODY]] ]
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ [[TMP3:%.*]], [[FLOW1]] ], [ true, [[FOR_BODY]] ]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[FOR_END:%.*]], label [[FOR_BODY]]
+; CHECK:       end.loop:
+; CHECK-NEXT:    [[I_INC:%.*]] = add i32 [[I]], 1
+; CHECK-NEXT:    br label [[FLOW1]]
+; CHECK:       Flow1:
+; CHECK-NEXT:    [[TMP2]] = phi i32 [ [[I_INC]], [[END_LOOP]] ], [ undef, [[MID_LOOP]] ]
+; CHECK-NEXT:    [[TMP3]] = phi i1 [ false, [[END_LOOP]] ], [ true, [[MID_LOOP]] ]
+; CHECK-NEXT:    br label [[FLOW]]
+; CHECK:       for.end:
+; CHECK-NEXT:    br i1 [[CC]], label [[IF:%.*]], label [[END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [0, %entry], [%i.inc, %end.loop]
+  %cc = icmp ult i32 %i, 4
+  br i1 %cc, label %mid.loop, label %for.end
+
+mid.loop:
+  %v = call i32 @llvm.amdgcn.workitem.id.x()
+  %cc2 = icmp eq i32 %v, 0
+  br i1 %cc2, label %end.loop, label %for.end
+
+end.loop:
+  %i.inc = add i32 %i, 1
+  br label %for.body
+
+for.end:
+  br i1 %cc, label %if, label %end
+
+if:
+  br label %end
+
+end:
+  ret void
+}
+
+declare i32 @llvm.amdgcn.workitem.id.x()

Added: llvm/trunk/test/Transforms/StructurizeCFG/branch-on-argument.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/branch-on-argument.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/branch-on-argument.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/branch-on-argument.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -S -o - -structurizecfg < %s | FileCheck %s
+
+; CHECK-LABEL: @invert_branch_on_arg_inf_loop(
+; CHECK: entry:
+; CHECK: %arg.inv = xor i1 %arg, true
+define void @invert_branch_on_arg_inf_loop(i32 addrspace(1)* %out, i1 %arg) {
+entry:
+  br i1 %arg, label %for.end, label %sesestart
+sesestart:
+  br label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  store i32 999, i32 addrspace(1)* %out, align 4
+  br i1 %arg, label %for.body, label %seseend
+seseend:
+  ret void
+
+for.end:                                          ; preds = %Flow
+  ret void
+}
+
+
+; CHECK-LABEL: @invert_branch_on_arg_jump_into_loop(
+; CHECK: entry:
+; CHECK: %arg.inv = xor i1 %arg, true
+; CHECK: Flow:
+; CHECK: Flow1:
+define void @invert_branch_on_arg_jump_into_loop(i32 addrspace(1)* %out, i32 %n, i1 %arg) {
+entry:
+  br label %for.body
+
+for.body:
+  %i = phi i32 [0, %entry], [%i.inc, %end.loop]
+  %ptr = getelementptr i32, i32 addrspace(1)* %out, i32 %i
+  store i32 %i, i32 addrspace(1)* %ptr, align 4
+  br i1 %arg, label %mid.loop, label %end.loop
+
+mid.loop:
+  store i32 333, i32 addrspace(1)* %out, align 4
+  br label %for.end
+
+end.loop:
+  %i.inc = add i32 %i, 1
+  %cmp = icmp ne i32 %i.inc, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.end:
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/StructurizeCFG/bug36015.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/bug36015.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/bug36015.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/bug36015.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; RUN: opt -S -structurizecfg %s | FileCheck %s
+
+; r321751 introduced a bug where control flow branching from if to exit was
+; not handled properly and instead ended up in an infinite loop.
+define void @bug36015(i32 %cmp0, i32 %count) {
+entry:
+  br label %loop.outer
+
+loop.outer:
+  %ctr.loop.outer = phi i32 [ 0, %entry ], [ %ctr.else, %else ]
+  call void @foo(i32 0)
+  br label %loop.inner
+
+loop.inner:
+  %ctr.loop.inner = phi i32 [ %ctr.loop.outer, %loop.outer ], [ %ctr.if, %if ]
+  call void @foo(i32 1)
+  %cond.inner = icmp eq i32 %cmp0, %ctr.loop.inner
+  br i1 %cond.inner, label %if, label %else
+
+; CHECK: if:
+; CHECK:   %0 = xor i1 %cond.if, true
+; CHECK:   br label %Flow
+if:
+  %ctr.if = add i32 %ctr.loop.inner, 1
+  call void @foo(i32 2)
+  %cond.if = icmp slt i32 %ctr.if, %count
+  br i1 %cond.if, label %loop.inner, label %exit
+
+; CHECK: Flow:
+; CHECK:   %2 = phi i1 [ %0, %if ], [ true, %loop.inner ]
+; CHECK:   %3 = phi i1 [ false, %if ], [ true, %loop.inner ]
+; CHECK:   br i1 %2, label %Flow1, label %loop.inner
+
+; CHECK: Flow1:
+; CHECK:   br i1 %3, label %else, label %Flow2
+
+; CHECK: else:
+; CHECK:   br label %Flow2
+else:
+  %ctr.else = add i32 %ctr.loop.inner, 1
+  call void @foo(i32 3)
+  %cond.else = icmp slt i32 %ctr.else, %count
+  br i1 %cond.else, label %loop.outer, label %exit
+
+; CHECK: Flow2:
+; CHECK:   %6 = phi i1 [ %4, %else ], [ true, %Flow1 ]
+; CHECK:   br i1 %6, label %exit, label %loop.outer
+
+exit:
+  ret void
+}
+
+declare void @foo(i32)

Added: llvm/trunk/test/Transforms/StructurizeCFG/invert-condition.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/invert-condition.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/invert-condition.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/invert-condition.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 -structurizecfg %s | FileCheck %s
+
+define void @invert_condition(i1 %arg) {
+; CHECK-LABEL: @invert_condition(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = load volatile float, float addrspace(1)* undef
+; CHECK-NEXT:    [[TMP1:%.*]] = load volatile float, float addrspace(1)* undef
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[TMP3:%.*]] = fcmp oge float [[TMP]], [[TMP1]]
+; CHECK-NEXT:    [[TMP4:%.*]] = xor i1 [[ARG:%.*]], [[TMP3]]
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[TMP4]], true
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB5:%.*]], label [[BB2]]
+; CHECK:       bb5:
+; CHECK-NEXT:    ret void
+;
+bb:
+  %tmp = load volatile float, float addrspace(1)* undef
+  %tmp1 = load volatile float, float addrspace(1)* undef
+  br label %bb2
+
+bb2:                                              ; preds = %bb2, %bb
+  %tmp3 = fcmp oge float %tmp, %tmp1
+  %tmp4 = xor i1 %arg, %tmp3
+  br i1 %tmp4, label %bb2, label %bb5
+
+bb5:                                              ; preds = %bb2
+  ret void
+}

Added: llvm/trunk/test/Transforms/StructurizeCFG/invert-constantexpr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/invert-constantexpr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/invert-constantexpr.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/invert-constantexpr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -o - -structurizecfg < %s | FileCheck %s
+
+ at g = global i32 0
+
+define void @invert_constantexpr_condition(i32 %arg, i32 %arg1) #0 {
+; CHECK-LABEL: @invert_constantexpr_condition(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = icmp eq i32 [[ARG:%.*]], 0
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[TMP]], true
+; CHECK-NEXT:    br i1 icmp eq (i32 ptrtoint (i32* @g to i32), i32 0), label [[BB2:%.*]], label [[FLOW:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[FLOW]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = phi i1 [ undef, [[FLOW]] ], [ [[TMP7:%.*]], [[BB6:%.*]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = or i1 [[TMP4]], icmp eq (i32 ptrtoint (i32* @g to i32), i32 0)
+; CHECK-NEXT:    br label [[BB8:%.*]]
+; CHECK:       Flow:
+; CHECK-NEXT:    [[TMP1:%.*]] = phi i1 [ [[TMP0]], [[BB2]] ], [ icmp ne (i32 ptrtoint (i32* @g to i32), i32 0), [[BB:%.*]] ]
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB6]], label [[BB3:%.*]]
+; CHECK:       bb6:
+; CHECK-NEXT:    [[TMP7]] = icmp slt i32 [[ARG]], [[ARG1:%.*]]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb8:
+; CHECK-NEXT:    ret void
+;
+bb:
+  %tmp = icmp eq i32 %arg, 0
+  br i1 icmp eq (i32 ptrtoint (i32* @g to i32), i32 0), label %bb2, label %bb6
+
+bb2:
+  br i1 %tmp, label %bb3, label %bb6
+
+bb3:
+  %tmp4 = phi i1 [ %tmp7, %bb6 ], [ undef, %bb2 ]
+  %tmp5 = or i1 %tmp4, icmp eq (i32 ptrtoint (i32* @g to i32), i32 0)
+  br i1 %tmp5, label %bb8, label %bb8
+
+bb6:
+  %tmp7 = icmp slt i32 %arg, %arg1
+  br label %bb3
+
+bb8:
+  ret void
+}
+
+declare i32 @llvm.amdgcn.workitem.id.x() #1
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }

Added: llvm/trunk/test/Transforms/StructurizeCFG/loop-continue-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/loop-continue-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/loop-continue-phi.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/loop-continue-phi.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 -o - -structurizecfg < %s | FileCheck %s
+
+define void @test1() {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       Flow:
+; CHECK-NEXT:    br label [[FLOW1:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[CTR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[CTR_NEXT:%.*]], [[FLOW1]] ]
+; CHECK-NEXT:    [[CTR_NEXT]] = add i32 [[CTR]], 1
+; CHECK-NEXT:    br i1 undef, label [[LOOP_A:%.*]], label [[FLOW1]]
+; CHECK:       loop.a:
+; CHECK-NEXT:    br i1 undef, label [[LOOP_B:%.*]], label [[FLOW:%.*]]
+; CHECK:       loop.b:
+; CHECK-NEXT:    br label [[FLOW]]
+; CHECK:       Flow1:
+; CHECK-NEXT:    [[TMP0:%.*]] = phi i1 [ false, [[FLOW]] ], [ true, [[LOOP]] ]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop
+
+loop:
+  %ctr = phi i32 [ 0, %entry ], [ %ctr.next, %loop.a ], [ %ctr.next, %loop.b ]
+  %ctr.next = add i32 %ctr, 1
+  br i1 undef, label %exit, label %loop.a
+
+loop.a:
+  br i1 undef, label %loop, label %loop.b
+
+loop.b:
+  br label %loop
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/StructurizeCFG/loop-multiple-exits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/loop-multiple-exits.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/loop-multiple-exits.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/loop-multiple-exits.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
+;
+; void loop(int *out, int cond_a, int cond_b) {
+;
+;   unsigned i;
+;   for (i = 0; i < cond_a; i++) {
+;     out[i] = i;
+;     if (i > cond_b) {
+;       break;
+;     }
+;     out[i + cond_a] = i;
+;   }
+; }
+
+define void @loop(i32 addrspace(1)* %out, i32 %cond_a, i32 %cond_b) nounwind uwtable {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cmp = icmp ult i32 %i.0, %cond_a
+  br i1 %cmp, label %for.body, label %for.end
+
+; CHECK: for.body:
+for.body:                                         ; preds = %for.cond
+  %arrayidx = getelementptr inbounds i32, i32 addrspace(1)* %out, i32 %i.0
+  store i32 %i.0, i32 addrspace(1)* %arrayidx, align 4
+  %cmp1 = icmp ugt i32 %i.0, %cond_b
+; CHECK: br i1 %{{[0-9a-zA-Z_]+}}, label %for.inc, label %[[FLOW1:[0-9a-zA-Z_]+]]
+  br i1 %cmp1, label %for.end, label %for.inc
+
+; CHECK: [[FLOW:[0-9a-zA-Z]+]]:
+; CHECK: br i1 %{{[0-9a-zA-Z_]+}}, label %for.end, label %for.cond
+
+; CHECK: for.inc:
+; CHECK: br label %[[FLOW1]]
+
+for.inc:                                          ; preds = %for.body
+  %0 = add i32 %cond_a, %i.0
+  %arrayidx3 = getelementptr inbounds i32, i32 addrspace(1)* %out, i32 %0
+  store i32 %i.0, i32 addrspace(1)* %arrayidx3, align 4
+  %inc = add i32 %i.0, 1
+  br label %for.cond
+
+; CHECK: [[FLOW1]]
+; CHECK: br label %[[FLOW]]
+
+for.end:                                          ; preds = %for.cond, %for.body
+  ret void
+}

Added: llvm/trunk/test/Transforms/StructurizeCFG/nested-loop-order.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/nested-loop-order.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/nested-loop-order.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/nested-loop-order.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,68 @@
+; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
+
+define void @main(float addrspace(1)* %out) {
+
+; CHECK: main_body:
+; CHECK: br label %LOOP.outer
+main_body:
+  br label %LOOP.outer
+
+; CHECK: LOOP.outer:
+; CHECK: br label %LOOP
+LOOP.outer:                                       ; preds = %ENDIF28, %main_body
+  %temp8.0.ph = phi float [ 0.000000e+00, %main_body ], [ %tmp35, %ENDIF28 ]
+  %temp4.0.ph = phi i32 [ 0, %main_body ], [ %tmp20, %ENDIF28 ]
+  br label %LOOP
+
+; CHECK: LOOP:
+; br i1 %{{[0-9]+}}, label %ENDIF, label %Flow
+LOOP:                                             ; preds = %IF29, %LOOP.outer
+  %temp4.0 = phi i32 [ %temp4.0.ph, %LOOP.outer ], [ %tmp20, %IF29 ]
+  %tmp20 = add i32 %temp4.0, 1
+  %tmp22 = icmp sgt i32 %tmp20, 3
+  br i1 %tmp22, label %ENDLOOP, label %ENDIF
+
+; CHECK: Flow3
+; CHECK: br i1 %{{[0-9]+}}, label %ENDLOOP, label %LOOP.outer
+
+; CHECK: ENDLOOP:
+; CHECK: ret void
+ENDLOOP:                                          ; preds = %ENDIF28, %IF29, %LOOP
+  %temp8.1 = phi float [ %temp8.0.ph, %LOOP ], [ %temp8.0.ph, %IF29 ], [ %tmp35, %ENDIF28 ]
+  %tmp23 = icmp eq i32 %tmp20, 3
+  %.45 = select i1 %tmp23, float 0.000000e+00, float 1.000000e+00
+  store float %.45, float addrspace(1)* %out
+  ret void
+
+; CHECK: ENDIF:
+; CHECK: br i1 %tmp31, label %IF29, label %Flow1
+ENDIF:                                            ; preds = %LOOP
+  %tmp31 = icmp sgt i32 %tmp20, 1
+  br i1 %tmp31, label %IF29, label %ENDIF28
+
+; CHECK: Flow:
+; CHECK: br i1 %{{[0-9]+}}, label %Flow2, label %LOOP
+
+; CHECK: IF29:
+; CHECK: br label %Flow1
+IF29:                                             ; preds = %ENDIF
+  %tmp32 = icmp sgt i32 %tmp20, 2
+  br i1 %tmp32, label %ENDLOOP, label %LOOP
+
+; CHECK: Flow1:
+; CHECK: br label %Flow
+
+; CHECK: Flow2:
+; CHECK: br i1 %{{[0-9]+}}, label %ENDIF28, label %Flow3
+
+; CHECK: ENDIF28:
+; CHECK: br label %Flow3
+ENDIF28:                                          ; preds = %ENDIF
+  %tmp35 = fadd float %temp8.0.ph, 1.0
+  %tmp36 = icmp sgt i32 %tmp20, 2
+  br i1 %tmp36, label %ENDLOOP, label %LOOP.outer
+}
+
+attributes #0 = { "enable-no-nans-fp-math"="true" "unsafe-fp-math"="true" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { readnone }

Added: llvm/trunk/test/Transforms/StructurizeCFG/no-branch-to-entry.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/no-branch-to-entry.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/no-branch-to-entry.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/no-branch-to-entry.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; XFAIL: *
+
+; This test used to generate a region that caused it to delete the entry block,
+; but it does not anymore after the changes to handling of infinite loops in the
+; PostDominatorTree.
+; TODO: This should be either replaced with another IR or deleted completely.
+
+; RUN: opt -S -o - -structurizecfg -verify-dom-info < %s | FileCheck %s
+
+; CHECK-LABEL: @no_branch_to_entry_undef(
+; CHECK: entry:
+; CHECK-NEXT: br label %entry.orig
+define void @no_branch_to_entry_undef(i32 addrspace(1)* %out) {
+entry:
+  br i1 undef, label %for.end, label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  store i32 999, i32 addrspace(1)* %out, align 4
+  br label %for.body
+
+for.end:                                          ; preds = %Flow
+  ret void
+}
+
+; CHECK-LABEL: @no_branch_to_entry_true(
+; CHECK: entry:
+; CHECK-NEXT: br label %entry.orig
+define void @no_branch_to_entry_true(i32 addrspace(1)* %out) {
+entry:
+  br i1 true, label %for.end, label %for.body
+
+for.body:                                         ; preds = %entry, %for.body
+  store i32 999, i32 addrspace(1)* %out, align 4
+  br label %for.body
+
+for.end:                                          ; preds = %Flow
+  ret void
+}

Added: llvm/trunk/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
+
+; CHECK-NOT: br i1 true
+
+define void @blam(i32 addrspace(1)* nocapture %arg, float %arg1, float %arg2) {
+; CHECK: bb:
+bb:
+  br label %bb3
+
+; CHECK: bb3:
+; CHECK:   %0 = xor i1 %tmp4, true
+; CHECK:   br i1 %0, label %bb5, label %Flow
+bb3:                                              ; preds = %bb7, %bb
+  %tmp = phi i64 [ 0, %bb ], [ %tmp8, %bb7 ]
+  %tmp4 = fcmp ult float %arg1, 3.500000e+00
+  br i1 %tmp4, label %bb7, label %bb5
+
+; CHECK: bb5:
+; CHECK:   %1 = xor i1 %tmp6, true
+; CHECK:   br label %Flow
+bb5:                                              ; preds = %bb3
+  %tmp6 = fcmp olt float 0.000000e+00, %arg2
+  br i1 %tmp6, label %bb10, label %bb7
+
+; CHECK: Flow:
+; CHECK:   %2 = phi i1 [ %1, %bb5 ], [ %tmp4, %bb3 ]
+; CHECK:   br i1 %2, label %bb7, label %Flow1
+
+; CHECK: bb7:
+; CHECK:   br label %Flow1
+bb7:                                              ; preds = %bb5, %bb3
+  %tmp8 = add nuw nsw i64 %tmp, 1
+  %tmp9 = icmp slt i64 %tmp8, 5
+  br i1 %tmp9, label %bb3, label %bb10
+
+; CHECK: Flow1:
+; CHECK:   %6 = phi i1 [ %3, %bb7 ], [ true, %Flow ]
+; CHECK:   br i1 %6, label %bb10, label %bb3
+
+; CHECK: bb10:
+bb10:                                             ; preds = %bb7, %bb5
+  %tmp11 = phi i32 [ 15, %bb5 ], [ 255, %bb7 ]
+  store i32 %tmp11, i32 addrspace(1)* %arg, align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/StructurizeCFG/post-order-traversal-bug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/post-order-traversal-bug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/post-order-traversal-bug.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/post-order-traversal-bug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
+
+; The structurize cfg pass used to do a post-order traversal to generate a list
+; of ; basic blocks and then operate on the list in reverse.  This led to bugs,
+; because sometimes successors would be visited before their predecessors.
+; The fix for this was to do a reverse post-order traversal which is what the
+; algorithm requires.
+
+; Function Attrs: nounwind
+define void @test(float* nocapture %out, i32 %K1, float* nocapture readonly %nr) {
+
+; CHECK: entry:
+; CHECK: br label %for.body
+entry:
+  br label %for.body
+
+; CHECK: for.body:
+; CHECK: br i1 %{{[0-9]+}}, label %lor.lhs.false, label %Flow
+for.body:                                         ; preds = %for.body.backedge, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.be, %for.body.backedge ], [ 1, %entry ]
+  %best_val.027 = phi float [ %best_val.027.be, %for.body.backedge ], [ 5.000000e+01, %entry ]
+  %prev_start.026 = phi i32 [ %tmp26, %for.body.backedge ], [ 0, %entry ]
+  %best_count.025 = phi i32 [ %best_count.025.be, %for.body.backedge ], [ 0, %entry ]
+  %tmp0 = trunc i64 %indvars.iv to i32
+  %cmp1 = icmp eq i32 %tmp0, %K1
+  br i1 %cmp1, label %if.then, label %lor.lhs.false
+
+; CHECK: lor.lhs.false:
+; CHECK: br label %Flow
+lor.lhs.false:                                    ; preds = %for.body
+  %arrayidx = getelementptr inbounds float, float* %nr, i64 %indvars.iv
+  %tmp1 = load float, float* %arrayidx, align 4
+  %tmp2 = add nsw i64 %indvars.iv, -1
+  %arrayidx2 = getelementptr inbounds float, float* %nr, i64 %tmp2
+  %tmp3 = load float, float* %arrayidx2, align 4
+  %cmp3 = fcmp une float %tmp1, %tmp3
+  br i1 %cmp3, label %if.then, label %for.body.1
+
+; CHECK: Flow:
+; CHECK: br i1 %{{[0-9]+}}, label %if.then, label %Flow1
+
+; CHECK: if.then:
+; CHECK: br label %Flow1
+if.then:                                          ; preds = %lor.lhs.false, %for.body
+  %sub4 = sub nsw i32 %tmp0, %prev_start.026
+  %tmp4 = add nsw i64 %indvars.iv, -1
+  %arrayidx8 = getelementptr inbounds float, float* %nr, i64 %tmp4
+  %tmp5 = load float, float* %arrayidx8, align 4
+  br i1 %cmp1, label %for.end, label %for.body.1
+
+; CHECK: for.end:
+; CHECK: ret void
+for.end:                                          ; preds = %for.body.1, %if.then
+  %best_val.0.lcssa = phi float [ %best_val.233, %for.body.1 ], [ %tmp5, %if.then ]
+  store float %best_val.0.lcssa, float* %out, align 4
+  ret void
+
+; CHECK: Flow1
+; CHECK: br i1 %{{[0-9]}}, label %for.body.1, label %Flow2
+
+; CHECK: for.body.1:
+; CHECK: br i1 %{{[0-9]+}}, label %for.body.6, label %Flow3
+for.body.1:                                       ; preds = %if.then, %lor.lhs.false
+  %best_val.233 = phi float [ %tmp5, %if.then ], [ %best_val.027, %lor.lhs.false ]
+  %best_count.231 = phi i32 [ %sub4, %if.then ], [ %best_count.025, %lor.lhs.false ]
+  %indvars.iv.next.454 = add nsw i64 %indvars.iv, 5
+  %tmp22 = trunc i64 %indvars.iv.next.454 to i32
+  %cmp1.5 = icmp eq i32 %tmp22, %K1
+  br i1 %cmp1.5, label %for.end, label %for.body.6
+
+; CHECK: Flow2:
+; CHECK: br i1 %{{[0-9]+}}, label %for.end, label %for.body
+
+; CHECK: for.body.6:
+; CHECK: br i1 %cmp5.6, label %if.then6.6, label %for.body.backedge
+for.body.6:                                       ; preds = %for.body.1
+  %indvars.iv.next.559 = add nsw i64 %indvars.iv, 6
+  %tmp26 = trunc i64 %indvars.iv.next.559 to i32
+  %sub4.6 = sub nsw i32 %tmp26, %tmp22
+  %cmp5.6 = icmp slt i32 %best_count.231, %sub4.6
+  br i1 %cmp5.6, label %if.then6.6, label %for.body.backedge
+
+; CHECK: if.then6.6
+; CHECK: br label %for.body.backedge
+if.then6.6:                                       ; preds = %for.body.6
+  %arrayidx8.6 = getelementptr inbounds float, float* %nr, i64 %indvars.iv.next.454
+  %tmp29 = load float, float* %arrayidx8.6, align 4
+  br label %for.body.backedge
+
+; CHECK: Flow3:
+; CHECK: br label %Flow2
+
+; CHECK: for.body.backedge:
+; CHECK: br label %Flow3
+for.body.backedge:                                ; preds = %if.then6.6, %for.body.6
+  %best_val.027.be = phi float [ %tmp29, %if.then6.6 ], [ %best_val.233, %for.body.6 ]
+  %best_count.025.be = phi i32 [ %sub4.6, %if.then6.6 ], [ %best_count.231, %for.body.6 ]
+  %indvars.iv.be = add nsw i64 %indvars.iv, 7
+  br label %for.body
+}

Added: llvm/trunk/test/Transforms/StructurizeCFG/rebuild-ssa-infinite-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/rebuild-ssa-infinite-loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/rebuild-ssa-infinite-loop.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/rebuild-ssa-infinite-loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -o /dev/null -structurizecfg %s
+
+; The following function caused an infinite loop inside the structurizer's
+; rebuildSSA routine, where we were iterating over an instruction's uses while
+; modifying the use list, without taking care to do this safely.
+
+target triple = "amdgcn--"
+
+define amdgpu_vs void @wrapper(i32 inreg %arg, i32 %arg1) {
+main_body:
+  %tmp = add i32 %arg1, %arg
+  %tmp2 = call <4 x float> @llvm.amdgcn.buffer.load.format.v4f32(<4 x i32> undef, i32 %tmp, i32 0, i1 false, i1 false)
+  %tmp3 = extractelement <4 x float> %tmp2, i32 1
+  %tmp4 = fptosi float %tmp3 to i32
+  %tmp5 = insertelement <2 x i32> undef, i32 %tmp4, i32 1
+  br label %loop11.i
+
+loop11.i:                                         ; preds = %endif46.i, %main_body
+  %tmp6 = phi i32 [ 0, %main_body ], [ %tmp14, %endif46.i ]
+  %tmp7 = icmp sgt i32 %tmp6, 999
+  br i1 %tmp7, label %main.exit, label %if16.i
+
+if16.i:                                           ; preds = %loop11.i
+  %tmp8 = call <4 x float> @llvm.amdgcn.image.load.v4f32.v2i32.v8i32(<2 x i32> %tmp5, <8 x i32> undef, i32 15, i1 true, i1 false, i1 false, i1 false)
+  %tmp9 = extractelement <4 x float> %tmp8, i32 0
+  %tmp10 = fcmp ult float 0.000000e+00, %tmp9
+  br i1 %tmp10, label %if28.i, label %endif46.i
+
+if28.i:                                           ; preds = %if16.i
+  %tmp11 = bitcast float %tmp9 to i32
+  %tmp12 = shl i32 %tmp11, 16
+  %tmp13 = bitcast i32 %tmp12 to float
+  br label %main.exit
+
+endif46.i:                                        ; preds = %if16.i
+  %tmp14 = add i32 %tmp6, 1
+  br label %loop11.i
+
+main.exit:                                        ; preds = %if28.i, %loop11.i
+  %tmp15 = phi float [ %tmp13, %if28.i ], [ 0x36F0800000000000, %loop11.i ]
+  call void @llvm.amdgcn.exp.f32(i32 32, i32 15, float %tmp15, float 0.000000e+00, float 0.000000e+00, float 0x36A0000000000000, i1 false, i1 false) #0
+  ret void
+}
+
+; Function Attrs: nounwind
+declare void @llvm.amdgcn.exp.f32(i32, i32, float, float, float, float, i1, i1) #0
+
+; Function Attrs: nounwind readnone
+declare <4 x float> @llvm.amdgcn.buffer.load.format.v4f32(<4 x i32>, i32, i32, i1, i1) #2
+
+; Function Attrs: nounwind readonly
+declare <4 x float> @llvm.amdgcn.image.load.v4f32.v2i32.v8i32(<2 x i32>, <8 x i32>, i32, i1, i1, i1, i1) #2
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind readonly }

Added: llvm/trunk/test/Transforms/StructurizeCFG/switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/StructurizeCFG/switch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/StructurizeCFG/switch.ll (added)
+++ llvm/trunk/test/Transforms/StructurizeCFG/switch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -S -structurizecfg %s -o - | FileCheck %s
+
+; The structurizecfg pass cannot handle switch instructions, so we need to
+; make sure the lower switch pass is always run before structurizecfg.
+
+; CHECK-LABEL: @switch
+define void @switch(i32 addrspace(1)* %out, i32 %cond) nounwind {
+entry:
+; CHECK: icmp
+  switch i32 %cond, label %done [ i32 0, label %zero]
+
+; CHECK: zero:
+zero:
+; CHECK: store i32 7, i32 addrspace(1)* %out
+  store i32 7, i32 addrspace(1)* %out
+; CHECK: br label %done
+  br label %done
+
+; CHECK: done:
+done:
+; CHECK: ret void
+  ret void
+}

Added: llvm/trunk/test/Transforms/SyntheticCountsPropagation/initial.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SyntheticCountsPropagation/initial.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SyntheticCountsPropagation/initial.ll (added)
+++ llvm/trunk/test/Transforms/SyntheticCountsPropagation/initial.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; RUN: opt -passes=synthetic-counts-propagation -S < %s | FileCheck %s
+
+; CHECK-LABEL: define void @foo()
+; CHECK: !prof ![[COUNT1:[0-9]+]]
+define void @foo() {
+  ret void
+}
+
+; CHECK-LABEL: define void @foo_inline() #0
+; CHECK: !prof ![[COUNT2:[0-9]+]]
+define void @foo_inline() #0 {
+  ret void
+}
+
+; CHECK-LABEL: define void @foo_always_inline() #1
+; CHECK: !prof ![[COUNT2]]
+define void @foo_always_inline() #1 {
+  ret void
+}
+
+; CHECK-LABEL: define void @foo_cold() #2
+; CHECK: !prof ![[COUNT3:[0-9]+]]
+define void @foo_cold() #2 {
+  ret void
+}
+
+; CHECK-LABEL: define void @foo_noinline() #3
+; CHECK: !prof ![[COUNT3]]
+define void @foo_noinline() #3 {
+  ret void
+}
+
+; CHECK-LABEL: define internal void @foo_local()
+; CHECK: !prof ![[COUNT4:[0-9]+]]
+define internal void @foo_local() {
+  ret void
+}
+
+; CHECK-LABEL: define internal void @foo_local_escaped()
+; CHECK: !prof ![[COUNT1]]
+define internal void @foo_local_escaped() {
+  ret void
+}
+
+declare void @ext(void ()*)
+
+define void @bar() {
+  call void @ext(void ()* nonnull @foo_local_escaped)
+  ret void
+}
+
+; CHECK-LABEL: define internal void @foo_local_inline() #0
+; CHECK: !prof ![[COUNT2]]
+define internal void @foo_local_inline() #0 {
+  ret void
+}
+
+; CHECK-LABEL: define internal void @foo_local_cold() #2
+; CHECK: !prof ![[COUNT4]]
+define internal void @foo_local_cold() #2 {
+  ret void
+}
+
+; CHECK-LABEL: define linkonce void @foo_linkonce()
+; CHECK: !prof ![[COUNT1]]
+define linkonce void @foo_linkonce() {
+  ret void
+}
+
+; CHECK: ![[COUNT1]] = !{!"synthetic_function_entry_count", i64 10}
+; CHECK: ![[COUNT2]] = !{!"synthetic_function_entry_count", i64 15}
+; CHECK: ![[COUNT3]] = !{!"synthetic_function_entry_count", i64 5}
+; CHECK: ![[COUNT4]] = !{!"synthetic_function_entry_count", i64 0}
+
+attributes #0 = {inlinehint}
+attributes #1 = {alwaysinline}
+attributes #2 = {cold}
+attributes #3 = {noinline}
+

Added: llvm/trunk/test/Transforms/SyntheticCountsPropagation/prop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SyntheticCountsPropagation/prop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SyntheticCountsPropagation/prop.ll (added)
+++ llvm/trunk/test/Transforms/SyntheticCountsPropagation/prop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -passes=synthetic-counts-propagation -S < %s | FileCheck %s
+
+; CHECK-LABEL: define void @level1a(i32 %n)
+; CHECK: !prof ![[COUNT1:[0-9]+]]
+define void @level1a(i32 %n) {
+entry:
+  %cmp = icmp sgt i32 %n, 10
+  br i1 %cmp, label %exit, label %loop
+loop:
+  %i = phi i32 [%n, %entry], [%i1, %loop]
+  call void @level2a(i32 %n)
+  %i1 = sub i32 %i, 1
+  %cmp2 = icmp eq i32 %i1, 0
+  br i1 %cmp2, label %exit, label %loop, !prof !1
+exit:
+  ret void
+}
+
+; CHECK-LABEL: define void @level2a(i32 %n)
+; CHECK: !prof ![[COUNT2:[0-9]+]]
+define void @level2a(i32 %n) {
+  call void @level2b(i32 %n)
+  ret void
+}
+
+; CHECK-LABEL: define void @level2b(i32 %n)
+; CHECK: !prof ![[COUNT2]]
+define void @level2b(i32 %n) {
+entry:
+  call void @level2a(i32 %n)
+  %cmp = icmp eq i32 %n, 0
+  br i1 %cmp, label %then, label %else, !prof !2
+then:
+  call void @level3a(i32 %n)
+  br label %else
+else:
+  ret void
+}
+
+; CHECK-LABEL: define internal void @level3a(i32 %n)
+; CHECK: !prof ![[COUNT3:[0-9]+]]
+define internal void @level3a(i32 %n) {
+  ret void
+}
+
+!1 = !{!"branch_weights", i32 1, i32 99}
+!2 = !{!"branch_weights", i32 1, i32 1}
+; CHECK: ![[COUNT1]] = !{!"synthetic_function_entry_count", i64 10}
+; CHECK: ![[COUNT2]] = !{!"synthetic_function_entry_count", i64 520}
+; CHECK: ![[COUNT3]] = !{!"synthetic_function_entry_count", i64 260}

Added: llvm/trunk/test/Transforms/SyntheticCountsPropagation/scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SyntheticCountsPropagation/scc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SyntheticCountsPropagation/scc.ll (added)
+++ llvm/trunk/test/Transforms/SyntheticCountsPropagation/scc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt -passes=synthetic-counts-propagation -S < %s | FileCheck %s
+
+; CHECK-LABEL: define void @foo()
+; CHECK: !prof ![[COUNT1:[0-9]+]]
+define void @foo() {
+  call void @bar()
+  ret void
+}
+
+; CHECK-LABEL: define void @bar() #0
+; CHECK: !prof ![[COUNT1]]
+define void @bar() #0 {
+  call void @foo()
+  ret void
+}
+
+attributes #0 = {inlinehint}
+
+; CHECK: ![[COUNT1]] = !{!"synthetic_function_entry_count", i64 25}

Added: llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+; PR7328
+; PR7506
+define i32 @foo(i32 %x) {
+; CHECK-LABEL: define i32 @foo(
+; CHECK: %accumulator.tr = phi i32 [ 1, %entry ], [ 0, %body ]
+entry:
+  %cond = icmp ugt i32 %x, 0                      ; <i1> [#uses=1]
+  br i1 %cond, label %return, label %body
+
+body:                                             ; preds = %entry
+  %y = add i32 %x, 1                              ; <i32> [#uses=1]
+  %tmp = call i32 @foo(i32 %y)                    ; <i32> [#uses=0]
+; CHECK-NOT: call
+  ret i32 0
+; CHECK: ret i32 %accumulator.tr
+
+return:                                           ; preds = %entry
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/TailCallElim/EraseBB.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/EraseBB.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/EraseBB.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/EraseBB.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -tailcallelim -verify-dom-info -S < %s 2>&1 | FileCheck %s
+
+; CHECK: add nsw i32
+; CHECK-NEXT: br label
+; CHECK: add nsw i32
+; CHECK-NEXT: br label
+; CHECK-NOT: Uses remain when a value is destroyed
+define i32 @test(i32 %n) {
+entry:
+  %cmp = icmp slt i32 %n, 2
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %v1 = add nsw i32 %n, -2
+  %call1 = tail call i32 @test(i32 %v1)
+  br label %return
+
+if.else:                                          ; preds = %entry
+  %v2 = add nsw i32 %n, 4
+  %call2 = tail call i32 @test(i32 %v2)
+  br label %return
+
+return:                                           ; preds = %if.end, %if.else
+  %retval = phi i32 [ %call1, %if.then ], [ %call2, %if.else ]
+  ret i32 %retval
+}

Added: llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/accum_recursion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+; RUN: opt < %s -passes=tailcallelim -verify-dom-info -S | FileCheck %s
+
+define i32 @test1_factorial(i32 %x) {
+entry:
+	%tmp.1 = icmp sgt i32 %x, 0		; <i1> [#uses=1]
+	br i1 %tmp.1, label %then, label %else
+then:		; preds = %entry
+	%tmp.6 = add i32 %x, -1		; <i32> [#uses=1]
+	%tmp.4 = call i32 @test1_factorial( i32 %tmp.6 )		; <i32> [#uses=1]
+	%tmp.7 = mul i32 %tmp.4, %x		; <i32> [#uses=1]
+	ret i32 %tmp.7
+else:		; preds = %entry
+	ret i32 1
+}
+
+; CHECK-LABEL: define i32 @test1_factorial(
+; CHECK: phi i32
+; CHECK-NOT: call i32
+; CHECK: else:
+
+; This is a more aggressive form of accumulator recursion insertion, which 
+; requires noticing that X doesn't change as we perform the tailcall.
+
+define i32 @test2_mul(i32 %x, i32 %y) {
+entry:
+	%tmp.1 = icmp eq i32 %y, 0		; <i1> [#uses=1]
+	br i1 %tmp.1, label %return, label %endif
+endif:		; preds = %entry
+	%tmp.8 = add i32 %y, -1		; <i32> [#uses=1]
+	%tmp.5 = call i32 @test2_mul( i32 %x, i32 %tmp.8 )		; <i32> [#uses=1]
+	%tmp.9 = add i32 %tmp.5, %x		; <i32> [#uses=1]
+	ret i32 %tmp.9
+return:		; preds = %entry
+	ret i32 %x
+}
+
+; CHECK-LABEL: define i32 @test2_mul(
+; CHECK: phi i32
+; CHECK-NOT: call i32
+; CHECK: return:
+
+
+define i64 @test3_fib(i64 %n) nounwind readnone {
+; CHECK-LABEL: @test3_fib(
+entry:
+; CHECK: tailrecurse:
+; CHECK: %accumulator.tr = phi i64 [ %n, %entry ], [ %3, %bb1 ]
+; CHECK: %n.tr = phi i64 [ %n, %entry ], [ %2, %bb1 ]
+  switch i64 %n, label %bb1 [
+; CHECK: switch i64 %n.tr, label %bb1 [
+    i64 0, label %bb2
+    i64 1, label %bb2
+  ]
+
+bb1:
+; CHECK: bb1:
+  %0 = add i64 %n, -1
+; CHECK: %0 = add i64 %n.tr, -1
+  %1 = tail call i64 @test3_fib(i64 %0) nounwind
+; CHECK: %1 = tail call i64 @test3_fib(i64 %0)
+  %2 = add i64 %n, -2
+; CHECK: %2 = add i64 %n.tr, -2
+  %3 = tail call i64 @test3_fib(i64 %2) nounwind
+; CHECK-NOT: tail call i64 @test3_fib
+  %4 = add nsw i64 %3, %1
+; CHECK: add nsw i64 %accumulator.tr, %1
+  ret i64 %4
+; CHECK: br label %tailrecurse
+
+bb2:
+; CHECK: bb2:
+  ret i64 %n
+; CHECK: ret i64 %accumulator.tr
+}

Added: llvm/trunk/test/Transforms/TailCallElim/ackermann.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/ackermann.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/ackermann.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/ackermann.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; REQUIRES: asserts
+; This function contains two tail calls, which should be eliminated
+; RUN: opt < %s -tailcallelim -verify-dom-info -stats -disable-output 2>&1 | grep "2 tailcallelim"
+
+define i32 @Ack(i32 %M.1, i32 %N.1) {
+entry:
+	%tmp.1 = icmp eq i32 %M.1, 0		; <i1> [#uses=1]
+	br i1 %tmp.1, label %then.0, label %endif.0
+then.0:		; preds = %entry
+	%tmp.4 = add i32 %N.1, 1		; <i32> [#uses=1]
+	ret i32 %tmp.4
+endif.0:		; preds = %entry
+	%tmp.6 = icmp eq i32 %N.1, 0		; <i1> [#uses=1]
+	br i1 %tmp.6, label %then.1, label %endif.1
+then.1:		; preds = %endif.0
+	%tmp.10 = add i32 %M.1, -1		; <i32> [#uses=1]
+	%tmp.8 = call i32 @Ack( i32 %tmp.10, i32 1 )		; <i32> [#uses=1]
+	ret i32 %tmp.8
+endif.1:		; preds = %endif.0
+	%tmp.13 = add i32 %M.1, -1		; <i32> [#uses=1]
+	%tmp.17 = add i32 %N.1, -1		; <i32> [#uses=1]
+	%tmp.14 = call i32 @Ack( i32 %M.1, i32 %tmp.17 )		; <i32> [#uses=1]
+	%tmp.11 = call i32 @Ack( i32 %tmp.13, i32 %tmp.14 )		; <i32> [#uses=1]
+	ret i32 %tmp.11
+}
+

Added: llvm/trunk/test/Transforms/TailCallElim/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/basic.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,241 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+
+declare void @noarg()
+declare void @use(i32*)
+declare void @use_nocapture(i32* nocapture)
+declare void @use2_nocapture(i32* nocapture, i32* nocapture)
+
+; Trivial case. Mark @noarg with tail call.
+define void @test0() {
+; CHECK: tail call void @noarg()
+	call void @noarg()
+	ret void
+}
+
+; PR615. Make sure that we do not move the alloca so that it interferes with the tail call.
+define i32 @test1() {
+; CHECK: i32 @test1()
+; CHECK-NEXT: alloca
+	%A = alloca i32		; <i32*> [#uses=2]
+	store i32 5, i32* %A
+	call void @use(i32* %A)
+; CHECK: tail call i32 @test1
+	%X = tail call i32 @test1()		; <i32> [#uses=1]
+	ret i32 %X
+}
+
+; This function contains intervening instructions which should be moved out of the way
+define i32 @test2(i32 %X) {
+; CHECK: i32 @test2
+; CHECK-NOT: call
+; CHECK: ret i32
+entry:
+	%tmp.1 = icmp eq i32 %X, 0		; <i1> [#uses=1]
+	br i1 %tmp.1, label %then.0, label %endif.0
+then.0:		; preds = %entry
+	%tmp.4 = add i32 %X, 1		; <i32> [#uses=1]
+	ret i32 %tmp.4
+endif.0:		; preds = %entry
+	%tmp.10 = add i32 %X, -1		; <i32> [#uses=1]
+	%tmp.8 = call i32 @test2(i32 %tmp.10)		; <i32> [#uses=1]
+	%DUMMY = add i32 %X, 1		; <i32> [#uses=0]
+	ret i32 %tmp.8
+}
+
+; Though this case seems to be fairly unlikely to occur in the wild, someone
+; plunked it into the demo script, so maybe they care about it.
+define i32 @test3(i32 %c) {
+; CHECK: i32 @test3
+; CHECK-NOT: call
+; CHECK: ret i32 0
+entry:
+	%tmp.1 = icmp eq i32 %c, 0		; <i1> [#uses=1]
+	br i1 %tmp.1, label %return, label %else
+else:		; preds = %entry
+	%tmp.5 = add i32 %c, -1		; <i32> [#uses=1]
+	%tmp.3 = call i32 @test3(i32 %tmp.5)		; <i32> [#uses=0]
+	ret i32 0
+return:		; preds = %entry
+	ret i32 0
+}
+
+; Make sure that a nocapture pointer does not stop adding a tail call marker to
+; an unrelated call and additionally that we do not mark the nocapture call with
+; a tail call.
+;
+; rdar://14324281
+define void @test4() {
+; CHECK: void @test4
+; CHECK-NOT: tail call void @use_nocapture
+; CHECK: tail call void @noarg()
+; CHECK: ret void
+  %a = alloca i32
+  call void @use_nocapture(i32* %a)
+  call void @noarg()
+  ret void
+}
+
+; Make sure that we do not perform TRE even with a nocapture use. This is due to
+; bad codegen caused by PR962.
+;
+; rdar://14324281.
+define i32* @test5(i32* nocapture %A, i1 %cond) {
+; CHECK: i32* @test5
+; CHECK-NOT: tailrecurse:
+; CHECK: ret i32* null
+  %B = alloca i32
+  br i1 %cond, label %cond_true, label %cond_false
+cond_true:
+  call i32* @test5(i32* %B, i1 false)
+  ret i32* null
+cond_false:
+  call void @use2_nocapture(i32* %A, i32* %B)
+  call void @noarg()
+  ret i32* null
+}
+
+; PR14143: Make sure that we do not mark functions with nocapture allocas with tail.
+;
+; rdar://14324281.
+define void @test6(i32* %a, i32* %b) {
+; CHECK-LABEL: @test6(
+; CHECK-NOT: tail call
+; CHECK: ret void
+  %c = alloca [100 x i8], align 16
+  %tmp = bitcast [100 x i8]* %c to i32*
+  call void @use2_nocapture(i32* %b, i32* %tmp)
+  ret void
+}
+
+; PR14143: Make sure that we do not mark functions with nocapture allocas with tail.
+;
+; rdar://14324281
+define void @test7(i32* %a, i32* %b) nounwind uwtable {
+entry:
+; CHECK-LABEL: @test7(
+; CHECK-NOT: tail call
+; CHECK: ret void
+  %c = alloca [100 x i8], align 16
+  %0 = bitcast [100 x i8]* %c to i32*
+  call void @use2_nocapture(i32* %0, i32* %a)
+  call void @use2_nocapture(i32* %b, i32* %0)
+  ret void
+}
+
+; If we have a mix of escaping captured/non-captured allocas, ensure that we do
+; not do anything including marking callsites with the tail call marker.
+;
+; rdar://14324281.
+define i32* @test8(i32* nocapture %A, i1 %cond) {
+; CHECK: i32* @test8
+; CHECK-NOT: tailrecurse:
+; CHECK-NOT: tail call
+; CHECK: ret i32* null
+  %B = alloca i32
+  %B2 = alloca i32
+  br i1 %cond, label %cond_true, label %cond_false
+cond_true:
+  call void @use(i32* %B2)
+  call i32* @test8(i32* %B, i1 false)
+  ret i32* null
+cond_false:
+  call void @use2_nocapture(i32* %A, i32* %B)
+  call void @noarg()
+  ret i32* null
+}
+
+; Don't tail call if a byval arg is captured.
+define void @test9(i32* byval %a) {
+; CHECK-LABEL: define void @test9(
+; CHECK: {{^ *}}call void @use(
+  call void @use(i32* %a)
+  ret void
+}
+
+%struct.X = type { i8* }
+
+declare void @ctor(%struct.X*)
+define void @test10(%struct.X* noalias sret %agg.result, i1 zeroext %b) {
+; CHECK-LABEL: @test10
+entry:
+  %x = alloca %struct.X, align 8
+  br i1 %b, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  call void @ctor(%struct.X* %agg.result)
+; CHECK: tail call void @ctor
+  br label %return
+
+if.end:
+  call void @ctor(%struct.X* %x)
+; CHECK: call void @ctor
+  br label %return
+
+return:
+  ret void
+}
+
+declare void @test11_helper1(i8** nocapture, i8*)
+declare void @test11_helper2(i8*)
+define void @test11() {
+; CHECK-LABEL: @test11
+; CHECK-NOT: tail
+  %a = alloca i8*
+  %b = alloca i8
+  call void @test11_helper1(i8** %a, i8* %b)  ; a = &b
+  %c = load i8*, i8** %a
+  call void @test11_helper2(i8* %c)
+; CHECK: call void @test11_helper2
+  ret void
+}
+
+; PR25928
+define void @test12() {
+entry:
+; CHECK-LABEL: @test12
+; CHECK: {{^ *}} call void undef(i8* undef) [ "foo"(i8* %e) ]
+  %e = alloca i8
+  call void undef(i8* undef) [ "foo"(i8* %e) ]
+  unreachable
+}
+
+%struct.foo = type { [10 x i32] }
+
+; If an alloca is passed byval it is not a use of the alloca or an escape
+; point, and both calls below can be marked tail.
+define void @test13() {
+; CHECK-LABEL: @test13
+; CHECK: tail call void @bar(%struct.foo* byval %f)
+; CHECK: tail call void @bar(%struct.foo* null)
+entry:
+  %f = alloca %struct.foo
+  call void @bar(%struct.foo* byval %f)
+  call void @bar(%struct.foo* null)
+  ret void
+}
+
+; A call which passes a byval parameter using byval can be marked tail.
+define void @test14(%struct.foo* byval %f) {
+; CHECK-LABEL: @test14
+; CHECK: tail call void @bar
+entry:
+  call void @bar(%struct.foo* byval %f)
+  ret void
+}
+
+; If a byval parameter is copied into an alloca and passed byval the call can
+; be marked tail.
+define void @test15(%struct.foo* byval %f) {
+; CHECK-LABEL: @test15
+; CHECK: tail call void @bar
+entry:
+  %agg.tmp = alloca %struct.foo
+  %0 = bitcast %struct.foo* %agg.tmp to i8*
+  %1 = bitcast %struct.foo* %f to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 40, i1 false)
+  call void @bar(%struct.foo* byval %agg.tmp)
+  ret void
+}
+
+declare void @bar(%struct.foo* byval)
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1)

Added: llvm/trunk/test/Transforms/TailCallElim/debugloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/debugloc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/debugloc.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/debugloc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -debugify -tailcallelim -S | FileCheck %s
+
+define void @foo() {
+entry:
+; CHECK-LABEL: entry:
+; CHECK: br label %tailrecurse, !dbg ![[DbgLoc:[0-9]+]]
+
+  call void @foo()                            ;; line 1
+  ret void
+
+; CHECK-LABEL: tailrecurse:
+; CHECK: br label %tailrecurse, !dbg ![[DbgLoc]]
+}
+
+;; Make sure tailrecurse has the call instruction's DL
+; CHECK: ![[DbgLoc]] = !DILocation(line: 1

Added: llvm/trunk/test/Transforms/TailCallElim/deopt-bundle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/deopt-bundle.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/deopt-bundle.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/deopt-bundle.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+
+define i32 @f_1(i32 %x) {
+; CHECK-LABEL: @f_1(
+wentry:
+  %cond = icmp ugt i32 %x, 0
+  br i1 %cond, label %return, label %body
+
+body:
+; CHECK: body:
+; CHECK: call i32 @f_1(i32 %y) [ "deopt"() ]
+  %y = add i32 %x, 1
+  %tmp = call i32 @f_1(i32 %y) [ "deopt"() ]
+  ret i32 0
+
+return:
+  ret i32 1
+}
+
+define i32 @f_2(i32 %x) {
+; CHECK-LABEL: @f_2
+
+entry:
+  %cond = icmp ugt i32 %x, 0
+  br i1 %cond, label %return, label %body
+
+body:
+; CHECK: body:
+; CHECK: call i32 @f_2(i32 %y) [ "unknown"() ]
+  %y = add i32 %x, 1
+  %tmp = call i32 @f_2(i32 %y) [ "unknown"() ]
+  ret i32 0
+
+return:
+  ret i32 1
+}
+
+declare void @func()
+
+define void @f_3(i1 %B) personality i8 42 {
+; CHECK-LABEL: @f_3(
+entry:
+  invoke void @func()
+          to label %exit unwind label %merge
+merge:
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+
+catch:
+; CHECK: catch:
+; CHECK: call void @f_3(i1 %B) [ "funclet"(token %cp) ]
+  %cp = catchpad within %cs1 []
+  call void @f_3(i1 %B) [ "funclet"(token %cp) ]
+  ret void
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/TailCallElim/dont_reorder_load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/dont_reorder_load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/dont_reorder_load.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/dont_reorder_load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,82 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | grep call | count 4
+; PR4323
+
+; Several cases where tail call elimination should not move the load above the
+; call, and thus can't eliminate the tail recursion.
+
+
+ at extern_weak_global = extern_weak global i32		; <i32*> [#uses=1]
+
+
+; This load can't be safely moved above the call because the load is from an
+; extern_weak global and may trap, but the call may unwind before that happens.
+define fastcc i32 @no_tailrecelim_1(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 37
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @no_tailrecelim_1(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* @extern_weak_global		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+
+; This load can't be safely moved above the call because function may write to the pointer.
+define fastcc i32 @no_tailrecelim_2(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind {
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	store i32 1, i32* %a_arg
+        ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @no_tailrecelim_2(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+; This load can't be safely moved above the call because that would change the
+; order in which the load volatiles are performed.
+define fastcc i32 @no_tailrecelim_3(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind {
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+        ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @no_tailrecelim_3(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load volatile i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+; This load can NOT be moved above the call because the a_arg is not
+; sufficiently dereferenceable.
+define fastcc i32 @no_tailrecelim_4(i32* dereferenceable(2) %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @no_tailrecelim_4(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}

Added: llvm/trunk/test/Transforms/TailCallElim/dup_tail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/dup_tail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/dup_tail.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/dup_tail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; REQUIRES: asserts
+; Duplicate the return into if.end to enable TCE.
+; RUN: opt -tailcallelim -verify-dom-info -stats -disable-output < %s 2>&1 | FileCheck %s
+
+; CHECK: Number of return duplicated
+
+define i32 @fib(i32 %n) nounwind ssp {
+entry:
+  %cmp = icmp slt i32 %n, 2
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %sub = add nsw i32 %n, -2
+  %call = call i32 @fib(i32 %sub)
+  %sub3 = add nsw i32 %n, -1
+  %call4 = call i32 @fib(i32 %sub3)
+  %add = add nsw i32 %call, %call4
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ %add, %if.end ]
+  ret i32 %retval.0
+}

Added: llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/inf-recursion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+
+; Don't turn this into an infinite loop, this is probably the implementation
+; of fabs and we expect the codegen to lower fabs.
+; CHECK: @fabs(double %f)
+; CHECK: call
+; CHECK: ret
+
+define double @fabs(double %f) {
+entry:
+        %tmp2 = call double @fabs( double %f )          ; <double> [#uses=1]
+        ret double %tmp2
+}
+
+; Do turn other calls into infinite loops though.
+
+; CHECK-LABEL: define double @foo(
+; CHECK-NOT: call
+; CHECK: }
+define double @foo(double %f) {
+        %t= call double @foo(double %f)
+        ret double %t
+}
+
+; CHECK-LABEL: define float @fabsf(
+; CHECK-NOT: call
+; CHECK: }
+define float @fabsf(float %f) {
+        %t= call float @fabsf(float 2.0)
+        ret float %t
+}
+
+declare x86_fp80 @fabsl(x86_fp80 %f)
+
+; Don't crash while transforming a function with infinite recursion.
+define i32 @PR22704(i1 %bool) {
+entry:
+  br i1 %bool, label %t, label %f
+
+t:
+  %call1 = call i32 @PR22704(i1 1)
+  br label %return
+
+f:
+  %call = call i32 @PR22704(i1 1)
+  br label %return
+
+return:
+  ret i32 0
+
+; CHECK-LABEL: @PR22704(
+; CHECK:       %bool.tr = phi i1 [ %bool, %entry ], [ true, %t ], [ true, %f ]
+; CHECK:       br i1 %bool.tr, label %t, label %f
+}

Added: llvm/trunk/test/Transforms/TailCallElim/notail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/notail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/notail.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/notail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+
+; CHECK: tail call void @callee0()
+; CHECK: notail call void @callee1()
+
+define void @foo1(i32 %a) {
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:
+  call void @callee0()
+  br label %if.end
+
+if.else:
+  notail call void @callee1()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+declare void @callee0()
+declare void @callee1()

Added: llvm/trunk/test/Transforms/TailCallElim/opt-remarks-recursion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/opt-remarks-recursion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/opt-remarks-recursion.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/opt-remarks-recursion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt %s -tailcallelim -verify-dom-info -pass-remarks=tailcallelim -o /dev/null 2>&1 | FileCheck %s
+; RUN: opt %s -o /dev/null -passes='require<opt-remark-emit>,tailcallelim' -pass-remarks=tailcallelim 2>&1 | FileCheck %s
+
+; CHECK: /home/davide/pat.c:2:20: transforming tail recursion into loop
+define i32 @fib(i32 %n) nounwind ssp {
+entry:
+  %cmp = icmp slt i32 %n, 2
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %sub = add nsw i32 %n, -2
+  %call = call i32 @fib(i32 %sub)
+  %sub3 = add nsw i32 %n, -1
+  %call4 = call i32 @fib(i32 %sub3), !dbg !8
+  %add = add nsw i32 %call, %call4
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ 1, %if.then ], [ %add, %if.end ]
+  ret i32 %retval.0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "/home/davide/pat.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"PIC Level", i32 2}
+!5 = !{!"clang version 3.9.0 "}
+!6 = distinct !DISubprogram(name: "success", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!7 = !DISubroutineType(types: !2)
+!8 = !DILocation(line: 2, column: 20, scope: !6)

Added: llvm/trunk/test/Transforms/TailCallElim/reorder_load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/reorder_load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/reorder_load.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/reorder_load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,174 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+; PR4323
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Several cases where tail call elimination should move the load above the call,
+; then eliminate the tail recursion.
+
+
+
+ at global = external global i32		; <i32*> [#uses=1]
+ at extern_weak_global = extern_weak global i32		; <i32*> [#uses=1]
+
+
+; This load can be moved above the call because the function won't write to it
+; and the call has no side effects.
+define fastcc i32 @raise_load_1(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind readonly {
+; CHECK-LABEL: @raise_load_1(
+; CHECK-NOT: call
+; CHECK: load i32, i32*
+; CHECK-NOT: call
+; CHECK: }
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @raise_load_1(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+
+; This load can be moved above the call because the function won't write to it
+; and the load provably can't trap.
+define fastcc i32 @raise_load_2(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
+; CHECK-LABEL: @raise_load_2(
+; CHECK-NOT: call
+; CHECK: load i32, i32*
+; CHECK-NOT: call
+; CHECK: }
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 0
+
+else:		; preds = %entry
+	%nullcheck = icmp eq i32* %a_arg, null		; <i1> [#uses=1]
+	br i1 %nullcheck, label %unwind, label %recurse
+
+unwind:		; preds = %else
+	unreachable
+
+recurse:		; preds = %else
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @raise_load_2(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* @global		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+
+; This load can be safely moved above the call (even though it's from an
+; extern_weak global) because the call has no side effects.
+define fastcc i32 @raise_load_3(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind readonly {
+; CHECK-LABEL: @raise_load_3(
+; CHECK-NOT: call
+; CHECK: load i32, i32*
+; CHECK-NOT: call
+; CHECK: }
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @raise_load_3(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* @extern_weak_global		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+
+; The second load can be safely moved above the call even though it's from an
+; unknown pointer (which normally means it might trap) because the first load
+; proves it doesn't trap.
+define fastcc i32 @raise_load_4(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
+; CHECK-LABEL: @raise_load_4(
+; CHECK-NOT: call
+; CHECK: load i32, i32*
+; CHECK-NEXT: load i32, i32*
+; CHECK-NOT: call
+; CHECK: }
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 0
+
+else:		; preds = %entry
+	%nullcheck = icmp eq i32* %a_arg, null		; <i1> [#uses=1]
+	br i1 %nullcheck, label %unwind, label %recurse
+
+unwind:		; preds = %else
+	unreachable
+
+recurse:		; preds = %else
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%first = load i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @raise_load_4(i32* %a_arg, i32 %first, i32 %tmp7)		; <i32> [#uses=1]
+	%second = load i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp10 = add i32 %second, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+; This load can be moved above the call because the function won't write to it
+; and the a_arg is dereferenceable.
+define fastcc i32 @raise_load_5(i32* dereferenceable(4) %a_arg, i32 %a_len_arg, i32 %start_arg) readonly {
+; CHECK-LABEL: @raise_load_5(
+; CHECK-NOT: call
+; CHECK: load i32, i32*
+; CHECK-NOT: call
+; CHECK: }
+entry:
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+	ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @raise_load_5(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* %a_arg		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}
+
+; This load can be moved above the call because the function call does not write to the memory the load
+; is accessing and the load is safe to speculate.
+define fastcc i32 @raise_load_6(i32* %a_arg, i32 %a_len_arg, i32 %start_arg) nounwind  {
+; CHECK-LABEL: @raise_load_6(
+; CHECK-NOT: call
+; CHECK: load i32, i32*
+; CHECK-NOT: call
+; CHECK: }
+entry:
+  %s = alloca i32
+  store i32 4, i32* %s
+	%tmp2 = icmp sge i32 %start_arg, %a_len_arg		; <i1> [#uses=1]
+	br i1 %tmp2, label %if, label %else
+
+if:		; preds = %entry
+  store i32 1, i32* %a_arg
+	ret i32 0
+
+else:		; preds = %entry
+	%tmp7 = add i32 %start_arg, 1		; <i32> [#uses=1]
+	%tmp8 = call fastcc i32 @raise_load_6(i32* %a_arg, i32 %a_len_arg, i32 %tmp7)		; <i32> [#uses=1]
+	%tmp9 = load i32, i32* %s		; <i32> [#uses=1]
+	%tmp10 = add i32 %tmp9, %tmp8		; <i32> [#uses=1]
+	ret i32 %tmp10
+}

Added: llvm/trunk/test/Transforms/TailCallElim/setjmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/TailCallElim/setjmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/TailCallElim/setjmp.ll (added)
+++ llvm/trunk/test/Transforms/TailCallElim/setjmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s
+
+; Test that we don't tail call in a functions that calls returns_twice
+; functions.
+
+declare void @bar()
+
+; CHECK: foo1
+; CHECK-NOT: tail call void @bar()
+
+define void @foo1(i32* %x) {
+bb:
+  %tmp75 = tail call i32 @setjmp(i32* %x)
+  call void @bar()
+  ret void
+}
+
+declare i32 @setjmp(i32*) returns_twice
+
+; CHECK: foo2
+; CHECK-NOT: tail call void @bar()
+
+define void @foo2(i32* %x) {
+bb:
+  %tmp75 = tail call i32 @zed2(i32* %x)
+  call void @bar()
+  ret void
+}
+declare i32 @zed2(i32*) returns_twice

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/circular-reference.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/circular-reference.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/circular-reference.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/circular-reference.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
+; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
+
+; M0: @g = external constant
+; M1: @g = constant
+ at g = constant i8* bitcast (i8** @g to i8*), !type !0
+
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/comdat.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/comdat.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/comdat.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,80 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=THIN %s
+; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=MERGED %s
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+; Internal comdat leader with type metadata. All comdat members need to live
+; in the merged module, and the comdat needs to be renamed.
+; MERGED: ${{"?lwt[^ ]+}} = comdat any
+$lwt = comdat any
+
+; External comdat leader, type metadata on non-leader. All comdat
+; members need to live in the merged module, internal members need to
+; be renamed.
+; MERGED: $nlwt = comdat any
+$nlwt = comdat any
+
+; Comdat with two members without type metadata. All comdat members live in
+; the ThinLTO module and no renaming needs to take place.
+; THIN: $nt = comdat any
+$nt = comdat any
+
+; MERGED: @lwt_aliasee = private unnamed_addr global
+; MERGED-SAME: comdat(${{"?lwt[^ ]+}})
+ at lwt_aliasee = private unnamed_addr global [1 x i8*] [i8* null], comdat($lwt), !type !0
+
+; MERGED: {{@"?lwt_nl[^ ]+}} = hidden unnamed_addr global
+; MERGED-SAME: comdat(${{"?lwt[^ ]+}})
+; THIN: {{@"?lwt_nl[^ ]+}} = external hidden
+ at lwt_nl = internal unnamed_addr global i32 0, comdat($lwt)
+
+; MERGED: @nlwt_aliasee = private unnamed_addr global
+; MERGED-SAME: comdat($nlwt)
+ at nlwt_aliasee = private unnamed_addr global [1 x i8*] [i8* null], comdat($nlwt), !type !0
+
+; MERGED: @nlwt = unnamed_addr global
+; MERGED-SAME: comdat
+; THIN: @nlwt = external
+ at nlwt = unnamed_addr global i32 0, comdat
+
+; THIN: @nt = internal
+; THIN-SAME: comdat
+ at nt = internal unnamed_addr global [1 x i8*] [i8* null], comdat
+
+; THIN: @nt_nl = internal
+; THIN-SAME: comdat($nt)
+ at nt_nl = internal unnamed_addr global i32 0, comdat($nt)
+
+; MERGED: {{@"?lwt[^ ]+}} = hidden unnamed_addr alias
+; THIN: {{@"?lwt[^ ]+}} = external hidden
+ at lwt = internal unnamed_addr alias [1 x i8*], [1 x i8*]* @lwt_aliasee
+
+; MERGED: {{@"?nlwt_nl[^ ]+}} = hidden unnamed_addr alias
+; THIN: {{@"?nlwt_nl[^ ]+}} = external hidden
+ at nlwt_nl = internal unnamed_addr alias [1 x i8*], [1 x i8*]* @nlwt_aliasee
+
+; The functions below exist just to make sure the globals are used.
+define i8* @lwt_fun() {
+  %1 = load i32, i32* @lwt_nl
+  %2 = getelementptr inbounds [1 x i8*], [1 x i8*]* @lwt, i32 0, i32 %1
+  %3 = load i8*, i8** %2
+  ret i8* %3
+}
+
+define i8* @nlwt_fun() {
+  %1 = load i32, i32* @nlwt
+  %2 = getelementptr inbounds [1 x i8*], [1 x i8*]* @nlwt_nl, i32 0, i32 %1
+  %3 = load i8*, i8** %2
+  ret i8* %3
+}
+
+define i8* @nt_fun() {
+  %1 = load i32, i32* @nt_nl
+  %2 = getelementptr inbounds [1 x i8*], [1 x i8*]* @nt, i32 0, i32 %1
+  %3 = load i8*, i8** %2
+  ret i8* %3
+}
+
+!0 = !{i64 8, !"?AVA@@"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/filter-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/filter-alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/filter-alias.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/filter-alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=CHECK0 %s
+; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=CHECK1 %s
+; CHECK0-NOT: @{{.*}}anon{{.*}}=
+; CHECK0: @al = external global i8*
+; CHECK0-NOT: @{{.*}}anon{{.*}}=
+; CHECK1: @al = unnamed_addr alias i8*,
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+$al = comdat any
+
+ at anon = private unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* null] }, comdat($al), !type !0
+
+ at al = external unnamed_addr alias i8*, getelementptr inbounds ({ [1 x i8*] }, { [1 x i8*] }* @anon, i32 0, i32 0, i32 1)
+
+ at foo = global i32 1
+
+!0 = !{i64 8, !"?AVA@@"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/function-alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=CHECK1 %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define hidden void @Func() !type !0 {
+  ret void
+}
+
+; CHECK1: !aliases = !{![[A1:[0-9]+]], ![[A2:[0-9]+]], ![[A3:[0-9]+]]}
+
+; CHECK1: ![[A1]] = !{!"Alias", !"Func", i8 1, i8 0}
+; CHECK1: ![[A2]] = !{!"Hidden_Alias", !"Func", i8 1, i8 0}
+; CHECK1: ![[A3]] = !{!"Weak_Alias", !"Func", i8 0, i8 1}
+ at Alias = hidden alias void (), void ()* @Func
+ at Hidden_Alias = hidden alias void (), void ()* @Func
+ at Weak_Alias = weak alias void (), void ()* @Func
+
+ at Variable = global i32 0
+
+; Only generate summary alias information for aliases to functions
+; CHECK1-NOT: Variable_Alias
+ at Variable_Alias = alias i32, i32* @Variable
+
+!0 = !{i64 0, !"_ZTSFvvE"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/new-pm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/new-pm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/new-pm.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/new-pm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+; RUN: opt -passes='no-op-module' -debug-pass-manager -thinlto-bc -thin-link-bitcode-file=%t2 -o %t %s 2>&1 | FileCheck %s --check-prefix=DEBUG_PM
+; RUN: llvm-bcanalyzer -dump %t2 | FileCheck %s --check-prefix=BITCODE
+
+; DEBUG_PM: ThinLTOBitcodeWriterPass
+; BITCODE: Foo
+
+define void @Foo() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/no-type-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/no-type-md.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/no-type-md.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/no-type-md.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; Generate bitcode files with summary, as well as minimized bitcode without
+; the debug metadata for the thin link.
+; RUN: opt -thinlto-bc -thin-link-bitcode-file=%t.thinlink.bc -o %t.bc %s
+; RUN: llvm-dis -o - %t.bc | FileCheck %s
+; RUN: llvm-bcanalyzer -dump %t.bc | FileCheck --check-prefix=BCA %s
+
+; Make sure the combined index files produced by both the normal and the
+; thin link bitcode files are identical
+; RUN: llvm-lto -thinlto -o %t3 %t.bc
+; Copy the minimized bitcode to the regular bitcode path so the module
+; paths in the index are the same (save and restore the regular bitcode
+; for use again further down).
+; RUN: mv %t.bc %t.bc.sv
+; RUN: cp %t.thinlink.bc %t.bc
+; RUN: llvm-lto -thinlto -o %t4 %t.bc
+; RUN: mv %t.bc.sv %t.bc
+; RUN: diff %t3.thinlto.bc %t4.thinlto.bc
+
+; Try again using -thinlto-action to produce combined index
+; RUN: rm -f %t3.thinlto.bc %t4.thinlto.bc
+; RUN: llvm-lto -thinlto-action=thinlink -o %t3.thinlto.bc %t.bc
+; Copy the minimized bitcode to the regular bitcode path so the module
+; paths in the index are the same.
+; RUN: cp %t.thinlink.bc %t.bc
+; RUN: llvm-lto -thinlto-action=thinlink -o %t4.thinlto.bc %t.bc
+; RUN: diff %t3.thinlto.bc %t4.thinlto.bc
+
+; BCA: <GLOBALVAL_SUMMARY_BLOCK
+
+; CHECK: @g = global i8 42
+ at g = global i8 42
+
+; CHECK: define void @f()
+define void @f() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; Test for a bug specific to the new pass manager where we may build a domtree
+; to make more precise AA queries for functions.
+;
+; RUN: opt -aa-pipeline=default -passes='no-op-module' -debug-pass-manager -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
+; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.hoge = type { %struct.widget }
+%struct.widget = type { i32 (...)** }
+
+; M0: @global = local_unnamed_addr global
+; M1-NOT: @global
+ at global = local_unnamed_addr global %struct.hoge { %struct.widget { i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @global.1, i32 0, inrange i32 0, i32 2) to i32 (...)**) } }, align 8
+
+; M0: @global.1 = external unnamed_addr constant
+; M1: @global.1 = linkonce_odr unnamed_addr constant
+ at global.1 = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @global.4 to i8*), i8* bitcast (i32 (%struct.widget*)* @quux to i8*)] }, align 8, !type !0
+
+; M0: @global.2 = external global
+; M1-NOT: @global.2
+ at global.2 = external global i8*
+
+; M0: @global.3 = linkonce_odr constant
+; M1-NOT: @global.3
+ at global.3 = linkonce_odr constant [22 x i8] c"zzzzzzzzzzzzzzzzzzzzz\00"
+
+; M0: @global.4 = linkonce_odr constant
+; M1: @global.4 = external constant
+ at global.4 = linkonce_odr constant { i8*, i8* }{ i8* bitcast (i8** getelementptr inbounds (i8*, i8** @global.2, i64 2) to i8*), i8* getelementptr inbounds ([22 x i8], [22 x i8]* @global.3, i32 0, i32 0) }
+
+ at llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer
+
+declare i32 @quux(%struct.widget*) unnamed_addr
+
+!0 = !{i64 16, !"yyyyyyyyyyyyyyyyyyyyyyyyy"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal-typeid.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal-typeid.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal-typeid.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal-typeid.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o %t0 %t
+; RUN: llvm-modextract -b -n 1 -o %t1 %t
+; RUN: not llvm-modextract -b -n 2 -o - %t 2>&1 | FileCheck --check-prefix=ERROR %s
+; RUN: llvm-dis -o - %t0 | FileCheck --check-prefix=M0 %s
+; RUN: llvm-dis -o - %t1 | FileCheck --check-prefix=M1 %s
+; RUN: llvm-bcanalyzer -dump %t0 | FileCheck --check-prefix=BCA0 %s
+; RUN: llvm-bcanalyzer -dump %t1 | FileCheck --check-prefix=BCA1 %s
+
+; ERROR: llvm-modextract: error: module index out of range; bitcode file contains 2 module(s)
+
+; BCA0: <GLOBALVAL_SUMMARY_BLOCK
+; BCA1-NOT: <GLOBALVAL_SUMMARY_BLOCK
+
+; M0: @g = external global i8{{$}}
+; M1: @g = global i8 42, !type !0, !type !1, !type !2
+ at g = global i8 42, !type !1, !type !2, !type !4
+
+; M0: define void @f()
+; M1-NOT: @f()
+define void @f() {
+  ; M0: llvm.type.test{{.*}}metadata !"1$f50b51a12bb012bebbeff978335e34cf"
+  %p = call i1 @llvm.type.test(i8* null, metadata !0)
+  ; M0: llvm.type.checked.load{{.*}}metadata !"2$f50b51a12bb012bebbeff978335e34cf"
+  %q = call {i8*, i1} @llvm.type.checked.load(i8* null, i32 0, metadata !3)
+  ret void
+}
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata)
+
+!0 = distinct !{}
+; M1: !0 = !{i32 0, !"1$f50b51a12bb012bebbeff978335e34cf"}
+!1 = !{i32 0, !0}
+; M1: !1 = !{i32 1, !"1$f50b51a12bb012bebbeff978335e34cf"}
+!2 = !{i32 1, !0}
+
+!3 = distinct !{}
+; M1: !2 = !{i32 0, !"2$f50b51a12bb012bebbeff978335e34cf"}
+!4 = !{i32 0, !3}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o %t0 %t
+; RUN: llvm-modextract -b -n 1 -o %t1 %t
+; RUN: not llvm-modextract -b -n 2 -o - %t 2>&1 | FileCheck --check-prefix=ERROR %s
+; RUN: llvm-dis -o - %t0 | FileCheck --check-prefix=M0 %s
+; RUN: llvm-dis -o - %t1 | FileCheck --check-prefix=M1 %s
+; RUN: llvm-bcanalyzer -dump %t0 | FileCheck --check-prefix=BCA0 %s
+; RUN: llvm-bcanalyzer -dump %t1 | FileCheck --check-prefix=BCA1 %s
+
+; ERROR: llvm-modextract: error: module index out of range; bitcode file contains 2 module(s)
+
+; BCA0: <GLOBALVAL_SUMMARY_BLOCK
+; BCA1-NOT: <GLOBALVAL_SUMMARY_BLOCK
+
+; M0: @"g$581d7631532fa146ba4061179da39272" = external hidden global i8{{$}}
+; M1: @"g$581d7631532fa146ba4061179da39272" = hidden global i8 42, !type !0
+ at g = internal global i8 42, !type !0
+
+; M0: define i8* @f()
+; M1-NOT: @f()
+define i8* @f() {
+  ; M0: ret i8* @"g$581d7631532fa146ba4061179da39272"
+  ret i8* @g
+}
+
+; M1: !0 = !{i32 0, !"typeid"}
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o %t0 %t
+; RUN: llvm-modextract -b -n 1 -o %t1 %t
+; RUN: not llvm-modextract -b -n 2 -o - %t 2>&1 | FileCheck --check-prefix=ERROR %s
+; RUN: llvm-dis -o - %t0 | FileCheck --check-prefix=M0 %s
+; RUN: llvm-dis -o - %t1 | FileCheck --check-prefix=M1 %s
+; RUN: llvm-bcanalyzer -dump %t0 | FileCheck --check-prefix=BCA0 %s
+; RUN: llvm-bcanalyzer -dump %t1 | FileCheck --check-prefix=BCA1 %s
+
+; ERROR: llvm-modextract: error: module index out of range; bitcode file contains 2 module(s)
+
+; BCA0: <GLOBALVAL_SUMMARY_BLOCK
+; BCA1-NOT: <GLOBALVAL_SUMMARY_BLOCK
+
+; M0: @g = external global void ()*{{$}}
+; M1: @g = global void ()* @"f$13757e0fb71915e385efa4dc9d1e08fd", !type !0
+ at g = global void ()* @f, !type !0
+
+; M0: define hidden void @"f$13757e0fb71915e385efa4dc9d1e08fd"()
+; M1: declare hidden void @"f$13757e0fb71915e385efa4dc9d1e08fd"()
+define internal void @f() {
+  call void @f2()
+  ret void
+}
+
+; M0: define internal void @f2()
+define internal void @f2() {
+  ret void
+}
+
+; M1: !0 = !{i32 0, !"typeid"}
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc-internal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
+; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
+
+define [1 x i8*]* @source() {
+  ret [1 x i8*]* @g
+}
+
+; M0: @"g$84f59439b469192440047efc8de357fb" = external hidden constant [1 x i8*]{{$}}
+; M1: @"g$84f59439b469192440047efc8de357fb" = hidden constant [1 x i8*] [i8* bitcast (i64 (i8*)* @"ok$84f59439b469192440047efc8de357fb" to i8*)]
+ at g = internal constant [1 x i8*] [
+  i8* bitcast (i64 (i8*)* @ok to i8*)
+], !type !0
+
+; M0: define hidden i64 @"ok$84f59439b469192440047efc8de357fb"
+; M1: define available_externally hidden i64 @"ok$84f59439b469192440047efc8de357fb"
+define internal i64 @ok(i8* %this) {
+  ret i64 42
+}
+
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
+; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
+
+; M0: @g = external constant [9 x i8*]{{$}}
+; M1: @g = constant [9 x i8*]
+ at g = constant [9 x i8*] [
+  i8* bitcast (i64 (i8*)* @ok1 to i8*),
+  i8* bitcast (i64 (i8*, i64)* @ok2 to i8*),
+  i8* bitcast (void (i8*)* @wrongtype1 to i8*),
+  i8* bitcast (i128 (i8*)* @wrongtype2 to i8*),
+  i8* bitcast (i64 ()* @wrongtype3 to i8*),
+  i8* bitcast (i64 (i8*, i8*)* @wrongtype4 to i8*),
+  i8* bitcast (i64 (i8*, i128)* @wrongtype5 to i8*),
+  i8* bitcast (i64 (i8*)* @usesthis to i8*),
+  i8* bitcast (i8 (i8*)* @reads to i8*)
+], !type !0
+
+; M0: define i64 @ok1
+; M1: define available_externally i64 @ok1
+define i64 @ok1(i8* %this) {
+  ret i64 42
+}
+
+; M0: define i64 @ok2
+; M1: define available_externally i64 @ok2
+define i64 @ok2(i8* %this, i64 %arg) {
+  %1 = tail call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %arg, i64 %arg)
+  ret i64 %arg
+}
+
+; M1: declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64)
+declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64)
+
+; M0: define void @wrongtype1
+; M1: declare void @wrongtype1()
+define void @wrongtype1(i8*) {
+  ret void
+}
+
+; M0: define i128 @wrongtype2
+; M1: declare void @wrongtype2()
+define i128 @wrongtype2(i8*) {
+  ret i128 0
+}
+
+; M0: define i64 @wrongtype3
+; M1: declare void @wrongtype3()
+define i64 @wrongtype3() {
+  ret i64 0
+}
+
+; M0: define i64 @wrongtype4
+; M1: declare void @wrongtype4()
+define i64 @wrongtype4(i8*, i8*) {
+  ret i64 0
+}
+
+; M0: define i64 @wrongtype5
+; M1: declare void @wrongtype5()
+define i64 @wrongtype5(i8*, i128) {
+  ret i64 0
+}
+
+; M0: define i64 @usesthis
+; M1: declare void @usesthis()
+define i64 @usesthis(i8* %this) {
+  %i = ptrtoint i8* %this to i64
+  ret i64 %i
+}
+
+; M0: define i8 @reads
+; M1: declare void @reads()
+define i8 @reads(i8* %this) {
+  %l = load i8, i8* %this
+  ret i8 %l
+}
+
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/split.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; Generate bitcode files with summary, as well as minimized bitcode without
+; the debug metadata for the thin link.
+; RUN: opt -thinlto-bc -thin-link-bitcode-file=%t2 -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o %t0.bc %t
+; RUN: llvm-modextract -b -n 1 -o %t1.bc %t
+; RUN: llvm-modextract -b -n 0 -o %t0.thinlink.bc %t2
+; RUN: llvm-modextract -b -n 1 -o %t1.thinlink.bc %t2
+; RUN: not llvm-modextract -b -n 2 -o - %t 2>&1 | FileCheck --check-prefix=ERROR %s
+; RUN: llvm-dis -o - %t0.bc | FileCheck --check-prefix=M0 %s
+; RUN: llvm-dis -o - %t1.bc | FileCheck --check-prefix=M1 %s
+; RUN: llvm-bcanalyzer -dump %t0.bc | FileCheck --check-prefix=BCA0 %s
+; RUN: llvm-bcanalyzer -dump %t1.bc | FileCheck --check-prefix=BCA1 %s
+
+; Make sure the combined index files produced by both the normal and the
+; thin link bitcode files are identical
+; RUN: llvm-lto -thinlto -o %t3 %t0.bc
+; Copy the minimized bitcode to the regular bitcode path so the module
+; paths in the index are the same.
+; RUN: cp %t0.thinlink.bc %t0.bc
+; RUN: llvm-lto -thinlto -o %t4 %t0.bc
+; RUN: diff %t3.thinlto.bc %t4.thinlto.bc
+
+; ERROR: llvm-modextract: error: module index out of range; bitcode file contains 2 module(s)
+
+; BCA0: <GLOBALVAL_SUMMARY_BLOCK
+; BCA1: <FULL_LTO_GLOBALVAL_SUMMARY_BLOCK
+; 16 = not eligible to import
+; BCA1: <PERMODULE_GLOBALVAR_INIT_REFS {{.*}} op1=16
+; BCA1-NOT: <GLOBALVAL_SUMMARY_BLOCK
+
+$g = comdat any
+
+; M0: @g = external global i8{{$}}
+; M1: @g = global i8 42, comdat, !type !0
+ at g = global i8 42, comdat, !type !0
+
+; M0: define i8* @f()
+; M1-NOT: @f()
+define i8* @f() {
+  ret i8* @g
+}
+
+; M1: !0 = !{i32 0, !"typeid"}
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck %s
+
+; The target assembly parser is required to parse the symver directives
+; REQUIRES: x86-registered-target
+
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".symver used, used at VER"
+module asm ".symver unused, unused at VER"
+module asm ".symver variable, variable at VER"
+
+declare !type !0 void @used()
+declare !type !0 void @unused()
+ at variable = global i32 0
+
+define i32* @use() {
+  call void @used()
+  ret i32* @variable
+}
+
+; CHECK: !symvers = !{![[SYMVER:[0-9]+]]}
+; CHECK: ![[SYMVER]] = !{!"used", !"used at VER"}
+
+!0 = !{i64 0, !"_ZTSFvvE"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt -thinlto-bc -thin-link-bitcode-file=%t2 -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-dis -o - %t | FileCheck %s
+; RUN: llvm-bcanalyzer -dump %t | FileCheck --check-prefix=BCA %s
+; When not splitting the module, the thin link bitcode file should simply be a
+; copy of the regular module.
+; RUN: diff %t %t2
+
+; BCA: <FULL_LTO_GLOBALVAL_SUMMARY_BLOCK
+; BCA-NOT: <GLOBALVAL_SUMMARY_BLOCK
+
+; CHECK: @llvm.global_ctors = appending global
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }]
+
+; CHECK: @g = internal global i8 42, !type !0
+ at g = internal global i8 42, !type !0
+
+declare void @sink(i8*)
+
+; CHECK: define internal void @f()
+define internal void @f() {
+  call void @sink(i8* @g)
+  ret void
+}
+
+$h = comdat any
+; CHECK: define void @h() comdat
+define void @h() comdat {
+  ret void
+}
+
+; CHECK: !llvm.module.flags = !{![[FLAG1:[0-9]+]], ![[FLAG2:[0-9]+]]}
+; CHECK: ![[FLAG1]] = !{i32 1, !"EnableSplitLTOUnit", i32 1}
+; CHECK: ![[FLAG2]] = !{i32 1, !"ThinLTO", i32 0}
+
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/x86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/x86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/x86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/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/ThinLTOBitcodeWriter/x86/module-asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/x86/module-asm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/x86/module-asm.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/x86/module-asm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
+; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
+; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at g = constant i32 0, !type !0
+!0 = !{i32 0, !"typeid"}
+
+; M0: module asm "ret"
+; M1-NOT: module asm
+module asm "ret"

Added: llvm/trunk/test/Transforms/Util/PR37334-break-crit-edges-require-dt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PR37334-break-crit-edges-require-dt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PR37334-break-crit-edges-require-dt.ll (added)
+++ llvm/trunk/test/Transforms/Util/PR37334-break-crit-edges-require-dt.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 -loop-sink -break-crit-edges -branch-prob -S | FileCheck %s
+; RUN: opt < %s -loop-sink -break-crit-edges -lazy-block-freq -S | FileCheck %s
+; RUN: opt < %s -loop-sink -break-crit-edges -lazy-branch-prob -S | FileCheck %s
+
+; BreakCriticalEdges tries to update LI and DT if they are present. However,
+; updating LI actually needs a DT, so we now require DT in
+; BranchProbabilityInfo/LazyBlockFrequencyInfo/LazyBranchProbabilityInfo so it
+; is indeed available when LI is.
+
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f1() {
+; CHECK-LABEL: @f1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    br i1 false, label [[FOR_BODY:%.*]], label [[FOR_COND_FOR_END_CRIT_EDGE:%.*]]
+; CHECK:       for.cond.for.end_crit_edge:
+; CHECK-NEXT:    br label [[FOR_END:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    br i1 true, label [[FOR_ENDSPLIT:%.*]], label [[FOR_INC:%.*]]
+; CHECK:       for.inc:
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       for.endsplit:
+; CHECK-NEXT:    br label [[FOR_END]]
+; CHECK:       for.end:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  br i1 undef, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br i1 undef, label %for.end, label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  br label %for.cond
+
+for.end:                                          ; preds = %for.body, %for.cond
+  ret void
+}

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/condprop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/condprop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/condprop.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/condprop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,471 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze  < %s 2>&1 | FileCheck %s
+
+ at a = external global i32		; <i32*> [#uses=7]
+
+define i32 @test1() nounwind {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB:%.*]], label [[BB1:%.*]]
+; CHECK:       bb:
+; CHECK-NEXT:    br label [[BB8:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 5
+; CHECK-NEXT:    br i1 [[TMP3]], label [[BB2:%.*]], label [[BB3:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br label [[BB8]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP4:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 4
+; CHECK-NEXT:    br i1 [[TMP5]], label [[BB4:%.*]], label [[BB5:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP7:%.*]] = add i32 [[TMP6]], 5
+; CHECK-NEXT:    br label [[BB8]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 5
+; CHECK-NEXT:    br i1 [[TMP9]], label [[BB6:%.*]], label [[BB7:%.*]]
+; CHECK:       bb6:
+; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP11:%.*]] = add i32 [[TMP10]], 4
+; CHECK-NEXT:    br label [[BB8]]
+; CHECK:       bb7:
+; CHECK-NEXT:    [[TMP12:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    br label [[BB8]]
+; CHECK:       bb8:
+; CHECK-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP12]], [[BB7]] ], [ [[TMP11]], [[BB6]] ], [ [[TMP7]], [[BB4]] ], [ 4, [[BB2]] ], [ 5, [[BB]] ]
+; CHECK-NEXT:    br label [[RETURN:%.*]]
+; CHECK:       return:
+; CHECK-NEXT:    ret i32 [[DOT0]]
+;
+entry:
+  %0 = load i32, i32* @a, align 4
+  %1 = icmp eq i32 %0, 4
+  br i1 %1, label %bb, label %bb1
+
+bb:		; preds = %entry
+  br label %bb8
+
+bb1:		; preds = %entry
+  %2 = load i32, i32* @a, align 4
+  %3 = icmp eq i32 %2, 5
+  br i1 %3, label %bb2, label %bb3
+
+bb2:		; preds = %bb1
+  br label %bb8
+
+bb3:		; preds = %bb1
+  %4 = load i32, i32* @a, align 4
+  %5 = icmp eq i32 %4, 4
+  br i1 %5, label %bb4, label %bb5
+
+bb4:		; preds = %bb3
+  %6 = load i32, i32* @a, align 4
+  %7 = add i32 %6, 5
+  br label %bb8
+
+bb5:		; preds = %bb3
+  %8 = load i32, i32* @a, align 4
+  %9 = icmp eq i32 %8, 5
+  br i1 %9, label %bb6, label %bb7
+
+bb6:		; preds = %bb5
+  %10 = load i32, i32* @a, align 4
+  %11 = add i32 %10, 4
+  br label %bb8
+
+bb7:		; preds = %bb5
+  %12 = load i32, i32* @a, align 4
+  br label %bb8
+
+bb8:		; preds = %bb7, %bb6, %bb4, %bb2, %bb
+  %.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ]
+  br label %return
+
+return:		; preds = %bb8
+  ret i32 %.0
+}
+
+declare void @foo(i1)
+declare void @bar(i32)
+
+define void @test3(i32 %x, i32 %y) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT:    [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
+; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
+; CHECK:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK-NEXT:    br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
+; CHECK:       both_zero:
+; CHECK-NEXT:    call void @foo(i1 [[XZ_0]])
+; CHECK-NEXT:    call void @foo(i1 [[YZ_0]])
+; CHECK-NEXT:    call void @bar(i32 [[X_0]])
+; CHECK-NEXT:    call void @bar(i32 [[Y_0]])
+; CHECK-NEXT:    ret void
+; CHECK:       nope:
+; CHECK-NEXT:    call void @foo(i1 [[Z_0]])
+; CHECK-NEXT:    ret void
+;
+  %xz = icmp eq i32 %x, 0
+  %yz = icmp eq i32 %y, 0
+  %z = and i1 %xz, %yz
+  br i1 %z, label %both_zero, label %nope
+both_zero:
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  ret void
+nope:
+  call void @foo(i1 %z)
+  ret void
+}
+
+define void @test4(i1 %b, i32 %x) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]]
+; CHECK:       sw:
+; CHECK:         i32 0, label [[CASE0:%.*]]
+; CHECK-NEXT:    i32 1, label [[CASE1:%.*]]
+; CHECK-NEXT:    i32 2, label [[CASE0]]
+; CHECK-NEXT:    i32 3, label [[CASE3]]
+; CHECK-NEXT:    i32 4, label [[DEFAULT:%.*]]
+; CHECK-NEXT:    ] Edge: [label [[SW]],label %case1] }
+; CHECK-NEXT:    [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X:%.*]])
+; CHECK-NEXT:    switch i32 [[X]], label [[DEFAULT]] [
+; CHECK-NEXT:    i32 0, label [[CASE0]]
+; CHECK-NEXT:    i32 1, label [[CASE1]]
+; CHECK-NEXT:    i32 2, label [[CASE0]]
+; CHECK-NEXT:    i32 3, label [[CASE3]]
+; CHECK-NEXT:    i32 4, label [[DEFAULT]]
+; CHECK-NEXT:    ]
+; CHECK:       default:
+; CHECK-NEXT:    call void @bar(i32 [[X]])
+; CHECK-NEXT:    ret void
+; CHECK:       case0:
+; CHECK-NEXT:    call void @bar(i32 [[X]])
+; CHECK-NEXT:    ret void
+; CHECK:       case1:
+; CHECK-NEXT:    call void @bar(i32 [[X_0]])
+; CHECK-NEXT:    ret void
+; CHECK:       case3:
+; CHECK-NEXT:    call void @bar(i32 [[X]])
+; CHECK-NEXT:    ret void
+;
+  br i1 %b, label %sw, label %case3
+sw:
+  switch i32 %x, label %default [
+  i32 0, label %case0
+  i32 1, label %case1
+  i32 2, label %case0
+  i32 3, label %case3
+  i32 4, label %default
+  ]
+default:
+  call void @bar(i32 %x)
+  ret void
+case0:
+  call void @bar(i32 %x)
+  ret void
+case1:
+  call void @bar(i32 %x)
+  ret void
+case3:
+  call void @bar(i32 %x)
+  ret void
+}
+
+define i1 @test5(i32 %x, i32 %y) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[X_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK:         [[Y_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[X_0]], [[Y_0]]
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[X_1]], [[Y_1]]
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp = icmp eq i32 %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  %cmp2 = icmp ne i32 %x, %y
+  ret i1 %cmp2
+
+different:
+  %cmp3 = icmp eq i32 %x, %y
+  ret i1 %cmp3
+}
+
+define i1 @test6(i32 %x, i32 %y) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp2 = icmp ne i32 %x, %y
+  %cmp = icmp eq i32 %x, %y
+  %cmp3 = icmp eq i32 %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  ret i1 %cmp2
+
+different:
+  ret i1 %cmp3
+}
+
+define i1 @test6_fp(float %x, float %y) {
+; CHECK-LABEL: @test6_fp(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp une float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP3:%.*]] = fcmp oeq float [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp2 = fcmp une float %x, %y
+  %cmp = fcmp oeq float %x, %y
+  %cmp3 = fcmp oeq float  %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  ret i1 %cmp2
+
+different:
+  ret i1 %cmp3
+}
+
+define i1 @test7(i32 %x, i32 %y) {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[X_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK:         [[Y_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[X_0]], [[Y_0]]
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[X_1]], [[Y_1]]
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  %cmp2 = icmp sle i32 %x, %y
+  ret i1 %cmp2
+
+different:
+  %cmp3 = icmp sgt i32 %x, %y
+  ret i1 %cmp3
+}
+
+define i1 @test7_fp(float %x, float %y) {
+; CHECK-LABEL: @test7_fp(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
+; CHECK:         [[X_0:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[X]])
+; CHECK:         [[X_1:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[X]])
+; CHECK:         [[Y_0:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[Y]])
+; CHECK:         [[Y_1:%.*]] = call float @llvm.ssa.copy.{{.+}}(float [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ule float [[X_0]], [[Y_0]]
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    [[CMP3:%.*]] = fcmp ogt float [[X_1]], [[Y_1]]
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp = fcmp ogt float %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  %cmp2 = fcmp ule float %x, %y
+  ret i1 %cmp2
+
+different:
+  %cmp3 = fcmp ogt float %x, %y
+  ret i1 %cmp3
+}
+
+define i1 @test8(i32 %x, i32 %y) {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp2 = icmp sle i32 %x, %y
+  %cmp = icmp sgt i32 %x, %y
+  %cmp3 = icmp sgt i32 %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  ret i1 %cmp2
+
+different:
+  ret i1 %cmp3
+}
+
+define i1 @test8_fp(float %x, float %y) {
+; CHECK-LABEL: @test8_fp(
+; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X]], [[Y]]
+; CHECK-NEXT:    [[CMP3:%.*]] = fcmp ogt float [[X]], [[Y]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
+; CHECK:       same:
+; CHECK-NEXT:    ret i1 [[CMP2]]
+; CHECK:       different:
+; CHECK-NEXT:    ret i1 [[CMP3]]
+;
+  %cmp2 = fcmp ule float %x, %y
+  %cmp = fcmp ogt float %x, %y
+  %cmp3 = fcmp ogt float %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  ret i1 %cmp2
+
+different:
+  ret i1 %cmp3
+}
+
+define i32 @test9(i32 %i, i32 %j) {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
+; CHECK:         [[I_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[I]])
+; CHECK:         [[J_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[J]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
+; CHECK:       cond_true:
+; CHECK-NEXT:    [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
+; CHECK-NEXT:    ret i32 [[DIFF]]
+; CHECK:       ret:
+; CHECK-NEXT:    ret i32 5
+;
+  %cmp = icmp eq i32 %i, %j
+  br i1 %cmp, label %cond_true, label %ret
+
+cond_true:
+  %diff = sub i32 %i, %j
+  ret i32 %diff
+
+ret:
+  ret i32 5
+}
+
+define i32 @test10(i32 %j, i32 %i) {
+; CHECK-LABEL: @test10(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
+; CHECK:         [[J_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[J]])
+; CHECK:         [[I_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[I]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
+; CHECK:       cond_true:
+; CHECK-NEXT:    [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
+; CHECK-NEXT:    ret i32 [[DIFF]]
+; CHECK:       ret:
+; CHECK-NEXT:    ret i32 5
+;
+  %cmp = icmp eq i32 %i, %j
+  br i1 %cmp, label %cond_true, label %ret
+
+cond_true:
+  %diff = sub i32 %i, %j
+  ret i32 %diff
+
+ret:
+  ret i32 5
+}
+
+declare i32 @yogibar()
+
+define i32 @test11(i32 %x) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT:    [[V0:%.*]] = call i32 @yogibar()
+; CHECK-NEXT:    [[V1:%.*]] = call i32 @yogibar()
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]]
+; CHECK:         [[V0_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[V0]])
+; CHECK:         [[V1_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[V1]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]]
+; CHECK:       cond_true:
+; CHECK-NEXT:    ret i32 [[V1_0]]
+; CHECK:       next:
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0_0]]
+; CHECK:         [[V0_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[V0_0]])
+; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]]
+; CHECK:       cond_true2:
+; CHECK-NEXT:    ret i32 [[V0_0_1]]
+; CHECK:       next2:
+; CHECK-NEXT:    ret i32 0
+;
+  %v0 = call i32 @yogibar()
+  %v1 = call i32 @yogibar()
+  %cmp = icmp eq i32 %v0, %v1
+  br i1 %cmp, label %cond_true, label %next
+
+cond_true:
+  ret i32 %v1
+
+next:
+  %cmp2 = icmp eq i32 %x, %v0
+  br i1 %cmp2, label %cond_true2, label %next2
+
+cond_true2:
+  ret i32 %v0
+
+next2:
+  ret i32 0
+}
+
+define i32 @test12(i32 %x) {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[X_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
+; CHECK:       cond_true:
+; CHECK-NEXT:    br label [[RET:%.*]]
+; CHECK:       cond_false:
+; CHECK-NEXT:    br label [[RET]]
+; CHECK:       ret:
+; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ [[X_0]], [[COND_TRUE]] ], [ [[X_1]], [[COND_FALSE]] ]
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %cmp = icmp eq i32 %x, 0
+  br i1 %cmp, label %cond_true, label %cond_false
+
+cond_true:
+  br label %ret
+
+cond_false:
+  br label %ret
+
+ret:
+  %res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ]
+  ret i32 %res
+}

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/diamond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/diamond.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/diamond.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/diamond.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 -print-predicateinfo < %s 2>&1 | FileCheck %s
+define i1 @f(i32 %x, i1 %y) {
+; CHECK-LABEL: @f(
+; CHECK-NEXT:    br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[X2:%.*]] = add nuw nsw i32 [[X]], 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
+; CHECK:         [[X2_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X2]])
+; CHECK-NEXT:    br i1 [[CMP2]], label [[BB2]], label [[BB3]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i1 false
+;
+  br i1 %y, label %bb0, label %bb1
+  bb0:
+  %cmp = icmp sge i32 %x, 0  ; x > 0
+  br i1 %cmp, label %bb2, label %bb3
+  bb1:
+  %x2 = add nsw nuw i32 %x, 1
+  %cmp2 = icmp sge i32 %x2, 2     ; x+1 > 2 / x > 1
+  br i1 %cmp2, label %bb2, label %bb3
+  bb2:
+  %x3 = phi i32 [ %x, %bb0 ], [ %x2, %bb1 ]
+  br label %bb3
+  bb3:
+  ret i1 0
+}
+
+define i1 @g(i32 %x, i1 %y) {
+; CHECK-LABEL: @g(
+; CHECK-NEXT:    br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
+; CHECK:       bb0:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[BB3:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    [[X2:%.*]] = add nuw nsw i32 [[X]], 1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
+; CHECK:         [[X2_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X2]])
+; CHECK-NEXT:    br i1 [[CMP2]], label [[BB3]], label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb3:
+; CHECK-NEXT:    ret i1 false
+;
+  br i1 %y, label %bb0, label %bb1
+  bb0:
+  %cmp = icmp sge i32 %x, 0  ; x > 0
+  br i1 %cmp, label %bb3, label %bb2
+  bb1:
+  %x2 = add nsw nuw i32 %x, 1
+  %cmp2 = icmp sge i32 %x2, 2     ; x+1 > 2 / x > 1
+  br i1 %cmp2, label %bb3, label %bb2
+  bb2:
+  %x3 = phi i32 [ %x, %bb0 ], [ %x2, %bb1 ]
+  br label %bb3
+  bb3:
+  ret i1 0
+}
+

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/edge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/edge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/edge.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/edge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,242 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze  < %s 2>&1 | FileCheck %s
+
+define i32 @f1(i32 %x) {
+; CHECK-LABEL: @f1(
+; CHECK-NEXT:  bb0:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT:    [[FOO:%.*]] = add i32 [[COND]], [[X]]
+; CHECK-NEXT:    ret i32 [[FOO]]
+;
+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
+}
+
+define i32 @f2(i32 %x) {
+; CHECK-LABEL: @f2(
+; CHECK-NEXT:  bb0:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT:    [[FOO:%.*]] = add i32 [[COND]], [[X]]
+; CHECK-NEXT:    ret i32 [[FOO]]
+;
+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
+}
+
+define i32 @f3(i32 %x) {
+; CHECK-LABEL: @f3(
+; CHECK-NEXT:  bb0:
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X:%.*]])
+; CHECK-NEXT:    switch i32 [[X]], label [[BB1:%.*]] [
+; CHECK-NEXT:    i32 0, label [[BB2:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       bb1:
+; CHECK-NEXT:    br label [[BB2]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
+; CHECK-NEXT:    [[FOO:%.*]] = add i32 [[COND]], [[X]]
+; CHECK-NEXT:    ret i32 [[FOO]]
+;
+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
+}
+
+
+define double @fcmp_oeq_not_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_oeq_not_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], 2.000000e+00
+; CHECK:         [[Y_0:%.*]] = call double @llvm.ssa.copy.{{.+}}(double [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret double [[RETVAL]]
+;
+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
+
+}
+
+define double @fcmp_une_not_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_une_not_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[Y:%.*]], 2.000000e+00
+; CHECK:         [[Y_0:%.*]] = call double @llvm.ssa.copy.{{.+}}(double [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret double [[RETVAL]]
+;
+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
+
+}
+
+define double @fcmp_oeq_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_oeq_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], 0.000000e+00
+; CHECK:         [[Y_0:%.*]] = call double @llvm.ssa.copy.{{.+}}(double [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret double [[RETVAL]]
+;
+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
+
+}
+
+define double @fcmp_une_zero(double %x, double %y) {
+; CHECK-LABEL: @fcmp_une_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[Y:%.*]], -0.000000e+00
+; CHECK:         [[Y_0:%.*]] = call double @llvm.ssa.copy.{{.+}}(double [[Y]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret double [[RETVAL]]
+;
+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
+
+}
+
+
+define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
+; CHECK-LABEL: @fcmp_oeq_maybe_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[Z:%.*]] = fadd double [[Z1:%.*]], [[Z2:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], [[Z]]
+; CHECK:         [[Z_0:%.*]] = call double @llvm.ssa.copy.{{.+}}(double [[Z]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X:%.*]], [[Z_0]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret double [[RETVAL]]
+;
+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
+
+}
+
+define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
+; CHECK-LABEL: @fcmp_une_maybe_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[Z:%.*]] = fadd double [[Z1:%.*]], [[Z2:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[Y:%.*]], [[Z]]
+; CHECK:         [[Z_0:%.*]] = call double @llvm.ssa.copy.{{.+}}(double [[Z]])
+; CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK:       else:
+; CHECK-NEXT:    [[DIV:%.*]] = fdiv double [[X:%.*]], [[Z_0]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret double [[RETVAL]]
+;
+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
+
+}

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/ordering.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/ordering.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/ordering.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/ordering.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; REQUIRES: assert
+; RUN: opt -print-predicateinfo -analyze -debug < %s 2>&1 | FileCheck %s
+
+declare void @use(i32)
+
+; Make sure we are visiting the values to build predicate infos for in a
+; deterministic order.
+define i32 @test12(i32 %x, i32 %y) {
+; CHECK: Visiting i32 %x
+; CHECK: Visiting i32 %y
+; CHECK: Visiting   %lcmp = icmp eq i32 %x, 0
+; CHECK: Visiting   %lcmp2 = icmp slt i32 %y, 1000
+; CHECK: Visiting   %lcmp3 = icmp slt i32 %y.0, 900
+; CHECK: Visiting   %lcmp4 = icmp slt i32 %y.0.1, 700
+; CHECK: Visiting   %lcmp5 = icmp slt i32 %y.0.1.2, 700
+; CHECK: Visiting   %lcmp6 = icmp slt i32 %y.0.1.2.3, 700
+; CHECK: Visiting   %lcmp7 = icmp slt i32 %y.0.1.2.3.4, 700
+; CHECK: Visiting   %rcmp = icmp eq i32 %x, 0
+entry:
+  br i1 undef, label %left, label %right
+
+left:
+  %lcmp = icmp eq i32 %x, 0
+  br i1 %lcmp, label %left_cond_true, label %left_cond_false
+
+left_cond_true:
+  %lcmp2 = icmp slt i32 %y, 1000
+  br i1 %lcmp2, label %left_cond_true2, label %left_ret
+
+left_cond_true2:
+  call void @use(i32 %y)
+  %lcmp3 = icmp slt i32 %y, 900
+  br i1 %lcmp3, label %left_cond_true3, label %left_ret
+
+left_cond_true3:
+  call void @use(i32 %y)
+  %lcmp4 = icmp slt i32 %y, 700
+  br i1 %lcmp4, label %left_cond_true4, label %left_ret
+
+left_cond_true4:
+  call void @use(i32 %y)
+  %lcmp5 = icmp slt i32 %y, 700
+  br i1 %lcmp5, label %left_cond_true5, label %left_ret
+
+left_cond_true5:
+  call void @use(i32 %y)
+  %lcmp6 = icmp slt i32 %y, 700
+  br i1 %lcmp6, label %left_cond_true6, label %left_ret
+
+left_cond_true6:
+  call void @use(i32 %y)
+  %lcmp7 = icmp slt i32 %y, 700
+  br i1 %lcmp7, label %left_cond_true7, label %left_ret
+
+left_cond_true7:
+  ret i32 %y
+
+left_cond_false:
+  br label %left_ret
+
+left_ret:
+  %lres = phi i32 [ %x, %left_cond_true ], [ %x, %left_cond_false ], [ %x, %left_cond_true2 ], [ %x, %left_cond_true3 ], [ %x, %left_cond_true4 ], [ %x, %left_cond_true5 ], [ %x, %left_cond_true6 ]
+
+  ret i32 %lres
+
+right:
+  %rcmp = icmp eq i32 %x, 0
+  br i1 %rcmp, label %right_cond_true, label %right_cond_false
+
+right_cond_true:
+  br label %right_ret
+
+right_cond_false:
+  br label %right_ret
+
+right_ret:
+  %rres = phi i32 [ %x, %right_cond_true ], [ %x, %right_cond_false ]
+  ret i32 %rres
+}

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/pr33456.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/pr33456.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/pr33456.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/pr33456.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 -print-predicateinfo -analyze  < %s 2>&1 | FileCheck %s
+; Don't insert predicate info for conditions with a single target.
+ at a = global i32 1, align 4
+ at d = common global i32 0, align 4
+ at c = common global i32 0, align 4
+ at b = common global i32 0, align 4
+ at e = common global i32 0, align 4
+
+define i32 @main() {
+; CHECK-LABEL: @main(
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @d, align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP13:%.*]]
+; CHECK:         [[TMP4:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* @c, align 4
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 1
+; CHECK-NEXT:    br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP9:%.*]]
+; CHECK:         [[TMP8:%.*]] = icmp eq i32 [[TMP4]], 0
+; CHECK-NEXT:    br i1 [[TMP8]], label [[TMP9]], label [[TMP9]]
+; CHECK:         [[DOT0:%.*]] = phi i32 [ [[TMP4]], [[TMP7]] ], [ [[TMP4]], [[TMP7]] ], [ [[DOT1:%.*]], [[TMP13]] ], [ [[TMP4]], [[TMP3]] ]
+; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* @b, align 4
+; CHECK-NEXT:    [[TMP11:%.*]] = sdiv i32 [[TMP10]], [[DOT0]]
+; CHECK-NEXT:    [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 0
+; CHECK-NEXT:    br i1 [[TMP12]], label [[TMP13]], label [[TMP13]]
+; CHECK:         [[DOT1]] = phi i32 [ [[DOT0]], [[TMP9]] ], [ [[DOT0]], [[TMP9]] ], [ undef, [[TMP0:%.*]] ]
+; CHECK-NEXT:    [[TMP14:%.*]] = load i32, i32* @e, align 4
+; CHECK-NEXT:    [[TMP15:%.*]] = icmp eq i32 [[TMP14]], 0
+; CHECK-NEXT:    br i1 [[TMP15]], label [[TMP16:%.*]], label [[TMP9]]
+; CHECK:         ret i32 0
+;
+  %1 = load i32, i32* @d, align 4
+  %2 = icmp eq i32 %1, 0
+  br i1 %2, label %3, label %13
+
+; <label>:3:                                      ; preds = %0
+  %4 = load i32, i32* @a, align 4
+  %5 = load i32, i32* @c, align 4
+  %6 = icmp slt i32 %5, 1
+  br i1 %6, label %7, label %9
+
+; <label>:7:                                      ; preds = %3
+  %8 = icmp eq i32 %4, 0
+  br i1 %8, label %9, label %9
+
+; <label>:9:                                      ; preds = %13, %7, %7, %3
+  %.0 = phi i32 [ %4, %7 ], [ %4, %7 ], [ %.1, %13 ], [ %4, %3 ]
+  %10 = load i32, i32* @b, align 4
+  %11 = sdiv i32 %10, %.0
+  %12 = icmp eq i32 %11, 0
+  br i1 %12, label %13, label %13
+
+; <label>:13:                                     ; preds = %9, %9, %0
+  %.1 = phi i32 [ %.0, %9 ], [ %.0, %9 ], [ undef, %0 ]
+  %14 = load i32, i32* @e, align 4
+  %15 = icmp eq i32 %14, 0
+  br i1 %15, label %16, label %9
+
+; <label>:16:                                     ; preds = %13
+  ret i32 0
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/pr33457.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/pr33457.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/pr33457.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/pr33457.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,93 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze  < %s 2>&1 | FileCheck %s
+; Don't insert predicate info for conditions with a single target.
+ at a = global i32 6, align 4
+ at c = global i32 -1, align 4
+ at e = common global i32 0, align 4
+ at .str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+ at d = common global i32 0, align 4
+ at b = common global [6 x i32] zeroinitializer, align 16
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @main() {
+; CHECK-LABEL: @main(
+; CHECK-NEXT:    store i32 6, i32* @e, align 4
+; CHECK-NEXT:    br label [[TMP1:%.*]]
+; CHECK:         [[TMP2:%.*]] = load i32, i32* @d, align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = sext i32 [[TMP2]] to i64
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @b, i64 0, i64 [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP4]], align 4
+; CHECK-NEXT:    [[TMP6:%.*]] = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 [[TMP5]])
+; CHECK-NEXT:    [[TMP7:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT:    br i1 [[TMP8]], label %thread-pre-split, label [[TMP9:%.*]]
+; CHECK:         [[TMP10:%.*]] = load i32, i32* @e, align 4
+; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT:    br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP12]]
+; CHECK:       thread-pre-split:
+; CHECK-NEXT:    [[DOTPR:%.*]] = load i32, i32* @e, align 4
+; CHECK-NEXT:    br label [[TMP12]]
+; CHECK:         [[TMP13:%.*]] = phi i32 [ [[DOTPR]], %thread-pre-split ], [ [[TMP10]], [[TMP9]] ], [ [[TMP10]], [[TMP9]] ]
+; CHECK-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; CHECK-NEXT:    br i1 [[TMP14]], label [[TMP15:%.*]], label [[TMP15]]
+; CHECK:         br i1 [[TMP14]], label [[TMP16:%.*]], label [[TMP17:%.*]]
+; CHECK:         br label [[TMP17]]
+; CHECK:         [[DOT0:%.*]] = phi i32 [ 1, [[TMP16]] ], [ -1, [[TMP15]] ]
+; CHECK-NEXT:    [[TMP18:%.*]] = and i32 [[DOT0]], 8693
+; CHECK-NEXT:    [[TMP19:%.*]] = load i32, i32* @c, align 4
+; CHECK-NEXT:    [[TMP20:%.*]] = xor i32 [[TMP18]], [[TMP19]]
+; CHECK-NEXT:    [[TMP21:%.*]] = xor i32 [[TMP20]], -1
+; CHECK-NEXT:    store i32 [[TMP21]], i32* @d, align 4
+; CHECK-NEXT:    [[TMP22:%.*]] = icmp slt i32 [[TMP20]], -2
+; CHECK-NEXT:    br i1 [[TMP22]], label [[TMP1]], label [[TMP23:%.*]]
+; CHECK:         ret i32 0
+;
+  store i32 6, i32* @e, align 4
+  br label %1
+
+; <label>:1:                                      ; preds = %17, %0
+  %2 = load i32, i32* @d, align 4
+  %3 = sext i32 %2 to i64
+  %4 = getelementptr inbounds [6 x i32], [6 x i32]* @b, i64 0, i64 %3
+  %5 = load i32, i32* %4, align 4
+  %6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %5) #2
+  %7 = load i32, i32* @a, align 4
+  %8 = icmp eq i32 %7, 0
+  br i1 %8, label %thread-pre-split, label %9
+
+; <label>:9:                                      ; preds = %1
+  %10 = load i32, i32* @e, align 4
+  %11 = icmp eq i32 %10, 0
+  br i1 %11, label %12, label %12
+
+thread-pre-split:                                 ; preds = %1
+  %.pr = load i32, i32* @e, align 4
+  br label %12
+
+; <label>:12:                                     ; preds = %thread-pre-split, %9, %9
+  %13 = phi i32 [ %.pr, %thread-pre-split ], [ %10, %9 ], [ %10, %9 ]
+  %14 = icmp ne i32 %13, 0
+  br i1 %14, label %15, label %15
+
+; <label>:15:                                     ; preds = %12, %12
+  br i1 %14, label %16, label %17
+
+; <label>:16:                                     ; preds = %15
+  br label %17
+
+; <label>:17:                                     ; preds = %16, %15
+  %.0 = phi i32 [ 1, %16 ], [ -1, %15 ]
+  %18 = and i32 %.0, 8693
+  %19 = load i32, i32* @c, align 4
+  %20 = xor i32 %18, %19
+  %21 = xor i32 %20, -1
+  store i32 %21, i32* @d, align 4
+  %22 = icmp slt i32 %20, -2
+  br i1 %22, label %1, label %23
+
+; <label>:23:                                     ; preds = %17
+  ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/testandor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/testandor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/testandor.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/testandor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,211 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
+
+declare void @foo(i1)
+declare void @bar(i32)
+declare void @llvm.assume(i1)
+
+define void @testor(i32 %x, i32 %y) {
+; CHECK-LABEL: @testor(
+; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT:    [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
+; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
+; CHECK:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK-NEXT:    br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
+; CHECK:       oneof:
+; CHECK-NEXT:    call void @foo(i1 [[XZ]])
+; CHECK-NEXT:    call void @foo(i1 [[YZ]])
+; CHECK-NEXT:    call void @bar(i32 [[X]])
+; CHECK-NEXT:    call void @bar(i32 [[Y]])
+; CHECK-NEXT:    ret void
+; CHECK:       neither:
+; CHECK-NEXT:    call void @foo(i1 [[XZ_0]])
+; CHECK-NEXT:    call void @foo(i1 [[YZ_0]])
+; CHECK-NEXT:    call void @bar(i32 [[X_0]])
+; CHECK-NEXT:    call void @bar(i32 [[Y_0]])
+; CHECK-NEXT:    call void @foo(i1 [[Z_0]])
+; CHECK-NEXT:    ret void
+;
+  %xz = icmp eq i32 %x, 0
+  %yz = icmp eq i32 %y, 0
+  %z = or i1 %xz, %yz
+  br i1 %z, label %oneof, label %neither
+oneof:
+;; Should not insert on the true edge for or
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  ret void
+neither:
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  call void @foo(i1 %z)
+  ret void
+}
+define void @testand(i32 %x, i32 %y) {
+; CHECK-LABEL: @testand(
+; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT:    [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[Y_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK:         [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
+; CHECK:         [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
+; CHECK:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK-NEXT:    br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK:       both:
+; CHECK-NEXT:    call void @foo(i1 [[XZ_0]])
+; CHECK-NEXT:    call void @foo(i1 [[YZ_0]])
+; CHECK-NEXT:    call void @bar(i32 [[X_0]])
+; CHECK-NEXT:    call void @bar(i32 [[Y_0]])
+; CHECK-NEXT:    ret void
+; CHECK:       nope:
+; CHECK-NEXT:    call void @foo(i1 [[XZ]])
+; CHECK-NEXT:    call void @foo(i1 [[YZ]])
+; CHECK-NEXT:    call void @bar(i32 [[X]])
+; CHECK-NEXT:    call void @bar(i32 [[Y]])
+; CHECK-NEXT:    call void @foo(i1 [[Z_0]])
+; CHECK-NEXT:    ret void
+;
+  %xz = icmp eq i32 %x, 0
+  %yz = icmp eq i32 %y, 0
+  %z = and i1 %xz, %yz
+  br i1 %z, label %both, label %nope
+both:
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  ret void
+nope:
+;; Should not insert on the false edge for and
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  call void @foo(i1 %z)
+  ret void
+}
+define void @testandsame(i32 %x, i32 %y) {
+; CHECK-LABEL: @testandsame(
+; CHECK-NEXT:    [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[XLT:%.*]] = icmp slt i32 [[X]], 100
+; CHECK-NEXT:    [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
+; CHECK:         [[X_0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X_0]])
+; CHECK:         [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XGT]])
+; CHECK:         [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XLT]])
+; CHECK:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK-NEXT:    br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK:       both:
+; CHECK-NEXT:    call void @foo(i1 [[XGT_0]])
+; CHECK-NEXT:    call void @foo(i1 [[XLT_0]])
+; CHECK-NEXT:    call void @bar(i32 [[X_0_1]])
+; CHECK-NEXT:    ret void
+; CHECK:       nope:
+; CHECK-NEXT:    call void @foo(i1 [[XGT]])
+; CHECK-NEXT:    call void @foo(i1 [[XLT]])
+; CHECK-NEXT:    call void @foo(i1 [[Z_0]])
+; CHECK-NEXT:    ret void
+;
+  %xgt = icmp sgt i32 %x, 0
+  %xlt = icmp slt i32 %x, 100
+  %z = and i1 %xgt, %xlt
+  br i1 %z, label %both, label %nope
+both:
+  call void @foo(i1 %xgt)
+  call void @foo(i1 %xlt)
+  call void @bar(i32 %x)
+  ret void
+nope:
+  call void @foo(i1 %xgt)
+  call void @foo(i1 %xlt)
+  call void @foo(i1 %z)
+  ret void
+}
+
+define void @testandassume(i32 %x, i32 %y) {
+; CHECK-LABEL: @testandassume(
+; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT:    [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
+; CHECK:         [[TMP1:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]])
+; CHECK:         [[TMP2:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]])
+; CHECK:         [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]])
+; CHECK:         [[TMP4:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]])
+; CHECK:         [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP5]])
+; CHECK:         [[DOT0:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP1]])
+; CHECK:         [[DOT01:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP2]])
+; CHECK:         [[DOT02:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP3]])
+; CHECK:         [[DOT03:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP4]])
+; CHECK:         [[DOT04:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]])
+; CHECK-NEXT:    br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK:       both:
+; CHECK-NEXT:    call void @foo(i1 [[DOT02]])
+; CHECK-NEXT:    call void @foo(i1 [[DOT03]])
+; CHECK-NEXT:    call void @bar(i32 [[DOT0]])
+; CHECK-NEXT:    call void @bar(i32 [[DOT01]])
+; CHECK-NEXT:    ret void
+; CHECK:       nope:
+; CHECK-NEXT:    call void @foo(i1 [[DOT04]])
+; CHECK-NEXT:    ret void
+;
+  %xz = icmp eq i32 %x, 0
+  %yz = icmp eq i32 %y, 0
+  %z = and i1 %xz, %yz
+  call void @llvm.assume(i1 %z)
+  br i1 %z, label %both, label %nope
+both:
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  ret void
+nope:
+  call void @foo(i1 %z)
+  ret void
+}
+
+;; Unlike and/or for branches, assume is *always* true, so we only match and for it
+define void @testorassume(i32 %x, i32 %y) {
+;
+; CHECK-LABEL: @testorassume(
+; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT:    [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[Z]])
+; CHECK:         [[Z_0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]])
+; CHECK-NEXT:    br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
+; CHECK:       both:
+; CHECK-NEXT:    call void @foo(i1 [[XZ]])
+; CHECK-NEXT:    call void @foo(i1 [[YZ]])
+; CHECK-NEXT:    call void @bar(i32 [[X]])
+; CHECK-NEXT:    call void @bar(i32 [[Y]])
+; CHECK-NEXT:    ret void
+; CHECK:       nope:
+; CHECK-NEXT:    call void @foo(i1 [[Z_0]])
+; CHECK-NEXT:    ret void
+;
+  %xz = icmp eq i32 %x, 0
+  %yz = icmp eq i32 %y, 0
+  %z = or i1 %xz, %yz
+  call void @llvm.assume(i1 %z)
+  br i1 %z, label %both, label %nope
+both:
+  call void @foo(i1 %xz)
+  call void @foo(i1 %yz)
+  call void @bar(i32 %x)
+  call void @bar(i32 %y)
+  ret void
+nope:
+  call void @foo(i1 %z)
+  ret void
+}

Added: llvm/trunk/test/Transforms/Util/PredicateInfo/unnamed-types.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/PredicateInfo/unnamed-types.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/PredicateInfo/unnamed-types.ll (added)
+++ llvm/trunk/test/Transforms/Util/PredicateInfo/unnamed-types.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -print-predicateinfo 2>&1 | FileCheck %s
+
+%1 = type opaque
+%0 = type opaque
+
+; Check we can use ssa.copy with unnamed types.
+
+; CHECK-LABEL: bb:
+; CHECK: Has predicate info
+; CHECK: branch predicate info { TrueEdge: 1 Comparison:  %cmp1 = icmp ne %0* %arg, null Edge: [label %bb,label %bb1] }
+; CHECK-NEXT:  %arg.0 = call %0* @llvm.ssa.copy.{{.+}}(%0* %arg)
+
+; CHECK-LABEL: bb1:
+; CHECK: Has predicate info
+; CHECK-NEXT: branch predicate info { TrueEdge: 0 Comparison:  %cmp2 = icmp ne %1* null, %tmp Edge: [label %bb1,label %bb3] }
+; CHECK-NEXT: %tmp.0 = call %1* @llvm.ssa.copy.{{.+}}(%1* %tmp)
+
+define void @f0(%0* %arg, %1* %tmp) {
+bb:
+  %cmp1 = icmp ne %0* %arg, null
+  br i1 %cmp1, label %bb1, label %bb2
+
+bb1:                                              ; preds = %bb
+  %cmp2 = icmp ne %1* null, %tmp
+  br i1 %cmp2, label %bb2, label %bb3
+
+bb2:                                              ; preds = %bb
+  ret void
+
+bb3:                                              ; preds = %bb
+  %u1 = call i8* @fun(%1* %tmp)
+  %tmp2 = bitcast %0* %arg to i8*
+  ret void
+}
+
+declare i8* @fun(%1*)

Added: llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast-attribute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast-attribute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast-attribute.ll (added)
+++ llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast-attribute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -S -pgo-icall-prom -icp-total-percent-threshold=0 < %s 2>&1 | FileCheck %s
+
+; Test that CallPromotionUtils will promote calls which require pointer cast
+; safely, i.e. drop incompatible attributes.
+
+ at foo = common global i8* (i8*)* null, align 8
+
+; casting to i64 and pointer attribute at callsite dropped.
+define i64 @func2(i64 %a) {
+  ret i64 undef
+}
+
+; no casting needed, attribute at callsite preserved.
+define i8* @func4(i8* %a) {
+  ret i8* undef
+}
+
+define i8* @bar(i8* %arg) {
+  %tmp = load i8* (i8*)*, i8* (i8*)** @foo, align 8
+
+; Make sure callsite attributes are preserved on arguments and retval.
+; CHECK: call noalias i8* @func4(i8* nonnull
+
+; Make sure callsite attributes are dropped on arguments and retval.
+; CHECK: [[ARG:%[0-9]+]] = ptrtoint i8* %arg to i64
+; CHECK-NEXT: call i64 @func2(i64 [[ARG]])
+
+  %call = call noalias i8* %tmp(i8* nonnull %arg), !prof !1
+  ret i8* %call
+}
+
+!1 = !{!"VP", i32 0, i64 1440, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410}

Added: llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast.ll (added)
+++ llvm/trunk/test/Transforms/Util/call-promotion-utils-ptrcast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -S -pgo-icall-prom -icp-total-percent-threshold=0 -icp-max-prom=4 < %s 2>&1 | FileCheck %s
+
+; Test that CallPromotionUtils will promote calls which require pointer casts.
+
+ at foo = common global i64 (i64)* null, align 8
+
+; Check ptrcast arguments.
+define i64 @func1(i8* %a) {
+  ret i64 undef
+}
+
+; Check ptrcast return.
+define i8* @func2(i64 %a) {
+  ret i8* undef
+}
+
+; Check ptrcast arguments and return.
+define i8* @func3(i8 *%a) {
+  ret i8* undef
+}
+
+; Check mixed ptrcast and bitcast.
+define i8* @func4(double %f) {
+  ret i8* undef
+}
+
+define i64 @bar() {
+  %tmp = load i64 (i64)*, i64 (i64)** @foo, align 8
+
+; CHECK: [[ARG:%[0-9]+]] = bitcast i64 1 to double
+; CHECK-NEXT: [[RET:%[0-9]+]] = call i8* @func4(double [[ARG]])
+; CHECK-NEXT: ptrtoint i8* [[RET]] to i64
+
+; CHECK: [[RET:%[0-9]+]] = call i8* @func2(i64 1)
+; CHECK-NEXT: ptrtoint i8* [[RET]] to i64
+
+; CHECK: [[ARG:%[0-9]+]] = inttoptr i64 1 to i8*
+; CHECK-NEXT: [[RET:%[0-9]+]] = call i8* @func3(i8* [[ARG]])
+; CHECK-NEXT: ptrtoint i8* [[RET]] to i64
+
+; CHECK: [[ARG:%[0-9]+]] = inttoptr i64 1 to i8*
+; CHECK-NEXT: call i64 @func1(i8* [[ARG]])
+; CHECK-NOT: ptrtoint
+; CHECK-NOT: bitcast
+
+  %call = call i64 %tmp(i64 1), !prof !1
+  ret i64 %call
+}
+
+!1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410, i64 -6929281286627296573, i64 150, i64 -2545542355363006406, i64 10}

Added: llvm/trunk/test/Transforms/Util/clone-dicompileunit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/clone-dicompileunit.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/clone-dicompileunit.ll (added)
+++ llvm/trunk/test/Transforms/Util/clone-dicompileunit.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,66 @@
+; RUN: opt -run-twice -verify -disable-debug-info-type-map -S -o - %s | FileCheck %s
+
+; Generated using:
+; $ cat p.cpp
+; void sink(void *);
+; class A {
+; public:
+;   template <typename> void m_fn2() { static int a; }
+;   virtual void m_fn1();
+; };
+; void foo() {
+;   class B : public A {
+;   public:
+;     B() { m_fn2<B>(); }
+;   };
+;   sink(new B);
+; }
+; $ clang++ -target x86_64-unknown-linux -fvisibility=hidden -O2 -g2 -flto -S p.cpp -o p.ll
+; # then manually removed function/gv definitions
+
+; Test that when the module is cloned it does not contain a reference to
+; the original DICompileUnit as a result of a collision between the cloned
+; DISubprogram for m_fn2<B> (which refers to the non-ODR entity B via
+; template parameters) and the original DISubprogram.
+
+; CHECK: DICompileUnit
+; CHECK-NOT: DICompileUnit
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux"
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!28, !29}
+!llvm.ident = !{!30}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
+!1 = !DIFile(filename: "p.cpp", directory: "/usr/local/google/home/pcc/b682773-2-repro/small2")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "a", scope: !6, file: !1, line: 5, type: !27, isLocal: true, isDefinition: true)
+!6 = distinct !DISubprogram(name: "m_fn2<B>", linkageName: "_ZN1A5m_fn2IZ3foovE1BEEvv", scope: !7, file: !1, line: 5, type: !8, isLocal: true, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !11, declaration: !23, retainedNodes: !24)
+!7 = !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !1, line: 3, flags: DIFlagFwdDecl, identifier: "_ZTS1A")
+!8 = !DISubroutineType(types: !9)
+!9 = !{null, !10}
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!11 = !{!12}
+!12 = !DITemplateTypeParameter(type: !13)
+!13 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B", scope: !14, file: !1, line: 10, size: 64, elements: !17, vtableHolder: !7)
+!14 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 9, type: !15, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null}
+!17 = !{!18, !19}
+!18 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !13, baseType: !7, flags: DIFlagPublic)
+!19 = !DISubprogram(name: "B", scope: !13, file: !1, line: 12, type: !20, isLocal: false, isDefinition: false, scopeLine: 12, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true)
+!20 = !DISubroutineType(types: !21)
+!21 = !{null, !22}
+!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!23 = !DISubprogram(name: "m_fn2<B>", linkageName: "_ZN1A5m_fn2IZ3foovE1BEEvv", scope: !7, file: !1, line: 5, type: !8, isLocal: false, isDefinition: false, scopeLine: 5, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true, templateParams: !11)
+!24 = !{!25}
+!25 = !DILocalVariable(name: "this", arg: 1, scope: !6, type: !26, flags: DIFlagArtificial | DIFlagObjectPointer)
+!26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!28 = !{i32 2, !"Dwarf Version", i32 4}
+!29 = !{i32 2, !"Debug Info Version", i32 3}
+!30 = !{!"clang version 5.0.0 "}

Added: llvm/trunk/test/Transforms/Util/combine-alias-scope-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/combine-alias-scope-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/combine-alias-scope-metadata.ll (added)
+++ llvm/trunk/test/Transforms/Util/combine-alias-scope-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -S -basicaa -memcpyopt | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @test(i8* noalias dereferenceable(1) %in, i8* noalias dereferenceable(1) %out) {
+  %tmp = alloca i8
+  %tmp2 = alloca i8
+; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %out, i8* align 8 %in, i64 1, i1 false)
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %tmp, i8* align 8 %in, i64 1, i1 false), !alias.scope !4
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %tmp2, i8* align 8 %tmp, i64 1, i1 false), !alias.scope !5
+
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %out, i8* align 8 %tmp2, i64 1, i1 false), !noalias !6
+
+  ret void
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)
+
+!0 = !{!0}
+!1 = distinct !{!1, !0, !"in"}
+!2 = distinct !{!2, !0, !"tmp"}
+!3 = distinct !{!3, !0, !"tmp2"}
+!4 = distinct !{!1, !2}
+!5 = distinct !{!2, !3}
+!6 = distinct !{!1, !2}

Added: llvm/trunk/test/Transforms/Util/dbg-user-of-aext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/dbg-user-of-aext.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/dbg-user-of-aext.ll (added)
+++ llvm/trunk/test/Transforms/Util/dbg-user-of-aext.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; Checks that llvm.dbg.declare -> llvm.dbg.value conversion utility
+; (here exposed through the SROA) pass refers to [s|z]exts of values (as
+; opposed to the operand of a [s|z]ext).
+; RUN: opt -S -sroa %s | FileCheck %s
+
+; Built from:
+; struct foo { bool b; long i; };
+; void f(bool b, bool expr, foo g) {
+; }
+; And modifying the frag dbg.declare to use a fragmented DIExpression (with offset: 0, size: 4)
+; to test the dbg.declare+fragment case here.
+
+; Expect two fragments:
+; * first starting at bit 0, 8 bits (for the bool)
+; * second starting at bit 32, 32 bits (for the long)
+; (this happens to create/demonstrate a gap from bits [7, 32))
+
+; But also check that a complex expression is not used for a lone bool
+; parameter. It can reference the register it's in directly without masking off
+; high bits or anything
+
+; CHECK: call void @llvm.dbg.value(metadata i8 %g.coerce0, metadata ![[VAR_STRUCT:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 8))
+; CHECK: call void @llvm.dbg.value(metadata i64 %g.coerce1, metadata ![[VAR_STRUCT]], metadata !DIExpression(DW_OP_LLVM_fragment, 32, 64))
+; CHECK: call void @llvm.dbg.value(metadata i8 %frombool, metadata ![[VAR_BOOL:[0-9]+]], metadata !DIExpression())
+; CHECK: call void @llvm.dbg.value(metadata i8 %frombool1, metadata ![[VAR_FRAG:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 4))
+
+%struct.foo = type { i8, i64 }
+
+; Function Attrs: noinline nounwind uwtable
+define void @_Z1fbb3foo(i1 zeroext %b, i1 zeroext %frag, i8 %g.coerce0, i64 %g.coerce1) #0 !dbg !6 {
+entry:
+  %g = alloca %struct.foo, align 8
+  %b.addr = alloca i8, align 1
+  %frag.addr = alloca i8, align 1
+  %0 = bitcast %struct.foo* %g to { i8, i64 }*
+  %1 = getelementptr inbounds { i8, i64 }, { i8, i64 }* %0, i32 0, i32 0
+  store i8 %g.coerce0, i8* %1, align 8
+  %2 = getelementptr inbounds { i8, i64 }, { i8, i64 }* %0, i32 0, i32 1
+  store i64 %g.coerce1, i64* %2, align 8
+  %frombool = zext i1 %b to i8
+  store i8 %frombool, i8* %b.addr, align 1
+  call void @llvm.dbg.declare(metadata i8* %b.addr, metadata !15, metadata !16), !dbg !17
+  %frombool1 = sext i1 %frag to i8
+  store i8 %frombool1, i8* %frag.addr, align 1
+  call void @llvm.dbg.declare(metadata i8* %frag.addr, metadata !18, metadata !23), !dbg !19
+  call void @llvm.dbg.declare(metadata %struct.foo* %g, metadata !20, metadata !16), !dbg !21
+  ret void, !dbg !22
+}
+
+; CHECK: ![[VAR_STRUCT]] = !DILocalVariable(name: "g"
+; CHECK: ![[VAR_BOOL]] = !DILocalVariable(name: "b"
+; CHECK: ![[VAR_FRAG]] = !DILocalVariable(name: "frag"
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { noinline nounwind 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"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 303077) (llvm/trunk 303098)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "foo.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang version 5.0.0 (trunk 303077) (llvm/trunk 303098)"}
+!6 = distinct !DISubprogram(name: "f", linkageName: "_Z1fbb3foo", 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: !8)
+!8 = !{null, !9, !9, !10}
+!9 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 1, size: 128, elements: !11, identifier: "_ZTS3foo")
+!11 = !{!12, !13}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !1, line: 1, baseType: !9, size: 8)
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 1, baseType: !14, size: 64, offset: 64)
+!14 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
+!15 = !DILocalVariable(name: "b", arg: 1, scope: !6, file: !1, line: 2, type: !9)
+!16 = !DIExpression()
+!17 = !DILocation(line: 2, column: 13, scope: !6)
+!18 = !DILocalVariable(name: "frag", arg: 2, scope: !6, file: !1, line: 2, type: !9)
+!19 = !DILocation(line: 2, column: 21, scope: !6)
+!20 = !DILocalVariable(name: "g", arg: 3, scope: !6, file: !1, line: 2, type: !10)
+!21 = !DILocation(line: 2, column: 31, scope: !6)
+!22 = !DILocation(line: 3, column: 1, scope: !6)
+!23 = !DIExpression(DW_OP_LLVM_fragment, 0, 4)

Added: llvm/trunk/test/Transforms/Util/flattencfg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/flattencfg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/flattencfg.ll (added)
+++ llvm/trunk/test/Transforms/Util/flattencfg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -flattencfg -S < %s | FileCheck %s
+
+
+; This test checks whether the pass completes without a crash.
+; The code is not transformed in any way
+;
+; CHECK-LABEL: @test_not_crash
+define void @test_not_crash(i32 %in_a) #0 {
+entry:
+  %cmp0 = icmp eq i32 %in_a, -1
+  %cmp1 = icmp ne i32 %in_a, 0
+  %cond0 = and i1 %cmp0, %cmp1
+  br i1 %cond0, label %b0, label %b1
+
+b0:                                ; preds = %entry
+  %cmp2 = icmp eq i32 %in_a, 0
+  %cmp3 = icmp ne i32 %in_a, 1
+  %cond1 = or i1 %cmp2, %cmp3
+  br i1 %cond1, label %exit, label %b1
+
+b1:                                       ; preds = %entry, %b0
+  br label %exit
+
+exit:                               ; preds = %entry, %b0, %b1
+  ret void
+}

Added: llvm/trunk/test/Transforms/Util/libcalls-fast-math-inf-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/libcalls-fast-math-inf-loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/libcalls-fast-math-inf-loop.ll (added)
+++ llvm/trunk/test/Transforms/Util/libcalls-fast-math-inf-loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt -S -instcombine -o - %s | FileCheck %s
+
+; Test that fast math lib call simplification of double math function to float
+; equivalent doesn't occur when the calling function matches the float
+; equivalent math function. Otherwise this can cause the generation of infinite
+; loops when compiled with -O2/3 and fast math.
+
+; Test case C source:
+;
+;   extern double exp(double x);
+;   inline float expf(float x) { return (float) exp((double) x); }
+;   float fn(float f) { return expf(f); }
+;
+; IR generated with command:
+;
+;   clang -cc1 -O2 -ffast-math -emit-llvm -disable-llvm-passes -triple x86_64-unknown-unknown -o - <srcfile>
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-unknown"
+
+; Function Attrs: nounwind
+define float @fn(float %f) #0 {
+; CHECK: define float @fn(
+; CHECK: call fast float @expf(
+  %f.addr = alloca float, align 4
+  store float %f, float* %f.addr, align 4, !tbaa !1
+  %1 = load float, float* %f.addr, align 4, !tbaa !1
+  %call = call fast float @expf(float %1) #3
+  ret float %call
+}
+
+; Function Attrs: inlinehint nounwind readnone
+define available_externally float @expf(float %x) #1 {
+; CHECK: define available_externally float @expf(
+; CHECK: fpext float
+; CHECK: call fast double @exp(
+; CHECK: fptrunc double
+  %x.addr = alloca float, align 4
+  store float %x, float* %x.addr, align 4, !tbaa !1
+  %1 = load float, float* %x.addr, align 4, !tbaa !1
+  %conv = fpext float %1 to double
+  %call = call fast double @exp(double %conv) #3
+  %conv1 = fptrunc double %call to float
+  ret float %conv1
+}
+
+; Function Attrs: nounwind readnone
+declare double @exp(double) #2
+
+attributes #0 = { nounwind "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-features"="+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { inlinehint 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-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readnone }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 5.0.0"}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"float", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}

Added: llvm/trunk/test/Transforms/Util/libcalls-opt-remarks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/libcalls-opt-remarks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/libcalls-opt-remarks.ll (added)
+++ llvm/trunk/test/Transforms/Util/libcalls-opt-remarks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,57 @@
+; RUN: opt < %s -instcombine -o /dev/null  -pass-remarks-output=%t -S \
+; RUN:     -pass-remarks=instcombine 2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+; RUN: opt < %s -passes='require<opt-remark-emit>,instcombine' -o /dev/null \
+; RUN:     -pass-remarks-output=%t -S -pass-remarks=instcombine 2>&1 | FileCheck %s
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+
+; CHECK:      remark: libcalls-opt-remarks.c:10:10: folded strlen(select) to select of constants{{$}}
+; CHECK-NOT:  remark:
+
+; YAML:      --- !Passed
+; YAML-NEXT: Pass:            instcombine
+; YAML-NEXT: Name:            simplify-libcalls
+; YAML-NEXT: DebugLoc:        { File: libcalls-opt-remarks.c, Line: 10, Column: 10 }
+; YAML-NEXT: Function:        f1
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'folded strlen(select) to select of constants'
+; YAML-NEXT: ...
+
+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"
+
+declare i32 @strlen(i8*)
+
+ at hello = constant [6 x i8] c"hello\00"
+ at longer = constant [7 x i8] c"longer\00"
+
+define i32 @f1(i1) !dbg !7 {
+  %hello = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0, !dbg !10
+  %longer = getelementptr [7 x i8], [7 x i8]* @longer, i32 0, i32 0, !dbg !12
+  %2 = select i1 %0, i8* %hello, i8* %longer, !dbg !9
+  %3 = call i32 @strlen(i8* %2), !dbg !14
+  ret i32 %3, !dbg !16
+}
+
+
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Apple LLVM version 8.1.0 (clang-802.0.42)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "libcalls-opt-remarks.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 = !{!"Apple LLVM version 8.1.0 (clang-802.0.42)"}
+!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 9, type: !8, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 10, column: 17, scope: !7)
+!10 = !DILocation(line: 10, column: 24, scope: !11)
+!11 = !DILexicalBlockFile(scope: !7, file: !1, discriminator: 1)
+!12 = !DILocation(line: 10, column: 32, scope: !13)
+!13 = !DILexicalBlockFile(scope: !7, file: !1, discriminator: 2)
+!14 = !DILocation(line: 10, column: 10, scope: !15)
+!15 = !DILexicalBlockFile(scope: !7, file: !1, discriminator: 3)
+!16 = !DILocation(line: 10, column: 3, scope: !15)

Added: llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-double.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-double.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-double.ll (added)
+++ llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-double.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,241 @@
+; RUN: opt < %s -libcalls-shrinkwrap -S | FileCheck %s
+; New PM
+; RUN: opt < %s -passes=libcalls-shrinkwrap -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 @test_range_error(double %value) {
+entry:
+  %call_0 = call double @cosh(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt double %value, -7.100000e+02
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt double %value, 7.100000e+02
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT:[0-9]+]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_0 = call double @cosh(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_1 = call double @exp(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt double %value, -7.450000e+02
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt double %value, 7.090000e+02
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_1 = call double @exp(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_3 = call double @exp2(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt double %value, -1.074000e+03
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt double %value, 1.023000e+03
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_3 = call double @exp2(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_4 = call double @sinh(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt double %value, -7.100000e+02
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt double %value, 7.100000e+02
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_4 = call double @sinh(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_5 = call double @expm1(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ogt double %value, 7.090000e+02
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_5 = call double @expm1(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  ret void
+}
+
+declare double @cosh(double)
+declare double @exp(double)
+declare double @exp2(double)
+declare double @sinh(double)
+declare double @expm1(double)
+
+define void @test_domain_error(double %value) {
+entry:
+  %call_00 = call double @acos(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt double %value, 1.000000e+00
+; CHECK: [[COND2:%[0-9]+]] = fcmp olt double %value, -1.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_00 = call double @acos(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_01 = call double @asin(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt double %value, 1.000000e+00
+; CHECK: [[COND2:%[0-9]+]] = fcmp olt double %value, -1.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_01 = call double @asin(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_02 = call double @cos(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oeq double %value, 0xFFF0000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp oeq double %value, 0x7FF0000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_02 = call double @cos(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_03 = call double @sin(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oeq double %value, 0xFFF0000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp oeq double %value, 0x7FF0000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_03 = call double @sin(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_04 = call double @acosh(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp olt double %value, 1.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_04 = call double @acosh(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_05 = call double @sqrt(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp olt double %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_05 = call double @sqrt(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_06 = call double @atanh(double %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oge double %value, 1.000000e+00
+; CHECK: [[COND2:%[0-9]+]] = fcmp ole double %value, -1.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_06 = call double @atanh(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_07 = call double @log(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole double %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_07 = call double @log(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_08 = call double @log10(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole double %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_08 = call double @log10(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_09 = call double @log2(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole double %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_09 = call double @log2(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_10 = call double @logb(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole double %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_10 = call double @logb(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_11 = call double @log1p(double %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole double %value, -1.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_11 = call double @log1p(double %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  ret void
+}
+
+declare double @acos(double)
+declare double @asin(double)
+declare double @cos(double)
+declare double @sin(double)
+declare double @acosh(double)
+declare double @sqrt(double)
+declare double @atanh(double)
+declare double @log(double)
+declare double @log10(double)
+declare double @log2(double)
+declare double @logb(double)
+declare double @log1p(double)
+
+define void @test_pow(i32 %int_val, double %exp) {
+  %call = call double @pow(double 2.500000e+00, double %exp)
+; CHECK: [[COND:%[0-9]+]] = fcmp ogt double %exp, 1.270000e+02
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call = call double @pow(double 2.500000e+00, double %exp)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %conv = sitofp i32 %int_val to double
+  %call1 = call double @pow(double %conv, double %exp)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt double %exp, 3.200000e+01
+; CHECK: [[COND2:%[0-9]+]] = fcmp ole double %conv, 0.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call1 = call double @pow(double %conv, double %exp)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %conv2 = trunc i32 %int_val to i8
+  %conv3 = uitofp i8 %conv2 to double
+  %call4 = call double @pow(double %conv3, double %exp)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt double %exp, 1.280000e+02
+; CHECK: [[COND2:%[0-9]+]] = fcmp ole double %conv3, 0.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call4 = call double @pow(double %conv3, double %exp)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+
+  %conv5 = trunc i32 %int_val to i16
+  %conv6 = uitofp i16 %conv5 to double
+  %call7 = call double @pow(double %conv6, double %exp)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt double %exp, 6.400000e+01
+; CHECK: [[COND2:%[0-9]+]] = fcmp ole double %conv6, 0.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call7 = call double @pow(double %conv6, double %exp)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  ret void
+}
+
+declare double @pow(double, double)
+
+; CHECK: ![[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1, i32 2000}

Added: llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-float.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-float.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-float.ll (added)
+++ llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-float.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,191 @@
+; RUN: opt < %s -libcalls-shrinkwrap -S | FileCheck %s
+; New PM
+; RUN: opt < %s -passes=libcalls-shrinkwrap -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 @test_range_error(float %value) {
+entry:
+  %call_0 = call float @coshf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt float %value, -8.900000e+01
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt float %value, 8.900000e+01
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT:[0-9]+]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_0 = call float @coshf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_1 = call float @expf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt float %value, -1.030000e+02
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt float %value, 8.800000e+01
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_1 = call float @expf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_3 = call float @exp2f(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt float %value, -1.490000e+02
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt float %value, 1.270000e+02
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_3 = call float @exp2f(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_4 = call float @sinhf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt float %value, -8.900000e+01
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt float %value, 8.900000e+01
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_4 = call float @sinhf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_5 = call float @expm1f(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ogt float %value, 8.800000e+01
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_5 = call float @expm1f(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  ret void
+}
+
+declare float @coshf(float)
+declare float @expf(float)
+declare float @exp2f(float)
+declare float @sinhf(float)
+declare float @expm1f(float)
+
+define void @test_domain_error(float %value) {
+entry:
+
+  %call_00 = call float @acosf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt float %value, 1.000000e+00
+; CHECK: [[COND2:%[0-9]+]] = fcmp olt float %value, -1.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_00 = call float @acosf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_01 = call float @asinf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt float %value, 1.000000e+00
+; CHECK: [[COND2:%[0-9]+]] = fcmp olt float %value, -1.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_01 = call float @asinf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_02 = call float @cosf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oeq float %value, 0xFFF0000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp oeq float %value, 0x7FF0000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_02 = call float @cosf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_03 = call float @sinf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oeq float %value, 0xFFF0000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp oeq float %value, 0x7FF0000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_03 = call float @sinf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_04 = call float @acoshf(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp olt float %value, 1.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_04 = call float @acoshf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_05 = call float @sqrtf(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp olt float %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_05 = call float @sqrtf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_06 = call float @atanhf(float %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oge float %value, 1.000000e+00
+; CHECK: [[COND2:%[0-9]+]] = fcmp ole float %value, -1.000000e+00
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_06 = call float @atanhf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_07 = call float @logf(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole float %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_07 = call float @logf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_08 = call float @log10f(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole float %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_08 = call float @log10f(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_09 = call float @log2f(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole float %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_09 = call float @log2f(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_10 = call float @logbf(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole float %value, 0.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_10 = call float @logbf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_11 = call float @log1pf(float %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole float %value, -1.000000e+00
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_11 = call float @log1pf(float %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+  ret void
+}
+
+declare float @acosf(float)
+declare float @asinf(float)
+declare float @cosf(float)
+declare float @sinf(float)
+declare float @acoshf(float)
+declare float @sqrtf(float)
+declare float @atanhf(float)
+declare float @logf(float)
+declare float @log10f(float)
+declare float @log2f(float)
+declare float @logbf(float)
+declare float @log1pf(float)
+
+; CHECK: ![[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1, i32 2000}

Added: llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-long-double.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-long-double.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-long-double.ll (added)
+++ llvm/trunk/test/Transforms/Util/libcalls-shrinkwrap-long-double.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,192 @@
+; RUN: opt < %s -libcalls-shrinkwrap -S | FileCheck %s
+; New PM
+; RUN: opt < %s -passes=libcalls-shrinkwrap -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 @test_range_error(x86_fp80 %value) {
+entry:
+  %call_0 = call x86_fp80 @coshl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xKC00CB174000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK400CB174000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT:[0-9]+]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_0 = call x86_fp80 @coshl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_1 = call x86_fp80 @expl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xKC00CB21C000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK400CB170000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_1 = call x86_fp80 @expl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_3 = call x86_fp80 @exp2l(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xKC00D807A000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK400CB1DC000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_3 = call x86_fp80 @exp2l(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_4 = call x86_fp80 @sinhl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xKC00CB174000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK400CB174000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_4 = call x86_fp80 @sinhl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_5 = call x86_fp80 @expm1l(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK400CB170000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_5 = call x86_fp80 @expm1l(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  ret void
+}
+
+declare x86_fp80 @coshl(x86_fp80)
+declare x86_fp80 @expl(x86_fp80)
+declare x86_fp80 @exp10l(x86_fp80)
+declare x86_fp80 @exp2l(x86_fp80)
+declare x86_fp80 @sinhl(x86_fp80)
+declare x86_fp80 @expm1l(x86_fp80)
+
+define void @test_domain_error(x86_fp80 %value) {
+entry:
+  %call_00 = call x86_fp80 @acosl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK3FFF8000000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xKBFFF8000000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_00 = call x86_fp80 @acosl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_01 = call x86_fp80 @asinl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp ogt x86_fp80 %value, 0xK3FFF8000000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xKBFFF8000000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_01 = call x86_fp80 @asinl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_02 = call x86_fp80 @cosl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oeq x86_fp80 %value, 0xKFFFF8000000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp oeq x86_fp80 %value, 0xK7FFF8000000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_02 = call x86_fp80 @cosl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_03 = call x86_fp80 @sinl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oeq x86_fp80 %value, 0xKFFFF8000000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp oeq x86_fp80 %value, 0xK7FFF8000000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_03 = call x86_fp80 @sinl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_04 = call x86_fp80 @acoshl(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xK3FFF8000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_04 = call x86_fp80 @acoshl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_05 = call x86_fp80 @sqrtl(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp olt x86_fp80 %value, 0xK00000000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_05 = call x86_fp80 @sqrtl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_06 = call x86_fp80 @atanhl(x86_fp80 %value)
+; CHECK: [[COND1:%[0-9]+]] = fcmp oge x86_fp80 %value, 0xK3FFF8000000000000000
+; CHECK: [[COND2:%[0-9]+]] = fcmp ole x86_fp80 %value, 0xKBFFF8000000000000000
+; CHECK: [[COND:%[0-9]+]] = or i1 [[COND2]], [[COND1]]
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_06 = call x86_fp80 @atanhl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_07 = call x86_fp80 @logl(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole x86_fp80 %value, 0xK00000000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_07 = call x86_fp80 @logl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_08 = call x86_fp80 @log10l(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole x86_fp80 %value, 0xK00000000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_08 = call x86_fp80 @log10l(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_09 = call x86_fp80 @log2l(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole x86_fp80 %value, 0xK00000000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_09 = call x86_fp80 @log2l(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_10 = call x86_fp80 @logbl(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole x86_fp80 %value, 0xK00000000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_10 = call x86_fp80 @logbl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  %call_11 = call x86_fp80 @log1pl(x86_fp80 %value)
+; CHECK: [[COND:%[0-9]+]] = fcmp ole x86_fp80 %value, 0xKBFFF8000000000000000
+; CHECK: br i1 [[COND]], label %[[CALL_LABEL:cdce.call[0-9]*]], label %[[END_LABEL:cdce.end[0-9]*]], !prof ![[BRANCH_WEIGHT]]
+; CHECK: [[CALL_LABEL]]:
+; CHECK-NEXT: %call_11 = call x86_fp80 @log1pl(x86_fp80 %value)
+; CHECK-NEXT: br label %[[END_LABEL]]
+; CHECK: [[END_LABEL]]:
+
+  ret void
+}
+
+declare x86_fp80 @acosl(x86_fp80)
+declare x86_fp80 @asinl(x86_fp80)
+declare x86_fp80 @cosl(x86_fp80)
+declare x86_fp80 @sinl(x86_fp80)
+declare x86_fp80 @acoshl(x86_fp80)
+declare x86_fp80 @sqrtl(x86_fp80)
+declare x86_fp80 @atanhl(x86_fp80)
+declare x86_fp80 @logl(x86_fp80)
+declare x86_fp80 @log10l(x86_fp80)
+declare x86_fp80 @log2l(x86_fp80)
+declare x86_fp80 @logbl(x86_fp80)
+declare x86_fp80 @log1pl(x86_fp80)
+
+; CHECK: ![[BRANCH_WEIGHT]] = !{!"branch_weights", i32 1, i32 2000}

Added: llvm/trunk/test/Transforms/Util/lowerinvoke-funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/lowerinvoke-funclet.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/lowerinvoke-funclet.ll (added)
+++ llvm/trunk/test/Transforms/Util/lowerinvoke-funclet.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -lowerinvoke -S < %s | FileCheck %s
+
+; Test if invoke instructions that have a funclet operand bundle can be lowered.
+
+%struct.Cleanup = type { i8 }
+
+define void @lowerinvoke_funclet() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+; CHECK-LABEL: @lowerinvoke_funclet
+entry:
+  %c = alloca %struct.Cleanup, align 1
+  invoke void @foo()
+          to label %try.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]
+  invoke void @bar(i32 3) [ "funclet"(token %1), "test"(i32 0) ]
+          to label %invoke.cont1 unwind label %ehcleanup
+; CHECK:  call void @bar(i32 3) [ "funclet"(token %1), "test"(i32 0) ]
+
+invoke.cont1:                                     ; preds = %catch
+  call void @"??1Cleanup@@QEAA at XZ"(%struct.Cleanup* %c) #3 [ "funclet"(token %1) ]
+  catchret from %1 to label %try.cont
+
+try.cont:                                         ; preds = %entry, %invoke.cont1
+  ret void
+
+ehcleanup:                                        ; preds = %catch
+  %2 = cleanuppad within %1 []
+  call void @"??1Cleanup@@QEAA at XZ"(%struct.Cleanup* %c) #3 [ "funclet"(token %2) ]
+  cleanupret from %2 unwind to caller
+}
+
+declare void @foo()
+declare void @bar(i32)
+declare i32 @__CxxFrameHandler3(...)
+declare void @"??1Cleanup@@QEAA at XZ"(%struct.Cleanup*) unnamed_addr

Added: llvm/trunk/test/Transforms/Util/lowerswitch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/lowerswitch.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/lowerswitch.ll (added)
+++ llvm/trunk/test/Transforms/Util/lowerswitch.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,302 @@
+; RUN: opt -lowerswitch -S < %s | FileCheck %s
+
+; Test that we don't crash and have a different basic block for each incoming edge.
+define void @test0(i32 %mode) {
+; CHECK-LABEL: @test0
+;
+; CHECK: icmp eq i32 %mode, 4
+; CHECK-NEXT: label %BB3, label %NewDefault
+;
+; CHECK: icmp eq i32 %mode, 2
+; CHECK-NEXT: label %BB3, label %NewDefault
+;
+; CHECK: icmp eq i32 %mode, 0
+; CHECK-NEXT: label %BB3, label %NewDefault
+;
+; CHECK: %merge = phi i64 [ 1, %BB3 ], [ 0, %NewDefault ]
+BB1:
+  switch i32 %mode, label %BB2 [
+    i32 3, label %BB2
+    i32 5, label %BB2
+    i32 0, label %BB3
+    i32 2, label %BB3
+    i32 4, label %BB3
+  ]
+
+BB2:
+  %merge = phi i64 [ 1, %BB3 ], [ 0, %BB1 ], [ 0, %BB1 ], [ 0, %BB1 ]
+  ret void
+
+BB3:
+  br label %BB2
+}
+
+; Test switch cases that are merged into a single case during lowerswitch
+; (take 84 and 85 below) - check that the number of incoming phi values match
+; the number of branches.
+define void @test1(i32 %mode) {
+; CHECK-LABEL: @test1
+entry:
+  br label %bb1
+
+bb1:
+  switch i32 %mode, label %bb1 [
+    i32 84, label %bb3
+    i32 85, label %bb3
+    i32 86, label %bb2
+    i32 78, label %exit
+    i32 99, label %bb3
+  ]
+
+bb2:
+  br label %bb3
+
+bb3:
+; CHECK-LABEL: bb3
+; CHECK: %tmp = phi i32 [ 1, %NodeBlock ], [ 0, %bb2 ], [ 1, %LeafBlock3 ]
+  %tmp = phi i32 [ 1, %bb1 ], [ 0, %bb2 ], [ 1, %bb1 ], [ 1, %bb1 ]
+; CHECK-NEXT: %tmp2 = phi i32 [ 2, %NodeBlock ], [ 5, %bb2 ], [ 2, %LeafBlock3 ]
+  %tmp2 = phi i32 [ 2, %bb1 ], [ 2, %bb1 ], [ 5, %bb2 ], [ 2, %bb1 ]
+  br label %exit
+
+exit:
+  ret void
+}
+
+; Test that we don't crash.
+define void @test2(i32 %mode) {
+; CHECK-LABEL: @test2
+  br i1 undef, label %1, label %._crit_edge
+
+; <label>:1                                       ; preds = %0
+  switch i32 %mode, label %33 [
+    i32 2, label %2
+    i32 3, label %3
+    i32 4, label %4
+    i32 5, label %5
+    i32 6, label %6
+    i32 7, label %7
+    i32 8, label %8
+    i32 9, label %9
+    i32 10, label %10
+    i32 11, label %14
+    i32 12, label %18
+    i32 13, label %22
+    i32 14, label %26
+    i32 15, label %27
+    i32 16, label %34
+    i32 17, label %34
+    i32 18, label %34
+    i32 19, label %34
+    i32 22, label %34
+    i32 20, label %31
+    i32 21, label %32
+  ]
+
+; <label>:2                                       ; preds = %1
+  br label %34
+
+; <label>:3                                       ; preds = %1
+  br label %34
+
+; <label>:4                                       ; preds = %1
+  br label %34
+
+; <label>:5                                       ; preds = %1
+  br label %34
+
+; <label>:6                                       ; preds = %1
+  br label %34
+
+; <label>:7                                       ; preds = %1
+  br label %34
+
+; <label>:8                                       ; preds = %1
+  br label %34
+
+; <label>:9                                       ; preds = %1
+  br label %34
+
+; <label>:10                                      ; preds = %1
+  br i1 undef, label %11, label %12
+
+; <label>:11                                      ; preds = %10
+  br label %13
+
+; <label>:12                                      ; preds = %10
+  br label %13
+
+; <label>:13                                      ; preds = %12, %11
+  br label %34
+
+; <label>:14                                      ; preds = %1
+  br i1 undef, label %15, label %16
+
+; <label>:15                                      ; preds = %14
+  br label %17
+
+; <label>:16                                      ; preds = %14
+  br label %17
+
+; <label>:17                                      ; preds = %16, %15
+  br label %34
+
+; <label>:18                                      ; preds = %1
+  br i1 undef, label %19, label %20
+
+; <label>:19                                      ; preds = %18
+  br label %21
+
+; <label>:20                                      ; preds = %18
+  br label %21
+
+; <label>:21                                      ; preds = %20, %19
+  br label %34
+
+; <label>:22                                      ; preds = %1
+  br i1 undef, label %23, label %24
+
+; <label>:23                                      ; preds = %22
+  br label %25
+
+; <label>:24                                      ; preds = %22
+  br label %25
+
+; <label>:25                                      ; preds = %24, %23
+  br label %34
+
+; <label>:26                                      ; preds = %1
+  br label %34
+
+; <label>:27                                      ; preds = %1
+  br i1 undef, label %28, label %29
+
+; <label>:28                                      ; preds = %27
+  br label %30
+
+; <label>:29                                      ; preds = %27
+  br label %30
+
+; <label>:30                                      ; preds = %29, %28
+  br label %34
+
+; <label>:31                                      ; preds = %1
+  br label %34
+
+; <label>:32                                      ; preds = %1
+  br label %34
+
+; <label>:33                                      ; preds = %1
+  br label %34
+
+; <label>:34                                      ; preds = %33, %32, %31, %30, %26, %25, %21, %17, %13, %9, %8, %7, %6, %5, %4, %3, %2, %1, %1, %1, %1, %1
+  %o.0 = phi float [ undef, %33 ], [ undef, %32 ], [ undef, %31 ], [ undef, %30 ], [ undef, %26 ], [ undef, %25 ], [ undef, %21 ], [ undef, %17 ], [ undef, %13 ], [ undef, %9 ], [ undef, %8 ], [ undef, %7 ], [ undef, %6 ], [ undef, %5 ], [ undef, %4 ], [ undef, %3 ], [ undef, %2 ], [ undef, %1 ], [ undef, %1 ], [ undef, %1 ], [ undef, %1 ], [ undef, %1 ]
+  br label %._crit_edge
+
+._crit_edge:                                      ; preds = %34, %0
+  ret void
+}
+
+; Test that the PHI node in for.cond should have one entry for each predecessor
+; of its parent basic block after lowerswitch merged several cases into a new
+; default block.
+define void @test3(i32 %mode) {
+; CHECK-LABEL: @test3
+entry:
+  br label %lbl1
+
+lbl1:                                             ; preds = %cleanup, %entry
+  br label %lbl2
+
+lbl2:                                             ; preds = %cleanup, %lbl1
+  br label %for.cond
+
+for.cond:                                         ; preds = %cleanup, %cleanup, %lbl2
+; CHECK: for.cond:
+; CHECK: phi i16 [ undef, %lbl2 ], [ %b.3, %NewDefault ]{{$}}
+; CHECK: for.cond1:
+  %b.2 = phi i16 [ undef, %lbl2 ], [ %b.3, %cleanup ], [ %b.3, %cleanup ]
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.cond
+  %b.3 = phi i16 [ %b.2, %for.cond ], [ undef, %for.inc ]
+  %tobool = icmp ne i16 %b.3, 0
+  br i1 %tobool, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond1
+  br i1 undef, label %if.then, label %for.inc
+
+if.then:                                          ; preds = %for.body
+  br label %cleanup
+
+for.inc:                                          ; preds = %for.body
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  br i1 undef, label %if.then4, label %for.body7
+
+if.then4:                                         ; preds = %for.end
+  br label %cleanup
+
+for.body7:                                        ; preds = %for.end
+  br label %cleanup
+
+cleanup:                                          ; preds = %for.body7, %if.then4, %if.then
+  switch i32 %mode, label %unreachable [
+    i32 0, label %for.cond
+    i32 2, label %lbl1
+    i32 5, label %for.cond
+    i32 3, label %lbl2
+  ]
+
+unreachable:                                      ; preds = %cleanup
+  unreachable
+}
+
+; Test that the PHI node in cleanup17 is removed as the switch default block is
+; not reachable.
+define void @test4(i32 %mode) {
+; CHECK-LABEL: @test4
+entry:
+  switch i32 %mode, label %cleanup17 [
+    i32 0, label %return
+    i32 9, label %return
+  ]
+
+cleanup17:
+; CHECK: cleanup17:
+; CHECK-NOT: phi i16 [ undef, %entry ]
+; CHECK: return:
+
+  %retval.4 = phi i16 [ undef, %entry ]
+  unreachable
+
+return:
+  ret void
+}
+
+; Test that the PHI node in for.inc is updated correctly as the switch is
+; replaced with a single branch to for.inc
+define void @test5(i32 %mode) {
+; CHECK-LABEL: @test5
+entry:
+  br i1 undef, label %cleanup10, label %cleanup10.thread
+
+cleanup10.thread:
+  br label %for.inc
+
+cleanup10:
+  switch i32 %mode, label %unreachable [
+    i32 0, label %for.inc
+    i32 4, label %for.inc
+  ]
+
+for.inc:
+; CHECK: for.inc:
+; CHECK-NEXT: phi i16 [ 0, %cleanup10.thread ], [ undef, %cleanup10 ]
+%0 = phi i16 [ undef, %cleanup10 ], [ 0, %cleanup10.thread ], [ undef, %cleanup10 ]
+  unreachable
+
+unreachable:
+  unreachable
+}

Added: llvm/trunk/test/Transforms/Util/simplify-dbg-declare-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/simplify-dbg-declare-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/simplify-dbg-declare-load.ll (added)
+++ llvm/trunk/test/Transforms/Util/simplify-dbg-declare-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,61 @@
+; RUN: opt -instcombine -instcombine-lower-dbg-declare=1 -S < %s | FileCheck %s
+; RUN: opt -instcombine -instcombine-lower-dbg-declare=0 -S < %s | FileCheck %s --check-prefix=DECLARE
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+%foo = type { i64, i32, i32 }
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+declare void @llvm.dbg.value(metadata, metadata, metadata) #0
+
+; Function Attrs: sspreq
+define void @julia_fastshortest_6256() #1 {
+top:
+  %cp = alloca %foo, align 8
+  %sink = alloca %foo, align 8
+  call void @llvm.dbg.declare(metadata %foo* %cp, metadata !1, metadata !16), !dbg !17
+  br i1 undef, label %idxend, label %fail
+
+fail:                                             ; preds = %top
+  unreachable
+
+idxend:                                           ; preds = %top
+; CHECK-NOT: call void @llvm.dbg.value(metadata %foo* %cp,
+  %0 = load %foo, %foo* %cp, align 8
+  store volatile %foo %0, %foo *%sink, align 8
+; CHECK: call void @llvm.dbg.value(metadata %foo %
+  store %foo %0, %foo* undef, align 8
+  ret void
+}
+
+; Keep the declare if we keep the alloca.
+; DECLARE-LABEL: define void @julia_fastshortest_6256()
+; DECLARE: %cp = alloca %foo, align 8
+; DECLARE: call void @llvm.dbg.declare(metadata %foo* %cp,
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { sspreq }
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!18}
+
+!0 = !{i32 1, !"Debug Info Version", i32 3}
+!1 = !DILocalVariable(name: "cp", scope: !2, file: !3, line: 106, type: !12)
+!2 = distinct !DISubprogram(name: "fastshortest", linkageName: "julia_fastshortest_6256", scope: null, file: !3, type: !4, isLocal: false, isDefinition: true, isOptimized: true, unit: !18, retainedNodes: !11)
+!3 = !DIFile(filename: "grisu/fastshortest.jl", directory: ".")
+!4 = !DISubroutineType(types: !5)
+!5 = !{!6, !7}
+!6 = !DIBasicType(name: "Float64", size: 64, align: 64, encoding: DW_ATE_unsigned)
+!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, align: 64)
+!8 = !DICompositeType(tag: DW_TAG_structure_type, name: "jl_value_t", file: !9, line: 71, align: 64, elements: !10)
+!9 = !DIFile(filename: "julia.h", directory: "")
+!10 = !{!7}
+!11 = !{}
+!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "Float", size: 128, align: 64, elements: !13, runtimeLang: DW_LANG_Julia)
+!13 = !{!14, !15, !15}
+!14 = !DIBasicType(name: "UInt64", size: 64, align: 64, encoding: DW_ATE_unsigned)
+!15 = !DIBasicType(name: "Int32", size: 32, align: 32, encoding: DW_ATE_unsigned)
+!16 = !DIExpression()
+!17 = !DILocation(line: 106, scope: !2)
+!18 = distinct !DICompileUnit(language: DW_LANG_Julia, file: !3)

Added: llvm/trunk/test/Transforms/Util/store-first-op.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/store-first-op.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/store-first-op.ll (added)
+++ llvm/trunk/test/Transforms/Util/store-first-op.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -instcombine -S %s | FileCheck %s
+
+%foo = type { i8 }
+
+; Function Attrs: nounwind uwtable
+define void @_ZN4llvm13ScaledNumbers10multiply64Emm() {
+entry:
+  %getU = alloca %foo, align 1
+; This is supposed to make sure that the declare conversion, does not accidentally think the store OF
+; %getU is a store TO %getU. There are valid reasons to have an llvm.dbg.value here, but if the pass
+; is changed to emit such, a more specific check should be added to make sure that any llvm.dbg.value
+; is correct.
+; CHECK-NOT: @llvm.dbg.value(metadata %foo* %getU
+  call void @llvm.dbg.declare(metadata %foo* %getU, metadata !3, metadata !6), !dbg !7
+  store %foo* %getU, %foo** undef, align 8, !tbaa !8
+  unreachable
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "none", directory: ".")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !DILocalVariable(name: "getU", scope: !4, file: !1, line: 25, type: !5)
+!4 = distinct !DISubprogram(name: "multiply64", linkageName: "_ZN4llvm13ScaledNumbers10multiply64Emm", scope: null, file: !1, line: 22, isLocal: false, isDefinition: true, scopeLine: 23, flags: DIFlagPrototyped, isOptimized: true, unit: !0)
+!5 = !DICompositeType(tag: DW_TAG_class_type, scope: !4, file: !1, line: 25, size: 8, align: 8)
+!6 = !DIExpression()
+!7 = !DILocation(line: 25, column: 8, scope: !4)
+!8 = !{!10, !10, i64 0}
+!9 = !{i64 0}
+!10 = !{!"scalar type", !9}

Added: llvm/trunk/test/Transforms/Util/strip-gc-relocates.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-gc-relocates.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-gc-relocates.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-gc-relocates.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,120 @@
+; RUN: opt -S -strip-gc-relocates -instcombine < %s | FileCheck %s
+; test utility/debugging pass which removes gc.relocates, inserted by -rewrite-statepoints-for-gc
+declare void @use_obj32(i32 addrspace(1)*) "gc-leaf-function"
+
+declare void @g()
+declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
+declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) #0
+declare void @do_safepoint()
+
+declare i32 addrspace(1)* @new_instance() #1
+
+
+; Simple case: remove gc.relocate
+define i32 addrspace(1)* @test1(i32 addrspace(1)* %arg) gc "statepoint-example" {
+entry:
+; CHECK-LABEL: test1
+; CHECK: gc.statepoint
+; CHECK-NOT: gc.relocate
+; CHECK: ret i32 addrspace(1)* %arg
+  %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg)
+  %arg.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 8) ; (%arg, %arg)
+  %arg.relocated.casted = bitcast i8 addrspace(1)* %arg.relocated to i32 addrspace(1)*
+  ret i32 addrspace(1)* %arg.relocated.casted
+}
+
+; Remove gc.relocates in presence of nested relocates.
+define void @test2(i32 addrspace(1)* %base) gc "statepoint-example" {
+entry:
+; CHECK-LABEL: test2
+; CHECK: statepoint
+; CHECK-NOT: gc.relocate
+; CHECK: call void @use_obj32(i32 addrspace(1)* %ptr.gep1)
+; CHECK: call void @use_obj32(i32 addrspace(1)* %ptr.gep1)
+  %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15
+  %ptr.gep1 = getelementptr i32, i32 addrspace(1)* %ptr.gep, i32 15
+  %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %ptr.gep1, i32 addrspace(1)* %base)
+  %ptr.gep1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 7) ; (%base, %ptr.gep1)
+  %ptr.gep1.relocated.casted = bitcast i8 addrspace(1)* %ptr.gep1.relocated to i32 addrspace(1)*
+  %base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 8) ; (%base, %base)
+  %base.relocated.casted = bitcast i8 addrspace(1)* %base.relocated to i32 addrspace(1)*
+  call void @use_obj32(i32 addrspace(1)* %ptr.gep1.relocated.casted)
+  %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %ptr.gep1.relocated.casted, i32 addrspace(1)* %base.relocated.casted)
+  %ptr.gep1.relocated2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token1, i32 8, i32 7) ; (%base.relocated.casted, %ptr.gep1.relocated.casted)
+  %ptr.gep1.relocated2.casted = bitcast i8 addrspace(1)* %ptr.gep1.relocated2 to i32 addrspace(1)*
+  %base.relocated3 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token1, i32 8, i32 8) ; (%base.relocated.casted, %base.relocated.casted)
+  %base.relocated3.casted = bitcast i8 addrspace(1)* %base.relocated3 to i32 addrspace(1)*
+  call void @use_obj32(i32 addrspace(1)* %ptr.gep1.relocated2.casted)
+  ret void
+}
+
+; landing pad gc.relocates removed by instcombine since it has no uses.
+define i32 addrspace(1)* @test3(i32 addrspace(1)* %arg) gc "statepoint-example" personality i32 8 {
+; CHECK-LABEL: test3(
+; CHECK: gc.statepoint
+; CHECK-LABEL: normal_dest:
+; CHECK-NOT: gc.relocate
+; CHECK: ret i32 addrspace(1)* %arg
+; CHECK-LABEL: unwind_dest:
+; CHECK-NOT: gc.relocate
+entry:
+  %statepoint_token = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg)
+          to label %normal_dest unwind label %unwind_dest
+
+normal_dest:                                      ; preds = %entry
+  %arg.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 8) ; (%arg, %arg)
+  %arg.relocated1.casted = bitcast i8 addrspace(1)* %arg.relocated1 to i32 addrspace(1)*
+  ret i32 addrspace(1)* %arg.relocated1.casted
+
+unwind_dest:                                      ; preds = %entry
+  %lpad = landingpad token
+          cleanup
+  %arg.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %lpad, i32 8, i32 8) ; (%arg, %arg)
+  %arg.relocated.casted = bitcast i8 addrspace(1)* %arg.relocated to i32 addrspace(1)*
+  resume token undef
+}
+
+; in presence of phi
+define void @test4(i1 %cond) gc "statepoint-example" {
+; CHECK-LABEL: test4
+entry:
+  %base1 = call i32 addrspace(1)* @new_instance()
+  %base2 = call i32 addrspace(1)* @new_instance()
+  br i1 %cond, label %here, label %there
+
+here:                                             ; preds = %entry
+  br label %merge
+
+there:                                            ; preds = %entry
+  br label %merge
+
+merge:                                            ; preds = %there, %here
+; CHECK-LABEL: merge:
+; CHECK-NOT: gc.relocate
+; CHECK: %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi.base
+  %basephi.base = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ], !is_base_value !0
+  %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ]
+  %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
+  %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %basephi.base)
+  %basephi.base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) ; (%basephi.base, %basephi.base)
+  %basephi.base.relocated.casted = bitcast i8 addrspace(1)* %basephi.base.relocated to i32 addrspace(1)*
+  %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15
+  call void @use_obj32(i32 addrspace(1)* %ptr.gep.remat)
+  ret void
+}
+
+; The gc.relocate type is different from %arg, but removing the gc.relocate,
+; needs a bitcast to be added from i32 addrspace(1)* to i8 addrspace(1)*
+define i8 addrspace(1)* @test5(i32 addrspace(1)* %arg) gc "statepoint-example" {
+entry:
+; CHECK-LABEL: test5
+; CHECK: gc.statepoint
+; CHECK-NOT: gc.relocate
+  %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg)
+  %arg.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 8) ; (%arg, %arg)
+  ret i8 addrspace(1)* %arg.relocated
+}
+
+attributes #0 = { nounwind readonly }
+attributes #1 = { nounwind "gc-leaf-function" }
+!0 = !{}

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-containingtypes.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,94 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o %t.ll
+; RUN: cat %t.ll | FileCheck %s
+; RUN: cat %t.ll | FileCheck %s --check-prefix=CHECK-NEG
+;
+; This test provides coverage for setting the containing type of a DISubprogram.
+;
+; Generated an reduced from:
+; struct A {
+;   virtual ~A();
+; };
+; struct B : A {};
+; B b;
+
+source_filename = "t.cpp"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+%struct.B = type { %struct.A }
+%struct.A = type { i32 (...)** }
+
+; CHECK: @b = global
+; CHECK-NOT: !dbg
+ at b = global %struct.B zeroinitializer, align 8, !dbg !0
+
+declare void @_ZN1BC2Ev(%struct.B*) unnamed_addr
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
+; CHECK: define
+
+; Function Attrs: inlinehint nounwind ssp uwtable
+define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr #1 align 2 !dbg !25 {
+entry:
+  %this.addr = alloca %struct.B*, align 8
+  store %struct.B* %this, %struct.B** %this.addr, align 8
+  ; CHECK-NOT: @llvm.dbg.declare
+  call void @llvm.dbg.declare(metadata %struct.B** %this.addr, metadata !30, metadata !32), !dbg !33
+  %this1 = load %struct.B*, %struct.B** %this.addr, align 8
+  call void @_ZN1BC2Ev(%struct.B* %this1) #2, !dbg !34
+  ret void, !dbg !34
+  ; CHECK: call void @_ZN1BC2Ev(%struct.B* %this1){{.*}} !dbg !
+}
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { inlinehint nounwind ssp uwtable }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!21, !22, !23}
+!llvm.ident = !{!24}
+
+; CHECK-NEG-NOT: !DI{{Basic|Composite|Derived}}Type
+
+!0 = distinct !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 5, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "t.cpp", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !3, line: 4, size: 64, align: 64, elements: !7, vtableHolder: !9, identifier: "_ZTS1B")
+!7 = !{!8}
+!8 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !6, baseType: !9)
+!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !3, line: 1, size: 64, align: 64, elements: !10, vtableHolder: !9, identifier: "_ZTS1A")
+!10 = !{!11, !17}
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$A", scope: !3, file: !3, baseType: !12, size: 64, flags: DIFlagArtificial)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
+!13 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !14, size: 64)
+!14 = !DISubroutineType(types: !15)
+!15 = !{!16}
+!16 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!17 = !DISubprogram(name: "~A", scope: !9, file: !3, line: 2, type: !18, isLocal: false, isDefinition: false, scopeLine: 2, containingType: !9, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, flags: DIFlagPrototyped, isOptimized: false)
+!18 = !DISubroutineType(types: !19)
+!19 = !{null, !20}
+!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!21 = !{i32 2, !"Dwarf Version", i32 4}
+!22 = !{i32 2, !"Debug Info Version", i32 3}
+!23 = !{i32 1, !"PIC Level", i32 2}
+!24 = !{!"clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)"}
+; Only referenced by the type system.
+; CHECK-NEG-NOT: !DISubprogram(name: "~A"
+!25 = distinct !DISubprogram(name: "B", linkageName: "_ZN1BC1Ev", scope: !6, file: !3, line: 4, type: !26, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !2, declaration: !29, retainedNodes: !4)
+!26 = !DISubroutineType(types: !27)
+!27 = !{null, !28}
+!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
+!29 = !DISubprogram(name: "B", scope: !6, type: !26, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
+!30 = !DILocalVariable(name: "this", arg: 1, scope: !25, type: !31, flags: DIFlagArtificial | DIFlagObjectPointer)
+!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 64)
+!32 = !DIExpression()
+!33 = !DILocation(line: 0, scope: !25)
+!34 = !DILocation(line: 4, column: 8, scope: !25)
+
+; CHECK: !DISubprogram(name: "B", scope: ![[FILE:.*]], file: ![[FILE]],
+; CHECK-NOT: containingType:
+; CHECK-NEG-NOT: !DISubprogram(name: "B", {{.*}}, isDefinition: false

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-cus.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
+!llvm.dbg.cu = !{!2, !6}
+!llvm.gcov = !{!3}
+!llvm.module.flags = !{!7}
+
+!1 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
+; The first CU is used for the line table, the second one is a module skeleton
+; and should be stripped.
+; CHECK: !llvm.dbg.cu = !{![[CU:[0-9]+]]}
+; CHECK: ![[CU]] = distinct !DICompileUnit({{.*}}"abc.debug"{{.*}}LineTablesOnly
+; CHECK-NOT: retainedTypes:
+; CHECK-SAME: )
+; CHECK-NOT: DICompositeType
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
+                             isOptimized: true, flags: "-O2", runtimeVersion: 2,
+                             splitDebugFilename: "abc.debug", emissionKind: FullDebug,
+                             retainedTypes: !4)
+!3 = !{!"path/to/file.o", !2}
+!4 = !{!5}
+!5 = !DICompositeType(tag: DW_TAG_structure_type, file: !1, identifier: "ThisWillBeStripped")
+!6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
+                             splitDebugFilename: "abc.dwo", emissionKind: FullDebug,
+                             dwoId: 1234)
+!7 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-localvars.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
+; CHECK: define void @f() !dbg ![[F:[0-9]+]]
+define void @f() !dbg !4 {
+entry:
+  %i = alloca i32, align 4
+  ; CHECK-NOT: llvm.dbg.declare
+  call void @llvm.dbg.declare(metadata i32* %i, metadata !11, metadata !13), !dbg !14
+  store i32 42, i32* %i, align 4, !dbg !14
+  ret void, !dbg !15
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2)
+!1 = !DIFile(filename: "f.c", directory: "/")
+!2 = !{}
+; CHECK: ![[F]] = distinct !DISubprogram(name: "f"
+; CHECK-NOT: retainedNodes:
+; CHECK-NOT: distinct !DISubprogram(name: "f"
+!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null}
+!7 = !{i32 2, !"Dwarf Version", i32 2}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"PIC Level", i32 2}
+!10 = !{!"LLVM"}
+!11 = !DILocalVariable(name: "i", scope: !4, file: !1, line: 1, type: !12)
+!12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!13 = !DIExpression()
+!14 = !DILocation(line: 1, column: 16, scope: !4)
+!15 = !DILocation(line: 1, column: 24, scope: !4)

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-loops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o %t
+; RUN: cat %t | FileCheck %s
+; RUN: cat %t | FileCheck %s --check-prefix=NEGATIVE
+; void f(volatile int *i) {
+;   while (--*i) {}
+; }
+source_filename = "/tmp/loop.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+define void @f(i32* %i) local_unnamed_addr #0 !dbg !7 {
+entry:
+  tail call void @llvm.dbg.value(metadata i32* %i, metadata !14, metadata !15), !dbg !16
+  br label %while.cond, !dbg !17
+
+while.cond:                                       ; preds = %while.cond, %entry
+  %0 = load volatile i32, i32* %i, align 4, !dbg !18, !tbaa !19
+  %dec = add nsw i32 %0, -1, !dbg !18
+  store volatile i32 %dec, i32* %i, align 4, !dbg !18, !tbaa !19
+  %tobool = icmp eq i32 %dec, 0, !dbg !17
+  ; CHECK: !llvm.loop ![[LOOP:[0-9]+]]
+  br i1 %tobool, label %while.end, label %while.cond, !dbg !17, !llvm.loop !23
+
+while.end:                                        ; preds = %while.cond
+  ret void, !dbg !25
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { nounwind ssp uwtable }
+attributes #1 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+; CHECK: ![[CU:.*]] = distinct !DICompileUnit(language: DW_LANG_C99,
+; CHECK-SAME:                                 emissionKind: LineTablesOnly
+; NEGATIVE-NOT: !DICompileUnit({{.*}} emissionKind: FullDebug
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 (trunk 298880) (llvm/trunk 298875)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "/tmp/loop.c", 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 = !{!"clang version 5.0.0 (trunk 298880) (llvm/trunk 298875)"}
+; CHECK: ![[F:[0-9]]] = distinct !DISubprogram(name: "f", scope: !1
+!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !13)
+!8 = !DISubroutineType(types: !9)
+!9 = !{null, !10}
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
+!11 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !12)
+; NEGATIVE-NOT: !DIBasicType(name: "int",
+!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!13 = !{!14}
+!14 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!15 = !DIExpression()
+!16 = !DILocation(line: 1, column: 22, scope: !7)
+; CHECK: ![[BEGIN:[0-9]+]] = !DILocation(line: 2, column: 3, scope: ![[F]])
+!17 = !DILocation(line: 2, column: 3, scope: !7)
+!18 = !DILocation(line: 2, column: 10, scope: !7)
+!19 = !{!20, !20, i64 0}
+!20 = !{!"int", !21, i64 0}
+!21 = !{!"omnipotent char", !22, i64 0}
+!22 = !{!"Simple C/C++ TBAA"}
+; CHECK: ![[LOOP]] = distinct !{![[LOOP]], ![[BEGIN]], ![[END:[0-9]+]]}
+!23 = distinct !{!23, !17, !24}
+; CHECK: ![[END]] = !DILocation(line: 3, column: 3, scope: ![[F]])
+!24 = !DILocation(line: 3, column: 3, scope: !7)
+!25 = !DILocation(line: 4, column: 1, scope: !7)

Added: llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll (added)
+++ llvm/trunk/test/Transforms/Util/strip-nonlinetable-debuginfo-subroutinetypes.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
+; Test that subroutine types are downgraded to (void)().
+define internal i32 @"__hidden#2878_"() #0 !dbg !12 {
+  ret i32 0, !dbg !634
+}
+!llvm.dbg.cu = !{!18}
+!llvm.module.flags = !{!482}
+!5 = !{}
+!2 = !{!12}
+; CHECK-NOT: DICompositeType
+; CHECK: distinct !DISubprogram(name: "f", {{.*}}, type: ![[FNTY:[0-9]+]]
+; CHECK: ![[FNTY]] = !DISubroutineType(types: ![[VOID:[0-9]+]])
+; CHECK: ![[VOID]] = !{}
+; CHECK-NOT: DICompositeType
+!12 = distinct !DISubprogram(name: "f", scope: !16, file: !16, line: 133, type: !13, isLocal: true, isDefinition: true, scopeLine: 133, flags: DIFlagPrototyped, isOptimized: true, unit: !18, retainedNodes: !5)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!17}
+!16 = !DIFile(filename: "f.m", directory: "/")
+!17 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e", scope: !18, file: !16, line: 13, size: 32, align: 32, flags: DIFlagFwdDecl)
+!18 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !16, producer: "clang", isOptimized: true, runtimeVersion: 2, emissionKind: 1, enums: !14, retainedTypes: !14, globals: !5, imports: !5)
+!482 = !{i32 2, !"Debug Info Version", i32 3}
+!634 = !DILocation(line: 143, column: 5, scope: !12)

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/export.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/export.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/export.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/export.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+---
+GlobalValueMap:
+  42:
+    - Live: true
+      TypeTestAssumeVCalls:
+        - GUID: 14276520915468743435  # typeid1
+          Offset: 0
+      TypeCheckedLoadVCalls:
+        - GUID: 15427464259790519041  # typeid2
+          Offset: 0
+      TypeTestAssumeConstVCalls:
+        - VFunc:
+            GUID: 3515965990081467659  # typeid3
+            Offset: 0
+          Args: [12, 24]
+      TypeCheckedLoadConstVCalls:
+        - VFunc:
+            GUID: 17525413373118030901  # typeid4
+            Offset: 0
+          Args: [24, 12]
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-branch-funnel.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-branch-funnel.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-branch-funnel.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-branch-funnel.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+---
+TypeIdMap:
+  typeid1:
+    WPDRes:
+      0:
+        Kind: BranchFunnel
+  typeid2:
+    WPDRes:
+      8:
+        Kind: BranchFunnel
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-indir.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+---
+GlobalValueMap:
+  42:
+    - Live: true
+      TypeTestAssumeVCalls:
+        - GUID: 123
+          Offset: 0
+        - GUID: 456
+          Offset: 4
+      TypeCheckedLoadVCalls:
+        - GUID: 789
+          Offset: 8
+        - GUID: 1234
+          Offset: 16
+      TypeTestAssumeConstVCalls:
+        - VFunc:
+            GUID: 123
+            Offset: 4
+          Args: [12, 24]
+      TypeCheckedLoadConstVCalls:
+        - VFunc:
+            GUID: 456
+            Offset: 8
+          Args: [24, 12]
+TypeIdMap:
+  typeid1:
+    WPDRes:
+      0:
+        Kind: Indir
+      4:
+        Kind: Indir
+        ResByArg:
+          "":
+            Kind: UniformRetVal
+            Info: 12
+          12:
+            Kind: UniformRetVal
+            Info: 24
+          "12,24":
+            Kind: UniformRetVal
+            Info: 48
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-single-impl.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-single-impl.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-single-impl.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-single-impl.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+---
+TypeIdMap:
+  typeid1:
+    WPDRes:
+      0:
+        Kind: SingleImpl
+        SingleImplName: singleimpl1
+  typeid2:
+    WPDRes:
+      8:
+        Kind: SingleImpl
+        SingleImplName: singleimpl2
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-uniform-ret-val.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-uniform-ret-val.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-uniform-ret-val.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-uniform-ret-val.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+---
+TypeIdMap:
+  typeid1:
+    WPDRes:
+      0:
+        Kind: Indir
+        ResByArg:
+          1:
+            Kind: UniformRetVal
+            Info: 42
+  typeid2:
+    WPDRes:
+      8:
+        Kind: Indir
+        ResByArg:
+          1:
+            Kind: UniformRetVal
+            Info: 42
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val0.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val0.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val0.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val0.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+---
+TypeIdMap:
+  typeid2:
+    WPDRes:
+      8:
+        Kind: Indir
+        ResByArg:
+          3:
+            Kind: UniqueRetVal
+            Info: 0
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val1.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val1.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val1.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-unique-ret-val1.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+---
+TypeIdMap:
+  typeid2:
+    WPDRes:
+      8:
+        Kind: Indir
+        ResByArg:
+          3:
+            Kind: UniqueRetVal
+            Info: 1
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp-branch-funnel.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp-branch-funnel.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp-branch-funnel.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp-branch-funnel.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+---
+TypeIdMap:
+  typeid1:
+    WPDRes:
+      0:
+        Kind: BranchFunnel
+        ResByArg:
+          1:
+            Kind: VirtualConstProp
+            Info: 0
+            Byte: 42
+            Bit: 0
+  typeid2:
+    WPDRes:
+      8:
+        Kind: BranchFunnel
+        ResByArg:
+          3:
+            Kind: VirtualConstProp
+            Info: 0
+            Byte: 43
+            Bit: 128
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+---
+TypeIdMap:
+  typeid1:
+    WPDRes:
+      0:
+        Kind: Indir
+        ResByArg:
+          1:
+            Kind: VirtualConstProp
+            Info: 0
+            Byte: 42
+            Bit: 0
+  typeid2:
+    WPDRes:
+      8:
+        Kind: Indir
+        ResByArg:
+          3:
+            Kind: VirtualConstProp
+            Info: 0
+            Byte: 43
+            Bit: 128
+...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/bad-read-from-vtable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/bad-read-from-vtable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/bad-read-from-vtable.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/bad-read-from-vtable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt -S -wholeprogramdevirt %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at vt1 = constant [2 x i8*] [i8* zeroinitializer, i8* bitcast (void (i8*)* @vf to i8*)], !type !0
+ at vt2 = constant i8* bitcast (void (i8*)* @vf to i8*), !type !1
+
+define void @vf(i8* %this) {
+  ret void
+}
+
+; CHECK: define void @unaligned1
+define void @unaligned1(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr i8, i8* %vtablei8, i32 1
+  %fptrptr_casted = bitcast i8* %fptrptr to i8**
+  %fptr = load i8*, i8** %fptrptr_casted
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  ; CHECK: call void %
+  call void %fptr_casted(i8* %obj)
+  ret void
+}
+
+; CHECK: define void @unaligned2
+define void @unaligned2(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid2")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr i8, i8* %vtablei8, i32 1
+  %fptrptr_casted = bitcast i8* %fptrptr to i8**
+  %fptr = load i8*, i8** %fptrptr_casted
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  ; CHECK: call void %
+  call void %fptr_casted(i8* %obj)
+  ret void
+}
+
+; CHECK: define void @outofbounds
+define void @outofbounds(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr i8, i8* %vtablei8, i32 16
+  %fptrptr_casted = bitcast i8* %fptrptr to i8**
+  %fptr = load i8*, i8** %fptrptr_casted
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  ; CHECK: call void %
+  call void %fptr_casted(i8* %obj)
+  ret void
+}
+
+; CHECK: define void @nonfunction
+define void @nonfunction(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr i8, i8* %vtablei8, i32 0
+  %fptrptr_casted = bitcast i8* %fptrptr to i8**
+  %fptr = load i8*, i8** %fptrptr_casted
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  ; CHECK: call void %
+  call void %fptr_casted(i8* %obj)
+  ret void
+}
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare void @llvm.assume(i1)
+
+!0 = !{i32 0, !"typeid"}
+!1 = !{i32 0, !"typeid2"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel-threshold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel-threshold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel-threshold.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel-threshold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -wholeprogramdevirt-branch-funnel-threshold=1 -S -o - %s | not grep @llvm.icall.branch.funnel | count 0
+
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -wholeprogramdevirt-branch-funnel-threshold=10 -S -o - %s | grep @llvm.icall.branch.funnel | count 4
+
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -wholeprogramdevirt-branch-funnel-threshold=100 -S -o - %s | grep @llvm.icall.branch.funnel | count 5
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at vt1_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf1_1 to i8*)], !type !0
+ at vt1_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf1_2 to i8*)], !type !0
+
+declare i32 @vf1_1(i8* %this, i32 %arg)
+declare i32 @vf1_2(i8* %this, i32 %arg)
+
+ at vt2_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_1 to i8*)], !type !1
+ at vt2_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_2 to i8*)], !type !1
+ at vt2_3 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_3 to i8*)], !type !1
+ at vt2_4 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_4 to i8*)], !type !1
+ at vt2_5 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_5 to i8*)], !type !1
+ at vt2_6 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_6 to i8*)], !type !1
+ at vt2_7 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_7 to i8*)], !type !1
+ at vt2_8 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_8 to i8*)], !type !1
+ at vt2_9 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_9 to i8*)], !type !1
+ at vt2_10 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_10 to i8*)], !type !1
+ at vt2_11 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_11 to i8*)], !type !1
+
+declare i32 @vf2_1(i8* %this, i32 %arg)
+declare i32 @vf2_2(i8* %this, i32 %arg)
+declare i32 @vf2_3(i8* %this, i32 %arg)
+declare i32 @vf2_4(i8* %this, i32 %arg)
+declare i32 @vf2_5(i8* %this, i32 %arg)
+declare i32 @vf2_6(i8* %this, i32 %arg)
+declare i32 @vf2_7(i8* %this, i32 %arg)
+declare i32 @vf2_8(i8* %this, i32 %arg)
+declare i32 @vf2_9(i8* %this, i32 %arg)
+declare i32 @vf2_10(i8* %this, i32 %arg)
+declare i32 @vf2_11(i8* %this, i32 %arg)
+
+ at vt3_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf3_1 to i8*)], !type !2
+ at vt3_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf3_2 to i8*)], !type !2
+
+declare i32 @vf3_1(i8* %this, i32 %arg)
+declare i32 @vf3_2(i8* %this, i32 %arg)
+
+ at vt4_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf4_1 to i8*)], !type !3
+ at vt4_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf4_2 to i8*)], !type !3
+
+declare i32 @vf4_1(i8* %this, i32 %arg)
+declare i32 @vf4_2(i8* %this, i32 %arg)
+
+define i32 @fn1(i8* %obj) #0 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid1")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)*
+  %result = call i32 %fptr_casted(i8* %obj, i32 1)
+  ret i32 %result
+}
+
+define i32 @fn2(i8* %obj) #0 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid2")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)*
+  %result = call i32 %fptr_casted(i8* %obj, i32 1)
+  ret i32 %result
+}
+
+define i32 @fn3(i8* %obj) #0 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !4)
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)*
+  %result = call i32 %fptr_casted(i8* %obj, i32 1)
+  ret i32 %result
+}
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare void @llvm.assume(i1)
+
+!0 = !{i32 0, !"typeid1"}
+!1 = !{i32 0, !"typeid2"}
+!2 = !{i32 0, !"typeid3"}
+!3 = !{i32 0, !4}
+!4 = distinct !{}
+
+attributes #0 = { "target-features"="+retpoline" }

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,163 @@
+; RUN: opt -S -wholeprogramdevirt %s | FileCheck --check-prefixes=CHECK,RETP %s
+; RUN: sed -e 's,+retpoline,-retpoline,g' %s | opt -S -wholeprogramdevirt | FileCheck --check-prefixes=CHECK,NORETP %s
+
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck --check-prefixes=CHECK,RETP %s
+
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t  -O3 -S -o - %s | FileCheck --check-prefixes=CHECK %s
+
+; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+
+; SUMMARY:      TypeIdMap:       
+; SUMMARY-NEXT:   typeid3:
+; SUMMARY-NEXT:     TTRes:           
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:          
+; SUMMARY-NEXT:       0:               
+; SUMMARY-NEXT:         Kind:            BranchFunnel
+; SUMMARY-NEXT:         SingleImplName:  ''
+; SUMMARY-NEXT:         ResByArg:        
+; SUMMARY-NEXT:   typeid1:
+; SUMMARY-NEXT:     TTRes:           
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:          
+; SUMMARY-NEXT:       0:               
+; SUMMARY-NEXT:         Kind:            BranchFunnel
+; SUMMARY-NEXT:         SingleImplName:  ''
+; SUMMARY-NEXT:         ResByArg:        
+; SUMMARY-NEXT:   typeid2:
+; SUMMARY-NEXT:     TTRes:           
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:          
+; SUMMARY-NEXT:       0:               
+; SUMMARY-NEXT:         Kind:            Indir
+; SUMMARY-NEXT:         SingleImplName:  ''
+; SUMMARY-NEXT:         ResByArg:        
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at vt1_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf1_1 to i8*)], !type !0
+ at vt1_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf1_2 to i8*)], !type !0
+
+declare i32 @vf1_1(i8* %this, i32 %arg)
+declare i32 @vf1_2(i8* %this, i32 %arg)
+
+ at vt2_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_1 to i8*)], !type !1
+ at vt2_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_2 to i8*)], !type !1
+ at vt2_3 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_3 to i8*)], !type !1
+ at vt2_4 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_4 to i8*)], !type !1
+ at vt2_5 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_5 to i8*)], !type !1
+ at vt2_6 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_6 to i8*)], !type !1
+ at vt2_7 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_7 to i8*)], !type !1
+ at vt2_8 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_8 to i8*)], !type !1
+ at vt2_9 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_9 to i8*)], !type !1
+ at vt2_10 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_10 to i8*)], !type !1
+ at vt2_11 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2_11 to i8*)], !type !1
+
+declare i32 @vf2_1(i8* %this, i32 %arg)
+declare i32 @vf2_2(i8* %this, i32 %arg)
+declare i32 @vf2_3(i8* %this, i32 %arg)
+declare i32 @vf2_4(i8* %this, i32 %arg)
+declare i32 @vf2_5(i8* %this, i32 %arg)
+declare i32 @vf2_6(i8* %this, i32 %arg)
+declare i32 @vf2_7(i8* %this, i32 %arg)
+declare i32 @vf2_8(i8* %this, i32 %arg)
+declare i32 @vf2_9(i8* %this, i32 %arg)
+declare i32 @vf2_10(i8* %this, i32 %arg)
+declare i32 @vf2_11(i8* %this, i32 %arg)
+
+ at vt3_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf3_1 to i8*)], !type !2
+ at vt3_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf3_2 to i8*)], !type !2
+
+declare i32 @vf3_1(i8* %this, i32 %arg)
+declare i32 @vf3_2(i8* %this, i32 %arg)
+
+ at vt4_1 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf4_1 to i8*)], !type !3
+ at vt4_2 = constant [1 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf4_2 to i8*)], !type !3
+
+declare i32 @vf4_1(i8* %this, i32 %arg)
+declare i32 @vf4_2(i8* %this, i32 %arg)
+
+
+
+; CHECK-LABEL: define i32 @fn1
+; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
+define i32 @fn1(i8* %obj) #0 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid1")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)*
+  ; RETP: {{.*}} = bitcast {{.*}} to i8*
+  ; RETP: [[VT1:%.*]] = bitcast {{.*}} to i8*
+  ; RETP: call i32 bitcast (void (i8*, ...)* @__typeid_typeid1_0_branch_funnel to i32 (i8*, i8*, i32)*)(i8* nest [[VT1]], i8* %obj, i32 1)
+  %result = call i32 %fptr_casted(i8* %obj, i32 1)
+  ; NORETP: call i32 %
+  ret i32 %result
+}
+
+; CHECK-LABEL: define i32 @fn2
+; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
+define i32 @fn2(i8* %obj) #0 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid2")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)*
+  ; CHECK: call i32 %
+  %result = call i32 %fptr_casted(i8* %obj, i32 1)
+  ret i32 %result
+}
+
+; CHECK-LABEL: define i32 @fn3
+; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
+define i32 @fn3(i8* %obj) #0 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !4)
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)*
+  ; RETP: call i32 bitcast (void (i8*, ...)* @branch_funnel to
+  ; NORETP: call i32 %
+  %result = call i32 %fptr_casted(i8* %obj, i32 1)
+  ret i32 %result
+}
+
+; CHECK-LABEL: define internal void @branch_funnel(i8*
+; CHECK: define hidden void @__typeid_typeid1_0_branch_funnel(i8* nest, ...)
+; CHECK-NEXT: musttail call void (...) @llvm.icall.branch.funnel(i8* %0, i8* bitcast ([1 x i8*]* {{(nonnull )?}}@vt1_1 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_1, i8* bitcast ([1 x i8*]* {{(nonnull )?}}@vt1_2 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_2, ...)
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare void @llvm.assume(i1)
+
+!0 = !{i32 0, !"typeid1"}
+!1 = !{i32 0, !"typeid2"}
+!2 = !{i32 0, !"typeid3"}
+!3 = !{i32 0, !4}
+!4 = distinct !{}
+
+attributes #0 = { "target-features"="+retpoline" }

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/constant-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/constant-arg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/constant-arg.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/constant-arg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; RUN: opt -S -wholeprogramdevirt %s | FileCheck %s
+; RUN: opt -S -passes=wholeprogramdevirt %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: private constant { [8 x i8], [1 x i8*], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf1 to i8*)], [0 x i8] zeroinitializer }, !type [[T8:![0-9]+]]
+; CHECK: private constant { [8 x i8], [1 x i8*], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\02", [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf2 to i8*)], [0 x i8] zeroinitializer }, !type [[T8]]
+; CHECK: private constant { [8 x i8], [1 x i8*], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf4 to i8*)], [0 x i8] zeroinitializer }, !type [[T8]]
+; CHECK: private constant { [8 x i8], [1 x i8*], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\02", [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf8 to i8*)], [0 x i8] zeroinitializer }, !type [[T8]]
+
+ at vt1 = constant [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf1 to i8*)], !type !0
+ at vt2 = constant [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf2 to i8*)], !type !0
+ at vt4 = constant [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf4 to i8*)], !type !0
+ at vt8 = constant [1 x i8*] [i8* bitcast (i1 (i8*, i32)* @vf8 to i8*)], !type !0
+
+define i1 @vf1(i8* %this, i32 %arg) readnone {
+  %and = and i32 %arg, 1
+  %cmp = icmp ne i32 %and, 0
+  ret i1 %cmp
+}
+
+define i1 @vf2(i8* %this, i32 %arg) readnone {
+  %and = and i32 %arg, 2
+  %cmp = icmp ne i32 %and, 0
+  ret i1 %cmp
+}
+
+define i1 @vf4(i8* %this, i32 %arg) readnone {
+  %and = and i32 %arg, 4
+  %cmp = icmp ne i32 %and, 0
+  ret i1 %cmp
+}
+
+define i1 @vf8(i8* %this, i32 %arg) readnone {
+  %and = and i32 %arg, 8
+  %cmp = icmp ne i32 %and, 0
+  ret i1 %cmp
+}
+
+; CHECK: define i1 @call1
+define i1 @call1(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i1 (i8*, i32)*
+  ; CHECK: getelementptr {{.*}} -1
+  ; CHECK: and {{.*}}, 1
+  %result = call i1 %fptr_casted(i8* %obj, i32 5)
+  ret i1 %result
+}
+
+; CHECK: define i1 @call2
+define i1 @call2(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to i1 (i8*, i32)*
+  ; CHECK: getelementptr {{.*}} -1
+  ; CHECK: and {{.*}}, 2
+  %result = call i1 %fptr_casted(i8* %obj, i32 10)
+  ret i1 %result
+}
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare void @llvm.assume(i1)
+
+; CHECK: [[T8]] = !{i32 8, !"typeid"}
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl-check.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl-check.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl-check.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl-check.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -S -wholeprogramdevirt -pass-remarks=wholeprogramdevirt %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: remark: <unknown>:0:0: single-impl: devirtualized a call to vf
+; CHECK: remark: <unknown>:0:0: devirtualized vf
+; CHECK-NOT: devirtualized
+
+ at vt1 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf to i8*)], !type !0
+ at vt2 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf to i8*)], !type !0
+
+define void @vf(i8* %this) {
+  ret void
+}
+
+; CHECK: define void @call
+define void @call(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %pair = call {i8*, i1} @llvm.type.checked.load(i8* %vtablei8, i32 0, metadata !"typeid")
+  %fptr = extractvalue {i8*, i1} %pair, 0
+  %p = extractvalue {i8*, i1} %pair, 1
+  ; CHECK: br i1 true,
+  br i1 %p, label %cont, label %trap
+
+cont:
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  ; CHECK: call void @vf(
+  call void %fptr_casted(i8* %obj)
+  ret void
+
+trap:
+  call void @llvm.trap()
+  unreachable
+}
+
+declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata)
+declare void @llvm.trap()
+
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/devirt-single-impl.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,47 @@
+; RUN: opt -S -wholeprogramdevirt -pass-remarks=wholeprogramdevirt %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: remark: devirt-single.cc:30:32: single-impl: devirtualized a call to vf
+; CHECK: remark: devirt-single.cc:13:0: devirtualized vf
+; CHECK-NOT: devirtualized
+
+ at vt1 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf to i8*)], !type !8
+ at vt2 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf to i8*)], !type !8
+
+define void @vf(i8* %this) #0 !dbg !7 {
+  ret void
+}
+
+; CHECK: define void @call
+define void @call(i8* %obj) #1 !dbg !5 {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
+  call void @llvm.assume(i1 %p)
+  %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
+  %fptr = load i8*, i8** %fptrptr
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  ; CHECK: call void @vf(
+  call void %fptr_casted(i8* %obj), !dbg !6
+  ret void
+}
+
+declare i1 @llvm.type.test(i8*, metadata)
+declare void @llvm.assume(i1)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+!llvm.ident = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 (trunk 278098)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "devirt-single.cc", directory: ".")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{!"clang version 4.0.0 (trunk 278098)"}
+!5 = distinct !DISubprogram(name: "call", linkageName: "_Z4callPv", scope: !1, file: !1, line: 29, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
+!6 = !DILocation(line: 30, column: 32, scope: !5)
+!7 = distinct !DISubprogram(name: "vf", linkageName: "_ZN3vt12vfEv", scope: !1, file: !1, line: 13, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
+!8 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/expand-check.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/expand-check.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/expand-check.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/expand-check.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,63 @@
+; RUN: opt -S -wholeprogramdevirt %s | FileCheck %s
+
+; Test that we correctly expand the llvm.type.checked.load intrinsic in cases
+; where we cannot devirtualize.
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at vt1 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf1 to i8*)], !type !0
+ at vt2 = constant [1 x i8*] [i8* bitcast (void (i8*)* @vf2 to i8*)], !type !0
+
+define void @vf1(i8* %this) {
+  ret void
+}
+
+define void @vf2(i8* %this) {
+  ret void
+}
+
+; CHECK: define void @call
+define void @call(i8* %obj) {
+  %vtableptr = bitcast i8* %obj to [1 x i8*]**
+  %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
+  %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
+  %pair = call {i8*, i1} @llvm.type.checked.load(i8* %vtablei8, i32 0, metadata !"typeid")
+  %p = extractvalue {i8*, i1} %pair, 1
+  ; CHECK: [[TT:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT:%[^,]*]], metadata !"typeid")
+  ; CHECK: br i1 [[TT]],
+  br i1 %p, label %cont, label %trap
+
+cont:
+  ; CHECK: [[GEP:%[^ ]*]] = getelementptr i8, i8* [[VT]], i32 0
+  ; CHECK: [[BC:%[^ ]*]] = bitcast i8* [[GEP]] to i8**
+  ; CHECK: [[LOAD:%[^ ]*]] = load i8*, i8** [[BC]]
+  ; CHECK: [[FPC:%[^ ]*]] = bitcast i8* [[LOAD]] to void (i8*)*
+  ; CHECK: call void [[FPC]]
+  %fptr = extractvalue {i8*, i1} %pair, 0
+  %fptr_casted = bitcast i8* %fptr to void (i8*)*
+  call void %fptr_casted(i8* %obj)
+  ret void
+
+trap:
+  call void @llvm.trap()
+  unreachable
+}
+
+; CHECK: define { i8*, i1 } @ret
+define {i8*, i1} @ret(i8* %vtablei8) {
+  ; CHECK: [[GEP2:%[^ ]*]] = getelementptr i8, i8* [[VT2:%[^,]*]], i32 1
+  ; CHECK: [[BC2:%[^ ]*]] = bitcast i8* [[GEP2]] to i8**
+  ; CHECK: [[LOAD2:%[^ ]*]] = load i8*, i8** [[BC2]]
+  ; CHECK: [[TT2:%[^ ]*]] = call i1 @llvm.type.test(i8* [[VT2]], metadata !"typeid")
+  ; CHECK: [[I1:%[^ ]*]] = insertvalue { i8*, i1 } undef, i8* [[LOAD2]], 0
+  ; CHECK: [[I2:%[^ ]*]] = insertvalue { i8*, i1 } %5, i1 [[TT2]], 1
+  %pair = call {i8*, i1} @llvm.type.checked.load(i8* %vtablei8, i32 1, metadata !"typeid")
+  ; CHECK: ret { i8*, i1 } [[I2]]
+  ret {i8*, i1} %pair
+}
+
+declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata)
+declare void @llvm.trap()
+
+!0 = !{i32 0, !"typeid"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-nothing.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,8 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-write-summary=%t -o /dev/null %s
+; RUN: FileCheck %s < %t
+
+; CHECK: ---
+; CHECK-NEXT: GlobalValueMap:
+; CHECK-NEXT: TypeIdMap:
+; CHECK-NEXT: WithGlobalValueDeadStripping: false
+; CHECK-NEXT: ...

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/export-single-impl.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/export-single-impl.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/export-single-impl.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-single-impl.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,101 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck %s
+; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+
+; SUMMARY:      TypeIdMap:
+; SUMMARY-NEXT:   typeid3:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            SingleImpl
+; SUMMARY-NEXT:         SingleImplName:  'vf3$merged'
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT:   typeid1:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            SingleImpl
+; SUMMARY-NEXT:         SingleImplName:  vf1
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT:   typeid2:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            SingleImpl
+; SUMMARY-NEXT:         SingleImplName:  vf2
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT:   typeid4:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            SingleImpl
+; SUMMARY-NEXT:         SingleImplName:  'vf4$merged'
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT: WithGlobalValueDeadStripping: false
+; SUMMARY-NEXT: ...
+
+; CHECK: $"vf4$merged" = comdat largest
+$vf4 = comdat largest
+
+; CHECK: @vt1 = constant void (i8*)* @vf1
+ at vt1 = constant void (i8*)* @vf1, !type !0
+
+; CHECK: @vt2 = constant void (i8*)* @vf2
+ at vt2 = constant void (i8*)* @vf2, !type !1
+
+ at vt3 = constant void (i8*)* @vf3, !type !2
+
+; CHECK: @vt4 = constant void (i8*)* @"vf4$merged", comdat($"vf4$merged")
+ at vt4 = constant void (i8*)* @vf4, comdat($vf4), !type !3
+
+ at vt5 = constant void (i8*)* @vf5, !type !4
+
+; CHECK: declare void @vf1(i8*)
+declare void @vf1(i8*)
+
+; CHECK: define void @vf2(i8*)
+define void @vf2(i8*) {
+  ret void
+}
+
+; CHECK: define hidden void @"vf3$merged"(i8*) {
+define internal void @vf3(i8*) {
+  ret void
+}
+
+; CHECK: define hidden void @"vf4$merged"(i8*) comdat {
+define internal void @vf4(i8*) comdat {
+  ret void
+}
+
+declare void @vf5(i8*)
+
+!0 = !{i32 0, !"typeid1"}
+!1 = !{i32 0, !"typeid2"}
+!2 = !{i32 0, !"typeid3"}
+!3 = !{i32 0, !"typeid4"}
+!4 = !{i32 0, !5}
+!5 = distinct !{}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,41 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck %s
+; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+
+; SUMMARY-NOT: TypeTests:
+
+; SUMMARY:      TypeIdMap:
+; SUMMARY-NEXT:   typeid4:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            Indir
+; SUMMARY-NEXT:         SingleImplName:  ''
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT:           24,12:
+; SUMMARY-NEXT:             Kind:            UniformRetVal
+; SUMMARY-NEXT:             Info:            36
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
+
+; CHECK: @vt4a = constant i32 (i8*, i32, i32)* @vf4a
+ at vt4a = constant i32 (i8*, i32, i32)* @vf4a, !type !0
+
+; CHECK: @vt4b = constant i32 (i8*, i32, i32)* @vf4b
+ at vt4b = constant i32 (i8*, i32, i32)* @vf4b, !type !0
+
+define i32 @vf4a(i8*, i32 %x, i32 %y) {
+  %z = add i32 %x, %y
+  ret i32 %z
+}
+
+define i32 @vf4b(i8*, i32 %x, i32 %y) {
+  ret i32 36
+}
+
+!0 = !{i32 0, !"typeid4"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,90 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck %s
+; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+
+; SUMMARY-NOT:  TypeTests:
+
+; SUMMARY:      TypeIdMap:
+; SUMMARY-NEXT:   typeid3:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            Indir
+; SUMMARY-NEXT:         SingleImplName:  ''
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT:           12,24:
+; SUMMARY-NEXT:             Kind:            UniqueRetVal
+; SUMMARY-NEXT:             Info:            0
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
+; SUMMARY-NEXT:   typeid4:
+; SUMMARY-NEXT:     TTRes:
+; SUMMARY-NEXT:       Kind:            Unsat
+; SUMMARY-NEXT:       SizeM1BitWidth:  0
+; SUMMARY-NEXT:       AlignLog2:       0
+; SUMMARY-NEXT:       SizeM1:          0
+; SUMMARY-NEXT:       BitMask:         0
+; SUMMARY-NEXT:       InlineBits:      0
+; SUMMARY-NEXT:     WPDRes:
+; SUMMARY-NEXT:       0:
+; SUMMARY-NEXT:         Kind:            Indir
+; SUMMARY-NEXT:         SingleImplName:  ''
+; SUMMARY-NEXT:         ResByArg:
+; SUMMARY-NEXT:           24,12:
+; SUMMARY-NEXT:             Kind:            UniqueRetVal
+; SUMMARY-NEXT:             Info:            1
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
+
+; CHECK: @vt3a = constant i1 (i8*, i32, i32)* @vf3a
+ at vt3a = constant i1 (i8*, i32, i32)* @vf3a, !type !0
+
+; CHECK: @vt3b = constant i1 (i8*, i32, i32)* @vf3b
+ at vt3b = constant i1 (i8*, i32, i32)* @vf3b, !type !0
+
+; CHECK: @vt3c = constant i1 (i8*, i32, i32)* @vf3c
+ at vt3c = constant i1 (i8*, i32, i32)* @vf3c, !type !0
+
+; CHECK: @vt4a = constant i1 (i8*, i32, i32)* @vf4a
+ at vt4a = constant i1 (i8*, i32, i32)* @vf4a, !type !1
+
+; CHECK: @vt4b = constant i1 (i8*, i32, i32)* @vf4b
+ at vt4b = constant i1 (i8*, i32, i32)* @vf4b, !type !1
+
+; CHECK: @vt4c = constant i1 (i8*, i32, i32)* @vf4c
+ at vt4c = constant i1 (i8*, i32, i32)* @vf4c, !type !1
+
+; CHECK: @__typeid_typeid3_0_12_24_unique_member = hidden alias i8, bitcast (i1 (i8*, i32, i32)** @vt3b to i8*)
+; CHECK: @__typeid_typeid4_0_24_12_unique_member = hidden alias i8, bitcast (i1 (i8*, i32, i32)** @vt4b to i8*)
+
+define i1 @vf3a(i8*, i32, i32) {
+  ret i1 true
+}
+
+define i1 @vf3b(i8*, i32, i32) {
+  ret i1 false
+}
+
+define i1 @vf3c(i8*, i32, i32) {
+  ret i1 true
+}
+
+define i1 @vf4a(i8*, i32, i32) {
+  ret i1 false
+}
+
+define i1 @vf4b(i8*, i32, i32) {
+  ret i1 true
+}
+
+define i1 @vf4c(i8*, i32, i32) {
+  ret i1 false
+}
+
+!0 = !{i32 0, !"typeid3"}
+!1 = !{i32 0, !"typeid4"}

Added: llvm/trunk/test/Transforms/WholeProgramDevirt/export-unsuccessful-checked.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/export-unsuccessful-checked.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/export-unsuccessful-checked.ll (added)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-unsuccessful-checked.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -o /dev/null %s
+; RUN: FileCheck %s < %t
+
+; CHECK:       TypeTests: [ 15427464259790519041, 17525413373118030901 ]
+; CHECK-NEXT:  TypeTestAssumeVCalls:
+
+ at vt1a = constant void (i8*)* @vf1a, !type !0
+ at vt1b = constant void (i8*)* @vf1b, !type !0
+ at vt2a = constant void (i8*)* @vf2a, !type !1
+ at vt2b = constant void (i8*)* @vf2b, !type !1
+ at vt3a = constant void (i8*)* @vf3a, !type !2
+ at vt3b = constant void (i8*)* @vf3b, !type !2
+ at vt4a = constant void (i8*)* @vf4a, !type !3
+ at vt4b = constant void (i8*)* @vf4b, !type !3
+
+declare void @vf1a(i8*)
+declare void @vf1b(i8*)
+declare void @vf2a(i8*)
+declare void @vf2b(i8*)
+declare void @vf3a(i8*)
+declare void @vf3b(i8*)
+declare void @vf4a(i8*)
+declare void @vf4b(i8*)
+
+!0 = !{i32 0, !"typeid1"}
+!1 = !{i32 0, !"typeid2"}
+!2 = !{i32 0, !"typeid3"}
+!3 = !{i32 0, !"typeid4"}




More information about the llvm-commits mailing list