summaryrefslogtreecommitdiff
path: root/test/Transforms
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-09 21:23:09 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-09 21:23:09 +0000
commit909545a822eef491158f831688066f0ec2866938 (patch)
tree5b0bf0e81294007a9b462b21031b3df272c655c3 /test/Transforms
parent7e7b6700743285c0af506ac6299ddf82ebd434b9 (diff)
Diffstat (limited to 'test/Transforms')
-rw-r--r--test/Transforms/GVN/invariant.group.ll52
-rw-r--r--test/Transforms/InstCombine/assume.ll45
-rw-r--r--test/Transforms/InstCombine/assume2.ll141
-rw-r--r--test/Transforms/InstCombine/fabs.ll42
-rw-r--r--test/Transforms/InstCombine/fast-math.ll6
-rw-r--r--test/Transforms/InstCombine/urem-simplify-bug.ll52
-rw-r--r--test/Transforms/InstSimplify/div.ll15
-rw-r--r--test/Transforms/InstSimplify/rem.ll14
-rw-r--r--test/Transforms/LICM/hoisting.ll27
-rw-r--r--test/Transforms/LoopLoadElim/forward.ll6
-rw-r--r--test/Transforms/LoopVectorize/iv_outside_user.ll45
-rw-r--r--test/Transforms/NewGVN/basic-cyclic-opt.ll235
-rw-r--r--test/Transforms/NewGVN/cyclic-phi-handling.ll37
-rw-r--r--test/Transforms/NewGVN/invariant.group.ll52
-rw-r--r--test/Transforms/NewGVN/memory-handling.ll195
-rw-r--r--test/Transforms/NewGVN/pr31501.ll136
-rw-r--r--test/Transforms/NewGVN/pr31573.ll42
17 files changed, 1005 insertions, 137 deletions
diff --git a/test/Transforms/GVN/invariant.group.ll b/test/Transforms/GVN/invariant.group.ll
index 026671a5bdf48..d0b32d7f3dd8c 100644
--- a/test/Transforms/GVN/invariant.group.ll
+++ b/test/Transforms/GVN/invariant.group.ll
@@ -344,11 +344,63 @@ _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: %trunc = trunc i8 %b to i1
+ %2 = load i1, i1* %b0, !invariant.group !0
+; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %trunc)
+ call void @fooBit(i1* %b0, i1 %2)
+ %3 = load i1, i1* %b0, !invariant.group !0
+; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %trunc)
+ call void @fooBit(i1* %b0, i1 %3)
+ 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.invariant.group.barrier(i8*)
; Function Attrs: nounwind
diff --git a/test/Transforms/InstCombine/assume.ll b/test/Transforms/InstCombine/assume.ll
index 7987aa2423199..6e690426db99f 100644
--- a/test/Transforms/InstCombine/assume.ll
+++ b/test/Transforms/InstCombine/assume.ll
@@ -2,7 +2,6 @@
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 @foo1(i32* %a) #0 {
entry:
%0 = load i32, i32* %a, align 4
@@ -22,7 +21,6 @@ entry:
ret i32 %0
}
-; Function Attrs: nounwind uwtable
define i32 @foo2(i32* %a) #0 {
entry:
; Same check as in @foo1, but make sure it works if the assume is first too.
@@ -40,7 +38,6 @@ entry:
ret i32 %0
}
-; Function Attrs: nounwind
declare void @llvm.assume(i1) #1
define i32 @simple(i32 %a) #1 {
@@ -55,7 +52,6 @@ entry:
ret i32 %a
}
-; Function Attrs: nounwind uwtable
define i32 @can1(i1 %a, i1 %b, i1 %c) {
entry:
%and1 = and i1 %a, %b
@@ -71,7 +67,6 @@ entry:
ret i32 5
}
-; Function Attrs: nounwind uwtable
define i32 @can2(i1 %a, i1 %b, i1 %c) {
entry:
%v = or i1 %a, %b
@@ -103,7 +98,6 @@ entry:
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @bar2(i32 %a) #0 {
entry:
; CHECK-LABEL: @bar2
@@ -118,7 +112,6 @@ entry:
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @bar3(i32 %a, i1 %x, i1 %y) #0 {
entry:
%and1 = and i32 %a, 3
@@ -139,7 +132,6 @@ entry:
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @bar4(i32 %a, i32 %b) {
entry:
%and1 = and i32 %b, 3
@@ -160,30 +152,41 @@ entry:
}
define i32 @icmp1(i32 %a) #0 {
-entry:
+; CHECK-LABEL: @icmp1(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 1
+;
%cmp = icmp sgt i32 %a, 5
tail call void @llvm.assume(i1 %cmp)
%conv = zext i1 %cmp to i32
ret i32 %conv
-
-; CHECK-LABEL: @icmp1
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 1
-
}
-; Function Attrs: nounwind uwtable
define i32 @icmp2(i32 %a) #0 {
-entry:
+; CHECK-LABEL: @icmp2(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 0
+;
%cmp = icmp sgt i32 %a, 5
tail call void @llvm.assume(i1 %cmp)
- %0 = zext i1 %cmp to i32
- %lnot.ext = xor i32 %0, 1
+ %t0 = zext i1 %cmp to i32
+ %lnot.ext = xor i32 %t0, 1
ret i32 %lnot.ext
+}
-; CHECK-LABEL: @icmp2
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 0
+; FIXME: If the 'not' of a condition is known true, then the condition must be false.
+
+define i1 @assume_not(i1 %cond) {
+; CHECK-LABEL: @assume_not(
+; CHECK-NEXT: [[NOTCOND:%.*]] = xor i1 [[COND:%.*]], true
+; CHECK-NEXT: call void @llvm.assume(i1 [[NOTCOND]])
+; CHECK-NEXT: ret i1 [[COND]]
+;
+ %notcond = xor i1 %cond, true
+ call void @llvm.assume(i1 %notcond)
+ ret i1 %cond
}
declare void @escape(i32* %a)
diff --git a/test/Transforms/InstCombine/assume2.ll b/test/Transforms/InstCombine/assume2.ll
index c41bbaa04eb73..e8fbc049f41aa 100644
--- a/test/Transforms/InstCombine/assume2.ll
+++ b/test/Transforms/InstCombine/assume2.ll
@@ -1,170 +1,155 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
-; Function Attrs: nounwind
declare void @llvm.assume(i1) #1
-; Function Attrs: nounwind uwtable
define i32 @test1(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test1
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 5
-
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 15
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 5
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 5
+;
%and = and i32 %a, 15
%cmp = icmp eq i32 %and, 5
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 7
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test2(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test2
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 2
-
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: [[A_NOT:%.*]] = or i32 [[A:%.*]], -16
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A_NOT]], -6
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 2
+;
%and = and i32 %a, 15
%nand = xor i32 %and, -1
%cmp = icmp eq i32 %nand, 4294967285
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 7
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test3(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test3
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 5
-
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: [[V:%.*]] = or i32 [[A:%.*]], -16
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V]], -11
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 5
+;
%v = or i32 %a, 4294967280
%cmp = icmp eq i32 %v, 4294967285
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 7
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test4(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test4
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 2
-
+; CHECK-LABEL: @test4(
+; CHECK-NEXT: [[A_NOT:%.*]] = and i32 [[A:%.*]], 15
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A_NOT]], 10
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 2
+;
%v = or i32 %a, 4294967280
%nv = xor i32 %v, -1
%cmp = icmp eq i32 %nv, 5
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 7
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test5(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test5
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 4
-
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], 4
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 4
+;
%v = xor i32 %a, 1
%cmp = icmp eq i32 %v, 5
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 7
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test6(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test6
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 5
-
+; CHECK-LABEL: @test6(
+; CHECK-NEXT: [[V_MASK:%.*]] = and i32 [[A:%.*]], 1073741823
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V_MASK]], 5
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 5
+;
%v = shl i32 %a, 2
%cmp = icmp eq i32 %v, 20
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 63
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test7(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test7
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 20
-
+; CHECK-LABEL: @test7(
+; CHECK-NEXT: [[V_MASK:%.*]] = and i32 [[A:%.*]], -4
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V_MASK]], 20
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 20
+;
%v = lshr i32 %a, 2
%cmp = icmp eq i32 %v, 5
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 252
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test8(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test8
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 20
-
+; CHECK-LABEL: @test8(
+; CHECK-NEXT: [[V_MASK:%.*]] = and i32 [[A:%.*]], -4
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V_MASK]], 20
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 20
+;
%v = lshr i32 %a, 2
%cmp = icmp eq i32 %v, 5
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 252
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test9(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test9
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 0
-
+; CHECK-LABEL: @test9(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 5
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 0
+;
%cmp = icmp sgt i32 %a, 5
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 2147483648
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test10(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test10
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 -2147483648
-
+; CHECK-LABEL: @test10(
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], -1
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 -2147483648
+;
%cmp = icmp sle i32 %a, -2
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 2147483648
ret i32 %and1
}
-; Function Attrs: nounwind uwtable
define i32 @test11(i32 %a) #0 {
-entry:
-; CHECK-LABEL: @test11
-; CHECK: call void @llvm.assume
-; CHECK: ret i32 0
-
+; CHECK-LABEL: @test11(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], 257
+; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: ret i32 0
+;
%cmp = icmp ule i32 %a, 256
tail call void @llvm.assume(i1 %cmp)
-
%and1 = and i32 %a, 3072
ret i32 %and1
}
diff --git a/test/Transforms/InstCombine/fabs.ll b/test/Transforms/InstCombine/fabs.ll
index 09bea5895aaff..6b5f5a9495301 100644
--- a/test/Transforms/InstCombine/fabs.ll
+++ b/test/Transforms/InstCombine/fabs.ll
@@ -13,7 +13,8 @@ define float @square_fabs_call_f32(float %x) {
; CHECK-LABEL: square_fabs_call_f32(
; CHECK-NEXT: %mul = fmul float %x, %x
-; CHECK-NEXT: ret float %mul
+; CHECK-NEXT: %fabsf = tail call float @fabsf(float %mul)
+; CHECK-NEXT: ret float %fabsf
}
define double @square_fabs_call_f64(double %x) {
@@ -23,7 +24,8 @@ define double @square_fabs_call_f64(double %x) {
; CHECK-LABEL: square_fabs_call_f64(
; CHECK-NEXT: %mul = fmul double %x, %x
-; CHECK-NEXT: ret double %mul
+; CHECK-NEXT: %fabs = tail call double @fabs(double %mul)
+; CHECK-NEXT: ret double %fabs
}
define fp128 @square_fabs_call_f128(fp128 %x) {
@@ -33,15 +35,18 @@ define fp128 @square_fabs_call_f128(fp128 %x) {
; CHECK-LABEL: square_fabs_call_f128(
; CHECK-NEXT: %mul = fmul fp128 %x, %x
-; CHECK-NEXT: ret fp128 %mul
+; CHECK-NEXT: %fabsl = tail call fp128 @fabsl(fp128 %mul)
+; CHECK-NEXT: ret fp128 %fabsl
}
-; Make sure all intrinsic calls are eliminated when the input is known positive.
+; Make sure all intrinsic calls are eliminated when the input is known
+; positive.
declare float @llvm.fabs.f32(float)
declare double @llvm.fabs.f64(double)
declare fp128 @llvm.fabs.f128(fp128)
+; The fabs cannot be eliminated because %x may be a NaN
define float @square_fabs_intrinsic_f32(float %x) {
%mul = fmul float %x, %x
%fabsf = tail call float @llvm.fabs.f32(float %mul)
@@ -49,7 +54,8 @@ define float @square_fabs_intrinsic_f32(float %x) {
; CHECK-LABEL: square_fabs_intrinsic_f32(
; CHECK-NEXT: %mul = fmul float %x, %x
-; CHECK-NEXT: ret float %mul
+; CHECK-NEXT: %fabsf = tail call float @llvm.fabs.f32(float %mul)
+; CHECK-NEXT: ret float %fabsf
}
define double @square_fabs_intrinsic_f64(double %x) {
@@ -59,7 +65,8 @@ define double @square_fabs_intrinsic_f64(double %x) {
; CHECK-LABEL: square_fabs_intrinsic_f64(
; CHECK-NEXT: %mul = fmul double %x, %x
-; CHECK-NEXT: ret double %mul
+; CHECK-NEXT: %fabs = tail call double @llvm.fabs.f64(double %mul)
+; CHECK-NEXT: ret double %fabs
}
define fp128 @square_fabs_intrinsic_f128(fp128 %x) {
@@ -69,7 +76,20 @@ define fp128 @square_fabs_intrinsic_f128(fp128 %x) {
; CHECK-LABEL: square_fabs_intrinsic_f128(
; CHECK-NEXT: %mul = fmul fp128 %x, %x
-; CHECK-NEXT: ret fp128 %mul
+; CHECK-NEXT: %fabsl = tail call fp128 @llvm.fabs.f128(fp128 %mul)
+; CHECK-NEXT: ret fp128 %fabsl
+}
+
+; TODO: This should be able to elimnated the fabs
+define float @square_nnan_fabs_intrinsic_f32(float %x) {
+ %mul = fmul nnan float %x, %x
+ %fabsf = call float @llvm.fabs.f32(float %mul)
+ ret float %fabsf
+
+; CHECK-LABEL: square_nnan_fabs_intrinsic_f32(
+; CHECK-NEXT: %mul = fmul nnan float %x, %x
+; CHECK-NEXT: %fabsf = call float @llvm.fabs.f32(float %mul)
+; CHECK-NEXT: ret float %fabsf
}
; Shrinking a library call to a smaller type should not be inhibited by nor inhibit the square optimization.
@@ -82,7 +102,10 @@ define float @square_fabs_shrink_call1(float %x) {
ret float %trunc
; CHECK-LABEL: square_fabs_shrink_call1(
-; CHECK-NEXT: %trunc = fmul float %x, %x
+; CHECK-NEXT: %ext = fpext float %x to double
+; CHECK-NEXT: %sq = fmul double %ext, %ext
+; CHECK-NEXT: call double @fabs(double %sq)
+; CHECK-NEXT: %trunc = fptrunc double %fabs to float
; CHECK-NEXT: ret float %trunc
}
@@ -95,7 +118,8 @@ define float @square_fabs_shrink_call2(float %x) {
; CHECK-LABEL: square_fabs_shrink_call2(
; CHECK-NEXT: %sq = fmul float %x, %x
-; CHECK-NEXT: ret float %sq
+; CHECK-NEXT: %fabsf = call float @fabsf(float %sq)
+; CHECK-NEXT: ret float %fabsf
}
; CHECK-LABEL: @fabs_select_constant_negative_positive(
diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll
index 6ccf6e9fa7742..84f24ca0bf247 100644
--- a/test/Transforms/InstCombine/fast-math.ll
+++ b/test/Transforms/InstCombine/fast-math.ll
@@ -672,7 +672,8 @@ define double @sqrt_intrinsic_arg_4th(double %x) {
; CHECK-LABEL: sqrt_intrinsic_arg_4th(
; CHECK-NEXT: %mul = fmul fast double %x, %x
-; CHECK-NEXT: ret double %mul
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %mul)
+; CHECK-NEXT: ret double %fabs
}
define double @sqrt_intrinsic_arg_5th(double %x) {
@@ -684,8 +685,9 @@ define double @sqrt_intrinsic_arg_5th(double %x) {
; CHECK-LABEL: sqrt_intrinsic_arg_5th(
; CHECK-NEXT: %mul = fmul fast double %x, %x
+; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %mul)
; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %x)
-; CHECK-NEXT: %1 = fmul fast double %mul, %sqrt1
+; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1
; CHECK-NEXT: ret double %1
}
diff --git a/test/Transforms/InstCombine/urem-simplify-bug.ll b/test/Transforms/InstCombine/urem-simplify-bug.ll
index 1220dfdc77f05..4f18f35985407 100644
--- a/test/Transforms/InstCombine/urem-simplify-bug.ll
+++ b/test/Transforms/InstCombine/urem-simplify-bug.ll
@@ -1,32 +1,36 @@
-; RUN: opt < %s -instcombine -S | grep "= or i32 %x, -5"
+; RUN: opt < %s -instcombine -S | FileCheck %s
-@.str = internal constant [5 x i8] c"foo\0A\00" ; <[5 x i8]*> [#uses=1]
-@.str1 = internal constant [5 x i8] c"bar\0A\00" ; <[5 x i8]*> [#uses=1]
+@.str = internal constant [5 x i8] c"foo\0A\00"
+@.str1 = internal constant [5 x i8] c"bar\0A\00"
define i32 @main() nounwind {
entry:
- %x = call i32 @func_11( ) nounwind ; <i32> [#uses=1]
- %tmp3 = or i32 %x, -5 ; <i32> [#uses=1]
- %tmp5 = urem i32 251, %tmp3 ; <i32> [#uses=1]
- %tmp6 = icmp ne i32 %tmp5, 0 ; <i1> [#uses=1]
- %tmp67 = zext i1 %tmp6 to i32 ; <i32> [#uses=1]
- %tmp9 = urem i32 %tmp67, 95 ; <i32> [#uses=1]
- %tmp10 = and i32 %tmp9, 1 ; <i32> [#uses=1]
- %tmp12 = icmp eq i32 %tmp10, 0 ; <i1> [#uses=1]
- br i1 %tmp12, label %bb14, label %bb
-
-bb: ; preds = %entry
- br label %bb15
-
-bb14: ; preds = %entry
- br label %bb15
-
-bb15: ; preds = %bb14, %bb
- %iftmp.0.0 = phi i8* [ getelementptr ([5 x i8], [5 x i8]* @.str1, i32 0, i32 0), %bb14 ], [ getelementptr ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), %bb ] ; <i8*> [#uses=1]
- %tmp17 = call i32 (i8*, ...) @printf( i8* %iftmp.0.0 ) nounwind ; <i32> [#uses=0]
- ret i32 0
+ %x = call i32 @func_11() nounwind
+ %tmp3 = or i32 %x, -5
+ %tmp5 = urem i32 251, %tmp3
+ %tmp6 = icmp ne i32 %tmp5, 0
+ %tmp67 = zext i1 %tmp6 to i32
+ %tmp9 = urem i32 %tmp67, 95
+ %tmp10 = and i32 %tmp9, 1
+ %tmp12 = icmp eq i32 %tmp10, 0
+ br i1 %tmp12, label %bb14, label %bb
+
+bb:
+ br label %bb15
+
+bb14:
+ br label %bb15
+
+bb15:
+ %iftmp.0.0 = phi i8* [ getelementptr ([5 x i8], [5 x i8]* @.str1, i32 0, i32 0), %bb14 ], [ getelementptr ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), %bb ]
+ %tmp17 = call i32 (i8*, ...) @printf(i8* %iftmp.0.0) nounwind
+ ret i32 0
}
+; CHECK-LABEL: define i32 @main(
+; CHECK: call i32 @func_11()
+; CHECK-NEXT: br i1 false, label %bb14, label %bb
+
declare i32 @func_11()
-declare i32 @printf(i8*, ...) nounwind
+declare i32 @printf(i8*, ...) nounwind
diff --git a/test/Transforms/InstSimplify/div.ll b/test/Transforms/InstSimplify/div.ll
new file mode 100644
index 0000000000000..b8ce34aaa37e6
--- /dev/null
+++ b/test/Transforms/InstSimplify/div.ll
@@ -0,0 +1,15 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+declare i32 @external()
+
+define i32 @div1() {
+; CHECK-LABEL: @div1(
+; CHECK: [[CALL:%.*]] = call i32 @external(), !range !0
+; CHECK-NEXT: ret i32 0
+;
+ %call = call i32 @external(), !range !0
+ %urem = udiv i32 %call, 3
+ ret i32 %urem
+}
+
+!0 = !{i32 0, i32 3}
diff --git a/test/Transforms/InstSimplify/rem.ll b/test/Transforms/InstSimplify/rem.ll
index df3f659b782e4..c73d34346ded5 100644
--- a/test/Transforms/InstSimplify/rem.ll
+++ b/test/Transforms/InstSimplify/rem.ll
@@ -49,3 +49,17 @@ define i32 @rem3(i32 %x, i32 %n) {
%mod1 = urem i32 %mod, %n
ret i32 %mod1
}
+
+declare i32 @external()
+
+define i32 @rem4() {
+; CHECK-LABEL: @rem4(
+; CHECK: [[CALL:%.*]] = call i32 @external(), !range !0
+; CHECK-NEXT: ret i32 [[CALL]]
+;
+ %call = call i32 @external(), !range !0
+ %urem = urem i32 %call, 3
+ ret i32 %urem
+}
+
+!0 = !{i32 0, i32 3}
diff --git a/test/Transforms/LICM/hoisting.ll b/test/Transforms/LICM/hoisting.ll
index cb6981ede1e7f..c61131b476b9c 100644
--- a/test/Transforms/LICM/hoisting.ll
+++ b/test/Transforms/LICM/hoisting.ll
@@ -5,6 +5,8 @@
declare void @foo()
+declare i32 @llvm.bitreverse.i32(i32)
+
; This testcase tests for a problem where LICM hoists
; potentially trapping instructions when they are not guaranteed to execute.
define i32 @test1(i1 %c) {
@@ -122,3 +124,28 @@ then: ; preds = %tailrecurse
ifend: ; preds = %tailrecurse
ret { i32*, i32 } %d
}
+
+; CHECK: define i32 @hoist_bitreverse(i32)
+; CHECK: bitreverse
+; CHECK: br label %header
+define i32 @hoist_bitreverse(i32) {
+ br label %header
+
+header:
+ %sum = phi i32 [ 0, %1 ], [ %5, %latch ]
+ %2 = phi i32 [ 0, %1 ], [ %6, %latch ]
+ %3 = icmp slt i32 %2, 1024
+ br i1 %3, label %body, label %return
+
+body:
+ %4 = call i32 @llvm.bitreverse.i32(i32 %0)
+ %5 = add i32 %sum, %4
+ br label %latch
+
+latch:
+ %6 = add nsw i32 %2, 1
+ br label %header
+
+return:
+ ret i32 %sum
+}
diff --git a/test/Transforms/LoopLoadElim/forward.ll b/test/Transforms/LoopLoadElim/forward.ll
index ed0d162ab7e3c..9a0e03a317c8c 100644
--- a/test/Transforms/LoopLoadElim/forward.ll
+++ b/test/Transforms/LoopLoadElim/forward.ll
@@ -16,8 +16,8 @@ define void @f(i32* %A, i32* %B, i32* %C, i64 %N) {
; CHECK-NOT: %found.conflict{{.*}} =
entry:
-; for.body.ph:
-; CHECK: %load_initial = load i32, i32* %A
+; Make sure the hoisted load keeps the alignment
+; CHECK: %load_initial = load i32, i32* %A, align 1
br label %for.body
for.body: ; preds = %for.body, %entry
@@ -34,7 +34,7 @@ for.body: ; preds = %for.body, %entry
%a_p1 = add i32 %b, 2
store i32 %a_p1, i32* %Aidx_next, align 4
- %a = load i32, i32* %Aidx, align 4
+ %a = load i32, i32* %Aidx, align 1
; CHECK: %c = mul i32 %store_forwarded, 2
%c = mul i32 %a, 2
store i32 %c, i32* %Cidx, align 4
diff --git a/test/Transforms/LoopVectorize/iv_outside_user.ll b/test/Transforms/LoopVectorize/iv_outside_user.ll
index d536d1023f413..8a44af96e7f4b 100644
--- a/test/Transforms/LoopVectorize/iv_outside_user.ll
+++ b/test/Transforms/LoopVectorize/iv_outside_user.ll
@@ -133,3 +133,48 @@ for.end:
store i32 %phi2, i32* %p
ret i32 %phi
}
+
+; CHECK-LABEL: @PR30742
+; CHECK: min.iters.checked
+; CHECK: %[[N_MOD_VF:.+]] = urem i32 %[[T5:.+]], 2
+; CHECK: %[[N_VEC:.+]] = sub i32 %[[T5]], %[[N_MOD_VF]]
+; CHECK: middle.block
+; CHECK: %[[CMP:.+]] = icmp eq i32 %[[T5]], %[[N_VEC]]
+; CHECK: %[[T15:.+]] = add i32 %tmp03, -7
+; CHECK: %[[T16:.+]] = shl i32 %[[N_MOD_VF]], 3
+; CHECK: %[[T17:.+]] = add i32 %[[T15]], %[[T16]]
+; CHECK: %[[T18:.+]] = shl i32 {{.*}}, 3
+; CHECK: %ind.escape = sub i32 %[[T17]], %[[T18]]
+; CHECK: br i1 %[[CMP]], label %BB3, label %scalar.ph
+define void @PR30742() {
+BB0:
+ br label %BB1
+
+BB1:
+ %tmp00 = load i32, i32* undef, align 16
+ %tmp01 = sub i32 %tmp00, undef
+ %tmp02 = icmp slt i32 %tmp01, 1
+ %tmp03 = select i1 %tmp02, i32 1, i32 %tmp01
+ %tmp04 = add nsw i32 %tmp03, -7
+ br label %BB2
+
+BB2:
+ %tmp05 = phi i32 [ %tmp04, %BB1 ], [ %tmp06, %BB2 ]
+ %tmp06 = add i32 %tmp05, -8
+ %tmp07 = icmp sgt i32 %tmp06, 0
+ br i1 %tmp07, label %BB2, label %BB3
+
+BB3:
+ %tmp08 = phi i32 [ %tmp05, %BB2 ]
+ %tmp09 = sub i32 %tmp00, undef
+ %tmp10 = icmp slt i32 %tmp09, 1
+ %tmp11 = select i1 %tmp10, i32 1, i32 %tmp09
+ %tmp12 = add nsw i32 %tmp11, -7
+ br label %BB4
+
+BB4:
+ %tmp13 = phi i32 [ %tmp12, %BB3 ], [ %tmp14, %BB4 ]
+ %tmp14 = add i32 %tmp13, -8
+ %tmp15 = icmp sgt i32 %tmp14, 0
+ br i1 %tmp15, label %BB4, label %BB1
+}
diff --git a/test/Transforms/NewGVN/basic-cyclic-opt.ll b/test/Transforms/NewGVN/basic-cyclic-opt.ll
new file mode 100644
index 0000000000000..523ed2612e3ce
--- /dev/null
+++ b/test/Transforms/NewGVN/basic-cyclic-opt.ll
@@ -0,0 +1,235 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+;; Function Attrs: nounwind ssp uwtable
+;; We should eliminate the sub, and one of the phi nodes
+define void @vnum_test1(i32* %data) #0 {
+; CHECK-LABEL: @vnum_test1(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 3
+; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 4
+; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
+; CHECK-NEXT: br label [[BB4:%.*]]
+; CHECK: bb4:
+; CHECK-NEXT: [[M_0:%.*]] = phi i32 [ [[TMP3]], [[BB:%.*]] ], [ [[TMP15:%.*]], [[BB17:%.*]] ]
+; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP18:%.*]], [[BB17]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[I_0]], [[TMP1]]
+; CHECK-NEXT: br i1 [[TMP5]], label [[BB6:%.*]], label [[BB19:%.*]]
+; CHECK: bb6:
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 2
+; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP7]], align 4
+; CHECK-NEXT: [[TMP9:%.*]] = sext i32 [[TMP8]] to i64
+; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 [[TMP9]]
+; CHECK-NEXT: store i32 2, i32* [[TMP10]], align 4
+; CHECK-NEXT: store i32 0, i32* [[DATA]], align 4
+; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 1
+; CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4
+; CHECK-NEXT: [[TMP15]] = add nsw i32 [[M_0]], [[TMP14]]
+; CHECK-NEXT: br label [[BB17]]
+; CHECK: bb17:
+; CHECK-NEXT: [[TMP18]] = add nsw i32 [[I_0]], 1
+; CHECK-NEXT: br label [[BB4]]
+; CHECK: bb19:
+; CHECK-NEXT: ret void
+;
+bb:
+ %tmp = getelementptr inbounds i32, i32* %data, i64 3
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = getelementptr inbounds i32, i32* %data, i64 4
+ %tmp3 = load i32, i32* %tmp2, align 4
+ br label %bb4
+
+bb4: ; preds = %bb17, %bb
+ %m.0 = phi i32 [ %tmp3, %bb ], [ %tmp15, %bb17 ]
+ %i.0 = phi i32 [ 0, %bb ], [ %tmp18, %bb17 ]
+ %n.0 = phi i32 [ %tmp3, %bb ], [ %tmp16, %bb17 ]
+ %tmp5 = icmp slt i32 %i.0, %tmp1
+ br i1 %tmp5, label %bb6, label %bb19
+
+bb6: ; preds = %bb4
+ %tmp7 = getelementptr inbounds i32, i32* %data, i64 2
+ %tmp8 = load i32, i32* %tmp7, align 4
+ %tmp9 = sext i32 %tmp8 to i64
+ %tmp10 = getelementptr inbounds i32, i32* %data, i64 %tmp9
+ store i32 2, i32* %tmp10, align 4
+ %tmp11 = sub nsw i32 %m.0, %n.0
+ %tmp12 = getelementptr inbounds i32, i32* %data, i64 0
+ store i32 %tmp11, i32* %tmp12, align 4
+ %tmp13 = getelementptr inbounds i32, i32* %data, i64 1
+ %tmp14 = load i32, i32* %tmp13, align 4
+ %tmp15 = add nsw i32 %m.0, %tmp14
+ %tmp16 = add nsw i32 %n.0, %tmp14
+ br label %bb17
+
+bb17: ; preds = %bb6
+ %tmp18 = add nsw i32 %i.0, 1
+ br label %bb4
+
+bb19: ; preds = %bb4
+ ret void
+}
+
+;; Function Attrs: nounwind ssp uwtable
+;; We should eliminate the sub, one of the phi nodes, prove the store of the sub
+;; and the load of data are equivalent, that the load always produces constant 0, and
+;; delete the load replacing it with constant 0.
+define i32 @vnum_test2(i32* %data) #0 {
+; CHECK-LABEL: @vnum_test2(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 3
+; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 4
+; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
+; CHECK-NEXT: br label [[BB4:%.*]]
+; CHECK: bb4:
+; CHECK-NEXT: [[M_0:%.*]] = phi i32 [ [[TMP3]], [[BB:%.*]] ], [ [[TMP15:%.*]], [[BB19:%.*]] ]
+; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP20:%.*]], [[BB19]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[I_0]], [[TMP1]]
+; CHECK-NEXT: br i1 [[TMP5]], label [[BB6:%.*]], label [[BB21:%.*]]
+; CHECK: bb6:
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 2
+; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[TMP7]], align 4
+; CHECK-NEXT: [[TMP9:%.*]] = sext i32 [[TMP8]] to i64
+; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 [[TMP9]]
+; CHECK-NEXT: store i32 2, i32* [[TMP10]], align 4
+; CHECK-NEXT: store i32 0, i32* [[DATA]], align 4
+; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 1
+; CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4
+; CHECK-NEXT: [[TMP15]] = add nsw i32 [[M_0]], [[TMP14]]
+; CHECK-NEXT: br label [[BB19]]
+; CHECK: bb19:
+; CHECK-NEXT: [[TMP20]] = add nsw i32 [[I_0]], 1
+; CHECK-NEXT: br label [[BB4]]
+; CHECK: bb21:
+; CHECK-NEXT: ret i32 0
+;
+bb:
+ %tmp = getelementptr inbounds i32, i32* %data, i64 3
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = getelementptr inbounds i32, i32* %data, i64 4
+ %tmp3 = load i32, i32* %tmp2, align 4
+ br label %bb4
+
+bb4: ; preds = %bb19, %bb
+ %m.0 = phi i32 [ %tmp3, %bb ], [ %tmp15, %bb19 ]
+ %n.0 = phi i32 [ %tmp3, %bb ], [ %tmp16, %bb19 ]
+ %i.0 = phi i32 [ 0, %bb ], [ %tmp20, %bb19 ]
+ %p.0 = phi i32 [ undef, %bb ], [ %tmp18, %bb19 ]
+ %tmp5 = icmp slt i32 %i.0, %tmp1
+ br i1 %tmp5, label %bb6, label %bb21
+
+bb6: ; preds = %bb4
+ %tmp7 = getelementptr inbounds i32, i32* %data, i64 2
+ %tmp8 = load i32, i32* %tmp7, align 4
+ %tmp9 = sext i32 %tmp8 to i64
+ %tmp10 = getelementptr inbounds i32, i32* %data, i64 %tmp9
+ store i32 2, i32* %tmp10, align 4
+ %tmp11 = sub nsw i32 %m.0, %n.0
+ %tmp12 = getelementptr inbounds i32, i32* %data, i64 0
+ store i32 %tmp11, i32* %tmp12, align 4
+ %tmp13 = getelementptr inbounds i32, i32* %data, i64 1
+ %tmp14 = load i32, i32* %tmp13, align 4
+ %tmp15 = add nsw i32 %m.0, %tmp14
+ %tmp16 = add nsw i32 %n.0, %tmp14
+ %tmp17 = getelementptr inbounds i32, i32* %data, i64 0
+ %tmp18 = load i32, i32* %tmp17, align 4
+ br label %bb19
+
+bb19: ; preds = %bb6
+ %tmp20 = add nsw i32 %i.0, 1
+ br label %bb4
+
+bb21: ; preds = %bb4
+ ret i32 %p.0
+}
+
+
+; Function Attrs: nounwind ssp uwtable
+;; Same as test 2, with a conditional store of m-n, so it has to also discover
+;; that data ends up with the same value no matter what branch is taken.
+define i32 @vnum_test3(i32* %data) #0 {
+; CHECK-LABEL: @vnum_test3(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 3
+; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 4
+; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
+; CHECK-NEXT: br label [[BB4:%.*]]
+; CHECK: bb4:
+; CHECK-NEXT: [[N_0:%.*]] = phi i32 [ [[TMP3]], [[BB:%.*]] ], [ [[TMP19:%.*]], [[BB21:%.*]] ]
+; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP22:%.*]], [[BB21]] ]
+; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[I_0]], [[TMP1]]
+; CHECK-NEXT: br i1 [[TMP5]], label [[BB6:%.*]], label [[BB23:%.*]]
+; CHECK: bb6:
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 2
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 5
+; CHECK-NEXT: store i32 0, i32* [[TMP9]], align 4
+; CHECK-NEXT: [[TMP10:%.*]] = icmp slt i32 [[I_0]], 30
+; CHECK-NEXT: br i1 [[TMP10]], label [[BB11:%.*]], label [[BB14:%.*]]
+; CHECK: bb11:
+; CHECK-NEXT: store i32 0, i32* [[TMP9]], align 4
+; CHECK-NEXT: br label [[BB14]]
+; CHECK: bb14:
+; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, i32* [[DATA]], i64 1
+; CHECK-NEXT: [[TMP18:%.*]] = load i32, i32* [[TMP17]], align 4
+; CHECK-NEXT: [[TMP19]] = add nsw i32 [[N_0]], [[TMP18]]
+; CHECK-NEXT: br label [[BB21]]
+; CHECK: bb21:
+; CHECK-NEXT: [[TMP22]] = add nsw i32 [[I_0]], 1
+; CHECK-NEXT: br label [[BB4]]
+; CHECK: bb23:
+; CHECK-NEXT: ret i32 0
+;
+bb:
+ %tmp = getelementptr inbounds i32, i32* %data, i64 3
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = getelementptr inbounds i32, i32* %data, i64 4
+ %tmp3 = load i32, i32* %tmp2, align 4
+ br label %bb4
+
+bb4: ; preds = %bb21, %bb
+ %n.0 = phi i32 [ %tmp3, %bb ], [ %tmp20, %bb21 ]
+ %m.0 = phi i32 [ %tmp3, %bb ], [ %tmp19, %bb21 ]
+ %p.0 = phi i32 [ 0, %bb ], [ %tmp16, %bb21 ]
+ %i.0 = phi i32 [ 0, %bb ], [ %tmp22, %bb21 ]
+ %tmp5 = icmp slt i32 %i.0, %tmp1
+ br i1 %tmp5, label %bb6, label %bb23
+
+bb6: ; preds = %bb4
+ %tmp7 = getelementptr inbounds i32, i32* %data, i64 2
+ %tmp8 = load i32, i32* %tmp7, align 4
+ %tmp9 = getelementptr inbounds i32, i32* %data, i64 5
+ store i32 0, i32* %tmp9, align 4
+ %tmp10 = icmp slt i32 %i.0, 30
+ br i1 %tmp10, label %bb11, label %bb14
+
+bb11: ; preds = %bb6
+ %tmp12 = sub nsw i32 %m.0, %n.0
+ %tmp13 = getelementptr inbounds i32, i32* %data, i64 5
+ store i32 %tmp12, i32* %tmp13, align 4
+ br label %bb14
+
+bb14: ; preds = %bb11, %bb6
+ %tmp15 = getelementptr inbounds i32, i32* %data, i64 5
+ %tmp16 = load i32, i32* %tmp15, align 4
+ %tmp17 = getelementptr inbounds i32, i32* %data, i64 1
+ %tmp18 = load i32, i32* %tmp17, align 4
+ %tmp19 = add nsw i32 %m.0, %tmp18
+ %tmp20 = add nsw i32 %n.0, %tmp18
+ br label %bb21
+
+bb21: ; preds = %bb14
+ %tmp22 = add nsw i32 %i.0, 1
+ br label %bb4
+
+bb23: ; preds = %bb4
+ ret i32 %p.0
+}
+
+attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.ident = !{!0, !0, !0}
+
+!0 = !{!"Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)"}
diff --git a/test/Transforms/NewGVN/cyclic-phi-handling.ll b/test/Transforms/NewGVN/cyclic-phi-handling.ll
new file mode 100644
index 0000000000000..283c78548995d
--- /dev/null
+++ b/test/Transforms/NewGVN/cyclic-phi-handling.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @foo(i32 %arg, i32 %arg1, i32 (i32, i32)* %arg2) {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: br label %bb3
+; CHECK: bb3:
+; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ %arg1, %bb ], [ [[TMP:%.*]]4, %bb7 ]
+; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ %arg, %bb ], [ [[TMP]], %bb7 ]
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 %arg2(i32 [[TMP4]], i32 [[TMP]])
+; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0
+; CHECK-NEXT: br i1 [[TMP6]], label %bb7, label %bb8
+; CHECK: bb7:
+; CHECK-NEXT: br label %bb3
+; CHECK: bb8:
+; CHECK-NEXT: ret void
+;
+bb:
+ br label %bb3
+
+;; While non-standard, llvm allows mutually dependent phi nodes
+;; Ensure we do not infinite loop trying to process them
+bb3: ; preds = %bb7, %bb
+ %tmp = phi i32 [ %arg1, %bb ], [ %tmp4, %bb7 ]
+ %tmp4 = phi i32 [ %arg, %bb ], [ %tmp, %bb7 ]
+ %tmp5 = call i32 %arg2(i32 %tmp4, i32 %tmp)
+ %tmp6 = icmp ne i32 %tmp5, 0
+ br i1 %tmp6, label %bb7, label %bb8
+
+bb7: ; preds = %bb3
+ br label %bb3
+
+bb8: ; preds = %bb3
+ ret void
+}
diff --git a/test/Transforms/NewGVN/invariant.group.ll b/test/Transforms/NewGVN/invariant.group.ll
index 2bddc99c8b855..80c6e05a8e24e 100644
--- a/test/Transforms/NewGVN/invariant.group.ll
+++ b/test/Transforms/NewGVN/invariant.group.ll
@@ -345,11 +345,63 @@ _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: %trunc = trunc i8 %b to i1
+ %2 = load i1, i1* %b0, !invariant.group !0
+; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %trunc)
+ call void @fooBit(i1* %b0, i1 %2)
+ %3 = load i1, i1* %b0, !invariant.group !0
+; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %trunc)
+ call void @fooBit(i1* %b0, i1 %3)
+ 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.invariant.group.barrier(i8*)
; Function Attrs: nounwind
diff --git a/test/Transforms/NewGVN/memory-handling.ll b/test/Transforms/NewGVN/memory-handling.ll
new file mode 100644
index 0000000000000..a0c4a998b8b6a
--- /dev/null
+++ b/test/Transforms/NewGVN/memory-handling.ll
@@ -0,0 +1,195 @@
+;; This test is really dependent on propagating a lot of memory info around, but in the end, not
+;; screwing up a single add.
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.Letter = type { i32, i32, i32, i32 }
+
+@alPhrase = external local_unnamed_addr global [26 x %struct.Letter], align 16
+@aqMainMask = external local_unnamed_addr global [2 x i64], align 16
+@aqMainSign = external local_unnamed_addr global [2 x i64], align 16
+@cchPhraseLength = external local_unnamed_addr global i32, align 4
+@auGlobalFrequency = external local_unnamed_addr global [26 x i32], align 16
+@.str.7 = external hidden unnamed_addr constant [28 x i8], align 1
+
+; Function Attrs: nounwind uwtable
+declare void @Fatal(i8*, i32) local_unnamed_addr #0
+
+; Function Attrs: nounwind readnone
+declare i16** @__ctype_b_loc() local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define void @BuildMask(i8* nocapture readonly) local_unnamed_addr #0 {
+ tail call void @llvm.memset.p0i8.i64(i8* bitcast ([26 x %struct.Letter]* @alPhrase to i8*), i8 0, i64 416, i32 16, i1 false)
+ tail call void @llvm.memset.p0i8.i64(i8* bitcast ([2 x i64]* @aqMainMask to i8*), i8 0, i64 16, i32 16, i1 false)
+ tail call void @llvm.memset.p0i8.i64(i8* bitcast ([2 x i64]* @aqMainSign to i8*), i8 0, i64 16, i32 16, i1 false)
+ br label %.sink.split
+
+.sink.split: ; preds = %14, %1
+ %.0 = phi i8* [ %0, %1 ], [ %.lcssa67, %14 ]
+ %.sink = phi i32 [ 0, %1 ], [ %23, %14 ]
+ store i32 %.sink, i32* @cchPhraseLength, align 4, !tbaa !1
+ br label %2
+
+; <label>:2: ; preds = %6, %.sink.split
+ %.1 = phi i8* [ %.0, %.sink.split ], [ %3, %6 ]
+ %3 = getelementptr inbounds i8, i8* %.1, i64 1
+ %4 = load i8, i8* %.1, align 1, !tbaa !5
+ %5 = icmp eq i8 %4, 0
+ br i1 %5, label %.preheader.preheader, label %6
+
+.preheader.preheader: ; preds = %2
+ br label %.preheader
+
+; <label>:6: ; preds = %2
+ %7 = tail call i16** @__ctype_b_loc() #4
+ %8 = load i16*, i16** %7, align 8, !tbaa !6
+ %9 = sext i8 %4 to i64
+ %10 = getelementptr inbounds i16, i16* %8, i64 %9
+ %11 = load i16, i16* %10, align 2, !tbaa !8
+ %12 = and i16 %11, 1024
+ %13 = icmp eq i16 %12, 0
+ br i1 %13, label %2, label %14
+
+; <label>:14: ; preds = %6
+ %.lcssa67 = phi i8* [ %3, %6 ]
+ %.lcssa65 = phi i8 [ %4, %6 ]
+ %15 = sext i8 %.lcssa65 to i32
+ %16 = tail call i32 @tolower(i32 %15) #5
+ %17 = add nsw i32 %16, -97
+ %18 = sext i32 %17 to i64
+ %19 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %18, i32 0
+ %20 = load i32, i32* %19, align 16, !tbaa !10
+ %21 = add i32 %20, 1
+ store i32 %21, i32* %19, align 16, !tbaa !10
+ %22 = load i32, i32* @cchPhraseLength, align 4, !tbaa !1
+ %23 = add nsw i32 %22, 1
+ br label %.sink.split
+
+.preheader: ; preds = %58, %.preheader.preheader
+ %indvars.iv = phi i64 [ 0, %.preheader.preheader ], [ %indvars.iv.next, %58 ]
+ %.04961 = phi i32 [ %.2, %58 ], [ 0, %.preheader.preheader ]
+ %.05160 = phi i32 [ %.253, %58 ], [ 0, %.preheader.preheader ]
+ %24 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 0
+ %25 = load i32, i32* %24, align 16, !tbaa !10
+ %26 = icmp eq i32 %25, 0
+ %27 = getelementptr inbounds [26 x i32], [26 x i32]* @auGlobalFrequency, i64 0, i64 %indvars.iv
+ br i1 %26, label %28, label %29
+
+; <label>:28: ; preds = %.preheader
+ store i32 -1, i32* %27, align 4, !tbaa !1
+ br label %58
+
+; <label>:29: ; preds = %.preheader
+ store i32 0, i32* %27, align 4, !tbaa !1
+ %30 = zext i32 %25 to i64
+ br i1 false, label %._crit_edge, label %.lr.ph.preheader
+
+.lr.ph.preheader: ; preds = %29
+ br label %.lr.ph
+
+.lr.ph: ; preds = %.lr.ph, %.lr.ph.preheader
+ %.04658 = phi i64 [ %32, %.lr.ph ], [ 1, %.lr.ph.preheader ]
+ %.04857 = phi i32 [ %31, %.lr.ph ], [ 1, %.lr.ph.preheader ]
+ %31 = add nuw nsw i32 %.04857, 1
+ %32 = shl i64 %.04658, 1
+ %33 = icmp ult i64 %30, %32
+ br i1 %33, label %._crit_edge.loopexit, label %.lr.ph
+
+._crit_edge.loopexit: ; preds = %.lr.ph
+ %.lcssa63 = phi i32 [ %31, %.lr.ph ]
+ %.lcssa = phi i64 [ %32, %.lr.ph ]
+ br label %._crit_edge
+
+._crit_edge: ; preds = %._crit_edge.loopexit, %29
+ %.048.lcssa = phi i32 [ 1, %29 ], [ %.lcssa63, %._crit_edge.loopexit ]
+ %.046.lcssa = phi i64 [ 1, %29 ], [ %.lcssa, %._crit_edge.loopexit ]
+ %34 = add nsw i32 %.048.lcssa, %.04961
+ %35 = icmp ugt i32 %34, 64
+ br i1 %35, label %36, label %40
+
+; <label>:36: ; preds = %._crit_edge
+; This testcase essentially comes down to this little add.
+; If we screw up the revisitation of the users of store of %sink above
+; we will end up propagating and simplifying this to 1 in the final output
+; because we keep an optimistic assumption we should not.
+; CHECK: add i32 %.05160, 1
+ %37 = add i32 %.05160, 1
+ %38 = icmp ugt i32 %37, 1
+ br i1 %38, label %39, label %40
+
+; <label>:39: ; preds = %36
+ tail call void @Fatal(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.7, i64 0, i64 0), i32 0)
+ br label %40
+
+; <label>:40: ; preds = %39, %36, %._crit_edge
+ %.152 = phi i32 [ %.05160, %._crit_edge ], [ %37, %39 ], [ %37, %36 ]
+ %.150 = phi i32 [ %.04961, %._crit_edge ], [ 0, %39 ], [ 0, %36 ]
+ %41 = add i64 %.046.lcssa, 4294967295
+ %42 = trunc i64 %41 to i32
+ %43 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 2
+ store i32 %42, i32* %43, align 8, !tbaa !12
+ %44 = zext i32 %.150 to i64
+ %.046. = shl i64 %.046.lcssa, %44
+ %45 = zext i32 %.152 to i64
+ %46 = getelementptr inbounds [2 x i64], [2 x i64]* @aqMainSign, i64 0, i64 %45
+ %47 = load i64, i64* %46, align 8, !tbaa !13
+ %48 = or i64 %47, %.046.
+ store i64 %48, i64* %46, align 8, !tbaa !13
+ %49 = load i32, i32* %24, align 16, !tbaa !10
+ %50 = zext i32 %49 to i64
+ %51 = shl i64 %50, %44
+ %52 = getelementptr inbounds [2 x i64], [2 x i64]* @aqMainMask, i64 0, i64 %45
+ %53 = load i64, i64* %52, align 8, !tbaa !13
+ %54 = or i64 %51, %53
+ store i64 %54, i64* %52, align 8, !tbaa !13
+ %55 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 1
+ store i32 %.150, i32* %55, align 4, !tbaa !15
+ %56 = getelementptr inbounds [26 x %struct.Letter], [26 x %struct.Letter]* @alPhrase, i64 0, i64 %indvars.iv, i32 3
+ store i32 %.152, i32* %56, align 4, !tbaa !16
+ %57 = add nsw i32 %.150, %.048.lcssa
+ br label %58
+
+; <label>:58: ; preds = %40, %28
+ %.253 = phi i32 [ %.05160, %28 ], [ %.152, %40 ]
+ %.2 = phi i32 [ %.04961, %28 ], [ %57, %40 ]
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %exitcond = icmp ne i64 %indvars.iv.next, 26
+ br i1 %exitcond, label %.preheader, label %59
+
+; <label>:59: ; preds = %58
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #2
+
+; Function Attrs: inlinehint nounwind readonly uwtable
+declare i32 @tolower(i32) local_unnamed_addr #3
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { argmemonly nounwind }
+attributes #3 = { inlinehint nounwind readonly uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind readnone }
+attributes #5 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 4.0.0 (http://llvm.org/git/clang.git 9b9db7fa41a1905899dbcbcc6cbdd05d2511da8e) (/Users/dannyb/sources/llvm-clean a3908a41623f6ac14ba8c04613d6c64e0544bb5d)"}
+!1 = !{!2, !2, i64 0}
+!2 = !{!"int", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!3, !3, i64 0}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"any pointer", !3, i64 0}
+!8 = !{!9, !9, i64 0}
+!9 = !{!"short", !3, i64 0}
+!10 = !{!11, !2, i64 0}
+!11 = !{!"", !2, i64 0, !2, i64 4, !2, i64 8, !2, i64 12}
+!12 = !{!11, !2, i64 8}
+!13 = !{!14, !14, i64 0}
+!14 = !{!"long", !3, i64 0}
+!15 = !{!11, !2, i64 4}
+!16 = !{!11, !2, i64 12}
diff --git a/test/Transforms/NewGVN/pr31501.ll b/test/Transforms/NewGVN/pr31501.ll
new file mode 100644
index 0000000000000..7122ade56eeb6
--- /dev/null
+++ b/test/Transforms/NewGVN/pr31501.ll
@@ -0,0 +1,136 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+%struct.foo = type { %struct.wombat.28*, %struct.zot, %struct.wombat.28* }
+%struct.zot = type { i64 }
+%struct.barney = type <{ %struct.wombat.28*, %struct.wibble, %struct.snork, %struct.quux.4, %struct.snork.10, %struct.ham.16*, %struct.wobble.23*, i32, i8, i8, [2 x i8] }>
+%struct.wibble = type { %struct.pluto, %struct.bar }
+%struct.pluto = type { %struct.quux }
+%struct.quux = type { %struct.eggs }
+%struct.eggs = type { %struct.zot.0, %struct.widget }
+%struct.zot.0 = type { i8*, i8*, i8* }
+%struct.widget = type { %struct.barney.1 }
+%struct.barney.1 = type { [8 x i8] }
+%struct.bar = type { [3 x %struct.widget] }
+%struct.snork = type <{ %struct.wobble, %struct.bar.3, [7 x i8] }>
+%struct.wobble = type { %struct.wombat }
+%struct.wombat = type { %struct.zot.2 }
+%struct.zot.2 = type { %struct.zot.0, %struct.ham }
+%struct.ham = type { %struct.barney.1 }
+%struct.bar.3 = type { i8 }
+%struct.quux.4 = type <{ %struct.quux.5, %struct.snork.9, [7 x i8] }>
+%struct.quux.5 = type { %struct.widget.6 }
+%struct.widget.6 = type { %struct.spam }
+%struct.spam = type { %struct.zot.0, %struct.ham.7 }
+%struct.ham.7 = type { %struct.barney.8 }
+%struct.barney.8 = type { [24 x i8] }
+%struct.snork.9 = type { i8 }
+%struct.snork.10 = type <{ %struct.foo.11, %struct.spam.15, [7 x i8] }>
+%struct.foo.11 = type { %struct.snork.12 }
+%struct.snork.12 = type { %struct.wombat.13 }
+%struct.wombat.13 = type { %struct.zot.0, %struct.wibble.14 }
+%struct.wibble.14 = type { %struct.barney.8 }
+%struct.spam.15 = type { i8 }
+%struct.ham.16 = type { %struct.pluto.17, %struct.pluto.17 }
+%struct.pluto.17 = type { %struct.bar.18 }
+%struct.bar.18 = type { %struct.baz*, %struct.zot.20, %struct.barney.22 }
+%struct.baz = type { %struct.wibble.19* }
+%struct.wibble.19 = type <{ %struct.baz, %struct.wibble.19*, %struct.baz*, i8, [7 x i8] }>
+%struct.zot.20 = type { %struct.ham.21 }
+%struct.ham.21 = type { %struct.baz }
+%struct.barney.22 = type { %struct.blam }
+%struct.blam = type { i64 }
+%struct.wobble.23 = type { %struct.spam.24, %struct.barney* }
+%struct.spam.24 = type { %struct.bar.25, %struct.zot.26* }
+%struct.bar.25 = type <{ i32 (...)**, i8, i8 }>
+%struct.zot.26 = type { i32 (...)**, i32, %struct.widget.27* }
+%struct.widget.27 = type { %struct.zot.26, %struct.zot.26* }
+%struct.wombat.28 = type <{ i32 (...)**, i8, i8, [6 x i8] }>
+
+; Function Attrs: norecurse nounwind ssp uwtable
+define weak_odr hidden %struct.foo* @quux(%struct.barney* %arg, %struct.wombat.28* %arg1) local_unnamed_addr #0 align 2 {
+; CHECK-LABEL: @quux(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0
+; CHECK-NEXT: [[TMP2:%.*]] = bitcast %struct.spam* [[TMP]] to %struct.foo**
+; CHECK-NEXT: [[TMP3:%.*]] = load %struct.foo*, %struct.foo** [[TMP2]], align 8, !tbaa !2
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0, i32 0, i32 1
+; CHECK-NEXT: [[TMP5:%.*]] = bitcast i8** [[TMP4]] to %struct.foo**
+; CHECK-NEXT: [[TMP6:%.*]] = load %struct.foo*, %struct.foo** [[TMP5]], align 8, !tbaa !7
+; CHECK-NEXT: [[TMP7:%.*]] = icmp eq %struct.foo* [[TMP3]], [[TMP6]]
+; CHECK-NEXT: br i1 [[TMP7]], label %bb21, label %bb8
+; CHECK: bb8:
+; CHECK-NEXT: br label %bb11
+; CHECK: bb9:
+; CHECK-NEXT: [[TMP10:%.*]] = icmp eq %struct.foo* [[TMP18:%.*]], [[TMP6]]
+; CHECK-NEXT: br i1 [[TMP10]], label %bb19, label %bb11
+; CHECK: bb11:
+; CHECK-NEXT: [[TMP12:%.*]] = phi %struct.foo* [ [[TMP17:%.*]], %bb9 ], [ undef, %bb8 ]
+; CHECK-NEXT: [[TMP13:%.*]] = phi %struct.foo* [ [[TMP18]], %bb9 ], [ [[TMP3]], %bb8 ]
+; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds %struct.foo, %struct.foo* [[TMP13]], i64 0, i32 0
+; CHECK-NEXT: [[TMP15:%.*]] = load %struct.wombat.28*, %struct.wombat.28** [[TMP14]], align 8, !tbaa !8
+; CHECK-NEXT: [[TMP16:%.*]] = icmp eq %struct.wombat.28* [[TMP15]], %arg1
+; CHECK-NEXT: [[TMP17]] = select i1 [[TMP16]], %struct.foo* [[TMP13]], %struct.foo* [[TMP12]]
+; CHECK-NEXT: [[TMP18]] = getelementptr inbounds %struct.foo, %struct.foo* [[TMP13]], i64 1
+; CHECK-NEXT: br i1 [[TMP16]], label %bb19, label %bb9
+; CHECK: bb19:
+; CHECK-NEXT: [[TMP20:%.*]] = phi %struct.foo* [ null, %bb9 ], [ [[TMP17]], %bb11 ]
+; CHECK-NEXT: br label %bb21
+; CHECK: bb21:
+; CHECK-NEXT: [[TMP22:%.*]] = phi %struct.foo* [ null, %bb ], [ [[TMP20]], %bb19 ]
+; CHECK-NEXT: ret %struct.foo* [[TMP22]]
+;
+bb:
+ %tmp = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0
+ %tmp2 = bitcast %struct.spam* %tmp to %struct.foo**
+ %tmp3 = load %struct.foo*, %struct.foo** %tmp2, align 8, !tbaa !2
+ %tmp4 = getelementptr inbounds %struct.barney, %struct.barney* %arg, i64 0, i32 3, i32 0, i32 0, i32 0, i32 0, i32 1
+ %tmp5 = bitcast i8** %tmp4 to %struct.foo**
+ %tmp6 = load %struct.foo*, %struct.foo** %tmp5, align 8, !tbaa !7
+ %tmp7 = icmp eq %struct.foo* %tmp3, %tmp6
+ br i1 %tmp7, label %bb21, label %bb8
+
+bb8: ; preds = %bb
+ br label %bb11
+
+bb9: ; preds = %bb11
+ %tmp10 = icmp eq %struct.foo* %tmp18, %tmp6
+ br i1 %tmp10, label %bb19, label %bb11
+
+bb11: ; preds = %bb9, %bb8
+ %tmp12 = phi %struct.foo* [ %tmp17, %bb9 ], [ undef, %bb8 ]
+ %tmp13 = phi %struct.foo* [ %tmp18, %bb9 ], [ %tmp3, %bb8 ]
+ %tmp14 = getelementptr inbounds %struct.foo, %struct.foo* %tmp13, i64 0, i32 0
+ %tmp15 = load %struct.wombat.28*, %struct.wombat.28** %tmp14, align 8, !tbaa !8
+ %tmp16 = icmp eq %struct.wombat.28* %tmp15, %arg1
+ %tmp17 = select i1 %tmp16, %struct.foo* %tmp13, %struct.foo* %tmp12
+ %tmp18 = getelementptr inbounds %struct.foo, %struct.foo* %tmp13, i64 1
+ br i1 %tmp16, label %bb19, label %bb9
+
+bb19: ; preds = %bb11, %bb9
+ %tmp20 = phi %struct.foo* [ null, %bb9 ], [ %tmp17, %bb11 ]
+ br label %bb21
+
+bb21: ; preds = %bb19, %bb
+ %tmp22 = phi %struct.foo* [ null, %bb ], [ %tmp20, %bb19 ]
+ ret %struct.foo* %tmp22
+}
+
+attributes #0 = { norecurse nounwind ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"PIC Level", i32 2}
+!1 = !{!"clang version 4.0.0 (http://llvm.org/git/clang.git b63fa9e2bb8aac0a80c3e3467991c6b1a4b01e6a) (llvm/trunk 290779)"}
+!2 = !{!3, !4, i64 0}
+!3 = !{!"_ZTSN4llvm15SmallVectorBaseE", !4, i64 0, !4, i64 8, !4, i64 16}
+!4 = !{!"any pointer", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple C++ TBAA"}
+!7 = !{!3, !4, i64 8}
+!8 = !{!9, !4, i64 0}
+!9 = !{!"_ZTSN4llvm9RecordValE", !4, i64 0, !10, i64 8, !4, i64 16}
+!10 = !{!"_ZTSN4llvm14PointerIntPairIPNS_5RecTyELj1EbNS_21PointerLikeTypeTraitsIS2_EENS_18PointerIntPairInfoIS2_Lj1ES4_EEEE", !11, i64 0}
+!11 = !{!"long", !5, i64 0}
diff --git a/test/Transforms/NewGVN/pr31573.ll b/test/Transforms/NewGVN/pr31573.ll
new file mode 100644
index 0000000000000..0450b4b1299be
--- /dev/null
+++ b/test/Transforms/NewGVN/pr31573.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -basicaa -newgvn -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @patatino(i8* %blah) {
+; CHECK-LABEL: @patatino(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[WHILE_COND:%.*]]
+; CHECK: while.cond:
+; CHECK-NEXT: [[MEH:%.*]] = phi i8* [ [[BLAH:%.*]], [[ENTRY:%.*]] ], [ null, [[WHILE_BODY:%.*]] ]
+; CHECK-NEXT: switch i32 undef, label [[WHILE_BODY]] [
+; CHECK-NEXT: i32 666, label [[WHILE_END:%.*]]
+; CHECK-NEXT: ]
+; CHECK: while.body:
+; CHECK-NEXT: br label [[WHILE_COND]]
+; CHECK: while.end:
+; CHECK-NEXT: store i8 0, i8* [[MEH]], align 1
+; CHECK-NEXT: store i8 0, i8* [[BLAH]], align 1
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %while.cond
+
+while.cond:
+ %meh = phi i8* [ %blah, %entry ], [ null, %while.body ]
+ switch i32 undef, label %while.body [
+ i32 666, label %while.end
+ ]
+
+while.body:
+ br label %while.cond
+
+while.end:
+;; These two stores will initially be considered equivalent, but then proven not.
+;; the second store would previously end up deciding it's equivalent to a previous
+;; store, but it was really just finding an optimistic version of itself
+;; in the congruence class.
+ store i8 0, i8* %meh, align 1
+ store i8 0, i8* %blah, align 1
+ ret void
+}