diff options
Diffstat (limited to 'test/Transforms')
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 |