diff options
Diffstat (limited to 'test/Transforms/InstCombine')
105 files changed, 5741 insertions, 744 deletions
diff --git a/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll b/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll index 7f06f009515f..c303ddd58974 100644 --- a/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll +++ b/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -instcombine -S | grep icmp ; PR1646 -@__gthrw_pthread_cancel = weak alias i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=1] +@__gthrw_pthread_cancel = weak alias i32 (i32), i32 (i32)* @pthread_cancel ; <i32 (i32)*> [#uses=1] @__gthread_active_ptr.5335 = internal constant i8* bitcast (i32 (i32)* @__gthrw_pthread_cancel to i8*) ; <i8**> [#uses=1] define weak i32 @pthread_cancel(i32) { ret i32 0 diff --git a/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll b/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll index 3793a860e8e9..7c6df1f984a4 100644 --- a/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll +++ b/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -instcombine -S | grep icmp ; PR1678 -@A = weak alias void ()* @B ; <void ()*> [#uses=1] +@A = weak alias void (), void ()* @B ; <void ()*> [#uses=1] define weak void @B() { ret void diff --git a/test/Transforms/InstCombine/LandingPadClauses.ll b/test/Transforms/InstCombine/LandingPadClauses.ll index a4d77cbe8efb..75050c91bbb4 100644 --- a/test/Transforms/InstCombine/LandingPadClauses.ll +++ b/test/Transforms/InstCombine/LandingPadClauses.ll @@ -69,9 +69,11 @@ lpad.c: filter [1 x i32*] [i32* @T1] catch i32* @T2 unreachable +; Caught types should not be removed from filters ; CHECK: %c = landingpad -; CHECK-NEXT: @T1 -; CHECK-NEXT: filter [0 x i32*] +; CHECK-NEXT: catch i32* @T1 +; CHECK-NEXT: filter [1 x i32*] [i32* @T1] +; CHECK-NEXT: catch i32* @T2 ; CHECK-NEXT: unreachable lpad.d: @@ -87,9 +89,10 @@ lpad.e: catch i32* @T1 filter [3 x i32*] [i32* @T1, i32* @T2, i32* @T2] unreachable +; Caught types should not be removed from filters ; CHECK: %e = landingpad -; CHECK-NEXT: @T1 -; CHECK-NEXT: filter [1 x i32*] [i32* @T2] +; CHECK-NEXT: catch i32* @T1 +; CHECK-NEXT: filter [2 x i32*] [i32* @T1, i32* @T2] ; CHECK-NEXT: unreachable lpad.f: diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll index 1af2b0ffbf0a..2fe9e8cadeb7 100644 --- a/test/Transforms/InstCombine/add2.ll +++ b/test/Transforms/InstCombine/add2.ll @@ -395,3 +395,13 @@ define i8 @add_of_mul(i8 %x, i8 %y, i8 %z) { %sum = add nsw i8 %mA, %mB ret i8 %sum } + +define i32 @add_of_selects(i1 %A, i32 %B) { + %sel0 = select i1 %A, i32 0, i32 -2 + %sel1 = select i1 %A, i32 %B, i32 2 + %add = add i32 %sel0, %sel1 + ret i32 %add +; CHECK-LABEL: @add_of_selects( +; CHECK-NEXT: %[[sel:.*]] = select i1 %A, i32 %B, i32 0 +; CHECK-NEXT: ret i32 %[[sel]] +} diff --git a/test/Transforms/InstCombine/alias-recursion.ll b/test/Transforms/InstCombine/alias-recursion.ll index 74254f3e8dff..efc1899e1f47 100644 --- a/test/Transforms/InstCombine/alias-recursion.ll +++ b/test/Transforms/InstCombine/alias-recursion.ll @@ -7,7 +7,7 @@ target triple = "x86_64-pc-windows-msvc" @0 = constant [1 x i8*] zeroinitializer -@vtbl = alias getelementptr inbounds ([1 x i8*], [1 x i8*]* @0, i32 0, i32 0) +@vtbl = alias i8*, getelementptr inbounds ([1 x i8*], [1 x i8*]* @0, i32 0, i32 0) define i32 (%class.A*)* @test() { ; CHECK-LABEL: test diff --git a/test/Transforms/InstCombine/all-bits-shift.ll b/test/Transforms/InstCombine/all-bits-shift.ll new file mode 100644 index 000000000000..b9eb19cf2ad1 --- /dev/null +++ b/test/Transforms/InstCombine/all-bits-shift.ll @@ -0,0 +1,46 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s +; RUN: opt -S -instsimplify < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +@d = global i32 15, align 4 +@b = global i32* @d, align 8 +@a = common global i32 0, align 4 + +; Function Attrs: nounwind +define signext i32 @main() #1 { +entry: + %0 = load i32*, i32** @b, align 8 + %1 = load i32, i32* @a, align 4 + %lnot = icmp eq i32 %1, 0 + %lnot.ext = zext i1 %lnot to i32 + %shr.i = lshr i32 2072, %lnot.ext + %call.lobit = lshr i32 %shr.i, 7 + %2 = and i32 %call.lobit, 1 + %3 = load i32, i32* %0, align 4 + %or = or i32 %2, %3 + store i32 %or, i32* %0, align 4 + %4 = load i32, i32* @a, align 4 + %lnot.1 = icmp eq i32 %4, 0 + %lnot.ext.1 = zext i1 %lnot.1 to i32 + %shr.i.1 = lshr i32 2072, %lnot.ext.1 + %call.lobit.1 = lshr i32 %shr.i.1, 7 + %5 = and i32 %call.lobit.1, 1 + %or.1 = or i32 %5, %or + store i32 %or.1, i32* %0, align 4 + ret i32 %or.1 + +; Check that both InstCombine and InstSimplify can use computeKnownBits to +; realize that: +; ((2072 >> (L == 0)) >> 7) & 1 +; is always zero. + +; CHECK-LABEL: @main +; CHECK: %[[V1:[0-9]+]] = load i32*, i32** @b, align 8 +; CHECK: %[[V2:[0-9]+]] = load i32, i32* %[[V1]], align 4 +; CHECK: ret i32 %[[V2]] +} + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } + diff --git a/test/Transforms/InstCombine/alloca.ll b/test/Transforms/InstCombine/alloca.ll index b61b75e9f9f3..2ee0372e5e0a 100644 --- a/test/Transforms/InstCombine/alloca.ll +++ b/test/Transforms/InstCombine/alloca.ll @@ -163,3 +163,14 @@ entry: call void (...) @use(i1* %v32, i1* %v64, i1* %v33) ret void } + +define void @test11() { +entry: +; ALL-LABEL: @test11( +; ALL: %y = alloca i32 +; ALL: call void (...) @use(i32* nonnull @int) [ "blah"(i32* %y) ] +; ALL: ret void + %y = alloca i32 + call void (...) @use(i32* nonnull @int) [ "blah"(i32* %y) ] + ret void +} diff --git a/test/Transforms/InstCombine/and-compare.ll b/test/Transforms/InstCombine/and-compare.ll index 037641b90ad7..53ea81d1c0d4 100644 --- a/test/Transforms/InstCombine/and-compare.ll +++ b/test/Transforms/InstCombine/and-compare.ll @@ -1,6 +1,9 @@ ; RUN: opt < %s -instcombine -S | \ ; RUN: FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + ; Should be optimized to one and. define i1 @test1(i32 %a, i32 %b) { ; CHECK-LABEL: @test1( @@ -13,3 +16,23 @@ define i1 @test1(i32 %a, i32 %b) { %tmp = icmp ne i32 %tmp1, %tmp3 ; <i1> [#uses=1] ret i1 %tmp } + +define zeroext i1 @test2(i64 %A) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: %[[trunc:.*]] = trunc i64 %A to i8 +; CHECK-NEXT: %[[icmp:.*]] = icmp sgt i8 %[[trunc]], -1 +; CHECK-NEXT: ret i1 %[[icmp]] + %and = and i64 %A, 128 + %cmp = icmp eq i64 %and, 0 + ret i1 %cmp +} + +define zeroext i1 @test3(i64 %A) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: %[[trunc:.*]] = trunc i64 %A to i8 +; CHECK-NEXT: %[[icmp:.*]] = icmp slt i8 %[[trunc]], 0 +; CHECK-NEXT: ret i1 %[[icmp]] + %and = and i64 %A, 128 + %cmp = icmp ne i64 %and, 0 + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll index 96b535dda99d..326bfda38553 100644 --- a/test/Transforms/InstCombine/and2.ll +++ b/test/Transforms/InstCombine/and2.ll @@ -77,3 +77,71 @@ define i1 @test8(i32 %i) { %cond = and i1 %cmp1, %cmp2 ret i1 %cond } + +; combine -x & 1 into x & 1 +define i64 @test9(i64 %x) { +; CHECK-LABEL: @test9( +; CHECK-NOT: %sub = sub nsw i64 0, %x +; CHECK-NOT: %and = and i64 %sub, 1 +; CHECK-NEXT: %and = and i64 %x, 1 +; CHECK-NEXT: ret i64 %and + %sub = sub nsw i64 0, %x + %and = and i64 %sub, 1 + ret i64 %and +} + +define i64 @test10(i64 %x) { +; CHECK-LABEL: @test10( +; CHECK-NOT: %sub = sub nsw i64 0, %x +; CHECK-NEXT: %and = and i64 %x, 1 +; CHECK-NOT: %add = add i64 %sub, %and +; CHECK-NEXT: %add = sub i64 %and, %x +; CHECK-NEXT: ret i64 %add + %sub = sub nsw i64 0, %x + %and = and i64 %sub, 1 + %add = add i64 %sub, %and + ret i64 %add +} + +define i64 @fabs_double(double %x) { +; CHECK-LABEL: @fabs_double( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %and = bitcast double %fabs to i64 +; CHECK-NEXT: ret i64 %and + %bc = bitcast double %x to i64 + %and = and i64 %bc, 9223372036854775807 + ret i64 %and +} + +define i64 @fabs_double_swap(double %x) { +; CHECK-LABEL: @fabs_double_swap( +; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %and = bitcast double %fabs to i64 +; CHECK-NEXT: ret i64 %and + %bc = bitcast double %x to i64 + %and = and i64 9223372036854775807, %bc + ret i64 %and +} + +define i32 @fabs_float(float %x) { +; CHECK-LABEL: @fabs_float( +; CHECK-NEXT: %fabs = call float @llvm.fabs.f32(float %x) +; CHECK-NEXT: %and = bitcast float %fabs to i32 +; CHECK-NEXT: ret i32 %and + %bc = bitcast float %x to i32 + %and = and i32 %bc, 2147483647 + ret i32 %and +} + +; Make sure that only a bitcast is transformed. + +define i64 @fabs_double_not_bitcast(double %x) { +; CHECK-LABEL: @fabs_double_not_bitcast( +; CHECK-NEXT: %bc = fptoui double %x to i64 +; CHECK-NEXT: %and = and i64 %bc, 9223372036854775807 +; CHECK-NEXT: ret i64 %and + %bc = fptoui double %x to i64 + %and = and i64 %bc, 9223372036854775807 + ret i64 %and +} + diff --git a/test/Transforms/InstCombine/apint-or.ll b/test/Transforms/InstCombine/apint-or.ll new file mode 100644 index 000000000000..e2312b61f2b9 --- /dev/null +++ b/test/Transforms/InstCombine/apint-or.ll @@ -0,0 +1,79 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; These tests are for Integer BitWidth <= 64 && BitWidth % 2 != 0. +define i23 @test1(i23 %A) { + ;; A | ~A == -1 + %NotA = xor i23 -1, %A + %B = or i23 %A, %NotA + ret i23 %B +; CHECK-LABEL: @test1 +; CHECK-NEXT: ret i23 -1 +} + +define i39 @test2(i39 %V, i39 %M) { + ;; If we have: ((V + N) & C1) | (V & C2) + ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 + ;; replace with V+N. + %C1 = xor i39 274877906943, -1 ;; C2 = 274877906943 + %N = and i39 %M, 274877906944 + %A = add i39 %V, %N + %B = and i39 %A, %C1 + %D = and i39 %V, 274877906943 + %R = or i39 %B, %D + ret i39 %R +; CHECK-LABEL: @test2 +; CHECK-NEXT: %N = and i39 %M, -274877906944 +; CHECK-NEXT: %A = add i39 %N, %V +; CHECK-NEXT: ret i39 %A +} + +define i43 @test3(i43 %A, i43 %B) { + ;; (~A | ~B) == (~(A & B)) - De Morgan's Law + %NotA = xor i43 %A, -1 + %NotB = xor i43 %B, -1 + %C1 = or i43 %NotA, %NotB + ret i43 %C1 +; CHECK-LABEL: @test3 +; CHECK-NEXT: %C1.demorgan = and i43 %A, %B +; CHECK-NEXT: %C1 = xor i43 %C1.demorgan, -1 +; CHECK-NEXT: ret i43 %C1 +} + +; These tests are for Integer BitWidth > 64 && BitWidth <= 1024. +define i1023 @test4(i1023 %A) { + ;; A | ~A == -1 + %NotA = xor i1023 -1, %A + %B = or i1023 %A, %NotA + ret i1023 %B +; CHECK-LABEL: @test4 +; CHECK-NEXT: ret i1023 -1 +} + +define i399 @test5(i399 %V, i399 %M) { + ;; If we have: ((V + N) & C1) | (V & C2) + ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 + ;; replace with V+N. + %C1 = xor i399 274877906943, -1 ;; C2 = 274877906943 + %N = and i399 %M, 18446742974197923840 + %A = add i399 %V, %N + %B = and i399 %A, %C1 + %D = and i399 %V, 274877906943 + %R = or i399 %B, %D + ret i399 %R +; CHECK-LABEL: @test5 +; CHECK-NEXT: %N = and i399 %M, 18446742974197923840 +; CHECK-NEXT: %A = add i399 %N, %V +; CHECK-NEXT: ret i399 %A +} + +define i129 @test6(i129 %A, i129 %B) { + ;; (~A | ~B) == (~(A & B)) - De Morgan's Law + %NotA = xor i129 %A, -1 + %NotB = xor i129 %B, -1 + %C1 = or i129 %NotA, %NotB + ret i129 %C1 +; CHECK-LABEL: @test6 +; CHECK-NEXT: %C1.demorgan = and i129 %A, %B +; CHECK-NEXT: %C1 = xor i129 %C1.demorgan, -1 +; CHECK-NEXT: ret i129 %C1 +} diff --git a/test/Transforms/InstCombine/apint-or1.ll b/test/Transforms/InstCombine/apint-or1.ll deleted file mode 100644 index d4f87ac894d9..000000000000 --- a/test/Transforms/InstCombine/apint-or1.ll +++ /dev/null @@ -1,36 +0,0 @@ -; This test makes sure that or instructions are properly eliminated. -; This test is for Integer BitWidth <= 64 && BitWidth % 2 != 0. -; - -; RUN: opt < %s -instcombine -S | not grep or - - -define i7 @test0(i7 %X) { - %Y = or i7 %X, 0 - ret i7 %Y -} - -define i17 @test1(i17 %X) { - %Y = or i17 %X, -1 - ret i17 %Y -} - -define i23 @test2(i23 %A) { - ;; A | ~A == -1 - %NotA = xor i23 -1, %A - %B = or i23 %A, %NotA - ret i23 %B -} - -define i39 @test3(i39 %V, i39 %M) { - ;; If we have: ((V + N) & C1) | (V & C2) - ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 - ;; replace with V+N. - %C1 = xor i39 274877906943, -1 ;; C2 = 274877906943 - %N = and i39 %M, 274877906944 - %A = add i39 %V, %N - %B = and i39 %A, %C1 - %D = and i39 %V, 274877906943 - %R = or i39 %B, %D - ret i39 %R -} diff --git a/test/Transforms/InstCombine/apint-or2.ll b/test/Transforms/InstCombine/apint-or2.ll deleted file mode 100644 index d7de255f7fd2..000000000000 --- a/test/Transforms/InstCombine/apint-or2.ll +++ /dev/null @@ -1,35 +0,0 @@ -; This test makes sure that or instructions are properly eliminated. -; This test is for Integer BitWidth > 64 && BitWidth <= 1024. -; -; RUN: opt < %s -instcombine -S | not grep or - - -define i777 @test0(i777 %X) { - %Y = or i777 %X, 0 - ret i777 %Y -} - -define i117 @test1(i117 %X) { - %Y = or i117 %X, -1 - ret i117 %Y -} - -define i1023 @test2(i1023 %A) { - ;; A | ~A == -1 - %NotA = xor i1023 -1, %A - %B = or i1023 %A, %NotA - ret i1023 %B -} - -define i399 @test3(i399 %V, i399 %M) { - ;; If we have: ((V + N) & C1) | (V & C2) - ;; .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 - ;; replace with V+N. - %C1 = xor i399 274877906943, -1 ;; C2 = 274877906943 - %N = and i399 %M, 18446742974197923840 - %A = add i399 %V, %N - %B = and i399 %A, %C1 - %D = and i399 %V, 274877906943 - %R = or i399 %B, %D - ret i399 %R -} diff --git a/test/Transforms/InstCombine/assume-redundant.ll b/test/Transforms/InstCombine/assume-redundant.ll index 4b869ef2c50e..4bdbcc8d086a 100644 --- a/test/Transforms/InstCombine/assume-redundant.ll +++ b/test/Transforms/InstCombine/assume-redundant.ll @@ -47,6 +47,32 @@ for.end: ; preds = %for.body ret void } +declare align 8 i8* @get() + +; Check that redundant align assume is removed +; CHECK-LABEL: @test +; CHECK-NOT: call void @llvm.assume +define void @test1() { + %p = call align 8 i8* @get() + %ptrint = ptrtoint i8* %p to i64 + %maskedptr = and i64 %ptrint, 7 + %maskcond = icmp eq i64 %maskedptr, 0 + call void @llvm.assume(i1 %maskcond) + ret void +} + +; Check that redundant align assume is removed +; CHECK-LABEL: @test +; CHECK-NOT: call void @llvm.assume +define void @test3() { + %p = alloca i8, align 8 + %ptrint = ptrtoint i8* %p to i64 + %maskedptr = and i64 %ptrint, 7 + %maskcond = icmp eq i64 %maskedptr, 0 + call void @llvm.assume(i1 %maskcond) + ret void +} + ; Function Attrs: nounwind declare void @llvm.assume(i1) #1 diff --git a/test/Transforms/InstCombine/bitcast-alias-function.ll b/test/Transforms/InstCombine/bitcast-alias-function.ll index 1a598a5d4153..b04308e10e23 100644 --- a/test/Transforms/InstCombine/bitcast-alias-function.ll +++ b/test/Transforms/InstCombine/bitcast-alias-function.ll @@ -6,46 +6,46 @@ target datalayout = "e-p:32:32:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16 ; Cases that should be bitcast ; Test cast between scalars with same bit sizes -@alias_i32_to_f32 = alias bitcast (i32 (i32)* @func_i32 to float (float)*) +@alias_i32_to_f32 = alias float (float), bitcast (i32 (i32)* @func_i32 to float (float)*) ; Test cast between vectors with same number of elements and bit sizes -@alias_v2i32_to_v2f32 = alias bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <2 x float> (<2 x float>)*) +@alias_v2i32_to_v2f32 = alias <2 x float> (<2 x float>), bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <2 x float> (<2 x float>)*) ; Test cast from vector to scalar with same number of bits -@alias_v2f32_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <2 x float> (<2 x float>)*) +@alias_v2f32_to_i64 = alias <2 x float> (<2 x float>), bitcast (i64 (i64)* @func_i64 to <2 x float> (<2 x float>)*) ; Test cast from scalar to vector with same number of bits -@alias_i64_to_v2f32 = alias bitcast (<2 x float> (<2 x float>)* @func_v2f32 to i64 (i64)*) +@alias_i64_to_v2f32 = alias i64 (i64), bitcast (<2 x float> (<2 x float>)* @func_v2f32 to i64 (i64)*) ; Test cast between vectors of pointers -@alias_v2i32p_to_v2i64p = alias bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to <2 x i64*> (<2 x i64*>)*) +@alias_v2i32p_to_v2i64p = alias <2 x i64*> (<2 x i64*>), bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to <2 x i64*> (<2 x i64*>)*) ; Cases that should be invalid and unchanged ; Test cast between scalars with different bit sizes -@alias_i64_to_f32 = alias bitcast (i64 (i64)* @func_i64 to float (float)*) +@alias_i64_to_f32 = alias float (float), bitcast (i64 (i64)* @func_i64 to float (float)*) ; Test cast between vectors with different bit sizes but the ; same number of elements -@alias_v2i64_to_v2f32 = alias bitcast (<2 x i64> (<2 x i64>)* @func_v2i64 to <2 x float> (<2 x float>)*) +@alias_v2i64_to_v2f32 = alias <2 x float> (<2 x float>), bitcast (<2 x i64> (<2 x i64>)* @func_v2i64 to <2 x float> (<2 x float>)*) ; Test cast between vectors with same number of bits and different ; numbers of elements -@alias_v2i32_to_v4f32 = alias bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <4 x float> (<4 x float>)*) +@alias_v2i32_to_v4f32 = alias <4 x float> (<4 x float>), bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <4 x float> (<4 x float>)*) ; Test cast between scalar and vector with different number of bits -@alias_i64_to_v4f32 = alias bitcast (<4 x float> (<4 x float>)* @func_v4f32 to i64 (i64)*) +@alias_i64_to_v4f32 = alias i64 (i64), bitcast (<4 x float> (<4 x float>)* @func_v4f32 to i64 (i64)*) ; Test cast between vector and scalar with different number of bits -@alias_v4f32_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <4 x float> (<4 x float>)*) +@alias_v4f32_to_i64 = alias <4 x float> (<4 x float>), bitcast (i64 (i64)* @func_i64 to <4 x float> (<4 x float>)*) ; Test cast from scalar to vector of pointers with same number of bits ; We don't know the pointer size at this point, so this can't be done -@alias_i64_to_v2i32p = alias bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to i64 (i64)*) +@alias_i64_to_v2i32p = alias i64 (i64), bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to i64 (i64)*) ; Test cast between vector of pointers and scalar with different number of bits -@alias_v4i32p_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <4 x i32*> (<4 x i32*>)*) +@alias_v4i32p_to_i64 = alias <4 x i32*> (<4 x i32*>), bitcast (i64 (i64)* @func_i64 to <4 x i32*> (<4 x i32*>)*) diff --git a/test/Transforms/InstCombine/bitcast-bitcast.ll b/test/Transforms/InstCombine/bitcast-bitcast.ll new file mode 100644 index 000000000000..0f46ff53bc18 --- /dev/null +++ b/test/Transforms/InstCombine/bitcast-bitcast.ll @@ -0,0 +1,84 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Check all scalar / vector combinations for a pair of bitcasts. + +define ppc_fp128 @bitcast_bitcast_s_s_s(i128 %a) { + %bc1 = bitcast i128 %a to fp128 + %bc2 = bitcast fp128 %bc1 to ppc_fp128 + ret ppc_fp128 %bc2 + +; CHECK-LABEL: @bitcast_bitcast_s_s_s( +; CHECK-NEXT: %bc2 = bitcast i128 %a to ppc_fp128 +; CHECK-NEXT: ret ppc_fp128 %bc2 +} + +define <2 x i32> @bitcast_bitcast_s_s_v(i64 %a) { + %bc1 = bitcast i64 %a to double + %bc2 = bitcast double %bc1 to <2 x i32> + ret <2 x i32> %bc2 + +; CHECK-LABEL: @bitcast_bitcast_s_s_v( +; CHECK-NEXT: %bc2 = bitcast i64 %a to <2 x i32> +; CHECK-NEXT: ret <2 x i32> %bc2 +} + +define double @bitcast_bitcast_s_v_s(i64 %a) { + %bc1 = bitcast i64 %a to <2 x i32> + %bc2 = bitcast <2 x i32> %bc1 to double + ret double %bc2 + +; CHECK-LABEL: @bitcast_bitcast_s_v_s( +; CHECK-NEXT: %bc2 = bitcast i64 %a to double +; CHECK-NEXT: ret double %bc2 +} + +define <2 x i32> @bitcast_bitcast_s_v_v(i64 %a) { + %bc1 = bitcast i64 %a to <4 x i16> + %bc2 = bitcast <4 x i16> %bc1 to <2 x i32> + ret <2 x i32> %bc2 + +; CHECK-LABEL: @bitcast_bitcast_s_v_v( +; CHECK-NEXT: %bc2 = bitcast i64 %a to <2 x i32> +; CHECK-NEXT: ret <2 x i32> %bc2 +} + +define i64 @bitcast_bitcast_v_s_s(<2 x i32> %a) { + %bc1 = bitcast <2 x i32> %a to double + %bc2 = bitcast double %bc1 to i64 + ret i64 %bc2 + +; CHECK-LABEL: @bitcast_bitcast_v_s_s( +; CHECK-NEXT: %bc2 = bitcast <2 x i32> %a to i64 +; CHECK-NEXT: ret i64 %bc2 +} + +define <4 x i16> @bitcast_bitcast_v_s_v(<2 x i32> %a) { + %bc1 = bitcast <2 x i32> %a to double + %bc2 = bitcast double %bc1 to <4 x i16> + ret <4 x i16> %bc2 + +; CHECK-LABEL: @bitcast_bitcast_v_s_v( +; CHECK-NEXT: %bc2 = bitcast <2 x i32> %a to <4 x i16> +; CHECK-NEXT: ret <4 x i16> %bc2 +} + +define double @bitcast_bitcast_v_v_s(<2 x float> %a) { + %bc1 = bitcast <2 x float> %a to <4 x i16> + %bc2 = bitcast <4 x i16> %bc1 to double + ret double %bc2 + +; CHECK-LABEL: @bitcast_bitcast_v_v_s( +; CHECK-NEXT: %bc2 = bitcast <2 x float> %a to double +; CHECK-NEXT: ret double %bc2 +} + +define <2 x i32> @bitcast_bitcast_v_v_v(<2 x float> %a) { + %bc1 = bitcast <2 x float> %a to <4 x i16> + %bc2 = bitcast <4 x i16> %bc1 to <2 x i32> + ret <2 x i32> %bc2 + +; CHECK-LABEL: @bitcast_bitcast_v_v_v( +; CHECK-NEXT: %bc2 = bitcast <2 x float> %a to <2 x i32> +; CHECK-NEXT: ret <2 x i32> %bc2 +} + diff --git a/test/Transforms/InstCombine/bitcast-vec-canon.ll b/test/Transforms/InstCombine/bitcast-vec-canon.ll index d27765e89424..97145221099e 100644 --- a/test/Transforms/InstCombine/bitcast-vec-canon.ll +++ b/test/Transforms/InstCombine/bitcast-vec-canon.ll @@ -1,22 +1,41 @@ -; RUN: opt < %s -instcombine -S | grep element | count 4 +; RUN: opt < %s -instcombine -S | FileCheck %s define double @a(<1 x i64> %y) { %c = bitcast <1 x i64> %y to double - ret double %c + ret double %c + +; CHECK-LABEL: @a( +; CHECK-NEXT: bitcast <1 x i64> %y to <1 x double> +; CHECK-NEXT: extractelement <1 x double> {{.*}}, i32 0 +; CHECK-NEXT: ret double } define i64 @b(<1 x i64> %y) { %c = bitcast <1 x i64> %y to i64 - ret i64 %c + ret i64 %c + +; CHECK-LABEL: @b( +; CHECK-NEXT: extractelement <1 x i64> %y, i32 0 +; CHECK-NEXT: ret i64 } define <1 x i64> @c(double %y) { %c = bitcast double %y to <1 x i64> ret <1 x i64> %c + +; CHECK-LABEL: @c( +; CHECK-NEXT: bitcast double %y to i64 +; CHECK-NEXT: insertelement <1 x i64> undef, i64 {{.*}}, i32 0 +; CHECK-NEXT: ret <1 x i64> } define <1 x i64> @d(i64 %y) { %c = bitcast i64 %y to <1 x i64> ret <1 x i64> %c + +; CHECK-LABEL: @d( +; CHECK-NEXT: insertelement <1 x i64> undef, i64 %y, i32 0 +; CHECK-NEXT: ret <1 x i64> } + diff --git a/test/Transforms/InstCombine/bitcast.ll b/test/Transforms/InstCombine/bitcast.ll index 579839e4245b..bccd19cc32ea 100644 --- a/test/Transforms/InstCombine/bitcast.ll +++ b/test/Transforms/InstCombine/bitcast.ll @@ -64,6 +64,61 @@ define float @test3(<2 x float> %A, <2 x i64> %B) { ; CHECK-NEXT: ret float %add } +; Both bitcasts are unnecessary; change the extractelement. + +define float @bitcast_extelt1(<2 x float> %A) { + %bc1 = bitcast <2 x float> %A to <2 x i32> + %ext = extractelement <2 x i32> %bc1, i32 0 + %bc2 = bitcast i32 %ext to float + ret float %bc2 + +; CHECK-LABEL: @bitcast_extelt1( +; CHECK-NEXT: %bc2 = extractelement <2 x float> %A, i32 0 +; CHECK-NEXT: ret float %bc2 +} + +; Second bitcast can be folded into the first. + +define i64 @bitcast_extelt2(<4 x float> %A) { + %bc1 = bitcast <4 x float> %A to <2 x double> + %ext = extractelement <2 x double> %bc1, i32 1 + %bc2 = bitcast double %ext to i64 + ret i64 %bc2 + +; CHECK-LABEL: @bitcast_extelt2( +; CHECK-NEXT: %bc = bitcast <4 x float> %A to <2 x i64> +; CHECK-NEXT: %bc2 = extractelement <2 x i64> %bc, i32 1 +; CHECK-NEXT: ret i64 %bc2 +} + +; TODO: This should return %A. + +define <2 x i32> @bitcast_extelt3(<2 x i32> %A) { + %bc1 = bitcast <2 x i32> %A to <1 x i64> + %ext = extractelement <1 x i64> %bc1, i32 0 + %bc2 = bitcast i64 %ext to <2 x i32> + ret <2 x i32> %bc2 + +; CHECK-LABEL: @bitcast_extelt3( +; CHECK-NEXT: %bc1 = bitcast <2 x i32> %A to <1 x i64> +; CHECK-NEXT: %ext = extractelement <1 x i64> %bc1, i32 0 +; CHECK-NEXT: %bc2 = bitcast i64 %ext to <2 x i32> +; CHECK-NEXT: ret <2 x i32> %bc2 +} + +; Handle the case where the input is not a vector. + +define double @bitcast_extelt4(i128 %A) { + %bc1 = bitcast i128 %A to <2 x i64> + %ext = extractelement <2 x i64> %bc1, i32 0 + %bc2 = bitcast i64 %ext to double + ret double %bc2 + +; CHECK-LABEL: @bitcast_extelt4( +; CHECK-NEXT: %bc = bitcast i128 %A to <2 x double> +; CHECK-NEXT: %bc2 = extractelement <2 x double> %bc, i32 0 +; CHECK-NEXT: ret double %bc2 +} define <2 x i32> @test4(i32 %A, i32 %B){ %tmp38 = zext i32 %A to i64 diff --git a/test/Transforms/InstCombine/bitreverse-fold.ll b/test/Transforms/InstCombine/bitreverse-fold.ll new file mode 100644 index 000000000000..ad7fc3a74644 --- /dev/null +++ b/test/Transforms/InstCombine/bitreverse-fold.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define i32 @test1(i32 %p) { +; CHECK-LABEL: @test1 +; CHECK-NEXT: ret i32 %p + %a = call i32 @llvm.bitreverse.i32(i32 %p) + %b = call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %b +} + +declare i32 @llvm.bitreverse.i32(i32) readnone diff --git a/test/Transforms/InstCombine/bitreverse-recognize.ll b/test/Transforms/InstCombine/bitreverse-recognize.ll new file mode 100644 index 000000000000..fbd5cb6d139c --- /dev/null +++ b/test/Transforms/InstCombine/bitreverse-recognize.ll @@ -0,0 +1,114 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +define zeroext i8 @f_u8(i8 zeroext %a) { +; CHECK-LABEL: @f_u8 +; CHECK-NEXT: %[[A:.*]] = call i8 @llvm.bitreverse.i8(i8 %a) +; CHECK-NEXT: ret i8 %[[A]] + %1 = shl i8 %a, 7 + %2 = shl i8 %a, 5 + %3 = and i8 %2, 64 + %4 = shl i8 %a, 3 + %5 = and i8 %4, 32 + %6 = shl i8 %a, 1 + %7 = and i8 %6, 16 + %8 = lshr i8 %a, 1 + %9 = and i8 %8, 8 + %10 = lshr i8 %a, 3 + %11 = and i8 %10, 4 + %12 = lshr i8 %a, 5 + %13 = and i8 %12, 2 + %14 = lshr i8 %a, 7 + %15 = or i8 %14, %1 + %16 = or i8 %15, %3 + %17 = or i8 %16, %5 + %18 = or i8 %17, %7 + %19 = or i8 %18, %9 + %20 = or i8 %19, %11 + %21 = or i8 %20, %13 + ret i8 %21 +} + +; The ANDs with 32 and 64 have been swapped here, so the sequence does not +; completely match a bitreverse. +define zeroext i8 @f_u8_fail(i8 zeroext %a) { +; CHECK-LABEL: @f_u8_fail +; CHECK-NOT: call +; CHECK: ret i8 + %1 = shl i8 %a, 7 + %2 = shl i8 %a, 5 + %3 = and i8 %2, 32 + %4 = shl i8 %a, 3 + %5 = and i8 %4, 64 + %6 = shl i8 %a, 1 + %7 = and i8 %6, 16 + %8 = lshr i8 %a, 1 + %9 = and i8 %8, 8 + %10 = lshr i8 %a, 3 + %11 = and i8 %10, 4 + %12 = lshr i8 %a, 5 + %13 = and i8 %12, 2 + %14 = lshr i8 %a, 7 + %15 = or i8 %14, %1 + %16 = or i8 %15, %3 + %17 = or i8 %16, %5 + %18 = or i8 %17, %7 + %19 = or i8 %18, %9 + %20 = or i8 %19, %11 + %21 = or i8 %20, %13 + ret i8 %21 +} + +define zeroext i16 @f_u16(i16 zeroext %a) { +; CHECK-LABEL: @f_u16 +; CHECK-NEXT: %[[A:.*]] = call i16 @llvm.bitreverse.i16(i16 %a) +; CHECK-NEXT: ret i16 %[[A]] + %1 = shl i16 %a, 15 + %2 = shl i16 %a, 13 + %3 = and i16 %2, 16384 + %4 = shl i16 %a, 11 + %5 = and i16 %4, 8192 + %6 = shl i16 %a, 9 + %7 = and i16 %6, 4096 + %8 = shl i16 %a, 7 + %9 = and i16 %8, 2048 + %10 = shl i16 %a, 5 + %11 = and i16 %10, 1024 + %12 = shl i16 %a, 3 + %13 = and i16 %12, 512 + %14 = shl i16 %a, 1 + %15 = and i16 %14, 256 + %16 = lshr i16 %a, 1 + %17 = and i16 %16, 128 + %18 = lshr i16 %a, 3 + %19 = and i16 %18, 64 + %20 = lshr i16 %a, 5 + %21 = and i16 %20, 32 + %22 = lshr i16 %a, 7 + %23 = and i16 %22, 16 + %24 = lshr i16 %a, 9 + %25 = and i16 %24, 8 + %26 = lshr i16 %a, 11 + %27 = and i16 %26, 4 + %28 = lshr i16 %a, 13 + %29 = and i16 %28, 2 + %30 = lshr i16 %a, 15 + %31 = or i16 %30, %1 + %32 = or i16 %31, %3 + %33 = or i16 %32, %5 + %34 = or i16 %33, %7 + %35 = or i16 %34, %9 + %36 = or i16 %35, %11 + %37 = or i16 %36, %13 + %38 = or i16 %37, %15 + %39 = or i16 %38, %17 + %40 = or i16 %39, %19 + %41 = or i16 %40, %21 + %42 = or i16 %41, %23 + %43 = or i16 %42, %25 + %44 = or i16 %43, %27 + %45 = or i16 %44, %29 + ret i16 %45 +}
\ No newline at end of file diff --git a/test/Transforms/InstCombine/blend_x86.ll b/test/Transforms/InstCombine/blend_x86.ll index 778d44ba342c..eb0b8d7584ab 100644 --- a/test/Transforms/InstCombine/blend_x86.ll +++ b/test/Transforms/InstCombine/blend_x86.ll @@ -2,42 +2,118 @@ define <2 x double> @constant_blendvpd(<2 x double> %xy, <2 x double> %ab) { ; CHECK-LABEL: @constant_blendvpd -; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x double> %ab, <2 x double> %xy +; CHECK-NEXT: %1 = select <2 x i1> <i1 true, i1 false>, <2 x double> %ab, <2 x double> %xy +; CHECK-NEXT: ret <2 x double> %1 %1 = tail call <2 x double> @llvm.x86.sse41.blendvpd(<2 x double> %xy, <2 x double> %ab, <2 x double> <double 0xFFFFFFFFE0000000, double 0.000000e+00>) ret <2 x double> %1 } +define <2 x double> @constant_blendvpd_zero(<2 x double> %xy, <2 x double> %ab) { +; CHECK-LABEL: @constant_blendvpd_zero +; CHECK-NEXT: ret <2 x double> %xy + %1 = tail call <2 x double> @llvm.x86.sse41.blendvpd(<2 x double> %xy, <2 x double> %ab, <2 x double> zeroinitializer) + ret <2 x double> %1 +} + +define <2 x double> @constant_blendvpd_dup(<2 x double> %xy, <2 x double> %sel) { +; CHECK-LABEL: @constant_blendvpd_dup +; CHECK-NEXT: ret <2 x double> %xy + %1 = tail call <2 x double> @llvm.x86.sse41.blendvpd(<2 x double> %xy, <2 x double> %xy, <2 x double> %sel) + ret <2 x double> %1 +} + define <4 x float> @constant_blendvps(<4 x float> %xyzw, <4 x float> %abcd) { ; CHECK-LABEL: @constant_blendvps -; CHECK: select <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> %abcd, <4 x float> %xyzw +; CHECK-NEXT: %1 = select <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> %abcd, <4 x float> %xyzw +; CHECK-NEXT: ret <4 x float> %1 %1 = tail call <4 x float> @llvm.x86.sse41.blendvps(<4 x float> %xyzw, <4 x float> %abcd, <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0xFFFFFFFFE0000000>) ret <4 x float> %1 } +define <4 x float> @constant_blendvps_zero(<4 x float> %xyzw, <4 x float> %abcd) { +; CHECK-LABEL: @constant_blendvps_zero +; CHECK-NEXT: ret <4 x float> %xyzw + %1 = tail call <4 x float> @llvm.x86.sse41.blendvps(<4 x float> %xyzw, <4 x float> %abcd, <4 x float> zeroinitializer) + ret <4 x float> %1 +} + +define <4 x float> @constant_blendvps_dup(<4 x float> %xyzw, <4 x float> %sel) { +; CHECK-LABEL: @constant_blendvps_dup +; CHECK-NEXT: ret <4 x float> %xyzw + %1 = tail call <4 x float> @llvm.x86.sse41.blendvps(<4 x float> %xyzw, <4 x float> %xyzw, <4 x float> %sel) + ret <4 x float> %1 +} + define <16 x i8> @constant_pblendvb(<16 x i8> %xyzw, <16 x i8> %abcd) { ; CHECK-LABEL: @constant_pblendvb -; CHECK: select <16 x i1> <i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false>, <16 x i8> %abcd, <16 x i8> %xyzw +; CHECK-NEXT: %1 = select <16 x i1> <i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false>, <16 x i8> %abcd, <16 x i8> %xyzw +; CHECK-NEXT: ret <16 x i8> %1 %1 = tail call <16 x i8> @llvm.x86.sse41.pblendvb(<16 x i8> %xyzw, <16 x i8> %abcd, <16 x i8> <i8 0, i8 0, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0>) ret <16 x i8> %1 } +define <16 x i8> @constant_pblendvb_zero(<16 x i8> %xyzw, <16 x i8> %abcd) { +; CHECK-LABEL: @constant_pblendvb_zero +; CHECK-NEXT: ret <16 x i8> %xyzw + %1 = tail call <16 x i8> @llvm.x86.sse41.pblendvb(<16 x i8> %xyzw, <16 x i8> %abcd, <16 x i8> zeroinitializer) + ret <16 x i8> %1 +} + +define <16 x i8> @constant_pblendvb_dup(<16 x i8> %xyzw, <16 x i8> %sel) { +; CHECK-LABEL: @constant_pblendvb_dup +; CHECK-NEXT: ret <16 x i8> %xyzw + %1 = tail call <16 x i8> @llvm.x86.sse41.pblendvb(<16 x i8> %xyzw, <16 x i8> %xyzw, <16 x i8> %sel) + ret <16 x i8> %1 +} + define <4 x double> @constant_blendvpd_avx(<4 x double> %xy, <4 x double> %ab) { ; CHECK-LABEL: @constant_blendvpd_avx -; CHECK: select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x double> %ab, <4 x double> %xy +; CHECK-NEXT: %1 = select <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x double> %ab, <4 x double> %xy +; CHECK-NEXT: ret <4 x double> %1 %1 = tail call <4 x double> @llvm.x86.avx.blendv.pd.256(<4 x double> %xy, <4 x double> %ab, <4 x double> <double 0xFFFFFFFFE0000000, double 0.000000e+00, double 0xFFFFFFFFE0000000, double 0.000000e+00>) ret <4 x double> %1 } +define <4 x double> @constant_blendvpd_avx_zero(<4 x double> %xy, <4 x double> %ab) { +; CHECK-LABEL: @constant_blendvpd_avx_zero +; CHECK-NEXT: ret <4 x double> %xy + %1 = tail call <4 x double> @llvm.x86.avx.blendv.pd.256(<4 x double> %xy, <4 x double> %ab, <4 x double> zeroinitializer) + ret <4 x double> %1 +} + +define <4 x double> @constant_blendvpd_avx_dup(<4 x double> %xy, <4 x double> %sel) { +; CHECK-LABEL: @constant_blendvpd_avx_dup +; CHECK-NEXT: ret <4 x double> %xy + %1 = tail call <4 x double> @llvm.x86.avx.blendv.pd.256(<4 x double> %xy, <4 x double> %xy, <4 x double> %sel) + ret <4 x double> %1 +} + define <8 x float> @constant_blendvps_avx(<8 x float> %xyzw, <8 x float> %abcd) { ; CHECK-LABEL: @constant_blendvps_avx -; CHECK: select <8 x i1> <i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false, i1 true>, <8 x float> %abcd, <8 x float> %xyzw +; CHECK-NEXT: %1 = select <8 x i1> <i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 false, i1 true>, <8 x float> %abcd, <8 x float> %xyzw +; CHECK-NEXT: ret <8 x float> %1 %1 = tail call <8 x float> @llvm.x86.avx.blendv.ps.256(<8 x float> %xyzw, <8 x float> %abcd, <8 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0xFFFFFFFFE0000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0xFFFFFFFFE0000000>) ret <8 x float> %1 } +define <8 x float> @constant_blendvps_avx_zero(<8 x float> %xyzw, <8 x float> %abcd) { +; CHECK-LABEL: @constant_blendvps_avx_zero +; CHECK-NEXT: ret <8 x float> %xyzw + %1 = tail call <8 x float> @llvm.x86.avx.blendv.ps.256(<8 x float> %xyzw, <8 x float> %abcd, <8 x float> zeroinitializer) + ret <8 x float> %1 +} + +define <8 x float> @constant_blendvps_avx_dup(<8 x float> %xyzw, <8 x float> %sel) { +; CHECK-LABEL: @constant_blendvps_avx_dup +; CHECK-NEXT: ret <8 x float> %xyzw + %1 = tail call <8 x float> @llvm.x86.avx.blendv.ps.256(<8 x float> %xyzw, <8 x float> %xyzw, <8 x float> %sel) + ret <8 x float> %1 +} + define <32 x i8> @constant_pblendvb_avx2(<32 x i8> %xyzw, <32 x i8> %abcd) { ; CHECK-LABEL: @constant_pblendvb_avx2 -; CHECK: select <32 x i1> <i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false>, <32 x i8> %abcd, <32 x i8> %xyzw +; CHECK-NEXT: %1 = select <32 x i1> <i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 true, i1 false>, <32 x i8> %abcd, <32 x i8> %xyzw +; CHECK-NEXT: ret <32 x i8> %1 %1 = tail call <32 x i8> @llvm.x86.avx2.pblendvb(<32 x i8> %xyzw, <32 x i8> %abcd, <32 x i8> <i8 0, i8 0, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, i8 0, i8 0, i8 255, i8 0, i8 255, i8 255, i8 255, i8 0, @@ -46,6 +122,20 @@ define <32 x i8> @constant_pblendvb_avx2(<32 x i8> %xyzw, <32 x i8> %abcd) { ret <32 x i8> %1 } +define <32 x i8> @constant_pblendvb_avx2_zero(<32 x i8> %xyzw, <32 x i8> %abcd) { +; CHECK-LABEL: @constant_pblendvb_avx2_zero +; CHECK-NEXT: ret <32 x i8> %xyzw + %1 = tail call <32 x i8> @llvm.x86.avx2.pblendvb(<32 x i8> %xyzw, <32 x i8> %abcd, <32 x i8> zeroinitializer) + ret <32 x i8> %1 +} + +define <32 x i8> @constant_pblendvb_avx2_dup(<32 x i8> %xyzw, <32 x i8> %sel) { +; CHECK-LABEL: @constant_pblendvb_avx2_dup +; CHECK-NEXT: ret <32 x i8> %xyzw + %1 = tail call <32 x i8> @llvm.x86.avx2.pblendvb(<32 x i8> %xyzw, <32 x i8> %xyzw, <32 x i8> %sel) + ret <32 x i8> %1 +} + declare <16 x i8> @llvm.x86.sse41.pblendvb(<16 x i8>, <16 x i8>, <16 x i8>) declare <4 x float> @llvm.x86.sse41.blendvps(<4 x float>, <4 x float>, <4 x float>) declare <2 x double> @llvm.x86.sse41.blendvpd(<2 x double>, <2 x double>, <2 x double>) diff --git a/test/Transforms/InstCombine/bswap-fold.ll b/test/Transforms/InstCombine/bswap-fold.ll index 63b0775e4aff..edf9572f1e11 100644 --- a/test/Transforms/InstCombine/bswap-fold.ll +++ b/test/Transforms/InstCombine/bswap-fold.ll @@ -51,7 +51,7 @@ define i32 @test5(i32 %a) nounwind { define i32 @test6(i32 %a) nounwind { ; CHECK-LABEL: @test6 ; CHECK-NEXT: %tmp2 = lshr i32 %a, 24 -; CHECK-NEXT ret i32 %tmp4 +; CHECK-NEXT: ret i32 %tmp2 %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) %tmp4 = and i32 %tmp2, 255 ret i32 %tmp4 @@ -62,7 +62,7 @@ define i16 @test7(i32 %A) { ; CHECK-LABEL: @test7 ; CHECK-NEXT: %1 = lshr i32 %A, 16 ; CHECK-NEXT: %D = trunc i32 %1 to i16 -; CHECK-NEXT ret i16 %D +; CHECK-NEXT: ret i16 %D %B = tail call i32 @llvm.bswap.i32(i32 %A) nounwind %C = trunc i32 %B to i16 %D = tail call i16 @llvm.bswap.i16(i16 %C) nounwind @@ -73,7 +73,7 @@ define i16 @test8(i64 %A) { ; CHECK-LABEL: @test8 ; CHECK-NEXT: %1 = lshr i64 %A, 48 ; CHECK-NEXT: %D = trunc i64 %1 to i16 -; CHECK-NEXT ret i16 %D +; CHECK-NEXT: ret i16 %D %B = tail call i64 @llvm.bswap.i64(i64 %A) nounwind %C = trunc i64 %B to i16 %D = tail call i16 @llvm.bswap.i16(i16 %C) nounwind diff --git a/test/Transforms/InstCombine/bswap-known-bits.ll b/test/Transforms/InstCombine/bswap-known-bits.ll new file mode 100644 index 000000000000..1f3285af65cc --- /dev/null +++ b/test/Transforms/InstCombine/bswap-known-bits.ll @@ -0,0 +1,47 @@ +; RUN: opt < %s -S -instcombine | FileCheck %s +; Note: This is testing functionality in computeKnownBits. I'd have rather +; used instsimplify, but the bit test folding is apparently only in instcombine. + +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) + +define i1 @test1(i16 %arg) { +; CHECK-LABEL: @test1 +; CHECK: ret i1 true + %a = or i16 %arg, 511 + %b = call i16 @llvm.bswap.i16(i16 %a) + %and = and i16 %b, 256 + %res = icmp eq i16 %and, 256 + ret i1 %res +} + +define i1 @test2(i16 %arg) { +; CHECK-LABEL: @test2 +; CHECK: ret i1 true + %a = or i16 %arg, 1 + %b = call i16 @llvm.bswap.i16(i16 %a) + %and = and i16 %b, 256 + %res = icmp eq i16 %and, 256 + ret i1 %res +} + + +define i1 @test3(i16 %arg) { +; CHECK-LABEL: @test3 +; CHECK: ret i1 true + %a = or i16 %arg, 256 + %b = call i16 @llvm.bswap.i16(i16 %a) + %and = and i16 %b, 1 + %res = icmp eq i16 %and, 1 + ret i1 %res +} + +define i1 @test4(i32 %arg) { +; CHECK-LABEL: @test4 +; CHECK: ret i1 true + %a = or i32 %arg, 2147483647 ; i32_MAX + %b = call i32 @llvm.bswap.i32(i32 %a) + %and = and i32 %b, 127 + %res = icmp eq i32 %and, 127 + ret i1 %res +} diff --git a/test/Transforms/InstCombine/bswap.ll b/test/Transforms/InstCombine/bswap.ll index ba7df3125f4e..b48b2a57c8ce 100644 --- a/test/Transforms/InstCombine/bswap.ll +++ b/test/Transforms/InstCombine/bswap.ll @@ -1,7 +1,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" ; RUN: opt < %s -instcombine -S | \ -; RUN: grep "call.*llvm.bswap" | count 6 +; RUN: grep "call.*llvm.bswap" | count 7 define i32 @test1(i32 %i) { %tmp1 = lshr i32 %i, 24 ; <i32> [#uses=1] @@ -72,3 +72,15 @@ define i32 @test6(i32 %x) nounwind readnone { ret i32 %tmp7 } +; PR23863 +define i32 @test7(i32 %x) { + %shl = shl i32 %x, 16 + %shr = lshr i32 %x, 16 + %or = or i32 %shl, %shr + %and2 = shl i32 %or, 8 + %shl3 = and i32 %and2, -16711936 + %and4 = lshr i32 %or, 8 + %shr5 = and i32 %and4, 16711935 + %or6 = or i32 %shl3, %shr5 + ret i32 %or6 +} diff --git a/test/Transforms/InstCombine/call_nonnull_arg.ll b/test/Transforms/InstCombine/call_nonnull_arg.ll new file mode 100644 index 000000000000..b10411f622be --- /dev/null +++ b/test/Transforms/InstCombine/call_nonnull_arg.ll @@ -0,0 +1,20 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; InstCombine should mark null-checked argument as nonnull at callsite +declare void @dummy(i32*, i32) + +define void @test(i32* %a, i32 %b) { +; CHECK-LABEL: @test +; CHECK: call void @dummy(i32* nonnull %a, i32 %b) +entry: + %cond1 = icmp eq i32* %a, null + br i1 %cond1, label %dead, label %not_null +not_null: + %cond2 = icmp eq i32 %b, 0 + br i1 %cond2, label %dead, label %not_zero +not_zero: + call void @dummy(i32* %a, i32 %b) + ret void +dead: + unreachable +} diff --git a/test/Transforms/InstCombine/cast-callee-deopt-bundles.ll b/test/Transforms/InstCombine/cast-callee-deopt-bundles.ll new file mode 100644 index 000000000000..0f8601b855cf --- /dev/null +++ b/test/Transforms/InstCombine/cast-callee-deopt-bundles.ll @@ -0,0 +1,11 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +declare void @foo(i32) + +define void @g() { +; CHECK-LABEL: @g( + entry: +; CHECK: call void @foo(i32 0) [ "deopt"() ] + call void bitcast (void (i32)* @foo to void ()*) () [ "deopt"() ] + ret void +} diff --git a/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll b/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll index 551d0efce5ea..2e87a7d78020 100644 --- a/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll +++ b/test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll @@ -10,8 +10,8 @@ define i1 @i32_cast_cmp_oeq_int_0_uitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_uitofp( -; CHECK: uitofp -; CHECK: fcmp oeq +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_oeq_int_n0_uitofp(i32 %i) { %f = uitofp i32 %i to float %cmp = fcmp oeq float %f, -0.0 @@ -28,8 +28,8 @@ define i1 @i32_cast_cmp_oeq_int_0_sitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_oeq_int_n0_sitofp( -; CHECK: sitofp -; CHECK: fcmp oeq +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_oeq_int_n0_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp oeq float %f, -0.0 @@ -46,8 +46,8 @@ define i1 @i32_cast_cmp_one_int_0_uitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_one_int_n0_uitofp( -; CHECK: uitofp -; CHECK: fcmp one +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_one_int_n0_uitofp(i32 %i) { %f = uitofp i32 %i to float %cmp = fcmp one float %f, -0.0 @@ -64,8 +64,8 @@ define i1 @i32_cast_cmp_one_int_0_sitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_one_int_n0_sitofp( -; CHECK: sitofp -; CHECK: fcmp one +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_one_int_n0_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp one float %f, -0.0 @@ -82,8 +82,8 @@ define i1 @i32_cast_cmp_ueq_int_0_uitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_ueq_int_n0_uitofp( -; CHECK: uitofp -; CHECK: fcmp ueq +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_ueq_int_n0_uitofp(i32 %i) { %f = uitofp i32 %i to float %cmp = fcmp ueq float %f, -0.0 @@ -100,8 +100,8 @@ define i1 @i32_cast_cmp_ueq_int_0_sitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_ueq_int_n0_sitofp( -; CHECK: sitofp -; CHECK: fcmp ueq +; CHECK-NEXT: icmp eq i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_ueq_int_n0_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp ueq float %f, -0.0 @@ -118,8 +118,8 @@ define i1 @i32_cast_cmp_une_int_0_uitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_une_int_n0_uitofp( -; CHECK: uitofp -; CHECK: fcmp une +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_une_int_n0_uitofp(i32 %i) { %f = uitofp i32 %i to float %cmp = fcmp une float %f, -0.0 @@ -136,8 +136,8 @@ define i1 @i32_cast_cmp_une_int_0_sitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_une_int_n0_sitofp( -; CHECK: sitofp -; CHECK: fcmp une +; CHECK-NEXT: icmp ne i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_une_int_n0_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp une float %f, -0.0 @@ -154,8 +154,8 @@ define i1 @i32_cast_cmp_ogt_int_0_uitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_ogt_int_n0_uitofp( -; CHECK: uitofp -; CHECK: fcmp ogt +; CHECK: icmp ne i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_ogt_int_n0_uitofp(i32 %i) { %f = uitofp i32 %i to float %cmp = fcmp ogt float %f, -0.0 @@ -172,8 +172,8 @@ define i1 @i32_cast_cmp_ogt_int_0_sitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_ogt_int_n0_sitofp( -; CHECK: sitofp -; CHECK: fcmp ogt +; CHECK: icmp sgt i32 %i, 0 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_ogt_int_n0_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp ogt float %f, -0.0 @@ -261,12 +261,13 @@ define i1 @i32_cast_cmp_oeq_int_0_uitofp_ppcf128(i32 %i) { ret i1 %cmp } -; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_uitofp( -; CHECK: uitofp -; CHECK: fcmp oeq +; Since 0xFFFFFF fits in a float, and one less and +; one more than it also fits without rounding, the +; test can be optimized to an integer compare. -; XCHECK: icmp eq i32 %i, 16777215 -; XCHECK-NEXT: ret +; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_uitofp( +; CHECK: icmp eq i32 %i, 16777215 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_oeq_int_i24max_uitofp(i32 %i) { %f = uitofp i32 %i to float %cmp = fcmp oeq float %f, 0x416FFFFFE0000000 @@ -274,17 +275,18 @@ define i1 @i32_cast_cmp_oeq_int_i24max_uitofp(i32 %i) { } ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24max_sitofp( -; CHECK: sitofp -; CHECK: fcmp oeq - -; XCHECK: icmp eq i32 %i, 16777215 -; XCHECK-NEXT: ret +; CHECK: icmp eq i32 %i, 16777215 +; CHECK-NEXT: ret define i1 @i32_cast_cmp_oeq_int_i24max_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp oeq float %f, 0x416FFFFFE0000000 ret i1 %cmp } +; Though 0x1000000 fits in a float, one more than it +; would round to it too, hence a single integer comparison +; does not suffice. + ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i24maxp1_uitofp( ; CHECK: uitofp ; CHECK: fcmp oeq @@ -319,10 +321,18 @@ define i1 @i32_cast_cmp_oeq_int_i32umax_uitofp(i32 %i) { ret i1 %cmp } +; 32-bit unsigned integer cannot possibly round up to 1<<33 +; CHECK-LABEL: @i32_cast_cmp_oeq_int_big_uitofp( +; CHECK-NEXT: ret i1 false +define i1 @i32_cast_cmp_oeq_int_big_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x4200000000000000 + ret i1 %cmp +} + +; 32-bit signed integer cannot possibly round up to 1<<32 ; CHECK-LABEL: @i32_cast_cmp_oeq_int_i32umax_sitofp( -; CHECK: sitofp -; CHECK: fcmp oeq -; CHECK-NEXT: ret +; CHECK-NEXT: ret i1 false define i1 @i32_cast_cmp_oeq_int_i32umax_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp oeq float %f, 0x41F0000000000000 @@ -379,10 +389,9 @@ define i1 @i32_cast_cmp_oeq_int_negi32umax_uitofp(i32 %i) { ret i1 %cmp } +; 32-bit signed integer cannot possibly round to -1<<32 ; CHECK-LABEL: @i32_cast_cmp_oeq_int_negi32umax_sitofp( -; CHECK: sitofp -; CHECK: fcmp oeq -; CHECK-NEXT: ret +; CHECK-NEXT: ret i1 false define i1 @i32_cast_cmp_oeq_int_negi32umax_sitofp(i32 %i) { %f = sitofp i32 %i to float %cmp = fcmp oeq float %f, 0xC1F0000000000000 @@ -452,3 +461,30 @@ define i1 @i32_cast_cmp_une_half_sitofp(i32 %i) { %cmp = fcmp une float %f, 0.5 ret i1 %cmp } + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_inf_uitofp( +; CHECK-NEXT: ret i1 false +define i1 @i32_cast_cmp_oeq_int_inf_uitofp(i32 %i) { + %f = uitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x7FF0000000000000 + ret i1 %cmp +} + +; CHECK-LABEL: @i32_cast_cmp_oeq_int_inf_sitofp( +; CHECK-NEXT: ret i1 false +define i1 @i32_cast_cmp_oeq_int_inf_sitofp(i32 %i) { + %f = sitofp i32 %i to float + %cmp = fcmp oeq float %f, 0x7FF0000000000000 + ret i1 %cmp +} + +; An i128 could round to an IEEE single-precision infinity. +; CHECK-LABEL: @i128_cast_cmp_oeq_int_inf_uitofp( +; CHECK: uitofp +; CHECK: fcmp oeq +; CHECK-NEXT: ret +define i1 @i128_cast_cmp_oeq_int_inf_uitofp(i128 %i) { + %f = uitofp i128 %i to float + %cmp = fcmp oeq float %f, 0x7FF0000000000000 + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/cast-set.ll b/test/Transforms/InstCombine/cast-set.ll index 47ba920d9286..8f19bdcdfde3 100644 --- a/test/Transforms/InstCombine/cast-set.ll +++ b/test/Transforms/InstCombine/cast-set.ll @@ -10,7 +10,7 @@ define i1 @test1(i32 %X) { ; Convert to setne int %X, 12 %c = icmp ne i32 %A, 12 ; <i1> [#uses=1] ret i1 %c -; CHECK-LABEL @test1( +; CHECK-LABEL: @test1( ; CHECK: %c = icmp ne i32 %X, 12 ; CHECK: ret i1 %c } @@ -21,7 +21,7 @@ define i1 @test2(i32 %X, i32 %Y) { ; Convert to setne int %X, %Y %c = icmp ne i32 %A, %B ; <i1> [#uses=1] ret i1 %c -; CHECK-LABEL @test2( +; CHECK-LABEL: @test2( ; CHECK: %c = icmp ne i32 %X, %Y ; CHECK: ret i1 %c } diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 7fe54ef8469b..016b6aa64558 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -187,8 +187,8 @@ define i32 @test21(i32 %X) { %c2 = sext i8 %c1 to i32 ; <i32> [#uses=1] %RV = and i32 %c2, 255 ; <i32> [#uses=1] ret i32 %RV -; CHECK: %c2.1 = and i32 %X, 255 -; CHECK: ret i32 %c2.1 +; CHECK: %c21 = and i32 %X, 255 +; CHECK: ret i32 %c21 } define i32 @test22(i32 %X) { @@ -722,7 +722,7 @@ define i1 @test67(i1 %a, i32 %b) { ; CHECK: ret i1 false } -%s = type { i32, i32, i32 } +%s = type { i32, i32, i16 } define %s @test68(%s *%p, i64 %i) { ; CHECK-LABEL: @test68( @@ -1062,6 +1062,43 @@ define i8 @test85(i32 %a) { ; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8 } +define i16 @test86(i16 %v) { + %a = sext i16 %v to i32 + %s = ashr i32 %a, 4 + %t = trunc i32 %s to i16 + ret i16 %t + +; CHECK-LABEL: @test86( +; CHECK: [[ASHR:%.*]] = ashr i16 %v, 4 +; CHECK-NEXT: ret i16 [[ASHR]] +} + +define i16 @test87(i16 %v) { + %c = sext i16 %v to i32 + %m = mul nsw i32 %c, 16 + %a = ashr i32 %m, 16 + %t = trunc i32 %a to i16 + ret i16 %t + +; CHECK-LABEL: @test87( +; CHECK: [[ASHR:%.*]] = ashr i16 %v, 12 +; CHECK-NEXT: ret i16 [[ASHR]] +} + +define i16 @test88(i16 %v) { + %a = sext i16 %v to i32 + %s = ashr i32 %a, 18 + %t = trunc i32 %s to i16 + ret i16 %t + +; Do not optimize to ashr i16 (shift by 18) +; CHECK-LABEL: @test88( +; CHECK: [[SEXT:%.*]] = sext i16 %v to i32 +; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[SEXT]], 18 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ASHR]] to i16 +; CHECK-NEXT: ret i16 [[TRUNC]] +} + ; Overflow on a float to int or int to float conversion is undefined (PR21130). define i8 @overflow_fptosi() { @@ -1137,3 +1174,14 @@ define i1 @PR23309v2(i32 %A, i32 %B) { %trunc = trunc i32 %sub to i1 ret i1 %trunc } + +define i16 @PR24763(i8 %V) { +; CHECK-LABEL: @PR24763( +; CHECK-NEXT: %[[sh:.*]] = ashr i8 +; CHECK-NEXT: %[[ext:.*]] = sext i8 %[[sh]] to i16 +; CHECK-NEXT: ret i16 %[[ext]] + %conv = sext i8 %V to i32 + %l = lshr i32 %conv, 1 + %t = trunc i32 %l to i16 + ret i16 %t +} diff --git a/test/Transforms/InstCombine/compare-alloca.ll b/test/Transforms/InstCombine/compare-alloca.ll new file mode 100644 index 000000000000..ca24da191779 --- /dev/null +++ b/test/Transforms/InstCombine/compare-alloca.ll @@ -0,0 +1,97 @@ +; RUN: opt -instcombine -S %s | FileCheck %s +target datalayout = "p:32:32" + + +define i1 @alloca_argument_compare(i64* %arg) { + %alloc = alloca i64 + %cmp = icmp eq i64* %arg, %alloc + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare + ; CHECK: ret i1 false +} + +define i1 @alloca_argument_compare_swapped(i64* %arg) { + %alloc = alloca i64 + %cmp = icmp eq i64* %alloc, %arg + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare_swapped + ; CHECK: ret i1 false +} + +define i1 @alloca_argument_compare_ne(i64* %arg) { + %alloc = alloca i64 + %cmp = icmp ne i64* %arg, %alloc + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare_ne + ; CHECK: ret i1 true +} + +define i1 @alloca_argument_compare_derived_ptrs(i64* %arg, i64 %x) { + %alloc = alloca i64, i64 8 + %p = getelementptr i64, i64* %arg, i64 %x + %q = getelementptr i64, i64* %alloc, i64 3 + %cmp = icmp eq i64* %p, %q + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare_derived_ptrs + ; CHECK: ret i1 false +} + +declare void @escape(i64*) +define i1 @alloca_argument_compare_escaped_alloca(i64* %arg) { + %alloc = alloca i64 + call void @escape(i64* %alloc) + %cmp = icmp eq i64* %alloc, %arg + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare_escaped_alloca + ; CHECK: %cmp = icmp eq i64* %alloc, %arg + ; CHECK: ret i1 %cmp +} + +declare void @check_compares(i1, i1) +define void @alloca_argument_compare_two_compares(i64* %p) { + %q = alloca i64, i64 8 + %r = getelementptr i64, i64* %p, i64 1 + %s = getelementptr i64, i64* %q, i64 2 + %cmp1 = icmp eq i64* %p, %q + %cmp2 = icmp eq i64* %r, %s + call void @check_compares(i1 %cmp1, i1 %cmp2) + ret void + ; We will only fold if there is a single cmp. + ; CHECK-LABEL: alloca_argument_compare_two_compares + ; CHECK: call void @check_compares(i1 %cmp1, i1 %cmp2) +} + +define i1 @alloca_argument_compare_escaped_through_store(i64* %arg, i64** %ptr) { + %alloc = alloca i64 + %cmp = icmp eq i64* %alloc, %arg + %p = getelementptr i64, i64* %alloc, i64 1 + store i64* %p, i64** %ptr + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare_escaped_through_store + ; CHECK: %cmp = icmp eq i64* %alloc, %arg + ; CHECK: ret i1 %cmp +} + +declare void @llvm.lifetime.start(i64, i8* nocapture) +declare void @llvm.lifetime.end(i64, i8* nocapture) +define i1 @alloca_argument_compare_benign_instrs(i8* %arg) { + %alloc = alloca i8 + call void @llvm.lifetime.start(i64 1, i8* %alloc) + %cmp = icmp eq i8* %arg, %alloc + %x = load i8, i8* %arg + store i8 %x, i8* %alloc + call void @llvm.lifetime.end(i64 1, i8* %alloc) + ret i1 %cmp + ; CHECK-LABEL: alloca_argument_compare_benign_instrs + ; CHECK: ret i1 false +} + +declare i64* @allocator() +define i1 @alloca_call_compare() { + %p = alloca i64 + %q = call i64* @allocator() + %cmp = icmp eq i64* %p, %q + ret i1 %cmp + ; CHECK-LABEL: alloca_call_compare + ; CHECK: ret i1 false +} diff --git a/test/Transforms/InstCombine/compare-signs.ll b/test/Transforms/InstCombine/compare-signs.ll index 62cd5b3f94d5..0ed0ac7d8d9c 100644 --- a/test/Transforms/InstCombine/compare-signs.ll +++ b/test/Transforms/InstCombine/compare-signs.ll @@ -56,3 +56,43 @@ entry: ; CHECK-NOT: zext ; CHECK: ret i32 %2 } + +define i1 @test4a(i32 %a) { +; CHECK-LABEL: @test4a( + entry: +; CHECK: %c = icmp slt i32 %a, 1 +; CHECK-NEXT: ret i1 %c + %l = ashr i32 %a, 31 + %na = sub i32 0, %a + %r = lshr i32 %na, 31 + %signum = or i32 %l, %r + %c = icmp slt i32 %signum, 1 + ret i1 %c +} + +define i1 @test4b(i64 %a) { +; CHECK-LABEL: @test4b( + entry: +; CHECK: %c = icmp slt i64 %a, 1 +; CHECK-NEXT: ret i1 %c + %l = ashr i64 %a, 63 + %na = sub i64 0, %a + %r = lshr i64 %na, 63 + %signum = or i64 %l, %r + %c = icmp slt i64 %signum, 1 + ret i1 %c +} + +define i1 @test4c(i64 %a) { +; CHECK-LABEL: @test4c( + entry: +; CHECK: %c = icmp slt i64 %a, 1 +; CHECK-NEXT: ret i1 %c + %l = ashr i64 %a, 63 + %na = sub i64 0, %a + %r = lshr i64 %na, 63 + %signum = or i64 %l, %r + %signum.trunc = trunc i64 %signum to i32 + %c = icmp slt i32 %signum.trunc, 1 + ret i1 %c +} diff --git a/test/Transforms/InstCombine/constant-fold-alias.ll b/test/Transforms/InstCombine/constant-fold-alias.ll index c872f57c37e1..810687255f61 100644 --- a/test/Transforms/InstCombine/constant-fold-alias.ll +++ b/test/Transforms/InstCombine/constant-fold-alias.ll @@ -6,8 +6,8 @@ target datalayout = "e-p1:16:16-p2:32:32-p3:64:64" @G2 = global i32 42 @G3 = global [4 x i8] zeroinitializer, align 1 -@A1 = alias bitcast (i8* getelementptr inbounds ([4 x i8], [4 x i8]* @G3, i32 0, i32 2) to i32*) -@A2 = alias inttoptr (i64 and (i64 ptrtoint (i8* getelementptr inbounds ([4 x i8], [4 x i8]* @G3, i32 0, i32 3) to i64), i64 -4) to i32*) +@A1 = alias i32, bitcast (i8* getelementptr inbounds ([4 x i8], [4 x i8]* @G3, i32 0, i32 2) to i32*) +@A2 = alias i32, inttoptr (i64 and (i64 ptrtoint (i8* getelementptr inbounds ([4 x i8], [4 x i8]* @G3, i32 0, i32 3) to i64), i64 -4) to i32*) define i64 @f1() { ; This cannot be constant folded because G1 is underaligned. diff --git a/test/Transforms/InstCombine/ctpop.ll b/test/Transforms/InstCombine/ctpop.ll new file mode 100644 index 000000000000..38612c92aaa4 --- /dev/null +++ b/test/Transforms/InstCombine/ctpop.ll @@ -0,0 +1,45 @@ +; RUN: opt < %s -S -instcombine | FileCheck %s + +declare i32 @llvm.ctpop.i32(i32) +declare i8 @llvm.ctpop.i8(i8) +declare void @llvm.assume(i1) + +define i1 @test1(i32 %arg) { +; CHECK: @test1 +; CHECK: ret i1 false + %and = and i32 %arg, 15 + %cnt = call i32 @llvm.ctpop.i32(i32 %and) + %res = icmp eq i32 %cnt, 9 + ret i1 %res +} + +define i1 @test2(i32 %arg) { +; CHECK: @test2 +; CHECK: ret i1 false + %and = and i32 %arg, 1 + %cnt = call i32 @llvm.ctpop.i32(i32 %and) + %res = icmp eq i32 %cnt, 2 + ret i1 %res +} + +define i1 @test3(i32 %arg) { +; CHECK: @test3 +; CHECK: ret i1 false + ;; Use an assume to make all the bits known without triggering constant + ;; folding. This is trying to hit a corner case where we have to avoid + ;; taking the log of 0. + %assume = icmp eq i32 %arg, 0 + call void @llvm.assume(i1 %assume) + %cnt = call i32 @llvm.ctpop.i32(i32 %arg) + %res = icmp eq i32 %cnt, 2 + ret i1 %res +} + +; Negative test for when we know nothing +define i1 @test4(i8 %arg) { +; CHECK: @test4 +; CHECK: ret i1 %res + %cnt = call i8 @llvm.ctpop.i8(i8 %arg) + %res = icmp eq i8 %cnt, 2 + ret i1 %res +} diff --git a/test/Transforms/InstCombine/debug-line.ll b/test/Transforms/InstCombine/debug-line.ll index 823ec98ebe2b..4b1db9db353b 100644 --- a/test/Transforms/InstCombine/debug-line.ll +++ b/test/Transforms/InstCombine/debug-line.ll @@ -3,7 +3,7 @@ @.str = private constant [3 x i8] c"%c\00" -define void @foo() nounwind ssp { +define void @foo() nounwind ssp !dbg !0 { ;CHECK: call i32 @putchar{{.+}} !dbg %1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i32 97), !dbg !5 ret void, !dbg !7 @@ -15,9 +15,9 @@ declare i32 @printf(i8*, ...) !llvm.module.flags = !{!10} !llvm.dbg.sp = !{!0} -!0 = !DISubprogram(name: "foo", line: 4, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, file: !8, scope: !1, type: !3, function: void ()* @foo) +!0 = distinct !DISubprogram(name: "foo", line: 4, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, file: !8, scope: !1, type: !3) !1 = !DIFile(filename: "m.c", directory: "/private/tmp") -!2 = !DICompileUnit(language: DW_LANG_C99, producer: "clang", isOptimized: true, emissionKind: 0, file: !8, enums: !{}, retainedTypes: !{}, subprograms: !9) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang", isOptimized: true, emissionKind: 0, file: !8, enums: !{}, retainedTypes: !{}, subprograms: !9) !3 = !DISubroutineType(types: !4) !4 = !{null} !5 = !DILocation(line: 5, column: 2, scope: !6) diff --git a/test/Transforms/InstCombine/debuginfo.ll b/test/Transforms/InstCombine/debuginfo.ll index 3875bcc9b8c6..9c8b2a8e4154 100644 --- a/test/Transforms/InstCombine/debuginfo.ll +++ b/test/Transforms/InstCombine/debuginfo.ll @@ -6,7 +6,7 @@ declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) nounwind readnone declare i8* @foo(i8*, i32, i64, i64) nounwind -define hidden i8* @foobar(i8* %__dest, i32 %__val, i64 %__len) nounwind inlinehint ssp { +define hidden i8* @foobar(i8* %__dest, i32 %__val, i64 %__len) nounwind inlinehint ssp !dbg !1 { entry: %__dest.addr = alloca i8*, align 8 %__val.addr = alloca i32, align 4 @@ -31,16 +31,16 @@ entry: !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!30} -!0 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "__dest", line: 78, arg: 1, scope: !1, file: !2, type: !6) -!1 = !DISubprogram(name: "foobar", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, scopeLine: 79, file: !27, scope: !2, type: !4, function: i8* (i8*, i32, i64)* @foobar, variables: !25) +!0 = !DILocalVariable(name: "__dest", line: 78, arg: 1, scope: !1, file: !2, type: !6) +!1 = distinct !DISubprogram(name: "foobar", line: 79, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, scopeLine: 79, file: !27, scope: !2, type: !4, variables: !25) !2 = !DIFile(filename: "string.h", directory: "Game") -!3 = !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.0 (trunk 127710)", isOptimized: true, emissionKind: 0, file: !28, enums: !29, retainedTypes: !29, subprograms: !24) +!3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.0 (trunk 127710)", isOptimized: true, emissionKind: 0, file: !28, enums: !29, retainedTypes: !29, subprograms: !24) !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, scope: !3, baseType: null) -!7 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "__val", line: 78, arg: 2, scope: !1, file: !2, type: !8) +!7 = !DILocalVariable(name: "__val", line: 78, arg: 2, scope: !1, file: !2, type: !8) !8 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) -!9 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "__len", line: 78, arg: 3, scope: !1, file: !2, type: !10) +!9 = !DILocalVariable(name: "__len", line: 78, arg: 3, scope: !1, file: !2, type: !10) !10 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", line: 80, file: !27, scope: !3, baseType: !11) !11 = !DIDerivedType(tag: DW_TAG_typedef, name: "__darwin_size_t", line: 90, file: !27, scope: !3, baseType: !12) !12 = !DIBasicType(tag: DW_TAG_base_type, name: "long unsigned int", size: 64, align: 64, encoding: DW_ATE_unsigned) diff --git a/test/Transforms/InstCombine/demorgan-zext.ll b/test/Transforms/InstCombine/demorgan-zext.ll new file mode 100644 index 000000000000..da41fac3e350 --- /dev/null +++ b/test/Transforms/InstCombine/demorgan-zext.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; PR22723: Recognize De Morgan's Laws when obfuscated by zexts. + +define i32 @demorgan_or(i1 %X, i1 %Y) { + %zextX = zext i1 %X to i32 + %zextY = zext i1 %Y to i32 + %notX = xor i32 %zextX, 1 + %notY = xor i32 %zextY, 1 + %or = or i32 %notX, %notY + ret i32 %or + +; CHECK-LABEL: demorgan_or( +; CHECK-NEXT: %[[AND:.*]] = and i1 %X, %Y +; CHECK-NEXT: %[[ZEXT:.*]] = zext i1 %[[AND]] to i32 +; CHECK-NEXT: %[[XOR:.*]] = xor i32 %[[ZEXT]], 1 +; CHECK-NEXT: ret i32 %[[XOR]] +} + +define i32 @demorgan_and(i1 %X, i1 %Y) { + %zextX = zext i1 %X to i32 + %zextY = zext i1 %Y to i32 + %notX = xor i32 %zextX, 1 + %notY = xor i32 %zextY, 1 + %and = and i32 %notX, %notY + ret i32 %and + +; CHECK-LABEL: demorgan_and( +; CHECK-NEXT: %[[OR:.*]] = or i1 %X, %Y +; CHECK-NEXT: %[[ZEXT:.*]] = zext i1 %[[OR]] to i32 +; CHECK-NEXT: %[[XOR:.*]] = xor i32 %[[ZEXT]], 1 +; CHECK-NEXT: ret i32 %[[XOR]] +} + diff --git a/test/Transforms/InstCombine/div.ll b/test/Transforms/InstCombine/div.ll index e0ff07baae7c..27a316113e52 100644 --- a/test/Transforms/InstCombine/div.ll +++ b/test/Transforms/InstCombine/div.ll @@ -163,7 +163,7 @@ define i32 @test19(i32 %x) { ; CHECK-LABEL: @test19( ; CHECK-NEXT: icmp eq i32 %x, 1 ; CHECK-NEXT: zext i1 %{{.*}} to i32 -; CHECK-NEXT ret i32 +; CHECK-NEXT: ret i32 } define i32 @test20(i32 %x) { @@ -270,9 +270,7 @@ define <2 x i32> @test31(<2 x i32> %x) { %div = udiv <2 x i32> %shr, <i32 2147483647, i32 2147483647> ret <2 x i32> %div ; CHECK-LABEL: @test31( -; CHECK-NEXT: %[[shr:.*]] = lshr <2 x i32> %x, <i32 31, i32 31> -; CHECK-NEXT: udiv <2 x i32> %[[shr]], <i32 2147483647, i32 2147483647> -; CHECK-NEXT: ret <2 x i32> +; CHECK-NEXT: ret <2 x i32> zeroinitializer } define i32 @test32(i32 %a, i32 %b) { @@ -325,3 +323,21 @@ define i32 @test36(i32 %A) { ; CHECK-NEXT: %[[shr:.*]] = lshr exact i32 %[[and]], %A ; CHECK-NEXT: ret i32 %[[shr]] } + +define i32 @test37(i32* %b) { +entry: + store i32 0, i32* %b, align 4 + %0 = load i32, i32* %b, align 4 + br i1 undef, label %lor.rhs, label %lor.end + +lor.rhs: ; preds = %entry + %mul = mul nsw i32 undef, %0 + br label %lor.end + +lor.end: ; preds = %lor.rhs, %entry + %t.0 = phi i32 [ %0, %entry ], [ %mul, %lor.rhs ] + %div = sdiv i32 %t.0, 2 + ret i32 %div +; CHECK-LABEL: @test37( +; CHECK: ret i32 0 +} diff --git a/test/Transforms/InstCombine/exp2-1.ll b/test/Transforms/InstCombine/exp2-1.ll index 8e6a0e0d93f6..b6a56b9a9a7e 100644 --- a/test/Transforms/InstCombine/exp2-1.ll +++ b/test/Transforms/InstCombine/exp2-1.ll @@ -1,7 +1,8 @@ ; Test that the exp2 library call simplifier works correctly. ; -; RUN: opt < %s -instcombine -S | FileCheck %s -; RUN: opt < %s -instcombine -S -mtriple=i386-pc-win32 | FileCheck %s -check-prefix=CHECK-WIN +; RUN: opt < %s -instcombine -S | FileCheck %s -check-prefix=CHECK -check-prefix=INTRINSIC -check-prefix=LDEXP -check-prefix=LDEXPF +; RUN: opt < %s -instcombine -S -mtriple=i386-pc-win32 | FileCheck %s -check-prefix=INTRINSIC -check-prefix=LDEXP -check-prefix=NOLDEXPF +; RUN: opt < %s -instcombine -S -mtriple=amdgcn-unknown-unknown | FileCheck %s -check-prefix=INTRINSIC -check-prefix=NOLDEXP -check-prefix=NOLDEXPF target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" @@ -80,21 +81,19 @@ declare double @llvm.exp2.f64(double) declare float @llvm.exp2.f32(float) define double @test_simplify9(i8 zeroext %x) { -; CHECK-LABEL: @test_simplify9( -; CHECK-WIN-LABEL: @test_simplify9( +; INTRINSIC-LABEL: @test_simplify9( %conv = uitofp i8 %x to double %ret = call double @llvm.exp2.f64(double %conv) -; CHECK: call double @ldexp -; CHECK-WIN: call double @ldexp +; LDEXP: call double @ldexp +; NOLDEXP-NOT: call double @ldexp ret double %ret } define float @test_simplify10(i8 zeroext %x) { -; CHECK-LABEL: @test_simplify10( -; CHECK-WIN-LABEL: @test_simplify10( +; INTRINSIC-LABEL: @test_simplify10( %conv = uitofp i8 %x to float %ret = call float @llvm.exp2.f32(float %conv) -; CHECK: call float @ldexpf -; CHECK-WIN-NOT: call float @ldexpf +; LDEXPF: call float @ldexpf +; NOLDEXPF-NOT: call float @ldexpf ret float %ret } diff --git a/test/Transforms/InstCombine/extractvalue.ll b/test/Transforms/InstCombine/extractvalue.ll index 6319590873a2..9c293581a069 100644 --- a/test/Transforms/InstCombine/extractvalue.ll +++ b/test/Transforms/InstCombine/extractvalue.ll @@ -48,16 +48,16 @@ define i32 @foo(i32 %a, i32 %b) { ; CHECK: call {{.*}}(i32 [[LOAD]]) ; CHECK-NOT: extractvalue ; CHECK: ret i32 [[LOAD]] -define i32 @extract2gep({i32, i32}* %pair, i32* %P) { +define i32 @extract2gep({i16, i32}* %pair, i32* %P) { ; The load + extractvalue should be converted ; to an inbounds gep + smaller load. ; The new load should be in the same spot as the old load. - %L = load {i32, i32}, {i32, i32}* %pair + %L = load {i16, i32}, {i16, i32}* %pair store i32 0, i32* %P br label %loop loop: - %E = extractvalue {i32, i32} %L, 1 + %E = extractvalue {i16, i32} %L, 1 %C = call i32 @baz(i32 %E) store i32 %C, i32* %P %cond = icmp eq i32 %C, 0 @@ -67,17 +67,17 @@ end: ret i32 %E } -; CHECK-LABEL: define i32 @doubleextract2gep( +; CHECK-LABEL: define i16 @doubleextract2gep( ; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}, {{.*}}* %arg, i64 0, i32 1, i32 1 -; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32, i32* [[GEP]] -; CHECK-NEXT: ret i32 [[LOAD]] -define i32 @doubleextract2gep({i32, {i32, i32}}* %arg) { +; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i16, i16* [[GEP]] +; CHECK-NEXT: ret i16 [[LOAD]] +define i16 @doubleextract2gep({i16, {i32, i16}}* %arg) { ; The load + extractvalues should be converted ; to a 3-index inbounds gep + smaller load. - %L = load {i32, {i32, i32}}, {i32, {i32, i32}}* %arg - %E1 = extractvalue {i32, {i32, i32}} %L, 1 - %E2 = extractvalue {i32, i32} %E1, 1 - ret i32 %E2 + %L = load {i16, {i32, i16}}, {i16, {i32, i16}}* %arg + %E1 = extractvalue {i16, {i32, i16}} %L, 1 + %E2 = extractvalue {i32, i16} %E1, 1 + ret i16 %E2 } ; CHECK: define i32 @nogep-multiuse diff --git a/test/Transforms/InstCombine/fabs.ll b/test/Transforms/InstCombine/fabs.ll index 0479549bea3f..941270df0e97 100644 --- a/test/Transforms/InstCombine/fabs.ll +++ b/test/Transforms/InstCombine/fabs.ll @@ -41,6 +41,7 @@ define fp128 @square_fabs_call_f128(fp128 %x) { declare float @llvm.fabs.f32(float) declare double @llvm.fabs.f64(double) declare fp128 @llvm.fabs.f128(fp128) +declare <4 x float> @llvm.fabs.v4f32(<4 x float>) define float @square_fabs_intrinsic_f32(float %x) { %mul = fmul float %x, %x @@ -98,3 +99,27 @@ define float @square_fabs_shrink_call2(float %x) { ; CHECK-NEXT: ret float %sq } +; A scalar fabs op makes the sign bit zero, so masking off all of the other bits means we can return zero. + +define i32 @fabs_value_tracking_f32(float %x) { + %call = call float @llvm.fabs.f32(float %x) + %bc = bitcast float %call to i32 + %and = and i32 %bc, 2147483648 + ret i32 %and + +; CHECK-LABEL: fabs_value_tracking_f32( +; CHECK: ret i32 0 +} + +; TODO: A vector fabs op makes the sign bits zero, so masking off all of the other bits means we can return zero. + +define <4 x i32> @fabs_value_tracking_v4f32(<4 x float> %x) { + %call = call <4 x float> @llvm.fabs.v4f32(<4 x float> %x) + %bc = bitcast <4 x float> %call to <4 x i32> + %and = and <4 x i32> %bc, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648> + ret <4 x i32> %and + +; CHECK-LABEL: fabs_value_tracking_v4f32( +; CHECK: ret <4 x i32> %and +} + diff --git a/test/Transforms/InstCombine/fast-math.ll b/test/Transforms/InstCombine/fast-math.ll index 4eebdbdfacf1..fd563481b3ed 100644 --- a/test/Transforms/InstCombine/fast-math.ll +++ b/test/Transforms/InstCombine/fast-math.ll @@ -570,7 +570,7 @@ define double @sqrt_intrinsic_arg_squared(double %x) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_arg_squared( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) ; CHECK-NEXT: ret double %fabs } @@ -584,8 +584,8 @@ define double @sqrt_intrinsic_three_args1(double %x, double %y) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args1( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y) ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -597,8 +597,8 @@ define double @sqrt_intrinsic_three_args2(double %x, double %y) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args2( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y) ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -610,8 +610,8 @@ define double @sqrt_intrinsic_three_args3(double %x, double %y) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args3( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y) ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -623,8 +623,8 @@ define double @sqrt_intrinsic_three_args4(double %x, double %y) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args4( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y) ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -636,8 +636,8 @@ define double @sqrt_intrinsic_three_args5(double %x, double %y) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args5( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y) ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -649,8 +649,8 @@ define double @sqrt_intrinsic_three_args6(double %x, double %y) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_intrinsic_three_args6( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %y) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %y) ; CHECK-NEXT: %1 = fmul fast double %fabs, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -675,7 +675,7 @@ define double @sqrt_intrinsic_arg_5th(double %x) #0 { ; CHECK-LABEL: sqrt_intrinsic_arg_5th( ; CHECK-NEXT: %mul = fmul fast double %x, %x -; CHECK-NEXT: %sqrt1 = call double @llvm.sqrt.f64(double %x) +; CHECK-NEXT: %sqrt1 = call fast double @llvm.sqrt.f64(double %x) ; CHECK-NEXT: %1 = fmul fast double %mul, %sqrt1 ; CHECK-NEXT: ret double %1 } @@ -692,7 +692,7 @@ define float @sqrt_call_squared_f32(float %x) #0 { ret float %sqrt ; CHECK-LABEL: sqrt_call_squared_f32( -; CHECK-NEXT: %fabs = call float @llvm.fabs.f32(float %x) +; CHECK-NEXT: %fabs = call fast float @llvm.fabs.f32(float %x) ; CHECK-NEXT: ret float %fabs } @@ -702,7 +702,7 @@ define double @sqrt_call_squared_f64(double %x) #0 { ret double %sqrt ; CHECK-LABEL: sqrt_call_squared_f64( -; CHECK-NEXT: %fabs = call double @llvm.fabs.f64(double %x) +; CHECK-NEXT: %fabs = call fast double @llvm.fabs.f64(double %x) ; CHECK-NEXT: ret double %fabs } @@ -712,7 +712,114 @@ define fp128 @sqrt_call_squared_f128(fp128 %x) #0 { ret fp128 %sqrt ; CHECK-LABEL: sqrt_call_squared_f128( -; CHECK-NEXT: %fabs = call fp128 @llvm.fabs.f128(fp128 %x) +; CHECK-NEXT: %fabs = call fast fp128 @llvm.fabs.f128(fp128 %x) ; CHECK-NEXT: ret fp128 %fabs } +; ========================================================================= +; +; Test-cases for fmin / fmax +; +; ========================================================================= + +declare double @fmax(double, double) +declare double @fmin(double, double) +declare float @fmaxf(float, float) +declare float @fminf(float, float) +declare fp128 @fmaxl(fp128, fp128) +declare fp128 @fminl(fp128, fp128) + +; No NaNs is the minimum requirement to replace these calls. +; This should always be set when unsafe-fp-math is true, but +; alternate the attributes for additional test coverage. +; 'nsz' is implied by the definition of fmax or fmin itself. +attributes #1 = { "no-nans-fp-math" = "true" } + +; Shrink and remove the call. +define float @max1(float %a, float %b) #0 { + %c = fpext float %a to double + %d = fpext float %b to double + %e = call double @fmax(double %c, double %d) + %f = fptrunc double %e to float + ret float %f + +; CHECK-LABEL: max1( +; CHECK-NEXT: fcmp fast ogt float %a, %b +; CHECK-NEXT: select {{.*}} float %a, float %b +; CHECK-NEXT: ret +} + +define float @max2(float %a, float %b) #1 { + %c = call float @fmaxf(float %a, float %b) + ret float %c + +; CHECK-LABEL: max2( +; CHECK-NEXT: fcmp nnan nsz ogt float %a, %b +; CHECK-NEXT: select {{.*}} float %a, float %b +; CHECK-NEXT: ret +} + + +define double @max3(double %a, double %b) #0 { + %c = call double @fmax(double %a, double %b) + ret double %c + +; CHECK-LABEL: max3( +; CHECK-NEXT: fcmp fast ogt double %a, %b +; CHECK-NEXT: select {{.*}} double %a, double %b +; CHECK-NEXT: ret +} + +define fp128 @max4(fp128 %a, fp128 %b) #1 { + %c = call fp128 @fmaxl(fp128 %a, fp128 %b) + ret fp128 %c + +; CHECK-LABEL: max4( +; CHECK-NEXT: fcmp nnan nsz ogt fp128 %a, %b +; CHECK-NEXT: select {{.*}} fp128 %a, fp128 %b +; CHECK-NEXT: ret +} + +; Shrink and remove the call. +define float @min1(float %a, float %b) #1 { + %c = fpext float %a to double + %d = fpext float %b to double + %e = call double @fmin(double %c, double %d) + %f = fptrunc double %e to float + ret float %f + +; CHECK-LABEL: min1( +; CHECK-NEXT: fcmp nnan nsz olt float %a, %b +; CHECK-NEXT: select {{.*}} float %a, float %b +; CHECK-NEXT: ret +} + +define float @min2(float %a, float %b) #0 { + %c = call float @fminf(float %a, float %b) + ret float %c + +; CHECK-LABEL: min2( +; CHECK-NEXT: fcmp fast olt float %a, %b +; CHECK-NEXT: select {{.*}} float %a, float %b +; CHECK-NEXT: ret +} + +define double @min3(double %a, double %b) #1 { + %c = call double @fmin(double %a, double %b) + ret double %c + +; CHECK-LABEL: min3( +; CHECK-NEXT: fcmp nnan nsz olt double %a, %b +; CHECK-NEXT: select {{.*}} double %a, double %b +; CHECK-NEXT: ret +} + +define fp128 @min4(fp128 %a, fp128 %b) #0 { + %c = call fp128 @fminl(fp128 %a, fp128 %b) + ret fp128 %c + +; CHECK-LABEL: min4( +; CHECK-NEXT: fcmp fast olt fp128 %a, %b +; CHECK-NEXT: select {{.*}} fp128 %a, fp128 %b +; CHECK-NEXT: ret +} diff --git a/test/Transforms/InstCombine/ffs-1.ll b/test/Transforms/InstCombine/ffs-1.ll index c8763dc199a9..d27fb5d89f09 100644 --- a/test/Transforms/InstCombine/ffs-1.ll +++ b/test/Transforms/InstCombine/ffs-1.ll @@ -1,9 +1,12 @@ ; Test that the ffs* library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s -; RUN: opt < %s -mtriple i386-pc-linux -instcombine -S | FileCheck %s -check-prefix=CHECK-LINUX - -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +; RUN: opt < %s -mtriple i386-pc-linux -instcombine -S | FileCheck %s -check-prefix=CHECK-FFS +; RUN: opt -instcombine -mtriple=arm64-apple-ios9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s +; RUN: opt -instcombine -mtriple=arm64-apple-tvos9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s +; RUN: opt -instcombine -mtriple=thumbv7k-apple-watchos2.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s +; RUN: opt -instcombine -mtriple=x86_64-apple-macosx10.11 -S %s | FileCheck --check-prefix=CHECK-FFS %s +; RUN: opt -instcombine -mtriple=x86_64-freebsd-gnu -S %s | FileCheck --check-prefix=CHECK-FFS %s declare i32 @ffs(i32) declare i32 @ffsl(i32) @@ -19,17 +22,17 @@ define i32 @test_simplify1() { } define i32 @test_simplify2() { -; CHECK-LINUX-LABEL: @test_simplify2( +; CHECK-FFS-LABEL: @test_simplify2( %ret = call i32 @ffsl(i32 0) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 0 +; CHECK-FFS-NEXT: ret i32 0 } define i32 @test_simplify3() { -; CHECK-LINUX-LABEL: @test_simplify3( +; CHECK-FFS-LABEL: @test_simplify3( %ret = call i32 @ffsll(i64 0) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 0 +; CHECK-FFS-NEXT: ret i32 0 } ; Check ffs(c) -> cttz(c) + 1, where 'c' is a constant. @@ -56,45 +59,45 @@ define i32 @test_simplify6() { } define i32 @test_simplify7() { -; CHECK-LINUX-LABEL: @test_simplify7( +; CHECK-FFS-LABEL: @test_simplify7( %ret = call i32 @ffsl(i32 65536) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 17 +; CHECK-FFS-NEXT: ret i32 17 } define i32 @test_simplify8() { -; CHECK-LINUX-LABEL: @test_simplify8( +; CHECK-FFS-LABEL: @test_simplify8( %ret = call i32 @ffsll(i64 1024) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 11 +; CHECK-FFS-NEXT: ret i32 11 } define i32 @test_simplify9() { -; CHECK-LINUX-LABEL: @test_simplify9( +; CHECK-FFS-LABEL: @test_simplify9( %ret = call i32 @ffsll(i64 65536) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 17 +; CHECK-FFS-NEXT: ret i32 17 } define i32 @test_simplify10() { -; CHECK-LINUX-LABEL: @test_simplify10( +; CHECK-FFS-LABEL: @test_simplify10( %ret = call i32 @ffsll(i64 17179869184) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 35 +; CHECK-FFS-NEXT: ret i32 35 } define i32 @test_simplify11() { -; CHECK-LINUX-LABEL: @test_simplify11( +; CHECK-FFS-LABEL: @test_simplify11( %ret = call i32 @ffsll(i64 281474976710656) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 49 +; CHECK-FFS-NEXT: ret i32 49 } define i32 @test_simplify12() { -; CHECK-LINUX-LABEL: @test_simplify12( +; CHECK-FFS-LABEL: @test_simplify12( %ret = call i32 @ffsll(i64 1152921504606846976) ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 61 +; CHECK-FFS-NEXT: ret i32 61 } ; Check ffs(x) -> x != 0 ? (i32)llvm.cttz(x) + 1 : 0. @@ -102,7 +105,7 @@ define i32 @test_simplify12() { define i32 @test_simplify13(i32 %x) { ; CHECK-LABEL: @test_simplify13( %ret = call i32 @ffs(i32 %x) -; CHECK-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 false) +; CHECK-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true) ; CHECK-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1 ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0 ; CHECK-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0 @@ -111,24 +114,24 @@ define i32 @test_simplify13(i32 %x) { } define i32 @test_simplify14(i32 %x) { -; CHECK-LINUX-LABEL: @test_simplify14( +; CHECK-FFS-LABEL: @test_simplify14( %ret = call i32 @ffsl(i32 %x) -; CHECK-LINUX-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 false) -; CHECK-LINUX-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1 -; CHECK-LINUX-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0 -; CHECK-LINUX-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0 +; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true) +; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1 +; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0 +; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0 ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 [[RET]] +; CHECK-FFS-NEXT: ret i32 [[RET]] } define i32 @test_simplify15(i64 %x) { -; CHECK-LINUX-LABEL: @test_simplify15( +; CHECK-FFS-LABEL: @test_simplify15( %ret = call i32 @ffsll(i64 %x) -; CHECK-LINUX-NEXT: [[CTTZ:%[a-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %x, i1 false) -; CHECK-LINUX-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i64 [[CTTZ]], 1 -; CHECK-LINUX-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i64 [[INC]] to i32 -; CHECK-LINUX-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i64 %x, 0 -; CHECK-LINUX-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[TRUNC]], i32 0 +; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %x, i1 true) +; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i64 [[CTTZ]], 1 +; CHECK-FFS-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i64 [[INC]] to i32 +; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i64 %x, 0 +; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[TRUNC]], i32 0 ret i32 %ret -; CHECK-LINUX-NEXT: ret i32 [[RET]] +; CHECK-FFS-NEXT: ret i32 [[RET]] } diff --git a/test/Transforms/InstCombine/fold-phi-load-metadata.ll b/test/Transforms/InstCombine/fold-phi-load-metadata.ll new file mode 100644 index 000000000000..7fa26b46e25d --- /dev/null +++ b/test/Transforms/InstCombine/fold-phi-load-metadata.ll @@ -0,0 +1,69 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +@g1 = common global i32* null, align 8 + +%struct.S1 = type { i32, float } +%struct.S2 = type { float, i32 } + +; Check that instcombine preserves metadata when it merges two loads. +; +; CHECK: return: +; CHECK: load i32*, i32** %{{[a-z0-9.]+}}, align 8, !nonnull ![[EMPTYNODE:[0-9]+]] +; CHECK: load i32, i32* %{{[a-z0-9.]+}}, align 4, !tbaa ![[TBAA:[0-9]+]], !range ![[RANGE:[0-9]+]], !invariant.load ![[EMPTYNODE:[0-9]+]], !alias.scope ![[ALIAS_SCOPE:[0-9]+]], !noalias ![[NOALIAS:[0-9]+]] + +; Function Attrs: nounwind ssp uwtable +define i32 @phi_load_metadata(%struct.S1* %s1, %struct.S2* %s2, i32 %c, i32** %x0, i32 **%x1) #0 { +entry: + %tobool = icmp eq i32 %c, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %i = getelementptr inbounds %struct.S2, %struct.S2* %s2, i64 0, i32 1 + %val = load i32, i32* %i, align 4, !tbaa !0, !alias.scope !13, !noalias !14, !invariant.load !17, !range !18 + %p0 = load i32*, i32** %x0, align 8, !nonnull !17 + br label %return + +if.end: ; preds = %entry + %i2 = getelementptr inbounds %struct.S1, %struct.S1* %s1, i64 0, i32 0 + %val2 = load i32, i32* %i2, align 4, !tbaa !2, !alias.scope !15, !noalias !16, !invariant.load !17, !range !19 + %p1 = load i32*, i32** %x1, align 8, !nonnull !17 + br label %return + +return: ; preds = %if.end, %if.then + %retval = phi i32 [ %val, %if.then ], [ %val2, %if.end ] + %pval = phi i32* [ %p0, %if.then ], [ %p1, %if.end ] + store i32* %pval, i32** @g1, align 8 + ret i32 %retval +} + +; CHECK: ![[EMPTYNODE]] = !{} +; CHECK: ![[TBAA]] = !{![[TAG1:[0-9]+]], ![[TAG1]], i64 0} +; CHECK: ![[TAG1]] = !{!"int", !{{[0-9]+}}, i64 0} +; CHECK: ![[RANGE]] = !{i32 10, i32 25} +; CHECK: ![[ALIAS_SCOPE]] = !{![[SCOPE0:[0-9]+]], ![[SCOPE1:[0-9]+]], ![[SCOPE2:[0-9]+]]} +; CHECK: ![[SCOPE0]] = distinct !{![[SCOPE0]], !{{[0-9]+}}, !"scope0"} +; CHECK: ![[SCOPE1]] = distinct !{![[SCOPE1]], !{{[0-9]+}}, !"scope1"} +; CHECK: ![[SCOPE2]] = distinct !{![[SCOPE2]], !{{[0-9]+}}, !"scope2"} +; CHECK: ![[NOALIAS]] = !{![[SCOPE3:[0-9]+]]} +; CHECK: ![[SCOPE3]] = distinct !{![[SCOPE3]], !{{[0-9]+}}, !"scope3"} + +!0 = !{!1, !4, i64 4} +!1 = !{!"", !7, i64 0, !4, i64 4} +!2 = !{!3, !4, i64 0} +!3 = !{!"", !4, i64 0, !7, i64 4} +!4 = !{!"int", !5, i64 0} +!5 = !{!"omnipotent char", !6, i64 0} +!6 = !{!"Simple C/C++ TBAA"} +!7 = !{!"float", !5, i64 0} +!8 = !{!8, !"some domain"} +!9 = !{!9, !8, !"scope0"} +!10 = !{!10, !8, !"scope1"} +!11 = !{!11, !8, !"scope2"} +!12 = !{!12, !8, !"scope3"} +!13 = !{!9, !10} +!14 = !{!11, !12} +!15 = !{!9, !11} +!16 = !{!10, !12} +!17 = !{} +!18 = !{i32 10, i32 20} +!19 = !{i32 15, i32 25} diff --git a/test/Transforms/InstCombine/gc.relocate.ll b/test/Transforms/InstCombine/gc.relocate.ll index a51aac10eb57..308258a19417 100644 --- a/test/Transforms/InstCombine/gc.relocate.ll +++ b/test/Transforms/InstCombine/gc.relocate.ll @@ -6,8 +6,8 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 ; then the return attribute of gc.relocate is dereferenceable(N). declare zeroext i1 @return_i1() -declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) -declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) +declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) define i32 addrspace(1)* @deref(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" { ; Checks that a dereferenceabler pointer @@ -15,7 +15,38 @@ define i32 addrspace(1)* @deref(i32 addrspace(1)* dereferenceable(8) %dparam) gc ; CHECK: call dereferenceable(8) entry: %load = load i32, i32 addrspace(1)* %dparam - %tok = tail call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) - %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 7, i32 7) + %tok = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 7, i32 7) ret i32 addrspace(1)* %relocate } + +define i32 @explicit_nonnull(i32 addrspace(1)* nonnull %dparam) gc "statepoint-example" { +; Checks that a nonnull pointer +; CHECK-LABEL: @explicit_nonnull +; CHECK: ret i32 1 +entry: + %load = load i32, i32 addrspace(1)* %dparam + %tok = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 7, i32 7) + %cmp = icmp eq i32 addrspace(1)* %relocate, null + %ret_val = select i1 %cmp, i32 0, i32 1 + ret i32 %ret_val +} + +define i32 @implicit_nonnull(i32 addrspace(1)* %dparam) gc "statepoint-example" { +; Checks that a nonnull pointer +; CHECK-LABEL: @implicit_nonnull +; CHECK: ret i32 1 +entry: + %cond = icmp eq i32 addrspace(1)* %dparam, null + br i1 %cond, label %no_gc, label %gc +gc: + %load = load i32, i32 addrspace(1)* %dparam + %tok = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 7, i32 7) + %cmp = icmp eq i32 addrspace(1)* %relocate, null + %ret_val = select i1 %cmp, i32 0, i32 1 + ret i32 %ret_val +no_gc: + unreachable +} diff --git a/test/Transforms/InstCombine/gepphigep.ll b/test/Transforms/InstCombine/gepphigep.ll index b98ea4cd1159..cc90d714be73 100644 --- a/test/Transforms/InstCombine/gepphigep.ll +++ b/test/Transforms/InstCombine/gepphigep.ll @@ -134,3 +134,53 @@ exit: ; CHECK: getelementptr{{.*}}i64 1 ; CHECK: exit: } + +@.str.4 = external unnamed_addr constant [100 x i8], align 1 + +; Instcombine shouldn't add new PHI nodes while folding GEPs if that will leave +; old PHI nodes behind as this is not clearly beneficial. +; CHECK-LABEL: @test5( +define void @test5(i16 *%idx, i8 **%in) #0 { +entry: + %0 = load i8*, i8** %in + %incdec.ptr = getelementptr inbounds i8, i8* %0, i32 1 + %1 = load i8, i8* %incdec.ptr, align 1 + %cmp23 = icmp eq i8 %1, 54 + br i1 %cmp23, label %while.cond, label %if.then.25 + +if.then.25: + call void @g(i8* getelementptr inbounds ([100 x i8], [100 x i8]* @.str.4, i32 0, i32 0)) + br label %while.cond + +while.cond: +; CHECK-LABEL: while.cond +; CHECK-NOT: phi i8* [ %0, %entry ], [ %Ptr, %while.body ], [ %0, %if.then.25 ] + %Ptr = phi i8* [ %incdec.ptr, %entry ], [ %incdec.ptr32, %while.body], [%incdec.ptr, %if.then.25 ] + %2 = load i8, i8* %Ptr + %and = and i8 %2, 64 + %lnot = icmp eq i8 %and, 0 + br i1 %lnot, label %while.body, label %while.cond.33 + +while.body: + %incdec.ptr32 = getelementptr inbounds i8, i8* %Ptr, i32 1 + br label %while.cond + +while.cond.33: + %incdec.ptr34 = getelementptr inbounds i8, i8* %Ptr, i32 1 + br label %while.cond.57 + +while.cond.57: + %3 = load i8, i8* %incdec.ptr34, align 1 + %conv59 = zext i8 %3 to i32 + %arrayidx61 = getelementptr inbounds i16, i16* %idx, i32 %conv59 + %4 = load i16, i16* %arrayidx61, align 2 + %and63 = and i16 %4, 2048 + %tobool64 = icmp eq i16 %and63, 0 + br i1 %tobool64, label %while.cond.73, label %while.cond.57 + +while.cond.73: + br label %while.cond.73 + +} + +declare void @g(i8*) diff --git a/test/Transforms/InstCombine/icmp-range.ll b/test/Transforms/InstCombine/icmp-range.ll index 041adf76b5e1..f035683170e1 100644 --- a/test/Transforms/InstCombine/icmp-range.ll +++ b/test/Transforms/InstCombine/icmp-range.ll @@ -54,8 +54,97 @@ define i1 @test_nonzero6(i8* %argw) { ret i1 %rval } +; Constant not in range, should return true. +define i1 @test_not_in_range(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_not_in_range +; CHECK: ret i1 true + %val = load i32, i32* %arg, !range !0 + %rval = icmp ne i32 %val, 6 + ret i1 %rval +} + +; Constant in range, can not fold. +define i1 @test_in_range(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_in_range +; CHECK: icmp ne i32 %val, 3 + %val = load i32, i32* %arg, !range !0 + %rval = icmp ne i32 %val, 3 + ret i1 %rval +} + +; Values in range greater than constant. +define i1 @test_range_sgt_constant(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_range_sgt_constant +; CHECK: ret i1 true + %val = load i32, i32* %arg, !range !0 + %rval = icmp sgt i32 %val, 0 + ret i1 %rval +} + +; Values in range less than constant. +define i1 @test_range_slt_constant(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_range_slt_constant +; CHECK: ret i1 false + %val = load i32, i32* %arg, !range !0 + %rval = icmp sgt i32 %val, 6 + ret i1 %rval +} + +; Values in union of multiple sub ranges not equal to constant. +define i1 @test_multi_range1(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_multi_range1 +; CHECK: ret i1 true + %val = load i32, i32* %arg, !range !4 + %rval = icmp ne i32 %val, 0 + ret i1 %rval +} + +; Values in multiple sub ranges not equal to constant, but in +; union of sub ranges could possibly equal to constant. This +; in theory could also be folded and might be implemented in +; the future if shown profitable in practice. +define i1 @test_multi_range2(i32* nocapture readonly %arg) { +; CHECK-LABEL: test_multi_range2 +; CHECK: icmp ne i32 %val, 7 + %val = load i32, i32* %arg, !range !4 + %rval = icmp ne i32 %val, 7 + ret i1 %rval +} + +; Values' ranges overlap each other, so it can not be simplified. +define i1 @test_two_ranges(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) { +; CHECK-LABEL: test_two_ranges +; CHECK: icmp ult i32 %val2, %val1 + %val1 = load i32, i32* %arg1, !range !5 + %val2 = load i32, i32* %arg2, !range !6 + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_two_ranges2(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) { +; CHECK-LABEL: test_two_ranges2 +; CHECK: ret i1 false + %val1 = load i32, i32* %arg1, !range !0 + %val2 = load i32, i32* %arg2, !range !6 + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to true. +define i1 @test_two_ranges3(i32* nocapture readonly %arg1, i32* nocapture readonly %arg2) { +; CHECK-LABEL: test_two_ranges3 +; CHECK: ret i1 true + %val1 = load i32, i32* %arg1, !range !0 + %val2 = load i32, i32* %arg2, !range !6 + %rval = icmp ugt i32 %val2, %val1 + ret i1 %rval +} !0 = !{i32 1, i32 6} !1 = !{i32 0, i32 6} !2 = !{i8 0, i8 1} !3 = !{i8 0, i8 6} +!4 = !{i32 1, i32 6, i32 8, i32 10} +!5 = !{i32 5, i32 10} +!6 = !{i32 8, i32 16} diff --git a/test/Transforms/InstCombine/icmp-shr.ll b/test/Transforms/InstCombine/icmp-shr.ll index 52414b99cca7..4fa85a72baf7 100644 --- a/test/Transforms/InstCombine/icmp-shr.ll +++ b/test/Transforms/InstCombine/icmp-shr.ll @@ -376,3 +376,12 @@ define i1 @PR21222(i32 %B) { %cmp = icmp eq i32 %shr, -2 ret i1 %cmp } + +; CHECK-LABEL: @PR24873( +; CHECK: %[[icmp:.*]] = icmp ugt i64 %V, 61 +; CHECK-NEXT: ret i1 %[[icmp]] +define i1 @PR24873(i64 %V) { + %ashr = ashr i64 -4611686018427387904, %V + %icmp = icmp eq i64 %ashr, -1 + ret i1 %icmp +} diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index edcf76d5a7d2..7d6ec96b5328 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -819,8 +819,8 @@ define i1 @test68(i32 %x) nounwind uwtable { ; PR14708 ; CHECK-LABEL: @test69( -; CHECK: %1 = and i32 %c, -33 -; CHECK: %2 = icmp eq i32 %1, 65 +; CHECK: %1 = or i32 %c, 32 +; CHECK: %2 = icmp eq i32 %1, 97 ; CHECK: ret i1 %2 define i1 @test69(i32 %c) nounwind uwtable { %1 = icmp eq i32 %c, 97 @@ -1603,3 +1603,72 @@ define i32 @f7(i32 %a, i32 %b) { %s = select i1 %cmp, i32 10000, i32 0 ret i32 %s } + +; CHECK: @f8( +; CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = icmp ne i32 %lim, 0 +; CHECK-NEXT: ret i1 [[RESULT]] +define i1 @f8(i32 %val, i32 %lim) { + %lim.sub = add i32 %lim, -1 + %val.and = and i32 %val, %lim.sub + %r = icmp ult i32 %val.and, %lim + ret i1 %r +} + +; CHECK: @f9( +; CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = icmp ne i32 %lim, 0 +; CHECK-NEXT: ret i1 [[RESULT]] +define i1 @f9(i32 %val, i32 %lim) { + %lim.sub = sub i32 %lim, 1 + %val.and = and i32 %val, %lim.sub + %r = icmp ult i32 %val.and, %lim + ret i1 %r +} + +; CHECK: @f10( +; CHECK: [[CMP:%.*]] = icmp uge i16 %p, mul (i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16), i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16)) +; CHECK-NEXT: ret i1 [[CMP]] +define i1 @f10(i16 %p) { +entry: + %cmp580 = icmp ule i16 mul (i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16), i16 zext (i8 ptrtoint (i1 (i16)* @f10 to i8) to i16)), %p + ret i1 %cmp580 +} + +; CHECK-LABEL: @cmp_sgt_rhs_dec +; CHECK-NOT: sub +; CHECK: icmp sge i32 %conv, %i +define i1 @cmp_sgt_rhs_dec(float %x, i32 %i) { + %conv = fptosi float %x to i32 + %dec = sub nsw i32 %i, 1 + %cmp = icmp sgt i32 %conv, %dec + ret i1 %cmp +} + +; CHECK-LABEL: @cmp_sle_rhs_dec +; CHECK-NOT: sub +; CHECK: icmp slt i32 %conv, %i +define i1 @cmp_sle_rhs_dec(float %x, i32 %i) { + %conv = fptosi float %x to i32 + %dec = sub nsw i32 %i, 1 + %cmp = icmp sle i32 %conv, %dec + ret i1 %cmp +} + +; CHECK-LABEL: @cmp_sge_rhs_inc +; CHECK-NOT: add +; CHECK: icmp sgt i32 %conv, %i +define i1 @cmp_sge_rhs_inc(float %x, i32 %i) { + %conv = fptosi float %x to i32 + %inc = add nsw i32 %i, 1 + %cmp = icmp sge i32 %conv, %inc + ret i1 %cmp +} + +; CHECK-LABEL: @cmp_slt_rhs_inc +; CHECK-NOT: add +; CHECK: icmp sle i32 %conv, %i +define i1 @cmp_slt_rhs_inc(float %x, i32 %i) { + %conv = fptosi float %x to i32 + %inc = add nsw i32 %i, 1 + %cmp = icmp slt i32 %conv, %inc + ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/inline-intrinsic-assert.ll b/test/Transforms/InstCombine/inline-intrinsic-assert.ll index af34277563e0..c6446d43cffd 100644 --- a/test/Transforms/InstCombine/inline-intrinsic-assert.ll +++ b/test/Transforms/InstCombine/inline-intrinsic-assert.ll @@ -9,7 +9,7 @@ define float @foo(float %f1) #0 { ret float %call ; CHECK-LABEL: @foo( -; CHECK-NEXT: call float @llvm.fabs.f32 +; CHECK-NEXT: call fast float @llvm.fabs.f32 ; CHECK-NEXT: ret float } diff --git a/test/Transforms/InstCombine/insert-extract-shuffle.ll b/test/Transforms/InstCombine/insert-extract-shuffle.ll index 8929c82def7b..c75c771407e5 100644 --- a/test/Transforms/InstCombine/insert-extract-shuffle.ll +++ b/test/Transforms/InstCombine/insert-extract-shuffle.ll @@ -24,14 +24,51 @@ define <4 x i16> @test2(<8 x i16> %in, <8 x i16> %in2) { ret <4 x i16> %vec.3 } -define <2 x i64> @test_vcopyq_lane_p64(<2 x i64> %a, <1 x i64> %b) #0 { +define <2 x i64> @test_vcopyq_lane_p64(<2 x i64> %a, <1 x i64> %b) { ; CHECK-LABEL: @test_vcopyq_lane_p64 -; CHECK: extractelement -; CHECK: insertelement -; CHECK-NOT: shufflevector -entry: +; CHECK-NEXT: %[[WIDEVEC:.*]] = shufflevector <1 x i64> %b, <1 x i64> undef, <2 x i32> <i32 0, i32 undef> +; CHECK-NEXT: shufflevector <2 x i64> %a, <2 x i64> %[[WIDEVEC]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: ret <2 x i64> %res %elt = extractelement <1 x i64> %b, i32 0 %res = insertelement <2 x i64> %a, i64 %elt, i32 1 ret <2 x i64> %res } +; PR2109: https://llvm.org/bugs/show_bug.cgi?id=2109 + +define <4 x float> @widen_extract2(<4 x float> %ins, <2 x float> %ext) { +; CHECK-LABEL: @widen_extract2( +; CHECK-NEXT: %[[WIDEVEC:.*]] = shufflevector <2 x float> %ext, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> +; CHECK-NEXT: shufflevector <4 x float> %ins, <4 x float> %[[WIDEVEC]], <4 x i32> <i32 0, i32 4, i32 2, i32 5> +; CHECK-NEXT: ret <4 x float> %i2 + %e1 = extractelement <2 x float> %ext, i32 0 + %e2 = extractelement <2 x float> %ext, i32 1 + %i1 = insertelement <4 x float> %ins, float %e1, i32 1 + %i2 = insertelement <4 x float> %i1, float %e2, i32 3 + ret <4 x float> %i2 +} + +define <4 x float> @widen_extract3(<4 x float> %ins, <3 x float> %ext) { +; CHECK-LABEL: @widen_extract3( +; CHECK-NEXT: %[[WIDEVEC:.*]] = shufflevector <3 x float> %ext, <3 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> +; CHECK-NEXT: shufflevector <4 x float> %ins, <4 x float> %[[WIDEVEC]], <4 x i32> <i32 6, i32 5, i32 4, i32 3> +; CHECK-NEXT: ret <4 x float> %i3 + %e1 = extractelement <3 x float> %ext, i32 0 + %e2 = extractelement <3 x float> %ext, i32 1 + %e3 = extractelement <3 x float> %ext, i32 2 + %i1 = insertelement <4 x float> %ins, float %e1, i32 2 + %i2 = insertelement <4 x float> %i1, float %e2, i32 1 + %i3 = insertelement <4 x float> %i2, float %e3, i32 0 + ret <4 x float> %i3 +} + +define <8 x float> @widen_extract4(<8 x float> %ins, <2 x float> %ext) { +; CHECK-LABEL: @widen_extract4( +; CHECK-NEXT: %[[WIDEVEC:.*]] = shufflevector <2 x float> %ext, <2 x float> undef, <8 x i32> <i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: shufflevector <8 x float> %ins, <8 x float> %[[WIDEVEC]], <8 x i32> <i32 0, i32 1, i32 8, i32 3, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: ret <8 x float> %i1 + %e1 = extractelement <2 x float> %ext, i32 0 + %i1 = insertelement <8 x float> %ins, float %e1, i32 2 + ret <8 x float> %i1 +} + diff --git a/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index bea063787a75..88f032498271 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/test/Transforms/InstCombine/intrinsics.ll @@ -19,6 +19,11 @@ declare i32 @llvm.ctpop.i32(i32) nounwind readnone declare i8 @llvm.ctlz.i8(i8, i1) nounwind readnone declare double @llvm.cos.f64(double %Val) nounwind readonly declare double @llvm.sin.f64(double %Val) nounwind readonly +declare double @llvm.floor.f64(double %Val) nounwind readonly +declare double @llvm.ceil.f64(double %Val) nounwind readonly +declare double @llvm.trunc.f64(double %Val) nounwind readonly +declare double @llvm.rint.f64(double %Val) nounwind readonly +declare double @llvm.nearbyint.f64(double %Val) nounwind readonly define i8 @uaddtest1(i8 %A, i8 %B) { %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B) @@ -447,3 +452,63 @@ entry: ; CHECK-LABEL: @sin( ; CHECK: store volatile double 0.000000e+00, double* %P } + +define void @floor(double *%P) { +entry: + %B = tail call double @llvm.floor.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.floor.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @floor( +; CHECK: store volatile double 1.000000e+00, double* %P, align 8 +; CHECK: store volatile double -2.000000e+00, double* %P, align 8 +} + +define void @ceil(double *%P) { +entry: + %B = tail call double @llvm.ceil.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.ceil.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @ceil( +; CHECK: store volatile double 2.000000e+00, double* %P, align 8 +; CHECK: store volatile double -1.000000e+00, double* %P, align 8 +} + +define void @trunc(double *%P) { +entry: + %B = tail call double @llvm.trunc.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.trunc.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @trunc( +; CHECK: store volatile double 1.000000e+00, double* %P, align 8 +; CHECK: store volatile double -1.000000e+00, double* %P, align 8 +} + +define void @rint(double *%P) { +entry: + %B = tail call double @llvm.rint.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.rint.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @rint( +; CHECK: store volatile double 2.000000e+00, double* %P, align 8 +; CHECK: store volatile double -2.000000e+00, double* %P, align 8 +} + +define void @nearbyint(double *%P) { +entry: + %B = tail call double @llvm.nearbyint.f64(double 1.5) nounwind + store volatile double %B, double* %P + %C = tail call double @llvm.nearbyint.f64(double -1.5) nounwind + store volatile double %C, double* %P + ret void +; CHECK-LABEL: @nearbyint( +; CHECK: store volatile double 2.000000e+00, double* %P, align 8 +; CHECK: store volatile double -2.000000e+00, double* %P, align 8 +} diff --git a/test/Transforms/InstCombine/lifetime.ll b/test/Transforms/InstCombine/lifetime.ll new file mode 100644 index 000000000000..e5cbe3401410 --- /dev/null +++ b/test/Transforms/InstCombine/lifetime.ll @@ -0,0 +1,93 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.lifetime.start(i64, i8* nocapture) +declare void @llvm.lifetime.end(i64, i8* nocapture) +declare void @foo(i8* nocapture, i8* nocapture) + +define void @bar(i1 %flag) !dbg !4 { +entry: +; CHECK-LABEL: @bar( +; CHECK: %[[T:[^ ]+]] = getelementptr inbounds [1 x i8], [1 x i8]* %text +; CHECK: %[[B:[^ ]+]] = getelementptr inbounds [1 x i8], [1 x i8]* %buff +; CHECK: if: +; CHECK-NEXT: br label %bb2 +; CHECK: bb2: +; CHECK-NEXT: br label %bb3 +; CHECK: bb3: +; CHECK-NEXT: call void @llvm.dbg.declare +; CHECK-NEXT: br label %fin +; CHECK: call void @llvm.lifetime.start(i64 1, i8* %[[T]]) +; CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* %[[B]]) +; CHECK-NEXT: call void @foo(i8* %[[B]], i8* %[[T]]) +; CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* %[[B]]) +; CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* %[[T]]) + %text = alloca [1 x i8], align 1 + %buff = alloca [1 x i8], align 1 + %0 = getelementptr inbounds [1 x i8], [1 x i8]* %text, i64 0, i64 0 + %1 = getelementptr inbounds [1 x i8], [1 x i8]* %buff, i64 0, i64 0 + br i1 %flag, label %if, label %else + +if: + call void @llvm.lifetime.start(i64 1, i8* %0) + call void @llvm.lifetime.start(i64 1, i8* %1) + call void @llvm.lifetime.end(i64 1, i8* %1) + call void @llvm.lifetime.end(i64 1, i8* %0) + br label %bb2 + +bb2: + call void @llvm.lifetime.start(i64 1, i8* %0) + call void @llvm.lifetime.start(i64 1, i8* %1) + call void @llvm.lifetime.end(i64 1, i8* %0) + call void @llvm.lifetime.end(i64 1, i8* %1) + br label %bb3 + +bb3: + call void @llvm.lifetime.start(i64 1, i8* %0) + call void @llvm.dbg.declare(metadata [1 x i8]* %text, metadata !14, metadata !25), !dbg !26 + call void @llvm.lifetime.end(i64 1, i8* %0) + br label %fin + +else: + call void @llvm.lifetime.start(i64 1, i8* %0) + call void @llvm.lifetime.start(i64 1, i8* %1) + call void @foo(i8* %1, i8* %0) + call void @llvm.lifetime.end(i64 1, i8* %1) + call void @llvm.lifetime.end(i64 1, i8* %0) + br label %fin + +fin: + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!22, !23} +!llvm.ident = !{!24} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.8.0 (trunk 248826) (llvm/trunk 248827)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3) +!1 = !DIFile(filename: "test.cpp", directory: "/home/user") +!2 = !{} +!3 = !{!4} +!4 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, variables: !8) +!5 = !DISubroutineType(types: !6) +!6 = !{null, !7} +!7 = !DIBasicType(name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean) +!8 = !{!9, !11, !12, !14, !21} +!9 = !DILocalVariable(name: "Size", arg: 1, scope: !4, file: !1, line: 2, type: !10) +!10 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!11 = !DILocalVariable(name: "flag", arg: 2, scope: !4, file: !1, line: 2, type: !7) +!12 = !DILocalVariable(name: "i", scope: !13, file: !1, line: 3, type: !10) +!13 = distinct !DILexicalBlock(scope: !4, file: !1, line: 3, column: 3) +!14 = !DILocalVariable(name: "text", scope: !15, file: !1, line: 4, type: !17) +!15 = distinct !DILexicalBlock(scope: !16, file: !1, line: 3, column: 30) +!16 = distinct !DILexicalBlock(scope: !13, file: !1, line: 3, column: 3) +!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !18, size: 8, align: 8, elements: !19) +!18 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +!19 = !{!20} +!20 = !DISubrange(count: 1) +!21 = !DILocalVariable(name: "buff", scope: !15, file: !1, line: 5, type: !17) +!22 = !{i32 2, !"Dwarf Version", i32 4} +!23 = !{i32 2, !"Debug Info Version", i32 3} +!24 = !{!"clang version 3.8.0 (trunk 248826) (llvm/trunk 248827)"} +!25 = !DIExpression() +!26 = !DILocation(line: 4, column: 10, scope: !15) diff --git a/test/Transforms/InstCombine/load-cmp.ll b/test/Transforms/InstCombine/load-cmp.ll index b0bfdc4c4c54..fe1bf1517539 100644 --- a/test/Transforms/InstCombine/load-cmp.ll +++ b/test/Transforms/InstCombine/load-cmp.ll @@ -148,8 +148,8 @@ define i1 @test8(i32 %X) { %S = icmp eq i16 %R, 0 ret i1 %S ; CHECK-LABEL: @test8( -; CHECK-NEXT: and i32 %X, -2 -; CHECK-NEXT: icmp eq i32 {{.*}}, 8 +; CHECK-NEXT: or i32 %X, 1 +; CHECK-NEXT: icmp eq i32 {{.*}}, 9 ; CHECK-NEXT: ret i1 } @@ -233,7 +233,8 @@ define i1 @test10_struct_arr(i32 %x) { define i1 @test10_struct_arr_noinbounds(i32 %x) { ; CHECK-LABEL: @test10_struct_arr_noinbounds( -; CHECK-NEXT %p = getelementptr [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2 +; CHECK-NEXT: %r = icmp ne i32 %x, 1 +; CHECK-NEXT: ret i1 %r %p = getelementptr [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i32 %x, i32 2 %q = load i32, i32* %p %r = icmp eq i32 %q, 9 diff --git a/test/Transforms/InstCombine/load-combine-metadata-2.ll b/test/Transforms/InstCombine/load-combine-metadata-2.ll new file mode 100644 index 000000000000..bec0d7d2c36b --- /dev/null +++ b/test/Transforms/InstCombine/load-combine-metadata-2.ll @@ -0,0 +1,20 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128" + +; CHECK-LABEL: @test_load_load_combine_metadata( +; Check that align metadata is combined +; CHECK: load i32*, i32** %0 +; CHECK-SAME: !align ![[ALIGN:[0-9]+]] +define void @test_load_load_combine_metadata(i32**, i32**, i32**) { + %a = load i32*, i32** %0, !align !0 + %b = load i32*, i32** %0, !align !1 + store i32 0, i32* %a + store i32 0, i32* %b + ret void +} + +; CHECK: ![[ALIGN]] = !{i64 4} + +!0 = !{i64 4} +!1 = !{i64 8}
\ No newline at end of file diff --git a/test/Transforms/InstCombine/load-combine-metadata-3.ll b/test/Transforms/InstCombine/load-combine-metadata-3.ll new file mode 100644 index 000000000000..bad4bb240590 --- /dev/null +++ b/test/Transforms/InstCombine/load-combine-metadata-3.ll @@ -0,0 +1,20 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128" + +; CHECK-LABEL: @test_load_load_combine_metadata( +; Check that dereferenceable metadata is combined +; CHECK: load i32*, i32** %0 +; CHECK-SAME: !dereferenceable ![[DEREF:[0-9]+]] +define void @test_load_load_combine_metadata(i32**, i32**, i32**) { + %a = load i32*, i32** %0, !dereferenceable !0 + %b = load i32*, i32** %0, !dereferenceable !1 + store i32 0, i32* %a + store i32 0, i32* %b + ret void +} + +; CHECK: ![[DEREF]] = !{i64 4} + +!0 = !{i64 4} +!1 = !{i64 8}
\ No newline at end of file diff --git a/test/Transforms/InstCombine/load-combine-metadata-4.ll b/test/Transforms/InstCombine/load-combine-metadata-4.ll new file mode 100644 index 000000000000..2a1ffcd0605e --- /dev/null +++ b/test/Transforms/InstCombine/load-combine-metadata-4.ll @@ -0,0 +1,20 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128" + +; CHECK-LABEL: @test_load_load_combine_metadata( +; Check that dereferenceable_or_null metadata is combined +; CHECK: load i32*, i32** %0 +; CHECK-SAME: !dereferenceable_or_null ![[DEREF:[0-9]+]] +define void @test_load_load_combine_metadata(i32**, i32**, i32**) { + %a = load i32*, i32** %0, !dereferenceable_or_null !0 + %b = load i32*, i32** %0, !dereferenceable_or_null !1 + store i32 0, i32* %a + store i32 0, i32* %b + ret void +} + +; CHECK: ![[DEREF]] = !{i64 4} + +!0 = !{i64 4} +!1 = !{i64 8} diff --git a/test/Transforms/InstCombine/load-combine-metadata.ll b/test/Transforms/InstCombine/load-combine-metadata.ll index 9b9c1fe607b9..24b26fa42135 100644 --- a/test/Transforms/InstCombine/load-combine-metadata.ll +++ b/test/Transforms/InstCombine/load-combine-metadata.ll @@ -17,9 +17,9 @@ define void @test_load_load_combine_metadata(i32*, i32*, i32*) { ret void } -; CHECK: ![[RANGE]] = !{i32 0, i32 1, i32 8, i32 9} -!0 = !{ i32 0, i32 1 } -!1 = !{ i32 8, i32 9 } +; CHECK: ![[RANGE]] = !{i32 0, i32 5, i32 7, i32 9} +!0 = !{ i32 0, i32 5 } +!1 = !{ i32 7, i32 9 } !2 = !{!2} !3 = !{!3, !2} !4 = !{!4, !2} diff --git a/test/Transforms/InstCombine/loadstore-metadata.ll b/test/Transforms/InstCombine/loadstore-metadata.ll index a30c0bc852ea..f72e36a7ea37 100644 --- a/test/Transforms/InstCombine/loadstore-metadata.ll +++ b/test/Transforms/InstCombine/loadstore-metadata.ll @@ -31,7 +31,7 @@ define float @test_load_cast_combine_range(i32* %ptr) { ; CHECK-NOT: !range ; CHECK: ret float entry: - %l = load i32, i32* %ptr, !range !5 + %l = load i32, i32* %ptr, !range !6 %c = bitcast i32 %l to float ret float %c } @@ -57,6 +57,39 @@ entry: ret i32 %c } +define i8* @test_load_cast_combine_align(i32** %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves align +; metadata. +; CHECK-LABEL: @test_load_cast_combine_align( +; CHECK: load i8*, i8** %{{.*}}, !align !5 +entry: + %l = load i32*, i32** %ptr, !align !5 + %c = bitcast i32* %l to i8* + ret i8* %c +} + +define i8* @test_load_cast_combine_deref(i32** %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves dereferenceable +; metadata. +; CHECK-LABEL: @test_load_cast_combine_deref( +; CHECK: load i8*, i8** %{{.*}}, !dereferenceable !5 +entry: + %l = load i32*, i32** %ptr, !dereferenceable !5 + %c = bitcast i32* %l to i8* + ret i8* %c +} + +define i8* @test_load_cast_combine_deref_or_null(i32** %ptr) { +; Ensure (cast (load (...))) -> (load (cast (...))) preserves +; dereferenceable_or_null metadata. +; CHECK-LABEL: @test_load_cast_combine_deref_or_null( +; CHECK: load i8*, i8** %{{.*}}, !dereferenceable_or_null !5 +entry: + %l = load i32*, i32** %ptr, !dereferenceable_or_null !5 + %c = bitcast i32* %l to i8* + ret i8* %c +} + define void @test_load_cast_combine_loop(float* %src, i32* %dst, i32 %n) { ; Ensure (cast (load (...))) -> (load (cast (...))) preserves loop access ; metadata. @@ -110,4 +143,5 @@ entry: !2 = !{ !2, !1 } !3 = !{ } !4 = !{ i32 1 } -!5 = !{ i32 0, i32 42 } +!5 = !{ i64 8 } +!6 = !{ i32 0, i32 42 } diff --git a/test/Transforms/InstCombine/log-pow-nofastmath.ll b/test/Transforms/InstCombine/log-pow-nofastmath.ll new file mode 100644 index 000000000000..faaef97311ec --- /dev/null +++ b/test/Transforms/InstCombine/log-pow-nofastmath.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @mylog(double %x, double %y) { +entry: + %pow = call double @llvm.pow.f64(double %x, double %y) + %call = call double @log(double %pow) + ret double %call +} + +; CHECK-LABEL: define double @mylog( +; CHECK: %pow = call double @llvm.pow.f64(double %x, double %y) +; CHECK: %call = call double @log(double %pow) +; CHECK: ret double %call +; CHECK: } + +define double @test3(double %x) { + %call2 = call double @exp2(double %x) + %call3 = call double @log(double %call2) + ret double %call3 +} + +; CHECK-LABEL: @test3 +; CHECK: %call2 = call double @exp2(double %x) +; CHECK: %call3 = call double @log(double %call2) +; CHECK: ret double %call3 +; CHECK: } + +declare double @log(double) +declare double @exp2(double) +declare double @llvm.pow.f64(double, double) diff --git a/test/Transforms/InstCombine/log-pow.ll b/test/Transforms/InstCombine/log-pow.ll new file mode 100644 index 000000000000..c5ca1688d34a --- /dev/null +++ b/test/Transforms/InstCombine/log-pow.ll @@ -0,0 +1,41 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @mylog(double %x, double %y) #0 { +entry: + %pow = call double @llvm.pow.f64(double %x, double %y) + %call = call double @log(double %pow) #0 + ret double %call +} + +; CHECK-LABEL: define double @mylog( +; CHECK: %log = call fast double @log(double %x) #0 +; CHECK: %mul = fmul fast double %log, %y +; CHECK: ret double %mul +; CHECK: } + +define double @test2(double ()* %fptr, double %p1) #0 { + %call1 = call double %fptr() + %pow = call double @log(double %call1) + ret double %pow +} + +; CHECK-LABEL: @test2 +; CHECK: log + +define double @test3(double %x) #0 { + %call2 = call double @exp2(double %x) #0 + %call3 = call double @log(double %call2) #0 + ret double %call3 +} + +; CHECK-LABEL: @test3 +; CHECK: %call2 = call double @exp2(double %x) #0 +; CHECK: %logmul = fmul fast double %x, 0x3FE62E42FEFA39EF +; CHECK: ret double %logmul +; CHECK: } + +declare double @log(double) #0 +declare double @exp2(double) #0 +declare double @llvm.pow.f64(double, double) + +attributes #0 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/malloc-free-delete.ll b/test/Transforms/InstCombine/malloc-free-delete.ll index 138001ace951..8fcb8214360d 100644 --- a/test/Transforms/InstCombine/malloc-free-delete.ll +++ b/test/Transforms/InstCombine/malloc-free-delete.ll @@ -186,3 +186,14 @@ define void @test8() { call void @_ZdaPvj(i8* %naj, i32 32) builtin ret void } + +declare noalias i8* @"\01??2@YAPEAX_K@Z"(i64) nobuiltin +declare void @"\01??3@YAXPEAX@Z"(i8*) nobuiltin + +; CHECK-LABEL: @test9( +define void @test9() { + ; CHECK-NOT: call + %new_long_long = call noalias i8* @"\01??2@YAPEAX_K@Z"(i64 32) builtin + call void @"\01??3@YAXPEAX@Z"(i8* %new_long_long) builtin + ret void +} diff --git a/test/Transforms/InstCombine/memcmp-1.ll b/test/Transforms/InstCombine/memcmp-1.ll index db15bd66b715..f9ff479e3add 100644 --- a/test/Transforms/InstCombine/memcmp-1.ll +++ b/test/Transforms/InstCombine/memcmp-1.ll @@ -2,7 +2,7 @@ ; ; RUN: opt < %s -instcombine -S | FileCheck %s -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32:64" @foo = constant [4 x i8] c"foo\00" @hel = constant [4 x i8] c"hel\00" @@ -70,3 +70,54 @@ define i32 @test_simplify6() { ret i32 %ret ; CHECK: ret i32 -1 } + +; Check memcmp(mem1, mem2, 8)==0 -> *(int64_t*)mem1 == *(int64_t*)mem2 + +define i1 @test_simplify7(i64 %x, i64 %y) { +; CHECK-LABEL: @test_simplify7( + %x.addr = alloca i64, align 8 + %y.addr = alloca i64, align 8 + store i64 %x, i64* %x.addr, align 8 + store i64 %y, i64* %y.addr, align 8 + %xptr = bitcast i64* %x.addr to i8* + %yptr = bitcast i64* %y.addr to i8* + %call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 8) + %cmp = icmp eq i32 %call, 0 + ret i1 %cmp +; CHECK: %cmp = icmp eq i64 %x, %y +; CHECK: ret i1 %cmp +} + +; Check memcmp(mem1, mem2, 4)==0 -> *(int32_t*)mem1 == *(int32_t*)mem2 + +define i1 @test_simplify8(i32 %x, i32 %y) { +; CHECK-LABEL: @test_simplify8( + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %xptr = bitcast i32* %x.addr to i8* + %yptr = bitcast i32* %y.addr to i8* + %call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 4) + %cmp = icmp eq i32 %call, 0 + ret i1 %cmp +; CHECK: %cmp = icmp eq i32 %x, %y +; CHECK: ret i1 %cmp +} + +; Check memcmp(mem1, mem2, 2)==0 -> *(int16_t*)mem1 == *(int16_t*)mem2 + +define i1 @test_simplify9(i16 %x, i16 %y) { +; CHECK-LABEL: @test_simplify9( + %x.addr = alloca i16, align 2 + %y.addr = alloca i16, align 2 + store i16 %x, i16* %x.addr, align 2 + store i16 %y, i16* %y.addr, align 2 + %xptr = bitcast i16* %x.addr to i8* + %yptr = bitcast i16* %y.addr to i8* + %call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 2) + %cmp = icmp eq i32 %call, 0 + ret i1 %cmp +; CHECK: %cmp = icmp eq i16 %x, %y +; CHECK: ret i1 %cmp +} diff --git a/test/Transforms/InstCombine/memset_chk-1.ll b/test/Transforms/InstCombine/memset_chk-1.ll index 27f7293a6bce..56ea14c8292d 100644 --- a/test/Transforms/InstCombine/memset_chk-1.ll +++ b/test/Transforms/InstCombine/memset_chk-1.ll @@ -63,4 +63,30 @@ define i8* @test_no_simplify2() { ret i8* %ret } +; Test that RAUW in SimplifyLibCalls for __memset_chk generates valid IR +define i32 @test_rauw(i8* %a, i8* %b, i8** %c) { +; CHECK-LABEL: test_rauw +entry: + %call49 = call i64 @strlen(i8* %a) + %add180 = add i64 %call49, 1 + %yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false) + %call50 = call i8* @__memmove_chk(i8* %b, i8* %a, i64 %add180, i64 %yo107) +; CHECK: %strlen = call i64 @strlen(i8* %b) +; CHECK-NEXT: %strchr2 = getelementptr i8, i8* %b, i64 %strlen + %call51i = call i8* @strrchr(i8* %b, i32 0) + %d = load i8*, i8** %c, align 8 + %sub182 = ptrtoint i8* %d to i64 + %sub183 = ptrtoint i8* %b to i64 + %sub184 = sub i64 %sub182, %sub183 + %add52.i.i = add nsw i64 %sub184, 1 +; CHECK: call void @llvm.memset.p0i8.i64(i8* %strchr2 + %call185 = call i8* @__memset_chk(i8* %call51i, i32 0, i64 %add52.i.i, i64 -1) + ret i32 4 +} + +declare i8* @__memmove_chk(i8*, i8*, i64, i64) +declare i8* @strrchr(i8*, i32) +declare i64 @strlen(i8* nocapture) +declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) + declare i8* @__memset_chk(i8*, i32, i64, i64) diff --git a/test/Transforms/InstCombine/minmax-fp.ll b/test/Transforms/InstCombine/minmax-fp.ll new file mode 100644 index 000000000000..b90afe3405f7 --- /dev/null +++ b/test/Transforms/InstCombine/minmax-fp.ll @@ -0,0 +1,156 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; CHECK-LABEL: @t1 +; CHECK-NEXT: fcmp oge float %a, 5.000000e+00 +; CHECK-NEXT: select i1 %.inv, float 5.000000e+00, float %a +; CHECK-NEXT: fpext float %1 to double +define double @t1(float %a) { + ; This is the canonical form for a type-changing min/max. + %1 = fcmp ult float %a, 5.0 + %2 = select i1 %1, float %a, float 5.0 + %3 = fpext float %2 to double + ret double %3 +} + +; CHECK-LABEL: @t2 +; CHECK-NEXT: fcmp oge float %a, 5.000000e+00 +; CHECK-NEXT: select i1 %.inv, float 5.000000e+00, float %a +; CHECK-NEXT: fpext float %1 to double +define double @t2(float %a) { + ; Check this is converted into canonical form, as above. + %1 = fcmp ult float %a, 5.0 + %2 = fpext float %a to double + %3 = select i1 %1, double %2, double 5.0 + ret double %3 +} + +; CHECK-LABEL: @t4 +; CHECK-NEXT: fcmp oge double %a, 5.000000e+00 +; CHECK-NEXT: select i1 %.inv, double 5.000000e+00, double %a +; CHECK-NEXT: fptrunc double %1 to float +define float @t4(double %a) { + ; Same again, with trunc. + %1 = fcmp ult double %a, 5.0 + %2 = fptrunc double %a to float + %3 = select i1 %1, float %2, float 5.0 + ret float %3 +} + +; CHECK-LABEL: @t5 +; CHECK-NEXT: fcmp ult float %a, 5.000000e+00 +; CHECK-NEXT: fpext float %a to double +; CHECK-NEXT: select i1 %1, double %2, double 5.001 +define double @t5(float %a) { + ; different values, should not be converted. + %1 = fcmp ult float %a, 5.0 + %2 = fpext float %a to double + %3 = select i1 %1, double %2, double 5.001 + ret double %3 +} + +; CHECK-LABEL: @t6 +; CHECK-NEXT: fcmp ult float %a, -0.0 +; CHECK-NEXT: fpext float %a to double +; CHECK-NEXT: select i1 %1, double %2, double 0.0 +define double @t6(float %a) { + ; Signed zero, should not be converted + %1 = fcmp ult float %a, -0.0 + %2 = fpext float %a to double + %3 = select i1 %1, double %2, double 0.0 + ret double %3 +} + +; CHECK-LABEL: @t7 +; CHECK-NEXT: fcmp ult float %a, 0.0 +; CHECK-NEXT: fpext float %a to double +; CHECK-NEXT: select i1 %1, double %2, double -0.0 +define double @t7(float %a) { + ; Signed zero, should not be converted + %1 = fcmp ult float %a, 0.0 + %2 = fpext float %a to double + %3 = select i1 %1, double %2, double -0.0 + ret double %3 +} + +; CHECK-LABEL: @t8 +; CHECK-NEXT: fcmp oge float %a, 5.000000e+00 +; CHECK-NEXT: select i1 %.inv, float 5.000000e+00, float %a +; CHECK-NEXT: fptoui float %1 to i64 +define i64 @t8(float %a) { + %1 = fcmp ult float %a, 5.0 + %2 = fptoui float %a to i64 + %3 = select i1 %1, i64 %2, i64 5 + ret i64 %3 +} + +; CHECK-LABEL: @t9 +; CHECK-NEXT: fcmp oge float %a, 0.000000e+00 +; CHECK-NEXT: select i1 %.inv, float 0.000000e+00, float %a +; CHECK-NEXT: fptosi float %1 to i8 +define i8 @t9(float %a) { + %1 = fcmp ult float %a, 0.0 + %2 = fptosi float %a to i8 + %3 = select i1 %1, i8 %2, i8 0 + ret i8 %3 +} + +; CHECK-LABEL: @t11 +; CHECK-NEXT: fcmp fast oge float %b, %a +; CHECK-NEXT: select i1 %.inv, float %a, float %b +; CHECK-NEXT: fptosi +define i8 @t11(float %a, float %b) { + ; Either operand could be NaN, but fast modifier applied. + %1 = fcmp fast ult float %b, %a + %2 = fptosi float %a to i8 + %3 = fptosi float %b to i8 + %4 = select i1 %1, i8 %3, i8 %2 + ret i8 %4 +} + +; CHECK-LABEL: @t12 +; CHECK-NEXT: fcmp nnan oge float %b, %a +; CHECK-NEXT: select i1 %.inv, float %a, float %b +; CHECK-NEXT: fptosi float %.v to i8 +define i8 @t12(float %a, float %b) { + ; Either operand could be NaN, but nnan modifier applied. + %1 = fcmp nnan ult float %b, %a + %2 = fptosi float %a to i8 + %3 = fptosi float %b to i8 + %4 = select i1 %1, i8 %3, i8 %2 + ret i8 %4 +} + +; CHECK-LABEL: @t13 +; CHECK-NEXT: fcmp ult float %a, 1.500000e+00 +; CHECK-NEXT: fptosi float %a to i8 +; CHECK-NEXT: select i1 %1, i8 %2, i8 1 +define i8 @t13(float %a) { + ; Float and int values do not match. + %1 = fcmp ult float %a, 1.5 + %2 = fptosi float %a to i8 + %3 = select i1 %1, i8 %2, i8 1 + ret i8 %3 +} + +; CHECK-LABEL: @t14 +; CHECK-NEXT: fcmp ule float %a, 0.000000e+00 +; CHECK-NEXT: fptosi float %a to i8 +; CHECK-NEXT: select i1 %1, i8 %2, i8 0 +define i8 @t14(float %a) { + ; <= comparison, where %a could be -0.0. Not safe. + %1 = fcmp ule float %a, 0.0 + %2 = fptosi float %a to i8 + %3 = select i1 %1, i8 %2, i8 0 + ret i8 %3 +} + +; CHECK-LABEL: @t15 +; CHECK-NEXT: fcmp nsz oge float %a, 0.000000e+00 +; CHECK-NEXT: select i1 %.inv, float 0.000000e+00, float %a +; CHECK-NEXT: fptosi float %1 to i8 +define i8 @t15(float %a) { + %1 = fcmp nsz ule float %a, 0.0 + %2 = fptosi float %a to i8 + %3 = select i1 %1, i8 %2, i8 0 + ret i8 %3 +} diff --git a/test/Transforms/InstCombine/neon-intrinsics.ll b/test/Transforms/InstCombine/neon-intrinsics.ll index 3ad09cc6c694..d22fa9c811dc 100644 --- a/test/Transforms/InstCombine/neon-intrinsics.ll +++ b/test/Transforms/InstCombine/neon-intrinsics.ll @@ -3,8 +3,8 @@ ; The alignment arguments for NEON load/store intrinsics can be increased ; by instcombine. Check for this. -; CHECK: vld4.v2i32({{.*}}, i32 32) -; CHECK: vst4.v2i32({{.*}}, i32 16) +; CHECK: vld4.v2i32.p0i8({{.*}}, i32 32) +; CHECK: vst4.p0i8.v2i32({{.*}}, i32 16) @x = common global [8 x i32] zeroinitializer, align 32 @y = common global [8 x i32] zeroinitializer, align 16 @@ -12,14 +12,14 @@ %struct.__neon_int32x2x4_t = type { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } define void @test() nounwind ssp { - %tmp1 = call %struct.__neon_int32x2x4_t @llvm.arm.neon.vld4.v2i32(i8* bitcast ([8 x i32]* @x to i8*), i32 1) + %tmp1 = call %struct.__neon_int32x2x4_t @llvm.arm.neon.vld4.v2i32.p0i8(i8* bitcast ([8 x i32]* @x to i8*), i32 1) %tmp2 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 0 %tmp3 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 1 %tmp4 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 2 %tmp5 = extractvalue %struct.__neon_int32x2x4_t %tmp1, 3 - call void @llvm.arm.neon.vst4.v2i32(i8* bitcast ([8 x i32]* @y to i8*), <2 x i32> %tmp2, <2 x i32> %tmp3, <2 x i32> %tmp4, <2 x i32> %tmp5, i32 1) + call void @llvm.arm.neon.vst4.p0i8.v2i32(i8* bitcast ([8 x i32]* @y to i8*), <2 x i32> %tmp2, <2 x i32> %tmp3, <2 x i32> %tmp4, <2 x i32> %tmp5, i32 1) ret void } -declare %struct.__neon_int32x2x4_t @llvm.arm.neon.vld4.v2i32(i8*, i32) nounwind readonly -declare void @llvm.arm.neon.vst4.v2i32(i8*, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>, i32) nounwind +declare %struct.__neon_int32x2x4_t @llvm.arm.neon.vld4.v2i32.p0i8(i8*, i32) nounwind readonly +declare void @llvm.arm.neon.vst4.p0i8.v2i32(i8*, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>, i32) nounwind diff --git a/test/Transforms/InstCombine/no_cgscc_assert.ll b/test/Transforms/InstCombine/no_cgscc_assert.ll index cec5297695b1..3df04d2c8902 100644 --- a/test/Transforms/InstCombine/no_cgscc_assert.ll +++ b/test/Transforms/InstCombine/no_cgscc_assert.ll @@ -10,7 +10,7 @@ define float @bar(float %f) #0 { ret float %call1 ; CHECK-LABEL: @bar( -; CHECK-NEXT: call float @llvm.fabs.f32 +; CHECK-NEXT: call fast float @llvm.fabs.f32 ; CHECK-NEXT: ret float } diff --git a/test/Transforms/InstCombine/nonnull-attribute.ll b/test/Transforms/InstCombine/nonnull-attribute.ll new file mode 100644 index 000000000000..74fb09114927 --- /dev/null +++ b/test/Transforms/InstCombine/nonnull-attribute.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; This test makes sure that we do not assume globals in address spaces other +; than 0 are able to be null. + +@as0 = external global i32 +@as1 = external addrspace(1) global i32 + +declare void @addrspace0(i32*) +declare void @addrspace1(i32 addrspace(1)*) + +; CHECK: call void @addrspace0(i32* nonnull @as0) +; CHECK: call void @addrspace1(i32 addrspace(1)* @as1) + +define void @test() { + call void @addrspace0(i32* @as0) + call void @addrspace1(i32 addrspace(1)* @as1) + ret void +} diff --git a/test/Transforms/InstCombine/not.ll b/test/Transforms/InstCombine/not.ll index 9d59edd7934d..edb402a125ac 100644 --- a/test/Transforms/InstCombine/not.ll +++ b/test/Transforms/InstCombine/not.ll @@ -5,51 +5,51 @@ ; CHECK-NOT: xor define i32 @test1(i32 %A) { - %B = xor i32 %A, -1 ; <i32> [#uses=1] - %C = xor i32 %B, -1 ; <i32> [#uses=1] + %B = xor i32 %A, -1 + %C = xor i32 %B, -1 ret i32 %C } define i1 @test2(i32 %A, i32 %B) { ; Can change into setge - %cond = icmp sle i32 %A, %B ; <i1> [#uses=1] - %Ret = xor i1 %cond, true ; <i1> [#uses=1] + %cond = icmp sle i32 %A, %B + %Ret = xor i1 %cond, true ret i1 %Ret } -; Test that demorgans law can be instcombined +; Test that De Morgan's law can be instcombined. define i32 @test3(i32 %A, i32 %B) { - %a = xor i32 %A, -1 ; <i32> [#uses=1] - %b = xor i32 %B, -1 ; <i32> [#uses=1] - %c = and i32 %a, %b ; <i32> [#uses=1] - %d = xor i32 %c, -1 ; <i32> [#uses=1] + %a = xor i32 %A, -1 + %b = xor i32 %B, -1 + %c = and i32 %a, %b + %d = xor i32 %c, -1 ret i32 %d } -; Test that demorgens law can work with constants +; Test that De Morgan's law can work with constants. define i32 @test4(i32 %A, i32 %B) { - %a = xor i32 %A, -1 ; <i32> [#uses=1] - %c = and i32 %a, 5 ; <i32> [#uses=1] - %d = xor i32 %c, -1 ; <i32> [#uses=1] + %a = xor i32 %A, -1 + %c = and i32 %a, 5 + %d = xor i32 %c, -1 ret i32 %d } -; test the mirror of demorgans law... +; Test the mirror of De Morgan's law. define i32 @test5(i32 %A, i32 %B) { - %a = xor i32 %A, -1 ; <i32> [#uses=1] - %b = xor i32 %B, -1 ; <i32> [#uses=1] - %c = or i32 %a, %b ; <i32> [#uses=1] - %d = xor i32 %c, -1 ; <i32> [#uses=1] + %a = xor i32 %A, -1 + %b = xor i32 %B, -1 + %c = or i32 %a, %b + %d = xor i32 %c, -1 ret i32 %d } ; PR2298 -define zeroext i8 @test6(i32 %a, i32 %b) nounwind { +define zeroext i8 @test6(i32 %a, i32 %b) { entry: - %tmp1not = xor i32 %a, -1 ; <i32> [#uses=1] - %tmp2not = xor i32 %b, -1 ; <i32> [#uses=1] - %tmp3 = icmp slt i32 %tmp1not, %tmp2not ; <i1> [#uses=1] - %retval67 = zext i1 %tmp3 to i8 ; <i8> [#uses=1] + %tmp1not = xor i32 %a, -1 + %tmp2not = xor i32 %b, -1 + %tmp3 = icmp slt i32 %tmp1not, %tmp2not + %retval67 = zext i1 %tmp3 to i8 ret i8 %retval67 } @@ -58,3 +58,4 @@ define <2 x i1> @test7(<2 x i32> %A, <2 x i32> %B) { %Ret = xor <2 x i1> %cond, <i1 true, i1 true> ret <2 x i1> %Ret } + diff --git a/test/Transforms/InstCombine/objsize-address-space.ll b/test/Transforms/InstCombine/objsize-address-space.ll index 6046dad89790..ab4b64dfbf07 100644 --- a/test/Transforms/InstCombine/objsize-address-space.ll +++ b/test/Transforms/InstCombine/objsize-address-space.ll @@ -32,7 +32,7 @@ define i16 @foo_as3_i16() nounwind { ret i16 %1 } -@a_alias = weak alias [60 x i8] addrspace(3)* @a_as3 +@a_alias = weak alias [60 x i8], [60 x i8] addrspace(3)* @a_as3 define i32 @foo_alias() nounwind { %1 = call i32 @llvm.objectsize.i32.p3i8(i8 addrspace(3)* getelementptr inbounds ([60 x i8], [60 x i8] addrspace(3)* @a_alias, i32 0, i32 0), i1 false) ret i32 %1 diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index 335a816e9ece..2af391f907cc 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -219,7 +219,7 @@ define i32 @test13(i8** %esc) { ret i32 %1 } -@globalalias = internal alias [60 x i8]* @a +@globalalias = internal alias [60 x i8], [60 x i8]* @a ; CHECK-LABEL: @test18( ; CHECK-NEXT: ret i32 60 @@ -229,7 +229,7 @@ define i32 @test18() { ret i32 %1 } -@globalalias2 = weak alias [60 x i8]* @a +@globalalias2 = weak alias [60 x i8], [60 x i8]* @a ; CHECK-LABEL: @test19( ; CHECK: llvm.objectsize diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index b91a5954d97e..a2bc4e7d9832 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -182,7 +182,7 @@ define i1 @test19(i32 %A) { %D = or i1 %B, %C ret i1 %D ; CHECK-LABEL: @test19( -; CHECK: and i32 +; CHECK: or i32 ; CHECK: icmp eq ; CHECK: ret i1 } diff --git a/test/Transforms/InstCombine/phi-load-metadata-2.ll b/test/Transforms/InstCombine/phi-load-metadata-2.ll new file mode 100644 index 000000000000..cfbf2dea8a7a --- /dev/null +++ b/test/Transforms/InstCombine/phi-load-metadata-2.ll @@ -0,0 +1,30 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +declare void @bar() +declare void @baz() + +; Check that dereferenceable metadata is combined +; CHECK-LABEL: cont: +; CHECK: load i32*, i32** +; CHECK-SAME: !dereferenceable ![[DEREF:[0-9]+]] +define i32* @test_phi_combine_load_metadata(i1 %c, i32** dereferenceable(8) %p1, i32** dereferenceable(8) %p2) { + br i1 %c, label %t, label %f +t: + call void @bar() + %v1 = load i32*, i32** %p1, align 8, !dereferenceable !0 + br label %cont + +f: + call void @baz() + %v2 = load i32*, i32** %p2, align 8, !dereferenceable !1 + br label %cont + +cont: + %res = phi i32* [ %v1, %t ], [ %v2, %f ] + ret i32* %res +} + +; CHECK: ![[DEREF]] = !{i64 8} + +!0 = !{i64 8} +!1 = !{i64 16} diff --git a/test/Transforms/InstCombine/phi-load-metadata-3.ll b/test/Transforms/InstCombine/phi-load-metadata-3.ll new file mode 100644 index 000000000000..39049c9c7181 --- /dev/null +++ b/test/Transforms/InstCombine/phi-load-metadata-3.ll @@ -0,0 +1,30 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +declare void @bar() +declare void @baz() + +; Check that dereferenceable_or_null metadata is combined +; CHECK-LABEL: cont: +; CHECK: load i32*, i32** +; CHECK-SAME: !dereferenceable_or_null ![[DEREF:[0-9]+]] +define i32* @test_phi_combine_load_metadata(i1 %c, i32** dereferenceable(8) %p1, i32** dereferenceable(8) %p2) { + br i1 %c, label %t, label %f +t: + call void @bar() + %v1 = load i32*, i32** %p1, align 8, !dereferenceable_or_null !0 + br label %cont + +f: + call void @baz() + %v2 = load i32*, i32** %p2, align 8, !dereferenceable_or_null !1 + br label %cont + +cont: + %res = phi i32* [ %v1, %t ], [ %v2, %f ] + ret i32* %res +} + +; CHECK: ![[DEREF]] = !{i64 8} + +!0 = !{i64 8} +!1 = !{i64 16} diff --git a/test/Transforms/InstCombine/phi-load-metadata.ll b/test/Transforms/InstCombine/phi-load-metadata.ll new file mode 100644 index 000000000000..004a355ca441 --- /dev/null +++ b/test/Transforms/InstCombine/phi-load-metadata.ll @@ -0,0 +1,30 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +declare void @bar() +declare void @baz() + +; Check that align metadata is combined +; CHECK-LABEL: cont: +; CHECK: load i32*, i32** +; CHECK-SAME: !align ![[ALIGN:[0-9]+]] +define i32* @test_phi_combine_load_metadata(i1 %c, i32** dereferenceable(8) %p1, i32** dereferenceable(8) %p2) { + br i1 %c, label %t, label %f +t: + call void @bar() + %v1 = load i32*, i32** %p1, align 8, !align !0 + br label %cont + +f: + call void @baz() + %v2 = load i32*, i32** %p2, align 8, !align !1 + br label %cont + +cont: + %res = phi i32* [ %v1, %t ], [ %v2, %f ] + ret i32* %res +} + +; CHECK: ![[ALIGN]] = !{i64 8} + +!0 = !{i64 8} +!1 = !{i64 16} diff --git a/test/Transforms/InstCombine/phi.ll b/test/Transforms/InstCombine/phi.ll index 54cc4cfe4594..d0441d76d399 100644 --- a/test/Transforms/InstCombine/phi.ll +++ b/test/Transforms/InstCombine/phi.ll @@ -630,3 +630,133 @@ done: %y = phi i32 [ undef, %entry ] ret i32 %y } + +; We should be able to fold the zexts to the other side of the phi +; even though there's a constant value input to the phi. This is +; because we can shrink that constant to the smaller phi type. + +define i1 @PR24766(i8 %x1, i8 %x2, i8 %condition) { +entry: + %conv = sext i8 %condition to i32 + switch i32 %conv, label %epilog [ + i32 0, label %sw1 + i32 1, label %sw2 + ] + +sw1: + %cmp1 = icmp eq i8 %x1, %x2 + %frombool1 = zext i1 %cmp1 to i8 + br label %epilog + +sw2: + %cmp2 = icmp sle i8 %x1, %x2 + %frombool2 = zext i1 %cmp2 to i8 + br label %epilog + +epilog: + %conditionMet = phi i8 [ 0, %entry ], [ %frombool2, %sw2 ], [ %frombool1, %sw1 ] + %tobool = icmp ne i8 %conditionMet, 0 + ret i1 %tobool + +; CHECK-LABEL: @PR24766( +; CHECK: %[[RES:.*]] = phi i1 [ false, %entry ], [ %cmp2, %sw2 ], [ %cmp1, %sw1 ] +; CHECK-NEXT: ret i1 %[[RES]] +} + +; Same as above (a phi with more than 2 operands), but no constants + +define i1 @PR24766_no_constants(i8 %x1, i8 %x2, i8 %condition, i1 %another_condition) { +entry: + %frombool0 = zext i1 %another_condition to i8 + %conv = sext i8 %condition to i32 + switch i32 %conv, label %epilog [ + i32 0, label %sw1 + i32 1, label %sw2 + ] + +sw1: + %cmp1 = icmp eq i8 %x1, %x2 + %frombool1 = zext i1 %cmp1 to i8 + br label %epilog + +sw2: + %cmp2 = icmp sle i8 %x1, %x2 + %frombool2 = zext i1 %cmp2 to i8 + br label %epilog + +epilog: + %conditionMet = phi i8 [ %frombool0, %entry ], [ %frombool2, %sw2 ], [ %frombool1, %sw1 ] + %tobool = icmp ne i8 %conditionMet, 0 + ret i1 %tobool + +; CHECK-LABEL: @PR24766_no_constants( +; CHECK: %[[RES:.*]] = phi i1 [ %another_condition, %entry ], [ %cmp2, %sw2 ], [ %cmp1, %sw1 ] +; CHECK-NEXT: ret i1 %[[RES]] +} + +; Same as above (a phi with more than 2 operands), but two constants + +define i1 @PR24766_two_constants(i8 %x1, i8 %x2, i8 %condition) { +entry: + %conv = sext i8 %condition to i32 + switch i32 %conv, label %epilog [ + i32 0, label %sw1 + i32 1, label %sw2 + ] + +sw1: + %cmp1 = icmp eq i8 %x1, %x2 + %frombool1 = zext i1 %cmp1 to i8 + br label %epilog + +sw2: + %cmp2 = icmp sle i8 %x1, %x2 + %frombool2 = zext i1 %cmp2 to i8 + br label %epilog + +epilog: + %conditionMet = phi i8 [ 0, %entry ], [ 1, %sw2 ], [ %frombool1, %sw1 ] + %tobool = icmp ne i8 %conditionMet, 0 + ret i1 %tobool + +; CHECK-LABEL: @PR24766_two_constants( +; CHECK: %[[RES:.*]] = phi i1 [ false, %entry ], [ true, %sw2 ], [ %cmp1, %sw1 ] +; CHECK-NEXT: ret i1 %[[RES]] +} + +; Same as above (a phi with more than 2 operands), but two constants and two variables + +define i1 @PR24766_two_constants_two_var(i8 %x1, i8 %x2, i8 %condition) { +entry: + %conv = sext i8 %condition to i32 + switch i32 %conv, label %epilog [ + i32 0, label %sw1 + i32 1, label %sw2 + i32 2, label %sw3 + ] + +sw1: + %cmp1 = icmp eq i8 %x1, %x2 + %frombool1 = zext i1 %cmp1 to i8 + br label %epilog + +sw2: + %cmp2 = icmp sle i8 %x1, %x2 + %frombool2 = zext i1 %cmp2 to i8 + br label %epilog + +sw3: + %cmp3 = icmp sge i8 %x1, %x2 + %frombool3 = zext i1 %cmp3 to i8 + br label %epilog + +epilog: + %conditionMet = phi i8 [ 0, %entry ], [ %frombool2, %sw2 ], [ %frombool1, %sw1 ], [ 1, %sw3 ] + %tobool = icmp ne i8 %conditionMet, 0 + ret i1 %tobool + +; CHECK-LABEL: @PR24766_two_constants_two_var( +; CHECK: %[[RES:.*]] = phi i1 [ false, %entry ], [ %cmp2, %sw2 ], [ %cmp1, %sw1 ], [ true, %sw3 ] +; CHECK-NEXT: ret i1 %[[RES]] +} + diff --git a/test/Transforms/InstCombine/pow-1.ll b/test/Transforms/InstCombine/pow-1.ll index fb3b7d796160..f2b56fd33d64 100644 --- a/test/Transforms/InstCombine/pow-1.ll +++ b/test/Transforms/InstCombine/pow-1.ll @@ -6,6 +6,8 @@ ; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefix=CHECK-NO-EXP10 ; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefix=CHECK-NO-EXP10 ; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefix=CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefix=CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefix=CHECK-EXP10 ; rdar://7251832 ; NOTE: The readonly attribute on the pow call should be preserved diff --git a/test/Transforms/InstCombine/pow-4.ll b/test/Transforms/InstCombine/pow-4.ll new file mode 100644 index 000000000000..76ef4c5de923 --- /dev/null +++ b/test/Transforms/InstCombine/pow-4.ll @@ -0,0 +1,120 @@ +; Test that the pow library call simplifier works correctly. + +; RUN: opt -instcombine -S < %s | FileCheck %s + +; Function Attrs: nounwind readnone +declare double @llvm.pow.f64(double, double) +declare float @llvm.pow.f32(float, float) + +; pow(x, 4.0f) +define float @test_simplify_4f(float %x) #0 { +; CHECK-LABEL: @test_simplify_4f( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul float %x, %x +; CHECK-NEXT: %2 = fmul float %1, %1 +; CHECK-NEXT: ret float %2 + %1 = call float @llvm.pow.f32(float %x, float 4.000000e+00) + ret float %1 +} + +; pow(x, 3.0) +define double @test_simplify_3(double %x) #0 { +; CHECK-LABEL: @test_simplify_3( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul double %x, %x +; CHECK-NEXT: %2 = fmul double %1, %x +; CHECK-NEXT: ret double %2 + %1 = call double @llvm.pow.f64(double %x, double 3.000000e+00) + ret double %1 +} + +; pow(x, 4.0) +define double @test_simplify_4(double %x) #0 { +; CHECK-LABEL: @test_simplify_4( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul double %x, %x +; CHECK-NEXT: %2 = fmul double %1, %1 +; CHECK-NEXT: ret double %2 + %1 = call double @llvm.pow.f64(double %x, double 4.000000e+00) + ret double %1 +} + +; pow(x, 15.0) +define double @test_simplify_15(double %x) #0 { +; CHECK-LABEL: @test_simplify_15( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul double %x, %x +; CHECK-NEXT: %2 = fmul double %1, %x +; CHECK-NEXT: %3 = fmul double %2, %2 +; CHECK-NEXT: %4 = fmul double %3, %3 +; CHECK-NEXT: %5 = fmul double %2, %4 +; CHECK-NEXT: ret double %5 + %1 = call double @llvm.pow.f64(double %x, double 1.500000e+01) + ret double %1 +} + +; pow(x, -7.0) +define double @test_simplify_neg_7(double %x) #0 { +; CHECK-LABEL: @test_simplify_neg_7( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul double %x, %x +; CHECK-NEXT: %2 = fmul double %1, %x +; CHECK-NEXT: %3 = fmul double %1, %2 +; CHECK-NEXT: %4 = fmul double %1, %3 +; CHECK-NEXT: %5 = fdiv double 1.000000e+00, %4 +; CHECK-NEXT: ret double %5 + %1 = call double @llvm.pow.f64(double %x, double -7.000000e+00) + ret double %1 +} + +; pow(x, -19.0) +define double @test_simplify_neg_19(double %x) #0 { +; CHECK-LABEL: @test_simplify_neg_19( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul double %x, %x +; CHECK-NEXT: %2 = fmul double %1, %1 +; CHECK-NEXT: %3 = fmul double %2, %2 +; CHECK-NEXT: %4 = fmul double %3, %3 +; CHECK-NEXT: %5 = fmul double %1, %4 +; CHECK-NEXT: %6 = fmul double %5, %x +; CHECK-NEXT: %7 = fdiv double 1.000000e+00, %6 +; CHECK-NEXT: ret double %7 + %1 = call double @llvm.pow.f64(double %x, double -1.900000e+01) + ret double %1 +} + +; pow(x, 11.23) +define double @test_simplify_11_23(double %x) #0 { +; CHECK-LABEL: @test_simplify_11_23( +; CHECK-NOT: fmul +; CHECK-NEXT: %1 = call double @llvm.pow.f64(double %x, double 1.123000e+01) +; CHECK-NEXT: ret double %1 + %1 = call double @llvm.pow.f64(double %x, double 1.123000e+01) + ret double %1 +} + +; pow(x, 32.0) +define double @test_simplify_32(double %x) #0 { +; CHECK-LABEL: @test_simplify_32( +; CHECK-NOT: pow +; CHECK-NEXT: %1 = fmul double %x, %x +; CHECK-NEXT: %2 = fmul double %1, %1 +; CHECK-NEXT: %3 = fmul double %2, %2 +; CHECK-NEXT: %4 = fmul double %3, %3 +; CHECK-NEXT: %5 = fmul double %4, %4 +; CHECK-NEXT: ret double %5 + %1 = call double @llvm.pow.f64(double %x, double 3.200000e+01) + ret double %1 +} + +; pow(x, 33.0) +define double @test_simplify_33(double %x) #0 { +; CHECK-LABEL: @test_simplify_33( +; CHECK-NOT: fmul +; CHECK-NEXT: %1 = call double @llvm.pow.f64(double %x, double 3.300000e+01) +; CHECK-NEXT: ret double %1 + %1 = call double @llvm.pow.f64(double %x, double 3.300000e+01) + ret double %1 +} + +attributes #0 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon" "unsafe-fp-math"="true" "use-soft-float"="false" } diff --git a/test/Transforms/InstCombine/pow-exp-nofastmath.ll b/test/Transforms/InstCombine/pow-exp-nofastmath.ll new file mode 100644 index 000000000000..9e596fa3a723 --- /dev/null +++ b/test/Transforms/InstCombine/pow-exp-nofastmath.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @mypow(double %x, double %y) #0 { +entry: + %call = call double @exp(double %x) + %pow = call double @llvm.pow.f64(double %call, double %y) + ret double %pow +} + +; CHECK-LABEL: define double @mypow( +; CHECK: %call = call double @exp(double %x) +; CHECK: %pow = call double @llvm.pow.f64(double %call, double %y) +; CHECK: ret double %pow +; CHECK: } + +declare double @exp(double) #1 +declare double @llvm.pow.f64(double, double) diff --git a/test/Transforms/InstCombine/pow-exp.ll b/test/Transforms/InstCombine/pow-exp.ll new file mode 100644 index 000000000000..acc512734ec5 --- /dev/null +++ b/test/Transforms/InstCombine/pow-exp.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @mypow(double %x, double %y) #0 { +entry: + %call = call double @exp(double %x) + %pow = call double @llvm.pow.f64(double %call, double %y) + ret double %pow +} + +; CHECK-LABEL: define double @mypow( +; CHECK: %mul = fmul fast double %x, %y +; CHECK: %exp = call fast double @exp(double %mul) #0 +; CHECK: ret double %exp +; CHECK: } + +define double @test2(double ()* %fptr, double %p1) #0 { + %call1 = call double %fptr() + %pow = call double @llvm.pow.f64(double %call1, double %p1) + ret double %pow +} + +; CHECK-LABEL: @test2 +; CHECK: llvm.pow.f64 + +declare double @exp(double) #1 +declare double @llvm.pow.f64(double, double) +attributes #0 = { "unsafe-fp-math"="true" } +attributes #1 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/pow-exp2.ll b/test/Transforms/InstCombine/pow-exp2.ll new file mode 100644 index 000000000000..c42cab391e64 --- /dev/null +++ b/test/Transforms/InstCombine/pow-exp2.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @mypow(double %x, double %y) #0 { +entry: + %call = call double @exp2(double %x) + %pow = call double @llvm.pow.f64(double %call, double %y) + ret double %pow +} + +; CHECK-LABEL: define double @mypow( +; CHECK: %mul = fmul fast double %x, %y +; CHECK: %exp2 = call fast double @exp2(double %mul) #0 +; CHECK: ret double %exp2 +; CHECK: } + +declare double @exp2(double) #1 +declare double @llvm.pow.f64(double, double) +attributes #0 = { "unsafe-fp-math"="true" } +attributes #1 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/pow-sqrt.ll b/test/Transforms/InstCombine/pow-sqrt.ll new file mode 100644 index 000000000000..8fc74e4a0024 --- /dev/null +++ b/test/Transforms/InstCombine/pow-sqrt.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @mypow(double %x) #0 { +entry: + %pow = call double @llvm.pow.f64(double %x, double 5.000000e-01) + ret double %pow +} + +; CHECK-LABEL: define double @mypow( +; CHECK: %sqrt = call double @sqrt(double %x) #1 +; CHECK: ret double %sqrt +; CHECK: } + +declare double @llvm.pow.f64(double, double) +attributes #0 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/pr20059.ll b/test/Transforms/InstCombine/pr20059.ll deleted file mode 100644 index 0ef315936ff2..000000000000 --- a/test/Transforms/InstCombine/pr20059.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: opt -S -instcombine < %s | FileCheck %s - -; In PR20059 ( http://llvm.org/pr20059 ), shufflevector operations are reordered/removed -; for an srem operation. This is not a valid optimization because it may cause a trap -; on div-by-zero. - -; CHECK-LABEL: @do_not_reorder -; CHECK: %splat1 = shufflevector <4 x i32> %p1, <4 x i32> undef, <4 x i32> zeroinitializer -; CHECK-NEXT: %splat2 = shufflevector <4 x i32> %p2, <4 x i32> undef, <4 x i32> zeroinitializer -; CHECK-NEXT: %retval = srem <4 x i32> %splat1, %splat2 -define <4 x i32> @do_not_reorder(<4 x i32> %p1, <4 x i32> %p2) { - %splat1 = shufflevector <4 x i32> %p1, <4 x i32> undef, <4 x i32> zeroinitializer - %splat2 = shufflevector <4 x i32> %p2, <4 x i32> undef, <4 x i32> zeroinitializer - %retval = srem <4 x i32> %splat1, %splat2 - ret <4 x i32> %retval -} diff --git a/test/Transforms/InstCombine/pr24605.ll b/test/Transforms/InstCombine/pr24605.ll new file mode 100644 index 000000000000..4b7b36137e6a --- /dev/null +++ b/test/Transforms/InstCombine/pr24605.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i1 @f(i8* %a, i8 %b) { +; CHECK-LABEL: @f( +entry: + %or = or i8 %b, -117 + %sub = add i8 %or, -1 + store i8 %sub, i8* %a, align 1 + %cmp = icmp ugt i8 %or, %sub + ret i1 %cmp +; CHECK: ret i1 true +} diff --git a/test/Transforms/InstCombine/pr25745.ll b/test/Transforms/InstCombine/pr25745.ll new file mode 100644 index 000000000000..3bf9efc92b90 --- /dev/null +++ b/test/Transforms/InstCombine/pr25745.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +; Checking for a crash + +declare void @use.i1(i1 %val) +declare void @use.i64(i64 %val) + +define i64 @f(i32 %x) { +; CHECK-LABEL: @f( + entry: + %x.wide = sext i32 %x to i64 + %minus.x = sub i32 0, %x + %minus.x.wide = sext i32 %minus.x to i64 + %c = icmp slt i32 %x, 0 + %val = select i1 %c, i64 %x.wide, i64 %minus.x.wide + call void @use.i1(i1 %c) + call void @use.i64(i64 %x.wide) + ret i64 %val +; CHECK: ret i64 %val +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index 79c2ae28105e..0b5b5deb68c5 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -575,7 +575,7 @@ entry: ; CHECK: %0 = shl i8 %tmp4, 2 ; CHECK: %tmp54 = and i8 %0, 16 %tmp55 = xor i8 %tmp54, %tmp51 -; CHECK: ret i8 %tmp55.1 +; CHECK: ret i8 %tmp551 ret i8 %tmp55 } @@ -743,7 +743,7 @@ define i32 @test57(i32 %x) { %or = or i32 %shl, 7 ret i32 %or ; CHECK-LABEL: @test57( -; CHECK: %shl = shl i32 %shr.1, 4 +; CHECK: %shl = shl i32 %shr1, 4 } diff --git a/test/Transforms/InstCombine/sincospi.ll b/test/Transforms/InstCombine/sincospi.ll index f49fb35cb76a..10342c500961 100644 --- a/test/Transforms/InstCombine/sincospi.ll +++ b/test/Transforms/InstCombine/sincospi.ll @@ -90,3 +90,12 @@ define double @test_constant_f64() { ; CHECK-NO-SINCOS: call double @__sinpi ; CHECK-NO-SINCOS: call double @__cospi } + +define double @test_fptr(double (double)* %fptr, double %p1) { + %sin = call double @__sinpi(double %p1) #0 + %cos = call double %fptr(double %p1) + %res = fadd double %sin, %cos + ret double %res +; CHECK-LABEL: @test_fptr +; CHECK: __sinpi +} diff --git a/test/Transforms/InstCombine/sqrt-nofast.ll b/test/Transforms/InstCombine/sqrt-nofast.ll new file mode 100644 index 000000000000..0d1dfc1542a5 --- /dev/null +++ b/test/Transforms/InstCombine/sqrt-nofast.ll @@ -0,0 +1,25 @@ +; Check that we skip transformations if the attribute unsafe-fp-math +; is not set. +; RUN: opt < %s -instcombine -S | FileCheck %s + +define float @mysqrt(float %x, float %y) #0 { +entry: + %x.addr = alloca float, align 4 + %y.addr = alloca float, align 4 + store float %x, float* %x.addr, align 4 + store float %y, float* %y.addr, align 4 + %0 = load float, float* %x.addr, align 4 + %1 = load float, float* %x.addr, align 4 + %mul = fmul fast float %0, %1 + %2 = call float @llvm.sqrt.f32(float %mul) + ret float %2 +} + +declare float @llvm.sqrt.f32(float) #1 + +; CHECK: define float @mysqrt(float %x, float %y) { +; CHECK: entry: +; CHECK: %mul = fmul fast float %x, %x +; CHECK: %0 = call float @llvm.sqrt.f32(float %mul) +; CHECK: ret float %0 +; CHECK: } diff --git a/test/Transforms/InstCombine/statepoint.ll b/test/Transforms/InstCombine/statepoint.ll index f904f207bfdc..54fb6a7756ff 100644 --- a/test/Transforms/InstCombine/statepoint.ll +++ b/test/Transforms/InstCombine/statepoint.ll @@ -7,8 +7,8 @@ declare void @func() define i1 @test_negative(i32 addrspace(1)* %p) gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7) + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 7, i32 7) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_negative @@ -18,8 +18,8 @@ entry: define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7) + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 7, i32 7) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_nonnull @@ -28,8 +28,8 @@ entry: define i1 @test_null() gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* null) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7) + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* null) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 7, i32 7) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_null @@ -39,8 +39,8 @@ entry: define i1 @test_undef() gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* undef) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7) + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* undef) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 7, i32 7) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_undef @@ -48,5 +48,5 @@ entry: ; CHECK: ret i1 undef } -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) -declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) #3 +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #3 diff --git a/test/Transforms/InstCombine/store.ll b/test/Transforms/InstCombine/store.ll index 5dfbd7140901..b8730413f1b5 100644 --- a/test/Transforms/InstCombine/store.ll +++ b/test/Transforms/InstCombine/store.ll @@ -113,6 +113,119 @@ for.end: ; preds = %for.cond ; CHECK-NEXT: store i32 %storemerge, i32* %gi, align 4, !tbaa !0 } +define void @dse1(i32* %p) { +; CHECK-LABEL: dse1 +; CHECK-NEXT: store +; CHECK-NEXT: ret + store i32 0, i32* %p + store i32 0, i32* %p + ret void +} + +; Slightly subtle: if we're mixing atomic and non-atomic access to the +; same location, then the contents of the location are undefined if there's +; an actual race. As such, we're free to pick either store under the +; assumption that we're not racing with any other thread. +define void @dse2(i32* %p) { +; CHECK-LABEL: dse2 +; CHECK-NEXT: store i32 0, i32* %p +; CHECK-NEXT: ret + store atomic i32 0, i32* %p unordered, align 4 + store i32 0, i32* %p + ret void +} + +define void @dse3(i32* %p) { +; CHECK-LABEL: dse3 +; CHECK-NEXT: store atomic i32 0, i32* %p unordered, align 4 +; CHECK-NEXT: ret + store i32 0, i32* %p + store atomic i32 0, i32* %p unordered, align 4 + ret void +} + +define void @dse4(i32* %p) { +; CHECK-LABEL: dse4 +; CHECK-NEXT: store atomic i32 0, i32* %p unordered, align 4 +; CHECK-NEXT: ret + store atomic i32 0, i32* %p unordered, align 4 + store atomic i32 0, i32* %p unordered, align 4 + ret void +} + +; Implementation limit - could remove unordered store here, but +; currently don't. +define void @dse5(i32* %p) { +; CHECK-LABEL: dse5 +; CHECK-NEXT: store +; CHECK-NEXT: store +; CHECK-NEXT: ret + store atomic i32 0, i32* %p unordered, align 4 + store atomic i32 0, i32* %p seq_cst, align 4 + ret void +} + +define void @write_back1(i32* %p) { +; CHECK-LABEL: write_back1 +; CHECK-NEXT: ret + %v = load i32, i32* %p + store i32 %v, i32* %p + ret void +} + +define void @write_back2(i32* %p) { +; CHECK-LABEL: write_back2 +; CHECK-NEXT: ret + %v = load atomic i32, i32* %p unordered, align 4 + store i32 %v, i32* %p + ret void +} + +define void @write_back3(i32* %p) { +; CHECK-LABEL: write_back3 +; CHECK-NEXT: ret + %v = load i32, i32* %p + store atomic i32 %v, i32* %p unordered, align 4 + ret void +} + +define void @write_back4(i32* %p) { +; CHECK-LABEL: write_back4 +; CHECK-NEXT: ret + %v = load atomic i32, i32* %p unordered, align 4 + store atomic i32 %v, i32* %p unordered, align 4 + ret void +} + +; Can't remove store due to ordering side effect +define void @write_back5(i32* %p) { +; CHECK-LABEL: write_back5 +; CHECK-NEXT: load +; CHECK-NEXT: store +; CHECK-NEXT: ret + %v = load atomic i32, i32* %p unordered, align 4 + store atomic i32 %v, i32* %p seq_cst, align 4 + ret void +} + +define void @write_back6(i32* %p) { +; CHECK-LABEL: write_back6 +; CHECK-NEXT: load +; CHECK-NEXT: ret + %v = load atomic i32, i32* %p seq_cst, align 4 + store atomic i32 %v, i32* %p unordered, align 4 + ret void +} + +define void @write_back7(i32* %p) { +; CHECK-LABEL: write_back7 +; CHECK-NEXT: load +; CHECK-NEXT: ret + %v = load atomic volatile i32, i32* %p seq_cst, align 4 + store atomic i32 %v, i32* %p unordered, align 4 + ret void +} + !0 = !{!4, !4, i64 0} !1 = !{!"omnipotent char", !2} !2 = !{!"Simple C/C++ TBAA"} diff --git a/test/Transforms/InstCombine/strto-1.ll b/test/Transforms/InstCombine/strto-1.ll index fc35dddcae5a..96f36e8d89c7 100644 --- a/test/Transforms/InstCombine/strto-1.ll +++ b/test/Transforms/InstCombine/strto-1.ll @@ -1,6 +1,6 @@ ; Test that the strto* library call simplifiers works correctly. ; -; RUN: opt < %s -instcombine -functionattrs -S | FileCheck %s +; RUN: opt < %s -instcombine -inferattrs -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" diff --git a/test/Transforms/InstCombine/tan-nofastmath.ll b/test/Transforms/InstCombine/tan-nofastmath.ll new file mode 100644 index 000000000000..0fe7b2c1d522 --- /dev/null +++ b/test/Transforms/InstCombine/tan-nofastmath.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define float @mytan(float %x) { +entry: + %call = call float @atanf(float %x) + %call1 = call float @tanf(float %call) + ret float %call1 +} + +; CHECK-LABEL: define float @mytan( +; CHECK: %call = call float @atanf(float %x) +; CHECK-NEXT: %call1 = call float @tanf(float %call) +; CHECK-NEXT: ret float %call1 +; CHECK-NEXT: } + +declare float @tanf(float) +declare float @atanf(float) diff --git a/test/Transforms/InstCombine/tan.ll b/test/Transforms/InstCombine/tan.ll new file mode 100644 index 000000000000..15a832f253a9 --- /dev/null +++ b/test/Transforms/InstCombine/tan.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define float @mytan(float %x) #0 { +entry: + %call = call float @atanf(float %x) + %call1 = call float @tanf(float %call) + ret float %call1 +} + +; CHECK-LABEL: define float @mytan( +; CHECK: ret float %x + +define float @test2(float ()* %fptr) #0 { + %call1 = call float %fptr() + %tan = call float @tanf(float %call1) + ret float %tan +} + +; CHECK-LABEL: @test2 +; CHECK: tanf + +declare float @tanf(float) #0 +declare float @atanf(float) #0 +attributes #0 = { "unsafe-fp-math"="true" } diff --git a/test/Transforms/InstCombine/token.ll b/test/Transforms/InstCombine/token.ll new file mode 100644 index 000000000000..0929cf7ebee1 --- /dev/null +++ b/test/Transforms/InstCombine/token.ll @@ -0,0 +1,89 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc18.0.0" + +declare i32 @__CxxFrameHandler3(...) + +define void @test1() personality i32 (...)* @__CxxFrameHandler3 { +bb: + unreachable + +unreachable: + %cl = cleanuppad within none [] + cleanupret from %cl unwind to caller +} + +; CHECK-LABEL: define void @test1( +; CHECK: unreachable: +; CHECK: %cl = cleanuppad within none [] +; CHECK: cleanupret from %cl unwind to caller + +define void @test2(i8 %A, i8 %B) personality i32 (...)* @__CxxFrameHandler3 { +bb: + %X = zext i8 %A to i32 + invoke void @g(i32 0) + to label %cont + unwind label %catch + +cont: + %Y = zext i8 %B to i32 + invoke void @g(i32 0) + to label %unreachable + unwind label %catch + +catch: + %phi = phi i32 [ %X, %bb ], [ %Y, %cont ] + %cs = catchswitch within none [label %doit] unwind to caller + +doit: + %cl = catchpad within %cs [] + call void @g(i32 %phi) + unreachable + +unreachable: + unreachable +} + +; CHECK-LABEL: define void @test2( +; CHECK: %X = zext i8 %A to i32 +; CHECK: %Y = zext i8 %B to i32 +; CHECK: %phi = phi i32 [ %X, %bb ], [ %Y, %cont ] + +define void @test3(i8 %A, i8 %B) personality i32 (...)* @__CxxFrameHandler3 { +bb: + %X = zext i8 %A to i32 + invoke void @g(i32 0) + to label %cont + unwind label %catch + +cont: + %Y = zext i8 %B to i32 + invoke void @g(i32 0) + to label %cont2 + unwind label %catch + +cont2: + invoke void @g(i32 0) + to label %unreachable + unwind label %catch + +catch: + %phi = phi i32 [ %X, %bb ], [ %Y, %cont ], [ %Y, %cont2 ] + %cs = catchswitch within none [label %doit] unwind to caller + +doit: + %cl = catchpad within %cs [] + call void @g(i32 %phi) + unreachable + +unreachable: + unreachable +} + +; CHECK-LABEL: define void @test3( +; CHECK: %X = zext i8 %A to i32 +; CHECK: %Y = zext i8 %B to i32 +; CHECK: %phi = phi i32 [ %X, %bb ], [ %Y, %cont ], [ %Y, %cont2 ] + + +declare void @g(i32) diff --git a/test/Transforms/InstCombine/trunc.ll b/test/Transforms/InstCombine/trunc.ll index ee81cf8c3c5d..38f6b2804d63 100644 --- a/test/Transforms/InstCombine/trunc.ll +++ b/test/Transforms/InstCombine/trunc.ll @@ -118,3 +118,45 @@ define i8 @test10(i32 %X) { ; CHECK: and ; CHECK: ret } + +; PR25543 +; https://llvm.org/bugs/show_bug.cgi?id=25543 +; This is an extractelement. + +define i32 @trunc_bitcast1(<4 x i32> %v) { + %bc = bitcast <4 x i32> %v to i128 + %shr = lshr i128 %bc, 32 + %ext = trunc i128 %shr to i32 + ret i32 %ext + +; CHECK-LABEL: @trunc_bitcast1( +; CHECK-NEXT: %ext = extractelement <4 x i32> %v, i32 1 +; CHECK-NEXT: ret i32 %ext +} + +; A bitcast may still be required. + +define i32 @trunc_bitcast2(<2 x i64> %v) { + %bc = bitcast <2 x i64> %v to i128 + %shr = lshr i128 %bc, 64 + %ext = trunc i128 %shr to i32 + ret i32 %ext + +; CHECK-LABEL: @trunc_bitcast2( +; CHECK-NEXT: %bc1 = bitcast <2 x i64> %v to <4 x i32> +; CHECK-NEXT: %ext = extractelement <4 x i32> %bc1, i32 2 +; CHECK-NEXT: ret i32 %ext +} + +; The right shift is optional. + +define i32 @trunc_bitcast3(<4 x i32> %v) { + %bc = bitcast <4 x i32> %v to i128 + %ext = trunc i128 %bc to i32 + ret i32 %ext + +; CHECK-LABEL: @trunc_bitcast3( +; CHECK-NEXT: %ext = extractelement <4 x i32> %v, i32 0 +; CHECK-NEXT: ret i32 %ext +} + diff --git a/test/Transforms/InstCombine/unpack-fca.ll b/test/Transforms/InstCombine/unpack-fca.ll index 48bb157956aa..9b8d10457491 100644 --- a/test/Transforms/InstCombine/unpack-fca.ll +++ b/test/Transforms/InstCombine/unpack-fca.ll @@ -5,110 +5,134 @@ target triple = "x86_64-unknown-linux-gnu" %A__vtbl = type { i8*, i32 (%A*)* } %A = type { %A__vtbl* } +%B = type { i8*, i64 } @A__vtblZ = constant %A__vtbl { i8* null, i32 (%A*)* @A.foo } declare i32 @A.foo(%A* nocapture %this) -declare i8* @allocmemory(i64) - -define void @storeA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to %A* +define void @storeA(%A* %a.ptr) { ; CHECK-LABEL: storeA -; CHECK: store %A__vtbl* @A__vtblZ - store %A { %A__vtbl* @A__vtblZ }, %A* %1, align 8 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds %A, %A* %a.ptr, i64 0, i32 0 +; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: ret void + store %A { %A__vtbl* @A__vtblZ }, %A* %a.ptr, align 8 + ret void +} + +define void @storeB(%B* %b.ptr) { +; CHECK-LABEL: storeB +; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 0 +; CHECK-NEXT: store i8* null, i8** [[GEP1]], align 8 +; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 1 +; CHECK-NEXT: store i64 42, i64* [[GEP2]], align 8 +; CHECK-NEXT: ret void + store %B { i8* null, i64 42 }, %B* %b.ptr, align 8 ret void } -define void @storeStructOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to { %A }* +define void @storeStructOfA({ %A }* %sa.ptr) { ; CHECK-LABEL: storeStructOfA -; CHECK: store %A__vtbl* @A__vtblZ - store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %1, align 8 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds { %A }, { %A }* %sa.ptr, i64 0, i32 0, i32 0 +; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: ret void + store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %sa.ptr, align 8 ret void } -define void @storeArrayOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to [1 x %A]* +define void @storeArrayOfA([1 x %A]* %aa.ptr) { ; CHECK-LABEL: storeArrayOfA -; CHECK: store %A__vtbl* @A__vtblZ - store [1 x %A] [%A { %A__vtbl* @A__vtblZ }], [1 x %A]* %1, align 8 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds [1 x %A], [1 x %A]* %aa.ptr, i64 0, i64 0, i32 0 +; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: ret void + store [1 x %A] [%A { %A__vtbl* @A__vtblZ }], [1 x %A]* %aa.ptr, align 8 ret void } -define void @storeStructOfArrayOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to { [1 x %A] }* +define void @storeStructOfArrayOfA({ [1 x %A] }* %saa.ptr) { ; CHECK-LABEL: storeStructOfArrayOfA -; CHECK: store %A__vtbl* @A__vtblZ - store { [1 x %A] } { [1 x %A] [%A { %A__vtbl* @A__vtblZ }] }, { [1 x %A] }* %1, align 8 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds { [1 x %A] }, { [1 x %A] }* %saa.ptr, i64 0, i32 0, i64 0, i32 0 +; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: ret void + store { [1 x %A] } { [1 x %A] [%A { %A__vtbl* @A__vtblZ }] }, { [1 x %A] }* %saa.ptr, align 8 ret void } -define %A @loadA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to %A* +define %A @loadA(%A* %a.ptr) { ; CHECK-LABEL: loadA -; CHECK: load %A__vtbl*, -; CHECK: insertvalue %A undef, %A__vtbl* {{.*}}, 0 - %2 = load %A, %A* %1, align 8 - ret %A %2 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds %A, %A* %a.ptr, i64 0, i32 0 +; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: [[IV:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0 +; CHECK-NEXT: ret %A [[IV]] + %1 = load %A, %A* %a.ptr, align 8 + ret %A %1 } -define { %A } @loadStructOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to { %A }* +define %B @loadB(%B* %b.ptr) { +; CHECK-LABEL: loadB +; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 0 +; CHECK-NEXT: [[LOAD1:%[a-z0-9\.]+]] = load i8*, i8** [[GEP1]], align 8 +; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %B undef, i8* [[LOAD1]], 0 +; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 1 +; CHECK-NEXT: [[LOAD2:%[a-z0-9\.]+]] = load i64, i64* [[GEP2]], align 8 +; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue %B [[IV1]], i64 [[LOAD2]], 1 +; CHECK-NEXT: ret %B [[IV2]] + %1 = load %B, %B* %b.ptr, align 8 + ret %B %1 +} + +define { %A } @loadStructOfA({ %A }* %sa.ptr) { ; CHECK-LABEL: loadStructOfA -; CHECK: load %A__vtbl*, -; CHECK: insertvalue %A undef, %A__vtbl* {{.*}}, 0 -; CHECK: insertvalue { %A } undef, %A {{.*}}, 0 - %2 = load { %A }, { %A }* %1, align 8 - ret { %A } %2 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds { %A }, { %A }* %sa.ptr, i64 0, i32 0, i32 0 +; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0 +; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue { %A } undef, %A [[IV1]], 0 +; CHECK-NEXT: ret { %A } [[IV2]] + %1 = load { %A }, { %A }* %sa.ptr, align 8 + ret { %A } %1 } -define [1 x %A] @loadArrayOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to [1 x %A]* +define [1 x %A] @loadArrayOfA([1 x %A]* %aa.ptr) { ; CHECK-LABEL: loadArrayOfA -; CHECK: load %A__vtbl*, -; CHECK: insertvalue %A undef, %A__vtbl* {{.*}}, 0 -; CHECK: insertvalue [1 x %A] undef, %A {{.*}}, 0 - %2 = load [1 x %A], [1 x %A]* %1, align 8 - ret [1 x %A] %2 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds [1 x %A], [1 x %A]* %aa.ptr, i64 0, i64 0, i32 0 +; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0 +; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue [1 x %A] undef, %A [[IV1]], 0 +; CHECK-NEXT: ret [1 x %A] [[IV2]] + %1 = load [1 x %A], [1 x %A]* %aa.ptr, align 8 + ret [1 x %A] %1 } -define { [1 x %A] } @loadStructOfArrayOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to { [1 x %A] }* +define { [1 x %A] } @loadStructOfArrayOfA({ [1 x %A] }* %saa.ptr) { ; CHECK-LABEL: loadStructOfArrayOfA -; CHECK: load %A__vtbl*, -; CHECK: insertvalue %A undef, %A__vtbl* {{.*}}, 0 -; CHECK: insertvalue [1 x %A] undef, %A {{.*}}, 0 -; CHECK: insertvalue { [1 x %A] } undef, [1 x %A] {{.*}}, 0 - %2 = load { [1 x %A] }, { [1 x %A] }* %1, align 8 - ret { [1 x %A] } %2 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds { [1 x %A] }, { [1 x %A] }* %saa.ptr, i64 0, i32 0, i64 0, i32 0 +; CHECK-NEXT: [[LOAD:%[a-z0-9\.]+]] = load %A__vtbl*, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %A undef, %A__vtbl* [[LOAD]], 0 +; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue [1 x %A] undef, %A [[IV1]], 0 +; CHECK-NEXT: [[IV3:%[a-z0-9\.]+]] = insertvalue { [1 x %A] } undef, [1 x %A] [[IV2]], 0 +; CHECK-NEXT: ret { [1 x %A] } [[IV3]] + %1 = load { [1 x %A] }, { [1 x %A] }* %saa.ptr, align 8 + ret { [1 x %A] } %1 } -define { %A } @structOfA() { -body: - %0 = tail call i8* @allocmemory(i64 32) - %1 = bitcast i8* %0 to { %A }* +define { %A } @structOfA({ %A }* %sa.ptr) { ; CHECK-LABEL: structOfA -; CHECK: store %A__vtbl* @A__vtblZ - store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %1, align 8 - %2 = load { %A }, { %A }* %1, align 8 -; CHECK-NOT: load -; CHECK: ret { %A } { %A { %A__vtbl* @A__vtblZ } } - ret { %A } %2 +; CHECK-NEXT: [[GEP:%[a-z0-9\.]+]] = getelementptr inbounds { %A }, { %A }* %sa.ptr, i64 0, i32 0, i32 0 +; CHECK-NEXT: store %A__vtbl* @A__vtblZ, %A__vtbl** [[GEP]], align 8 +; CHECK-NEXT: ret { %A } { %A { %A__vtbl* @A__vtblZ } } + store { %A } { %A { %A__vtbl* @A__vtblZ } }, { %A }* %sa.ptr, align 8 + %1 = load { %A }, { %A }* %sa.ptr, align 8 + ret { %A } %1 +} + +define %B @structB(%B* %b.ptr) { +; CHECK-LABEL: structB +; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 0 +; CHECK-NEXT: store i8* null, i8** [[GEP1]], align 8 +; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds %B, %B* %b.ptr, i64 0, i32 1 +; CHECK-NEXT: store i64 42, i64* [[GEP2]], align 8 +; CHECK-NEXT: ret %B { i8* null, i64 42 } + store %B { i8* null, i64 42 }, %B* %b.ptr, align 8 + %1 = load %B, %B* %b.ptr, align 8 + ret %B %1 } diff --git a/test/Transforms/InstCombine/vec_demanded_elts.ll b/test/Transforms/InstCombine/vec_demanded_elts.ll index 4245c7a3c134..0b9663300c39 100644 --- a/test/Transforms/InstCombine/vec_demanded_elts.ll +++ b/test/Transforms/InstCombine/vec_demanded_elts.ll @@ -138,22 +138,6 @@ declare i64 @llvm.x86.sse2.cvtsd2si64(<2 x double>) declare i32 @llvm.x86.sse2.cvttsd2si(<2 x double>) declare i64 @llvm.x86.sse2.cvttsd2si64(<2 x double>) -; <rdar://problem/6945110> -define <4 x i32> @kernel3_vertical(<4 x i16> * %src, <8 x i16> * %foo) nounwind { -entry: - %tmp = load <4 x i16>, <4 x i16>* %src - %tmp1 = load <8 x i16>, <8 x i16>* %foo -; CHECK: %tmp2 = shufflevector - %tmp2 = shufflevector <4 x i16> %tmp, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef> -; pmovzxwd ignores the upper 64-bits of its input; -instcombine should remove this shuffle: -; CHECK-NOT: shufflevector - %tmp3 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> -; CHECK-NEXT: pmovzxwd - %0 = call <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16> %tmp3) - ret <4 x i32> %0 -} -declare <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16>) nounwind readnone - define <4 x float> @dead_shuffle_elt(<4 x float> %x, <2 x float> %y) nounwind { entry: ; CHECK-LABEL: define <4 x float> @dead_shuffle_elt( @@ -210,130 +194,6 @@ define <4 x float> @test_select(float %f, float %g) { ret <4 x float> %ret } -; We should optimize these two redundant insertqi into one -; CHECK: define <2 x i64> @testInsertTwice(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertTwice(<2 x i64> %v, <2 x i64> %i) { -; CHECK: call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 32) -; CHECK-NOT: insertqi - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 32) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 32, i8 32) - ret <2 x i64> %2 -} - -; The result of this insert is the second arg, since the top 64 bits of -; the result are undefined, and we copy the bottom 64 bits from the -; second arg -; CHECK: define <2 x i64> @testInsert64Bits(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsert64Bits(<2 x i64> %v, <2 x i64> %i) { -; CHECK: ret <2 x i64> %i - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 64, i8 0) - ret <2 x i64> %1 -} - -; Test the several types of ranges and ordering that exist for two insertqi -; CHECK: define <2 x i64> @testInsertContainedRange(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertContainedRange(<2 x i64> %v, <2 x i64> %i) { -; CHECK: %[[RES:.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 0) -; CHECK: ret <2 x i64> %[[RES]] - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 0) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 16, i8 16) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertContainedRange_2(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertContainedRange_2(<2 x i64> %v, <2 x i64> %i) { -; CHECK: %[[RES:.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 0) -; CHECK: ret <2 x i64> %[[RES]] - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 16, i8 16) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 32, i8 0) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertOverlappingRange(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertOverlappingRange(<2 x i64> %v, <2 x i64> %i) { -; CHECK: %[[RES:.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 0) -; CHECK: ret <2 x i64> %[[RES]] - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 0) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 32, i8 16) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertOverlappingRange_2(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertOverlappingRange_2(<2 x i64> %v, <2 x i64> %i) { -; CHECK: %[[RES:.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 0) -; CHECK: ret <2 x i64> %[[RES]] - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 16) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 32, i8 0) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertAdjacentRange(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertAdjacentRange(<2 x i64> %v, <2 x i64> %i) { -; CHECK: %[[RES:.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 0) -; CHECK: ret <2 x i64> %[[RES]] - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 32, i8 0) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 16, i8 32) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertAdjacentRange_2(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertAdjacentRange_2(<2 x i64> %v, <2 x i64> %i) { -; CHECK: %[[RES:.*]] = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 0) -; CHECK: ret <2 x i64> %[[RES]] - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 16, i8 32) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 32, i8 0) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertDisjointRange(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertDisjointRange(<2 x i64> %v, <2 x i64> %i) { -; CHECK: tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 16, i8 0) -; CHECK: tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 16, i8 32) - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 16, i8 0) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 16, i8 32) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testInsertDisjointRange_2(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testInsertDisjointRange_2(<2 x i64> %v, <2 x i64> %i) { -; CHECK: tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 16, i8 0) -; CHECK: tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 16, i8 32) - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 16, i8 0) - %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %i, i8 16, i8 32) - ret <2 x i64> %2 -} - -; CHECK: define <2 x i64> @testZeroLength(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testZeroLength(<2 x i64> %v, <2 x i64> %i) { -; CHECK: ret <2 x i64> %i - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 0, i8 0) - ret <2 x i64> %1 -} - -; CHECK: define <2 x i64> @testUndefinedInsertq_1(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testUndefinedInsertq_1(<2 x i64> %v, <2 x i64> %i) { -; CHECK: ret <2 x i64> undef - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 0, i8 16) - ret <2 x i64> %1 -} - -; CHECK: define <2 x i64> @testUndefinedInsertq_2(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testUndefinedInsertq_2(<2 x i64> %v, <2 x i64> %i) { -; CHECK: ret <2 x i64> undef - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 32) - ret <2 x i64> %1 -} - -; CHECK: define <2 x i64> @testUndefinedInsertq_3(<2 x i64> %v, <2 x i64> %i) -define <2 x i64> @testUndefinedInsertq_3(<2 x i64> %v, <2 x i64> %i) { -; CHECK: ret <2 x i64> undef - %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 64, i8 16) - ret <2 x i64> %1 -} - -; CHECK: declare <2 x i64> @llvm.x86.sse4a.insertqi -declare <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64>, <2 x i64>, i8, i8) nounwind - declare <4 x float> @llvm.x86.avx.vpermilvar.ps(<4 x float>, <4 x i32>) define <4 x float> @test_vpermilvar_ps(<4 x float> %v) { ; CHECK-LABEL: @test_vpermilvar_ps( @@ -394,212 +254,15 @@ define <4 x double> @test_vpermilvar_pd_256_zero(<4 x double> %v) { ret <4 x double> %a } -define <2 x i64> @test_sse2_1() nounwind readnone uwtable { - %S = bitcast i32 1 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> %4) - %6 = bitcast <8 x i16> %5 to <4 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %6, <4 x i32> %7) - %9 = bitcast <4 x i32> %8 to <2 x i64> - %10 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %9, <2 x i64> %3) - %11 = bitcast <2 x i64> %10 to <8 x i16> - %12 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %11, i32 %S) - %13 = bitcast <8 x i16> %12 to <4 x i32> - %14 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %13, i32 %S) - %15 = bitcast <4 x i32> %14 to <2 x i64> - %16 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %15, i32 %S) - ret <2 x i64> %16 -; CHECK: test_sse2_1 -; CHECK: ret <2 x i64> <i64 72058418680037440, i64 144117112246370624> -} - -define <4 x i64> @test_avx2_1() nounwind readnone uwtable { - %S = bitcast i32 1 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> <i16 1, i16 0, i16 0, i16 0, i16 2, i16 0, i16 0, i16 0, i16 3, i16 0, i16 0, i16 0, i16 4, i16 0, i16 0, i16 0>, <8 x i16> %4) - %6 = bitcast <16 x i16> %5 to <8 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %6, <4 x i32> %7) - %9 = bitcast <8 x i32> %8 to <4 x i64> - %10 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %9, <2 x i64> %3) - %11 = bitcast <4 x i64> %10 to <16 x i16> - %12 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %11, i32 %S) - %13 = bitcast <16 x i16> %12 to <8 x i32> - %14 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %13, i32 %S) - %15 = bitcast <8 x i32> %14 to <4 x i64> - %16 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %15, i32 %S) - ret <4 x i64> %16 -; CHECK: test_avx2_1 -; CHECK: ret <4 x i64> <i64 64, i64 128, i64 192, i64 256> -} - -define <2 x i64> @test_sse2_0() nounwind readnone uwtable { - %S = bitcast i32 128 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> %4) - %6 = bitcast <8 x i16> %5 to <4 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %6, <4 x i32> %7) - %9 = bitcast <4 x i32> %8 to <2 x i64> - %10 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %9, <2 x i64> %3) - %11 = bitcast <2 x i64> %10 to <8 x i16> - %12 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %11, i32 %S) - %13 = bitcast <8 x i16> %12 to <4 x i32> - %14 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %13, i32 %S) - %15 = bitcast <4 x i32> %14 to <2 x i64> - %16 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %15, i32 %S) - ret <2 x i64> %16 -; CHECK: test_sse2_0 -; CHECK: ret <2 x i64> zeroinitializer -} - -define <4 x i64> @test_avx2_0() nounwind readnone uwtable { - %S = bitcast i32 128 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> <i16 1, i16 0, i16 0, i16 0, i16 2, i16 0, i16 0, i16 0, i16 3, i16 0, i16 0, i16 0, i16 4, i16 0, i16 0, i16 0>, <8 x i16> %4) - %6 = bitcast <16 x i16> %5 to <8 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %6, <4 x i32> %7) - %9 = bitcast <8 x i32> %8 to <4 x i64> - %10 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %9, <2 x i64> %3) - %11 = bitcast <4 x i64> %10 to <16 x i16> - %12 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %11, i32 %S) - %13 = bitcast <16 x i16> %12 to <8 x i32> - %14 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %13, i32 %S) - %15 = bitcast <8 x i32> %14 to <4 x i64> - %16 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %15, i32 %S) - ret <4 x i64> %16 -; CHECK: test_avx2_0 -; CHECK: ret <4 x i64> zeroinitializer -} -define <2 x i64> @test_sse2_psrl_1() nounwind readnone uwtable { - %S = bitcast i32 1 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> <i16 16, i16 32, i16 64, i16 128, i16 256, i16 512, i16 1024, i16 2048>, <8 x i16> %4) - %6 = bitcast <8 x i16> %5 to <4 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %6, <4 x i32> %7) - %9 = bitcast <4 x i32> %8 to <2 x i64> - %10 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %9, <2 x i64> %3) - %11 = bitcast <2 x i64> %10 to <8 x i16> - %12 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %11, i32 %S) - %13 = bitcast <8 x i16> %12 to <4 x i32> - %14 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %13, i32 %S) - %15 = bitcast <4 x i32> %14 to <2 x i64> - %16 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %15, i32 %S) - ret <2 x i64> %16 -; CHECK: test_sse2_psrl_1 -; CHECK: ret <2 x i64> <i64 562954248421376, i64 9007267974742020> -} - -define <4 x i64> @test_avx2_psrl_1() nounwind readnone uwtable { - %S = bitcast i32 1 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> <i16 1024, i16 0, i16 0, i16 0, i16 2048, i16 0, i16 0, i16 0, i16 4096, i16 0, i16 0, i16 0, i16 8192, i16 0, i16 0, i16 0>, <8 x i16> %4) - %6 = bitcast <16 x i16> %5 to <8 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %6, <4 x i32> %7) - %9 = bitcast <8 x i32> %8 to <4 x i64> - %10 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %9, <2 x i64> %3) - %11 = bitcast <4 x i64> %10 to <16 x i16> - %12 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %11, i32 %S) - %13 = bitcast <16 x i16> %12 to <8 x i32> - %14 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %13, i32 %S) - %15 = bitcast <8 x i32> %14 to <4 x i64> - %16 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %15, i32 %S) - ret <4 x i64> %16 -; CHECK: test_avx2_psrl_1 -; CHECK: ret <4 x i64> <i64 16, i64 32, i64 64, i64 128> -} - -define <2 x i64> @test_sse2_psrl_0() nounwind readnone uwtable { - %S = bitcast i32 128 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> <i16 32, i16 64, i16 128, i16 256, i16 512, i16 1024, i16 2048, i16 4096>, <8 x i16> %4) - %6 = bitcast <8 x i16> %5 to <4 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %6, <4 x i32> %7) - %9 = bitcast <4 x i32> %8 to <2 x i64> - %10 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %9, <2 x i64> %3) - %11 = bitcast <2 x i64> %10 to <8 x i16> - %12 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %11, i32 %S) - %13 = bitcast <8 x i16> %12 to <4 x i32> - %14 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %13, i32 %S) - %15 = bitcast <4 x i32> %14 to <2 x i64> - %16 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %15, i32 %S) - ret <2 x i64> %16 -; CHECK: test_sse2_psrl_0 -; CHECK: ret <2 x i64> zeroinitializer -} - -define <4 x i64> @test_avx2_psrl_0() nounwind readnone uwtable { - %S = bitcast i32 128 to i32 - %1 = zext i32 %S to i64 - %2 = insertelement <2 x i64> undef, i64 %1, i32 0 - %3 = insertelement <2 x i64> %2, i64 0, i32 1 - %4 = bitcast <2 x i64> %3 to <8 x i16> - %5 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> <i16 1024, i16 0, i16 0, i16 0, i16 2048, i16 0, i16 0, i16 0, i16 4096, i16 0, i16 0, i16 0, i16 8192, i16 0, i16 0, i16 0>, <8 x i16> %4) - %6 = bitcast <16 x i16> %5 to <8 x i32> - %7 = bitcast <2 x i64> %3 to <4 x i32> - %8 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %6, <4 x i32> %7) - %9 = bitcast <8 x i32> %8 to <4 x i64> - %10 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %9, <2 x i64> %3) - %11 = bitcast <4 x i64> %10 to <16 x i16> - %12 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %11, i32 %S) - %13 = bitcast <16 x i16> %12 to <8 x i32> - %14 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %13, i32 %S) - %15 = bitcast <8 x i32> %14 to <4 x i64> - %16 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %15, i32 %S) - ret <4 x i64> %16 -; CHECK: test_avx2_psrl_0 -; CHECK: ret <4 x i64> zeroinitializer +define <2 x i64> @PR24922(<2 x i64> %v) { +; CHECK-LABEL: @PR24922 +; CHECK: select <2 x i1> +; +; Check that instcombine doesn't wrongly fold the select statement into a +; ret <2 x i64> %v +; +; FIXME: We should be able to simplify the ConstantExpr in the select mask. +entry: + %result = select <2 x i1> <i1 icmp eq (i64 extractelement (<2 x i64> bitcast (<4 x i32> <i32 15, i32 15, i32 15, i32 15> to <2 x i64>), i64 0), i64 0), i1 true>, <2 x i64> %v, <2 x i64> zeroinitializer + ret <2 x i64> %result } - -declare <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64>, i32) #1 -declare <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32>, i32) #1 -declare <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16>, i32) #1 -declare <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64>, <2 x i64>) #1 -declare <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32>, <4 x i32>) #1 -declare <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16>, <8 x i16>) #1 -declare <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64>, i32) #1 -declare <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32>, i32) #1 -declare <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16>, i32) #1 -declare <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64>, <2 x i64>) #1 -declare <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32>, <4 x i32>) #1 -declare <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16>, <8 x i16>) #1 -declare <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64>, i32) #1 -declare <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32>, i32) #1 -declare <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16>, i32) #1 -declare <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64>, <2 x i64>) #1 -declare <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32>, <4 x i32>) #1 -declare <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16>, <8 x i16>) #1 -declare <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64>, i32) #1 -declare <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32>, i32) #1 -declare <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16>, i32) #1 -declare <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64>, <2 x i64>) #1 -declare <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32>, <4 x i32>) #1 -declare <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16>, <8 x i16>) #1 - -attributes #1 = { nounwind readnone } diff --git a/test/Transforms/InstCombine/vec_shuffle.ll b/test/Transforms/InstCombine/vec_shuffle.ll index d4d7f167ef07..d2cd2b90abc2 100644 --- a/test/Transforms/InstCombine/vec_shuffle.ll +++ b/test/Transforms/InstCombine/vec_shuffle.ll @@ -310,16 +310,16 @@ define <4 x i32> @shuffle_17addnuw(<4 x i32> %v1, <4 x i32> %v2) nounwind uwtabl ret <4 x i32> %r } -define <4 x float> @shuffle_17fsub(<4 x float> %v1, <4 x float> %v2) nounwind uwtable { -; CHECK-LABEL: @shuffle_17fsub( -; CHECK-NOT: shufflevector -; CHECK: fsub <4 x float> %v1, %v2 -; CHECK: shufflevector +define <4 x float> @shuffle_17fsub_fast(<4 x float> %v1, <4 x float> %v2) nounwind uwtable { +; CHECK-LABEL: @shuffle_17fsub_fast( +; CHECK-NEXT: [[VAR1:%[a-zA-Z0-9.]+]] = fsub fast <4 x float> %v1, %v2 +; CHECK-NEXT: shufflevector <4 x float> [[VAR1]], <4 x float> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0> +; CHECK-NEXT: ret <4 x float> %t1 = shufflevector <4 x float> %v1, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> %t2 = shufflevector <4 x float> %v2, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> - %r = fsub <4 x float> %t1, %t2 + %r = fsub fast <4 x float> %t1, %t2 ret <4 x float> %r } @@ -406,6 +406,21 @@ define i32 @pr19737(<4 x i32> %in0) { ret i32 %rv } +; In PR20059 ( http://llvm.org/pr20059 ), shufflevector operations are reordered/removed +; for an srem operation. This is not a valid optimization because it may cause a trap +; on div-by-zero. + +define <4 x i32> @pr20059(<4 x i32> %p1, <4 x i32> %p2) { +; CHECK-LABEL: @pr20059( +; CHECK-NEXT: %splat1 = shufflevector <4 x i32> %p1, <4 x i32> undef, <4 x i32> zeroinitializer +; CHECK-NEXT: %splat2 = shufflevector <4 x i32> %p2, <4 x i32> undef, <4 x i32> zeroinitializer +; CHECK-NEXT: %retval = srem <4 x i32> %splat1, %splat2 + %splat1 = shufflevector <4 x i32> %p1, <4 x i32> undef, <4 x i32> zeroinitializer + %splat2 = shufflevector <4 x i32> %p2, <4 x i32> undef, <4 x i32> zeroinitializer + %retval = srem <4 x i32> %splat1, %splat2 + ret <4 x i32> %retval +} + define <4 x i32> @pr20114(<4 x i32> %__mask) { ; CHECK-LABEL: @pr20114 ; CHECK: shufflevector diff --git a/test/Transforms/InstCombine/vector_gep2.ll b/test/Transforms/InstCombine/vector_gep2.ll index d76a7d56cc7a..1b80ffd101c9 100644 --- a/test/Transforms/InstCombine/vector_gep2.ll +++ b/test/Transforms/InstCombine/vector_gep2.ll @@ -9,3 +9,26 @@ define <2 x i8*> @testa(<2 x i8*> %a) { ; CHECK: getelementptr i8, <2 x i8*> %a, <2 x i64> <i64 0, i64 1> ret <2 x i8*> %g } + +define <8 x double*> @vgep_s_v8i64(double* %a, <8 x i64>%i) { +; CHECK-LABEL: @vgep_s_v8i64 +; CHECK: getelementptr double, double* %a, <8 x i64> %i + %VectorGep = getelementptr double, double* %a, <8 x i64> %i + ret <8 x double*> %VectorGep +} + +define <8 x double*> @vgep_s_v8i32(double* %a, <8 x i32>%i) { +; CHECK-LABEL: @vgep_s_v8i32 +; CHECK: %1 = sext <8 x i32> %i to <8 x i64> +; CHECK: getelementptr double, double* %a, <8 x i64> %1 + %VectorGep = getelementptr double, double* %a, <8 x i32> %i + ret <8 x double*> %VectorGep +} + +define <8 x i8*> @vgep_v8iPtr_i32(<8 x i8*> %a, i32 %i) { +; CHECK-LABEL: @vgep_v8iPtr_i32 +; CHECK: %1 = sext i32 %i to i64 +; CHECK: %VectorGep = getelementptr i8, <8 x i8*> %a, i64 %1 + %VectorGep = getelementptr i8, <8 x i8*> %a, i32 %i + ret <8 x i8*> %VectorGep +} diff --git a/test/Transforms/InstCombine/x86-f16c.ll b/test/Transforms/InstCombine/x86-f16c.ll new file mode 100644 index 000000000000..e10b339907e3 --- /dev/null +++ b/test/Transforms/InstCombine/x86-f16c.ll @@ -0,0 +1,61 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare <4 x float> @llvm.x86.vcvtph2ps.128(<8 x i16>) +declare <8 x float> @llvm.x86.vcvtph2ps.256(<8 x i16>) + +; +; Vector Demanded Bits +; + +; Only bottom 4 elements required. +define <4 x float> @demand_vcvtph2ps_128(<8 x i16> %A) { +; CHECK-LABEL: @demand_vcvtph2ps_128 +; CHECK-NEXT: %1 = tail call <4 x float> @llvm.x86.vcvtph2ps.128(<8 x i16> %A) +; CHECK-NEXT: ret <4 x float> %1 + %1 = shufflevector <8 x i16> %A, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <4 x float> @llvm.x86.vcvtph2ps.128(<8 x i16> %1) + ret <4 x float> %2 +} + +; All 8 elements required. +define <8 x float> @demand_vcvtph2ps_256(<8 x i16> %A) { +; CHECK-LABEL: @demand_vcvtph2ps_256 +; CHECK-NEXT: %1 = shufflevector <8 x i16> %A, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: %2 = tail call <8 x float> @llvm.x86.vcvtph2ps.256(<8 x i16> %1) +; CHECK-NEXT: ret <8 x float> %2 + %1 = shufflevector <8 x i16> %A, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <8 x float> @llvm.x86.vcvtph2ps.256(<8 x i16> %1) + ret <8 x float> %2 +} + +; +; Constant Folding +; + +define <4 x float> @fold_vcvtph2ps_128() { +; CHECK-LABEL: @fold_vcvtph2ps_128 +; CHECK-NEXT: ret <4 x float> <float 0.000000e+00, float 5.000000e-01, float 1.000000e+00, float -0.000000e+00> + %1 = tail call <4 x float> @llvm.x86.vcvtph2ps.128(<8 x i16> <i16 0, i16 14336, i16 15360, i16 32768, i16 16384, i16 31743, i16 48128, i16 49152>) + ret <4 x float> %1 +} + +define <8 x float> @fold_vcvtph2ps_256() { +; CHECK-LABEL: @fold_vcvtph2ps_256 +; CHECK-NEXT: ret <8 x float> <float 0.000000e+00, float 5.000000e-01, float 1.000000e+00, float -0.000000e+00, float 2.000000e+00, float 6.550400e+04, float -1.000000e+00, float -2.000000e+00> + %1 = tail call <8 x float> @llvm.x86.vcvtph2ps.256(<8 x i16> <i16 0, i16 14336, i16 15360, i16 32768, i16 16384, i16 31743, i16 48128, i16 49152>) + ret <8 x float> %1 +} + +define <4 x float> @fold_vcvtph2ps_128_zero() { +; CHECK-LABEL: @fold_vcvtph2ps_128_zero +; CHECK-NEXT: ret <4 x float> zeroinitializer + %1 = tail call <4 x float> @llvm.x86.vcvtph2ps.128(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>) + ret <4 x float> %1 +} + +define <8 x float> @fold_vcvtph2ps_256_zero() { +; CHECK-LABEL: @fold_vcvtph2ps_256_zero +; CHECK-NEXT: ret <8 x float> zeroinitializer + %1 = tail call <8 x float> @llvm.x86.vcvtph2ps.256(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>) + ret <8 x float> %1 +} diff --git a/test/Transforms/InstCombine/x86-pmovsx.ll b/test/Transforms/InstCombine/x86-pmovsx.ll new file mode 100644 index 000000000000..31bdc59b16a8 --- /dev/null +++ b/test/Transforms/InstCombine/x86-pmovsx.ll @@ -0,0 +1,136 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare <4 x i32> @llvm.x86.sse41.pmovsxbd(<16 x i8>) nounwind readnone +declare <2 x i64> @llvm.x86.sse41.pmovsxbq(<16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.sse41.pmovsxbw(<16 x i8>) nounwind readnone +declare <2 x i64> @llvm.x86.sse41.pmovsxdq(<4 x i32>) nounwind readnone +declare <4 x i32> @llvm.x86.sse41.pmovsxwd(<8 x i16>) nounwind readnone +declare <2 x i64> @llvm.x86.sse41.pmovsxwq(<8 x i16>) nounwind readnone + +declare <8 x i32> @llvm.x86.avx2.pmovsxbd(<16 x i8>) nounwind readnone +declare <4 x i64> @llvm.x86.avx2.pmovsxbq(<16 x i8>) nounwind readnone +declare <16 x i16> @llvm.x86.avx2.pmovsxbw(<16 x i8>) nounwind readnone +declare <4 x i64> @llvm.x86.avx2.pmovsxdq(<4 x i32>) nounwind readnone +declare <8 x i32> @llvm.x86.avx2.pmovsxwd(<8 x i16>) nounwind readnone +declare <4 x i64> @llvm.x86.avx2.pmovsxwq(<8 x i16>) nounwind readnone + +; +; Basic sign extension tests +; + +define <4 x i32> @sse41_pmovsxbd(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovsxbd +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: sext <4 x i8> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + + %res = call <4 x i32> @llvm.x86.sse41.pmovsxbd(<16 x i8> %v) + ret <4 x i32> %res +} + +define <2 x i64> @sse41_pmovsxbq(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovsxbq +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <2 x i32> <i32 0, i32 1> +; CHECK-NEXT: sext <2 x i8> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + + %res = call <2 x i64> @llvm.x86.sse41.pmovsxbq(<16 x i8> %v) + ret <2 x i64> %res +} + +define <8 x i16> @sse41_pmovsxbw(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovsxbw +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: sext <8 x i8> %1 to <8 x i16> +; CHECK-NEXT: ret <8 x i16> %2 + + %res = call <8 x i16> @llvm.x86.sse41.pmovsxbw(<16 x i8> %v) + ret <8 x i16> %res +} + +define <2 x i64> @sse41_pmovsxdq(<4 x i32> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovsxdq +; CHECK-NEXT: shufflevector <4 x i32> %v, <4 x i32> undef, <2 x i32> <i32 0, i32 1> +; CHECK-NEXT: sext <2 x i32> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + + %res = call <2 x i64> @llvm.x86.sse41.pmovsxdq(<4 x i32> %v) + ret <2 x i64> %res +} + +define <4 x i32> @sse41_pmovsxwd(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovsxwd +; CHECK-NEXT: shufflevector <8 x i16> %v, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: sext <4 x i16> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + + %res = call <4 x i32> @llvm.x86.sse41.pmovsxwd(<8 x i16> %v) + ret <4 x i32> %res +} + +define <2 x i64> @sse41_pmovsxwq(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovsxwq +; CHECK-NEXT: shufflevector <8 x i16> %v, <8 x i16> undef, <2 x i32> <i32 0, i32 1> +; CHECK-NEXT: sext <2 x i16> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + + %res = call <2 x i64> @llvm.x86.sse41.pmovsxwq(<8 x i16> %v) + ret <2 x i64> %res +} + +define <8 x i32> @avx2_pmovsxbd(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovsxbd +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: sext <8 x i8> %1 to <8 x i32> +; CHECK-NEXT: ret <8 x i32> %2 + + %res = call <8 x i32> @llvm.x86.avx2.pmovsxbd(<16 x i8> %v) + ret <8 x i32> %res +} + +define <4 x i64> @avx2_pmovsxbq(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovsxbq +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: sext <4 x i8> %1 to <4 x i64> +; CHECK-NEXT: ret <4 x i64> %2 + + %res = call <4 x i64> @llvm.x86.avx2.pmovsxbq(<16 x i8> %v) + ret <4 x i64> %res +} + +define <16 x i16> @avx2_pmovsxbw(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovsxbw +; CHECK-NEXT: sext <16 x i8> %v to <16 x i16> +; CHECK-NEXT: ret <16 x i16> %1 + + %res = call <16 x i16> @llvm.x86.avx2.pmovsxbw(<16 x i8> %v) + ret <16 x i16> %res +} + +define <4 x i64> @avx2_pmovsxdq(<4 x i32> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovsxdq +; CHECK-NEXT: sext <4 x i32> %v to <4 x i64> +; CHECK-NEXT: ret <4 x i64> %1 + + %res = call <4 x i64> @llvm.x86.avx2.pmovsxdq(<4 x i32> %v) + ret <4 x i64> %res +} + +define <8 x i32> @avx2_pmovsxwd(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovsxwd +; CHECK-NEXT: sext <8 x i16> %v to <8 x i32> +; CHECK-NEXT: ret <8 x i32> %1 + + %res = call <8 x i32> @llvm.x86.avx2.pmovsxwd(<8 x i16> %v) + ret <8 x i32> %res +} + +define <4 x i64> @avx2_pmovsxwq(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovsxwq +; CHECK-NEXT: shufflevector <8 x i16> %v, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: sext <4 x i16> %1 to <4 x i64> +; CHECK-NEXT: ret <4 x i64> %2 + + %res = call <4 x i64> @llvm.x86.avx2.pmovsxwq(<8 x i16> %v) + ret <4 x i64> %res +} diff --git a/test/Transforms/InstCombine/x86-pmovzx.ll b/test/Transforms/InstCombine/x86-pmovzx.ll new file mode 100644 index 000000000000..31028cba26eb --- /dev/null +++ b/test/Transforms/InstCombine/x86-pmovzx.ll @@ -0,0 +1,136 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare <4 x i32> @llvm.x86.sse41.pmovzxbd(<16 x i8>) nounwind readnone +declare <2 x i64> @llvm.x86.sse41.pmovzxbq(<16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.sse41.pmovzxbw(<16 x i8>) nounwind readnone +declare <2 x i64> @llvm.x86.sse41.pmovzxdq(<4 x i32>) nounwind readnone +declare <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16>) nounwind readnone +declare <2 x i64> @llvm.x86.sse41.pmovzxwq(<8 x i16>) nounwind readnone + +declare <8 x i32> @llvm.x86.avx2.pmovzxbd(<16 x i8>) nounwind readnone +declare <4 x i64> @llvm.x86.avx2.pmovzxbq(<16 x i8>) nounwind readnone +declare <16 x i16> @llvm.x86.avx2.pmovzxbw(<16 x i8>) nounwind readnone +declare <4 x i64> @llvm.x86.avx2.pmovzxdq(<4 x i32>) nounwind readnone +declare <8 x i32> @llvm.x86.avx2.pmovzxwd(<8 x i16>) nounwind readnone +declare <4 x i64> @llvm.x86.avx2.pmovzxwq(<8 x i16>) nounwind readnone + +; +; Basic zero extension tests +; + +define <4 x i32> @sse41_pmovzxbd(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovzxbd +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: zext <4 x i8> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + + %res = call <4 x i32> @llvm.x86.sse41.pmovzxbd(<16 x i8> %v) + ret <4 x i32> %res +} + +define <2 x i64> @sse41_pmovzxbq(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovzxbq +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <2 x i32> <i32 0, i32 1> +; CHECK-NEXT: zext <2 x i8> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + + %res = call <2 x i64> @llvm.x86.sse41.pmovzxbq(<16 x i8> %v) + ret <2 x i64> %res +} + +define <8 x i16> @sse41_pmovzxbw(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovzxbw +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: zext <8 x i8> %1 to <8 x i16> +; CHECK-NEXT: ret <8 x i16> %2 + + %res = call <8 x i16> @llvm.x86.sse41.pmovzxbw(<16 x i8> %v) + ret <8 x i16> %res +} + +define <2 x i64> @sse41_pmovzxdq(<4 x i32> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovzxdq +; CHECK-NEXT: shufflevector <4 x i32> %v, <4 x i32> undef, <2 x i32> <i32 0, i32 1> +; CHECK-NEXT: zext <2 x i32> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + + %res = call <2 x i64> @llvm.x86.sse41.pmovzxdq(<4 x i32> %v) + ret <2 x i64> %res +} + +define <4 x i32> @sse41_pmovzxwd(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovzxwd +; CHECK-NEXT: shufflevector <8 x i16> %v, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: zext <4 x i16> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + + %res = call <4 x i32> @llvm.x86.sse41.pmovzxwd(<8 x i16> %v) + ret <4 x i32> %res +} + +define <2 x i64> @sse41_pmovzxwq(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @sse41_pmovzxwq +; CHECK-NEXT: shufflevector <8 x i16> %v, <8 x i16> undef, <2 x i32> <i32 0, i32 1> +; CHECK-NEXT: zext <2 x i16> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + + %res = call <2 x i64> @llvm.x86.sse41.pmovzxwq(<8 x i16> %v) + ret <2 x i64> %res +} + +define <8 x i32> @avx2_pmovzxbd(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovzxbd +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: zext <8 x i8> %1 to <8 x i32> +; CHECK-NEXT: ret <8 x i32> %2 + + %res = call <8 x i32> @llvm.x86.avx2.pmovzxbd(<16 x i8> %v) + ret <8 x i32> %res +} + +define <4 x i64> @avx2_pmovzxbq(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovzxbq +; CHECK-NEXT: shufflevector <16 x i8> %v, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: zext <4 x i8> %1 to <4 x i64> +; CHECK-NEXT: ret <4 x i64> %2 + + %res = call <4 x i64> @llvm.x86.avx2.pmovzxbq(<16 x i8> %v) + ret <4 x i64> %res +} + +define <16 x i16> @avx2_pmovzxbw(<16 x i8> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovzxbw +; CHECK-NEXT: zext <16 x i8> %v to <16 x i16> +; CHECK-NEXT: ret <16 x i16> %1 + + %res = call <16 x i16> @llvm.x86.avx2.pmovzxbw(<16 x i8> %v) + ret <16 x i16> %res +} + +define <4 x i64> @avx2_pmovzxdq(<4 x i32> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovzxdq +; CHECK-NEXT: zext <4 x i32> %v to <4 x i64> +; CHECK-NEXT: ret <4 x i64> %1 + + %res = call <4 x i64> @llvm.x86.avx2.pmovzxdq(<4 x i32> %v) + ret <4 x i64> %res +} + +define <8 x i32> @avx2_pmovzxwd(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovzxwd +; CHECK-NEXT: zext <8 x i16> %v to <8 x i32> +; CHECK-NEXT: ret <8 x i32> %1 + + %res = call <8 x i32> @llvm.x86.avx2.pmovzxwd(<8 x i16> %v) + ret <8 x i32> %res +} + +define <4 x i64> @avx2_pmovzxwq(<8 x i16> %v) nounwind readnone { +; CHECK-LABEL: @avx2_pmovzxwq +; CHECK-NEXT: shufflevector <8 x i16> %v, <8 x i16> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: zext <4 x i16> %1 to <4 x i64> +; CHECK-NEXT: ret <4 x i64> %2 + + %res = call <4 x i64> @llvm.x86.avx2.pmovzxwq(<8 x i16> %v) + ret <4 x i64> %res +} diff --git a/test/Transforms/InstCombine/x86-pshufb.ll b/test/Transforms/InstCombine/x86-pshufb.ll new file mode 100644 index 000000000000..caaaed8910a8 --- /dev/null +++ b/test/Transforms/InstCombine/x86-pshufb.ll @@ -0,0 +1,267 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Verify that instcombine is able to fold identity shuffles. + +define <16 x i8> @identity_test(<16 x i8> %InVec) { +; CHECK-LABEL: @identity_test +; CHECK: ret <16 x i8> %InVec + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15>) + ret <16 x i8> %1 +} + +define <32 x i8> @identity_test_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @identity_test_avx2 +; CHECK: ret <32 x i8> %InVec + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15>) + ret <32 x i8> %1 +} + + +; Verify that instcombine is able to fold byte shuffles with zero masks. + +define <16 x i8> @fold_to_zero_vector(<16 x i8> %InVec) { +; CHECK-LABEL: @fold_to_zero_vector +; CHECK: ret <16 x i8> zeroinitializer + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <16 x i8> %1 +} + +define <32 x i8> @fold_to_zero_vector_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @fold_to_zero_vector_avx2 +; CHECK: ret <32 x i8> zeroinitializer + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <32 x i8> %1 +} + +; Instcombine should be able to fold the following byte shuffle to a builtin shufflevector +; with a shuffle mask of all zeroes. + +define <16 x i8> @splat_test(<16 x i8> %InVec) { +; CHECK-LABEL: @splat_test +; CHECK: shufflevector <16 x i8> %InVec, <16 x i8> undef, <16 x i32> zeroinitializer + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> zeroinitializer) + ret <16 x i8> %1 +} + +; In the test case below, elements in the low 128-bit lane of the result +; vector are equal to the lower byte of %InVec (shuffle index 0). +; Elements in the high 128-bit lane of the result vector are equal to +; the lower byte in the high 128-bit lane of %InVec (shuffle index 16). + +define <32 x i8> @splat_test_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @splat_test_avx2 +; CHECK: shufflevector <32 x i8> %InVec, <32 x i8> undef, <32 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> zeroinitializer) + ret <32 x i8> %1 +} + +; Each of the byte shuffles in the following tests is equivalent to a blend between +; vector %InVec and a vector of all zeroes. + +define <16 x i8> @blend1(<16 x i8> %InVec) { +; CHECK-LABEL: @blend1 +; CHECK: shufflevector <16 x i8> %InVec, {{.*}}, <16 x i32> <i32 16, i32 1, i32 16, i32 3, i32 16, i32 5, i32 16, i32 7, i32 16, i32 9, i32 16, i32 11, i32 16, i32 13, i32 16, i32 15> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 -128, i8 1, i8 -128, i8 3, i8 -128, i8 5, i8 -128, i8 7, i8 -128, i8 9, i8 -128, i8 11, i8 -128, i8 13, i8 -128, i8 15>) + ret <16 x i8> %1 +} + +define <16 x i8> @blend2(<16 x i8> %InVec) { +; CHECK-LABEL: @blend2 +; CHECK: shufflevector <16 x i8> %InVec, {{.*}}, <16 x i32> <i32 16, i32 16, i32 2, i32 3, i32 16, i32 16, i32 6, i32 7, i32 16, i32 16, i32 10, i32 11, i32 16, i32 16, i32 14, i32 15> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 -128, i8 -128, i8 2, i8 3, i8 -128, i8 -128, i8 6, i8 7, i8 -128, i8 -128, i8 10, i8 11, i8 -128, i8 -128, i8 14, i8 15>) + ret <16 x i8> %1 +} + +define <16 x i8> @blend3(<16 x i8> %InVec) { +; CHECK-LABEL: @blend3 +; CHECK: shufflevector <16 x i8> %InVec, {{.*}}, <16 x i32> <i32 16, i32 16, i32 16, i32 16, i32 4, i32 5, i32 6, i32 7, i32 16, i32 16, i32 16, i32 16, i32 12, i32 13, i32 14, i32 15> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 4, i8 5, i8 6, i8 7, i8 -128, i8 -128, i8 -128, i8 -128, i8 12, i8 13, i8 14, i8 15>) + ret <16 x i8> %1 +} + +define <16 x i8> @blend4(<16 x i8> %InVec) { +; CHECK-LABEL: @blend4 +; CHECK: shufflevector <16 x i8> %InVec, {{.*}}, <16 x i32> <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15>) + ret <16 x i8> %1 +} + +define <16 x i8> @blend5(<16 x i8> %InVec) { +; CHECK-LABEL: @blend5 +; CHECK: shufflevector <16 x i8> %InVec, {{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 0, i8 1, i8 2, i8 3, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <16 x i8> %1 +} + +define <16 x i8> @blend6(<16 x i8> %InVec) { +; CHECK-LABEL: @blend6 +; CHECK: shufflevector <16 x i8> %InVec, {{.*}}, <16 x i32> <i32 0, i32 1, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 0, i8 1, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <16 x i8> %1 +} + +define <32 x i8> @blend1_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @blend1_avx2 +; CHECK: shufflevector <32 x i8> %InVec, {{.*}}, <32 x i32> <i32 32, i32 1, i32 32, i32 3, i32 32, i32 5, i32 32, i32 7, i32 32, i32 9, i32 32, i32 11, i32 32, i32 13, i32 32, i32 15, i32 48, i32 17, i32 48, i32 19, i32 48, i32 21, i32 48, i32 23, i32 48, i32 25, i32 48, i32 27, i32 48, i32 29, i32 48, i32 31> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 -128, i8 1, i8 -128, i8 3, i8 -128, i8 5, i8 -128, i8 7, i8 -128, i8 9, i8 -128, i8 11, i8 -128, i8 13, i8 -128, i8 15, i8 -128, i8 1, i8 -128, i8 3, i8 -128, i8 5, i8 -128, i8 7, i8 -128, i8 9, i8 -128, i8 11, i8 -128, i8 13, i8 -128, i8 15>) + ret <32 x i8> %1 +} + +define <32 x i8> @blend2_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @blend2_avx2 +; CHECK: shufflevector <32 x i8> %InVec, {{.*}}, <32 x i32> <i32 32, i32 32, i32 2, i32 3, i32 32, i32 32, i32 6, i32 7, i32 32, i32 32, i32 10, i32 11, i32 32, i32 32, i32 14, i32 15, i32 48, i32 48, i32 18, i32 19, i32 48, i32 48, i32 22, i32 23, i32 48, i32 48, i32 26, i32 27, i32 48, i32 48, i32 30, i32 31> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 -128, i8 -128, i8 2, i8 3, i8 -128, i8 -128, i8 6, i8 7, i8 -128, i8 -128, i8 10, i8 11, i8 -128, i8 -128, i8 14, i8 15, i8 -128, i8 -128, i8 2, i8 3, i8 -128, i8 -128, i8 6, i8 7, i8 -128, i8 -128, i8 10, i8 11, i8 -128, i8 -128, i8 14, i8 15>) + ret <32 x i8> %1 +} + +define <32 x i8> @blend3_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @blend3_avx2 +; CHECK: shufflevector <32 x i8> %InVec, {{.*}}, <32 x i32> <i32 32, i32 32, i32 32, i32 32, i32 4, i32 5, i32 6, i32 7, i32 32, i32 32, i32 32, i32 32, i32 12, i32 13, i32 14, i32 15, i32 48, i32 48, i32 48, i32 48, i32 20, i32 21, i32 22, i32 23, i32 48, i32 48, i32 48, i32 48, i32 28, i32 29, i32 30, i32 31> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 4, i8 5, i8 6, i8 7, i8 -128, i8 -128, i8 -128, i8 -128, i8 12, i8 13, i8 14, i8 15, i8 -128, i8 -128, i8 -128, i8 -128, i8 4, i8 5, i8 6, i8 7, i8 -128, i8 -128, i8 -128, i8 -128, i8 12, i8 13, i8 14, i8 15>) + ret <32 x i8> %1 +} + +define <32 x i8> @blend4_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @blend4_avx2 +; CHECK: shufflevector <32 x i8> %InVec, {{.*}}, <32 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 8, i8 9, i8 10, i8 11, i8 12, i8 13, i8 14, i8 15>) + ret <32 x i8> %1 +} + +define <32 x i8> @blend5_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @blend5_avx2 +; CHECK: shufflevector <32 x i8> %InVec, {{.*}}, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 16, i32 17, i32 18, i32 19, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 0, i8 1, i8 2, i8 3, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 0, i8 1, i8 2, i8 3, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <32 x i8> %1 +} + +define <32 x i8> @blend6_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @blend6_avx2 +; CHECK: shufflevector <32 x i8> %InVec, {{.*}}, <32 x i32> <i32 0, i32 1, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 16, i32 17, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 0, i8 1, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 0, i8 1, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <32 x i8> %1 +} + +; movq idiom. +define <16 x i8> @movq_idiom(<16 x i8> %InVec) { +; CHECK-LABEL: @movq_idiom +; CHECK: shufflevector <16 x i8> %InVec, <16 x i8> <i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <16 x i8> %1 +} + +define <32 x i8> @movq_idiom_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @movq_idiom_avx2 +; CHECK: shufflevector <32 x i8> %InVec, <32 x i8> <i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128, i8 -128>) + ret <32 x i8> %1 +} + +; Vector permutations using byte shuffles. + +define <16 x i8> @permute1(<16 x i8> %InVec) { +; CHECK-LABEL: @permute1 +; CHECK: shufflevector <16 x i8> %InVec, <16 x i8> undef, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15, i32 12, i32 13, i32 14, i32 15> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 4, i8 5, i8 6, i8 7, i8 4, i8 5, i8 6, i8 7, i8 12, i8 13, i8 14, i8 15, i8 12, i8 13, i8 14, i8 15>) + ret <16 x i8> %1 +} + +define <16 x i8> @permute2(<16 x i8> %InVec) { +; CHECK-LABEL: @permute2 +; CHECK: shufflevector <16 x i8> %InVec, <16 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7>) + ret <16 x i8> %1 +} + +define <32 x i8> @permute1_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @permute1_avx2 +; CHECK: shufflevector <32 x i8> %InVec, <32 x i8> undef, <32 x i32> <i32 4, i32 5, i32 6, i32 7, i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15, i32 12, i32 13, i32 14, i32 15, i32 20, i32 21, i32 22, i32 23, i32 20, i32 21, i32 22, i32 23, i32 28, i32 29, i32 30, i32 31, i32 28, i32 29, i32 30, i32 31> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 4, i8 5, i8 6, i8 7, i8 4, i8 5, i8 6, i8 7, i8 12, i8 13, i8 14, i8 15, i8 12, i8 13, i8 14, i8 15, i8 4, i8 5, i8 6, i8 7, i8 4, i8 5, i8 6, i8 7, i8 12, i8 13, i8 14, i8 15, i8 12, i8 13, i8 14, i8 15>) + ret <32 x i8> %1 +} + +define <32 x i8> @permute2_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @permute2_avx2 +; CHECK: shufflevector <32 x i8> %InVec, <32 x i8> undef, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 0, i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7>) + ret <32 x i8> %1 +} + +; Test that instcombine correctly folds a pshufb with values that +; are not -128 and that are not encoded in four bits. + +define <16 x i8> @identity_test2_2(<16 x i8> %InVec) { +; CHECK-LABEL: @identity_test2_2 +; CHECK: ret <16 x i8> %InVec + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 16, i8 17, i8 18, i8 19, i8 20, i8 21, i8 22, i8 23, i8 24, i8 25, i8 26, i8 27, i8 28, i8 29, i8 30, i8 31>) + ret <16 x i8> %1 +} + +define <32 x i8> @identity_test_avx2_2(<32 x i8> %InVec) { +; CHECK-LABEL: @identity_test_avx2_2 +; CHECK: ret <32 x i8> %InVec + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 16, i8 33, i8 66, i8 19, i8 36, i8 69, i8 22, i8 39, i8 72, i8 25, i8 42, i8 75, i8 28, i8 45, i8 78, i8 31, i8 48, i8 81, i8 34, i8 51, i8 84, i8 37, i8 54, i8 87, i8 40, i8 57, i8 90, i8 43, i8 60, i8 93, i8 46, i8 63>) + ret <32 x i8> %1 +} + +define <16 x i8> @fold_to_zero_vector_2(<16 x i8> %InVec) { +; CHECK-LABEL: @fold_to_zero_vector_2 +; CHECK: ret <16 x i8> zeroinitializer + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 -125, i8 -1, i8 -53, i8 -32, i8 -4, i8 -7, i8 -33, i8 -66, i8 -99, i8 -120, i8 -100, i8 -22, i8 -17, i8 -1, i8 -11, i8 -15>) + ret <16 x i8> %1 +} + +define <32 x i8> @fold_to_zero_vector_avx2_2(<32 x i8> %InVec) { +; CHECK-LABEL: @fold_to_zero_vector_avx2_2 +; CHECK: ret <32 x i8> zeroinitializer + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 -127, i8 -1, i8 -53, i8 -32, i8 -4, i8 -7, i8 -33, i8 -66, i8 -99, i8 -120, i8 -100, i8 -22, i8 -17, i8 -1, i8 -11, i8 -15, i8 -126, i8 -2, i8 -52, i8 -31, i8 -5, i8 -8, i8 -34, i8 -67, i8 -100, i8 -119, i8 -101, i8 -23, i8 -16, i8 -2, i8 -12, i8 -16>) + ret <32 x i8> %1 +} + +define <16 x i8> @permute3(<16 x i8> %InVec) { +; CHECK-LABEL: @permute3 +; CHECK: shufflevector <16 x i8> %InVec, <16 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + + %1 = tail call <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8> %InVec, <16 x i8> <i8 48, i8 17, i8 34, i8 51, i8 20, i8 37, i8 54, i8 23, i8 16, i8 49, i8 66, i8 19, i8 52, i8 69, i8 22, i8 55>) + ret <16 x i8> %1 +} + +define <32 x i8> @permute3_avx2(<32 x i8> %InVec) { +; CHECK-LABEL: @permute3_avx2 +; CHECK: shufflevector <32 x i8> %InVec, <32 x i8> undef, <32 x i32> <i32 4, i32 5, i32 6, i32 7, i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15, i32 12, i32 13, i32 14, i32 15, i32 20, i32 21, i32 22, i32 23, i32 20, i32 21, i32 22, i32 23, i32 28, i32 29, i32 30, i32 31, i32 28, i32 29, i32 30, i32 31> + + %1 = tail call <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8> %InVec, <32 x i8> <i8 52, i8 21, i8 38, i8 55, i8 20, i8 37, i8 54, i8 23, i8 28, i8 61, i8 78, i8 31, i8 60, i8 29, i8 30, i8 79, i8 52, i8 21, i8 38, i8 55, i8 20, i8 53, i8 102, i8 23, i8 92, i8 93, i8 94, i8 95, i8 108, i8 109, i8 110, i8 111>) + ret <32 x i8> %1 +} + + +declare <16 x i8> @llvm.x86.ssse3.pshuf.b.128(<16 x i8>, <16 x i8>) +declare <32 x i8> @llvm.x86.avx2.pshuf.b(<32 x i8>, <32 x i8>) diff --git a/test/Transforms/InstCombine/x86-sse4a.ll b/test/Transforms/InstCombine/x86-sse4a.ll new file mode 100644 index 000000000000..815d26bd2254 --- /dev/null +++ b/test/Transforms/InstCombine/x86-sse4a.ll @@ -0,0 +1,336 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; +; EXTRQ +; + +define <2 x i64> @test_extrq_call(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_call +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %y) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %y) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrq_zero_arg0(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_zero_arg0 +; CHECK-NEXT: ret <2 x i64> <i64 0, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> zeroinitializer, <16 x i8> %y) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrq_zero_arg1(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_zero_arg1 +; CHECK-NEXT: ret <2 x i64> %x + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> zeroinitializer) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrq_to_extqi(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_to_extqi +; CHECK-NEXT: %1 = call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 8, i8 15) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> <i8 8, i8 15, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrq_constant(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_constant +; CHECK-NEXT: ret <2 x i64> <i64 255, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> <i64 -1, i64 55>, <16 x i8> <i8 8, i8 15, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrq_constant_undef(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_constant_undef +; CHECK-NEXT: ret <2 x i64> <i64 65535, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> <i64 -1, i64 undef>, <16 x i8> <i8 16, i8 15, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>) nounwind + ret <2 x i64> %1 +} + +; +; EXTRQI +; + +define <2 x i64> @test_extrqi_call(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_call +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 8, i8 23) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 8, i8 23) + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrqi_shuffle_1zuu(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_shuffle_1zuu +; CHECK-NEXT: %1 = bitcast <2 x i64> %x to <16 x i8> +; CHECK-NEXT: %2 = shufflevector <16 x i8> %1, <16 x i8> <i8 undef, i8 undef, i8 undef, i8 undef, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 20, i32 21, i32 22, i32 23, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: %3 = bitcast <16 x i8> %2 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %3 + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 32, i8 32) + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrqi_shuffle_2zzzzzzzuuuuuuuu(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_shuffle_2zzzzzzzuuuuuuuu +; CHECK-NEXT: %1 = bitcast <2 x i64> %x to <16 x i8> +; CHECK-NEXT: %2 = shufflevector <16 x i8> %1, <16 x i8> <i8 undef, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>, <16 x i32> <i32 2, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: %3 = bitcast <16 x i8> %2 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %3 + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 8, i8 16) + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrqi_undef(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_undef +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> zeroinitializer, i8 32, i8 33) + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrqi_zero(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_zero +; CHECK-NEXT: ret <2 x i64> <i64 0, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> zeroinitializer, i8 3, i8 18) + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrqi_constant(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_constant +; CHECK-NEXT: ret <2 x i64> <i64 7, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> <i64 -1, i64 55>, i8 3, i8 18) + ret <2 x i64> %1 +} + +define <2 x i64> @test_extrqi_constant_undef(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_constant_undef +; CHECK-NEXT: ret <2 x i64> <i64 15, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> <i64 -1, i64 undef>, i8 4, i8 18) + ret <2 x i64> %1 +} + +; +; INSERTQ +; + +define <2 x i64> @test_insertq_call(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertq_call +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> %y) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> %y) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_insertq_to_insertqi(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertq_to_insertqi +; CHECK-NEXT: %1 = call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> <i64 8, i64 undef>, i8 18, i8 2) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> <i64 8, i64 658>) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_insertq_constant(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertq_constant +; CHECK-NEXT: ret <2 x i64> <i64 32, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> <i64 0, i64 0>, <2 x i64> <i64 8, i64 658>) nounwind + ret <2 x i64> %1 +} + +define <2 x i64> @test_insertq_constant_undef(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertq_constant_undef +; CHECK-NEXT: ret <2 x i64> <i64 33, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> <i64 1, i64 undef>, <2 x i64> <i64 8, i64 658>) nounwind + ret <2 x i64> %1 +} + +; +; INSERTQI +; + +define <16 x i8> @test_insertqi_shuffle_04uu(<16 x i8> %v, <16 x i8> %i) { +; CHECK-LABEL: @test_insertqi_shuffle_04uu +; CHECK-NEXT: %1 = shufflevector <16 x i8> %v, <16 x i8> %i, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: ret <16 x i8> %1 + %1 = bitcast <16 x i8> %v to <2 x i64> + %2 = bitcast <16 x i8> %i to <2 x i64> + %3 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %2, i8 32, i8 32) + %4 = bitcast <2 x i64> %3 to <16 x i8> + ret <16 x i8> %4 +} + +define <16 x i8> @test_insertqi_shuffle_8123uuuu(<16 x i8> %v, <16 x i8> %i) { +; CHECK-LABEL: @test_insertqi_shuffle_8123uuuu +; CHECK-NEXT: %1 = shufflevector <16 x i8> %v, <16 x i8> %i, <16 x i32> <i32 16, i32 17, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> +; CHECK-NEXT: ret <16 x i8> %1 + %1 = bitcast <16 x i8> %v to <2 x i64> + %2 = bitcast <16 x i8> %i to <2 x i64> + %3 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %2, i8 16, i8 0) + %4 = bitcast <2 x i64> %3 to <16 x i8> + ret <16 x i8> %4 +} + +define <2 x i64> @test_insertqi_constant(<2 x i64> %v, <2 x i64> %i) { +; CHECK-LABEL: @test_insertqi_constant +; CHECK-NEXT: ret <2 x i64> <i64 -131055, i64 undef> + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> <i64 -1, i64 -1>, <2 x i64> <i64 8, i64 0>, i8 16, i8 1) + ret <2 x i64> %1 +} + +; The result of this insert is the second arg, since the top 64 bits of +; the result are undefined, and we copy the bottom 64 bits from the +; second arg +define <2 x i64> @testInsert64Bits(<2 x i64> %v, <2 x i64> %i) { +; CHECK-LABEL: @testInsert64Bits +; CHECK-NEXT: ret <2 x i64> %i + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 64, i8 0) + ret <2 x i64> %1 +} + +define <2 x i64> @testZeroLength(<2 x i64> %v, <2 x i64> %i) { +; CHECK-LABEL: @testZeroLength +; CHECK-NEXT: ret <2 x i64> %i + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 0, i8 0) + ret <2 x i64> %1 +} + +define <2 x i64> @testUndefinedInsertq_1(<2 x i64> %v, <2 x i64> %i) { +; CHECK-LABEL: @testUndefinedInsertq_1 +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 0, i8 16) + ret <2 x i64> %1 +} + +define <2 x i64> @testUndefinedInsertq_2(<2 x i64> %v, <2 x i64> %i) { +; CHECK-LABEL: @testUndefinedInsertq_2 +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 48, i8 32) + ret <2 x i64> %1 +} + +define <2 x i64> @testUndefinedInsertq_3(<2 x i64> %v, <2 x i64> %i) { +; CHECK-LABEL: @testUndefinedInsertq_3 +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %v, <2 x i64> %i, i8 64, i8 16) + ret <2 x i64> %1 +} + +; +; Vector Demanded Bits +; + +define <2 x i64> @test_extrq_arg0(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_arg0 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %y) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %x, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %1, <16 x i8> %y) nounwind + ret <2 x i64> %2 +} + +define <2 x i64> @test_extrq_arg1(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_arg1 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %y) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <16 x i8> %y, <16 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %1) nounwind + ret <2 x i64> %2 +} + +define <2 x i64> @test_extrq_args01(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_args01 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %y) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %x, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = shufflevector <16 x i8> %y, <16 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0> + %3 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %1, <16 x i8> %2) nounwind + ret <2 x i64> %3 +} + +define <2 x i64> @test_extrq_ret(<2 x i64> %x, <16 x i8> %y) { +; CHECK-LABEL: @test_extrq_ret +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> %y) nounwind + %2 = shufflevector <2 x i64> %1, <2 x i64> undef, <2 x i32> <i32 1, i32 1> + ret <2 x i64> %2 +} + +define <2 x i64> @test_extrqi_arg0(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_arg0 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 3, i8 2) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %x, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %1, i8 3, i8 2) + ret <2 x i64> %2 +} + +define <2 x i64> @test_extrqi_ret(<2 x i64> %x) { +; CHECK-LABEL: @test_extrqi_ret +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> %x, i8 3, i8 2) nounwind + %2 = shufflevector <2 x i64> %1, <2 x i64> undef, <2 x i32> <i32 1, i32 1> + ret <2 x i64> %2 +} + +define <2 x i64> @test_insertq_arg0(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertq_arg0 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> %y) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %x, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %1, <2 x i64> %y) nounwind + ret <2 x i64> %2 +} + +define <2 x i64> @test_insertq_ret(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertq_ret +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64> %x, <2 x i64> %y) nounwind + %2 = shufflevector <2 x i64> %1, <2 x i64> undef, <2 x i32> <i32 1, i32 1> + ret <2 x i64> %2 +} + +define <2 x i64> @test_insertqi_arg0(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertqi_arg0 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> %y, i8 3, i8 2) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %x, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %y, i8 3, i8 2) nounwind + ret <2 x i64> %2 +} + +define <2 x i64> @test_insertqi_arg1(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertqi_arg1 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> %y, i8 3, i8 2) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %y, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> %1, i8 3, i8 2) nounwind + ret <2 x i64> %2 +} + +define <2 x i64> @test_insertqi_args01(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertqi_args01 +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> %y, i8 3, i8 2) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %x, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = shufflevector <2 x i64> %y, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %3 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %1, <2 x i64> %2, i8 3, i8 2) nounwind + ret <2 x i64> %3 +} + +define <2 x i64> @test_insertqi_ret(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: @test_insertqi_ret +; CHECK-NEXT: ret <2 x i64> undef + %1 = tail call <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64> %x, <2 x i64> %y, i8 3, i8 2) nounwind + %2 = shufflevector <2 x i64> %1, <2 x i64> undef, <2 x i32> <i32 1, i32 1> + ret <2 x i64> %2 +} + +; CHECK: declare <2 x i64> @llvm.x86.sse4a.extrq +declare <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64>, <16 x i8>) nounwind + +; CHECK: declare <2 x i64> @llvm.x86.sse4a.extrqi +declare <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64>, i8, i8) nounwind + +; CHECK: declare <2 x i64> @llvm.x86.sse4a.insertq +declare <2 x i64> @llvm.x86.sse4a.insertq(<2 x i64>, <2 x i64>) nounwind + +; CHECK: declare <2 x i64> @llvm.x86.sse4a.insertqi +declare <2 x i64> @llvm.x86.sse4a.insertqi(<2 x i64>, <2 x i64>, i8, i8) nounwind diff --git a/test/Transforms/InstCombine/x86-vector-shifts.ll b/test/Transforms/InstCombine/x86-vector-shifts.ll new file mode 100644 index 000000000000..59e445a40bef --- /dev/null +++ b/test/Transforms/InstCombine/x86-vector-shifts.ll @@ -0,0 +1,1318 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; +; ASHR - Immediate +; + +define <8 x i16> @sse2_psrai_w_0(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrai_w_0 +; CHECK-NEXT: ret <8 x i16> %v + %1 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %v, i32 0) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrai_w_15(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrai_w_15 +; CHECK-NEXT: %1 = ashr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %v, i32 15) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrai_w_64(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrai_w_64 +; CHECK-NEXT: %1 = ashr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %v, i32 64) + ret <8 x i16> %1 +} + +define <4 x i32> @sse2_psrai_d_0(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrai_d_0 +; CHECK-NEXT: ret <4 x i32> %v + %1 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %v, i32 0) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrai_d_15(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrai_d_15 +; CHECK-NEXT: %1 = ashr <4 x i32> %v, <i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %v, i32 15) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrai_d_64(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrai_d_64 +; CHECK-NEXT: %1 = ashr <4 x i32> %v, <i32 31, i32 31, i32 31, i32 31> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %v, i32 64) + ret <4 x i32> %1 +} + +define <16 x i16> @avx2_psrai_w_0(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrai_w_0 +; CHECK-NEXT: ret <16 x i16> %v + %1 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %v, i32 0) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrai_w_15(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrai_w_15 +; CHECK-NEXT: %1 = ashr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %v, i32 15) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrai_w_64(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrai_w_64 +; CHECK-NEXT: %1 = ashr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %v, i32 64) + ret <16 x i16> %1 +} + +define <8 x i32> @avx2_psrai_d_0(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrai_d_0 +; CHECK-NEXT: ret <8 x i32> %v + %1 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %v, i32 0) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrai_d_15(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrai_d_15 +; CHECK-NEXT: %1 = ashr <8 x i32> %v, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %v, i32 15) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrai_d_64(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrai_d_64 +; CHECK-NEXT: %1 = ashr <8 x i32> %v, <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %v, i32 64) + ret <8 x i32> %1 +} + +; +; LSHR - Immediate +; + +define <8 x i16> @sse2_psrli_w_0(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrli_w_0 +; CHECK-NEXT: ret <8 x i16> %v + %1 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %v, i32 0) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrli_w_15(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrli_w_15 +; CHECK-NEXT: %1 = lshr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %v, i32 15) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrli_w_64(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrli_w_64 +; CHECK-NEXT: ret <8 x i16> zeroinitializer + %1 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %v, i32 64) + ret <8 x i16> %1 +} + +define <4 x i32> @sse2_psrli_d_0(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrli_d_0 +; CHECK-NEXT: ret <4 x i32> %v + %1 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %v, i32 0) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrli_d_15(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrli_d_15 +; CHECK-NEXT: %1 = lshr <4 x i32> %v, <i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %v, i32 15) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrli_d_64(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrli_d_64 +; CHECK-NEXT: ret <4 x i32> zeroinitializer + %1 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %v, i32 64) + ret <4 x i32> %1 +} + +define <2 x i64> @sse2_psrli_q_0(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psrli_q_0 +; CHECK-NEXT: ret <2 x i64> %v + %1 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %v, i32 0) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_psrli_q_15(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psrli_q_15 +; CHECK-NEXT: %1 = lshr <2 x i64> %v, <i64 15, i64 15> +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %v, i32 15) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_psrli_q_64(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psrli_q_64 +; CHECK-NEXT: ret <2 x i64> zeroinitializer + %1 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %v, i32 64) + ret <2 x i64> %1 +} + +define <16 x i16> @avx2_psrli_w_0(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrli_w_0 +; CHECK-NEXT: ret <16 x i16> %v + %1 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %v, i32 0) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrli_w_15(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrli_w_15 +; CHECK-NEXT: %1 = lshr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %v, i32 15) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrli_w_64(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrli_w_64 +; CHECK-NEXT: ret <16 x i16> zeroinitializer + %1 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %v, i32 64) + ret <16 x i16> %1 +} + +define <8 x i32> @avx2_psrli_d_0(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrli_d_0 +; CHECK-NEXT: ret <8 x i32> %v + %1 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %v, i32 0) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrli_d_15(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrli_d_15 +; CHECK-NEXT: %1 = lshr <8 x i32> %v, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %v, i32 15) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrli_d_64(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrli_d_64 +; CHECK-NEXT: ret <8 x i32> zeroinitializer + %1 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %v, i32 64) + ret <8 x i32> %1 +} + +define <4 x i64> @avx2_psrli_q_0(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psrli_q_0 +; CHECK-NEXT: ret <4 x i64> %v + %1 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %v, i32 0) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_psrli_q_15(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psrli_q_15 +; CHECK-NEXT: %1 = lshr <4 x i64> %v, <i64 15, i64 15, i64 15, i64 15> +; CHECK-NEXT: ret <4 x i64> %1 + %1 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %v, i32 15) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_psrli_q_64(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psrli_q_64 +; CHECK-NEXT: ret <4 x i64> zeroinitializer + %1 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %v, i32 64) + ret <4 x i64> %1 +} + +; +; SHL - Immediate +; + +define <8 x i16> @sse2_pslli_w_0(<8 x i16> %v) { +; CHECK-LABEL: @sse2_pslli_w_0 +; CHECK-NEXT: ret <8 x i16> %v + %1 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %v, i32 0) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_pslli_w_15(<8 x i16> %v) { +; CHECK-LABEL: @sse2_pslli_w_15 +; CHECK-NEXT: %1 = shl <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %v, i32 15) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_pslli_w_64(<8 x i16> %v) { +; CHECK-LABEL: @sse2_pslli_w_64 +; CHECK-NEXT: ret <8 x i16> zeroinitializer + %1 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %v, i32 64) + ret <8 x i16> %1 +} + +define <4 x i32> @sse2_pslli_d_0(<4 x i32> %v) { +; CHECK-LABEL: @sse2_pslli_d_0 +; CHECK-NEXT: ret <4 x i32> %v + %1 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %v, i32 0) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_pslli_d_15(<4 x i32> %v) { +; CHECK-LABEL: @sse2_pslli_d_15 +; CHECK-NEXT: %1 = shl <4 x i32> %v, <i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %v, i32 15) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_pslli_d_64(<4 x i32> %v) { +; CHECK-LABEL: @sse2_pslli_d_64 +; CHECK-NEXT: ret <4 x i32> zeroinitializer + %1 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %v, i32 64) + ret <4 x i32> %1 +} + +define <2 x i64> @sse2_pslli_q_0(<2 x i64> %v) { +; CHECK-LABEL: @sse2_pslli_q_0 +; CHECK-NEXT: ret <2 x i64> %v + %1 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %v, i32 0) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_pslli_q_15(<2 x i64> %v) { +; CHECK-LABEL: @sse2_pslli_q_15 +; CHECK-NEXT: %1 = shl <2 x i64> %v, <i64 15, i64 15> +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %v, i32 15) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_pslli_q_64(<2 x i64> %v) { +; CHECK-LABEL: @sse2_pslli_q_64 +; CHECK-NEXT: ret <2 x i64> zeroinitializer + %1 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %v, i32 64) + ret <2 x i64> %1 +} + +define <16 x i16> @avx2_pslli_w_0(<16 x i16> %v) { +; CHECK-LABEL: @avx2_pslli_w_0 +; CHECK-NEXT: ret <16 x i16> %v + %1 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %v, i32 0) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_pslli_w_15(<16 x i16> %v) { +; CHECK-LABEL: @avx2_pslli_w_15 +; CHECK-NEXT: %1 = shl <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %v, i32 15) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_pslli_w_64(<16 x i16> %v) { +; CHECK-LABEL: @avx2_pslli_w_64 +; CHECK-NEXT: ret <16 x i16> zeroinitializer + %1 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %v, i32 64) + ret <16 x i16> %1 +} + +define <8 x i32> @avx2_pslli_d_0(<8 x i32> %v) { +; CHECK-LABEL: @avx2_pslli_d_0 +; CHECK-NEXT: ret <8 x i32> %v + %1 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %v, i32 0) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_pslli_d_15(<8 x i32> %v) { +; CHECK-LABEL: @avx2_pslli_d_15 +; CHECK-NEXT: %1 = shl <8 x i32> %v, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %v, i32 15) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_pslli_d_64(<8 x i32> %v) { +; CHECK-LABEL: @avx2_pslli_d_64 +; CHECK-NEXT: ret <8 x i32> zeroinitializer + %1 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %v, i32 64) + ret <8 x i32> %1 +} + +define <4 x i64> @avx2_pslli_q_0(<4 x i64> %v) { +; CHECK-LABEL: @avx2_pslli_q_0 +; CHECK-NEXT: ret <4 x i64> %v + %1 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %v, i32 0) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_pslli_q_15(<4 x i64> %v) { +; CHECK-LABEL: @avx2_pslli_q_15 +; CHECK-NEXT: %1 = shl <4 x i64> %v, <i64 15, i64 15, i64 15, i64 15> +; CHECK-NEXT: ret <4 x i64> %1 + %1 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %v, i32 15) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_pslli_q_64(<4 x i64> %v) { +; CHECK-LABEL: @avx2_pslli_q_64 +; CHECK-NEXT: ret <4 x i64> zeroinitializer + %1 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %v, i32 64) + ret <4 x i64> %1 +} + +; +; ASHR - Constant Vector +; + +define <8 x i16> @sse2_psra_w_0(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psra_w_0 +; CHECK-NEXT: ret <8 x i16> %v + %1 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> zeroinitializer) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psra_w_15(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psra_w_15 +; CHECK-NEXT: %1 = ashr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> <i16 15, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psra_w_15_splat(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psra_w_15_splat +; CHECK-NEXT: %1 = ashr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psra_w_64(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psra_w_64 +; CHECK-NEXT: %1 = ashr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> <i16 64, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <8 x i16> %1 +} + +define <4 x i32> @sse2_psra_d_0(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psra_d_0 +; CHECK-NEXT: ret <4 x i32> %v + %1 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> zeroinitializer) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psra_d_15(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psra_d_15 +; CHECK-NEXT: %1 = ashr <4 x i32> %v, <i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> <i32 15, i32 0, i32 9999, i32 9999>) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psra_d_15_splat(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psra_d_15_splat +; CHECK-NEXT: %1 = ashr <4 x i32> %v, <i32 31, i32 31, i32 31, i32 31> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> <i32 15, i32 15, i32 15, i32 15>) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psra_d_64(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psra_d_64 +; CHECK-NEXT: %1 = ashr <4 x i32> %v, <i32 31, i32 31, i32 31, i32 31> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> <i32 64, i32 0, i32 9999, i32 9999>) + ret <4 x i32> %1 +} + +define <16 x i16> @avx2_psra_w_0(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psra_w_0 +; CHECK-NEXT: ret <16 x i16> %v + %1 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %v, <8 x i16> zeroinitializer) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psra_w_15(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psra_w_15 +; CHECK-NEXT: %1 = ashr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %v, <8 x i16> <i16 15, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psra_w_15_splat(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psra_w_15_splat +; CHECK-NEXT: %1 = ashr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %v, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psra_w_64(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psra_w_64 +; CHECK-NEXT: %1 = ashr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %v, <8 x i16> <i16 64, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <16 x i16> %1 +} + +define <8 x i32> @avx2_psra_d_0(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psra_d_0 +; CHECK-NEXT: ret <8 x i32> %v + %1 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %v, <4 x i32> zeroinitializer) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psra_d_15(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psra_d_15 +; CHECK-NEXT: %1 = ashr <8 x i32> %v, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %v, <4 x i32> <i32 15, i32 0, i32 9999, i32 9999>) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psra_d_15_splat(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psra_d_15_splat +; CHECK-NEXT: %1 = ashr <8 x i32> %v, <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %v, <4 x i32> <i32 15, i32 15, i32 15, i32 15>) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psra_d_64(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psra_d_64 +; CHECK-NEXT: %1 = ashr <8 x i32> %v, <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31, i32 31> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %v, <4 x i32> <i32 64, i32 0, i32 9999, i32 9999>) + ret <8 x i32> %1 +} + +; +; LSHR - Constant Vector +; + +define <8 x i16> @sse2_psrl_w_0(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrl_w_0 +; CHECK-NEXT: ret <8 x i16> %v + %1 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %v, <8 x i16> zeroinitializer) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrl_w_15(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrl_w_15 +; CHECK-NEXT: %1 = lshr <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %v, <8 x i16> <i16 15, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrl_w_15_splat(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrl_w_15_splat +; CHECK-NEXT: ret <8 x i16> zeroinitializer + %1 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %v, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psrl_w_64(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psrl_w_64 +; CHECK-NEXT: ret <8 x i16> zeroinitializer + %1 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %v, <8 x i16> <i16 64, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <8 x i16> %1 +} + +define <4 x i32> @sse2_psrl_d_0(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrl_d_0 +; CHECK-NEXT: ret <4 x i32> %v + %1 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %v, <4 x i32> zeroinitializer) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrl_d_15(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrl_d_15 +; CHECK-NEXT: %1 = lshr <4 x i32> %v, <i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %v, <4 x i32> <i32 15, i32 0, i32 9999, i32 9999>) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrl_d_15_splat(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrl_d_15_splat +; CHECK-NEXT: ret <4 x i32> zeroinitializer + %1 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %v, <4 x i32> <i32 15, i32 15, i32 15, i32 15>) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psrl_d_64(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psrl_d_64 +; CHECK-NEXT: ret <4 x i32> zeroinitializer + %1 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %v, <4 x i32> <i32 64, i32 0, i32 9999, i32 9999>) + ret <4 x i32> %1 +} + +define <2 x i64> @sse2_psrl_q_0(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psrl_q_0 +; CHECK-NEXT: ret <2 x i64> %v + %1 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %v, <2 x i64> zeroinitializer) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_psrl_q_15(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psrl_q_15 +; CHECK-NEXT: %1 = lshr <2 x i64> %v, <i64 15, i64 15> +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %v, <2 x i64> <i64 15, i64 9999>) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_psrl_q_64(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psrl_q_64 +; CHECK-NEXT: ret <2 x i64> zeroinitializer + %1 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %v, <2 x i64> <i64 64, i64 9999>) + ret <2 x i64> %1 +} + +define <16 x i16> @avx2_psrl_w_0(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrl_w_0 +; CHECK-NEXT: ret <16 x i16> %v + %1 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> zeroinitializer) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrl_w_15(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrl_w_15 +; CHECK-NEXT: %1 = lshr <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> <i16 15, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrl_w_15_splat(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrl_w_15_splat +; CHECK-NEXT: ret <16 x i16> zeroinitializer + %1 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psrl_w_64(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psrl_w_64 +; CHECK-NEXT: ret <16 x i16> zeroinitializer + %1 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> <i16 64, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <16 x i16> %1 +} + +define <8 x i32> @avx2_psrl_d_0(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrl_d_0 +; CHECK-NEXT: ret <8 x i32> %v + %1 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> zeroinitializer) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrl_d_15(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrl_d_15 +; CHECK-NEXT: %1 = lshr <8 x i32> %v, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> <i32 15, i32 0, i32 9999, i32 9999>) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrl_d_15_splat(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrl_d_15_splat +; CHECK-NEXT: ret <8 x i32> zeroinitializer + %1 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> <i32 15, i32 15, i32 15, i32 15>) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psrl_d_64(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psrl_d_64 +; CHECK-NEXT: ret <8 x i32> zeroinitializer + %1 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> <i32 64, i32 0, i32 9999, i32 9999>) + ret <8 x i32> %1 +} + +define <4 x i64> @avx2_psrl_q_0(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psrl_q_0 +; CHECK-NEXT: ret <4 x i64> %v + %1 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %v, <2 x i64> zeroinitializer) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_psrl_q_15(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psrl_q_15 +; CHECK-NEXT: %1 = lshr <4 x i64> %v, <i64 15, i64 15, i64 15, i64 15> +; CHECK-NEXT: ret <4 x i64> %1 + %1 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %v, <2 x i64> <i64 15, i64 9999>) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_psrl_q_64(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psrl_q_64 +; CHECK-NEXT: ret <4 x i64> zeroinitializer + %1 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %v, <2 x i64> <i64 64, i64 9999>) + ret <4 x i64> %1 +} + +; +; SHL - Constant Vector +; + +define <8 x i16> @sse2_psll_w_0(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psll_w_0 +; CHECK-NEXT: ret <8 x i16> %v + %1 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> %v, <8 x i16> zeroinitializer) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psll_w_15(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psll_w_15 +; CHECK-NEXT: %1 = shl <8 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <8 x i16> %1 + %1 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> %v, <8 x i16> <i16 15, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psll_w_15_splat(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psll_w_15_splat +; CHECK-NEXT: ret <8 x i16> zeroinitializer + %1 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> %v, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + ret <8 x i16> %1 +} + +define <8 x i16> @sse2_psll_w_64(<8 x i16> %v) { +; CHECK-LABEL: @sse2_psll_w_64 +; CHECK-NEXT: ret <8 x i16> zeroinitializer + %1 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> %v, <8 x i16> <i16 64, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <8 x i16> %1 +} + +define <4 x i32> @sse2_psll_d_0(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psll_d_0 +; CHECK-NEXT: ret <4 x i32> %v + %1 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %v, <4 x i32> zeroinitializer) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psll_d_15(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psll_d_15 +; CHECK-NEXT: %1 = shl <4 x i32> %v, <i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <4 x i32> %1 + %1 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %v, <4 x i32> <i32 15, i32 0, i32 9999, i32 9999>) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psll_d_15_splat(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psll_d_15_splat +; CHECK-NEXT: ret <4 x i32> zeroinitializer + %1 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %v, <4 x i32> <i32 15, i32 15, i32 15, i32 15>) + ret <4 x i32> %1 +} + +define <4 x i32> @sse2_psll_d_64(<4 x i32> %v) { +; CHECK-LABEL: @sse2_psll_d_64 +; CHECK-NEXT: ret <4 x i32> zeroinitializer + %1 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %v, <4 x i32> <i32 64, i32 0, i32 9999, i32 9999>) + ret <4 x i32> %1 +} + +define <2 x i64> @sse2_psll_q_0(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psll_q_0 +; CHECK-NEXT: ret <2 x i64> %v + %1 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %v, <2 x i64> zeroinitializer) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_psll_q_15(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psll_q_15 +; CHECK-NEXT: %1 = shl <2 x i64> %v, <i64 15, i64 15> +; CHECK-NEXT: ret <2 x i64> %1 + %1 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %v, <2 x i64> <i64 15, i64 9999>) + ret <2 x i64> %1 +} + +define <2 x i64> @sse2_psll_q_64(<2 x i64> %v) { +; CHECK-LABEL: @sse2_psll_q_64 +; CHECK-NEXT: ret <2 x i64> zeroinitializer + %1 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %v, <2 x i64> <i64 64, i64 9999>) + ret <2 x i64> %1 +} + +define <16 x i16> @avx2_psll_w_0(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psll_w_0 +; CHECK-NEXT: ret <16 x i16> %v + %1 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> %v, <8 x i16> zeroinitializer) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psll_w_15(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psll_w_15 +; CHECK-NEXT: %1 = shl <16 x i16> %v, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15> +; CHECK-NEXT: ret <16 x i16> %1 + %1 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> %v, <8 x i16> <i16 15, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psll_w_15_splat(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psll_w_15_splat +; CHECK-NEXT: ret <16 x i16> zeroinitializer + %1 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> %v, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + ret <16 x i16> %1 +} + +define <16 x i16> @avx2_psll_w_64(<16 x i16> %v) { +; CHECK-LABEL: @avx2_psll_w_64 +; CHECK-NEXT: ret <16 x i16> zeroinitializer + %1 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> %v, <8 x i16> <i16 64, i16 0, i16 0, i16 0, i16 9999, i16 9999, i16 9999, i16 9999>) + ret <16 x i16> %1 +} + +define <8 x i32> @avx2_psll_d_0(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psll_d_0 +; CHECK-NEXT: ret <8 x i32> %v + %1 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %v, <4 x i32> zeroinitializer) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psll_d_15(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psll_d_15 +; CHECK-NEXT: %1 = shl <8 x i32> %v, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15> +; CHECK-NEXT: ret <8 x i32> %1 + %1 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %v, <4 x i32> <i32 15, i32 0, i32 9999, i32 9999>) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psll_d_15_splat(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psll_d_15_splat +; CHECK-NEXT: ret <8 x i32> zeroinitializer + %1 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %v, <4 x i32> <i32 15, i32 15, i32 15, i32 15>) + ret <8 x i32> %1 +} + +define <8 x i32> @avx2_psll_d_64(<8 x i32> %v) { +; CHECK-LABEL: @avx2_psll_d_64 +; CHECK-NEXT: ret <8 x i32> zeroinitializer + %1 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %v, <4 x i32> <i32 64, i32 0, i32 9999, i32 9999>) + ret <8 x i32> %1 +} + +define <4 x i64> @avx2_psll_q_0(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psll_q_0 +; CHECK-NEXT: ret <4 x i64> %v + %1 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %v, <2 x i64> zeroinitializer) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_psll_q_15(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psll_q_15 +; CHECK-NEXT: %1 = shl <4 x i64> %v, <i64 15, i64 15, i64 15, i64 15> +; CHECK-NEXT: ret <4 x i64> %1 + %1 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %v, <2 x i64> <i64 15, i64 9999>) + ret <4 x i64> %1 +} + +define <4 x i64> @avx2_psll_q_64(<4 x i64> %v) { +; CHECK-LABEL: @avx2_psll_q_64 +; CHECK-NEXT: ret <4 x i64> zeroinitializer + %1 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %v, <2 x i64> <i64 64, i64 9999>) + ret <4 x i64> %1 +} + +; +; Vector Demanded Bits +; + +define <8 x i16> @sse2_psra_w_var(<8 x i16> %v, <8 x i16> %a) { +; CHECK-LABEL: @sse2_psra_w_var +; CHECK-NEXT: %1 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> %a) +; CHECK-NEXT: ret <8 x i16> %1 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> %1) + ret <8 x i16> %2 +} + +define <8 x i16> @sse2_psra_w_var_bc(<8 x i16> %v, <2 x i64> %a) { +; CHECK-LABEL: @sse2_psra_w_var_bc +; CHECK-NEXT: %1 = bitcast <2 x i64> %a to <8 x i16> +; CHECK-NEXT: %2 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> %1) +; CHECK-NEXT: ret <8 x i16> %2 + %1 = shufflevector <2 x i64> %a, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = bitcast <2 x i64> %1 to <8 x i16> + %3 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %v, <8 x i16> %2) + ret <8 x i16> %3 +} + +define <4 x i32> @sse2_psra_d_var(<4 x i32> %v, <4 x i32> %a) { +; CHECK-LABEL: @sse2_psra_d_var +; CHECK-NEXT: %1 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> %a) +; CHECK-NEXT: ret <4 x i32> %1 + %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %2 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> %1) + ret <4 x i32> %2 +} + +define <4 x i32> @sse2_psra_d_var_bc(<4 x i32> %v, <8 x i16> %a) { +; CHECK-LABEL: @sse2_psra_d_var_bc +; CHECK-NEXT: %1 = bitcast <8 x i16> %a to <4 x i32> +; CHECK-NEXT: %2 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> %1) +; CHECK-NEXT: ret <4 x i32> %2 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = bitcast <8 x i16> %1 to <4 x i32> + %3 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %v, <4 x i32> %2) + ret <4 x i32> %3 +} + +define <16 x i16> @avx2_psra_w_var(<16 x i16> %v, <8 x i16> %a) { +; CHECK-LABEL: @avx2_psra_w_var +; CHECK-NEXT: %1 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %v, <8 x i16> %a) +; CHECK-NEXT: ret <16 x i16> %1 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %v, <8 x i16> %1) + ret <16 x i16> %2 +} + +define <8 x i32> @avx2_psra_d_var(<8 x i32> %v, <4 x i32> %a) { +; CHECK-LABEL: @avx2_psra_d_var +; CHECK-NEXT: %1 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %v, <4 x i32> %a) +; CHECK-NEXT: ret <8 x i32> %1 + %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %2 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %v, <4 x i32> %1) + ret <8 x i32> %2 +} + +define <8 x i16> @sse2_psrl_w_var(<8 x i16> %v, <8 x i16> %a) { +; CHECK-LABEL: @sse2_psrl_w_var +; CHECK-NEXT: %1 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %v, <8 x i16> %a) +; CHECK-NEXT: ret <8 x i16> %1 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> %v, <8 x i16> %1) + ret <8 x i16> %2 +} + +define <4 x i32> @sse2_psrl_d_var(<4 x i32> %v, <4 x i32> %a) { +; CHECK-LABEL: @sse2_psrl_d_var +; CHECK-NEXT: %1 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %v, <4 x i32> %a) +; CHECK-NEXT: ret <4 x i32> %1 + %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %2 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %v, <4 x i32> %1) + ret <4 x i32> %2 +} + +define <2 x i64> @sse2_psrl_q_var(<2 x i64> %v, <2 x i64> %a) { +; CHECK-LABEL: @sse2_psrl_q_var +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %v, <2 x i64> %a) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %a, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %v, <2 x i64> %1) + ret <2 x i64> %2 +} + +define <16 x i16> @avx2_psrl_w_var(<16 x i16> %v, <8 x i16> %a) { +; CHECK-LABEL: @avx2_psrl_w_var +; CHECK-NEXT: %1 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> %a) +; CHECK-NEXT: ret <16 x i16> %1 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> %1) + ret <16 x i16> %2 +} + +define <16 x i16> @avx2_psrl_w_var_bc(<16 x i16> %v, <16 x i8> %a) { +; CHECK-LABEL: @avx2_psrl_w_var_bc +; CHECK-NEXT: %1 = bitcast <16 x i8> %a to <8 x i16> +; CHECK-NEXT: %2 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> %1) +; CHECK-NEXT: ret <16 x i16> %2 + %1 = shufflevector <16 x i8> %a, <16 x i8> undef, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %2 = bitcast <16 x i8> %1 to <8 x i16> + %3 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> %v, <8 x i16> %2) + ret <16 x i16> %3 +} + +define <8 x i32> @avx2_psrl_d_var(<8 x i32> %v, <4 x i32> %a) { +; CHECK-LABEL: @avx2_psrl_d_var +; CHECK-NEXT: %1 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> %a) +; CHECK-NEXT: ret <8 x i32> %1 + %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %2 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> %1) + ret <8 x i32> %2 +} + +define <8 x i32> @avx2_psrl_d_var_bc(<8 x i32> %v, <2 x i64> %a) { +; CHECK-LABEL: @avx2_psrl_d_var_bc +; CHECK-NEXT: %1 = bitcast <2 x i64> %a to <4 x i32> +; CHECK-NEXT: %2 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> %1) +; CHECK-NEXT: ret <8 x i32> %2 + %1 = shufflevector <2 x i64> %a, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = bitcast <2 x i64> %1 to <4 x i32> + %3 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %v, <4 x i32> %2) + ret <8 x i32> %3 +} + +define <4 x i64> @avx2_psrl_q_var(<4 x i64> %v, <2 x i64> %a) { +; CHECK-LABEL: @avx2_psrl_q_var +; CHECK-NEXT: %1 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %v, <2 x i64> %a) +; CHECK-NEXT: ret <4 x i64> %1 + %1 = shufflevector <2 x i64> %a, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %v, <2 x i64> %1) + ret <4 x i64> %2 +} + +define <8 x i16> @sse2_psll_w_var(<8 x i16> %v, <8 x i16> %a) { +; CHECK-LABEL: @sse2_psll_w_var +; CHECK-NEXT: %1 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> %v, <8 x i16> %a) +; CHECK-NEXT: ret <8 x i16> %1 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> %v, <8 x i16> %1) + ret <8 x i16> %2 +} + +define <4 x i32> @sse2_psll_d_var(<4 x i32> %v, <4 x i32> %a) { +; CHECK-LABEL: @sse2_psll_d_var +; CHECK-NEXT: %1 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %v, <4 x i32> %a) +; CHECK-NEXT: ret <4 x i32> %1 + %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %2 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %v, <4 x i32> %1) + ret <4 x i32> %2 +} + +define <2 x i64> @sse2_psll_q_var(<2 x i64> %v, <2 x i64> %a) { +; CHECK-LABEL: @sse2_psll_q_var +; CHECK-NEXT: %1 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %v, <2 x i64> %a) +; CHECK-NEXT: ret <2 x i64> %1 + %1 = shufflevector <2 x i64> %a, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %v, <2 x i64> %1) + ret <2 x i64> %2 +} + +define <16 x i16> @avx2_psll_w_var(<16 x i16> %v, <8 x i16> %a) { +; CHECK-LABEL: @avx2_psll_w_var +; CHECK-NEXT: %1 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> %v, <8 x i16> %a) +; CHECK-NEXT: ret <16 x i16> %1 + %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 0, i32 1, i32 2, i32 3> + %2 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> %v, <8 x i16> %1) + ret <16 x i16> %2 +} + +define <8 x i32> @avx2_psll_d_var(<8 x i32> %v, <4 x i32> %a) { +; CHECK-LABEL: @avx2_psll_d_var +; CHECK-NEXT: %1 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %v, <4 x i32> %a) +; CHECK-NEXT: ret <8 x i32> %1 + %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 0, i32 1> + %2 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %v, <4 x i32> %1) + ret <8 x i32> %2 +} + +define <4 x i64> @avx2_psll_q_var(<4 x i64> %v, <2 x i64> %a) { +; CHECK-LABEL: @avx2_psll_q_var +; CHECK-NEXT: %1 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %v, <2 x i64> %a) +; CHECK-NEXT: ret <4 x i64> %1 + %1 = shufflevector <2 x i64> %a, <2 x i64> undef, <2 x i32> <i32 0, i32 0> + %2 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %v, <2 x i64> %1) + ret <4 x i64> %2 +} + +; +; Constant Folding +; + +define <8 x i16> @test_sse2_psra_w_0(<8 x i16> %A) { +; CHECK-LABEL: @test_sse2_psra_w_0 +; CHECK-NEXT: ret <8 x i16> %A + %1 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %A, i32 0) + %2 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %1, <8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 7, i16 0, i16 0, i16 0>) + %3 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %2, i32 0) + ret <8 x i16> %3 +} + +define <8 x i16> @test_sse2_psra_w_8() { +; CHECK-LABEL: @test_sse2_psra_w_8 +; CHECK-NEXT: ret <8 x i16> <i16 -128, i16 64, i16 32, i16 16, i16 -128, i16 64, i16 32, i16 16> + %1 = bitcast <2 x i64> <i64 1152956690052710400, i64 1152956690052710400> to <8 x i16> + %2 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %1, i32 3) + %3 = tail call <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16> %2, <8 x i16> <i16 3, i16 0, i16 0, i16 0, i16 7, i16 0, i16 0, i16 0>) + %4 = tail call <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16> %3, i32 2) + ret <8 x i16> %4 +} + +define <4 x i32> @test_sse2_psra_d_0(<4 x i32> %A) { +; CHECK-LABEL: @test_sse2_psra_d_0 +; CHECK-NEXT: ret <4 x i32> %A + %1 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %A, i32 0) + %2 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %1, <4 x i32> <i32 0, i32 0, i32 7, i32 0>) + %3 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %1, i32 0) + ret <4 x i32> %3 +} + +define <4 x i32> @sse2_psra_d_8() { +; CHECK-LABEL: @sse2_psra_d_8 +; CHECK-NEXT: ret <4 x i32> <i32 4194432, i32 1048608, i32 4194432, i32 1048608> + %1 = bitcast <2 x i64> <i64 1152956690052710400, i64 1152956690052710400> to <4 x i32> + %2 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %1, i32 3) + %3 = tail call <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32> %2, <4 x i32> <i32 3, i32 0, i32 7, i32 0>) + %4 = tail call <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32> %3, i32 2) + ret <4 x i32> %4 +} + +define <16 x i16> @test_avx2_psra_w_0(<16 x i16> %A) { +; CHECK-LABEL: @test_avx2_psra_w_0 +; CHECK-NEXT: ret <16 x i16> %A + %1 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %A, i32 0) + %2 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %1, <8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 7, i16 0, i16 0, i16 0>) + %3 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %2, i32 0) + ret <16 x i16> %3 +} + +define <16 x i16> @test_avx2_psra_w_8(<16 x i16> %A) { +; CHECK-LABEL: @test_avx2_psra_w_8 +; CHECK-NEXT: ret <16 x i16> <i16 -128, i16 64, i16 32, i16 16, i16 -128, i16 64, i16 32, i16 16, i16 -128, i16 64, i16 32, i16 16, i16 -128, i16 64, i16 32, i16 16> + %1 = bitcast <4 x i64> <i64 1152956690052710400, i64 1152956690052710400, i64 1152956690052710400, i64 1152956690052710400> to <16 x i16> + %2 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %1, i32 3) + %3 = tail call <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16> %2, <8 x i16> <i16 3, i16 0, i16 0, i16 0, i16 7, i16 0, i16 0, i16 0>) + %4 = tail call <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16> %3, i32 2) + ret <16 x i16> %4 +} + +define <8 x i32> @test_avx2_psra_d_0(<8 x i32> %A) { +; CHECK-LABEL: @test_avx2_psra_d_0 +; CHECK-NEXT: ret <8 x i32> %A + %1 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %A, i32 0) + %2 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %1, <4 x i32> <i32 0, i32 0, i32 7, i32 0>) + %3 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %2, i32 0) + ret <8 x i32> %3 +} + +define <8 x i32> @test_avx2_psra_d_8() { +; CHECK-LABEL: @test_avx2_psra_d_8 +; CHECK-NEXT: ret <8 x i32> <i32 4194432, i32 1048608, i32 4194432, i32 1048608, i32 4194432, i32 1048608, i32 4194432, i32 1048608> + %1 = bitcast <4 x i64> <i64 1152956690052710400, i64 1152956690052710400, i64 1152956690052710400, i64 1152956690052710400> to <8 x i32> + %2 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %1, i32 3) + %3 = tail call <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32> %2, <4 x i32> <i32 3, i32 0, i32 7, i32 0>) + %4 = tail call <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32> %3, i32 2) + ret <8 x i32> %4 +} + +define <2 x i64> @test_sse2_1() { + %S = bitcast i32 1 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> %4) + %6 = bitcast <8 x i16> %5 to <4 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %6, <4 x i32> %7) + %9 = bitcast <4 x i32> %8 to <2 x i64> + %10 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %9, <2 x i64> %3) + %11 = bitcast <2 x i64> %10 to <8 x i16> + %12 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %11, i32 %S) + %13 = bitcast <8 x i16> %12 to <4 x i32> + %14 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %13, i32 %S) + %15 = bitcast <4 x i32> %14 to <2 x i64> + %16 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %15, i32 %S) + ret <2 x i64> %16 +; CHECK: test_sse2_1 +; CHECK: ret <2 x i64> <i64 72058418680037440, i64 144117112246370624> +} + +define <4 x i64> @test_avx2_1() { + %S = bitcast i32 1 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> <i16 1, i16 0, i16 0, i16 0, i16 2, i16 0, i16 0, i16 0, i16 3, i16 0, i16 0, i16 0, i16 4, i16 0, i16 0, i16 0>, <8 x i16> %4) + %6 = bitcast <16 x i16> %5 to <8 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %6, <4 x i32> %7) + %9 = bitcast <8 x i32> %8 to <4 x i64> + %10 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %9, <2 x i64> %3) + %11 = bitcast <4 x i64> %10 to <16 x i16> + %12 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %11, i32 %S) + %13 = bitcast <16 x i16> %12 to <8 x i32> + %14 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %13, i32 %S) + %15 = bitcast <8 x i32> %14 to <4 x i64> + %16 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %15, i32 %S) + ret <4 x i64> %16 +; CHECK: test_avx2_1 +; CHECK: ret <4 x i64> <i64 64, i64 128, i64 192, i64 256> +} + +define <2 x i64> @test_sse2_0() { + %S = bitcast i32 128 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> %4) + %6 = bitcast <8 x i16> %5 to <4 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %6, <4 x i32> %7) + %9 = bitcast <4 x i32> %8 to <2 x i64> + %10 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %9, <2 x i64> %3) + %11 = bitcast <2 x i64> %10 to <8 x i16> + %12 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %11, i32 %S) + %13 = bitcast <8 x i16> %12 to <4 x i32> + %14 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %13, i32 %S) + %15 = bitcast <4 x i32> %14 to <2 x i64> + %16 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %15, i32 %S) + ret <2 x i64> %16 +; CHECK: test_sse2_0 +; CHECK: ret <2 x i64> zeroinitializer +} + +define <4 x i64> @test_avx2_0() { + %S = bitcast i32 128 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> <i16 1, i16 0, i16 0, i16 0, i16 2, i16 0, i16 0, i16 0, i16 3, i16 0, i16 0, i16 0, i16 4, i16 0, i16 0, i16 0>, <8 x i16> %4) + %6 = bitcast <16 x i16> %5 to <8 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %6, <4 x i32> %7) + %9 = bitcast <8 x i32> %8 to <4 x i64> + %10 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %9, <2 x i64> %3) + %11 = bitcast <4 x i64> %10 to <16 x i16> + %12 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %11, i32 %S) + %13 = bitcast <16 x i16> %12 to <8 x i32> + %14 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %13, i32 %S) + %15 = bitcast <8 x i32> %14 to <4 x i64> + %16 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %15, i32 %S) + ret <4 x i64> %16 +; CHECK: test_avx2_0 +; CHECK: ret <4 x i64> zeroinitializer +} +define <2 x i64> @test_sse2_psrl_1() { + %S = bitcast i32 1 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> <i16 16, i16 32, i16 64, i16 128, i16 256, i16 512, i16 1024, i16 2048>, <8 x i16> %4) + %6 = bitcast <8 x i16> %5 to <4 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %6, <4 x i32> %7) + %9 = bitcast <4 x i32> %8 to <2 x i64> + %10 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %9, <2 x i64> %3) + %11 = bitcast <2 x i64> %10 to <8 x i16> + %12 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %11, i32 %S) + %13 = bitcast <8 x i16> %12 to <4 x i32> + %14 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %13, i32 %S) + %15 = bitcast <4 x i32> %14 to <2 x i64> + %16 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %15, i32 %S) + ret <2 x i64> %16 +; CHECK: test_sse2_psrl_1 +; CHECK: ret <2 x i64> <i64 562954248421376, i64 9007267974742020> +} + +define <4 x i64> @test_avx2_psrl_1() { + %S = bitcast i32 1 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> <i16 1024, i16 0, i16 0, i16 0, i16 2048, i16 0, i16 0, i16 0, i16 4096, i16 0, i16 0, i16 0, i16 8192, i16 0, i16 0, i16 0>, <8 x i16> %4) + %6 = bitcast <16 x i16> %5 to <8 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %6, <4 x i32> %7) + %9 = bitcast <8 x i32> %8 to <4 x i64> + %10 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %9, <2 x i64> %3) + %11 = bitcast <4 x i64> %10 to <16 x i16> + %12 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %11, i32 %S) + %13 = bitcast <16 x i16> %12 to <8 x i32> + %14 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %13, i32 %S) + %15 = bitcast <8 x i32> %14 to <4 x i64> + %16 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %15, i32 %S) + ret <4 x i64> %16 +; CHECK: test_avx2_psrl_1 +; CHECK: ret <4 x i64> <i64 16, i64 32, i64 64, i64 128> +} + +define <2 x i64> @test_sse2_psrl_0() { + %S = bitcast i32 128 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16> <i16 32, i16 64, i16 128, i16 256, i16 512, i16 1024, i16 2048, i16 4096>, <8 x i16> %4) + %6 = bitcast <8 x i16> %5 to <4 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32> %6, <4 x i32> %7) + %9 = bitcast <4 x i32> %8 to <2 x i64> + %10 = tail call <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64> %9, <2 x i64> %3) + %11 = bitcast <2 x i64> %10 to <8 x i16> + %12 = tail call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %11, i32 %S) + %13 = bitcast <8 x i16> %12 to <4 x i32> + %14 = tail call <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32> %13, i32 %S) + %15 = bitcast <4 x i32> %14 to <2 x i64> + %16 = tail call <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64> %15, i32 %S) + ret <2 x i64> %16 +; CHECK: test_sse2_psrl_0 +; CHECK: ret <2 x i64> zeroinitializer +} + +define <4 x i64> @test_avx2_psrl_0() { + %S = bitcast i32 128 to i32 + %1 = zext i32 %S to i64 + %2 = insertelement <2 x i64> undef, i64 %1, i32 0 + %3 = insertelement <2 x i64> %2, i64 0, i32 1 + %4 = bitcast <2 x i64> %3 to <8 x i16> + %5 = tail call <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16> <i16 1024, i16 0, i16 0, i16 0, i16 2048, i16 0, i16 0, i16 0, i16 4096, i16 0, i16 0, i16 0, i16 8192, i16 0, i16 0, i16 0>, <8 x i16> %4) + %6 = bitcast <16 x i16> %5 to <8 x i32> + %7 = bitcast <2 x i64> %3 to <4 x i32> + %8 = tail call <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32> %6, <4 x i32> %7) + %9 = bitcast <8 x i32> %8 to <4 x i64> + %10 = tail call <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64> %9, <2 x i64> %3) + %11 = bitcast <4 x i64> %10 to <16 x i16> + %12 = tail call <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16> %11, i32 %S) + %13 = bitcast <16 x i16> %12 to <8 x i32> + %14 = tail call <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32> %13, i32 %S) + %15 = bitcast <8 x i32> %14 to <4 x i64> + %16 = tail call <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64> %15, i32 %S) + ret <4 x i64> %16 +; CHECK: test_avx2_psrl_0 +; CHECK: ret <4 x i64> zeroinitializer +} + +declare <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64>, i32) #1 +declare <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32>, i32) #1 +declare <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16>, i32) #1 +declare <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64>, <2 x i64>) #1 +declare <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32>, <4 x i32>) #1 +declare <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16>, <8 x i16>) #1 +declare <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64>, i32) #1 +declare <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32>, i32) #1 +declare <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16>, i32) #1 +declare <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64>, <2 x i64>) #1 +declare <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32>, <4 x i32>) #1 +declare <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16>, <8 x i16>) #1 + +declare <4 x i64> @llvm.x86.avx2.psrli.q(<4 x i64>, i32) #1 +declare <8 x i32> @llvm.x86.avx2.psrli.d(<8 x i32>, i32) #1 +declare <16 x i16> @llvm.x86.avx2.psrli.w(<16 x i16>, i32) #1 +declare <4 x i64> @llvm.x86.avx2.psrl.q(<4 x i64>, <2 x i64>) #1 +declare <8 x i32> @llvm.x86.avx2.psrl.d(<8 x i32>, <4 x i32>) #1 +declare <16 x i16> @llvm.x86.avx2.psrl.w(<16 x i16>, <8 x i16>) #1 +declare <2 x i64> @llvm.x86.sse2.psrli.q(<2 x i64>, i32) #1 +declare <4 x i32> @llvm.x86.sse2.psrli.d(<4 x i32>, i32) #1 +declare <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16>, i32) #1 +declare <2 x i64> @llvm.x86.sse2.psrl.q(<2 x i64>, <2 x i64>) #1 +declare <4 x i32> @llvm.x86.sse2.psrl.d(<4 x i32>, <4 x i32>) #1 +declare <8 x i16> @llvm.x86.sse2.psrl.w(<8 x i16>, <8 x i16>) #1 + +declare <8 x i32> @llvm.x86.avx2.psrai.d(<8 x i32>, i32) #1 +declare <16 x i16> @llvm.x86.avx2.psrai.w(<16 x i16>, i32) #1 +declare <8 x i32> @llvm.x86.avx2.psra.d(<8 x i32>, <4 x i32>) #1 +declare <16 x i16> @llvm.x86.avx2.psra.w(<16 x i16>, <8 x i16>) #1 +declare <4 x i32> @llvm.x86.sse2.psrai.d(<4 x i32>, i32) #1 +declare <8 x i16> @llvm.x86.sse2.psrai.w(<8 x i16>, i32) #1 +declare <4 x i32> @llvm.x86.sse2.psra.d(<4 x i32>, <4 x i32>) #1 +declare <8 x i16> @llvm.x86.sse2.psra.w(<8 x i16>, <8 x i16>) #1 + +attributes #1 = { nounwind readnone } diff --git a/test/Transforms/InstCombine/x86-xop.ll b/test/Transforms/InstCombine/x86-xop.ll new file mode 100644 index 000000000000..176c504989df --- /dev/null +++ b/test/Transforms/InstCombine/x86-xop.ll @@ -0,0 +1,209 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define <2 x i64> @cmp_slt_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: @cmp_slt_v2i64 +; CHECK-NEXT: %1 = icmp slt <2 x i64> %a, %b +; CHECK-NEXT: %2 = sext <2 x i1> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + %1 = tail call <2 x i64> @llvm.x86.xop.vpcomltq(<2 x i64> %a, <2 x i64> %b) + ret <2 x i64> %1 +} + +define <2 x i64> @cmp_ult_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: @cmp_ult_v2i64 +; CHECK-NEXT: %1 = icmp ult <2 x i64> %a, %b +; CHECK-NEXT: %2 = sext <2 x i1> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + %1 = tail call <2 x i64> @llvm.x86.xop.vpcomltuq(<2 x i64> %a, <2 x i64> %b) + ret <2 x i64> %1 +} + +define <2 x i64> @cmp_sle_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: @cmp_sle_v2i64 +; CHECK-NEXT: %1 = icmp sle <2 x i64> %a, %b +; CHECK-NEXT: %2 = sext <2 x i1> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + %1 = tail call <2 x i64> @llvm.x86.xop.vpcomleq(<2 x i64> %a, <2 x i64> %b) + ret <2 x i64> %1 +} + +define <2 x i64> @cmp_ule_v2i64(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: @cmp_ule_v2i64 +; CHECK-NEXT: %1 = icmp ule <2 x i64> %a, %b +; CHECK-NEXT: %2 = sext <2 x i1> %1 to <2 x i64> +; CHECK-NEXT: ret <2 x i64> %2 + %1 = tail call <2 x i64> @llvm.x86.xop.vpcomleuq(<2 x i64> %a, <2 x i64> %b) + ret <2 x i64> %1 +} + +define <4 x i32> @cmp_sgt_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @cmp_sgt_v4i32 +; CHECK-NEXT: %1 = icmp sgt <4 x i32> %a, %b +; CHECK-NEXT: %2 = sext <4 x i1> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + %1 = tail call <4 x i32> @llvm.x86.xop.vpcomgtd(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %1 +} + +define <4 x i32> @cmp_ugt_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @cmp_ugt_v4i32 +; CHECK-NEXT: %1 = icmp ugt <4 x i32> %a, %b +; CHECK-NEXT: %2 = sext <4 x i1> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + %1 = tail call <4 x i32> @llvm.x86.xop.vpcomgtud(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %1 +} + +define <4 x i32> @cmp_sge_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @cmp_sge_v4i32 +; CHECK-NEXT: %1 = icmp sge <4 x i32> %a, %b +; CHECK-NEXT: %2 = sext <4 x i1> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + %1 = tail call <4 x i32> @llvm.x86.xop.vpcomged(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %1 +} + +define <4 x i32> @cmp_uge_v4i32(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @cmp_uge_v4i32 +; CHECK-NEXT: %1 = icmp uge <4 x i32> %a, %b +; CHECK-NEXT: %2 = sext <4 x i1> %1 to <4 x i32> +; CHECK-NEXT: ret <4 x i32> %2 + %1 = tail call <4 x i32> @llvm.x86.xop.vpcomgeud(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %1 +} + +define <8 x i16> @cmp_seq_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK-LABEL: @cmp_seq_v8i16 +; CHECK-NEXT: %1 = icmp eq <8 x i16> %a, %b +; CHECK-NEXT: %2 = sext <8 x i1> %1 to <8 x i16> +; CHECK-NEXT: ret <8 x i16> %2 + %1 = tail call <8 x i16> @llvm.x86.xop.vpcomeqw(<8 x i16> %a, <8 x i16> %b) + ret <8 x i16> %1 +} + +define <8 x i16> @cmp_ueq_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK-LABEL: @cmp_ueq_v8i16 +; CHECK-NEXT: %1 = icmp eq <8 x i16> %a, %b +; CHECK-NEXT: %2 = sext <8 x i1> %1 to <8 x i16> +; CHECK-NEXT: ret <8 x i16> %2 + %1 = tail call <8 x i16> @llvm.x86.xop.vpcomequw(<8 x i16> %a, <8 x i16> %b) + ret <8 x i16> %1 +} + +define <8 x i16> @cmp_sne_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK-LABEL: @cmp_sne_v8i16 +; CHECK-NEXT: %1 = icmp ne <8 x i16> %a, %b +; CHECK-NEXT: %2 = sext <8 x i1> %1 to <8 x i16> +; CHECK-NEXT: ret <8 x i16> %2 + %1 = tail call <8 x i16> @llvm.x86.xop.vpcomnew(<8 x i16> %a, <8 x i16> %b) + ret <8 x i16> %1 +} + +define <8 x i16> @cmp_une_v8i16(<8 x i16> %a, <8 x i16> %b) { +; CHECK-LABEL: @cmp_une_v8i16 +; CHECK-NEXT: %1 = icmp ne <8 x i16> %a, %b +; CHECK-NEXT: %2 = sext <8 x i1> %1 to <8 x i16> +; CHECK-NEXT: ret <8 x i16> %2 + %1 = tail call <8 x i16> @llvm.x86.xop.vpcomneuw(<8 x i16> %a, <8 x i16> %b) + ret <8 x i16> %1 +} + +define <16 x i8> @cmp_strue_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: @cmp_strue_v16i8 +; CHECK-NEXT: ret <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> + %1 = tail call <16 x i8> @llvm.x86.xop.vpcomtrueb(<16 x i8> %a, <16 x i8> %b) + ret <16 x i8> %1 +} + +define <16 x i8> @cmp_utrue_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: @cmp_utrue_v16i8 +; CHECK-NEXT: ret <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1> + %1 = tail call <16 x i8> @llvm.x86.xop.vpcomtrueub(<16 x i8> %a, <16 x i8> %b) + ret <16 x i8> %1 +} + +define <16 x i8> @cmp_sfalse_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: @cmp_sfalse_v16i8 +; CHECK-NEXT: ret <16 x i8> zeroinitializer + %1 = tail call <16 x i8> @llvm.x86.xop.vpcomfalseb(<16 x i8> %a, <16 x i8> %b) + ret <16 x i8> %1 +} + +define <16 x i8> @cmp_ufalse_v16i8(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: @cmp_ufalse_v16i8 +; CHECK-NEXT: ret <16 x i8> zeroinitializer + %1 = tail call <16 x i8> @llvm.x86.xop.vpcomfalseub(<16 x i8> %a, <16 x i8> %b) + ret <16 x i8> %1 +} + +declare <16 x i8> @llvm.x86.xop.vpcomltb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomltw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomltd(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomltq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomltub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomltuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomltud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomltuq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomleb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomlew(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomled(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomleq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomleub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomleuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomleud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomleuq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomgtb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomgtw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomgtd(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomgtq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomgtub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomgtuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomgtud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomgtuq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomgeb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomgew(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomged(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomgeq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomgeub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomgeuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomgeud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomgeuq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomeqb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomeqw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomeqd(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomeqq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomequb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomequw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomequd(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomequq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomneb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomnew(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomned(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomneq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomneub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomneuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomneud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomneuq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomfalseb(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomfalsew(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomfalsed(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomfalseq(<2 x i64>, <2 x i64>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomfalseub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomfalseuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomfalseud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomfalseuq(<2 x i64>, <2 x i64>) nounwind readnone + +declare <16 x i8> @llvm.x86.xop.vpcomtrueb(<16 x i8>, <16 x i8>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomtrued(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomtrueq(<2 x i64>, <2 x i64>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomtruew(<8 x i16>, <8 x i16>) nounwind readnone +declare <16 x i8> @llvm.x86.xop.vpcomtrueub(<16 x i8>, <16 x i8>) nounwind readnone +declare <8 x i16> @llvm.x86.xop.vpcomtrueuw(<8 x i16>, <8 x i16>) nounwind readnone +declare <4 x i32> @llvm.x86.xop.vpcomtrueud(<4 x i32>, <4 x i32>) nounwind readnone +declare <2 x i64> @llvm.x86.xop.vpcomtrueuq(<2 x i64>, <2 x i64>) nounwind readnone diff --git a/test/Transforms/InstCombine/xor.ll b/test/Transforms/InstCombine/xor.ll index 33d5a2a9fda5..c8debcbac226 100644 --- a/test/Transforms/InstCombine/xor.ll +++ b/test/Transforms/InstCombine/xor.ll @@ -63,8 +63,8 @@ define i32 @test7(i32 %A, i32 %B) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: %A1 = and i32 %A, 7 ; CHECK-NEXT: %B1 = and i32 %B, 128 -; CHECK-NEXT: %C1.1 = or i32 %A1, %B1 -; CHECK-NEXT: ret i32 %C1.1 +; CHECK-NEXT: %C11 = or i32 %A1, %B1 +; CHECK-NEXT: ret i32 %C11 %A1 = and i32 %A, 7 ; <i32> [#uses=1] %B1 = and i32 %B, 128 ; <i32> [#uses=1] %C1 = xor i32 %A1, %B1 ; <i32> [#uses=1] @@ -96,8 +96,8 @@ define i1 @test9(i8 %A) { define i8 @test10(i8 %A) { ; CHECK-LABEL: @test10( ; CHECK-NEXT: %B = and i8 %A, 3 -; CHECK-NEXT: %C.1 = or i8 %B, 4 -; CHECK-NEXT: ret i8 %C.1 +; CHECK-NEXT: %C1 = or i8 %B, 4 +; CHECK-NEXT: ret i8 %C1 %B = and i8 %A, 3 ; <i8> [#uses=1] %C = xor i8 %B, 4 ; <i8> [#uses=1] ret i8 %C |
