[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/DeadStoreElimination/tail-byval.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/tail-byval.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/DeadStoreElimination/tail-byval.ll (added)
+++ llvm/trunk/test/Transforms/DeadStoreElimination/tail-byval.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -dse -S < %s | FileCheck %s
+
+; Don't eliminate stores to allocas before tail calls to functions that use
+; byval. It's correct to mark calls like these as 'tail'. To implement this tail
+; call, the backend should copy the bytes from the alloca into the argument area
+; before clearing the stack.
+
+target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
+target triple = "i386-unknown-linux-gnu"
+
+declare void @g(i32* byval %p)
+
+define void @f(i32* byval %x) {
+entry:
+  %p = alloca i32
+  %v = load i32, i32* %x
+  store i32 %v, i32* %p
+  tail call void @g(i32* byval %p)
+  ret void
+}
+; CHECK-LABEL: define void @f(i32* byval %x)
+; CHECK:   store i32 %v, i32* %p
+; CHECK:   tail call void @g(i32* byval %p)

Added: llvm/trunk/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll (added)
+++ llvm/trunk/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,303 @@
+; RUN: opt < %s -div-rem-pairs -S -mtriple=powerpc64-unknown-unknown | FileCheck %s
+
+declare void @foo(i32, i32)
+
+define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) {
+; CHECK-LABEL: @decompose_illegal_srem_same_block(
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[DIV]], %b
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 %a, [[TMP1]]
+; CHECK-NEXT:    call void @foo(i32 [[TMP2]], i32 [[DIV]])
+; CHECK-NEXT:    ret void
+;
+  %rem = srem i32 %a, %b
+  %div = sdiv i32 %a, %b
+  call void @foo(i32 %rem, i32 %div)
+  ret void
+}
+
+define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) {
+; CHECK-LABEL: @decompose_illegal_urem_same_block(
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 %a, %b
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[DIV]], %b
+; CHECK-NEXT:    [[TMP2:%.*]] = sub i32 %a, [[TMP1]]
+; CHECK-NEXT:    call void @foo(i32 [[TMP2]], i32 [[DIV]])
+; CHECK-NEXT:    ret void
+;
+  %div = udiv i32 %a, %b
+  %rem = urem i32 %a, %b
+  call void @foo(i32 %rem, i32 %div)
+  ret void
+}
+
+; Hoist and optionally decompose the sdiv because it's safe and free.
+; PR31028 - https://bugs.llvm.org/show_bug.cgi?id=31028
+
+define i32 @hoist_sdiv(i32 %a, i32 %b) {
+; CHECK-LABEL: @hoist_sdiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i32 [[DIV]], %b
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 %a, [[TMP0]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; 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
+}
+
+; Hoist and optionally decompose the udiv because it's safe and free.
+
+define i64 @hoist_udiv(i64 %a, i64 %b) {
+; CHECK-LABEL: @hoist_udiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i64 %a, %b
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i64 [[DIV]], %b
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 %a, [[TMP0]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[TMP1]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; 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
+}
+
+; Hoist the srem if it's safe and free, otherwise decompose it.
+
+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:    [[TMP0:%.*]] = mul i16 [[DIV]], %b
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i16 %a, [[TMP0]]
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i16 [ [[TMP1]], %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
+}
+
+; Hoist the urem if it's safe and free, otherwise decompose it.
+
+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:    [[TMP0:%.*]] = mul i8 [[DIV]], %b
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 %a, [[TMP0]]
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i8 [ [[TMP1]], %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
+}
+
+; If the ops don't match, don't do anything: signedness.
+
+define i32 @dont_hoist_udiv(i32 %a, i32 %b) {
+; CHECK-LABEL: @dont_hoist_udiv(
+; 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:%.*]] = udiv 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 = udiv i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+; If the ops don't match, don't do anything: operation.
+
+define i32 @dont_hoist_srem(i32 %a, i32 %b) {
+; CHECK-LABEL: @dont_hoist_srem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[REM:%.*]] = urem i32 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[REM]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[REM2:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i32 [ [[REM2]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+entry:
+  %rem = urem i32 %a, %b
+  %cmp = icmp eq i32 %rem, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %rem2 = srem i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %rem2, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+; If the ops don't match, don't do anything: operands.
+
+define i32 @dont_hoist_sdiv(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @dont_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, %c
+; 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, %c
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+; If the target doesn't have a unified div/rem op for the type, decompose rem in-place to mul+sub.
+
+define i128 @dont_hoist_urem(i128 %a, i128 %b) {
+; CHECK-LABEL: @dont_hoist_urem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i128 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i128 [[DIV]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i128 [[DIV]], %b
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i128 %a, [[TMP0]]
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i128 [ [[TMP1]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i128 [[RET]]
+;
+entry:
+  %div = udiv i128 %a, %b
+  %cmp = icmp eq i128 %div, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %rem = urem i128 %a, %b
+  br label %end
+
+end:
+  %ret = phi i128 [ %rem, %if ], [ 3, %entry ]
+  ret i128 %ret
+}
+
+; We don't hoist if one op does not dominate the other,
+; but we could hoist both ops to the common predecessor block?
+
+define i32 @no_domination(i1 %cmp, i32 %a, i32 %b) {
+; CHECK-LABEL: @no_domination(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 %cmp, label %if, label %else
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       else:
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ [[REM]], %else ]
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+entry:
+  br i1 %cmp, label %if, label %else
+
+if:
+  %div = sdiv i32 %a, %b
+  br label %end
+
+else:
+  %rem = srem i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ %rem, %else ]
+  ret i32 %ret
+}
+

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

Added: llvm/trunk/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll (added)
+++ llvm/trunk/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,297 @@
+; RUN: opt < %s -div-rem-pairs -S -mtriple=x86_64-unknown-unknown    | FileCheck %s
+
+declare void @foo(i32, i32)
+
+define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) {
+; CHECK-LABEL: @decompose_illegal_srem_same_block(
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    call void @foo(i32 [[REM]], i32 [[DIV]])
+; CHECK-NEXT:    ret void
+;
+  %rem = srem i32 %a, %b
+  %div = sdiv i32 %a, %b
+  call void @foo(i32 %rem, i32 %div)
+  ret void
+}
+
+define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) {
+; CHECK-LABEL: @decompose_illegal_urem_same_block(
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 %a, %b
+; CHECK-NEXT:    [[REM:%.*]] = urem i32 %a, %b
+; CHECK-NEXT:    call void @foo(i32 [[REM]], i32 [[DIV]])
+; CHECK-NEXT:    ret void
+;
+  %div = udiv i32 %a, %b
+  %rem = urem i32 %a, %b
+  call void @foo(i32 %rem, i32 %div)
+  ret void
+}
+
+; Hoist and optionally decompose the sdiv because it's safe and free.
+; PR31028 - https://bugs.llvm.org/show_bug.cgi?id=31028
+
+define i32 @hoist_sdiv(i32 %a, i32 %b) {
+; CHECK-LABEL: @hoist_sdiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[REM]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; 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
+}
+
+; Hoist and optionally decompose the udiv because it's safe and free.
+
+define i64 @hoist_udiv(i64 %a, i64 %b) {
+; CHECK-LABEL: @hoist_udiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[REM:%.*]] = urem i64 %a, %b
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i64 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[REM]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; 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
+}
+
+; Hoist the srem if it's safe and free, otherwise decompose it.
+
+define i16 @hoist_srem(i16 %a, i16 %b) {
+; CHECK-LABEL: @hoist_srem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i16 %a, %b
+; CHECK-NEXT:    [[REM:%.*]] = srem i16 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[DIV]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; 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
+}
+
+; Hoist the urem if it's safe and free, otherwise decompose it.
+
+define i8 @hoist_urem(i8 %a, i8 %b) {
+; CHECK-LABEL: @hoist_urem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i8 %a, %b
+; CHECK-NEXT:    [[REM:%.*]] = urem i8 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[DIV]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; 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
+}
+
+; If the ops don't match, don't do anything: signedness.
+
+define i32 @dont_hoist_udiv(i32 %a, i32 %b) {
+; CHECK-LABEL: @dont_hoist_udiv(
+; 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:%.*]] = udiv 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 = udiv i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+; If the ops don't match, don't do anything: operation.
+
+define i32 @dont_hoist_srem(i32 %a, i32 %b) {
+; CHECK-LABEL: @dont_hoist_srem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[REM:%.*]] = urem i32 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[REM]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[REM2:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i32 [ [[REM2]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+entry:
+  %rem = urem i32 %a, %b
+  %cmp = icmp eq i32 %rem, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %rem2 = srem i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %rem2, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+; If the ops don't match, don't do anything: operands.
+
+define i32 @dont_hoist_sdiv(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @dont_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, %c
+; 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, %c
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ 3, %entry ]
+  ret i32 %ret
+}
+
+; If the target doesn't have a unified div/rem op for the type, decompose rem in-place to mul+sub.
+
+define i128 @dont_hoist_urem(i128 %a, i128 %b) {
+; CHECK-LABEL: @dont_hoist_urem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV:%.*]] = udiv i128 %a, %b
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i128 [[DIV]], 42
+; CHECK-NEXT:    br i1 [[CMP]], label %if, label %end
+; CHECK:       if:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i128 [[DIV]], %b
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i128 %a, [[TMP0]]
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i128 [ [[TMP1]], %if ], [ 3, %entry ]
+; CHECK-NEXT:    ret i128 [[RET]]
+;
+entry:
+  %div = udiv i128 %a, %b
+  %cmp = icmp eq i128 %div, 42
+  br i1 %cmp, label %if, label %end
+
+if:
+  %rem = urem i128 %a, %b
+  br label %end
+
+end:
+  %ret = phi i128 [ %rem, %if ], [ 3, %entry ]
+  ret i128 %ret
+}
+
+; We don't hoist if one op does not dominate the other,
+; but we could hoist both ops to the common predecessor block?
+
+define i32 @no_domination(i1 %cmp, i32 %a, i32 %b) {
+; CHECK-LABEL: @no_domination(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 %cmp, label %if, label %else
+; CHECK:       if:
+; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       else:
+; CHECK-NEXT:    [[REM:%.*]] = srem i32 %a, %b
+; CHECK-NEXT:    br label %end
+; CHECK:       end:
+; CHECK-NEXT:    [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ [[REM]], %else ]
+; CHECK-NEXT:    ret i32 [[RET]]
+;
+entry:
+  br i1 %cmp, label %if, label %else
+
+if:
+  %div = sdiv i32 %a, %b
+  br label %end
+
+else:
+  %rem = srem i32 %a, %b
+  br label %end
+
+end:
+  %ret = phi i32 [ %div, %if ], [ %rem, %else ]
+  ret i32 %ret
+}
+

Added: llvm/trunk/test/Transforms/DivRemPairs/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DivRemPairs/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/DivRemPairs/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/DivRemPairs/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/EarlyCSE/AArch64/intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/AArch64/intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/AArch64/intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/AArch64/intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,234 @@
+; RUN: opt < %s -S -mtriple=aarch64-none-linux-gnu -mattr=+neon -early-cse | FileCheck %s
+; RUN: opt < %s -S -mtriple=aarch64-none-linux-gnu -mattr=+neon -basicaa -early-cse-memssa | FileCheck %s
+; RUN: opt < %s -S -mtriple=aarch64-none-linux-gnu -mattr=+neon -passes=early-cse | FileCheck %s
+; RUN: opt < %s -S -mtriple=aarch64-none-linux-gnu -mattr=+neon -aa-pipeline=basic-aa -passes=early-cse-memssa | FileCheck %s
+
+define <4 x i32> @test_cse(i32* %a, [2 x <4 x i32>] %s.coerce, i32 %n) {
+entry:
+; Check that @llvm.aarch64.neon.ld2 is optimized away by Early CSE.
+; CHECK-LABEL: @test_cse
+; CHECK-NOT: call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8
+  %s.coerce.fca.0.extract = extractvalue [2 x <4 x i32>] %s.coerce, 0
+  %s.coerce.fca.1.extract = extractvalue [2 x <4 x i32>] %s.coerce, 1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %res.0 = phi <4 x i32> [ undef, %entry ], [ %call, %for.body ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %0 = bitcast i32* %a to i8*
+  %1 = bitcast <4 x i32> %s.coerce.fca.0.extract to <16 x i8>
+  %2 = bitcast <4 x i32> %s.coerce.fca.1.extract to <16 x i8>
+  %3 = bitcast <16 x i8> %1 to <4 x i32>
+  %4 = bitcast <16 x i8> %2 to <4 x i32>
+  call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %4, i8* %0)
+  %5 = bitcast i32* %a to i8*
+  %vld2 = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8(i8* %5)
+  %vld2.fca.0.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 0
+  %vld2.fca.1.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 1
+  %call = call <4 x i32> @vaddq_s32(<4 x i32> %vld2.fca.0.extract, <4 x i32> %vld2.fca.0.extract)
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret <4 x i32> %res.0
+}
+
+define <4 x i32> @test_cse2(i32* %a, [2 x <4 x i32>] %s.coerce, i32 %n) {
+entry:
+; Check that the first @llvm.aarch64.neon.st2 is optimized away by Early CSE.
+; CHECK-LABEL: @test_cse2
+; CHECK-NOT: call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %3, i8* %0)
+; CHECK: call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %s.coerce.fca.0.extract, <4 x i32> %s.coerce.fca.1.extract, i8* %0)
+  %s.coerce.fca.0.extract = extractvalue [2 x <4 x i32>] %s.coerce, 0
+  %s.coerce.fca.1.extract = extractvalue [2 x <4 x i32>] %s.coerce, 1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %res.0 = phi <4 x i32> [ undef, %entry ], [ %call, %for.body ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %0 = bitcast i32* %a to i8*
+  %1 = bitcast <4 x i32> %s.coerce.fca.0.extract to <16 x i8>
+  %2 = bitcast <4 x i32> %s.coerce.fca.1.extract to <16 x i8>
+  %3 = bitcast <16 x i8> %1 to <4 x i32>
+  %4 = bitcast <16 x i8> %2 to <4 x i32>
+  call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %3, i8* %0)
+  call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %4, i8* %0)
+  %5 = bitcast i32* %a to i8*
+  %vld2 = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8(i8* %5)
+  %vld2.fca.0.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 0
+  %vld2.fca.1.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 1
+  %call = call <4 x i32> @vaddq_s32(<4 x i32> %vld2.fca.0.extract, <4 x i32> %vld2.fca.0.extract)
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret <4 x i32> %res.0
+}
+
+define <4 x i32> @test_cse3(i32* %a, [2 x <4 x i32>] %s.coerce, i32 %n) #0 {
+entry:
+; Check that the first @llvm.aarch64.neon.ld2 is optimized away by Early CSE.
+; CHECK-LABEL: @test_cse3
+; CHECK: call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8
+; CHECK-NOT: call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8
+  %s.coerce.fca.0.extract = extractvalue [2 x <4 x i32>] %s.coerce, 0
+  %s.coerce.fca.1.extract = extractvalue [2 x <4 x i32>] %s.coerce, 1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %res.0 = phi <4 x i32> [ undef, %entry ], [ %call, %for.body ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %0 = bitcast i32* %a to i8*
+  %vld2 = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8(i8* %0)
+  %vld2.fca.0.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 0
+  %vld2.fca.1.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 1
+  %1 = bitcast i32* %a to i8*
+  %vld22 = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8(i8* %1)
+  %vld22.fca.0.extract = extractvalue { <4 x i32>, <4 x i32> } %vld22, 0
+  %vld22.fca.1.extract = extractvalue { <4 x i32>, <4 x i32> } %vld22, 1
+  %call = call <4 x i32> @vaddq_s32(<4 x i32> %vld2.fca.0.extract, <4 x i32> %vld22.fca.0.extract)
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret <4 x i32> %res.0
+}
+
+
+define <4 x i32> @test_nocse(i32* %a, i32* %b, [2 x <4 x i32>] %s.coerce, i32 %n) {
+entry:
+; Check that the store prevents @llvm.aarch64.neon.ld2 from being optimized
+; away by Early CSE.
+; CHECK-LABEL: @test_nocse
+; CHECK: call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8
+  %s.coerce.fca.0.extract = extractvalue [2 x <4 x i32>] %s.coerce, 0
+  %s.coerce.fca.1.extract = extractvalue [2 x <4 x i32>] %s.coerce, 1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %res.0 = phi <4 x i32> [ undef, %entry ], [ %call, %for.body ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %0 = bitcast i32* %a to i8*
+  %1 = bitcast <4 x i32> %s.coerce.fca.0.extract to <16 x i8>
+  %2 = bitcast <4 x i32> %s.coerce.fca.1.extract to <16 x i8>
+  %3 = bitcast <16 x i8> %1 to <4 x i32>
+  %4 = bitcast <16 x i8> %2 to <4 x i32>
+  call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %4, i8* %0)
+  store i32 0, i32* %b, align 4
+  %5 = bitcast i32* %a to i8*
+  %vld2 = call { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8(i8* %5)
+  %vld2.fca.0.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 0
+  %vld2.fca.1.extract = extractvalue { <4 x i32>, <4 x i32> } %vld2, 1
+  %call = call <4 x i32> @vaddq_s32(<4 x i32> %vld2.fca.0.extract, <4 x i32> %vld2.fca.0.extract)
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret <4 x i32> %res.0
+}
+
+define <4 x i32> @test_nocse2(i32* %a, [2 x <4 x i32>] %s.coerce, i32 %n) {
+entry:
+; Check that @llvm.aarch64.neon.ld3 is not optimized away by Early CSE due
+; to mismatch between st2 and ld3.
+; CHECK-LABEL: @test_nocse2
+; CHECK: call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0i8
+  %s.coerce.fca.0.extract = extractvalue [2 x <4 x i32>] %s.coerce, 0
+  %s.coerce.fca.1.extract = extractvalue [2 x <4 x i32>] %s.coerce, 1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %res.0 = phi <4 x i32> [ undef, %entry ], [ %call, %for.body ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %0 = bitcast i32* %a to i8*
+  %1 = bitcast <4 x i32> %s.coerce.fca.0.extract to <16 x i8>
+  %2 = bitcast <4 x i32> %s.coerce.fca.1.extract to <16 x i8>
+  %3 = bitcast <16 x i8> %1 to <4 x i32>
+  %4 = bitcast <16 x i8> %2 to <4 x i32>
+  call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %4, i8* %0)
+  %5 = bitcast i32* %a to i8*
+  %vld3 = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0i8(i8* %5)
+  %vld3.fca.0.extract = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } %vld3, 0
+  %vld3.fca.2.extract = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } %vld3, 2
+  %call = call <4 x i32> @vaddq_s32(<4 x i32> %vld3.fca.0.extract, <4 x i32> %vld3.fca.2.extract)
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret <4 x i32> %res.0
+}
+
+define <4 x i32> @test_nocse3(i32* %a, [2 x <4 x i32>] %s.coerce, i32 %n) {
+entry:
+; Check that @llvm.aarch64.neon.st3 is not optimized away by Early CSE due to
+; mismatch between st2 and st3.
+; CHECK-LABEL: @test_nocse3
+; CHECK: call void @llvm.aarch64.neon.st3.v4i32.p0i8
+; CHECK: call void @llvm.aarch64.neon.st2.v4i32.p0i8
+  %s.coerce.fca.0.extract = extractvalue [2 x <4 x i32>] %s.coerce, 0
+  %s.coerce.fca.1.extract = extractvalue [2 x <4 x i32>] %s.coerce, 1
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %res.0 = phi <4 x i32> [ undef, %entry ], [ %call, %for.body ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %0 = bitcast i32* %a to i8*
+  %1 = bitcast <4 x i32> %s.coerce.fca.0.extract to <16 x i8>
+  %2 = bitcast <4 x i32> %s.coerce.fca.1.extract to <16 x i8>
+  %3 = bitcast <16 x i8> %1 to <4 x i32>
+  %4 = bitcast <16 x i8> %2 to <4 x i32>
+  call void @llvm.aarch64.neon.st3.v4i32.p0i8(<4 x i32> %4, <4 x i32> %3, <4 x i32> %3, i8* %0)
+  call void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32> %3, <4 x i32> %3, i8* %0)
+  %5 = bitcast i32* %a to i8*
+  %vld3 = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0i8(i8* %5)
+  %vld3.fca.0.extract = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } %vld3, 0
+  %vld3.fca.1.extract = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } %vld3, 1
+  %call = call <4 x i32> @vaddq_s32(<4 x i32> %vld3.fca.0.extract, <4 x i32> %vld3.fca.0.extract)
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret <4 x i32> %res.0
+}
+
+; Function Attrs: nounwind
+declare void @llvm.aarch64.neon.st2.v4i32.p0i8(<4 x i32>, <4 x i32>, i8* nocapture)
+
+; Function Attrs: nounwind
+declare void @llvm.aarch64.neon.st3.v4i32.p0i8(<4 x i32>, <4 x i32>, <4 x i32>, i8* nocapture)
+
+; Function Attrs: nounwind readonly
+declare { <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld2.v4i32.p0i8(i8*)
+
+; Function Attrs: nounwind readonly
+declare { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.aarch64.neon.ld3.v4i32.p0i8(i8*)
+
+define internal fastcc <4 x i32> @vaddq_s32(<4 x i32> %__p0, <4 x i32> %__p1) {
+entry:
+  %add = add <4 x i32> %__p0, %__p1
+  ret <4 x i32> %add
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/AArch64/ldstN.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/AArch64/ldstN.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/AArch64/ldstN.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/AArch64/ldstN.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+; RUN: opt -S -basicaa -early-cse-memssa < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+declare { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4.v4i16.p0v4i16(<4 x i16>*)
+
+; Although the store and the ld4 are using the same pointer, the
+; data can not be reused because ld4 accesses multiple elements.
+define { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @foo() {
+entry:
+  store <4 x i16> undef, <4 x i16>* undef, align 8
+  %0 = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.aarch64.neon.ld4.v4i16.p0v4i16(<4 x i16>* undef)
+  ret { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %0
+; CHECK-LABEL: @foo(
+; CHECK: store
+; CHECK-NEXT: call
+; CHECK-NEXT: ret
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/AArch64/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/AArch64/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/AArch64/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/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/EarlyCSE/AMDGPU/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/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 'AMDGPU' in targets:
+    config.unsupported = True

Added: llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/memrealtime.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/memrealtime.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/memrealtime.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/AMDGPU/memrealtime.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -early-cse-memssa < %s | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5"
+
+; CHECK-LABEL: @memrealtime(
+; CHECK: call i64 @llvm.amdgcn.s.memrealtime()
+; CHECK: call i64 @llvm.amdgcn.s.memrealtime()
+define amdgpu_kernel void @memrealtime(i64 %cycles) #0 {
+entry:
+  %0 = tail call i64 @llvm.amdgcn.s.memrealtime()
+  %cmp3 = icmp sgt i64 %cycles, 0
+  br i1 %cmp3, label %while.body, label %while.end
+
+while.body:
+  %1 = tail call i64 @llvm.amdgcn.s.memrealtime()
+  %sub = sub nsw i64 %1, %0
+  %cmp = icmp slt i64 %sub, %cycles
+  br i1 %cmp, label %while.body, label %while.end
+
+while.end:
+  ret void
+}
+
+; CHECK-LABEL: @memtime(
+; CHECK: call i64 @llvm.amdgcn.s.memtime()
+; CHECK: call i64 @llvm.amdgcn.s.memtime()
+define amdgpu_kernel void @memtime(i64 %cycles) #0 {
+entry:
+  %0 = tail call i64 @llvm.amdgcn.s.memtime()
+  %cmp3 = icmp sgt i64 %cycles, 0
+  br i1 %cmp3, label %while.body, label %while.end
+
+while.body:
+  %1 = tail call i64 @llvm.amdgcn.s.memtime()
+  %sub = sub nsw i64 %1, %0
+  %cmp = icmp slt i64 %sub, %cycles
+  br i1 %cmp, label %while.body, label %while.end
+
+while.end:
+  ret void
+}
+
+declare i64 @llvm.amdgcn.s.memrealtime()
+declare i64 @llvm.amdgcn.s.memtime()

Added: llvm/trunk/test/Transforms/EarlyCSE/and_or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/and_or.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/and_or.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/and_or.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,144 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -early-cse -S < %s | FileCheck %s
+; RUN: opt -basicaa -early-cse-memssa -S < %s | FileCheck %s
+
+define i32 @test_01(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_01(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    ret i32 [[A]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret i32 [[B]]
+;
+entry:
+  %cond = icmp slt i32 %a, %b
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  %cond2 = icmp slt i32 %a, %b
+  %x = select i1 %cond2, i32 %a, i32 %b
+  ret i32 %x
+
+if.false:
+  %cond3 = icmp slt i32 %a, %b
+  %y = select i1 %cond3, i32 %a, i32 %b
+  ret i32 %y
+}
+
+define i32 @test_02(i32 %a, i32 %b, i1 %c) {
+; CHECK-LABEL: @test_02(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[AND_COND:%.*]] = and i1 [[COND]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[AND_COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    ret i32 [[A]]
+; CHECK:       if.false:
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT:    ret i32 [[Y]]
+;
+entry:
+  %cond = icmp slt i32 %a, %b
+  %and.cond = and i1 %cond, %c
+  br i1 %and.cond, label %if.true, label %if.false
+
+if.true:
+  %cond2 = icmp slt i32 %a, %b
+  %x = select i1 %cond2, i32 %a, i32 %b
+  ret i32 %x
+
+if.false:
+  %cond3 = icmp slt i32 %a, %b
+  %y = select i1 %cond3, i32 %a, i32 %b
+  ret i32 %y
+}
+
+define i32 @test_03(i32 %a, i32 %b, i1 %c) {
+; CHECK-LABEL: @test_03(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[COND]], [[C:%.*]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    [[X:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT:    ret i32 [[X]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret i32 [[B]]
+;
+entry:
+  %cond = icmp slt i32 %a, %b
+  %or.cond = or i1 %cond, %c
+  br i1 %or.cond, label %if.true, label %if.false
+
+if.true:
+  %cond2 = icmp slt i32 %a, %b
+  %x = select i1 %cond2, i32 %a, i32 %b
+  ret i32 %x
+
+if.false:
+  %cond3 = icmp slt i32 %a, %b
+  %y = select i1 %cond3, i32 %a, i32 %b
+  ret i32 %y
+}
+
+define i32 @test_04(i32 %a, i32 %b, i1 %c1, i1 %c2) {
+; CHECK-LABEL: @test_04(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[AND_COND1:%.*]] = and i1 [[COND]], [[C1:%.*]]
+; CHECK-NEXT:    [[AND_COND2:%.*]] = and i1 [[AND_COND1]], [[C2:%.*]]
+; CHECK-NEXT:    br i1 [[AND_COND2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    ret i32 [[A]]
+; CHECK:       if.false:
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT:    ret i32 [[Y]]
+;
+entry:
+  %cond = icmp slt i32 %a, %b
+  %and.cond1 = and i1 %cond, %c1
+  %and.cond2 = and i1 %and.cond1, %c2
+  br i1 %and.cond2, label %if.true, label %if.false
+
+if.true:
+  %cond2 = icmp slt i32 %a, %b
+  %x = select i1 %cond2, i32 %a, i32 %b
+  ret i32 %x
+
+if.false:
+  %cond3 = icmp slt i32 %a, %b
+  %y = select i1 %cond3, i32 %a, i32 %b
+  ret i32 %y
+}
+
+define i32 @test_05(i32 %a, i32 %b, i1 %c1, i1 %c2) {
+; CHECK-LABEL: @test_05(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[OR_COND1:%.*]] = or i1 [[COND]], [[C1:%.*]]
+; CHECK-NEXT:    [[OR_COND2:%.*]] = or i1 [[OR_COND1]], [[C2:%.*]]
+; CHECK-NEXT:    br i1 [[OR_COND2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    [[X:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT:    ret i32 [[X]]
+; CHECK:       if.false:
+; CHECK-NEXT:    ret i32 [[B]]
+;
+entry:
+  %cond = icmp slt i32 %a, %b
+  %or.cond1 = or i1 %cond, %c1
+  %or.cond2 = or i1 %or.cond1, %c2
+  br i1 %or.cond2, label %if.true, label %if.false
+
+if.true:
+  %cond2 = icmp slt i32 %a, %b
+  %x = select i1 %cond2, i32 %a, i32 %b
+  ret i32 %x
+
+if.false:
+  %cond3 = icmp slt i32 %a, %b
+  %y = select i1 %cond3, i32 %a, i32 %b
+  ret i32 %y
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/atomics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/atomics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/atomics.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/atomics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,260 @@
+; RUN: opt < %s -S -early-cse | FileCheck %s
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+
+; CHECK-LABEL: @test12(
+define i32 @test12(i1 %B, i32* %P1, i32* %P2) {
+  %load0 = load i32, i32* %P1
+  %1 = load atomic i32, i32* %P2 seq_cst, align 4
+  %load1 = load i32, i32* %P1
+  %sel = select i1 %B, i32 %load0, i32 %load1
+  ret i32 %sel
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load i32, i32* %P1
+}
+
+; CHECK-LABEL: @test13(
+; atomic to non-atomic forwarding is legal
+define i32 @test13(i1 %B, i32* %P1) {
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %b = load i32, i32* %P1
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load atomic i32, i32* %P1
+  ; CHECK: ret i32 0
+}
+
+; CHECK-LABEL: @test14(
+; atomic to unordered atomic forwarding is legal
+define i32 @test14(i1 %B, i32* %P1) {
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load atomic i32, i32* %P1 seq_cst
+  ; CHECK-NEXT: ret i32 0
+}
+
+; CHECK-LABEL: @test15(
+; implementation restriction: can't forward to stonger
+; than unordered
+define i32 @test15(i1 %B, i32* %P1, i32* %P2) {
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %b = load atomic i32, i32* %P1 seq_cst, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load atomic i32, i32* %P1
+  ; CHECK: load atomic i32, i32* %P1
+}
+
+; CHECK-LABEL: @test16(
+; forwarding non-atomic to atomic is wrong! (However,
+; it would be legal to use the later value in place of the
+; former in this particular example.  We just don't
+; do that right now.)
+define i32 @test16(i1 %B, i32* %P1, i32* %P2) {
+  %a = load i32, i32* %P1, align 4
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load atomic i32, i32* %P1
+}
+
+; Can't DSE across a full fence
+define void @fence_seq_cst_store(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_seq_cst_store
+; CHECK: store
+; CHECK: store atomic
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  store atomic i32 0, i32* %P2 seq_cst, align 4
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full fence
+define void @fence_seq_cst(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_seq_cst
+; CHECK: store
+; CHECK: fence seq_cst
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  fence seq_cst
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full fence
+define void @fence_asm_sideeffect(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_asm_sideeffect
+; CHECK: store
+; CHECK: call void asm sideeffect
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  call void asm sideeffect "", ""()
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full fence
+define void @fence_asm_memory(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_asm_memory
+; CHECK: store
+; CHECK: call void asm
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  call void asm "", "~{memory}"()
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't remove a volatile load
+define i32 @volatile_load(i1 %B, i32* %P1, i32* %P2) {
+  %a = load i32, i32* %P1, align 4
+  %b = load volatile i32, i32* %P1, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK-LABEL: @volatile_load
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load volatile i32, i32* %P1
+}
+
+; Can't remove redundant volatile loads
+define i32 @redundant_volatile_load(i1 %B, i32* %P1, i32* %P2) {
+  %a = load volatile i32, i32* %P1, align 4
+  %b = load volatile i32, i32* %P1, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK-LABEL: @redundant_volatile_load
+  ; CHECK: load volatile i32, i32* %P1
+  ; CHECK: load volatile i32, i32* %P1
+  ; CHECK: sub
+}
+
+; Can't DSE a volatile store
+define void @volatile_store(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @volatile_store
+; CHECK: store volatile
+; CHECK: store
+  store volatile i32 0, i32* %P1, align 4
+  store i32 3, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE a redundant volatile store
+define void @redundant_volatile_store(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @redundant_volatile_store
+; CHECK: store volatile
+; CHECK: store volatile
+  store volatile i32 0, i32* %P1, align 4
+  store volatile i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can value forward from volatiles
+define i32 @test20(i1 %B, i32* %P1, i32* %P2) {
+  %a = load volatile i32, i32* %P1, align 4
+  %b = load i32, i32* %P1, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK-LABEL: @test20
+  ; CHECK: load volatile i32, i32* %P1
+  ; CHECK: ret i32 0
+}
+
+; Can DSE a non-volatile store in favor of a volatile one
+; currently a missed optimization
+define void @test21(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test21
+; CHECK: store 
+; CHECK: store volatile
+  store i32 0, i32* %P1, align 4
+  store volatile i32 3, i32* %P1, align 4
+  ret void
+}
+
+; Can DSE a normal store in favor of a unordered one
+define void @test22(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test22
+; CHECK-NEXT: store atomic
+  store i32 0, i32* %P1, align 4
+  store atomic i32 3, i32* %P1 unordered, align 4
+  ret void
+}
+
+; Can also DSE a unordered store in favor of a normal one
+define void @test23(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test23
+; CHECK-NEXT: store i32 0
+  store atomic i32 3, i32* %P1 unordered, align 4
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; As an implementation limitation, can't remove ordered stores
+; Note that we could remove the earlier store if we could
+; represent the required ordering.
+define void @test24(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test24
+; CHECK-NEXT: store atomic
+; CHECK-NEXT: store i32 0
+  store atomic i32 3, i32* %P1 release, align 4
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't remove volatile stores - each is independently observable and
+; the count of such stores is an observable program side effect.
+define void @test25(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test25
+; CHECK-NEXT: store volatile
+; CHECK-NEXT: store volatile
+  store volatile i32 3, i32* %P1, align 4
+  store volatile i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can DSE a unordered store in favor of a unordered one
+define void @test26(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test26
+; CHECK-NEXT: store atomic i32 3, i32* %P1 unordered, align 4
+; CHECK-NEXT: ret
+  store atomic i32 0, i32* %P1 unordered, align 4
+  store atomic i32 3, i32* %P1 unordered, align 4
+  ret void
+}
+
+; Can DSE a unordered store in favor of a ordered one,
+; but current don't due to implementation limits
+define void @test27(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test27
+; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
+; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
+; CHECK-NEXT: ret
+  store atomic i32 0, i32* %P1 unordered, align 4
+  store atomic i32 3, i32* %P1 release, align 4
+  ret void
+}
+
+; Can DSE an unordered atomic store in favor of an
+; ordered one, but current don't due to implementation limits
+define void @test28(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test28
+; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4
+; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4
+; CHECK-NEXT: ret
+  store atomic i32 0, i32* %P1 unordered, align 4
+  store atomic i32 3, i32* %P1 release, align 4
+  ret void
+}
+
+; As an implementation limitation, can't remove ordered stores
+; see also: @test24
+define void @test29(i1 %B, i32* %P1, i32* %P2) {
+; CHECK-LABEL: @test29
+; CHECK-NEXT: store atomic
+; CHECK-NEXT: store atomic
+  store atomic i32 3, i32* %P1 release, align 4
+  store atomic i32 0, i32* %P1 unordered, align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/basic.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,293 @@
+; RUN: opt < %s -S -early-cse | FileCheck %s
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+; RUN: opt < %s -S -passes=early-cse | FileCheck %s
+
+declare void @llvm.assume(i1) nounwind
+
+; CHECK-LABEL: @test1(
+define void @test1(i8 %V, i32 *%P) {
+  %A = bitcast i64 42 to double  ;; dead
+  %B = add i32 4, 19             ;; constant folds
+  store i32 %B, i32* %P
+  ; CHECK-NEXT: store i32 23, i32* %P
+  
+  %C = zext i8 %V to i32
+  %D = zext i8 %V to i32  ;; CSE
+  store volatile i32 %C, i32* %P
+  store volatile i32 %D, i32* %P
+  ; CHECK-NEXT: %C = zext i8 %V to i32
+  ; CHECK-NEXT: store volatile i32 %C
+  ; CHECK-NEXT: store volatile i32 %C
+  
+  %E = add i32 %C, %C
+  %F = add i32 %C, %C
+  store volatile i32 %E, i32* %P
+  store volatile i32 %F, i32* %P
+  ; CHECK-NEXT: %E = add i32 %C, %C
+  ; CHECK-NEXT: store volatile i32 %E
+  ; CHECK-NEXT: store volatile i32 %E
+
+  %G = add nuw i32 %C, %C
+  store volatile i32 %G, i32* %P
+  ; CHECK-NEXT: store volatile i32 %E
+  ret void
+}
+
+
+;; Simple load value numbering.
+; CHECK-LABEL: @test2(
+define i32 @test2(i32 *%P) {
+  %V1 = load i32, i32* %P
+  %V2 = load i32, i32* %P
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: ret i32 0
+}
+
+; CHECK-LABEL: @test2a(
+define i32 @test2a(i32 *%P, i1 %b) {
+  %V1 = load i32, i32* %P
+  tail call void @llvm.assume(i1 %b)
+  %V2 = load i32, i32* %P
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: ret i32 0
+}
+
+;; Cross block load value numbering.
+; CHECK-LABEL: @test3(
+define i32 @test3(i32 *%P, i1 %Cond) {
+  %V1 = load i32, i32* %P
+  br i1 %Cond, label %T, label %F
+T:
+  store i32 4, i32* %P
+  ret i32 42
+F:
+  %V2 = load i32, i32* %P
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: F:
+  ; CHECK: ret i32 0
+}
+
+; CHECK-LABEL: @test3a(
+define i32 @test3a(i32 *%P, i1 %Cond, i1 %b) {
+  %V1 = load i32, i32* %P
+  br i1 %Cond, label %T, label %F
+T:
+  store i32 4, i32* %P
+  ret i32 42
+F:
+  tail call void @llvm.assume(i1 %b)
+  %V2 = load i32, i32* %P
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: F:
+  ; CHECK: ret i32 0
+}
+
+;; Cross block load value numbering stops when stores happen.
+; CHECK-LABEL: @test4(
+define i32 @test4(i32 *%P, i1 %Cond) {
+  %V1 = load i32, i32* %P
+  br i1 %Cond, label %T, label %F
+T:
+  ret i32 42
+F:
+  ; Clobbers V1
+  store i32 42, i32* %P
+  
+  %V2 = load i32, i32* %P
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: F:
+  ; CHECK: ret i32 %Diff
+}
+
+declare i32 @func(i32 *%P) readonly
+
+;; Simple call CSE'ing.
+; CHECK-LABEL: @test5(
+define i32 @test5(i32 *%P) {
+  %V1 = call i32 @func(i32* %P)
+  %V2 = call i32 @func(i32* %P)
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: ret i32 0
+}
+
+;; Trivial Store->load forwarding
+; CHECK-LABEL: @test6(
+define i32 @test6(i32 *%P) {
+  store i32 42, i32* %P
+  %V1 = load i32, i32* %P
+  ret i32 %V1
+  ; CHECK: ret i32 42
+}
+
+; CHECK-LABEL: @test6a(
+define i32 @test6a(i32 *%P, i1 %b) {
+  store i32 42, i32* %P
+  tail call void @llvm.assume(i1 %b)
+  %V1 = load i32, i32* %P
+  ret i32 %V1
+  ; CHECK: ret i32 42
+}
+
+;; Trivial dead store elimination.
+; CHECK-LABEL: @test7(
+define void @test7(i32 *%P) {
+  store i32 42, i32* %P
+  store i32 45, i32* %P
+  ret void
+  ; CHECK-NEXT: store i32 45
+  ; CHECK-NEXT: ret void
+}
+
+;; Readnone functions aren't invalidated by stores.
+; CHECK-LABEL: @test8(
+define i32 @test8(i32 *%P) {
+  %V1 = call i32 @func(i32* %P) readnone
+  store i32 4, i32* %P
+  %V2 = call i32 @func(i32* %P) readnone
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: ret i32 0
+}
+
+;; Trivial DSE can't be performed across a readonly call.  The call
+;; can observe the earlier write.
+; CHECK-LABEL: @test9(
+define i32 @test9(i32 *%P) {
+  store i32 4, i32* %P
+  %V1 = call i32 @func(i32* %P) readonly
+  store i32 5, i32* %P        
+  ret i32 %V1
+  ; CHECK: store i32 4, i32* %P        
+  ; CHECK-NEXT: %V1 = call i32 @func(i32* %P)
+  ; CHECK-NEXT: store i32 5, i32* %P        
+  ; CHECK-NEXT: ret i32 %V1
+}
+
+;; Trivial DSE can be performed across a readnone call.
+; CHECK-LABEL: @test10
+define i32 @test10(i32 *%P) {
+  store i32 4, i32* %P
+  %V1 = call i32 @func(i32* %P) readnone
+  store i32 5, i32* %P        
+  ret i32 %V1
+  ; CHECK-NEXT: %V1 = call i32 @func(i32* %P)
+  ; CHECK-NEXT: store i32 5, i32* %P        
+  ; CHECK-NEXT: ret i32 %V1
+}
+
+;; Trivial dead store elimination - should work for an entire series of dead stores too.
+; CHECK-LABEL: @test11(
+define void @test11(i32 *%P) {
+  store i32 42, i32* %P
+  store i32 43, i32* %P
+  store i32 44, i32* %P
+  store i32 45, i32* %P
+  ret void
+  ; CHECK-NEXT: store i32 45
+  ; CHECK-NEXT: ret void
+}
+
+; CHECK-LABEL: @test12(
+define i32 @test12(i1 %B, i32* %P1, i32* %P2) {
+  %load0 = load i32, i32* %P1
+  %1 = load atomic i32, i32* %P2 seq_cst, align 4
+  %load1 = load i32, i32* %P1
+  %sel = select i1 %B, i32 %load0, i32 %load1
+  ret i32 %sel
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load i32, i32* %P1
+}
+
+define void @dse1(i32 *%P) {
+; CHECK-LABEL: @dse1
+; CHECK-NOT: store
+  %v = load i32, i32* %P
+  store i32 %v, i32* %P
+  ret void
+}
+
+define void @dse2(i32 *%P) {
+; CHECK-LABEL: @dse2
+; CHECK-NOT: store
+  %v = load atomic i32, i32* %P seq_cst, align 4
+  store i32 %v, i32* %P
+  ret void
+}
+
+define void @dse3(i32 *%P) {
+; CHECK-LABEL: @dse3
+; CHECK-NOT: store
+  %v = load atomic i32, i32* %P seq_cst, align 4
+  store atomic i32 %v, i32* %P unordered, align 4
+  ret void
+}
+
+define i32 @dse4(i32 *%P, i32 *%Q) {
+; CHECK-LABEL: @dse4
+; CHECK-NOT: store
+; CHECK: ret i32 0
+  %a = load i32, i32* %Q
+  %v = load atomic i32, i32* %P unordered, align 4
+  store atomic i32 %v, i32* %P unordered, align 4
+  %b = load i32, i32* %Q
+  %res = sub i32 %a, %b
+  ret i32 %res
+}
+
+; Note that in this example, %P and %Q could in fact be the same
+; pointer.  %v could be different than the value observed for %a
+; and that's okay because we're using relaxed memory ordering.  
+; The only guarantee we have to provide is that each of the loads 
+; has to observe some value written to that location.  We  do 
+; not have to respect the order in which those writes were done.  
+define i32 @dse5(i32 *%P, i32 *%Q) {
+; CHECK-LABEL: @dse5
+; CHECK-NOT: store
+; CHECK: ret i32 0
+  %v = load atomic i32, i32* %P unordered, align 4
+  %a = load atomic i32, i32* %Q unordered, align 4
+  store atomic i32 %v, i32* %P unordered, align 4
+  %b = load atomic i32, i32* %Q unordered, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+}
+
+
+define void @dse_neg1(i32 *%P) {
+; CHECK-LABEL: @dse_neg1
+; CHECK: store
+  %v = load i32, i32* %P
+  store i32 5, i32* %P
+  ret void
+}
+
+; Could remove the store, but only if ordering was somehow
+; encoded.
+define void @dse_neg2(i32 *%P) {
+; CHECK-LABEL: @dse_neg2
+; CHECK: store
+  %v = load i32, i32* %P
+  store atomic i32 %v, i32* %P seq_cst, align 4
+  ret void
+}
+
+ at c = external global i32, align 4
+declare i32 @reads_c(i32 returned)
+define void @pr28763() {
+entry:
+; CHECK-LABEL: @pr28763(
+; CHECK: store i32 0, i32* @c, align 4
+; CHECK: call i32 @reads_c(i32 0)
+; CHECK: store i32 2, i32* @c, align 4
+  %load = load i32, i32* @c, align 4
+  store i32 0, i32* @c, align 4
+  %call = call i32 @reads_c(i32 0)
+  store i32 2, i32* @c, align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/commute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/commute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/commute.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/commute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,546 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -early-cse | FileCheck %s
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+
+define void @test1(float %A, float %B, float* %PA, float* %PB) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:    [[C:%.*]] = fadd float [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    store float [[C]], float* [[PA:%.*]]
+; CHECK-NEXT:    store float [[C]], float* [[PB:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %C = fadd float %A, %B
+  store float %C, float* %PA
+  %D = fadd float %B, %A
+  store float %D, float* %PB
+  ret void
+}
+
+define void @test2(float %A, float %B, i1* %PA, i1* %PB) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:    [[C:%.*]] = fcmp oeq float [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %C = fcmp oeq float %A, %B
+  store i1 %C, i1* %PA
+  %D = fcmp oeq float %B, %A
+  store i1 %D, i1* %PB
+  ret void
+}
+
+define void @test3(float %A, float %B, i1* %PA, i1* %PB) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:    [[C:%.*]] = fcmp uge float [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %C = fcmp uge float %A, %B
+  store i1 %C, i1* %PA
+  %D = fcmp ule float %B, %A
+  store i1 %D, i1* %PB
+  ret void
+}
+
+define void @test4(i32 %A, i32 %B, i1* %PA, i1* %PB) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %C = icmp eq i32 %A, %B
+  store i1 %C, i1* %PA
+  %D = icmp eq i32 %B, %A
+  store i1 %D, i1* %PB
+  ret void
+}
+
+define void @test5(i32 %A, i32 %B, i1* %PA, i1* %PB) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PA:%.*]]
+; CHECK-NEXT:    store i1 [[C]], i1* [[PB:%.*]]
+; CHECK-NEXT:    ret void
+;
+  %C = icmp sgt i32 %A, %B
+  store i1 %C, i1* %PA
+  %D = icmp slt i32 %B, %A
+  store i1 %D, i1* %PB
+  ret void
+}
+
+; Min/max operands may be commuted in the compare and select.
+
+define i8 @smin_commute(i8 %a, i8 %b) {
+; CHECK-LABEL: @smin_commute(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[B]], [[A]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    [[R:%.*]] = mul i8 [[M1]], [[M1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp slt i8 %b, %a
+  %m1 = select i1 %cmp1, i8 %a, i8 %b
+  %m2 = select i1 %cmp2, i8 %b, i8 %a
+  %r = mul i8 %m1, %m2
+  ret i8 %r
+}
+
+; Min/max can also have a swapped predicate and select operands.
+
+define i1 @smin_swapped(i8 %a, i8 %b) {
+; CHECK-LABEL: @smin_swapped(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], [[B]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
+; CHECK-NEXT:    ret i1 true
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp slt i8 %a, %b
+  %m1 = select i1 %cmp1, i8 %b, i8 %a
+  %m2 = select i1 %cmp2, i8 %a, i8 %b
+  %r = icmp eq i8 %m2, %m1
+  ret i1 %r
+}
+
+define i8 @smax_commute(i8 %a, i8 %b) {
+; CHECK-LABEL: @smax_commute(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[B]], [[A]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    ret i8 0
+;
+  %cmp1 = icmp sgt i8 %a, %b
+  %cmp2 = icmp sgt i8 %b, %a
+  %m1 = select i1 %cmp1, i8 %a, i8 %b
+  %m2 = select i1 %cmp2, i8 %b, i8 %a
+  %r = urem i8 %m2, %m1
+  ret i8 %r
+}
+
+define i8 @smax_swapped(i8 %a, i8 %b) {
+; CHECK-LABEL: @smax_swapped(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[A]], [[B]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
+; CHECK-NEXT:    ret i8 1
+;
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp sgt i8 %a, %b
+  %m1 = select i1 %cmp1, i8 %b, i8 %a
+  %m2 = select i1 %cmp2, i8 %a, i8 %b
+  %r = sdiv i8 %m1, %m2
+  ret i8 %r
+}
+
+define i8 @umin_commute(i8 %a, i8 %b) {
+; CHECK-LABEL: @umin_commute(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 [[B]], [[A]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    ret i8 0
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ult i8 %b, %a
+  %m1 = select i1 %cmp1, i8 %a, i8 %b
+  %m2 = select i1 %cmp2, i8 %b, i8 %a
+  %r = sub i8 %m2, %m1
+  ret i8 %r
+}
+
+; Choose a vector type just to show that works.
+
+define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @umin_swapped(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt <2 x i8> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult <2 x i8> [[A]], [[B]]
+; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> [[B]], <2 x i8> [[A]]
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
+;
+  %cmp1 = icmp ugt <2 x i8> %a, %b
+  %cmp2 = icmp ult <2 x i8> %a, %b
+  %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a
+  %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b
+  %r = sub <2 x i8> %m2, %m1
+  ret <2 x i8> %r
+}
+
+define i8 @umax_commute(i8 %a, i8 %b) {
+; CHECK-LABEL: @umax_commute(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 [[B]], [[A]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
+; CHECK-NEXT:    ret i8 1
+;
+  %cmp1 = icmp ugt i8 %a, %b
+  %cmp2 = icmp ugt i8 %b, %a
+  %m1 = select i1 %cmp1, i8 %a, i8 %b
+  %m2 = select i1 %cmp2, i8 %b, i8 %a
+  %r = udiv i8 %m1, %m2
+  ret i8 %r
+}
+
+define i8 @umax_swapped(i8 %a, i8 %b) {
+; CHECK-LABEL: @umax_swapped(
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 [[A]], [[B]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
+; CHECK-NEXT:    [[R:%.*]] = add i8 [[M1]], [[M1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %cmp1 = icmp ult i8 %a, %b
+  %cmp2 = icmp ugt i8 %a, %b
+  %m1 = select i1 %cmp1, i8 %b, i8 %a
+  %m2 = select i1 %cmp2, i8 %a, i8 %b
+  %r = add i8 %m2, %m1
+  ret i8 %r
+}
+
+; Min/max may exist with non-canonical operands. Value tracking can match those.
+
+define i8 @smax_nsw(i8 %a, i8 %b) {
+; CHECK-LABEL: @smax_nsw(
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], [[B]]
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]
+; CHECK-NEXT:    ret i8 0
+;
+  %sub = sub nsw i8 %a, %b
+  %cmp1 = icmp slt i8 %a, %b
+  %cmp2 = icmp sgt i8 %sub, 0
+  %m1 = select i1 %cmp1, i8 0, i8 %sub
+  %m2 = select i1 %cmp2, i8 %sub, i8 0
+  %r = sub i8 %m2, %m1
+  ret i8 %r
+}
+
+define i8 @abs_swapped(i8 %a) {
+; CHECK-LABEL: @abs_swapped(
+; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], 0
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
+; CHECK-NEXT:    ret i8 [[M1]]
+;
+  %neg = sub i8 0, %a
+  %cmp1 = icmp sgt i8 %a, 0
+  %cmp2 = icmp slt i8 %a, 0
+  %m1 = select i1 %cmp1, i8 %a, i8 %neg
+  %m2 = select i1 %cmp2, i8 %neg, i8 %a
+  %r = or i8 %m2, %m1
+  ret i8 %r
+}
+
+define i8 @nabs_swapped(i8 %a) {
+; CHECK-LABEL: @nabs_swapped(
+; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[A]], 0
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
+; CHECK-NEXT:    ret i8 0
+;
+  %neg = sub i8 0, %a
+  %cmp1 = icmp slt i8 %a, 0
+  %cmp2 = icmp sgt i8 %a, 0
+  %m1 = select i1 %cmp1, i8 %a, i8 %neg
+  %m2 = select i1 %cmp2, i8 %neg, i8 %a
+  %r = xor i8 %m2, %m1
+  ret i8 %r
+}
+
+; These two tests make sure we still consider it a match when the RHS of the
+; compares are different.
+define i8 @abs_different_constants(i8 %a) {
+; CHECK-LABEL: @abs_different_constants(
+; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 [[A]], -1
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 [[A]], 0
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
+; CHECK-NEXT:    ret i8 [[M1]]
+;
+  %neg = sub i8 0, %a
+  %cmp1 = icmp sgt i8 %a, -1
+  %cmp2 = icmp slt i8 %a, 0
+  %m1 = select i1 %cmp1, i8 %a, i8 %neg
+  %m2 = select i1 %cmp2, i8 %neg, i8 %a
+  %r = or i8 %m2, %m1
+  ret i8 %r
+}
+
+define i8 @nabs_different_constants(i8 %a) {
+; CHECK-LABEL: @nabs_different_constants(
+; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[A:%.*]]
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 [[A]], 0
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[A]], -1
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
+; CHECK-NEXT:    ret i8 0
+;
+  %neg = sub i8 0, %a
+  %cmp1 = icmp slt i8 %a, 0
+  %cmp2 = icmp sgt i8 %a, -1
+  %m1 = select i1 %cmp1, i8 %a, i8 %neg
+  %m2 = select i1 %cmp2, i8 %neg, i8 %a
+  %r = xor i8 %m2, %m1
+  ret i8 %r
+}
+
+; https://bugs.llvm.org/show_bug.cgi?id=41101
+; Detect equivalence of selects with commuted operands: 'not' cond.
+
+define i32 @select_not_cond(i1 %cond, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_cond(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[COND:%.*]], true
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    ret i32 0
+;
+  %not = xor i1 %cond, -1
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %not, i32 %f, i32 %t
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; Detect equivalence of selects with commuted operands: 'not' cond with vector select.
+
+define <2 x double> @select_not_cond_commute_vec(<2 x i1> %cond, <2 x double> %t, <2 x double> %f) {
+; CHECK-LABEL: @select_not_cond_commute_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i1> [[COND:%.*]], <i1 true, i1 true>
+; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[COND]], <2 x double> [[T:%.*]], <2 x double> [[F:%.*]]
+; CHECK-NEXT:    ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
+;
+  %not = xor <2 x i1> %cond, <i1 -1, i1 -1>
+  %m1 = select <2 x i1> %cond, <2 x double> %t, <2 x double> %f
+  %m2 = select <2 x i1> %not, <2 x double> %f, <2 x double> %t
+  %r = fdiv nnan <2 x double> %m1, %m2
+  ret <2 x double> %r
+}
+
+; Negative test - select ops must be commuted.
+
+define i32 @select_not_cond_wrong_select_ops(i1 %cond, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_cond_wrong_select_ops(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[COND:%.*]], true
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T]], i32 [[F]]
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %not = xor i1 %cond, -1
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %not, i32 %t, i32 %f
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; Negative test - not a 'not'.
+
+define i32 @select_not_cond_wrong_cond(i1 %cond, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_cond_wrong_cond(
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND:%.*]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %not = xor i1 %cond, -2
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %not, i32 %f, i32 %t
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; Detect equivalence of selects with commuted operands: inverted pred with fcmps.
+
+define i32 @select_invert_pred_cond(float %x, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_invert_pred_cond(
+; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
+; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    ret i32 0
+;
+  %cond = fcmp ueq float %x, 42.0
+  %invcond = fcmp one float %x, 42.0
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %invcond, i32 %f, i32 %t
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.
+
+define <2 x i32> @select_invert_pred_cond_commute_vec(<2 x i8> %x, <2 x i32> %t, <2 x i32> %f) {
+; CHECK-LABEL: @select_invert_pred_cond_commute_vec(
+; CHECK-NEXT:    [[COND:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 42, i8 -1>
+; CHECK-NEXT:    [[INVCOND:%.*]] = icmp sle <2 x i8> [[X]], <i8 42, i8 -1>
+; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[T:%.*]], <2 x i32> [[F:%.*]]
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
+;
+  %cond = icmp sgt <2 x i8> %x, <i8 42, i8 -1>
+  %invcond = icmp sle <2 x i8> %x, <i8 42, i8 -1>
+  %m1 = select <2 x i1> %cond, <2 x i32> %t, <2 x i32> %f
+  %m2 = select <2 x i1> %invcond, <2 x i32> %f, <2 x i32> %t
+  %r = xor <2 x i32> %m1, %m2
+  ret <2 x i32> %r
+}
+
+; Negative test - select ops must be commuted.
+
+define i32 @select_invert_pred_wrong_select_ops(float %x, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_invert_pred_wrong_select_ops(
+; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
+; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[F:%.*]], i32 [[T:%.*]]
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %cond = fcmp ueq float %x, 42.0
+  %invcond = fcmp one float %x, 42.0
+  %m1 = select i1 %cond, i32 %f, i32 %t
+  %m2 = select i1 %invcond, i32 %f, i32 %t
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; Negative test - not an inverted predicate.
+
+define i32 @select_invert_pred_wrong_cond(float %x, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_invert_pred_wrong_cond(
+; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
+; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp une float [[X]], 4.200000e+01
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %cond = fcmp ueq float %x, 42.0
+  %invcond = fcmp une float %x, 42.0
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %invcond, i32 %f, i32 %t
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; Negative test - cmp ops must match.
+
+define i32 @select_invert_pred_wrong_cmp_ops(float %x, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_invert_pred_wrong_cmp_ops(
+; CHECK-NEXT:    [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
+; CHECK-NEXT:    [[INVCOND:%.*]] = fcmp one float [[X]], 4.300000e+01
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %cond = fcmp ueq float %x, 42.0
+  %invcond = fcmp one float %x, 43.0
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %invcond, i32 %f, i32 %t
+  %r = xor i32 %m2, %m1
+  ret i32 %r
+}
+
+; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
+
+define i32 @select_not_invert_pred_cond(i8 %x, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_invert_pred_cond(
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X:%.*]], 42
+; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X]], 42
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    ret i32 0
+;
+  %cond = icmp ugt i8 %x, 42
+  %invcond = icmp ule i8 %x, 42
+  %not = xor i1 %invcond, -1
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %m2 = select i1 %not, i32 %t, i32 %f
+  %r = sub i32 %m1, %m2
+  ret i32 %r
+}
+
+; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
+
+define i32 @select_not_invert_pred_cond_commute(i8 %x, i8 %y, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_invert_pred_cond_commute(
+; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
+; CHECK-NEXT:    ret i32 0
+;
+  %invcond = icmp ule i8 %x, %y
+  %not = xor i1 %invcond, -1
+  %m2 = select i1 %not, i32 %t, i32 %f
+  %cond = icmp ugt i8 %x, %y
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %r = sub i32 %m2, %m1
+  ret i32 %r
+}
+
+; Negative test - not an inverted predicate.
+
+define i32 @select_not_invert_pred_cond_wrong_pred(i8 %x, i8 %y, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_invert_pred_cond_wrong_pred(
+; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
+; CHECK-NEXT:    [[R:%.*]] = sub i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %invcond = icmp ult i8 %x, %y
+  %not = xor i1 %invcond, -1
+  %m2 = select i1 %not, i32 %t, i32 %f
+  %cond = icmp ugt i8 %x, %y
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %r = sub i32 %m2, %m1
+  ret i32 %r
+}
+
+; Negative test - cmp ops must match.
+
+define i32 @select_not_invert_pred_cond_wrong_cmp_op(i8 %x, i8 %y, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_invert_pred_cond_wrong_cmp_op(
+; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], 42
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
+; CHECK-NEXT:    [[R:%.*]] = sub i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %invcond = icmp ule i8 %x, 42
+  %not = xor i1 %invcond, -1
+  %m2 = select i1 %not, i32 %t, i32 %f
+  %cond = icmp ugt i8 %x, %y
+  %m1 = select i1 %cond, i32 %t, i32 %f
+  %r = sub i32 %m2, %m1
+  ret i32 %r
+}
+
+; Negative test - select ops must be same (and not commuted).
+
+define i32 @select_not_invert_pred_cond_wrong_select_op(i8 %x, i8 %y, i32 %t, i32 %f) {
+; CHECK-LABEL: @select_not_invert_pred_cond_wrong_select_op(
+; CHECK-NEXT:    [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[INVCOND]], true
+; CHECK-NEXT:    [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
+; CHECK-NEXT:    [[M1:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
+; CHECK-NEXT:    [[R:%.*]] = sub i32 [[M2]], [[M1]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %invcond = icmp ule i8 %x, %y
+  %not = xor i1 %invcond, -1
+  %m2 = select i1 %not, i32 %t, i32 %f
+  %cond = icmp ugt i8 %x, %y
+  %m1 = select i1 %cond, i32 %f, i32 %t
+  %r = sub i32 %m2, %m1
+  ret i32 %r
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/conditional.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/conditional.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/conditional.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/conditional.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,108 @@
+; RUN: opt -early-cse -S < %s | FileCheck %s
+; RUN: opt -basicaa -early-cse-memssa -S < %s | FileCheck %s
+
+; Can we CSE a known condition to a constant?
+define i1 @test(i8* %p) {
+; CHECK-LABEL: @test
+entry:
+  %cnd1 = icmp eq i8* %p, null
+  br i1 %cnd1, label %taken, label %untaken
+
+taken:
+; CHECK-LABEL: taken:
+; CHECK-NEXT: ret i1 true
+  %cnd2 = icmp eq i8* %p, null
+  ret i1 %cnd2
+
+untaken:
+; CHECK-LABEL: untaken:
+; CHECK-NEXT: ret i1 false
+  %cnd3 = icmp eq i8* %p, null
+  ret i1 %cnd3
+}
+
+; We can CSE the condition, but we *don't* know it's value after the merge
+define i1 @test_neg1(i8* %p) {
+; CHECK-LABEL: @test_neg1
+entry:
+  %cnd1 = icmp eq i8* %p, null
+  br i1 %cnd1, label %taken, label %untaken
+
+taken:
+  br label %merge
+
+untaken:
+  br label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+  %cnd3 = icmp eq i8* %p, null
+  ret i1 %cnd3
+}
+
+; Check specifically for a case where we have a unique predecessor, but
+; not a single predecessor.  We can not know the value of the condition here.
+define i1 @test_neg2(i8* %p) {
+; CHECK-LABEL: @test_neg2
+entry:
+  %cnd1 = icmp eq i8* %p, null
+  br i1 %cnd1, label %merge, label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+  %cnd3 = icmp eq i8* %p, null
+  ret i1 %cnd3
+}
+
+; Replace a use rather than CSE
+define i1 @test2(i8* %p) {
+; CHECK-LABEL: @test2
+entry:
+  %cnd = icmp eq i8* %p, null
+  br i1 %cnd, label %taken, label %untaken
+
+taken:
+; CHECK-LABEL: taken:
+; CHECK-NEXT: ret i1 true
+  ret i1 %cnd
+
+untaken:
+; CHECK-LABEL: untaken:
+; CHECK-NEXT: ret i1 false
+  ret i1 %cnd
+}
+
+; Not legal to replace use given it's not dominated by edge
+define i1 @test2_neg1(i8* %p) {
+; CHECK-LABEL: @test2_neg1
+entry:
+  %cnd1 = icmp eq i8* %p, null
+  br i1 %cnd1, label %taken, label %untaken
+
+taken:
+  br label %merge
+
+untaken:
+  br label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+  ret i1 %cnd1
+}
+
+; Another single predecessor test, but for dominated use
+define i1 @test2_neg2(i8* %p) {
+; CHECK-LABEL: @test2_neg2
+entry:
+  %cnd1 = icmp eq i8* %p, null
+  br i1 %cnd1, label %merge, label %merge
+
+merge:
+; CHECK-LABEL: merge:
+; CHECK-NEXT: ret i1 %cnd1
+  ret i1 %cnd1
+}
+

Added: llvm/trunk/test/Transforms/EarlyCSE/const-speculation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/const-speculation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/const-speculation.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/const-speculation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -early-cse -S %s | FileCheck %s
+
+%mystruct = type { i32 }
+
+; @var is global so that *every* GEP argument is Constant.
+ at var = external global %mystruct
+
+; Control flow is to make the dominance tree consider the final icmp before it
+; gets to simplify the purely constant one (%tst). Since that icmp uses the
+; select that gets considered next. Finally the select simplification looks at
+; the %tst icmp and we don't want it to speculate about what happens if "i32 0"
+; is actually "i32 1", broken universes are automatic UB.
+;
+; In this case doing the speculation would create an invalid GEP(@var, 0, 1) and
+; crash.
+
+define i1 @test_constant_speculation() {
+; CHECK-LABEL: define i1 @test_constant_speculation
+entry:
+  br i1 undef, label %end, label %select
+
+select:
+; CHECK: select:
+; CHECK-NOT: icmp
+; CHECK-NOT: getelementptr
+; CHECK-NOT: select
+
+  %tst = icmp eq i32 1, 0
+  %elt = getelementptr %mystruct, %mystruct* @var, i64 0, i32 0
+  %sel = select i1 %tst, i32* null, i32* %elt
+  br label %end
+
+end:
+; CHECK: end:
+; CHECK: %tmp = phi i32* [ null, %entry ], [ getelementptr inbounds (%mystruct, %mystruct* @var, i64 0, i32 0), %select ]
+  %tmp = phi i32* [null, %entry], [%sel, %select]
+  %res = icmp eq i32* %tmp, null
+  ret i1 %res
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/debug-info-undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/debug-info-undef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/debug-info-undef.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/debug-info-undef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -S %s -early-cse | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+ at a = global i8 25, align 1, !dbg !0
+
+define signext i16 @b() !dbg !12 {
+entry:
+  call void @llvm.dbg.value(metadata i16 23680, metadata !17, metadata !DIExpression()), !dbg !18
+  %0 = load i8, i8* @a, align 1, !dbg !19, !tbaa !20
+  %conv = sext i8 %0 to i16, !dbg !19
+
+; CHECK: call void @llvm.dbg.value(metadata i16 undef, metadata !17, metadata !DIExpression()), !dbg !18
+; CHECK-NEXT:  call i32 (...) @optimize_me_not()
+
+  call void @llvm.dbg.value(metadata i16 %conv, metadata !17, metadata !DIExpression()), !dbg !18
+  %call = call i32 (...) @optimize_me_not(), !dbg !23
+  %1 = load i8, i8* @a, align 1, !dbg !24, !tbaa !20
+  %conv1 = sext i8 %1 to i16, !dbg !24
+  ret i16 %conv1, !dbg !25
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+declare i32 @optimize_me_not(...)
+
+define i32 @main() !dbg !26 {
+entry:
+  %call = call signext i16 @b(), !dbg !30
+  ret i32 0, !dbg !31
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!7, !8, !9, !10}
+!llvm.ident = !{!11}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: GNU)
+!3 = !DIFile(filename: "patatino.c", directory: "/Users/davide/llvm-monorepo/llvm-mono/build/bin")
+!4 = !{}
+!5 = !{!0}
+!6 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{i32 7, !"PIC Level", i32 2}
+!11 = !{!"clang version 8.0.0 "}
+!12 = distinct !DISubprogram(name: "b", scope: !3, file: !3, line: 2, type: !13, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!15}
+!15 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
+!16 = !{!17}
+!17 = !DILocalVariable(name: "i", scope: !12, file: !3, line: 3, type: !15)
+!18 = !DILocation(line: 3, column: 9, scope: !12)
+!19 = !DILocation(line: 4, column: 7, scope: !12)
+!20 = !{!21, !21, i64 0}
+!21 = !{!"omnipotent char", !22, i64 0}
+!22 = !{!"Simple C/C++ TBAA"}
+!23 = !DILocation(line: 5, column: 3, scope: !12)
+!24 = !DILocation(line: 6, column: 10, scope: !12)
+!25 = !DILocation(line: 6, column: 3, scope: !12)
+!26 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 8, type: !27, scopeLine: 8, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
+!27 = !DISubroutineType(types: !28)
+!28 = !{!29}
+!29 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!30 = !DILocation(line: 8, column: 14, scope: !26)
+!31 = !DILocation(line: 8, column: 19, scope: !26)

Added: llvm/trunk/test/Transforms/EarlyCSE/debuginfo-dce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/debuginfo-dce.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/debuginfo-dce.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/debuginfo-dce.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; RUN: opt -early-cse -S %s -o - | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: nounwind uwtable
+define i32 @foo() !dbg !6 {
+entry:
+  %0 = call i64 @llvm.ctpop.i64(i64 0), !dbg !14
+  %1 = inttoptr i64 %0 to i32*, !dbg !14
+  call void @llvm.dbg.value(metadata i32* %1, i64 0, metadata !11, metadata !13), !dbg !14
+; CHECK: call void @llvm.dbg.value(metadata i64 0, metadata !11, metadata !DIExpression()), !dbg !13
+  %call = call i32* (...) @baa(), !dbg !15
+  %2 = ptrtoint i32* %call to i64, !dbg !16
+  %3 = inttoptr i64 %2 to i32*, !dbg !16
+  call void @llvm.dbg.value(metadata i32* %3, i64 0, metadata !11, metadata !13), !dbg !14
+  %tobool = icmp ne i32* %3, null, !dbg !17
+  br i1 %tobool, label %if.end, label %if.then, !dbg !19
+
+if.then:                                          ; preds = %entry
+  br label %cleanup, !dbg !20
+
+if.end:                                           ; preds = %entry
+  %4 = ptrtoint i32* %3 to i32, !dbg !21
+  br label %cleanup, !dbg !22
+
+cleanup:                                          ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ %4, %if.end ], [ 0, %if.then ]
+  ret i32 %retval.0, !dbg !22
+}
+
+declare i32* @baa(...)
+
+; Function Attrs: nounwind readnone
+declare i64 @llvm.ctpop.i64(i64)
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!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: "test.c", directory: "/dir")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang version 6.0.0"}
+!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !7, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, retainedNodes: !10)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{!11}
+!11 = !DILocalVariable(name: "ptr", scope: !6, file: !1, line: 4, type: !12)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64)
+!13 = !DIExpression()
+!14 = !DILocation(line: 4, column: 8, scope: !6)
+!15 = !DILocation(line: 5, column: 9, scope: !6)
+!16 = !DILocation(line: 5, column: 7, scope: !6)
+!17 = !DILocation(line: 7, column: 7, scope: !18)
+!18 = distinct !DILexicalBlock(scope: !6, file: !1, line: 7, column: 6)
+!19 = !DILocation(line: 7, column: 6, scope: !6)
+!20 = !DILocation(line: 8, column: 5, scope: !18)
+!21 = !DILocation(line: 10, column: 10, scope: !6)
+!22 = !DILocation(line: 11, column: 1, scope: !6)

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

Added: llvm/trunk/test/Transforms/EarlyCSE/fence.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/fence.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/fence.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/fence.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,87 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+; NOTE: This file is testing the current implementation.  Some of
+; the transforms used as negative tests below would be legal, but 
+; only if reached through a chain of logic which EarlyCSE is incapable
+; of performing.  To say it differently, this file tests a conservative
+; version of the memory model.  If we want to extend EarlyCSE to be more
+; aggressive in the future, we may need to relax some of the negative tests.
+
+; We can value forward across the fence since we can (semantically) 
+; reorder the following load before the fence.
+define i32 @test(i32* %addr.i) {
+; CHECK-LABEL: @test
+; CHECK: store
+; CHECK: fence
+; CHECK-NOT: load
+; CHECK: ret
+  store i32 5, i32* %addr.i, align 4
+  fence release
+  %a = load i32, i32* %addr.i, align 4
+  ret i32 %a
+}
+
+; Same as above
+define i32 @test2(i32* noalias %addr.i, i32* noalias %otheraddr) {
+; CHECK-LABEL: @test2
+; CHECK: load
+; CHECK: fence
+; CHECK-NOT: load
+; CHECK: ret
+  %a = load i32, i32* %addr.i, align 4
+  fence release
+  %a2 = load i32, i32* %addr.i, align 4
+  %res = sub i32 %a, %a2
+  ret i32 %a
+}
+
+; We can not value forward across an acquire barrier since we might
+; be syncronizing with another thread storing to the same variable
+; followed by a release fence.  If this thread observed the release 
+; had happened, we must present a consistent view of memory at the
+; fence.  Note that it would be legal to reorder '%a' after the fence
+; and then remove '%a2'.  The current implementation doesn't know how
+; to do this, but if it learned, this test will need revised.
+define i32 @test3(i32* noalias %addr.i, i32* noalias %otheraddr) {
+; CHECK-LABEL: @test3
+; CHECK: load
+; CHECK: fence
+; CHECK: load
+; CHECK: sub
+; CHECK: ret
+  %a = load i32, i32* %addr.i, align 4
+  fence acquire
+  %a2 = load i32, i32* %addr.i, align 4
+  %res = sub i32 %a, %a2
+  ret i32 %res
+}
+
+; We can not dead store eliminate accross the fence.  We could in 
+; principal reorder the second store above the fence and then DSE either
+; store, but this is beyond the simple last-store DSE which EarlyCSE
+; implements.
+define void @test4(i32* %addr.i) {
+; CHECK-LABEL: @test4
+; CHECK: store
+; CHECK: fence
+; CHECK: store
+; CHECK: ret
+  store i32 5, i32* %addr.i, align 4
+  fence release
+  store i32 5, i32* %addr.i, align 4
+  ret void
+}
+
+; We *could* DSE across this fence, but don't.  No other thread can
+; observe the order of the acquire fence and the store.
+define void @test5(i32* %addr.i) {
+; CHECK-LABEL: @test5
+; CHECK: store
+; CHECK: fence
+; CHECK: store
+; CHECK: ret
+  store i32 5, i32* %addr.i, align 4
+  fence acquire
+  store i32 5, i32* %addr.i, align 4
+  ret void
+}

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

Added: llvm/trunk/test/Transforms/EarlyCSE/floatingpoint.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/floatingpoint.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/floatingpoint.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/floatingpoint.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -S -early-cse | FileCheck %s
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+
+; Ensure we don't simplify away additions vectors of +0.0's (same as scalars).
+define <4 x float> @fV( <4 x float> %a) {
+       ; CHECK: %b = fadd <4 x float> %a, zeroinitializer
+       %b = fadd  <4 x float> %a, <float 0.0,float 0.0,float 0.0,float 0.0>
+       ret <4 x float> %b
+}
+
+define <4 x float> @fW( <4 x float> %a) {
+       ; CHECK: ret <4 x float> %a
+       %b = fadd  <4 x float> %a, <float -0.0,float -0.0,float -0.0,float -0.0>
+       ret <4 x float> %b
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/globalsaa-memoryssa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/globalsaa-memoryssa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/globalsaa-memoryssa.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/globalsaa-memoryssa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -S -globals-aa -early-cse-memssa | FileCheck %s
+
+define i16 @f1() readonly {
+  ret i16 0
+}
+
+declare void @f2()
+
+; Check that EarlyCSE correctly handles function calls that don't have
+; a MemoryAccess.  In this case the calls to @f1 have no
+; MemoryAccesses since globals-aa determines that @f1 doesn't
+; read/write memory at all.
+
+define void @f3() {
+; CHECK-LABEL: @f3(
+; CHECK-NEXT:    [[CALL1:%.*]] = call i16 @f1()
+; CHECK-NEXT:    call void @f2()
+; CHECK-NEXT:    ret void
+;
+  %call1 = call i16 @f1()
+  call void @f2()
+  %call2 = call i16 @f1()
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/guards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/guards.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/guards.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,528 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+
+declare void @llvm.experimental.guard(i1,...)
+
+declare void @llvm.assume(i1)
+
+define i32 @test0(i32* %ptr, i1 %cond) {
+; We can do store to load forwarding over a guard, since it does not
+; clobber memory
+
+; CHECK-LABEL: @test0(
+; CHECK-NEXT:  store i32 40, i32* %ptr
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
+; CHECK-NEXT:  ret i32 40
+
+  store i32 40, i32* %ptr
+  call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
+  %rval = load i32, i32* %ptr
+  ret i32 %rval
+}
+
+define i32 @test1(i32* %val, i1 %cond) {
+; We can CSE loads over a guard, since it does not clobber memory
+
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  %val0 = load i32, i32* %val
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
+; CHECK-NEXT:  ret i32 0
+
+  %val0 = load i32, i32* %val
+  call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
+  %val1 = load i32, i32* %val
+  %rval = sub i32 %val0, %val1
+  ret i32 %rval
+}
+
+define i32 @test2() {
+; Guards on "true" get removed
+
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: ret i32 0
+  call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
+  ret i32 0
+}
+
+define i32 @test3(i32 %val) {
+; After a guard has executed the condition it was guarding is known to
+; be true.
+
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
+; CHECK-NEXT:  ret i32 -1
+
+  %cond0 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
+  %cond1 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+
+  %cond2 = icmp slt i32 %val, 40
+  %rval = sext i1 %cond2 to i32
+  ret i32 %rval
+}
+
+define i32 @test3.unhandled(i32 %val) {
+; After a guard has executed the condition it was guarding is known to
+; be true.
+
+; CHECK-LABEL: @test3.unhandled(
+; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
+; CHECK-NEXT:  %cond1 = icmp sge i32 %val, 40
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+; CHECK-NEXT:  ret i32 0
+
+; Demonstrates a case we do not yet handle (it is legal to fold %cond2
+; to false)
+  %cond0 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
+  %cond1 = icmp sge i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+  ret i32 0
+}
+
+define i32 @test4(i32 %val, i1 %c) {
+; Same as test3, but with some control flow involved.
+
+; CHECK-LABEL: @test4(
+; CHECK: entry:
+; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0
+; CHECK-NEXT:  br label %bb0
+
+; CHECK:     bb0:
+; CHECK-NEXT:  %cond2 = icmp ult i32 %val, 200
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond2
+; CHECK-NEXT:  br i1 %c, label %left, label %right
+
+; CHECK:     left:
+; CHECK-NEXT:  ret i32 0
+
+; CHECK:     right:
+; CHECK-NEXT:  ret i32 20
+
+entry:
+  %cond0 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
+  %cond1 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+  br label %bb0
+
+bb0:
+  %cond2 = icmp ult i32 %val, 200
+  call void(i1,...) @llvm.experimental.guard(i1 %cond2) [ "deopt"() ]
+  br i1 %c, label %left, label %right
+
+left:
+  %cond3 = icmp ult i32 %val, 200
+  call void(i1,...) @llvm.experimental.guard(i1 %cond3) [ "deopt"() ]
+  ret i32 0
+
+right:
+ ret i32 20
+}
+
+define i32 @test5(i32 %val, i1 %c) {
+; Same as test4, but the %left block has mutliple predecessors.
+
+; CHECK-LABEL: @test5(
+
+; CHECK: entry:
+; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0
+; CHECK-NEXT:  br label %bb0
+
+; CHECK: bb0:
+; CHECK-NEXT:  %cond2 = icmp ult i32 %val, 200
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond2
+; CHECK-NEXT:  br i1 %c, label %left, label %right
+
+; CHECK: left:
+; CHECK-NEXT:  br label %right
+
+; CHECK: right:
+; CHECK-NEXT:  br label %left
+
+entry:
+  %cond0 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
+  %cond1 = icmp slt i32 %val, 40
+  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
+  br label %bb0
+
+bb0:
+  %cond2 = icmp ult i32 %val, 200
+  call void(i1,...) @llvm.experimental.guard(i1 %cond2) [ "deopt"() ]
+  br i1 %c, label %left, label %right
+
+left:
+  %cond3 = icmp ult i32 %val, 200
+  call void(i1,...) @llvm.experimental.guard(i1 %cond3) [ "deopt"() ]
+  br label %right
+
+right:
+  br label %left
+}
+
+define void @test6(i1 %c, i32* %ptr) {
+; Check that we do not DSE over calls to @llvm.experimental.guard.
+; Guard intrinsics do _read_ memory, so th call to guard below needs
+; to see the store of 500 to %ptr
+
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:  store i32 500, i32* %ptr
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"() ]
+; CHECK-NEXT:  store i32 600, i32* %ptr
+
+
+  store i32 500, i32* %ptr
+  call void(i1,...) @llvm.experimental.guard(i1 %c) [ "deopt"() ]
+  store i32 600, i32* %ptr
+  ret void
+}
+
+define void @test07(i32 %a, i32 %b) {
+; Check that we are able to remove the guards on the same condition even if the
+; condition is not being recalculated.
+
+; CHECK-LABEL: @test07(
+; CHECK-NEXT:  %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+; CHECK-NEXT:  ret void
+
+  %cmp = icmp eq i32 %a, %b
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  ret void
+}
+
+define void @test08(i32 %a, i32 %b, i32* %ptr) {
+; Check that we deal correctly with stores when removing guards in the same
+; block in case when the condition is not recalculated.
+
+; CHECK-LABEL: @test08(
+; CHECK-NEXT:  %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:  store i32 100, i32* %ptr
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+; CHECK-NEXT:  store i32 400, i32* %ptr
+; CHECK-NEXT:  ret void
+
+  %cmp = icmp eq i32 %a, %b
+  store i32 100, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 200, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 300, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 400, i32* %ptr
+  ret void
+}
+
+define void @test09(i32 %a, i32 %b, i1 %c, i32* %ptr) {
+; Similar to test08, but with more control flow.
+; TODO: Can we get rid of the store in the end of entry given that it is
+; post-dominated by other stores?
+
+; CHECK-LABEL: @test09(
+; CHECK:       entry:
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    store i32 100, i32* %ptr
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+; CHECK-NEXT:    store i32 400, i32* %ptr
+; CHECK-NEXT:    br i1 %c, label %if.true, label %if.false
+; CHECK:       if.true:
+; CHECK-NEXT:    store i32 500, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       if.false:
+; CHECK-NEXT:    store i32 600, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+
+entry:
+  %cmp = icmp eq i32 %a, %b
+  store i32 100, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 200, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 300, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 400, i32* %ptr
+  br i1 %c, label %if.true, label %if.false
+
+if.true:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 500, i32* %ptr
+  br label %merge
+
+if.false:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 600, i32* %ptr
+  br label %merge
+
+merge:
+  ret void
+}
+
+define void @test10(i32 %a, i32 %b, i1 %c, i32* %ptr) {
+; Make sure that non-dominating guards do not cause other guards removal.
+
+; CHECK-LABEL: @test10(
+; CHECK:       entry:
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    br i1 %c, label %if.true, label %if.false
+; CHECK:       if.true:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+; CHECK-NEXT:    store i32 100, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       if.false:
+; CHECK-NEXT:    store i32 200, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       merge:
+; CHECK-NEXT:    store i32 300, i32* %ptr
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+; CHECK-NEXT:    store i32 400, i32* %ptr
+; CHECK-NEXT:    ret void
+
+entry:
+  %cmp = icmp eq i32 %a, %b
+  br i1 %c, label %if.true, label %if.false
+
+if.true:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 100, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  br label %merge
+
+if.false:
+  store i32 200, i32* %ptr
+  br label %merge
+
+merge:
+  store i32 300, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 400, i32* %ptr
+  ret void
+}
+
+define void @test11(i32 %a, i32 %b, i32* %ptr) {
+; Make sure that branching condition is applied to guards.
+
+; CHECK-LABEL: @test11(
+; CHECK:       entry:
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    br i1 %cmp, label %if.true, label %if.false
+; CHECK:       if.true:
+; CHECK-NEXT:    br label %merge
+; CHECK:       if.false:
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
+; CHECK-NEXT:    br label %merge
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+
+entry:
+  %cmp = icmp eq i32 %a, %b
+  br i1 %cmp, label %if.true, label %if.false
+
+if.true:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  br label %merge
+
+if.false:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  br label %merge
+
+merge:
+  ret void
+}
+
+define void @test12(i32 %a, i32 %b) {
+; Check that the assume marks its condition as being true (and thus allows to
+; eliminate the dominated guards).
+
+; CHECK-LABEL: @test12(
+; CHECK-NEXT:  %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:  call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:  ret void
+
+  %cmp = icmp eq i32 %a, %b
+  call void @llvm.assume(i1 %cmp)
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  ret void
+}
+
+define void @test13(i32 %a, i32 %b, i32* %ptr) {
+; Check that we deal correctly with stores when removing guards due to assume.
+
+; CHECK-LABEL: @test13(
+; CHECK-NEXT:  %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:  call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:  store i32 400, i32* %ptr
+; CHECK-NEXT:  ret void
+
+  %cmp = icmp eq i32 %a, %b
+  call void @llvm.assume(i1 %cmp)
+  store i32 100, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 200, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 300, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 400, i32* %ptr
+  ret void
+}
+
+define void @test14(i32 %a, i32 %b, i1 %c, i32* %ptr) {
+; Similar to test13, but with more control flow.
+; TODO: Can we get rid of the store in the end of entry given that it is
+; post-dominated by other stores?
+
+; CHECK-LABEL: @test14(
+; CHECK:       entry:
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:    store i32 400, i32* %ptr
+; CHECK-NEXT:    br i1 %c, label %if.true, label %if.false
+; CHECK:       if.true:
+; CHECK-NEXT:    store i32 500, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       if.false:
+; CHECK-NEXT:    store i32 600, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+
+entry:
+  %cmp = icmp eq i32 %a, %b
+  call void @llvm.assume(i1 %cmp)
+  store i32 100, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 200, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 300, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 400, i32* %ptr
+  br i1 %c, label %if.true, label %if.false
+
+if.true:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 500, i32* %ptr
+  br label %merge
+
+if.false:
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 600, i32* %ptr
+  br label %merge
+
+merge:
+  ret void
+}
+
+define void @test15(i32 %a, i32 %b, i1 %c, i32* %ptr) {
+; Make sure that non-dominating assumes do not cause guards removal.
+
+; CHECK-LABEL: @test15(
+; CHECK:       entry:
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    br i1 %c, label %if.true, label %if.false
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:    store i32 100, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       if.false:
+; CHECK-NEXT:    store i32 200, i32* %ptr
+; CHECK-NEXT:    br label %merge
+; CHECK:       merge:
+; CHECK-NEXT:    store i32 300, i32* %ptr
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+; CHECK-NEXT:    store i32 400, i32* %ptr
+; CHECK-NEXT:    ret void
+
+entry:
+  %cmp = icmp eq i32 %a, %b
+  br i1 %c, label %if.true, label %if.false
+
+if.true:
+  call void @llvm.assume(i1 %cmp)
+  store i32 100, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  br label %merge
+
+if.false:
+  store i32 200, i32* %ptr
+  br label %merge
+
+merge:
+  store i32 300, i32* %ptr
+  call void (i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+  store i32 400, i32* %ptr
+  ret void
+}
+
+define void @test16(i32 %a, i32 %b) {
+; Check that we don't bother to do anything with assumes even if we know the
+; condition being true.
+
+; CHECK-LABEL: @test16(
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:    call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:    ret void
+
+  %cmp = icmp eq i32 %a, %b
+  call void @llvm.assume(i1 %cmp)
+  call void @llvm.assume(i1 %cmp)
+  ret void
+}
+
+define void @test17(i32 %a, i32 %b, i1 %c, i32* %ptr) {
+; Check that we don't bother to do anything with assumes even if we know the
+; condition being true or false (includes come control flow).
+
+; CHECK-LABEL: @test17(
+; CHECK:       entry:
+; CHECK-NEXT:    %cmp = icmp eq i32 %a, %b
+; CHECK-NEXT:    br i1 %c, label %if.true, label %if.false
+; CHECK:       if.true:
+; CHECK-NEXT:    call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:    br label %merge
+; CHECK:       if.false:
+; CHECK-NEXT:    call void @llvm.assume(i1 %cmp)
+; CHECK-NEXT:    br label %merge
+; CHECK:       merge:
+; CHECK-NEXT:    ret void
+
+entry:
+  %cmp = icmp eq i32 %a, %b
+  br i1 %c, label %if.true, label %if.false
+
+if.true:
+  call void @llvm.assume(i1 %cmp)
+  br label %merge
+
+if.false:
+  call void @llvm.assume(i1 %cmp)
+  br label %merge
+
+merge:
+  ret void
+}
+
+define void @test18(i1 %c) {
+; Check that we don't bother to do anything with assumes even if we know the
+; condition being true and not being an instruction.
+
+; CHECK-LABEL: @test18(
+; CHECK-NEXT:    call void @llvm.assume(i1 %c)
+; CHECK-NEXT:    call void @llvm.assume(i1 %c)
+; CHECK-NEXT:    ret void
+
+  call void @llvm.assume(i1 %c)
+  call void @llvm.assume(i1 %c)
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/instsimplify-dom.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/instsimplify-dom.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/instsimplify-dom.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/instsimplify-dom.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -early-cse -S < %s | FileCheck %s
+; RUN: opt -basicaa -early-cse-memssa -S < %s | FileCheck %s
+; PR12231
+
+declare i32 @f()
+
+define i32 @fn() {
+entry:
+  br label %lbl_1215
+
+lbl_1215:
+  %ins34 = phi i32 [ %ins35, %xxx ], [ undef, %entry ]
+  ret i32 %ins34
+
+xxx:
+  %ins35 = call i32 @f()
+  br label %lbl_1215
+}
+
+; CHECK-LABEL: define i32 @fn(

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

Added: llvm/trunk/test/Transforms/EarlyCSE/intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/intrinsics.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/intrinsics.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/intrinsics.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -S -mtriple=amdgcn-- -early-cse | FileCheck %s
+
+; CHECK-LABEL: @no_cse
+; CHECK: call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 0, i32 0)
+; CHECK: call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 4, i32 0)
+define void @no_cse(i32 addrspace(1)* %out, <4 x i32> %in) {
+  %a = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 0, i32 0)
+  %b = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 4, i32 0)
+  %c = add i32 %a, %b
+  store i32 %c, i32 addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @cse_zero_offset
+; CHECK: [[CSE:%[a-z0-9A-Z]+]] = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 0, i32 0)
+; CHECK: add i32 [[CSE]], [[CSE]]
+define void @cse_zero_offset(i32 addrspace(1)* %out, <4 x i32> %in) {
+  %a = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 0, i32 0)
+  %b = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 0, i32 0)
+  %c = add i32 %a, %b
+  store i32 %c, i32 addrspace(1)* %out
+  ret void
+}
+
+; CHECK-LABEL: @cse_nonzero_offset
+; CHECK: [[CSE:%[a-z0-9A-Z]+]] = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 4, i32 0)
+; CHECK: add i32 [[CSE]], [[CSE]]
+define void @cse_nonzero_offset(i32 addrspace(1)* %out, <4 x i32> %in) {
+  %a = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 4, i32 0)
+  %b = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %in, i32 4, i32 0)
+  %c = add i32 %a, %b
+  store i32 %c, i32 addrspace(1)* %out
+  ret void
+}
+
+declare i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> nocapture, i32, i32)

Added: llvm/trunk/test/Transforms/EarlyCSE/invariant-loads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/invariant-loads.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/invariant-loads.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/invariant-loads.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,158 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+; RUN: opt -S -basicaa -early-cse-memssa < %s | FileCheck %s
+
+declare void @clobber_and_use(i32)
+
+define void @f_0(i32* %ptr) {
+; CHECK-LABEL: @f_0(
+; CHECK:   %val0 = load i32, i32* %ptr, !invariant.load !0
+; CHECK:   call void @clobber_and_use(i32 %val0)
+; CHECK:   call void @clobber_and_use(i32 %val0)
+; CHECK:   call void @clobber_and_use(i32 %val0)
+; CHECK:   ret void
+
+  %val0 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val0)
+  %val1 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val1)
+  %val2 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val2)
+  ret void
+}
+
+define void @f_1(i32* %ptr) {
+; We can forward invariant loads to non-invariant loads.
+
+; CHECK-LABEL: @f_1(
+; CHECK:   %val0 = load i32, i32* %ptr, !invariant.load !0
+; CHECK:   call void @clobber_and_use(i32 %val0)
+; CHECK:   call void @clobber_and_use(i32 %val0)
+
+  %val0 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val0)
+  %val1 = load i32, i32* %ptr
+  call void @clobber_and_use(i32 %val1)
+  ret void
+}
+
+define void @f_2(i32* %ptr) {
+; We can forward a non-invariant load into an invariant load.
+
+; CHECK-LABEL: @f_2(
+; CHECK:   %val0 = load i32, i32* %ptr
+; CHECK:   call void @clobber_and_use(i32 %val0)
+; CHECK:   call void @clobber_and_use(i32 %val0)
+
+  %val0 = load i32, i32* %ptr
+  call void @clobber_and_use(i32 %val0)
+  %val1 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val1)
+  ret void
+}
+
+define void @f_3(i1 %cond, i32* %ptr) {
+; CHECK-LABEL: @f_3(
+  %val0 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val0)
+  br i1 %cond, label %left, label %right
+
+; CHECK:  %val0 = load i32, i32* %ptr, !invariant.load !0
+; CHECK: left:
+; CHECK-NEXT:  call void @clobber_and_use(i32 %val0)
+
+left:
+  %val1 = load i32, i32* %ptr
+  call void @clobber_and_use(i32 %val1)
+  ret void
+
+right:
+  ret void
+}
+
+define void @f_4(i1 %cond, i32* %ptr) {
+; Negative test -- can't forward %val0 to %va1 because that'll break
+; def-dominates-use.
+
+; CHECK-LABEL: @f_4(
+  br i1 %cond, label %left, label %merge
+
+left:
+; CHECK: left:
+; CHECK-NEXT:  %val0 = load i32, i32* %ptr, !invariant.load !
+; CHECK-NEXT:  call void @clobber_and_use(i32 %val0)
+
+  %val0 = load i32, i32* %ptr, !invariant.load !{}
+  call void @clobber_and_use(i32 %val0)
+  br label %merge
+
+merge:
+; CHECK: merge:
+; CHECK-NEXT:   %val1 = load i32, i32* %ptr
+; CHECK-NEXT:   call void @clobber_and_use(i32 %val1)
+
+  %val1 = load i32, i32* %ptr
+  call void @clobber_and_use(i32 %val1)
+  ret void
+}
+
+; By assumption, the call can't change contents of p
+; LangRef is a bit unclear about whether the store is reachable, so
+; for the moment we chose to be conservative and just assume it's valid
+; to restore the same unchanging value.
+define void @test_dse1(i32* %p) {
+; CHECK-LABEL: @test_dse1
+; CHECK-NOT: store
+  %v1 = load i32, i32* %p, !invariant.load !{}
+  call void @clobber_and_use(i32 %v1)
+  store i32 %v1, i32* %p
+  ret void
+}
+
+; By assumption, v1 must equal v2 (TODO)
+define void @test_false_negative_dse2(i32* %p, i32 %v2) {
+; CHECK-LABEL: @test_false_negative_dse2
+; CHECK: store
+  %v1 = load i32, i32* %p, !invariant.load !{}
+  call void @clobber_and_use(i32 %v1)
+  store i32 %v2, i32* %p
+  ret void
+}
+
+; If we remove the load, we still start an invariant scope since
+; it lets us remove later loads not explicitly marked invariant
+define void @test_scope_start_without_load(i32* %p) {
+; CHECK-LABEL: @test_scope_start_without_load
+; CHECK:   %v1 = load i32, i32* %p
+; CHECK:   %add = add i32 %v1, %v1
+; CHECK:   call void @clobber_and_use(i32 %add)
+; CHECK:   call void @clobber_and_use(i32 %v1)
+; CHECK:   ret void
+  %v1 = load i32, i32* %p
+  %v2 = load i32, i32* %p, !invariant.load !{}
+  %add = add i32 %v1, %v2
+  call void @clobber_and_use(i32 %add)
+  %v3 = load i32, i32* %p
+  call void @clobber_and_use(i32 %v3)
+  ret void
+}
+
+; If we already have an invariant scope, don't want to start a new one
+; with a potentially greater generation.  This hides the earlier invariant
+; load
+define void @test_scope_restart(i32* %p) {
+; CHECK-LABEL: @test_scope_restart
+; CHECK:   %v1 = load i32, i32* %p
+; CHECK:   call void @clobber_and_use(i32 %v1)
+; CHECK:   %add = add i32 %v1, %v1
+; CHECK:   call void @clobber_and_use(i32 %add)
+; CHECK:   call void @clobber_and_use(i32 %v1)
+; CHECK:   ret void
+  %v1 = load i32, i32* %p, !invariant.load !{}
+  call void @clobber_and_use(i32 %v1)
+  %v2 = load i32, i32* %p, !invariant.load !{}
+  %add = add i32 %v1, %v2
+  call void @clobber_and_use(i32 %add)
+  %v3 = load i32, i32* %p
+  call void @clobber_and_use(i32 %v3)
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/invariant.start.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/invariant.start.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/invariant.start.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/invariant.start.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,290 @@
+; RUN: opt < %s -S -early-cse | FileCheck %s
+; RUN: opt < %s -S -passes=early-cse | FileCheck %s
+
+declare {}* @llvm.invariant.start.p0i8(i64, i8* nocapture) nounwind readonly
+declare void @llvm.invariant.end.p0i8({}*, i64, i8* nocapture) nounwind
+
+; Check that we do load-load forwarding over invariant.start, since it does not
+; clobber memory
+define i8 @test_bypass1(i8 *%P) {
+  ; CHECK-LABEL: @test_bypass1(
+  ; CHECK-NEXT: %V1 = load i8, i8* %P
+  ; CHECK-NEXT: %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+  ; CHECK-NEXT: ret i8 0
+
+  %V1 = load i8, i8* %P
+  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+  %V2 = load i8, i8* %P
+  %Diff = sub i8 %V1, %V2
+  ret i8 %Diff
+}
+
+
+; Trivial Store->load forwarding over invariant.start
+define i8 @test_bypass2(i8 *%P) {
+  ; CHECK-LABEL: @test_bypass2(
+  ; CHECK-NEXT: store i8 42, i8* %P
+  ; CHECK-NEXT: %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+  ; CHECK-NEXT: ret i8 42
+
+  store i8 42, i8* %P
+  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+  %V1 = load i8, i8* %P
+  ret i8 %V1
+}
+
+; We can DSE over invariant.start calls, since the first store to
+; %P is valid, and the second store is actually unreachable based on semantics
+; of invariant.start.
+define void @test_bypass3(i8* %P) {
+; CHECK-LABEL: @test_bypass3(
+; CHECK-NEXT:  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+; CHECK-NEXT:  store i8 60, i8* %P
+
+  store i8 50, i8* %P
+  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+  store i8 60, i8* %P
+  ret void
+}
+
+
+; FIXME: Now the first store can actually be eliminated, since there is no read within
+; the invariant region, between start and end.
+define void @test_bypass4(i8* %P) {
+
+; CHECK-LABEL: @test_bypass4(
+; CHECK-NEXT: store i8 50, i8* %P
+; CHECK-NEXT:  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+; CHECK-NEXT: call void @llvm.invariant.end.p0i8({}* %i, i64 1, i8* %P)
+; CHECK-NEXT:  store i8 60, i8* %P
+
+
+  store i8 50, i8* %P
+  %i = call {}* @llvm.invariant.start.p0i8(i64 1, i8* %P)
+  call void @llvm.invariant.end.p0i8({}* %i, i64 1, i8* %P)
+  store i8 60, i8* %P
+  ret void
+}
+
+
+declare void @clobber()
+declare {}* @llvm.invariant.start.p0i32(i64 %size, i32* nocapture %ptr)
+declare void @llvm.invariant.end.p0i32({}*, i64, i32* nocapture) nounwind
+
+define i32 @test_before_load(i32* %p) {
+; CHECK-LABEL: @test_before_load
+; CHECK: ret i32 0
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_before_clobber(i32* %p) {
+; CHECK-LABEL: @test_before_clobber
+; CHECK: ret i32 0
+  %v1 = load i32, i32* %p
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_duplicate_scope(i32* %p) {
+; CHECK-LABEL: @test_duplicate_scope
+; CHECK: ret i32 0
+  %v1 = load i32, i32* %p
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @clobber()
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_unanalzyable_load(i32* %p) {
+; CHECK-LABEL: @test_unanalzyable_load
+; CHECK: ret i32 0
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @clobber()
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_negative_after_clobber(i32* %p) {
+; CHECK-LABEL: @test_negative_after_clobber
+; CHECK: ret i32 %sub
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_merge(i32* %p, i1 %cnd) {
+; CHECK-LABEL: @test_merge
+; CHECK: ret i32 0
+  %v1 = load i32, i32* %p
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  br i1 %cnd, label %merge, label %taken
+
+taken:
+  call void @clobber()
+  br label %merge
+merge:
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_negative_after_mergeclobber(i32* %p, i1 %cnd) {
+; CHECK-LABEL: @test_negative_after_mergeclobber
+; CHECK: ret i32 %sub
+  %v1 = load i32, i32* %p
+  br i1 %cnd, label %merge, label %taken
+
+taken:
+  call void @clobber()
+  br label %merge
+merge:
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+; In theory, this version could work, but earlycse is incapable of
+; merging facts along distinct paths.  
+define i32 @test_false_negative_merge(i32* %p, i1 %cnd) {
+; CHECK-LABEL: @test_false_negative_merge
+; CHECK: ret i32 %sub
+  %v1 = load i32, i32* %p
+  br i1 %cnd, label %merge, label %taken
+
+taken:
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @clobber()
+  br label %merge
+merge:
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_merge_unanalyzable_load(i32* %p, i1 %cnd) {
+; CHECK-LABEL: @test_merge_unanalyzable_load
+; CHECK: ret i32 0
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @clobber()
+  %v1 = load i32, i32* %p
+  br i1 %cnd, label %merge, label %taken
+
+taken:
+  call void @clobber()
+  br label %merge
+merge:
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define void @test_dse_before_load(i32* %p, i1 %cnd) {
+; CHECK-LABEL: @test_dse_before_load
+; CHECK-NOT: store
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  store i32 %v1, i32* %p
+  ret void
+}
+
+define void @test_dse_after_load(i32* %p, i1 %cnd) {
+; CHECK-LABEL: @test_dse_after_load
+; CHECK-NOT: store
+  %v1 = load i32, i32* %p
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @clobber()
+  store i32 %v1, i32* %p
+  ret void
+}
+
+
+; In this case, we have a false negative since MemoryLocation is implicitly
+; typed due to the user of a Value to represent the address.  Note that other
+; passes will canonicalize away the bitcasts in this example.
+define i32 @test_false_negative_types(i32* %p) {
+; CHECK-LABEL: @test_false_negative_types
+; CHECK: ret i32 %sub
+  call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %pf = bitcast i32* %p to float*
+  %v2f = load float, float* %pf
+  %v2 = bitcast float %v2f to i32
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_negative_size1(i32* %p) {
+; CHECK-LABEL: @test_negative_size1
+; CHECK: ret i32 %sub
+  call {}* @llvm.invariant.start.p0i32(i64 3, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_negative_size2(i32* %p) {
+; CHECK-LABEL: @test_negative_size2
+; CHECK: ret i32 %sub
+  call {}* @llvm.invariant.start.p0i32(i64 0, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_negative_scope(i32* %p) {
+; CHECK-LABEL: @test_negative_scope
+; CHECK: ret i32 %sub
+  %scope = call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  call void @llvm.invariant.end.p0i32({}* %scope, i64 4, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+define i32 @test_false_negative_scope(i32* %p) {
+; CHECK-LABEL: @test_false_negative_scope
+; CHECK: ret i32 %sub
+  %scope = call {}* @llvm.invariant.start.p0i32(i64 4, i32* %p)
+  %v1 = load i32, i32* %p
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  call void @llvm.invariant.end.p0i32({}* %scope, i64 4, i32* %p)
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}
+
+; Invariant load defact starts an invariant.start scope of the appropriate size
+define i32 @test_invariant_load_scope(i32* %p) {
+; CHECK-LABEL: @test_invariant_load_scope
+; CHECK: ret i32 0
+  %v1 = load i32, i32* %p, !invariant.load !{}
+  call void @clobber()
+  %v2 = load i32, i32* %p
+  %sub = sub i32 %v1, %v2
+  ret i32 %sub
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/memoryssa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/memoryssa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/memoryssa.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/memoryssa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,150 @@
+; RUN: opt < %s -S -early-cse | FileCheck %s --check-prefix=CHECK-NOMEMSSA
+; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
+; RUN: opt < %s -S -passes='early-cse' | FileCheck %s --check-prefix=CHECK-NOMEMSSA
+; RUN: opt < %s -S -aa-pipeline=basic-aa -passes='early-cse-memssa' | FileCheck %s
+
+ at G1 = global i32 zeroinitializer
+ at G2 = global i32 zeroinitializer
+ at G3 = global i32 zeroinitializer
+
+;; Simple load value numbering across non-clobbering store.
+; CHECK-LABEL: @test1(
+; CHECK-NOMEMSSA-LABEL: @test1(
+define i32 @test1() {
+  %V1 = load i32, i32* @G1
+  store i32 0, i32* @G2
+  %V2 = load i32, i32* @G1
+  ; CHECK-NOMEMSSA: sub i32 %V1, %V2
+  %Diff = sub i32 %V1, %V2
+  ret i32 %Diff
+  ; CHECK: ret i32 0
+}
+
+;; Simple dead store elimination across non-clobbering store.
+; CHECK-LABEL: @test2(
+; CHECK-NOMEMSSA-LABEL: @test2(
+define void @test2() {
+entry:
+  %V1 = load i32, i32* @G1
+  ; CHECK: store i32 0, i32* @G2
+  store i32 0, i32* @G2
+  ; CHECK-NOT: store
+  ; CHECK-NOMEMSSA: store i32 %V1, i32* @G1
+  store i32 %V1, i32* @G1
+  ret void
+}
+
+;; Check that memoryphi optimization happens during EarlyCSE, enabling
+;; more load CSE opportunities.
+; CHECK-LABEL: @test_memphiopt(
+; CHECK-NOMEMSSA-LABEL: @test_memphiopt(
+define void @test_memphiopt(i1 %c, i32* %p) {
+; CHECK-LABEL: entry:
+; CHECK-NOMEMSSA-LABEL: entry:
+entry:
+; CHECK: load
+; CHECK-NOMEMSSA: load
+  %v1 = load i32, i32* @G1
+  br i1 %c, label %then, label %end
+
+; CHECK-LABEL: then:
+; CHECK-NOMEMSSA-LABEL: then:
+then:
+; CHECK: load
+; CHECK-NOMEMSSA: load
+  %pv = load i32, i32* %p
+; CHECK-NOT: store
+; CHECK-NOMEMSSA-NOT: store
+  store i32 %pv, i32* %p
+  br label %end
+
+; CHECK-LABEL: end:
+; CHECK-NOMEMSSA-LABEL: end:
+end:
+; CHECK-NOT: load
+; CHECK-NOMEMSSA: load
+  %v2 = load i32, i32* @G1
+  %sum = add i32 %v1, %v2
+  store i32 %sum, i32* @G2
+  ret void
+}
+
+
+;; Check that MemoryPhi optimization and MemoryUse re-optimization
+;; happens during EarlyCSE, enabling more load CSE opportunities.
+; CHECK-LABEL: @test_memphiopt2(
+; CHECK-NOMEMSSA-LABEL: @test_memphiopt2(
+define void @test_memphiopt2(i1 %c, i32* %p) {
+; CHECK-LABEL: entry:
+; CHECK-NOMEMSSA-LABEL: entry:
+entry:
+; CHECK: load
+; CHECK-NOMEMSSA: load
+  %v1 = load i32, i32* @G1
+; CHECK: store
+; CHECK-NOMEMSSA: store
+  store i32 %v1, i32* @G2
+  br i1 %c, label %then, label %end
+
+; CHECK-LABEL: then:
+; CHECK-NOMEMSSA-LABEL: then:
+then:
+; CHECK: load
+; CHECK-NOMEMSSA: load
+  %pv = load i32, i32* %p
+; CHECK-NOT: store
+; CHECK-NOMEMSSA-NOT: store
+  store i32 %pv, i32* %p
+  br label %end
+
+; CHECK-LABEL: end:
+; CHECK-NOMEMSSA-LABEL: end:
+end:
+; CHECK-NOT: load
+; CHECK-NOMEMSSA: load
+  %v2 = load i32, i32* @G1
+  store i32 %v2, i32* @G3
+  ret void
+}
+
+;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
+;; stores that, without the lifetime calls, would be writebacks.
+; CHECK-LABEL: @test_writeback_lifetimes(
+; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes(
+define void @test_writeback_lifetimes(i32* %p) {
+entry:
+  %q = getelementptr i32, i32* %p, i64 1
+  %pv = load i32, i32* %p
+  %qv = load i32, i32* %q
+  call void @llvm.lifetime.end.p0i8(i64 8, i32* %p)
+  call void @llvm.lifetime.start.p0i8(i64 8, i32* %p)
+  ; CHECK: store i32 %pv
+  ; CHECK-NOMEMSSA-LABEL: store i32 %pv
+  store i32 %pv, i32* %p
+  ; CHECK: store i32 %qv, i32* %q
+  ; CHECK-NOMEMSSA-LABEL: store i32 %qv, i32* %q
+  store i32 %qv, i32* %q
+  ret void
+}
+
+;; Check that we respect lifetime.start/lifetime.end intrinsics when deleting
+;; stores that, without the lifetime calls, would be writebacks.
+; CHECK-LABEL: @test_writeback_lifetimes_multi_arg(
+; CHECK-NOMEMSSA-LABEL: @test_writeback_lifetimes_multi_arg(
+define void @test_writeback_lifetimes_multi_arg(i32* %p, i32* %q) {
+entry:
+  %pv = load i32, i32* %p
+  %qv = load i32, i32* %q
+  call void @llvm.lifetime.end.p0i8(i64 8, i32* %p)
+  call void @llvm.lifetime.start.p0i8(i64 8, i32* %p)
+  ; CHECK: store i32 %pv
+  ; CHECK-NOMEMSSA-LABEL: store i32 %pv
+  store i32 %pv, i32* %p
+  ; CHECK: store i32 %qv, i32* %q
+  ; CHECK-NOMEMSSA-LABEL: store i32 %qv, i32* %q
+  store i32 %qv, i32* %q
+  ret void
+}
+
+declare void @llvm.lifetime.end.p0i8(i64, i32*)
+declare void @llvm.lifetime.start.p0i8(i64, i32*)

Added: llvm/trunk/test/Transforms/EarlyCSE/pr33406.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/pr33406.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/pr33406.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/pr33406.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt -early-cse-memssa -S %s | FileCheck %s
+
+; CHECK: define void @patatino() {
+; CHECK:  for.cond:
+; CHECK-NEXT:  br i1 true, label %if.end, label %for.inc
+; CHECK:  if.end:
+; CHECK-NEXT:  %tinkywinky = load i32, i32* @b
+; CHECK-NEXT:  br i1 true, label %for.inc, label %for.inc
+; CHECK:  for.inc:
+; CHECK-NEXT:  ret void
+
+
+ at b = external global i32
+
+define void @patatino() {
+for.cond:
+  br i1 true, label %if.end, label %for.inc
+
+if.end:
+  %tinkywinky = load i32, i32* @b
+  store i32 %tinkywinky, i32* @b
+  br i1 true, label %for.inc, label %for.inc
+
+for.inc:
+  ret void
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/preserve_memoryssa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/preserve_memoryssa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/preserve_memoryssa.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/preserve_memoryssa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,137 @@
+; RUN: opt < %s -early-cse-memssa -verify-memoryssa -disable-output
+; REQUIRES: asserts
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Tests below highlight scenarios where EarlyCSE does not preserve MemorySSA
+; optimized accesses. Current MemorySSA verify will accept these.
+
+; Test 1:
+; AA cannot tell here that the last load does not alias the only store.
+; The first two loads are a common expression, EarlyCSE removes the second one,
+; and then AA can see that the last load is a Use(LoE). Hence not optimized as
+; it claims. Note that if we replace the GEP indices 2 and 1, AA sees NoAlias
+; for the last load, before CSE-ing the first 2 loads.
+%struct.ImageParameters = type { i32, i32, i32 }
+ at img = external global %struct.ImageParameters*, align 8
+define void @test1_macroblock() {
+entry:
+  ; MemoryUse(LoE)
+  %0 = load %struct.ImageParameters*, %struct.ImageParameters** @img, align 8
+
+  %Pos_2 = getelementptr inbounds %struct.ImageParameters, %struct.ImageParameters* %0, i64 0, i32 2
+  ; 1 = MemoryDef(LoE)
+  store i32 undef, i32* %Pos_2, align 8
+
+  ; MemoryUse(LoE)
+  %1 = load %struct.ImageParameters*, %struct.ImageParameters** @img, align 8
+
+  %Pos_1 = getelementptr inbounds %struct.ImageParameters, %struct.ImageParameters* %1, i64 0, i32 1
+  ; MemoryUse(1) MayAlias
+  %2 = load i32, i32* %Pos_1, align 4
+  unreachable
+}
+
+; Test 2:
+; EarlyCSE simplifies %string to undef. Def and Use used to be MustAlias, with
+; undef they are NoAlias. The Use can be optimized further to LoE. We can
+; de-optimize uses of replaced instructions, but in general this is not enough
+; (see next tests).
+%struct.TermS = type { i32, i32, i32, i32, i32, i8* }
+define fastcc void @test2_term_string() {
+entry:
+  %string = getelementptr inbounds %struct.TermS, %struct.TermS* undef, i64 0, i32 5
+  ; 1 = MemoryDef(LoE)
+  store i8* undef, i8** %string, align 8
+  ; MemoryUse(1) MustAlias
+  %0 = load i8*, i8** %string, align 8
+  unreachable
+}
+
+; Test 3:
+; EarlyCSE simplifies %0 to undef. So the second Def now stores to undef.
+; We now find the second load (Use(2) can be optimized further to LoE)
+; When replacing instructions, we can deoptimize all uses of the replaced
+; instruction and all uses of transitive accesses. However this does not stop
+; MemorySSA from being tripped by AA (see test4).
+%struct.Grammar = type { i8*, i8*, %struct.anon }
+%struct.anon = type { i32, i32, %struct.Term**, [3 x %struct.Term*] }
+%struct.Term = type { i32 }
+
+define fastcc void @test3_term_string(%struct.Grammar* %g) {
+entry:
+  ; 1 = MemoryDef(LoE)
+  store i8* undef, i8** undef, align 8
+  ; MemoryUse(LoE)
+  %0 = load i8*, i8** undef, align 8
+  %arrayidx = getelementptr inbounds i8, i8* %0, i64 undef
+  ; 2 = MemoryDef(1)
+  store i8 0, i8* %arrayidx, align 1
+  %v = getelementptr inbounds %struct.Grammar, %struct.Grammar* %g, i64 0, i32 2, i32 2
+  ; MemoryUse(2) MayAlias
+  %1 = load %struct.Term**, %struct.Term*** %v, align 8
+  unreachable
+}
+
+; Test 4:
+; Removing dead/unused instructions in if.then274 makes AA smarter. Before
+; removal, it finds %4 MayAlias the store above. After removal this can be
+; optimized to LoE. Hence after EarlyCSE, there is an access who claims is
+; optimized and it can be optimized further.
+
+; We can't escape such cases in general when relying on Alias Analysis.
+; The only fail-safe way to actually preserve MemorySSA when removing or
+; replacing instructions (i.e. get the *same* MemorySSA as if it was computed
+; for the updated IR) is to recompute it from scratch. What we get now is still
+; a correct update, but with accesses that claim to be optimized and can be
+; optimized further if we were to re-run MemorySSA on the IR.
+%struct.gnode.0.1.3.6.9.18.20.79 = type { i32, i32, i32, i32, i32, i32, i32, %struct.gnode.0.1.3.6.9.18.20.79* }
+ at gnodeArray = external global %struct.gnode.0.1.3.6.9.18.20.79**, align 8
+
+define void @test4_shortest() {
+entry:
+  %exl.i = alloca [5 x i32], align 16
+  br i1 undef, label %if.then274, label %for.cond404
+
+if.then274:                                       ; preds = %if.end256
+  %0 = bitcast [5 x i32]* %exl.i to i8*
+  %arrayidx.i = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 1
+  %arrayidx1.i = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 2
+  %arrayidx2.i = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 3
+  %arrayidx3.i = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 4
+  %1 = bitcast [5 x i32]* %exl.i to i8*
+  %arrayidx.i1034 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 1
+  %arrayidx1.i1035 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 2
+  %arrayidx2.i1036 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 3
+  %arrayidx3.i1037 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 4
+  unreachable
+
+for.cond404:                                      ; preds = %if.end256
+  %2 = bitcast [5 x i32]* %exl.i to i8*
+  %arrayidx.i960 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 1
+  %arrayidx1.i961 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 2
+  %arrayidx2.i962 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 3
+  ; 1 = MemoryDef(LoE)
+  store i32 undef, i32* %arrayidx2.i962, align 4
+  %arrayidx3.i963 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 4
+
+  ; MemoryUse(LoE)
+  %3 = load %struct.gnode.0.1.3.6.9.18.20.79**, %struct.gnode.0.1.3.6.9.18.20.79*** @gnodeArray, align 8
+  %arrayidx6.i968 = getelementptr inbounds %struct.gnode.0.1.3.6.9.18.20.79*, %struct.gnode.0.1.3.6.9.18.20.79** %3, i64 undef
+  ; MemoryUse(1) MayAlias
+  %4 = load %struct.gnode.0.1.3.6.9.18.20.79*, %struct.gnode.0.1.3.6.9.18.20.79** %arrayidx6.i968, align 8
+  br i1 undef, label %for.cond26.preheader.i974, label %if.then20.for.body_crit_edge.i999
+
+for.cond26.preheader.i974:                        ; preds = %if.then20.i996
+  %5 = bitcast [5 x i32]* %exl.i to i8*
+  %arrayidx.i924 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 1
+  %arrayidx1.i925 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 2
+  %arrayidx2.i926 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 3
+  %arrayidx3.i927 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 4
+  unreachable
+
+if.then20.for.body_crit_edge.i999:                ; preds = %if.then20.i996
+  %arrayidx9.phi.trans.insert.i997 = getelementptr inbounds [5 x i32], [5 x i32]* %exl.i, i64 0, i64 undef
+  unreachable
+}

Added: llvm/trunk/test/Transforms/EarlyCSE/read-reg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/read-reg.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/read-reg.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/read-reg.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+; RUN: opt -S -basicaa -early-cse-memssa < %s | FileCheck %s
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define i64 @f(i64 %x) #0 {
+entry:
+  %0 = call i64 @llvm.read_register.i64(metadata !0)
+  call void bitcast (void (...)* @foo to void ()*)()
+  %1 = call i64 @llvm.read_register.i64(metadata !0)
+  %add = add nsw i64 %0, %1
+  ret i64 %add
+}
+
+; CHECK-LABEL: @f
+; CHECK: call i64 @llvm.read_register.i64
+; CHECK: call i64 @llvm.read_register.i64
+
+; Function Attrs: nounwind readnone
+declare i64 @llvm.read_register.i64(metadata) #1
+
+; Function Attrs: nounwind
+declare void @llvm.write_register.i64(metadata, i64) #2
+
+declare void @foo(...)
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind }
+
+!llvm.named.register.r1 = !{!0}
+
+!0 = !{!"r1"}
+

Added: llvm/trunk/test/Transforms/EarlyCSE/readnone-mayunwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EarlyCSE/readnone-mayunwind.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EarlyCSE/readnone-mayunwind.ll (added)
+++ llvm/trunk/test/Transforms/EarlyCSE/readnone-mayunwind.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+
+declare void @readnone_may_unwind() readnone
+
+define void @f(i32* %ptr) {
+; CHECK-LABEL: @f(
+; CHECK: store i32 100, i32* %ptr
+; CHECK: call void @readnone_may_unwind()
+; CHECK: store i32 200, i32* %ptr
+
+  store i32 100, i32* %ptr
+  call void @readnone_may_unwind()
+  store i32 200, i32* %ptr
+  ret void
+}

Added: llvm/trunk/test/Transforms/EliminateAvailableExternally/visibility.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EliminateAvailableExternally/visibility.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EliminateAvailableExternally/visibility.ll (added)
+++ llvm/trunk/test/Transforms/EliminateAvailableExternally/visibility.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt -passes=elim-avail-extern -S < %s | FileCheck %s
+
+; CHECK: declare hidden void @f()
+define available_externally hidden void @f() {
+  ret void
+}
+
+define void @g() {
+  call void @f()
+  ret void
+}

Added: llvm/trunk/test/Transforms/EntryExitInstrumenter/debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EntryExitInstrumenter/debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EntryExitInstrumenter/debug-info.ll (added)
+++ llvm/trunk/test/Transforms/EntryExitInstrumenter/debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -passes="function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument)" -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"
+
+define i32 @f(i32 %x) #0 !dbg !7 {
+entry:
+  %x.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  ret i32 42, !dbg !12
+
+; CHECK-LABEL: define i32 @f(i32 %x)
+; CHECK: call i8* @llvm.returnaddress(i32 0), !dbg ![[ENTRYLOC:[0-9]+]]
+; CHECK: call void @__cyg_profile_func_enter{{.*}}, !dbg ![[ENTRYLOC]]
+
+; CHECK: call i8* @llvm.returnaddress(i32 0), !dbg ![[EXITLOC:[0-9]+]]
+; CHECK: call void @__cyg_profile_func_exit{{.*}}, !dbg ![[EXITLOC]]
+; CHECK: ret i32 42, !dbg ![[EXITLOC]]
+}
+
+; CHECK: ![[SP:[0-9]+]] = distinct !DISubprogram(name: "f"
+; CHECK: ![[ENTRYLOC]] = !DILocation(line: 2, scope: ![[SP]])
+; CHECK: ![[EXITLOC]] = !DILocation(line: 4, column: 3, scope: ![[SP]])
+
+attributes #0 = { "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
+
+!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 (trunk 319007) (llvm/trunk 319050)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "a.c", directory: "/tmp")
+!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 (trunk 319007) (llvm/trunk 319050)"}
+!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocalVariable(name: "x", arg: 1, scope: !7, file: !1, line: 2, type: !10)
+!12 = !DILocation(line: 4, column: 3, scope: !7)

Added: llvm/trunk/test/Transforms/EntryExitInstrumenter/mcount.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/EntryExitInstrumenter/mcount.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/EntryExitInstrumenter/mcount.ll (added)
+++ llvm/trunk/test/Transforms/EntryExitInstrumenter/mcount.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,114 @@
+; RUN: opt -passes="function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument)" -S < %s | FileCheck %s
+
+; Running the passes twice should not result in more instrumentation.
+; RUN: opt -passes="function(ee-instrument),function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument),function(post-inline-ee-instrument)" -S < %s | FileCheck %s
+
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-bgq-linux"
+
+define void @leaf_function() #0 {
+entry:
+  ret void
+
+; CHECK-LABEL: define void @leaf_function()
+; CHECK: entry:
+; CHECK-NEXT: call void @mcount()
+; CHECK-NEXT: %0 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT: call void @__cyg_profile_func_enter(i8* bitcast (void ()* @leaf_function to i8*), i8* %0)
+; CHECK-NEXT: %1 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT: call void @__cyg_profile_func_exit(i8* bitcast (void ()* @leaf_function to i8*), i8* %1)
+; CHECK-NEXT: ret void
+}
+
+
+define void @root_function() #0 {
+entry:
+  call void @leaf_function()
+  ret void
+
+; CHECK-LABEL: define void @root_function()
+; CHECK: entry:
+; CHECK-NEXT: call void @mcount()
+
+; CHECK-NEXT %0 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT call void @__cyg_profile_func_enter(i8* bitcast (void ()* @root_function to i8*), i8* %0)
+
+; Entry and exit calls, inlined from @leaf_function()
+; CHECK-NEXT %1 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT call void @__cyg_profile_func_enter(i8* bitcast (void ()* @leaf_function to i8*), i8* %1)
+; CHECK-NEXT %2 = call i8* @llvm.returnaddress(i32 0)
+; CHECK-NEXT call void @__cyg_profile_func_exit(i8* bitcast (void ()* @leaf_function to i8*), i8* %2)
+; CHECK-NEXT %3 = call i8* @llvm.returnaddress(i32 0)
+
+; CHECK-NEXT call void @__cyg_profile_func_exit(i8* bitcast (void ()* @root_function to i8*), i8* %3)
+; CHECK-NEXT ret void
+}
+
+
+
+; The mcount function has many different names.
+
+define void @f1() #1 { entry: ret void }
+; CHECK-LABEL: define void @f1
+; CHECK: call void @.mcount
+
+define void @f2() #2 { entry: ret void }
+; CHECK-LABEL: define void @f2
+; CHECK: call void @"\01__gnu_mcount_nc"
+
+define void @f3() #3 { entry: ret void }
+; CHECK-LABEL: define void @f3
+; CHECK: call void @"\01_mcount"
+
+define void @f4() #4 { entry: ret void }
+; CHECK-LABEL: define void @f4
+; CHECK: call void @"\01mcount"
+
+define void @f5() #5 { entry: ret void }
+; CHECK-LABEL: define void @f5
+; CHECK: call void @__mcount
+
+define void @f6() #6 { entry: ret void }
+; CHECK-LABEL: define void @f6
+; CHECK: call void @_mcount
+
+define void @f7() #7 { entry: ret void }
+; CHECK-LABEL: define void @f7
+; CHECK: call void @__cyg_profile_func_enter_bare
+
+
+; Treat musttail calls as terminators; inserting between the musttail call and
+; ret is not allowed.
+declare i32* @tailcallee()
+define i32* @tailcaller() #8 {
+  %1 = musttail call i32* @tailcallee()
+  ret i32* %1
+; CHECK-LABEL: define i32* @tailcaller
+; CHECK: call void @__cyg_profile_func_exit
+; CHECK: musttail call i32* @tailcallee
+; CHECK: ret
+}
+define i8* @tailcaller2() #8 {
+  %1 = musttail call i32* @tailcallee()
+  %2 = bitcast i32* %1 to i8*
+  ret i8* %2
+; CHECK-LABEL: define i8* @tailcaller2
+; CHECK: call void @__cyg_profile_func_exit
+; CHECK: musttail call i32* @tailcallee
+; CHECK: bitcast
+; CHECK: ret
+}
+
+; The attributes are "consumed" when the instrumentation is inserted.
+; CHECK: attributes
+; CHECK-NOT: instrument-function
+
+attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
+attributes #1 = { "instrument-function-entry-inlined"=".mcount" }
+attributes #2 = { "instrument-function-entry-inlined"="\01__gnu_mcount_nc" }
+attributes #3 = { "instrument-function-entry-inlined"="\01_mcount" }
+attributes #4 = { "instrument-function-entry-inlined"="\01mcount" }
+attributes #5 = { "instrument-function-entry-inlined"="__mcount" }
+attributes #6 = { "instrument-function-entry-inlined"="_mcount" }
+attributes #7 = { "instrument-function-entry-inlined"="__cyg_profile_func_enter_bare" }
+attributes #8 = { "instrument-function-exit"="__cyg_profile_func_exit" }

Added: llvm/trunk/test/Transforms/ExpandMemCmp/X86/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ExpandMemCmp/X86/lit.local.cfg?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ExpandMemCmp/X86/lit.local.cfg (added)
+++ llvm/trunk/test/Transforms/ExpandMemCmp/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/ExpandMemCmp/X86/memcmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ExpandMemCmp/X86/memcmp.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ExpandMemCmp/X86/memcmp.ll (added)
+++ llvm/trunk/test/Transforms/ExpandMemCmp/X86/memcmp.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,1219 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -expandmemcmp -mtriple=i686-unknown-unknown   -data-layout=e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128 < %s | FileCheck %s --check-prefix=ALL --check-prefix=X32
+; RUN: opt -S -expandmemcmp -memcmp-num-loads-per-block=1 -mtriple=x86_64-unknown-unknown -data-layout=e-m:o-i64:64-f80:128-n8:16:32:64-S128         < %s | FileCheck %s --check-prefix=ALL --check-prefix=X64 --check-prefix=X64_1LD
+; RUN: opt -S -expandmemcmp -memcmp-num-loads-per-block=2 -mtriple=x86_64-unknown-unknown -data-layout=e-m:o-i64:64-f80:128-n8:16:32:64-S128         < %s | FileCheck %s --check-prefix=ALL --check-prefix=X64 --check-prefix=X64_2LD
+
+declare i32 @memcmp(i8* nocapture, i8* nocapture, i64)
+
+define i32 @cmp2(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp2(
+; ALL-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i16*
+; ALL-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i16*
+; ALL-NEXT:    [[TMP3:%.*]] = load i16, i16* [[TMP1]]
+; ALL-NEXT:    [[TMP4:%.*]] = load i16, i16* [[TMP2]]
+; ALL-NEXT:    [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP3]])
+; ALL-NEXT:    [[TMP6:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP4]])
+; ALL-NEXT:    [[TMP7:%.*]] = zext i16 [[TMP5]] to i32
+; ALL-NEXT:    [[TMP8:%.*]] = zext i16 [[TMP6]] to i32
+; ALL-NEXT:    [[TMP9:%.*]] = sub i32 [[TMP7]], [[TMP8]]
+; ALL-NEXT:    ret i32 [[TMP9]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 2)
+  ret i32 %call
+}
+
+define i32 @cmp3(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp3(
+; ALL-NEXT:    br label [[LOADBB:%.*]]
+; ALL:       res_block:
+; ALL-NEXT:    [[PHI_SRC1:%.*]] = phi i16 [ [[TMP7:%.*]], [[LOADBB]] ]
+; ALL-NEXT:    [[PHI_SRC2:%.*]] = phi i16 [ [[TMP8:%.*]], [[LOADBB]] ]
+; ALL-NEXT:    [[TMP1:%.*]] = icmp ult i16 [[PHI_SRC1]], [[PHI_SRC2]]
+; ALL-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; ALL-NEXT:    br label [[ENDBLOCK:%.*]]
+; ALL:       loadbb:
+; ALL-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i16*
+; ALL-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i16*
+; ALL-NEXT:    [[TMP5:%.*]] = load i16, i16* [[TMP3]]
+; ALL-NEXT:    [[TMP6:%.*]] = load i16, i16* [[TMP4]]
+; ALL-NEXT:    [[TMP7]] = call i16 @llvm.bswap.i16(i16 [[TMP5]])
+; ALL-NEXT:    [[TMP8]] = call i16 @llvm.bswap.i16(i16 [[TMP6]])
+; ALL-NEXT:    [[TMP9:%.*]] = icmp eq i16 [[TMP7]], [[TMP8]]
+; ALL-NEXT:    br i1 [[TMP9]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]]
+; ALL:       loadbb1:
+; ALL-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 2
+; ALL-NEXT:    [[TMP11:%.*]] = getelementptr i8, i8* [[Y]], i8 2
+; ALL-NEXT:    [[TMP12:%.*]] = load i8, i8* [[TMP10]]
+; ALL-NEXT:    [[TMP13:%.*]] = load i8, i8* [[TMP11]]
+; ALL-NEXT:    [[TMP14:%.*]] = zext i8 [[TMP12]] to i32
+; ALL-NEXT:    [[TMP15:%.*]] = zext i8 [[TMP13]] to i32
+; ALL-NEXT:    [[TMP16:%.*]] = sub i32 [[TMP14]], [[TMP15]]
+; ALL-NEXT:    br label [[ENDBLOCK]]
+; ALL:       endblock:
+; ALL-NEXT:    [[PHI_RES:%.*]] = phi i32 [ [[TMP16]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; ALL-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 3)
+  ret i32 %call
+}
+
+define i32 @cmp4(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp4(
+; ALL-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; ALL-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; ALL-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; ALL-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; ALL-NEXT:    [[TMP5:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP3]])
+; ALL-NEXT:    [[TMP6:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP4]])
+; ALL-NEXT:    [[TMP7:%.*]] = icmp ugt i32 [[TMP5]], [[TMP6]]
+; ALL-NEXT:    [[TMP8:%.*]] = icmp ult i32 [[TMP5]], [[TMP6]]
+; ALL-NEXT:    [[TMP9:%.*]] = zext i1 [[TMP7]] to i32
+; ALL-NEXT:    [[TMP10:%.*]] = zext i1 [[TMP8]] to i32
+; ALL-NEXT:    [[TMP11:%.*]] = sub i32 [[TMP9]], [[TMP10]]
+; ALL-NEXT:    ret i32 [[TMP11]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 4)
+  ret i32 %call
+}
+
+define i32 @cmp5(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp5(
+; ALL-NEXT:    br label [[LOADBB:%.*]]
+; ALL:       res_block:
+; ALL-NEXT:    [[PHI_SRC1:%.*]] = phi i32 [ [[TMP7:%.*]], [[LOADBB]] ]
+; ALL-NEXT:    [[PHI_SRC2:%.*]] = phi i32 [ [[TMP8:%.*]], [[LOADBB]] ]
+; ALL-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
+; ALL-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; ALL-NEXT:    br label [[ENDBLOCK:%.*]]
+; ALL:       loadbb:
+; ALL-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; ALL-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; ALL-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP3]]
+; ALL-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP4]]
+; ALL-NEXT:    [[TMP7]] = call i32 @llvm.bswap.i32(i32 [[TMP5]])
+; ALL-NEXT:    [[TMP8]] = call i32 @llvm.bswap.i32(i32 [[TMP6]])
+; ALL-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP7]], [[TMP8]]
+; ALL-NEXT:    br i1 [[TMP9]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]]
+; ALL:       loadbb1:
+; ALL-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; ALL-NEXT:    [[TMP11:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; ALL-NEXT:    [[TMP12:%.*]] = load i8, i8* [[TMP10]]
+; ALL-NEXT:    [[TMP13:%.*]] = load i8, i8* [[TMP11]]
+; ALL-NEXT:    [[TMP14:%.*]] = zext i8 [[TMP12]] to i32
+; ALL-NEXT:    [[TMP15:%.*]] = zext i8 [[TMP13]] to i32
+; ALL-NEXT:    [[TMP16:%.*]] = sub i32 [[TMP14]], [[TMP15]]
+; ALL-NEXT:    br label [[ENDBLOCK]]
+; ALL:       endblock:
+; ALL-NEXT:    [[PHI_RES:%.*]] = phi i32 [ [[TMP16]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; ALL-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 5)
+  ret i32 %call
+}
+
+define i32 @cmp6(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp6(
+; ALL-NEXT:    br label [[LOADBB:%.*]]
+; ALL:       res_block:
+; ALL-NEXT:    [[PHI_SRC1:%.*]] = phi i32 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP18:%.*]], [[LOADBB1:%.*]] ]
+; ALL-NEXT:    [[PHI_SRC2:%.*]] = phi i32 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP19:%.*]], [[LOADBB1]] ]
+; ALL-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
+; ALL-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; ALL-NEXT:    br label [[ENDBLOCK:%.*]]
+; ALL:       loadbb:
+; ALL-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; ALL-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; ALL-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP3]]
+; ALL-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP4]]
+; ALL-NEXT:    [[TMP7]] = call i32 @llvm.bswap.i32(i32 [[TMP5]])
+; ALL-NEXT:    [[TMP8]] = call i32 @llvm.bswap.i32(i32 [[TMP6]])
+; ALL-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP7]], [[TMP8]]
+; ALL-NEXT:    br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; ALL:       loadbb1:
+; ALL-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; ALL-NEXT:    [[TMP11:%.*]] = bitcast i8* [[TMP10]] to i16*
+; ALL-NEXT:    [[TMP12:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; ALL-NEXT:    [[TMP13:%.*]] = bitcast i8* [[TMP12]] to i16*
+; ALL-NEXT:    [[TMP14:%.*]] = load i16, i16* [[TMP11]]
+; ALL-NEXT:    [[TMP15:%.*]] = load i16, i16* [[TMP13]]
+; ALL-NEXT:    [[TMP16:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP14]])
+; ALL-NEXT:    [[TMP17:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP15]])
+; ALL-NEXT:    [[TMP18]] = zext i16 [[TMP16]] to i32
+; ALL-NEXT:    [[TMP19]] = zext i16 [[TMP17]] to i32
+; ALL-NEXT:    [[TMP20:%.*]] = icmp eq i32 [[TMP18]], [[TMP19]]
+; ALL-NEXT:    br i1 [[TMP20]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; ALL:       endblock:
+; ALL-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; ALL-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 6)
+  ret i32 %call
+}
+
+define i32 @cmp7(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp7(
+; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 7)
+; ALL-NEXT:    ret i32 [[CALL]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 7)
+  ret i32 %call
+}
+
+define i32 @cmp8(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp8(
+; X32-NEXT:    br label [[LOADBB:%.*]]
+; X32:       res_block:
+; X32-NEXT:    [[PHI_SRC1:%.*]] = phi i32 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP16:%.*]], [[LOADBB1:%.*]] ]
+; X32-NEXT:    [[PHI_SRC2:%.*]] = phi i32 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP17:%.*]], [[LOADBB1]] ]
+; X32-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[PHI_SRC1]], [[PHI_SRC2]]
+; X32-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X32-NEXT:    br label [[ENDBLOCK:%.*]]
+; X32:       loadbb:
+; X32-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X32-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X32-NEXT:    [[TMP5:%.*]] = load i32, i32* [[TMP3]]
+; X32-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP4]]
+; X32-NEXT:    [[TMP7]] = call i32 @llvm.bswap.i32(i32 [[TMP5]])
+; X32-NEXT:    [[TMP8]] = call i32 @llvm.bswap.i32(i32 [[TMP6]])
+; X32-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP7]], [[TMP8]]
+; X32-NEXT:    br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; X32:       loadbb1:
+; X32-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X32-NEXT:    [[TMP11:%.*]] = bitcast i8* [[TMP10]] to i32*
+; X32-NEXT:    [[TMP12:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X32-NEXT:    [[TMP13:%.*]] = bitcast i8* [[TMP12]] to i32*
+; X32-NEXT:    [[TMP14:%.*]] = load i32, i32* [[TMP11]]
+; X32-NEXT:    [[TMP15:%.*]] = load i32, i32* [[TMP13]]
+; X32-NEXT:    [[TMP16]] = call i32 @llvm.bswap.i32(i32 [[TMP14]])
+; X32-NEXT:    [[TMP17]] = call i32 @llvm.bswap.i32(i32 [[TMP15]])
+; X32-NEXT:    [[TMP18:%.*]] = icmp eq i32 [[TMP16]], [[TMP17]]
+; X32-NEXT:    br i1 [[TMP18]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; X32:       endblock:
+; X32-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X32-NEXT:    ret i32 [[PHI_RES]]
+;
+; X64-LABEL: @cmp8(
+; X64-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64-NEXT:    [[TMP5:%.*]] = call i64 @llvm.bswap.i64(i64 [[TMP3]])
+; X64-NEXT:    [[TMP6:%.*]] = call i64 @llvm.bswap.i64(i64 [[TMP4]])
+; X64-NEXT:    [[TMP7:%.*]] = icmp ugt i64 [[TMP5]], [[TMP6]]
+; X64-NEXT:    [[TMP8:%.*]] = icmp ult i64 [[TMP5]], [[TMP6]]
+; X64-NEXT:    [[TMP9:%.*]] = zext i1 [[TMP7]] to i32
+; X64-NEXT:    [[TMP10:%.*]] = zext i1 [[TMP8]] to i32
+; X64-NEXT:    [[TMP11:%.*]] = sub i32 [[TMP9]], [[TMP10]]
+; X64-NEXT:    ret i32 [[TMP11]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 8)
+  ret i32 %call
+}
+
+define i32 @cmp9(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp9(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 9)
+; X32-NEXT:    ret i32 [[CALL]]
+;
+; X64-LABEL: @cmp9(
+; X64-NEXT:    br label [[LOADBB:%.*]]
+; X64:       res_block:
+; X64-NEXT:    [[PHI_SRC1:%.*]] = phi i64 [ [[TMP7:%.*]], [[LOADBB]] ]
+; X64-NEXT:    [[PHI_SRC2:%.*]] = phi i64 [ [[TMP8:%.*]], [[LOADBB]] ]
+; X64-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[PHI_SRC1]], [[PHI_SRC2]]
+; X64-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64:       loadbb:
+; X64-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64-NEXT:    [[TMP5:%.*]] = load i64, i64* [[TMP3]]
+; X64-NEXT:    [[TMP6:%.*]] = load i64, i64* [[TMP4]]
+; X64-NEXT:    [[TMP7]] = call i64 @llvm.bswap.i64(i64 [[TMP5]])
+; X64-NEXT:    [[TMP8]] = call i64 @llvm.bswap.i64(i64 [[TMP6]])
+; X64-NEXT:    [[TMP9:%.*]] = icmp eq i64 [[TMP7]], [[TMP8]]
+; X64-NEXT:    br i1 [[TMP9]], label [[LOADBB1:%.*]], label [[RES_BLOCK:%.*]]
+; X64:       loadbb1:
+; X64-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64-NEXT:    [[TMP11:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64-NEXT:    [[TMP12:%.*]] = load i8, i8* [[TMP10]]
+; X64-NEXT:    [[TMP13:%.*]] = load i8, i8* [[TMP11]]
+; X64-NEXT:    [[TMP14:%.*]] = zext i8 [[TMP12]] to i32
+; X64-NEXT:    [[TMP15:%.*]] = zext i8 [[TMP13]] to i32
+; X64-NEXT:    [[TMP16:%.*]] = sub i32 [[TMP14]], [[TMP15]]
+; X64-NEXT:    br label [[ENDBLOCK]]
+; X64:       endblock:
+; X64-NEXT:    [[PHI_RES:%.*]] = phi i32 [ [[TMP16]], [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 9)
+  ret i32 %call
+}
+
+define i32 @cmp10(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp10(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 10)
+; X32-NEXT:    ret i32 [[CALL]]
+;
+; X64-LABEL: @cmp10(
+; X64-NEXT:    br label [[LOADBB:%.*]]
+; X64:       res_block:
+; X64-NEXT:    [[PHI_SRC1:%.*]] = phi i64 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP18:%.*]], [[LOADBB1:%.*]] ]
+; X64-NEXT:    [[PHI_SRC2:%.*]] = phi i64 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP19:%.*]], [[LOADBB1]] ]
+; X64-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[PHI_SRC1]], [[PHI_SRC2]]
+; X64-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64:       loadbb:
+; X64-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64-NEXT:    [[TMP5:%.*]] = load i64, i64* [[TMP3]]
+; X64-NEXT:    [[TMP6:%.*]] = load i64, i64* [[TMP4]]
+; X64-NEXT:    [[TMP7]] = call i64 @llvm.bswap.i64(i64 [[TMP5]])
+; X64-NEXT:    [[TMP8]] = call i64 @llvm.bswap.i64(i64 [[TMP6]])
+; X64-NEXT:    [[TMP9:%.*]] = icmp eq i64 [[TMP7]], [[TMP8]]
+; X64-NEXT:    br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; X64:       loadbb1:
+; X64-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64-NEXT:    [[TMP11:%.*]] = bitcast i8* [[TMP10]] to i16*
+; X64-NEXT:    [[TMP12:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64-NEXT:    [[TMP13:%.*]] = bitcast i8* [[TMP12]] to i16*
+; X64-NEXT:    [[TMP14:%.*]] = load i16, i16* [[TMP11]]
+; X64-NEXT:    [[TMP15:%.*]] = load i16, i16* [[TMP13]]
+; X64-NEXT:    [[TMP16:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP14]])
+; X64-NEXT:    [[TMP17:%.*]] = call i16 @llvm.bswap.i16(i16 [[TMP15]])
+; X64-NEXT:    [[TMP18]] = zext i16 [[TMP16]] to i64
+; X64-NEXT:    [[TMP19]] = zext i16 [[TMP17]] to i64
+; X64-NEXT:    [[TMP20:%.*]] = icmp eq i64 [[TMP18]], [[TMP19]]
+; X64-NEXT:    br i1 [[TMP20]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; X64:       endblock:
+; X64-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 10)
+  ret i32 %call
+}
+
+define i32 @cmp11(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp11(
+; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 11)
+; ALL-NEXT:    ret i32 [[CALL]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 11)
+  ret i32 %call
+}
+
+define i32 @cmp12(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp12(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 12)
+; X32-NEXT:    ret i32 [[CALL]]
+;
+; X64-LABEL: @cmp12(
+; X64-NEXT:    br label [[LOADBB:%.*]]
+; X64:       res_block:
+; X64-NEXT:    [[PHI_SRC1:%.*]] = phi i64 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP18:%.*]], [[LOADBB1:%.*]] ]
+; X64-NEXT:    [[PHI_SRC2:%.*]] = phi i64 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP19:%.*]], [[LOADBB1]] ]
+; X64-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[PHI_SRC1]], [[PHI_SRC2]]
+; X64-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64:       loadbb:
+; X64-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64-NEXT:    [[TMP5:%.*]] = load i64, i64* [[TMP3]]
+; X64-NEXT:    [[TMP6:%.*]] = load i64, i64* [[TMP4]]
+; X64-NEXT:    [[TMP7]] = call i64 @llvm.bswap.i64(i64 [[TMP5]])
+; X64-NEXT:    [[TMP8]] = call i64 @llvm.bswap.i64(i64 [[TMP6]])
+; X64-NEXT:    [[TMP9:%.*]] = icmp eq i64 [[TMP7]], [[TMP8]]
+; X64-NEXT:    br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; X64:       loadbb1:
+; X64-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64-NEXT:    [[TMP11:%.*]] = bitcast i8* [[TMP10]] to i32*
+; X64-NEXT:    [[TMP12:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64-NEXT:    [[TMP13:%.*]] = bitcast i8* [[TMP12]] to i32*
+; X64-NEXT:    [[TMP14:%.*]] = load i32, i32* [[TMP11]]
+; X64-NEXT:    [[TMP15:%.*]] = load i32, i32* [[TMP13]]
+; X64-NEXT:    [[TMP16:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP14]])
+; X64-NEXT:    [[TMP17:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP15]])
+; X64-NEXT:    [[TMP18]] = zext i32 [[TMP16]] to i64
+; X64-NEXT:    [[TMP19]] = zext i32 [[TMP17]] to i64
+; X64-NEXT:    [[TMP20:%.*]] = icmp eq i64 [[TMP18]], [[TMP19]]
+; X64-NEXT:    br i1 [[TMP20]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; X64:       endblock:
+; X64-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 12)
+  ret i32 %call
+}
+
+define i32 @cmp13(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp13(
+; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 13)
+; ALL-NEXT:    ret i32 [[CALL]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 13)
+  ret i32 %call
+}
+
+define i32 @cmp14(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp14(
+; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 14)
+; ALL-NEXT:    ret i32 [[CALL]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 14)
+  ret i32 %call
+}
+
+define i32 @cmp15(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp15(
+; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 15)
+; ALL-NEXT:    ret i32 [[CALL]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 15)
+  ret i32 %call
+}
+
+define i32 @cmp16(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp16(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 16)
+; X32-NEXT:    ret i32 [[CALL]]
+;
+; X64-LABEL: @cmp16(
+; X64-NEXT:    br label [[LOADBB:%.*]]
+; X64:       res_block:
+; X64-NEXT:    [[PHI_SRC1:%.*]] = phi i64 [ [[TMP7:%.*]], [[LOADBB]] ], [ [[TMP16:%.*]], [[LOADBB1:%.*]] ]
+; X64-NEXT:    [[PHI_SRC2:%.*]] = phi i64 [ [[TMP8:%.*]], [[LOADBB]] ], [ [[TMP17:%.*]], [[LOADBB1]] ]
+; X64-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[PHI_SRC1]], [[PHI_SRC2]]
+; X64-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 -1, i32 1
+; X64-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64:       loadbb:
+; X64-NEXT:    [[TMP3:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64-NEXT:    [[TMP4:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64-NEXT:    [[TMP5:%.*]] = load i64, i64* [[TMP3]]
+; X64-NEXT:    [[TMP6:%.*]] = load i64, i64* [[TMP4]]
+; X64-NEXT:    [[TMP7]] = call i64 @llvm.bswap.i64(i64 [[TMP5]])
+; X64-NEXT:    [[TMP8]] = call i64 @llvm.bswap.i64(i64 [[TMP6]])
+; X64-NEXT:    [[TMP9:%.*]] = icmp eq i64 [[TMP7]], [[TMP8]]
+; X64-NEXT:    br i1 [[TMP9]], label [[LOADBB1]], label [[RES_BLOCK:%.*]]
+; X64:       loadbb1:
+; X64-NEXT:    [[TMP10:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64-NEXT:    [[TMP11:%.*]] = bitcast i8* [[TMP10]] to i64*
+; X64-NEXT:    [[TMP12:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64-NEXT:    [[TMP13:%.*]] = bitcast i8* [[TMP12]] to i64*
+; X64-NEXT:    [[TMP14:%.*]] = load i64, i64* [[TMP11]]
+; X64-NEXT:    [[TMP15:%.*]] = load i64, i64* [[TMP13]]
+; X64-NEXT:    [[TMP16]] = call i64 @llvm.bswap.i64(i64 [[TMP14]])
+; X64-NEXT:    [[TMP17]] = call i64 @llvm.bswap.i64(i64 [[TMP15]])
+; X64-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP16]], [[TMP17]]
+; X64-NEXT:    br i1 [[TMP18]], label [[ENDBLOCK]], label [[RES_BLOCK]]
+; X64:       endblock:
+; X64-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ [[TMP2]], [[RES_BLOCK]] ]
+; X64-NEXT:    ret i32 [[PHI_RES]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 16)
+  ret i32 %call
+}
+
+define i32 @cmp_eq2(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp_eq2(
+; ALL-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i16*
+; ALL-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i16*
+; ALL-NEXT:    [[TMP3:%.*]] = load i16, i16* [[TMP1]]
+; ALL-NEXT:    [[TMP4:%.*]] = load i16, i16* [[TMP2]]
+; ALL-NEXT:    [[TMP5:%.*]] = icmp ne i16 [[TMP3]], [[TMP4]]
+; ALL-NEXT:    [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
+; ALL-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP6]], 0
+; ALL-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; ALL-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 2)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq3(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq3(
+; X32-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i16*
+; X32-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i16*
+; X32-NEXT:    [[TMP3:%.*]] = load i16, i16* [[TMP1]]
+; X32-NEXT:    [[TMP4:%.*]] = load i16, i16* [[TMP2]]
+; X32-NEXT:    [[TMP5:%.*]] = xor i16 [[TMP3]], [[TMP4]]
+; X32-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 2
+; X32-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 2
+; X32-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X32-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X32-NEXT:    [[TMP10:%.*]] = zext i8 [[TMP8]] to i16
+; X32-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP9]] to i16
+; X32-NEXT:    [[TMP12:%.*]] = xor i16 [[TMP10]], [[TMP11]]
+; X32-NEXT:    [[TMP13:%.*]] = or i16 [[TMP5]], [[TMP12]]
+; X32-NEXT:    [[TMP14:%.*]] = icmp ne i16 [[TMP13]], 0
+; X32-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq3(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i16*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i16*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i16, i16* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i16, i16* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i16 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 2
+; X64_1LD-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 2
+; X64_1LD-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X64_1LD-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP10:%.*]] = icmp ne i8 [[TMP8]], [[TMP9]]
+; X64_1LD-NEXT:    br i1 [[TMP10]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq3(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i16*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i16*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i16, i16* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i16, i16* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i16 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 2
+; X64_2LD-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 2
+; X64_2LD-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X64_2LD-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP10:%.*]] = zext i8 [[TMP8]] to i16
+; X64_2LD-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP9]] to i16
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i16 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i16 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i16 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 3)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq4(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; ALL-LABEL: @cmp_eq4(
+; ALL-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; ALL-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; ALL-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; ALL-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; ALL-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP3]], [[TMP4]]
+; ALL-NEXT:    [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
+; ALL-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP6]], 0
+; ALL-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; ALL-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 4)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq5(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq5(
+; X32-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X32-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X32-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X32-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X32-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X32-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X32-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X32-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X32-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X32-NEXT:    [[TMP10:%.*]] = zext i8 [[TMP8]] to i32
+; X32-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP9]] to i32
+; X32-NEXT:    [[TMP12:%.*]] = xor i32 [[TMP10]], [[TMP11]]
+; X32-NEXT:    [[TMP13:%.*]] = or i32 [[TMP5]], [[TMP12]]
+; X32-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; X32-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq5(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X64_1LD-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X64_1LD-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X64_1LD-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP10:%.*]] = icmp ne i8 [[TMP8]], [[TMP9]]
+; X64_1LD-NEXT:    br i1 [[TMP10]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq5(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X64_2LD-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X64_2LD-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X64_2LD-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP10:%.*]] = zext i8 [[TMP8]] to i32
+; X64_2LD-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP9]] to i32
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i32 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i32 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 5)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq6(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq6(
+; X32-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X32-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X32-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X32-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X32-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X32-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X32-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i16*
+; X32-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X32-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i16*
+; X32-NEXT:    [[TMP10:%.*]] = load i16, i16* [[TMP7]]
+; X32-NEXT:    [[TMP11:%.*]] = load i16, i16* [[TMP9]]
+; X32-NEXT:    [[TMP12:%.*]] = zext i16 [[TMP10]] to i32
+; X32-NEXT:    [[TMP13:%.*]] = zext i16 [[TMP11]] to i32
+; X32-NEXT:    [[TMP14:%.*]] = xor i32 [[TMP12]], [[TMP13]]
+; X32-NEXT:    [[TMP15:%.*]] = or i32 [[TMP5]], [[TMP14]]
+; X32-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0
+; X32-NEXT:    [[TMP17:%.*]] = zext i1 [[TMP16]] to i32
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP17]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq6(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i16*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i16*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i16, i16* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i16, i16* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i16 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq6(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i16*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i16*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i16, i16* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i16, i16* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = zext i16 [[TMP10]] to i32
+; X64_2LD-NEXT:    [[TMP13:%.*]] = zext i16 [[TMP11]] to i32
+; X64_2LD-NEXT:    [[TMP14:%.*]] = xor i32 [[TMP12]], [[TMP13]]
+; X64_2LD-NEXT:    [[TMP15:%.*]] = or i32 [[TMP5]], [[TMP14]]
+; X64_2LD-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[TMP17:%.*]] = zext i1 [[TMP16]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP17]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 6)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq7(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq7(
+; X32-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X32-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X32-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X32-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X32-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X32-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 3
+; X32-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i32*
+; X32-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 3
+; X32-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
+; X32-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP7]]
+; X32-NEXT:    [[TMP11:%.*]] = load i32, i32* [[TMP9]]
+; X32-NEXT:    [[TMP12:%.*]] = xor i32 [[TMP10]], [[TMP11]]
+; X32-NEXT:    [[TMP13:%.*]] = or i32 [[TMP5]], [[TMP12]]
+; X32-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; X32-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq7(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 3
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i32*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 3
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i32, i32* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq7(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 3
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i32*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 3
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i32, i32* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i32 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i32 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 7)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq8(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq8(
+; X32-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*
+; X32-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i32*
+; X32-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP1]]
+; X32-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP2]]
+; X32-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP3]], [[TMP4]]
+; X32-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 4
+; X32-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i32*
+; X32-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 4
+; X32-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
+; X32-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP7]]
+; X32-NEXT:    [[TMP11:%.*]] = load i32, i32* [[TMP9]]
+; X32-NEXT:    [[TMP12:%.*]] = xor i32 [[TMP10]], [[TMP11]]
+; X32-NEXT:    [[TMP13:%.*]] = or i32 [[TMP5]], [[TMP12]]
+; X32-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; X32-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64-LABEL: @cmp_eq8(
+; X64-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64-NEXT:    [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
+; X64-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP6]], 0
+; X64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 8)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq9(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq9(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 9)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq9(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64_1LD-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64_1LD-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X64_1LD-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP10:%.*]] = icmp ne i8 [[TMP8]], [[TMP9]]
+; X64_1LD-NEXT:    br i1 [[TMP10]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq9(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64_2LD-NEXT:    [[TMP7:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64_2LD-NEXT:    [[TMP8:%.*]] = load i8, i8* [[TMP6]]
+; X64_2LD-NEXT:    [[TMP9:%.*]] = load i8, i8* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP10:%.*]] = zext i8 [[TMP8]] to i64
+; X64_2LD-NEXT:    [[TMP11:%.*]] = zext i8 [[TMP9]] to i64
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i64 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i64 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i64 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 9)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq10(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq10(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 10)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq10(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i16*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i16*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i16, i16* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i16, i16* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i16 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq10(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i16*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i16*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i16, i16* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i16, i16* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = zext i16 [[TMP10]] to i64
+; X64_2LD-NEXT:    [[TMP13:%.*]] = zext i16 [[TMP11]] to i64
+; X64_2LD-NEXT:    [[TMP14:%.*]] = xor i64 [[TMP12]], [[TMP13]]
+; X64_2LD-NEXT:    [[TMP15:%.*]] = or i64 [[TMP5]], [[TMP14]]
+; X64_2LD-NEXT:    [[TMP16:%.*]] = icmp ne i64 [[TMP15]], 0
+; X64_2LD-NEXT:    [[TMP17:%.*]] = zext i1 [[TMP16]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP17]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 10)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq11(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq11(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 11)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq11(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 3
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 3
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i64 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq11(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 3
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 3
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i64 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i64 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i64 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 11)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq12(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq12(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 12)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq12(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i32*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i32, i32* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq12(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 8
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i32*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 8
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i32*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i32, i32* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = zext i32 [[TMP10]] to i64
+; X64_2LD-NEXT:    [[TMP13:%.*]] = zext i32 [[TMP11]] to i64
+; X64_2LD-NEXT:    [[TMP14:%.*]] = xor i64 [[TMP12]], [[TMP13]]
+; X64_2LD-NEXT:    [[TMP15:%.*]] = or i64 [[TMP5]], [[TMP14]]
+; X64_2LD-NEXT:    [[TMP16:%.*]] = icmp ne i64 [[TMP15]], 0
+; X64_2LD-NEXT:    [[TMP17:%.*]] = zext i1 [[TMP16]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP17]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 12)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq13(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq13(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 13)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq13(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 5
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 5
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i64 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq13(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 5
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 5
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i64 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i64 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i64 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 13)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq14(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq14(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 14)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq14(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 6
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 6
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i64 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq14(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 6
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 6
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i64 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i64 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i64 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 14)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq15(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq15(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 15)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64_1LD-LABEL: @cmp_eq15(
+; X64_1LD-NEXT:    br label [[LOADBB:%.*]]
+; X64_1LD:       res_block:
+; X64_1LD-NEXT:    br label [[ENDBLOCK:%.*]]
+; X64_1LD:       loadbb:
+; X64_1LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_1LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_1LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_1LD-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP3]], [[TMP4]]
+; X64_1LD-NEXT:    br i1 [[TMP5]], label [[RES_BLOCK:%.*]], label [[LOADBB1:%.*]]
+; X64_1LD:       loadbb1:
+; X64_1LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 7
+; X64_1LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_1LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 7
+; X64_1LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_1LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_1LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_1LD-NEXT:    [[TMP12:%.*]] = icmp ne i64 [[TMP10]], [[TMP11]]
+; X64_1LD-NEXT:    br i1 [[TMP12]], label [[RES_BLOCK]], label [[ENDBLOCK]]
+; X64_1LD:       endblock:
+; X64_1LD-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 0, [[LOADBB1]] ], [ 1, [[RES_BLOCK]] ]
+; X64_1LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[PHI_RES]], 0
+; X64_1LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_1LD-NEXT:    ret i32 [[CONV]]
+;
+; X64_2LD-LABEL: @cmp_eq15(
+; X64_2LD-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i64*
+; X64_2LD-NEXT:    [[TMP3:%.*]] = load i64, i64* [[TMP1]]
+; X64_2LD-NEXT:    [[TMP4:%.*]] = load i64, i64* [[TMP2]]
+; X64_2LD-NEXT:    [[TMP5:%.*]] = xor i64 [[TMP3]], [[TMP4]]
+; X64_2LD-NEXT:    [[TMP6:%.*]] = getelementptr i8, i8* [[X]], i8 7
+; X64_2LD-NEXT:    [[TMP7:%.*]] = bitcast i8* [[TMP6]] to i64*
+; X64_2LD-NEXT:    [[TMP8:%.*]] = getelementptr i8, i8* [[Y]], i8 7
+; X64_2LD-NEXT:    [[TMP9:%.*]] = bitcast i8* [[TMP8]] to i64*
+; X64_2LD-NEXT:    [[TMP10:%.*]] = load i64, i64* [[TMP7]]
+; X64_2LD-NEXT:    [[TMP11:%.*]] = load i64, i64* [[TMP9]]
+; X64_2LD-NEXT:    [[TMP12:%.*]] = xor i64 [[TMP10]], [[TMP11]]
+; X64_2LD-NEXT:    [[TMP13:%.*]] = or i64 [[TMP5]], [[TMP12]]
+; X64_2LD-NEXT:    [[TMP14:%.*]] = icmp ne i64 [[TMP13]], 0
+; X64_2LD-NEXT:    [[TMP15:%.*]] = zext i1 [[TMP14]] to i32
+; X64_2LD-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP15]], 0
+; X64_2LD-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64_2LD-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 15)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+
+define i32 @cmp_eq16(i8* nocapture readonly %x, i8* nocapture readonly %y)  {
+; X32-LABEL: @cmp_eq16(
+; X32-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[X:%.*]], i8* [[Y:%.*]], i64 16)
+; X32-NEXT:    [[CMP:%.*]] = icmp eq i32 [[CALL]], 0
+; X32-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X32-NEXT:    ret i32 [[CONV]]
+;
+; X64-LABEL: @cmp_eq16(
+; X64-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i128*
+; X64-NEXT:    [[TMP2:%.*]] = bitcast i8* [[Y:%.*]] to i128*
+; X64-NEXT:    [[TMP3:%.*]] = load i128, i128* [[TMP1]]
+; X64-NEXT:    [[TMP4:%.*]] = load i128, i128* [[TMP2]]
+; X64-NEXT:    [[TMP5:%.*]] = icmp ne i128 [[TMP3]], [[TMP4]]
+; X64-NEXT:    [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
+; X64-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP6]], 0
+; X64-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32
+; X64-NEXT:    ret i32 [[CONV]]
+;
+  %call = tail call i32 @memcmp(i8* %x, i8* %y, i64 16)
+  %cmp = icmp eq i32 %call, 0
+  %conv = zext i1 %cmp to i32
+  ret i32 %conv
+}
+

Added: llvm/trunk/test/Transforms/Float2Int/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Float2Int/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Float2Int/basic.ll (added)
+++ llvm/trunk/test/Transforms/Float2Int/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,267 @@
+; RUN: opt < %s -float2int -S | FileCheck %s
+; RUN: opt < %s -passes='float2int' -S | FileCheck %s
+
+;
+; Positive tests
+;
+
+; CHECK-LABEL: @simple1
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = add i32 %1, 1
+; CHECK:  %3 = trunc i32 %2 to i16
+; CHECK:  ret i16 %3
+define i16 @simple1(i8 %a) {
+  %1 = uitofp i8 %a to float
+  %2 = fadd float %1, 1.0
+  %3 = fptoui float %2 to i16
+  ret i16 %3
+}
+
+; CHECK-LABEL: @simple2
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = sub i32 %1, 1
+; CHECK:  %3 = trunc i32 %2 to i8
+; CHECK:  ret i8 %3
+define i8 @simple2(i8 %a) {
+  %1 = uitofp i8 %a to float
+  %2 = fsub float %1, 1.0
+  %3 = fptoui float %2 to i8
+  ret i8 %3
+}
+
+; CHECK-LABEL: @simple3
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = sub i32 %1, 1
+; CHECK:  ret i32 %2
+define i32 @simple3(i8 %a) {
+  %1 = uitofp i8 %a to float
+  %2 = fsub float %1, 1.0
+  %3 = fptoui float %2 to i32
+  ret i32 %3
+}
+
+; CHECK-LABEL: @cmp
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = zext i8 %b to i32
+; CHECK:  %3 = icmp slt i32 %1, %2
+; CHECK:  ret i1 %3
+define i1 @cmp(i8 %a, i8 %b) {
+  %1 = uitofp i8 %a to float
+  %2 = uitofp i8 %b to float
+  %3 = fcmp ult float %1, %2
+  ret i1 %3
+}
+
+; CHECK-LABEL: @simple4
+; CHECK:  %1 = zext i32 %a to i64
+; CHECK:  %2 = add i64 %1, 1
+; CHECK:  %3 = trunc i64 %2 to i32
+; CHECK:  ret i32 %3
+define i32 @simple4(i32 %a) {
+  %1 = uitofp i32 %a to double
+  %2 = fadd double %1, 1.0
+  %3 = fptoui double %2 to i32
+  ret i32 %3
+}
+
+; CHECK-LABEL: @simple5
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = zext i8 %b to i32
+; CHECK:  %3 = add i32 %1, 1
+; CHECK:  %4 = mul i32 %3, %2
+; CHECK:  ret i32 %4
+define i32 @simple5(i8 %a, i8 %b) {
+  %1 = uitofp i8 %a to float
+  %2 = uitofp i8 %b to float
+  %3 = fadd float %1, 1.0
+  %4 = fmul float %3, %2
+  %5 = fptoui float %4 to i32
+  ret i32 %5
+}
+
+; The two chains don't interact - failure of one shouldn't
+; cause failure of the other.
+
+; CHECK-LABEL: @multi1
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = zext i8 %b to i32
+; CHECK:  %fc = uitofp i8 %c to float
+; CHECK:  %x1 = add i32 %1, %2
+; CHECK:  %z = fadd float %fc, %d
+; CHECK:  %w = fptoui float %z to i32
+; CHECK:  %r = add i32 %x1, %w
+; CHECK:  ret i32 %r
+define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) {
+  %fa = uitofp i8 %a to float
+  %fb = uitofp i8 %b to float
+  %fc = uitofp i8 %c to float
+  %x = fadd float %fa, %fb
+  %y = fptoui float %x to i32
+  %z = fadd float %fc, %d
+  %w = fptoui float %z to i32
+  %r = add i32 %y, %w
+  ret i32 %r
+}
+
+; CHECK-LABEL: @simple_negzero
+; CHECK:  %1 = zext i8 %a to i32
+; CHECK:  %2 = add i32 %1, 0
+; CHECK:  %3 = trunc i32 %2 to i16
+; CHECK:  ret i16 %3
+define i16 @simple_negzero(i8 %a) {
+  %1 = uitofp i8 %a to float
+  %2 = fadd fast float %1, -0.0
+  %3 = fptoui float %2 to i16
+  ret i16 %3
+}
+
+; CHECK-LABEL: @simple_negative
+; CHECK: %1 = sext i8 %call to i32
+; CHECK: %mul1 = mul i32 %1, -3
+; CHECK: %2 = trunc i32 %mul1 to i8
+; CHECK: %conv3 = sext i8 %2 to i32
+; CHECK: ret i32 %conv3
+define i32 @simple_negative(i8 %call) {
+  %conv1 = sitofp i8 %call to float
+  %mul = fmul float %conv1, -3.000000e+00
+  %conv2 = fptosi float %mul to i8
+  %conv3 = sext i8 %conv2 to i32
+  ret i32 %conv3
+}
+
+;
+; Negative tests
+;
+
+; CHECK-LABEL: @neg_multi1
+; CHECK:  %fa = uitofp i8 %a to float
+; CHECK:  %fc = uitofp i8 %c to float
+; CHECK:  %x = fadd float %fa, %fc
+; CHECK:  %y = fptoui float %x to i32
+; CHECK:  %z = fadd float %fc, %d
+; CHECK:  %w = fptoui float %z to i32
+; CHECK:  %r = add i32 %y, %w
+; CHECK:  ret i32 %r
+; The two chains intersect, which means because one fails, no
+; transform can occur.
+define i32 @neg_multi1(i8 %a, i8 %b, i8 %c, float %d) {
+  %fa = uitofp i8 %a to float
+  %fc = uitofp i8 %c to float
+  %x = fadd float %fa, %fc
+  %y = fptoui float %x to i32
+  %z = fadd float %fc, %d
+  %w = fptoui float %z to i32
+  %r = add i32 %y, %w
+  ret i32 %r
+}
+
+; CHECK-LABEL: @neg_muld
+; CHECK:  %fa = uitofp i32 %a to double
+; CHECK:  %fb = uitofp i32 %b to double
+; CHECK:  %mul = fmul double %fa, %fb
+; CHECK:  %r = fptoui double %mul to i64
+; CHECK:  ret i64 %r
+; The i32 * i32 = i64, which has 64 bits, which is greater than the 52 bits
+; that can be exactly represented in a double.
+define i64 @neg_muld(i32 %a, i32 %b) {
+  %fa = uitofp i32 %a to double
+  %fb = uitofp i32 %b to double
+  %mul = fmul double %fa, %fb
+  %r = fptoui double %mul to i64
+  ret i64 %r
+}
+
+; CHECK-LABEL: @neg_mulf
+; CHECK:  %fa = uitofp i16 %a to float
+; CHECK:  %fb = uitofp i16 %b to float
+; CHECK:  %mul = fmul float %fa, %fb
+; CHECK:  %r = fptoui float %mul to i32
+; CHECK:  ret i32 %r
+; The i16 * i16 = i32, which can't be represented in a float, but can in a
+; double. This should fail, as the written code uses floats, not doubles so
+; the original result may be inaccurate.
+define i32 @neg_mulf(i16 %a, i16 %b) {
+  %fa = uitofp i16 %a to float
+  %fb = uitofp i16 %b to float
+  %mul = fmul float %fa, %fb
+  %r = fptoui float %mul to i32
+  ret i32 %r
+}
+
+; CHECK-LABEL: @neg_cmp
+; CHECK:  %1 = uitofp i8 %a to float
+; CHECK:  %2 = uitofp i8 %b to float
+; CHECK:  %3 = fcmp false float %1, %2
+; CHECK:  ret i1 %3
+; "false" doesn't have an icmp equivalent.
+define i1 @neg_cmp(i8 %a, i8 %b) {
+  %1 = uitofp i8 %a to float
+  %2 = uitofp i8 %b to float
+  %3 = fcmp false float %1, %2
+  ret i1 %3
+}
+
+; CHECK-LABEL: @neg_div
+; CHECK:  %1 = uitofp i8 %a to float
+; CHECK:  %2 = fdiv float %1, 1.0
+; CHECK:  %3 = fptoui float %2 to i16
+; CHECK:  ret i16 %3
+; Division isn't a supported operator.
+define i16 @neg_div(i8 %a) {
+  %1 = uitofp i8 %a to float
+  %2 = fdiv float %1, 1.0
+  %3 = fptoui float %2 to i16
+  ret i16 %3
+}
+
+; CHECK-LABEL: @neg_remainder
+; CHECK:  %1 = uitofp i8 %a to float
+; CHECK:  %2 = fadd float %1, 1.2
+; CHECK:  %3 = fptoui float %2 to i16
+; CHECK:  ret i16 %3
+; 1.2 is not an integer.
+define i16 @neg_remainder(i8 %a) {
+  %1 = uitofp i8 %a to float
+  %2 = fadd float %1, 1.25
+  %3 = fptoui float %2 to i16
+  ret i16 %3
+}
+
+; CHECK-LABEL: @neg_toolarge
+; CHECK:  %1 = uitofp i80 %a to fp128
+; CHECK:  %2 = fadd fp128 %1, %1
+; CHECK:  %3 = fptoui fp128 %2 to i80
+; CHECK:  ret i80 %3
+; i80 > i64, which is the largest bitwidth handleable by default.
+define i80 @neg_toolarge(i80 %a) {
+  %1 = uitofp i80 %a to fp128
+  %2 = fadd fp128 %1, %1
+  %3 = fptoui fp128 %2 to i80
+  ret i80 %3
+}
+
+; CHECK-LABEL: @neg_calluser
+; CHECK: sitofp
+; CHECK: fcmp
+; The sequence %1..%3 cannot be converted because %4 uses %2.
+define i32 @neg_calluser(i32 %value) {
+  %1 = sitofp i32 %value to double
+  %2 = fadd double %1, 1.0
+  %3 = fcmp olt double %2, 0.000000e+00
+  %4 = tail call double @g(double %2)
+  %5 = fptosi double %4 to i32
+  %6 = zext i1 %3 to i32
+  %7 = add i32 %6, %5
+  ret i32 %7
+}
+declare double @g(double)
+
+; CHECK-LABEL: @neg_vector
+; CHECK:  %1 = uitofp <4 x i8> %a to <4 x float>
+; CHECK:  %2 = fptoui <4 x float> %1 to <4 x i16>
+; CHECK:  ret <4 x i16> %2
+define <4 x i16> @neg_vector(<4 x i8> %a) {
+  %1 = uitofp <4 x i8> %a to <4 x float>
+  %2 = fptoui <4 x float> %1 to <4 x i16>
+  ret <4 x i16> %2
+}

Added: llvm/trunk/test/Transforms/Float2Int/float2int-optnone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Float2Int/float2int-optnone.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Float2Int/float2int-optnone.ll (added)
+++ llvm/trunk/test/Transforms/Float2Int/float2int-optnone.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -float2int -S | FileCheck %s
+;
+; Verify that pass float2int is not run on optnone functions.
+
+define i16 @simple1(i8 %a) #0 {
+; CHECK-LABEL: @simple1
+; CHECK:  %1 = uitofp i8 %a to float
+; CHECK-NEXT:  %2 = fadd float %1, 1.0
+; CHECK-NEXT:  %3 = fptoui float %2 to i16
+; CHECK-NEXT:  ret i16 %3
+  %1 = uitofp i8 %a to float
+  %2 = fadd float %1, 1.0
+  %3 = fptoui float %2 to i16
+  ret i16 %3
+}
+
+attributes #0 = { noinline optnone }

Added: llvm/trunk/test/Transforms/Float2Int/toolarge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Float2Int/toolarge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Float2Int/toolarge.ll (added)
+++ llvm/trunk/test/Transforms/Float2Int/toolarge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -float2int -float2int-max-integer-bw=256 -S | FileCheck %s
+
+; CHECK-LABEL: @neg_toolarge
+; CHECK:  %1 = uitofp i80 %a to fp128
+; CHECK:  %2 = fadd fp128 %1, %1
+; CHECK:  %3 = fptoui fp128 %2 to i80
+; CHECK:  ret i80 %3
+; fp128 has a 112-bit mantissa, which can hold an i80. But we only support
+; up to i64, so it should fail (even though the max integer bitwidth is 256).
+define i80 @neg_toolarge(i80 %a) {
+  %1 = uitofp i80 %a to fp128
+  %2 = fadd fp128 %1, %1
+  %3 = fptoui fp128 %2 to i80
+  ret i80 %3
+}
+

Added: llvm/trunk/test/Transforms/ForcedFunctionAttrs/forced.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ForcedFunctionAttrs/forced.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ForcedFunctionAttrs/forced.ll (added)
+++ llvm/trunk/test/Transforms/ForcedFunctionAttrs/forced.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt < %s -S -forceattrs | FileCheck %s --check-prefix=CHECK-CONTROL
+; RUN: opt < %s -S -forceattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
+; RUN: opt < %s -S -passes=forceattrs -force-attribute foo:noinline | FileCheck %s --check-prefix=CHECK-FOO
+
+; CHECK-CONTROL: define void @foo() {
+; CHECK-FOO: define void @foo() #0 {
+define void @foo() {
+  ret void
+}
+
+
+; CHECK-FOO: attributes #0 = { noinline }

Added: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @a
+define i32 @a() {
+	%tmp = call i32 @b( )		; <i32> [#uses=1]
+	ret i32 %tmp
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @b
+define i32 @b() {
+	%tmp = call i32 @a( )		; <i32> [#uses=1]
+	ret i32 %tmp
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
+
+ at x = global i32 0
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: declare i32 @e
+declare i32 @e() readnone
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @f
+define i32 @f() {
+	%tmp = call i32 @e( )		; <i32> [#uses=1]
+	ret i32 %tmp
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @g
+define i32 @g() readonly {
+	ret i32 0
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NEXT: define i32 @h
+define i32 @h() readnone {
+	%tmp = load i32, i32* @x		; <i32> [#uses=1]
+	ret i32 %tmp
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
+
+; CHECK: define i32 @f() #0
+define i32 @f() {
+entry:
+  %tmp = call i32 @e( )
+  ret i32 %tmp
+}
+
+; CHECK: declare i32 @e() #0
+declare i32 @e() readonly
+
+; CHECK: attributes #0 = { readonly }

Added: llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+; PR2792
+
+ at g = global i32 0		; <i32*> [#uses=1]
+
+define i32 @f() {
+	%t = load volatile i32, i32* @g		; <i32> [#uses=1]
+	ret i32 %t
+}
+
+; CHECK-NOT: attributes #{{.*}} read

Added: llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,12 @@
+; RUN: opt < %s -basicaa -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s
+
+ at s = external constant i8		; <i8*> [#uses=1]
+
+; CHECK: define i8 @f() #0
+define i8 @f() {
+	%tmp = load i8, i8* @s		; <i8> [#uses=1]
+	ret i8 %tmp
+}
+
+; CHECK: attributes #0 = { {{.*}} readnone

Added: llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+; CHECK: define i32* @a(i32** nocapture readonly %p)
+define i32* @a(i32** %p) {
+	%tmp = load i32*, i32** %p
+	ret i32* %tmp
+}
+
+; CHECK: define i32* @b(i32* %q)
+define i32* @b(i32 *%q) {
+	%mem = alloca i32*
+	store i32* %q, i32** %mem
+	%tmp = call i32* @a(i32** %mem)
+	ret i32* %tmp
+}
+
+; CHECK: define i32* @c(i32* readnone returned %r)
+ at g = global i32 0
+define i32* @c(i32 *%r) {
+	%a = icmp eq i32* %r, null
+	store i32 1, i32* @g
+	ret i32* %r
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+; PR8279
+
+ at g = constant i32 1
+
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse
+; CHECK-NOT: readonly
+; CHECK-NEXT: void @foo()
+define void @foo() {
+  %tmp = load volatile i32, i32* @g
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/assume.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/assume.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/assume.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/assume.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,5 @@
+; RUN: opt -S -o - -functionattrs %s | FileCheck %s
+; RUN: opt -S -o - -passes=function-attrs %s | FileCheck %s
+
+; CHECK-NOT: readnone
+declare void @llvm.assume(i1)

Added: llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/atomic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -basicaa -functionattrs -S < %s | FileCheck %s
+; RUN: opt -aa-pipeline=basic-aa -passes=function-attrs -S < %s | FileCheck %s
+
+; Atomic load/store to local doesn't affect whether a function is
+; readnone/readonly.
+define i32 @test1(i32 %x) uwtable ssp {
+; CHECK: define i32 @test1(i32 %x) #0 {
+entry:
+  %x.addr = alloca i32, align 4
+  store atomic i32 %x, i32* %x.addr seq_cst, align 4
+  %r = load atomic i32, i32* %x.addr seq_cst, align 4
+  ret i32 %r
+}
+
+; A function with an Acquire load is not readonly.
+define i32 @test2(i32* %x) uwtable ssp {
+; CHECK: define i32 @test2(i32* nocapture readonly %x) #1 {
+entry:
+  %r = load atomic i32, i32* %x seq_cst, align 4
+  ret i32 %r
+}
+
+; CHECK: attributes #0 = { norecurse nounwind readnone ssp uwtable }
+; CHECK: attributes #1 = { norecurse nounwind ssp uwtable }

Added: llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/comdat-ipo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+; See PR26774
+
+; CHECK-LABEL: define void @bar(i8* readonly) {
+define void @bar(i8* readonly) {
+  call void @foo(i8* %0)
+  ret void
+}
+
+
+; CHECK-LABEL: define linkonce_odr void @foo(i8* readonly) {
+define linkonce_odr void @foo(i8* readonly) {
+  call void @bar(i8* %0)
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/convergent.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,110 @@
+; FIXME: convert CHECK-INDIRECT into CHECK (and remove -check-prefixes) as soon
+; FIXME: as new-pass-manager's handling of indirect_non_convergent_call is fixed
+;
+; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-INDIRECT
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
+
+; CHECK: Function Attrs
+; CHECK-NOT: convergent
+; CHECK-NEXT: define i32 @nonleaf()
+define i32 @nonleaf() convergent {
+  %a = call i32 @leaf()
+  ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-NOT: convergent
+; CHECK-NEXT: define i32 @leaf()
+define i32 @leaf() convergent {
+  ret i32 0
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: declare i32 @k()
+declare i32 @k() convergent
+
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: define i32 @extern()
+define i32 @extern() convergent {
+  %a = call i32 @k() convergent
+  ret i32 %a
+}
+
+; Convergent should not be removed on the function here.  Although the call is
+; not explicitly convergent, it picks up the convergent attr from the callee.
+;
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: define i32 @extern_non_convergent_call()
+define i32 @extern_non_convergent_call() convergent {
+  %a = call i32 @k()
+  ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: define i32 @indirect_convergent_call(
+define i32 @indirect_convergent_call(i32 ()* %f) convergent {
+   %a = call i32 %f() convergent
+   ret i32 %a
+}
+; Give indirect_non_convergent_call the norecurse attribute so we get a
+; "Function Attrs" comment in the output.
+;
+; CHECK: Function Attrs
+; CHECK-INDIRECT-NOT: convergent
+; CHECK-INDIRECT-NEXT: define i32 @indirect_non_convergent_call(
+define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse {
+   %a = call i32 %f()
+   ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: declare void @llvm.nvvm.barrier0()
+declare void @llvm.nvvm.barrier0() convergent
+
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: define i32 @intrinsic()
+define i32 @intrinsic() convergent {
+  ; Implicitly convergent, because the intrinsic is convergent.
+  call void @llvm.nvvm.barrier0()
+  ret i32 0
+}
+
+; CHECK: Function Attrs
+; CHECK-NOT: convergent
+; CHECK-NEXT: define i32 @recursive1()
+define i32 @recursive1() convergent {
+  %a = call i32 @recursive2() convergent
+  ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-NOT: convergent
+; CHECK-NEXT: define i32 @recursive2()
+define i32 @recursive2() convergent {
+  %a = call i32 @recursive1() convergent
+  ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: define i32 @noopt()
+define i32 @noopt() convergent optnone noinline {
+  %a = call i32 @noopt_friend() convergent
+  ret i32 0
+}
+
+; A function which is mutually-recursive with a convergent, optnone function
+; shouldn't have its convergent attribute stripped.
+; CHECK: Function Attrs
+; CHECK-SAME: convergent
+; CHECK-NEXT: define i32 @noopt_friend()
+define i32 @noopt_friend() convergent {
+  %a = call i32 @noopt()
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt -S -o - -functionattrs %s | FileCheck %s
+; RUN: opt -S -o - -passes=function-attrs %s | FileCheck %s
+
+; Verify we remove argmemonly/inaccessiblememonly/inaccessiblemem_or_argmemonly
+; function attributes when we derive readnone.
+
+; Function Attrs: argmemonly
+define i32* @given_argmem_infer_readnone(i32* %p) #0 {
+; CHECK: define i32* @given_argmem_infer_readnone(i32* readnone returned %p) #0 {
+entry:
+  ret i32* %p
+}
+
+; Function Attrs: inaccessiblememonly
+define i32* @given_inaccessible_infer_readnone(i32* %p) #1 {
+; CHECK: define i32* @given_inaccessible_infer_readnone(i32* readnone returned %p) #0 {
+entry:
+  ret i32* %p
+}
+
+; Function Attrs: inaccessiblemem_or_argmemonly
+define i32* @given_inaccessible_or_argmem_infer_readnone(i32* %p) #2 {
+; CHECK: define i32* @given_inaccessible_or_argmem_infer_readnone(i32* readnone returned %p) #0 {
+entry:
+  ret i32* %p
+}
+
+attributes #0 = { argmemonly }
+attributes #1 = { inaccessiblememonly }
+attributes #2 = { inaccessiblemem_or_argmemonly }
+; CHECK: attributes #0 = { norecurse nounwind readnone }
+; CHECK-NOT: attributes

Added: llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/int_sideeffect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -S < %s -functionattrs | FileCheck %s
+; RUN: opt -S < %s -passes=function-attrs | FileCheck %s
+
+; CHECK: Function Attrs
+; CHECK-SAME: inaccessiblememonly
+; CHECK-NEXT: declare void @llvm.sideeffect()
+declare void @llvm.sideeffect()
+
+; Don't add readnone or similar attributes when an @llvm.sideeffect() intrinsic
+; is present.
+
+; CHECK: Function Attrs
+; CHECK-NOT: readnone
+; CHECK: define void @test()
+define void @test() {
+    call void @llvm.sideeffect()
+    ret void
+}
+
+; CHECK: Function Attrs
+; CHECK-NOT: readnone
+; CHECK: define void @loop()
+define void @loop() {
+    br label %loop
+
+loop:
+    call void @llvm.sideeffect()
+    br label %loop
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/naked_functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/naked_functions.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/naked_functions.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/naked_functions.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -S -functionattrs %s | FileCheck %s
+; RUN: opt -S -passes='function-attrs' %s | FileCheck %s
+
+; Don't change the attributes of parameters of naked functions, in particular
+; don't mark them as readnone
+
+ at g = common global i32 0, align 4
+
+define i32 @bar() {
+entry:
+  %call = call i32 @foo(i32* @g)
+; CHECK: %call = call i32 @foo(i32* @g)
+  ret i32 %call
+}
+
+define internal i32 @foo(i32*) #0 {
+entry:
+  %retval = alloca i32, align 4
+  call void asm sideeffect "ldr r0, [r0] \0Abx lr        \0A", ""()
+  unreachable
+}
+
+; CHECK: define internal i32 @foo(i32*)
+
+attributes #0 = { naked }

Added: llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nocapture.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,257 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+ at g = global i32* null		; <i32**> [#uses=1]
+
+; CHECK: define i32* @c1(i32* readnone returned %q)
+define i32* @c1(i32* %q) {
+	ret i32* %q
+}
+
+; CHECK: define void @c2(i32* %q)
+; It would also be acceptable to mark %q as readnone. Update @c3 too.
+define void @c2(i32* %q) {
+	store i32* %q, i32** @g
+	ret void
+}
+
+; CHECK: define void @c3(i32* %q)
+define void @c3(i32* %q) {
+	call void @c2(i32* %q)
+	ret void
+}
+
+; CHECK: define i1 @c4(i32* %q, i32 %bitno)
+define i1 @c4(i32* %q, i32 %bitno) {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = trunc i32 %tmp2 to i1
+	br i1 %bit, label %l1, label %l0
+l0:
+	ret i1 0 ; escaping value not caught by def-use chaining.
+l1:
+	ret i1 1 ; escaping value not caught by def-use chaining.
+}
+
+ at lookup_table = global [2 x i1] [ i1 0, i1 1 ]
+
+; CHECK: define i1 @c5(i32* %q, i32 %bitno)
+define i1 @c5(i32* %q, i32 %bitno) {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = and i32 %tmp2, 1
+        ; subtle escape mechanism follows
+	%lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
+	%val = load i1, i1* %lookup
+	ret i1 %val
+}
+
+declare void @throw_if_bit_set(i8*, i8) readonly
+
+; CHECK: define i1 @c6(i8* readonly %q, i8 %bit)
+define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 {
+	invoke void @throw_if_bit_set(i8* %q, i8 %bit)
+		to label %ret0 unwind label %ret1
+ret0:
+	ret i1 0
+ret1:
+        %exn = landingpad {i8*, i32}
+                 cleanup
+	ret i1 1
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
+	%tmp = ptrtoint i32* %q to i32
+	%tmp2 = lshr i32 %tmp, %bitno
+	%bit = and i32 %tmp2, 1
+	%lookup = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 %bit
+	ret i1* %lookup
+}
+
+; CHECK: define i1 @c7(i32* readonly %q, i32 %bitno)
+define i1 @c7(i32* %q, i32 %bitno) {
+	%ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
+	%val = load i1, i1* %ptr
+	ret i1 %val
+}
+
+
+; CHECK: define i32 @nc1(i32* %q, i32* nocapture %p, i1 %b)
+define i32 @nc1(i32* %q, i32* %p, i1 %b) {
+e:
+	br label %l
+l:
+	%x = phi i32* [ %p, %e ]
+	%y = phi i32* [ %q, %e ]
+	%tmp = bitcast i32* %x to i32*		; <i32*> [#uses=2]
+	%tmp2 = select i1 %b, i32* %tmp, i32* %y
+	%val = load i32, i32* %tmp2		; <i32> [#uses=1]
+	store i32 0, i32* %tmp
+	store i32* %y, i32** @g
+	ret i32 %val
+}
+
+; CHECK: define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* nocapture %p, i1 %b)
+define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) {
+e:
+	br label %l
+l:
+	%x = phi i32 addrspace(1)* [ %p, %e ]
+	%y = phi i32* [ %q, %e ]
+	%tmp = addrspacecast i32 addrspace(1)* %x to i32*		; <i32*> [#uses=2]
+	%tmp2 = select i1 %b, i32* %tmp, i32* %y
+	%val = load i32, i32* %tmp2		; <i32> [#uses=1]
+	store i32 0, i32* %tmp
+	store i32* %y, i32** @g
+	ret i32 %val
+}
+
+; CHECK: define void @nc2(i32* nocapture %p, i32* %q)
+define void @nc2(i32* %p, i32* %q) {
+	%1 = call i32 @nc1(i32* %q, i32* %p, i1 0)		; <i32> [#uses=0]
+	ret void
+}
+
+; CHECK: define void @nc3(void ()* nocapture %p)
+define void @nc3(void ()* %p) {
+	call void %p()
+	ret void
+}
+
+declare void @external(i8*) readonly nounwind
+; CHECK: define void @nc4(i8* nocapture readonly %p)
+define void @nc4(i8* %p) {
+	call void @external(i8* %p)
+	ret void
+}
+
+; CHECK: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
+define void @nc5(void (i8*)* %f, i8* %p) {
+	call void %f(i8* %p) readonly nounwind
+	call void %f(i8* nocapture %p)
+	ret void
+}
+
+; CHECK: define void @test1_1(i8* nocapture readnone %x1_1, i8* %y1_1)
+; It would be acceptable to add readnone to %y1_1 and %y1_2.
+define void @test1_1(i8* %x1_1, i8* %y1_1) {
+  call i8* @test1_2(i8* %x1_1, i8* %y1_1)
+  store i32* null, i32** @g
+  ret void
+}
+
+; CHECK: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2)
+define i8* @test1_2(i8* %x1_2, i8* %y1_2) {
+  call void @test1_1(i8* %x1_2, i8* %y1_2)
+  store i32* null, i32** @g
+  ret i8* %y1_2
+}
+
+; CHECK: define void @test2(i8* nocapture readnone %x2)
+define void @test2(i8* %x2) {
+  call void @test2(i8* %x2)
+  store i32* null, i32** @g
+  ret void
+}
+
+; CHECK: define void @test3(i8* nocapture readnone %x3, i8* nocapture readnone %y3, i8* nocapture readnone %z3)
+define void @test3(i8* %x3, i8* %y3, i8* %z3) {
+  call void @test3(i8* %z3, i8* %y3, i8* %x3)
+  store i32* null, i32** @g
+  ret void
+}
+
+; CHECK: define void @test4_1(i8* %x4_1)
+define void @test4_1(i8* %x4_1) {
+  call i8* @test4_2(i8* %x4_1, i8* %x4_1, i8* %x4_1)
+  store i32* null, i32** @g
+  ret void
+}
+
+; CHECK: define i8* @test4_2(i8* nocapture readnone %x4_2, i8* readnone returned %y4_2, i8* nocapture readnone %z4_2)
+define i8* @test4_2(i8* %x4_2, i8* %y4_2, i8* %z4_2) {
+  call void @test4_1(i8* null)
+  store i32* null, i32** @g
+  ret i8* %y4_2
+}
+
+declare i8* @test5_1(i8* %x5_1)
+
+; CHECK: define void @test5_2(i8* %x5_2)
+define void @test5_2(i8* %x5_2) {
+  call i8* @test5_1(i8* %x5_2)
+  store i32* null, i32** @g
+  ret void
+}
+
+declare void @test6_1(i8* %x6_1, i8* nocapture %y6_1, ...)
+
+; CHECK: define void @test6_2(i8* %x6_2, i8* nocapture %y6_2, i8* %z6_2)
+define void @test6_2(i8* %x6_2, i8* %y6_2, i8* %z6_2) {
+  call void (i8*, i8*, ...) @test6_1(i8* %x6_2, i8* %y6_2, i8* %z6_2)
+  store i32* null, i32** @g
+  ret void
+}
+
+; CHECK: define void @test_cmpxchg(i32* nocapture %p)
+define void @test_cmpxchg(i32* %p) {
+  cmpxchg i32* %p, i32 0, i32 1 acquire monotonic
+  ret void
+}
+
+; CHECK: define void @test_cmpxchg_ptr(i32** nocapture %p, i32* %q)
+define void @test_cmpxchg_ptr(i32** %p, i32* %q) {
+  cmpxchg i32** %p, i32* null, i32* %q acquire monotonic
+  ret void
+}
+
+; CHECK: define void @test_atomicrmw(i32* nocapture %p)
+define void @test_atomicrmw(i32* %p) {
+  atomicrmw add i32* %p, i32 1 seq_cst
+  ret void
+}
+
+; CHECK: define void @test_volatile(i32* %x)
+define void @test_volatile(i32* %x) {
+entry:
+  %gep = getelementptr i32, i32* %x, i64 1
+  store volatile i32 0, i32* %gep, align 4
+  ret void
+}
+
+; CHECK: nocaptureLaunder(i8* nocapture %p)
+define void @nocaptureLaunder(i8* %p) {
+entry:
+  %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
+  store i8 42, i8* %b
+  ret void
+}
+
+ at g2 = global i8* null
+; CHECK: define void @captureLaunder(i8* %p)
+define void @captureLaunder(i8* %p) {
+  %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
+  store i8* %b, i8** @g2
+  ret void
+}
+
+; CHECK: @nocaptureStrip(i8* nocapture %p)
+define void @nocaptureStrip(i8* %p) {
+entry:
+  %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
+  store i8 42, i8* %b
+  ret void
+}
+
+ at g3 = global i8* null
+; CHECK: define void @captureStrip(i8* %p)
+define void @captureStrip(i8* %p) {
+  %b = call i8* @llvm.strip.invariant.group.p0i8(i8* %p)
+  store i8* %b, i8** @g3
+  ret void
+}
+
+declare i8* @llvm.launder.invariant.group.p0i8(i8*)
+declare i8* @llvm.strip.invariant.group.p0i8(i8*)

Added: llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull-global.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt -S -functionattrs %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs %s | FileCheck %s
+
+ at a = external global i8, !absolute_symbol !0
+
+; CHECK-NOT: define nonnull
+define i8* @foo() {
+  ret i8* @a
+}
+
+!0 = !{i64 0, i64 256}

Added: llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/nonnull.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,240 @@
+; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s
+
+declare nonnull i8* @ret_nonnull()
+
+; Return a pointer trivially nonnull (call return attribute)
+define i8* @test1() {
+; CHECK: define nonnull i8* @test1
+  %ret = call i8* @ret_nonnull()
+  ret i8* %ret
+}
+
+; Return a pointer trivially nonnull (argument attribute)
+define i8* @test2(i8* nonnull %p) {
+; CHECK: define nonnull i8* @test2
+  ret i8* %p
+}
+
+; Given an SCC where one of the functions can not be marked nonnull,
+; can we still mark the other one which is trivially nonnull
+define i8* @scc_binder() {
+; CHECK: define i8* @scc_binder
+  call i8* @test3()
+  ret i8* null
+}
+
+define i8* @test3() {
+; CHECK: define nonnull i8* @test3
+  call i8* @scc_binder()
+  %ret = call i8* @ret_nonnull()
+  ret i8* %ret
+}
+
+; Given a mutual recursive set of functions, we can mark them
+; nonnull if neither can ever return null.  (In this case, they
+; just never return period.)
+define i8* @test4_helper() {
+; CHECK: define noalias nonnull i8* @test4_helper
+  %ret = call i8* @test4()
+  ret i8* %ret
+}
+
+define i8* @test4() {
+; CHECK: define noalias nonnull i8* @test4
+  %ret = call i8* @test4_helper()
+  ret i8* %ret
+}
+
+; Given a mutual recursive set of functions which *can* return null
+; make sure we haven't marked them as nonnull.
+define i8* @test5_helper() {
+; CHECK: define noalias i8* @test5_helper
+  %ret = call i8* @test5()
+  ret i8* null
+}
+
+define i8* @test5() {
+; CHECK: define noalias i8* @test5
+  %ret = call i8* @test5_helper()
+  ret i8* %ret
+}
+
+; Local analysis, but going through a self recursive phi
+define i8* @test6() {
+entry:
+; CHECK: define nonnull i8* @test6
+  %ret = call i8* @ret_nonnull()
+  br label %loop
+loop:
+  %phi = phi i8* [%ret, %entry], [%phi, %loop]
+  br i1 undef, label %loop, label %exit
+exit:
+  ret i8* %phi
+}
+
+; Test propagation of nonnull callsite args back to caller.
+
+declare void @use1(i8* %x)
+declare void @use2(i8* %x, i8* %y);
+declare void @use3(i8* %x, i8* %y, i8* %z);
+
+declare void @use1nonnull(i8* nonnull %x);
+declare void @use2nonnull(i8* nonnull %x, i8* nonnull %y);
+declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z);
+
+declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantees that execution continues to successor
+
+; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.
+
+define void @parent1(i8* %a, i8* %b, i8* %c) {
+; CHECK-LABEL: @parent1(i8* %a, i8* %b, i8* %c)
+; CHECK-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
+; CHECK-NEXT:    call void @use3nonnull(i8* %b, i8* %c, i8* %a)
+; CHECK-NEXT:    ret void
+;
+  call void @use3(i8* %c, i8* %a, i8* %b)
+  call void @use3nonnull(i8* %b, i8* %c, i8* %a)
+  ret void
+}
+
+; Extend non-null to parent for all arguments.
+
+define void @parent2(i8* %a, i8* %b, i8* %c) {
+; CHECK-LABEL: @parent2(i8* nonnull %a, i8* nonnull %b, i8* nonnull %c)
+; CHECK-NEXT:    call void @use3nonnull(i8* %b, i8* %c, i8* %a)
+; CHECK-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
+; CHECK-NEXT:    ret void
+;
+  call void @use3nonnull(i8* %b, i8* %c, i8* %a)
+  call void @use3(i8* %c, i8* %a, i8* %b)
+  ret void
+}
+
+; Extend non-null to parent for 1st argument.
+
+define void @parent3(i8* %a, i8* %b, i8* %c) {
+; CHECK-LABEL: @parent3(i8* nonnull %a, i8* %b, i8* %c)
+; CHECK-NEXT:    call void @use1nonnull(i8* %a)
+; CHECK-NEXT:    call void @use3(i8* %c, i8* %b, i8* %a)
+; CHECK-NEXT:    ret void
+;
+  call void @use1nonnull(i8* %a)
+  call void @use3(i8* %c, i8* %b, i8* %a)
+  ret void
+}
+
+; Extend non-null to parent for last 2 arguments.
+
+define void @parent4(i8* %a, i8* %b, i8* %c) {
+; CHECK-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c)
+; CHECK-NEXT:    call void @use2nonnull(i8* %c, i8* %b)
+; CHECK-NEXT:    call void @use2(i8* %a, i8* %c)
+; CHECK-NEXT:    call void @use1(i8* %b)
+; CHECK-NEXT:    ret void
+;
+  call void @use2nonnull(i8* %c, i8* %b)
+  call void @use2(i8* %a, i8* %c)
+  call void @use1(i8* %b)
+  ret void
+}
+
+; The callsite must execute in order for the attribute to transfer to the parent.
+; It appears benign to extend non-null to the parent in this case, but we can't do that
+; because it would incorrectly propagate the wrong information to its callers.
+
+define void @parent5(i8* %a, i1 %a_is_notnull) {
+; CHECK-LABEL: @parent5(i8* %a, i1 %a_is_notnull)
+; CHECK-NEXT:    br i1 %a_is_notnull, label %t, label %f
+; CHECK:       t:
+; CHECK-NEXT:    call void @use1nonnull(i8* %a)
+; CHECK-NEXT:    ret void
+; CHECK:       f:
+; CHECK-NEXT:    ret void
+;
+  br i1 %a_is_notnull, label %t, label %f
+t:
+  call void @use1nonnull(i8* %a)
+  ret void
+f:
+  ret void
+}
+
+; The callsite must execute in order for the attribute to transfer to the parent.
+; The volatile load might trap, so there's no guarantee that we'll ever get to the call.
+
+define i8 @parent6(i8* %a, i8* %b) {
+; CHECK-LABEL: @parent6(i8* %a, i8* %b)
+; CHECK-NEXT:    [[C:%.*]] = load volatile i8, i8* %b
+; CHECK-NEXT:    call void @use1nonnull(i8* %a)
+; CHECK-NEXT:    ret i8 [[C]]
+;
+  %c = load volatile i8, i8* %b
+  call void @use1nonnull(i8* %a)
+  ret i8 %c
+}
+
+; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.
+
+define i8 @parent7(i8* %a) {
+; CHECK-LABEL: @parent7(i8* nonnull %a)
+; CHECK-NEXT:    [[RET:%.*]] = call i8 @use1safecall(i8* %a)
+; CHECK-NEXT:    call void @use1nonnull(i8* %a)
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+  %ret = call i8 @use1safecall(i8* %a)
+  call void @use1nonnull(i8* %a)
+  ret i8 %ret
+}
+
+; Make sure that an invoke works similarly to a call.
+
+declare i32 @esfp(...)
+
+define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){
+; CHECK-LABEL: @parent8(i8* nonnull %a, i8* nocapture readnone %bogus1, i8* nonnull %b)
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    invoke void @use2nonnull(i8* %a, i8* %b)
+; CHECK-NEXT:    to label %cont unwind label %exc
+; CHECK:       cont:
+; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i8* %b, null
+; CHECK-NEXT:    ret i1 [[NULL_CHECK]]
+; CHECK:       exc:
+; CHECK-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
+; CHECK-NEXT:    filter [0 x i8*] zeroinitializer
+; CHECK-NEXT:    unreachable
+;
+entry:
+  invoke void @use2nonnull(i8* %a, i8* %b)
+  to label %cont unwind label %exc
+
+cont:
+  %null_check = icmp eq i8* %b, null
+  ret i1 %null_check
+
+exc:
+  %lp = landingpad { i8*, i32 }
+  filter [0 x i8*] zeroinitializer
+  unreachable
+}
+
+; CHECK: define nonnull i32* @gep1(
+define i32* @gep1(i32* %p) {
+  %q = getelementptr inbounds i32, i32* %p, i32 1
+  ret i32* %q
+}
+
+define i32* @gep1_no_null_opt(i32* %p) #0 {
+; Should't be able to derive nonnull based on gep.
+; CHECK: define i32* @gep1_no_null_opt(
+  %q = getelementptr inbounds i32, i32* %p, i32 1
+  ret i32* %q
+}
+
+; CHECK: define i32 addrspace(3)* @gep2(
+define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) {
+  %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1
+  ret i32 addrspace(3)* %q
+}
+
+attributes #0 = { "null-pointer-is-valid"="true" }

Added: llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/norecurse.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,91 @@
+; RUN: opt < %s -basicaa -functionattrs -rpo-functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-functionattrs' -S | FileCheck %s
+
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse nounwind readnone
+; CHECK-NEXT: define i32 @leaf()
+define i32 @leaf() {
+  ret i32 1
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @self_rec()
+define i32 @self_rec() {
+  %a = call i32 @self_rec()
+  ret i32 4
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec()
+define i32 @indirect_rec() {
+  %a = call i32 @indirect_rec2()
+  ret i32 %a
+}
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @indirect_rec2()
+define i32 @indirect_rec2() {
+  %a = call i32 @indirect_rec()
+  ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: readnone
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define i32 @extern()
+define i32 @extern() {
+  %a = call i32 @k()
+  ret i32 %a
+}
+
+; CHECK: Function Attrs
+; CHECK-NEXT: declare i32 @k()
+declare i32 @k() readnone
+
+; CHECK: Function Attrs
+; CHECK-SAME: nounwind
+; CHECK-NOT: norecurse
+; CHECK-NEXT: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len)
+define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false)
+  ret void
+}
+
+; CHECK: Function Attrs
+; CHECK-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)
+
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse readnone
+; CHECK-NEXT: define internal i32 @called_by_norecurse()
+define internal i32 @called_by_norecurse() {
+  %a = call i32 @k()
+  ret i32 %a
+}
+; CHECK: Function Attrs
+; CHECK-NEXT: define void @m()
+define void @m() norecurse {
+  %a = call i32 @called_by_norecurse()
+  ret void
+}
+
+; CHECK: Function Attrs
+; CHECK-SAME: norecurse readnone
+; CHECK-NEXT: define internal i32 @called_by_norecurse_indirectly()
+define internal i32 @called_by_norecurse_indirectly() {
+  %a = call i32 @k()
+  ret i32 %a
+}
+define internal void @o() {
+  %a = call i32 @called_by_norecurse_indirectly()
+  ret void
+}
+define void @p() norecurse {
+  call void @o()
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/operand-bundles-scc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt -S -functionattrs < %s | FileCheck %s
+; RUN: opt -S -passes=function-attrs < %s | FileCheck %s
+
+define void @f() {
+; CHECK-LABEL:  define void @f() #0 {
+ call void @g() [ "unknown"() ]
+ ret void
+}
+
+define void @g() {
+; CHECK-LABEL:  define void @g() #0 {
+ call void @f()
+ ret void
+}
+
+
+; CHECK: attributes #0 = { nounwind }

Added: llvm/trunk/test/Transforms/FunctionAttrs/optnone-simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/optnone-simple.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/optnone-simple.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/optnone-simple.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,135 @@
+; RUN: opt -O3 -S < %s | FileCheck %s
+; Show 'optnone' suppresses optimizations.
+
+; Two attribute groups that differ only by 'optnone'.
+; 'optnone' requires 'noinline' so #0 is 'noinline' by itself,
+; even though it would otherwise be irrelevant to this example.
+attributes #0 = { noinline }
+attributes #1 = { noinline optnone }
+
+; int iadd(int a, int b){ return a + b; }
+
+define i32 @iadd_optimize(i32 %a, i32 %b) #0 {
+entry:
+  %a.addr = alloca i32, align 4
+  %b.addr = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  store i32 %b, i32* %b.addr, align 4
+  %0 = load i32, i32* %a.addr, align 4
+  %1 = load i32, i32* %b.addr, align 4
+  %add = add nsw i32 %0, %1
+  ret i32 %add
+}
+
+; CHECK-LABEL: @iadd_optimize
+; CHECK-NOT: alloca
+; CHECK-NOT: store
+; CHECK-NOT: load
+; CHECK: ret
+
+define i32 @iadd_optnone(i32 %a, i32 %b) #1 {
+entry:
+  %a.addr = alloca i32, align 4
+  %b.addr = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  store i32 %b, i32* %b.addr, align 4
+  %0 = load i32, i32* %a.addr, align 4
+  %1 = load i32, i32* %b.addr, align 4
+  %add = add nsw i32 %0, %1
+  ret i32 %add
+}
+
+; CHECK-LABEL: @iadd_optnone
+; CHECK: alloca i32
+; CHECK: alloca i32
+; CHECK: store i32
+; CHECK: store i32
+; CHECK: load i32
+; CHECK: load i32
+; CHECK: add nsw i32
+; CHECK: ret i32
+
+; float fsub(float a, float b){ return a - b; }
+
+define float @fsub_optimize(float %a, float %b) #0 {
+entry:
+  %a.addr = alloca float, align 4
+  %b.addr = alloca float, align 4
+  store float %a, float* %a.addr, align 4
+  store float %b, float* %b.addr, align 4
+  %0 = load float, float* %a.addr, align 4
+  %1 = load float, float* %b.addr, align 4
+  %sub = fsub float %0, %1
+  ret float %sub
+}
+
+; CHECK-LABEL: @fsub_optimize
+; CHECK-NOT: alloca
+; CHECK-NOT: store
+; CHECK-NOT: load
+; CHECK: ret
+
+define float @fsub_optnone(float %a, float %b) #1 {
+entry:
+  %a.addr = alloca float, align 4
+  %b.addr = alloca float, align 4
+  store float %a, float* %a.addr, align 4
+  store float %b, float* %b.addr, align 4
+  %0 = load float, float* %a.addr, align 4
+  %1 = load float, float* %b.addr, align 4
+  %sub = fsub float %0, %1
+  ret float %sub
+}
+
+; CHECK-LABEL: @fsub_optnone
+; CHECK: alloca float
+; CHECK: alloca float
+; CHECK: store float
+; CHECK: store float
+; CHECK: load float
+; CHECK: load float
+; CHECK: fsub float
+; CHECK: ret float
+
+; typedef float __attribute__((ext_vector_type(4))) float4;
+; float4 vmul(float4 a, float4 b){ return a * b; }
+
+define <4 x float> @vmul_optimize(<4 x float> %a, <4 x float> %b) #0 {
+entry:
+  %a.addr = alloca <4 x float>, align 16
+  %b.addr = alloca <4 x float>, align 16
+  store <4 x float> %a, <4 x float>* %a.addr, align 16
+  store <4 x float> %b, <4 x float>* %b.addr, align 16
+  %0 = load <4 x float>, <4 x float>* %a.addr, align 16
+  %1 = load <4 x float>, <4 x float>* %b.addr, align 16
+  %mul = fmul <4 x float> %0, %1
+  ret <4 x float> %mul
+}
+
+; CHECK-LABEL: @vmul_optimize
+; CHECK-NOT: alloca
+; CHECK-NOT: store
+; CHECK-NOT: load
+; CHECK: ret
+
+define <4 x float> @vmul_optnone(<4 x float> %a, <4 x float> %b) #1 {
+entry:
+  %a.addr = alloca <4 x float>, align 16
+  %b.addr = alloca <4 x float>, align 16
+  store <4 x float> %a, <4 x float>* %a.addr, align 16
+  store <4 x float> %b, <4 x float>* %b.addr, align 16
+  %0 = load <4 x float>, <4 x float>* %a.addr, align 16
+  %1 = load <4 x float>, <4 x float>* %b.addr, align 16
+  %mul = fmul <4 x float> %0, %1
+  ret <4 x float> %mul
+}
+
+; CHECK-LABEL: @vmul_optnone
+; CHECK: alloca <4 x float>
+; CHECK: alloca <4 x float>
+; CHECK: store <4 x float>
+; CHECK: store <4 x float>
+; CHECK: load <4 x float>
+; CHECK: load <4 x float>
+; CHECK: fmul <4 x float>
+; CHECK: ret

Added: llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/optnone.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+ at x = global i32 0
+
+define void @test_opt(i8* %p) {
+; CHECK-LABEL: @test_opt
+; CHECK: (i8* nocapture readnone %p) #0 {
+  ret void
+}
+
+define void @test_optnone(i8* %p) noinline optnone {
+; CHECK-LABEL: @test_optnone
+; CHECK: (i8* %p) #1 {
+  ret void
+}
+
+declare i8 @strlen(i8*) noinline optnone
+; CHECK-LABEL: @strlen
+; CHECK: (i8*) #1
+
+; CHECK-LABEL: attributes #0
+; CHECK: = { norecurse nounwind readnone }
+; CHECK-LABEL: attributes #1
+; CHECK: = { noinline optnone }

Added: llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/out-of-bounds-iterator-bug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -functionattrs -S < %s | FileCheck %s
+; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
+
+; This checks for an iterator wraparound bug in FunctionAttrs.  The previous
+; "incorrect" behavior was inferring readonly for the %x argument in @caller.
+; Inferring readonly for %x *is* actually correct, since @va_func is marked
+; readonly, but FunctionAttrs was inferring readonly for the wrong reasons (and
+; we _need_ the readonly on @va_func to trigger the problematic code path).  It
+; is possible that in the future FunctionAttrs becomes smart enough to infer
+; readonly for %x for the right reasons, and at that point this test will have
+; to be marked invalid.
+
+declare void @llvm.va_start(i8*)
+declare void @llvm.va_end(i8*)
+
+define void @va_func(i32* readonly %b, ...) readonly nounwind {
+; CHECK-LABEL: define void @va_func(i32* nocapture readonly %b, ...)
+ entry:
+  %valist = alloca i8
+  call void @llvm.va_start(i8* %valist)
+  call void @llvm.va_end(i8* %valist)
+  %x = call i32 @caller(i32* %b)
+  ret void
+}
+
+define i32 @caller(i32* %x) {
+; CHECK-LABEL: define i32 @caller(i32* nocapture %x)
+ entry:
+  call void(i32*,...) @va_func(i32* null, i32 0, i32 0, i32 0, i32* %x)
+  ret i32 42
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/readattrs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,115 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s
+ at x = global i32 0
+
+declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...)
+
+; CHECK: define void @test1_2(i8* %x1_2, i8* readonly %y1_2, i8* %z1_2)
+define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2) {
+  call void (i8*, i8*, ...) @test1_1(i8* %x1_2, i8* %y1_2, i8* %z1_2)
+  store i32 0, i32* @x
+  ret void
+}
+
+; CHECK: define i8* @test2(i8* readnone returned %p)
+define i8* @test2(i8* %p) {
+  store i32 0, i32* @x
+  ret i8* %p
+}
+
+; CHECK: define i1 @test3(i8* readnone %p, i8* readnone %q)
+define i1 @test3(i8* %p, i8* %q) {
+  %A = icmp ult i8* %p, %q
+  ret i1 %A
+}
+
+declare void @test4_1(i8* nocapture) readonly
+
+; CHECK: define void @test4_2(i8* nocapture readonly %p)
+define void @test4_2(i8* %p) {
+  call void @test4_1(i8* %p)
+  ret void
+}
+
+; CHECK: define void @test5(i8** nocapture %p, i8* %q)
+; Missed optz'n: we could make %q readnone, but don't break test6!
+define void @test5(i8** %p, i8* %q) {
+  store i8* %q, i8** %p
+  ret void
+}
+
+declare void @test6_1()
+; CHECK: define void @test6_2(i8** nocapture %p, i8* %q)
+; This is not a missed optz'n.
+define void @test6_2(i8** %p, i8* %q) {
+  store i8* %q, i8** %p
+  call void @test6_1()
+  ret void
+}
+
+; CHECK: define void @test7_1(i32* inalloca nocapture %a)
+; inalloca parameters are always considered written
+define void @test7_1(i32* inalloca %a) {
+  ret void
+}
+
+; CHECK: define i32* @test8_1(i32* readnone returned %p)
+define i32* @test8_1(i32* %p) {
+entry:
+  ret i32* %p
+}
+
+; CHECK: define void @test8_2(i32* %p)
+define void @test8_2(i32* %p) {
+entry:
+  %call = call i32* @test8_1(i32* %p)
+  store i32 10, i32* %call, align 4
+  ret void
+}
+
+; CHECK: declare void @llvm.masked.scatter
+declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*>, i32, <4 x i1>)
+
+; CHECK-NOT: readnone
+; CHECK-NOT: readonly
+; CHECK: define void @test9
+define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) {
+  call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>)
+  ret void
+}
+
+; CHECK: declare <4 x i32> @llvm.masked.gather
+declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
+; CHECK: readonly
+; CHECK: define <4 x i32> @test10
+define <4 x i32> @test10(<4 x i32*> %ptrs) {
+  %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>, <4 x i32>undef)
+  ret <4 x i32> %res
+}
+
+; CHECK: declare <4 x i32> @test11_1
+declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly
+; CHECK: readonly
+; CHECK-NOT: readnone
+; CHECK: define <4 x i32> @test11_2
+define <4 x i32> @test11_2(<4 x i32*> %ptrs) {
+  %res = call <4 x i32> @test11_1(<4 x i32*> %ptrs)
+  ret <4 x i32> %res
+}
+
+declare <4 x i32> @test12_1(<4 x i32*>) argmemonly nounwind
+; CHECK-NOT: readnone
+; CHECK: define <4 x i32> @test12_2
+define <4 x i32> @test12_2(<4 x i32*> %ptrs) {
+  %res = call <4 x i32> @test12_1(<4 x i32*> %ptrs)
+  ret <4 x i32> %res
+}
+
+; CHECK: define i32 @volatile_load(
+; CHECK-NOT: readonly
+; CHECK: ret
+define i32 @volatile_load(i32* %p) {
+  %load = load volatile i32, i32* %p
+  ret i32 %load
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/readnone.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+; CHECK: define void @bar(i8* nocapture readnone)
+define void @bar(i8* readonly) {
+  call void @foo(i8* %0)
+    ret void
+}
+
+; CHECK: define void @foo(i8* nocapture readnone)
+define void @foo(i8* readonly) {
+  call void @bar(i8* %0)
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionAttrs/returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/returned.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/returned.ll (added)
+++ llvm/trunk/test/Transforms/FunctionAttrs/returned.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt < %s -functionattrs -S | FileCheck %s
+; RUN: opt < %s -passes=function-attrs -S | FileCheck %s
+
+; CHECK: define i32 @test1(i32 %p, i32 %q)
+define i32 @test1(i32 %p, i32 %q) {
+entry:
+  %cmp = icmp sgt i32 %p, %q
+  br i1 %cmp, label %cond.end, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %entry
+  %tobool = icmp ne i32 %p, 0
+  %tobool1 = icmp ne i32 %q, 0
+  %or.cond = and i1 %tobool, %tobool1
+  %p.q = select i1 %or.cond, i32 %p, i32 %q
+  ret i32 %p.q
+
+cond.end:                                         ; preds = %entry
+  ret i32 %p
+}
+
+; CHECK: define i32 @test2(i32 %p1, i32 returned %p2)
+define i32 @test2(i32 %p1, i32 returned %p2) {
+  %_tmp4 = icmp eq i32 %p1, %p2
+  br i1 %_tmp4, label %bb2, label %bb1
+
+bb2:                                              ; preds = %0
+  ret i32 %p1
+
+bb1:                                              ; preds = %bb1, %0
+  br label %bb1
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/adjustable_threshold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/adjustable_threshold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/adjustable_threshold.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/adjustable_threshold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+define void @globalfunc1() {
+entry:
+  call void @trampoline()
+  ret void
+}
+; Adds an artificial level in the call graph to reduce the importing threshold
+define void @trampoline() {
+entry:
+  call void @largefunction()
+  ret void
+}
+
+define void @globalfunc2() {
+entry:
+  call void @largefunction()
+  ret void
+}
+
+
+; Size is 5: if two layers below in the call graph the threshold will be 4,
+; but if only one layer below the threshold will be 7.
+define void @largefunction() {
+  entry:
+  call void @staticfunc2()
+  call void @staticfunc2()
+  call void @staticfunc2()
+  call void @staticfunc2()
+  call void @staticfunc2()
+  ret void
+}
+
+define internal void @staticfunc2() {
+entry:
+  ret void
+}
+
+

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/comdat.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/comdat.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/comdat.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+define void @main() {
+entry:
+  call i8* @lwt_fun()
+  ret void
+}
+
+declare i8* @lwt_fun()

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,165 @@
+ at globalvar = global i32 1, align 4
+ at staticvar = internal global i32 1, align 4
+ at staticconstvar = internal unnamed_addr constant [2 x i32] [i32 10, i32 20], align 4
+ at commonvar = common global i32 0, align 4
+ at P = internal global void ()* null, align 8
+
+ at weakalias = weak alias void (...), bitcast (void ()* @globalfunc1 to void (...)*)
+ at analias = alias void (...), bitcast (void ()* @globalfunc2 to void (...)*)
+ at linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*)
+
+define void @globalfunc1() #0 {
+entry:
+  call void @funcwithpersonality()
+  call void (...) @variadic_va_start()
+  ret void
+}
+
+define void @globalfunc2() #0 {
+entry:
+  ret void
+}
+
+define linkonce_odr void @linkoncefunc() #0 {
+entry:
+  ret void
+}
+
+define i32 @referencestatics(i32 %i) #0 {
+entry:
+  %i.addr = alloca i32, align 4
+  store i32 %i, i32* %i.addr, align 4
+  %call = call i32 @staticfunc()
+  %0 = load i32, i32* @staticvar, align 4
+  %add = add nsw i32 %call, %0
+  %1 = load i32, i32* %i.addr, align 4
+  %idxprom = sext i32 %1 to i64
+  %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @staticconstvar, i64 0, i64 %idxprom
+  %2 = load i32, i32* %arrayidx, align 4
+  %add1 = add nsw i32 %add, %2
+  ret i32 %add1
+}
+
+define i32 @referenceglobals(i32 %i) #0 {
+entry:
+  %i.addr = alloca i32, align 4
+  store i32 %i, i32* %i.addr, align 4
+  call void @globalfunc1()
+  %0 = load i32, i32* @globalvar, align 4
+  ret i32 %0
+}
+
+define i32 @referencecommon(i32 %i) #0 {
+entry:
+  %i.addr = alloca i32, align 4
+  store i32 %i, i32* %i.addr, align 4
+  %0 = load i32, i32* @commonvar, align 4
+  ret i32 %0
+}
+
+define void @setfuncptr() #0 {
+entry:
+  store void ()* @staticfunc2, void ()** @P, align 8
+  ret void
+}
+
+define void @callfuncptr() #0 {
+entry:
+  %0 = load void ()*, void ()** @P, align 8
+  call void %0()
+  ret void
+}
+
+ at weakvar = weak global i32 1, align 4
+define weak void @weakfunc() #0 {
+entry:
+  ret void
+}
+
+define linkonce void @linkoncefunc2() #0 {
+entry:
+  ret void
+}
+
+define internal i32 @staticfunc() #0 {
+entry:
+  ret i32 1
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+; Add enough instructions to prevent import with inst limit of 5
+define internal void @funcwithpersonality() #2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  ret void
+}
+
+define internal void @staticfunc2() #0 {
+entry:
+  ret void
+}
+
+define void @referencelargelinkonce() #0 {
+entry:
+  call void @linkonceodr()
+  ret void
+}
+
+; A large enough linkonce_odr function that should never be imported
+define linkonce_odr void @linkonceodr() #0 {
+entry:
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  call void @globalfunc2()
+  ret void
+}
+
+; Variadic function without va_start can be imported because inliner
+; can handle it.
+define void @variadic_no_va_start(...) {
+    ret void
+}
+
+; Variadic function with va_start should not be imported because inliner
+; doesn't handle it.
+define void @variadic_va_start(...) {
+    %ap = alloca i8*, align 8
+    %ap.0 = bitcast i8** %ap to i8*
+    call void @llvm.va_start(i8* %ap.0)
+    ret void
+}
+
+declare void @llvm.va_start(i8*) nounwind

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,7 @@
+declare void @analias()
+
+define void @callanalias() #0 {
+entry:
+  call void @analias()
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_cutoff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_cutoff.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_cutoff.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_cutoff.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,9 @@
+define void @foo() {
+entry:
+  ret void
+}
+
+define void @bar() {
+entry:
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_debug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_debug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_debug.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_debug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; ModuleID = 'funcimport_debug.o'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define void @func() #0 !dbg !4 {
+entry:
+    ret void, !dbg !10
+}
+
+attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (trunk 255685) (llvm/trunk 255682)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "funcimport_debug.c", directory: ".")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "func", 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 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{!"clang version 3.8.0 (trunk 255685) (llvm/trunk 255682)"}
+!10 = !DILocation(line: 2, column: 1, scope: !4)

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_forcecold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_forcecold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_forcecold.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_forcecold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,4 @@
+define void @foo() {
+entry:
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved1.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+define void @foo() {
+  call void @linkonceodrfunc()
+  call void @linkonceodrfunc2()
+  ret void
+}
+
+define linkonce_odr void @linkonceodrfunc() {
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  ret void
+}
+
+define linkonce_odr void @linkonceodrfunc2() {
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  call void @f()
+  ret void
+}
+
+define internal void @f() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved2.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_resolved2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,6 @@
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+define linkonce_odr void @linkonceodrfunc() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_var2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_var2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_var2.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_var2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at link = internal global i32 0, align 4
+
+; Function Attrs: norecurse nounwind readnone uwtable
+define nonnull i32* @get_link() local_unnamed_addr {
+  ret i32* @link
+}
+

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/hotness_based_import.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/hotness_based_import.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/hotness_based_import.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/hotness_based_import.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; ModuleID = 'thinlto-function-summary-callgraph-profile-summary2.ll'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+
+define void @hot1() #1 {
+  ret void
+}
+define void @hot2() #1 !prof !20  {
+  call void @calledFromHot()
+  call void @calledFromHot()
+  ret void
+}
+define void @hot3() #1 !prof !20 {
+  call void @calledFromHot()
+  call void @calledFromHot()
+  call void @calledFromHot()
+  ret void
+}
+define void @cold() #1 !prof !0 {
+  ret void
+}
+define void @cold2() #1 !prof !0  {
+  call void @calledFromCold()
+  call void @calledFromCold()
+  ret void
+}
+
+define void @none1() #1 {
+  ret void
+}
+
+define void @none2() #1 {
+  call void @calledFromNone()
+  ret void
+}
+define void @none3() #1 {
+  call void @calledFromNone()
+  call void @calledFromNone()
+  ret void
+}
+
+define void @calledFromCold() {
+  ret void
+}
+
+define void @calledFromHot() !prof !20 {
+  call void @calledFromHot2()
+  ret void
+}
+
+define void @calledFromHot2() !prof !20 {
+  call void @calledFromHot3()
+  ret void
+}
+
+define void @calledFromNone() !prof !0 {
+  ret void
+}
+
+declare void @calledFromHot3()
+
+!0 = !{!"function_entry_count", i64 1}
+!20 = !{!"function_entry_count", i64 110}
+
+!llvm.module.flags = !{!1}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 10}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}
\ No newline at end of file

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/import_stats.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/import_stats.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/import_stats.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/import_stats.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; ModuleID = 'import_stats2.ll'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at globalvar = global i32 1, align 4
+
+define void @hot() {
+  store i32 0, i32* @globalvar, align 4
+  ret void
+}
+define void @critical() {
+  ret void
+}
+define void @none() {
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/inlineasm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+ at myvar = internal constant i8 1, align 1
+ at llvm.used = appending global [1 x i8*] [i8* @myvar], section "llvm.metadata"
+
+define void @foo(i64* %v) #0 {
+entry:
+  %v.addr = alloca i64*, align 8
+  store i64* %v, i64** %v.addr, align 8
+  %0 = load i64*, i64** %v.addr, align 8
+  call void asm sideeffect "movzbl     myvar(%rip), %eax\0A\09movq %rax, $0\0A\09", "=*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i64* %0) #1
+  ret void
+}

Added: llvm/trunk/test/Transforms/FunctionImport/Inputs/not-prevailing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/Inputs/not-prevailing.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/Inputs/not-prevailing.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/Inputs/not-prevailing.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,6 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define weak i32 @foo() {
+  ret i32 0
+}

Added: llvm/trunk/test/Transforms/FunctionImport/adjustable_threshold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/adjustable_threshold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/adjustable_threshold.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/adjustable_threshold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/adjustable_threshold.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Test import with default progressive instruction factor
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=10 -S | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIM-DEFAULT
+; INSTLIM-DEFAULT: call void @staticfunc2.llvm.
+
+; Test import with a reduced progressive instruction factor
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=10 -import-instr-evolution-factor=0.5 -S | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIM-PROGRESSIVE
+; INSTLIM-PROGRESSIVE-NOT: call void @staticfunc
+
+
+
+declare void @globalfunc1()
+declare void @globalfunc2()
+
+define void @entry() {
+entry:
+; Call site are processed in reversed order!
+
+; On the direct call, we reconsider @largefunction with a higher threshold and
+; import it
+  call void @globalfunc2()
+; When importing globalfunc1, the threshold was limited and @largefunction was
+; not imported.
+  call void @globalfunc1()
+  ret void
+}
+

Added: llvm/trunk/test/Transforms/FunctionImport/comdat.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/comdat.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/comdat.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/comdat.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; Test to ensure that comdat is renamed consistently when comdat leader is
+; promoted and renamed due to an import. Required by COFF.
+
+; REQUIRES: x86-registered-target
+
+; RUN: opt -thinlto-bc -o %t1.bc %s
+; RUN: opt -thinlto-bc -o %t2.bc %S/Inputs/comdat.ll
+; RUN: llvm-lto2 run -save-temps -o %t3 %t1.bc %t2.bc \
+; RUN:          -r %t1.bc,lwt_fun,plx \
+; RUN:          -r %t2.bc,main,plx \
+; RUN:          -r %t2.bc,lwt_fun,
+; RUN: llvm-dis -o - %t3.1.3.import.bc | FileCheck %s
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+; CHECK: $lwt.llvm.[[HASH:[0-9]+]] = comdat any
+$lwt = comdat any
+
+; CHECK: @lwt_aliasee = private unnamed_addr global {{.*}}, comdat($lwt.llvm.[[HASH]])
+ at lwt_aliasee = private unnamed_addr global [1 x i8*] [i8* null], comdat($lwt)
+
+; CHECK: @lwt.llvm.[[HASH]] = hidden unnamed_addr alias
+ at lwt = internal unnamed_addr alias [1 x i8*], [1 x i8*]* @lwt_aliasee
+
+; Below function should get imported into other module, resulting in @lwt being
+; promoted and renamed.
+define i8* @lwt_fun() {
+  %1 = getelementptr inbounds [1 x i8*], [1 x i8*]* @lwt, i32 0, i32 0
+  %2 = load i8*, i8** %1
+  ret i8* %2
+}

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,162 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -print-summary-global-ids -o %t3 %t.bc %t2.bc 2>&1 | FileCheck %s --check-prefix=GUID
+
+; Do the import now
+; RUN: opt -function-import -stats -print-imports -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIMDEF
+; Try again with new pass manager
+; RUN: opt -passes='function-import' -stats -print-imports -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIMDEF
+; RUN: opt -passes='function-import' -debug-only=function-import -enable-import-metadata -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=DUMP
+; "-stats" and "-debug-only" require +Asserts.
+; REQUIRES: asserts
+
+; Test import with smaller instruction limit
+; RUN: opt -function-import -enable-import-metadata  -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=5 -S | FileCheck %s --check-prefix=CHECK --check-prefix=INSTLIM5
+; INSTLIM5-NOT: @staticfunc.llvm.
+
+
+define i32 @main() #0 {
+entry:
+  call void (...) @weakalias()
+  call void (...) @analias()
+  call void (...) @linkoncealias()
+  %call = call i32 (...) @referencestatics()
+  %call1 = call i32 (...) @referenceglobals()
+  %call2 = call i32 (...) @referencecommon()
+  call void (...) @setfuncptr()
+  call void (...) @callfuncptr()
+  call void (...) @weakfunc()
+  call void (...) @linkoncefunc2()
+  call void (...) @referencelargelinkonce()
+  call void (...) @variadic_no_va_start()
+  call void (...) @variadic_va_start()
+  ret i32 0
+}
+
+; Won't import weak alias
+; CHECK-DAG: declare void @weakalias
+declare void @weakalias(...) #1
+
+; External alias imported as available_externally copy of aliasee
+; CHECK-DAG: define available_externally void @analias
+declare void @analias(...) #1
+
+; External alias imported as available_externally copy of aliasee
+; (linkoncealias is an external alias to a linkonce_odr)
+declare void @linkoncealias(...) #1
+; CHECK-DAG: define available_externally void @linkoncealias()
+
+; INSTLIMDEF-DAG: Import referencestatics
+; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i) !thinlto_src_module !0 {
+; INSTLIM5-DAG: declare i32 @referencestatics(...)
+declare i32 @referencestatics(...) #1
+
+; The import of referencestatics will expose call to staticfunc that
+; should in turn be imported as a promoted/renamed and hidden function.
+; Ensure that the call is to the properly-renamed function.
+; INSTLIMDEF-DAG: Import staticfunc
+; INSTLIMDEF-DAG: %call = call i32 @staticfunc.llvm.
+; INSTLIMDEF-DAG: define available_externally hidden i32 @staticfunc.llvm.{{.*}} !thinlto_src_module !0 {
+
+; INSTLIMDEF-DAG: Import referenceglobals
+; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i) !thinlto_src_module !0 {
+declare i32 @referenceglobals(...) #1
+
+; The import of referenceglobals will expose call to globalfunc1 that
+; should in turn be imported.
+; INSTLIMDEF-DAG: Import globalfunc1
+; CHECK-DAG: define available_externally void @globalfunc1() !thinlto_src_module !0
+
+; INSTLIMDEF-DAG: Import referencecommon
+; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i) !thinlto_src_module !0 {
+declare i32 @referencecommon(...) #1
+
+; INSTLIMDEF-DAG: Import setfuncptr
+; CHECK-DAG: define available_externally void @setfuncptr() !thinlto_src_module !0 {
+declare void @setfuncptr(...) #1
+
+; INSTLIMDEF-DAG: Import callfuncptr
+; CHECK-DAG: define available_externally void @callfuncptr() !thinlto_src_module !0 {
+declare void @callfuncptr(...) #1
+
+; Ensure that all uses of local variable @P which has used in setfuncptr
+; and callfuncptr are to the same promoted/renamed global.
+; CHECK-DAG: @P.llvm.{{.*}} = available_externally hidden global void ()* null
+; CHECK-DAG: %0 = load void ()*, void ()** @P.llvm.
+; CHECK-DAG: store void ()* @staticfunc2.llvm.{{.*}}, void ()** @P.llvm.
+
+; Ensure that @referencelargelinkonce definition is pulled in, but later we
+; also check that the linkonceodr function is not.
+; CHECK-DAG: define available_externally void @referencelargelinkonce() !thinlto_src_module !0 {
+; INSTLIM5-DAG: declare void @linkonceodr()
+declare void @referencelargelinkonce(...)
+
+; Won't import weak func
+; CHECK-DAG: declare void @weakfunc(...)
+declare void @weakfunc(...) #1
+
+; Won't import linkonce func
+; CHECK-DAG: declare void @linkoncefunc2(...)
+declare void @linkoncefunc2(...) #1
+
+; INSTLIMDEF-DAG: Import funcwithpersonality
+; INSTLIMDEF-DAG: define available_externally hidden void @funcwithpersonality.llvm.{{.*}}() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) !thinlto_src_module !0 {
+; INSTLIM5-DAG: declare hidden void @funcwithpersonality.llvm.{{.*}}()
+
+; We can import variadic functions without a va_start, since the inliner
+; can handle them.
+; INSTLIMDEF-DAG: Import variadic_no_va_start
+; CHECK-DAG: define available_externally void @variadic_no_va_start(...) !thinlto_src_module !0 {
+declare void @variadic_no_va_start(...)
+
+; We can import variadic functions with a va_start, since the inliner
+; can sometimes handle them.
+; CHECK-DAG: define available_externally void @variadic_va_start(...)
+declare void @variadic_va_start(...)
+
+; INSTLIMDEF-DAG: Import globalfunc2
+; INSTLIMDEF-DAG: 15 function-import - Number of functions imported
+; INSTLIMDEF-DAG: 4 function-import - Number of global variables imported
+
+; CHECK-DAG: !0 = !{!"{{.*}}/Inputs/funcimport.ll"}
+
+; The actual GUID values will depend on path to test.
+; GUID-DAG: GUID {{.*}} is weakalias
+; GUID-DAG: GUID {{.*}} is referenceglobals
+; GUID-DAG: GUID {{.*}} is weakfunc
+; GUID-DAG: GUID {{.*}} is main
+; GUID-DAG: GUID {{.*}} is referencecommon
+; GUID-DAG: GUID {{.*}} is analias
+; GUID-DAG: GUID {{.*}} is referencestatics
+; GUID-DAG: GUID {{.*}} is linkoncealias
+; GUID-DAG: GUID {{.*}} is setfuncptr
+; GUID-DAG: GUID {{.*}} is callfuncptr
+; GUID-DAG: GUID {{.*}} is funcwithpersonality
+; GUID-DAG: GUID {{.*}} is setfuncptr
+; GUID-DAG: GUID {{.*}} is staticfunc2
+; GUID-DAG: GUID {{.*}} is __gxx_personality_v0
+; GUID-DAG: GUID {{.*}} is referencestatics
+; GUID-DAG: GUID {{.*}} is globalfunc1
+; GUID-DAG: GUID {{.*}} is globalfunc2
+; GUID-DAG: GUID {{.*}} is P
+; GUID-DAG: GUID {{.*}} is staticvar
+; GUID-DAG: GUID {{.*}} is commonvar
+; GUID-DAG: GUID {{.*}} is weakalias
+; GUID-DAG: GUID {{.*}} is staticfunc
+; GUID-DAG: GUID {{.*}} is weakfunc
+; GUID-DAG: GUID {{.*}} is referenceglobals
+; GUID-DAG: GUID {{.*}} is weakvar
+; GUID-DAG: GUID {{.*}} is staticconstvar
+; GUID-DAG: GUID {{.*}} is analias
+; GUID-DAG: GUID {{.*}} is globalvar
+; GUID-DAG: GUID {{.*}} is referencecommon
+; GUID-DAG: GUID {{.*}} is linkoncealias
+; GUID-DAG: GUID {{.*}} is callfuncptr
+; GUID-DAG: GUID {{.*}} is linkoncefunc
+
+; DUMP:       Module [[M1:.*]] imports from 1 module
+; DUMP-NEXT:  15 functions imported from [[M2:.*]]
+; DUMP-NEXT:  4 vars imported from [[M2]]
+; DUMP:       Imported 15 functions for Module [[M1]]
+; DUMP-NEXT:  Imported 4 global variables for Module [[M1]]

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_alias.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_alias.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Do the import now. Ensures that the importer handles an external call
+; from imported callanalias() to a function that is defined already in
+; the dest module, but as an alias.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -S | FileCheck %s
+
+define i32 @main() #0 {
+entry:
+  call void @callanalias()
+  ret i32 0
+}
+
+ at analias = alias void (), void ()* @globalfunc
+
+define void @globalfunc() #0 {
+entry:
+  ret void
+}
+
+declare void @callanalias() #1
+; CHECK-DAG: define available_externally void @callanalias()

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_cutoff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_cutoff.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_cutoff.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_cutoff.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; Test to ensure that thin linking with -import-cutoff stops importing when
+; expected.
+
+; "-stats" and "-debug-only" require +Asserts.
+; REQUIRES: asserts
+
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_cutoff.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; First do with default options, which should import both foo and bar
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT
+
+; Next try to restrict to 1 import. This should import just foo.
+; RUN: opt -import-cutoff=1 -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT1
+
+; Next try to restrict to 0 imports. This should not import.
+; RUN: opt -import-cutoff=0 -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT
+
+define i32 @main() {
+entry:
+  call void @foo()
+  call void @bar()
+  ret i32 0
+}
+
+declare void @foo()
+declare void @bar()
+
+; Check -print-imports output
+; IMPORT: Import foo
+; IMPORT: Import bar
+; IMPORT1: Import foo
+; IMPORT1-NOT: Import bar
+; NOIMPORT-NOT: Import foo
+; NOIMPORT-NOT: Import bar
+
+; Check -S output
+; IMPORT-DAG: define available_externally void @foo()
+; IMPORT-DAG: define available_externally void @bar()
+; NOIMPORT-DAG: declare void @foo()
+; NOIMPORT-DAG: declare void @bar()
+; IMPORT1-DAG: define available_externally void @foo()
+; IMPORT1-DAG: declare void @bar()
+
+; Check -stats output
+; IMPORT: 2 function-import - Number of functions imported
+; IMPORT1: 1 function-import - Number of functions imported
+; NOIMPORT-NOT: function-import - Number of functions imported

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_debug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_debug.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_debug.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_debug.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_debug.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Do the import now and confirm that metadata is linked for imported function.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -S | FileCheck %s
+
+; CHECK: define available_externally void @func()
+
+; Check that we have exactly two subprograms (that func's subprogram wasn't
+; linked more than once for example), and that they are connected to
+; the correct compile unit.
+; CHECK: ![[CU1:[0-9]+]] = distinct !DICompileUnit(
+; CHECK: ![[CU2:[0-9]+]] = distinct !DICompileUnit(
+; CHECK: distinct !DISubprogram(name: "main"
+; CHECK-SAME:                   unit: ![[CU1]]
+; CHECK: distinct !DISubprogram(name: "func"
+; CHECK-SAME:                   unit: ![[CU2]]
+; CHECK-NOT: distinct !DISubprogram
+
+; ModuleID = 'funcimport_debug.o'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind uwtable
+define i32 @main() #0 !dbg !4 {
+entry:
+  call void (...) @func(), !dbg !11
+  ret i32 0, !dbg !12
+}
+
+declare void @func(...) #1
+
+attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+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"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8, !9}
+!llvm.ident = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (trunk 255685) (llvm/trunk 255682)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "funcimport_debug.c", directory: ".")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, retainedNodes: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7}
+!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{!"clang version 3.8.0 (trunk 255685) (llvm/trunk 255682)"}
+!11 = !DILocation(line: 3, column: 3, scope: !4)
+!12 = !DILocation(line: 4, column: 1, scope: !4)

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; Test to ensure that building summary with -force-summary-edges-cold
+; blocks importing as expected.
+
+; "-stats" and "-debug-only" require +Asserts.
+; REQUIRES: asserts
+
+; First do with default options, which should import
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_forcecold.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT
+
+; Next rebuild caller module summary with non-critical edges forced cold (which
+; should affect all edges in this test as we don't have any sample pgo).
+; Make sure we don't import.
+; RUN: opt -force-summary-edges-cold=all-non-critical -module-summary %s -o %t.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT
+
+; Next rebuild caller module summary with all edges forced cold.
+; Make sure we don't import.
+; RUN: opt -force-summary-edges-cold=all -module-summary %s -o %t.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT
+
+define i32 @main() {
+entry:
+  call void @foo()
+  ret i32 0
+}
+
+; IMPORT: Import foo
+; NOIMPORT-NOT: Import foo
+; IMPORT: define available_externally void @foo()
+; NOIMPORT: declare void @foo()
+declare void @foo()

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold_samplepgo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold_samplepgo.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold_samplepgo.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_forcecold_samplepgo.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; Test to ensure that building summary with -force-summary-edges-cold
+; blocks importing as expected.
+
+; "-stats" and "-debug-only" require +Asserts.
+; REQUIRES: asserts
+
+; First do with default options, which should import
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_forcecold.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT
+
+; Next rebuild caller module summary with only non-critical edges forced cold,
+; which should still import in this case.
+; RUN: opt -force-summary-edges-cold=all-non-critical -module-summary %s -o %t.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=IMPORT
+
+; Next rebuild caller module summary with all edges forced cold.
+; Make sure we don't import.
+; RUN: opt -force-summary-edges-cold=all -module-summary %s -o %t.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: opt -function-import -stats -print-imports -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s --check-prefix=NOIMPORT
+
+define i32 @main() !prof !1 {
+entry:
+  call void @foo()
+  ret i32 0
+}
+
+; IMPORT: Import foo
+; NOIMPORT-NOT: Import foo
+; IMPORT: define available_externally void @foo()
+; NOIMPORT: declare void @foo()
+declare void @foo()
+
+!1 = !{!"function_entry_count", i64 110, i64 6699318081062747564}

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_resolved.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_resolved.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_resolved.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_resolved.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; Test to ensure that we always select the same copy of a linkonce function
+; when it is encountered with different thresholds. When we encounter the
+; copy in funcimport_resolved1.ll with a higher threshold via the direct call
+; from main(), it will be selected for importing. When we encounter it with a
+; lower threshold by reaching it from the deeper call chain via foo(), it
+; won't be selected for importing. We don't want to select both the copy from
+; funcimport_resolved1.ll and the smaller one from funcimport_resolved2.ll,
+; leaving it up to the backend to figure out which one to actually import.
+; The linkonce_odr may have different instruction counts in practice due to
+; different inlines in the compile step.
+
+; Require asserts so we can use -debug-only
+; REQUIRES: asserts
+
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_resolved1.ll -o %t2.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_resolved2.ll -o %t3.bc
+
+; First do a sanity check that all callees are imported with the default
+; instruction limit
+; RUN: llvm-lto2 run %t.bc %t2.bc %t3.bc -o %t4 -r=%t.bc,_main,pl -r=%t.bc,_linkonceodrfunc,l -r=%t.bc,_foo,l -r=%t2.bc,_foo,pl -r=%t2.bc,_linkonceodrfunc,pl -r=%t2.bc,_linkonceodrfunc2,pl -r=%t3.bc,_linkonceodrfunc,l -thinlto-threads=1 -debug-only=function-import 2>&1 | FileCheck %s --check-prefix=INSTLIMDEFAULT
+; INSTLIMDEFAULT: Is importing function {{.*}} foo from {{.*}}funcimport_resolved1.ll
+; INSTLIMDEFAULT: Is importing function {{.*}} linkonceodrfunc from {{.*}}funcimport_resolved1.ll
+; INSTLIMDEFAULT: Is importing function {{.*}} linkonceodrfunc2 from {{.*}}funcimport_resolved1.ll
+; INSTLIMDEFAULT: Is importing function {{.*}} f from {{.*}}funcimport_resolved1.ll
+; INSTLIMDEFAULT-NOT: Is importing function {{.*}} linkonceodrfunc from {{.*}}funcimport_resolved2.ll
+
+; Now run with the lower threshold that will only allow linkonceodrfunc to be
+; imported from funcimport_resolved1.ll when encountered via the direct call
+; from main(). Ensure we don't also select the copy in funcimport_resolved2.ll
+; when it is encountered via the deeper call chain.
+; RUN: llvm-lto2 run %t.bc %t2.bc %t3.bc -o %t4 -r=%t.bc,_main,pl -r=%t.bc,_linkonceodrfunc,l -r=%t.bc,_foo,l -r=%t2.bc,_foo,pl -r=%t2.bc,_linkonceodrfunc,pl -r=%t2.bc,_linkonceodrfunc2,pl -r=%t3.bc,_linkonceodrfunc,l -thinlto-threads=1 -debug-only=function-import -import-instr-limit=8 2>&1 | FileCheck %s --check-prefix=INSTLIM8
+; INSTLIM8: Is importing function {{.*}} foo from {{.*}}funcimport_resolved1.ll
+; INSTLIM8: Is importing function {{.*}} linkonceodrfunc from {{.*}}funcimport_resolved1.ll
+; INSTLIM8: Not importing function {{.*}} linkonceodrfunc2 from {{.*}}funcimport_resolved1.ll
+; INSTLIM8: Is importing function {{.*}} f from {{.*}}funcimport_resolved1.ll
+; INSTLIM8-NOT: Is importing function {{.*}} linkonceodrfunc from {{.*}}funcimport_resolved2.ll
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.11.0"
+
+define i32 @main() #0 {
+entry:
+  call void (...) @foo()
+  call void (...) @linkonceodrfunc()
+  ret i32 0
+}
+
+declare void @foo(...) #1
+declare void @linkonceodrfunc(...) #1

Added: llvm/trunk/test/Transforms/FunctionImport/funcimport_var.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/funcimport_var.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/funcimport_var.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/funcimport_var.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; This test makes sure a static var is not selected as a callee target
+; (which will crash compilation).
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/funcimport_var2.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -thinlto-action=thinlink -o %t3 %t.bc %t2.bc
+; RUN: llvm-lto -thinlto -thinlto-action=import -thinlto-index=%t3 %t.bc %t2.bc
+; RUN: llvm-lto -thinlto -thinlto-action=run %t.bc %t2.bc -exported-symbol=_Z4LinkPKcS0_
+; RUN: llvm-nm %t.bc.thinlto.o | FileCheck %s
+; RUN: llvm-lto2 run %t.bc %t2.bc -o %t.out \
+; RUN:   -r %t.bc,_Z4LinkPKcS0_,plx \
+; RUN:   -r %t.bc,link,l \
+; RUN:   -r %t2.bc,get_link,plx
+; RUN: llvm-nm %t.out.1 | FileCheck %s
+; CHECK: U link
+
+; REQUIRES: x86-registered-target
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @_Z4LinkPKcS0_(i8*, i8*) local_unnamed_addr  {
+  %3 = tail call i32 @link(i8* %0, i8* %1) #2
+  ret i32 %3
+}
+
+; Function Attrs: nounwind
+declare i32 @link(i8*, i8*) local_unnamed_addr 

Added: llvm/trunk/test/Transforms/FunctionImport/hotness_based_import.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/hotness_based_import.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/hotness_based_import.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/hotness_based_import.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,137 @@
+; Test to check the callgraph in summary when there is PGO
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/hotness_based_import.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Test import with default hot multiplier (3) and default hot-evolution-factor (1.0)
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 --S | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-DEFAULT
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 --S -import-hot-multiplier=3.0 -import-cold-multiplier=0.0 | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-DEFAULT
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 --S -import-hot-multiplier=3.0 | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-DEFAULT
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 --S -import-hot-multiplier=3.0 -import-instr-evolution-factor=0.0 | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-DEFAULT
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 --S -import-hot-multiplier=3.0 -import-hot-evolution-factor=1.0 | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-DEFAULT
+; HOT-DEFAULT-DAG: define available_externally void @hot1()
+; HOT-DEFAULT-DAG: define available_externally void @hot2()
+; HOT-DEFAULT-DAG: define available_externally void @calledFromHot()
+; HOT-DEFAULT-DAG: define available_externally void @calledFromHot2()
+; HOT-DEFAULT-DAG: define available_externally void @none1()
+; HOT-DEFAULT-NOT: define available_externally void @cold()
+; HOT-DEFAULT-NOT: define available_externally void @hot3()
+; HOT-DEFAULT-NOT: define available_externally void @none2()
+; HOT-DEFAULT-NOT: define available_externally void @none3()
+; HOT-DEFAULT-NOT: define available_externally void @cold2()
+; HOT-DEFAULT-NOT: define available_externally void @calledFromCold()
+; HOT-DEFAULT-NOT: define available_externally void @calledFromNone()
+
+; This one tests if we decay threshold for hot callsites. With hot-evolution-factor of 0
+; we should not import any of calledFromHot functions
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 --S -import-hot-multiplier=3.0 -import-hot-evolution-factor=0.0 | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-EVOLUTION
+; HOT-EVOLUTION-DAG: define available_externally void @hot1()
+; HOT-EVOLUTION-DAG: define available_externally void @hot2()
+; HOT-EVOLUTION-DAG: define available_externally void @none1()
+; HOT-EVOLUTION-NOT: define available_externally void @hot3()
+; HOT-EVOLUTION-NOT: define available_externally void @cold()
+; HOT-EVOLUTION-NOT: define available_externally void @none2()
+; HOT-EVOLUTION-NOT: define available_externally void @none3()
+; HOT-EVOLUTION-NOT: define available_externally void @cold2()
+; HOT-EVOLUTION-NOT: define available_externally void @calledFromHot()
+; HOT-EVOLUTION-NOT: define available_externally void @calledFromHot2()
+
+; Test import with hot multiplier 1.0 - treat hot callsites as normal.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 -import-hot-multiplier=1.0 --S | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-ONE
+; HOT-ONE-DAG: define available_externally void @hot1()
+; HOT-ONE-DAG: define available_externally void @none1()
+; HOT-ONE-NOT: define available_externally void @cold()
+; HOT-ONE-NOT: define available_externally void @hot2()
+; HOT-ONE-NOT: define available_externally void @hot3()
+; HOT-ONE-NOT: define available_externally void @none2()
+; HOT-ONE-NOT: define available_externally void @none3()
+; HOT-ONE-NOT: define available_externally void @cold2()
+
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=1 -import-hot-multiplier=1.0 -import-cold-multiplier=1.0 --S | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-COLD-ONE
+; HOT-COLD-ONE-DAG: define available_externally void @hot1()
+; HOT-COLD-ONE-DAG: define available_externally void @cold()
+; HOT-COLD-ONE-DAG: define available_externally void @none1()
+; HOT-COLD-ONE-NOT: define available_externally void @hot2()
+; HOT-COLD-ONE-NOT: define available_externally void @hot3()
+; HOT-COLD-ONE-NOT: define available_externally void @none2()
+; HOT-COLD-ONE-NOT: define available_externally void @none3()
+; HOT-COLD-ONE-NOT: define available_externally void @cold2()
+
+; Test import with hot multiplier 0.0 and high threshold - don't import functions called from hot callsite.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -import-instr-limit=10 -import-hot-multiplier=0.0 -import-cold-multiplier=1.0 --S | FileCheck %s --check-prefix=CHECK --check-prefix=HOT-ZERO
+; HOT-ZERO-DAG: define available_externally void @cold()
+; HOT-ZERO-DAG: define available_externally void @none1()
+; HOT-ZERO-DAG: define available_externally void @none2()
+; HOT-ZERO-DAG: define available_externally void @none3()
+; HOT-ZERO-DAG: define available_externally void @cold2()
+; HOT-ZERO-DAG: define available_externally void @calledFromCold()
+; HOT-ZERO-DAG: define available_externally void @calledFromNone()
+; HOT-ZERO-NOT: define available_externally void @hot2()
+; HOT-ZERO-NOT: define available_externally void @hot1()
+; HOT-ZERO-NOT: define available_externally void @hot3()
+; HOT-ZERO-NOT: define available_externally void @calledFromHot()
+; HOT-ZERO-NOT: define available_externally void @calledFromHot2()
+
+
+; ModuleID = 'thinlto-function-summary-callgraph.ll'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This function have high profile count, so entry block is hot.
+define void @hot_function(i1 %a, i1 %a2) !prof !20 {
+entry:
+    call void @hot1()
+    br i1 %a, label %Cold, label %Hot, !prof !41
+Cold:           ; 1/1000 goes here
+  call void @cold()
+  call void @cold2()
+  call void @hot2()
+  call void @none1()
+  br label %exit
+Hot:            ; 999/1000 goes here
+  call void @hot2()
+  call void @hot3()
+  br i1 %a2, label %None1, label %None2, !prof !42
+None1:          ; half goes here
+  call void @none1()
+  call void @none2()
+  br label %exit
+None2:          ; half goes here
+  call void @none3()
+  br label %exit
+exit:
+  ret void
+}
+
+declare void @hot1() #1
+declare void @hot2() #1
+declare void @hot3() #1
+declare void @cold() #1
+declare void @cold2() #1
+declare void @none1() #1
+declare void @none2() #1
+declare void @none3() #1
+
+
+!41 = !{!"branch_weights", i32 1, i32 1000}
+!42 = !{!"branch_weights", i32 1, i32 1}
+
+
+
+!llvm.module.flags = !{!1}
+!20 = !{!"function_entry_count", i64 110}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 10}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}

Added: llvm/trunk/test/Transforms/FunctionImport/import_stats.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/import_stats.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/import_stats.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/import_stats.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; Test to check thin link importing stats
+
+; -stats requires asserts
+; REQUIRES: asserts
+
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/import_stats.ll -o %t2.bc
+
+; Test thin link stats with both new and old LTO
+; RUN: llvm-lto -thinlto-action=run -stats %t.bc %t2.bc \
+; RUN:		2>&1 | FileCheck %s --check-prefix=THINLINKSTATS
+; RUN: llvm-lto2 run -stats -o %t3 %t.bc %t2.bc \
+; RUN:          -r %t.bc,hot_function,plx \
+; RUN:          -r %t.bc,hot, \
+; RUN:          -r %t.bc,critical, \
+; RUN:          -r %t.bc,none, \
+; RUN:          -r %t2.bc,hot,plx \
+; RUN:          -r %t2.bc,critical,plx \
+; RUN:          -r %t2.bc,none,plx \
+; RUN:          -r %t2.bc,globalvar,plx \
+; RUN:          2>&1 | FileCheck %s --check-prefix=THINLINKSTATS
+
+; THINLINKSTATS-DAG: 1 function-import   - Number of global variables thin link decided to import
+; THINLINKSTATS-DAG: 1 function-import  - Number of critical functions thin link decided to import
+; THINLINKSTATS-DAG: 3 function-import  - Number of functions thin link decided to import
+; THINLINKSTATS-DAG: 1 function-import  - Number of hot functions thin link decided to import
+
+; ModuleID = 'import_stats.ll'
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This function has a high profile count, so entry block is hot.
+define void @hot_function(i1 %a) !prof !20 {
+entry:
+  call void @hot()
+  call void @critical()
+  br i1 %a, label %None1, label %None2, !prof !42
+None1:          ; half goes here
+  call void @none()
+  br label %exit
+None2:          ; half goes here
+  br label %exit
+exit:
+  ret void
+}
+
+declare void @hot()
+declare void @none()
+declare void @critical()
+
+!42 = !{!"branch_weights", i32 1, i32 1}
+
+!llvm.module.flags = !{!1}
+!20 = !{!"function_entry_count", i64 100, i64 696010031887058302}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 300}
+!5 = !{!"MaxCount", i64 100}
+!6 = !{!"MaxInternalCount", i64 100}
+!7 = !{!"MaxFunctionCount", i64 100}
+!8 = !{!"NumCounts", i64 4}
+!9 = !{!"NumFunctions", i64 1}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 4}

Added: llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/inlineasm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; Do setup work for all below tests: generate bitcode and combined index
+; RUN: opt -module-summary %s -o %t.bc
+; RUN: opt -module-summary %p/Inputs/inlineasm.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+
+; Attempt the import now, ensure below that file containing inline assembly
+; is not imported from. Otherwise we would need to promote its local variable
+; used in the inline assembly, which would not see the rename.
+; RUN: opt -function-import -summary-file %t3.thinlto.bc %t.bc -S 2>&1 | FileCheck %s
+
+define i32 @main() #0 {
+entry:
+  %f = alloca i64, align 8
+  call void @foo(i64* %f)
+  ret i32 0
+}
+
+; CHECK: declare void @foo(i64*)
+declare void @foo(i64*) #1

Added: llvm/trunk/test/Transforms/FunctionImport/not-prevailing.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionImport/not-prevailing.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/FunctionImport/not-prevailing.ll (added)
+++ llvm/trunk/test/Transforms/FunctionImport/not-prevailing.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -module-summary %s -o %t1.bc
+; RUN: opt -module-summary -o %t2.bc %S/Inputs/not-prevailing.ll
+; RUN: not llvm-lto2 run -o %t3.bc %t1.bc %t2.bc -r %t1.bc,bar,px \
+; RUN:     -r %t1.bc,foo,x -r %t2.bc,foo,x -save-temps 2>&1 | FileCheck %s
+
+; CHECK: Interposable and available_externally/linkonce_odr/weak_odr symbol
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define available_externally i32 @foo() {
+  ret i32 1
+}
+
+define i32 @bar() {
+  %1 = call i32 @foo()
+  ret i32 %1
+}

Added: llvm/trunk/test/Transforms/GCOVProfiling/function-numbering.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/function-numbering.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/function-numbering.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/function-numbering.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,123 @@
+; Test that GCOV instrumentation numbers functions correctly when some
+; functions aren't emitted.
+
+; Inject metadata to set the .gcno file location
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: echo '!14 = !{!"%/t/function-numbering.ll", !0}' > %t/1
+; RUN: cat %s %t/1 > %t/2
+
+; RUN: opt -insert-gcov-profiling -S < %t/2 | FileCheck --check-prefix GCDA %s
+; RUN: llvm-cov gcov -n -dump %t/function-numbering.gcno 2>&1 | FileCheck --check-prefix GCNO %s
+; RUNN: rm %t/function-numbering.gcno
+
+; RUN: opt -passes=insert-gcov-profiling -S < %t/2 | FileCheck --check-prefix GCDA %s
+; RUN: llvm-cov gcov -n -dump %t/function-numbering.gcno 2>&1 | FileCheck --check-prefix GCNO %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+; GCDA: @[[FOO:[0-9]+]] = private unnamed_addr constant [4 x i8] c"foo\00"
+; GCDA-NOT: @{{[0-9]+}} = private unnamed_addr constant .* c"bar\00"
+; GCDA: @[[BAZ:[0-9]+]] = private unnamed_addr constant [4 x i8] c"baz\00"
+; GCDA: @__llvm_internal_gcov_emit_function_args.0 = internal unnamed_addr constant
+; GCDA-SAME: { i32 0, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[FOO]]
+; GCDA-SAME: { i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[BAZ]]
+;
+; GCDA-LABEL: define internal void @__llvm_gcov_writeout() {{.*}} {
+; GCDA-NEXT:  entry:
+; GCDA-NEXT:    br label %[[FILE_LOOP_HEADER:.*]]
+;
+; GCDA:       [[FILE_LOOP_HEADER]]:
+; GCDA-NEXT:    %[[IV:.*]] = phi i32 [ 0, %entry ], [ %[[NEXT_IV:.*]], %[[FILE_LOOP_LATCH:.*]] ]
+; GCDA-NEXT:    %[[FILE_INFO:.*]] = getelementptr inbounds {{.*}}, {{.*}}* @__llvm_internal_gcov_emit_file_info, i32 0, i32 %[[IV]]
+; GCDA-NEXT:    %[[START_FILE_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 0
+; GCDA-NEXT:    %[[START_FILE_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[START_FILE_ARGS]], i32 0, i32 0
+; GCDA-NEXT:    %[[START_FILE_ARG_0:.*]] = load i8*, i8** %[[START_FILE_ARG_0_PTR]]
+; GCDA-NEXT:    %[[START_FILE_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[START_FILE_ARGS]], i32 0, i32 1
+; GCDA-NEXT:    %[[START_FILE_ARG_1:.*]] = load i8*, i8** %[[START_FILE_ARG_1_PTR]]
+; GCDA-NEXT:    %[[START_FILE_ARG_2_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[START_FILE_ARGS]], i32 0, i32 2
+; GCDA-NEXT:    %[[START_FILE_ARG_2:.*]] = load i32, i32* %[[START_FILE_ARG_2_PTR]]
+; GCDA-NEXT:    call void @llvm_gcda_start_file(i8* %[[START_FILE_ARG_0]], i8* %[[START_FILE_ARG_1]], i32 %[[START_FILE_ARG_2]])
+; GCDA-NEXT:    %[[NUM_COUNTERS_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 1
+; GCDA-NEXT:    %[[NUM_COUNTERS:.*]] = load i32, i32* %[[NUM_COUNTERS_PTR]]
+; GCDA-NEXT:    %[[EMIT_FUN_ARGS_ARRAY_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 2
+; GCDA-NEXT:    %[[EMIT_FUN_ARGS_ARRAY:.*]] = load {{.*}}*, {{.*}}** %[[EMIT_FUN_ARGS_ARRAY_PTR]]
+; GCDA-NEXT:    %[[EMIT_ARCS_ARGS_ARRAY_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 3
+; GCDA-NEXT:    %[[EMIT_ARCS_ARGS_ARRAY:.*]] = load {{.*}}*, {{.*}}** %[[EMIT_ARCS_ARGS_ARRAY_PTR]]
+; GCDA-NEXT:    %[[ENTER_COUNTER_LOOP_COND:.*]] = icmp slt i32 0, %[[NUM_COUNTERS]]
+; GCDA-NEXT:    br i1 %[[ENTER_COUNTER_LOOP_COND]], label %[[COUNTER_LOOP:.*]], label %[[FILE_LOOP_LATCH]]
+;
+; GCDA:       [[COUNTER_LOOP]]:
+; GCDA-NEXT:    %[[JV:.*]] = phi i32 [ 0, %[[FILE_LOOP_HEADER]] ], [ %[[NEXT_JV:.*]], %[[COUNTER_LOOP]] ]
+; GCDA-NEXT:    %[[EMIT_FUN_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS_ARRAY]], i32 %[[JV]]
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 0
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_0:.*]] = load i32, i32* %[[EMIT_FUN_ARG_0_PTR]]
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 1
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_1:.*]] = load i8*, i8** %[[EMIT_FUN_ARG_1_PTR]]
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_2_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 2
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_2:.*]] = load i32, i32* %[[EMIT_FUN_ARG_2_PTR]]
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_3_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 3
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_3:.*]] = load i8, i8* %[[EMIT_FUN_ARG_3_PTR]]
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_4_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 4
+; GCDA-NEXT:    %[[EMIT_FUN_ARG_4:.*]] = load i32, i32* %[[EMIT_FUN_ARG_4_PTR]]
+; GCDA-NEXT:    call void @llvm_gcda_emit_function(i32 %[[EMIT_FUN_ARG_0]],
+; GCDA-SAME:                                       i8* %[[EMIT_FUN_ARG_1]],
+; GCDA-SAME:                                       i32 %[[EMIT_FUN_ARG_2]],
+; GCDA-SAME:                                       i8 %[[EMIT_FUN_ARG_3]],
+; GCDA-SAME:                                       i32 %[[EMIT_FUN_ARG_4]])
+; GCDA-NEXT:    %[[EMIT_ARCS_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS_ARRAY]], i32 %[[JV]]
+; GCDA-NEXT:    %[[EMIT_ARCS_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS]], i32 0, i32 0
+; GCDA-NEXT:    %[[EMIT_ARCS_ARG_0:.*]] = load i32, i32* %[[EMIT_ARCS_ARG_0_PTR]]
+; GCDA-NEXT:    %[[EMIT_ARCS_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS]], i32 0, i32 1
+; GCDA-NEXT:    %[[EMIT_ARCS_ARG_1:.*]] = load i64*, i64** %[[EMIT_ARCS_ARG_1_PTR]]
+; GCDA-NEXT:    call void @llvm_gcda_emit_arcs(i32 %[[EMIT_ARCS_ARG_0]],
+; GCDA-SAME:                                   i64* %[[EMIT_ARCS_ARG_1]])
+; GCDA-NEXT:    %[[NEXT_JV]] = add i32 %[[JV]], 1
+; GCDA-NEXT:    %[[COUNTER_LOOP_COND:.*]] = icmp slt i32 %[[NEXT_JV]], %[[NUM_COUNTERS]]
+; GCDA-NEXT:    br i1 %[[COUNTER_LOOP_COND]], label %[[COUNTER_LOOP]], label %[[FILE_LOOP_LATCH]]
+;
+; GCDA:       [[FILE_LOOP_LATCH]]:
+; GCDA-NEXT:    call void @llvm_gcda_summary_info()
+; GCDA-NEXT:    call void @llvm_gcda_end_file()
+; GCDA-NEXT:    %[[NEXT_IV]] = add i32 %[[IV]], 1
+; GCDA-NEXT:    %[[FILE_LOOP_COND:.*]] = icmp slt i32 %[[NEXT_IV]], 1
+; GCDA-NEXT:    br i1 %[[FILE_LOOP_COND]], label %[[FILE_LOOP_HEADER]], label %[[EXIT:.*]]
+;
+; GCDA:       [[EXIT]]:
+; GCDA-NEXT:    ret void
+
+; GCNO: == foo (0) @
+; GCNO-NOT: == bar ({{[0-9]+}}) @
+; GCNO: == baz (1) @
+
+define void @foo() !dbg !4 {
+  ret void, !dbg !12
+}
+
+define void @bar() !dbg !7 {
+  ; This function is referenced by the debug info, but no lines have locations.
+  ret void
+}
+
+define void @baz() !dbg !8 {
+  ret void, !dbg !13
+}
+
+!llvm.gcov = !{!14}
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10}
+!llvm.ident = !{!11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.6.0 ", isOptimized: false, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+!1 = !DIFile(filename: ".../llvm/test/Transforms/GCOVProfiling/function-numbering.ll", directory: "")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!5 = !DIFile(filename: ".../llvm/test/Transforms/GCOVProfiling/function-numbering.ll", directory: "")
+!6 = !DISubroutineType(types: !2)
+!7 = distinct !DISubprogram(name: "bar", line: 2, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!8 = distinct !DISubprogram(name: "baz", line: 3, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 3, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!9 = !{i32 2, !"Dwarf Version", i32 2}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{!"clang version 3.6.0 "}
+!12 = !DILocation(line: 1, column: 13, scope: !4)
+!13 = !DILocation(line: 3, column: 13, scope: !8)

Added: llvm/trunk/test/Transforms/GCOVProfiling/global-ctor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/global-ctor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/global-ctor.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/global-ctor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: echo '!16 = !{!"%/t/global-ctor.ll", !0}' > %t/1
+; RUN: cat %s %t/1 > %t/2
+; RUN: opt -insert-gcov-profiling -disable-output < %t/2
+; RUN: not grep '_GLOBAL__sub_I_global-ctor' %t/global-ctor.gcno
+; RUN: rm %t/global-ctor.gcno
+
+; RUN: opt -passes=insert-gcov-profiling -disable-output < %t/2
+; RUN: not grep '_GLOBAL__sub_I_global-ctor' %t/global-ctor.gcno
+; RUN: rm %t/global-ctor.gcno
+
+ at x = global i32 0, align 4
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_global-ctor.ll, i8* null }]
+
+; Function Attrs: nounwind
+define internal void @__cxx_global_var_init() #0 section ".text.startup" !dbg !4 {
+entry:
+  br label %0
+
+; <label>:0                                       ; preds = %entry
+  %call = call i32 @_Z1fv(), !dbg !13
+  store i32 %call, i32* @x, align 4, !dbg !13
+  ret void, !dbg !13
+}
+
+declare i32 @_Z1fv() #1
+
+; Function Attrs: nounwind
+define internal void @_GLOBAL__sub_I_global-ctor.ll() #0 section ".text.startup" {
+entry:
+  br label %0
+
+; <label>:0                                       ; preds = %entry
+  call void @__cxx_global_var_init(), !dbg !14
+  ret void, !dbg !14
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { "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" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10, !11}
+!llvm.gcov = !{!16}
+!llvm.ident = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 (trunk 210217)", isOptimized: false, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
+!1 = !DIFile(filename: "<stdin>", directory: "/home/nlewycky")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "__cxx_global_var_init", line: 2, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 2, file: !5, scope: !6, type: !7, retainedNodes: !2)
+!5 = !DIFile(filename: "global-ctor.ll", directory: "/home/nlewycky")
+!6 = !DIFile(filename: "global-ctor.ll", directory: "/home/nlewycky")
+!7 = !DISubroutineType(types: !2)
+!8 = distinct !DISubprogram(name: "", linkageName: "_GLOBAL__sub_I_global-ctor.ll", isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagArtificial, isOptimized: false, unit: !0, file: !1, scope: !9, type: !7, retainedNodes: !2)
+!9 = !DIFile(filename: "<stdin>", directory: "/home/nlewycky")
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{!"clang version 3.5.0 (trunk 210217)"}
+!13 = !DILocation(line: 2, scope: !4)
+!14 = !DILocation(line: 0, scope: !15)
+!15 = !DILexicalBlockFile(discriminator: 0, file: !5, scope: !8)

Added: llvm/trunk/test/Transforms/GCOVProfiling/linezero.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/linezero.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/linezero.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/linezero.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,145 @@
+; RUN: rm -rf %t && mkdir -p %t
+
+; RUN: sed -e 's|PATTERN|%/t|g' %s | opt -insert-gcov-profiling -disable-output
+; RUN: rm %t/linezero.gcno
+
+; RUN: sed -e 's|PATTERN|%/t|g' %s | opt -passes=insert-gcov-profiling -disable-output
+; RUN: rm %t/linezero.gcno
+
+; This is a crash test.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.vector = type { i8 }
+
+; Function Attrs: nounwind
+define i32 @_Z4testv() #0 !dbg !15 {
+entry:
+  %retval = alloca i32, align 4
+  %__range = alloca %struct.vector*, align 8
+  %ref.tmp = alloca %struct.vector, align 1
+  %undef.agg.tmp = alloca %struct.vector, align 1
+  %__begin = alloca i8*, align 8
+  %__end = alloca i8*, align 8
+  %spec = alloca i8, align 1
+  call void @llvm.dbg.declare(metadata %struct.vector** %__range, metadata !27, metadata !DIExpression()), !dbg !30
+  br label %0
+
+; <label>:0                                       ; preds = %entry
+  call void @_Z13TagFieldSpecsv(), !dbg !31
+  store %struct.vector* %ref.tmp, %struct.vector** %__range, align 8, !dbg !31
+  call void @llvm.dbg.declare(metadata i8** %__begin, metadata !32, metadata !DIExpression()), !dbg !30
+  %1 = load %struct.vector*, %struct.vector** %__range, align 8, !dbg !31
+  %call = call i8* @_ZN6vector5beginEv(%struct.vector* %1), !dbg !31
+  store i8* %call, i8** %__begin, align 8, !dbg !31
+  call void @llvm.dbg.declare(metadata i8** %__end, metadata !33, metadata !DIExpression()), !dbg !30
+  %2 = load %struct.vector*, %struct.vector** %__range, align 8, !dbg !31
+  %call1 = call i8* @_ZN6vector3endEv(%struct.vector* %2), !dbg !31
+  store i8* %call1, i8** %__end, align 8, !dbg !31
+  br label %for.cond, !dbg !31
+
+for.cond:                                         ; preds = %for.inc, %0
+  %3 = load i8*, i8** %__begin, align 8, !dbg !34
+  %4 = load i8*, i8** %__end, align 8, !dbg !34
+  %cmp = icmp ne i8* %3, %4, !dbg !34
+  br i1 %cmp, label %for.body, label %for.end, !dbg !34
+
+for.body:                                         ; preds = %for.cond
+  call void @llvm.dbg.declare(metadata i8* %spec, metadata !37, metadata !DIExpression()), !dbg !31
+  %5 = load i8*, i8** %__begin, align 8, !dbg !38
+  %6 = load i8, i8* %5, align 1, !dbg !38
+  store i8 %6, i8* %spec, align 1, !dbg !38
+  br label %for.inc, !dbg !38
+
+for.inc:                                          ; preds = %for.body
+  %7 = load i8*, i8** %__begin, align 8, !dbg !40
+  %incdec.ptr = getelementptr inbounds i8, i8* %7, i32 1, !dbg !40
+  store i8* %incdec.ptr, i8** %__begin, align 8, !dbg !40
+  br label %for.cond, !dbg !40
+
+for.end:                                          ; preds = %for.cond
+  call void @llvm.trap(), !dbg !42
+  unreachable, !dbg !42
+
+return:                                           ; No predecessors!
+  %8 = load i32, i32* %retval, !dbg !44
+  ret i32 %8, !dbg !44
+}
+
+; Function Attrs: nounwind readnone
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+declare void @_Z13TagFieldSpecsv() #2
+
+declare i8* @_ZN6vector5beginEv(%struct.vector*) #2
+
+declare i8* @_ZN6vector3endEv(%struct.vector*) #2
+
+; Function Attrs: noreturn nounwind
+declare void @llvm.trap() #3
+
+; Function Attrs: nounwind
+define void @_Z2f1v() #0 !dbg !20 {
+entry:
+  br label %0
+
+; <label>:0                                       ; preds = %entry
+  ret void, !dbg !45
+}
+
+attributes #0 = { nounwind "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" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { "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" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { noreturn nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!23, !24}
+!llvm.gcov = !{!25}
+!llvm.ident = !{!26}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 (trunk 209871)", isOptimized: false, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !2)
+!1 = !DIFile(filename: "<stdin>", directory: "PATTERN")
+!2 = !{}
+!3 = !{!4}
+!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "vector", line: 21, size: 8, align: 8, file: !5, elements: !6, identifier: "_ZTS6vector")
+!5 = !DIFile(filename: "linezero.cc", directory: "PATTERN")
+!6 = !{!7, !13}
+!7 = !DISubprogram(name: "begin", linkageName: "_ZN6vector5beginEv", line: 25, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 25, file: !5, scope: !4, type: !8)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !12}
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: !11)
+!11 = !DIBasicType(tag: DW_TAG_base_type, name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer, baseType: !4)
+!13 = !DISubprogram(name: "end", linkageName: "_ZN6vector3endEv", line: 26, isLocal: false, isDefinition: false, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 26, file: !5, scope: !4, type: !8)
+!15 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", line: 50, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 50, file: !5, scope: !16, type: !17, retainedNodes: !2)
+!16 = !DIFile(filename: "linezero.cc", directory: "PATTERN")
+!17 = !DISubroutineType(types: !18)
+!18 = !{!19}
+!19 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!20 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", line: 54, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 54, file: !5, scope: !16, type: !21, retainedNodes: !2)
+!21 = !DISubroutineType(types: !22)
+!22 = !{null}
+!23 = !{i32 2, !"Dwarf Version", i32 4}
+!24 = !{i32 2, !"Debug Info Version", i32 3}
+!25 = !{!"PATTERN/linezero.o", !0}
+!26 = !{!"clang version 3.5.0 (trunk 209871)"}
+!27 = !DILocalVariable(name: "__range", flags: DIFlagArtificial, scope: !28, type: !29)
+!28 = distinct !DILexicalBlock(line: 51, column: 0, file: !5, scope: !15)
+!29 = !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: !4)
+!30 = !DILocation(line: 0, scope: !28)
+!31 = !DILocation(line: 51, scope: !28)
+!32 = !DILocalVariable(name: "__begin", flags: DIFlagArtificial, scope: !28, type: !10)
+!33 = !DILocalVariable(name: "__end", flags: DIFlagArtificial, scope: !28, type: !10)
+!34 = !DILocation(line: 51, scope: !35)
+!35 = distinct !DILexicalBlock(line: 51, column: 0, file: !5, scope: !36)
+!36 = distinct !DILexicalBlock(line: 51, column: 0, file: !5, scope: !28)
+!37 = !DILocalVariable(name: "spec", line: 51, scope: !28, file: !16, type: !11)
+!38 = !DILocation(line: 51, scope: !39)
+!39 = distinct !DILexicalBlock(line: 51, column: 0, file: !5, scope: !28)
+!40 = !DILocation(line: 51, scope: !41)
+!41 = distinct !DILexicalBlock(line: 51, column: 0, file: !5, scope: !28)
+!42 = !DILocation(line: 51, scope: !43)
+!43 = distinct !DILexicalBlock(line: 51, column: 0, file: !5, scope: !28)
+!44 = !DILocation(line: 52, scope: !15)
+!45 = !DILocation(line: 54, scope: !20)

Added: llvm/trunk/test/Transforms/GCOVProfiling/linkagename.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/linkagename.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/linkagename.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/linkagename.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: echo '!9 = !{!"%/t/linkagename.ll", !0}' > %t/1
+; RUN: cat %s %t/1 > %t/2
+; RUN: opt -insert-gcov-profiling -disable-output < %t/2
+; RUN: grep _Z3foov %t/linkagename.gcno
+; RUN: rm %t/linkagename.gcno
+
+; RUN: opt -passes=insert-gcov-profiling -disable-output < %t/2
+; RUN: grep _Z3foov %t/linkagename.gcno
+; RUN: rm %t/linkagename.gcno
+
+define void @_Z3foov() !dbg !5 {
+entry:
+  ret void, !dbg !8
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!10}
+!llvm.gcov = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.3 (trunk 177323)", isOptimized: false, emissionKind: FullDebug, file: !2, enums: !3, retainedTypes: !3, globals: !3, imports:  !3)
+!1 = !DIFile(filename: "hello.cc", directory: "/home/nlewycky")
+!2 = !DIFile(filename: "hello.cc", directory: "/home/nlewycky")
+!3 = !{}
+!5 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !1, type: !6, retainedNodes: !3)
+!6 = !DISubroutineType(types: !7)
+!7 = !{null}
+!8 = !DILocation(line: 1, scope: !5)
+
+
+!10 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/GCOVProfiling/modules.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/modules.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/modules.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/modules.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt -insert-gcov-profiling -o - < %s | llvm-dis | FileCheck -check-prefix=EMIT-ARCS %s
+; RUN: opt -passes=insert-gcov-profiling -o - < %s | llvm-dis | FileCheck -check-prefix=EMIT-ARCS %s
+
+; EMIT-ARCS-NOT: call void @llvm_gcda_start_file
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 2, splitDebugFilename: "my.dwo", emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2, dwoId: 43981)
+!1 = !DIFile(filename: "<stdin>", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/GCOVProfiling/return-block.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/return-block.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/return-block.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/return-block.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,84 @@
+; Inject metadata to set the .gcno file location
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: echo '!19 = !{!"%/t/return-block.ll", !0}' > %t/1
+; RUN: cat %s %t/1 > %t/2
+
+; By default, the return block is last.
+; RUN: opt -insert-gcov-profiling -disable-output %t/2
+; RUN: llvm-cov gcov -n -dump %t/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-LAST %s
+
+; But we can optionally emit it second, to match newer gcc versions.
+; RUN: opt -insert-gcov-profiling -gcov-exit-block-before-body -disable-output %t/2
+; RUN: llvm-cov gcov -n -dump %t/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-SECOND %s
+; RUN: rm  %t/return-block.gcno
+
+; By default, the return block is last.
+; RUN: opt -passes=insert-gcov-profiling -disable-output %t/2
+; RUN: llvm-cov gcov -n -dump %t/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-LAST %s
+
+; But we can optionally emit it second, to match newer gcc versions.
+; RUN: opt -passes=insert-gcov-profiling -gcov-exit-block-before-body -disable-output %t/2
+; RUN: llvm-cov gcov -n -dump %t/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-SECOND %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at A = common global i32 0, align 4, !dbg !9
+
+; Function Attrs: nounwind uwtable
+define void @test() #0 !dbg !4 {
+entry:
+  tail call void (...) @f() #2, !dbg !14
+  %0 = load i32, i32* @A, align 4, !dbg !15
+  %tobool = icmp eq i32 %0, 0, !dbg !15
+  br i1 %tobool, label %if.end, label %if.then, !dbg !15
+
+if.then:                                          ; preds = %entry
+  tail call void (...) @g() #2, !dbg !16
+  br label %if.end, !dbg !16
+
+if.end:                                           ; preds = %entry, %if.then
+  ret void, !dbg !18
+}
+
+declare void @f(...) #1
+
+declare void @g(...) #1
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+
+!llvm.gcov = !{!19}
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12}
+!llvm.ident = !{!13}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.6.0 (trunk 223182)", isOptimized: true, emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !2, globals: !8, imports: !2)
+!1 = !DIFile(filename: ".../llvm/test/Transforms/GCOVProfiling/return-block.ll", directory: "")
+!2 = !{}
+!4 = distinct !DISubprogram(name: "test", line: 5, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, scopeLine: 5, file: !1, scope: !5, type: !6, retainedNodes: !2)
+!5 = !DIFile(filename: ".../llvm/test/Transforms/GCOVProfiling/return-block.ll", directory: "")
+!6 = !DISubroutineType(types: !7)
+!7 = !{null}
+!8 = !{!9}
+!9 = !DIGlobalVariableExpression(var: !DIGlobalVariable(name: "A", line: 3, isLocal: false, isDefinition: true, scope: null, file: !5, type: !10), expr: !DIExpression())
+!10 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{!"clang version 3.6.0 (trunk 223182)"}
+!14 = !DILocation(line: 6, column: 3, scope: !4)
+!15 = !DILocation(line: 7, column: 7, scope: !4)
+!16 = !DILocation(line: 8, column: 5, scope: !17)
+!17 = distinct !DILexicalBlock(line: 7, column: 7, file: !1, scope: !4)
+!18 = !DILocation(line: 9, column: 1, scope: !4)
+
+; There should be no destination edges for the exit block.
+; CHECK: Block : 1 Counter : 0
+; RETURN-LAST:       Destination Edges
+; RETURN-SECOND-NOT: Destination Edges
+; CHECK: Block : 2 Counter : 0
+; CHECK: Block : 4 Counter : 0
+; RETURN-LAST-NOT: Destination Edges
+; RETURN-SECOND:   Destination Edges
+; CHECK-NOT: Block :

Added: llvm/trunk/test/Transforms/GCOVProfiling/three-element-mdnode.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/three-element-mdnode.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/three-element-mdnode.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/three-element-mdnode.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: echo '!10 = !{!"%/t/aaa.gcno", !"%/t/bbb.gcda", !0}' > %t/1
+; RUN: cat %s %t/1 > %t/2
+; RUN: opt -insert-gcov-profiling -S -o %t/3 < %t/2
+; RUN: grep _Z3foov %t/aaa.gcno
+; RUN: grep bbb.gcda %t/3
+; RUN: rm %t/aaa.gcno
+
+define void @_Z3foov() !dbg !5 {
+entry:
+  ret void, !dbg !8
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9}
+!llvm.gcov = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.3 (trunk 177323)", isOptimized: false, emissionKind: FullDebug, file: !2, enums: !3, retainedTypes: !3, globals: !3, imports:  !3)
+!1 = !DIFile(filename: "hello.cc", directory: "/home/nlewycky")
+!2 = !DIFile(filename: "hello.cc", directory: "/home/nlewycky")
+!3 = !{}
+!5 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", line: 1, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, scopeLine: 1, file: !1, scope: !1, type: !6, retainedNodes: !3)
+!6 = !DISubroutineType(types: !7)
+!7 = !{null}
+!8 = !DILocation(line: 1, scope: !5)
+
+
+!9 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/GCOVProfiling/version.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GCOVProfiling/version.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GCOVProfiling/version.ll (added)
+++ llvm/trunk/test/Transforms/GCOVProfiling/version.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: rm -rf %t && mkdir -p %t
+; RUN: echo '!9 = !{!"%/t/version.ll", !0}' > %t/1
+; RUN: cat %s %t/1 > %t/2
+; RUN: opt -insert-gcov-profiling -disable-output < %t/2
+; RUN: head -c8 %t/version.gcno | grep '^oncg.204'
+; RUN: rm %t/version.gcno
+; RUN: not opt -insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t/2
+; RUN: opt -insert-gcov-profiling -default-gcov-version=407* -disable-output < %t/2
+; RUN: head -c8 %t/version.gcno | grep '^oncg.704'
+; RUN: rm %t/version.gcno
+
+; RUN: opt -passes=insert-gcov-profiling -disable-output < %t/2
+; RUN: head -c8 %t/version.gcno | grep '^oncg.204'
+; RUN: rm %t/version.gcno
+; RUN: not opt -passes=insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t/2
+; RUN: opt -passes=insert-gcov-profiling -default-gcov-version=407* -disable-output < %t/2
+; RUN: head -c8 %t/version.gcno | grep '^oncg.704'
+; RUN: rm %t/version.gcno
+
+define void @test() !dbg !5 {
+  ret void, !dbg !8
+}
+
+!llvm.gcov = !{!9}
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.3 (trunk 176994)", isOptimized: false, emissionKind: FullDebug, file: !11, enums: !3, retainedTypes: !3, globals: !3)
+!2 = !DIFile(filename: "version", directory: "/usr/local/google/home/nlewycky")
+!3 = !{}
+!5 = distinct !DISubprogram(name: "test", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 1, file: !10, scope: !6, type: !7, retainedNodes: !3)
+!6 = !DIFile(filename: "<stdin>", directory: ".")
+!7 = !DISubroutineType(types: !{null})
+!8 = !DILocation(line: 1, scope: !5)
+;; !9 is added through the echo line at the top.
+!10 = !DIFile(filename: "<stdin>", directory: ".")
+!11 = !DIFile(filename: "version", directory: "/usr/local/google/home/nlewycky")
+!12 = !{i32 1, !"Debug Info Version", i32 3}

Added: llvm/trunk/test/Transforms/GVN/2007-07-25-DominatedLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-25-DominatedLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-25-DominatedLoop.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-25-DominatedLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,86 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+	%struct.PerlInterpreter = type { i8 }
+ at PL_sv_count = external global i32		; <i32*> [#uses=2]
+
+define void @perl_destruct(%struct.PerlInterpreter* %sv_interp) {
+entry:
+	br i1 false, label %cond_next25, label %cond_true16
+
+cond_true16:		; preds = %entry
+	ret void
+
+cond_next25:		; preds = %entry
+	br i1 false, label %cond_next33, label %cond_true32
+
+cond_true32:		; preds = %cond_next25
+	ret void
+
+cond_next33:		; preds = %cond_next25
+	br i1 false, label %cond_next61, label %cond_true.i46
+
+cond_true.i46:		; preds = %cond_next33
+	ret void
+
+cond_next61:		; preds = %cond_next33
+	br i1 false, label %cond_next69, label %cond_true66
+
+cond_true66:		; preds = %cond_next61
+	ret void
+
+cond_next69:		; preds = %cond_next61
+	br i1 false, label %Perl_safefree.exit52, label %cond_true.i50
+
+cond_true.i50:		; preds = %cond_next69
+	ret void
+
+Perl_safefree.exit52:		; preds = %cond_next69
+	br i1 false, label %cond_next80, label %cond_true77
+
+cond_true77:		; preds = %Perl_safefree.exit52
+	ret void
+
+cond_next80:		; preds = %Perl_safefree.exit52
+	br i1 false, label %Perl_safefree.exit56, label %cond_true.i54
+
+cond_true.i54:		; preds = %cond_next80
+	ret void
+
+Perl_safefree.exit56:		; preds = %cond_next80
+	br i1 false, label %Perl_safefree.exit60, label %cond_true.i58
+
+cond_true.i58:		; preds = %Perl_safefree.exit56
+	ret void
+
+Perl_safefree.exit60:		; preds = %Perl_safefree.exit56
+	br i1 false, label %Perl_safefree.exit64, label %cond_true.i62
+
+cond_true.i62:		; preds = %Perl_safefree.exit60
+	ret void
+
+Perl_safefree.exit64:		; preds = %Perl_safefree.exit60
+	br i1 false, label %Perl_safefree.exit68, label %cond_true.i66
+
+cond_true.i66:		; preds = %Perl_safefree.exit64
+	ret void
+
+Perl_safefree.exit68:		; preds = %Perl_safefree.exit64
+	br i1 false, label %cond_next150, label %cond_true23.i
+
+cond_true23.i:		; preds = %Perl_safefree.exit68
+	ret void
+
+cond_next150:		; preds = %Perl_safefree.exit68
+	%tmp16092 = load i32, i32* @PL_sv_count, align 4		; <i32> [#uses=0]
+	br label %cond_next165
+
+bb157:		; preds = %cond_next165
+	%tmp158 = load i32, i32* @PL_sv_count, align 4		; <i32> [#uses=0]
+	br label %cond_next165
+
+cond_next165:		; preds = %bb157, %cond_next150
+	br i1 false, label %bb171, label %bb157
+
+bb171:		; preds = %cond_next165
+	ret void
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+	%struct.INT2 = type { i32, i32 }
+ at blkshifts = external global %struct.INT2*		; <%struct.INT2**> [#uses=2]
+
+define i32 @xcompact() {
+entry:
+	store %struct.INT2* null, %struct.INT2** @blkshifts, align 4
+	br label %bb
+
+bb:		; preds = %bb, %entry
+	%tmp10 = load %struct.INT2*, %struct.INT2** @blkshifts, align 4		; <%struct.INT2*> [#uses=0]
+; CHECK-NOT:  %tmp10
+	br label %bb
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-25-Loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-25-Loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-25-Loop.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-25-Loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+	%struct.s_segment_inf = type { float, i32, i16, i16, float, float, i32, float, float }
+
+define void @print_arch(i8* %arch_file, i32 %route_type, i64 %det_routing_arch.0.0, i64 %det_routing_arch.0.1, i64 %det_routing_arch.0.2, i64 %det_routing_arch.0.3, i64 %det_routing_arch.0.4, %struct.s_segment_inf* %segment_inf, i64 %timing_inf.0.0, i64 %timing_inf.0.1, i64 %timing_inf.0.2, i64 %timing_inf.0.3, i64 %timing_inf.0.4, i32 %timing_inf.1) {
+entry:
+	br i1 false, label %bb278, label %bb344
+
+bb278:		; preds = %bb278, %entry
+	br i1 false, label %bb278, label %bb344
+
+bb344:		; preds = %bb278, %entry
+	%tmp38758 = load i16, i16* null, align 2		; <i16> [#uses=0]
+	ret void
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-25-NestedLoop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-25-NestedLoop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-25-NestedLoop.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-25-NestedLoop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+	%struct.TypHeader = type { i32, %struct.TypHeader**, [3 x i8], i8 }
+
+define %struct.TypHeader* @LtRec(%struct.TypHeader* %hdL, %struct.TypHeader* %hdR) {
+entry:
+	br i1 false, label %bb556.preheader, label %bb534.preheader
+
+bb534.preheader:		; preds = %entry
+	ret %struct.TypHeader* null
+
+bb556.preheader:		; preds = %entry
+	%tmp56119 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0		; <i32*> [#uses=1]
+	%tmp56220 = load i32, i32* %tmp56119		; <i32> [#uses=0]
+	br i1 false, label %bb.nph23, label %bb675.preheader
+
+bb.nph23:		; preds = %bb556.preheader
+	ret %struct.TypHeader* null
+
+bb656:		; preds = %bb675.outer, %bb656
+	%tmp678 = load i32, i32* %tmp677		; <i32> [#uses=0]
+	br i1 false, label %bb684, label %bb656
+
+bb684:		; preds = %bb675.outer, %bb656
+	br i1 false, label %bb924.preheader, label %bb675.outer
+
+bb675.outer:		; preds = %bb675.preheader, %bb684
+	%tmp67812 = load i32, i32* %tmp67711		; <i32> [#uses=0]
+	br i1 false, label %bb684, label %bb656
+
+bb675.preheader:		; preds = %bb556.preheader
+	%tmp67711 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0		; <i32*> [#uses=1]
+	%tmp677 = getelementptr %struct.TypHeader, %struct.TypHeader* %hdR, i32 0, i32 0		; <i32*> [#uses=1]
+	br label %bb675.outer
+
+bb924.preheader:		; preds = %bb684
+	ret %struct.TypHeader* null
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+	%struct.ggBRDF = type { i32 (...)** }
+	%struct.ggBox3 = type { %struct.ggPoint3, %struct.ggPoint3 }
+	%struct.ggMaterialRecord = type { %struct.ggPoint2, %struct.ggBox3, %struct.ggBox3, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggBRDF*, i32, i32, i32, i32 }
+	%struct.ggONB3 = type { %struct.ggPoint3, %struct.ggPoint3, %struct.ggPoint3 }
+	%struct.ggPoint2 = type { [2 x double] }
+	%struct.ggPoint3 = type { [3 x double] }
+	%struct.ggSpectrum = type { [8 x float] }
+	%struct.mrViewingHitRecord = type { double, %struct.ggPoint3, %struct.ggONB3, %struct.ggPoint2, double, %struct.ggSpectrum, %struct.ggSpectrum, i32, i32, i32, i32 }
+	%struct.mrXEllipticalCylinder = type { %struct.ggBRDF, float, float, float, float, float, float }
+
+define i32 @_ZNK21mrZEllipticalCylinder10viewingHitERK6ggRay3dddR18mrViewingHitRecordR16ggMaterialRecord(%struct.mrXEllipticalCylinder* %this, %struct.ggBox3* %ray, double %unnamed_arg, double %tmin, double %tmax, %struct.mrViewingHitRecord* %VHR, %struct.ggMaterialRecord* %unnamed_arg2) {
+entry:
+	%tmp80.i = getelementptr %struct.mrViewingHitRecord, %struct.mrViewingHitRecord* %VHR, i32 0, i32 1, i32 0, i32 0		; <double*> [#uses=1]
+	store double 0.000000e+00, double* %tmp80.i
+	br i1 false, label %return, label %cond_next.i
+
+cond_next.i:		; preds = %entry
+	br i1 false, label %return, label %cond_true
+
+cond_true:		; preds = %cond_next.i
+	%tmp3.i8 = getelementptr %struct.mrViewingHitRecord, %struct.mrViewingHitRecord* %VHR, i32 0, i32 1, i32 0, i32 0		; <double*> [#uses=1]
+	%tmp46 = load double, double* %tmp3.i8		; <double> [#uses=0]
+	ret i32 1
+
+return:		; preds = %cond_next.i, %entry
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+ at last = external global [65 x i32*]
+
+define i32 @NextRootMove(i32 %wtm, i32 %x, i32 %y, i32 %z) {
+entry:
+        %A = alloca i32*
+	%tmp17618 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4
+        store i32* %tmp17618, i32** %A
+; CHECK: entry:
+; CHECK-NEXT: alloca i32
+; CHECK-NEXT: %tmp17618 = load
+; CHECK-NOT: load
+; CHECK-NOT: phi
+	br label %cond_true116
+
+cond_true116:
+   %cmp = icmp eq i32 %x, %y
+	br i1 %cmp, label %cond_true128, label %cond_true145
+
+cond_true128:
+	%tmp17625 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4
+        store i32* %tmp17625, i32** %A
+   %cmp1 = icmp eq i32 %x, %z
+	br i1 %cmp1 , label %bb98.backedge, label %return.loopexit
+
+bb98.backedge:
+	br label %cond_true116
+
+cond_true145:
+	%tmp17631 = load i32*, i32** getelementptr ([65 x i32*], [65 x i32*]* @last, i32 0, i32 1), align 4
+        store i32* %tmp17631, i32** %A
+	br i1 false, label %bb98.backedge, label %return.loopexit
+
+return.loopexit:
+	br label %return
+
+return:
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-26-NonRedundant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-26-NonRedundant.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-26-NonRedundant.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-26-NonRedundant.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+ at bsLive = external global i32		; <i32*> [#uses=2]
+
+define i32 @bsR(i32 %n) {
+entry:
+	br i1 false, label %cond_next, label %bb19
+
+cond_next:		; preds = %entry
+	store i32 0, i32* @bsLive, align 4
+	br label %bb19
+
+bb19:		; preds = %cond_next, %entry
+	%tmp29 = load i32, i32* @bsLive, align 4		; <i32> [#uses=0]
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-26-PhiErasure.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-26-PhiErasure.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-26-PhiErasure.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-26-PhiErasure.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+	%struct..0anon = type { i32 }
+	%struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
+	%struct.__sFILEX = type opaque
+	%struct.__sbuf = type { i8*, i32 }
+	%struct.rtx_def = type { i16, i8, i8, [1 x %struct..0anon] }
+ at n_spills = external global i32		; <i32*> [#uses=2]
+
+define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) {
+cond_next2835.1:		; preds = %cond_next2861
+	%tmp2922 = load i32, i32* @n_spills, align 4		; <i32> [#uses=0]
+	br label %bb2928
+
+bb2928:		; preds = %cond_next2835.1, %cond_next2943
+	br i1 false, label %cond_next2943, label %cond_true2935
+
+cond_true2935:		; preds = %bb2928
+	br label %cond_next2943
+
+cond_next2943:		; preds = %cond_true2935, %bb2928
+	br i1 false, label %bb2982.preheader, label %bb2928
+
+bb2982.preheader:		; preds = %cond_next2943
+	%tmp298316 = load i32, i32* @n_spills, align 4		; <i32> [#uses=0]
+	ret i32 %tmp298316
+
+}
+
+; CHECK: define i32 @reload(%struct.rtx_def* %first, i32 %global, %struct.FILE* %dumpfile) {
+; CHECK-NEXT: cond_next2835.1:
+; CHECK-NEXT:   br label %bb2928
+; CHECK: bb2928:
+; CHECK-NEXT:   br i1 false, label %bb2928.cond_next2943_crit_edge, label %cond_true2935
+; CHECK: bb2928.cond_next2943_crit_edge:
+; CHECK-NEXT:   br label %cond_next2943
+; CHECK: cond_true2935:
+; CHECK-NEXT:   br label %cond_next2943
+; CHECK: cond_next2943:
+; CHECK-NEXT:   br i1 false, label %bb2982.preheader, label %bb2928
+; CHECK: bb2982.preheader:
+; CHECK-NEXT:   %tmp298316 = load i32, i32* @n_spills, align 4
+; CHECK-NEXT:   ret i32 %tmp298316
+; CHECK-NEXT: }

Added: llvm/trunk/test/Transforms/GVN/2007-07-30-PredIDom.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-30-PredIDom.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-30-PredIDom.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-30-PredIDom.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,274 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+	%"struct.Block::$_16" = type { i32 }
+	%struct.Exp = type { %struct.Exp_*, i32, i32, i32, %struct.Exp*, %struct.Exp*, %"struct.Exp::$_10", %"struct.Block::$_16", %"struct.Exp::$_12" }
+	%"struct.Exp::$_10" = type { %struct.Exp* }
+	%"struct.Exp::$_12" = type { %struct.Exp** }
+	%struct.Exp_ = type { i32, i32, i32, i32, %struct.Id* }
+	%struct.Id = type { i8*, i32, i32, i32, %"struct.Id::$_13" }
+	%"struct.Id::$_13" = type { double }
+
+define i8* @_ZN3Exp8toStringEj(%struct.Exp* %this, i32 %nextpc) {
+entry:
+	switch i32 0, label %bb970 [
+		 i32 1, label %bb
+		 i32 2, label %bb39
+		 i32 3, label %bb195
+		 i32 4, label %bb270
+		 i32 5, label %bb418
+		 i32 6, label %bb633
+		 i32 7, label %bb810
+		 i32 8, label %bb882
+		 i32 9, label %bb925
+	]
+
+bb:		; preds = %entry
+	store i8* null, i8** null
+	br label %return
+
+bb39:		; preds = %entry
+	br i1 false, label %cond_true, label %cond_false132
+
+cond_true:		; preds = %bb39
+	br i1 false, label %cond_true73, label %cond_false
+
+cond_true73:		; preds = %cond_true
+	br i1 false, label %cond_true108, label %cond_next
+
+cond_true108:		; preds = %cond_true73
+	br label %cond_next
+
+cond_next:		; preds = %cond_true108, %cond_true73
+	br label %cond_next131
+
+cond_false:		; preds = %cond_true
+	br label %cond_next131
+
+cond_next131:		; preds = %cond_false, %cond_next
+	br label %cond_next141
+
+cond_false132:		; preds = %bb39
+	br label %cond_next141
+
+cond_next141:		; preds = %cond_false132, %cond_next131
+	br i1 false, label %cond_true169, label %cond_false175
+
+cond_true169:		; preds = %cond_next141
+	br label %cond_next181
+
+cond_false175:		; preds = %cond_next141
+	br label %cond_next181
+
+cond_next181:		; preds = %cond_false175, %cond_true169
+	br i1 false, label %cond_true189, label %cond_next191
+
+cond_true189:		; preds = %cond_next181
+	br label %cond_next191
+
+cond_next191:		; preds = %cond_true189, %cond_next181
+	store i8* null, i8** null
+	br label %return
+
+bb195:		; preds = %entry
+	br i1 false, label %cond_true248, label %cond_false250
+
+cond_true248:		; preds = %bb195
+	br label %cond_next252
+
+cond_false250:		; preds = %bb195
+	br label %cond_next252
+
+cond_next252:		; preds = %cond_false250, %cond_true248
+	br i1 false, label %cond_true265, label %cond_next267
+
+cond_true265:		; preds = %cond_next252
+	br label %cond_next267
+
+cond_next267:		; preds = %cond_true265, %cond_next252
+	store i8* null, i8** null
+	br label %return
+
+bb270:		; preds = %entry
+	br i1 false, label %cond_true338, label %cond_false340
+
+cond_true338:		; preds = %bb270
+	br label %cond_next342
+
+cond_false340:		; preds = %bb270
+	br label %cond_next342
+
+cond_next342:		; preds = %cond_false340, %cond_true338
+	br i1 false, label %cond_true362, label %cond_false364
+
+cond_true362:		; preds = %cond_next342
+	br label %cond_next366
+
+cond_false364:		; preds = %cond_next342
+	br label %cond_next366
+
+cond_next366:		; preds = %cond_false364, %cond_true362
+	br i1 false, label %cond_true393, label %cond_next395
+
+cond_true393:		; preds = %cond_next366
+	br label %cond_next395
+
+cond_next395:		; preds = %cond_true393, %cond_next366
+	br i1 false, label %cond_true406, label %cond_next408
+
+cond_true406:		; preds = %cond_next395
+	br label %cond_next408
+
+cond_next408:		; preds = %cond_true406, %cond_next395
+	br i1 false, label %cond_true413, label %cond_next415
+
+cond_true413:		; preds = %cond_next408
+	br label %cond_next415
+
+cond_next415:		; preds = %cond_true413, %cond_next408
+	store i8* null, i8** null
+	br label %return
+
+bb418:		; preds = %entry
+	br i1 false, label %cond_true512, label %cond_false514
+
+cond_true512:		; preds = %bb418
+	br label %cond_next516
+
+cond_false514:		; preds = %bb418
+	br label %cond_next516
+
+cond_next516:		; preds = %cond_false514, %cond_true512
+	br i1 false, label %cond_true536, label %cond_false538
+
+cond_true536:		; preds = %cond_next516
+	br label %cond_next540
+
+cond_false538:		; preds = %cond_next516
+	br label %cond_next540
+
+cond_next540:		; preds = %cond_false538, %cond_true536
+	br i1 false, label %cond_true560, label %cond_false562
+
+cond_true560:		; preds = %cond_next540
+	br label %cond_next564
+
+cond_false562:		; preds = %cond_next540
+	br label %cond_next564
+
+cond_next564:		; preds = %cond_false562, %cond_true560
+	br i1 false, label %cond_true597, label %cond_next599
+
+cond_true597:		; preds = %cond_next564
+	br label %cond_next599
+
+cond_next599:		; preds = %cond_true597, %cond_next564
+	br i1 false, label %cond_true614, label %cond_next616
+
+cond_true614:		; preds = %cond_next599
+	br label %cond_next616
+
+cond_next616:		; preds = %cond_true614, %cond_next599
+	br i1 false, label %cond_true621, label %cond_next623
+
+cond_true621:		; preds = %cond_next616
+	br label %cond_next623
+
+cond_next623:		; preds = %cond_true621, %cond_next616
+	br i1 false, label %cond_true628, label %cond_next630
+
+cond_true628:		; preds = %cond_next623
+	br label %cond_next630
+
+cond_next630:		; preds = %cond_true628, %cond_next623
+	store i8* null, i8** null
+	br label %return
+
+bb633:		; preds = %entry
+	br i1 false, label %cond_true667, label %cond_next669
+
+cond_true667:		; preds = %bb633
+	br label %cond_next669
+
+cond_next669:		; preds = %cond_true667, %bb633
+	br i1 false, label %cond_true678, label %cond_next791
+
+cond_true678:		; preds = %cond_next669
+	br label %bb735
+
+bb679:		; preds = %bb735
+	br i1 false, label %cond_true729, label %cond_next731
+
+cond_true729:		; preds = %bb679
+	br label %cond_next731
+
+cond_next731:		; preds = %cond_true729, %bb679
+	br label %bb735
+
+bb735:		; preds = %cond_next731, %cond_true678
+	br i1 false, label %bb679, label %bb743
+
+bb743:		; preds = %bb735
+	br i1 false, label %cond_true788, label %cond_next790
+
+cond_true788:		; preds = %bb743
+	br label %cond_next790
+
+cond_next790:		; preds = %cond_true788, %bb743
+	br label %cond_next791
+
+cond_next791:		; preds = %cond_next790, %cond_next669
+	br i1 false, label %cond_true805, label %cond_next807
+
+cond_true805:		; preds = %cond_next791
+	br label %cond_next807
+
+cond_next807:		; preds = %cond_true805, %cond_next791
+	store i8* null, i8** null
+	br label %return
+
+bb810:		; preds = %entry
+	br i1 false, label %cond_true870, label %cond_next872
+
+cond_true870:		; preds = %bb810
+	br label %cond_next872
+
+cond_next872:		; preds = %cond_true870, %bb810
+	br i1 false, label %cond_true877, label %cond_next879
+
+cond_true877:		; preds = %cond_next872
+	br label %cond_next879
+
+cond_next879:		; preds = %cond_true877, %cond_next872
+	store i8* null, i8** null
+	br label %return
+
+bb882:		; preds = %entry
+	br i1 false, label %cond_true920, label %cond_next922
+
+cond_true920:		; preds = %bb882
+	br label %cond_next922
+
+cond_next922:		; preds = %cond_true920, %bb882
+	store i8* null, i8** null
+	br label %return
+
+bb925:		; preds = %entry
+	br i1 false, label %cond_true965, label %cond_next967
+
+cond_true965:		; preds = %bb925
+	br label %cond_next967
+
+cond_next967:		; preds = %cond_true965, %bb925
+	store i8* null, i8** null
+	br label %return
+
+bb970:		; preds = %entry
+	unreachable
+		; No predecessors!
+	store i8* null, i8** null
+	br label %return
+
+return:		; preds = %0, %cond_next967, %cond_next922, %cond_next879, %cond_next807, %cond_next630, %cond_next415, %cond_next267, %cond_next191, %bb
+	%retval980 = load i8*, i8** null		; <i8*> [#uses=1]
+	ret i8* %retval980
+}

Added: llvm/trunk/test/Transforms/GVN/2007-07-31-NoDomInherit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-31-NoDomInherit.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-31-NoDomInherit.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-31-NoDomInherit.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,314 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+	%struct.anon = type { i32 (i32, i32, i32)*, i32, i32, [3 x i32], i8*, i8*, i8* }
+ at debug = external constant i32		; <i32*> [#uses=0]
+ at counters = external constant i32		; <i32*> [#uses=1]
+ at trialx = external global [17 x i32]		; <[17 x i32]*> [#uses=1]
+ at dummy1 = external global [7 x i32]		; <[7 x i32]*> [#uses=0]
+ at dummy2 = external global [4 x i32]		; <[4 x i32]*> [#uses=0]
+ at unacceptable = external global i32		; <i32*> [#uses=0]
+ at isa = external global [13 x %struct.anon]		; <[13 x %struct.anon]*> [#uses=3]
+ at .str = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str1 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str2 = external constant [1 x i8]		; <[1 x i8]*> [#uses=0]
+ at .str3 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str4 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str5 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str6 = external constant [2 x i8]		; <[2 x i8]*> [#uses=0]
+ at .str7 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str8 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str9 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str10 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str11 = external constant [2 x i8]		; <[2 x i8]*> [#uses=0]
+ at .str12 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str13 = external constant [2 x i8]		; <[2 x i8]*> [#uses=0]
+ at .str14 = external constant [5 x i8]		; <[5 x i8]*> [#uses=0]
+ at .str15 = external constant [5 x i8]		; <[5 x i8]*> [#uses=0]
+ at .str16 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str17 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str18 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str19 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str20 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str21 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str22 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str23 = external constant [5 x i8]		; <[5 x i8]*> [#uses=0]
+ at .str24 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str25 = external constant [6 x i8]		; <[6 x i8]*> [#uses=0]
+ at .str26 = external constant [5 x i8]		; <[5 x i8]*> [#uses=0]
+ at .str27 = external constant [6 x i8]		; <[6 x i8]*> [#uses=0]
+ at r = external global [17 x i32]		; <[17 x i32]*> [#uses=0]
+ at .str28 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str29 = external constant [5 x i8]		; <[5 x i8]*> [#uses=0]
+ at pgm = external global [5 x { i32, [3 x i32] }]		; <[5 x { i32, [3 x i32] }]*> [#uses=4]
+ at .str30 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str31 = external constant [13 x i8]		; <[13 x i8]*> [#uses=0]
+ at .str32 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str33 = external constant [4 x i8]		; <[4 x i8]*> [#uses=0]
+ at .str34 = external constant [20 x i8]		; <[20 x i8]*> [#uses=0]
+ at numi = external global i32		; <i32*> [#uses=7]
+ at .str35 = external constant [10 x i8]		; <[10 x i8]*> [#uses=0]
+ at counter = external global [5 x i32]		; <[5 x i32]*> [#uses=2]
+ at itrialx.2510 = external global i32		; <i32*> [#uses=0]
+ at .str36 = external constant [43 x i8]		; <[43 x i8]*> [#uses=0]
+ at .str37 = external constant [42 x i8]		; <[42 x i8]*> [#uses=0]
+ at corr_result = external global i32		; <i32*> [#uses=0]
+ at .str38 = external constant [3 x i8]		; <[3 x i8]*> [#uses=0]
+ at .str39 = external constant [5 x i8]		; <[5 x i8]*> [#uses=0]
+ at .str40 = external constant [47 x i8]		; <[47 x i8]*> [#uses=0]
+ at correct_result = external global [17 x i32]		; <[17 x i32]*> [#uses=1]
+ at .str41 = external constant [46 x i8]		; <[46 x i8]*> [#uses=0]
+ at .str42 = external constant [32 x i8]		; <[32 x i8]*> [#uses=0]
+ at .str43 = external constant [44 x i8]		; <[44 x i8]*> [#uses=1]
+ at .str44 = external constant [21 x i8]		; <[21 x i8]*> [#uses=1]
+ at .str45 = external constant [12 x i8]		; <[12 x i8]*> [#uses=1]
+ at .str46 = external constant [5 x i8]		; <[5 x i8]*> [#uses=1]
+ at .str47 = external constant [12 x i8]		; <[12 x i8]*> [#uses=1]
+
+declare i32 @neg(i32, i32, i32)
+
+declare i32 @Not(i32, i32, i32)
+
+declare i32 @pop(i32, i32, i32)
+
+declare i32 @nlz(i32, i32, i32)
+
+declare i32 @rev(i32, i32, i32)
+
+declare i32 @add(i32, i32, i32)
+
+declare i32 @sub(i32, i32, i32)
+
+declare i32 @mul(i32, i32, i32)
+
+declare i32 @divide(i32, i32, i32)
+
+declare i32 @divu(i32, i32, i32)
+
+declare i32 @And(i32, i32, i32)
+
+declare i32 @Or(i32, i32, i32)
+
+declare i32 @Xor(i32, i32, i32)
+
+declare i32 @rotl(i32, i32, i32)
+
+declare i32 @shl(i32, i32, i32)
+
+declare i32 @shr(i32, i32, i32)
+
+declare i32 @shrs(i32, i32, i32)
+
+declare i32 @cmpeq(i32, i32, i32)
+
+declare i32 @cmplt(i32, i32, i32)
+
+declare i32 @cmpltu(i32, i32, i32)
+
+declare i32 @seleq(i32, i32, i32)
+
+declare i32 @sellt(i32, i32, i32)
+
+declare i32 @selle(i32, i32, i32)
+
+declare void @print_expr(i32)
+
+declare i32 @printf(i8*, ...)
+
+declare i32 @putchar(i32)
+
+declare void @print_pgm()
+
+declare void @simulate_one_instruction(i32)
+
+declare i32 @check(i32)
+
+declare i32 @puts(i8*)
+
+declare void @fix_operands(i32)
+
+declare void @abort()
+
+declare i32 @increment()
+
+declare i32 @search()
+
+define i32 @main(i32 %argc, i8** %argv) {
+entry:
+	%argc_addr = alloca i32		; <i32*> [#uses=1]
+	%argv_addr = alloca i8**		; <i8***> [#uses=1]
+	%retval = alloca i32, align 4		; <i32*> [#uses=2]
+	%tmp = alloca i32, align 4		; <i32*> [#uses=2]
+	%i = alloca i32, align 4		; <i32*> [#uses=21]
+	%num_sol = alloca i32, align 4		; <i32*> [#uses=4]
+	%total = alloca i32, align 4		; <i32*> [#uses=4]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	store i32 %argc, i32* %argc_addr
+	store i8** %argv, i8*** %argv_addr
+	store i32 0, i32* %num_sol
+	store i32 1, i32* @numi
+	br label %bb91
+
+bb:		; preds = %cond_next97
+	%tmp1 = load i32, i32* @numi		; <i32> [#uses=1]
+	%tmp2 = getelementptr [44 x i8], [44 x i8]* @.str43, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp3 = call i32 (i8*, ...) @printf( i8* %tmp2, i32 %tmp1 )		; <i32> [#uses=0]
+	store i32 0, i32* %i
+	br label %bb13
+
+bb4:		; preds = %bb13
+	%tmp5 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp6 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp7 = getelementptr [17 x i32], [17 x i32]* @trialx, i32 0, i32 %tmp6		; <i32*> [#uses=1]
+	%tmp8 = load i32, i32* %tmp7		; <i32> [#uses=1]
+	%tmp9 = call i32 @userfun( i32 %tmp8 )		; <i32> [#uses=1]
+	%tmp10 = getelementptr [17 x i32], [17 x i32]* @correct_result, i32 0, i32 %tmp5		; <i32*> [#uses=1]
+	store i32 %tmp9, i32* %tmp10
+	%tmp11 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp12 = add i32 %tmp11, 1		; <i32> [#uses=1]
+	store i32 %tmp12, i32* %i
+	br label %bb13
+
+bb13:		; preds = %bb4, %bb
+	%tmp14 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp15 = icmp sle i32 %tmp14, 16		; <i1> [#uses=1]
+	%tmp1516 = zext i1 %tmp15 to i32		; <i32> [#uses=1]
+	%toBool = icmp ne i32 %tmp1516, 0		; <i1> [#uses=1]
+	br i1 %toBool, label %bb4, label %bb17
+
+bb17:		; preds = %bb13
+	store i32 0, i32* %i
+	br label %bb49
+
+bb18:		; preds = %bb49
+	%tmp19 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp20 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp19		; <{ i32, [3 x i32] }*> [#uses=1]
+	%tmp21 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp20, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 0, i32* %tmp21
+	%tmp22 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp23 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0		; <%struct.anon*> [#uses=1]
+	%tmp24 = getelementptr %struct.anon, %struct.anon* %tmp23, i32 0, i32 3		; <[3 x i32]*> [#uses=1]
+	%tmp25 = getelementptr [3 x i32], [3 x i32]* %tmp24, i32 0, i32 0		; <i32*> [#uses=1]
+	%tmp26 = load i32, i32* %tmp25		; <i32> [#uses=1]
+	%tmp27 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp22		; <{ i32, [3 x i32] }*> [#uses=1]
+	%tmp28 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp27, i32 0, i32 1		; <[3 x i32]*> [#uses=1]
+	%tmp29 = getelementptr [3 x i32], [3 x i32]* %tmp28, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 %tmp26, i32* %tmp29
+	%tmp30 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp31 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0		; <%struct.anon*> [#uses=1]
+	%tmp32 = getelementptr %struct.anon, %struct.anon* %tmp31, i32 0, i32 3		; <[3 x i32]*> [#uses=1]
+	%tmp33 = getelementptr [3 x i32], [3 x i32]* %tmp32, i32 0, i32 1		; <i32*> [#uses=1]
+	%tmp34 = load i32, i32* %tmp33		; <i32> [#uses=1]
+	%tmp35 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp30		; <{ i32, [3 x i32] }*> [#uses=1]
+	%tmp36 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp35, i32 0, i32 1		; <[3 x i32]*> [#uses=1]
+	%tmp37 = getelementptr [3 x i32], [3 x i32]* %tmp36, i32 0, i32 1		; <i32*> [#uses=1]
+	store i32 %tmp34, i32* %tmp37
+	%tmp38 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp39 = getelementptr [13 x %struct.anon], [13 x %struct.anon]* @isa, i32 0, i32 0		; <%struct.anon*> [#uses=1]
+	%tmp40 = getelementptr %struct.anon, %struct.anon* %tmp39, i32 0, i32 3		; <[3 x i32]*> [#uses=1]
+	%tmp41 = getelementptr [3 x i32], [3 x i32]* %tmp40, i32 0, i32 2		; <i32*> [#uses=1]
+	%tmp42 = load i32, i32* %tmp41		; <i32> [#uses=1]
+	%tmp43 = getelementptr [5 x { i32, [3 x i32] }], [5 x { i32, [3 x i32] }]* @pgm, i32 0, i32 %tmp38		; <{ i32, [3 x i32] }*> [#uses=1]
+	%tmp44 = getelementptr { i32, [3 x i32] }, { i32, [3 x i32] }* %tmp43, i32 0, i32 1		; <[3 x i32]*> [#uses=1]
+	%tmp45 = getelementptr [3 x i32], [3 x i32]* %tmp44, i32 0, i32 2		; <i32*> [#uses=1]
+	store i32 %tmp42, i32* %tmp45
+	%tmp46 = load i32, i32* %i		; <i32> [#uses=1]
+	call void @fix_operands( i32 %tmp46 )
+	%tmp47 = load i32, i32* %i		; <i32> [#uses=1]
+; CHECK: %tmp47 = phi i32 [ %tmp48, %bb18 ], [ 0, %bb17 ]
+	%tmp48 = add i32 %tmp47, 1		; <i32> [#uses=1]
+	store i32 %tmp48, i32* %i
+	br label %bb49
+
+bb49:		; preds = %bb18, %bb17
+	%tmp50 = load i32, i32* @numi		; <i32> [#uses=1]
+	%tmp51 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp52 = icmp slt i32 %tmp51, %tmp50		; <i1> [#uses=1]
+	%tmp5253 = zext i1 %tmp52 to i32		; <i32> [#uses=1]
+	%toBool54 = icmp ne i32 %tmp5253, 0		; <i1> [#uses=1]
+	br i1 %toBool54, label %bb18, label %bb55
+
+bb55:		; preds = %bb49
+	%tmp56 = call i32 @search( )		; <i32> [#uses=1]
+	store i32 %tmp56, i32* %num_sol
+	%tmp57 = getelementptr [21 x i8], [21 x i8]* @.str44, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp58 = load i32, i32* %num_sol		; <i32> [#uses=1]
+	%tmp59 = call i32 (i8*, ...) @printf( i8* %tmp57, i32 %tmp58 )		; <i32> [#uses=0]
+	%tmp60 = load i32, i32* @counters		; <i32> [#uses=1]
+	%tmp61 = icmp ne i32 %tmp60, 0		; <i1> [#uses=1]
+	%tmp6162 = zext i1 %tmp61 to i32		; <i32> [#uses=1]
+	%toBool63 = icmp ne i32 %tmp6162, 0		; <i1> [#uses=1]
+	br i1 %toBool63, label %cond_true, label %cond_next
+
+cond_true:		; preds = %bb55
+	store i32 0, i32* %total
+	%tmp64 = getelementptr [12 x i8], [12 x i8]* @.str45, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp65 = call i32 (i8*, ...) @printf( i8* %tmp64 )		; <i32> [#uses=0]
+	store i32 0, i32* %i
+	br label %bb79
+
+bb66:		; preds = %bb79
+	%tmp67 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp68 = getelementptr [5 x i32], [5 x i32]* @counter, i32 0, i32 %tmp67		; <i32*> [#uses=1]
+	%tmp69 = load i32, i32* %tmp68		; <i32> [#uses=1]
+	%tmp70 = getelementptr [5 x i8], [5 x i8]* @.str46, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp71 = call i32 (i8*, ...) @printf( i8* %tmp70, i32 %tmp69 )		; <i32> [#uses=0]
+	%tmp72 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp73 = getelementptr [5 x i32], [5 x i32]* @counter, i32 0, i32 %tmp72		; <i32*> [#uses=1]
+	%tmp74 = load i32, i32* %tmp73		; <i32> [#uses=1]
+	%tmp75 = load i32, i32* %total		; <i32> [#uses=1]
+	%tmp76 = add i32 %tmp74, %tmp75		; <i32> [#uses=1]
+	store i32 %tmp76, i32* %total
+	%tmp77 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp78 = add i32 %tmp77, 1		; <i32> [#uses=1]
+	store i32 %tmp78, i32* %i
+	br label %bb79
+
+bb79:		; preds = %bb66, %cond_true
+	%tmp80 = load i32, i32* @numi		; <i32> [#uses=1]
+	%tmp81 = load i32, i32* %i		; <i32> [#uses=1]
+	%tmp82 = icmp slt i32 %tmp81, %tmp80		; <i1> [#uses=1]
+	%tmp8283 = zext i1 %tmp82 to i32		; <i32> [#uses=1]
+	%toBool84 = icmp ne i32 %tmp8283, 0		; <i1> [#uses=1]
+	br i1 %toBool84, label %bb66, label %bb85
+
+bb85:		; preds = %bb79
+	%tmp86 = getelementptr [12 x i8], [12 x i8]* @.str47, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp87 = load i32, i32* %total		; <i32> [#uses=1]
+	%tmp88 = call i32 (i8*, ...) @printf( i8* %tmp86, i32 %tmp87 )		; <i32> [#uses=0]
+	br label %cond_next
+
+cond_next:		; preds = %bb85, %bb55
+	%tmp89 = load i32, i32* @numi		; <i32> [#uses=1]
+	%tmp90 = add i32 %tmp89, 1		; <i32> [#uses=1]
+	store i32 %tmp90, i32* @numi
+	br label %bb91
+
+bb91:		; preds = %cond_next, %entry
+	%tmp92 = load i32, i32* @numi		; <i32> [#uses=1]
+	%tmp93 = icmp sgt i32 %tmp92, 5		; <i1> [#uses=1]
+	%tmp9394 = zext i1 %tmp93 to i32		; <i32> [#uses=1]
+	%toBool95 = icmp ne i32 %tmp9394, 0		; <i1> [#uses=1]
+	br i1 %toBool95, label %cond_true96, label %cond_next97
+
+cond_true96:		; preds = %bb91
+	br label %bb102
+
+cond_next97:		; preds = %bb91
+	%tmp98 = load i32, i32* %num_sol		; <i32> [#uses=1]
+	%tmp99 = icmp eq i32 %tmp98, 0		; <i1> [#uses=1]
+	%tmp99100 = zext i1 %tmp99 to i32		; <i32> [#uses=1]
+	%toBool101 = icmp ne i32 %tmp99100, 0		; <i1> [#uses=1]
+	br i1 %toBool101, label %bb, label %bb102
+
+bb102:		; preds = %cond_next97, %cond_true96
+	store i32 0, i32* %tmp
+	%tmp103 = load i32, i32* %tmp		; <i32> [#uses=1]
+	store i32 %tmp103, i32* %retval
+	br label %return
+
+return:		; preds = %bb102
+	%retval104 = load i32, i32* %retval		; <i32> [#uses=1]
+	ret i32 %retval104
+}
+
+declare i32 @userfun(i32)

Added: llvm/trunk/test/Transforms/GVN/2007-07-31-RedundantPhi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2007-07-31-RedundantPhi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2007-07-31-RedundantPhi.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2007-07-31-RedundantPhi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+ at img_width = external global i16		; <i16*> [#uses=2]
+
+define i32 @smpUMHEXBipredIntegerPelBlockMotionSearch(i16* %cur_pic, i16 signext  %ref, i32 %list, i32 %pic_pix_x, i32 %pic_pix_y, i32 %blocktype, i16 signext  %pred_mv_x1, i16 signext  %pred_mv_y1, i16 signext  %pred_mv_x2, i16 signext  %pred_mv_y2, i16* %mv_x, i16* %mv_y, i16* %s_mv_x, i16* %s_mv_y, i32 %search_range, i32 %min_mcost, i32 %lambda_factor) {
+cond_next143:		; preds = %entry
+	store i16 0, i16* @img_width, align 2
+	br i1 false, label %cond_next449, label %cond_false434
+
+cond_false434:		; preds = %cond_true415
+	br label %cond_next449
+
+cond_next449:		; preds = %cond_false434, %cond_true415
+	br i1 false, label %cond_next698, label %cond_false470
+
+cond_false470:		; preds = %cond_next449
+	br label %cond_next698
+
+cond_next698:		; preds = %cond_true492
+	%tmp701 = load i16, i16* @img_width, align 2		; <i16> [#uses=0]
+; CHECK-NOT: %tmp701 =
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/GVN/2008-02-12-UndefLoad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-02-12-UndefLoad.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-02-12-UndefLoad.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-02-12-UndefLoad.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+; PR1996
+
+%struct.anon = type { i32, i8, i8, i8, i8 }
+
+define i32 @a() {
+entry:
+        %c = alloca %struct.anon                ; <%struct.anon*> [#uses=2]
+        %tmp = getelementptr %struct.anon, %struct.anon* %c, i32 0, i32 0             ; <i32*> [#uses=1]
+        %tmp1 = getelementptr i32, i32* %tmp, i32 1          ; <i32*> [#uses=2]
+        %tmp2 = load i32, i32* %tmp1, align 4                ; <i32> [#uses=1]
+; CHECK-NOT: load
+        %tmp3 = or i32 %tmp2, 11                ; <i32> [#uses=1]
+        %tmp4 = and i32 %tmp3, -21              ; <i32> [#uses=1]
+        store i32 %tmp4, i32* %tmp1, align 4
+        %call = call i32 (...) @x( %struct.anon* %c )          ; <i32> [#uses=0]
+        ret i32 undef
+}
+
+
+declare i32 @x(...)

Added: llvm/trunk/test/Transforms/GVN/2008-02-13-NewPHI.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-02-13-NewPHI.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-02-13-NewPHI.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-02-13-NewPHI.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -gvn
+; PR2032
+
+define i32 @sscal(i32 %n, double %sa1, float* %sx, i32 %incx) {
+entry:
+	%sx_addr = alloca float*		; <float**> [#uses=3]
+	store float* %sx, float** %sx_addr, align 4
+	br label %bb33
+
+bb:		; preds = %bb33
+	%tmp27 = load float*, float** %sx_addr, align 4		; <float*> [#uses=1]
+	store float 0.000000e+00, float* %tmp27, align 4
+	store float* null, float** %sx_addr, align 4
+	br label %bb33
+
+bb33:		; preds = %bb, %entry
+	br i1 false, label %bb, label %return
+
+return:		; preds = %bb33
+	%retval59 = load i32, i32* null, align 4		; <i32> [#uses=1]
+	ret i32 %retval59
+}

Added: llvm/trunk/test/Transforms/GVN/2008-07-02-Unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-07-02-Unreachable.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-07-02-Unreachable.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-07-02-Unreachable.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+; PR2503
+
+ at g_3 = external global i8		; <i8*> [#uses=2]
+
+define i8 @func_1(i32 %x, i32 %y) nounwind  {
+entry:
+  %A = alloca i8
+    %cmp = icmp eq i32 %x, %y
+	br i1 %cmp, label %ifelse, label %ifthen
+
+ifthen:		; preds = %entry
+	br label %ifend
+
+ifelse:		; preds = %entry
+	%tmp3 = load i8, i8* @g_3		; <i8> [#uses=0]
+        store i8 %tmp3, i8* %A
+	br label %afterfor
+
+forcond:		; preds = %forinc
+	br i1 false, label %afterfor, label %forbody
+
+forbody:		; preds = %forcond
+	br label %forinc
+
+forinc:		; preds = %forbody
+	br label %forcond
+
+afterfor:		; preds = %forcond, %forcond.thread
+	%tmp10 = load i8, i8* @g_3		; <i8> [#uses=0]
+	ret i8 %tmp10
+; CHECK: ret i8 %tmp3
+
+ifend:		; preds = %afterfor, %ifthen
+	ret i8 0
+}

Added: llvm/trunk/test/Transforms/GVN/2008-12-09-SelfRemove.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-12-09-SelfRemove.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-12-09-SelfRemove.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-12-09-SelfRemove.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.5"
+	%struct.anon = type { i8*, i32 }
+	%struct.d_print_info = type { i32, i8*, i32, i32, %struct.d_print_template*, %struct.d_print_mod*, i32 }
+	%struct.d_print_mod = type { %struct.d_print_mod*, %struct.demangle_component*, i32, %struct.d_print_template* }
+	%struct.d_print_template = type { %struct.d_print_template*, %struct.demangle_component* }
+	%struct.demangle_component = type { i32, { %struct.anon } }
+
+define void @d_print_mod_list(%struct.d_print_info* %dpi, %struct.d_print_mod* %mods, i32 %suffix) nounwind {
+entry:
+	%0 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1		; <i8**> [#uses=1]
+	br i1 false, label %return, label %bb
+
+bb:		; preds = %entry
+	%1 = load i8*, i8** %0, align 4		; <i8*> [#uses=0]
+	%2 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1		; <i8**> [#uses=0]
+	br label %bb21
+
+bb21:		; preds = %bb21, %bb
+	br label %bb21
+
+return:		; preds = %entry
+	ret void
+}
+
+; CHECK: define void @d_print_mod_list(%struct.d_print_info* %dpi, %struct.d_print_mod* %mods, i32 %suffix) #0 {
+; CHECK: entry:
+; CHECK:   %0 = getelementptr %struct.d_print_info, %struct.d_print_info* %dpi, i32 0, i32 1
+; CHECK:   br i1 false, label %return, label %bb
+; CHECK: bb:
+; CHECK:   br label %bb21
+; CHECK: bb21:
+; CHECK:   br label %bb21
+; CHECK: return:
+; CHECK:   ret void
+; CHECK: }

Added: llvm/trunk/test/Transforms/GVN/2008-12-12-RLE-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-12-12-RLE-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-12-12-RLE-Crash.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-12-12-RLE-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,35 @@
+; RUN: opt < %s -gvn | llvm-dis
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+define i32 @main(i32 %argc, i8** %argv) nounwind {
+entry:
+	br label %bb84
+
+bb41:		; preds = %bb82
+	%tmp = load i8, i8* %opt.0, align 1		; <i8> [#uses=0]
+	%tmp1 = getelementptr i8, i8* %opt.0, i32 1		; <i8*> [#uses=2]
+	switch i32 0, label %bb81 [
+		i32 102, label %bb82
+		i32 110, label %bb79
+		i32 118, label %bb80
+	]
+
+bb79:		; preds = %bb41
+	br label %bb82
+
+bb80:		; preds = %bb41
+	ret i32 0
+
+bb81:		; preds = %bb41
+	ret i32 1
+
+bb82:		; preds = %bb84, %bb79, %bb41
+	%opt.0 = phi i8* [ %tmp3, %bb84 ], [ %tmp1, %bb79 ], [ %tmp1, %bb41 ]		; <i8*> [#uses=3]
+	%tmp2 = load i8, i8* %opt.0, align 1		; <i8> [#uses=0]
+	br i1 false, label %bb84, label %bb41
+
+bb84:		; preds = %bb82, %entry
+	%tmp3 = getelementptr i8, i8* null, i32 1		; <i8*> [#uses=1]
+	br label %bb82
+}

Added: llvm/trunk/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -gvn | llvm-dis
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+ at sort_value = external global [256 x i32], align 32		; <[256 x i32]*> [#uses=2]
+
+define i32 @Quiesce(i32 %alpha, i32 %beta, i32 %wtm, i32 %ply) nounwind {
+entry:
+	br label %bb22
+
+bb22:		; preds = %bb23, %bb22, %entry
+	br i1 false, label %bb23, label %bb22
+
+bb23:		; preds = %bb23, %bb22
+	%sortv.233 = phi i32* [ getelementptr ([256 x i32], [256 x i32]* @sort_value, i32 0, i32 0), %bb22 ], [ %sortv.2, %bb23 ]		; <i32*> [#uses=1]
+	%0 = load i32, i32* %sortv.233, align 4		; <i32> [#uses=0]
+	%sortv.2 = getelementptr [256 x i32], [256 x i32]* @sort_value, i32 0, i32 0		; <i32*> [#uses=1]
+	br i1 false, label %bb23, label %bb22
+}

Added: llvm/trunk/test/Transforms/GVN/2008-12-15-CacheVisited.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2008-12-15-CacheVisited.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2008-12-15-CacheVisited.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2008-12-15-CacheVisited.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -gvn | llvm-dis
+; Cached results must be added to and verified against the visited sets.
+; PR3217
+
+define fastcc void @gen_field_die(i32* %decl) nounwind {
+entry:
+	br i1 false, label %bb203, label %bb202
+
+bb202:		; preds = %entry
+	unreachable
+
+bb203:		; preds = %entry
+	%tmp = getelementptr i32, i32* %decl, i32 1		; <i32*> [#uses=1]
+	%tmp1 = load i32, i32* %tmp, align 4		; <i32> [#uses=0]
+	br i1 false, label %bb207, label %bb204
+
+bb204:		; preds = %bb203
+	%tmp2 = getelementptr i32, i32* %decl, i32 1		; <i32*> [#uses=1]
+	br label %bb208
+
+bb207:		; preds = %bb203
+	br label %bb208
+
+bb208:		; preds = %bb207, %bb204
+	%iftmp.1374.0.in = phi i32* [ null, %bb207 ], [ %tmp2, %bb204 ]		; <i32*> [#uses=1]
+	%iftmp.1374.0 = load i32, i32* %iftmp.1374.0.in		; <i32> [#uses=0]
+	unreachable
+}

Added: llvm/trunk/test/Transforms/GVN/2009-01-21-SortInvalidation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2009-01-21-SortInvalidation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2009-01-21-SortInvalidation.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2009-01-21-SortInvalidation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt < %s -gvn | llvm-dis
+; PR3358
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+	%struct.re_pattern_buffer = type { i8*, i64, i64, i64, i8*, i8*, i64, i8 }
+	%struct.re_registers = type { i32, i32*, i32* }
+
+define fastcc i32 @byte_re_match_2_internal(%struct.re_pattern_buffer* nocapture %bufp, i8* %string1, i32 %size1, i8* %string2, i32 %size2, i32 %pos, %struct.re_registers* %regs, i32 %stop) nounwind {
+entry:
+	br label %bb159
+
+succeed_label:		; preds = %bb159
+	ret i32 0
+
+bb159:		; preds = %bb664, %bb554, %bb159, %bb159, %bb159, %entry
+	%d.0 = phi i8* [ null, %entry ], [ %d.0, %bb159 ], [ %d.0, %bb554 ], [ %d.0, %bb159 ], [ %d.0, %bb159 ], [ %d.12, %bb664 ]		; <i8*> [#uses=5]
+	switch i32 0, label %bb661 [
+		i32 0, label %bb159
+		i32 1, label %succeed_label
+		i32 13, label %bb159
+		i32 14, label %bb159
+		i32 16, label %bb411
+		i32 24, label %bb622
+		i32 28, label %bb543
+	]
+
+bb411:		; preds = %bb411, %bb159
+	br label %bb411
+
+bb543:		; preds = %bb159
+	br i1 false, label %bb549, label %bb550
+
+bb549:		; preds = %bb543
+	br label %bb554
+
+bb550:		; preds = %bb543
+	br i1 false, label %bb554, label %bb552
+
+bb552:		; preds = %bb550
+	%0 = load i8, i8* %d.0, align 8		; <i8> [#uses=0]
+	br label %bb554
+
+bb554:		; preds = %bb552, %bb550, %bb549
+	br i1 false, label %bb159, label %bb661
+
+bb622:		; preds = %bb622, %bb159
+	br label %bb622
+
+bb661:		; preds = %bb554, %bb159
+	%d.12 = select i1 false, i8* null, i8* null		; <i8*> [#uses=1]
+	br label %bb664
+
+bb664:		; preds = %bb664, %bb661
+	br i1 false, label %bb159, label %bb664
+}

Added: llvm/trunk/test/Transforms/GVN/2009-01-22-SortInvalidation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2009-01-22-SortInvalidation.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2009-01-22-SortInvalidation.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2009-01-22-SortInvalidation.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,100 @@
+; RUN: opt < %s -gvn | llvm-dis
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+	%struct..4sPragmaType = type { i8*, i32 }
+	%struct.AggInfo = type { i8, i8, i32, %struct.ExprList*, i32, %struct.AggInfo_col*, i32, i32, i32, %struct.AggInfo_func*, i32, i32 }
+	%struct.AggInfo_col = type { %struct.Table*, i32, i32, i32, i32, %struct.Expr* }
+	%struct.AggInfo_func = type { %struct.Expr*, %struct.FuncDef*, i32, i32 }
+	%struct.AuxData = type { i8*, void (i8*)* }
+	%struct.Bitvec = type { i32, i32, i32, { [125 x i32] } }
+	%struct.BtCursor = type { %struct.Btree*, %struct.BtShared*, %struct.BtCursor*, %struct.BtCursor*, i32 (i8*, i32, i8*, i32, i8*)*, i8*, i32, %struct.MemPage*, i32, %struct.CellInfo, i8, i8, i8*, i64, i32, i8, i32* }
+	%struct.BtLock = type { %struct.Btree*, i32, i8, %struct.BtLock* }
+	%struct.BtShared = type { %struct.Pager*, %struct.sqlite3*, %struct.BtCursor*, %struct.MemPage*, i8, i8, i8, i8, i8, i8, i8, i8, i32, i16, i16, i32, i32, i32, i32, i8, i32, i8*, void (i8*)*, %struct.sqlite3_mutex*, %struct.BusyHandler, i32, %struct.BtShared*, %struct.BtLock*, %struct.Btree* }
+	%struct.Btree = type { %struct.sqlite3*, %struct.BtShared*, i8, i8, i8, i32, %struct.Btree*, %struct.Btree* }
+	%struct.BtreeMutexArray = type { i32, [11 x %struct.Btree*] }
+	%struct.BusyHandler = type { i32 (i8*, i32)*, i8*, i32 }
+	%struct.CellInfo = type { i8*, i64, i32, i32, i16, i16, i16, i16 }
+	%struct.CollSeq = type { i8*, i8, i8, i8*, i32 (i8*, i32, i8*, i32, i8*)*, void (i8*)* }
+	%struct.Column = type { i8*, %struct.Expr*, i8*, i8*, i8, i8, i8, i8 }
+	%struct.Context = type { i64, i32, %struct.Fifo }
+	%struct.CountCtx = type { i64 }
+	%struct.Cursor = type { %struct.BtCursor*, i32, i64, i64, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i64, %struct.Btree*, i32, i8*, i64, i8*, %struct.KeyInfo*, i32, i64, %struct.sqlite3_vtab_cursor*, %struct.sqlite3_module*, i32, i32, i32*, i32*, i8* }
+	%struct.Db = type { i8*, %struct.Btree*, i8, i8, i8*, void (i8*)*, %struct.Schema* }
+	%struct.Expr = type { i8, i8, i16, %struct.CollSeq*, %struct.Expr*, %struct.Expr*, %struct.ExprList*, %struct..4sPragmaType, %struct..4sPragmaType, i32, i32, %struct.AggInfo*, i32, i32, %struct.Select*, %struct.Table*, i32 }
+	%struct.ExprList = type { i32, i32, i32, %struct.ExprList_item* }
+	%struct.ExprList_item = type { %struct.Expr*, i8*, i8, i8, i8 }
+	%struct.FKey = type { %struct.Table*, %struct.FKey*, i8*, %struct.FKey*, i32, %struct.sColMap*, i8, i8, i8, i8 }
+	%struct.Fifo = type { i32, %struct.FifoPage*, %struct.FifoPage* }
+	%struct.FifoPage = type { i32, i32, i32, %struct.FifoPage*, [1 x i64] }
+	%struct.FuncDef = type { i16, i8, i8, i8, i8*, %struct.FuncDef*, void (%struct.sqlite3_context*, i32, %struct.Mem**)*, void (%struct.sqlite3_context*, i32, %struct.Mem**)*, void (%struct.sqlite3_context*)*, [1 x i8] }
+	%struct.Hash = type { i8, i8, i32, i32, %struct.HashElem*, %struct._ht* }
+	%struct.HashElem = type { %struct.HashElem*, %struct.HashElem*, i8*, i8*, i32 }
+	%struct.IdList = type { %struct..4sPragmaType*, i32, i32 }
+	%struct.Index = type { i8*, i32, i32*, i32*, %struct.Table*, i32, i8, i8, i8*, %struct.Index*, %struct.Schema*, i8*, i8** }
+	%struct.KeyInfo = type { %struct.sqlite3*, i8, i8, i8, i32, i8*, [1 x %struct.CollSeq*] }
+	%struct.Mem = type { %struct.CountCtx, double, %struct.sqlite3*, i8*, i32, i16, i8, i8, void (i8*)* }
+	%struct.MemPage = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i16, i16, i16, i16, i16, i16, [5 x %struct._OvflCell], %struct.BtShared*, i8*, %struct.PgHdr*, i32, %struct.MemPage* }
+	%struct.Module = type { %struct.sqlite3_module*, i8*, i8*, void (i8*)* }
+	%struct.Op = type { i8, i8, i8, i8, i32, i32, i32, { i32 } }
+	%struct.Pager = type { %struct.sqlite3_vfs*, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, %struct.Bitvec*, %struct.Bitvec*, i8*, i8*, i8*, i8*, %struct.sqlite3_file*, %struct.sqlite3_file*, %struct.sqlite3_file*, %struct.BusyHandler*, %struct.PagerLruList, %struct.PgHdr*, %struct.PgHdr*, %struct.PgHdr*, i64, i64, i64, i64, i64, i32, void (%struct.PgHdr*, i32)*, void (%struct.PgHdr*, i32)*, i32, %struct.PgHdr**, i8*, [16 x i8] }
+	%struct.PagerLruLink = type { %struct.PgHdr*, %struct.PgHdr* }
+	%struct.PagerLruList = type { %struct.PgHdr*, %struct.PgHdr*, %struct.PgHdr* }
+	%struct.Parse = type { %struct.sqlite3*, i32, i8*, %struct.Vdbe*, i8, i8, i8, i8, i8, i8, i8, [8 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [12 x i32], i32, %struct.TableLock*, i32, i32, i32, i32, i32, %struct.Expr**, i8, %struct..4sPragmaType, %struct..4sPragmaType, %struct..4sPragmaType, i8*, i8*, %struct.Table*, %struct.Trigger*, %struct.TriggerStack*, i8*, %struct..4sPragmaType, i8, %struct.Table*, i32 }
+	%struct.PgHdr = type { %struct.Pager*, i32, %struct.PgHdr*, %struct.PgHdr*, %struct.PagerLruLink, %struct.PgHdr*, i8, i8, i8, i8, i8, i16, %struct.PgHdr*, %struct.PgHdr*, i8* }
+	%struct.Schema = type { i32, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Table*, i8, i8, i16, i32, %struct.sqlite3* }
+	%struct.Select = type { %struct.ExprList*, i8, i8, i8, i8, i8, i8, i8, %struct.SrcList*, %struct.Expr*, %struct.ExprList*, %struct.Expr*, %struct.ExprList*, %struct.Select*, %struct.Select*, %struct.Select*, %struct.Expr*, %struct.Expr*, i32, i32, [3 x i32] }
+	%struct.SrcList = type { i16, i16, [1 x %struct.SrcList_item] }
+	%struct.SrcList_item = type { i8*, i8*, i8*, %struct.Table*, %struct.Select*, i8, i8, i32, %struct.Expr*, %struct.IdList*, i64 }
+	%struct.Table = type { i8*, i32, %struct.Column*, i32, %struct.Index*, i32, %struct.Select*, i32, %struct.Trigger*, %struct.FKey*, i8*, %struct.Expr*, i32, i8, i8, i8, i8, i8, i8, i8, %struct.Module*, %struct.sqlite3_vtab*, i32, i8**, %struct.Schema* }
+	%struct.TableLock = type { i32, i32, i8, i8* }
+	%struct.Trigger = type { i8*, i8*, i8, i8, %struct.Expr*, %struct.IdList*, %struct..4sPragmaType, %struct.Schema*, %struct.Schema*, %struct.TriggerStep*, %struct.Trigger* }
+	%struct.TriggerStack = type { %struct.Table*, i32, i32, i32, i32, i32, i32, %struct.Trigger*, %struct.TriggerStack* }
+	%struct.TriggerStep = type { i32, i32, %struct.Trigger*, %struct.Select*, %struct..4sPragmaType, %struct.Expr*, %struct.ExprList*, %struct.IdList*, %struct.TriggerStep*, %struct.TriggerStep* }
+	%struct.Vdbe = type { %struct.sqlite3*, %struct.Vdbe*, %struct.Vdbe*, i32, i32, %struct.Op*, i32, i32, i32*, %struct.Mem**, %struct.Mem*, i32, %struct.Cursor**, i32, %struct.Mem*, i8**, i32, i32, i32, %struct.Mem*, i32, i32, %struct.Fifo, i32, i32, %struct.Context*, i32, i32, i32, i32, i32, [25 x i32], i32, i32, i8**, i8*, %struct.Mem*, i8, i8, i8, i8, i8, i8, i32, i64, i32, %struct.BtreeMutexArray, i32, i8*, i32 }
+	%struct.VdbeFunc = type { %struct.FuncDef*, i32, [1 x %struct.AuxData] }
+	%struct._OvflCell = type { i8*, i16 }
+	%struct._ht = type { i32, %struct.HashElem* }
+	%struct.anon = type { double }
+	%struct.sColMap = type { i32, i8* }
+	%struct.sqlite3 = type { %struct.sqlite3_vfs*, i32, %struct.Db*, i32, i32, i32, i32, i8, i8, i8, i8, i32, %struct.CollSeq*, i64, i64, i32, i32, i32, %struct.sqlite3_mutex*, %struct.sqlite3InitInfo, i32, i8**, %struct.Vdbe*, i32, void (i8*, i8*)*, i8*, void (i8*, i8*, i64)*, i8*, i8*, i32 (i8*)*, i8*, void (i8*)*, i8*, void (i8*, i32, i8*, i8*, i64)*, void (i8*, %struct.sqlite3*, i32, i8*)*, void (i8*, %struct.sqlite3*, i32, i8*)*, i8*, %struct.Mem*, i8*, i8*, %struct.anon, i32 (i8*, i32, i8*, i8*, i8*, i8*)*, i8*, i32 (i8*)*, i8*, i32, %struct.Hash, %struct.Table*, %struct.sqlite3_vtab**, i32, %struct.Hash, %struct.Hash, %struct.BusyHandler, i32, [2 x %struct.Db], i8 }
+	%struct.sqlite3InitInfo = type { i32, i32, i8 }
+	%struct.sqlite3_context = type { %struct.FuncDef*, %struct.VdbeFunc*, %struct.Mem, %struct.Mem*, i32, %struct.CollSeq* }
+	%struct.sqlite3_file = type { %struct.sqlite3_io_methods* }
+	%struct.sqlite3_index_constraint = type { i32, i8, i8, i32 }
+	%struct.sqlite3_index_constraint_usage = type { i32, i8 }
+	%struct.sqlite3_index_info = type { i32, %struct.sqlite3_index_constraint*, i32, %struct.sqlite3_index_constraint_usage*, %struct.sqlite3_index_constraint_usage*, i32, i8*, i32, i32, double }
+	%struct.sqlite3_io_methods = type { i32, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*, i8*, i32, i64)*, i32 (%struct.sqlite3_file*, i8*, i32, i64)*, i32 (%struct.sqlite3_file*, i64)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*, i64*)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*, i32)*, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*, i32, i8*)*, i32 (%struct.sqlite3_file*)*, i32 (%struct.sqlite3_file*)* }
+	%struct.sqlite3_module = type { i32, i32 (%struct.sqlite3*, i8*, i32, i8**, %struct.sqlite3_vtab**, i8**)*, i32 (%struct.sqlite3*, i8*, i32, i8**, %struct.sqlite3_vtab**, i8**)*, i32 (%struct.sqlite3_vtab*, %struct.sqlite3_index_info*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*, %struct.sqlite3_vtab_cursor**)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*, i32, i8*, i32, %struct.Mem**)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*)*, i32 (%struct.sqlite3_vtab_cursor*, %struct.sqlite3_context*, i32)*, i32 (%struct.sqlite3_vtab_cursor*, i64*)*, i32 (%struct.sqlite3_vtab*, i32, %struct.Mem**, i64*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*)*, i32 (%struct.sqlite3_vtab*, i32, i8*, void (%struct.sqlite3_context*, i32, %struct.Mem**)**, i8**)*, i32 (%struct.sqlite3_vtab*, i8*)* }
+	%struct.sqlite3_mutex = type opaque
+	%struct.sqlite3_vfs = type { i32, i32, i32, %struct.sqlite3_vfs*, i8*, i8*, i32 (%struct.sqlite3_vfs*, i8*, %struct.sqlite3_file*, i32, i32*)*, i32 (%struct.sqlite3_vfs*, i8*, i32)*, i32 (%struct.sqlite3_vfs*, i8*, i32)*, i32 (%struct.sqlite3_vfs*, i32, i8*)*, i32 (%struct.sqlite3_vfs*, i8*, i32, i8*)*, i8* (%struct.sqlite3_vfs*, i8*)*, void (%struct.sqlite3_vfs*, i32, i8*)*, i8* (%struct.sqlite3_vfs*, i8*, i8*)*, void (%struct.sqlite3_vfs*, i8*)*, i32 (%struct.sqlite3_vfs*, i32, i8*)*, i32 (%struct.sqlite3_vfs*, i32)*, i32 (%struct.sqlite3_vfs*, double*)* }
+	%struct.sqlite3_vtab = type { %struct.sqlite3_module*, i32, i8* }
+	%struct.sqlite3_vtab_cursor = type { %struct.sqlite3_vtab* }
+
+define fastcc void @sqlite3Insert(%struct.Parse* %pParse, %struct.SrcList* %pTabList, %struct.ExprList* %pList, %struct.Select* %pSelect, %struct.IdList* %pColumn, i32 %onError) nounwind {
+entry:
+	br i1 false, label %bb54, label %bb69.loopexit
+
+bb54:		; preds = %entry
+	br label %bb69.loopexit
+
+bb59:		; preds = %bb63.preheader
+	%0 = load %struct..4sPragmaType*, %struct..4sPragmaType** %3, align 4		; <%struct..4sPragmaType*> [#uses=0]
+	br label %bb65
+
+bb65:		; preds = %bb63.preheader, %bb59
+	%1 = load %struct..4sPragmaType*, %struct..4sPragmaType** %4, align 4		; <%struct..4sPragmaType*> [#uses=0]
+	br i1 false, label %bb67, label %bb63.preheader
+
+bb67:		; preds = %bb65
+	%2 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0		; <%struct..4sPragmaType**> [#uses=0]
+	unreachable
+
+bb69.loopexit:		; preds = %bb54, %entry
+	%3 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0		; <%struct..4sPragmaType**> [#uses=1]
+	%4 = getelementptr %struct.IdList, %struct.IdList* %pColumn, i32 0, i32 0		; <%struct..4sPragmaType**> [#uses=1]
+	br label %bb63.preheader
+
+bb63.preheader:		; preds = %bb69.loopexit, %bb65
+	br i1 false, label %bb59, label %bb65
+}

Added: llvm/trunk/test/Transforms/GVN/2009-03-10-PREOnVoid.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2009-03-10-PREOnVoid.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2009-03-10-PREOnVoid.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2009-03-10-PREOnVoid.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,110 @@
+; RUN: opt < %s -gvn -disable-output
+; PR3775
+
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+	%llvm.dbg.anchor.type = type { i32, i32 }
+	%"struct.__gnu_cxx::hash<void*>" = type <{ i8 }>
+	%struct.__sched_param = type { i32 }
+	%struct._pthread_descr_struct = type opaque
+	%struct.pthread_attr_t = type { i32, i32, %struct.__sched_param, i32, i32, i32, i32, i8*, i32 }
+	%struct.pthread_mutex_t = type { i32, i32, %struct._pthread_descr_struct*, i32, %llvm.dbg.anchor.type }
+	%"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >" = type { %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<void*>,false>" }
+	%"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<void*>,false>" = type { %"struct.__gnu_cxx::hash<void*>", %"struct.std::_Rb_tree_node_base", i32 }
+	%"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >" = type { %"struct.std::_Rb_tree_node_base"* }
+	%"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
+	%"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>" = type { %"struct.std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >", i8 }
+	%"struct.std::pair<void* const,void*>" = type { i8*, i8* }
+
+ at _ZL20__gthrw_pthread_oncePiPFvvE = weak alias i32 (i32*, void ()*), i32 (i32*, void ()*)* @pthread_once		; <i32 (i32*, void ()*)*> [#uses=0]
+ at _ZL27__gthrw_pthread_getspecificj = weak alias i8* (i32), i8* (i32)* @pthread_getspecific		; <i8* (i32)*> [#uses=0]
+ at _ZL27__gthrw_pthread_setspecificjPKv = weak alias i32 (i32, i8*), i32 (i32, i8*)* @pthread_setspecific		; <i32 (i32, i8*)*> [#uses=0]
+ at _ZL22__gthrw_pthread_createPmPK16__pthread_attr_sPFPvS3_ES3_ = weak alias i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*), i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create		; <i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)*> [#uses=0]
+ at _ZL22__gthrw_pthread_cancelm = weak alias i32 (i32), i32 (i32)* @pthread_cancel		; <i32 (i32)*> [#uses=0]
+ at _ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock		; <i32 (%struct.pthread_mutex_t*)*> [#uses=0]
+ at _ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock		; <i32 (%struct.pthread_mutex_t*)*> [#uses=0]
+ at _ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = weak alias i32 (%struct.pthread_mutex_t*), i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock		; <i32 (%struct.pthread_mutex_t*)*> [#uses=0]
+ at _ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = weak alias i32 (%struct.pthread_mutex_t*, %struct.__sched_param*), i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)* @pthread_mutex_init		; <i32 (%struct.pthread_mutex_t*, %struct.__sched_param*)*> [#uses=0]
+ at _ZL26__gthrw_pthread_key_createPjPFvPvE = weak alias i32 (i32*, void (i8*)*), i32 (i32*, void (i8*)*)* @pthread_key_create		; <i32 (i32*, void (i8*)*)*> [#uses=0]
+ at _ZL26__gthrw_pthread_key_deletej = weak alias i32 (i32), i32 (i32)* @pthread_key_delete		; <i32 (i32)*> [#uses=0]
+ at _ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*), i32 (%struct.__sched_param*)* @pthread_mutexattr_init		; <i32 (%struct.__sched_param*)*> [#uses=0]
+ at _ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = weak alias i32 (%struct.__sched_param*, i32), i32 (%struct.__sched_param*, i32)* @pthread_mutexattr_settype		; <i32 (%struct.__sched_param*, i32)*> [#uses=0]
+ at _ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = weak alias i32 (%struct.__sched_param*), i32 (%struct.__sched_param*)* @pthread_mutexattr_destroy		; <i32 (%struct.__sched_param*)*> [#uses=0]
+
+declare fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind readnone
+
+define fastcc void @_ZNSt8_Rb_treeIPvSt4pairIKS0_S0_ESt10_Select1stIS3_ESt4lessIS0_ESaIS3_EE16_M_insert_uniqueERKS3_(%"struct.std::pair<std::_Rb_tree_iterator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>"* noalias nocapture sret %agg.result, %"struct.std::_Rb_tree<void*,std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<void*>,std::allocator<std::pair<void* const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >"* %this, %"struct.std::pair<void* const,void*>"* %__v) nounwind {
+entry:
+	br i1 false, label %bb7, label %bb
+
+bb:		; preds = %bb, %entry
+	br i1 false, label %bb5, label %bb
+
+bb5:		; preds = %bb
+	call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind
+	br i1 false, label %bb11, label %bb7
+
+bb7:		; preds = %bb5, %entry
+	br label %bb11
+
+bb11:		; preds = %bb7, %bb5
+	call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind
+	unreachable
+}
+
+define i32 @pthread_once(i32*, void ()*) {
+       ret i32 0
+}
+
+define i8* @pthread_getspecific(i32) {
+       ret i8* null
+}
+
+define i32 @pthread_setspecific(i32, i8*) {
+        ret i32 0
+}
+
+define i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*) {
+       ret i32 0
+}
+
+define i32 @pthread_cancel(i32) {
+      ret i32 0
+}
+
+define i32 @pthread_mutex_lock(%struct.pthread_mutex_t*) {
+       ret i32 0
+}
+
+define i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*) {
+       ret i32 0
+}
+
+define i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*) {
+       ret i32 0
+}
+
+define i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct.__sched_param*) {
+        ret i32 0
+}
+
+define i32 @pthread_key_create(i32*, void (i8*)*) {
+       ret i32 0
+}
+
+define i32 @pthread_key_delete(i32) {
+        ret i32 0
+}
+
+define i32 @pthread_mutexattr_init(%struct.__sched_param*) {
+        ret i32 0
+}
+
+define i32 @pthread_mutexattr_settype(%struct.__sched_param*, i32) {
+        ret i32 0
+}
+
+define i32 @pthread_mutexattr_destroy(%struct.__sched_param*) {
+       ret i32 0
+}

Added: llvm/trunk/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,67 @@
+; RUN: opt < %s -gvn | llvm-dis
+; PR4256
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+	%llvm.dbg.anchor.type = type { i32, i32 }
+	%struct.cset = type { i8*, i8, i8, i32, i8* }
+	%struct.lmat = type { %struct.re_guts*, i32, %llvm.dbg.anchor.type*, i8*, i8*, i8*, i8*, i8**, i32, i8*, i8*, i8*, i8*, i8* }
+	%struct.re_guts = type { i32*, %struct.cset*, i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8*, i8*, i32, i32, i32, i32, [1 x i8] }
+
+define i8* @lbackref(%struct.lmat* %m, i8* %start, i8* %stop, i32 %startst, i32 %stopst, i32 %lev, i32 %rec) nounwind {
+entry:
+	br label %bb63
+
+bb:		; preds = %bb63
+	switch i32 0, label %bb62 [
+		i32 268435456, label %bb2
+		i32 805306368, label %bb9
+		i32 -1610612736, label %bb51
+	]
+
+bb2:		; preds = %bb
+	br label %bb62
+
+bb9:		; preds = %bb
+	%0 = load i8, i8* %sp.1, align 1		; <i8> [#uses=0]
+	br label %bb62
+
+bb51:		; preds = %bb
+	%1 = load i8, i8* %sp.1, align 1		; <i8> [#uses=0]
+	ret i8* null
+
+bb62:		; preds = %bb9, %bb2, %bb
+	br label %bb63
+
+bb63:		; preds = %bb84, %bb69, %bb62, %entry
+	%sp.1 = phi i8* [ null, %bb62 ], [ %sp.1.lcssa, %bb84 ], [ %start, %entry ], [ %sp.1.lcssa, %bb69 ]		; <i8*> [#uses=3]
+	br i1 false, label %bb, label %bb65
+
+bb65:		; preds = %bb63
+	%sp.1.lcssa = phi i8* [ %sp.1, %bb63 ]		; <i8*> [#uses=4]
+	br i1 false, label %bb66, label %bb69
+
+bb66:		; preds = %bb65
+	ret i8* null
+
+bb69:		; preds = %bb65
+	switch i32 0, label %bb108.loopexit2.loopexit.loopexit [
+		i32 1342177280, label %bb63
+		i32 1476395008, label %bb84
+		i32 1879048192, label %bb104
+		i32 2013265920, label %bb93
+	]
+
+bb84:		; preds = %bb69
+	%2 = tail call i8* @lbackref(%struct.lmat* %m, i8* %sp.1.lcssa, i8* %stop, i32 0, i32 %stopst, i32 0, i32 0) nounwind		; <i8*> [#uses=0]
+	br label %bb63
+
+bb93:		; preds = %bb69
+	ret i8* null
+
+bb104:		; preds = %bb69
+	%sp.1.lcssa.lcssa33 = phi i8* [ %sp.1.lcssa, %bb69 ]		; <i8*> [#uses=0]
+	unreachable
+
+bb108.loopexit2.loopexit.loopexit:		; preds = %bb69
+	ret i8* null
+}

Added: llvm/trunk/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; Test to make sure malloc's bitcast does not block detection of a store 
+; to aliased memory; GVN should not optimize away the load in this program.
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+define i64 @test() {
+  %1 = tail call i8* @malloc(i64 mul (i64 4, i64 ptrtoint (i64* getelementptr (i64, i64* null, i64 1) to i64))) ; <i8*> [#uses=2]
+  store i8 42, i8* %1
+  %X = bitcast i8* %1 to i64*                     ; <i64*> [#uses=1]
+  %Y = load i64, i64* %X                               ; <i64> [#uses=1]
+  ret i64 %Y
+; CHECK: %Y = load i64, i64* %X
+; CHECK: ret i64 %Y
+}
+
+declare noalias i8* @malloc(i64)

Added: llvm/trunk/test/Transforms/GVN/2010-03-31-RedundantPHIs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2010-03-31-RedundantPHIs.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2010-03-31-RedundantPHIs.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2010-03-31-RedundantPHIs.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+; CHECK-NOT: load
+; CHECK-NOT: phi
+
+define i8* @cat(i8* %s1, ...) nounwind {
+entry:
+  br i1 undef, label %bb, label %bb3
+
+bb:                                               ; preds = %entry
+  unreachable
+
+bb3:                                              ; preds = %entry
+  store i8* undef, i8** undef, align 4
+  br i1 undef, label %bb5, label %bb6
+
+bb5:                                              ; preds = %bb3
+  unreachable
+
+bb6:                                              ; preds = %bb3
+  br label %bb12
+
+bb8:                                              ; preds = %bb12
+  br i1 undef, label %bb9, label %bb10
+
+bb9:                                              ; preds = %bb8
+  %0 = load i8*, i8** undef, align 4                   ; <i8*> [#uses=0]
+  %1 = load i8*, i8** undef, align 4                   ; <i8*> [#uses=0]
+  br label %bb11
+
+bb10:                                             ; preds = %bb8
+  br label %bb11
+
+bb11:                                             ; preds = %bb10, %bb9
+  br label %bb12
+
+bb12:                                             ; preds = %bb11, %bb6
+  br i1 undef, label %bb8, label %bb13
+
+bb13:                                             ; preds = %bb12
+  ret i8* undef
+}

Added: llvm/trunk/test/Transforms/GVN/2010-05-08-OneBit.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2010-05-08-OneBit.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2010-05-08-OneBit.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2010-05-08-OneBit.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,67 @@
+; RUN: opt < %s -gvn
+; PR7052
+
+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-unknown-linux-gnu"
+
+define i32 @main(i32 %argc, i8** nocapture %argv) personality i32 (...)* @__gxx_personality_v0 {
+entry:
+  %0 = getelementptr inbounds i8, i8* undef, i64 5    ; <i8*> [#uses=1]
+  %1 = bitcast i8* %0 to i32*                     ; <i32*> [#uses=1]
+  store i32 undef, i32* %1, align 1
+  br i1 undef, label %k121.i.i, label %l117.i.i
+
+l117.i.i:                                         ; preds = %entry
+  invoke fastcc void @foo()
+          to label %.noexc5 unwind label %landing_pad
+
+.noexc5:                                          ; preds = %l117.i.i
+  unreachable
+
+k121.i.i:                                         ; preds = %entry
+  br i1 undef, label %l129.i.i, label %k133.i.i
+
+l129.i.i:                                         ; preds = %k121.i.i
+  invoke fastcc void @foo()
+          to label %.noexc7 unwind label %landing_pad
+
+.noexc7:                                          ; preds = %l129.i.i
+  unreachable
+
+k133.i.i:                                         ; preds = %k121.i.i
+  %2 = getelementptr i8, i8* undef, i64 5             ; <i8*> [#uses=1]
+  %3 = bitcast i8* %2 to i1*                      ; <i1*> [#uses=1]
+  %4 = load i1, i1* %3                                ; <i1> [#uses=1]
+  br i1 %4, label %k151.i.i, label %l147.i.i
+
+l147.i.i:                                         ; preds = %k133.i.i
+  invoke fastcc void @foo()
+          to label %.noexc10 unwind label %landing_pad
+
+.noexc10:                                         ; preds = %l147.i.i
+  unreachable
+
+k151.i.i:                                         ; preds = %k133.i.i
+  ret i32 0
+
+landing_pad:                                      ; preds = %l147.i.i, %l129.i.i, %l117.i.i
+  %exn = landingpad {i8*, i32}
+            cleanup
+  switch i32 undef, label %fin [
+    i32 1, label %catch1
+    i32 2, label %catch
+  ]
+
+fin:                                              ; preds = %landing_pad
+  unreachable
+
+catch:                                            ; preds = %landing_pad
+  ret i32 1
+
+catch1:                                           ; preds = %landing_pad
+  ret i32 2
+}
+
+declare fastcc void @foo()
+
+declare i32 @__gxx_personality_v0(...)

Added: llvm/trunk/test/Transforms/GVN/2010-11-13-Simplify.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2010-11-13-Simplify.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2010-11-13-Simplify.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2010-11-13-Simplify.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+declare i32 @foo(i32) readnone
+
+define i1 @bar() {
+; CHECK-LABEL: @bar(
+  %a = call i32 @foo (i32 0) readnone
+  %b = call i32 @foo (i32 0) readnone
+  %c = and i32 %a, %b
+  %x = call i32 @foo (i32 %a) readnone
+  %y = call i32 @foo (i32 %c) readnone
+  %z = icmp eq i32 %x, %y
+  ret i1 %z
+; CHECK: ret i1 true
+} 

Added: llvm/trunk/test/Transforms/GVN/2011-04-27-phioperands.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2011-04-27-phioperands.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2011-04-27-phioperands.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2011-04-27-phioperands.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,106 @@
+; RUN: opt -gvn -disable-output < %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
+
+ at nuls = external global [10 x i8]
+
+define fastcc void @p_ere() nounwind {
+entry:
+  br label %"<bb 5>"
+
+"<L18>.i":
+  br i1 undef, label %"<bb 3>.i30.i", label %doemit.exit51.i
+
+"<bb 3>.i30.i":
+  unreachable
+
+doemit.exit51.i:
+  br label %"<bb 53>.i"
+
+"<L19>.i":
+  br i1 undef, label %"<bb 3>.i55.i", label %doemit.exit76.i
+
+"<bb 3>.i55.i":
+  unreachable
+
+doemit.exit76.i:
+  br label %"<bb 53>.i"
+
+"<L98>.i":
+  store i8* getelementptr inbounds ([10 x i8], [10 x i8]* @nuls, i64 0, i64 0), i8** undef, align 8
+  br label %"<bb 53>.i"
+
+"<L99>.i":
+  br label %"<bb 53>.i"
+
+"<L24>.i":
+  br i1 undef, label %"<bb 53>.i", label %"<bb 35>.i"
+
+"<bb 35>.i":
+  br label %"<bb 53>.i"
+
+"<L28>.i":
+  br label %"<bb 53>.i"
+
+"<L29>.i":
+  br label %"<bb 53>.i"
+
+"<L39>.i":
+  br label %"<bb 53>.i"
+
+"<bb 53>.i":
+  %wascaret_2.i = phi i32 [ 0, %"<L39>.i" ], [ 0, %"<L29>.i" ], [ 0, %"<L28>.i" ], [ 0, %"<bb 35>.i" ], [ 0, %"<L99>.i" ], [ 0, %"<L98>.i" ], [ 0, %doemit.exit76.i ], [ 1, %doemit.exit51.i ], [ 0, %"<L24>.i" ]
+  %D.5496_84.i = load i8*, i8** undef, align 8
+  br i1 undef, label %"<bb 54>.i", label %"<bb 5>"
+
+"<bb 54>.i":
+  br i1 undef, label %"<bb 5>", label %"<bb 58>.i"
+
+"<bb 58>.i":
+  br i1 undef, label %"<bb 64>.i", label %"<bb 59>.i"
+
+"<bb 59>.i":
+  br label %"<bb 64>.i"
+
+"<bb 64>.i":
+  switch i32 undef, label %"<bb 5>" [
+    i32 42, label %"<L54>.i"
+    i32 43, label %"<L55>.i"
+    i32 63, label %"<L56>.i"
+    i32 123, label %"<bb 5>.i258.i"
+  ]
+
+"<L54>.i":
+  br i1 undef, label %"<bb 3>.i105.i", label %doemit.exit127.i
+
+"<bb 3>.i105.i":
+  unreachable
+
+doemit.exit127.i:
+  unreachable
+
+"<L55>.i":
+  br i1 undef, label %"<bb 3>.i157.i", label %"<bb 5>"
+
+"<bb 3>.i157.i":
+  unreachable
+
+"<L56>.i":
+  br label %"<bb 5>"
+
+"<bb 5>.i258.i":
+  unreachable
+
+"<bb 5>":
+  switch i32 undef, label %"<L39>.i" [
+    i32 36, label %"<L19>.i"
+    i32 94, label %"<L18>.i"
+    i32 124, label %"<L98>.i"
+    i32 42, label %"<L99>.i"
+    i32 43, label %"<L99>.i"
+    i32 46, label %"<L24>.i"
+    i32 63, label %"<L99>.i"
+    i32 91, label %"<L28>.i"
+    i32 92, label %"<L29>.i"
+  ]
+}

Added: llvm/trunk/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2011-07-07-MatchIntrinsicExtract.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,85 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+;
+
+%0 = type { i64, i1 }
+
+define i64 @test1(i64 %a, i64 %b) nounwind ssp {
+entry:
+  %uadd = tail call %0 @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
+  %uadd.0 = extractvalue %0 %uadd, 0
+  %add1 = add i64 %a, %b
+  ret i64 %add1
+}
+
+; CHECK-LABEL: @test1(
+; CHECK-NOT: add1
+; CHECK: ret
+
+define i64 @test2(i64 %a, i64 %b) nounwind ssp {
+entry:
+  %usub = tail call %0 @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
+  %usub.0 = extractvalue %0 %usub, 0
+  %sub1 = sub i64 %a, %b
+  ret i64 %sub1
+}
+
+; CHECK-LABEL: @test2(
+; CHECK-NOT: sub1
+; CHECK: ret
+
+define i64 @test3(i64 %a, i64 %b) nounwind ssp {
+entry:
+  %umul = tail call %0 @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
+  %umul.0 = extractvalue %0 %umul, 0
+  %mul1 = mul i64 %a, %b
+  ret i64 %mul1
+}
+
+; CHECK-LABEL: @test3(
+; CHECK-NOT: mul1
+; CHECK: ret
+
+define i64 @test4(i64 %a, i64 %b) nounwind ssp {
+entry:
+  %sadd = tail call %0 @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
+  %sadd.0 = extractvalue %0 %sadd, 0
+  %add1 = add i64 %a, %b
+  ret i64 %add1
+}
+
+; CHECK-LABEL: @test4(
+; CHECK-NOT: add1
+; CHECK: ret
+
+define i64 @test5(i64 %a, i64 %b) nounwind ssp {
+entry:
+  %ssub = tail call %0 @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
+  %ssub.0 = extractvalue %0 %ssub, 0
+  %sub1 = sub i64 %a, %b
+  ret i64 %sub1
+}
+
+; CHECK-LABEL: @test5(
+; CHECK-NOT: sub1
+; CHECK: ret
+
+define i64 @test6(i64 %a, i64 %b) nounwind ssp {
+entry:
+  %smul = tail call %0 @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
+  %smul.0 = extractvalue %0 %smul, 0
+  %mul1 = mul i64 %a, %b
+  ret i64 %mul1
+}
+
+; CHECK-LABEL: @test6(
+; CHECK-NOT: mul1
+; CHECK: ret
+
+declare void @exit(i32) noreturn
+declare %0 @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone
+declare %0 @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
+declare %0 @llvm.umul.with.overflow.i64(i64, i64) nounwind readnone
+declare %0 @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
+declare %0 @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
+declare %0 @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone
+

Added: llvm/trunk/test/Transforms/GVN/2011-09-07-TypeIdFor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2011-09-07-TypeIdFor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2011-09-07-TypeIdFor.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2011-09-07-TypeIdFor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
+%struct.__type_info_pseudo = type { i8*, i8* }
+
+ at _ZTIi = external constant %struct.__fundamental_type_info_pseudo
+ at _ZTIb = external constant %struct.__fundamental_type_info_pseudo
+
+declare void @_Z4barv()
+
+declare void @_Z7cleanupv()
+
+declare i32 @llvm.eh.typeid.for(i8*) nounwind readonly
+
+declare i8* @__cxa_begin_catch(i8*) nounwind
+
+declare void @__cxa_end_catch()
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
+
+define void @_Z3foov() uwtable personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 {
+entry:
+  invoke void @_Z4barv()
+          to label %return unwind label %lpad
+
+lpad:                                             ; preds = %entry
+  %0 = landingpad { i8*, i32 }
+          catch %struct.__fundamental_type_info_pseudo* @_ZTIi
+          catch %struct.__fundamental_type_info_pseudo* @_ZTIb
+          catch %struct.__fundamental_type_info_pseudo* @_ZTIi
+          catch %struct.__fundamental_type_info_pseudo* @_ZTIb
+  %exc_ptr2.i = extractvalue { i8*, i32 } %0, 0
+  %filter3.i = extractvalue { i8*, i32 } %0, 1
+  %typeid.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
+; CHECK: call i32 @llvm.eh.typeid.for
+  %1 = icmp eq i32 %filter3.i, %typeid.i
+  br i1 %1, label %ppad, label %next
+
+next:                                             ; preds = %lpad
+  %typeid1.i = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
+; CHECK: call i32 @llvm.eh.typeid.for
+  %2 = icmp eq i32 %filter3.i, %typeid1.i
+  br i1 %2, label %ppad2, label %next2
+
+ppad:                                             ; preds = %lpad
+  %3 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+  tail call void @__cxa_end_catch() nounwind
+  br label %return
+
+ppad2:                                            ; preds = %next
+  %D.2073_5.i = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+  tail call void @__cxa_end_catch() nounwind
+  br label %return
+
+next2:                                            ; preds = %next
+  call void @_Z7cleanupv()
+  %typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
+; CHECK-NOT: call i32 @llvm.eh.typeid.for
+  %4 = icmp eq i32 %filter3.i, %typeid
+  br i1 %4, label %ppad3, label %next3
+
+next3:                                            ; preds = %next2
+  %typeid1 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIb to i8*))
+  %5 = icmp eq i32 %filter3.i, %typeid1
+  br i1 %5, label %ppad4, label %unwind
+
+unwind:                                           ; preds = %next3
+  resume { i8*, i32 } %0
+
+ppad3:                                            ; preds = %next2
+  %6 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+  tail call void @__cxa_end_catch() nounwind
+  br label %return
+
+ppad4:                                            ; preds = %next3
+  %D.2080_5 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr2.i) nounwind
+  tail call void @__cxa_end_catch() nounwind
+  br label %return
+
+return:                                           ; preds = %ppad4, %ppad3, %ppad2, %ppad, %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/2012-05-22-PreCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2012-05-22-PreCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2012-05-22-PreCrash.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2012-05-22-PreCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -gvn
+; PR12858
+
+define void @fn5(i16 signext %p1, i8 signext %p2) nounwind uwtable {
+entry:
+  br i1 undef, label %if.else, label %if.then
+
+if.then:                                          ; preds = %entry
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %conv = sext i16 %p1 to i32
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %conv1 = sext i16 %p1 to i32
+  br i1 undef, label %if.then3, label %if.else4
+
+if.then3:                                         ; preds = %if.end
+  br label %if.end12
+
+if.else4:                                         ; preds = %if.end
+  %conv7 = sext i8 %p2 to i32
+  %cmp8 = icmp eq i32 %conv1, %conv7
+  br i1 %cmp8, label %if.then10, label %if.end12
+
+if.then10:                                        ; preds = %if.else4
+  br label %if.end12
+
+if.end12:                                         ; preds = %if.then10, %if.else4, %if.then3
+  %conv13 = sext i8 %p2 to i32
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll (added)
+++ llvm/trunk/test/Transforms/GVN/2016-08-30-MaskedScatterGather.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+declare void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> , <2 x i32*> , i32 , <2 x i1> )
+declare <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*>, i32, <2 x i1>, <2 x i32>)
+
+; This test ensures that masked scatter and gather operations, which take vectors of pointers,
+; do not have pointer aliasing ignored when being processed.
+; No scatter/gather calls should end up eliminated
+; CHECK: llvm.masked.gather
+; CHECK: llvm.masked.gather
+; CHECK: llvm.masked.scatter
+; CHECK: llvm.masked.gather
+; CHECK: llvm.masked.scatter
+; CHECK: llvm.masked.gather
+define spir_kernel void @test(<2 x i32*> %in1, <2 x i32*> %in2, i32* %out) {
+entry:
+  ; Just some temporary storage
+  %tmp.0 = alloca i32
+  %tmp.1 = alloca i32
+  %tmp.i = insertelement <2 x i32*> undef, i32* %tmp.0, i32 0
+  %tmp = insertelement <2 x i32*> %tmp.i, i32* %tmp.1, i32 1
+  ; Read from in1 and in2
+  %in1.v = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %in1, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+  %in2.v = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %in2, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+  ; Store in1 to the allocas
+  call void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> %in1.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
+  ; Read in1 from the allocas
+  ; This gather should alias the scatter we just saw
+  %tmp.v.0 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+  ; Store in2 to the allocas
+  call void @llvm.masked.scatter.v2i32.v2p0i32(<2 x i32> %in2.v, <2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>);
+  ; Read in2 from the allocas
+  ; This gather should alias the scatter we just saw, and not be eliminated
+  %tmp.v.1 = call <2 x i32> @llvm.masked.gather.v2i32.v2p0i32(<2 x i32*> %tmp, i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) #1
+  ; Store in2 to out for good measure
+  %tmp.v.1.0 = extractelement <2 x i32> %tmp.v.1, i32 0
+  %tmp.v.1.1 = extractelement <2 x i32> %tmp.v.1, i32 1
+  store i32 %tmp.v.1.0, i32* %out
+  %out.1 = getelementptr i32, i32* %out, i32 1
+  store i32 %tmp.v.1.1, i32* %out.1
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/MemdepMiscompile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/MemdepMiscompile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/MemdepMiscompile.ll (added)
+++ llvm/trunk/test/Transforms/GVN/MemdepMiscompile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+; rdar://12801584
+; Value of %shouldExit can be changed by RunInMode.
+; Make sure we do not replace load %shouldExit in while.cond.backedge
+; with a phi node where the value from while.body is 0.
+define i32 @test() nounwind ssp {
+entry:
+; CHECK: test()
+; CHECK: while.body:
+; CHECK: call void @RunInMode
+; CHECK: br i1 %tobool, label %while.cond.backedge, label %if.then
+; CHECK: while.cond.backedge:
+; CHECK: load i32, i32* %shouldExit
+; CHECK: br i1 %cmp, label %while.body
+  %shouldExit = alloca i32, align 4
+  %tasksIdle = alloca i32, align 4
+  store i32 0, i32* %shouldExit, align 4
+  store i32 0, i32* %tasksIdle, align 4
+  call void @CTestInitialize(i32* %tasksIdle) nounwind
+  %0 = load i32, i32* %shouldExit, align 4
+  %cmp1 = icmp eq i32 %0, 0
+  br i1 %cmp1, label %while.body.lr.ph, label %while.end
+
+while.body.lr.ph:
+  br label %while.body
+
+while.body:
+  call void @RunInMode(i32 100) nounwind
+  %1 = load i32, i32* %tasksIdle, align 4
+  %tobool = icmp eq i32 %1, 0
+  br i1 %tobool, label %while.cond.backedge, label %if.then
+
+if.then:
+  store i32 0, i32* %tasksIdle, align 4
+  call void @TimerCreate(i32* %shouldExit) nounwind
+  br label %while.cond.backedge
+
+while.cond.backedge:
+  %2 = load i32, i32* %shouldExit, align 4
+  %cmp = icmp eq i32 %2, 0
+  br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
+
+while.cond.while.end_crit_edge:
+  br label %while.end
+
+while.end:
+  ret i32 0
+}
+declare void @CTestInitialize(i32*)
+declare void @RunInMode(i32)
+declare void @TimerCreate(i32*)

Added: llvm/trunk/test/Transforms/GVN/PRE/2009-02-17-LoadPRECrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/2009-02-17-LoadPRECrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/2009-02-17-LoadPRECrash.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/2009-02-17-LoadPRECrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,193 @@
+; RUN: opt < %s -gvn -enable-load-pre -disable-output
+
+	%struct.VEC_rtx_base = type { i32, i32, [1 x %struct.rtx_def*] }
+	%struct.VEC_rtx_gc = type { %struct.VEC_rtx_base }
+	%struct.block_symbol = type { [3 x %struct.cgraph_rtl_info], %struct.object_block*, i64 }
+	%struct.cgraph_rtl_info = type { i32 }
+	%struct.object_block = type { %struct.section*, i32, i64, %struct.VEC_rtx_gc*, %struct.VEC_rtx_gc* }
+	%struct.rtvec_def = type { i32, [1 x %struct.rtx_def*] }
+	%struct.rtx_def = type { i16, i8, i8, %struct.u }
+	%struct.section = type { %struct.unnamed_section }
+	%struct.u = type { %struct.block_symbol }
+	%struct.unnamed_section = type { %struct.cgraph_rtl_info, void (i8*)*, i8*, %struct.section* }
+
+declare %struct.rtvec_def* @gen_rtvec(i32, ...)
+
+declare %struct.rtx_def* @plus_constant(%struct.rtx_def*, i64)
+
+declare %struct.rtx_def* @gen_rtx_fmt_Ei(i32, i32, %struct.rtvec_def*, i32)
+
+declare i32 @local_symbolic_operand(%struct.rtx_def*, i32)
+
+define %struct.rtx_def* @legitimize_pic_address(%struct.rtx_def* %orig, %struct.rtx_def* %reg) nounwind {
+entry:
+	%addr = alloca %struct.rtx_def*		; <%struct.rtx_def**> [#uses=5]
+	%iftmp.1532 = alloca %struct.rtx_def*		; <%struct.rtx_def**> [#uses=3]
+	store %struct.rtx_def* %orig, %struct.rtx_def** null
+	%0 = load %struct.rtx_def*, %struct.rtx_def** null, align 4		; <%struct.rtx_def*> [#uses=0]
+	br i1 false, label %bb96, label %bb59
+
+bb59:		; preds = %entry
+	%1 = load %struct.rtx_def*, %struct.rtx_def** %addr, align 4		; <%struct.rtx_def*> [#uses=1]
+	%2 = call i32 @local_symbolic_operand(%struct.rtx_def* %1, i32 0) nounwind		; <i32> [#uses=0]
+	br i1 false, label %bb96, label %bb63
+
+bb63:		; preds = %bb59
+	br i1 false, label %bb64, label %bb74
+
+bb64:		; preds = %bb63
+	br i1 false, label %bb72, label %bb65
+
+bb65:		; preds = %bb64
+	br label %bb72
+
+bb72:		; preds = %bb65, %bb64
+	br label %bb74
+
+bb74:		; preds = %bb72, %bb63
+	br i1 false, label %bb75, label %bb76
+
+bb75:		; preds = %bb74
+	br label %bb76
+
+bb76:		; preds = %bb75, %bb74
+	br i1 false, label %bb77, label %bb84
+
+bb77:		; preds = %bb76
+	%3 = getelementptr [1 x %struct.cgraph_rtl_info], [1 x %struct.cgraph_rtl_info]* null, i32 0, i32 0		; <%struct.cgraph_rtl_info*> [#uses=0]
+	unreachable
+
+bb84:		; preds = %bb76
+	br i1 false, label %bb85, label %bb86
+
+bb85:		; preds = %bb84
+	br label %bb87
+
+bb86:		; preds = %bb84
+	br label %bb87
+
+bb87:		; preds = %bb86, %bb85
+	%4 = call %struct.rtx_def* @gen_rtx_fmt_Ei(i32 16, i32 0, %struct.rtvec_def* null, i32 1) nounwind		; <%struct.rtx_def*> [#uses=0]
+	br i1 false, label %bb89, label %bb90
+
+bb89:		; preds = %bb87
+	br label %bb91
+
+bb90:		; preds = %bb87
+	br label %bb91
+
+bb91:		; preds = %bb90, %bb89
+	br i1 false, label %bb92, label %bb93
+
+bb92:		; preds = %bb91
+	br label %bb94
+
+bb93:		; preds = %bb91
+	br label %bb94
+
+bb94:		; preds = %bb93, %bb92
+	unreachable
+
+bb96:		; preds = %bb59, %entry
+	%5 = load %struct.rtx_def*, %struct.rtx_def** %addr, align 4		; <%struct.rtx_def*> [#uses=1]
+	%6 = getelementptr %struct.rtx_def, %struct.rtx_def* %5, i32 0, i32 0		; <i16*> [#uses=1]
+	%7 = load i16, i16* %6, align 2		; <i16> [#uses=0]
+	br i1 false, label %bb147, label %bb97
+
+bb97:		; preds = %bb96
+	%8 = load %struct.rtx_def*, %struct.rtx_def** %addr, align 4		; <%struct.rtx_def*> [#uses=0]
+	br i1 false, label %bb147, label %bb99
+
+bb99:		; preds = %bb97
+	unreachable
+
+bb147:		; preds = %bb97, %bb96
+	%9 = load %struct.rtx_def*, %struct.rtx_def** %addr, align 4		; <%struct.rtx_def*> [#uses=1]
+	%10 = getelementptr %struct.rtx_def, %struct.rtx_def* %9, i32 0, i32 0		; <i16*> [#uses=1]
+	%11 = load i16, i16* %10, align 2		; <i16> [#uses=0]
+	br i1 false, label %bb164, label %bb148
+
+bb148:		; preds = %bb147
+	br i1 false, label %bb164, label %bb149
+
+bb149:		; preds = %bb148
+	br i1 false, label %bb150, label %bb152
+
+bb150:		; preds = %bb149
+	unreachable
+
+bb152:		; preds = %bb149
+	br label %bb164
+
+bb164:		; preds = %bb152, %bb148, %bb147
+	%12 = getelementptr [1 x %struct.cgraph_rtl_info], [1 x %struct.cgraph_rtl_info]* null, i32 0, i32 1		; <%struct.cgraph_rtl_info*> [#uses=0]
+	br i1 false, label %bb165, label %bb166
+
+bb165:		; preds = %bb164
+	br label %bb167
+
+bb166:		; preds = %bb164
+	br label %bb167
+
+bb167:		; preds = %bb166, %bb165
+	br i1 false, label %bb211, label %bb168
+
+bb168:		; preds = %bb167
+	br i1 false, label %bb211, label %bb170
+
+bb170:		; preds = %bb168
+	br i1 false, label %bb172, label %bb181
+
+bb172:		; preds = %bb170
+	br i1 false, label %bb179, label %bb174
+
+bb174:		; preds = %bb172
+	br i1 false, label %bb177, label %bb175
+
+bb175:		; preds = %bb174
+	br i1 false, label %bb177, label %bb176
+
+bb176:		; preds = %bb175
+	br label %bb178
+
+bb177:		; preds = %bb175, %bb174
+	br label %bb178
+
+bb178:		; preds = %bb177, %bb176
+	br label %bb180
+
+bb179:		; preds = %bb172
+	br label %bb180
+
+bb180:		; preds = %bb179, %bb178
+	br label %bb181
+
+bb181:		; preds = %bb180, %bb170
+	%13 = call %struct.rtvec_def* (i32, ...) @gen_rtvec(i32 1, %struct.rtx_def* null) nounwind		; <%struct.rtvec_def*> [#uses=0]
+	unreachable
+
+bb211:		; preds = %bb168, %bb167
+	%14 = load %struct.rtx_def*, %struct.rtx_def** %addr, align 4		; <%struct.rtx_def*> [#uses=0]
+	%15 = getelementptr [1 x %struct.cgraph_rtl_info], [1 x %struct.cgraph_rtl_info]* null, i32 0, i32 0		; <%struct.cgraph_rtl_info*> [#uses=0]
+	store %struct.rtx_def* null, %struct.rtx_def** null, align 4
+	br i1 false, label %bb212, label %bb213
+
+bb212:		; preds = %bb211
+	store %struct.rtx_def* null, %struct.rtx_def** %iftmp.1532, align 4
+	br label %bb214
+
+bb213:		; preds = %bb211
+	store %struct.rtx_def* null, %struct.rtx_def** %iftmp.1532, align 4
+	br label %bb214
+
+bb214:		; preds = %bb213, %bb212
+	%16 = bitcast %struct.block_symbol* null to [1 x %struct.cgraph_rtl_info]*		; <[1 x %struct.cgraph_rtl_info]*> [#uses=1]
+	%17 = getelementptr [1 x %struct.cgraph_rtl_info], [1 x %struct.cgraph_rtl_info]* %16, i32 0, i32 1		; <%struct.cgraph_rtl_info*> [#uses=0]
+	%18 = load %struct.rtx_def*, %struct.rtx_def** %iftmp.1532, align 4		; <%struct.rtx_def*> [#uses=0]
+	%19 = getelementptr %struct.rtx_def, %struct.rtx_def* null, i32 0, i32 3		; <%struct.u*> [#uses=1]
+	%20 = getelementptr %struct.u, %struct.u* %19, i32 0, i32 0		; <%struct.block_symbol*> [#uses=1]
+	%21 = bitcast %struct.block_symbol* %20 to [1 x i64]*		; <[1 x i64]*> [#uses=1]
+	%22 = getelementptr [1 x i64], [1 x i64]* %21, i32 0, i32 0		; <i64*> [#uses=0]
+	%23 = call %struct.rtx_def* @plus_constant(%struct.rtx_def* null, i64 0) nounwind		; <%struct.rtx_def*> [#uses=0]
+	unreachable
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/2009-06-17-InvalidPRE.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/2009-06-17-InvalidPRE.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/2009-06-17-InvalidPRE.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/2009-06-17-InvalidPRE.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,73 @@
+; RUN: opt < %s -gvn -enable-load-pre -S | FileCheck %s
+; CHECK-NOT: pre1
+; GVN load pre was hoisting the loads at %13 and %16 up to bb4.outer.  
+; This is invalid as it bypasses the check for %m.0.ph==null in bb4. 
+; ModuleID = 'mbuf.c'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.6"
+  %struct.mbuf = type { %struct.mbuf*, %struct.mbuf*, i32, i8*, i16, i16, i32 }
+
+define void @m_adj(%struct.mbuf* %mp, i32 %req_len) nounwind optsize {
+entry:
+  %0 = icmp eq %struct.mbuf* %mp, null    ; <i1> [#uses=1]
+  %1 = icmp slt i32 %req_len, 0   ; <i1> [#uses=1]
+  %or.cond = or i1 %1, %0   ; <i1> [#uses=1]
+  br i1 %or.cond, label %return, label %bb4.preheader
+
+bb4.preheader:    ; preds = %entry
+  br label %bb4.outer
+
+bb2:    ; preds = %bb1
+  %2 = sub i32 %len.0, %13   ; <i32> [#uses=1]
+  %3 = getelementptr %struct.mbuf, %struct.mbuf* %m.0.ph, i32 0, i32 2    ; <i32*> [#uses=1]
+  store i32 0, i32* %3, align 4
+  %4 = getelementptr %struct.mbuf, %struct.mbuf* %m.0.ph, i32 0, i32 0    ; <%struct.mbuf**> [#uses=1]
+  %5 = load %struct.mbuf*, %struct.mbuf** %4, align 4    ; <%struct.mbuf*> [#uses=1]
+  br label %bb4.outer
+
+bb4.outer:    ; preds = %bb4.preheader, %bb2
+  %m.0.ph = phi %struct.mbuf* [ %5, %bb2 ], [ %mp, %bb4.preheader ]   ; <%struct.mbuf*> [#uses=7]
+  %len.0.ph = phi i32 [ %2, %bb2 ], [ %req_len, %bb4.preheader ]    ; <i32> [#uses=1]
+  %6 = icmp ne %struct.mbuf* %m.0.ph, null    ; <i1> [#uses=1]
+  %7 = getelementptr %struct.mbuf, %struct.mbuf* %m.0.ph, i32 0, i32 2    ; <i32*> [#uses=1]
+  %8 = getelementptr %struct.mbuf, %struct.mbuf* %m.0.ph, i32 0, i32 2   ; <i32*> [#uses=1]
+  %9 = getelementptr %struct.mbuf, %struct.mbuf* %m.0.ph, i32 0, i32 3   ; <i8**> [#uses=1]
+  %10 = getelementptr %struct.mbuf, %struct.mbuf* %m.0.ph, i32 0, i32 3   ; <i8**> [#uses=1]
+  br label %bb4
+
+bb4:    ; preds = %bb4.outer, %bb3
+  %len.0 = phi i32 [ 0, %bb3 ], [ %len.0.ph, %bb4.outer ]   ; <i32> [#uses=6]
+  %11 = icmp sgt i32 %len.0, 0    ; <i1> [#uses=1]
+  %12 = and i1 %11, %6    ; <i1> [#uses=1]
+  br i1 %12, label %bb1, label %bb7
+
+bb1:    ; preds = %bb4
+  %13 = load i32, i32* %7, align 4    ; <i32> [#uses=3]
+  %14 = icmp sgt i32 %13, %len.0    ; <i1> [#uses=1]
+  br i1 %14, label %bb3, label %bb2
+
+bb3:    ; preds = %bb1
+  %15 = sub i32 %13, %len.0    ; <i32> [#uses=1]
+  store i32 %15, i32* %8, align 4
+  %16 = load i8*, i8** %9, align 4    ; <i8*> [#uses=1]
+  %17 = getelementptr i8, i8* %16, i32 %len.0   ; <i8*> [#uses=1]
+  store i8* %17, i8** %10, align 4
+  br label %bb4
+
+bb7:    ; preds = %bb4
+  %18 = getelementptr %struct.mbuf, %struct.mbuf* %mp, i32 0, i32 5   ; <i16*> [#uses=1]
+  %19 = load i16, i16* %18, align 2    ; <i16> [#uses=1]
+  %20 = zext i16 %19 to i32   ; <i32> [#uses=1]
+  %21 = and i32 %20, 2    ; <i32> [#uses=1]
+  %22 = icmp eq i32 %21, 0    ; <i1> [#uses=1]
+  br i1 %22, label %return, label %bb8
+
+bb8:    ; preds = %bb7
+  %23 = sub i32 %req_len, %len.0    ; <i32> [#uses=1]
+  %24 = getelementptr %struct.mbuf, %struct.mbuf* %mp, i32 0, i32 6   ; <i32*> [#uses=1]
+  store i32 %23, i32* %24, align 4
+  ret void
+
+return:   ; preds = %bb7, %entry
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/2011-06-01-NonLocalMemdepMiscompile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/2011-06-01-NonLocalMemdepMiscompile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/2011-06-01-NonLocalMemdepMiscompile.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/2011-06-01-NonLocalMemdepMiscompile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,60 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+; This test is checking that (a) this doesn't crash, and (b) we don't
+; conclude the value of %tmp17 is available in bb1.bb15_crit_edge.
+; rdar://9429882
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+define i1 @rb_intern(i8 *%foo) nounwind ssp {
+; CHECK-LABEL: @rb_intern(
+
+bb:
+  %tmp = alloca i8*, align 8
+  store i8* null, i8** %tmp, align 8
+  store i8 undef, i8* null, align 536870912
+  br label %bb1
+
+bb1:
+  br i1 undef, label %bb3, label %bb15
+
+; CHECK: bb1:
+; CHECK: [[TMP:%.*]] = phi i8* [ %tmp14, %bb10 ], [ null, %bb ]
+
+; CHECK: bb1.bb15_crit_edge:
+; CHECK: %tmp17.pre = load i8, i8* [[TMP]], align 1
+
+bb3:
+  call void @isalnum()
+  br i1 undef, label %bb10, label %bb5
+
+bb5:
+  br i1 undef, label %bb10, label %bb6
+
+bb6:
+  %tmp7 = load i8*, i8** %tmp, align 8
+  %tmp8 = load i8, i8* %tmp7, align 1
+  %tmp9 = zext i8 %tmp8 to i64
+  br i1 undef, label %bb15, label %bb10
+
+bb10:
+  %tmp11 = load i8*, i8** %tmp, align 8
+  %tmp12 = load i8, i8* %tmp11, align 1
+  %tmp13 = zext i8 %tmp12 to i64
+  %tmp14 = getelementptr inbounds i8, i8* %foo, i64 undef
+  store i8* %tmp14, i8** %tmp, align 8
+  br label %bb1
+
+bb15:
+  %tmp16 = load i8*, i8** %tmp, align 8
+  %tmp17 = load i8, i8* %tmp16, align 1
+  %tmp18 = icmp eq i8 %tmp17, 0
+  br label %bb19
+
+; CHECK: bb15:
+; CHECK: %tmp17 = phi i8 [ %tmp17.pre, %bb1.bb15_crit_edge ], [ %tmp8, %bb6 ]
+
+bb19:                                             ; preds = %bb15
+  ret i1 %tmp18
+}
+
+declare void @isalnum() nounwind inlinehint ssp

Added: llvm/trunk/test/Transforms/GVN/PRE/2017-06-28-pre-load-dbgloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/2017-06-28-pre-load-dbgloc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/2017-06-28-pre-load-dbgloc.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/2017-06-28-pre-load-dbgloc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,79 @@
+; This test checks if debug loc is propagated to load/store created by GVN/Instcombine.
+; RUN: opt < %s -gvn -S | FileCheck %s --check-prefixes=ALL,GVN
+; RUN: opt < %s -gvn -instcombine -S | FileCheck %s --check-prefixes=ALL,INSTCOMBINE
+
+; struct node {
+;  int  *v;
+; struct desc *descs;
+; };
+
+; struct desc {
+;  struct node *node;
+; };
+
+; extern int bar(void *v, void* n);
+
+; int test(struct desc *desc)
+; {
+;  void *v, *n;
+;  v = !desc ? ((void *)0) : desc->node->v;  // Line 15
+;  n = &desc->node->descs[0];                // Line 16
+;  return bar(v, n);
+; }
+
+; Line 16, Column 13:
+;   n = &desc->node->descs[0];
+;              ^
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+%struct.desc = type { %struct.node* }
+%struct.node = type { i32*, %struct.desc* }
+
+define i32 @test(%struct.desc* readonly %desc) local_unnamed_addr #0 !dbg !4 {
+entry:
+  %tobool = icmp eq %struct.desc* %desc, null
+  br i1 %tobool, label %cond.end, label %cond.false, !dbg !9
+; ALL: br i1 %tobool, label %entry.cond.end_crit_edge, label %cond.false, !dbg [[LOC_15_6:![0-9]+]]
+; ALL: entry.cond.end_crit_edge:
+; GVN: %.pre = load %struct.node*, %struct.node** null, align 8, !dbg [[LOC_16_13:![0-9]+]]
+; INSTCOMBINE:store %struct.node* undef, %struct.node** null, align 536870912, !dbg [[LOC_16_13:![0-9]+]]
+
+cond.false:
+  %0 = bitcast %struct.desc* %desc to i8***, !dbg !11
+  %1 = load i8**, i8*** %0, align 8, !dbg !11
+  %2 = load i8*, i8** %1, align 8
+  br label %cond.end, !dbg !9
+
+cond.end:
+  %3 = phi i8* [ %2, %cond.false ], [ null, %entry ], !dbg !9
+  %node2 = getelementptr inbounds %struct.desc, %struct.desc* %desc, i64 0, i32 0
+  %4 = load %struct.node*, %struct.node** %node2, align 8, !dbg !10
+  %descs = getelementptr inbounds %struct.node, %struct.node* %4, i64 0, i32 1
+  %5 = bitcast %struct.desc** %descs to i8**
+  %6 = load i8*, i8** %5, align 8
+  %call = tail call i32 @bar(i8* %3, i8* %6)
+  ret i32 %call
+}
+
+declare i32 @bar(i8*, i8*) local_unnamed_addr #1
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.c", directory: ".")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 12, type: !5, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !8)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{}
+!9 = !DILocation(line: 15, column: 6, scope: !4)
+!10 = !DILocation(line: 16, column: 13, scope: !4)
+!11 = !DILocation(line: 15, column: 34, scope: !4)
+
+;ALL: [[SCOPE:![0-9]+]] = distinct  !DISubprogram(name: "test",{{.*}}
+;ALL: [[LOC_15_6]] = !DILocation(line: 15, column: 6, scope: [[SCOPE]])
+;ALL: [[LOC_16_13]] = !DILocation(line: 16, column: 13, scope: [[SCOPE]])

Added: llvm/trunk/test/Transforms/GVN/PRE/2017-10-16-LoadPRECrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/2017-10-16-LoadPRECrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/2017-10-16-LoadPRECrash.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/2017-10-16-LoadPRECrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; RUN: opt -S -gvn -enable-load-pre < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%ArrayImpl = type { i64, i64 addrspace(100)*, [1 x i64], [1 x i64], [1 x i64], i64, i64, double addrspace(100)*, double addrspace(100)*, i8, i64 }
+
+; Function Attrs: readnone
+declare %ArrayImpl* @getaddr_ArrayImpl(%ArrayImpl addrspace(100)*) #0
+
+; Function Attrs: readnone
+declare i64* @getaddr_i64(i64 addrspace(100)*) #0
+
+; Make sure that the test compiles without a crash.
+; Bug https://bugs.llvm.org/show_bug.cgi?id=34937
+
+define hidden void @wrapon_fn173() {
+
+; CHECK-LABEL: @wrapon_fn173
+; CHECK:       entry:
+; CHECK-NEXT:    call %ArrayImpl* @getaddr_ArrayImpl(%ArrayImpl addrspace(100)* undef)
+; CHECK-NEXT:    %.pre = load i64 addrspace(100)*, i64 addrspace(100)** null, align 8
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    call i64* @getaddr_i64(i64 addrspace(100)* %.pre)
+; CHECK-NEXT:    br label %loop
+
+entry:
+  %0 = call %ArrayImpl* @getaddr_ArrayImpl(%ArrayImpl addrspace(100)* undef)
+  br label %loop
+
+loop:
+  %1 = call %ArrayImpl* @getaddr_ArrayImpl(%ArrayImpl addrspace(100)* undef)
+  %2 = load i64 addrspace(100)*, i64 addrspace(100)** null, align 8
+  %3 = call i64* @getaddr_i64(i64 addrspace(100)* %2)
+  br label %loop
+}
+
+attributes #0 = { readnone }

Added: llvm/trunk/test/Transforms/GVN/PRE/2018-06-08-pre-load-dbgloc-no-null-opt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/2018-06-08-pre-load-dbgloc-no-null-opt.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/2018-06-08-pre-load-dbgloc-no-null-opt.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/2018-06-08-pre-load-dbgloc-no-null-opt.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,82 @@
+; This test checks if debug loc is propagated to load/store created by GVN/Instcombine.
+; RUN: opt < %s -gvn -S | FileCheck %s --check-prefixes=ALL
+; RUN: opt < %s -gvn -instcombine -S | FileCheck %s --check-prefixes=ALL
+
+; struct node {
+;  int  *v;
+; struct desc *descs;
+; };
+
+; struct desc {
+;  struct node *node;
+; };
+
+; extern int bar(void *v, void* n);
+
+; int test(struct desc *desc)
+; {
+;  void *v, *n;
+;  v = !desc ? ((void *)0) : desc->node->v;  // Line 15
+;  n = &desc->node->descs[0];                // Line 16
+;  return bar(v, n);
+; }
+
+; Line 16, Column 13:
+;   n = &desc->node->descs[0];
+;              ^
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+%struct.desc = type { %struct.node* }
+%struct.node = type { i32*, %struct.desc* }
+
+define i32 @test_no_null_opt(%struct.desc* readonly %desc) local_unnamed_addr #0 !dbg !4 {
+entry:
+  %tobool = icmp eq %struct.desc* %desc, null
+  br i1 %tobool, label %cond.end, label %cond.false, !dbg !9
+; ALL: br i1 %tobool, label %entry.cond.end_crit_edge, label %cond.false, !dbg [[LOC_15_6:![0-9]+]]
+; ALL: entry.cond.end_crit_edge:
+; ALL: load %struct.node*, %struct.node** null, align {{[0-9]+}}, !dbg [[LOC_16_13:![0-9]+]]
+
+cond.false:
+  %0 = bitcast %struct.desc* %desc to i8***, !dbg !11
+  %1 = load i8**, i8*** %0, align 8, !dbg !11
+  %2 = load i8*, i8** %1, align 8
+  br label %cond.end, !dbg !9
+
+cond.end:
+; ALL: phi %struct.node* [ %3, %cond.false ], [ %.pre, %entry.cond.end_crit_edge ]
+; ALL: phi i8* [ %2, %cond.false ], [ null, %entry.cond.end_crit_edge ]
+
+  %3 = phi i8* [ %2, %cond.false ], [ null, %entry ], !dbg !9
+  %node2 = getelementptr inbounds %struct.desc, %struct.desc* %desc, i64 0, i32 0
+  %4 = load %struct.node*, %struct.node** %node2, align 8, !dbg !10
+  %descs = getelementptr inbounds %struct.node, %struct.node* %4, i64 0, i32 1
+  %5 = bitcast %struct.desc** %descs to i8**
+  %6 = load i8*, i8** %5, align 8
+  %call = tail call i32 @bar(i8* %3, i8* %6)
+  ret i32 %call
+}
+attributes #0 = { "null-pointer-is-valid"="true" }
+
+declare i32 @bar(i8*, i8*) local_unnamed_addr #1
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "test.c", directory: ".")
+!2 = !{i32 2, !"Dwarf Version", i32 4}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = distinct !DISubprogram(name: "test_no_null_opt", scope: !1, file: !1, line: 12, type: !5, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !8)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{}
+!9 = !DILocation(line: 15, column: 6, scope: !4)
+!10 = !DILocation(line: 16, column: 13, scope: !4)
+!11 = !DILocation(line: 15, column: 34, scope: !4)
+
+;ALL: [[SCOPE:![0-9]+]] = distinct  !DISubprogram(name: "test_no_null_opt",{{.*}}
+;ALL: [[LOC_15_6]] = !DILocation(line: 15, column: 6, scope: [[SCOPE]])
+;ALL: [[LOC_16_13]] = !DILocation(line: 16, column: 13, scope: [[SCOPE]])

Added: llvm/trunk/test/Transforms/GVN/PRE/atomic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/atomic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/atomic.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/atomic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,503 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-macosx10.7.0"
+
+ at x = common global i32 0, align 4
+ at y = common global i32 0, align 4
+
+; GVN across unordered store (allowed)
+define i32 @test1() nounwind uwtable ssp {
+; CHECK-LABEL: test1
+; CHECK: add i32 %x, %x
+entry:
+  %x = load i32, i32* @y
+  store atomic i32 %x, i32* @x unordered, align 4
+  %y = load i32, i32* @y
+  %z = add i32 %x, %y
+  ret i32 %z
+}
+
+; GVN across unordered load (allowed)
+define i32 @test3() nounwind uwtable ssp {
+; CHECK-LABEL: test3
+; CHECK: add i32 %x, %x
+entry:
+  %x = load i32, i32* @y
+  %y = load atomic i32, i32* @x unordered, align 4
+  %z = load i32, i32* @y
+  %a = add i32 %x, %z
+  %b = add i32 %y, %a
+  ret i32 %b
+}
+
+; GVN load to unordered load (allowed)
+define i32 @test5() nounwind uwtable ssp {
+; CHECK-LABEL: test5
+; CHECK: add i32 %x, %x
+entry:
+  %x = load atomic i32, i32* @x unordered, align 4
+  %y = load i32, i32* @x
+  %z = add i32 %x, %y
+  ret i32 %z
+}
+
+; GVN unordered load to load (unordered load must not be removed)
+define i32 @test6() nounwind uwtable ssp {
+; CHECK-LABEL: test6
+; CHECK: load atomic i32, i32* @x unordered
+entry:
+  %x = load i32, i32* @x
+  %x2 = load atomic i32, i32* @x unordered, align 4
+  %x3 = add i32 %x, %x2
+  ret i32 %x3
+}
+
+; GVN across release-acquire pair (forbidden)
+define i32 @test7() nounwind uwtable ssp {
+; CHECK-LABEL: test7
+; CHECK: add i32 %x, %y
+entry:
+  %x = load i32, i32* @y
+  store atomic i32 %x, i32* @x release, align 4
+  %w = load atomic i32, i32* @x acquire, align 4
+  %y = load i32, i32* @y
+  %z = add i32 %x, %y
+  ret i32 %z
+}
+
+; GVN across monotonic store (allowed)
+define i32 @test9() nounwind uwtable ssp {
+; CHECK-LABEL: test9
+; CHECK: add i32 %x, %x
+entry:
+  %x = load i32, i32* @y
+  store atomic i32 %x, i32* @x monotonic, align 4
+  %y = load i32, i32* @y
+  %z = add i32 %x, %y
+  ret i32 %z
+}
+
+; GVN of an unordered across monotonic load (not allowed)
+define i32 @test10() nounwind uwtable ssp {
+; CHECK-LABEL: test10
+; CHECK: add i32 %x, %y
+entry:
+  %x = load atomic i32, i32* @y unordered, align 4
+  %clobber = load atomic i32, i32* @x monotonic, align 4
+  %y = load atomic i32, i32* @y monotonic, align 4
+  %z = add i32 %x, %y
+  ret i32 %z
+}
+
+define i32 @PR22708(i1 %flag) {
+; CHECK-LABEL: PR22708
+entry:
+  br i1 %flag, label %if.then, label %if.end
+
+if.then:
+  store i32 43, i32* @y, align 4
+; CHECK: store i32 43, i32* @y, align 4
+  br label %if.end
+
+if.end:
+  load atomic i32, i32* @x acquire, align 4
+  %load = load i32, i32* @y, align 4
+; CHECK: load atomic i32, i32* @x acquire, align 4
+; CHECK: load i32, i32* @y, align 4
+  ret i32 %load
+}
+
+; CHECK-LABEL: @test12(
+; Can't remove a load over a ordering barrier
+define i32 @test12(i1 %B, i32* %P1, i32* %P2) {
+  %load0 = load i32, i32* %P1
+  %1 = load atomic i32, i32* %P2 seq_cst, align 4
+  %load1 = load i32, i32* %P1
+  %sel = select i1 %B, i32 %load0, i32 %load1
+  ret i32 %sel
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load i32, i32* %P1
+}
+
+; CHECK-LABEL: @test13(
+; atomic to non-atomic forwarding is legal
+define i32 @test13(i32* %P1) {
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %b = load i32, i32* %P1
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load atomic i32, i32* %P1
+  ; CHECK: ret i32 0
+}
+
+; CHECK-LABEL: @test13b(
+define i32 @test13b(i32* %P1) {
+  store  atomic i32 0, i32* %P1 unordered, align 4
+  %b = load i32, i32* %P1
+  ret i32 %b
+  ; CHECK: ret i32 0
+}
+
+; CHECK-LABEL: @test14(
+; atomic to unordered atomic forwarding is legal
+define i32 @test14(i32* %P1) {
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load atomic i32, i32* %P1 seq_cst
+  ; CHECK-NEXT: ret i32 0
+}
+
+; CHECK-LABEL: @test15(
+; implementation restriction: can't forward to stonger
+; than unordered
+define i32 @test15(i32* %P1, i32* %P2) {
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %b = load atomic i32, i32* %P1 seq_cst, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load atomic i32, i32* %P1
+  ; CHECK: load atomic i32, i32* %P1
+}
+
+; CHECK-LABEL: @test16(
+; forwarding non-atomic to atomic is wrong! (However,
+; it would be legal to use the later value in place of the
+; former in this particular example.  We just don't
+; do that right now.)
+define i32 @test16(i32* %P1, i32* %P2) {
+  %a = load i32, i32* %P1, align 4
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load atomic i32, i32* %P1
+}
+
+; CHECK-LABEL: @test16b(
+define i32 @test16b(i32* %P1) {
+  store i32 0, i32* %P1
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  ret i32 %b
+  ; CHECK: load atomic i32, i32* %P1
+}
+
+; Can't DSE across a full fence
+define void @fence_seq_cst_store(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_seq_cst_store(
+; CHECK: store
+; CHECK: store atomic
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  store atomic i32 0, i32* %P2 seq_cst, align 4
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full fence
+define void @fence_seq_cst(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_seq_cst(
+; CHECK: store
+; CHECK: fence seq_cst
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  fence seq_cst
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full syncscope("singlethread") fence
+define void @fence_seq_cst_st(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_seq_cst_st(
+; CHECK: store
+; CHECK: fence syncscope("singlethread") seq_cst
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  fence syncscope("singlethread") seq_cst
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full fence
+define void @fence_asm_sideeffect(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_asm_sideeffect(
+; CHECK: store
+; CHECK: call void asm sideeffect
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  call void asm sideeffect "", ""()
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE across a full fence
+define void @fence_asm_memory(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @fence_asm_memory(
+; CHECK: store
+; CHECK: call void asm
+; CHECK: store
+  store i32 0, i32* %P1, align 4
+  call void asm "", "~{memory}"()
+  store i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can't remove a volatile load
+define i32 @volatile_load(i32* %P1, i32* %P2) {
+  %a = load i32, i32* %P1, align 4
+  %b = load volatile i32, i32* %P1, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK-LABEL: @volatile_load(
+  ; CHECK: load i32, i32* %P1
+  ; CHECK: load volatile i32, i32* %P1
+}
+
+; Can't remove redundant volatile loads
+define i32 @redundant_volatile_load(i32* %P1, i32* %P2) {
+  %a = load volatile i32, i32* %P1, align 4
+  %b = load volatile i32, i32* %P1, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK-LABEL: @redundant_volatile_load(
+  ; CHECK: load volatile i32, i32* %P1
+  ; CHECK: load volatile i32, i32* %P1
+  ; CHECK: sub
+}
+
+; Can't DSE a volatile store
+define void @volatile_store(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @volatile_store(
+; CHECK: store volatile
+; CHECK: store
+  store volatile i32 0, i32* %P1, align 4
+  store i32 3, i32* %P1, align 4
+  ret void
+}
+
+; Can't DSE a redundant volatile store
+define void @redundant_volatile_store(i32* %P1, i32* %P2) {
+; CHECK-LABEL: @redundant_volatile_store(
+; CHECK: store volatile
+; CHECK: store volatile
+  store volatile i32 0, i32* %P1, align 4
+  store volatile i32 0, i32* %P1, align 4
+  ret void
+}
+
+; Can value forward from volatiles
+define i32 @test20(i32* %P1, i32* %P2) {
+  %a = load volatile i32, i32* %P1, align 4
+  %b = load i32, i32* %P1, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+  ; CHECK-LABEL: @test20(
+  ; CHECK: load volatile i32, i32* %P1
+  ; CHECK: ret i32 0
+}
+
+; We're currently conservative about widening
+define i64 @widen1(i32* %P1) {
+  ; CHECK-LABEL: @widen1(
+  ; CHECK: load atomic i32, i32* %P1
+  ; CHECK: load atomic i64, i64* %p2
+  %p2 = bitcast i32* %P1 to i64*
+  %a = load atomic i32, i32* %P1 unordered, align 4
+  %b = load atomic i64, i64* %p2 unordered, align 4
+  %a64 = sext i32 %a to i64
+  %res = sub i64 %a64, %b
+  ret i64 %res
+}
+
+; narrowing does work
+define i64 @narrow(i32* %P1) {
+  ; CHECK-LABEL: @narrow(
+  ; CHECK: load atomic i64, i64* %p2
+  ; CHECK-NOT: load atomic i32, i32* %P1
+  %p2 = bitcast i32* %P1 to i64*
+  %a64 = load atomic i64, i64* %p2 unordered, align 4
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  %b64 = sext i32 %b to i64
+  %res = sub i64 %a64, %b64
+  ret i64 %res
+}
+
+; Missed optimization, we don't yet optimize ordered loads
+define i64 @narrow2(i32* %P1) {
+  ; CHECK-LABEL: @narrow2(
+  ; CHECK: load atomic i64, i64* %p2
+  ; CHECK: load atomic i32, i32* %P1
+  %p2 = bitcast i32* %P1 to i64*
+  %a64 = load atomic i64, i64* %p2 acquire, align 4
+  %b = load atomic i32, i32* %P1 acquire, align 4
+  %b64 = sext i32 %b to i64
+  %res = sub i64 %a64, %b64
+  ret i64 %res
+}
+
+; Note: The cross block FRE testing is deliberately light.  All of the tricky
+; bits of legality are shared code with the block-local FRE above.  These
+; are here only to show that we haven't obviously broken anything.
+
+; unordered atomic to unordered atomic
+define i32 @non_local_fre(i32* %P1) {
+; CHECK-LABEL: @non_local_fre(
+; CHECK: load atomic i32, i32* %P1
+; CHECK: ret i32 0
+; CHECK: ret i32 0
+  %a = load atomic i32, i32* %P1 unordered, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  ret i32 %a
+next:
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+}
+
+; unordered atomic to non-atomic
+define i32 @non_local_fre2(i32* %P1) {
+; CHECK-LABEL: @non_local_fre2(
+; CHECK: load atomic i32, i32* %P1
+; CHECK: ret i32 0
+; CHECK: ret i32 0
+  %a = load atomic i32, i32* %P1 unordered, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  ret i32 %a
+next:
+  %b = load i32, i32* %P1
+  %res = sub i32 %a, %b
+  ret i32 %res
+}
+
+; Can't forward ordered atomics.
+define i32 @non_local_fre3(i32* %P1) {
+; CHECK-LABEL: @non_local_fre3(
+; CHECK: load atomic i32, i32* %P1 acquire
+; CHECK: ret i32 0
+; CHECK: load atomic i32, i32* %P1 acquire
+; CHECK: ret i32 %res
+  %a = load atomic i32, i32* %P1 acquire, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  ret i32 %a
+next:
+  %b = load atomic i32, i32* %P1 acquire, align 4
+  %res = sub i32 %a, %b
+  ret i32 %res
+}
+
+declare void @clobber()
+
+; unordered atomic to unordered atomic
+define i32 @non_local_pre(i32* %P1) {
+; CHECK-LABEL: @non_local_pre(
+; CHECK: load atomic i32, i32* %P1 unordered
+; CHECK: load atomic i32, i32* %P1 unordered
+; CHECK: %b = phi i32 [ %b.pre, %early ], [ %a, %0 ]
+; CHECK: ret i32 %b
+  %a = load atomic i32, i32* %P1 unordered, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  call void @clobber()
+  br label %next
+next:
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  ret i32 %b
+}
+
+; unordered atomic to non-atomic
+define i32 @non_local_pre2(i32* %P1) {
+; CHECK-LABEL: @non_local_pre2(
+; CHECK: load atomic i32, i32* %P1 unordered
+; CHECK: load i32, i32* %P1
+; CHECK: %b = phi i32 [ %b.pre, %early ], [ %a, %0 ]
+; CHECK: ret i32 %b
+  %a = load atomic i32, i32* %P1 unordered, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  call void @clobber()
+  br label %next
+next:
+  %b = load i32, i32* %P1
+  ret i32 %b
+}
+
+; non-atomic to unordered atomic - can't forward!
+define i32 @non_local_pre3(i32* %P1) {
+; CHECK-LABEL: @non_local_pre3(
+; CHECK: %a = load i32, i32* %P1
+; CHECK: %b = load atomic i32, i32* %P1 unordered
+; CHECK: ret i32 %b
+  %a = load i32, i32* %P1
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  call void @clobber()
+  br label %next
+next:
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  ret i32 %b
+}
+
+; ordered atomic to ordered atomic - can't forward
+define i32 @non_local_pre4(i32* %P1) {
+; CHECK-LABEL: @non_local_pre4(
+; CHECK: %a = load atomic i32, i32* %P1 seq_cst
+; CHECK: %b = load atomic i32, i32* %P1 seq_cst
+; CHECK: ret i32 %b
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  call void @clobber()
+  br label %next
+next:
+  %b = load atomic i32, i32* %P1 seq_cst, align 4
+  ret i32 %b
+}
+
+; can't remove volatile on any path
+define i32 @non_local_pre5(i32* %P1) {
+; CHECK-LABEL: @non_local_pre5(
+; CHECK: %a = load atomic i32, i32* %P1 seq_cst
+; CHECK: %b = load volatile i32, i32* %P1
+; CHECK: ret i32 %b
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  call void @clobber()
+  br label %next
+next:
+  %b = load volatile i32, i32* %P1
+  ret i32 %b
+}
+
+
+; ordered atomic to unordered atomic
+define i32 @non_local_pre6(i32* %P1) {
+; CHECK-LABEL: @non_local_pre6(
+; CHECK: load atomic i32, i32* %P1 seq_cst
+; CHECK: load atomic i32, i32* %P1 unordered
+; CHECK: %b = phi i32 [ %b.pre, %early ], [ %a, %0 ]
+; CHECK: ret i32 %b
+  %a = load atomic i32, i32* %P1 seq_cst, align 4
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %early, label %next
+early:
+  call void @clobber()
+  br label %next
+next:
+  %b = load atomic i32, i32* %P1 unordered, align 4
+  ret i32 %b
+}
+

Added: llvm/trunk/test/Transforms/GVN/PRE/invariant-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/invariant-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/invariant-load.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/invariant-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,136 @@
+; Test if the !invariant.load metadata is maintained by GVN.
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+define i32 @test1(i32* nocapture %p, i8* nocapture %q) {
+; CHECK-LABEL: test1
+; CHECK: %x = load i32, i32* %p, align 4, !invariant.load !0
+; CHECK-NOT: %y = load
+entry:
+  %x = load i32, i32* %p, align 4, !invariant.load !0
+  %conv = trunc i32 %x to i8
+  store i8 %conv, i8* %q, align 1
+  %y = load i32, i32* %p, align 4, !invariant.load !0
+  %add = add i32 %y, 1
+  ret i32 %add
+}
+
+define i32 @test2(i32* nocapture %p, i8* nocapture %q) {
+; CHECK-LABEL: test2
+; CHECK-NOT: !invariant.load
+; CHECK-NOT: %y = load
+entry:
+  %x = load i32, i32* %p, align 4
+  %conv = trunc i32 %x to i8
+  store i8 %conv, i8* %q, align 1
+  %y = load i32, i32* %p, align 4, !invariant.load !0
+  %add = add i32 %y, 1
+  ret i32 %add
+}
+
+; With the invariant.load metadata, what would otherwise
+; be a case for PRE becomes a full redundancy.
+define i32 @test3(i1 %cnd, i32* %p, i32* %q) {
+; CHECK-LABEL: test3
+; CHECK-NOT: load
+entry:
+  %v1 = load i32, i32* %p
+  br i1 %cnd, label %bb1, label %bb2
+
+bb1:
+  store i32 5, i32* %q
+  br label %bb2
+
+bb2:
+  %v2 = load i32, i32* %p, !invariant.load !0
+  %res = sub i32 %v1, %v2
+  ret i32 %res
+}
+
+; This test is here to document a case which doesn't optimize
+; as well as it could.  
+define i32 @test4(i1 %cnd, i32* %p, i32* %q) {
+; CHECK-LABEL: test4
+; %v2 is redundant, but GVN currently doesn't catch that
+entry:
+  %v1 = load i32, i32* %p, !invariant.load !0
+  br i1 %cnd, label %bb1, label %bb2
+
+bb1:
+  store i32 5, i32* %q
+  br label %bb2
+
+bb2:
+  %v2 = load i32, i32* %p
+  %res = sub i32 %v1, %v2
+  ret i32 %res
+}
+
+; Checks that we return the mustalias store as a def
+; so that it contributes to value forwarding.  Note
+; that we could and should remove the store too.
+define i32 @test5(i1 %cnd, i32* %p) {
+; CHECK-LABEL: test5
+; CHECK-LABEL: entry:
+; CHECK-NEXT: store i32 5, i32* %p
+; CHECK-NEXT: ret i32 5
+entry:
+  %v1 = load i32, i32* %p, !invariant.load !0
+  store i32 5, i32* %p ;; must alias store, want to exploit
+  %v2 = load i32, i32* %p, !invariant.load !0
+  ret i32 %v2
+}
+
+
+declare void @foo()
+
+; Clobbering (mayalias) stores, even in function calls, can be ignored
+define i32 @test6(i1 %cnd, i32* %p) {
+; CHECK-LABEL: test6
+; CHECK-LABEL: entry:
+; CHECK-NEXT: @foo
+; CHECK-NEXT: ret i32 0
+entry:
+  %v1 = load i32, i32* %p, !invariant.load !0
+  call void @foo()
+  %v2 = load i32, i32* %p, !invariant.load !0
+  %res = sub i32 %v1, %v2
+  ret i32 %res
+}
+
+declare noalias i32* @bar(...) 
+
+; Same as previous, but a function with a noalias result (since they're handled
+; differently in MDA)
+define i32 @test7(i1 %cnd, i32* %p) {
+; CHECK-LABEL: test7
+; CHECK-LABEL: entry:
+; CHECK-NEXT: @bar
+; CHECK-NEXT: ret i32 0
+entry:
+  %v1 = load i32, i32* %p, !invariant.load !0
+  call i32* (...) @bar(i32* %p)
+  %v2 = load i32, i32* %p, !invariant.load !0
+  %res = sub i32 %v1, %v2
+  ret i32 %res
+}
+
+define i32 @test8(i1 %cnd, i32* %p) {
+; CHECK-LABEL: test8
+; CHECK: @bar
+; CHECK: load i32, i32* %p2, !invariant.load
+; CHECK: br label %merge
+entry:
+  %v1 = load i32, i32* %p, !invariant.load !0
+  br i1 %cnd, label %taken, label %merge
+taken:
+  %p2 = call i32* (...) @bar(i32* %p)
+  br label %merge
+merge:
+  %p3 = phi i32* [%p, %entry], [%p2, %taken]
+  %v2 = load i32, i32* %p3, !invariant.load !0
+  %res = sub i32 %v1, %v2
+  ret i32 %res
+}
+
+!0 = !{ }
+

Added: llvm/trunk/test/Transforms/GVN/PRE/load-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/load-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/load-metadata.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/load-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt -S -gvn < %s | FileCheck %s
+
+define i32 @test1(i32* %p, i1 %C) {
+; CHECK-LABEL: @test1(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+ br label %block4
+; CHECK: block2:
+; CHECK-NEXT: load i32, i32* %p, !range !0, !invariant.group !1
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+  %PRE = load i32, i32* %p, !range !0, !invariant.group !1
+  ret i32 %PRE
+}
+
+
+!0 = !{i32 40, i32 100}
+!1 = !{!"magic ptr"}

Added: llvm/trunk/test/Transforms/GVN/PRE/load-pre-align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/load-pre-align.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/load-pre-align.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/load-pre-align.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,44 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32"
+
+ at p = external global i32
+
+define i32 @test(i32 %n) nounwind {
+; CHECK-LABEL: @test(
+entry:
+  br label %for.cond
+
+; loads aligned greater than the memory should not be moved past conditionals
+; CHECK-NOT: load
+; CHECK: br i1
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %indvar.next, %for.inc ]
+  %cmp = icmp slt i32 %i.0, %n
+  br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:
+; ...but PRE can still move the load out of for.end to here.
+; CHECK: for.cond.for.end_crit_edge:
+; CHECK-NEXT: load
+  br label %for.end
+
+for.body:
+  %tmp3 = load i32, i32* @p, align 8
+  %dec = add i32 %tmp3, -1
+  store i32 %dec, i32* @p
+  %cmp6 = icmp slt i32 %dec, 0
+  br i1 %cmp6, label %for.body.for.end_crit_edge, label %for.inc
+
+for.body.for.end_crit_edge:
+  br label %for.end
+
+for.inc:
+  %indvar.next = add i32 %i.0, 1
+  br label %for.cond
+
+for.end:
+  %tmp9 = load i32, i32* @p, align 8
+  ret i32 %tmp9
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/load-pre-licm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/load-pre-licm.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/load-pre-licm.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/load-pre-licm.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,207 @@
+; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
+target triple = "i386-apple-darwin11.0.0"
+
+ at sortlist = external global [5001 x i32], align 4
+
+define void @Bubble() nounwind noinline {
+; CHECK: entry:
+; CHECK-NEXT: %tmp7.pre = load i32
+entry:
+  br label %while.body5
+
+; CHECK: while.body5:
+; CHECK: %tmp7 = phi i32
+; CHECK-NOT: %tmp7 = load i32
+while.body5:
+  %indvar = phi i32 [ 0, %entry ], [ %tmp6, %if.end ]
+  %tmp5 = add i32 %indvar, 2
+  %arrayidx9 = getelementptr [5001 x i32], [5001 x i32]* @sortlist, i32 0, i32 %tmp5
+  %tmp6 = add i32 %indvar, 1
+  %arrayidx = getelementptr [5001 x i32], [5001 x i32]* @sortlist, i32 0, i32 %tmp6
+  %tmp7 = load i32, i32* %arrayidx, align 4
+  %tmp10 = load i32, i32* %arrayidx9, align 4
+  %cmp11 = icmp sgt i32 %tmp7, %tmp10
+  br i1 %cmp11, label %if.then, label %if.end
+
+; CHECK: if.then:
+if.then:
+  store i32 %tmp10, i32* %arrayidx, align 4
+  store i32 %tmp7, i32* %arrayidx9, align 4
+  br label %if.end
+
+if.end:
+  %exitcond = icmp eq i32 %tmp6, 100
+  br i1 %exitcond, label %while.end.loopexit, label %while.body5
+
+while.end.loopexit:
+  ret void
+}
+
+declare void @hold(i32) readonly
+declare void @clobber()
+
+; This is a classic LICM case
+define i32 @test1(i1 %cnd, i32* %p) {
+; CHECK-LABEL: @test1
+entry: 
+; CHECK-LABEL: entry
+; CHECK-NEXT: %v1.pre = load i32, i32* %p
+  br label %header
+
+header:
+; CHECK-LABEL: header
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br label %header
+}
+
+
+; Slightly more complicated case to highlight that MemoryDependenceAnalysis
+; can compute availability for internal control flow.  In this case, because
+; the value is fully available across the backedge, we only need to establish
+; anticipation for the preheader block (which is trivial in this case.)
+define i32 @test2(i1 %cnd, i32* %p) {
+; CHECK-LABEL: @test2
+entry: 
+; CHECK-LABEL: entry
+; CHECK-NEXT: %v1.pre = load i32, i32* %p
+  br label %header
+
+header:
+; CHECK-LABEL: header
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br i1 %cnd, label %bb1, label %bb2
+
+bb1:
+  br label %merge
+
+bb2:
+  br label %merge
+
+merge:
+  br label %header
+}
+
+
+; TODO: at the moment, our anticipation check does not handle anything
+; other than straight-line unconditional fallthrough.  This particular
+; case could be solved through either a backwards anticipation walk or
+; use of the "safe to speculate" status (if we annotate the param)
+define i32 @test3(i1 %cnd, i32* %p) {
+entry: 
+; CHECK-LABEL: @test3
+; CHECK-LABEL: entry
+  br label %header
+
+header:
+  br i1 %cnd, label %bb1, label %bb2
+
+bb1:
+  br label %merge
+
+bb2:
+  br label %merge
+
+merge:
+; CHECK-LABEL: merge
+; CHECK: load i32, i32* %p
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br label %header
+}
+
+; Highlight that we can PRE into a latch block when there are multiple
+; latches only one of which clobbers an otherwise invariant value.
+define i32 @test4(i1 %cnd, i32* %p) {
+; CHECK-LABEL: @test4
+entry: 
+; CHECK-LABEL: entry
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br label %header
+
+header:
+; CHECK-LABEL: header
+  %v2 = load i32, i32* %p
+  call void @hold(i32 %v2)
+  br i1 %cnd, label %bb1, label %bb2
+
+bb1:
+  br label %header
+
+bb2:
+; CHECK-LABEL: bb2
+; CHECK:       call void @clobber()
+; CHECK-NEXT:  %v2.pre = load i32, i32* %p
+; CHECK-NEXT:  br label %header
+
+  call void @clobber()
+  br label %header
+}
+
+; Highlight the fact that we can PRE into a single clobbering latch block
+; even in loop simplify form (though multiple applications of the same
+; transformation).
+define i32 @test5(i1 %cnd, i32* %p) {
+; CHECK-LABEL: @test5
+entry: 
+; CHECK-LABEL: entry
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br label %header
+
+header:
+; CHECK-LABEL: header
+  %v2 = load i32, i32* %p
+  call void @hold(i32 %v2)
+  br i1 %cnd, label %bb1, label %bb2
+
+bb1:
+  br label %merge
+
+bb2:
+; CHECK-LABEL: bb2
+; CHECK:       call void @clobber()
+; CHECK-NEXT:  %v2.pre.pre = load i32, i32* %p
+; CHECK-NEXT:  br label %merge
+
+  call void @clobber()
+  br label %merge
+
+merge:
+  br label %header
+}
+
+declare void @llvm.experimental.guard(i1 %cnd, ...)
+
+; These two tests highlight speculation safety when we can not establish
+; anticipation (since the original load might actually not execcute)
+define i32 @test6a(i1 %cnd, i32* %p) {
+entry: 
+; CHECK-LABEL: @test6a
+  br label %header
+
+header:
+; CHECK-LABEL: header
+; CHECK: load i32, i32* %p
+  call void (i1, ...) @llvm.experimental.guard(i1 %cnd) ["deopt"()]
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br label %header
+}
+
+define i32 @test6b(i1 %cnd, i32* dereferenceable(8) %p) {
+entry: 
+; CHECK-LABEL: @test6b
+; CHECK: load i32, i32* %p
+  br label %header
+
+header:
+; CHECK-LABEL: header
+  call void (i1, ...) @llvm.experimental.guard(i1 %cnd) ["deopt"()]
+  %v1 = load i32, i32* %p
+  call void @hold(i32 %v1)
+  br label %header
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/load-pre-nonlocal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/load-pre-nonlocal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/load-pre-nonlocal.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/load-pre-nonlocal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,112 @@
+; RUN: opt -S -o - -basicaa -domtree -gvn %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.S1 = type { i32, i32 }
+
+ at a2 = common global i32* null, align 8
+ at a = common global i32* null, align 8
+ at s1 = common global %struct.S1 zeroinitializer, align 8
+
+; Check that GVN doesn't determine %2 is partially redundant.
+
+; CHECK-LABEL: define i32 @volatile_load
+; CHECK: for.body:
+; CHECK: %2 = load i32, i32*
+; CHECK: %3 = load volatile i32, i32*
+; CHECK: for.cond.for.end_crit_edge:
+
+define i32 @volatile_load(i32 %n) {
+entry:
+  %cmp6 = icmp sgt i32 %n, 0
+  br i1 %cmp6, label %for.body.lr.ph, label %for.end
+
+for.body.lr.ph:
+  %0 = load i32*, i32** @a2, align 8, !tbaa !1
+  %1 = load i32*, i32** @a, align 8, !tbaa !1
+  br label %for.body
+
+for.body:
+  %indvars.iv = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next, %for.body ]
+  %s.09 = phi i32 [ 0, %for.body.lr.ph ], [ %add, %for.body ]
+  %p.08 = phi i32* [ %0, %for.body.lr.ph ], [ %incdec.ptr, %for.body ]
+  %2 = load i32, i32* %p.08, align 4, !tbaa !5
+  %arrayidx = getelementptr inbounds i32, i32* %1, i64 %indvars.iv
+  store i32 %2, i32* %arrayidx, align 4, !tbaa !5
+  %3 = load volatile i32, i32* %p.08, align 4, !tbaa !5
+  %add = add nsw i32 %3, %s.09
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %incdec.ptr = getelementptr inbounds i32, i32* %p.08, i64 1
+  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
+  %exitcond = icmp ne i32 %lftr.wideiv, %n
+  br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:
+  %add.lcssa = phi i32 [ %add, %for.body ]
+  br label %for.end
+
+for.end:
+  %s.0.lcssa = phi i32 [ %add.lcssa, %for.cond.for.end_crit_edge ], [ 0, %entry ]
+  ret i32 %s.0.lcssa
+}
+
+; %1 is partially redundant if %0 can be widened to a 64-bit load.
+; But we should not widen %0 to 64-bit load.
+
+; CHECK-LABEL: define i32 @overaligned_load
+; CHECK: if.then:
+; CHECK-NOT:   %0 = load i64
+; CHECK-NOT:   [[LSHR:%[0-9]+]] = lshr i64 %0, 32, !dbg [[LSHR_LOC:![0-9]+]]
+; CHECK-NOT:   trunc i64 [[LSHR]] to i32
+; CHECK: if.end:
+; CHECK: %1 = load i32, i32*
+; CHECK-NOT: [[LSHR_LOC]] = !DILocation(line: 101, column: 1, scope: !{{.*}})
+
+define i32 @overaligned_load(i32 %a, i32* nocapture %b) !dbg !13 {
+entry:
+  %cmp = icmp sgt i32 %a, 0, !dbg !14
+  br i1 %cmp, label %if.then, label %if.else, !dbg !14
+
+if.then:
+  %0 = load i32, i32* getelementptr inbounds (%struct.S1, %struct.S1* @s1, i64 0, i32 0), align 8, !tbaa !5, !dbg !15
+  br label %if.end, !dbg !15
+
+if.else:
+  %arrayidx = getelementptr inbounds i32, i32* %b, i64 2, !dbg !16
+  store i32 10, i32* %arrayidx, align 4, !tbaa !5, !dbg !16
+  br label %if.end, !dbg !16
+
+if.end:
+  %i.0 = phi i32 [ %0, %if.then ], [ 0, %if.else ]
+  %p.0 = phi i32* [ getelementptr inbounds (%struct.S1, %struct.S1* @s1, i64 0, i32 0), %if.then ], [ %b, %if.else ]
+  %add.ptr = getelementptr inbounds i32, i32* %p.0, i64 1, !dbg !17
+  %1 = load i32, i32* %add.ptr, align 4, !tbaa !5, !dbg !17
+  %add1 = add nsw i32 %1, %i.0, !dbg !17
+  ret i32 %add1, !dbg !17
+}
+
+!1 = !{!2, !2, i64 0}
+!2 = !{!"any pointer", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !3, i64 0}
+
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.dbg.cu = !{!18}
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"PIC Level", i32 2}
+
+!10 = !{}
+!11 = !DISubroutineType(types: !10)
+!12 = !DIFile(filename: "test.cpp", directory: "/tmp")
+!13 = distinct !DISubprogram(name: "test", scope: !12, file: !12, line: 99, type: !11, isLocal: false, isDefinition: true, scopeLine: 100, flags: DIFlagPrototyped, isOptimized: false, unit: !18, retainedNodes: !10)
+!14 = !DILocation(line: 100, column: 1, scope: !13)
+!15 = !DILocation(line: 101, column: 1, scope: !13)
+!16 = !DILocation(line: 102, column: 1, scope: !13)
+!17 = !DILocation(line: 103, column: 1, scope: !13)
+!18 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
+                             file: !12,
+                             isOptimized: true, flags: "-O2",
+                             splitDebugFilename: "abc.debug", emissionKind: 2)

Added: llvm/trunk/test/Transforms/GVN/PRE/local-pre.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/local-pre.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/local-pre.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/local-pre.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,147 @@
+; RUN: opt < %s -gvn -enable-pre -S | FileCheck %s
+
+declare void @may_exit() nounwind
+
+declare void @may_exit_1(i32) nounwind
+
+define i32 @main(i32 %p, i32 %q) {
+
+; CHECK-LABEL: @main(
+
+block1:
+    %cmp = icmp eq i32 %p, %q 
+	br i1 %cmp, label %block2, label %block3
+
+block2:
+ %a = add i32 %p, 1
+ br label %block4
+
+block3:
+  br label %block4
+; CHECK: %.pre = add i32 %p, 1
+; CHECK-NEXT: br label %block4
+
+block4:
+  %b = add i32 %p, 1
+  ret i32 %b
+; CHECK: %b.pre-phi = phi i32 [ %.pre, %block3 ], [ %a, %block2 ]
+; CHECK-NEXT: ret i32 %b.pre-phi
+}
+
+; Don't PRE across implicit control flow.
+define i32 @test2(i32 %p, i32 %q) {
+
+; CHECK-LABEL: @test2
+; CHECK: block1:
+
+block1:
+  %cmp = icmp eq i32 %p, %q
+  br i1 %cmp, label %block2, label %block3
+
+block2:
+ %a = sdiv i32 %p, %q
+ br label %block4
+
+block3:
+  br label %block4
+
+; CHECK: block4:
+; CHECK-NEXT: call void @may_exit(
+; CHECK-NEXT: %b = sdiv
+; CHECK-NEXT: ret i32 %b
+
+block4:
+  call void @may_exit() nounwind
+  %b = sdiv i32 %p, %q
+  ret i32 %b
+}
+
+; Don't PRE across implicit control flow.
+define i32 @test3(i32 %p, i32 %q, i1 %r) {
+
+; CHECK-LABEL: @test3
+; CHECK: block1:
+
+block1:
+  br i1 %r, label %block2, label %block3
+
+block2:
+ %a = sdiv i32 %p, %q
+ br label %block4
+
+block3:
+  br label %block4
+
+block4:
+
+; CHECK: block4:
+; CHECK-NEXT: phi i32
+; CHECK-NEXT: call void @may_exit_1(
+; CHECK-NEXT: %b = sdiv
+; CHECK-NEXT: ret i32 %b
+
+  %phi = phi i32 [ 0, %block3 ], [ %a, %block2 ]
+  call void @may_exit_1(i32 %phi) nounwind
+  %b = sdiv i32 %p, %q
+  ret i32 %b
+
+}
+
+; It's OK to PRE an instruction that is guaranteed to be safe to execute
+; speculatively.
+; TODO: Does it make any sense in this case?
+define i32 @test4(i32 %p, i32 %q) {
+
+; CHECK-LABEL: @test4
+; CHECK: block1:
+
+block1:
+  %cmp = icmp eq i32 %p, %q
+  br i1 %cmp, label %block2, label %block3
+
+block2:
+ %a = sdiv i32 %p, 6
+ br label %block4
+
+block3:
+  br label %block4
+
+; CHECK: block4:
+; CHECK-NEXT: %b.pre-phi = phi i32
+; CHECK-NEXT: call void @may_exit(
+; CHECK-NEXT: ret i32 %b
+
+block4:
+  call void @may_exit() nounwind
+  %b = sdiv i32 %p, 6
+  ret i32 %b
+}
+
+; It is OK to PRE across implicit control flow if we don't insert new
+; instructions.
+define i32 @test5(i1 %cond, i32 %p, i32 %q) {
+
+; CHECK-LABEL: @test5
+; CHECK: block1:
+
+block1:
+  br i1 %cond, label %block2, label %block3
+
+block2:
+ %a = sdiv i32 %p, %q
+ br label %block4
+
+block3:
+  %b = sdiv i32 %p, %q
+  br label %block4
+
+; CHECK: block4:
+; CHECK-NEXT: %c.pre-phi = phi i32 [ %b, %block3 ], [ %a, %block2 ]
+; CHECK-NEXT: call void @may_exit()
+; CHECK-NEXT: ret i32 %c.pre-phi
+
+block4:
+  call void @may_exit() nounwind
+  %c = sdiv i32 %p, %q
+  ret i32 %c
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap-2.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -S -basicaa -gvn -enable-load-pre < %s | FileCheck %s
+;
+; The partially redundant load in bb1 should be hoisted to "bb".  This comes
+; from this C code (GCC PR 23455):
+;   unsigned outcnt;  extern void flush_outbuf(void);
+;   void bi_windup(unsigned char *outbuf, unsigned char bi_buf) {
+;     outbuf[outcnt] = bi_buf;
+;     if (outcnt == 16384)
+;       flush_outbuf();
+;     outbuf[outcnt] = bi_buf;
+;   }
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+ at outcnt = common global i32 0		; <i32*> [#uses=3]
+
+define void @bi_windup(i8* %outbuf, i8 zeroext %bi_buf) nounwind {
+entry:
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	%0 = load i32, i32* @outcnt, align 4		; <i32> [#uses=1]
+	%1 = getelementptr i8, i8* %outbuf, i32 %0		; <i8*> [#uses=1]
+	store i8 %bi_buf, i8* %1, align 1
+	%2 = load i32, i32* @outcnt, align 4		; <i32> [#uses=1]
+	%3 = icmp eq i32 %2, 16384		; <i1> [#uses=1]
+	br i1 %3, label %bb, label %bb1
+
+bb:		; preds = %entry
+	call void @flush_outbuf() nounwind
+	br label %bb1
+
+bb1:		; preds = %bb, %entry
+; CHECK: bb1:
+; CHECK-NEXT: phi
+; CHECK-NEXT: getelementptr
+	%4 = load i32, i32* @outcnt, align 4		; <i32> [#uses=1]
+	%5 = getelementptr i8, i8* %outbuf, i32 %4		; <i8*> [#uses=1]
+	store i8 %bi_buf, i8* %5, align 1
+	ret void
+}
+
+declare void @flush_outbuf()

Added: llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/lpre-call-wrap.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt -S -gvn -enable-load-pre < %s | FileCheck %s
+;
+; Make sure the load in bb3.backedge is removed and moved into bb1 after the 
+; call.  This makes the non-call case faster. 
+;
+; This test is derived from this C++ code (GCC PR 37810):
+; void g();
+; struct A { 
+;   int n; int m;
+;   A& operator++(void) { ++n; if (n == m) g(); return *this; }
+;   A() : n(0), m(0) { } 
+;   friend bool operator!=(A const& a1, A const& a2) { return a1.n != a2.n; }
+; };
+; void testfunction(A& iter) { A const end; while (iter != end) ++iter; }
+;
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+	%struct.A = type { i32, i32 }
+
+define void @_Z12testfunctionR1A(%struct.A* %iter) {
+entry:
+	%0 = getelementptr %struct.A, %struct.A* %iter, i32 0, i32 0		; <i32*> [#uses=3]
+	%1 = load i32, i32* %0, align 4		; <i32> [#uses=2]
+	%2 = icmp eq i32 %1, 0		; <i1> [#uses=1]
+	br i1 %2, label %return, label %bb.nph
+
+bb.nph:		; preds = %entry
+	%3 = getelementptr %struct.A, %struct.A* %iter, i32 0, i32 1		; <i32*> [#uses=1]
+	br label %bb
+
+bb:		; preds = %bb3.backedge, %bb.nph
+	%.rle = phi i32 [ %1, %bb.nph ], [ %7, %bb3.backedge ]		; <i32> [#uses=1]
+	%4 = add i32 %.rle, 1		; <i32> [#uses=2]
+	store i32 %4, i32* %0, align 4
+	%5 = load i32, i32* %3, align 4		; <i32> [#uses=1]
+	%6 = icmp eq i32 %4, %5		; <i1> [#uses=1]
+	br i1 %6, label %bb1, label %bb3.backedge
+
+bb1:		; preds = %bb
+	tail call void @_Z1gv()
+	br label %bb3.backedge
+
+bb3.backedge:		; preds = %bb, %bb1
+; CHECK: bb3.backedge:
+; CHECK-NEXT: phi
+; CHECK-NEXT: icmp
+	%7 = load i32, i32* %0, align 4		; <i32> [#uses=2]
+	%8 = icmp eq i32 %7, 0		; <i1> [#uses=1]
+	br i1 %8, label %return, label %bb
+
+return:		; preds = %bb3.backedge, %entry
+	ret void
+}
+
+declare void @_Z1gv()

Added: llvm/trunk/test/Transforms/GVN/PRE/nonintegral.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/nonintegral.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/nonintegral.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/nonintegral.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @nipre(double addrspace(4)** noalias %p, i64 addrspace(4)** noalias %p2, i8 %jmp) {
+
+; CHECK-LABEL: @nipre(
+; CHECK:    [[PCAST:%.*]] = bitcast double addrspace(4)** [[P:%.*]] to i64 addrspace(4)**
+; CHECK:       a:
+; CHECK:    [[L1:%.*]] = load i64 addrspace(4)*, i64 addrspace(4)** [[PCAST]]
+; CHECK:    [[TMP0:%.*]] = bitcast i64 addrspace(4)* [[L1]] to double addrspace(4)*
+; CHECK:       b:
+; CHECK:    [[L2:%.*]] = load i64 addrspace(4)*, i64 addrspace(4)** [[PCAST]]
+; CHECK:    [[TMP1:%.*]] = bitcast i64 addrspace(4)* [[L2]] to double addrspace(4)*
+; CHECK:       c:
+; CHECK-NEXT:    [[L3_PRE:%.*]] = load double addrspace(4)*, double addrspace(4)** %p
+
+entry:
+  %pcast = bitcast double addrspace(4)** %p to i64 addrspace(4)**
+  switch i8 %jmp, label %c [ i8 0, label %a
+  i8 1, label %b]
+a:
+  %l1 = load i64 addrspace(4)*, i64 addrspace(4)** %pcast
+  store i64 addrspace(4)* %l1, i64 addrspace(4)** %p2
+  br label %tail
+b:
+  %l2 = load i64 addrspace(4)*, i64 addrspace(4)** %pcast
+  store i64 addrspace(4)* %l2, i64 addrspace(4)** %p2
+  br label %tail
+c:
+  br label %tail
+tail:
+  %l3 = load double addrspace(4)*, double addrspace(4)** %p
+  %l3cast = bitcast double addrspace(4)* %l3 to i64 addrspace(4)*
+  store i64 addrspace(4)* %l3cast, i64 addrspace(4)** %p2
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/phi-translate-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/phi-translate-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/phi-translate-2.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/phi-translate-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,220 @@
+; RUN: opt < %s -debugify -gvn -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+ at a = common global [100 x i64] zeroinitializer, align 16
+ at b = common global [100 x i64] zeroinitializer, align 16
+ at g1 = common global i64 0, align 8
+ at g2 = common global i64 0, align 8
+ at g3 = common global i64 0, align 8
+declare i64 @goo(...) local_unnamed_addr #1
+
+define void @test1(i64 %a, i64 %b, i64 %c, i64 %d) {
+entry:
+  %mul = mul nsw i64 %b, %a
+  store i64 %mul, i64* @g1, align 8
+  %t0 = load i64, i64* @g2, align 8
+  %cmp = icmp sgt i64 %t0, 3
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %mul2 = mul nsw i64 %d, %c
+  store i64 %mul2, i64* @g2, align 8
+  br label %if.end
+
+; Check phi-translate works and mul is removed.
+; CHECK-LABEL: @test1(
+; CHECK: if.end:
+; CHECK: %[[MULPHI:.*]] = phi i64 [ {{.*}}, %if.then ], [ %mul, %entry ]
+; CHECK-NOT: = mul
+; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8
+if.end:                                           ; preds = %if.then, %entry
+  %b.addr.0 = phi i64 [ %d, %if.then ], [ %b, %entry ]
+  %a.addr.0 = phi i64 [ %c, %if.then ], [ %a, %entry ]
+  %mul3 = mul nsw i64 %a.addr.0, %b.addr.0
+  store i64 %mul3, i64* @g3, align 8
+  ret void
+}
+
+define void @test2(i64 %i) {
+entry:
+  %arrayidx = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i
+  %t0 = load i64, i64* %arrayidx, align 8
+  %arrayidx1 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i
+  %t1 = load i64, i64* %arrayidx1, align 8
+  %mul = mul nsw i64 %t1, %t0
+  store i64 %mul, i64* @g1, align 8
+  %cmp = icmp sgt i64 %mul, 3
+  br i1 %cmp, label %if.then, label %if.end
+
+; Check phi-translate works for the phi generated by loadpre. A new mul will be
+; inserted in if.then block.
+; CHECK-LABEL: @test2(
+; CHECK: if.then:
+; CHECK: %[[MUL_THEN:.*]] = mul
+; CHECK: br label %if.end
+if.then:                                          ; preds = %entry
+  %call = tail call i64 (...) @goo() #2
+  store i64 %call, i64* @g2, align 8
+  br label %if.end
+
+; CHECK: if.end:
+; CHECK: %[[MULPHI:.*]] = phi i64 [ %[[MUL_THEN]], %if.then ], [ %mul, %entry ]
+; CHECK-NOT: = mul
+; CHECK: store i64 %[[MULPHI]], i64* @g3, align 8
+if.end:                                           ; preds = %if.then, %entry
+  %i.addr.0 = phi i64 [ 3, %if.then ], [ %i, %entry ]
+  %arrayidx3 = getelementptr inbounds [100 x i64], [100 x i64]* @a, i64 0, i64 %i.addr.0
+  %t2 = load i64, i64* %arrayidx3, align 8
+  %arrayidx4 = getelementptr inbounds [100 x i64], [100 x i64]* @b, i64 0, i64 %i.addr.0
+  %t3 = load i64, i64* %arrayidx4, align 8
+  %mul5 = mul nsw i64 %t3, %t2
+  store i64 %mul5, i64* @g3, align 8
+  ret void
+}
+
+; Check phi-translate doesn't go through backedge, which may lead to incorrect
+; pre transformation.
+; CHECK: for.end:
+; CHECK-NOT: %{{.*pre-phi}} = phi
+; CHECK: ret void
+define void @test3(i64 %N, i64* nocapture readonly %a) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.body, %entry
+  %i.0 = phi i64 [ 0, %entry ], [ %add, %for.body ]
+  %add = add nuw nsw i64 %i.0, 1
+  %arrayidx = getelementptr inbounds i64, i64* %a, i64 %add
+  %tmp0 = load i64, i64* %arrayidx, align 8
+  %cmp = icmp slt i64 %i.0, %N
+  br i1 %cmp, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %call = tail call i64 (...) @goo() #2
+  %add1 = sub nsw i64 0, %call
+  %tobool = icmp eq i64 %tmp0, %add1
+  br i1 %tobool, label %for.cond, label %for.end
+
+for.end:                                          ; preds = %for.body, %for.cond
+  %i.0.lcssa = phi i64 [ %i.0, %for.body ], [ %i.0, %for.cond ]
+  %arrayidx2 = getelementptr inbounds i64, i64* %a, i64 %i.0.lcssa
+  %tmp1 = load i64, i64* %arrayidx2, align 8
+  store i64 %tmp1, i64* @g1, align 8
+  ret void
+}
+
+; It is incorrect to use the value of %andres in last loop iteration
+; to do pre.
+; CHECK-LABEL: @test4(
+; CHECK: for.body:
+; CHECK-NOT: %andres.pre-phi = phi i32
+; CHECK: br i1 %tobool1
+
+define i32 @test4(i32 %cond, i32 %SectionAttrs.0231.ph, i32 *%AttrFlag) {
+for.body.preheader:
+  %t514 = load volatile i32, i32* %AttrFlag
+  br label %for.body
+
+for.body:
+  %t320 = phi i32 [ %t334, %bb343 ], [ %t514, %for.body.preheader ]
+  %andres = and i32 %t320, %SectionAttrs.0231.ph
+  %tobool1 = icmp eq i32 %andres, 0
+  br i1 %tobool1, label %bb343, label %critedge.loopexit
+
+bb343:
+  %t334 = load volatile i32, i32* %AttrFlag
+  %tobool2 = icmp eq i32 %cond, 0
+  br i1 %tobool2, label %critedge.loopexit, label %for.body
+
+critedge.loopexit:
+  unreachable
+}
+
+; Check sub expression will be pre transformed.
+; CHECK-LABEL: @test5(
+; CHECK: entry:
+; CHECK: %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+; CHECK: br i1 %cmp
+; CHECK: if.then2:
+; CHECK: %[[PTRTOINT:.*]] = ptrtoint i32* %add.ptr to i64
+; CHECK: %[[SUB:.*]] = sub i64 %sub.ptr.lhs.cast, %[[PTRTOINT]]
+; CHECK: br label %if.end3
+; CHECK: if.end3:
+; CHECK: %[[PREPHI:.*]] = phi i64 [ %sub.ptr.sub, %if.else ], [ %[[SUB]], %if.then2 ], [ %sub.ptr.sub, %entry ]
+; CHECK: call void @llvm.dbg.value(metadata i32* %p.0, metadata [[var_p0:![0-9]+]], metadata !DIExpression())
+; CHECK: call void @llvm.dbg.value(metadata i64 %sub.ptr.rhs.cast5.pre-phi, metadata [[var_sub_ptr:![0-9]+]], metadata !DIExpression())
+; CHECK: %[[DIV:.*]] = ashr exact i64 %[[PREPHI]], 2
+; CHECK: ret i64 %[[DIV]]
+
+declare void @bar(...) local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i64 @test5(i32* %start, i32* %e, i32 %n1, i32 %n2) local_unnamed_addr #0 {
+entry:
+  %sub.ptr.lhs.cast = ptrtoint i32* %e to i64
+  %sub.ptr.rhs.cast = ptrtoint i32* %start to i64
+  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
+  %cmp = icmp sgt i64 %sub.ptr.sub, 4000
+  br i1 %cmp, label %if.then, label %if.end3
+
+if.then:                                          ; preds = %entry
+  %cmp1 = icmp sgt i32 %n1, %n2
+  br i1 %cmp1, label %if.then2, label %if.else
+
+if.then2:                                         ; preds = %if.then
+  %add.ptr = getelementptr inbounds i32, i32* %start, i64 800
+  br label %if.end3
+
+if.else:                                          ; preds = %if.then
+  tail call void (...) @bar() #2
+  br label %if.end3
+
+if.end3:                                          ; preds = %if.then2, %if.else, %entry
+  %p.0 = phi i32* [ %add.ptr, %if.then2 ], [ %start, %if.else ], [ %start, %entry ]
+  %sub.ptr.rhs.cast5 = ptrtoint i32* %p.0 to i64
+  %sub.ptr.sub6 = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast5
+  %sub.ptr.div7 = ashr exact i64 %sub.ptr.sub6, 2
+  ret i64 %sub.ptr.div7
+}
+
+; Here the load from arrayidx1 is partially redundant, but its value is
+; available in if.then. Check that we correctly phi-translate to the phi that
+; the load has been replaced with.
+; CHECK-LABEL: @test6
+define void @test6(i32* %ptr) {
+; CHECK: entry:
+; CHECK: %[[PREGEP:.*]] = getelementptr inbounds i32, i32* %ptr, i64 1
+; CHECK: %[[PRE:.*]] = load i32, i32* %[[PREGEP]]
+entry:
+  br label %while
+
+; CHECK: while:
+; CHECK: %[[PHI1:.*]] = phi i32 [ %[[PRE]], %entry ], [ %[[PHI2:.*]], %if.end ]
+; CHECK-NOT: load i32, i32* %arrayidx1
+; CHECK: %[[LOAD:.*]] = load i32, i32* %arrayidx2
+while:
+  %i = phi i64 [ 1, %entry ], [ %i.next, %if.end ]
+  %arrayidx1 = getelementptr inbounds i32, i32* %ptr, i64 %i
+  %0 = load i32, i32* %arrayidx1, align 4
+  %i.next = add nuw nsw i64 %i, 1
+  %arrayidx2 = getelementptr inbounds i32, i32* %ptr, i64 %i.next
+  %1 = load i32, i32* %arrayidx2, align 4
+  %cmp = icmp sgt i32 %0, %1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  store i32 %1, i32* %arrayidx1, align 4
+  store i32 %0, i32* %arrayidx2, align 4
+  br label %if.end
+
+; CHECK: if.then:
+; CHECK: %[[PHI2]] = phi i32 [ %[[PHI1]], %if.then ], [ %[[LOAD]], %while ]
+if.end:
+  br i1 undef, label %while.end, label %while
+
+while.end:
+  ret void
+}
+
+; CHECK: [[var_p0]] = !DILocalVariable
+; CHECK: [[var_sub_ptr]] = !DILocalVariable

Added: llvm/trunk/test/Transforms/GVN/PRE/phi-translate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/phi-translate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/phi-translate.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/phi-translate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+; CHECK-LABEL: @foo(
+; CHECK: entry.end_crit_edge:
+; CHECK: %[[INDEX:[a-z0-9.]+]] = sext i32 %x to i64{{$}}
+; CHECK: %[[ADDRESS:[a-z0-9.]+]] = getelementptr [100 x i32], [100 x i32]* @G, i64 0, i64 %[[INDEX]]{{$}}
+; CHECK:   %n.pre = load i32, i32* %[[ADDRESS]], !dbg [[N_LOC:![0-9]+]]
+; CHECK: br label %end
+; CHECK: then:
+; CHECK:   store i32 %z
+; CHECK: end:
+; CHECK:   %n = phi i32 [ %n.pre, %entry.end_crit_edge ], [ %z, %then ], !dbg [[N_LOC]]
+; CHECK:   ret i32 %n
+
+; CHECK: [[N_LOC]] = !DILocation(line: 47, column: 1, scope: !{{.*}})
+
+ at G = external global [100 x i32]
+define i32 @foo(i32 %x, i32 %z) !dbg !6 {
+entry:
+  %tobool = icmp eq i32 %z, 0, !dbg !7
+  br i1 %tobool, label %end, label %then, !dbg !7
+
+then:
+  %i = sext i32 %x to i64, !dbg !8
+  %p = getelementptr [100 x i32], [100 x i32]* @G, i64 0, i64 %i, !dbg !8
+  store i32 %z, i32* %p, !dbg !8
+  br label %end, !dbg !8
+
+end:
+  %j = sext i32 %x to i64, !dbg !9
+  %q = getelementptr [100 x i32], [100 x i32]* @G, i64 0, i64 %j, !dbg !10
+  %n = load i32, i32* %q, !dbg !11
+  ret i32 %n, !dbg !11
+}
+
+!llvm.module.flags = !{!0, !1, !2}
+!llvm.dbg.cu = !{!12}
+!0 = !{i32 2, !"Dwarf Version", i32 4}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = !{i32 1, !"PIC Level", i32 2}
+
+!3 = !{}
+!4 = !DISubroutineType(types: !3)
+!5 = !DIFile(filename: "a.cc", directory: "/tmp")
+!6 = distinct !DISubprogram(name: "foo", scope: !5, file: !5, line: 42, type: !4, isLocal: false, isDefinition: true, scopeLine: 43, flags: DIFlagPrototyped, isOptimized: false, unit: !12, retainedNodes: !3)
+!7 = !DILocation(line: 43, column: 1, scope: !6)
+!8 = !DILocation(line: 44, column: 1, scope: !6)
+!9 = !DILocation(line: 45, column: 1, scope: !6)
+!10 = !DILocation(line: 46, column: 1, scope: !6)
+!11 = !DILocation(line: 47, column: 1, scope: !6)
+!12 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
+                             file: !5,
+                             isOptimized: true, flags: "-O2",
+                             splitDebugFilename: "abc.debug", emissionKind: 2)

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-after-rle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-after-rle.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-after-rle.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-after-rle.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,84 @@
+; RUN: opt -gvn -S < %s | FileCheck %s
+
+declare noalias i8* @malloc(i64)
+
+; Detecting that %s is fully redundant should let us detect that %w is partially
+; redundant.
+define void @fn1(i32** noalias %start, i32* %width, i32 %h) {
+; CHECK-LABEL: @fn1
+entry:
+  %call = tail call noalias i8* @malloc(i64 1024)
+  %call.cast = bitcast i8* %call to i32*
+  store i32* %call.cast, i32** %start, align 8
+  br label %preheader
+
+preheader:
+  %cmp = icmp slt i32 1, %h
+  br i1 %cmp, label %body, label %exit
+
+; CHECK-LABEL: preheader.body_crit_edge:
+; CHECK: load i32, i32* %width, align 8
+
+; CHECK-LABEL: body:
+; CHECK-NOT: load i32*, i32** %start, align 8
+; CHECK-NOT: load i32, i32* %width, align 8
+body:
+  %j = phi i32 [ 0, %preheader ], [ %j.next, %body ]
+  %s = load i32*, i32** %start, align 8
+  %idx = getelementptr inbounds i32, i32* %s, i64 0
+  store i32 0, i32* %idx, align 4
+  %j.next = add nuw nsw i32 %j, 1
+  %w = load i32, i32* %width, align 8
+  %cmp3 = icmp slt i32 %j.next, %w
+  br i1 %cmp3, label %body, label %preheader
+
+exit:
+  ret void
+}
+
+; %s is fully redundant but has more than one available value. Detecting that
+; %w is partially redundant requires alias analysis that can analyze those
+; values.
+define void @fn2(i32** noalias %start, i32* %width, i32 %h, i32 %arg) {
+; CHECK-LABEL: @fn2
+entry:
+  %call = tail call noalias i8* @malloc(i64 1024)
+  %call.cast = bitcast i8* %call to i32*
+  %cmp1 = icmp slt i32 %arg, 0
+  br i1 %cmp1, label %if, label %else
+
+if:
+  store i32* %call.cast, i32** %start, align 8
+  br label %preheader
+
+else:
+  %gep = getelementptr inbounds i32, i32* %call.cast, i32 %arg
+  store i32* %gep, i32** %start, align 8
+  br label %preheader
+
+; CHECK-LABEL: preheader:
+; CHECK: %s = phi i32* [ %s, %body ], [ %gep, %else ], [ %call.cast, %if ]
+
+preheader:
+  %cmp = icmp slt i32 1, %h
+  br i1 %cmp, label %body, label %exit
+
+; CHECK-LABEL: preheader.body_crit_edge:
+; CHECK: load i32, i32* %width, align 8
+
+; CHECK-LABEL: body:
+; CHECK-NOT: load i32*, i32** %start, align 8
+; CHECK-NOT: load i32, i32* %width, align 8
+body:
+  %j = phi i32 [ 0, %preheader ], [ %j.next, %body ]
+  %s = load i32*, i32** %start, align 8
+  %idx = getelementptr inbounds i32, i32* %s, i64 0
+  store i32 0, i32* %idx, align 4
+  %j.next = add nuw nsw i32 %j, 1
+  %w = load i32, i32* %width, align 8
+  %cmp3 = icmp slt i32 %j.next, %w
+  br i1 %cmp3, label %body, label %preheader
+
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-basic-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-basic-add.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-basic-add.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-basic-add.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,32 @@
+; RUN: opt < %s -gvn -enable-pre -S | FileCheck %s
+
+ at H = common global i32 0		; <i32*> [#uses=2]
+ at G = common global i32 0		; <i32*> [#uses=1]
+
+define i32 @test() nounwind {
+entry:
+	%0 = load i32, i32* @H, align 4		; <i32> [#uses=2]
+	%1 = call i32 (...) @foo() nounwind		; <i32> [#uses=1]
+	%2 = icmp ne i32 %1, 0		; <i1> [#uses=1]
+	br i1 %2, label %bb, label %bb1
+
+bb:		; preds = %entry
+	%3 = add i32 %0, 42		; <i32> [#uses=1]
+; CHECK: %.pre = add i32 %0, 42
+	store i32 %3, i32* @G, align 4
+	br label %bb1
+
+bb1:		; preds = %bb, %entry
+	%4 = add i32 %0, 42		; <i32> [#uses=1]
+	store i32 %4, i32* @H, align 4
+	br label %return
+
+; CHECK: %.pre-phi = phi i32 [ %.pre, %entry.bb1_crit_edge ], [ %3, %bb ]
+; CHECK-NEXT: store i32 %.pre-phi, i32* @H, align 4
+; CHECK-NEXT: ret i32 0
+
+return:		; preds = %bb1
+	ret i32 0
+}
+
+declare i32 @foo(...)

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-gep-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-gep-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-gep-load.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-gep-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,130 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=gvn -enable-load-pre -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+define double @foo(i32 %stat, i32 %i, double** %p) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[STAT:%.*]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 0, label [[SW_BB:%.*]]
+; CHECK-NEXT:    i32 1, label [[SW_BB]]
+; CHECK-NEXT:    i32 2, label [[ENTRY_SW_BB2_CRIT_EDGE:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       entry.sw.bb2_crit_edge:
+; CHECK-NEXT:    [[DOTPRE:%.*]] = load double*, double** [[P:%.*]], align 8
+; CHECK-NEXT:    [[DOTPRE1:%.*]] = sext i32 [[I:%.*]] to i64
+; CHECK-NEXT:    [[ARRAYIDX5_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds double, double* [[DOTPRE]], i64 [[DOTPRE1]]
+; CHECK-NEXT:    [[DOTPRE2:%.*]] = load double, double* [[ARRAYIDX5_PHI_TRANS_INSERT]], align 8
+; CHECK-NEXT:    br label [[SW_BB2:%.*]]
+; CHECK:       sw.bb:
+; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I]] to i64
+; CHECK-NEXT:    [[TMP0:%.*]] = load double*, double** [[P]], align 8
+; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[TMP0]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = load double, double* [[ARRAYIDX1]], align 8
+; CHECK-NEXT:    [[SUB:%.*]] = fsub double [[TMP1]], 1.000000e+00
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[SUB]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    br label [[RETURN:%.*]]
+; CHECK:       if.end:
+; CHECK-NEXT:    br label [[SW_BB2]]
+; CHECK:       sw.bb2:
+; CHECK-NEXT:    [[TMP2:%.*]] = phi double [ [[DOTPRE2]], [[ENTRY_SW_BB2_CRIT_EDGE]] ], [ [[TMP1]], [[IF_END]] ]
+; CHECK-NEXT:    [[IDXPROM3_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE1]], [[ENTRY_SW_BB2_CRIT_EDGE]] ], [ [[IDXPROM]], [[IF_END]] ]
+; CHECK-NEXT:    [[TMP3:%.*]] = phi double* [ [[DOTPRE]], [[ENTRY_SW_BB2_CRIT_EDGE]] ], [ [[TMP0]], [[IF_END]] ]
+; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds double, double* [[TMP3]], i64 [[IDXPROM3_PRE_PHI]]
+; CHECK-NEXT:    [[SUB6:%.*]] = fsub double 3.000000e+00, [[TMP2]]
+; CHECK-NEXT:    store double [[SUB6]], double* [[ARRAYIDX5]]
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.default:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi double [ 0.000000e+00, [[SW_DEFAULT]] ], [ [[SUB6]], [[SW_BB2]] ], [ [[SUB]], [[IF_THEN]] ]
+; CHECK-NEXT:    ret double [[RETVAL_0]]
+;
+entry:
+  switch i32 %stat, label %sw.default [
+  i32 0, label %sw.bb
+  i32 1, label %sw.bb
+  i32 2, label %sw.bb2
+  ]
+
+sw.bb:                                            ; preds = %entry, %entry
+  %idxprom = sext i32 %i to i64
+  %arrayidx = getelementptr inbounds double*, double** %p, i64 0
+  %0 = load double*, double** %arrayidx, align 8
+  %arrayidx1 = getelementptr inbounds double, double* %0, i64 %idxprom
+  %1 = load double, double* %arrayidx1, align 8
+  %sub = fsub double %1, 1.000000e+00
+  %cmp = fcmp olt double %sub, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %sw.bb
+  br label %return
+
+if.end:                                           ; preds = %sw.bb
+  br label %sw.bb2
+
+sw.bb2:                                           ; preds = %if.end, %entry
+  %idxprom3 = sext i32 %i to i64
+  %arrayidx4 = getelementptr inbounds double*, double** %p, i64 0
+  %2 = load double*, double** %arrayidx4, align 8
+  %arrayidx5 = getelementptr inbounds double, double* %2, i64 %idxprom3
+  %3 = load double, double* %arrayidx5, align 8
+  %sub6 = fsub double 3.000000e+00, %3
+  store double %sub6, double* %arrayidx5
+  br label %return
+
+sw.default:                                       ; preds = %entry
+  br label %return
+
+return:                                           ; preds = %sw.default, %sw.bb2, %if.then
+  %retval.0 = phi double [ 0.000000e+00, %sw.default ], [ %sub6, %sw.bb2 ], [ %sub, %if.then ]
+  ret double %retval.0
+}
+
+; The load causes the GEP's operands to be PREd earlier than normal. The
+; resulting sext ends up in pre.dest and in the GVN system before that BB is
+; actually processed. Make sure we can deal with the situation.
+
+define void @test_shortcut_safe(i1 %tst, i32 %p1, i32* %a) {
+; CHECK-LABEL: @test_shortcut_safe(
+; CHECK-NEXT:    br i1 [[TST:%.*]], label [[SEXT1:%.*]], label [[DOTPRE_DEST_CRIT_EDGE:%.*]]
+; CHECK:       .pre.dest_crit_edge:
+; CHECK-NEXT:    [[DOTPRE1:%.*]] = sext i32 [[P1:%.*]] to i64
+; CHECK-NEXT:    br label [[PRE_DEST:%.*]]
+; CHECK:       pre.dest:
+; CHECK-NEXT:    [[DOTPRE_PRE_PHI:%.*]] = phi i64 [ [[DOTPRE1]], [[DOTPRE_DEST_CRIT_EDGE]] ], [ [[IDXPROM2_PRE_PHI:%.*]], [[SEXT_USE:%.*]] ]
+; CHECK-NEXT:    br label [[SEXT_USE]]
+; CHECK:       sext1:
+; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[P1]] to i64
+; CHECK-NEXT:    br label [[SEXT_USE]]
+; CHECK:       sext.use:
+; CHECK-NEXT:    [[IDXPROM2_PRE_PHI]] = phi i64 [ [[IDXPROM]], [[SEXT1]] ], [ [[DOTPRE_PRE_PHI]], [[PRE_DEST]] ]
+; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[IDXPROM2_PRE_PHI]]
+; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[ARRAYIDX3]], align 4
+; CHECK-NEXT:    tail call void @g(i32 [[VAL]])
+; CHECK-NEXT:    br label [[PRE_DEST]]
+;
+
+  br i1 %tst, label %sext1, label %pre.dest
+
+pre.dest:
+  br label %sext.use
+
+sext1:
+  %idxprom = sext i32 %p1 to i64
+  br label %sext.use
+
+sext.use:
+  %idxprom2 = sext i32 %p1 to i64
+  %arrayidx3 = getelementptr inbounds i32, i32* %a, i64 %idxprom2
+  %val = load i32, i32* %arrayidx3, align 4
+  tail call void (i32) @g(i32 %val)
+  br label %pre.dest
+}
+
+declare void @g(i32)

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-jt-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-jt-add.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-jt-add.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-jt-add.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -gvn -enable-pre -jump-threading -S | FileCheck %s
+
+ at H = common global i32 0
+ at G = common global i32 0
+
+define i32 @test(i1 %cond, i32 %v) nounwind {
+; CHECK-LABEL: @test
+entry:
+  br i1 %cond, label %bb, label %bb1
+
+bb:
+; CHECK: store
+; CHECK-NOT: br label %return
+  %add.1 = add nuw nsw i32 %v, -1
+  store i32 %add.1, i32* @G, align 4
+  br label %merge
+
+bb1:
+  br label %merge
+
+merge:
+  %add.2 = add i32 %v, -1
+  %cmp = icmp sgt i32 %add.2, 0
+  br i1 %cmp, label %action, label %return
+
+action:
+; CHECK: store
+; CHECK-NEXT: br label %return
+  store i32 %add.2, i32* @H, align 4
+  br label %return
+
+return:
+  %p = phi i32 [0, %merge], [1, %action]
+  ret i32 %p
+}
+

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-load-guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-load-guards.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-load-guards.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-load-guards.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,146 @@
+; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+declare void @llvm.experimental.guard(i1, ...)
+
+; This is a motivating example on why we prohibit hoisting through guards.
+; In the bottom block, we check that the index is within bounds and only access
+; the element in this case and deoptimize otherwise. If we hoist the load to a
+; place above the guard, it will may lead to out-of-bound array access.
+define i32 @test_motivation(i32* %p, i32* %q, i1 %C, i32 %index, i32 %len) {
+; CHECK-LABEL: @test_motivation(
+block1:
+  %el1 = getelementptr inbounds i32, i32* %q, i32 %index
+  %el2 = getelementptr inbounds i32, i32* %p, i32 %index
+	br i1 %C, label %block2, label %block3
+
+block2:
+
+; CHECK:        block2:
+; CHECK-NEXT:     br
+; CHECK-NOT:      load
+; CHECK-NOT:      sge
+; CHECK-NOT:      slt
+; CHECK-NOT:      and
+  br label %block4
+
+block3:
+  store i32 0, i32* %el1
+  br label %block4
+
+block4:
+
+; CHECK:        block4:
+; CHECK:          %cond1 = icmp sge i32 %index, 0
+; CHECK-NEXT:     %cond2 = icmp slt i32 %index, %len
+; CHECK-NEXT:     %in.bounds = and i1 %cond1, %cond2
+; CHECK:          call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds)
+; CHECK-NEXT:     %PRE = load i32, i32* %P2
+; CHECK:          ret i32 %PRE
+
+  %P2 = phi i32* [%el2, %block3], [%el1, %block2]
+  %cond1 = icmp sge i32 %index, 0
+  %cond2 = icmp slt i32 %index, %len
+  %in.bounds = and i1 %cond1, %cond2
+  call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds) [ "deopt"() ]
+  %PRE = load i32, i32* %P2
+  ret i32 %PRE
+}
+
+; Guard in load's block that is above the load should prohibit the PRE.
+define i32 @test_guard_01(i32* %p, i32* %q, i1 %C, i1 %G) {
+; CHECK-LABEL: @test_guard_01(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+
+; CHECK:        block2:
+; CHECK-NEXT:     br
+; CHECK-NOT:      load
+
+ br label %block4
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+
+; CHECK:        block4:
+; CHECK:          call void (i1, ...) @llvm.experimental.guard(i1 %G)
+; CHECK-NEXT:     load
+; CHECK:          ret i32
+
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
+  %PRE = load i32, i32* %P2
+  ret i32 %PRE
+}
+
+; Guard in load's block that is below the load should not prohibit the PRE.
+define i32 @test_guard_02(i32* %p, i32* %q, i1 %C, i1 %G) {
+; CHECK-LABEL: @test_guard_02(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+
+; CHECK:        block2:
+; CHECK-NEXT:     load i32, i32* %q
+
+ br label %block4
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+
+; CHECK:        block4:
+; CHECK-NEXT:     phi i32 [
+; CHECK-NEXT:     phi i32* [
+; CHECK-NEXT:     call void (i1, ...) @llvm.experimental.guard(i1 %G)
+; CHECK-NOT:      load
+; CHECK:          ret i32
+
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  %PRE = load i32, i32* %P2
+  call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
+  ret i32 %PRE
+}
+
+; Guard above the load's block should prevent PRE from hoisting through it.
+define i32 @test_guard_03(i32* %p, i32* %q, i1 %C, i1 %G) {
+; CHECK-LABEL: @test_guard_03(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+
+; CHECK:        block2:
+; CHECK-NEXT:     br
+; CHECK-NOT:      load
+
+ br label %block4
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+
+; CHECK:        block4:
+; CHECK-NEXT:     phi i32*
+; CHECK-NEXT:     call void (i1, ...) @llvm.experimental.guard(i1 %G)
+; CHECK-NEXT:     load
+; CHECK-NEXT:     ret i32
+
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
+  br label %block5
+
+block5:
+  %PRE = load i32, i32* %P2
+  ret i32 %PRE
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-load-implicit-cf-updates.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-load-implicit-cf-updates.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-load-implicit-cf-updates.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-load-implicit-cf-updates.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,118 @@
+; RUN: opt -S -gvn -enable-load-pre < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; These tests exercise situations when instructions that were first instructions
+; with implicit control flow get removed. We make sure that after that we don't
+; face crashes and are still able to perform PRE correctly.
+
+declare i32 @foo(i32 %arg) #0
+
+define hidden void @test_01(i32 %x, i32 %y) {
+
+; c2 only throws if c1 throws, so it can be safely removed and then PRE can
+; hoist the load out of loop.
+
+; CHECK-LABEL: @test_01
+; CHECK:       entry:
+; CHECK-NEXT:    %c1 = call i32 @foo(i32 %x)
+; CHECK-NEXT:    %val.pre = load i32, i32* null, align 8
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    %c3 = call i32 @foo(i32 %val.pre)
+; CHECK-NEXT:    br label %loop
+
+entry:
+  %c1 = call i32 @foo(i32 %x)
+  br label %loop
+
+loop:
+  %c2 = call i32 @foo(i32 %x)
+  %val = load i32, i32* null, align 8
+  %c3 = call i32 @foo(i32 %val)
+  br label %loop
+}
+
+define hidden void @test_02(i32 %x, i32 %y) {
+
+; PRE is not allowed because c2 may throw.
+
+; CHECK-LABEL: @test_02
+; CHECK:       entry:
+; CHECK-NEXT:    %c1 = call i32 @foo(i32 %x)
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    %c2 = call i32 @foo(i32 %y)
+; CHECK-NEXT:    %val = load i32, i32* null, align 8
+; CHECK-NEXT:    %c3 = call i32 @foo(i32 %val)
+; CHECK-NEXT:    br label %loop
+
+entry:
+  %c1 = call i32 @foo(i32 %x)
+  br label %loop
+
+loop:
+  %c2 = call i32 @foo(i32 %y)
+  %val = load i32, i32* null, align 8
+  %c3 = call i32 @foo(i32 %val)
+  br label %loop
+}
+
+define hidden void @test_03(i32 %x, i32 %y) {
+
+; PRE of load is allowed because c2 only throws if c1 throws. c3 should
+; not be eliminated. c4 is eliminated because it only throws if c3 throws.
+
+; CHECK-LABEL: @test_03
+; CHECK:       entry:
+; CHECK-NEXT:    %c1 = call i32 @foo(i32 %x)
+; CHECK-NEXT:    %val.pre = load i32, i32* null, align 8
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    %c3 = call i32 @foo(i32 %y)
+; CHECK-NEXT:    %c5 = call i32 @foo(i32 %val.pre)
+; CHECK-NEXT:    br label %loop
+
+entry:
+  %c1 = call i32 @foo(i32 %x)
+  br label %loop
+
+loop:
+  %c2 = call i32 @foo(i32 %x)
+  %val = load i32, i32* null, align 8
+  %c3 = call i32 @foo(i32 %y)
+  %val2 = load i32, i32* null, align 8
+  %c4 = call i32 @foo(i32 %y)
+  %c5 = call i32 @foo(i32 %val)
+  br label %loop
+}
+
+define hidden void @test_04(i32 %x, i32 %y) {
+
+; PRE is not allowed even after we remove c2 because now c3 prevents us from it.
+
+; CHECK-LABEL: @test_04
+; CHECK:       entry:
+; CHECK-NEXT:    %c1 = call i32 @foo(i32 %x)
+; CHECK-NEXT:    br label %loop
+; CHECK:       loop:
+; CHECK-NEXT:    %c3 = call i32 @foo(i32 %y)
+; CHECK-NEXT:    %val = load i32, i32* null, align 8
+; CHECK-NEXT:    %c5 = call i32 @foo(i32 %val)
+; CHECK-NEXT:    br label %loop
+
+entry:
+  %c1 = call i32 @foo(i32 %x)
+  br label %loop
+
+loop:
+  %c2 = call i32 @foo(i32 %x)
+  %c3 = call i32 @foo(i32 %y)
+  %val = load i32, i32* null, align 8
+  %c4 = call i32 @foo(i32 %y)
+  %c5 = call i32 @foo(i32 %val)
+  br label %loop
+}
+
+attributes #0 = { readnone }

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-load.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,590 @@
+; RUN: opt < %s -basicaa -gvn -enable-load-pre -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"
+
+define i32 @test1(i32* %p, i1 %C) {
+; CHECK-LABEL: @test1(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+ br label %block4
+; CHECK: block2:
+; CHECK-NEXT: load i32, i32* %p
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+  %PRE = load i32, i32* %p
+  ret i32 %PRE
+; CHECK: block4:
+; CHECK-NEXT: phi i32
+; CHECK-NEXT: ret i32
+}
+
+; This is a simple phi translation case.
+define i32 @test2(i32* %p, i32* %q, i1 %C) {
+; CHECK-LABEL: @test2(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+ br label %block4
+; CHECK: block2:
+; CHECK-NEXT: load i32, i32* %q
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  %PRE = load i32, i32* %P2
+  ret i32 %PRE
+; CHECK: block4:
+; CHECK-NEXT: phi i32 [
+; CHECK-NOT: load
+; CHECK: ret i32
+}
+
+; This is a PRE case that requires phi translation through a GEP.
+define i32 @test3(i32* %p, i32* %q, i32** %Hack, i1 %C) {
+; CHECK-LABEL: @test3(
+block1:
+  %B = getelementptr i32, i32* %q, i32 1
+  store i32* %B, i32** %Hack
+	br i1 %C, label %block2, label %block3
+
+block2:
+ br label %block4
+; CHECK: block2:
+; CHECK-NEXT: load i32, i32* %B
+
+block3:
+  %A = getelementptr i32, i32* %p, i32 1
+  store i32 0, i32* %A
+  br label %block4
+
+block4:
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  %P3 = getelementptr i32, i32* %P2, i32 1
+  %PRE = load i32, i32* %P3
+  ret i32 %PRE
+; CHECK: block4:
+; CHECK: phi i32 [
+; CHECK-NOT: load
+; CHECK: ret i32
+}
+
+;; Here the loaded address is available, but the computation is in 'block3'
+;; which does not dominate 'block2'.
+define i32 @test4(i32* %p, i32* %q, i32** %Hack, i1 %C) {
+; CHECK-LABEL: @test4(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+ br label %block4
+; CHECK: block2:
+; CHECK:   load i32, i32*
+; CHECK:   br label %block4
+
+block3:
+  %B = getelementptr i32, i32* %q, i32 1
+  store i32* %B, i32** %Hack
+
+  %A = getelementptr i32, i32* %p, i32 1
+  store i32 0, i32* %A
+  br label %block4
+
+block4:
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  %P3 = getelementptr i32, i32* %P2, i32 1
+  %PRE = load i32, i32* %P3
+  ret i32 %PRE
+; CHECK: block4:
+; CHECK: phi i32 [
+; CHECK-NOT: load
+; CHECK: ret i32
+}
+
+;void test5(int N, double *G) {
+;  int j;
+;  for (j = 0; j < N - 1; j++)
+;    G[j] = G[j] + G[j+1];
+;}
+
+define void @test5(i32 %N, double* nocapture %G) nounwind ssp {
+; CHECK-LABEL: @test5(
+entry:
+  %0 = add i32 %N, -1           
+  %1 = icmp sgt i32 %0, 0       
+  br i1 %1, label %bb.nph, label %return
+
+bb.nph:                         
+  %tmp = zext i32 %0 to i64     
+  br label %bb
+
+; CHECK: bb.nph:
+; CHECK: load double, double*
+; CHECK: br label %bb
+
+bb:             
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ]
+  %tmp6 = add i64 %indvar, 1                    
+  %scevgep = getelementptr double, double* %G, i64 %tmp6
+  %scevgep7 = getelementptr double, double* %G, i64 %indvar
+  %2 = load double, double* %scevgep7, align 8
+  %3 = load double, double* %scevgep, align 8 
+  %4 = fadd double %2, %3             
+  store double %4, double* %scevgep7, align 8
+  %exitcond = icmp eq i64 %tmp6, %tmp 
+  br i1 %exitcond, label %return, label %bb
+
+; Should only be one load in the loop.
+; CHECK: bb:
+; CHECK: load double, double*
+; CHECK-NOT: load double, double*
+; CHECK: br i1 %exitcond
+
+return:                               
+  ret void
+}
+
+;void test6(int N, double *G) {
+;  int j;
+;  for (j = 0; j < N - 1; j++)
+;    G[j+1] = G[j] + G[j+1];
+;}
+
+define void @test6(i32 %N, double* nocapture %G) nounwind ssp {
+; CHECK-LABEL: @test6(
+entry:
+  %0 = add i32 %N, -1           
+  %1 = icmp sgt i32 %0, 0       
+  br i1 %1, label %bb.nph, label %return
+
+bb.nph:                         
+  %tmp = zext i32 %0 to i64     
+  br label %bb
+
+; CHECK: bb.nph:
+; CHECK: load double, double*
+; CHECK: br label %bb
+
+bb:             
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp6, %bb ]
+  %tmp6 = add i64 %indvar, 1                    
+  %scevgep = getelementptr double, double* %G, i64 %tmp6
+  %scevgep7 = getelementptr double, double* %G, i64 %indvar
+  %2 = load double, double* %scevgep7, align 8
+  %3 = load double, double* %scevgep, align 8 
+  %4 = fadd double %2, %3             
+  store double %4, double* %scevgep, align 8
+  %exitcond = icmp eq i64 %tmp6, %tmp 
+  br i1 %exitcond, label %return, label %bb
+
+; Should only be one load in the loop.
+; CHECK: bb:
+; CHECK: load double, double*
+; CHECK-NOT: load double, double*
+; CHECK: br i1 %exitcond
+
+return:                               
+  ret void
+}
+
+;void test7(int N, double* G) {
+;  long j;
+;  G[1] = 1;
+;  for (j = 1; j < N - 1; j++)
+;      G[j+1] = G[j] + G[j+1];
+;}
+
+; This requires phi translation of the adds.
+define void @test7(i32 %N, double* nocapture %G) nounwind ssp {
+entry:
+  %0 = getelementptr inbounds double, double* %G, i64 1   
+  store double 1.000000e+00, double* %0, align 8
+  %1 = add i32 %N, -1                             
+  %2 = icmp sgt i32 %1, 1                         
+  br i1 %2, label %bb.nph, label %return
+
+bb.nph:                                           
+  %tmp = sext i32 %1 to i64                       
+  %tmp7 = add i64 %tmp, -1                        
+  br label %bb
+
+bb:                                               
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ] 
+  %tmp8 = add i64 %indvar, 2                      
+  %scevgep = getelementptr double, double* %G, i64 %tmp8  
+  %tmp9 = add i64 %indvar, 1                      
+  %scevgep10 = getelementptr double, double* %G, i64 %tmp9 
+  %3 = load double, double* %scevgep10, align 8           
+  %4 = load double, double* %scevgep, align 8             
+  %5 = fadd double %3, %4                         
+  store double %5, double* %scevgep, align 8
+  %exitcond = icmp eq i64 %tmp9, %tmp7            
+  br i1 %exitcond, label %return, label %bb
+
+; Should only be one load in the loop.
+; CHECK: bb:
+; CHECK: load double, double*
+; CHECK-NOT: load double, double*
+; CHECK: br i1 %exitcond
+
+return:                                           
+  ret void
+}
+
+;; Here the loaded address isn't available in 'block2' at all, requiring a new
+;; GEP to be inserted into it.
+define i32 @test8(i32* %p, i32* %q, i32** %Hack, i1 %C) {
+; CHECK-LABEL: @test8(
+block1:
+	br i1 %C, label %block2, label %block3
+
+block2:
+ br label %block4
+; CHECK: block2:
+; CHECK:   load i32, i32*
+; CHECK:   br label %block4
+
+block3:
+  %A = getelementptr i32, i32* %p, i32 1
+  store i32 0, i32* %A
+  br label %block4
+
+block4:
+  %P2 = phi i32* [%p, %block3], [%q, %block2]
+  %P3 = getelementptr i32, i32* %P2, i32 1
+  %PRE = load i32, i32* %P3
+  ret i32 %PRE
+; CHECK: block4:
+; CHECK: phi i32 [
+; CHECK-NOT: load
+; CHECK: ret i32
+}
+
+;void test9(int N, double* G) {
+;  long j;
+;  for (j = 1; j < N - 1; j++)
+;      G[j+1] = G[j] + G[j+1];
+;}
+
+; This requires phi translation of the adds.
+define void @test9(i32 %N, double* nocapture %G) nounwind ssp {
+entry:
+  add i32 0, 0
+  %1 = add i32 %N, -1                             
+  %2 = icmp sgt i32 %1, 1                         
+  br i1 %2, label %bb.nph, label %return
+
+bb.nph:                                           
+  %tmp = sext i32 %1 to i64                       
+  %tmp7 = add i64 %tmp, -1                        
+  br label %bb
+
+; CHECK: bb.nph:
+; CHECK:   load double, double*
+; CHECK:   br label %bb
+
+bb:                                               
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp9, %bb ] 
+  %tmp8 = add i64 %indvar, 2                      
+  %scevgep = getelementptr double, double* %G, i64 %tmp8  
+  %tmp9 = add i64 %indvar, 1                      
+  %scevgep10 = getelementptr double, double* %G, i64 %tmp9 
+  %3 = load double, double* %scevgep10, align 8           
+  %4 = load double, double* %scevgep, align 8             
+  %5 = fadd double %3, %4                         
+  store double %5, double* %scevgep, align 8
+  %exitcond = icmp eq i64 %tmp9, %tmp7            
+  br i1 %exitcond, label %return, label %bb
+
+; Should only be one load in the loop.
+; CHECK: bb:
+; CHECK: load double, double*
+; CHECK-NOT: load double, double*
+; CHECK: br i1 %exitcond
+
+return:                                           
+  ret void
+}
+
+;void test10(int N, double* G) {
+;  long j;
+;  for (j = 1; j < N - 1; j++)
+;      G[j] = G[j] + G[j+1] + G[j-1];
+;}
+
+; PR5501
+define void @test10(i32 %N, double* nocapture %G) nounwind ssp {
+entry:
+  %0 = add i32 %N, -1
+  %1 = icmp sgt i32 %0, 1
+  br i1 %1, label %bb.nph, label %return
+
+bb.nph:
+  %tmp = sext i32 %0 to i64
+  %tmp8 = add i64 %tmp, -1
+  br label %bb
+; CHECK: bb.nph:
+; CHECK:   load double, double*
+; CHECK:   load double, double*
+; CHECK:   br label %bb
+
+
+bb:
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp11, %bb ]
+  %scevgep = getelementptr double, double* %G, i64 %indvar
+  %tmp9 = add i64 %indvar, 2
+  %scevgep10 = getelementptr double, double* %G, i64 %tmp9
+  %tmp11 = add i64 %indvar, 1
+  %scevgep12 = getelementptr double, double* %G, i64 %tmp11
+  %2 = load double, double* %scevgep12, align 8
+  %3 = load double, double* %scevgep10, align 8
+  %4 = fadd double %2, %3
+  %5 = load double, double* %scevgep, align 8
+  %6 = fadd double %4, %5
+  store double %6, double* %scevgep12, align 8
+  %exitcond = icmp eq i64 %tmp11, %tmp8
+  br i1 %exitcond, label %return, label %bb
+
+; Should only be one load in the loop.
+; CHECK: bb:
+; CHECK: load double, double*
+; CHECK-NOT: load double, double*
+; CHECK: br i1 %exitcond
+
+return:
+  ret void
+}
+
+; Test critical edge splitting.
+define i32 @test11(i32* %p, i1 %C, i32 %N) {
+; CHECK-LABEL: @test11(
+block1:
+        br i1 %C, label %block2, label %block3
+
+block2:
+ %cond = icmp sgt i32 %N, 1
+ br i1 %cond, label %block4, label %block5
+; CHECK: load i32, i32* %p
+; CHECK-NEXT: br label %block4
+
+block3:
+  store i32 0, i32* %p
+  br label %block4
+
+block4:
+  %PRE = load i32, i32* %p
+  br label %block5
+
+block5:
+  %ret = phi i32 [ 0, %block2 ], [ %PRE, %block4 ]
+  ret i32 %ret
+; CHECK: block4:
+; CHECK-NEXT: phi i32
+}
+
+declare void @f()
+declare void @g(i32)
+declare i32 @__CxxFrameHandler3(...)
+
+; Test that loads aren't PRE'd into EH pads.
+define void @test12(i32* %p) personality i32 (...)* @__CxxFrameHandler3 {
+; CHECK-LABEL: @test12(
+block1:
+  invoke void @f()
+          to label %block2 unwind label %catch.dispatch
+
+block2:
+  invoke void @f()
+          to label %block3 unwind label %cleanup
+
+block3:
+  ret void
+
+catch.dispatch:
+  %cs1 = catchswitch within none [label %catch] unwind label %cleanup2
+
+catch:
+  %c = catchpad within %cs1 []
+  catchret from %c to label %block2
+
+cleanup:
+  %c1 = cleanuppad within none []
+  store i32 0, i32* %p
+  cleanupret from %c1 unwind label %cleanup2
+
+; CHECK: cleanup2:
+; CHECK-NOT: phi
+; CHECK-NEXT: %c2 = cleanuppad within none []
+; CHECK-NEXT: %NOTPRE = load i32, i32* %p
+cleanup2:
+  %c2 = cleanuppad within none []
+  %NOTPRE = load i32, i32* %p
+  call void @g(i32 %NOTPRE)
+  cleanupret from %c2 unwind to caller
+}
+
+; Don't PRE load across potentially throwing calls.
+
+define i32 @test13(i32* noalias nocapture readonly %x, i32* noalias nocapture %r, i32 %a) {
+
+; CHECK-LABEL: @test13(
+; CHECK: entry:
+; CHECK-NEXT: icmp eq
+; CHECK-NEXT: br i1
+
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+; CHECK: if.then:
+; CHECK-NEXT: load i32
+; CHECK-NEXT: store i32
+
+if.then:
+  %uu = load i32, i32* %x, align 4
+  store i32 %uu, i32* %r, align 4
+  br label %if.end
+
+; CHECK: if.end:
+; CHECK-NEXT: call void @f()
+; CHECK-NEXT: load i32
+
+if.end:
+  call void @f()
+  %vv = load i32, i32* %x, align 4
+  ret i32 %vv
+}
+
+; Same as test13, but now the blocking function is not immediately in load's
+; block.
+
+define i32 @test14(i32* noalias nocapture readonly %x, i32* noalias nocapture %r, i32 %a) {
+
+; CHECK-LABEL: @test14(
+; CHECK: entry:
+; CHECK-NEXT: icmp eq
+; CHECK-NEXT: br i1
+
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+; CHECK: if.then:
+; CHECK-NEXT: load i32
+; CHECK-NEXT: store i32
+
+if.then:
+  %uu = load i32, i32* %x, align 4
+  store i32 %uu, i32* %r, align 4
+  br label %if.end
+
+; CHECK: if.end:
+; CHECK-NEXT: call void @f()
+; CHECK-NEXT: load i32
+
+if.end:
+  call void @f()
+  br label %follow_1
+
+follow_1:
+  br label %follow_2
+
+follow_2:
+  %vv = load i32, i32* %x, align 4
+  ret i32 %vv
+}
+
+; Same as test13, but %x here is dereferenceable. A pointer that is
+; dereferenceable can be loaded from speculatively without a risk of trapping.
+; Since it is OK to speculate, PRE is allowed.
+
+define i32 @test15(i32* noalias nocapture readonly dereferenceable(8) %x, i32* noalias nocapture %r, i32 %a) {
+
+; CHECK-LABEL: @test15
+; CHECK: entry:
+; CHECK-NEXT: icmp eq
+; CHECK-NEXT: br i1
+
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+; CHECK: entry.if.end_crit_edge:
+; CHECK-NEXT: %vv.pre = load i32, i32* %x, align 4
+; CHECK-NEXT: br label %if.end
+
+if.then:
+  %uu = load i32, i32* %x, align 4
+  store i32 %uu, i32* %r, align 4
+  br label %if.end
+
+; CHECK: if.then:
+; CHECK-NEXT: %uu = load i32, i32* %x, align 4
+; CHECK-NEXT: store i32 %uu, i32* %r, align 4
+; CHECK-NEXT: br label %if.end
+
+if.end:
+  call void @f()
+  %vv = load i32, i32* %x, align 4
+  ret i32 %vv
+
+; CHECK: if.end:
+; CHECK-NEXT: %vv = phi i32 [ %vv.pre, %entry.if.end_crit_edge ], [ %uu, %if.then ]
+; CHECK-NEXT: call void @f()
+; CHECK-NEXT: ret i32 %vv
+
+}
+
+; Same as test14, but %x here is dereferenceable. A pointer that is
+; dereferenceable can be loaded from speculatively without a risk of trapping.
+; Since it is OK to speculate, PRE is allowed.
+
+define i32 @test16(i32* noalias nocapture readonly dereferenceable(8) %x, i32* noalias nocapture %r, i32 %a) {
+
+; CHECK-LABEL: @test16(
+; CHECK: entry:
+; CHECK-NEXT: icmp eq
+; CHECK-NEXT: br i1
+
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+; CHECK: entry.if.end_crit_edge:
+; CHECK-NEXT: %vv.pre = load i32, i32* %x, align 4
+; CHECK-NEXT: br label %if.end
+
+if.then:
+  %uu = load i32, i32* %x, align 4
+  store i32 %uu, i32* %r, align 4
+  br label %if.end
+
+; CHECK: if.then:
+; CHECK-NEXT: %uu = load i32, i32* %x, align 4
+; CHECK-NEXT: store i32 %uu, i32* %r, align 4
+; CHECK-NEXT: br label %if.end
+
+if.end:
+  call void @f()
+  br label %follow_1
+
+; CHECK: if.end:
+; CHECK-NEXT: %vv = phi i32 [ %vv.pre, %entry.if.end_crit_edge ], [ %uu, %if.then ]
+; CHECK-NEXT: call void @f()
+; CHECK-NEXT: ret i32 %vv
+
+follow_1:
+  br label %follow_2
+
+follow_2:
+  %vv = load i32, i32* %x, align 4
+  ret i32 %vv
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-no-cost-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-no-cost-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-no-cost-phi.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-no-cost-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+; This testcase tests insertion of no-cost phis.  That is,
+; when the value is already available in every predecessor,
+; and we just need to insert a phi node to merge the available values.
+
+ at c = global i32 0, align 4
+ at d = global i32 0, align 4
+
+
+define i32 @mai(i32 %foo, i32 %a, i32 %b) {
+  %1 = icmp ne i32 %foo, 0
+  br i1 %1, label %bb1, label %bb2
+
+bb1:
+  %2 = add nsw i32 %a, %b
+  store i32 %2, i32* @c, align 4
+  br label %mergeblock
+
+bb2:
+  %3 = add nsw i32 %a, %b
+  store i32 %3, i32* @d, align 4
+  br label %mergeblock
+
+mergeblock:
+; CHECK: pre-phi = phi i32 [ %3, %bb2 ], [ %2, %bb1 ]
+; CHECK-NEXT: ret i32 %.pre-phi
+  %4 = add nsw i32 %a, %b
+  ret i32 %4
+}
+
+

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-poison-add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-poison-add.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-poison-add.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-poison-add.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt < %s -gvn -enable-pre -S | FileCheck %s
+
+ at H = common global i32 0
+ at G = common global i32 0
+
+define i32 @test1(i1 %cond, i32 %v) nounwind {
+; CHECK-LABEL: @test1
+entry:
+    br i1 %cond, label %bb, label %bb1
+
+bb:
+    %add.1 = add nuw nsw i32 %v, 42
+; CHECK: %add.1 = add i32 %v, 42
+    store i32 %add.1, i32* @G, align 4
+    br label %return
+
+bb1:
+; CHECK: %.pre = add i32 %v, 42
+    br label %return
+
+return:
+; CHECK: %add.2.pre-phi = phi i32 [ %.pre, %bb1 ], [ %add.1, %bb ]
+; CHECK-NEXT: store i32 %add.2.pre-phi, i32* @H, align 4
+; CHECK-NEXT: ret i32 0
+    %add.2 = add i32 %v, 42
+    store i32 %add.2, i32* @H, align 4
+    ret i32 0
+}
+
+define i32 @test2(i1 %cond, i32 %v) nounwind {
+; CHECK-LABEL: @test2
+entry:
+    br i1 %cond, label %bb, label %bb1
+
+bb:
+    %add.1 = add i32 %v, 42
+; CHECK: %add.1 = add i32 %v, 42
+    store i32 %add.1, i32* @G, align 4
+    br label %return
+
+bb1:
+; CHECK: %.pre = add nuw nsw i32 %v, 42
+    br label %return
+
+return:
+; CHECK: %add.2.pre-phi = phi i32 [ %.pre, %bb1 ], [ %add.1, %bb ]
+; CHECK-NEXT: store i32 %add.2.pre-phi, i32* @H, align 4
+; CHECK-NEXT: ret i32 0
+    %add.2 = add nuw nsw i32 %v, 42
+    store i32 %add.2, i32* @H, align 4
+    ret i32 0
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/pre-single-pred.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/pre-single-pred.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/pre-single-pred.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/pre-single-pred.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -gvn -enable-load-pre -S | FileCheck %s
+; This testcase assumed we'll PRE the load into %for.cond, but we don't actually
+; verify that doing so is safe.  If there didn't _happen_ to be a load in
+; %for.end, we would actually be lengthening the execution on some paths, and
+; we were never actually checking that case.  Now we actually do perform some
+; conservative checking to make sure we don't make paths longer, but we don't
+; currently get this case, which we got lucky on previously.
+;
+; Now that that faulty assumption is corrected, test that we DON'T incorrectly
+; hoist the load.  Doing the right thing for the wrong reasons is still a bug.
+
+ at p = external global i32
+define i32 @f(i32 %n) nounwind {
+entry:
+	br label %for.cond
+
+for.cond:		; preds = %for.inc, %entry
+	%i.0 = phi i32 [ 0, %entry ], [ %indvar.next, %for.inc ]		; <i32> [#uses=2]
+	%cmp = icmp slt i32 %i.0, %n		; <i1> [#uses=1]
+	br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:		; preds = %for.cond
+	br label %for.end
+
+; CHECK: for.body:
+; CHECK-NEXT: %tmp3 = load i32, i32* @p
+for.body:		; preds = %for.cond
+	%tmp3 = load i32, i32* @p		; <i32> [#uses=1]
+	%dec = add i32 %tmp3, -1		; <i32> [#uses=2]
+	store i32 %dec, i32* @p
+	%cmp6 = icmp slt i32 %dec, 0		; <i1> [#uses=1]
+	br i1 %cmp6, label %for.body.for.end_crit_edge, label %for.inc
+
+; CHECK: for.body.for.end_crit_edge:
+for.body.for.end_crit_edge:		; preds = %for.body
+	br label %for.end
+
+for.inc:		; preds = %for.body
+	%indvar.next = add i32 %i.0, 1		; <i32> [#uses=1]
+	br label %for.cond
+
+for.end:		; preds = %for.body.for.end_crit_edge, %for.cond.for.end_crit_edge
+	%tmp9 = load i32, i32* @p		; <i32> [#uses=1]
+	ret i32 %tmp9
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/preserve-tbaa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/preserve-tbaa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/preserve-tbaa.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/preserve-tbaa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -tbaa -basicaa -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+; GVN should preserve the TBAA tag on loads when doing PRE.
+
+; CHECK-LABEL: @test(
+; CHECK: %tmp33.pre = load i16, i16* %P, align 2, !tbaa !0
+; CHECK: br label %for.body
+define void @test(i16 *%P, i16* %Q) nounwind {
+entry:
+  br i1 undef, label %bb.nph, label %for.end
+
+bb.nph:                                           ; preds = %entry
+  br label %for.body
+
+for.body:                                         ; preds = %for.body, %bb.nph
+  %tmp33 = load i16, i16* %P, align 2, !tbaa !0
+  store i16 %tmp33, i16* %Q
+
+  store i16 0, i16* %P, align 2, !tbaa !0
+  br i1 false, label %for.end, label %for.body
+
+for.end:                                          ; preds = %for.body, %entry
+  ret void
+}
+
+!0 = !{!3, !3, i64 0}
+!1 = !{!"omnipotent char", !2}
+!2 = !{!"Simple C/C++ TBAA"}
+!3 = !{!"short", !1}

Added: llvm/trunk/test/Transforms/GVN/PRE/rle-addrspace-cast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/rle-addrspace-cast.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/rle-addrspace-cast.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/rle-addrspace-cast.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; RUN: opt < %s -data-layout="e-p:32:32:32-p1:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-n8:16:32" -basicaa -gvn -S -die | FileCheck %s
+
+define i8 @coerce_offset0_addrspacecast(i32 %V, i32* %P) {
+  store i32 %V, i32* %P
+
+  %P2 = addrspacecast i32* %P to i8 addrspace(1)*
+  %P3 = getelementptr i8, i8 addrspace(1)* %P2, i32 2
+
+  %A = load i8, i8 addrspace(1)* %P3
+  ret i8 %A
+; CHECK-LABEL: @coerce_offset0_addrspacecast(
+; CHECK-NOT: load
+; CHECK: ret i8
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/rle-phi-translate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/rle-phi-translate.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/rle-phi-translate.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/rle-phi-translate.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,146 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+define i32 @test1(i32* %b, i32* %c) nounwind {
+; CHECK-LABEL: @test1(
+entry:
+	%g = alloca i32
+	%t1 = icmp eq i32* %b, null
+	br i1 %t1, label %bb, label %bb1
+
+bb:
+	%t2 = load i32, i32* %c, align 4
+	%t3 = add i32 %t2, 1
+	store i32 %t3, i32* %g, align 4
+	br label %bb2
+
+bb1:		; preds = %entry
+	%t5 = load i32, i32* %b, align 4
+	%t6 = add i32 %t5, 1
+	store i32 %t6, i32* %g, align 4
+	br label %bb2
+
+bb2:		; preds = %bb1, %bb
+	%c_addr.0 = phi i32* [ %g, %bb1 ], [ %c, %bb ]
+	%b_addr.0 = phi i32* [ %b, %bb1 ], [ %g, %bb ]
+	%cv = load i32, i32* %c_addr.0, align 4
+	%bv = load i32, i32* %b_addr.0, align 4
+; CHECK: %bv = phi i32
+; CHECK: %cv = phi i32
+; CHECK-NOT: load
+; CHECK: ret i32
+	%ret = add i32 %cv, %bv
+	ret i32 %ret
+}
+
+define i8 @test2(i1 %cond, i32* %b, i32* %c) nounwind {
+; CHECK-LABEL: @test2(
+entry:
+  br i1 %cond, label %bb, label %bb1
+
+bb:
+  %b1 = bitcast i32* %b to i8*
+  store i8 4, i8* %b1
+  br label %bb2
+
+bb1:
+  %c1 = bitcast i32* %c to i8*
+  store i8 92, i8* %c1
+  br label %bb2
+
+bb2:
+  %d = phi i32* [ %c, %bb1 ], [ %b, %bb ]
+  %d1 = bitcast i32* %d to i8*
+  %dv = load i8, i8* %d1
+; CHECK: %dv = phi i8 [ 92, %bb1 ], [ 4, %bb ]
+; CHECK-NOT: load
+; CHECK: ret i8 %dv
+  ret i8 %dv
+}
+
+define i32 @test3(i1 %cond, i32* %b, i32* %c) nounwind {
+; CHECK-LABEL: @test3(
+entry:
+  br i1 %cond, label %bb, label %bb1
+
+bb:
+  %b1 = getelementptr i32, i32* %b, i32 17
+  store i32 4, i32* %b1
+  br label %bb2
+
+bb1:
+  %c1 = getelementptr i32, i32* %c, i32 7
+  store i32 82, i32* %c1
+  br label %bb2
+
+bb2:
+  %d = phi i32* [ %c, %bb1 ], [ %b, %bb ]
+  %i = phi i32 [ 7, %bb1 ], [ 17, %bb ]
+  %d1 = getelementptr i32, i32* %d, i32 %i
+  %dv = load i32, i32* %d1
+; CHECK: %dv = phi i32 [ 82, %bb1 ], [ 4, %bb ]
+; CHECK-NOT: load
+; CHECK: ret i32 %dv
+  ret i32 %dv
+}
+
+; PR5313
+define i32 @test4(i1 %cond, i32* %b, i32* %c) nounwind {
+; CHECK-LABEL: @test4(
+entry:
+  br i1 %cond, label %bb, label %bb1
+
+bb:
+  store i32 4, i32* %b
+  br label %bb2
+
+bb1:
+  %c1 = getelementptr i32, i32* %c, i32 7
+  store i32 82, i32* %c1
+  br label %bb2
+
+bb2:
+  %d = phi i32* [ %c, %bb1 ], [ %b, %bb ]
+  %i = phi i32 [ 7, %bb1 ], [ 0, %bb ]
+  %d1 = getelementptr i32, i32* %d, i32 %i
+  %dv = load i32, i32* %d1
+; CHECK: %dv = phi i32 [ 82, %bb1 ], [ 4, %bb ]
+; CHECK-NOT: load
+; CHECK: ret i32 %dv
+  ret i32 %dv
+}
+
+
+
+; void test5(int N, double* G) {
+;   for (long j = 1; j < 1000; j++)
+;     G[j] = G[j] + G[j-1];
+; }
+;
+; Should compile into one load in the loop.
+define void @test5(i32 %N, double* nocapture %G) nounwind ssp {
+; CHECK-LABEL: @test5(
+bb.nph:
+  br label %for.body
+
+for.body:
+  %indvar = phi i64 [ 0, %bb.nph ], [ %tmp, %for.body ]
+  %arrayidx6 = getelementptr double, double* %G, i64 %indvar
+  %tmp = add i64 %indvar, 1
+  %arrayidx = getelementptr double, double* %G, i64 %tmp
+  %tmp3 = load double, double* %arrayidx
+  %tmp7 = load double, double* %arrayidx6
+  %add = fadd double %tmp3, %tmp7
+  store double %add, double* %arrayidx
+  %exitcond = icmp eq i64 %tmp, 999
+  br i1 %exitcond, label %for.end, label %for.body
+; CHECK: for.body:
+; CHECK: phi double
+; CHECK: load double
+; CHECK-NOT: load double
+; CHECK: br i1
+for.end:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/rle-semidominated.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/rle-semidominated.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/rle-semidominated.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/rle-semidominated.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+define i32 @main(i32* %p, i32 %x, i32 %y) {
+block1:
+  %z = load i32, i32* %p
+  %cmp = icmp eq i32 %x, %y
+	br i1 %cmp, label %block2, label %block3
+
+block2:
+ br label %block4
+
+block3:
+  %b = bitcast i32 0 to i32
+  store i32 %b, i32* %p
+  br label %block4
+
+block4:
+  %DEAD = load i32, i32* %p
+  ret i32 %DEAD
+}
+
+; CHECK: define i32 @main(i32* %p, i32 %x, i32 %y) {
+; CHECK-NEXT: block1:
+; CHECK-NOT:    %z = load i32, i32* %p
+; CHECK-NEXT:   %cmp = icmp eq i32 %x, %y
+; CHECK-NEXT:   br i1 %cmp, label %block2, label %block3
+; CHECK: block2:
+; CHECK-NEXT:   %DEAD.pre = load i32, i32* %p
+; CHECK-NEXT:   br label %block4
+; CHECK: block3:
+; CHECK-NEXT:   store i32 0, i32* %p
+; CHECK-NEXT:   br label %block4
+; CHECK: block4:
+; CHECK-NEXT:   %DEAD = phi i32 [ 0, %block3 ], [ %DEAD.pre, %block2 ]
+; CHECK-NEXT:   ret i32 %DEAD
+; CHECK-NEXT: }

Added: llvm/trunk/test/Transforms/GVN/PRE/rle.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/rle.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/rle.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/rle.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,694 @@
+; RUN: opt < %s -data-layout="e-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-n8:16:32" -basicaa -gvn -S -die | FileCheck %s
+; RUN: opt < %s -data-layout="E-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-n32"      -basicaa -gvn -S -die | FileCheck %s
+
+;; Trivial RLE test.
+define i32 @test0(i32 %V, i32* %P) {
+  store i32 %V, i32* %P
+
+  %A = load i32, i32* %P
+  ret i32 %A
+; CHECK-LABEL: @test0(
+; CHECK: ret i32 %V
+}
+
+
+;;===----------------------------------------------------------------------===;;
+;; Tests for crashers
+;;===----------------------------------------------------------------------===;;
+
+;; PR5016
+define i8 @crash0({i32, i32} %A, {i32, i32}* %P) {
+  store {i32, i32} %A, {i32, i32}* %P
+  %X = bitcast {i32, i32}* %P to i8*
+  %Y = load i8, i8* %X
+  ret i8 %Y
+}
+
+;; No PR filed, crashed in CaptureTracker.
+declare void @helper()
+define void @crash1() {
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* undef, i8* undef, i64 undef, i1 false) nounwind
+  %tmp = load i8, i8* bitcast (void ()* @helper to i8*)
+  %x = icmp eq i8 %tmp, 15
+  ret void
+}
+
+
+;;===----------------------------------------------------------------------===;;
+;; Store -> Load  and  Load -> Load forwarding where src and dst are different
+;; types, but where the base pointer is a must alias.
+;;===----------------------------------------------------------------------===;;
+
+;; i32 -> f32 forwarding.
+define float @coerce_mustalias1(i32 %V, i32* %P) {
+  store i32 %V, i32* %P
+   
+  %P2 = bitcast i32* %P to float*
+
+  %A = load float, float* %P2
+  ret float %A
+; CHECK-LABEL: @coerce_mustalias1(
+; CHECK-NOT: load
+; CHECK: ret float 
+}
+
+;; i32* -> float forwarding.
+define float @coerce_mustalias2(i32* %V, i32** %P) {
+  store i32* %V, i32** %P
+   
+  %P2 = bitcast i32** %P to float*
+
+  %A = load float, float* %P2
+  ret float %A
+; CHECK-LABEL: @coerce_mustalias2(
+; CHECK-NOT: load
+; CHECK: ret float 
+}
+
+;; float -> i32* forwarding.
+define i32* @coerce_mustalias3(float %V, float* %P) {
+  store float %V, float* %P
+   
+  %P2 = bitcast float* %P to i32**
+
+  %A = load i32*, i32** %P2
+  ret i32* %A
+; CHECK-LABEL: @coerce_mustalias3(
+; CHECK-NOT: load
+; CHECK: ret i32* 
+}
+
+;; i32 -> f32 load forwarding.
+define float @coerce_mustalias4(i32* %P, i1 %cond) {
+  %A = load i32, i32* %P
+  
+  %P2 = bitcast i32* %P to float*
+  %B = load float, float* %P2
+  br i1 %cond, label %T, label %F
+T:
+  ret float %B
+  
+F:
+  %X = bitcast i32 %A to float
+  ret float %X
+
+; CHECK-LABEL: @coerce_mustalias4(
+; CHECK: %A = load i32, i32* %P
+; CHECK-NOT: load
+; CHECK: ret float
+; CHECK: F:
+}
+
+;; i32 -> i8 forwarding
+define i8 @coerce_mustalias5(i32 %V, i32* %P) {
+  store i32 %V, i32* %P
+   
+  %P2 = bitcast i32* %P to i8*
+
+  %A = load i8, i8* %P2
+  ret i8 %A
+; CHECK-LABEL: @coerce_mustalias5(
+; CHECK-NOT: load
+; CHECK: ret i8
+}
+
+;; i64 -> float forwarding
+define float @coerce_mustalias6(i64 %V, i64* %P) {
+  store i64 %V, i64* %P
+   
+  %P2 = bitcast i64* %P to float*
+
+  %A = load float, float* %P2
+  ret float %A
+; CHECK-LABEL: @coerce_mustalias6(
+; CHECK-NOT: load
+; CHECK: ret float
+}
+
+;; i64 -> i8* (32-bit) forwarding
+define i8* @coerce_mustalias7(i64 %V, i64* %P) {
+  store i64 %V, i64* %P
+   
+  %P2 = bitcast i64* %P to i8**
+
+  %A = load i8*, i8** %P2
+  ret i8* %A
+; CHECK-LABEL: @coerce_mustalias7(
+; CHECK-NOT: load
+; CHECK: ret i8*
+}
+
+; memset -> i16 forwarding.
+define signext i16 @memset_to_i16_local(i16* %A) nounwind ssp {
+entry:
+  %conv = bitcast i16* %A to i8* 
+  tail call void @llvm.memset.p0i8.i64(i8* %conv, i8 1, i64 200, i1 false)
+  %arrayidx = getelementptr inbounds i16, i16* %A, i64 42
+  %tmp2 = load i16, i16* %arrayidx
+  ret i16 %tmp2
+; CHECK-LABEL: @memset_to_i16_local(
+; CHECK-NOT: load
+; CHECK: ret i16 257
+}
+
+; memset -> float forwarding.
+define float @memset_to_float_local(float* %A, i8 %Val) nounwind ssp {
+entry:
+  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
+  tail call void @llvm.memset.p0i8.i64(i8* %conv, i8 %Val, i64 400, i1 false)
+  %arrayidx = getelementptr inbounds float, float* %A, i64 42 ; <float*> [#uses=1]
+  %tmp2 = load float, float* %arrayidx                   ; <float> [#uses=1]
+  ret float %tmp2
+; CHECK-LABEL: @memset_to_float_local(
+; CHECK-NOT: load
+; CHECK: zext
+; CHECK-NEXT: shl
+; CHECK-NEXT: or
+; CHECK-NEXT: shl
+; CHECK-NEXT: or
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: ret float
+}
+
+;; non-local memset -> i16 load forwarding.
+define i16 @memset_to_i16_nonlocal0(i16* %P, i1 %cond) {
+  %P3 = bitcast i16* %P to i8*
+  br i1 %cond, label %T, label %F
+T:
+  tail call void @llvm.memset.p0i8.i64(i8* %P3, i8 1, i64 400, i1 false)
+  br label %Cont
+  
+F:
+  tail call void @llvm.memset.p0i8.i64(i8* %P3, i8 2, i64 400, i1 false)
+  br label %Cont
+
+Cont:
+  %P2 = getelementptr i16, i16* %P, i32 4
+  %A = load i16, i16* %P2
+  ret i16 %A
+
+; CHECK-LABEL: @memset_to_i16_nonlocal0(
+; CHECK: Cont:
+; CHECK-NEXT:   %A = phi i16 [ 514, %F ], [ 257, %T ]
+; CHECK-NOT: load
+; CHECK: ret i16 %A
+}
+
+ at GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 }
+ at GCst_as1 = addrspace(1) constant {i32, float, i32 } { i32 42, float 14., i32 97 }
+
+; memset -> float forwarding.
+define float @memcpy_to_float_local(float* %A) nounwind ssp {
+entry:
+  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
+  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %conv, i8* bitcast ({i32, float, i32 }* @GCst to i8*), i64 12, i1 false)
+  %arrayidx = getelementptr inbounds float, float* %A, i64 1 ; <float*> [#uses=1]
+  %tmp2 = load float, float* %arrayidx                   ; <float> [#uses=1]
+  ret float %tmp2
+; CHECK-LABEL: @memcpy_to_float_local(
+; CHECK-NOT: load
+; CHECK: ret float 1.400000e+01
+}
+
+; memcpy from address space 1
+define float @memcpy_to_float_local_as1(float* %A) nounwind ssp {
+entry:
+  %conv = bitcast float* %A to i8*                ; <i8*> [#uses=1]
+  tail call void @llvm.memcpy.p0i8.p1i8.i64(i8* %conv, i8 addrspace(1)* bitcast ({i32, float, i32 } addrspace(1)* @GCst_as1 to i8 addrspace(1)*), i64 12, i1 false)
+  %arrayidx = getelementptr inbounds float, float* %A, i64 1 ; <float*> [#uses=1]
+  %tmp2 = load float, float* %arrayidx                   ; <float> [#uses=1]
+  ret float %tmp2
+; CHECK-LABEL: @memcpy_to_float_local_as1(
+; CHECK-NOT: load
+; CHECK: ret float 1.400000e+01
+}
+
+;; non-local i32/float -> i8 load forwarding.
+define i8 @coerce_mustalias_nonlocal0(i32* %P, i1 %cond) {
+  %P2 = bitcast i32* %P to float*
+  %P3 = bitcast i32* %P to i8*
+  br i1 %cond, label %T, label %F
+T:
+  store i32 42, i32* %P
+  br label %Cont
+  
+F:
+  store float 1.0, float* %P2
+  br label %Cont
+
+Cont:
+  %A = load i8, i8* %P3
+  ret i8 %A
+
+; CHECK-LABEL: @coerce_mustalias_nonlocal0(
+; CHECK: Cont:
+; CHECK:   %A = phi i8 [
+; CHECK-NOT: load
+; CHECK: ret i8 %A
+}
+
+
+;; non-local i32/float -> i8 load forwarding.  This also tests that the "P3"
+;; bitcast equivalence can be properly phi translated.
+define i8 @coerce_mustalias_nonlocal1(i32* %P, i1 %cond) {
+  %P2 = bitcast i32* %P to float*
+  br i1 %cond, label %T, label %F
+T:
+  store i32 42, i32* %P
+  br label %Cont
+  
+F:
+  store float 1.0, float* %P2
+  br label %Cont
+
+Cont:
+  %P3 = bitcast i32* %P to i8*
+  %A = load i8, i8* %P3
+  ret i8 %A
+
+; CHECK-LABEL: @coerce_mustalias_nonlocal1(
+; CHECK: Cont:
+; CHECK:   %A = phi i8 [
+; CHECK-NOT: load
+; CHECK: ret i8 %A
+}
+
+
+;; non-local i32 -> i8 partial redundancy load forwarding.
+define i8 @coerce_mustalias_pre0(i32* %P, i1 %cond) {
+  %P3 = bitcast i32* %P to i8*
+  br i1 %cond, label %T, label %F
+T:
+  store i32 42, i32* %P
+  br label %Cont
+  
+F:
+  br label %Cont
+
+Cont:
+  %A = load i8, i8* %P3
+  ret i8 %A
+
+; CHECK-LABEL: @coerce_mustalias_pre0(
+; CHECK: F:
+; CHECK:   load i8, i8* %P3
+; CHECK: Cont:
+; CHECK:   %A = phi i8 [
+; CHECK-NOT: load
+; CHECK: ret i8 %A
+}
+
+;;===----------------------------------------------------------------------===;;
+;; Store -> Load  and  Load -> Load forwarding where src and dst are different
+;; types, and the reload is an offset from the store pointer.
+;;===----------------------------------------------------------------------===;;
+
+;; i32 -> i8 forwarding.
+;; PR4216
+define i8 @coerce_offset0(i32 %V, i32* %P) {
+  store i32 %V, i32* %P
+   
+  %P2 = bitcast i32* %P to i8*
+  %P3 = getelementptr i8, i8* %P2, i32 2
+
+  %A = load i8, i8* %P3
+  ret i8 %A
+; CHECK-LABEL: @coerce_offset0(
+; CHECK-NOT: load
+; CHECK: ret i8
+}
+
+;; non-local i32/float -> i8 load forwarding.
+define i8 @coerce_offset_nonlocal0(i32* %P, i1 %cond) {
+  %P2 = bitcast i32* %P to float*
+  %P3 = bitcast i32* %P to i8*
+  %P4 = getelementptr i8, i8* %P3, i32 2
+  br i1 %cond, label %T, label %F
+T:
+  store i32 57005, i32* %P
+  br label %Cont
+  
+F:
+  store float 1.0, float* %P2
+  br label %Cont
+
+Cont:
+  %A = load i8, i8* %P4
+  ret i8 %A
+
+; CHECK-LABEL: @coerce_offset_nonlocal0(
+; CHECK: Cont:
+; CHECK:   %A = phi i8 [
+; CHECK-NOT: load
+; CHECK: ret i8 %A
+}
+
+
+;; non-local i32 -> i8 partial redundancy load forwarding.
+define i8 @coerce_offset_pre0(i32* %P, i1 %cond) {
+  %P3 = bitcast i32* %P to i8*
+  %P4 = getelementptr i8, i8* %P3, i32 2
+  br i1 %cond, label %T, label %F
+T:
+  store i32 42, i32* %P
+  br label %Cont
+  
+F:
+  br label %Cont
+
+Cont:
+  %A = load i8, i8* %P4
+  ret i8 %A
+
+; CHECK-LABEL: @coerce_offset_pre0(
+; CHECK: F:
+; CHECK:   load i8, i8* %P4
+; CHECK: Cont:
+; CHECK:   %A = phi i8 [
+; CHECK-NOT: load
+; CHECK: ret i8 %A
+}
+
+define i32 @chained_load(i32** %p, i32 %x, i32 %y) {
+block1:
+  %A = alloca i32*
+
+  %z = load i32*, i32** %p
+  store i32* %z, i32** %A
+  %cmp = icmp eq i32 %x, %y
+  br i1 %cmp, label %block2, label %block3
+
+block2:
+ %a = load i32*, i32** %p
+ br label %block4
+
+block3:
+  %b = load i32*, i32** %p
+  br label %block4
+
+block4:
+  %c = load i32*, i32** %p
+  %d = load i32, i32* %c
+  ret i32 %d
+  
+; CHECK-LABEL: @chained_load(
+; CHECK: %z = load i32*, i32** %p
+; CHECK-NOT: load
+; CHECK: %d = load i32, i32* %z
+; CHECK-NEXT: ret i32 %d
+}
+
+
+declare i1 @cond() readonly
+declare i1 @cond2() readonly
+
+define i32 @phi_trans2() {
+; CHECK-LABEL: @phi_trans2(
+entry:
+  %P = alloca i32, i32 400
+  br label %F1
+  
+F1:
+  %A = phi i32 [1, %entry], [2, %F]
+  %cond2 = call i1 @cond()
+  br i1 %cond2, label %T1, label %TY
+  
+T1:
+  %P2 = getelementptr i32, i32* %P, i32 %A
+  %x = load i32, i32* %P2
+  %cond = call i1 @cond2()
+  br i1 %cond, label %TX, label %F
+  
+F:
+  %P3 = getelementptr i32, i32* %P, i32 2
+  store i32 17, i32* %P3
+  
+  store i32 42, i32* %P2  ; Provides "P[A]".
+  br label %F1
+
+TX:
+  ; This load should not be compiled to 'ret i32 42'.  An overly clever
+  ; implementation of GVN would see that we're returning 17 if the loop
+  ; executes once or 42 if it executes more than that, but we'd have to do
+  ; loop restructuring to expose this, and GVN shouldn't do this sort of CFG
+  ; transformation.
+  
+; CHECK: TX:
+; CHECK: ret i32 %x
+  ret i32 %x
+TY:
+  ret i32 0
+}
+
+define i32 @phi_trans3(i32* %p, i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @phi_trans3(
+block1:
+  %cmpxy = icmp eq i32 %x, %y
+  br i1 %cmpxy, label %block2, label %block3
+
+block2:
+ store i32 87, i32* %p
+ br label %block4
+
+block3:
+  %p2 = getelementptr i32, i32* %p, i32 43
+  store i32 97, i32* %p2
+  br label %block4
+
+block4:
+  %A = phi i32 [-1, %block2], [42, %block3]
+  br i1 %cmpxy, label %block5, label %exit
+  
+; CHECK: block4:
+; CHECK-NEXT: %D = phi i32 [ 87, %block2 ], [ 97, %block3 ]  
+; CHECK-NOT: load
+
+block5:
+  %B = add i32 %A, 1
+  br i1 %cmpxy, label %block6, label %exit
+  
+block6:
+  %C = getelementptr i32, i32* %p, i32 %B
+  br i1 %cmpxy, label %block7, label %exit
+  
+block7:
+  %D = load i32, i32* %C
+  ret i32 %D
+  
+; CHECK: block7:
+; CHECK-NEXT: ret i32 %D
+
+exit:
+  ret i32 -1
+}
+
+define i8 @phi_trans4(i8* %p) {
+; CHECK-LABEL: @phi_trans4(
+entry:
+  %X3 = getelementptr i8, i8* %p, i32 192
+  store i8 192, i8* %X3
+  
+  %X = getelementptr i8, i8* %p, i32 4
+  %Y = load i8, i8* %X
+  br label %loop
+
+loop:
+  %i = phi i32 [4, %entry], [192, %loop]
+  %X2 = getelementptr i8, i8* %p, i32 %i
+  %Y2 = load i8, i8* %X2
+  
+; CHECK: loop:
+; CHECK-NEXT: %Y2 = phi i8 [ %Y, %entry ], [ 0, %loop ]
+; CHECK-NOT: load i8
+  
+  %cond = call i1 @cond2()
+
+  %Z = bitcast i8 *%X3 to i32*
+  store i32 0, i32* %Z
+  br i1 %cond, label %loop, label %out
+  
+out:
+  %R = add i8 %Y, %Y2
+  ret i8 %R
+}
+
+define i8 @phi_trans5(i8* %p) {
+; CHECK-LABEL: @phi_trans5(
+entry:
+  
+  %X4 = getelementptr i8, i8* %p, i32 2
+  store i8 19, i8* %X4
+  
+  %X = getelementptr i8, i8* %p, i32 4
+  %Y = load i8, i8* %X
+  br label %loop
+
+loop:
+  %i = phi i32 [4, %entry], [3, %cont]
+  %X2 = getelementptr i8, i8* %p, i32 %i
+  %Y2 = load i8, i8* %X2  ; Ensure this load is not being incorrectly replaced.
+  %cond = call i1 @cond2()
+  br i1 %cond, label %cont, label %out
+
+cont:
+  %Z = getelementptr i8, i8* %X2, i32 -1
+  %Z2 = bitcast i8 *%Z to i32*
+  store i32 50462976, i32* %Z2  ;; (1 << 8) | (2 << 16) | (3 << 24)
+
+
+; CHECK: store i32
+; CHECK-NEXT: getelementptr i8, i8* %p, i32 3
+; CHECK-NEXT: load i8, i8*
+  br label %loop
+  
+out:
+  %R = add i8 %Y, %Y2
+  ret i8 %R
+}
+
+
+; PR6642
+define i32 @memset_to_load() nounwind readnone {
+entry:
+  %x = alloca [256 x i32], align 4                ; <[256 x i32]*> [#uses=2]
+  %tmp = bitcast [256 x i32]* %x to i8*           ; <i8*> [#uses=1]
+  call void @llvm.memset.p0i8.i64(i8* align 4 %tmp, i8 0, i64 1024, i1 false)
+  %arraydecay = getelementptr inbounds [256 x i32], [256 x i32]* %x, i32 0, i32 0 ; <i32*>
+  %tmp1 = load i32, i32* %arraydecay                   ; <i32> [#uses=1]
+  ret i32 %tmp1
+; CHECK-LABEL: @memset_to_load(
+; CHECK: ret i32 0
+}
+
+
+;;===----------------------------------------------------------------------===;;
+;; Load -> Load forwarding in partial alias case.
+;;===----------------------------------------------------------------------===;;
+
+define i32 @load_load_partial_alias(i8* %P) nounwind ssp {
+entry:
+  %0 = bitcast i8* %P to i32*
+  %tmp2 = load i32, i32* %0
+  %add.ptr = getelementptr inbounds i8, i8* %P, i64 1
+  %tmp5 = load i8, i8* %add.ptr
+  %conv = zext i8 %tmp5 to i32
+  %add = add nsw i32 %tmp2, %conv
+  ret i32 %add
+
+; TEMPORARILYDISABLED-LABEL: @load_load_partial_alias(
+; TEMPORARILYDISABLED: load i32, i32*
+; TEMPORARILYDISABLED-NOT: load
+; TEMPORARILYDISABLED: lshr i32 {{.*}}, 8
+; TEMPORARILYDISABLED-NOT: load
+; TEMPORARILYDISABLED: trunc i32 {{.*}} to i8
+; TEMPORARILYDISABLED-NOT: load
+; TEMPORARILYDISABLED: ret i32
+}
+
+
+; Cross block partial alias case.
+define i32 @load_load_partial_alias_cross_block(i8* %P) nounwind ssp {
+entry:
+  %xx = bitcast i8* %P to i32*
+  %x1 = load i32, i32* %xx, align 4
+  %cmp = icmp eq i32 %x1, 127
+  br i1 %cmp, label %land.lhs.true, label %if.end
+
+land.lhs.true:                                    ; preds = %entry
+  %arrayidx4 = getelementptr inbounds i8, i8* %P, i64 1
+  %tmp5 = load i8, i8* %arrayidx4, align 1
+  %conv6 = zext i8 %tmp5 to i32
+  ret i32 %conv6
+
+if.end:
+  ret i32 52
+; TEMPORARILY_DISABLED-LABEL: @load_load_partial_alias_cross_block(
+; TEMPORARILY_DISABLED: land.lhs.true:
+; TEMPORARILY_DISABLED-NOT: load i8
+; TEMPORARILY_DISABLED: ret i32 %conv6
+}
+
+
+;;===----------------------------------------------------------------------===;;
+;; Load Widening
+;; We explicitly choose NOT to widen. And are testing to make sure we don't.
+;;===----------------------------------------------------------------------===;;
+
+%widening1 = type { i32, i8, i8, i8, i8 }
+
+ at f = global %widening1 zeroinitializer, align 4
+
+define i32 @test_widening1(i8* %P) nounwind ssp noredzone {
+entry:
+  %tmp = load i8, i8* getelementptr inbounds (%widening1, %widening1* @f, i64 0, i32 1), align 4
+  %conv = zext i8 %tmp to i32
+  %tmp1 = load i8, i8* getelementptr inbounds (%widening1, %widening1* @f, i64 0, i32 2), align 1
+  %conv2 = zext i8 %tmp1 to i32
+  %add = add nsw i32 %conv, %conv2
+  ret i32 %add
+; CHECK-LABEL: @test_widening1(
+; CHECK-NOT: load
+; CHECK: load i8, i8*
+; CHECK: load i8, i8*
+; CHECK-NOT: load
+; CHECK: ret i32
+}
+
+define i32 @test_widening2() nounwind ssp noredzone {
+entry:
+  %tmp = load i8, i8* getelementptr inbounds (%widening1, %widening1* @f, i64 0, i32 1), align 4
+  %conv = zext i8 %tmp to i32
+  %tmp1 = load i8, i8* getelementptr inbounds (%widening1, %widening1* @f, i64 0, i32 2), align 1
+  %conv2 = zext i8 %tmp1 to i32
+  %add = add nsw i32 %conv, %conv2
+
+  %tmp2 = load i8, i8* getelementptr inbounds (%widening1, %widening1* @f, i64 0, i32 3), align 2
+  %conv3 = zext i8 %tmp2 to i32
+  %add2 = add nsw i32 %add, %conv3
+
+  %tmp3 = load i8, i8* getelementptr inbounds (%widening1, %widening1* @f, i64 0, i32 4), align 1
+  %conv4 = zext i8 %tmp3 to i32
+  %add3 = add nsw i32 %add2, %conv3
+
+  ret i32 %add3
+; CHECK-LABEL: @test_widening2(
+; CHECK-NOT: load
+; CHECK: load i8, i8*
+; CHECK: load i8, i8*
+; CHECK: load i8, i8*
+; CHECK: load i8, i8*
+; CHECK-NOT: load
+; CHECK: ret i32
+}
+
+declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
+declare void @llvm.memcpy.p0i8.p1i8.i64(i8* nocapture, i8 addrspace(1)* nocapture, i64, i1) nounwind
+
+
+;;===----------------------------------------------------------------------===;;
+;; Load -> Store dependency which isn't interfered with by a call that happens
+;; before the pointer was captured.
+;;===----------------------------------------------------------------------===;;
+
+%class.X = type { [8 x i8] }
+
+ at _ZTV1X = weak_odr constant [5 x i8*] zeroinitializer
+ at _ZTV1Y = weak_odr constant [5 x i8*] zeroinitializer
+
+declare void @use()
+declare void @use3(i8***, i8**)
+
+; PR8908
+define void @test_escape1() nounwind {
+  %x = alloca i8**, align 8
+  store i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTV1X, i64 0, i64 2), i8*** %x, align 8
+  call void @use() nounwind
+  %DEAD = load i8**, i8*** %x, align 8
+  call void @use3(i8*** %x, i8** %DEAD) nounwind
+  ret void
+; CHECK: test_escape1
+; CHECK-NOT: DEAD
+; CHECK: ret
+}

Added: llvm/trunk/test/Transforms/GVN/PRE/volatile.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/PRE/volatile.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/PRE/volatile.ll (added)
+++ llvm/trunk/test/Transforms/GVN/PRE/volatile.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,167 @@
+; Tests that check our handling of volatile instructions encountered
+; when scanning for dependencies
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+; Check that we can bypass a volatile load when searching
+; for dependencies of a non-volatile load
+define i32 @test1(i32* nocapture %p, i32* nocapture %q) {
+; CHECK-LABEL: test1
+; CHECK:      %0 = load volatile i32, i32* %q
+; CHECK-NEXT: ret i32 0
+entry:
+  %x = load i32, i32* %p
+  load volatile i32, i32* %q
+  %y = load i32, i32* %p
+  %add = sub i32 %y, %x
+  ret i32 %add
+}
+
+; We can not value forward if the query instruction is 
+; volatile, this would be (in effect) removing the volatile load
+define i32 @test2(i32* nocapture %p, i32* nocapture %q) {
+; CHECK-LABEL: test2
+; CHECK:      %x = load i32, i32* %p
+; CHECK-NEXT: %y = load volatile i32, i32* %p
+; CHECK-NEXT: %add = sub i32 %y, %x
+entry:
+  %x = load i32, i32* %p
+  %y = load volatile i32, i32* %p
+  %add = sub i32 %y, %x
+  ret i32 %add
+}
+
+; If the query instruction is itself volatile, we *cannot*
+; reorder it even if p and q are noalias
+define i32 @test3(i32* noalias nocapture %p, i32* noalias nocapture %q) {
+; CHECK-LABEL: test3
+; CHECK:      %x = load i32, i32* %p
+; CHECK-NEXT: %0 = load volatile i32, i32* %q
+; CHECK-NEXT: %y = load volatile i32, i32* %p
+entry:
+  %x = load i32, i32* %p
+  load volatile i32, i32* %q
+  %y = load volatile i32, i32* %p
+  %add = sub i32 %y, %x
+  ret i32 %add
+}
+
+; If an encountered instruction is both volatile and ordered, 
+; we need to use the strictest ordering of either.  In this 
+; case, the ordering prevents forwarding.
+define i32 @test4(i32* noalias nocapture %p, i32* noalias nocapture %q) {
+; CHECK-LABEL: test4
+; CHECK:      %x = load i32, i32* %p
+; CHECK-NEXT: %0 = load atomic volatile i32, i32* %q seq_cst 
+; CHECK-NEXT: %y = load atomic i32, i32* %p seq_cst
+entry:
+  %x = load i32, i32* %p
+  load atomic volatile i32, i32* %q seq_cst, align 4
+  %y = load atomic i32, i32* %p seq_cst, align 4
+  %add = sub i32 %y, %x
+  ret i32 %add
+}
+
+; Value forwarding from a volatile load is perfectly legal
+define i32 @test5(i32* nocapture %p, i32* nocapture %q) {
+; CHECK-LABEL: test5
+; CHECK:      %x = load volatile i32, i32* %p
+; CHECK-NEXT: ret i32 0
+entry:
+  %x = load volatile i32, i32* %p
+  %y = load i32, i32* %p
+  %add = sub i32 %y, %x
+  ret i32 %add
+}
+
+; Does cross block redundancy elimination work with volatiles?
+define i32 @test6(i32* noalias nocapture %p, i32* noalias nocapture %q) {
+; CHECK-LABEL: test6
+; CHECK:      %y1 = load i32, i32* %p
+; CHECK-LABEL: header
+; CHECK:      %x = load volatile i32, i32* %q
+; CHECK-NEXT: %add = sub i32 %y1, %x
+entry:
+  %y1 = load i32, i32* %p
+  call void @use(i32 %y1)
+  br label %header
+header:
+  %x = load volatile i32, i32* %q
+  %y = load i32, i32* %p
+  %add = sub i32 %y, %x
+  %cnd = icmp eq i32 %add, 0
+  br i1 %cnd, label %exit, label %header
+exit:
+  ret i32 %add
+}
+
+; Does cross block PRE work with volatiles?
+define i32 @test7(i1 %c, i32* noalias nocapture %p, i32* noalias nocapture %q) {
+; CHECK-LABEL: test7
+; CHECK-LABEL: entry.header_crit_edge:
+; CHECK:       %y.pre = load i32, i32* %p
+; CHECK-LABEL: skip:
+; CHECK:       %y1 = load i32, i32* %p
+; CHECK-LABEL: header:
+; CHECK:      %y = phi i32
+; CHECK-NEXT: %x = load volatile i32, i32* %q
+; CHECK-NEXT: %add = sub i32 %y, %x
+entry:
+  br i1 %c, label %header, label %skip
+skip:
+  %y1 = load i32, i32* %p
+  call void @use(i32 %y1)
+  br label %header
+header:
+  %x = load volatile i32, i32* %q
+  %y = load i32, i32* %p
+  %add = sub i32 %y, %x
+  %cnd = icmp eq i32 %add, 0
+  br i1 %cnd, label %exit, label %header
+exit:
+  ret i32 %add
+}
+
+; Another volatile PRE case - two paths through a loop
+; load in preheader, one path read only, one not
+define i32 @test8(i1 %b, i1 %c, i32* noalias %p, i32* noalias %q) {
+; CHECK-LABEL: test8
+; CHECK-LABEL: entry
+; CHECK:       %y1 = load i32, i32* %p
+; CHECK-LABEL: header:
+; CHECK:      %y = phi i32
+; CHECK-NEXT: %x = load volatile i32, i32* %q
+; CHECK-NOT:  load
+; CHECK-LABEL: skip.header_crit_edge:
+; CHECK:       %y.pre = load i32, i32* %p
+entry:
+  %y1 = load i32, i32* %p
+  call void @use(i32 %y1)
+  br label %header
+header:
+  %x = load volatile i32, i32* %q
+  %y = load i32, i32* %p
+  call void @use(i32 %y)
+  br i1 %b, label %skip, label %header
+skip:
+  ; escaping the arguments is explicitly required since we marked 
+  ; them noalias
+  call void @clobber(i32* %p, i32* %q)
+  br i1 %c, label %header, label %exit
+exit:
+  %add = sub i32 %y, %x
+  ret i32 %add
+}
+
+define i32 @test9(i32* %V) {
+entry:
+  %load = load volatile i32, i32* %V, !range !0
+  ret i32 %load
+}
+; CHECK-LABEL: test9
+; CHECK: load volatile
+; CHECK: ret i32 0
+
+declare void @use(i32) readonly
+declare void @clobber(i32* %p, i32* %q)
+
+!0 = !{ i32 0, i32 1 }

Added: llvm/trunk/test/Transforms/GVN/assume-equal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/assume-equal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/assume-equal.ll (added)
+++ llvm/trunk/test/Transforms/GVN/assume-equal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,273 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+%struct.A = type { i32 (...)** }
+ at _ZTV1A = available_externally unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)], align 8
+ at _ZTI1A = external constant i8*
+
+; Checks if indirect calls can be replaced with direct
+; assuming that %vtable == @_ZTV1A (with alignment).
+; Checking const propagation across other BBs
+; CHECK-LABEL: define void @_Z1gb(
+
+define void @_Z1gb(i1 zeroext %p) {
+entry:
+  %call = tail call noalias i8* @_Znwm(i64 8) #4
+  %0 = bitcast i8* %call to %struct.A*
+  tail call void @_ZN1AC1Ev(%struct.A* %0) #1
+  %1 = bitcast i8* %call to i8***
+  %vtable = load i8**, i8*** %1, align 8
+  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
+  tail call void @llvm.assume(i1 %cmp.vtables)
+  br i1 %p, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
+  %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
+  
+  ; CHECK: call i32 @_ZN1A3fooEv(
+  %call2 = tail call i32 %2(%struct.A* %0) #1
+  
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
+  %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
+  
+  ; CHECK: call i32 @_ZN1A3barEv(
+  %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
+  
+  %call5 = tail call i32 %3(%struct.A* %0) #1
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+
+; Check integration with invariant.group handling
+; CHECK-LABEL: define void @invariantGroupHandling(i1 zeroext %p) {
+define void @invariantGroupHandling(i1 zeroext %p) {
+entry:
+  %call = tail call noalias i8* @_Znwm(i64 8) #4
+  %0 = bitcast i8* %call to %struct.A*
+  tail call void @_ZN1AC1Ev(%struct.A* %0) #1
+  %1 = bitcast i8* %call to i8***
+  %vtable = load i8**, i8*** %1, align 8, !invariant.group !0
+  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
+  tail call void @llvm.assume(i1 %cmp.vtables)
+  br i1 %p, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
+  %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
+  
+; CHECK: call i32 @_ZN1A3fooEv(
+  %call2 = tail call i32 %2(%struct.A* %0) #1
+  %vtable1 = load i8**, i8*** %1, align 8, !invariant.group !0
+  %vtable2.cast = bitcast i8** %vtable1 to i32 (%struct.A*)**
+  %call1 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable2.cast, align 8
+; CHECK: call i32 @_ZN1A3fooEv(
+  %callx = tail call i32 %call1(%struct.A* %0) #1
+  
+  %vtable2 = load i8**, i8*** %1, align 8, !invariant.group !0
+  %vtable3.cast = bitcast i8** %vtable2 to i32 (%struct.A*)**
+  %call4 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable3.cast, align 8
+; CHECK: call i32 @_ZN1A3fooEv(
+  %cally = tail call i32 %call4(%struct.A* %0) #1
+  
+  %b = bitcast i8* %call to %struct.A**
+  %vtable3 = load %struct.A*, %struct.A** %b, align 8, !invariant.group !0
+  %vtable4.cast = bitcast %struct.A* %vtable3 to i32 (%struct.A*)**
+  %vfun = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable4.cast, align 8
+; CHECK: call i32 @_ZN1A3fooEv(
+  %unknown = tail call i32 %vfun(%struct.A* %0) #1
+  
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %vfn47 = getelementptr inbounds i8*, i8** %vtable, i64 1
+  %vfn4 = bitcast i8** %vfn47 to i32 (%struct.A*)**
+  
+  ; CHECK: call i32 @_ZN1A3barEv(
+  %3 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vfn4, align 8
+  
+  %call5 = tail call i32 %3(%struct.A* %0) #1
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+
+
+; Checking const propagation in the same BB
+; CHECK-LABEL: define i32 @main()
+
+define i32 @main() {
+entry:
+  %call = tail call noalias i8* @_Znwm(i64 8) 
+  %0 = bitcast i8* %call to %struct.A*
+  tail call void @_ZN1AC1Ev(%struct.A* %0) 
+  %1 = bitcast i8* %call to i8***
+  %vtable = load i8**, i8*** %1, align 8
+  %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTV1A, i64 0, i64 2)
+  tail call void @llvm.assume(i1 %cmp.vtables)
+  %vtable1.cast = bitcast i8** %vtable to i32 (%struct.A*)**
+  
+  ; CHECK: call i32 @_ZN1A3fooEv(
+  %2 = load i32 (%struct.A*)*, i32 (%struct.A*)** %vtable1.cast, align 8
+  
+  %call2 = tail call i32 %2(%struct.A* %0)
+  ret i32 0
+}
+
+; This tests checks const propatation with fcmp instruction.
+; CHECK-LABEL: define float @_Z1gf(float %p)
+
+define float @_Z1gf(float %p) {
+entry:
+  %p.addr = alloca float, align 4
+  %f = alloca float, align 4
+  store float %p, float* %p.addr, align 4
+  
+  store float 3.000000e+00, float* %f, align 4
+  %0 = load float, float* %p.addr, align 4
+  %1 = load float, float* %f, align 4
+  %cmp = fcmp oeq float %1, %0 ; note const on lhs
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: ret float 3.000000e+00
+  ret float %0
+}
+
+; CHECK-LABEL: define float @_Z1hf(float %p)
+
+define float @_Z1hf(float %p) {
+entry:
+  %p.addr = alloca float, align 4
+  store float %p, float* %p.addr, align 4
+  
+  %0 = load float, float* %p.addr, align 4
+  %cmp = fcmp nnan ueq float %0, 3.000000e+00
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: ret float 3.000000e+00
+  ret float %0
+}
+
+; CHECK-LABEL: define float @_Z1if(float %p)
+define float @_Z1if(float %p) {
+entry:
+  %p.addr = alloca float, align 4
+  store float %p, float* %p.addr, align 4
+  
+  %0 = load float, float* %p.addr, align 4
+  %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK-NOT: ret float 3.000000e+00
+  ret float %0
+}
+
+; This test checks if constant propagation works for multiple node edges
+; CHECK-LABEL: define i32 @_Z1ii(i32 %p)
+define i32 @_Z1ii(i32 %p) {
+entry:
+  %cmp = icmp eq i32 %p, 42
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb2
+  br i1 %cmp, label %bb2, label %bb2
+bb2:
+  call void @llvm.assume(i1 true)
+  ; CHECK: br i1 true, label %bb2, label %bb2
+  br i1 %cmp, label %bb2, label %bb2
+  
+  ; CHECK: ret i32 42
+  ret i32 %p
+}
+
+; CHECK-LABEL: define i32 @_Z1ij(i32 %p)
+define i32 @_Z1ij(i32 %p) {
+entry:
+  %cmp = icmp eq i32 %p, 42
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb2
+  br i1 %cmp, label %bb2, label %bb2
+bb2:
+   ; CHECK-NOT: %cmp2 = 
+  %cmp2 = icmp eq i32 %p, 42
+  ; CHECK-NOT: call void @llvm.assume(
+  call void @llvm.assume(i1 %cmp2)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb2
+  br i1 %cmp, label %bb2, label %bb2
+  
+  ; CHECK: ret i32 42
+  ret i32 %p
+}
+
+; CHECK-LABEL: define i32 @_Z1ik(i32 %p)
+define i32 @_Z1ik(i32 %p) {
+entry:
+  %cmp = icmp eq i32 %p, 42
+  call void @llvm.assume(i1 %cmp)
+  
+  ; CHECK: br i1 true, label %bb2, label %bb3
+  br i1 %cmp, label %bb2, label %bb3
+bb2:
+  ; CHECK-NOT: %cmp3 = 
+  %cmp3 = icmp eq i32 %p, 43
+  ; CHECK: store i8 undef, i8* null
+  call void @llvm.assume(i1 %cmp3)
+  ret i32 15
+bb3:
+  ret i32 17
+}
+
+; This test checks if GVN can do the constant propagation correctly
+; when there are multiple uses of the same assume value in the 
+; basic block that has a loop back-edge pointing to itself.
+;
+; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k)
+define i32 @_Z1il(i32 %val, i1 %k) {
+  br label %next
+
+next:
+; CHECK: tail call void @llvm.assume(i1 %k)
+; CHECK-NEXT: %cmp = icmp eq i32 %val, 50
+  tail call void @llvm.assume(i1 %k)
+  tail call void @llvm.assume(i1 %k)
+  %cmp = icmp eq i32 %val, 50
+  br i1 %cmp, label %next, label %meh
+
+meh:
+  ret i32 0 
+}
+
+; This test checks if GVN can prevent the constant propagation correctly
+; in the successor blocks that are not dominated by the basic block
+; with the assume instruction.
+;
+; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j)
+define i1 @_z1im(i32 %val, i1 %k, i1 %j) {
+  br i1 %j, label %next, label %meh
+
+next:
+; CHECK: tail call void @llvm.assume(i1 %k)
+; CHECK-NEXT: br label %meh
+  tail call void @llvm.assume(i1 %k)
+  tail call void @llvm.assume(i1 %k)
+  br label %meh
+
+meh:
+; CHECK: ret i1 %k
+  ret i1 %k
+}
+
+declare noalias i8* @_Znwm(i64)
+declare void @_ZN1AC1Ev(%struct.A*)
+declare void @llvm.assume(i1)
+declare i32 @_ZN1A3fooEv(%struct.A*)
+declare i32 @_ZN1A3barEv(%struct.A*)
+
+!0 = !{!"struct A"}

Added: llvm/trunk/test/Transforms/GVN/basic-undef-test.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/basic-undef-test.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/basic-undef-test.ll (added)
+++ llvm/trunk/test/Transforms/GVN/basic-undef-test.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+; ModuleID = 'test3.ll'
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define i32 @main(i32 *%foo)  {
+entry:
+; CHECK: load i32, i32* %foo, align 4
+  %0 = load i32, i32* %foo, align 4
+  store i32 5, i32* undef, align 4
+; CHECK-NOT: load i32, i32* %foo, align 4
+  %1 = load i32, i32* %foo, align 4
+; CHECK: add i32 %0, %0
+  %2 = add i32 %0, %1
+  ret i32 %2
+}

Added: llvm/trunk/test/Transforms/GVN/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/basic.ll (added)
+++ llvm/trunk/test/Transforms/GVN/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+; RUN: opt < %s -passes=gvn -S | FileCheck %s
+
+define i32 @main() {
+block1:
+	%z1 = bitcast i32 0 to i32
+	br label %block2
+block2:
+  %z2 = bitcast i32 0 to i32
+  ret i32 %z2
+}
+
+; CHECK: define i32 @main() {
+; CHECK-NEXT: block1:
+; CHECK-NEXT:   ret i32 0
+; CHECK-NEXT: }

Added: llvm/trunk/test/Transforms/GVN/big-endian.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/big-endian.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/big-endian.ll (added)
+++ llvm/trunk/test/Transforms/GVN/big-endian.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt -gvn -S < %s | FileCheck %s
+
+target datalayout = "E-m:e-i64:64-n32:64"                                                                                         
+target triple = "powerpc64-unknown-linux-gnu"                                                                                     
+
+;; Make sure we use correct bit shift based on storage size for
+;; loads reusing a load value.
+define i64 @test1({ i1, i8 }* %predA, { i1, i8 }* %predB) {
+; CHECK-LABEL: @test1
+; CHECK-NOT: [[V1:%.*]] = load i16, i16* %{{.*}}
+; CHECK-NOT: [[V2:%.*]] = lshr i16 [[V1]], 8
+; CHECK-NOT: trunc i16 [[V2]] to i1
+
+  %valueLoadA.fca.0.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predA, i64 0, i32 0
+  %valueLoadA.fca.0.load = load i1, i1* %valueLoadA.fca.0.gep, align 8
+  %valueLoadB.fca.0.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predB, i64 0, i32 0
+  %valueLoadB.fca.0.load = load i1, i1* %valueLoadB.fca.0.gep, align 8
+  %isTrue = and i1 %valueLoadA.fca.0.load, %valueLoadB.fca.0.load
+  %valueLoadA.fca.1.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predA, i64 0, i32 1
+  %valueLoadA.fca.1.load = load i8, i8* %valueLoadA.fca.1.gep, align 1
+  %isNotNullA = icmp ne i8 %valueLoadA.fca.1.load, 0
+  %valueLoadB.fca.1.gep = getelementptr inbounds { i1, i8 }, { i1, i8 }* %predB, i64 0, i32 1
+  %valueLoadB.fca.1.load = load i8, i8* %valueLoadB.fca.1.gep, align 1
+  %isNotNullB = icmp ne i8 %valueLoadB.fca.1.load, 0
+  %isNotNull = and i1 %isNotNullA, %isNotNullB
+  %isTrueAndNotNull = and i1 %isTrue, %isNotNull
+  %ret = zext i1 %isTrueAndNotNull to i64
+  ret i64 %ret
+}
+
+;; And likewise for loads reusing a store value.
+define i1 @test2(i8 %V, i8* %P) {
+; CHECK-LABEL: @test2
+; CHECK-NOT: lshr
+  store i8 %V, i8* %P
+  %P2 = bitcast i8* %P to i1*
+  %A = load i1, i1* %P2
+  ret i1 %A
+}
+

Added: llvm/trunk/test/Transforms/GVN/bitcast-of-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/bitcast-of-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/bitcast-of-call.ll (added)
+++ llvm/trunk/test/Transforms/GVN/bitcast-of-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+; PR2213
+
+define i32* @f(i8* %x) {
+entry:
+        %tmp = call i8* @m( i32 12 )            ; <i8*> [#uses=2]
+        %tmp1 = bitcast i8* %tmp to i32*                ; <i32*> [#uses=0]
+        %tmp2 = bitcast i8* %tmp to i32*                ; <i32*> [#uses=0]
+; CHECK-NOT: %tmp2
+        ret i32* %tmp2
+}
+
+declare i8* @m(i32)

Added: llvm/trunk/test/Transforms/GVN/br-identical.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/br-identical.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/br-identical.ll (added)
+++ llvm/trunk/test/Transforms/GVN/br-identical.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt -gvn -S -o - %s | FileCheck %s
+
+; If a branch has two identical successors, we cannot declare either dead.
+
+define void @widget(i1 %p) {
+entry:
+  br label %bb2
+
+bb2:
+  %t1 = phi i64 [ 0, %entry ], [ %t5, %bb7 ]
+  %t2 = add i64 %t1, 1
+  %t3 = icmp ult i64 0, %t2
+  br i1 %t3, label %bb3, label %bb4
+
+bb3:
+  %t4 = call i64 @f()
+  br label %bb4
+
+bb4:
+  ; CHECK-NOT: phi {{.*}} undef
+  %foo = phi i64 [ %t4, %bb3 ], [ 0, %bb2 ]
+  br i1 %p, label %bb5, label %bb6
+
+bb5:
+  br i1 true, label %bb7, label %bb7
+
+bb6:
+  br i1 true, label %bb7, label %bb7
+
+bb7:
+  %t5 = add i64 %t1, 1
+  br i1 %p, label %bb2, label %bb8
+
+bb8:
+  ret void
+}
+
+declare i64 @f()

Added: llvm/trunk/test/Transforms/GVN/callbr-loadpre-critedge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/callbr-loadpre-critedge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/callbr-loadpre-critedge.ll (added)
+++ llvm/trunk/test/Transforms/GVN/callbr-loadpre-critedge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+; This test checks that we don't hang trying to split a critical edge in loadpre
+; when the control flow uses a callbr instruction.
+
+%struct.pluto = type <{ i8, i8 }>
+
+define void @widget(%struct.pluto** %tmp1) {
+; CHECK-LABEL: @widget(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    callbr void asm sideeffect "", "X,X"(i8* blockaddress(@widget, [[BB5:%.*]]), i8* blockaddress(@widget, [[BB8:%.*]]))
+; CHECK-NEXT:    to label [[BB4:%.*]] [label [[BB5]], label %bb8]
+; CHECK:       bb4:
+; CHECK-NEXT:    br label [[BB5]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[TMP6:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1:%.*]]
+; CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_PLUTO:%.*]], %struct.pluto* [[TMP6]], i64 0, i32 1
+; CHECK-NEXT:    br label [[BB8]]
+; CHECK:       bb8:
+; CHECK-NEXT:    [[TMP9:%.*]] = phi i8* [ [[TMP7]], [[BB5]] ], [ null, [[BB:%.*]] ]
+; CHECK-NEXT:    [[TMP10:%.*]] = load %struct.pluto*, %struct.pluto** [[TMP1]]
+; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_PLUTO]], %struct.pluto* [[TMP10]], i64 0, i32 0
+; CHECK-NEXT:    [[TMP12:%.*]] = load i8, i8* [[TMP11]]
+; CHECK-NEXT:    tail call void @spam(i8* [[TMP9]], i8 [[TMP12]])
+; CHECK-NEXT:    ret void
+;
+bb:
+  callbr void asm sideeffect "", "X,X"(i8* blockaddress(@widget, %bb5), i8* blockaddress(@widget, %bb8))
+  to label %bb4 [label %bb5, label %bb8]
+
+bb4:                                              ; preds = %bb
+  br label %bb5
+
+bb5:                                              ; preds = %bb4, %bb
+  %tmp6 = load %struct.pluto*, %struct.pluto** %tmp1
+  %tmp7 = getelementptr inbounds %struct.pluto, %struct.pluto* %tmp6, i64 0, i32 1
+  br label %bb8
+
+bb8:                                              ; preds = %bb5, %bb
+  %tmp9 = phi i8* [ %tmp7, %bb5 ], [ null, %bb ]
+  %tmp10 = load %struct.pluto*, %struct.pluto** %tmp1
+  %tmp11 = getelementptr inbounds %struct.pluto, %struct.pluto* %tmp10, i64 0, i32 0
+  %tmp12 = load i8, i8* %tmp11
+  tail call void @spam(i8* %tmp9, i8 %tmp12)
+  ret void
+}
+
+declare void @spam(i8*, i8)

Added: llvm/trunk/test/Transforms/GVN/callbr-scalarpre-critedge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/callbr-scalarpre-critedge.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/callbr-scalarpre-critedge.ll (added)
+++ llvm/trunk/test/Transforms/GVN/callbr-scalarpre-critedge.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+; This test checks that we don't hang trying to split a critical edge in scalar
+; PRE when the control flow uses a callbr instruction.
+
+define void @wombat(i64 %arg, i64* %arg1, i64 %arg2, i32* %arg3) {
+; CHECK-LABEL: @wombat(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP5:%.*]] = or i64 [[ARG2:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    callbr void asm sideeffect "", "X,X"(i8* blockaddress(@wombat, [[BB7:%.*]]), i8* blockaddress(@wombat, [[BB9:%.*]]))
+; CHECK-NEXT:    to label [[BB6:%.*]] [label [[BB7]], label %bb9]
+; CHECK:       bb6:
+; CHECK-NEXT:    br label [[BB7]]
+; CHECK:       bb7:
+; CHECK-NEXT:    [[TMP8:%.*]] = trunc i64 [[TMP5]] to i32
+; CHECK-NEXT:    tail call void @barney(i32 [[TMP8]])
+; CHECK-NEXT:    br label [[BB9]]
+; CHECK:       bb9:
+; CHECK-NEXT:    [[TMP10:%.*]] = trunc i64 [[TMP5]] to i32
+; CHECK-NEXT:    store i32 [[TMP10]], i32* [[ARG3:%.*]]
+; CHECK-NEXT:    ret void
+;
+bb:
+  %tmp5 = or i64 %arg2, %arg
+  callbr void asm sideeffect "", "X,X"(i8* blockaddress(@wombat, %bb7), i8* blockaddress(@wombat, %bb9))
+          to label %bb6 [label %bb7, label %bb9]
+
+bb6:                                              ; preds = %bb
+  br label %bb7
+
+bb7:                                              ; preds = %bb6, %bb
+  %tmp8 = trunc i64 %tmp5 to i32
+  tail call void @barney(i32 %tmp8)
+  br label %bb9
+
+bb9:                                              ; preds = %bb7, %bb
+  %tmp10 = trunc i64 %tmp5 to i32
+  store i32 %tmp10, i32* %arg3
+  ret void
+}
+
+declare void @barney(i32)

Added: llvm/trunk/test/Transforms/GVN/calloc-load-removal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/calloc-load-removal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/calloc-load-removal.ll (added)
+++ llvm/trunk/test/Transforms/GVN/calloc-load-removal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
+; RUN: opt -S -basicaa -gvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS
+; Check that loads from calloc are recognized as being zero.
+
+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"
+
+; Function Attrs: nounwind uwtable
+define i32 @test1() {
+  %1 = tail call noalias i8* @calloc(i64 1, i64 4)
+  %2 = bitcast i8* %1 to i32*
+  ; This load is trivially constant zero
+  %3 = load i32, i32* %2, align 4
+  ret i32 %3
+
+; CHECK-LABEL: @test1(
+; CHECK-NOT: %3 = load i32, i32* %2, align 4
+; CHECK: ret i32 0
+
+; CHECK_NO_LIBCALLS-LABEL: @test1(
+; CHECK_NO_LIBCALLS: load
+; CHECK_NO_LIBCALLS: ret i32 %
+
+}
+
+declare noalias i8* @calloc(i64, i64)

Added: llvm/trunk/test/Transforms/GVN/calls-nonlocal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/calls-nonlocal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/calls-nonlocal.ll (added)
+++ llvm/trunk/test/Transforms/GVN/calls-nonlocal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,75 @@
+; Two occurrences of strlen should be zapped.
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9"
+
+define i32 @test(i32 %g, i8* %P) nounwind  {
+entry:
+	%tmp2 = call i32 @strlen( i8* %P ) nounwind readonly 		; <i32> [#uses=1]
+	%tmp3 = icmp eq i32 %tmp2, 100		; <i1> [#uses=1]
+	%tmp34 = zext i1 %tmp3 to i8		; <i8> [#uses=1]
+	%toBool = icmp ne i8 %tmp34, 0		; <i1> [#uses=1]
+	br i1 %toBool, label %bb, label %bb6
+
+bb:		; preds = %entry
+	br label %bb27
+
+bb6:		; preds = %entry
+	%tmp8 = add i32 %g, 42		; <i32> [#uses=2]
+	%tmp10 = call i32 @strlen( i8* %P ) nounwind readonly 		; <i32> [#uses=1]
+	%tmp11 = icmp eq i32 %tmp10, 100		; <i1> [#uses=1]
+	%tmp1112 = zext i1 %tmp11 to i8		; <i8> [#uses=1]
+	%toBool13 = icmp ne i8 %tmp1112, 0		; <i1> [#uses=1]
+	br i1 %toBool13, label %bb14, label %bb16
+
+bb14:		; preds = %bb6
+	br label %bb27
+
+bb16:		; preds = %bb6
+	%tmp18 = mul i32 %tmp8, 2		; <i32> [#uses=1]
+	%tmp20 = call i32 @strlen( i8* %P ) nounwind readonly 		; <i32> [#uses=1]
+	%tmp21 = icmp eq i32 %tmp20, 100		; <i1> [#uses=1]
+	%tmp2122 = zext i1 %tmp21 to i8		; <i8> [#uses=1]
+	%toBool23 = icmp ne i8 %tmp2122, 0		; <i1> [#uses=1]
+	br i1 %toBool23, label %bb24, label %bb26
+
+bb24:		; preds = %bb16
+	br label %bb27
+
+bb26:		; preds = %bb16
+	br label %bb27
+
+bb27:		; preds = %bb26, %bb24, %bb14, %bb
+	%tmp.0 = phi i32 [ 11, %bb26 ], [ %tmp18, %bb24 ], [ %tmp8, %bb14 ], [ %g, %bb ]		; <i32> [#uses=1]
+	br label %return
+
+return:		; preds = %bb27
+	ret i32 %tmp.0
+}
+
+; CHECK: define i32 @test(i32 %g, i8* %P) #0 {
+; CHECK: entry:
+; CHECK:   %tmp2 = call i32 @strlen(i8* %P) #1
+; CHECK:   %tmp3 = icmp eq i32 %tmp2, 100
+; CHECK:   %tmp34 = zext i1 %tmp3 to i8
+; CHECK:   br i1 %tmp3, label %bb, label %bb6
+; CHECK: bb:
+; CHECK:   br label %bb27
+; CHECK: bb6:
+; CHECK:   %tmp8 = add i32 %g, 42
+; CHECK:   br i1 false, label %bb14, label %bb16
+; CHECK: bb14:
+; CHECK:   br label %bb27
+; CHECK: bb16:
+; CHECK:   %tmp18 = mul i32 %tmp8, 2
+; CHECK:   br i1 false, label %bb24, label %bb26
+; CHECK: bb24:
+; CHECK:   br label %bb27
+; CHECK: bb26:
+; CHECK:   br label %bb27
+; CHECK: bb27:
+; CHECK:   %tmp.0 = phi i32 [ 11, %bb26 ], [ undef, %bb24 ], [ undef, %bb14 ], [ %g, %bb ]
+; CHECK:   ret i32 %tmp.0
+; CHECK: }
+
+declare i32 @strlen(i8*) nounwind readonly 

Added: llvm/trunk/test/Transforms/GVN/calls-readonly.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/calls-readonly.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/calls-readonly.ll (added)
+++ llvm/trunk/test/Transforms/GVN/calls-readonly.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+; Should delete the second call to strlen even though the intervening strchr call exists.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+
+define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) nounwind readonly {
+entry:
+  %0 = tail call i32 @strlen(i8* %P)              ; <i32> [#uses=2]
+  %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
+  br i1 %1, label %bb, label %bb1
+
+bb:                                               ; preds = %entry
+  %2 = sdiv i32 %x, %y                            ; <i32> [#uses=1]
+  br label %bb1
+
+bb1:                                              ; preds = %bb, %entry
+  %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] ; <i32> [#uses=1]
+  %3 = tail call i8* @strchr(i8* %Q, i32 97)      ; <i8*> [#uses=1]
+  %4 = tail call i32 @strlen(i8* %P)              ; <i32> [#uses=1]
+  %5 = add i32 %x_addr.0, %0                      ; <i32> [#uses=1]
+  %.sum = sub i32 %5, %4                          ; <i32> [#uses=1]
+  %6 = getelementptr i8, i8* %3, i32 %.sum            ; <i8*> [#uses=1]
+  ret i8* %6
+}
+
+; CHECK: define i8* @test(i8* %P, i8* %Q, i32 %x, i32 %y) #0 {
+; CHECK: entry:
+; CHECK-NEXT:   %0 = tail call i32 @strlen(i8* %P)
+; CHECK-NEXT:   %1 = icmp eq i32 %0, 0
+; CHECK-NEXT:   br i1 %1, label %bb, label %bb1
+; CHECK: bb:
+; CHECK-NEXT:   %2 = sdiv i32 %x, %y
+; CHECK-NEXT:   br label %bb1
+; CHECK: bb1:
+; CHECK-NEXT:   %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ]
+; CHECK-NEXT:   %3 = tail call i8* @strchr(i8* %Q, i32 97)
+; CHECK-NEXT:   %4 = add i32 %x_addr.0, %0
+; CHECK-NEXT:   %5 = getelementptr i8, i8* %3, i32 %x_addr.0
+; CHECK-NEXT:   ret i8* %5
+; CHECK: }
+
+declare i32 @strlen(i8*) nounwind readonly
+
+declare i8* @strchr(i8*, i32) nounwind readonly

Added: llvm/trunk/test/Transforms/GVN/commute.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/commute.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/commute.ll (added)
+++ llvm/trunk/test/Transforms/GVN/commute.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,23 @@
+; RUN: opt -gvn -S < %s | FileCheck %s
+
+declare void @use(i32, i32)
+
+define void @foo(i32 %x, i32 %y) {
+  ; CHECK-LABEL: @foo(
+  %add1 = add i32 %x, %y
+  %add2 = add i32 %y, %x
+  call void @use(i32 %add1, i32 %add2)
+  ; CHECK: @use(i32 %add1, i32 %add1)
+  ret void
+}
+
+declare void @vse(i1, i1)
+
+define void @bar(i32 %x, i32 %y) {
+  ; CHECK-LABEL: @bar(
+  %cmp1 = icmp ult i32 %x, %y
+  %cmp2 = icmp ugt i32 %y, %x
+  call void @vse(i1 %cmp1, i1 %cmp2)
+  ; CHECK: @vse(i1 %cmp1, i1 %cmp1)
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVN/cond_br.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/cond_br.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/cond_br.ll (added)
+++ llvm/trunk/test/Transforms/GVN/cond_br.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+ at y = external global i32
+ at z = external global i32
+
+; Function Attrs: nounwind ssp uwtable
+define void @foo(i32 %x) {
+; CHECK: @foo(i32 %x)
+; CHECK: %.pre = load i32, i32* @y
+; CHECK: call void @bar(i32 %.pre)
+
+  %t = sub i32 %x, %x
+  %.pre = load i32, i32* @y, align 4
+  %cmp = icmp sgt i32 %t, 2
+  br i1 %cmp, label %if.then, label %entry.if.end_crit_edge
+
+entry.if.end_crit_edge:                           ; preds = %entry
+  br label %if.end
+
+if.then:                                          ; preds = %entry
+  %add = add nsw i32 %x, 3
+  store i32 %add, i32* @y, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %entry.if.end_crit_edge, %if.then
+  %1 = phi i32 [ %.pre, %entry.if.end_crit_edge ], [ %add, %if.then ]
+  tail call void @bar(i32 %1)
+  ret void
+}
+
+define void @foo2(i32 %x) {
+; CHECK: @foo2(i32 %x)
+; CHECK: %.pre = load i32, i32* @y
+; CHECK: tail call void @bar(i32 %.pre)
+entry:
+  %t = sub i32 %x, %x
+  %.pre = load i32, i32* @y, align 4
+  %cmp = icmp sgt i32 %t, 2
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %add = add nsw i32 %x, 3
+  store i32 %add, i32* @y, align 4
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  store i32 1, i32* @z, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %0 = phi i32 [ %.pre, %if.else ], [ %add, %if.then ]
+  tail call void @bar(i32 %0)
+  ret void
+}
+
+declare void @bar(i32)

Added: llvm/trunk/test/Transforms/GVN/cond_br2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/cond_br2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/cond_br2.ll (added)
+++ llvm/trunk/test/Transforms/GVN/cond_br2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,140 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+%"class.llvm::SmallVector" = type { %"class.llvm::SmallVectorImpl", [1 x %"union.llvm::SmallVectorBase::U"] }
+%"class.llvm::SmallVectorImpl" = type { %"class.llvm::SmallVectorTemplateBase" }
+%"class.llvm::SmallVectorTemplateBase" = type { %"class.llvm::SmallVectorTemplateCommon" }
+%"class.llvm::SmallVectorTemplateCommon" = type { %"class.llvm::SmallVectorBase" }
+%"class.llvm::SmallVectorBase" = type { i8*, i8*, i8*, %"union.llvm::SmallVectorBase::U" }
+%"union.llvm::SmallVectorBase::U" = type { x86_fp80 }
+
+; Function Attrs: ssp uwtable
+define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+; CHECK: @_Z4testv()
+; CHECK: invoke.cont:
+; CHECK: br i1 true, label %new.notnull.i11, label %if.end.i14
+; CHECK: Retry.i10:
+
+entry:
+  %sv = alloca %"class.llvm::SmallVector", align 16
+  %0 = bitcast %"class.llvm::SmallVector"* %sv to i8*
+  call void @llvm.lifetime.start.p0i8(i64 64, i8* %0) #1
+  %BeginX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 0
+  %FirstEl.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 3
+  %1 = bitcast %"union.llvm::SmallVectorBase::U"* %FirstEl.i.i.i.i.i.i to i8*
+  store i8* %1, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4
+  %EndX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1
+  store i8* %1, i8** %EndX.i.i.i.i.i.i, align 8, !tbaa !4
+  %CapacityX.i.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2
+  %add.ptr.i.i.i.i2.i.i = getelementptr inbounds %"union.llvm::SmallVectorBase::U", %"union.llvm::SmallVectorBase::U"* %FirstEl.i.i.i.i.i.i, i64 2
+  %add.ptr.i.i.i.i.i.i = bitcast %"union.llvm::SmallVectorBase::U"* %add.ptr.i.i.i.i2.i.i to i8*
+  store i8* %add.ptr.i.i.i.i.i.i, i8** %CapacityX.i.i.i.i.i.i, align 16, !tbaa !4
+  %EndX.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1
+  %2 = load i8*, i8** %EndX.i, align 8, !tbaa !4
+  %CapacityX.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2
+  %cmp.i = icmp ult i8* %2, %add.ptr.i.i.i.i.i.i
+  br i1 %cmp.i, label %Retry.i, label %if.end.i
+
+Retry.i:                                          ; preds = %.noexc, %entry
+  %3 = phi i8* [ %2, %entry ], [ %.pre.i, %.noexc ]
+  %new.isnull.i = icmp eq i8* %3, null
+  br i1 %new.isnull.i, label %invoke.cont, label %new.notnull.i
+
+new.notnull.i:                                    ; preds = %Retry.i
+  %4 = bitcast i8* %3 to i32*
+  store i32 1, i32* %4, align 4, !tbaa !5
+  br label %invoke.cont
+
+if.end.i:                                         ; preds = %entry
+  %5 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0
+  invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"* %5, i64 0, i64 4)
+          to label %.noexc unwind label %lpad
+
+.noexc:                                           ; preds = %if.end.i
+  %.pre.i = load i8*, i8** %EndX.i, align 8, !tbaa !4
+  br label %Retry.i
+
+invoke.cont:                                      ; preds = %new.notnull.i, %Retry.i
+  %add.ptr.i = getelementptr inbounds i8, i8* %3, i64 4
+  store i8* %add.ptr.i, i8** %EndX.i, align 8, !tbaa !4
+  %6 = load i8*, i8** %CapacityX.i, align 16, !tbaa !4
+  %cmp.i8 = icmp ult i8* %add.ptr.i, %6
+  br i1 %cmp.i8, label %new.notnull.i11, label %if.end.i14
+
+Retry.i10:                                        ; preds = %if.end.i14
+  %.pre.i13 = load i8*, i8** %EndX.i, align 8, !tbaa !4
+  %new.isnull.i9 = icmp eq i8* %.pre.i13, null
+  br i1 %new.isnull.i9, label %invoke.cont2, label %new.notnull.i11
+
+new.notnull.i11:                                  ; preds = %invoke.cont, %Retry.i10
+  %7 = phi i8* [ %.pre.i13, %Retry.i10 ], [ %add.ptr.i, %invoke.cont ]
+  %8 = bitcast i8* %7 to i32*
+  store i32 2, i32* %8, align 4, !tbaa !5
+  br label %invoke.cont2
+
+if.end.i14:                                       ; preds = %invoke.cont
+  %9 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %sv, i64 0, i32 0, i32 0, i32 0, i32 0
+  invoke void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"* %9, i64 0, i64 4)
+          to label %Retry.i10 unwind label %lpad
+
+invoke.cont2:                                     ; preds = %new.notnull.i11, %Retry.i10
+  %10 = phi i8* [ null, %Retry.i10 ], [ %7, %new.notnull.i11 ]
+  %add.ptr.i12 = getelementptr inbounds i8, i8* %10, i64 4
+  store i8* %add.ptr.i12, i8** %EndX.i, align 8, !tbaa !4
+  invoke void @_Z1gRN4llvm11SmallVectorIiLj8EEE(%"class.llvm::SmallVector"* %sv)
+          to label %invoke.cont3 unwind label %lpad
+
+invoke.cont3:                                     ; preds = %invoke.cont2
+  %11 = load i8*, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4
+  %cmp.i.i.i.i19 = icmp eq i8* %11, %1
+  br i1 %cmp.i.i.i.i19, label %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21, label %if.then.i.i.i20
+
+if.then.i.i.i20:                                  ; preds = %invoke.cont3
+  call void @free(i8* %11) #1
+  br label %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21
+
+_ZN4llvm11SmallVectorIiLj8EED1Ev.exit21:          ; preds = %invoke.cont3, %if.then.i.i.i20
+  call void @llvm.lifetime.end.p0i8(i64 64, i8* %0) #1
+  ret void
+
+lpad:                                             ; preds = %if.end.i14, %if.end.i, %invoke.cont2
+  %12 = landingpad { i8*, i32 }
+          cleanup
+  %13 = load i8*, i8** %BeginX.i.i.i.i.i.i, align 16, !tbaa !4
+  %cmp.i.i.i.i = icmp eq i8* %13, %1
+  br i1 %cmp.i.i.i.i, label %eh.resume, label %if.then.i.i.i
+
+if.then.i.i.i:                                    ; preds = %lpad
+  call void @free(i8* %13) #1
+  br label %eh.resume
+
+eh.resume:                                        ; preds = %if.then.i.i.i, %lpad
+  resume { i8*, i32 } %12
+}
+
+; Function Attrs: nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @_Z1gRN4llvm11SmallVectorIiLj8EEE(%"class.llvm::SmallVector"*) #2
+
+; Function Attrs: nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+declare void @_ZN4llvm15SmallVectorBase8grow_podEmm(%"class.llvm::SmallVectorBase"*, i64, i64) #2
+
+; Function Attrs: nounwind
+declare void @free(i8* nocapture) #3
+
+attributes #0 = { ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind }
+attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!0 = !{!"any pointer", !1}
+!1 = !{!"omnipotent char", !2}
+!2 = !{!"Simple C/C++ TBAA"}
+!3 = !{!"int", !1}
+!4 = !{!0, !0, i64 0}
+!5 = !{!3, !3, i64 0}

Added: llvm/trunk/test/Transforms/GVN/condprop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/condprop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/condprop.ll (added)
+++ llvm/trunk/test/Transforms/GVN/condprop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,371 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+ at a = external global i32		; <i32*> [#uses=7]
+
+; CHECK-LABEL: @test1(
+define i32 @test1() nounwind {
+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
+; CHECK: br i1 false, label %bb4, label %bb5
+	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
+; CHECK: br i1 false, label %bb6, label %bb7
+	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)
+
+; CHECK-LABEL: @test3(
+define void @test3(i32 %x, i32 %y) {
+  %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)
+; CHECK: call void @foo(i1 true)
+  call void @foo(i1 %yz)
+; CHECK: call void @foo(i1 true)
+  call void @bar(i32 %x)
+; CHECK: call void @bar(i32 0)
+  call void @bar(i32 %y)
+; CHECK: call void @bar(i32 0)
+  ret void
+nope:
+  call void @foo(i1 %z)
+; CHECK: call void @foo(i1 false)
+  ret void
+}
+
+; CHECK-LABEL: @test4(
+define void @test4(i1 %b, i32 %x) {
+  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:
+; CHECK: default:
+  call void @bar(i32 %x)
+; CHECK: call void @bar(i32 %x)
+  ret void
+case0:
+; CHECK: case0:
+  call void @bar(i32 %x)
+; CHECK: call void @bar(i32 %x)
+  ret void
+case1:
+; CHECK: case1:
+  call void @bar(i32 %x)
+; CHECK: call void @bar(i32 1)
+  ret void
+case3:
+; CHECK: case3:
+  call void @bar(i32 %x)
+; CHECK: call void @bar(i32 %x)
+  ret void
+}
+
+; CHECK-LABEL: @test5(
+define i1 @test5(i32 %x, i32 %y) {
+  %cmp = icmp eq i32 %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  %cmp2 = icmp ne i32 %x, %y
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+  %cmp3 = icmp eq i32 %x, %y
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; CHECK-LABEL: @test6(
+define i1 @test6(i32 %x, i32 %y) {
+  %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:
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; CHECK-LABEL: @test6_fp(
+define i1 @test6_fp(float %x, float %y) {
+  %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:
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; CHECK-LABEL: @test7(
+define i1 @test7(i32 %x, i32 %y) {
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  %cmp2 = icmp sle i32 %x, %y
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+  %cmp3 = icmp sgt i32 %x, %y
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; CHECK-LABEL: @test7_fp(
+define i1 @test7_fp(float %x, float %y) {
+  %cmp = fcmp ogt float %x, %y
+  br i1 %cmp, label %same, label %different
+
+same:
+  %cmp2 = fcmp ule float %x, %y
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+  %cmp3 = fcmp ogt float %x, %y
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; CHECK-LABEL: @test8(
+define i1 @test8(i32 %x, i32 %y) {
+  %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:
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; CHECK-LABEL: @test8_fp(
+define i1 @test8_fp(float %x, float %y) {
+  %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:
+; CHECK: ret i1 false
+  ret i1 %cmp2
+
+different:
+; CHECK: ret i1 false
+  ret i1 %cmp3
+}
+
+; PR1768
+; CHECK-LABEL: @test9(
+define i32 @test9(i32 %i, i32 %j) {
+  %cmp = icmp eq i32 %i, %j
+  br i1 %cmp, label %cond_true, label %ret
+
+cond_true:
+  %diff = sub i32 %i, %j
+  ret i32 %diff
+; CHECK: ret i32 0
+
+ret:
+  ret i32 5
+; CHECK: ret i32 5
+}
+
+; PR1768
+; CHECK-LABEL: @test10(
+define i32 @test10(i32 %j, i32 %i) {
+  %cmp = icmp eq i32 %i, %j
+  br i1 %cmp, label %cond_true, label %ret
+
+cond_true:
+  %diff = sub i32 %i, %j
+  ret i32 %diff
+; CHECK: ret i32 0
+
+ret:
+  ret i32 5
+; CHECK: ret i32 5
+}
+
+declare i32 @yogibar()
+
+; CHECK-LABEL: @test11(
+define i32 @test11(i32 %x) {
+  %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
+; CHECK: ret i32 %v0
+
+next:
+  %cmp2 = icmp eq i32 %x, %v0
+  br i1 %cmp2, label %cond_true2, label %next2
+
+cond_true2:
+  ret i32 %v0
+; CHECK: ret i32 %x
+
+next2:
+  ret i32 0
+}
+
+; CHECK-LABEL: @test12(
+define i32 @test12(i32 %x) {
+  %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 ]
+; CHECK: %res = phi i32 [ 0, %cond_true ], [ %x, %cond_false ]
+  ret i32 %res
+}
+
+; On the path from entry->if->end we know that ptr1==ptr2, so we can determine
+; that gep2 does not alias ptr1 on that path (as it would require that
+; ptr2==ptr2+2), so we can perform PRE of the load.
+; CHECK-LABEL: @test13
+define i32 @test13(i32* %ptr1, i32* %ptr2) {
+; CHECK-LABEL: entry:
+entry:
+  %gep1 = getelementptr i32, i32* %ptr2, i32 1
+  %gep2 = getelementptr i32, i32* %ptr2, i32 2
+  %cmp = icmp eq i32* %ptr1, %ptr2
+  br i1 %cmp, label %if, label %end
+
+; CHECK: [[CRIT_EDGE:.*]]:
+; CHECK: %[[PRE:.*]] = load i32, i32* %gep2, align 4
+
+; CHECK-LABEL: if:
+if:
+  %val1 = load i32, i32* %gep2, align 4
+  br label %end
+
+; CHECK-LABEL: end:
+; CHECK: %val2 = phi i32 [ %val1, %if ], [ %[[PRE]], %[[CRIT_EDGE]] ]
+; CHECK-NOT: load
+end:
+  %phi1 = phi i32* [ %ptr1, %if ], [ %gep1, %entry ]
+  %phi2 = phi i32 [ %val1, %if ], [ 0, %entry ]
+  store i32 0, i32* %phi1, align 4
+  %val2 = load i32, i32* %gep2, align 4
+  %ret = add i32 %phi2, %val2
+  ret i32 %ret
+}
+
+; CHECK-LABEL: @test14
+define void @test14(i32* %ptr1, i32* noalias %ptr2) {
+entry:
+  %gep1 = getelementptr inbounds i32, i32* %ptr1, i32 1
+  %gep2 = getelementptr inbounds i32, i32* %ptr1, i32 2
+  br label %loop
+
+; CHECK-LABEL: loop:
+loop:
+  %phi1 = phi i32* [ %gep3, %loop.end ], [ %gep1, %entry ]
+  br i1 undef, label %if1, label %then
+
+; CHECK: [[CRIT_EDGE:.*]]:
+; CHECK: %[[PRE:.*]] = load i32, i32* %gep2, align 4
+
+; CHECK-LABEL: if1:
+; CHECK: %val2 = phi i32 [ %[[PRE]], %[[CRIT_EDGE]] ], [ %val3, %loop.end ]
+; CHECK-NOT: load
+if1:
+  %val2 = load i32, i32* %gep2, align 4
+  store i32 %val2, i32* %gep2, align 4
+  store i32 0, i32* %phi1, align 4
+  br label %then
+
+; CHECK-LABEL: then:
+then:
+  %cmp = icmp eq i32* %gep2, %ptr2
+  br i1 %cmp, label %loop.end, label %if2
+
+if2:
+  br label %loop.end
+
+loop.end:
+  %phi3 = phi i32* [ %gep2, %then ], [ %ptr1, %if2 ]
+  %val3 = load i32, i32* %gep2, align 4
+  store i32 %val3, i32* %phi3, align 4
+  %gep3 = getelementptr inbounds i32, i32* %ptr1, i32 1
+  br i1 undef, label %loop, label %if1
+}

Added: llvm/trunk/test/Transforms/GVN/crash-no-aa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/crash-no-aa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/crash-no-aa.ll (added)
+++ llvm/trunk/test/Transforms/GVN/crash-no-aa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,15 @@
+; RUN: opt -disable-basicaa -gvn -S < %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-freebsd8.0"
+
+; PR5744
+define i32 @test1({i16, i32} *%P) {
+  %P2 = getelementptr {i16, i32}, {i16, i32} *%P, i32 0, i32 0
+  store i16 42, i16* %P2
+
+  %P3 = getelementptr {i16, i32}, {i16, i32} *%P, i32 0, i32 1
+  %V = load i32, i32* %P3
+  ret i32 %V
+}
+

Added: llvm/trunk/test/Transforms/GVN/crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/crash.ll (added)
+++ llvm/trunk/test/Transforms/GVN/crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,201 @@
+; RUN: opt -gvn -disable-output < %s
+
+; PR5631
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0"
+
+define i32* @test1(i8* %name, i32 %namelen, i32* %o, i32 %expected_type) nounwind ssp {
+entry:
+  br i1 undef, label %if.end13, label %while.body.preheader
+
+
+if.end13:                                         ; preds = %if.then6
+  br label %while.body.preheader
+
+while.body.preheader:                             ; preds = %if.end13, %if.end
+  br label %while.body
+
+while.body:                                       ; preds = %while.body.backedge, %while.body.preheader
+  %o.addr.0 = phi i32* [ undef, %while.body.preheader ], [ %o.addr.0.be, %while.body.backedge ] ; <i32*> [#uses=2]
+  br i1 false, label %return.loopexit, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %while.body
+  %tmp20 = bitcast i32* %o.addr.0 to i32*         ; <i32*> [#uses=1]
+  %tmp22 = load i32, i32* %tmp20                       ; <i32> [#uses=0]
+  br i1 undef, label %land.lhs.true24, label %if.end31
+
+land.lhs.true24:                                  ; preds = %lor.lhs.false
+  %call28 = call i32* @parse_object(i8* undef) nounwind ; <i32*> [#uses=0]
+  br i1 undef, label %return.loopexit, label %if.end31
+
+if.end31:                                         ; preds = %land.lhs.true24, %lor.lhs.false
+  br i1 undef, label %return.loopexit, label %if.end41
+
+if.end41:                                         ; preds = %if.end31
+  %tmp43 = bitcast i32* %o.addr.0 to i32*         ; <i32*> [#uses=1]
+  %tmp45 = load i32, i32* %tmp43                       ; <i32> [#uses=0]
+  br i1 undef, label %if.then50, label %if.else
+
+if.then50:                                        ; preds = %if.end41
+  %tmp53 = load i32*, i32** undef                       ; <i32*> [#uses=1]
+  br label %while.body.backedge
+
+if.else:                                          ; preds = %if.end41
+  br i1 undef, label %if.then62, label %if.else67
+
+if.then62:                                        ; preds = %if.else
+  br label %while.body.backedge
+
+while.body.backedge:                              ; preds = %if.then62, %if.then50
+  %o.addr.0.be = phi i32* [ %tmp53, %if.then50 ], [ undef, %if.then62 ] ; <i32*> [#uses=1]
+  br label %while.body
+
+if.else67:                                        ; preds = %if.else
+  ret i32* null
+
+return.loopexit:                                  ; preds = %if.end31, %land.lhs.true24, %while.body
+  ret i32* undef
+}
+
+declare i32* @parse_object(i8*)
+
+
+
+
+
+
+%struct.attribute_spec = type { i8*, i32, i32, i8, i8, i8 }
+
+ at attribute_tables = external global [4 x %struct.attribute_spec*] ; <[4 x %struct.attribute_spec*]*> [#uses=2]
+
+define void @test2() nounwind {
+entry:
+  br label %bb69.i
+
+bb69.i:                                           ; preds = %bb57.i.preheader
+  %tmp4 = getelementptr inbounds [4 x %struct.attribute_spec*], [4 x %struct.attribute_spec*]* @attribute_tables, i32 0, i32 undef ; <%struct.attribute_spec**> [#uses=1]
+  %tmp3 = load %struct.attribute_spec*, %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1]
+  br label %bb65.i
+
+bb65.i:                                           ; preds = %bb65.i.preheader, %bb64.i
+  %storemerge6.i = phi i32 [ 1, %bb64.i ], [ 0, %bb69.i ] ; <i32> [#uses=3]
+  %scevgep14 = getelementptr inbounds %struct.attribute_spec, %struct.attribute_spec* %tmp3, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=1]
+  %tmp2 = load i8*, i8** %scevgep14, align 4           ; <i8*> [#uses=0]
+  %tmp = load %struct.attribute_spec*, %struct.attribute_spec** %tmp4, align 4 ; <%struct.attribute_spec*> [#uses=1]
+  %scevgep1516 = getelementptr inbounds %struct.attribute_spec, %struct.attribute_spec* %tmp, i32 %storemerge6.i, i32 0 ; <i8**> [#uses=0]
+  unreachable
+
+bb64.i:                                           ; Unreachable
+  br label %bb65.i
+
+bb66.i:                                           ; Unreachable
+  br label %bb69.i
+}
+
+
+
+; rdar://7438974
+
+ at g = external global i64, align 8
+
+define i32* @test3() {
+do.end17.i:
+  %tmp18.i = load i7*, i7** undef
+  %tmp1 = bitcast i7* %tmp18.i to i8*
+  br i1 undef, label %do.body36.i, label %if.then21.i
+
+if.then21.i:
+  %tmp2 = bitcast i7* %tmp18.i to i8*
+  ret i32* undef
+
+do.body36.i:
+  %ivar38.i = load i64, i64* @g 
+  %tmp3 = bitcast i7* %tmp18.i to i8*
+  %add.ptr39.sum.i = add i64 %ivar38.i, 8
+  %tmp40.i = getelementptr inbounds i8, i8* %tmp3, i64 %add.ptr39.sum.i
+  %tmp4 = bitcast i8* %tmp40.i to i64*
+  %tmp41.i = load i64, i64* %tmp4
+  br i1 undef, label %if.then48.i, label %do.body57.i
+
+if.then48.i:
+  %call54.i = call i32 @foo2()
+  br label %do.body57.i
+
+do.body57.i:
+  %tmp58.i = load i7*, i7** undef
+  %ivar59.i = load i64, i64* @g
+  %tmp5 = bitcast i7* %tmp58.i to i8*
+  %add.ptr65.sum.i = add i64 %ivar59.i, 8
+  %tmp66.i = getelementptr inbounds i8, i8* %tmp5, i64 %add.ptr65.sum.i
+  %tmp6 = bitcast i8* %tmp66.i to i64*
+  %tmp67.i = load i64, i64* %tmp6
+  ret i32* undef
+}
+
+declare i32 @foo2()
+
+
+
+define i32 @test4() {
+entry:
+  ret i32 0
+  
+dead:
+  %P2 = getelementptr i32, i32 *%P2, i32 52
+  %Q2 = getelementptr i32, i32 *%Q2, i32 52
+  store i32 4, i32* %P2
+  %A = load i32, i32* %Q2
+  br i1 true, label %dead, label %dead2
+  
+dead2:
+  ret i32 %A
+}
+
+
+; PR9841
+define fastcc i8 @test5(i8* %P) nounwind {
+entry:
+  %0 = load i8, i8* %P, align 2
+
+  %Q = getelementptr i8, i8* %P, i32 1
+  %1 = load i8, i8* %Q, align 1
+  ret i8 %1
+}
+
+
+; Test that a GEP in an unreachable block with the following form doesn't crash
+; GVN:
+;
+;    %x = gep %some.type %x, ...
+
+%struct.type = type { i64, i32, i32 }
+
+define fastcc void @func() nounwind uwtable ssp align 2 {
+entry:
+  br label %reachable.bb
+
+;; Unreachable code.
+
+unreachable.bb:
+  %gep.val = getelementptr inbounds %struct.type, %struct.type* %gep.val, i64 1
+  br i1 undef, label %u2.bb, label %u1.bb
+
+u1.bb:
+  %tmp1 = getelementptr inbounds %struct.type, %struct.type* %gep.val, i64 0, i32 0
+  store i64 -1, i64* %tmp1, align 8
+  br label %unreachable.bb
+
+u2.bb:
+  %0 = load i32, i32* undef, align 4
+  %conv.i.i.i.i.i = zext i32 %0 to i64
+  br label %u2.bb
+
+;; Reachable code.
+
+reachable.bb:
+  br label %r1.bb
+
+r1.bb:
+  br label %u2.bb
+}

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

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

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

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

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

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

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

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

Added: llvm/trunk/test/Transforms/GVN/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/int_sideeffect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/int_sideeffect.ll (added)
+++ llvm/trunk/test/Transforms/GVN/int_sideeffect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; RUN: opt -S < %s -gvn | FileCheck %s
+
+declare void @llvm.sideeffect()
+
+; Store-to-load forwarding across a @llvm.sideeffect.
+
+; CHECK-LABEL: s2l
+; CHECK-NOT: load
+define float @s2l(float* %p) {
+    store float 0.0, float* %p
+    call void @llvm.sideeffect()
+    %t = load float, float* %p
+    ret float %t
+}
+
+; Redundant load elimination across a @llvm.sideeffect.
+
+; CHECK-LABEL: rle
+; CHECK: load
+; CHECK-NOT: load
+define float @rle(float* %p) {
+    %r = load float, float* %p
+    call void @llvm.sideeffect()
+    %s = load float, float* %p
+    %t = fadd float %r, %s
+    ret float %t
+}
+
+; LICM across a @llvm.sideeffect.
+
+; CHECK-LABEL: licm
+; CHECK: load
+; CHECK: loop:
+; CHECK-NOT: load
+define float @licm(i64 %n, float* nocapture readonly %p) #0 {
+bb0:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %bb0 ], [ %t5, %loop ]
+  %sum = phi float [ 0.000000e+00, %bb0 ], [ %t4, %loop ]
+  call void @llvm.sideeffect()
+  %t3 = load float, float* %p
+  %t4 = fadd float %sum, %t3
+  %t5 = add i64 %i, 1
+  %t6 = icmp ult i64 %t5, %n
+  br i1 %t6, label %loop, label %bb2
+
+bb2:
+  ret float %t4
+}

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

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

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

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

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

Added: llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll (added)
+++ llvm/trunk/test/Transforms/GVN/malloc-load-removal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,56 @@
+; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
+; RUN: opt -S -basicaa -gvn -disable-simplify-libcalls < %s | FileCheck %s -check-prefix=CHECK_NO_LIBCALLS
+; PR13694
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.8.0"
+
+declare i8* @malloc(i64) nounwind
+
+define noalias i8* @test1() nounwind uwtable ssp {
+entry:
+  %call = tail call i8* @malloc(i64 100) nounwind
+  %0 = load i8, i8* %call, align 1
+  %tobool = icmp eq i8 %0, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  store i8 0, i8* %call, align 1
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  ret i8* %call
+
+; CHECK-LABEL: @test1(
+; CHECK-NOT: load
+; CHECK-NOT: icmp
+
+; CHECK_NO_LIBCALLS-LABEL: @test1(
+; CHECK_NO_LIBCALLS: load
+; CHECK_NO_LIBCALLS: icmp
+}
+
+declare i8* @_Znwm(i64) nounwind
+
+define noalias i8* @test2() nounwind uwtable ssp {
+entry:
+  %call = tail call i8* @_Znwm(i64 100) nounwind
+  %0 = load i8, i8* %call, align 1
+  %tobool = icmp eq i8 %0, 0
+  br i1 %tobool, label %if.end, label %if.then
+
+if.then:                                          ; preds = %entry
+  store i8 0, i8* %call, align 1
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  ret i8* %call
+
+; CHECK-LABEL: @test2(
+; CHECK-NOT: load
+; CHECK-NOT: icmp
+
+; CHECK_NO_LIBCALLS-LABEL: @test2(
+; CHECK_NO_LIBCALLS: load
+; CHECK_NO_LIBCALLS: icmp
+}

Added: llvm/trunk/test/Transforms/GVN/no-mem-dep-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/no-mem-dep-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/no-mem-dep-info.ll (added)
+++ llvm/trunk/test/Transforms/GVN/no-mem-dep-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt %s -gvn -S -enable-gvn-memdep=false | FileCheck %s
+; RUN: opt %s -gvn -S -enable-gvn-memdep=true | FileCheck %s
+
+; Check that llvm.x86.avx2.gather.d.ps.256 intrinsic is not eliminated by GVN
+; with and without memory dependence info.
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind readonly
+declare <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float>, i8*, <8 x i32>, <8 x float>, i8) #0
+
+; Function Attrs: nounwind
+define <8 x float> @foo1(i8* noalias readonly %arr.ptr, <8 x i32>* noalias readonly %vix.ptr, i8* noalias %t2.ptr) #1 {
+allocas:
+  %vix = load <8 x i32>, <8 x i32>* %vix.ptr, align 4
+  %t1.ptr = getelementptr i8, i8* %arr.ptr, i8 4
+
+  %v1 = tail call <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float> undef, i8* %arr.ptr, <8 x i32> %vix, <8 x float> <float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000>, i8 1) #2
+  store i8 1, i8* %t1.ptr, align 4
+
+  %v2 = tail call <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float> undef, i8* %arr.ptr, <8 x i32> %vix, <8 x float> <float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000>, i8 1) #2
+  %res = fadd <8 x float> %v1, %v2
+
+  ret <8 x float> %res
+}
+; CHECK: foo1
+; CHECK: llvm.x86.avx2.gather.d.ps.256
+; CHECK: store
+; CHECK: llvm.x86.avx2.gather.d.ps.256

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

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

Added: llvm/trunk/test/Transforms/GVN/non-integral-pointers.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/non-integral-pointers.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/non-integral-pointers.ll (added)
+++ llvm/trunk/test/Transforms/GVN/non-integral-pointers.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,287 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f0(i1 %alwaysFalse, i64 %val, i64* %loc) {
+; CHECK-LABEL: @f0(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    store i64 [[VAL:%.*]], i64* [[LOC:%.*]]
+; CHECK-NEXT:    br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
+; CHECK:       neverTaken:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i64* [[LOC]] to i8 addrspace(4)**
+; CHECK-NEXT:    [[PTR:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)** [[LOC_BC]]
+; CHECK-NEXT:    store i8 5, i8 addrspace(4)* [[PTR]]
+; CHECK-NEXT:    ret void
+; CHECK:       alwaysTaken:
+; CHECK-NEXT:    ret void
+;
+  entry:
+  store i64 %val, i64* %loc
+  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
+
+  neverTaken:
+  %loc.bc = bitcast i64* %loc to i8 addrspace(4)**
+  %ptr = load i8 addrspace(4)*, i8 addrspace(4)** %loc.bc
+  store i8 5, i8 addrspace(4)* %ptr
+  ret void
+
+  alwaysTaken:
+  ret void
+}
+
+define i64 @f1(i1 %alwaysFalse, i8 addrspace(4)* %val, i8 addrspace(4)** %loc) {
+; CHECK-LABEL: @f1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    store i8 addrspace(4)* [[VAL:%.*]], i8 addrspace(4)** [[LOC:%.*]]
+; CHECK-NEXT:    br i1 [[ALWAYSFALSE:%.*]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]]
+; CHECK:       neverTaken:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)** [[LOC]] to i64*
+; CHECK-NEXT:    [[INT:%.*]] = load i64, i64* [[LOC_BC]]
+; CHECK-NEXT:    ret i64 [[INT]]
+; CHECK:       alwaysTaken:
+; CHECK-NEXT:    ret i64 42
+;
+  entry:
+  store i8 addrspace(4)* %val, i8 addrspace(4)** %loc
+  br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken
+
+  neverTaken:
+  %loc.bc = bitcast i8 addrspace(4)** %loc to i64*
+  %int = load i64, i64* %loc.bc
+  ret i64 %int
+
+  alwaysTaken:
+  ret i64 42
+}
+
+;; Note: For terseness, we stop using the %alwaysfalse trick for the
+;; tests below and just exercise the bits of forwarding logic directly.
+
+declare void @llvm.memset.p4i8.i64(i8 addrspace(4)* nocapture, i8, i64, i1) nounwind
+
+; Can't forward as the load might be dead.  (Pretend we wrote out the alwaysfalse idiom above.)
+define i8 addrspace(4)* @neg_forward_memset(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_forward_memset(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
+; CHECK-NEXT:    call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 7, i64 8, i1 false)
+; CHECK-NEXT:    [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret i8 addrspace(4)* [[REF]]
+;
+  entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
+  call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 7, i64 8, i1 false)
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+define <1 x i8 addrspace(4)*> @neg_forward_memset_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_forward_memset_vload(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
+; CHECK-NEXT:    call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 7, i64 8, i1 false)
+; CHECK-NEXT:    [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret <1 x i8 addrspace(4)*> [[REF]]
+;
+  entry:
+  %loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i8 addrspace(4)*
+  call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 7, i64 8, i1 false)
+  %ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
+  ret <1 x i8 addrspace(4)*> %ref
+}
+
+
+; Can forward since we can do so w/o breaking types
+define i8 addrspace(4)* @forward_memset_zero(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @forward_memset_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
+; CHECK-NEXT:    call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8 0, i64 8, i1 false)
+; CHECK-NEXT:    ret i8 addrspace(4)* null
+;
+  entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
+  call void @llvm.memset.p4i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8 0, i64 8, i1 false)
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+; Can't forward as the load might be dead.  (Pretend we wrote out the alwaysfalse idiom above.)
+define i8 addrspace(4)* @neg_forward_store(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_forward_store(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
+; CHECK-NEXT:    store i64 5, i64 addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret i8 addrspace(4)* [[REF]]
+;
+  entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i64 addrspace(4)*
+  store i64 5, i64 addrspace(4)* %loc.bc
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+define <1 x i8 addrspace(4)*> @neg_forward_store_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_forward_store_vload(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
+; CHECK-NEXT:    store i64 5, i64 addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret <1 x i8 addrspace(4)*> [[REF]]
+;
+  entry:
+  %loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i64 addrspace(4)*
+  store i64 5, i64 addrspace(4)* %loc.bc
+  %ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
+  ret <1 x i8 addrspace(4)*> %ref
+}
+
+; Nulls have known bit patterns, so we can forward
+define i8 addrspace(4)* @forward_store_zero(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @forward_store_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i64 addrspace(4)*
+; CHECK-NEXT:    store i64 0, i64 addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    ret i8 addrspace(4)* null
+;
+  entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i64 addrspace(4)*
+  store i64 0, i64 addrspace(4)* %loc.bc
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+; Nulls have known bit patterns, so we can forward
+define i8 addrspace(4)* @forward_store_zero2(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @forward_store_zero2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i32> addrspace(4)*
+; CHECK-NEXT:    store <2 x i32> zeroinitializer, <2 x i32> addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    ret i8 addrspace(4)* null
+;
+  entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i32> addrspace(4)*
+  store <2 x i32> zeroinitializer, <2 x i32> addrspace(4)* %loc.bc
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+ at NonZeroConstant = constant <4 x i64> <i64 3, i64 3, i64 3, i64 3>
+ at ZeroConstant = constant <4 x i64> zeroinitializer
+
+
+; Can't forward as the load might be dead.  (Pretend we wrote out the alwaysfalse idiom above.)
+define i8 addrspace(4)* @neg_forward_memcopy(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_forward_memcopy(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
+; CHECK-NEXT:    call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @NonZeroConstant to i8*), i64 8, i1 false)
+; CHECK-NEXT:    [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret i8 addrspace(4)* [[REF]]
+;
+entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
+  %src.bc = bitcast <4 x i64>* @NonZeroConstant to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+define <1 x i8 addrspace(4)*> @neg_forward_memcpy_vload(<1 x i8 addrspace(4)*> addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_forward_memcpy_vload(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast <1 x i8 addrspace(4)*> addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
+; CHECK-NEXT:    call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @NonZeroConstant to i8*), i64 8, i1 false)
+; CHECK-NEXT:    [[REF:%.*]] = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret <1 x i8 addrspace(4)*> [[REF]]
+;
+entry:
+  %loc.bc = bitcast <1 x i8 addrspace(4)*> addrspace(4)* %loc to i8 addrspace(4)*
+  %src.bc = bitcast <4 x i64>* @NonZeroConstant to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
+  %ref = load <1 x i8 addrspace(4)*>, <1 x i8 addrspace(4)*> addrspace(4)* %loc
+  ret <1 x i8 addrspace(4)*> %ref
+}
+
+
+; Can forward since we can do so w/o breaking types
+; TODO: missed optimization
+define i8 addrspace(4)* @forward_memcpy_zero(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @forward_memcpy_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to i8 addrspace(4)*
+; CHECK-NEXT:    call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 [[LOC_BC]], i8* bitcast (<4 x i64>* @ZeroConstant to i8*), i64 8, i1 false)
+; CHECK-NEXT:    [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]]
+; CHECK-NEXT:    ret i8 addrspace(4)* [[REF]]
+;
+entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to i8 addrspace(4)*
+  %src.bc = bitcast <4 x i64>* @ZeroConstant to i8*
+  call void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* align 4 %loc.bc, i8* %src.bc, i64 8, i1 false)
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc
+  ret i8 addrspace(4)* %ref
+}
+
+declare void @llvm.memcpy.p4i8.p0i8.i64(i8 addrspace(4)* nocapture, i8* nocapture, i64, i1) nounwind
+
+
+; Same as the neg_forward_store cases, but for non defs.
+; (Pretend we wrote out the alwaysfalse idiom above.)
+define i8 addrspace(4)* @neg_store_clobber(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_store_clobber(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
+; CHECK-NEXT:    store <2 x i64> <i64 4, i64 4>, <2 x i64> addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
+; CHECK-NEXT:    [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC_OFF]]
+; CHECK-NEXT:    ret i8 addrspace(4)* [[REF]]
+;
+entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
+  store <2 x i64> <i64 4, i64 4>, <2 x i64> addrspace(4)* %loc.bc
+  %loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
+  ret i8 addrspace(4)* %ref
+}
+
+declare void @use(<2 x i64>) inaccessiblememonly
+
+; Same as the neg_forward_store cases, but for non defs.
+; (Pretend we wrote out the alwaysfalse idiom above.)
+define i8 addrspace(4)* @neg_load_clobber(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @neg_load_clobber(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
+; CHECK-NEXT:    [[V:%.*]] = load <2 x i64>, <2 x i64> addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    call void @use(<2 x i64> [[V]])
+; CHECK-NEXT:    [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
+; CHECK-NEXT:    [[REF:%.*]] = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC_OFF]]
+; CHECK-NEXT:    ret i8 addrspace(4)* [[REF]]
+;
+entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
+  %v = load <2 x i64>, <2 x i64> addrspace(4)* %loc.bc
+  call void @use(<2 x i64> %v)
+  %loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
+  ret i8 addrspace(4)* %ref
+}
+
+define i8 addrspace(4)* @store_clobber_zero(i8 addrspace(4)* addrspace(4)* %loc) {
+; CHECK-LABEL: @store_clobber_zero(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[LOC_BC:%.*]] = bitcast i8 addrspace(4)* addrspace(4)* [[LOC:%.*]] to <2 x i64> addrspace(4)*
+; CHECK-NEXT:    store <2 x i64> zeroinitializer, <2 x i64> addrspace(4)* [[LOC_BC]]
+; CHECK-NEXT:    [[LOC_OFF:%.*]] = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* [[LOC]], i64 1
+; CHECK-NEXT:    ret i8 addrspace(4)* null
+;
+entry:
+  %loc.bc = bitcast i8 addrspace(4)* addrspace(4)* %loc to <2 x i64> addrspace(4)*
+  store <2 x i64> zeroinitializer, <2 x i64> addrspace(4)* %loc.bc
+  %loc.off = getelementptr i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc, i64 1
+  %ref = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %loc.off
+  ret i8 addrspace(4)* %ref
+}

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

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

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

Added: llvm/trunk/test/Transforms/GVN/opt-remarks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/opt-remarks.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/opt-remarks.ll (added)
+++ llvm/trunk/test/Transforms/GVN/opt-remarks.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,114 @@
+; RUN: opt < %s -gvn -o /dev/null  -S -pass-remarks=gvn -pass-remarks-missed=gvn  \
+; RUN:     2>&1 | FileCheck %s
+; RUN: opt < %s -gvn -o /dev/null  -pass-remarks-output=%t -S
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=gvn -o /dev/null -S -pass-remarks=gvn -pass-remarks-missed=gvn \
+; RUN:     2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=gvn -o /dev/null -pass-remarks-output=%t -S
+; RUN: cat %t | FileCheck -check-prefix=YAML %s
+
+; CHECK:      remark: <unknown>:0:0: load of type i32 eliminated{{$}}
+; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
+; CHECK-NEXT: remark: <unknown>:0:0: load of type i32 eliminated{{$}}
+; CHECK-NEXT: remark: /tmp/s.c:3:3: load of type i32 not eliminated
+
+; YAML:      --- !Passed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadElim
+; YAML-NEXT: Function:        arg
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - InfavorOfValue:  i
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Passed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadElim
+; YAML-NEXT: Function:        const
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - InfavorOfValue:  '4'
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Passed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadElim
+; YAML-NEXT: Function:        inst
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - InfavorOfValue:  load
+; YAML-NEXT: ...
+; YAML-NEXT: --- !Missed
+; YAML-NEXT: Pass:            gvn
+; YAML-NEXT: Name:            LoadClobbered
+; YAML-NEXT: DebugLoc:        { File: '/tmp/s.c', Line: 3, Column: 3 }
+; YAML-NEXT: Function:        may_alias
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'load of type '
+; YAML-NEXT:   - Type:            i32
+; YAML-NEXT:   - String:          ' not eliminated'
+; YAML-NEXT:   - String:          ' in favor of '
+; YAML-NEXT:   - OtherAccess:     load
+; YAML-NEXT:     DebugLoc:        { File: '/tmp/s.c', Line: 1, Column: 13 }
+; YAML-NEXT:   - String:          ' because it is clobbered by '
+; YAML-NEXT:   - ClobberedBy:     store
+; YAML-NEXT:     DebugLoc:        { File: '/tmp/s.c', Line: 2, Column: 10 }
+; YAML-NEXT: ...
+
+define i32 @arg(i32* %p, i32 %i) {
+entry:
+  store i32 %i, i32* %p
+  %load = load i32, i32* %p
+  ret i32 %load
+}
+
+define i32 @const(i32* %p) {
+entry:
+  store i32 4, i32* %p
+  %load = load i32, i32* %p
+  ret i32 %load
+}
+
+define i32 @inst(i32* %p) {
+entry:
+  %load1 = load i32, i32* %p
+  %load = load i32, i32* %p
+  %add = add i32 %load1, %load
+  ret i32 %add
+}
+
+define i32 @may_alias(i32* %p, i32* %r) !dbg !7 {
+entry:
+  %load1 = load i32, i32* %p, !tbaa !13, !dbg !9
+  store i32 4, i32* %r, !tbaa !13, !dbg !10
+  %load = load i32, i32* %p, !tbaa !13, !dbg !11
+  %add = add i32 %load1, %load
+  ret i32 %add
+}
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "/tmp/s.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"PIC Level", i32 2}
+!6 = !{!"clang version 4.0.0 (trunk 282540) (llvm/trunk 282542)"}
+!7 = distinct !DISubprogram(name: "may_alias", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 1, column: 13, scope: !7)
+!10 = !DILocation(line: 2, column: 10, scope: !7)
+!11 = !DILocation(line: 3, column: 3, scope: !7)
+
+!12 = !{ !"tbaa root" }
+!13 = !{ !"int", !12 }

Added: llvm/trunk/test/Transforms/GVN/phi-translate-partial-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/phi-translate-partial-alias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/phi-translate-partial-alias.ll (added)
+++ llvm/trunk/test/Transforms/GVN/phi-translate-partial-alias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt -basicaa -gvn -S < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
+
+; GVN shouldn't PRE the load around the loop backedge because it's
+; not actually redundant around the loop backedge, despite appearances
+; if phi-translation is ignored.
+
+; CHECK: define void @test0(i8* %begin)
+; CHECK: loop:
+; CHECK:   %l0 = load i8, i8* %phi
+; CHECK:   call void @bar(i8 %l0)
+; CHECK:   %l1 = load i8, i8* %phi
+define void @test0(i8* %begin) {
+entry:
+  br label %loop
+
+loop:
+  %phi = phi i8* [ %begin, %entry ], [ %next, %loop ]
+  %l0 = load i8, i8* %phi
+  call void @bar(i8 %l0)
+  %l1 = load i8, i8* %phi
+  %next = getelementptr inbounds i8, i8* %phi, i8 %l1
+  br label %loop
+}
+
+declare void @bar(i8)

Added: llvm/trunk/test/Transforms/GVN/pr10820.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pr10820.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/pr10820.ll (added)
+++ llvm/trunk/test/Transforms/GVN/pr10820.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+target datalayout =
+"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at g = external global i31
+
+define void @main() nounwind uwtable {
+entry:
+; CHECK: store i32
+  store i32 402662078, i32* bitcast (i31* @g to i32*), align 8
+; CHECK-NOT: load i31
+  %0 = load i31, i31* @g, align 8
+; CHECK: store i31
+  store i31 %0, i31* undef, align 1
+  unreachable
+}

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

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

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

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

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

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

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

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

Added: llvm/trunk/test/Transforms/GVN/pr28879.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pr28879.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/pr28879.ll (added)
+++ llvm/trunk/test/Transforms/GVN/pr28879.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt -gvn <%s -S -o - | FileCheck %s
+
+define void @f() {
+entry:
+  %a = alloca <7 x i1>, align 2
+  store <7 x i1> undef, <7 x i1>* %a, align 2
+; CHECK: store <7 x i1> undef, <7 x i1>*
+  %0 = getelementptr inbounds <7 x i1>, <7 x i1>* %a, i64 0, i64 0
+  %val = load i1, i1* %0, align 2
+; CHECK: load i1, i1* 
+  br i1 %val, label %cond.true, label %cond.false
+
+cond.true:
+  ret void
+
+cond.false:
+  ret void
+}
+
+define <7 x i1> @g(<7 x i1>* %a) {
+entry:
+  %vec = load <7 x i1>, <7 x i1>* %a
+; CHECK: load <7 x i1>, <7 x i1>*
+  %0 = getelementptr inbounds <7 x i1>, <7 x i1>* %a, i64 0, i64 0
+  %val = load i1, i1* %0, align 2
+; CHECK: load i1, i1*
+  br i1 %val, label %cond.true, label %cond.false
+
+cond.true:
+  ret <7 x i1> %vec
+
+cond.false:
+  ret <7 x i1> <i1 false, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false>
+}

Added: llvm/trunk/test/Transforms/GVN/pr32314.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pr32314.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/pr32314.ll (added)
+++ llvm/trunk/test/Transforms/GVN/pr32314.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -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"
+
+; The load in the loop can not bypass the data from the previous loop. The store above it in the loop aliases.
+define void @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A:%.*]] = alloca [3 x i32], align 4
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    ret void
+; CHECK:       for.body:
+; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[P_017:%.*]] = phi i32* [ undef, [[ENTRY]] ], [ [[ARRAYIDX3:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[A]], i64 0, i64 [[TMP0]]
+; CHECK-NEXT:    store i32 50, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[P_017]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT:    [[ARRAYIDX3]] = getelementptr inbounds [3 x i32], [3 x i32]* [[A]], i64 0, i64 [[INDVARS_IV]]
+; CHECK-NEXT:    store i32 60, i32* [[ARRAYIDX3]], align 4
+; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 3
+; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
+;
+entry:
+  %a = alloca [3 x i32], align 4
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.body
+  ret void
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv = phi i64 [ 1, %entry ], [ %indvars.iv.next, %for.body ]
+  %p.017 = phi i32* [ undef, %entry ], [ %arrayidx3, %for.body ]
+  %0 = add nsw i64 %indvars.iv, -1
+  %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %0
+  store i32 50, i32* %arrayidx, align 4
+  %1 = shl i64 %indvars.iv, 1
+  %2 = load i32, i32* %p.017, align 4
+  %3 = trunc i64 %1 to i32
+  %add1 = add nsw i32 %2, %3
+  %arrayidx3 = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %indvars.iv
+  store i32 60, i32* %arrayidx3, align 4
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %exitcond = icmp ne i64 %indvars.iv.next, 3
+  br i1 %exitcond, label %for.body, label %for.cond.cleanup
+}

Added: llvm/trunk/test/Transforms/GVN/pr34908.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pr34908.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/pr34908.ll (added)
+++ llvm/trunk/test/Transforms/GVN/pr34908.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+define i1 @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:    call void @llvm.assume(i1 undef)
+; CHECK-NEXT:    ret i1 undef
+;
+  call void @llvm.assume(i1 undef)
+  ret i1 undef
+}
+
+declare void @llvm.assume(i1)

Added: llvm/trunk/test/Transforms/GVN/pr36063.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pr36063.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/pr36063.ll (added)
+++ llvm/trunk/test/Transforms/GVN/pr36063.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt < %s -memcpyopt -mldst-motion -gvn -S | FileCheck %s
+
+define void @foo(i8* %ret, i1 %x) {
+  %a = alloca i8
+  br i1 %x, label %yes, label %no
+
+yes:                                              ; preds = %0
+  %gepa = getelementptr i8, i8* %a, i64 0
+  store i8 5, i8* %gepa
+  br label %out
+
+no:                                               ; preds = %0
+  %gepb = getelementptr i8, i8* %a, i64 0
+  store i8 5, i8* %gepb
+  br label %out
+
+out:                                              ; preds = %no, %yes
+  %tmp = load i8, i8* %a
+; CHECK-NOT: undef
+  store i8 %tmp, i8* %ret
+  ret void
+}

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

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

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

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

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

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

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

Added: llvm/trunk/test/Transforms/GVN/rle-nonlocal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/rle-nonlocal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/rle-nonlocal.ll (added)
+++ llvm/trunk/test/Transforms/GVN/rle-nonlocal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,25 @@
+; RUN: opt < %s -basicaa -gvn -S | FileCheck %s
+
+define i32 @main(i32** %p, i32 %x, i32 %y) {
+block1:
+    %cmp = icmp eq i32 %x, %y
+	br i1 %cmp , label %block2, label %block3
+
+block2:
+ %a = load i32*, i32** %p
+ br label %block4
+
+block3:
+  %b = load i32*, i32** %p
+  br label %block4
+
+block4:
+; CHECK-NOT: %existingPHI = phi
+; CHECK: %DEAD = phi
+  %existingPHI = phi i32* [ %a, %block2 ], [ %b, %block3 ] 
+  %DEAD = load i32*, i32** %p
+  %c = load i32, i32* %DEAD
+  %d = load i32, i32* %existingPHI
+  %e = add i32 %c, %d
+  ret i32 %e
+}

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

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

Added: llvm/trunk/test/Transforms/GVN/unreachable-predecessor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/unreachable-predecessor.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/unreachable-predecessor.ll (added)
+++ llvm/trunk/test/Transforms/GVN/unreachable-predecessor.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt < %s -gvn -S | FileCheck %s
+
+; loop.then is not reachable from loop, so we should be able to deduce that the
+; store through %phi2 cannot alias %ptr1.
+
+; CHECK-LABEL: @test1
+define void @test1(i32* %ptr1, i32* %ptr2) {
+; CHECK-LABEL: entry:
+; CHECK: %[[GEP:.*]] = getelementptr inbounds i32, i32* %ptr1, i64 1
+; CHECK: %[[VAL1:.*]] = load i32, i32* %[[GEP]]
+entry:
+  br label %loop.preheader
+
+loop.preheader:
+  %gep1 = getelementptr inbounds i32, i32* %ptr1, i64 1
+  br label %loop
+
+; CHECK-LABEL: loop:
+; CHECK-NOT: load
+loop:
+  %phi1 = phi i32* [ %gep1, %loop.preheader ], [ %phi2, %loop.then ]
+  %val1 = load i32, i32* %phi1
+  br i1 false, label %loop.then, label %loop.if
+
+loop.if:
+  %gep2 = getelementptr inbounds i32, i32* %gep1, i64 1
+  %val2 = load i32, i32* %gep2
+  %cmp = icmp slt i32 %val1, %val2
+  br label %loop.then
+
+; CHECK-LABEL: loop.then
+; CHECK: store i32 %[[VAL1]], i32* %phi2
+loop.then:
+  %phi2 = phi i32* [ %ptr2, %loop ], [ %gep2, %loop.if ]
+  store i32 %val1, i32* %phi2
+  store i32 0, i32* %ptr1
+  br label %loop
+}

Added: llvm/trunk/test/Transforms/GVN/unreachable_block_infinite_loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/unreachable_block_infinite_loop.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVN/unreachable_block_infinite_loop.ll (added)
+++ llvm/trunk/test/Transforms/GVN/unreachable_block_infinite_loop.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,43 @@
+; RUN: opt -memdep -gvn -disable-output < %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-apple-darwin10.0"
+
+define i32 @test2() nounwind ssp {
+entry:
+    ret i32 0
+
+unreachable_block:
+    %a = add i32 %a, 1
+    ret i32 %a
+}
+
+define i32 @pr23096_test0() {
+entry:
+  br label %bb0
+
+bb1:
+  %ptr1 = ptrtoint i32* %ptr2 to i64
+  %ptr2 = inttoptr i64 %ptr1 to i32*
+  br i1 undef, label %bb0, label %bb1
+
+bb0:
+  %phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ]
+  %load = load i32, i32* %phi
+  ret i32 %load
+}
+
+define i32 @pr23096_test1() {
+entry:
+  br label %bb0
+
+bb1:
+  %ptr1 = getelementptr i32, i32* %ptr2, i32 0
+  %ptr2 = getelementptr i32, i32* %ptr1, i32 0
+  br i1 undef, label %bb0, label %bb1
+
+bb0:
+  %phi = phi i32* [ undef, %entry ], [ %ptr2, %bb1 ]
+  %load = load i32, i32* %phi
+  ret i32 %load
+}

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

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-call.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Check that the call and fcmp are hoisted.
+; CHECK-LABEL: define void @fun(
+; CHECK: call float
+; CHECK: fcmp oeq
+; CHECK-NOT: call float
+; CHECK-NOT: fcmp oeq
+
+define void @fun(float %__b) minsize {
+entry:
+  br label %if.then
+
+if.then:                                          ; preds = %entry
+  br i1 undef, label %if.then8, label %lor.lhs.false
+
+lor.lhs.false:                                    ; preds = %if.then
+  %0 = call float @llvm.fabs.f32(float %__b) #2
+  %cmpinf7 = fcmp oeq float %0, 0x7FF0000000000000
+  unreachable
+
+if.then8:                                         ; preds = %if.then
+  %1 = call float @llvm.fabs.f32(float %__b) #2
+  %cmpinf10 = fcmp oeq float %1, 0x7FF0000000000000
+  ret void
+}
+
+declare float @llvm.fabs.f32(float)

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-convergent.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-convergent.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-convergent.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-convergent.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,93 @@
+; RUN: opt -gvn-hoist -S < %s | FileCheck %s
+
+; Check that convergent calls are not hoisted.
+;
+; CHECK-LABEL: @no_convergent_func_hoisting(
+; CHECK: if.then:
+; CHECK: call float @convergent_func(
+
+; CHECK: if.else:
+; CHECK: call float @convergent_func(
+define float @no_convergent_func_hoisting(float %d, float %min, float %max, float %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %sub1 = fsub float %max, %a
+  %mul2 = call float @convergent_func(float %sub1, float %div)
+  br label %if.end
+
+if.else:
+  %sub5 = fsub float %max, %a
+  %mul6 = call float @convergent_func(float %sub5, float %div)
+  br label %if.end
+
+if.end:
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %add = fadd float %tmax.0, 10.0
+  ret float %add
+}
+
+; The call site is convergent but the declaration is not.
+; CHECK-LABEL: @no_convergent_call_hoisting(
+
+; CHECK: if.then:
+; CHECK: call float @func(
+
+; CHECK: if.else:
+; CHECK: call float @func(
+define float @no_convergent_call_hoisting(float %d, float %min, float %max, float %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %sub1 = fsub float %max, %a
+  %mul2 = call float @func(float %sub1, float %div) #0
+  br label %if.end
+
+if.else:
+  %sub5 = fsub float %max, %a
+  %mul6 = call float @func(float %sub5, float %div) #0
+  br label %if.end
+
+if.end:
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %add = fadd float %tmax.0, 10.0
+  ret float %add
+}
+
+; The call site is convergent but the declaration is not.
+; CHECK-LABEL: @call_hoisting(
+; CHECK: call float @func(
+; CHECK-NOT: call float @func(
+define float @call_hoisting(float %d, float %min, float %max, float %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %sub1 = fsub float %max, %a
+  %mul2 = call float @func(float %sub1, float %div)
+  br label %if.end
+
+if.else:
+  %sub5 = fsub float %max, %a
+  %mul6 = call float @func(float %sub5, float %div)
+  br label %if.end
+
+if.end:
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %add = fadd float %tmax.0, 10.0
+  ret float %add
+}
+
+declare float @convergent_func(float, float) #0
+declare float @func(float, float) #1
+
+attributes #0 = { nounwind readnone convergent }
+attributes #1 = { nounwind readnone }

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-inline.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-inline.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-inline.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,38 @@
+; RUN: opt -S -O2 -enable-gvn-hoist < %s | FileCheck %s
+
+; Check that the inlined loads are hoisted.
+; CHECK-LABEL: define i32 @fun(
+; CHECK-LABEL: entry:
+; CHECK: load i32, i32* @A
+; CHECK: if.then:
+
+ at A = external global i32
+ at B = external global i32
+ at C = external global i32
+
+define i32 @loadA() {
+   %a = load i32, i32* @A
+   ret i32 %a
+}
+
+define i32 @fun(i1 %c) {
+entry:
+  br i1 %c, label %if.then, label %if.else
+
+if.then:
+  store i32 1, i32* @B
+  %call1 = call i32 @loadA()
+  store i32 2, i32* @C
+  br label %if.endif
+
+if.else:
+  store i32 2, i32* @C
+  %call2 = call i32 @loadA()
+  store i32 1, i32* @B
+  br label %if.endif
+
+if.endif:
+  %ret = phi i32 [ %call1, %if.then ], [ %call2, %if.else ]
+  ret i32 %ret
+}
+

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-md.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-md.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-md.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,121 @@
+; RUN: opt -S -gvn-hoist < %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(i1 %b, i32* %x) {
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  store i32 2, i32* %x, align 4, !tbaa !1
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  store i32 2, i32* %x, align 4, !tbaa !5
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+; CHECK-LABEL: define void @test1(
+; CHECK: store i32 2, i32* %x, align 4
+; CHECK-NEXT: br i1 %b
+
+define void @test2(i1 %b, i32* %x) {
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %gep1 = getelementptr inbounds i32, i32* %x, i64 1
+  store i32 2, i32* %gep1, align 4, !tbaa !1
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %gep2 = getelementptr inbounds i32, i32* %x, i64 1
+  store i32 2, i32* %gep2, align 4, !tbaa !5
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+; CHECK-LABEL: define void @test2(
+; CHECK: %[[gep:.*]] = getelementptr inbounds i32, i32* %x, i64 1
+; CHECK: store i32 2, i32* %[[gep]], align 4
+; CHECK-NEXT: br i1 %b
+
+define void @test3(i1 %b, i32* %x) {
+entry:
+  br i1 %b, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %gep1 = getelementptr inbounds i32, i32* %x, i64 1
+  store i32 2, i32* %gep1, align 4, !tbaa !1
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %gep2 = getelementptr i32, i32* %x, i64 1
+  store i32 2, i32* %gep2, align 4, !tbaa !5
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+; CHECK-LABEL: define void @test3(
+; CHECK: %[[gep:.*]] = getelementptr i32, i32* %x, i64 1
+; CHECK: store i32 2, i32* %[[gep]], align 4
+; CHECK-NEXT: br i1 %b
+
+!1 = !{!2, !2, i64 0}
+!2 = !{!"int", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C++ TBAA"}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"_ZTS1e", !3, i64 0}
+
+define i32 @test4(i1 %b, i32* %y) {
+entry:
+  br i1 %b, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %0 = load i32, i32* %y, align 4, !range !7
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %1 = load i32, i32* %y, align 4, !range !8
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ %0, %if.then ], [ %1, %if.end ]
+  ret i32 %retval.0
+}
+; CHECK-LABEL: define i32 @test4(
+; CHECK: %[[load:.*]] = load i32, i32* %y, align 4, !range ![[range_md:.*]]
+; CHECK: %[[phi:.*]] = phi i32 [ %[[load]], %{{.*}} ], [ %[[load]], %{{.*}} ]
+; CHECK: ret i32 %[[phi]]
+
+define i32* @test5(i1 %b, i32** %y) {
+entry:
+  br i1 %b, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %0 = load i32*, i32** %y, align 4, !nonnull !9
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %1 = load i32*, i32** %y, align 4
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32* [ %0, %if.then ], [ %1, %if.end ]
+  ret i32* %retval.0
+}
+; CHECK-LABEL: define i32* @test5(
+; CHECK: %[[load:.*]] = load i32*, i32** %y, align 4
+; CHECK-NOT: !nonnull
+; CHECK: %[[phi:.*]] = phi i32* [ %[[load]], %{{.*}} ], [ %[[load]], %{{.*}} ]
+; CHECK: ret i32* %[[phi]]
+
+!7 = !{i32 0, i32 2}
+!8 = !{i32 3, i32 4}
+!9 = !{}
+; CHECK: ![[range_md]] = !{i32 0, i32 2, i32 3, i32 4}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-more-than-two-branches.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-more-than-two-branches.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-more-than-two-branches.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-more-than-two-branches.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -gvn-hoist -S < %s | FileCheck %s
+
+; CHECK: store
+; CHECK-NOT: store
+
+; Check that an instruction can be hoisted to a basic block
+; with more than two successors.
+
+ at G = external global i32, align 4
+
+define void @foo(i32 %c1) {
+entry:
+  switch i32 %c1, label %exit1 [
+    i32 0, label %sw0
+    i32 1, label %sw1
+  ]
+
+sw0:
+  store i32 1, i32* @G
+  br label %exit
+
+sw1:
+  store i32 1, i32* @G
+  br label %exit
+
+exit1:
+  store i32 1, i32* @G
+  ret void
+exit:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-mssa.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-mssa.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-mssa.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-mssa.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,69 @@
+; RUN: opt -S -gvn-hoist -newgvn < %s | FileCheck %s
+
+; Check that store hoisting works: there should be only one store left.
+; CHECK-LABEL: @getopt
+; CHECK: store i32
+; CHECK-NOT: store i32
+
+ at optind = external global i32, align 4
+
+define void @getopt() {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb
+  br i1 undef, label %bb2, label %bb3
+
+bb2:                                              ; preds = %bb1
+  br label %bb13
+
+bb3:                                              ; preds = %bb1
+  br i1 undef, label %bb4, label %bb9
+
+bb4:                                              ; preds = %bb3
+  %tmp = load i32, i32* @optind, align 4
+  br i1 undef, label %bb5, label %bb7
+
+bb5:                                              ; preds = %bb4
+  %tmp6 = add nsw i32 %tmp, 1
+  store i32 %tmp6, i32* @optind, align 4
+  br label %bb12
+
+bb7:                                              ; preds = %bb4
+  %tmp8 = add nsw i32 %tmp, 1
+  store i32 %tmp8, i32* @optind, align 4
+  br label %bb13
+
+bb9:                                              ; preds = %bb3
+  %tmp10 = load i32, i32* @optind, align 4
+  %tmp11 = add nsw i32 %tmp10, 1
+  store i32 %tmp11, i32* @optind, align 4
+  br label %bb12
+
+bb12:                                             ; preds = %bb9, %bb5
+  br label %bb13
+
+bb13:                                             ; preds = %bb12, %bb7, %bb2
+  ret void
+}
+
+ at GlobalVar = internal global float 1.000000e+00
+
+; Check that we hoist stores and remove the MSSA phi node.
+; CHECK-LABEL: @hoistStoresUpdateMSSA
+; CHECK: store float
+; CHECK-NOT: store float
+define float @hoistStoresUpdateMSSA(float %d) {
+entry:
+  store float 0.000000e+00, float* @GlobalVar
+  %cmp = fcmp oge float %d, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  store float 0.000000e+00, float* @GlobalVar
+  br label %if.end
+
+if.end:
+  %tmp = load float, float* @GlobalVar, align 4
+  ret float %tmp
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-newgvn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-newgvn.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-newgvn.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-newgvn.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,105 @@
+; RUN: opt -gvn-hoist -newgvn -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"
+
+ at GlobalVar = internal global float 1.000000e+00
+
+; Check that we hoist load and scalar expressions in dominator.
+; CHECK-LABEL: @dominatorHoisting
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: load
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @dominatorHoisting(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                          ; preds = %entry
+  %p1 = phi float [ %mul4, %if.then ], [ 0.000000e+00, %entry ]
+  %p2 = phi float [ %mul6, %if.then ], [ 0.000000e+00, %entry ]
+
+  %x = fadd float %p1, %mul2
+  %y = fadd float %p2, %mul
+  %z = fadd float %x, %y
+  ret float %z
+}
+
+; Check that we hoist load and scalar expressions in dominator.
+; CHECK-LABEL: @domHoisting
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: load
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @domHoisting(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.else:
+  %6 = load float, float* %max, align 4
+  %7 = load float, float* %a, align 4
+  %sub9 = fsub float %6, %7
+  %mul10 = fmul float %sub9, %div
+  %8 = load float, float* %min, align 4
+  %sub12 = fsub float %8, %7
+  %mul13 = fmul float %sub12, %div
+  br label %if.end
+
+if.end:
+  %p1 = phi float [ %mul4, %if.then ], [ %mul10, %if.else ]
+  %p2 = phi float [ %mul6, %if.then ], [ %mul13, %if.else ]
+
+  %x = fadd float %p1, %mul2
+  %y = fadd float %p2, %mul
+  %z = fadd float %x, %y
+  ret float %z
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-pr20242.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-pr20242.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-pr20242.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-pr20242.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,77 @@
+; RUN: opt -gvn-hoist -newgvn -gvn-hoist  -S < %s | FileCheck %s
+; Test to demonstrate that newgvn creates opportunities for
+; more gvn-hoist when sibling branches contain identical expressions.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Check that all "or" expressions are hoisted.
+; CHECK-LABEL: @encode
+; CHECK: or i32
+; CHECK-NOT: or i32
+
+define i8* @encode(i8* %p, i32 %v) {
+entry:
+  %p.addr = alloca i8*, align 8
+  %v.addr = alloca i32, align 4
+  store i8* %p, i8** %p.addr, align 8
+  store i32 %v, i32* %v.addr, align 4
+  %0 = load i32, i32* %v.addr, align 4
+  %cmp = icmp ult i32 %0, 23
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %1 = load i32, i32* %v.addr, align 4
+  %or = or i32 %1, 128
+  %conv = trunc i32 %or to i8
+  %2 = load i8*, i8** %p.addr, align 8
+  %incdec.ptr = getelementptr inbounds i8, i8* %2, i32 1
+  store i8* %incdec.ptr, i8** %p.addr, align 8
+  store i8 %conv, i8* %2, align 1
+  br label %if.end15
+
+if.else:                                          ; preds = %entry
+  %3 = load i32, i32* %v.addr, align 4
+  %cmp1 = icmp ult i32 %3, 42
+  br i1 %cmp1, label %if.then3, label %if.else9
+
+if.then3:                                         ; preds = %if.else
+  %4 = load i32, i32* %v.addr, align 4
+  %or4 = or i32 %4, 128
+  %conv5 = trunc i32 %or4 to i8
+  %5 = load i8*, i8** %p.addr, align 8
+  %incdec.ptr6 = getelementptr inbounds i8, i8* %5, i32 1
+  store i8* %incdec.ptr6, i8** %p.addr, align 8
+  store i8 %conv5, i8* %5, align 1
+  %6 = load i32, i32* %v.addr, align 4
+  %conv7 = trunc i32 %6 to i8
+  %7 = load i8*, i8** %p.addr, align 8
+  %incdec.ptr8 = getelementptr inbounds i8, i8* %7, i32 1
+  store i8* %incdec.ptr8, i8** %p.addr, align 8
+  store i8 %conv7, i8* %7, align 1
+  br label %if.end
+
+if.else9:                                         ; preds = %if.else
+  %8 = load i32, i32* %v.addr, align 4
+  %or10 = or i32 %8, 128
+  %conv11 = trunc i32 %or10 to i8
+  %9 = load i8*, i8** %p.addr, align 8
+  %incdec.ptr12 = getelementptr inbounds i8, i8* %9, i32 1
+  store i8* %incdec.ptr12, i8** %p.addr, align 8
+  store i8 %conv11, i8* %9, align 1
+  %10 = load i32, i32* %v.addr, align 4
+  %shr = lshr i32 %10, 7
+  %conv13 = trunc i32 %shr to i8
+  %11 = load i8*, i8** %p.addr, align 8
+  %incdec.ptr14 = getelementptr inbounds i8, i8* %11, i32 1
+  store i8* %incdec.ptr14, i8** %p.addr, align 8
+  store i8 %conv13, i8* %11, align 1
+  br label %if.end
+
+if.end:                                           ; preds = %if.else9, %if.then3
+  br label %if.end15
+
+if.end15:                                         ; preds = %if.end, %if.then
+  %12 = load i8*, i8** %p.addr, align 8
+  ret i8* %12
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-pr22005.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-pr22005.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-pr22005.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-pr22005.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -gvn-hoist -S < %s | FileCheck %s
+target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Check that all "sub" expressions are hoisted.
+; CHECK-LABEL: @fun
+; CHECK: sub i64
+; CHECK-NOT: sub i64
+
+define i64 @fun(i8* %out, i8* %end) {
+  %1 = icmp ult i8* %out, %end
+  br i1 %1, label %2, label %6
+
+; <label>:2                                       ; preds = %0
+  %3 = ptrtoint i8* %end to i64
+  %4 = ptrtoint i8* %out to i64
+  %5 = sub i64 %3, %4
+  br label %10
+
+; <label>:6                                       ; preds = %0
+  %7 = ptrtoint i8* %out to i64
+  %8 = ptrtoint i8* %end to i64
+  %9 = sub i64 %8, %7
+  br label %10
+
+; <label>:10                                      ; preds = %6, %2
+  %.in = phi i64 [ %5, %2 ], [ %9, %6 ]
+  %11 = add i64 %.in, 257
+  ret i64 %11
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-pr28606.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-pr28606.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-pr28606.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-pr28606.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt -gvn-hoist -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-msvc18.0.0"
+
+%struct.S = type { i8* }
+
+declare void @f(<{ %struct.S }>* inalloca)
+
+
+; Check that we don't clone the %x alloca and insert it in the live range of
+; %argmem, which would break the inalloca contract.
+;
+; CHECK-LABEL: @test
+; CHECK: alloca i8
+; CHECK: stacksave
+; CHECK: alloca inalloca
+; CHECK-NOT: alloca i8
+
+; Check that store instructions are hoisted.
+; CHECK: store i8
+; CHECK-NOT: store i8
+; CHECK: stackrestore
+
+define void @test(i1 %b) {
+entry:
+  %x = alloca i8
+  %inalloca.save = call i8* @llvm.stacksave()
+  %argmem = alloca inalloca <{ %struct.S }>, align 4
+  %0 = getelementptr inbounds <{ %struct.S }>, <{ %struct.S }>* %argmem, i32 0, i32 0
+  br i1 %b, label %true, label %false
+
+true:
+  %p = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0
+  store i8* %x, i8** %p, align 4
+  br label %exit
+
+false:
+  %p2 = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0
+  store i8* %x, i8** %p2, align 4
+  br label %exit
+
+exit:
+  call void @f(<{ %struct.S }>* inalloca %argmem)
+  call void @llvm.stackrestore(i8* %inalloca.save)
+  ret void
+}
+
+declare i8* @llvm.stacksave()
+declare void @llvm.stackrestore(i8*)

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-pr28933.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-pr28933.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-pr28933.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-pr28933.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -S -gvn-hoist -verify-memoryssa -newgvn < %s | FileCheck %s
+
+; Check that we end up with one load and one store, in the right order
+; CHECK-LABEL:  define void @test_it(
+; CHECK: store
+; CHECK-NOT: store
+; CHECK-NOT: load
+        
+%rec894.0.1.2.3.12 = type { i16 }
+
+ at a = external global %rec894.0.1.2.3.12
+
+define void @test_it() {
+bb2:
+  store i16 undef, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  %_tmp61 = load i16, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  store i16 undef, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  %_tmp92 = load i16, i16* getelementptr inbounds (%rec894.0.1.2.3.12, %rec894.0.1.2.3.12* @a, i16 0, i32 0), align 1
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-pr31891.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-pr31891.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-pr31891.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-pr31891.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,83 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Hoisted inlinable calls need to have accurate scope information, but we're
+; allowed to erase the line information.
+
+source_filename = "t.c"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+; Function Attrs: noinline nounwind readnone uwtable
+define float @fabsf(float %f) #0 !dbg !7 {
+entry:
+  %conv = fpext float %f to double, !dbg !9
+  %call = call double @fabs(double %conv) #1, !dbg !10
+  %conv1 = fptrunc double %call to float, !dbg !11
+  ret float %conv1, !dbg !12
+}
+
+; Function Attrs: nounwind readnone
+declare double @fabs(double) #1
+
+; Function Attrs: noinline nounwind uwtable
+define void @hoistit(i32 %cond, float %f) #2 !dbg !13 {
+entry:
+  %tobool = icmp ne i32 %cond, 0, !dbg !14
+  br i1 %tobool, label %if.then, label %if.else, !dbg !14
+
+if.then:                                          ; preds = %entry
+  %call = call float @fabsf(float %f) #1, !dbg !15
+  call void @useit1(float %call), !dbg !16
+  br label %if.end, !dbg !18
+
+if.else:                                          ; preds = %entry
+  %call1 = call float @fabsf(float %f) #1, !dbg !19
+  call void @useit2(float %call1), !dbg !20
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void, !dbg !21
+}
+
+; CHECK-LABEL: define void @hoistit
+; CHECK-SAME: 		!dbg ![[sp_hoistit:[0-9]+]]
+; CHECK: call float @fabsf(float %f) {{.*}} !dbg ![[dbgloc:[0-9]+]]
+; CHECK: br i1 %tobool, label %if.then, label %if.else
+
+; CHECK: ![[sp_hoistit]] = distinct !DISubprogram(name: "hoistit", {{.*}})
+; CHECK: ![[dbgloc]] = !DILocation({{.*}}, scope: ![[sp_hoistit]])
+
+declare void @useit1(float)
+
+declare void @useit2(float)
+
+attributes #0 = { noinline nounwind readnone uwtable }
+attributes #1 = { nounwind readnone }
+attributes #2 = { noinline nounwind uwtable }
+
+!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 5.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2)
+!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm\5Cbuild")
+!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 "}
+!7 = distinct !DISubprogram(name: "fabsf", scope: !1, file: !1, line: 4, type: !8, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 5, column: 22, scope: !7)
+!10 = !DILocation(line: 5, column: 17, scope: !7)
+!11 = !DILocation(line: 5, column: 10, scope: !7)
+!12 = !DILocation(line: 5, column: 3, scope: !7)
+!13 = distinct !DISubprogram(name: "hoistit", scope: !1, file: !1, line: 7, type: !8, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!14 = !DILocation(line: 8, column: 7, scope: !13)
+!15 = !DILocation(line: 9, column: 12, scope: !13)
+!16 = !DILocation(line: 9, column: 5, scope: !17)
+!17 = !DILexicalBlockFile(scope: !13, file: !1, discriminator: 1)
+!18 = !DILocation(line: 10, column: 3, scope: !13)
+!19 = !DILocation(line: 11, column: 12, scope: !13)
+!20 = !DILocation(line: 11, column: 5, scope: !17)
+!21 = !DILocation(line: 13, column: 1, scope: !13)

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-recursive-geps.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-recursive-geps.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-recursive-geps.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-recursive-geps.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,106 @@
+; RUN: opt -gvn-hoist -newgvn -gvn-hoist -S < %s | FileCheck %s
+
+; Check that recursive GEPs are hoisted. Since hoisting creates
+; fully redundant instructions, newgvn is run to remove them which then
+; creates more opportunites for hoisting.
+
+; CHECK-LABEL: @fun
+; CHECK: load
+; CHECK: fdiv
+; CHECK: load
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: fsub
+; CHECK-NOT: fmul
+
+%0 = type { double, double, double }
+%1 = type { double, double, double }
+%2 = type { %3, %1, %1 }
+%3 = type { i32 (...)**, %4, %10*, %11, %11, %11, %11, %11, %11, %11, %11, %11 }
+%4 = type { %5 }
+%5 = type { %6 }
+%6 = type { %7 }
+%7 = type { %8 }
+%8 = type { %9 }
+%9 = type { i64, i64, i8* }
+%10 = type <{ i32 (...)**, i32, [4 x i8] }>
+%11 = type { [4 x [4 x double]] }
+%12 = type <{ %1, %0, i32, [4 x i8] }>
+%13 = type { %1, %0, %12, %3*, %14* }
+%14 = type opaque
+
+ at d = external global %0, align 8
+ at p = external global %1, align 8
+
+define zeroext i1 @fun(%2*, %12* dereferenceable(56), double*, %13*) {
+  %5 = alloca %2*, align 8
+  %6 = alloca %12*, align 8
+  %7 = alloca double*, align 8
+  %8 = alloca %13*, align 8
+  %9 = alloca double, align 8
+  %10 = alloca double, align 8
+  %11 = alloca double, align 8
+  %12 = alloca double, align 8
+  %13 = alloca double, align 8
+  %14 = alloca double, align 8
+  %15 = alloca double, align 8
+  store %2* %0, %2** %5, align 8
+  store %12* %1, %12** %6, align 8
+  store double* %2, double** %7, align 8
+  store %13* %3, %13** %8, align 8
+  %16 = load %2*, %2** %5, align 8
+  %17 = load double, double* getelementptr inbounds (%0, %0* @d, i32 0, i32 0), align 8
+  %18 = fdiv double 1.000000e+00, %17
+  store double %18, double* %15, align 8
+  %19 = load double, double* %15, align 8
+  %20 = fcmp oge double %19, 0.000000e+00
+  br i1 %20, label %21, label %36
+
+; <label>:21:                                     ; preds = %4
+  %22 = getelementptr inbounds %2, %2* %16, i32 0, i32 1
+  %23 = getelementptr inbounds %1, %1* %22, i32 0, i32 0
+  %24 = load double, double* %23, align 8
+  %25 = load double, double* getelementptr inbounds (%1, %1* @p, i32 0, i32 0), align 8
+  %26 = fsub double %24, %25
+  %27 = load double, double* %15, align 8
+  %28 = fmul double %26, %27
+  store double %28, double* %9, align 8
+  %29 = getelementptr inbounds %2, %2* %16, i32 0, i32 2
+  %30 = getelementptr inbounds %1, %1* %29, i32 0, i32 0
+  %31 = load double, double* %30, align 8
+  %32 = load double, double* getelementptr inbounds (%1, %1* @p, i32 0, i32 0), align 8
+  %33 = fsub double %31, %32
+  %34 = load double, double* %15, align 8
+  %35 = fmul double %33, %34
+  store double %35, double* %12, align 8
+  br label %51
+
+; <label>:36:                                     ; preds = %4
+  %37 = getelementptr inbounds %2, %2* %16, i32 0, i32 2
+  %38 = getelementptr inbounds %1, %1* %37, i32 0, i32 0
+  %39 = load double, double* %38, align 8
+  %40 = load double, double* getelementptr inbounds (%1, %1* @p, i32 0, i32 0), align 8
+  %41 = fsub double %39, %40
+  %42 = load double, double* %15, align 8
+  %43 = fmul double %41, %42
+  store double %43, double* %9, align 8
+  %44 = getelementptr inbounds %2, %2* %16, i32 0, i32 1
+  %45 = getelementptr inbounds %1, %1* %44, i32 0, i32 0
+  %46 = load double, double* %45, align 8
+  %47 = load double, double* getelementptr inbounds (%1, %1* @p, i32 0, i32 0), align 8
+  %48 = fsub double %46, %47
+  %49 = load double, double* %15, align 8
+  %50 = fmul double %48, %49
+  store double %50, double* %12, align 8
+  br label %51
+
+; <label>:51:                                     ; preds = %36, %21
+  %52 = load double, double* %12, align 8
+  %53 = load double, double* %9, align 8
+  %54 = fcmp olt double %52, %53
+  ret i1 %54
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-simplify-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-simplify-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-simplify-phi.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-simplify-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,54 @@
+; RUN: opt < %s -gvn-hoist -S | FileCheck %s
+
+; This test is meant to make sure that MemorySSAUpdater works correctly
+; in non-trivial cases.
+
+; CHECK: if.else218:
+; CHECK-NEXT: %0 = getelementptr inbounds %s, %s* undef, i32 0, i32 0
+; CHECK-NEXT: %1 = load i32, i32* %0, align 4
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+%s = type { i32, %s**, [3 x i8], i8 }
+
+define void @test() {
+entry:
+  br label %cond.end118
+
+cond.end118:                                      ; preds = %entry
+  br i1 undef, label %cleanup, label %if.end155
+
+if.end155:                                        ; preds = %cond.end118
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %if.end155
+  br i1 undef, label %while.end, label %while.body
+
+while.body:                                       ; preds = %while.cond
+  br label %while.cond
+
+while.end:                                        ; preds = %while.cond
+  switch i32 undef, label %if.else218 [
+    i32 1, label %cleanup
+    i32 0, label %if.then174
+  ]
+
+if.then174:                                       ; preds = %while.end
+  unreachable
+
+if.else218:                                       ; preds = %while.end
+  br i1 undef, label %if.then226, label %if.else326
+
+if.then226:                                       ; preds = %if.else218
+  %size227 = getelementptr inbounds %s, %s* undef, i32 0, i32 0
+  %0 = load i32, i32* %size227, align 4
+  unreachable
+
+if.else326:                                       ; preds = %if.else218
+  %size330 = getelementptr inbounds %s, %s* undef, i32 0, i32 0
+  %1 = load i32, i32* %size330, align 4
+  unreachable
+
+cleanup:                                          ; preds = %while.end, %cond.end118
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-unsafe-pr31729.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-unsafe-pr31729.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-unsafe-pr31729.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-unsafe-pr31729.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,81 @@
+; RUN: opt -gvn-hoist -S < %s | FileCheck %s
+
+; Check that urem is not hoisted.
+; CHECK-LABEL: @main
+; CHECK: urem
+; CHECK: urem
+; CHECK: urem
+
+ at g_x_s = global i32 -470211272, align 4
+ at g_z_s = global i32 2007237709, align 4
+ at g_x_u = global i32 282475249, align 4
+ at g_z_u = global i32 984943658, align 4
+ at g_m = global i32 16807, align 4
+ at res = common global i32 0, align 4
+
+; Function Attrs:
+define i64 @func() #0 {
+entry:
+  ret i64 1
+}
+
+; Function Attrs:
+define i32 @main() {
+entry:
+  %0 = load volatile i32, i32* @g_x_s, align 4
+  %1 = load volatile i32, i32* @g_z_s, align 4
+  %2 = load volatile i32, i32* @g_x_u, align 4
+  %3 = load volatile i32, i32* @g_z_u, align 4
+  %4 = load volatile i32, i32* @g_m, align 4
+  %call = call i64 @func() #4
+  %conv = sext i32 %1 to i64
+  %cmp = icmp ne i64 %call, %conv
+  br i1 %cmp, label %if.end, label %lor.lhs.false
+
+lor.lhs.false:
+  %div = udiv i32 %4, %1
+  %rem = urem i32 %0, %div
+  %cmp2 = icmp eq i32 %rem, 0
+  br i1 %cmp2, label %if.end, label %if.then
+
+if.then:
+  br label %cleanup
+
+if.end:
+  %call4 = call i64 @func() #4
+  %conv5 = zext i32 %3 to i64
+  %cmp6 = icmp ne i64 %call4, %conv5
+  br i1 %cmp6, label %if.end14, label %lor.lhs.false8
+
+lor.lhs.false8:
+  %div9 = udiv i32 %4, %3
+  %rem10 = urem i32 %0, %div9
+  %cmp11 = icmp eq i32 %rem10, 0
+  br i1 %cmp11, label %if.end14, label %if.then13
+
+if.then13:
+  br label %cleanup
+
+if.end14:
+  %call15 = call i64 @func() #4
+  %cmp17 = icmp ne i64 %call15, %conv
+  br i1 %cmp17, label %if.end25, label %lor.lhs.false19
+
+lor.lhs.false19:
+  %div20 = udiv i32 %4, %1
+  %rem21 = urem i32 %0, %div20
+  %cmp22 = icmp eq i32 %rem21, 0
+  br i1 %cmp22, label %if.end25, label %if.then24
+
+if.then24:
+  br label %cleanup
+
+if.end25:
+  br label %cleanup
+
+cleanup:
+  %retval.0 = phi i32 [ 0, %if.end25 ], [ 1, %if.then24 ], [ 1, %if.then13 ], [ 1, %if.then ]
+  ret i32 %retval.0
+}
+
+attributes #0 = { minsize noinline nounwind optsize uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

Added: llvm/trunk/test/Transforms/GVNHoist/hoist-very-busy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist-very-busy.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist-very-busy.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist-very-busy.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+%struct.__jmp_buf_tag = type { [8 x i64], i32 }
+
+; Check that hoisting only happens when the expression is very busy.
+; CHECK: store
+; CHECK: store
+
+ at test_exit_buf = global %struct.__jmp_buf_tag zeroinitializer
+ at G = global i32 0
+
+define void @test_command(i32 %c1) {
+entry:
+  switch i32 %c1, label %exit [
+    i32 0, label %sw0
+    i32 1, label %sw1
+  ]
+
+sw0:
+  store i32 1, i32* @G
+  br label %exit
+
+sw1:
+  store i32 1, i32* @G
+  br label %exit
+
+exit:
+  call void @longjmp(%struct.__jmp_buf_tag* @test_exit_buf, i32 1) #0
+  unreachable
+}
+
+declare void @longjmp(%struct.__jmp_buf_tag*, i32) #0
+
+attributes #0 = { noreturn nounwind }
+
+; Check that the store is hoisted.
+; CHECK-LABEL: define void @fun(
+; CHECK: store
+; CHECK-NOT: store
+
+define void @fun() {
+entry:
+  br label %if.then
+
+if.then:                                          ; preds = %entry
+  br i1 undef, label %sw0, label %sw1
+
+sw0:
+  store i32 1, i32* @G
+  unreachable
+
+sw1:
+  store i32 1, i32* @G
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVNHoist/hoist.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/hoist.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/hoist.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/hoist.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,646 @@
+; RUN: opt -gvn-hoist -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"
+
+ at GlobalVar = internal global float 1.000000e+00
+
+; Check that all scalar expressions are hoisted.
+;
+; CHECK-LABEL: @scalarsHoisting
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @scalarsHoisting(float %d, float %min, float %max, float %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %sub = fsub float %min, %a
+  %mul = fmul float %sub, %div
+  %sub1 = fsub float %max, %a
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %sub3 = fsub float %max, %a
+  %mul4 = fmul float %sub3, %div
+  %sub5 = fsub float %min, %a
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that all loads and scalars depending on the loads are hoisted.
+; Check that getelementptr computation gets hoisted before the load.
+;
+; CHECK-LABEL: @readsAndScalarsHoisting
+; CHECK: load
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: load
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @readsAndScalarsHoisting(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %A = getelementptr float, float* %min, i32 1
+  %0 = load float, float* %A, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %B = getelementptr float, float* %min, i32 1
+  %5 = load float, float* %B, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that we do not hoist loads after a store: the first two loads will be
+; hoisted, and then the third load will not be hoisted.
+;
+; CHECK-LABEL: @readsAndWrites
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: store
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: load
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @readsAndWrites(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  store float %0, float* @GlobalVar
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that we do hoist loads when the store is above the insertion point.
+;
+; CHECK-LABEL: @readsAndWriteAboveInsertPt
+; CHECK: load
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: load
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @readsAndWriteAboveInsertPt(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  store float 0.000000e+00, float* @GlobalVar
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that dependent expressions are hoisted.
+; CHECK-LABEL: @dependentScalarsHoisting
+; CHECK: fsub
+; CHECK: fadd
+; CHECK: fdiv
+; CHECK: fmul
+; CHECK-NOT: fsub
+; CHECK-NOT: fadd
+; CHECK-NOT: fdiv
+; CHECK-NOT: fmul
+define float @dependentScalarsHoisting(float %a, float %b, i1 %c) {
+entry:
+  br i1 %c, label %if.then, label %if.else
+
+if.then:
+  %d = fsub float %b, %a
+  %e = fadd float %d, %a
+  %f = fdiv float %e, %a
+  %g = fmul float %f, %a
+  br label %if.end
+
+if.else:
+  %h = fsub float %b, %a
+  %i = fadd float %h, %a
+  %j = fdiv float %i, %a
+  %k = fmul float %j, %a
+  br label %if.end
+
+if.end:
+  %r = phi float [ %g, %if.then ], [ %k, %if.else ]
+  ret float %r
+}
+
+; Check that all independent expressions are hoisted.
+; CHECK-LABEL: @independentScalarsHoisting
+; CHECK: fsub
+; CHECK: fdiv
+; CHECK: fmul
+; CHECK: fadd
+; CHECK-NOT: fsub
+; CHECK-NOT: fdiv
+; CHECK-NOT: fmul
+define float @independentScalarsHoisting(float %a, float %b, i1 %c) {
+entry:
+  br i1 %c, label %if.then, label %if.else
+
+if.then:
+  %d = fadd float %b, %a
+  %e = fsub float %b, %a
+  %f = fdiv float %b, %a
+  %g = fmul float %b, %a
+  br label %if.end
+
+if.else:
+  %i = fadd float %b, %a
+  %h = fsub float %b, %a
+  %j = fdiv float %b, %a
+  %k = fmul float %b, %a
+  br label %if.end
+
+if.end:
+  %p = phi float [ %d, %if.then ], [ %i, %if.else ]
+  %q = phi float [ %e, %if.then ], [ %h, %if.else ]
+  %r = phi float [ %f, %if.then ], [ %j, %if.else ]
+  %s = phi float [ %g, %if.then ], [ %k, %if.else ]
+  %t = fadd float %p, %q
+  %u = fadd float %r, %s
+  %v = fadd float %t, %u
+  ret float %v
+}
+
+; Check that we hoist load and scalar expressions in triangles.
+; CHECK-LABEL: @triangleHoisting
+; CHECK: load
+; CHECK: load
+; CHECK: load
+; CHECK: fsub
+; CHECK: fmul
+; CHECK: fsub
+; CHECK: fmul
+; CHECK-NOT: load
+; CHECK-NOT: fmul
+; CHECK-NOT: fsub
+define float @triangleHoisting(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.end:                                          ; preds = %entry
+  %p1 = phi float [ %mul2, %if.then ], [ 0.000000e+00, %entry ]
+  %p2 = phi float [ %mul, %if.then ], [ 0.000000e+00, %entry ]
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+
+  %x = fadd float %p1, %mul6
+  %y = fadd float %p2, %mul4
+  %z = fadd float %x, %y
+  ret float %z
+}
+
+; Check that we do not hoist loads past stores within a same basic block.
+; CHECK-LABEL: @noHoistInSingleBBWithStore
+; CHECK: load
+; CHECK: store
+; CHECK: load
+; CHECK: store
+define i32 @noHoistInSingleBBWithStore() {
+entry:
+  %D = alloca i32, align 4
+  %0 = bitcast i32* %D to i8*
+  %bf = load i8, i8* %0, align 4
+  %bf.clear = and i8 %bf, -3
+  store i8 %bf.clear, i8* %0, align 4
+  %bf1 = load i8, i8* %0, align 4
+  %bf.clear1 = and i8 %bf1, 1
+  store i8 %bf.clear1, i8* %0, align 4
+  ret i32 0
+}
+
+; Check that we do not hoist loads past calls within a same basic block.
+; CHECK-LABEL: @noHoistInSingleBBWithCall
+; CHECK: load
+; CHECK: call
+; CHECK: load
+declare void @foo()
+define i32 @noHoistInSingleBBWithCall() {
+entry:
+  %D = alloca i32, align 4
+  %0 = bitcast i32* %D to i8*
+  %bf = load i8, i8* %0, align 4
+  %bf.clear = and i8 %bf, -3
+  call void @foo()
+  %bf1 = load i8, i8* %0, align 4
+  %bf.clear1 = and i8 %bf1, 1
+  ret i32 0
+}
+
+; Check that we do not hoist loads past stores in any branch of a diamond.
+; CHECK-LABEL: @noHoistInDiamondWithOneStore1
+; CHECK: fdiv
+; CHECK: fcmp
+; CHECK: br
+define float @noHoistInDiamondWithOneStore1(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  store float 0.000000e+00, float* @GlobalVar
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  ; There are no side effects on the if.else branch.
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
+
+  %6 = load float, float* %max, align 4
+  %7 = load float, float* %a, align 4
+  %sub6 = fsub float %6, %7
+  %mul7 = fmul float %sub6, %div
+  %8 = load float, float* %min, align 4
+  %sub8 = fsub float %8, %7
+  %mul9 = fmul float %sub8, %div
+
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that we do not hoist loads past stores from half diamond.
+; CHECK-LABEL: @noHoistInHalfDiamondPastStore
+; CHECK: load
+; CHECK-NEXT: load
+; CHECK-NEXT: store
+; CHECK-NEXT: br
+; CHECK: load
+; CHECK: load
+; CHECK: load
+; CHECK: br
+define float @noHoistInHalfDiamondPastStore(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+
+  ; Loads should not be hoisted above this store.
+  store float 0.000000e+00, float* @GlobalVar
+
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  ; There are no side effects on the if.then branch.
+  %2 = load float, float* %max, align 4
+  %3 = load float, float* %a, align 4
+  %sub3 = fsub float %2, %3
+  %mul4 = fmul float %sub3, %div
+  %4 = load float, float* %min, align 4
+  %sub5 = fsub float %4, %3
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:
+  %tmax.0 = phi float [ %mul4, %if.then ], [ %0, %entry ]
+  %tmin.0 = phi float [ %mul6, %if.then ], [ %1, %entry ]
+
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that we do not hoist loads past a store in any branch of a diamond.
+; CHECK-LABEL: @noHoistInDiamondWithOneStore2
+; CHECK: fdiv
+; CHECK: fcmp
+; CHECK: br
+define float @noHoistInDiamondWithOneStore2(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  ; There are no side effects on the if.then branch.
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  store float 0.000000e+00, float* @GlobalVar
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
+
+  %6 = load float, float* %max, align 4
+  %7 = load float, float* %a, align 4
+  %sub6 = fsub float %6, %7
+  %mul7 = fmul float %sub6, %div
+  %8 = load float, float* %min, align 4
+  %sub8 = fsub float %8, %7
+  %mul9 = fmul float %sub8, %div
+
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that we do not hoist loads outside a loop containing stores.
+; CHECK-LABEL: @noHoistInLoopsWithStores
+; CHECK: fdiv
+; CHECK: fcmp
+; CHECK: br
+define float @noHoistInLoopsWithStores(float %d, float* %min, float* %max, float* %a) {
+entry:
+  %div = fdiv float 1.000000e+00, %d
+  %cmp = fcmp oge float %div, 0.000000e+00
+  br i1 %cmp, label %do.body, label %if.else
+
+do.body:
+  %0 = load float, float* %min, align 4
+  %1 = load float, float* %a, align 4
+
+  ; It is unsafe to hoist the loads outside the loop because of the store.
+  store float 0.000000e+00, float* @GlobalVar
+
+  %sub = fsub float %0, %1
+  %mul = fmul float %sub, %div
+  %2 = load float, float* %max, align 4
+  %sub1 = fsub float %2, %1
+  %mul2 = fmul float %sub1, %div
+  br label %while.cond
+
+while.cond:
+  %cmp1 = fcmp oge float %mul2, 0.000000e+00
+  br i1 %cmp1, label %if.end, label %do.body
+
+if.else:
+  %3 = load float, float* %max, align 4
+  %4 = load float, float* %a, align 4
+  %sub3 = fsub float %3, %4
+  %mul4 = fmul float %sub3, %div
+  %5 = load float, float* %min, align 4
+  %sub5 = fsub float %5, %4
+  %mul6 = fmul float %sub5, %div
+  br label %if.end
+
+if.end:
+  %tmax.0 = phi float [ %mul2, %while.cond ], [ %mul6, %if.else ]
+  %tmin.0 = phi float [ %mul, %while.cond ], [ %mul4, %if.else ]
+
+  %add = fadd float %tmax.0, %tmin.0
+  ret float %add
+}
+
+; Check that we hoist stores: all the instructions from the then branch
+; should be hoisted.
+; CHECK-LABEL: @hoistStores
+; CHECK: zext
+; CHECK-NEXT: trunc
+; CHECK-NEXT: getelementptr
+; CHECK-NEXT: load
+; CHECK-NEXT: getelementptr
+; CHECK-NEXT: getelementptr
+; CHECK-NEXT: store
+; CHECK-NEXT: load
+; CHECK-NEXT: load
+; CHECK-NEXT: zext
+; CHECK-NEXT: add
+; CHECK-NEXT: store
+; CHECK-NEXT: br
+; CHECK: if.then
+; CHECK: br
+
+%struct.foo = type { i16* }
+
+define void @hoistStores(%struct.foo* %s, i32* %coord, i1 zeroext %delta) {
+entry:
+  %frombool = zext i1 %delta to i8
+  %tobool = trunc i8 %frombool to i1
+  br i1 %tobool, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  %p = getelementptr inbounds %struct.foo, %struct.foo* %s, i32 0, i32 0
+  %0 = load i16*, i16** %p, align 8
+  %incdec.ptr = getelementptr inbounds i16, i16* %0, i32 1
+  store i16* %incdec.ptr, i16** %p, align 8
+  %1 = load i16, i16* %0, align 2
+  %conv = zext i16 %1 to i32
+  %2 = load i32, i32* %coord, align 4
+  %add = add i32 %2, %conv
+  store i32 %add, i32* %coord, align 4
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  %p1 = getelementptr inbounds %struct.foo, %struct.foo* %s, i32 0, i32 0
+  %3 = load i16*, i16** %p1, align 8
+  %incdec.ptr2 = getelementptr inbounds i16, i16* %3, i32 1
+  store i16* %incdec.ptr2, i16** %p1, align 8
+  %4 = load i16, i16* %3, align 2
+  %conv3 = zext i16 %4 to i32
+  %5 = load i32, i32* %coord, align 4
+  %add4 = add i32 %5, %conv3
+  store i32 %add4, i32* %coord, align 4
+  %6 = load i16*, i16** %p1, align 8
+  %incdec.ptr6 = getelementptr inbounds i16, i16* %6, i32 1
+  store i16* %incdec.ptr6, i16** %p1, align 8
+  %7 = load i16, i16* %6, align 2
+  %conv7 = zext i16 %7 to i32
+  %shl = shl i32 %conv7, 8
+  %8 = load i32, i32* %coord, align 4
+  %add8 = add i32 %8, %shl
+  store i32 %add8, i32* %coord, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  ret void
+}
+
+define i32 @mergeAlignments(i1 %b, i32* %y) {
+entry:
+  br i1 %b, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %l1 = load i32, i32* %y, align 4
+  br label %return
+
+if.end:                                           ; preds = %entry
+  %l2 = load i32, i32* %y, align 1
+  br label %return
+
+return:                                           ; preds = %if.end, %if.then
+  %retval.0 = phi i32 [ %l1, %if.then ], [ %l2, %if.end ]
+  ret i32 %retval.0
+}
+; CHECK-LABEL: define i32 @mergeAlignments(
+; CHECK: %[[load:.*]] = load i32, i32* %y, align 1
+; CHECK: %[[phi:.*]] = phi i32 [ %[[load]], %{{.*}} ], [ %[[load]], %{{.*}} ]
+; CHECK: i32 %[[phi]]
+
+
+declare i8 @pr30991_f() nounwind readonly
+declare void @pr30991_f1(i8)
+define i8 @pr30991(i8* %sp, i8* %word, i1 %b1, i1 %b2) {
+entry:
+  br i1 %b1, label %a, label %b
+
+a:
+  %r0 = load i8, i8* %word, align 1
+  %incdec.ptr = getelementptr i8, i8* %sp, i32 1
+  %rr0 = call i8 @pr30991_f() nounwind readonly
+  call void @pr30991_f1(i8 %r0)
+  ret i8 %rr0
+
+b:
+  br i1 %b2, label %c, label %x
+
+c:
+  %r1 = load i8, i8* %word, align 1
+  %incdec.ptr115 = getelementptr i8, i8* %sp, i32 1
+  %rr1 = call i8 @pr30991_f() nounwind readonly
+  call void @pr30991_f1(i8 %r1)
+  ret i8 %rr1
+
+x:
+  %r2 = load i8, i8* %word, align 1
+  ret i8 %r2
+}
+
+; CHECK-LABEL: define i8 @pr30991
+; CHECK:  %r0 = load i8, i8* %word, align 1
+; CHECK-NEXT:  br i1 %b1, label %a, label %b

Added: llvm/trunk/test/Transforms/GVNHoist/infinite-loop-direct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/infinite-loop-direct.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/infinite-loop-direct.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/infinite-loop-direct.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,96 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Checking gvn-hoist in case of infinite loops and irreducible control flow.
+
+; Check that bitcast is not hoisted beacuse down safety is not guaranteed.
+; CHECK-LABEL: @bazv1
+; CHECK: if.then.i:
+; CHECK: bitcast
+; CHECK-NEXT: load
+; CHECK: if.then4.i:
+; CHECK: bitcast
+; CHECK-NEXT: load
+
+%class.bar = type { i8*, %class.base* }
+%class.base = type { i32 (...)** }
+
+; Function Attrs: noreturn nounwind uwtable
+define void @bazv1() local_unnamed_addr {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x.sroa.2.0..sroa_idx2 = getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  store %class.base* null, %class.base** %x.sroa.2.0..sroa_idx2, align 8
+  call void @_Z3foo3bar(%class.bar* nonnull %agg.tmp)
+  %0 = load %class.base*, %class.base** %x.sroa.2.0..sroa_idx2, align 8
+  %1 = bitcast %class.bar* %agg.tmp to %class.base*
+  %cmp.i = icmp eq %class.base* %0, %1
+  br i1 %cmp.i, label %if.then.i, label %if.else.i
+
+if.then.i:                                        ; preds = %entry
+  %2 = bitcast %class.base* %0 to void (%class.base*)***
+  %vtable.i = load void (%class.base*)**, void (%class.base*)*** %2, align 8
+  %vfn.i = getelementptr inbounds void (%class.base*)*, void (%class.base*)** %vtable.i, i64 2
+  %3 = load void (%class.base*)*, void (%class.base*)** %vfn.i, align 8
+  call void %3(%class.base* %0)
+  br label %while.cond.preheader
+
+if.else.i:                                        ; preds = %entry
+  %tobool.i = icmp eq %class.base* %0, null
+  br i1 %tobool.i, label %while.cond.preheader, label %if.then4.i
+
+if.then4.i:                                       ; preds = %if.else.i
+  %4 = bitcast %class.base* %0 to void (%class.base*)***
+  %vtable6.i = load void (%class.base*)**, void (%class.base*)*** %4, align 8
+  %vfn7.i = getelementptr inbounds void (%class.base*)*, void (%class.base*)** %vtable6.i, i64 3
+  %5 = load void (%class.base*)*, void (%class.base*)** %vfn7.i, align 8
+  call void %5(%class.base* nonnull %0)
+  br label %while.cond.preheader
+
+while.cond.preheader:                             ; preds = %if.then.i, %if.else.i, %if.then4.i
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond.preheader, %while.cond
+  %call = call i32 @sleep(i32 10)
+  br label %while.cond
+}
+
+declare void @_Z3foo3bar(%class.bar*) local_unnamed_addr
+
+declare i32 @sleep(i32) local_unnamed_addr
+
+; Check that the load is hoisted even if it is inside an irreducible control flow
+; because the load is anticipable on all paths.
+
+; CHECK-LABEL: @bazv
+; CHECK: bb2:
+; CHECK-NOT: load
+; CHECK-NOT: bitcast
+
+define void @bazv() {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x= getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  %0 = load %class.base*, %class.base** %x, align 8
+  %1 = bitcast %class.bar* %agg.tmp to %class.base*
+  %cmp.i = icmp eq %class.base* %0, %1
+  br i1 %cmp.i, label %bb1, label %bb4
+
+bb1:
+  %b1 = bitcast %class.base* %0 to void (%class.base*)***
+  %i = load void (%class.base*)**, void (%class.base*)*** %b1, align 8
+  %vfn.i = getelementptr inbounds void (%class.base*)*, void (%class.base*)** %i, i64 2
+  %cmp.j = icmp eq %class.base* %0, %1
+  br i1 %cmp.j, label %bb2, label %bb3
+
+bb2:
+  %l1 = load void (%class.base*)*, void (%class.base*)** %vfn.i, align 8
+  br label %bb3
+
+bb3:
+  %l2 = load void (%class.base*)*, void (%class.base*)** %vfn.i, align 8
+  br label %bb2
+
+bb4:
+  %b2 = bitcast %class.base* %0 to void (%class.base*)***
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVNHoist/infinite-loop-indirect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/infinite-loop-indirect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/infinite-loop-indirect.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/infinite-loop-indirect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,285 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Checking gvn-hoist in case of indirect branches.
+
+; Check that the bitcast is not hoisted because it is after an indirect call
+; CHECK-LABEL: @foo
+; CHECK-LABEL: l1.preheader:
+; CHECK-NEXT: bitcast
+; CHECK-LABEL: l1
+; CHECK: bitcast
+
+%class.bar = type { i8*, %class.base* }
+%class.base = type { i32 (...)** }
+
+ at bar = local_unnamed_addr global i32 ()* null, align 8
+ at bar1 = local_unnamed_addr global i32 ()* null, align 8
+
+define i32 @foo(i32* nocapture readonly %i) {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x= getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  %y = load %class.base*, %class.base** %x, align 8
+  %0 = load i32, i32* %i, align 4
+  %.off = add i32 %0, -1
+  %switch = icmp ult i32 %.off, 2
+  br i1 %switch, label %l1.preheader, label %sw.default
+
+l1.preheader:                                     ; preds = %sw.default, %entry
+  %b1 = bitcast %class.base* %y to void (%class.base*)***
+  br label %l1
+
+l1:                                               ; preds = %l1.preheader, %l1
+  %1 = load i32 ()*, i32 ()** @bar, align 8
+  %call = tail call i32 %1()
+  %b2 = bitcast %class.base* %y to void (%class.base*)***
+  br label %l1
+
+sw.default:                                       ; preds = %entry
+  %2 = load i32 ()*, i32 ()** @bar1, align 8
+  %call2 = tail call i32 %2()
+  br label %l1.preheader
+}
+
+
+; Any instruction inside an infinite loop will not be hoisted because
+; there is no path to exit of the function.
+
+; CHECK-LABEL: @foo1
+; CHECK-LABEL: l1.preheader:
+; CHECK-NEXT: bitcast
+; CHECK-LABEL: l1:
+; CHECK: bitcast
+
+define i32 @foo1(i32* nocapture readonly %i) {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x= getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  %y = load %class.base*, %class.base** %x, align 8
+  %0 = load i32, i32* %i, align 4
+  %.off = add i32 %0, -1
+  %switch = icmp ult i32 %.off, 2
+  br i1 %switch, label %l1.preheader, label %sw.default
+
+l1.preheader:                                     ; preds = %sw.default, %entry
+  %b1 = bitcast %class.base* %y to void (%class.base*)***
+  %y1 = load %class.base*, %class.base** %x, align 8
+  br label %l1
+
+l1:                                               ; preds = %l1.preheader, %l1
+  %b2 = bitcast %class.base* %y to void (%class.base*)***
+  %1 = load i32 ()*, i32 ()** @bar, align 8
+  %y2 = load %class.base*, %class.base** %x, align 8
+  %call = tail call i32 %1()
+  br label %l1
+
+sw.default:                                       ; preds = %entry
+  %2 = load i32 ()*, i32 ()** @bar1, align 8
+  %call2 = tail call i32 %2()
+  br label %l1.preheader
+}
+
+; Check that bitcast is hoisted even when one of them is partially redundant.
+; CHECK-LABEL: @test13
+; CHECK: bitcast
+; CHECK-NOT: bitcast
+
+define i32 @test13(i32* %P, i8* %Ptr, i32* nocapture readonly %i) {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x= getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  %y = load %class.base*, %class.base** %x, align 8
+  indirectbr i8* %Ptr, [label %BrBlock, label %B2]
+
+B2:
+  %b1 = bitcast %class.base* %y to void (%class.base*)***
+  store i32 4, i32 *%P
+  br label %BrBlock
+
+BrBlock:
+  %b2 = bitcast %class.base* %y to void (%class.base*)***
+  %L = load i32, i32* %P
+  %C = icmp eq i32 %L, 42
+  br i1 %C, label %T, label %F
+
+T:
+  ret i32 123
+F:
+  ret i32 1422
+}
+
+; Check that the bitcast is not hoisted because anticipability
+; cannot be guaranteed here as one of the indirect branch targets
+; do not have the bitcast instruction.
+
+; CHECK-LABEL: @test14
+; CHECK-LABEL: B2:
+; CHECK-NEXT: bitcast
+; CHECK-LABEL: BrBlock:
+; CHECK-NEXT: bitcast
+
+define i32 @test14(i32* %P, i8* %Ptr, i32* nocapture readonly %i) {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x= getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  %y = load %class.base*, %class.base** %x, align 8
+  indirectbr i8* %Ptr, [label %BrBlock, label %B2, label %T]
+
+B2:
+  %b1 = bitcast %class.base* %y to void (%class.base*)***
+  store i32 4, i32 *%P
+  br label %BrBlock
+
+BrBlock:
+  %b2 = bitcast %class.base* %y to void (%class.base*)***
+  %L = load i32, i32* %P
+  %C = icmp eq i32 %L, 42
+  br i1 %C, label %T, label %F
+
+T:
+  %pi = load i32, i32* %i, align 4
+  ret i32 %pi
+F:
+  %pl = load i32, i32* %P
+  ret i32 %pl
+}
+
+
+; Check that the bitcast is not hoisted because of a cycle
+; due to indirect branches
+; CHECK-LABEL: @test16
+; CHECK-LABEL: B2:
+; CHECK-NEXT: bitcast
+; CHECK-LABEL: BrBlock:
+; CHECK-NEXT: bitcast
+
+define i32 @test16(i32* %P, i8* %Ptr, i32* nocapture readonly %i) {
+entry:
+  %agg.tmp = alloca %class.bar, align 8
+  %x= getelementptr inbounds %class.bar, %class.bar* %agg.tmp, i64 0, i32 1
+  %y = load %class.base*, %class.base** %x, align 8
+  indirectbr i8* %Ptr, [label %BrBlock, label %B2]
+
+B2:
+  %b1 = bitcast %class.base* %y to void (%class.base*)***
+  %0 = load i32, i32* %i, align 4
+  store i32 %0, i32 *%P
+  br label %BrBlock
+
+BrBlock:
+  %b2 = bitcast %class.base* %y to void (%class.base*)***
+  %L = load i32, i32* %P
+  %C = icmp eq i32 %L, 42
+  br i1 %C, label %T, label %F
+
+T:
+  indirectbr i32* %P, [label %BrBlock, label %B2]
+
+F:
+  indirectbr i8* %Ptr, [label %BrBlock, label %B2]
+}
+
+
+ at _ZTIi = external constant i8*
+
+; Check that an instruction is not hoisted out of landing pad (%lpad4)
+; Also within a landing pad no redundancies are removed by gvn-hoist,
+; however an instruction may be hoisted into a landing pad if
+; landing pad has direct branches (e.g., %lpad to %catch1, %catch)
+; This CFG has a cycle (%lpad -> %catch1 -> %lpad4 -> %lpad)
+
+; CHECK-LABEL: @foo2
+; Check that nothing gets hoisted out of %lpad
+; CHECK-LABEL: lpad:
+; CHECK: %bc1 = add i32 %0, 10
+; CHECK: %bc7 = add i32 %0, 10
+
+; Check that the add is hoisted
+; CHECK-LABEL: catch1:
+; CHECK-NEXT: invoke
+
+; Check that the add is hoisted
+; CHECK-LABEL: catch:
+; CHECK-NEXT: load
+
+; Check that other adds are not hoisted
+; CHECK-LABEL: lpad4:
+; CHECK: %bc5 = add i32 %0, 10
+; CHECK-LABEL: unreachable:
+; CHECK: %bc2 = add i32 %0, 10
+
+; Function Attrs: noinline uwtable
+define i32 @foo2(i32* nocapture readonly %i) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %0 = load i32, i32* %i, align 4
+  %cmp = icmp eq i32 %0, 0
+  br i1 %cmp, label %try.cont, label %if.then
+
+if.then:
+  %exception = tail call i8* @__cxa_allocate_exception(i64 4) #2
+  %1 = bitcast i8* %exception to i32*
+  store i32 %0, i32* %1, align 16
+  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3
+          to label %unreachable unwind label %lpad
+
+lpad:
+  %2 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @_ZTIi to i8*)
+          catch i8* null
+  %bc1 = add i32 %0, 10
+  %3 = extractvalue { i8*, i32 } %2, 0
+  %4 = extractvalue { i8*, i32 } %2, 1
+  %5 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2
+  %matches = icmp eq i32 %4, %5
+  %bc7 = add i32 %0, 10
+  %6 = tail call i8* @__cxa_begin_catch(i8* %3) #2
+  br i1 %matches, label %catch1, label %catch
+
+catch1:
+  %bc3 = add i32 %0, 10
+  invoke void @__cxa_rethrow() #3
+          to label %unreachable unwind label %lpad4
+
+catch:
+  %bc4 = add i32 %0, 10
+  %7 = load i32, i32* %i, align 4
+  %add = add nsw i32 %7, 1
+  tail call void @__cxa_end_catch()
+  br label %try.cont
+
+lpad4:
+  %8 = landingpad { i8*, i32 }
+          cleanup
+  %bc5 = add i32 %0, 10
+  tail call void @__cxa_end_catch() #2
+  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3
+          to label %unreachable unwind label %lpad
+
+try.cont:
+  %k.0 = phi i32 [ %add, %catch ], [ 0, %entry ]
+  %bc6 = add i32 %0, 10
+  ret i32 %k.0
+
+unreachable:
+  %bc2 = add i32 %0, 10
+  ret i32 %bc2
+}
+
+declare i8* @__cxa_allocate_exception(i64) local_unnamed_addr
+
+declare void @__cxa_throw(i8*, i8*, i8*) local_unnamed_addr
+
+declare i32 @__gxx_personality_v0(...)
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.typeid.for(i8*) #1
+
+declare i8* @__cxa_begin_catch(i8*) local_unnamed_addr
+
+declare void @__cxa_end_catch() local_unnamed_addr
+
+declare void @__cxa_rethrow() local_unnamed_addr
+
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind }
+attributes #3 = { noreturn }

Added: llvm/trunk/test/Transforms/GVNHoist/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/int_sideeffect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/int_sideeffect.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/int_sideeffect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -S < %s -gvn-hoist | FileCheck %s
+
+declare void @llvm.sideeffect()
+
+; GVN hoisting across a @llvm.sideeffect.
+
+; CHECK-LABEL: scalarsHoisting
+; CHECK: = fsub
+; CHECK: br i1 %cmp,
+; CHECK-NOT: fsub
+define float @scalarsHoisting(float %d, float %m, float %a, i1 %cmp) {
+entry:
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  call void @llvm.sideeffect()
+  %sub0 = fsub float %m, %a
+  %mul = fmul float %sub0, %d
+  br label %if.end
+
+if.else:
+  %sub1 = fsub float %m, %a
+  %div = fdiv float %sub1, %d
+  br label %if.end
+
+if.end:
+  %phi = phi float [ %mul, %if.then ], [ %div, %if.else ]
+  ret float %phi
+}
+

Added: llvm/trunk/test/Transforms/GVNHoist/ld_hoist1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/ld_hoist1.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/ld_hoist1.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/ld_hoist1.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,64 @@
+; Test load hoist
+; RUN: opt -gvn-hoist -S < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc_linux"
+
+; Function Attrs: nounwind uwtable
+define float* @foo(i32* noalias nocapture readonly %in, float* noalias %out, i32 %size, i32* nocapture readonly %trigger)  {
+entry:
+  %cmp11 = icmp eq i32 %size, 0
+  br i1 %cmp11, label %for.end, label %for.body.lr.ph
+
+for.body.lr.ph:                                   ; preds = %entry
+  %0 = add i32 %size, -1
+  br label %for.body
+
+; CHECK-LABEL: for.body
+; CHECK: load
+; CHECK:  %2 = getelementptr inbounds i32, i32* %in, i64 %indvars.iv
+; CHECK:  %3 = load i32, i32* %2, align 4
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.inc
+  %indvars.iv = phi i64 [ 0, %for.body.lr.ph ], [ %indvars.iv.next, %for.inc ]
+  %arrayidx = getelementptr inbounds i32, i32* %trigger, i64 %indvars.iv
+  %1 = load i32, i32* %arrayidx, align 4
+  %cmp1 = icmp sgt i32 %1, 0
+  br i1 %cmp1, label %if.then, label %if.else
+
+; CHECK-LABEL: if.then
+if.then:                                          ; preds = %for.body
+; This load should be hoisted
+  %arrayidx3 = getelementptr inbounds i32, i32* %in, i64 %indvars.iv
+  %2 = load i32, i32* %arrayidx3, align 4
+  %conv = sitofp i32 %2 to float
+  %add = fadd float %conv, 5.000000e-01
+  %arrayidx5 = getelementptr inbounds float, float* %out, i64 %indvars.iv
+  store float %add, float* %arrayidx5, align 4
+  br label %for.inc
+
+if.else:                                          ; preds = %for.body
+  %arrayidx7 = getelementptr inbounds float, float* %out, i64 %indvars.iv
+  %3 = load float, float* %arrayidx7, align 4
+  %div = fdiv float %3, 3.000000e+00
+  store float %div, float* %arrayidx7, align 4
+; This load should be hoisted in spite of store 
+  %arrayidx9 = getelementptr inbounds i32, i32* %in, i64 %indvars.iv
+  %4 = load i32, i32* %arrayidx9, align 4
+  %conv10 = sitofp i32 %4 to float
+  %add13 = fadd float %div, %conv10
+  store float %add13, float* %arrayidx7, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.then, %if.else
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  %lftr.wideiv = trunc i64 %indvars.iv to i32
+  %exitcond = icmp ne i32 %lftr.wideiv, %0
+  br i1 %exitcond, label %for.body, label %for.cond.for.end_crit_edge
+
+for.cond.for.end_crit_edge:                       ; preds = %for.inc
+  br label %for.end
+
+for.end:                                          ; preds = %entry, %for.cond.for.end_crit_edge
+  ret float* %out
+}
+

Added: llvm/trunk/test/Transforms/GVNHoist/ld_hoist_st_sink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/ld_hoist_st_sink.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/ld_hoist_st_sink.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/ld_hoist_st_sink.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,84 @@
+; Tests to make sure that loads and stores in a diamond get merged
+; Loads are hoisted into the header. Stores sunks into the footer.
+; RUN: opt -gvn-hoist -S < %s | FileCheck %s
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+%struct.node = type { i64, %struct.node*, %struct.node*, %struct.node*, i64, %struct.arc*, i64, i64, i64 }
+%struct.arc = type { i64, i64, i64 }
+
+define i64 @foo(%struct.node* nocapture readonly %r) nounwind {
+entry:
+  %node.0.in16 = getelementptr inbounds %struct.node, %struct.node* %r, i64 0, i32 2
+  %node.017 = load %struct.node*, %struct.node** %node.0.in16, align 8
+  %tobool18 = icmp eq %struct.node* %node.017, null
+  br i1 %tobool18, label %while.end, label %while.body.preheader
+
+; CHECK-LABEL: while.body.preheader
+while.body.preheader:                             ; preds = %entry
+; CHECK: load
+  br label %while.body
+
+while.body:                                       ; preds = %while.body.preheader, %if.end
+  %node.020 = phi %struct.node* [ %node.0, %if.end ], [ %node.017, %while.body.preheader ]
+  %sum.019 = phi i64 [ %inc, %if.end ], [ 0, %while.body.preheader ]
+  %orientation = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 4
+  %0 = load i64, i64* %orientation, align 8
+  %cmp = icmp eq i64 %0, 1
+  br i1 %cmp, label %if.then, label %if.else
+; CHECK: if.then
+if.then:                                          ; preds = %while.body
+  %a = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 5
+; CHECK-NOT: load %struct.arc
+  %1 = load %struct.arc*, %struct.arc** %a, align 8
+  %cost = getelementptr inbounds %struct.arc, %struct.arc* %1, i64 0, i32 0
+; CHECK-NOT: load i64, i64*
+  %2 = load i64, i64* %cost, align 8
+  %pred = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 1
+; CHECK-NOT: load %struct.node*, %struct.node**
+  %3 = load %struct.node*, %struct.node** %pred, align 8
+  %p = getelementptr inbounds %struct.node, %struct.node* %3, i64 0, i32 6
+; CHECK-NOT: load i64, i64*
+  %4 = load i64, i64* %p, align 8
+  %add = add nsw i64 %4, %2
+  %p1 = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 6
+; FIXME: store i64
+  store i64 %add, i64* %p1, align 8
+  br label %if.end
+
+; CHECK: if.else
+if.else:                                          ; preds = %while.body
+  %pred2 = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 1
+; CHECK-NOT: load %struct.node*, %struct.node**
+  %5 = load %struct.node*, %struct.node** %pred2, align 8
+  %p3 = getelementptr inbounds %struct.node, %struct.node* %5, i64 0, i32 6
+; CHECK-NOT: load i64, i64*
+  %6 = load i64, i64* %p3, align 8
+  %a4 = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 5
+; CHECK-NOT: load %struct.arc*, %struct.arc**
+  %7 = load %struct.arc*, %struct.arc** %a4, align 8
+  %cost5 = getelementptr inbounds %struct.arc, %struct.arc* %7, i64 0, i32 0
+; CHECK-NOT: load i64, i64*
+  %8 = load i64, i64* %cost5, align 8
+  %sub = sub nsw i64 %6, %8
+  %p6 = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 6
+; FIXME: store i64
+  store i64 %sub, i64* %p6, align 8
+  br label %if.end
+
+; CHECK: if.end
+if.end:                                           ; preds = %if.else, %if.then
+; FIXME: store
+  %inc = add nsw i64 %sum.019, 1
+  %node.0.in = getelementptr inbounds %struct.node, %struct.node* %node.020, i64 0, i32 2
+  %node.0 = load %struct.node*, %struct.node** %node.0.in, align 8
+  %tobool = icmp eq %struct.node* %node.0, null
+  br i1 %tobool, label %while.end.loopexit, label %while.body
+
+while.end.loopexit:                               ; preds = %if.end
+  %inc.lcssa = phi i64 [ %inc, %if.end ]
+  br label %while.end
+
+while.end:                                        ; preds = %while.end.loopexit, %entry
+  %sum.0.lcssa = phi i64 [ 0, %entry ], [ %inc.lcssa, %while.end.loopexit ]
+  ret i64 %sum.0.lcssa
+}

Added: llvm/trunk/test/Transforms/GVNHoist/non-trivial-phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/non-trivial-phi.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/non-trivial-phi.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/non-trivial-phi.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt -gvn-hoist %s -S -o - | FileCheck %s
+
+; CHECK: store
+; CHECK-NOT: store
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+define void @f(i8* %p) {
+entry:
+  switch i4 undef, label %if.then30 [
+    i4 4, label %if.end
+    i4 0, label %if.end
+  ]
+
+if.end:
+  br label %if.end19
+
+if.end19:
+  br i1 undef, label %e, label %e.thread
+
+e.thread:
+  store i8 0, i8* %p, align 4
+  br label %if.then30
+
+if.then30:
+  call void @g()
+  unreachable
+
+e:
+  store i8 0, i8* %p, align 4
+  unreachable
+}
+
+declare void @g()

Added: llvm/trunk/test/Transforms/GVNHoist/pr28626.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr28626.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr28626.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr28626.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt -S -gvn-hoist < %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(i1 %a, i1** %d) {
+entry:
+  %0 = load i1*, i1** %d, align 8
+  br i1 %a, label %if.then, label %if.else
+
+if.then:                                          ; preds = %entry
+  br label %if.end
+
+if.else:                                          ; preds = %entry
+  br label %if.end
+
+if.end:                                           ; preds = %if.else, %if.then
+  %c.0 = phi i1 [ 1, %if.then ], [ 0, %if.else ]
+  br i1 %c.0, label %if.then2, label %if.else3
+
+if.then2:                                         ; preds = %if.end
+  %rc = getelementptr inbounds i1, i1* %0, i64 0
+  store i1 %c.0, i1* %rc, align 4
+  br label %if.end6
+
+if.else3:                                         ; preds = %if.end
+  %rc5 = getelementptr inbounds i1, i1* %0, i64 0
+  store i1 %c.0, i1* %rc5, align 4
+  br label %if.end6
+
+if.end6:                                          ; preds = %if.else3, %if.then2
+  ret void
+}
+
+; CHECK-LABEL: define void @test1(
+; CHECK:  %[[load:.*]] = load i1*, i1** %d, align 8
+; CHECK:  %[[phi:.*]] = phi i1 [ true, {{.*}} ], [ false, {{.*}} ]
+
+; CHECK: %[[gep0:.*]] = getelementptr inbounds i1, i1* %[[load]], i64 0
+; CHECK: store i1 %[[phi]], i1* %[[gep0]], align 4
+
+; Check that store instructions are hoisted.
+; CHECK-NOT: store
\ No newline at end of file

Added: llvm/trunk/test/Transforms/GVNHoist/pr29031.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr29031.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr29031.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr29031.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,51 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Check that the stores are not hoisted: it is invalid to hoist stores if they
+; are not executed on all paths. In this testcase, there are paths in the loop
+; that do not execute the stores.
+
+; CHECK-LABEL: define i32 @main
+; CHECK: store
+; CHECK: store
+; CHECK: store
+
+ at a = global i32 0, align 4
+
+define i32 @main() {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc5, %entry
+  %0 = load i32, i32* @a, align 4
+  %cmp = icmp slt i32 %0, 1
+  br i1 %cmp, label %for.cond1, label %for.end7
+
+for.cond1:                                        ; preds = %for.cond, %for.inc
+  %1 = load i32, i32* @a, align 4
+  %cmp2 = icmp slt i32 %1, 1
+  br i1 %cmp2, label %for.body3, label %for.inc5
+
+for.body3:                                        ; preds = %for.cond1
+  %tobool = icmp ne i32 %1, 0
+  br i1 %tobool, label %if.then, label %for.inc
+
+if.then:                                          ; preds = %for.body3
+  %inc = add nsw i32 %1, 1
+  store i32 %inc, i32* @a, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3, %if.then
+  %2 = load i32, i32* @a, align 4
+  %inc4 = add nsw i32 %2, 1
+  store i32 %inc4, i32* @a, align 4
+  br label %for.cond1
+
+for.inc5:                                         ; preds = %for.cond1
+  %inc6 = add nsw i32 %1, 1
+  store i32 %inc6, i32* @a, align 4
+  br label %for.cond
+
+for.end7:                                         ; preds = %for.cond
+  ret i32 %0
+}
+

Added: llvm/trunk/test/Transforms/GVNHoist/pr29034.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr29034.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr29034.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr29034.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,122 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Check that the stores are not hoisted: it is invalid to hoist stores if they
+; are not executed on all paths. In this testcase, there are paths in the loop
+; that do not execute the stores.
+
+; CHECK-LABEL: define void @music_task
+; CHECK: store
+; CHECK: store
+; CHECK: store
+
+
+%struct._MUSIC_OP_API_ = type { %struct._FILE_OPERATE_*, %struct.__MUSIC_API* }
+%struct._FILE_OPERATE_ = type { %struct._FILE_OPERATE_INIT_*, %struct._lg_dev_info_* }
+%struct._FILE_OPERATE_INIT_ = type { i32, i32, i32, i32, i32*, i8*, i32 }
+%struct._lg_dev_info_ = type { %struct.os_event, i32, i32, %struct._lg_dev_hdl_*, i8, i8, i8, i8, i8 }
+%struct.os_event = type { i8, i32, i8*, %union.anon }
+%union.anon = type { %struct.event_cnt }
+%struct.event_cnt = type { i16 }
+%struct._lg_dev_hdl_ = type { i8*, i8*, i8*, i8*, i8* }
+%struct.__MUSIC_API = type <{ i8*, i8*, i32, %struct._DEC_API, %struct._DEC_API_IO*, %struct._FS_BRK_POINT* }>
+%struct._DEC_API = type { %struct._DEC_PHY*, i8*, i8*, i8* (i8*)*, i32* (i8*)*, i8*, %struct._AAC_DEFAULT_SETTING, i32, i32, i8*, %struct.decoder_inf*, i32, i8, i8*, i8, i8* }
+%struct._DEC_PHY = type { i8*, %struct.__audio_decoder_ops*, i8*, %struct.if_decoder_io, %struct.if_dec_file*, i8*, i32 (i8*)*, i32, i8, %struct.__FF_FR }
+%struct.__audio_decoder_ops = type { i8*, i32 (i8*, %struct.if_decoder_io*, i8*)*, i32 (i8*)*, i32 (i8*, i32)*, %struct.decoder_inf* (i8*)*, i32 (i8*)*, i32 (i8*)*, i32 (...)*, i32 (...)*, i32 (...)*, void (i8*, i32)*, void (i8*, i32, i8*, i32)*, i32 (i8*, i32, i8*)* }
+%struct.if_decoder_io = type { i8*, i32 (i8*, i32, i8*, i32, i8)*, i32 (i8*, i32, i8*)*, void (i8*, i8*, i32)*, i32 (i8*)*, i32 (i8*, i32, i32)* }
+%struct.if_dec_file = type { i32 (i8*, i8*, i32)*, i32 (i8*, i32, i32)* }
+%struct.__FF_FR = type { i32, i32, i8, i8, i8 }
+%struct._AAC_DEFAULT_SETTING = type { i32, i32, i32 }
+%struct.decoder_inf = type { i16, i16, i32, i32 }
+%struct._DEC_API_IO = type { i8*, i8*, i16 (i8*, i8*, i16)*, i32 (i8*, i8, i32)*, i32 (%struct.decoder_inf*, i32)*, %struct.__OP_IO, i32, i32 }
+%struct.__OP_IO = type { i8*, i8* (i8*, i8*, i32)* }
+%struct._FS_BRK_POINT = type { %struct._FS_BRK_INFO, i32, i32 }
+%struct._FS_BRK_INFO = type { i32, i32, [8 x i8], i8, i8, i16 }
+
+ at .str = external hidden unnamed_addr constant [10 x i8], align 1
+
+define void @music_task(i8* nocapture readnone %p) local_unnamed_addr {
+entry:
+  %mapi = alloca %struct._MUSIC_OP_API_*, align 8
+  %0 = bitcast %struct._MUSIC_OP_API_** %mapi to i8*
+  call void @llvm.lifetime.start.p0i8(i64 8, i8* %0)
+  store %struct._MUSIC_OP_API_* null, %struct._MUSIC_OP_API_** %mapi, align 8, !tbaa !1
+  %call = call i32 @music_decoder_init(%struct._MUSIC_OP_API_** nonnull %mapi)
+  br label %while.cond
+
+while.cond.loopexit:                              ; preds = %while.cond2
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.cond.loopexit, %entry
+  %1 = load %struct._MUSIC_OP_API_*, %struct._MUSIC_OP_API_** %mapi, align 8, !tbaa !1
+  %dop_api = getelementptr inbounds %struct._MUSIC_OP_API_, %struct._MUSIC_OP_API_* %1, i64 0, i32 1
+  %2 = load %struct.__MUSIC_API*, %struct.__MUSIC_API** %dop_api, align 8, !tbaa !5
+  %file_num = getelementptr inbounds %struct.__MUSIC_API, %struct.__MUSIC_API* %2, i64 0, i32 2
+  %3 = bitcast i32* %file_num to i8*
+  %call1 = call i32 @music_play_api(%struct._MUSIC_OP_API_* %1, i32 33, i32 0, i32 28, i8* %3)
+  br label %while.cond2
+
+while.cond2:                                      ; preds = %while.cond2.backedge, %while.cond
+  %err.0 = phi i32 [ %call1, %while.cond ], [ %err.0.be, %while.cond2.backedge ]
+  switch i32 %err.0, label %sw.default [
+    i32 0, label %while.cond.loopexit
+    i32 35, label %sw.bb
+    i32 11, label %sw.bb7
+    i32 12, label %sw.bb13
+  ]
+
+sw.bb:                                            ; preds = %while.cond2
+  %4 = load %struct._MUSIC_OP_API_*, %struct._MUSIC_OP_API_** %mapi, align 8, !tbaa !1
+  %dop_api4 = getelementptr inbounds %struct._MUSIC_OP_API_, %struct._MUSIC_OP_API_* %4, i64 0, i32 1
+  %5 = load %struct.__MUSIC_API*, %struct.__MUSIC_API** %dop_api4, align 8, !tbaa !5
+  %file_num5 = getelementptr inbounds %struct.__MUSIC_API, %struct.__MUSIC_API* %5, i64 0, i32 2
+  %6 = load i32, i32* %file_num5, align 1, !tbaa !7
+  %call6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i64 0, i64 0), i32 %6)
+  br label %while.cond2.backedge
+
+sw.bb7:                                           ; preds = %while.cond2
+  %7 = load %struct._MUSIC_OP_API_*, %struct._MUSIC_OP_API_** %mapi, align 8, !tbaa !1
+  %dop_api8 = getelementptr inbounds %struct._MUSIC_OP_API_, %struct._MUSIC_OP_API_* %7, i64 0, i32 1
+  %8 = load %struct.__MUSIC_API*, %struct.__MUSIC_API** %dop_api8, align 8, !tbaa !5
+  %file_num9 = getelementptr inbounds %struct.__MUSIC_API, %struct.__MUSIC_API* %8, i64 0, i32 2
+  store i32 1, i32* %file_num9, align 1, !tbaa !7
+  %9 = bitcast i32* %file_num9 to i8*
+  %call12 = call i32 @music_play_api(%struct._MUSIC_OP_API_* %7, i32 34, i32 0, i32 24, i8* %9)
+  br label %while.cond2.backedge
+
+sw.bb13:                                          ; preds = %while.cond2
+  %10 = load %struct._MUSIC_OP_API_*, %struct._MUSIC_OP_API_** %mapi, align 8, !tbaa !1
+  %dop_api14 = getelementptr inbounds %struct._MUSIC_OP_API_, %struct._MUSIC_OP_API_* %10, i64 0, i32 1
+  %11 = load %struct.__MUSIC_API*, %struct.__MUSIC_API** %dop_api14, align 8, !tbaa !5
+  %file_num15 = getelementptr inbounds %struct.__MUSIC_API, %struct.__MUSIC_API* %11, i64 0, i32 2
+  store i32 1, i32* %file_num15, align 1, !tbaa !7
+  %12 = bitcast i32* %file_num15 to i8*
+  %call18 = call i32 @music_play_api(%struct._MUSIC_OP_API_* %10, i32 35, i32 0, i32 26, i8* %12)
+  br label %while.cond2.backedge
+
+sw.default:                                       ; preds = %while.cond2
+  %13 = load %struct._MUSIC_OP_API_*, %struct._MUSIC_OP_API_** %mapi, align 8, !tbaa !1
+  %call19 = call i32 @music_play_api(%struct._MUSIC_OP_API_* %13, i32 33, i32 0, i32 22, i8* null)
+  br label %while.cond2.backedge
+
+while.cond2.backedge:                             ; preds = %sw.default, %sw.bb13, %sw.bb7, %sw.bb
+  %err.0.be = phi i32 [ %call19, %sw.default ], [ %call18, %sw.bb13 ], [ %call12, %sw.bb7 ], [ 0, %sw.bb ]
+  br label %while.cond2
+}
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare i32 @music_decoder_init(%struct._MUSIC_OP_API_**)
+declare i32 @music_play_api(%struct._MUSIC_OP_API_*, i32, i32, i32, i8*)
+declare i32 @printf(i8* nocapture readonly, ...)
+
+!0 = !{!"clang version 4.0.0 "}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"any pointer", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!6, !2, i64 8}
+!6 = !{!"_MUSIC_OP_API_", !2, i64 0, !2, i64 8}
+!7 = !{!8, !9, i64 16}
+!8 = !{!"__MUSIC_API", !2, i64 0, !2, i64 8, !9, i64 16, !10, i64 20, !2, i64 140, !2, i64 148}
+!9 = !{!"int", !3, i64 0}
+!10 = !{!"_DEC_API", !2, i64 0, !2, i64 8, !2, i64 16, !2, i64 24, !2, i64 32, !2, i64 40, !11, i64 48, !9, i64 60, !9, i64 64, !2, i64 72, !2, i64 80, !9, i64 88, !3, i64 92, !2, i64 96, !3, i64 104, !2, i64 112}
+!11 = !{!"_AAC_DEFAULT_SETTING", !9, i64 0, !9, i64 4, !9, i64 8}

Added: llvm/trunk/test/Transforms/GVNHoist/pr30216.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr30216.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr30216.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr30216.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,52 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+
+; Make sure the two stores @B do not get hoisted past the load @B.
+
+; CHECK-LABEL: define i8* @Foo
+; CHECK: store
+; CHECK: store
+; CHECK: load
+; CHECK: store
+
+ at A = external global i8
+ at B = external global i8*
+
+define i8* @Foo() {
+  store i8 0, i8* @A
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  store i8* null, i8** @B
+  ret i8* null
+
+if.else:
+  %1 = load i8*, i8** @B
+  store i8* null, i8** @B
+  ret i8* %1
+}
+
+; Make sure the two stores @B do not get hoisted past the store @GlobalVar.
+
+; CHECK-LABEL: define i8* @Fun
+; CHECK: store
+; CHECK: store
+; CHECK: store
+; CHECK: store
+; CHECK: load
+
+ at GlobalVar = internal global i8 0
+
+define i8* @Fun() {
+  store i8 0, i8* @A
+  br i1 undef, label %if.then, label %if.else
+
+if.then:
+  store i8* null, i8** @B
+  ret i8* null
+
+if.else:
+  store i8 0, i8* @GlobalVar
+  store i8* null, i8** @B
+  %1 = load i8*, i8** @B
+  ret i8* %1
+}

Added: llvm/trunk/test/Transforms/GVNHoist/pr30499.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr30499.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr30499.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr30499.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -S -gvn-hoist < %s
+
+define void @_Z3fn2v() #0 {
+entry:
+  %a = alloca i8*, align 8
+  %b = alloca i32, align 4
+  %0 = load i8*, i8** %a, align 8
+  store i8 0, i8* %0, align 1
+  %1 = load i32, i32* %b, align 4
+  %tobool = icmp ne i32 %1, 0
+  br i1 %tobool, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %call = call i64 @_Z3fn1v() #2
+  %conv = trunc i64 %call to i32
+  store i32 %conv, i32* %b, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %entry
+  %2 = load i8*, i8** %a, align 8
+  store i8 0, i8* %2, align 1
+  ret void
+}
+
+; Function Attrs: nounwind readonly
+declare i64 @_Z3fn1v() #1
+
+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-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind readonly }

Added: llvm/trunk/test/Transforms/GVNHoist/pr35222-hoist-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr35222-hoist-load.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr35222-hoist-load.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr35222-hoist-load.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s
+; CHECK-LABEL: build_tree
+; CHECK: load
+; CHECK: load
+; Check that the load is not hoisted because the call can potentially
+; modify the global
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+ at heap = external global i32, align 4
+
+define i32 @build_tree() unnamed_addr {
+entry:
+  br label %do.body
+
+do.body:                                          ; preds = %do.body, %entry
+  %tmp9 = load i32, i32* @heap, align 4
+  %cmp = call i1 @pqdownheap(i32 %tmp9)
+  br i1 %cmp, label %do.body, label %do.end
+
+do.end:                                           ; preds = %do.body
+  %tmp20 = load i32, i32* @heap, align 4
+  ret i32 %tmp20
+}
+
+declare i1 @pqdownheap(i32)
+
+ at i = external hidden unnamed_addr global i32, align 4
+ at j = external hidden unnamed_addr global [573 x i32], align 4
+ at v = external global i1
+
+; CHECK-LABEL: test
+; CHECK-LABEL: do.end
+; CHECK: load
+; Check that the load is not hoisted because the call can potentially
+; modify the global
+
+define i32 @test() {
+entry:
+  br label %for.cond
+
+for.cond:
+  %a3 = load volatile i1, i1* @v
+  br i1 %a3, label %for.body, label %while.end
+
+for.body:
+  br label %if.then
+
+if.then:
+  %tmp4 = load i32, i32* @i, align 4
+  br label %for.cond
+
+while.end:
+  br label %do.body
+
+do.body:
+  %tmp9 = load i32, i32* getelementptr inbounds ([573 x i32], [573 x i32]* @j,
+i32 0, i32 1), align 4
+  %tmp10 = load i32, i32* @i, align 4
+  call void @fn()
+  %a1 = load volatile i1, i1* @v
+  br i1 %a1, label %do.body, label %do.end
+
+do.end:
+  %tmp20 = load i32, i32* getelementptr inbounds ([573 x i32], [573 x i32]* @j,
+i32 0, i32 1), align 4
+  ret i32 %tmp20
+}
+
+declare void @fn()

Added: llvm/trunk/test/Transforms/GVNHoist/pr36787.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr36787.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr36787.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr36787.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,76 @@
+; RUN: opt < %s -gvn-hoist -S | FileCheck %s
+
+ at g = external constant i8*
+
+declare i32 @gxx_personality(...)
+declare void @f0()
+declare void @f1()
+declare void @f2()
+
+; Make sure opt won't crash and that the load
+; is not hoisted from label6 to label4
+
+;CHECK-LABEL: @func
+
+define void @func() personality i8* bitcast (i32 (...)* @gxx_personality to i8*) {
+  invoke void @f0()
+          to label %3 unwind label %1
+
+1:
+  %2 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @g to i8*)
+          catch i8* null
+  br label %16
+
+3:
+  br i1 undef, label %4, label %10
+
+;CHECK:       4:
+;CHECK-NEXT:    %5 = load i32*, i32** undef, align 8
+;CHECK-NEXT:    invoke void @f1()
+
+4:
+  %5 = load i32*, i32** undef, align 8
+  invoke void @f1()
+          to label %6 unwind label %1
+
+;CHECK:       6:
+;CHECK-NEXT:    %7 = load i32*, i32** undef, align 8
+;CHECK-NEXT:    %8 = load i32*, i32** undef, align 8
+
+6:
+  %7 = load i32*, i32** undef, align 8
+  %8 = load i32*, i32** undef, align 8
+  br i1 true, label %9, label %17
+
+9:
+  invoke void @f0()
+          to label %10 unwind label %1
+
+10:
+  invoke void @f2()
+          to label %11 unwind label %1
+
+11:
+  %12 = invoke signext i32 undef(i32* null, i32 signext undef, i1 zeroext undef)
+          to label %13 unwind label %14
+
+13:
+  unreachable
+
+14:
+  %15 = landingpad { i8*, i32 }
+          catch i8* bitcast (i8** @g to i8*)
+          catch i8* null
+  br label %16
+
+16:
+  unreachable
+
+17:
+  ret void
+
+; uselistorder directives
+  uselistorder void ()* @f0, { 1, 0 }
+  uselistorder label %1, { 0, 3, 1, 2 }
+}

Added: llvm/trunk/test/Transforms/GVNHoist/pr37445.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr37445.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr37445.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr37445.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,119 @@
+; RUN: opt < %s -early-cse-memssa -gvn-hoist -S | FileCheck %s
+
+; Make sure opt won't crash and that this pair of
+; instructions (load, icmp) is hoisted successfully
+; from bb45 and bb58 to bb41.
+
+ at g_10 = external global i32, align 4
+ at g_536 = external global i8*, align 8
+ at g_1629 = external global i32**, align 8
+ at g_963 = external global i32**, align 8
+ at g_1276 = external global i32**, align 8
+
+;CHECK-LABEL: @func_22
+
+define void @func_22(i32* %arg, i32* %arg1) {
+bb:
+  br label %bb12
+
+bb12:
+  %tmp3.0 = phi i32 [ undef, %bb ], [ %tmp40, %bb36 ]
+  %tmp7.0 = phi i32 [ undef, %bb ], [ %spec.select, %bb36 ]
+  %tmp14 = icmp eq i32 %tmp3.0, 6
+  br i1 %tmp14, label %bb41, label %bb15
+
+bb15:
+  %tmp183 = trunc i16 0 to i8
+  %tmp20 = load i8*, i8** @g_536, align 8
+  %tmp21 = load i8, i8* %tmp20, align 1
+  %tmp23 = or i8 %tmp21, %tmp183
+  store i8 %tmp23, i8* %tmp20, align 1
+  %tmp5.i = icmp eq i8 %tmp23, 0
+  br i1 %tmp5.i, label %safe_div_func_uint8_t_u_u.exit, label %bb8.i
+
+bb8.i:
+  %0 = udiv i8 1, %tmp23
+  br label %safe_div_func_uint8_t_u_u.exit
+
+safe_div_func_uint8_t_u_u.exit:
+  %tmp13.in.i = phi i8 [ %0, %bb8.i ], [ 1, %bb15 ]
+  %tmp31 = icmp eq i8 %tmp13.in.i, 0
+  %spec.select = select i1 %tmp31, i32 %tmp7.0, i32 53
+  %tmp35 = icmp eq i32 %spec.select, 0
+  br i1 %tmp35, label %bb36, label %bb41
+
+bb36:
+  %tmp38 = sext i32 %tmp3.0 to i64
+  %tmp40 = trunc i64 %tmp38 to i32
+  br label %bb12
+
+;CHECK: bb41:
+;CHECK:   %tmp47 = load i32, i32* %arg1, align 4
+;CHECK:   %tmp48 = icmp eq i32 %tmp47, 0
+
+bb41:
+  %tmp43 = load i32, i32* %arg, align 4
+  %tmp44 = icmp eq i32 %tmp43, 0
+  br i1 %tmp44, label %bb52, label %bb45
+
+;CHECK:     bb45:
+;CHECK-NOT:   %tmp47 = load i32, i32* %arg1, align 4
+;CHECK-NOT:   %tmp48 = icmp eq i32 %tmp47, 0
+
+bb45:
+  %tmp47 = load i32, i32* %arg1, align 4
+  %tmp48 = icmp eq i32 %tmp47, 0
+  br i1 %tmp48, label %bb50, label %bb64
+
+bb50:
+  %tmp51 = load volatile i32**, i32*** @g_963, align 8
+  unreachable
+
+bb52:
+  %tmp8.0 = phi i32 [ undef, %bb41 ], [ %tmp57, %bb55 ]
+  %tmp54 = icmp slt i32 %tmp8.0, 3
+  br i1 %tmp54, label %bb55, label %bb58
+
+bb55:
+  %tmp57 = add nsw i32 %tmp8.0, 1
+  br label %bb52
+
+;CHECK:     bb58:
+;CHECK-NOT:   %tmp60 = load i32, i32* %arg1, align 4
+;CHECK-NOT:   %tmp61 = icmp eq i32 %tmp60, 0
+
+bb58:
+  %tmp60 = load i32, i32* %arg1, align 4
+  %tmp61 = icmp eq i32 %tmp60, 0
+  br i1 %tmp61, label %bb62, label %bb64
+
+bb62:
+  %tmp63 = load volatile i32**, i32*** @g_1276, align 8
+  unreachable
+
+bb64:
+  %tmp65 = load volatile i32**, i32*** @g_1629, align 8
+  unreachable
+
+; uselistorder directives
+  uselistorder i32 %spec.select, { 1, 0 }
+  uselistorder i32* %arg1, { 1, 0 }
+  uselistorder label %bb64, { 1, 0 }
+  uselistorder label %bb52, { 1, 0 }
+  uselistorder label %bb41, { 1, 0 }
+  uselistorder label %safe_div_func_uint8_t_u_u.exit, { 1, 0 }
+}
+
+define zeroext i8 @safe_div_func_uint8_t_u_u(i8 zeroext %arg, i8 zeroext %arg1) {
+bb:
+  %tmp5 = icmp eq i8 %arg1, 0
+  br i1 %tmp5, label %bb12, label %bb8
+
+bb8:
+  %0 = udiv i8 %arg, %arg1
+  br label %bb12
+
+bb12:
+  %tmp13.in = phi i8 [ %0, %bb8 ], [ %arg, %bb ]
+  ret i8 %tmp13.in
+}

Added: llvm/trunk/test/Transforms/GVNHoist/pr37808.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr37808.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr37808.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr37808.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,40 @@
+; RUN: opt < %s -gvn-hoist -S | FileCheck %s
+
+define void @func() {
+; CHECK-LABEL: @func()
+; CHECK:       bb6:
+; CHECK:         store i64 0, i64* undef, align 8
+; CHECK:       bb7:
+; CHECK-NOT:     store i64 0, i64* undef, align 8
+; CHECK:       bb8:
+; CHECK-NOT:     store i64 0, i64* undef, align 8
+
+entry:
+  br label %bb1
+
+bb1:
+  br label %bb2
+
+bb2:
+  br label %bb3
+
+bb3:
+  br i1 undef, label %bb4, label %bb2
+
+bb4:
+  br i1 undef, label %bb5, label %bb3
+
+bb5:
+  br label %bb6
+
+bb6:
+  br i1 undef, label %bb7, label %bb8
+
+bb7:
+  store i64 0, i64* undef, align 8
+  unreachable
+
+bb8:
+  store i64 0, i64* undef, align 8
+  ret void
+}

Added: llvm/trunk/test/Transforms/GVNHoist/pr38807.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr38807.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNHoist/pr38807.ll (added)
+++ llvm/trunk/test/Transforms/GVNHoist/pr38807.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,50 @@
+; RUN: opt < %s -early-cse-memssa -gvn-hoist -S | FileCheck %s
+
+; Make sure opt doesn't crash. On top of that, the instructions
+; of the side blocks should be hoisted to the entry block.
+
+%s = type { i32, i64 }
+%S = type { %s, i32 }
+
+;CHECK-LABEL: @foo
+
+define void @foo(i32* %arg) {
+bb0:
+  %0 = bitcast i32* %arg to %S*
+  %call.idx.i = getelementptr %S, %S* %0, i64 0, i32 0, i32 0
+  %call.idx.val.i = load i32, i32* %call.idx.i
+  br label %bb1
+
+;CHECK: bb1:
+;CHECK:   %call264 = call zeroext i1 @bar
+;CHECK:   store i32 %call.idx.val.i, i32* %call.idx.i
+;CHECK:   %1 = getelementptr inbounds %S, %S* %0, i64 0, i32 0, i32 1
+;CHECK:   store i64 undef, i64* %1
+;CHECK:   br i1 %call264, label %bb2, label %bb3
+
+bb1:
+  %call264 = call zeroext i1 @bar()
+  br i1 %call264, label %bb2, label %bb3
+
+;CHECK:     bb2:
+;CHECK-NOT:   store i32 %call.idx.val.i, i32* %call.idx.i
+;CHECK-NOT:   store i64 undef, i64* %{.*}
+
+bb2:
+  store i32 %call.idx.val.i, i32* %call.idx.i
+  %1 = getelementptr inbounds %S, %S* %0, i64 0, i32 0, i32 1
+  store i64 undef, i64* %1
+  ret void
+
+;CHECK:     bb3:
+;CHECK-NOT:   store i32 %call.idx.val.i, i32* %call.idx.i
+;CHECK-NOT:   store i64 undef, i64* %{.*}
+
+bb3:
+  store i32 %call.idx.val.i, i32* %call.idx.i
+  %2 = getelementptr inbounds %S, %S* %0, i64 0, i32 0, i32 1
+  store i64 undef, i64* %2
+  ret void
+}
+
+declare zeroext i1 @bar()

Added: llvm/trunk/test/Transforms/GVNSink/dither.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNSink/dither.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNSink/dither.ll (added)
+++ llvm/trunk/test/Transforms/GVNSink/dither.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,42 @@
+; RUN: opt < %s -S -gvn-sink | FileCheck %s
+
+; Because %tmp17 has flipped operands to its equivalents %tmp14 and %tmp7, we
+; can't sink the zext as we'd need a shuffling PHI in between.
+;
+; Just sinking the zext isn't profitable, so ensure nothing is sunk.
+
+; CHECK-LABEL: @hoge
+; CHECK-NOT: bb18.gvnsink.split
+define void @hoge() {
+bb:
+  br i1 undef, label %bb4, label %bb11
+
+bb4:                                              ; preds = %bb3
+  br i1 undef, label %bb6, label %bb8
+
+bb6:                                              ; preds = %bb5
+  %tmp = zext i16 undef to i64
+  %tmp7 = add i64 %tmp, undef
+  br label %bb18
+
+bb8:                                              ; preds = %bb5
+  %tmp9 = zext i16 undef to i64
+  br label %bb18
+
+bb11:                                             ; preds = %bb10
+  br i1 undef, label %bb12, label %bb15
+
+bb12:                                             ; preds = %bb11
+  %tmp13 = zext i16 undef to i64
+  %tmp14 = add i64 %tmp13, undef
+  br label %bb18
+
+bb15:                                             ; preds = %bb11
+  %tmp16 = zext i16 undef to i64
+  %tmp17 = add i64 undef, %tmp16
+  br label %bb18
+
+bb18:                                             ; preds = %bb15, %bb12, %bb8, %bb6
+  %tmp19 = phi i64 [ %tmp7, %bb6 ], [ undef, %bb8 ], [ %tmp14, %bb12 ], [ %tmp17, %bb15 ]
+  unreachable
+}

Added: llvm/trunk/test/Transforms/GVNSink/indirect-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNSink/indirect-call.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNSink/indirect-call.ll (added)
+++ llvm/trunk/test/Transforms/GVNSink/indirect-call.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,70 @@
+; RUN: opt < %s -gvn-sink -simplifycfg -simplifycfg-sink-common=false -S | FileCheck %s
+
+declare i8 @ext(i1)
+
+define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks, i8(i1)* %ext) {
+entry:
+  %cmp = icmp uge i32 %blksA, %nblks
+  br i1 %flag, label %if.then, label %if.else
+
+; CHECK-LABEL: test1
+; CHECK: call i8 @ext
+; CHECK: call i8 %ext
+if.then:
+  %frombool1 = call i8 @ext(i1 %cmp)
+  br label %if.end
+
+if.else:
+  %frombool3 = call i8 %ext(i1 %cmp)
+  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, i8(i1)* %ext) {
+entry:
+  %cmp = icmp uge i32 %blksA, %nblks
+  br i1 %flag, label %if.then, label %if.else
+
+; CHECK-LABEL: test2
+; CHECK: call i8 %ext
+; CHECK-NOT: call
+if.then:
+  %frombool1 = call i8 %ext(i1 %cmp)
+  br label %if.end
+
+if.else:
+  %frombool3 = call i8 %ext(i1 %cmp)
+  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 @test3(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks, i8(i1)* %ext1, i8(i1)* %ext2) {
+entry:
+  %cmp = icmp uge i32 %blksA, %nblks
+  br i1 %flag, label %if.then, label %if.else
+
+; CHECK-LABEL: test3
+; CHECK: %[[x:.*]] = select i1 %flag, i8 (i1)* %ext1, i8 (i1)* %ext2
+; CHECK: call i8 %[[x]](i1 %cmp)
+; CHECK-NOT: call
+if.then:
+  %frombool1 = call i8 %ext1(i1 %cmp)
+  br label %if.end
+
+if.else:
+  %frombool3 = call i8 %ext2(i1 %cmp)
+  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
+}

Added: llvm/trunk/test/Transforms/GVNSink/int_sideeffect.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNSink/int_sideeffect.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNSink/int_sideeffect.ll (added)
+++ llvm/trunk/test/Transforms/GVNSink/int_sideeffect.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt -S < %s -gvn-sink | FileCheck %s
+
+declare void @llvm.sideeffect()
+
+; GVN sinking across a @llvm.sideeffect.
+
+; CHECK-LABEL: scalarsSinking
+; CHECK-NOT: fmul
+; CHECK: = phi
+; CHECK: = fmul
+define float @scalarsSinking(float %d, float %m, float %a, i1 %cmp) {
+entry:
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+  call void @llvm.sideeffect()
+  %sub = fsub float %m, %a
+  %mul0 = fmul float %sub, %d
+  br label %if.end
+
+if.else:
+  %add = fadd float %m, %a
+  %mul1 = fmul float %add, %d
+  br label %if.end
+
+if.end:
+  %phi = phi float [ %mul0, %if.then ], [ %mul1, %if.else ]
+  ret float %phi
+}
+

Added: llvm/trunk/test/Transforms/GVNSink/sink-combine-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNSink/sink-combine-metadata.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNSink/sink-combine-metadata.ll (added)
+++ llvm/trunk/test/Transforms/GVNSink/sink-combine-metadata.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,55 @@
+; RUN: opt < %s -gvn-sink -S | FileCheck %s
+
+; Check that nonnull metadata for non-dominating loads is not propagated.
+; CHECK-LABEL: @test1(
+; CHECK-LABEL: if.end:
+; CHECK:  %[[ptr:.*]] = phi i32**
+; CHECK: %[[load:.*]] = load i32*, i32** %[[ptr]]
+; CHECK-NOT: !nonnull
+; CHECK: ret i32* %[[load]]
+define i32* @test1(i1 zeroext %flag, i32*** %p) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %a = load i32**, i32*** %p
+  %aa = load i32*, i32** %a, !nonnull !0
+  br label %if.end
+
+if.else:
+  %b = load i32**, i32*** %p
+  %bb= load i32*, i32** %b
+  br label %if.end
+
+if.end:
+  %c = phi i32* [ %aa, %if.then ], [ %bb, %if.else ]
+  ret i32* %c
+}
+
+; CHECK-LABEL: @test2(
+; CHECK-LABEL: if.end:
+; CHECK:  %[[ptr:.*]] = phi i32**
+; CHECK: %[[load:.*]] = load i32*, i32** %[[ptr]]
+; CHECK-NOT: !nonnull
+; CHECK: ret i32* %[[load]]
+define i32* @test2(i1 zeroext %flag, i32*** %p) {
+entry:
+  br i1 %flag, label %if.then, label %if.else
+
+if.then:
+  %a = load i32**, i32*** %p
+  %aa = load i32*, i32** %a
+  br label %if.end
+
+if.else:
+  %b = load i32**, i32*** %p
+  %bb= load i32*, i32** %b, !nonnull !0
+  br label %if.end
+
+if.end:
+  %c = phi i32* [ %aa, %if.then ], [ %bb, %if.else ]
+  ret i32* %c
+}
+
+
+!0 = !{}

Added: llvm/trunk/test/Transforms/GVNSink/sink-common-code.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNSink/sink-common-code.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNSink/sink-common-code.ll (added)
+++ llvm/trunk/test/Transforms/GVNSink/sink-common-code.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,697 @@
+; RUN: opt < %s -gvn-sink -simplifycfg -simplifycfg-sink-common=false -S | FileCheck %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
+
+; FIXME: The test failes when the original order of the
+; candidates with the same cost is preserved.
+;
+;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
+
+; 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: store volatile
+; CHECK: getelementptr
+; 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 !0
+; 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
+  br label %if.end
+
+if.end:
+  %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ]
+  ret i32 1
+}
+
+; 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, 56
+  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
+  %b1 = sext i8 %frombool1 to i32
+  %b2 = trunc i32 %b1 to i8
+  store i8 %b2, 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
+  %a1 = sext i8 %frombool3 to i32
+  %a2 = trunc i32 %a1 to i8
+  store i8 %a2, 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)
+  %a1 = sext i8 %frombool1 to i32
+  %a2 = trunc i32 %a1 to i8
+  br label %if.end
+
+if.then2:
+  %add = add i32 %nblks, %blksB
+  %cmp2 = icmp ule i32 %add, %blksA
+  %frombool3 = call i8 @i1toi8(i1 %cmp2)
+  %b1 = sext i8 %frombool3 to i32
+  %b2 = trunc i32 %b1 to i8
+  br label %if.end
+
+if.end:
+  %obeys.0 = phi i8 [ %a2, %if.then ], [ %b2, %if.then2 ], [ 0, %entry ]
+  %tobool4 = icmp ne i8 %obeys.0, 0
+  ret i1 %tobool4
+}
+declare i8 @i1toi8(i1)
+
+; FIXME: DISABLED - we don't consider this profitable. We should
+;  - Consider argument setup/return mov'ing for calls, like InlineCost does.
+;  - Consider the removal of the %obeys.0 PHI (zero PHI movement overall)
+
+; DISABLED-CHECK-LABEL: test17
+; DISABLED-CHECK: if.then:
+; DISABLED-CHECK-NEXT: icmp uge
+; DISABLED-CHECK-NEXT: br label %[[x:.*]]
+
+; DISABLED-CHECK: if.then2:
+; DISABLED-CHECK-NEXT: add
+; DISABLED-CHECK-NEXT: icmp ule
+; DISABLED-CHECK-NEXT: br label %[[x]]
+
+; DISABLED-CHECK: [[x]]:
+; DISABLED-CHECK-NEXT: %[[y:.*]] = phi i1 [ %cmp
+; DISABLED-CHECK-NEXT: %[[z:.*]] = call i8 @i1toi8(i1 %[[y]])
+; DISABLED-CHECK-NEXT: br label %if.end
+
+; DISABLED-CHECK: if.end:
+; DISABLED-CHECK-NEXT: phi i8
+; DISABLED-CHECK-DAG: [ %[[z]], %[[x]] ]
+; DISABLED-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
+
+; 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-NOT: 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: !0 = !{!1, !1, i64 0}
+; CHECK: !1 = !{!"float", !2}
+; CHECK: !2 = !{!"an example type tree"}

Added: llvm/trunk/test/Transforms/GVNSink/struct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNSink/struct.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GVNSink/struct.ll (added)
+++ llvm/trunk/test/Transforms/GVNSink/struct.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,71 @@
+; RUN: opt -gvn-sink -S < %s | FileCheck %s
+
+%struct = type {i32, i32}
+%struct2 = type { [ 2 x i32], i32 }
+
+; Struct indices cannot be variant.
+
+; CHECK-LABEL: @f() {
+; CHECK: getelementptr
+; CHECK: getelementptr
+define void @f() {
+bb:
+  br i1 undef, label %bb2, label %bb1
+
+bb1:                                              ; preds = %bb
+  %tmp = getelementptr inbounds %struct, %struct* null, i64 0, i32 1
+  br label %bb4
+
+bb2:                                              ; preds = %bb
+  %tmp3 = getelementptr inbounds %struct, %struct* null, i64 0, i32 0
+  br label %bb4
+
+bb4:                                              ; preds = %bb2, %bb1
+  %tmp5 = phi i32 [ 1, %bb1 ], [ 0, %bb2 ]
+  ret void
+}
+
+; Struct indices cannot be variant.
+
+; CHECK-LABEL: @g() {
+; CHECK: getelementptr
+; CHECK: getelementptr
+define void @g() {
+bb:
+  br i1 undef, label %bb2, label %bb1
+
+bb1:                                              ; preds = %bb
+  %tmp = getelementptr inbounds %struct2, %struct2* null, i64 0, i32 0, i32 1
+  br label %bb4
+
+bb2:                                              ; preds = %bb
+  %tmp3 = getelementptr inbounds %struct2, %struct2* null, i64 0, i32 0, i32 0
+  br label %bb4
+
+bb4:                                              ; preds = %bb2, %bb1
+  %tmp5 = phi i32 [ 1, %bb1 ], [ 0, %bb2 ]
+  ret void
+}
+
+
+; ... but the first parameter to a GEP can.
+
+; CHECK-LABEL: @h() {
+; CHECK: getelementptr
+; CHECK-NOT: getelementptr
+define void @h() {
+bb:
+  br i1 undef, label %bb2, label %bb1
+
+bb1:                                              ; preds = %bb
+  %tmp = getelementptr inbounds %struct, %struct* null, i32 0, i32 0
+  br label %bb4
+
+bb2:                                              ; preds = %bb
+  %tmp3 = getelementptr inbounds %struct, %struct* null, i32 1, i32 0
+  br label %bb4
+
+bb4:                                              ; preds = %bb2, %bb1
+  %tmp5 = phi i32 [ 0, %bb1 ], [ 1, %bb2 ]
+  ret void
+}
\ No newline at end of file

Added: llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-CastRef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-CastRef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-CastRef.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-CastRef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -globaldce
+;
+define internal void @func() {
+        ret void
+}
+
+define void @main() {
+        %X = bitcast void ()* @func to i32*             ; <i32*> [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-ConstantRef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-ConstantRef.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-ConstantRef.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2002-07-17-ConstantRef.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt < %s -globaldce
+;
+
+ at X = global void ()* @func              ; <void ()**> [#uses=0]
+
+; Not dead, can be reachable via X
+define internal void @func() {
+        ret void
+}
+
+define void @main() {
+        ret void
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-FunctionDGE.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-FunctionDGE.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-FunctionDGE.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-FunctionDGE.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; Make sure that functions are removed successfully if they are referred to by
+; a global that is dead.  Make sure any globals they refer to die as well.
+
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+; CHECK-NOT: foo
+;; Unused, kills %foo
+ at b = internal global i32 ()* @foo               ; <i32 ()**> [#uses=0]
+
+;; Should die when function %foo is killed
+ at foo.upgrd.1 = internal global i32 7            ; <i32*> [#uses=1]
+
+ ;; dies when %b dies.
+define internal i32 @foo() {
+        %ret = load i32, i32* @foo.upgrd.1           ; <i32> [#uses=1]
+        ret i32 %ret
+}
+

Added: llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-WorkListTest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-WorkListTest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-WorkListTest.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2002-08-17-WorkListTest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,14 @@
+; This testcase tests that a worklist is being used, and that globals can be 
+; removed if they are the subject of a constexpr and ConstantPointerRef
+
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+; CHECK-NOT: global
+
+ at t0 = internal global [4 x i8] c"foo\00"                ; <[4 x i8]*> [#uses=1]
+ at t1 = internal global [4 x i8] c"bar\00"                ; <[4 x i8]*> [#uses=1]
+ at s1 = internal global [1 x i8*] [ i8* getelementptr ([4 x i8], [4 x i8]* @t0, i32 0, i32 0) ]             ; <[1 x i8*]*> [#uses=0]
+ at s2 = internal global [1 x i8*] [ i8* getelementptr ([4 x i8], [4 x i8]* @t1, i64 0, i64 0) ]             ; <[1 x i8*]*> [#uses=0]
+ at b = internal global i32* @a            ; <i32**> [#uses=0]
+ at a = internal global i32 7              ; <i32*> [#uses=1]
+

Added: llvm/trunk/test/Transforms/GlobalDCE/2002-09-12-Redeletion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2002-09-12-Redeletion.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2002-09-12-Redeletion.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2002-09-12-Redeletion.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,11 @@
+; RUN: opt < %s -globaldce
+
+;; Should die when function %foo is killed
+ at foo.upgrd.1 = internal global i32 7            ; <i32*> [#uses=3]
+ at bar = internal global [2 x { i32*, i32 }] [ { i32*, i32 } { i32* @foo.upgrd.1, i32 7 }, { i32*, i32 } { i32* @foo.upgrd.1, i32 1 } ]            ; <[2 x { i32*, i32 }]*> [#uses=0]
+
+define internal i32 @foo() {
+        %ret = load i32, i32* @foo.upgrd.1           ; <i32> [#uses=1]
+        ret i32 %ret
+}
+

Added: llvm/trunk/test/Transforms/GlobalDCE/2003-07-01-SelfReference.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2003-07-01-SelfReference.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2003-07-01-SelfReference.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2003-07-01-SelfReference.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; distilled from 255.vortex
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+; CHECK-NOT: testfunc
+
+declare i1 ()* @getfunc()
+
+define internal i1 @testfunc() {
+        %F = call i1 ()* () @getfunc( )                ; <i1 ()*> [#uses=1]
+        %c = icmp eq i1 ()* %F, @testfunc               ; <i1> [#uses=1]
+        ret i1 %c
+}
+

Added: llvm/trunk/test/Transforms/GlobalDCE/2003-10-09-PreserveWeakGlobals.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2003-10-09-PreserveWeakGlobals.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2003-10-09-PreserveWeakGlobals.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2003-10-09-PreserveWeakGlobals.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,6 @@
+; Weak variables should be preserved by global DCE!
+
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+; CHECK: @A
+ at A = weak global i32 54

Added: llvm/trunk/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -globaldce -S > %t
+; RUN: FileCheck %s < %t
+; RUN: FileCheck --check-prefix=DEAD %s < %t
+
+ at A = global i32 0
+; CHECK: @A = global i32 0
+
+ at D = internal alias i32, i32* @A
+; DEAD-NOT: @D
+
+ at L1 = alias i32, i32* @A
+; CHECK: @L1 = alias i32, i32* @A
+
+ at L2 = internal alias i32, i32* @L1
+; CHECK: @L2 = internal alias i32, i32* @L1
+
+ at L3 = alias i32, i32* @L2
+; CHECK: @L3 = alias i32, i32* @L2

Added: llvm/trunk/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,4 @@
+; RUN: opt < %s -globaldce
+
+ at A = internal alias void (), void ()* @F
+define internal void @F() { ret void }

Added: llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/basicvariabletest.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,6 @@
+; RUN: opt < %s -passes=globaldce -S | FileCheck %s
+
+; CHECK-NOT: global
+ at X = external global i32
+ at Y = internal global i32 7
+

Added: llvm/trunk/test/Transforms/GlobalDCE/comdats.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/comdats.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/comdats.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/comdats.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,178 @@
+; Test the behavior of GlobalDCE in conjunction with comdats.
+;
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+; First test checks that if one function in a comdat group is used, both other
+; functions and other globals even if unused will be preserved.
+$test1_c = comdat any
+; CHECK: $test1_c = comdat any
+
+; Second test checks that if one function in a comdat group is used, both other
+; functions and other globals even if unused will be preserved.
+$test2_c = comdat any
+; CHECK: $test2_c = comdat any
+
+; Third test checks that calling a function in a comdat group with an alias
+; preserves the alias.
+$test3_c = comdat any
+; CHECK: $test3_c = comdat any
+
+; Fourth test checks that calling an alias in a comdat group with a function
+; preserves the function. (This is the trivial case as the alias uses the
+; function.)
+$test4_c = comdat any
+; CHECK: $test4_c = comdat any
+
+; Fifth test checks that calling a function in a comdat group that is used as
+; the resolver of an ifunc doesn't preserve that ifunc. ifunc symbols don't
+; participate in the comdat group of their resolver function as they are
+; considered separate objects.
+$test5_c = comdat any
+; CHECK: $test5_c = comdat any
+
+; Sixth test checks that calling an ifunc whose resolver is in a comdat group
+; preserves the resolver. This is the trivial case as the ifunc uses the
+; resolver.
+$test6_c = comdat any
+; CHECK: $test6_c = comdat any
+
+; Seventh test checks that we can eliminate a comdat when it has only one dead function participant.
+$test7_c = comdat any
+; CHECK-NOT: $test7_c = comdat any
+
+; Eighth test checks that we can eliminate a comdat when it has only one dead global participant.
+$test8_c = comdat any
+; CHECK-NOT: $test8_c = comdat any
+
+; Ninth test checks that we can eliminate a comdat when there are multiple
+; dead participants.
+$test9_c = comdat any
+; CHECK-NOT: $test9_c = comdat any
+
+; Tenth test checks that we can eliminate a comdat when it has multiple
+; participants that form internal cyclic uses but are never used externally and
+; thus the entire ifunc can safely be eliminated.
+$test10_c = comdat any
+; CHECK-NOT: $test10_c = comdat any
+
+ at test1_gv = linkonce_odr unnamed_addr global i32 42, comdat($test1_c)
+; CHECK: @test1_gv = linkonce_odr unnamed_addr global
+
+ at test2_used = linkonce_odr unnamed_addr global i32 42, comdat($test2_c)
+; CHECK: @test2_used = linkonce_odr unnamed_addr global
+
+ at test2_gv = linkonce_odr unnamed_addr global i32 42, comdat($test2_c)
+; CHECK: @test2_gv = linkonce_odr unnamed_addr global
+
+ at test8_gv = linkonce_odr unnamed_addr global i32 42, comdat($test8_c)
+; CHECK-NOT: @test8_gv
+
+ at test9_gv = linkonce_odr unnamed_addr global i32 42, comdat($test9_c)
+; CHECK-NOT: @test9_gv
+
+ at test10_gv = linkonce_odr unnamed_addr global void ()* @test10_f, comdat($test10_c)
+; CHECK-NOT: @test10_gv
+
+ at test3_a = linkonce_odr unnamed_addr alias void (), void ()* @test3_f
+; CHECK: @test3_a = linkonce_odr unnamed_addr alias
+
+ at test4_a = linkonce_odr unnamed_addr alias void (), void ()* @test4_f
+; CHECK: @test4_a = linkonce_odr unnamed_addr alias
+
+ at test10_a = linkonce_odr unnamed_addr alias void (), void ()* @test10_g
+; CHECK-NOT: @test10_a
+
+ at test5_if = linkonce_odr ifunc void (), void ()* ()* @test5_f
+; CHECK-NOT: @test5_if
+
+ at test6_if = linkonce_odr ifunc void (), void ()* ()* @test6_f
+; CHECK: @test6_if = linkonce_odr ifunc
+
+; This function is directly used and so cannot be eliminated.
+define linkonce_odr void @test1_used() comdat($test1_c) {
+; CHECK: define linkonce_odr void @test1_used()
+entry:
+  ret void
+}
+
+define linkonce_odr void @test1_f() comdat($test1_c) {
+; CHECK: define linkonce_odr void @test1_f()
+entry:
+  ret void
+}
+
+; Now test that a function, global variable, alias, and ifunc in the same
+; comdat are kept.
+define linkonce_odr void @test2_f() comdat($test2_c) {
+; CHECK: define linkonce_odr void @test2_f()
+entry:
+  ret void
+}
+
+define linkonce_odr void @test3_f() comdat($test3_c) {
+; CHECK: define linkonce_odr void @test3_f()
+entry:
+  ret void
+}
+
+define linkonce_odr void @test4_f() comdat($test4_c) {
+; CHECK: define linkonce_odr void @test4_f()
+entry:
+  ret void
+}
+
+declare void @test_external()
+
+define linkonce_odr void ()* @test5_f() comdat($test5_c) {
+; CHECK: define linkonce_odr void ()* @test5_f()
+entry:
+  ret void ()* @test_external
+}
+
+define linkonce_odr void ()* @test6_f() comdat($test6_c) {
+; CHECK: define linkonce_odr void ()* @test6_f()
+entry:
+  ret void ()* @test_external
+}
+
+define linkonce_odr void @test7_f() comdat($test7_c) {
+; CHECK-NOT: @test7_f
+entry:
+  ret void
+}
+
+define linkonce_odr void @test9_f() comdat($test9_c) {
+; CHECK-NOT: @test9_f
+entry:
+  ret void
+}
+
+define linkonce_odr void @test10_f() comdat($test10_c) {
+; CHECK-NOT: @test10_f
+entry:
+  %gv = load void ()*, void ()** @test10_gv
+  call void @test10_a()
+  ret void
+}
+
+define linkonce_odr void @test10_g() comdat($test10_c) {
+; CHECK-NOT: @test10_g
+entry:
+  call void @test10_f()
+  ret void
+}
+
+
+; An external function to pin as "used" various things above that shouldn't be
+; eliminated.
+define void @external_user() {
+  call void @test1_used()
+  %gv = load i32, i32* @test2_used
+
+  call void @test3_f()
+  call void @test4_a()
+
+  %fptr = call void() *@test5_f()
+  call void @test6_if()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/complex-constantexpr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/complex-constantexpr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/complex-constantexpr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/complex-constantexpr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,97 @@
+; RUN: opt -O2 -disable-output < %s
+; PR15714
+
+%struct.ham = type { i32 }
+
+ at global5 = common global i32 0, align 4
+ at global6 = common global i32 0, align 4
+ at global7 = common global i32 0, align 4
+ at global = common global i32 0, align 4
+ at global8 = common global %struct.ham zeroinitializer, align 4
+ at global9 = common global i32 0, align 4
+ at global10 = common global i32 0, align 4
+ at global11 = common global i32 0, align 4
+
+define void @zot12() {
+bb:
+  store i32 0, i32* @global5, align 4
+  store i32 0, i32* @global6, align 4
+  br label %bb2
+
+bb1:                                              ; preds = %bb11
+  %tmp = load i32, i32* @global5, align 4
+  br label %bb2
+
+bb2:                                              ; preds = %bb1, %bb
+  %tmp3 = phi i32 [ %tmp, %bb1 ], [ 0, %bb ]
+  %tmp4 = xor i32 %tmp3, zext (i1 icmp ne (i64 ptrtoint (i32* @global5 to i64), i64 1) to i32)
+  store i32 %tmp4, i32* @global5, align 4
+  %tmp5 = icmp eq i32 %tmp3, zext (i1 icmp ne (i64 ptrtoint (i32* @global5 to i64), i64 1) to i32)
+  br i1 %tmp5, label %bb8, label %bb6
+
+bb6:                                              ; preds = %bb2
+  %tmp7 = tail call i32 @quux13()
+  br label %bb8
+
+bb8:                                              ; preds = %bb6, %bb2
+  %tmp9 = load i32, i32* @global7, align 4
+  %tmp10 = icmp eq i32 %tmp9, 0
+  br i1 %tmp10, label %bb11, label %bb15
+
+bb11:                                             ; preds = %bb8
+  %tmp12 = load i32, i32* @global6, align 4
+  %tmp13 = add nsw i32 %tmp12, 1
+  store i32 %tmp13, i32* @global6, align 4
+  %tmp14 = icmp slt i32 %tmp13, 42
+  br i1 %tmp14, label %bb1, label %bb15
+
+bb15:                                             ; preds = %bb11, %bb8
+  ret void
+}
+
+define i32 @quux13() {
+bb:
+  store i32 1, i32* @global5, align 4
+  ret i32 1
+}
+
+define void @wombat() {
+bb:
+  tail call void @zot12()
+  ret void
+}
+
+define void @wombat14() {
+bb:
+  tail call void @blam()
+  ret void
+}
+
+define void @blam() {
+bb:
+  store i32 ptrtoint (i32* @global to i32), i32* getelementptr inbounds (%struct.ham, %struct.ham* @global8, i64 0, i32 0), align 4
+  store i32 0, i32* @global9, align 4
+  %tmp = load i32, i32* getelementptr inbounds (%struct.ham, %struct.ham* @global8, i64 0, i32 0), align 4
+  br label %bb1
+
+bb1:                                              ; preds = %bb1, %bb
+  %tmp2 = phi i32 [ 0, %bb ], [ %tmp11, %bb1 ]
+  %tmp3 = phi i32 [ %tmp, %bb ], [ %tmp10, %bb1 ]
+  %tmp4 = icmp sgt i32 %tmp3, 0
+  %tmp5 = zext i1 %tmp4 to i32
+  %tmp6 = urem i32 %tmp5, 5
+  %tmp7 = mul i32 %tmp3, -80
+  %tmp8 = or i32 %tmp7, %tmp6
+  %tmp9 = icmp eq i32 %tmp8, 0
+  %tmp10 = zext i1 %tmp9 to i32
+  %tmp11 = add nsw i32 %tmp2, 1
+  %tmp12 = icmp eq i32 %tmp11, 20
+  br i1 %tmp12, label %bb13, label %bb1
+
+bb13:                                             ; preds = %bb1
+  store i32 %tmp10, i32* getelementptr inbounds (%struct.ham, %struct.ham* @global8, i64 0, i32 0), align 4
+  store i32 0, i32* @global10, align 4
+  store i32 %tmp6, i32* @global11, align 4
+  store i32 20, i32* @global9, align 4
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/crash-assertingvh.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; Make sure that if a pass like jump threading populates a function analysis
+; like LVI with asserting handles into the body of a function, those don't begin
+; to assert when global DCE deletes the body of the function.
+;
+; RUN: opt -disable-output < %s -passes='module(function(jump-threading),globaldce)'
+; RUN: opt -disable-output < %s -passes='module(rpo-functionattrs,globaldce)'
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare i32 @bar()
+
+define internal i32 @foo() {
+entry:
+  %call4 = call i32 @bar()
+  %cmp5 = icmp eq i32 %call4, 0
+  br i1 %cmp5, label %if.then6, label %if.end8
+
+if.then6:
+  ret i32 0
+
+if.end8:
+  ret i32 1
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/deadblockaddr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/deadblockaddr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/deadblockaddr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/deadblockaddr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,16 @@
+; RUN: opt -globaldce -simplifycfg -S < %s | FileCheck %s
+
+; Tests whether globaldce does the right cleanup while removing @bar
+; so that a dead BlockAddress reference to foo won't prevent other passes
+; to work properly, e.g. simplifycfg
+ at bar = internal unnamed_addr constant i8* blockaddress(@foo, %L1)
+
+; CHECK-LABEL: foo
+; CHECK-NOT: br label %L1
+; CHECK: ret void
+define void @foo() {
+entry:
+  br label %L1
+L1:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/externally_available.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,21 @@
+; RUN: opt < %s -globaldce -S | FileCheck %s
+
+; test_global should not be emitted to the .s file.
+; CHECK-NOT: @test_global =
+ at test_global = available_externally global i32 4
+
+; test_global2 is a normal global using an available externally function.
+; CHECK: @test_global2 =
+ at test_global2 = global i32 ()* @test_function2
+
+; test_function should not be emitted to the .s file.
+; CHECK-NOT: define {{.*}} @test_function()
+define available_externally i32 @test_function() {
+  ret i32 4
+}
+
+; test_function2 isn't actually dead even though it's available externally.
+; CHECK: define available_externally i32 @test_function2()
+define available_externally i32 @test_function2() {
+  ret i32 4
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/global-ifunc.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,13 @@
+; RUN: opt -S -globaldce < %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 if = ifunc void (), void ()* @fn
+
+define internal void @fn() {
+entry:
+  ret void
+}
+
+; CHECK-DAG: @if = ifunc void (), void ()* @fn
+; CHECK-DAG: define internal void @fn(

Added: llvm/trunk/test/Transforms/GlobalDCE/global_ctors.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/global_ctors.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/global_ctors.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/global_ctors.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,37 @@
+; RUN: opt -S -globaldce < %s | FileCheck %s
+
+; Test that the presence of debug intrinsics isn't affecting GlobalDCE.
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_notremovable }]
+; CHECK-NOT: @_GLOBAL__I_a
+
+declare void @_notremovable()
+
+ at llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_b }, { i32, void ()* } { i32 65535, void ()* @_notremovable }]
+
+ at x = internal unnamed_addr constant i8 undef, align 1
+
+; Function Attrs: nounwind readnone
+define internal void @_GLOBAL__I_a() #1 section "__TEXT,__StaticInit,regular,pure_instructions" {
+entry:
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+define internal void @_GLOBAL__I_b() #1 section "__TEXT,__StaticInit,regular,pure_instructions" {
+entry:
+  tail call void @llvm.dbg.value(metadata i8* @x, metadata !4, metadata !DIExpression(DW_OP_deref, DW_OP_constu, 0, DW_OP_swap, DW_OP_xderef)), !dbg !5
+  ret void
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!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, emissionKind: FullDebug)
+!2 = !DIFile(filename: "filename", directory: "directory")
+!3 = distinct !DISubprogram(name: "h1", unit: !1)
+!4 = !DILocalVariable(name: "b", arg: 1, scope: !3)
+!5 = !DILocation(scope: !3)

Added: llvm/trunk/test/Transforms/GlobalDCE/global_ctors_integration.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/global_ctors_integration.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/global_ctors_integration.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/global_ctors_integration.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,45 @@
+; RUN: opt -S -O2 < %s | FileCheck %s
+
+; This test checks that -O2 is able to delete constructors that become empty
+; only after some optimization passes have run, even if the pass structure
+; changes.
+; CHECK-NOT: @_GLOBAL__I_a
+
+%class.Foo = type { i32 }
+
+ at foo = global %class.Foo zeroinitializer, align 4
+ at _ZN3Bar18LINKER_INITIALIZEDE = external constant i32
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
+define internal void @__cxx_global_var_init() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  %1 = load i32, i32* @_ZN3Bar18LINKER_INITIALIZEDE, align 4
+  call void @_ZN3FooC1E17LinkerInitialized(%class.Foo* @foo, i32 %1)
+  ret void
+}
+
+; Function Attrs: ssp uwtable
+define linkonce_odr void @_ZN3FooC1E17LinkerInitialized(%class.Foo* %this, i32) unnamed_addr #0 align 2 {
+  %2 = alloca %class.Foo*, align 8
+  %3 = alloca i32, align 4
+  store %class.Foo* %this, %class.Foo** %2, align 8
+  store i32 %0, i32* %3, align 4
+  %4 = load %class.Foo*, %class.Foo** %2
+  %5 = load i32, i32* %3, align 4
+  call void @_ZN3FooC2E17LinkerInitialized(%class.Foo* %4, i32 %5)
+  ret void
+}
+
+; Function Attrs: nounwind ssp uwtable
+define linkonce_odr void @_ZN3FooC2E17LinkerInitialized(%class.Foo* %this, i32) unnamed_addr #1 align 2 {
+  %2 = alloca %class.Foo*, align 8
+  %3 = alloca i32, align 4
+  store %class.Foo* %this, %class.Foo** %2, align 8
+  store i32 %0, i32* %3, align 4
+  %4 = load %class.Foo*, %class.Foo** %2
+  ret void
+}
+
+define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
+  call void @__cxx_global_var_init()
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalDCE/indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalDCE/indirectbr.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalDCE/indirectbr.ll (added)
+++ llvm/trunk/test/Transforms/GlobalDCE/indirectbr.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt -S -globaldce < %s | FileCheck %s
+
+ at L = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@test1, %L1), i8* blockaddress(@test1, %L2), i8* null], align 16
+
+; CHECK: @L = internal unnamed_addr constant
+
+define void @test1(i32 %idx) {
+entry:
+  br label %L1
+
+L1:
+  %arrayidx = getelementptr inbounds [3 x i8*], [3 x i8*]* @L, i32 0, i32 %idx
+  %l = load i8*, i8** %arrayidx
+  indirectbr i8* %l, [label %L1, label %L2]
+
+L2:
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/alignment-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,22 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; This produces align 4, not the obvious align 1, to be consistent with what
+; the AsmPrinter would do.
+; CHECK: @_MergedGlobals = private global <{ [2 x i32], [2 x i32] }> <{ [2 x i32] [i32 1, i32 1], [2 x i32] [i32 2, i32 2] }>, align 4
+
+; CHECK: @a = internal alias [2 x i32], getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 0)
+ at a = internal global [2 x i32] [i32 1, i32 1], align 1
+
+; CHECK: @b = internal alias [2 x i32], getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 1)
+ at b = internal global [2 x i32] [i32 2, i32 2], align 1
+
+define void @use() {
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 0, i32 0)
+  %x = load i32, i32* bitcast ([2 x i32]* @a to i32*)
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ [2 x i32], [2 x i32] }>, <{ [2 x i32], [2 x i32] }>* @_MergedGlobals, i32 0, i32 1, i32 0)
+  %y = load i32, i32* bitcast ([2 x i32]* @b to i32*)
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalMerge/alignment.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/alignment.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/alignment.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/alignment.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,20 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @_MergedGlobals = private global <{ [5 x i8], [3 x i8], [2 x i32] }> <{ [5 x i8] c"\01\01\01\01\01", [3 x i8] zeroinitializer, [2 x i32] [i32 2, i32 2] }>, align 4
+
+; CHECK: @a = internal alias [5 x i8], getelementptr inbounds (<{ [5 x i8], [3 x i8], [2 x i32] }>, <{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals, i32 0, i32 0)
+ at a = internal global [5 x i8] [i8 1, i8 1, i8 1, i8 1, i8 1], align 4
+
+; CHECK: @b = internal alias [2 x i32], getelementptr inbounds (<{ [5 x i8], [3 x i8], [2 x i32] }>, <{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals, i32 0, i32 2)
+ at b = internal global [2 x i32] [i32 2, i32 2]
+
+define void @use() {
+  ; CHECK: load i32, i32* bitcast (<{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals to i32*)
+  %x = load i32, i32* bitcast ([5 x i8]* @a to i32*)
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ [5 x i8], [3 x i8], [2 x i32] }>, <{ [5 x i8], [3 x i8], [2 x i32] }>* @_MergedGlobals, i32 0, i32 2, i32 0)
+  %y = load i32, i32* bitcast ([2 x i32]* @b to i32*)
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalMerge/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/basic.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/basic.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/basic.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,31 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 3, i32 4 }>, section "foo", align 4
+; CHECK: @_MergedGlobals.1 = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4
+
+; CHECK-DAG: @a = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals.1, i32 0, i32 0)
+ at a = internal global i32 1
+
+; CHECK-DAG: @b = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals.1, i32 0, i32 1)
+ at b = internal global i32 2
+
+; CHECK-DAG: @c = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0)
+ at c = internal global i32 3, section "foo"
+
+; CHECK-DAG: @d = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1)
+ at d = internal global i32 4, section "foo"
+
+define void @use() {
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals.1, i32 0, i32 0)
+  %x = load i32, i32* @a
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals.1, i32 0, i32 1)
+  %y = load i32, i32* @b
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0)
+  %z1 = load i32, i32* @c
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1)
+  %z2 = load i32, i32* @d
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/debug-info.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+source_filename = "test/Transforms/GlobalMerge/debug-info.ll"
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4, !dbg [[A:![0-9]+]], !dbg [[B:![0-9]+]]
+
+ at a = internal global i32 1, !dbg !0
+ at b = internal global i32 2, !dbg !2
+
+define void @use1() {
+  %x = load i32, i32* @a
+  %y = load i32, i32* @b
+  ret void
+}
+; CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AVAR:![0-9]+]], expr: !DIExpression())
+; CHECK: [[AVAR]] = !DIGlobalVariable(name: "a", scope: null, type: !2, isLocal: false, isDefinition: true)
+; CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BVAR:![0-9]+]], expr: !DIExpression(DW_OP_plus_uconst, 4))
+; CHECK: [[BVAR]] = !DIGlobalVariable(name: "b", scope: null, type: !2, isLocal: false, isDefinition: true)
+
+!llvm.module.flags = !{!4, !5}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = !DIGlobalVariable(name: "a", scope: null, type: !6, isLocal: false, isDefinition: true)
+!2 = !DIGlobalVariableExpression(var: !3, expr: !DIExpression())
+!3 = !DIGlobalVariable(name: "b", scope: null, type: !6, isLocal: false, isDefinition: true)
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 2, !"Dwarf Version", i32 4}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

Added: llvm/trunk/test/Transforms/GlobalMerge/used.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalMerge/used.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalMerge/used.ll (added)
+++ llvm/trunk/test/Transforms/GlobalMerge/used.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,29 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 3, i32 3 }>, align 4
+
+ at a = internal global i32 1
+
+ at b = internal global i32 2
+
+ at c = internal global i32 3
+
+ at d = internal global i32 3
+
+ at llvm.used = appending global [1 x i8*] [i8* bitcast (i32* @a to i8*)], section "llvm.metadata"
+ at llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (i32* @b to i8*)], section "llvm.metadata"
+
+define void @use() {
+  ; CHECK: load i32, i32* @a
+  %x = load i32, i32* @a
+  ; CHECK: load i32, i32* @b
+  %y = load i32, i32* @b
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0)
+  %z1 = load i32, i32* @c
+  ; CHECK: load i32, i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1)
+  %z2 = load i32, i32* @d
+  ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2004-10-10-CastStoreOnce.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2004-10-10-CastStoreOnce.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2004-10-10-CastStoreOnce.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2004-10-10-CastStoreOnce.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,17 @@
+; RUN: opt < %s -globalopt
+
+ at V = global float 1.200000e+01          ; <float*> [#uses=1]
+ at G = internal global i32* null          ; <i32**> [#uses=2]
+
+define i32 @user() {
+        %P = load i32*, i32** @G              ; <i32*> [#uses=1]
+        %Q = load i32, i32* %P               ; <i32> [#uses=1]
+        ret i32 %Q
+}
+
+define void @setter() {
+        %Vi = bitcast float* @V to i32*         ; <i32*> [#uses=1]
+        store i32* %Vi, i32** @G
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2005-06-15-LocalizeConstExprCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2005-06-15-LocalizeConstExprCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2005-06-15-LocalizeConstExprCrash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2005-06-15-LocalizeConstExprCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -globalopt -disable-output
+; PR579
+
+ at g_40507551 = internal global i16 31038         ; <i16*> [#uses=1]
+
+define void @main() {
+        %tmp.4.i.1 = load i8, i8* getelementptr (i8, i8* bitcast (i16* @g_40507551 to i8*), i32 1)              ; <i8> [#uses=0]
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2005-09-27-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2005-09-27-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2005-09-27-Crash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2005-09-27-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,27 @@
+; RUN: opt < %s -globalopt -disable-output
+        %RPyString = type { i32, %arraytype.Char }
+        %arraytype.Char = type { i32, [0 x i8] }
+        %arraytype.Signed = type { i32, [0 x i32] }
+        %functiontype.1 = type { %RPyString* (i32) *} 
+        %structtype.test = type { i32, %arraytype.Signed }
+ at structinstance.test = internal global { i32, { i32, [2 x i32] } } { i32 41, { i32, [2 x i32] } { i32 2, [2 x i32] [ i32 100, i32 101 ] } }              ; <{ i32, { i32, [2 x i32] } }*> [#uses=1]
+
+define fastcc void @pypy_array_constant() {
+block0:
+        %tmp.9 = getelementptr %structtype.test, %structtype.test* bitcast ({ i32, { i32, [2 x i32] } }* @structinstance.test to %structtype.test*), i32 0, i32 0          ; <i32*> [#uses=0]
+        ret void
+}
+
+define fastcc void @new.varsizestruct.rpy_string() {
+        unreachable
+}
+
+define void @__entrypoint__pypy_array_constant() {
+        call fastcc void @pypy_array_constant( )
+        ret void
+}
+
+define void @__entrypoint__raised_LLVMException() {
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2006-07-07-InlineAsmCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2006-07-07-InlineAsmCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2006-07-07-InlineAsmCrash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2006-07-07-InlineAsmCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,135 @@
+; RUN: opt < %s -globalopt -disable-output
+; PR820
+target datalayout = "e-p:32:32"
+target triple = "i686-pc-linux-gnu"
+	%struct..0FileDescriptor = type { i32 }
+	%"struct.FlagDescription<int32>" = type { i8*, i32*, i1, i1, i32, i8* }
+	%"struct.FlagRegisterer<bool>" = type { i8 }
+	%struct.MutexLock = type { %struct..0FileDescriptor* }
+	%"struct.std::DisabledRangeMap" = type { %"struct.std::_Rb_tree<const char*,std::pair<const char* const, FlagDescription<bool> >,std::_Select1st<std::pair<const char* const, FlagDescription<bool> > >,StringCmp,std::allocator<std::pair<const char* const, FlagDescription<bool> > > >" }
+	%"struct.std::_Rb_tree<const char*,std::pair<const char* const, FlagDescription<bool> >,std::_Select1st<std::pair<const char* const, FlagDescription<bool> > >,StringCmp,std::allocator<std::pair<const char* const, FlagDescription<bool> > > >" = type { %"struct.std::_Rb_tree<const char*,std::pair<const char* const, FlagDescription<bool> >,std::_Select1st<std::pair<const char* const, FlagDescription<bool> > >,StringCmp,std::allocator<std::pair<const char* const, FlagDescription<bool> > > >::_Rb_tree_impl<StringCmp,false>" }
+	%"struct.std::_Rb_tree<const char*,std::pair<const char* const, FlagDescription<bool> >,std::_Select1st<std::pair<const char* const, FlagDescription<bool> > >,StringCmp,std::allocator<std::pair<const char* const, FlagDescription<bool> > > >::_Rb_tree_impl<StringCmp,false>" = type { %"struct.FlagRegisterer<bool>", %"struct.std::_Rb_tree_node_base", i32 }
+	%"struct.std::_Rb_tree_const_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >" = type { %"struct.std::_Rb_tree_node_base"* }
+	%"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
+	%"struct.std::_Vector_base<int,std::allocator<int> >" = type { %"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl" }
+	%"struct.std::_Vector_base<int,std::allocator<int> >::_Vector_impl" = type { i32*, i32*, i32* }
+	%"struct.std::vector<int,std::allocator<int> >" = type { %"struct.std::_Vector_base<int,std::allocator<int> >" }
+ at registry_lock = external global %struct..0FileDescriptor		; <%struct..0FileDescriptor*> [#uses=0]
+ at _ZN61FLAG__foo_int32_44FLAGS_E = external global %"struct.FlagRegisterer<bool>"		; <%"struct.FlagRegisterer<bool>"*> [#uses=0]
+ at llvm.global_ctors = appending global [20 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_10FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN60FLAG__foo_bool_19FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZNK5Bzh4Enum13is_contiguousEv }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_21FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN7ScannerC2Ev }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__Z11StripStringPSsPKcc }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZNK9__gnu_cxx4hashI11StringPieceEclERKS1_ }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN8Hasher325ResetEj }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__Z25ACLRv }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int64_25FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_7FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_18FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_25FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_eventbuf }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN61FLAG__foo_int32_26FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN62FLAG__foo_string_16FLAGS_E }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN17InitializerC2EPKcS1_PFvvE }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__checker_bcad_variable } ]		; <[20 x { i32, void ()* }]*> [#uses=0]
+
+declare void @_GLOBAL__I__ZN62FLAG__foo_string_10FLAGS_E()
+
+declare void @_GLOBAL__I__ZN60FLAG__foo_bool_19FLAGS_E()
+
+declare void @_GLOBAL__I__ZNK5Bzh4Enum13is_contiguousEv()
+
+declare void @_GLOBAL__I__ZN62FLAG__foo_string_17FLAGS_E()
+
+declare void @_GLOBAL__I__ZN61FLAG__foo_int32_21FLAGS_E()
+
+define void @_ZN14FlagRegistererIiEC1EPKcRK15FlagDescriptionIiE() {
+entry:
+	call void @_Z12RegisterFlagIiEvPKcRK15FlagDescriptionIT_E( )
+	ret void
+}
+
+define void @_Z12RegisterFlagIiEvPKcRK15FlagDescriptionIT_E() {
+entry:
+	call void @_ZN9MutexLockC1EP5Mutex( )
+	ret void
+}
+
+declare void @_GLOBAL__I__ZN7ScannerC2Ev()
+
+declare void @_GLOBAL__I__Z11StripStringPSsPKcc()
+
+define void @_ZNSt6vectorIiSaIiEEC1ERKS0_() {
+entry:
+	unreachable
+}
+
+declare void @_GLOBAL__I__ZNK9__gnu_cxx4hashI11StringPieceEclERKS1_()
+
+declare void @_GLOBAL__I__ZN8Hasher325ResetEj()
+
+declare void @_GLOBAL__I__Z25ACLRv()
+
+define void @_ZN9MutexLockC1EP5Mutex() {
+entry:
+	call void @_ZN5Mutex4LockEv( )
+	ret void
+}
+
+define void @_ZN5Mutex4LockEv() {
+entry:
+	call void @_Z22Acquire_CASPViii( )
+	ret void
+}
+
+define void @_ZNSt3mapIPKc15FlagDescriptionIiE9StringCmpSaISt4pairIKS1_S3_EEE3endEv(%"struct.std::_Rb_tree_const_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >"* sret  %agg.result) {
+entry:
+	unreachable
+}
+
+declare void @_GLOBAL__I__ZN61FLAG__foo_int64_25FLAGS_E()
+
+define void @_Z14CASPViii() {
+entry:
+	%tmp3 = call i32 asm sideeffect "lock; cmpxchg $1,$2", "={ax},q,m,0,~{dirflag},~{fpsr},~{flags},~{memory}"( i32 0, i32* null, i32 0 )		; <i32> [#uses=0]
+	unreachable
+}
+
+declare void @_GLOBAL__I__ZN61FLAG__foo_int32_7FLAGS_E()
+
+declare void @_GLOBAL__I__ZN62FLAG__foo_string_18FLAGS_E()
+
+define void @_Z22Acquire_CASPViii() {
+entry:
+	call void @_Z14CASPViii( )
+	unreachable
+}
+
+declare void @_GLOBAL__I__ZN61FLAG__foo_int32_25FLAGS_E()
+
+declare void @_GLOBAL__I_eventbuf()
+
+define void @_GLOBAL__I__ZN61FLAG__foo_int32_26FLAGS_E() {
+entry:
+	call void @_Z41__static_initialization_and_destruction_0ii1662( i32 1, i32 65535 )
+	ret void
+}
+
+define void @_Z41__static_initialization_and_destruction_0ii1662(i32 %__initialize_p, i32 %__priority) {
+entry:
+	%__initialize_p_addr = alloca i32		; <i32*> [#uses=2]
+	%__priority_addr = alloca i32		; <i32*> [#uses=2]
+	store i32 %__initialize_p, i32* %__initialize_p_addr
+	store i32 %__priority, i32* %__priority_addr
+	%tmp = load i32, i32* %__priority_addr		; <i32> [#uses=1]
+	%tmp.upgrd.1 = icmp eq i32 %tmp, 65535		; <i1> [#uses=1]
+	br i1 %tmp.upgrd.1, label %cond_true, label %cond_next14
+
+cond_true:		; preds = %entry
+	%tmp8 = load i32, i32* %__initialize_p_addr		; <i32> [#uses=1]
+	%tmp9 = icmp eq i32 %tmp8, 1		; <i1> [#uses=1]
+	br i1 %tmp9, label %cond_true10, label %cond_next14
+
+cond_true10:		; preds = %cond_true
+	call void @_ZN14FlagRegistererIiEC1EPKcRK15FlagDescriptionIiE( )
+	ret void
+
+cond_next14:		; preds = %cond_true, %entry
+	ret void
+}
+
+declare void @_GLOBAL__I__ZN62FLAG__foo_string_16FLAGS_E()
+
+define void @_ZN9__gnu_cxx13new_allocatorIPNS_15_Hashtable_nodeIjEEEC2Ev() {
+entry:
+	unreachable
+}
+
+declare void @_GLOBAL__I__ZN17InitializerC2EPKcS1_PFvvE()
+
+declare void @_GLOBAL__I__checker_bcad_variable()

Added: llvm/trunk/test/Transforms/GlobalOpt/2006-11-01-ShrinkGlobalPhiCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2006-11-01-ShrinkGlobalPhiCrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2006-11-01-ShrinkGlobalPhiCrash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2006-11-01-ShrinkGlobalPhiCrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,33 @@
+; RUN: opt < %s -globalopt -disable-output
+
+        %struct._list = type { i32*, %struct._list* }
+        %struct._play = type { i32, i32*, %struct._list*, %struct._play* }
+ at nrow = internal global i32 0           ; <i32*> [#uses=2]
+
+define void @make_play() {
+entry:
+        br label %cond_true16.i
+
+cond_true16.i:          ; preds = %cond_true16.i, %entry
+        %low.0.in.i.0 = phi i32* [ @nrow, %entry ], [ null, %cond_true16.i ]            ; <i32*> [#uses=1]
+        %low.0.i = load i32, i32* %low.0.in.i.0              ; <i32> [#uses=0]
+        br label %cond_true16.i
+}
+
+define void @make_wanted() {
+entry:
+        unreachable
+}
+
+define void @get_good_move() {
+entry:
+        ret void
+}
+
+define void @main() {
+entry:
+        store i32 8, i32* @nrow
+        tail call void @make_play( )
+        ret void
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2007-04-05-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2007-04-05-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2007-04-05-Crash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2007-04-05-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; RUN: opt < %s -globalopt -disable-output
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32"
+target triple = "thumb-apple-darwin8"
+ at replacementUnichar = internal global i16 -3		; <i16*> [#uses=2]
+@"L_OBJC_IMAGE_INFO" = internal global [2 x i32] zeroinitializer		; <[2 x i32]*> [#uses=1]
+ at llvm.used = appending global [1 x i8*] [ i8* bitcast ([2 x i32]* @"L_OBJC_IMAGE_INFO" to i8*) ]		; <[1 x i8*]*> [#uses=0]
+
+define zeroext i16 @__NSCharToUnicharCFWrapper(i8 zeroext  %ch)   {
+entry:
+	%iftmp.0.0.in.in = select i1 false, i16* @replacementUnichar, i16* null		; <i16*> [#uses=1]
+	%iftmp.0.0.in = load i16, i16* %iftmp.0.0.in.in		; <i16> [#uses=1]
+	ret i16 %iftmp.0.0.in
+}
+
+define void @__NSASCIICharToUnichar() {
+entry:
+	ret void
+}
+
+define void @_NSDefaultCStringEncoding() {
+entry:
+	call void @__NSSetCStringCharToUnichar( )
+	br i1 false, label %cond_true6, label %cond_next8
+
+cond_true6:		; preds = %entry
+	store i16 -2, i16* @replacementUnichar
+	ret void
+
+cond_next8:		; preds = %entry
+	ret void
+}
+
+declare void @__NSSetCStringCharToUnichar()

Added: llvm/trunk/test/Transforms/GlobalOpt/2007-05-13-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2007-05-13-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2007-05-13-Crash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2007-05-13-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,74 @@
+; RUN: opt < %s  -globalopt -disable-output
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
+target triple = "i686-apple-darwin8"
+        %struct.SFLMutableListItem = type { i16 }
+        %struct.__CFDictionary = type opaque
+        %struct.__CFString = type opaque
+        %struct.__builtin_CFString = type { i32*, i32, i8*, i32 }
+ at _ZZ19SFLGetVisibilityKeyvE19_kSFLLVisibilityKey = internal global %struct.__CFString* null             ; <%struct.__CFString**> [#uses=2]
+ at _ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey = internal global %struct.__CFString* null               ; <%struct.__CFString**> [#uses=7]
+ at 0 = internal constant %struct.__builtin_CFString {
+    i32* getelementptr ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), 
+    i32 1992, 
+    i8* getelementptr ([14 x i8], [14 x i8]* @.str, i32 0, i32 0), 
+    i32 13 }, section "__DATA,__cfstring"               ; <%struct.__builtin_CFString*>:0 [#uses=1]
+ at __CFConstantStringClassReference = external global [0 x i32]           ; <[0 x i32]*> [#uses=1]
+ at .str = internal constant [14 x i8] c"AlwaysVisible\00"         ; <[14 x i8]*> [#uses=1]
+ at _ZZ21SFLGetNeverVisibleKeyvE21_kSFLLNeverVisibleKey = internal global %struct.__CFString* null         ; <%struct.__CFString**> [#uses=2]
+
+define %struct.__CFString* @_Z19SFLGetVisibilityKeyv() {
+entry:
+        %tmp1 = load %struct.__CFString*, %struct.__CFString** @_ZZ19SFLGetVisibilityKeyvE19_kSFLLVisibilityKey              ; <%struct.__CFString*> [#uses=1]
+        ret %struct.__CFString* %tmp1
+}
+
+define %struct.__CFString* @_Z22SFLGetAlwaysVisibleKeyv() {
+entry:
+        %tmp1 = load %struct.__CFString*, %struct.__CFString** @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey                ; <%struct.__CFString*> [#uses=1]
+        %tmp2 = icmp eq %struct.__CFString* %tmp1, null         ; <i1> [#uses=1]
+        br i1 %tmp2, label %cond_true, label %cond_next
+
+cond_true:              ; preds = %entry
+        store %struct.__CFString* bitcast (%struct.__builtin_CFString* @0 to %struct.__CFString*), %struct.__CFString** @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey
+        br label %cond_next
+
+cond_next:              ; preds = %entry, %cond_true
+        %tmp4 = load %struct.__CFString*, %struct.__CFString** @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey                ; <%struct.__CFString*> [#uses=1]
+        ret %struct.__CFString* %tmp4
+}
+
+define %struct.__CFString* @_Z21SFLGetNeverVisibleKeyv() {
+entry:
+        %tmp1 = load %struct.__CFString*, %struct.__CFString** @_ZZ21SFLGetNeverVisibleKeyvE21_kSFLLNeverVisibleKey          ; <%struct.__CFString*> [#uses=1]
+        ret %struct.__CFString* %tmp1
+}
+
+define %struct.__CFDictionary* @_ZN18SFLMutableListItem18GetPrefsDictionaryEv(%struct.SFLMutableListItem* %this) {
+entry:
+        %tmp4 = getelementptr %struct.SFLMutableListItem, %struct.SFLMutableListItem* %this, i32 0, i32 0  ; <i16*> [#uses=1]
+        %tmp5 = load i16, i16* %tmp4         ; <i16> [#uses=1]
+        %tmp6 = icmp eq i16 %tmp5, 0            ; <i1> [#uses=1]
+        br i1 %tmp6, label %cond_next22, label %cond_true
+
+cond_true:              ; preds = %entry
+        %tmp9 = load %struct.__CFString*, %struct.__CFString** @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey                ; <%struct.__CFString*> [#uses=1]
+        %tmp10 = icmp eq %struct.__CFString* %tmp9, null                ; <i1> [#uses=1]
+        br i1 %tmp10, label %cond_true13, label %cond_next22
+
+cond_true13:            ; preds = %cond_true
+        store %struct.__CFString* bitcast (%struct.__builtin_CFString* @0 to %struct.__CFString*), %struct.__CFString** @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey
+        br label %cond_next22
+
+cond_next22:            ; preds = %entry, %cond_true13, %cond_true
+        %iftmp.1.0.in = phi %struct.__CFString** [ @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey, %cond_true ], [ @_ZZ22SFLGetAlwaysVisibleKeyvE22_kSFLLAlwaysVisibleKey, %cond_true13 ], [ @_ZZ21SFLGetNeverVisibleKeyvE21_kSFLLNeverVisibleKey, %entry ]             ; <%struct.__CFString**> [#uses=1]
+        %iftmp.1.0 = load %struct.__CFString*, %struct.__CFString** %iftmp.1.0.in            ; <%struct.__CFString*> [#uses=1]
+        %tmp24 = load %struct.__CFString*, %struct.__CFString** @_ZZ19SFLGetVisibilityKeyvE19_kSFLLVisibilityKey             ; <%struct.__CFString*> [#uses=1]
+        %tmp2728 = bitcast %struct.__CFString* %tmp24 to i8*            ; <i8*> [#uses=1]
+        %tmp2930 = bitcast %struct.__CFString* %iftmp.1.0 to i8*               ; <i8*> [#uses=1]
+        call void @_Z20CFDictionaryAddValuePKvS0_( i8* %tmp2728, i8* %tmp2930 )
+        ret %struct.__CFDictionary* undef
+}
+
+declare void @_Z20CFDictionaryAddValuePKvS0_(i8*, i8*)
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -globalopt -disable-output
+; PR1491
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
+target triple = "i686-pc-linux-gnu"
+	%"struct.__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<const int, int> > >" = type <{ i8 }>
+	%"struct.std::_Rb_tree<int,std::pair<const int, int>,std::_Select1st<std::pair<const int, int> >,std::less<int>,std::allocator<std::pair<const int, int> > >" = type { %"struct.std::_Rb_tree<int,std::pair<const int, int>,std::_Select1st<std::pair<const int, int> >,std::less<int>,std::allocator<std::pair<const int, int> > >::_Rb_tree_impl<std::less<int>,false>" }
+	%"struct.std::_Rb_tree<int,std::pair<const int, int>,std::_Select1st<std::pair<const int, int> >,std::less<int>,std::allocator<std::pair<const int, int> > >::_Rb_tree_impl<std::less<int>,false>" = type { %"struct.__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<const int, int> > >", %"struct.std::_Rb_tree_node_base", i32 }
+	%"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* }
+	%"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >" = type { %"struct.std::_Rb_tree<int,std::pair<const int, int>,std::_Select1st<std::pair<const int, int> >,std::less<int>,std::allocator<std::pair<const int, int> > >" }
+ at someMap = global %"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >" zeroinitializer		; <%"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >"*> [#uses=1]
+ at llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_someMap } ]		; <[1 x { i32, void ()* }]*> [#uses=0]
+ at llvm.global_dtors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__D_someMap } ]		; <[1 x { i32, void ()* }]*> [#uses=0]
+
+define void @_GLOBAL__I_someMap() {
+entry:
+	call void @_Z41__static_initialization_and_destruction_0ii( i32 1, i32 65535 )
+	ret void
+}
+
+declare void @_GLOBAL__D_someMap()
+
+define void @_Z41__static_initialization_and_destruction_0ii(i32 %__initialize_p, i32 %__priority) {
+entry:
+	%tmp1 = icmp eq i32 %__priority, 65535		; <i1> [#uses=1]
+	%tmp4 = icmp eq i32 %__initialize_p, 1		; <i1> [#uses=1]
+	%tmp7 = and i1 %tmp1, %tmp4		; <i1> [#uses=1]
+	br i1 %tmp7, label %cond_true, label %cond_next
+
+cond_true:		; preds = %entry
+	store i8 0, i8* getelementptr (%"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >", %"struct.std::map<int,int,std::less<int>,std::allocator<std::pair<const int, int> > >"* @someMap, i32 0, i32 0, i32 0, i32 0, i32 0)
+	ret void
+
+cond_next:		; preds = %entry
+	ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2007-11-09-GEP-GEP-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2007-11-09-GEP-GEP-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2007-11-09-GEP-GEP-Crash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2007-11-09-GEP-GEP-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,19 @@
+; RUN: opt < %s -globalopt -disable-output
+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-f128:64:128"
+target triple = "powerpc-unknown-linux-gnu"
+        %struct.empty0 = type {  }
+        %struct.es = type { %struct.empty0 }
+        %struct.es1 = type { %struct.empty0 }
+ at aaui1 = internal global [6 x [2 x i32]] [ [2 x i32] [ i32 1, i32 1 ], [2 x i32] [ i32 1, i32 1 ], [2 x i32] [ i32 1, i32 1 ], [2 x i32] [ i32 1, i32 1 ], [2 x i32] [ i32 1, i32 1 ], [2 x i32] [ i32 1, i32 1 ] ]              ; <[6 x [2 x i32]]*> [#uses=1]
+ at aaui0 = internal global [0 x [2 x i32]] zeroinitializer                ; <[0 x [2 x i32]]*> [#uses=1]
+
+define i8 @func() {
+entry:
+        %tmp10 = getelementptr [2 x i32], [2 x i32]* getelementptr ([6 x [2 x i32]], [6 x [2 x i32]]* @aaui1, i32 0, i32 0), i32 5, i32 1           ; <i32*> [#uses=1]
+        %tmp11 = load i32, i32* %tmp10, align 4              ; <i32> [#uses=1]
+        %tmp12 = call i32 (...) @func3( i32* null, i32 0, i32 %tmp11 )         ; <i32> [#uses=0]
+        ret i8 undef
+}
+
+declare i32 @func3(...)
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2008-01-03-Crash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2008-01-03-Crash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2008-01-03-Crash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2008-01-03-Crash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,26 @@
+; RUN: opt < %s -globalopt | llvm-dis
+; PR1896
+
+ at indirect1 = internal global void (i32)* null		; <void (i32)**> [#uses=2]
+
+declare void @indirectmarked(i32)
+
+define i32 @main() {
+entry:
+	br i1 false, label %cond_next20.i, label %cond_true.i9
+
+cond_true.i9:		; preds = %entry
+	ret i32 0
+
+cond_next20.i:		; preds = %entry
+	store void (i32)* @indirectmarked, void (i32)** @indirect1, align 4
+	br i1 false, label %cond_next21.i.i23.i, label %stack_restore
+
+stack_restore:		; preds = %cond_next20.i
+	ret i32 0
+
+cond_next21.i.i23.i:		; preds = %cond_next20.i
+	%tmp6.i4.i = load i32, i32* bitcast (void (i32)** @indirect1 to i32*), align 4		; <i32> [#uses=0]
+	ret i32 0
+}
+

Added: llvm/trunk/test/Transforms/GlobalOpt/2008-01-13-OutOfRangeSROA.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2008-01-13-OutOfRangeSROA.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2008-01-13-OutOfRangeSROA.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2008-01-13-OutOfRangeSROA.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,18 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; The 'X' indices could be larger than 31.  Do not SROA the outer
+; indices of this array.
+; CHECK: @mm = {{.*}} [16 x [31 x double]] zeroinitializer
+ at mm = internal global [16 x [31 x double]] zeroinitializer, align 32
+
+define void @test(i32 %X) {
+	%P = getelementptr [16 x [31 x double]], [16 x [31 x double]]* @mm, i32 0, i32 0, i32 %X
+	store double 1.0, double* %P
+	ret void
+}
+
+define double @get(i32 %X) {
+	%P = getelementptr [16 x [31 x double]], [16 x [31 x double]]* @mm, i32 0, i32 0, i32 %X
+	%V = load double, double* %P
+	ret double %V
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: load volatile
+ at t0.1441 = internal global double 0x3FD5555555555555, align 8		; <double*> [#uses=1]
+
+define double @foo() nounwind  {
+entry:
+	%tmp1 = load volatile double, double* @t0.1441, align 8		; <double> [#uses=2]
+	%tmp4 = fmul double %tmp1, %tmp1		; <double> [#uses=1]
+	ret double %tmp4
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,34 @@
+; Verify that when @G is SROA'd that the new globals have correct 
+; alignments.  Elements 0 and 2 must be 16-byte aligned, and element 
+; 1 must be at least 8 byte aligned (but could be more). 
+
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: @G.0 = internal unnamed_addr global {{.*}}align 16
+; CHECK: @G.1 = internal unnamed_addr global {{.*}}align 8
+; CHECK: @G.2 = internal unnamed_addr global {{.*}}align 16
+
+; rdar://5891920
+
+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:32:32-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin8"
+
+%T = type { double, double, double }
+
+ at G = internal global %T zeroinitializer, align 16
+
+
+define void @test() {
+  store double 1.0, double* getelementptr (%T, %T* @G, i32 0, i32 0), align 16
+  store double 2.0, double* getelementptr (%T, %T* @G, i32 0, i32 1), align 8
+  store double 3.0, double* getelementptr (%T, %T* @G, i32 0, i32 2), align 16
+  ret void
+}
+
+define double @test2() {
+  %V1 = load double, double* getelementptr (%T, %T* @G, i32 0, i32 0), align 16
+  %V2 = load double, double* getelementptr (%T, %T* @G, i32 0, i32 1), align 8
+  %V3 = load double, double* getelementptr (%T, %T* @G, i32 0, i32 2), align 16
+  %R = fadd double %V1, %V2
+  %R2 = fadd double %R, %V3
+  ret double %R2
+}

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

Added: llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash-2.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash-2.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash-2.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,28 @@
+; RUN: opt < %s -globalopt | llvm-dis
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null		; <%struct.foo**> [#uses=2]
+
+define void @bar(i32 %Size) nounwind noinline {
+entry:
+        %malloccall = tail call i8* @malloc(i32 trunc (i64 mul (i64 ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64), i64 2000000) to i32))
+        %tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]*
+	%.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0		; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i32)
+
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%tmpLD1 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=2]
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%tmp = phi %struct.foo* [ %tmpLD1, %bb1.thread ], [ %tmpLD1, %bb1 ]		; <%struct.foo*> [#uses=1]
+	%0 = getelementptr %struct.foo, %struct.foo* %tmp, i32 1		; <%struct.foo*> [#uses=0]
+	br label %bb1
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,30 @@
+; RUN: opt < %s -globalopt | llvm-dis
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin7"
+	%struct.foo = type { i32, i32 }
+ at X = internal global %struct.foo* null		; <%struct.foo**> [#uses=2]
+
+define void @bar(i32 %Size) nounwind noinline {
+entry:
+        %malloccall = tail call i8* @malloc(i32 trunc (i64 mul (i64 ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64), i64 2000000) to i32))
+        %tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]*
+	%.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0		; <%struct.foo*> [#uses=1]
+	store %struct.foo* %.sub, %struct.foo** @X, align 4
+	ret void
+}
+
+declare noalias i8* @malloc(i32)
+
+define i32 @baz() nounwind readonly noinline {
+bb1.thread:
+	%tmpLD1 = load %struct.foo*, %struct.foo** @X, align 4		; <%struct.foo*> [#uses=3]
+	store %struct.foo* %tmpLD1, %struct.foo** null
+	br label %bb1
+
+bb1:		; preds = %bb1, %bb1.thread
+	%tmp = phi %struct.foo* [ %tmpLD1, %bb1.thread ], [ %tmpLD1, %bb1 ]		; <%struct.foo*> [#uses=0]
+	br i1 false, label %bb2, label %bb1
+
+bb2:		; preds = %bb1
+	ret i32 0
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-01-13-phi-user.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-01-13-phi-user.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-01-13-phi-user.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-01-13-phi-user.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,36 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+; CHECK: phi{{.*}}@head
+; PR3321
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+	%struct.node = type { %struct.node*, i32 }
+ at head = internal global %struct.node* null		; <%struct.node**> [#uses=2]
+ at node = internal global %struct.node { %struct.node* null, i32 42 }, align 16		; <%struct.node*> [#uses=1]
+
+define i32 @f() nounwind {
+entry:
+	store %struct.node* @node, %struct.node** @head, align 8
+	br label %bb1
+
+bb:		; preds = %bb1
+	%0 = getelementptr %struct.node, %struct.node* %t.0, i64 0, i32 1		; <i32*> [#uses=1]
+	%1 = load i32, i32* %0, align 4		; <i32> [#uses=1]
+	%2 = getelementptr %struct.node, %struct.node* %t.0, i64 0, i32 0		; <%struct.node**> [#uses=1]
+	br label %bb1
+
+bb1:		; preds = %bb, %entry
+	%value.0 = phi i32 [ undef, %entry ], [ %1, %bb ]		; <i32> [#uses=1]
+	%t.0.in = phi %struct.node** [ @head, %entry ], [ %2, %bb ]		; <%struct.node**> [#uses=1]
+	%t.0 = load %struct.node*, %struct.node** %t.0.in		; <%struct.node*> [#uses=3]
+	%3 = icmp eq %struct.node* %t.0, null		; <i1> [#uses=1]
+	br i1 %3, label %bb2, label %bb
+
+bb2:		; preds = %bb1
+	ret i32 %value.0
+}
+
+define i32 @main() nounwind {
+entry:
+	%0 = call i32 @f() nounwind		; <i32> [#uses=1]
+	ret i32 %0
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,10 @@
+; RUN: opt < %s -globalopt
+
+ at g = global i32 0
+
+ at a = alias i8, bitcast (i32* @g to i8*)
+
+define void @f() {
+	%tmp = load i8, i8* @a
+	ret void
+}

Added: llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll?rev=358552&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll (added)
+++ llvm/trunk/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll Tue Apr 16 21:52:47 2019
@@ -0,0 +1,24 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+define internal void @f() {
+; CHECK-NOT: @f(
+; CHECK: define void @a
+	ret void
+}
+
+ at a = alias void (), void ()* @f
+
+define void @g() {
+	call void() @a()
+	ret void
+}
+
+ at b = internal alias  void (),  void ()* @g
+; CHECK-NOT: @b
+
+define void @h() {
+	call void() @b()
+; CHECK: call void @g
+	ret void
+}
+




More information about the llvm-commits mailing list