From 98c5eebcf786ee970c57a752ac3dfededa90501a Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 26 Sep 2020 20:08:43 +0100 Subject: [PATCH] [InstCombine] Add basic vector test coverage for icmp_eq/ne zero combines --- .../Transforms/InstCombine/onehot_merge.ll | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/onehot_merge.ll b/llvm/test/Transforms/InstCombine/onehot_merge.ll index e667b7f72857..3d40d4b8c008 100644 --- a/llvm/test/Transforms/InstCombine/onehot_merge.ll +++ b/llvm/test/Transforms/InstCombine/onehot_merge.ll @@ -15,6 +15,23 @@ define i1 @and_consts(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @and_consts_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @and_consts_vector( +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[K:%.*]], +; CHECK-NEXT: [[T2:%.*]] = icmp eq <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[K]], +; CHECK-NEXT: [[T6:%.*]] = icmp eq <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %t1 = and <2 x i32> , %k + %t2 = icmp eq <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> , %k + %t6 = icmp eq <2 x i32> %t5, zeroinitializer + %or = or <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + define i1 @foo1_and(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and( ; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] @@ -34,6 +51,27 @@ define i1 @foo1_and(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @foo1_and_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @foo1_and_vector( +; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> , [[C1:%.*]] +; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> , [[C2:%.*]] +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[T]], [[K:%.*]] +; CHECK-NEXT: [[T2:%.*]] = icmp eq <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[T4]], [[K]] +; CHECK-NEXT: [[T6:%.*]] = icmp eq <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %t = shl <2 x i32> , %c1 + %t4 = shl <2 x i32> , %c2 + %t1 = and <2 x i32> %t, %k + %t2 = icmp eq <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> %t4, %k + %t6 = icmp eq <2 x i32> %t5, zeroinitializer + %or = or <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + ; Same as above but with operands commuted one of the ands, but not the other. define i1 @foo1_and_commuted(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and_commuted( @@ -56,6 +94,29 @@ define i1 @foo1_and_commuted(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @foo1_and_commuted_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @foo1_and_commuted_vector( +; CHECK-NEXT: [[K2:%.*]] = mul <2 x i32> [[K:%.*]], [[K]] +; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> , [[C1:%.*]] +; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> , [[C2:%.*]] +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[K2]], [[T]] +; CHECK-NEXT: [[T2:%.*]] = icmp eq <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[T4]], [[K2]] +; CHECK-NEXT: [[T6:%.*]] = icmp eq <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %k2 = mul <2 x i32> %k, %k ; to trick the complexity sorting + %t = shl <2 x i32> , %c1 + %t4 = shl <2 x i32> , %c2 + %t1 = and <2 x i32> %k2, %t + %t2 = icmp eq <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> %t4, %k2 + %t6 = icmp eq <2 x i32> %t5, zeroinitializer + %or = or <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + define i1 @or_consts(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @or_consts( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K:%.*]], 12 @@ -70,6 +131,23 @@ define i1 @or_consts(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @or_consts_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @or_consts_vector( +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[K:%.*]], +; CHECK-NEXT: [[T2:%.*]] = icmp ne <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[K]], +; CHECK-NEXT: [[T6:%.*]] = icmp ne <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %t1 = and <2 x i32> , %k + %t2 = icmp ne <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> , %k + %t6 = icmp ne <2 x i32> %t5, zeroinitializer + %or = and <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + define i1 @foo1_or(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_or( ; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] @@ -89,6 +167,27 @@ define i1 @foo1_or(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @foo1_or_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @foo1_or_vector( +; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> , [[C1:%.*]] +; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> , [[C2:%.*]] +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[T]], [[K:%.*]] +; CHECK-NEXT: [[T2:%.*]] = icmp ne <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[T4]], [[K]] +; CHECK-NEXT: [[T6:%.*]] = icmp ne <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %t = shl <2 x i32> , %c1 + %t4 = shl <2 x i32> , %c2 + %t1 = and <2 x i32> %t, %k + %t2 = icmp ne <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> %t4, %k + %t6 = icmp ne <2 x i32> %t5, zeroinitializer + %or = and <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + ; Same as above but with operands commuted one of the ors, but not the other. define i1 @foo1_or_commuted(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_or_commuted( @@ -111,6 +210,29 @@ define i1 @foo1_or_commuted(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @foo1_or_commuted_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @foo1_or_commuted_vector( +; CHECK-NEXT: [[K2:%.*]] = mul <2 x i32> [[K:%.*]], [[K]] +; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> , [[C1:%.*]] +; CHECK-NEXT: [[T4:%.*]] = shl <2 x i32> , [[C2:%.*]] +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[K2]], [[T]] +; CHECK-NEXT: [[T2:%.*]] = icmp ne <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[T4]], [[K2]] +; CHECK-NEXT: [[T6:%.*]] = icmp ne <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %k2 = mul <2 x i32> %k, %k ; to trick the complexity sorting + %t = shl <2 x i32> , %c1 + %t4 = shl <2 x i32> , %c2 + %t1 = and <2 x i32> %k2, %t + %t2 = icmp ne <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> %t4, %k2 + %t6 = icmp ne <2 x i32> %t5, zeroinitializer + %or = and <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + define i1 @foo1_and_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and_signbit_lshr( ; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] @@ -130,6 +252,27 @@ define i1 @foo1_and_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @foo1_and_signbit_lshr_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @foo1_and_signbit_lshr_vector( +; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> , [[C1:%.*]] +; CHECK-NEXT: [[T4:%.*]] = lshr <2 x i32> , [[C2:%.*]] +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[T]], [[K:%.*]] +; CHECK-NEXT: [[T2:%.*]] = icmp eq <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[T4]], [[K]] +; CHECK-NEXT: [[T6:%.*]] = icmp eq <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %t = shl <2 x i32> , %c1 + %t4 = lshr <2 x i32> , %c2 + %t1 = and <2 x i32> %t, %k + %t2 = icmp eq <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> %t4, %k + %t6 = icmp eq <2 x i32> %t5, zeroinitializer + %or = or <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + define i1 @foo1_or_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_or_signbit_lshr( ; CHECK-NEXT: [[T:%.*]] = shl i32 1, [[C1:%.*]] @@ -149,6 +292,27 @@ define i1 @foo1_or_signbit_lshr(i32 %k, i32 %c1, i32 %c2) { ret i1 %or } +define <2 x i1> @foo1_or_signbit_lshr_vector(<2 x i32> %k, <2 x i32> %c1, <2 x i32> %c2) { +; CHECK-LABEL: @foo1_or_signbit_lshr_vector( +; CHECK-NEXT: [[T:%.*]] = shl <2 x i32> , [[C1:%.*]] +; CHECK-NEXT: [[T4:%.*]] = lshr <2 x i32> , [[C2:%.*]] +; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[T]], [[K:%.*]] +; CHECK-NEXT: [[T2:%.*]] = icmp ne <2 x i32> [[T1]], zeroinitializer +; CHECK-NEXT: [[T5:%.*]] = and <2 x i32> [[T4]], [[K]] +; CHECK-NEXT: [[T6:%.*]] = icmp ne <2 x i32> [[T5]], zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[T2]], [[T6]] +; CHECK-NEXT: ret <2 x i1> [[OR]] +; + %t = shl <2 x i32> , %c1 + %t4 = lshr <2 x i32> , %c2 + %t1 = and <2 x i32> %t, %k + %t2 = icmp ne <2 x i32> %t1, zeroinitializer + %t5 = and <2 x i32> %t4, %k + %t6 = icmp ne <2 x i32> %t5, zeroinitializer + %or = and <2 x i1> %t2, %t6 + ret <2 x i1> %or +} + ; Same as last two, but shift-of-signbit replaced with 'icmp s*' define i1 @foo1_and_signbit_lshr_without_shifting_signbit(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit(