summaryrefslogtreecommitdiff
path: root/test/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms')
-rw-r--r--test/Transforms/InstCombine/2008-09-29-FoldingOr.ll10
-rw-r--r--test/Transforms/InstCombine/AMDGPU/amdgcn-demanded-vector-elts.ll (renamed from test/Transforms/InstCombine/amdgcn-demanded-vector-elts.ll)0
-rw-r--r--test/Transforms/InstCombine/NVPTX/lit.local.cfg2
-rw-r--r--test/Transforms/InstCombine/NVPTX/nvvm-intrins.ll (renamed from test/Transforms/InstCombine/nvvm-intrins.ll)0
-rw-r--r--test/Transforms/InstCombine/cast.ll52
-rw-r--r--test/Transforms/InstCombine/lshr.ll72
-rw-r--r--test/Transforms/InstCombine/memchr.ll9
-rw-r--r--test/Transforms/InstCombine/set.ll94
-rw-r--r--test/Transforms/InstCombine/wcslen-1.ll191
-rw-r--r--test/Transforms/InstCombine/wcslen-2.ll18
-rw-r--r--test/Transforms/InstCombine/wcslen-3.ll197
-rw-r--r--test/Transforms/InstSimplify/AndOrXor.ll76
-rw-r--r--test/Transforms/InstSimplify/icmp-bool-constant.ll171
-rw-r--r--test/Transforms/JumpThreading/assume.ll44
-rw-r--r--test/Transforms/JumpThreading/fold-not-thread.ll4
-rw-r--r--test/Transforms/JumpThreading/guards.ll94
-rw-r--r--test/Transforms/LoopStrengthReduce/X86/canonical-2.ll36
-rw-r--r--test/Transforms/NewGVN/completeness.ll415
-rw-r--r--test/Transforms/NewGVN/pr32838.ll157
-rw-r--r--test/Transforms/NewGVN/pr32845.ll64
-rw-r--r--test/Transforms/NewGVN/pr32897.ll26
-rw-r--r--test/Transforms/NewGVN/pr32945.ll24
-rw-r--r--test/Transforms/NewGVN/pr33014.ll54
-rw-r--r--test/Transforms/NewGVN/pr33086.ll59
-rw-r--r--test/Transforms/NewGVN/pr33116.ll39
-rw-r--r--test/Transforms/NewGVN/storeoverstore.ll20
-rw-r--r--test/Transforms/SafeStack/X86/coloring-ssp.ll2
-rw-r--r--test/Transforms/SafeStack/X86/coloring.ll4
-rw-r--r--test/Transforms/SafeStack/X86/coloring2.ll4
-rw-r--r--test/Transforms/SafeStack/X86/layout-frag.ll2
30 files changed, 1902 insertions, 38 deletions
diff --git a/test/Transforms/InstCombine/2008-09-29-FoldingOr.ll b/test/Transforms/InstCombine/2008-09-29-FoldingOr.ll
deleted file mode 100644
index 4d00d495a07f4..0000000000000
--- a/test/Transforms/InstCombine/2008-09-29-FoldingOr.ll
+++ /dev/null
@@ -1,10 +0,0 @@
-; RUN: opt < %s -instcombine -S | grep "or i1"
-; PR2844
-
-define i32 @test(i32 %p_74) {
- %A = icmp eq i32 %p_74, 0 ; <i1> [#uses=1]
- %B = icmp slt i32 %p_74, -638208501 ; <i1> [#uses=1]
- %or.cond = or i1 %A, %B ; <i1> [#uses=1]
- %iftmp.10.0 = select i1 %or.cond, i32 0, i32 1 ; <i32> [#uses=1]
- ret i32 %iftmp.10.0
-}
diff --git a/test/Transforms/InstCombine/amdgcn-demanded-vector-elts.ll b/test/Transforms/InstCombine/AMDGPU/amdgcn-demanded-vector-elts.ll
index 0c4842c159880..0c4842c159880 100644
--- a/test/Transforms/InstCombine/amdgcn-demanded-vector-elts.ll
+++ b/test/Transforms/InstCombine/AMDGPU/amdgcn-demanded-vector-elts.ll
diff --git a/test/Transforms/InstCombine/NVPTX/lit.local.cfg b/test/Transforms/InstCombine/NVPTX/lit.local.cfg
new file mode 100644
index 0000000000000..2cb98eb371b21
--- /dev/null
+++ b/test/Transforms/InstCombine/NVPTX/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'NVPTX' in config.root.targets:
+ config.unsupported = True
diff --git a/test/Transforms/InstCombine/nvvm-intrins.ll b/test/Transforms/InstCombine/NVPTX/nvvm-intrins.ll
index cb65b8fdc5477..cb65b8fdc5477 100644
--- a/test/Transforms/InstCombine/nvvm-intrins.ll
+++ b/test/Transforms/InstCombine/NVPTX/nvvm-intrins.ll
diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll
index a4375a5cd57e8..486a617097e17 100644
--- a/test/Transforms/InstCombine/cast.ll
+++ b/test/Transforms/InstCombine/cast.ll
@@ -1470,3 +1470,55 @@ define i32 @test93(i32 %A) {
%D = trunc i96 %C to i32
ret i32 %D
}
+
+; The following four tests sext + lshr + trunc patterns.
+; PR33078
+
+define i8 @pr33078_1(i8 %A) {
+; CHECK-LABEL: @pr33078_1(
+; CHECK-NEXT: [[C:%.*]] = ashr i8 [[A:%.*]], 7
+; CHECK-NEXT: ret i8 [[C]]
+;
+ %B = sext i8 %A to i16
+ %C = lshr i16 %B, 8
+ %D = trunc i16 %C to i8
+ ret i8 %D
+}
+
+define i12 @pr33078_2(i8 %A) {
+; CHECK-LABEL: @pr33078_2(
+; CHECK-NEXT: [[C:%.*]] = ashr i8 [[A:%.*]], 4
+; CHECK-NEXT: [[D:%.*]] = sext i8 [[C]] to i12
+; CHECK-NEXT: ret i12 [[D]]
+;
+ %B = sext i8 %A to i16
+ %C = lshr i16 %B, 4
+ %D = trunc i16 %C to i12
+ ret i12 %D
+}
+
+define i4 @pr33078_3(i8 %A) {
+; CHECK-LABEL: @pr33078_3(
+; CHECK-NEXT: [[B:%.*]] = sext i8 [[A:%.*]] to i16
+; CHECK-NEXT: [[C:%.*]] = lshr i16 [[B]], 12
+; CHECK-NEXT: [[D:%.*]] = trunc i16 [[C]] to i4
+; CHECK-NEXT: ret i4 [[D]]
+;
+ %B = sext i8 %A to i16
+ %C = lshr i16 %B, 12
+ %D = trunc i16 %C to i4
+ ret i4 %D
+}
+
+define i8 @pr33078_4(i3 %x) {
+; Don't turn this in an `ashr`. This was getting miscompiled
+; CHECK-LABEL: @pr33078_4(
+; CHECK-NEXT: [[B:%.*]] = sext i3 %x to i16
+; CHECK-NEXT: [[C:%.*]] = lshr i16 [[B]], 13
+; CHECK-NEXT: [[D:%.*]] = trunc i16 [[C]] to i8
+; CHECK-NEXT: ret i8 [[D]]
+ %B = sext i3 %x to i16
+ %C = lshr i16 %B, 13
+ %D = trunc i16 %C to i8
+ ret i8 %D
+}
diff --git a/test/Transforms/InstCombine/lshr.ll b/test/Transforms/InstCombine/lshr.ll
index b81371b030429..0cad7f833ab6f 100644
--- a/test/Transforms/InstCombine/lshr.ll
+++ b/test/Transforms/InstCombine/lshr.ll
@@ -100,3 +100,75 @@ define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {
ret <2 x i8> %lshr
}
+; FIXME: The bool bit got smeared across a wide val, but then we zero'd out those bits. This is just a zext.
+
+define i16 @bool_zext(i1 %x) {
+; CHECK-LABEL: @bool_zext(
+; CHECK-NEXT: [[SEXT:%.*]] = sext i1 %x to i16
+; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 15
+; CHECK-NEXT: ret i16 [[HIBIT]]
+;
+ %sext = sext i1 %x to i16
+ %hibit = lshr i16 %sext, 15
+ ret i16 %hibit
+}
+
+define <2 x i8> @bool_zext_splat(<2 x i1> %x) {
+; CHECK-LABEL: @bool_zext_splat(
+; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i1> %x to <2 x i8>
+; CHECK-NEXT: [[HIBIT:%.*]] = lshr <2 x i8> [[SEXT]], <i8 7, i8 7>
+; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
+;
+ %sext = sext <2 x i1> %x to <2 x i8>
+ %hibit = lshr <2 x i8> %sext, <i8 7, i8 7>
+ ret <2 x i8> %hibit
+}
+
+; FIXME: The replicated sign bits are all that's left. This could be ashr+zext.
+
+define i16 @smear_sign_and_widen(i4 %x) {
+; CHECK-LABEL: @smear_sign_and_widen(
+; CHECK-NEXT: [[SEXT:%.*]] = sext i4 %x to i16
+; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
+; CHECK-NEXT: ret i16 [[HIBIT]]
+;
+ %sext = sext i4 %x to i16
+ %hibit = lshr i16 %sext, 12
+ ret i16 %hibit
+}
+
+define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
+; CHECK-LABEL: @smear_sign_and_widen_splat(
+; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i6> %x to <2 x i8>
+; CHECK-NEXT: [[HIBIT:%.*]] = lshr <2 x i8> [[SEXT]], <i8 2, i8 2>
+; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
+;
+ %sext = sext <2 x i6> %x to <2 x i8>
+ %hibit = lshr <2 x i8> %sext, <i8 2, i8 2>
+ ret <2 x i8> %hibit
+}
+
+; FIXME: All of the replicated sign bits are wiped out by the lshr. This could be lshr+zext.
+
+define i16 @fake_sext(i3 %x) {
+; CHECK-LABEL: @fake_sext(
+; CHECK-NEXT: [[SEXT:%.*]] = sext i3 %x to i16
+; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[SEXT]], 15
+; CHECK-NEXT: ret i16 [[SH]]
+;
+ %sext = sext i3 %x to i16
+ %sh = lshr i16 %sext, 15
+ ret i16 %sh
+}
+
+define <2 x i8> @fake_sext_splat(<2 x i3> %x) {
+; CHECK-LABEL: @fake_sext_splat(
+; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i3> %x to <2 x i8>
+; CHECK-NEXT: [[SH:%.*]] = lshr <2 x i8> [[SEXT]], <i8 7, i8 7>
+; CHECK-NEXT: ret <2 x i8> [[SH]]
+;
+ %sext = sext <2 x i3> %x to <2 x i8>
+ %sh = lshr <2 x i8> %sext, <i8 7, i8 7>
+ ret <2 x i8> %sh
+}
+
diff --git a/test/Transforms/InstCombine/memchr.ll b/test/Transforms/InstCombine/memchr.ll
index b0573567bf604..5a081c222fb02 100644
--- a/test/Transforms/InstCombine/memchr.ll
+++ b/test/Transforms/InstCombine/memchr.ll
@@ -190,3 +190,12 @@ define i1 @test15(i32 %C) {
%cmp = icmp ne i8* %dst, null
ret i1 %cmp
}
+
+@s = internal constant [1 x i8] [i8 0], align 1
+define i8* @pr32124() {
+; CHECK-LABEL: @pr32124(
+; CHECK-NEXT: ret i8* getelementptr inbounds ([1 x i8], [1 x i8]* @s, i32 0, i32 0)
+;
+ %res = tail call i8* @memchr(i8* getelementptr ([1 x i8], [1 x i8]* @s, i64 0, i64 0), i32 0, i32 1)
+ ret i8* %res
+}
diff --git a/test/Transforms/InstCombine/set.ll b/test/Transforms/InstCombine/set.ll
index 494a603790114..db2b4c3558e81 100644
--- a/test/Transforms/InstCombine/set.ll
+++ b/test/Transforms/InstCombine/set.ll
@@ -110,8 +110,8 @@ define i1 @test12(i1 %A) {
define i1 @test13(i1 %A, i1 %B) {
; CHECK-LABEL: @test13(
-; CHECK-NEXT: [[CTMP:%.*]] = xor i1 %B, true
-; CHECK-NEXT: [[C:%.*]] = or i1 [[CTMP]], %A
+; CHECK-NEXT: [[TMP1:%.*]] = xor i1 %B, true
+; CHECK-NEXT: [[C:%.*]] = or i1 [[TMP1]], %A
; CHECK-NEXT: ret i1 [[C]]
;
%C = icmp uge i1 %A, %B
@@ -120,8 +120,8 @@ define i1 @test13(i1 %A, i1 %B) {
define <2 x i1> @test13vec(<2 x i1> %A, <2 x i1> %B) {
; CHECK-LABEL: @test13vec(
-; CHECK-NEXT: [[CTMP:%.*]] = xor <2 x i1> %B, <i1 true, i1 true>
-; CHECK-NEXT: [[C:%.*]] = or <2 x i1> [[CTMP]], %A
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i1> %B, <i1 true, i1 true>
+; CHECK-NEXT: [[C:%.*]] = or <2 x i1> [[TMP1]], %A
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%C = icmp uge <2 x i1> %A, %B
@@ -130,8 +130,8 @@ define <2 x i1> @test13vec(<2 x i1> %A, <2 x i1> %B) {
define i1 @test14(i1 %A, i1 %B) {
; CHECK-LABEL: @test14(
-; CHECK-NEXT: [[CTMP:%.*]] = xor i1 %A, %B
-; CHECK-NEXT: [[C:%.*]] = xor i1 [[CTMP]], true
+; CHECK-NEXT: [[TMP1:%.*]] = xor i1 %A, %B
+; CHECK-NEXT: [[C:%.*]] = xor i1 [[TMP1]], true
; CHECK-NEXT: ret i1 [[C]]
;
%C = icmp eq i1 %A, %B
@@ -140,14 +140,88 @@ define i1 @test14(i1 %A, i1 %B) {
define <3 x i1> @test14vec(<3 x i1> %A, <3 x i1> %B) {
; CHECK-LABEL: @test14vec(
-; CHECK-NEXT: [[CTMP:%.*]] = xor <3 x i1> %A, %B
-; CHECK-NEXT: [[C:%.*]] = xor <3 x i1> [[CTMP]], <i1 true, i1 true, i1 true>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <3 x i1> %A, %B
+; CHECK-NEXT: [[C:%.*]] = xor <3 x i1> [[TMP1]], <i1 true, i1 true, i1 true>
; CHECK-NEXT: ret <3 x i1> [[C]]
;
%C = icmp eq <3 x i1> %A, %B
ret <3 x i1> %C
}
+define i1 @bool_eq0(i64 %a) {
+; CHECK-LABEL: @bool_eq0(
+; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 %a, 1
+; CHECK-NEXT: ret i1 [[TMP1]]
+;
+ %b = icmp sgt i64 %a, 0
+ %c = icmp eq i64 %a, 1
+ %notc = icmp eq i1 %c, false
+ %and = and i1 %b, %notc
+ ret i1 %and
+}
+
+; FIXME: This is equivalent to the previous test.
+
+define i1 @xor_of_icmps(i64 %a) {
+; CHECK-LABEL: @xor_of_icmps(
+; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 %a, 0
+; CHECK-NEXT: [[C:%.*]] = icmp eq i64 %a, 1
+; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[C]], [[B]]
+; CHECK-NEXT: ret i1 [[XOR]]
+;
+ %b = icmp sgt i64 %a, 0
+ %c = icmp eq i64 %a, 1
+ %xor = xor i1 %c, %b
+ ret i1 %xor
+}
+
+; FIXME: This is also equivalent to the previous test.
+
+define i1 @xor_of_icmps_commute(i64 %a) {
+; CHECK-LABEL: @xor_of_icmps_commute(
+; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 %a, 0
+; CHECK-NEXT: [[C:%.*]] = icmp eq i64 %a, 1
+; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[B]], [[C]]
+; CHECK-NEXT: ret i1 [[XOR]]
+;
+ %b = icmp sgt i64 %a, 0
+ %c = icmp eq i64 %a, 1
+ %xor = xor i1 %b, %c
+ ret i1 %xor
+}
+
+; FIXME: This is (a != 5).
+
+define i1 @xor_of_icmps_folds_more(i64 %a) {
+; CHECK-LABEL: @xor_of_icmps_folds_more(
+; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 %a, 4
+; CHECK-NEXT: [[C:%.*]] = icmp slt i64 %a, 6
+; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[B]], [[C]]
+; CHECK-NEXT: ret i1 [[XOR]]
+;
+ %b = icmp sgt i64 %a, 4
+ %c = icmp slt i64 %a, 6
+ %xor = xor i1 %b, %c
+ ret i1 %xor
+}
+
+; https://bugs.llvm.org/show_bug.cgi?id=2844
+
+define i32 @PR2844(i32 %x) {
+; CHECK-LABEL: @PR2844(
+; CHECK-NEXT: [[A:%.*]] = icmp eq i32 %x, 0
+; CHECK-NEXT: [[B:%.*]] = icmp sgt i32 %x, -638208502
+; CHECK-NEXT: [[NOT_OR:%.*]] = xor i1 [[A]], [[B]]
+; CHECK-NEXT: [[SEL:%.*]] = zext i1 [[NOT_OR]] to i32
+; CHECK-NEXT: ret i32 [[SEL]]
+;
+ %A = icmp eq i32 %x, 0
+ %B = icmp slt i32 %x, -638208501
+ %or = or i1 %A, %B
+ %sel = select i1 %or, i32 0, i32 1
+ ret i32 %sel
+}
+
define i1 @test16(i32 %A) {
; CHECK-LABEL: @test16(
; CHECK-NEXT: ret i1 false
@@ -191,8 +265,8 @@ endif:
define i1 @test19(i1 %A, i1 %B) {
; CHECK-LABEL: @test19(
-; CHECK-NEXT: [[CTMP:%.*]] = xor i1 %A, %B
-; CHECK-NEXT: [[C:%.*]] = xor i1 [[CTMP]], true
+; CHECK-NEXT: [[TMP1:%.*]] = xor i1 %A, %B
+; CHECK-NEXT: [[C:%.*]] = xor i1 [[TMP1]], true
; CHECK-NEXT: ret i1 [[C]]
;
%a = zext i1 %A to i32
diff --git a/test/Transforms/InstCombine/wcslen-1.ll b/test/Transforms/InstCombine/wcslen-1.ll
new file mode 100644
index 0000000000000..d4e51750f6da7
--- /dev/null
+++ b/test/Transforms/InstCombine/wcslen-1.ll
@@ -0,0 +1,191 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; Test that the wcslen library call simplifier works correctly.
+;
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+declare i64 @wcslen(i32*)
+
+@hello = constant [6 x i32] [i32 104, i32 101, i32 108, i32 108, i32 111, i32 0]
+@longer = constant [7 x i32] [i32 108, i32 111, i32 110, i32 103, i32 101, i32 114, i32 0]
+@null = constant [1 x i32] zeroinitializer
+@null_hello = constant [7 x i32] [i32 0, i32 104, i32 101, i32 108, i32 108, i32 111, i32 0]
+@nullstring = constant i32 0
+@a = common global [32 x i32] zeroinitializer, align 1
+@null_hello_mid = constant [13 x i32] [i32 104, i32 101, i32 108, i32 108, i32 111, i32 32, i32 119, i32 111, i32 114, i32 0, i32 108, i32 100, i32 0]
+
+define i64 @test_simplify1() {
+; CHECK-LABEL: @test_simplify1(
+; CHECK-NEXT: ret i64 5
+;
+ %hello_p = getelementptr [6 x i32], [6 x i32]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ ret i64 %hello_l
+}
+
+define i64 @test_simplify2() {
+; CHECK-LABEL: @test_simplify2(
+; CHECK-NEXT: ret i64 0
+;
+ %null_p = getelementptr [1 x i32], [1 x i32]* @null, i64 0, i64 0
+ %null_l = call i64 @wcslen(i32* %null_p)
+ ret i64 %null_l
+}
+
+define i64 @test_simplify3() {
+; CHECK-LABEL: @test_simplify3(
+; CHECK-NEXT: ret i64 0
+;
+ %null_hello_p = getelementptr [7 x i32], [7 x i32]* @null_hello, i64 0, i64 0
+ %null_hello_l = call i64 @wcslen(i32* %null_hello_p)
+ ret i64 %null_hello_l
+}
+
+define i64 @test_simplify4() {
+; CHECK-LABEL: @test_simplify4(
+; CHECK-NEXT: ret i64 0
+;
+ %len = tail call i64 @wcslen(i32* @nullstring) nounwind
+ ret i64 %len
+}
+
+; Check wcslen(x) == 0 --> *x == 0.
+
+define i1 @test_simplify5() {
+; CHECK-LABEL: @test_simplify5(
+; CHECK-NEXT: ret i1 false
+;
+ %hello_p = getelementptr [6 x i32], [6 x i32]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ %eq_hello = icmp eq i64 %hello_l, 0
+ ret i1 %eq_hello
+}
+
+define i1 @test_simplify6(i32* %str_p) {
+; CHECK-LABEL: @test_simplify6(
+; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i32, i32* [[STR_P:%.*]], align 4
+; CHECK-NEXT: [[EQ_NULL:%.*]] = icmp eq i32 [[STRLENFIRST]], 0
+; CHECK-NEXT: ret i1 [[EQ_NULL]]
+;
+ %str_l = call i64 @wcslen(i32* %str_p)
+ %eq_null = icmp eq i64 %str_l, 0
+ ret i1 %eq_null
+}
+
+; Check wcslen(x) != 0 --> *x != 0.
+
+define i1 @test_simplify7() {
+; CHECK-LABEL: @test_simplify7(
+; CHECK-NEXT: ret i1 true
+;
+ %hello_p = getelementptr [6 x i32], [6 x i32]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ %ne_hello = icmp ne i64 %hello_l, 0
+ ret i1 %ne_hello
+}
+
+define i1 @test_simplify8(i32* %str_p) {
+; CHECK-LABEL: @test_simplify8(
+; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i32, i32* [[STR_P:%.*]], align 4
+; CHECK-NEXT: [[NE_NULL:%.*]] = icmp ne i32 [[STRLENFIRST]], 0
+; CHECK-NEXT: ret i1 [[NE_NULL]]
+;
+ %str_l = call i64 @wcslen(i32* %str_p)
+ %ne_null = icmp ne i64 %str_l, 0
+ ret i1 %ne_null
+}
+
+define i64 @test_simplify9(i1 %x) {
+; CHECK-LABEL: @test_simplify9(
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i64 5, i64 6
+; CHECK-NEXT: ret i64 [[TMP1]]
+;
+ %hello = getelementptr [6 x i32], [6 x i32]* @hello, i64 0, i64 0
+ %longer = getelementptr [7 x i32], [7 x i32]* @longer, i64 0, i64 0
+ %s = select i1 %x, i32* %hello, i32* %longer
+ %l = call i64 @wcslen(i32* %s)
+ ret i64 %l
+}
+
+; Check the case that should be simplified to a sub instruction.
+; wcslen(@hello + x) --> 5 - x
+
+define i64 @test_simplify10(i32 %x) {
+; CHECK-LABEL: @test_simplify10(
+; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[X:%.*]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i64 5, [[TMP1]]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %hello_p = getelementptr inbounds [6 x i32], [6 x i32]* @hello, i32 0, i32 %x
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ ret i64 %hello_l
+}
+
+; wcslen(@null_hello_mid + (x & 7)) --> 9 - (x & 7)
+
+define i64 @test_simplify11(i32 %x) {
+; CHECK-LABEL: @test_simplify11(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 7
+; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[AND]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i64 9, [[TMP1]]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %and = and i32 %x, 7
+ %hello_p = getelementptr inbounds [13 x i32], [13 x i32]* @null_hello_mid, i32 0, i32 %and
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ ret i64 %hello_l
+}
+
+; Check cases that shouldn't be simplified.
+
+define i64 @test_no_simplify1() {
+; CHECK-LABEL: @test_no_simplify1(
+; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i32* getelementptr inbounds ([32 x i32], [32 x i32]* @a, i64 0, i64 0))
+; CHECK-NEXT: ret i64 [[A_L]]
+;
+ %a_p = getelementptr [32 x i32], [32 x i32]* @a, i64 0, i64 0
+ %a_l = call i64 @wcslen(i32* %a_p)
+ ret i64 %a_l
+}
+
+; wcslen(@null_hello + x) should not be simplified to a sub instruction.
+
+define i64 @test_no_simplify2(i32 %x) {
+; CHECK-LABEL: @test_no_simplify2(
+; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[X:%.*]] to i64
+; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @null_hello, i64 0, i64 [[TMP1]]
+; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i32* [[HELLO_P]])
+; CHECK-NEXT: ret i64 [[HELLO_L]]
+;
+ %hello_p = getelementptr inbounds [7 x i32], [7 x i32]* @null_hello, i32 0, i32 %x
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ ret i64 %hello_l
+}
+
+; wcslen(@null_hello_mid + (x & 15)) should not be simplified to a sub instruction.
+
+define i64 @test_no_simplify3(i32 %x) {
+; CHECK-LABEL: @test_no_simplify3(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 15
+; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[AND]] to i64
+; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [13 x i32], [13 x i32]* @null_hello_mid, i64 0, i64 [[TMP1]]
+; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i32* [[HELLO_P]])
+; CHECK-NEXT: ret i64 [[HELLO_L]]
+;
+ %and = and i32 %x, 15
+ %hello_p = getelementptr inbounds [13 x i32], [13 x i32]* @null_hello_mid, i32 0, i32 %and
+ %hello_l = call i64 @wcslen(i32* %hello_p)
+ ret i64 %hello_l
+}
+
+@str16 = constant [1 x i16] [i16 0]
+
+define i64 @test_no_simplify4() {
+; CHECK-LABEL: @test_no_simplify4(
+; CHECK-NEXT: [[L:%.*]] = call i64 @wcslen(i32* bitcast ([1 x i16]* @str16 to i32*))
+; CHECK-NEXT: ret i64 [[L]]
+;
+ %l = call i64 @wcslen(i32* bitcast ([1 x i16]* @str16 to i32*))
+ ret i64 %l
+}
diff --git a/test/Transforms/InstCombine/wcslen-2.ll b/test/Transforms/InstCombine/wcslen-2.ll
new file mode 100644
index 0000000000000..c1a70312a2b36
--- /dev/null
+++ b/test/Transforms/InstCombine/wcslen-2.ll
@@ -0,0 +1,18 @@
+; Test that the wcslen library call simplifier works correctly.
+;
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+@hello = constant [6 x i32] [i32 104, i32 101, i32 108, i32 108, i32 111, i32 0]
+
+declare i64 @wcslen(i32*, i32)
+
+define i64 @test_no_simplify1() {
+; CHECK-LABEL: @test_no_simplify1(
+ %hello_p = getelementptr [6 x i32], [6 x i32]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i32* %hello_p, i32 187)
+; CHECK-NEXT: %hello_l = call i64 @wcslen
+ ret i64 %hello_l
+; CHECK-NEXT: ret i64 %hello_l
+}
diff --git a/test/Transforms/InstCombine/wcslen-3.ll b/test/Transforms/InstCombine/wcslen-3.ll
new file mode 100644
index 0000000000000..c766ff21412d0
--- /dev/null
+++ b/test/Transforms/InstCombine/wcslen-3.ll
@@ -0,0 +1,197 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; Test that the wcslen library call simplifier works correctly.
+;
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+; Test behavior for wchar_size==2
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"wchar_size", i32 2}
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+
+declare i64 @wcslen(i16*)
+
+@hello = constant [6 x i16] [i16 104, i16 101, i16 108, i16 108, i16 111, i16 0]
+@longer = constant [7 x i16] [i16 108, i16 111, i16 110, i16 103, i16 101, i16 114, i16 0]
+@null = constant [1 x i16] zeroinitializer
+@null_hello = constant [7 x i16] [i16 0, i16 104, i16 101, i16 108, i16 108, i16 111, i16 0]
+@nullstring = constant i16 0
+@a = common global [32 x i16] zeroinitializer, align 1
+@null_hello_mid = constant [13 x i16] [i16 104, i16 101, i16 108, i16 108, i16 111, i16 32, i16 119, i16 111, i16 114, i16 0, i16 108, i16 100, i16 0]
+
+define i64 @test_simplify1() {
+; CHECK-LABEL: @test_simplify1(
+; CHECK-NEXT: ret i64 5
+;
+ %hello_p = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ ret i64 %hello_l
+}
+
+define i64 @test_simplify2() {
+; CHECK-LABEL: @test_simplify2(
+; CHECK-NEXT: ret i64 0
+;
+ %null_p = getelementptr [1 x i16], [1 x i16]* @null, i64 0, i64 0
+ %null_l = call i64 @wcslen(i16* %null_p)
+ ret i64 %null_l
+}
+
+define i64 @test_simplify3() {
+; CHECK-LABEL: @test_simplify3(
+; CHECK-NEXT: ret i64 0
+;
+ %null_hello_p = getelementptr [7 x i16], [7 x i16]* @null_hello, i64 0, i64 0
+ %null_hello_l = call i64 @wcslen(i16* %null_hello_p)
+ ret i64 %null_hello_l
+}
+
+define i64 @test_simplify4() {
+; CHECK-LABEL: @test_simplify4(
+; CHECK-NEXT: ret i64 0
+;
+ %len = tail call i64 @wcslen(i16* @nullstring) nounwind
+ ret i64 %len
+}
+
+; Check wcslen(x) == 0 --> *x == 0.
+
+define i1 @test_simplify5() {
+; CHECK-LABEL: @test_simplify5(
+; CHECK-NEXT: ret i1 false
+;
+ %hello_p = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ %eq_hello = icmp eq i64 %hello_l, 0
+ ret i1 %eq_hello
+}
+
+define i1 @test_simplify6(i16* %str_p) {
+; CHECK-LABEL: @test_simplify6(
+; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i16, i16* [[STR_P:%.*]], align 2
+; CHECK-NEXT: [[EQ_NULL:%.*]] = icmp eq i16 [[STRLENFIRST]], 0
+; CHECK-NEXT: ret i1 [[EQ_NULL]]
+;
+ %str_l = call i64 @wcslen(i16* %str_p)
+ %eq_null = icmp eq i64 %str_l, 0
+ ret i1 %eq_null
+}
+
+; Check wcslen(x) != 0 --> *x != 0.
+
+define i1 @test_simplify7() {
+; CHECK-LABEL: @test_simplify7(
+; CHECK-NEXT: ret i1 true
+;
+ %hello_p = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ %ne_hello = icmp ne i64 %hello_l, 0
+ ret i1 %ne_hello
+}
+
+define i1 @test_simplify8(i16* %str_p) {
+; CHECK-LABEL: @test_simplify8(
+; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i16, i16* [[STR_P:%.*]], align 2
+; CHECK-NEXT: [[NE_NULL:%.*]] = icmp ne i16 [[STRLENFIRST]], 0
+; CHECK-NEXT: ret i1 [[NE_NULL]]
+;
+ %str_l = call i64 @wcslen(i16* %str_p)
+ %ne_null = icmp ne i64 %str_l, 0
+ ret i1 %ne_null
+}
+
+define i64 @test_simplify9(i1 %x) {
+; CHECK-LABEL: @test_simplify9(
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i64 5, i64 6
+; CHECK-NEXT: ret i64 [[TMP1]]
+;
+ %hello = getelementptr [6 x i16], [6 x i16]* @hello, i64 0, i64 0
+ %longer = getelementptr [7 x i16], [7 x i16]* @longer, i64 0, i64 0
+ %s = select i1 %x, i16* %hello, i16* %longer
+ %l = call i64 @wcslen(i16* %s)
+ ret i64 %l
+}
+
+; Check the case that should be simplified to a sub instruction.
+; wcslen(@hello + x) --> 5 - x
+
+define i64 @test_simplify10(i16 %x) {
+; CHECK-LABEL: @test_simplify10(
+; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i64 5, [[TMP1]]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %hello_p = getelementptr inbounds [6 x i16], [6 x i16]* @hello, i16 0, i16 %x
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ ret i64 %hello_l
+}
+
+; wcslen(@null_hello_mid + (x & 7)) --> 9 - (x & 7)
+
+define i64 @test_simplify11(i16 %x) {
+; CHECK-LABEL: @test_simplify11(
+; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 7
+; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[AND]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i64 9, [[TMP1]]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %and = and i16 %x, 7
+ %hello_p = getelementptr inbounds [13 x i16], [13 x i16]* @null_hello_mid, i16 0, i16 %and
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ ret i64 %hello_l
+}
+
+; Check cases that shouldn't be simplified.
+
+define i64 @test_no_simplify1() {
+; CHECK-LABEL: @test_no_simplify1(
+; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a, i64 0, i64 0))
+; CHECK-NEXT: ret i64 [[A_L]]
+;
+ %a_p = getelementptr [32 x i16], [32 x i16]* @a, i64 0, i64 0
+ %a_l = call i64 @wcslen(i16* %a_p)
+ ret i64 %a_l
+}
+
+; wcslen(@null_hello + x) should not be simplified to a sub instruction.
+
+define i64 @test_no_simplify2(i16 %x) {
+; CHECK-LABEL: @test_no_simplify2(
+; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i64
+; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [7 x i16], [7 x i16]* @null_hello, i64 0, i64 [[TMP1]]
+; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i16* [[HELLO_P]])
+; CHECK-NEXT: ret i64 [[HELLO_L]]
+;
+ %hello_p = getelementptr inbounds [7 x i16], [7 x i16]* @null_hello, i16 0, i16 %x
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ ret i64 %hello_l
+}
+
+; wcslen(@null_hello_mid + (x & 15)) should not be simplified to a sub instruction.
+
+define i64 @test_no_simplify3(i16 %x) {
+; CHECK-LABEL: @test_no_simplify3(
+; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 15
+; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[AND]] to i64
+; CHECK-NEXT: [[HELLO_P:%.*]] = getelementptr inbounds [13 x i16], [13 x i16]* @null_hello_mid, i64 0, i64 [[TMP1]]
+; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i16* [[HELLO_P]])
+; CHECK-NEXT: ret i64 [[HELLO_L]]
+;
+ %and = and i16 %x, 15
+ %hello_p = getelementptr inbounds [13 x i16], [13 x i16]* @null_hello_mid, i16 0, i16 %and
+ %hello_l = call i64 @wcslen(i16* %hello_p)
+ ret i64 %hello_l
+}
+
+@str32 = constant [1 x i32] [i32 0]
+
+; This could in principle be simplified, but the current implementation bails on
+; type mismatches.
+define i64 @test_no_simplify4() {
+; CHECK-LABEL: @test_no_simplify4(
+; CHECK-NEXT: [[L:%.*]] = call i64 @wcslen(i16* bitcast ([1 x i32]* @str32 to i16*))
+; CHECK-NEXT: ret i64 [[L]]
+;
+ %l = call i64 @wcslen(i16* bitcast ([1 x i32]* @str32 to i16*))
+ ret i64 %l
+}
diff --git a/test/Transforms/InstSimplify/AndOrXor.ll b/test/Transforms/InstSimplify/AndOrXor.ll
index a9b4e4e5cfcc7..a027c7e182809 100644
--- a/test/Transforms/InstSimplify/AndOrXor.ll
+++ b/test/Transforms/InstSimplify/AndOrXor.ll
@@ -735,6 +735,74 @@ define i32 @test54(i32 %a, i32 %b) {
ret i32 %or
}
+; (A & B) | ~(A ^ B) -> ~(A ^ B)
+
+define i32 @test55(i32 %a, i32 %b) {
+; CHECK-LABEL: @test55(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
+; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XNOR]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %and = and i32 %a, %b
+ %xor = xor i32 %a, %b
+ %xnor = xor i32 %xor, -1
+ %or = or i32 %and, %xnor
+ ret i32 %or
+}
+
+; ~(A ^ B) | (A & B) -> ~(A ^ B)
+
+define i32 @test56(i32 %a, i32 %b) {
+; CHECK-LABEL: @test56(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
+; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XNOR]], [[AND]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %and = and i32 %a, %b
+ %xor = xor i32 %a, %b
+ %xnor = xor i32 %xor, -1
+ %or = or i32 %xnor, %and
+ ret i32 %or
+}
+
+; (B & A) | ~(A ^ B) -> ~(A ^ B)
+
+define i32 @test57(i32 %a, i32 %b) {
+; CHECK-LABEL: @test57(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
+; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XNOR]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %and = and i32 %b, %a
+ %xor = xor i32 %a, %b
+ %xnor = xor i32 %xor, -1
+ %or = or i32 %and, %xnor
+ ret i32 %or
+}
+
+; ~(A ^ B) | (A & B) -> ~(A ^ B)
+
+define i32 @test58(i32 %a, i32 %b) {
+; CHECK-LABEL: @test58(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
+; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XNOR]], [[AND]]
+; CHECK-NEXT: ret i32 [[OR]]
+;
+ %and = and i32 %b, %a
+ %xor = xor i32 %a, %b
+ %xnor = xor i32 %xor, -1
+ %or = or i32 %xnor, %and
+ ret i32 %or
+}
+
define i8 @lshr_perfect_mask(i8 %x) {
; CHECK-LABEL: @lshr_perfect_mask(
; CHECK-NEXT: [[SH:%.*]] = lshr i8 %x, 5
@@ -797,3 +865,11 @@ define <2 x i8> @shl_undersized_mask_splat(<2 x i8> %x) {
ret <2 x i8> %mask
}
+define i32 @reversed_not(i32 %a) {
+; CHECK-LABEL: @reversed_not(
+; CHECK-NEXT: ret i32 -1
+;
+ %nega = xor i32 -1, %a
+ %or = or i32 %a, %nega
+ ret i32 %or
+}
diff --git a/test/Transforms/InstSimplify/icmp-bool-constant.ll b/test/Transforms/InstSimplify/icmp-bool-constant.ll
new file mode 100644
index 0000000000000..f711fae0a8570
--- /dev/null
+++ b/test/Transforms/InstSimplify/icmp-bool-constant.ll
@@ -0,0 +1,171 @@
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+; Test all integer predicates with bool types and true/false constants.
+; Use vectors to provide test coverage that is not duplicated in other folds.
+
+define <2 x i1> @eq_t(<2 x i1> %a) {
+; CHECK-LABEL: @eq_t(
+; CHECK-NEXT: ret <2 x i1> %a
+;
+ %r = icmp eq <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @eq_f(<2 x i1> %a) {
+; CHECK-LABEL: @eq_f(
+; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i1> %a, zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %r = icmp eq <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ne_t(<2 x i1> %a) {
+; CHECK-LABEL: @ne_t(
+; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i1> %a, <i1 true, i1 true>
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %r = icmp ne <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ne_f(<2 x i1> %a) {
+; CHECK-LABEL: @ne_f(
+; CHECK-NEXT: ret <2 x i1> %a
+;
+ %r = icmp ne <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ugt_t(<2 x i1> %a) {
+; CHECK-LABEL: @ugt_t(
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
+;
+ %r = icmp ugt <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ugt_f(<2 x i1> %a) {
+; CHECK-LABEL: @ugt_f(
+; CHECK-NEXT: ret <2 x i1> %a
+;
+ %r = icmp ugt <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ult_t(<2 x i1> %a) {
+; CHECK-LABEL: @ult_t(
+; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i1> %a, <i1 true, i1 true>
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %r = icmp ult <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ult_f(<2 x i1> %a) {
+; CHECK-LABEL: @ult_f(
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
+;
+ %r = icmp ult <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @sgt_t(<2 x i1> %a) {
+; CHECK-LABEL: @sgt_t(
+; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i1> %a, <i1 true, i1 true>
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %r = icmp sgt <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @sgt_f(<2 x i1> %a) {
+; CHECK-LABEL: @sgt_f(
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
+;
+ %r = icmp sgt <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @slt_t(<2 x i1> %a) {
+; CHECK-LABEL: @slt_t(
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
+;
+ %r = icmp slt <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @slt_f(<2 x i1> %a) {
+; CHECK-LABEL: @slt_f(
+; CHECK-NEXT: ret <2 x i1> %a
+;
+ %r = icmp slt <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @uge_t(<2 x i1> %a) {
+; CHECK-LABEL: @uge_t(
+; CHECK-NEXT: ret <2 x i1> %a
+;
+ %r = icmp uge <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @uge_f(<2 x i1> %a) {
+; CHECK-LABEL: @uge_f(
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
+;
+ %r = icmp uge <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ule_t(<2 x i1> %a) {
+; CHECK-LABEL: @ule_t(
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
+;
+ %r = icmp ule <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @ule_f(<2 x i1> %a) {
+; CHECK-LABEL: @ule_f(
+; CHECK-NEXT: [[R:%.*]] = icmp ule <2 x i1> %a, zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %r = icmp ule <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @sge_t(<2 x i1> %a) {
+; CHECK-LABEL: @sge_t(
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
+;
+ %r = icmp sge <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @sge_f(<2 x i1> %a) {
+; CHECK-LABEL: @sge_f(
+; CHECK-NEXT: [[R:%.*]] = icmp sge <2 x i1> %a, zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %r = icmp sge <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @sle_t(<2 x i1> %a) {
+; CHECK-LABEL: @sle_t(
+; CHECK-NEXT: ret <2 x i1> %a
+;
+ %r = icmp sle <2 x i1> %a, <i1 true, i1 true>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @sle_f(<2 x i1> %a) {
+; CHECK-LABEL: @sle_f(
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
+;
+ %r = icmp sle <2 x i1> %a, <i1 false, i1 false>
+ ret <2 x i1> %r
+}
+
diff --git a/test/Transforms/JumpThreading/assume.ll b/test/Transforms/JumpThreading/assume.ll
index 53010b71c7285..3a039676e172b 100644
--- a/test/Transforms/JumpThreading/assume.ll
+++ b/test/Transforms/JumpThreading/assume.ll
@@ -56,6 +56,50 @@ return: ; preds = %entry, %if.then
ret i32 %retval.0
}
+@g = external global i32
+
+; Check that we do prove a fact using an assume within the block.
+; FIXME: We can fold the assume based on the semantics of assume.
+; CHECK-LABEL: @can_fold_assume
+; CHECK: %notnull = icmp ne i32* %array, null
+; CHECK-NEXT: call void @llvm.assume(i1 %notnull)
+; CHECK-NEXT: ret void
+define void @can_fold_assume(i32* %array) {
+ %notnull = icmp ne i32* %array, null
+ call void @llvm.assume(i1 %notnull)
+ br i1 %notnull, label %normal, label %error
+
+normal:
+ ret void
+
+error:
+ store atomic i32 0, i32* @g unordered, align 4
+ ret void
+}
+
+declare void @f(i1)
+declare void @exit()
+; We can fold the assume but not the uses before the assume.
+define void @dont_fold_incorrectly(i32* %array) {
+; CHECK-LABEL:@dont_fold_incorrectly
+; CHECK: @f(i1 %notnull)
+; CHECK-NEXT: exit()
+; CHECK-NEXT: assume(i1 %notnull)
+; CHECK-NEXT: ret void
+ %notnull = icmp ne i32* %array, null
+ call void @f(i1 %notnull)
+ call void @exit()
+ call void @llvm.assume(i1 %notnull)
+ br i1 %notnull, label %normal, label %error
+
+normal:
+ ret void
+
+error:
+ store atomic i32 0, i32* @g unordered, align 4
+ ret void
+}
+
; Function Attrs: nounwind
declare void @llvm.assume(i1) #1
diff --git a/test/Transforms/JumpThreading/fold-not-thread.ll b/test/Transforms/JumpThreading/fold-not-thread.ll
index 06ddc10e02b6e..f05169b31bc8d 100644
--- a/test/Transforms/JumpThreading/fold-not-thread.ll
+++ b/test/Transforms/JumpThreading/fold-not-thread.ll
@@ -133,10 +133,10 @@ L3:
ret void
}
-; Make sure we can do the RAUW for %add...
+; FIXME: Make sure we can do the RAUW for %add...
;
; CHECK-LABEL: @rauw_if_possible(
-; CHECK: call void @f4(i32 96)
+; CHECK: call void @f4(i32 %add)
define void @rauw_if_possible(i32 %value) nounwind {
entry:
%cmp = icmp eq i32 %value, 32
diff --git a/test/Transforms/JumpThreading/guards.ll b/test/Transforms/JumpThreading/guards.ll
index eac2b5dcd85f9..c5f72b113efce 100644
--- a/test/Transforms/JumpThreading/guards.ll
+++ b/test/Transforms/JumpThreading/guards.ll
@@ -181,3 +181,97 @@ Exit:
; CHECK-NEXT: ret void
ret void
}
+
+declare void @never_called()
+
+; Assume the guard is always taken and we deoptimize, so we never reach the
+; branch below that guard. We should *never* change the behaviour of a guard from
+; `must deoptimize` to `may deoptimize`, since this affects the program
+; semantics.
+define void @dont_fold_guard(i8* %addr, i32 %i, i32 %length) {
+; CHECK-LABEL: dont_fold_guard
+; CHECK: experimental.guard(i1 %wide.chk)
+
+entry:
+ br label %BBPred
+
+BBPred:
+ %cond = icmp eq i8* %addr, null
+ br i1 %cond, label %zero, label %not_zero
+
+zero:
+ unreachable
+
+not_zero:
+ %c1 = icmp ult i32 %i, %length
+ %c2 = icmp eq i32 %i, 0
+ %wide.chk = and i1 %c1, %c2
+ call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+ br i1 %c2, label %unreachedBB2, label %unreachedBB1
+
+unreachedBB2:
+ call void @never_called()
+ ret void
+
+unreachedBB1:
+ ret void
+}
+
+
+; same as dont_fold_guard1 but condition %cmp is not an instruction.
+; We cannot fold the guard under any circumstance.
+; FIXME: We can merge unreachableBB2 into not_zero.
+define void @dont_fold_guard2(i8* %addr, i1 %cmp, i32 %i, i32 %length) {
+; CHECK-LABEL: dont_fold_guard2
+; CHECK: guard(i1 %cmp)
+
+entry:
+ br label %BBPred
+
+BBPred:
+ %cond = icmp eq i8* %addr, null
+ br i1 %cond, label %zero, label %not_zero
+
+zero:
+ unreachable
+
+not_zero:
+ call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+ br i1 %cmp, label %unreachedBB2, label %unreachedBB1
+
+unreachedBB2:
+ call void @never_called()
+ ret void
+
+unreachedBB1:
+ ret void
+}
+
+; Same as dont_fold_guard1 but use switch instead of branch.
+; triggers source code `ProcessThreadableEdges`.
+declare void @f(i1)
+define void @dont_fold_guard3(i1 %cmp1, i32 %i) nounwind {
+; CHECK-LABEL: dont_fold_guard3
+; CHECK-LABEL: L2:
+; CHECK-NEXT: %cmp = icmp eq i32 %i, 0
+; CHECK-NEXT: guard(i1 %cmp)
+; CHECK-NEXT: @f(i1 %cmp)
+; CHECK-NEXT: ret void
+entry:
+ br i1 %cmp1, label %L0, label %L3
+L0:
+ %cmp = icmp eq i32 %i, 0
+ call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
+ switch i1 %cmp, label %L3 [
+ i1 false, label %L1
+ i1 true, label %L2
+ ]
+
+L1:
+ ret void
+L2:
+ call void @f(i1 %cmp)
+ ret void
+L3:
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/X86/canonical-2.ll b/test/Transforms/LoopStrengthReduce/X86/canonical-2.ll
new file mode 100644
index 0000000000000..69bae3a511591
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/X86/canonical-2.ll
@@ -0,0 +1,36 @@
+; REQUIRES: asserts
+; RUN: opt -mtriple=x86_64-unknown-linux-gnu -loop-reduce -S < %s
+; PR33077. Check the LSR Use formula to be inserted is already canonicalized and
+; will not trigger assertion.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+; Function Attrs: uwtable
+define void @foo() {
+cHeapLvb.exit:
+ br label %not_zero48.us
+
+not_zero48.us: ; preds = %not_zero48.us, %cHeapLvb.exit
+ %indvars.iv.us = phi i64 [ %indvars.iv.next.us.7, %not_zero48.us ], [ undef, %cHeapLvb.exit ]
+ %0 = phi i32 [ %13, %not_zero48.us ], [ undef, %cHeapLvb.exit ]
+ %indvars.iv.next.us = add nuw nsw i64 %indvars.iv.us, 1
+ %1 = add i32 %0, 2
+ %2 = getelementptr inbounds i32, i32 addrspace(1)* undef, i64 %indvars.iv.next.us
+ %3 = load i32, i32 addrspace(1)* %2, align 4
+ %4 = add i32 %0, 3
+ %5 = load i32, i32 addrspace(1)* undef, align 4
+ %6 = sub i32 undef, %5
+ %factor.us.2 = shl i32 %6, 1
+ %7 = add i32 %factor.us.2, %1
+ %8 = load i32, i32 addrspace(1)* undef, align 4
+ %9 = sub i32 %7, %8
+ %factor.us.3 = shl i32 %9, 1
+ %10 = add i32 %factor.us.3, %4
+ %11 = load i32, i32 addrspace(1)* undef, align 4
+ %12 = sub i32 %10, %11
+ %factor.us.4 = shl i32 %12, 1
+ %13 = add i32 %0, 8
+ %indvars.iv.next.us.7 = add nsw i64 %indvars.iv.us, 8
+ br label %not_zero48.us
+}
+
diff --git a/test/Transforms/NewGVN/completeness.ll b/test/Transforms/NewGVN/completeness.ll
new file mode 100644
index 0000000000000..bafe5f966d22a
--- /dev/null
+++ b/test/Transforms/NewGVN/completeness.ll
@@ -0,0 +1,415 @@
+; 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 i32 @test1(i32, i8**) {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
+; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
+; CHECK: br label [[TMP6:%.*]]
+; CHECK: br label [[TMP6]]
+; CHECK: [[TMP7:%.*]] = phi i32 [ 75, [[TMP4]] ], [ 105, [[TMP5]] ]
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 5, [[TMP4]] ], [ 7, [[TMP5]] ]
+; CHECK-NEXT: ret i32 [[TMP7]]
+;
+ %3 = icmp ne i32 %0, 0
+ br i1 %3, label %4, label %5
+
+; <label>:4: ; preds = %2
+ br label %6
+
+; <label>:5: ; preds = %2
+ br label %6
+
+; <label>:6: ; preds = %5, %4
+ %.0 = phi i32 [ 5, %4 ], [ 7, %5 ]
+ %7 = mul nsw i32 %.0, 15
+ ret i32 %7
+}
+
+define i32 @test2(i32) {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
+; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
+; CHECK: br label [[TMP5:%.*]]
+; CHECK: br label [[TMP5]]
+; CHECK: [[DOT01:%.*]] = phi i32 [ 3, [[TMP3]] ], [ 2, [[TMP4]] ]
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 2, [[TMP3]] ], [ 3, [[TMP4]] ]
+; CHECK-NEXT: ret i32 5
+;
+ %2 = icmp ne i32 %0, 0
+ br i1 %2, label %3, label %4
+
+; <label>:3: ; preds = %1
+ br label %5
+
+; <label>:4: ; preds = %1
+ br label %5
+
+; <label>:5: ; preds = %4, %3
+ %.01 = phi i32 [ 3, %3 ], [ 2, %4 ]
+ %.0 = phi i32 [ 2, %3 ], [ 3, %4 ]
+ %6 = add nsw i32 %.01, %.0
+ ret i32 %6
+}
+define i32 @test3(i1 %which) {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]
+; CHECK: delay:
+; CHECK-NEXT: br label [[FINAL]]
+; CHECK: final:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ -877, [[ENTRY:%.*]] ], [ 113, [[DELAY]] ]
+; CHECK-NEXT: [[A:%.*]] = phi i32 [ 1000, [[ENTRY]] ], [ 10, [[DELAY]] ]
+; CHECK-NEXT: ret i32 [[TMP0]]
+;
+
+entry:
+ br i1 %which, label %final, label %delay
+
+delay:
+ br label %final
+
+final:
+ %A = phi i32 [ 1000, %entry ], [ 10, %delay ]
+ %value = sub i32 123, %A
+ ret i32 %value
+}
+
+define <2 x i32> @test3vec(i1 %which) {
+; CHECK-LABEL: @test3vec(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]
+; CHECK: delay:
+; CHECK-NEXT: br label [[FINAL]]
+; CHECK: final:
+; CHECK-NEXT: [[TMP0:%.*]] = phi <2 x i32> [ <i32 -877, i32 -877>, [[ENTRY:%.*]] ], [ <i32 113, i32 113>, [[DELAY]] ]
+; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ <i32 1000, i32 1000>, [[ENTRY]] ], [ <i32 10, i32 10>, [[DELAY]] ]
+; CHECK-NEXT: ret <2 x i32> [[TMP0]]
+;
+
+entry:
+ br i1 %which, label %final, label %delay
+
+delay:
+ br label %final
+
+final:
+ %A = phi <2 x i32> [ <i32 1000, i32 1000>, %entry ], [ <i32 10, i32 10>, %delay ]
+ %value = sub <2 x i32> <i32 123, i32 123>, %A
+ ret <2 x i32> %value
+}
+
+define <2 x i32> @test3vec2(i1 %which) {
+; CHECK-LABEL: @test3vec2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]
+; CHECK: delay:
+; CHECK-NEXT: br label [[FINAL]]
+; CHECK: final:
+; CHECK-NEXT: [[TMP0:%.*]] = phi <2 x i32> [ <i32 -877, i32 -2167>, [[ENTRY:%.*]] ], [ <i32 113, i32 303>, [[DELAY]] ]
+; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ <i32 1000, i32 2500>, [[ENTRY]] ], [ <i32 10, i32 30>, [[DELAY]] ]
+; CHECK-NEXT: ret <2 x i32> [[TMP0]]
+;
+
+entry:
+ br i1 %which, label %final, label %delay
+
+delay:
+ br label %final
+
+final:
+ %A = phi <2 x i32> [ <i32 1000, i32 2500>, %entry ], [ <i32 10, i32 30>, %delay ]
+ %value = sub <2 x i32> <i32 123, i32 333>, %A
+ ret <2 x i32> %value
+}
+
+;; This example is a bit contrived because we can't create fake memoryuses, so we use two loads in the if blocks
+define i32 @test4(i32, i8**, i32* noalias, i32* noalias) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT: store i32 5, i32* [[TMP2:%.*]], align 4
+; CHECK-NEXT: store i32 7, i32* [[TMP3:%.*]], align 4
+; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
+; CHECK-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP7:%.*]]
+; CHECK: br label [[TMP8:%.*]]
+; CHECK: br label [[TMP8]]
+; CHECK: [[DOT01:%.*]] = phi i32 [ 5, [[TMP6]] ], [ 7, [[TMP7]] ]
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32* [ [[TMP2]], [[TMP6]] ], [ [[TMP3]], [[TMP7]] ]
+; CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOT0]], align 4
+; CHECK-NEXT: [[TMP10:%.*]] = mul nsw i32 [[TMP9]], 15
+; CHECK-NEXT: [[TMP11:%.*]] = mul nsw i32 [[TMP10]], [[DOT01]]
+; CHECK-NEXT: ret i32 [[TMP11]]
+;
+ store i32 5, i32* %2, align 4
+ store i32 7, i32* %3, align 4
+ %5 = icmp ne i32 %0, 0
+ br i1 %5, label %6, label %8
+
+; <label>:6: ; preds = %4
+ %7 = load i32, i32* %2, align 4
+ br label %10
+
+; <label>:8: ; preds = %4
+ %9 = load i32, i32* %3, align 4
+ br label %10
+
+; <label>:10: ; preds = %8, %6
+ %.01 = phi i32 [ %7, %6 ], [ %9, %8 ]
+ %.0 = phi i32* [ %2, %6 ], [ %3, %8 ]
+ %11 = load i32, i32* %.0, align 4
+ %12 = mul nsw i32 %11, 15
+ %13 = mul nsw i32 %12, %.01
+ ret i32 %13
+}
+
+@global = common global [100 x i64] zeroinitializer, align 16
+@global.1 = common global [100 x i64] zeroinitializer, align 16
+define i64 @test5(i64 %arg) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: [[TMP:%.*]] = alloca i64, align 8
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[ARG:%.*]], 0
+; CHECK-NEXT: br i1 [[TMP1]], label [[BB28:%.*]], label [[BB2:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: br label [[BB7:%.*]]
+; CHECK: bb4:
+; CHECK-NEXT: br label [[BB5:%.*]]
+; CHECK: bb5:
+; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP9:%.*]], 0
+; CHECK-NEXT: br i1 [[TMP6]], label [[BB27:%.*]], label [[BB7]]
+; CHECK: bb7:
+; CHECK-NEXT: [[TMP8:%.*]] = phi i64 [ [[ARG]], [[BB2]] ], [ [[TMP9]], [[BB5]] ]
+; CHECK-NEXT: [[TMP9]] = add nsw i64 [[TMP8]], -1
+; CHECK-NEXT: [[TMP10:%.*]] = load i64, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @global, i64 0, i64 0), align 16
+; CHECK-NEXT: [[TMP11:%.*]] = load i64, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @global.1, i64 0, i64 0), align 16
+; CHECK-NEXT: [[TMP12:%.*]] = mul nsw i64 [[TMP11]], [[TMP10]]
+; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i64 [[TMP12]], 0
+; CHECK-NEXT: br i1 [[TMP13]], label [[BB5]], label [[BB14:%.*]]
+; CHECK: bb14:
+; CHECK-NEXT: br label [[BB15:%.*]]
+; CHECK: bb15:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ [[TMP25:%.*]], [[BB15]] ], [ [[TMP12]], [[BB14]] ]
+; CHECK-NEXT: [[TMP16:%.*]] = phi i64 [ [[TMP24:%.*]], [[BB15]] ], [ [[TMP11]], [[BB14]] ]
+; CHECK-NEXT: [[TMP17:%.*]] = phi i64 [ [[TMP22:%.*]], [[BB15]] ], [ [[TMP10]], [[BB14]] ]
+; CHECK-NEXT: [[TMP18:%.*]] = phi i64 [ [[TMP20:%.*]], [[BB15]] ], [ 0, [[BB14]] ]
+; CHECK-NEXT: store i64 [[TMP0]], i64* [[TMP]], align 8
+; CHECK-NEXT: [[TMP20]] = add nuw nsw i64 [[TMP18]], 1
+; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [100 x i64], [100 x i64]* @global, i64 0, i64 [[TMP20]]
+; CHECK-NEXT: [[TMP22]] = load i64, i64* [[TMP21]], align 8
+; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [100 x i64], [100 x i64]* @global.1, i64 0, i64 [[TMP20]]
+; CHECK-NEXT: [[TMP24]] = load i64, i64* [[TMP23]], align 8
+; CHECK-NEXT: [[TMP25]] = mul nsw i64 [[TMP24]], [[TMP22]]
+; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[TMP20]], [[TMP25]]
+; CHECK-NEXT: br i1 [[TMP26]], label [[BB4:%.*]], label [[BB15]]
+; CHECK: bb27:
+; CHECK-NEXT: br label [[BB28]]
+; CHECK: bb28:
+; CHECK-NEXT: ret i64 0
+;
+bb:
+ %tmp = alloca i64, align 8
+ %tmp1 = icmp eq i64 %arg, 0
+ br i1 %tmp1, label %bb28, label %bb2
+
+bb2: ; preds = %bb
+ %tmp3 = bitcast i64* %tmp to i8*
+ br label %bb7
+
+bb4: ; preds = %bb15
+ br label %bb5
+
+bb5: ; preds = %bb7, %bb4
+ %tmp6 = icmp eq i64 %tmp9, 0
+ br i1 %tmp6, label %bb27, label %bb7
+
+bb7: ; preds = %bb5, %bb2
+ %tmp8 = phi i64 [ %arg, %bb2 ], [ %tmp9, %bb5 ]
+ %tmp9 = add nsw i64 %tmp8, -1
+ %tmp10 = load i64, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @global, i64 0, i64 0), align 16
+ %tmp11 = load i64, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @global.1, i64 0, i64 0), align 16
+ %tmp12 = mul nsw i64 %tmp11, %tmp10
+ %tmp13 = icmp eq i64 %tmp12, 0
+ br i1 %tmp13, label %bb5, label %bb14
+
+bb14: ; preds = %bb7
+ br label %bb15
+
+bb15: ; preds = %bb15, %bb14
+ %tmp16 = phi i64 [ %tmp24, %bb15 ], [ %tmp11, %bb14 ]
+ %tmp17 = phi i64 [ %tmp22, %bb15 ], [ %tmp10, %bb14 ]
+ %tmp18 = phi i64 [ %tmp20, %bb15 ], [ 0, %bb14 ]
+;; This multiply is an op of phis which is really equivalent to phi(tmp25, tmp12)
+ %tmp19 = mul nsw i64 %tmp16, %tmp17
+ store i64 %tmp19, i64* %tmp, align 8
+ %tmp20 = add nuw nsw i64 %tmp18, 1
+ %tmp21 = getelementptr inbounds [100 x i64], [100 x i64]* @global, i64 0, i64 %tmp20
+ %tmp22 = load i64, i64* %tmp21, align 8
+ %tmp23 = getelementptr inbounds [100 x i64], [100 x i64]* @global.1, i64 0, i64 %tmp20
+ %tmp24 = load i64, i64* %tmp23, align 8
+ %tmp25 = mul nsw i64 %tmp24, %tmp22
+ %tmp26 = icmp eq i64 %tmp20, %tmp25
+ br i1 %tmp26, label %bb4, label %bb15
+
+bb27: ; preds = %bb5
+ br label %bb28
+
+bb28: ; preds = %bb27, %bb
+ ret i64 0
+}
+
+;; These icmps are all equivalent to phis of constants
+define i8 @test6(i8* %addr) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT: entry-block:
+; CHECK-NEXT: br label %main-loop
+; CHECK: main-loop:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, %entry-block ], [ false, [[CORE:%.*]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ false, %entry-block ], [ true, [[CORE]] ]
+; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ 0, %entry-block ], [ 1, [[CORE]] ]
+; CHECK-NEXT: store volatile i8 0, i8* [[ADDR:%.*]]
+; CHECK-NEXT: br i1 [[TMP0]], label %busy-wait-phi-0, label [[EXIT:%.*]]
+; CHECK: busy-wait-phi-0:
+; CHECK-NEXT: [[LOAD:%.*]] = load volatile i8, i8* [[ADDR]]
+; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[LOAD]], 0
+; CHECK-NEXT: br i1 [[ICMP]], label %busy-wait-phi-0, label [[CORE]]
+; CHECK: core:
+; CHECK-NEXT: br i1 [[TMP1]], label [[TRAP:%.*]], label %main-loop
+; CHECK: trap:
+; CHECK-NEXT: ret i8 1
+; CHECK: exit:
+; CHECK-NEXT: ret i8 0
+;
+entry-block:
+ br label %main-loop
+
+main-loop:
+ %phi = phi i8 [ 0, %entry-block ], [ 1, %core ]
+ %switch_0 = icmp eq i8 %phi, 0
+ store volatile i8 0, i8* %addr
+ br i1 %switch_0, label %busy-wait-phi-0, label %exit
+
+busy-wait-phi-0:
+ %load = load volatile i8, i8* %addr
+ %icmp = icmp eq i8 %load, 0
+ br i1 %icmp, label %busy-wait-phi-0, label %core
+
+core:
+ %switch_1 = icmp eq i8 %phi, 1
+ br i1 %switch_1, label %trap, label %main-loop
+
+trap:
+ ret i8 1
+
+exit:
+ ret i8 0
+}
+
+; Test that we don't infinite loop simplifying
+; an undefined value that can go both ways.
+define void @test7() {
+; CHECK-LABEL: @test7(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: br label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[BB1]]
+;
+bb:
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb
+ %tmp = phi i32 [ undef, %bb ], [ %tmp3, %bb1 ]
+ %tmp2 = icmp eq i32 %tmp, 0
+ %tmp3 = select i1 %tmp2, i32 1, i32 %tmp
+ br label %bb1
+}
+
+
+
+; Test that we get a consistent answer about what the
+; value of this undefined select is.
+define void @test8() {
+; CHECK-LABEL: @test8(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: br label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[BB1]]
+;
+bb:
+ %tmp = select i1 undef, i8 0, i8 1
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb
+ %tmp2 = phi i8 [ %tmp4, %bb1 ], [ %tmp, %bb ]
+ %tmp3 = icmp eq i8 %tmp2, 0
+ %tmp4 = select i1 %tmp3, i8 1, i8 %tmp2
+ br label %bb1
+}
+
+
+;; Make sure we handle the case where we later come up with an expression that we need
+;; for a phi of ops.
+define void @test9() {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: br label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: br i1 undef, label [[BB1]], label [[BB2:%.*]]
+; CHECK: bb2:
+; CHECK-NEXT: br label [[BB6:%.*]]
+; CHECK: bb6:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ -13, [[BB2]] ], [ [[TMP11:%.*]], [[BB6]] ]
+; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ 1, [[BB2]] ], [ [[TMP8:%.*]], [[BB6]] ]
+; CHECK-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP7]], 1
+; CHECK-NEXT: [[TMP11]] = add i32 -14, [[TMP8]]
+; CHECK-NEXT: br label [[BB6]]
+;
+bb:
+ br label %bb1
+
+bb1: ; preds = %bb1, %bb
+ br i1 undef, label %bb1, label %bb2
+
+bb2: ; preds = %bb1
+ %tmp = select i1 true, i32 -14, i32 -10
+ %tmp3 = add i32 %tmp, 0
+ %tmp4 = select i1 true, i32 -14, i32 -10
+ %tmp5 = add i32 %tmp4, 0
+ br label %bb6
+
+bb6: ; preds = %bb6, %bb2
+ %tmp7 = phi i32 [ 1, %bb2 ], [ %tmp13, %bb6 ]
+ %tmp8 = add nuw nsw i32 %tmp7, 1
+ %tmp9 = add i32 %tmp3, %tmp7
+ %tmp10 = select i1 false, i32 undef, i32 %tmp9
+ %tmp11 = add i32 %tmp5, %tmp8
+ %tmp12 = select i1 undef, i32 undef, i32 %tmp11
+ %tmp13 = add nuw nsw i32 %tmp7, 1
+ br label %bb6
+}
+
+;; Ensure that we revisit predicateinfo operands at the right points in time.
+define void @test10() {
+b:
+ %m = getelementptr i32, i32* null, i64 8
+ br label %g
+
+g: ; preds = %i, %b
+ %n = phi i32* [ %h, %i ], [ null, %b ]
+ %h = getelementptr i32, i32* %n, i64 1
+ %j = icmp eq i32* %h, %m
+ br i1 %j, label %c, label %i
+
+i: ; preds = %g
+ br i1 undef, label %k, label %g
+
+k: ; preds = %i
+ %l = icmp eq i32* %n, %m
+ br i1 %l, label %c, label %o
+
+o: ; preds = %k
+ br label %c
+
+c: ; preds = %o, %k, %g
+ %0 = phi i32* [ undef, %o ], [ %m, %k ], [ %m, %g ]
+ ret void
+}
diff --git a/test/Transforms/NewGVN/pr32838.ll b/test/Transforms/NewGVN/pr32838.ll
new file mode 100644
index 0000000000000..b6b7b0d19b867
--- /dev/null
+++ b/test/Transforms/NewGVN/pr32838.ll
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;RUN: opt -newgvn -S < %s | FileCheck %s
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+;; Ensure we don't infinite loop when all phi arguments are really unreachable or self-defined
+define void @fn1(i64 %arg) {
+; CHECK-LABEL: @fn1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[COND_TRUE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]]
+; CHECK: firstphiblock:
+; CHECK-NEXT: br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK:%.*]]
+; CHECK: secondphiblock:
+; CHECK-NEXT: [[SECONDPHI:%.*]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ undef, [[FIRSTPHIBLOCK]] ]
+; CHECK-NEXT: br i1 undef, label [[FIRSTPHIBLOCK]], label [[THIRDPHIBLOCK]]
+; CHECK: thirdphiblock:
+; CHECK-NEXT: [[THIRDPHI]] = phi i64 [ [[SECONDPHI]], [[SECONDPHIBLOCK]] ], [ [[DIV:%.*]], [[COND_TRUE]] ]
+; CHECK-NEXT: br label [[SECONDPHIBLOCK]]
+; CHECK: for.cond17thread-pre-split:
+; CHECK-NEXT: br label [[COND_TRUE]]
+; CHECK: cond.true:
+; CHECK-NEXT: [[DIV]] = sdiv i64 [[ARG:%.*]], 4
+; CHECK-NEXT: br label [[THIRDPHIBLOCK]]
+; CHECK: temp:
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 undef, label %if.then, label %cond.true
+if.then:
+ br i1 false, label %firstphiblock, label %temp
+firstphiblock:
+ %firstphi = phi i64 [ %arg, %if.then ], [ undef, %secondphiblock ]
+ br i1 undef, label %for.cond17thread-pre-split, label %secondphiblock
+secondphiblock:
+ %secondphi = phi i64 [ %thirdphi, %thirdphiblock ], [ %firstphi, %firstphiblock ]
+ br i1 undef, label %firstphiblock, label %thirdphiblock
+thirdphiblock:
+ %thirdphi = phi i64 [ %secondphi, %secondphiblock ], [ %div, %cond.true ]
+ br label %secondphiblock
+for.cond17thread-pre-split:
+ br label %cond.true
+cond.true:
+ %fourthphi = phi i64 [ %arg, %entry ], [ %firstphi, %for.cond17thread-pre-split ]
+ %div = sdiv i64 %fourthphi, 4
+ br label %thirdphiblock
+temp:
+ ret void
+}
+define void @fn2(i64 %arg) {
+; CHECK-LABEL: @fn2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[COND_TRUE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]]
+; CHECK: firstphiblock:
+; CHECK-NEXT: [[FIRSTPHI:%.*]] = phi i64 [ undef, [[IF_THEN]] ], [ [[SECONDPHI:%.*]], [[SECONDPHIBLOCK:%.*]] ]
+; CHECK-NEXT: br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK]]
+; CHECK: secondphiblock:
+; CHECK-NEXT: [[SECONDPHI]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ [[FIRSTPHI]], [[FIRSTPHIBLOCK]] ]
+; CHECK-NEXT: br i1 undef, label [[FIRSTPHIBLOCK]], label [[THIRDPHIBLOCK]]
+; CHECK: thirdphiblock:
+; CHECK-NEXT: [[THIRDPHI]] = phi i64 [ [[SECONDPHI]], [[SECONDPHIBLOCK]] ], [ [[DIV:%.*]], [[COND_TRUE]] ]
+; CHECK-NEXT: br label [[SECONDPHIBLOCK]]
+; CHECK: for.cond17thread-pre-split:
+; CHECK-NEXT: br label [[COND_TRUE]]
+; CHECK: cond.true:
+; CHECK-NEXT: [[FOURTHPHI:%.*]] = phi i64 [ [[ARG:%.*]], [[ENTRY:%.*]] ], [ [[FIRSTPHI]], %for.cond17thread-pre-split ]
+; CHECK-NEXT: [[DIV]] = sdiv i64 [[FOURTHPHI]], 4
+; CHECK-NEXT: br label [[THIRDPHIBLOCK]]
+; CHECK: temp:
+; CHECK-NEXT: ret void
+;
+entry:
+ br i1 undef, label %if.then, label %cond.true
+if.then:
+ br i1 false, label %firstphiblock, label %temp
+firstphiblock:
+ %firstphi = phi i64 [ %arg, %if.then ], [ %secondphi, %secondphiblock ]
+ br i1 undef, label %for.cond17thread-pre-split, label %secondphiblock
+secondphiblock:
+ %secondphi = phi i64 [ %thirdphi, %thirdphiblock ], [ %firstphi, %firstphiblock ]
+ br i1 undef, label %firstphiblock, label %thirdphiblock
+thirdphiblock:
+ %thirdphi = phi i64 [ %secondphi, %secondphiblock ], [ %div, %cond.true ]
+ br label %secondphiblock
+for.cond17thread-pre-split:
+ br label %cond.true
+cond.true:
+ %fourthphi = phi i64 [ %arg, %entry ], [ %firstphi, %for.cond17thread-pre-split ]
+ %div = sdiv i64 %fourthphi, 4
+ br label %thirdphiblock
+temp:
+ ret void
+}
+@b = external global i32, align 4
+@a = external global i32, align 4
+define void @fn3() {
+; CHECK-LABEL: @fn3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[L1:%.*]]
+; CHECK: l1.loopexit:
+; CHECK-NEXT: br label [[L1]]
+; CHECK: l1:
+; CHECK-NEXT: [[F_0:%.*]] = phi i32* [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: br label [[FOR_COND:%.*]]
+; CHECK: for.cond.loopexit:
+; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: br label [[FOR_COND]]
+; CHECK: for.cond:
+; CHECK-NEXT: br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]]
+; CHECK: for.cond1.preheader:
+; CHECK-NEXT: br label [[FOR_BODY3:%.*]]
+; CHECK: for.cond1:
+; CHECK-NEXT: br label [[L2:%.*]]
+; CHECK: for.body3:
+; CHECK-NEXT: br i1 undef, label [[FOR_COND1:%.*]], label [[L1_LOOPEXIT]]
+; CHECK: l2:
+; CHECK-NEXT: [[G_4:%.*]] = phi i32* [ @b, [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT: [[F_2:%.*]] = phi i32* [ [[F_0]], [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT: br label [[FOR_INC:%.*]]
+; CHECK: for.inc:
+; CHECK-NEXT: br i1 false, label [[FOR_COND_LOOPEXIT:%.*]], label [[FOR_INC]]
+; CHECK: for.end14:
+; CHECK-NEXT: br label [[L2]]
+;
+entry:
+ br label %l1
+l1.loopexit:
+ %g.223.lcssa = phi i32* [ @b, %for.body3 ]
+ br label %l1
+l1:
+ %g.0 = phi i32* [ undef, %entry ], [ %g.223.lcssa, %l1.loopexit ]
+ %f.0 = phi i32* [ @b, %entry ], [ @a, %l1.loopexit ]
+ br label %for.cond
+for.cond.loopexit:
+ br label %for.cond
+for.cond:
+ %g.1 = phi i32* [ %g.0, %l1 ], [ %g.4, %for.cond.loopexit ]
+ %f.1 = phi i32* [ %f.0, %l1 ], [ %f.2, %for.cond.loopexit ]
+ br i1 undef, label %for.end14, label %for.cond1.preheader
+for.cond1.preheader:
+ br label %for.body3
+for.cond1:
+ br label %l2
+for.body3:
+ br i1 undef, label %for.cond1, label %l1.loopexit
+l2:
+ %g.4 = phi i32* [ %g.1, %for.end14 ], [ @a, %for.cond1 ]
+ %f.2 = phi i32* [ %f.1, %for.end14 ], [ @a, %for.cond1 ]
+ br label %for.inc
+for.inc:
+ br i1 false, label %for.cond.loopexit, label %for.inc
+for.end14:
+ br label %l2
+}
+
diff --git a/test/Transforms/NewGVN/pr32845.ll b/test/Transforms/NewGVN/pr32845.ll
new file mode 100644
index 0000000000000..beba3363b3032
--- /dev/null
+++ b/test/Transforms/NewGVN/pr32845.ll
@@ -0,0 +1,64 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -newgvn %s -S | FileCheck %s
+
+@b = external global i32, align 4
+@a = external global i32, align 4
+define void @tinkywinky() {
+; CHECK-LABEL: @tinkywinky(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[L1:%.*]]
+; CHECK: l1.loopexit:
+; CHECK-NEXT: br label [[L1]]
+; CHECK: l1:
+; CHECK-NEXT: [[F_0:%.*]] = phi i32* [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ]
+; CHECK-NEXT: br label [[FOR_COND:%.*]]
+; CHECK: for.cond.loopexit:
+; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: br label [[FOR_COND]]
+; CHECK: for.cond:
+; CHECK-NEXT: br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]]
+; CHECK: for.cond1.preheader:
+; CHECK-NEXT: br label [[FOR_BODY3:%.*]]
+; CHECK: for.cond1:
+; CHECK-NEXT: br label [[L2:%.*]]
+; CHECK: for.body3:
+; CHECK-NEXT: br i1 undef, label [[FOR_COND1:%.*]], label [[L1_LOOPEXIT]]
+; CHECK: l2:
+; CHECK-NEXT: [[G_4:%.*]] = phi i32* [ @b, [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT: [[F_2:%.*]] = phi i32* [ [[F_0]], [[FOR_END14]] ], [ @a, [[FOR_COND1]] ]
+; CHECK-NEXT: br label [[FOR_INC:%.*]]
+; CHECK: for.inc:
+; CHECK-NEXT: br i1 false, label [[FOR_COND_LOOPEXIT:%.*]], label [[FOR_INC]]
+; CHECK: for.end14:
+; CHECK-NEXT: br label [[L2]]
+;
+entry:
+ br label %l1
+l1.loopexit:
+ %g.223.lcssa = phi i32* [ @b, %for.body3 ]
+ br label %l1
+l1:
+ %g.0 = phi i32* [ undef, %entry ], [ %g.223.lcssa, %l1.loopexit ]
+ %f.0 = phi i32* [ @b, %entry ], [ @a, %l1.loopexit ]
+ br label %for.cond
+for.cond.loopexit:
+ br label %for.cond
+for.cond:
+ %g.1 = phi i32* [ %g.0, %l1 ], [ %g.4, %for.cond.loopexit ]
+ %f.1 = phi i32* [ %f.0, %l1 ], [ %f.2, %for.cond.loopexit ]
+ br i1 undef, label %for.end14, label %for.cond1.preheader
+for.cond1.preheader:
+ br label %for.body3
+for.cond1:
+ br label %l2
+for.body3:
+ br i1 undef, label %for.cond1, label %l1.loopexit
+l2:
+ %g.4 = phi i32* [ %g.1, %for.end14 ], [ @a, %for.cond1 ]
+ %f.2 = phi i32* [ %f.1, %for.end14 ], [ @a, %for.cond1 ]
+ br label %for.inc
+for.inc:
+ br i1 false, label %for.cond.loopexit, label %for.inc
+for.end14:
+ br label %l2
+}
diff --git a/test/Transforms/NewGVN/pr32897.ll b/test/Transforms/NewGVN/pr32897.ll
new file mode 100644
index 0000000000000..eb19aa367b72f
--- /dev/null
+++ b/test/Transforms/NewGVN/pr32897.ll
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+define void @tinkywinky(i64* %b) {
+; CHECK-LABEL: @tinkywinky(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[BODY:%.*]]
+; CHECK: body:
+; CHECK-NEXT: store i64 undef, i64* [[B:%.*]]
+; CHECK-NEXT: [[B2:%.*]] = load i64, i64* [[B]]
+; CHECK-NEXT: br i1 undef, label [[BODY]], label [[END:%.*]]
+; CHECK: end:
+; CHECK-NEXT: br label [[BODY]]
+;
+entry:
+ br label %body
+body:
+ %d.1 = phi i64* [ undef, %entry ], [ %d.1, %body ], [ %b, %end ]
+ store i64 undef, i64* %d.1
+ %b2 = load i64, i64* %b
+ %or = or i64 %b2, 0
+ store i64 %or, i64* %b
+ br i1 undef, label %body, label %end
+end:
+ br label %body
+}
diff --git a/test/Transforms/NewGVN/pr32945.ll b/test/Transforms/NewGVN/pr32945.ll
new file mode 100644
index 0000000000000..553ba4bd4aaaf
--- /dev/null
+++ b/test/Transforms/NewGVN/pr32945.ll
@@ -0,0 +1,24 @@
+; RUN: opt -S -newgvn %s | FileCheck %s
+; CHECK-NOT: call i32 @llvm.ssa.copy
+
+@d = external global i32
+@e = external global i32
+define void @tinkywinky() {
+ br i1 true, label %lor.lhs.false, label %cond.true
+lor.lhs.false:
+ %tmp = load i32, i32* @d, align 4
+ %patatino = load i32, i32* null, align 4
+ %or = or i32 %tmp, %patatino
+ store i32 %or, i32* @d, align 4
+ br label %cond.true
+cond.true:
+ %tmp1 = load i32, i32* @e, align 4
+ %tmp2 = load i32, i32* @d, align 4
+ %cmp = icmp eq i32 %tmp1, %tmp2
+ br i1 %cmp, label %cond.true6, label %cond.false
+cond.true6:
+ %cmp7 = icmp slt i32 %tmp1, 0
+ br i1 %cmp7, label %cond.false, label %cond.false
+cond.false:
+ ret void
+}
diff --git a/test/Transforms/NewGVN/pr33014.ll b/test/Transforms/NewGVN/pr33014.ll
new file mode 100644
index 0000000000000..4157178e4f0cc
--- /dev/null
+++ b/test/Transforms/NewGVN/pr33014.ll
@@ -0,0 +1,54 @@
+; Make sure we don't end up in an infinite recursion in singleReachablePHIPath().
+; REQUIRES: asserts
+; RUN: opt -newgvn -S %s | FileCheck %s
+
+@c = external global i64, align 8
+
+; CHECK-LABEL: define void @tinkywinky() {
+; CHECK: entry:
+; CHECK-NEXT: br i1 undef, label %l2, label %if.then
+; CHECK: if.then: ; preds = %entry
+; CHECK-NEXT: br label %for.body
+; CHECK: ph: ; preds = %back, %ontrue
+; CHECK-NEXT: br label %for.body
+; CHECK: for.body: ; preds = %ph, %if.then
+; CHECK-NEXT: br i1 undef, label %ontrue, label %onfalse
+; CHECK: onfalse: ; preds = %for.body
+; CHECK-NEXT: %patatino = load i64, i64* @c
+; CHECK-NEXT: ret void
+; CHECK: ontrue: ; preds = %for.body
+; CHECK-NEXT: %dipsy = load i64, i64* @c
+; CHECK-NEXT: br label %ph
+; CHECK: back: ; preds = %l2
+; CHECK-NEXT: store i8 undef, i8* null
+; CHECK-NEXT: br label %ph
+; CHECK: end: ; preds = %l2
+; CHECK-NEXT: ret void
+; CHECK: l2: ; preds = %entry
+; CHECK-NEXT: br i1 false, label %back, label %end
+; CHECK-NEXT: }
+
+define void @tinkywinky() {
+entry:
+ br i1 undef, label %l2, label %if.then
+if.then:
+ br label %for.body
+ph:
+ br label %for.body
+for.body:
+ br i1 undef, label %ontrue, label %onfalse
+onfalse:
+ %patatino = load i64, i64* @c
+ store i64 %patatino, i64* @c
+ ret void
+ontrue:
+ %dipsy = load i64, i64* @c
+ store i64 %dipsy, i64* @c
+ br label %ph
+back:
+ br label %ph
+end:
+ ret void
+l2:
+ br i1 false, label %back, label %end
+}
diff --git a/test/Transforms/NewGVN/pr33086.ll b/test/Transforms/NewGVN/pr33086.ll
new file mode 100644
index 0000000000000..6117ef35e6deb
--- /dev/null
+++ b/test/Transforms/NewGVN/pr33086.ll
@@ -0,0 +1,59 @@
+; RUN: opt -newgvn -S %s | FileCheck %s
+; REQUIRES: asserts
+
+; CHECK-LABEL: define void @tinkywinky() {
+; CHECK: entry:
+; CHECK-NEXT: br i1 undef, label %for.cond18, label %for.cond.preheader
+; CHECK: for.cond.preheader:
+; CHECK-NEXT: br label %for.cond2thread-pre-split
+; CHECK: for.cond2thread-pre-split:
+; CHECK-NEXT: %conv24 = phi i32 [ 0, %for.cond.preheader ], [ %conv, %for.inc.split ]
+; CHECK-NEXT: br label %for.inc.split
+; CHECK: for.inc.split:
+; CHECK-NEXT: %add = shl nsw i32 %conv24, 16
+; CHECK-NEXT: %sext23 = add i32 %add, 65536
+; CHECK-NEXT: %conv = ashr exact i32 %sext23, 16
+; CHECK-NEXT: %cmp = icmp slt i32 %sext23, 3604480
+; CHECK-NEXT: br i1 %cmp, label %for.cond2thread-pre-split, label %l1.loopexit
+; CHECK: l1.loopexit:
+; CHECK-NEXT: br label %l1
+; CHECK: l1:
+; CHECK-NEXT: %0 = load i16, i16* null, align 2
+; CHECK-NEXT: %g.0.g.0..pr = load i16, i16* null, align 2
+; CHECK-NEXT: ret void
+; CHECK: for.cond18:
+; CHECK-NEXT: br label %l1
+; CHECK-NEXT: }
+
+define void @tinkywinky() {
+entry:
+ br i1 undef, label %for.cond18, label %for.cond.preheader
+
+for.cond.preheader:
+ br label %for.cond2thread-pre-split
+
+for.cond2thread-pre-split:
+ %conv24 = phi i32 [ 0, %for.cond.preheader ], [ %conv, %for.inc.split ]
+ br label %for.inc.split
+
+for.inc.split:
+ %add = shl nsw i32 %conv24, 16
+ %sext23 = add i32 %add, 65536
+ %conv = ashr exact i32 %sext23, 16
+ %cmp = icmp slt i32 %sext23, 3604480
+ br i1 %cmp, label %for.cond2thread-pre-split, label %l1.loopexit
+
+l1.loopexit:
+ br label %l1
+
+l1:
+ %h.0 = phi i16* [ undef, %for.cond18 ], [ null, %l1.loopexit ]
+ %0 = load i16, i16* %h.0, align 2
+ store i16 %0, i16* null, align 2
+ %g.0.g.0..pr = load i16, i16* null, align 2
+ %tobool15 = icmp eq i16 %g.0.g.0..pr, 0
+ ret void
+
+for.cond18:
+ br label %l1
+}
diff --git a/test/Transforms/NewGVN/pr33116.ll b/test/Transforms/NewGVN/pr33116.ll
new file mode 100644
index 0000000000000..9bf6bb1ff6efe
--- /dev/null
+++ b/test/Transforms/NewGVN/pr33116.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -newgvn %s | FileCheck %s
+
+@a = external global i32
+
+define void @b() {
+; CHECK-LABEL: @b(
+; CHECK-NEXT: br i1 false, label [[C:%.*]], label [[WHILE_D:%.*]]
+; CHECK: while.d:
+; CHECK-NEXT: br label [[F:%.*]]
+; CHECK: f:
+; CHECK-NEXT: br i1 undef, label [[IF_E:%.*]], label [[C]]
+; CHECK: c:
+; CHECK-NEXT: br i1 undef, label [[IF_G:%.*]], label [[IF_E]]
+; CHECK: if.g:
+; CHECK-NEXT: store i32 undef, i32* @a
+; CHECK-NEXT: br label [[WHILE_D]]
+; CHECK: if.e:
+; CHECK-NEXT: br label [[F]]
+;
+ br i1 false, label %c, label %while.d
+
+while.d: ; preds = %if.g, %0
+ br label %f
+
+f: ; preds = %if.e, %while.d
+ br i1 undef, label %if.e, label %c
+
+c: ; preds = %f, %0
+ br i1 undef, label %if.g, label %if.e
+
+if.g: ; preds = %c
+ store i32 undef, i32* @a
+ br label %while.d
+
+if.e: ; preds = %c, %f
+ br label %f
+}
+
diff --git a/test/Transforms/NewGVN/storeoverstore.ll b/test/Transforms/NewGVN/storeoverstore.ll
index 49b55d430dc75..28f5eea03ced6 100644
--- a/test/Transforms/NewGVN/storeoverstore.ll
+++ b/test/Transforms/NewGVN/storeoverstore.ll
@@ -13,11 +13,11 @@ define i32 @foo(i32*, i32) {
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
; CHECK: br label [[TMP5]]
-; CHECK: [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP2:%.*]] ]
-; CHECK-NEXT: br i1 [[TMP3]], label [[TMP6:%.*]], label [[TMP8:%.*]]
-; CHECK: [[TMP7:%.*]] = add nsw i32 [[DOT0]], 5
-; CHECK-NEXT: br label [[TMP8]]
-; CHECK: [[DOT1:%.*]] = phi i32 [ [[TMP7]], [[TMP6]] ], [ [[DOT0]], [[TMP5]] ]
+; CHECK: [[TMP6:%.*]] = phi i32 [ 15, [[TMP4]] ], [ 10, [[TMP2:%.*]] ]
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP2]] ]
+; CHECK-NEXT: br i1 [[TMP3]], label [[TMP7:%.*]], label [[TMP8:%.*]]
+; CHECK: br label [[TMP8]]
+; CHECK: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP7]] ], [ [[DOT0]], [[TMP5]] ]
; CHECK-NEXT: ret i32 [[DOT1]]
;
store i32 5, i32* %0, align 4
@@ -54,11 +54,11 @@ define i32 @foo2(i32*, i32) {
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
; CHECK: br label [[TMP6:%.*]]
; CHECK: br label [[TMP6]]
-; CHECK: [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP5]] ]
-; CHECK-NEXT: br i1 [[TMP3]], label [[TMP7:%.*]], label [[TMP9:%.*]]
-; CHECK: [[TMP8:%.*]] = add nsw i32 [[DOT0]], 5
-; CHECK-NEXT: br label [[TMP9]]
-; CHECK: [[DOT1:%.*]] = phi i32 [ [[TMP8]], [[TMP7]] ], [ [[DOT0]], [[TMP6]] ]
+; CHECK: [[TMP7:%.*]] = phi i32 [ 15, [[TMP4]] ], [ 10, [[TMP5]] ]
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP5]] ]
+; CHECK-NEXT: br i1 [[TMP3]], label [[TMP8:%.*]], label [[TMP9:%.*]]
+; CHECK: br label [[TMP9]]
+; CHECK: [[DOT1:%.*]] = phi i32 [ [[TMP7]], [[TMP8]] ], [ [[DOT0]], [[TMP6]] ]
; CHECK-NEXT: ret i32 [[DOT1]]
;
store i32 5, i32* %0, align 4
diff --git a/test/Transforms/SafeStack/X86/coloring-ssp.ll b/test/Transforms/SafeStack/X86/coloring-ssp.ll
index 3b04fdf13fbc6..040632e7526d1 100644
--- a/test/Transforms/SafeStack/X86/coloring-ssp.ll
+++ b/test/Transforms/SafeStack/X86/coloring-ssp.ll
@@ -1,4 +1,4 @@
-; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
; %x and %y share a stack slot between them, but not with the stack guard.
define void @f() safestack sspreq {
diff --git a/test/Transforms/SafeStack/X86/coloring.ll b/test/Transforms/SafeStack/X86/coloring.ll
index 76bdf37dbf4e8..60e960e693d5e 100644
--- a/test/Transforms/SafeStack/X86/coloring.ll
+++ b/test/Transforms/SafeStack/X86/coloring.ll
@@ -1,5 +1,5 @@
-; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
-; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
define void @f() safestack {
entry:
diff --git a/test/Transforms/SafeStack/X86/coloring2.ll b/test/Transforms/SafeStack/X86/coloring2.ll
index 2a8f871945ffc..ef00d9b547158 100644
--- a/test/Transforms/SafeStack/X86/coloring2.ll
+++ b/test/Transforms/SafeStack/X86/coloring2.ll
@@ -1,5 +1,5 @@
-; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
-; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
; x and y share the stack slot.
define void @f() safestack {
diff --git a/test/Transforms/SafeStack/X86/layout-frag.ll b/test/Transforms/SafeStack/X86/layout-frag.ll
index b127defc2c5d8..b9831c26b74cb 100644
--- a/test/Transforms/SafeStack/X86/layout-frag.ll
+++ b/test/Transforms/SafeStack/X86/layout-frag.ll
@@ -1,5 +1,5 @@
; Test that safestack layout reuses a region w/o fragmentation.
-; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -safe-stack-coloring=1 -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
define void @f() safestack {
; CHECK-LABEL: define void @f