From: Sanjay Patel Date: Fri, 6 Jul 2018 17:24:32 +0000 (+0000) Subject: [InstCombine] add more tests with poison and undef; NFC X-Git-Tag: llvmorg-7.0.0-rc1~2060 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a212b0bc18c9095d6580de6a85740114d1e94916;p=platform%2Fupstream%2Fllvm.git [InstCombine] add more tests with poison and undef; NFC As discussed in D48987 and D48893, there are many different ways to go wrong depending on the binop (and as shown here we already do go wrong in some cases). llvm-svn: 336450 --- diff --git a/llvm/test/Transforms/InstCombine/shuffle_select.ll b/llvm/test/Transforms/InstCombine/shuffle_select.ll index 4216f99..ee6d843 100644 --- a/llvm/test/Transforms/InstCombine/shuffle_select.ll +++ b/llvm/test/Transforms/InstCombine/shuffle_select.ll @@ -14,6 +14,40 @@ define <4 x i32> @add(<4 x i32> %v) { ret <4 x i32> %s } +; Propagate flags when possible. + +define <4 x i32> @add_nuw_nsw(<4 x i32> %v) { +; CHECK-LABEL: @add_nuw_nsw( +; CHECK-NEXT: [[S:%.*]] = add nuw nsw <4 x i32> [[V:%.*]], +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = add nuw nsw <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @add_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @add_undef_mask_elt( +; CHECK-NEXT: [[S:%.*]] = add <4 x i32> [[V:%.*]], +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = add <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +; FIXME: Poison flags must be dropped or undef must be replaced with safe constant. + +define <4 x i32> @add_nuw_nsw_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @add_nuw_nsw_undef_mask_elt( +; CHECK-NEXT: [[S:%.*]] = add nuw nsw <4 x i32> [[V:%.*]], +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = add nuw nsw <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + ; Constant operand 0 (LHS) could work for some non-commutative binops? define <4 x i32> @sub(<4 x i32> %v) { @@ -29,7 +63,8 @@ define <4 x i32> @sub(<4 x i32> %v) { ; If any element of the shuffle mask operand is undef, that element of the result is undef. ; The shuffle is eliminated in this transform, but we can replace a constant element with undef. -; Preserve flags when possible. +; FIXME: +; Preserve flags when possible. It's not safe to propagate poison-generating flags with undef constants. define <4 x i32> @mul(<4 x i32> %v) { ; CHECK-LABEL: @mul( @@ -43,6 +78,39 @@ define <4 x i32> @mul(<4 x i32> %v) { define <4 x i32> @shl(<4 x i32> %v) { ; CHECK-LABEL: @shl( +; CHECK-NEXT: [[B:%.*]] = shl <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = shl <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @shl_nsw(<4 x i32> %v) { +; CHECK-LABEL: @shl_nsw( +; CHECK-NEXT: [[B:%.*]] = shl nsw <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = shl nsw <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @shl_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @shl_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = shl <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = shl <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @shl_nuw_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @shl_nuw_undef_mask_elt( ; CHECK-NEXT: [[B:%.*]] = shl nuw <4 x i32> [[V:%.*]], ; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[S]] @@ -54,6 +122,17 @@ define <4 x i32> @shl(<4 x i32> %v) { define <4 x i32> @lshr_constant_op0(<4 x i32> %v) { ; CHECK-LABEL: @lshr_constant_op0( +; CHECK-NEXT: [[B:%.*]] = lshr <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = lshr <4 x i32> %v, + %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @lshr_exact_constant_op0(<4 x i32> %v) { +; CHECK-LABEL: @lshr_exact_constant_op0( ; CHECK-NEXT: [[B:%.*]] = lshr exact <4 x i32> [[V:%.*]], ; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[S]] @@ -62,6 +141,29 @@ define <4 x i32> @lshr_constant_op0(<4 x i32> %v) { %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> ret <4 x i32> %s } + +define <4 x i32> @lshr_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @lshr_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = shl <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = shl <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @lshr_exact_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @lshr_exact_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = lshr exact <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = lshr exact <4 x i32> %v, + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + define <4 x i32> @lshr_constant_op1(<4 x i32> %v) { ; CHECK-LABEL: @lshr_constant_op1( ; CHECK-NEXT: [[B:%.*]] = lshr exact <4 x i32> , [[V:%.*]] @@ -134,11 +236,66 @@ define <4 x i32> @udiv(<4 x i32> %v) { ret <4 x i32> %s } -; Div/rem need special handling if the shuffle has undef elements. +define <4 x i32> @udiv_exact(<4 x i32> %v) { +; CHECK-LABEL: @udiv_exact( +; CHECK-NEXT: [[B:%.*]] = udiv exact <4 x i32> , [[V:%.*]] +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = udiv exact <4 x i32> , %v + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @udiv_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @udiv_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = udiv <4 x i32> , [[V:%.*]] +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = udiv <4 x i32> , %v + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @udiv_exact_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @udiv_exact_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = udiv exact <4 x i32> , [[V:%.*]] +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = udiv exact <4 x i32> , %v + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} define <4 x i32> @sdiv(<4 x i32> %v) { ; CHECK-LABEL: @sdiv( ; CHECK-NEXT: [[B:%.*]] = sdiv <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = sdiv <4 x i32> %v, + %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @sdiv_exact(<4 x i32> %v) { +; CHECK-LABEL: @sdiv_exact( +; CHECK-NEXT: [[B:%.*]] = sdiv exact <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = sdiv exact <4 x i32> %v, + %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> + ret <4 x i32> %s +} + +; Div/rem need special handling if the shuffle has undef elements. + +define <4 x i32> @sdiv_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @sdiv_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = sdiv <4 x i32> [[V:%.*]], ; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[S]] ; @@ -147,9 +304,31 @@ define <4 x i32> @sdiv(<4 x i32> %v) { ret <4 x i32> %s } +define <4 x i32> @sdiv_exact_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @sdiv_exact_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = sdiv exact <4 x i32> [[V:%.*]], +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = sdiv exact <4 x i32> %v, + %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> + ret <4 x i32> %s +} + define <4 x i32> @urem(<4 x i32> %v) { ; CHECK-LABEL: @urem( ; CHECK-NEXT: [[B:%.*]] = urem <4 x i32> , [[V:%.*]] +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[S]] +; + %b = urem <4 x i32> , %v + %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> + ret <4 x i32> %s +} + +define <4 x i32> @urem_undef_mask_elt(<4 x i32> %v) { +; CHECK-LABEL: @urem_undef_mask_elt( +; CHECK-NEXT: [[B:%.*]] = urem <4 x i32> , [[V:%.*]] ; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[S]] ; @@ -250,6 +429,41 @@ define <4 x i32> @add_add(<4 x i32> %v0) { ret <4 x i32> %t3 } +define <4 x i32> @add_add_nsw(<4 x i32> %v0) { +; CHECK-LABEL: @add_add_nsw( +; CHECK-NEXT: [[T3:%.*]] = add nsw <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = add nsw <4 x i32> %v0, + %t2 = add nsw <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @add_add_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @add_add_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = add <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = add <4 x i32> %v0, + %t2 = add <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Poison flags must be dropped or undef must be replaced with safe constant. + +define <4 x i32> @add_add_nsw_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @add_add_nsw_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = add nsw <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = add nsw <4 x i32> %v0, + %t2 = add nsw <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + ; Constant operand 0 (LHS) also works. define <4 x i32> @sub_sub(<4 x i32> %v0) { @@ -263,6 +477,41 @@ define <4 x i32> @sub_sub(<4 x i32> %v0) { ret <4 x i32> %t3 } +define <4 x i32> @sub_sub_nuw(<4 x i32> %v0) { +; CHECK-LABEL: @sub_sub_nuw( +; CHECK-NEXT: [[T3:%.*]] = sub nuw <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub nuw <4 x i32> , %v0 + %t2 = sub nuw <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @sub_sub_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @sub_sub_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = sub <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub <4 x i32> , %v0 + %t2 = sub <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Poison flags must be dropped or undef must be replaced with safe constant. + +define <4 x i32> @sub_sub_nuw_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @sub_sub_nuw_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = sub nuw <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub nuw <4 x i32> , %v0 + %t2 = sub nuw <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + ; If any element of the shuffle mask operand is undef, that element of the result is undef. ; The shuffle is eliminated in this transform, but we can replace a constant element with undef. @@ -281,6 +530,43 @@ define <4 x i32> @mul_mul(<4 x i32> %v0) { define <4 x i32> @shl_shl(<4 x i32> %v0) { ; CHECK-LABEL: @shl_shl( +; CHECK-NEXT: [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl <4 x i32> %v0, + %t2 = shl <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @shl_shl_nuw(<4 x i32> %v0) { +; CHECK-LABEL: @shl_shl_nuw( +; CHECK-NEXT: [[T3:%.*]] = shl nuw <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl nuw <4 x i32> %v0, + %t2 = shl nuw <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Shift by undef is poison. Undef must be replaced by safe constant. + +define <4 x i32> @shl_shl_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @shl_shl_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl <4 x i32> %v0, + %t2 = shl <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Shift by undef is poison. Undef must be replaced by safe constant. + +define <4 x i32> @shl_shl_nuw_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @shl_shl_nuw_undef_mask_elt( ; CHECK-NEXT: [[T3:%.*]] = shl nuw <4 x i32> [[V0:%.*]], ; CHECK-NEXT: ret <4 x i32> [[T3]] ; @@ -378,6 +664,28 @@ define <4 x i32> @udiv_udiv(<4 x i32> %v0) { define <4 x i32> @sdiv_sdiv(<4 x i32> %v0) { ; CHECK-LABEL: @sdiv_sdiv( +; CHECK-NEXT: [[T3:%.*]] = sdiv <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv <4 x i32> %v0, + %t2 = sdiv <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @sdiv_sdiv_exact(<4 x i32> %v0) { +; CHECK-LABEL: @sdiv_sdiv_exact( +; CHECK-NEXT: [[T3:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv exact <4 x i32> %v0, + %t2 = sdiv exact <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @sdiv_sdiv_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @sdiv_sdiv_undef_mask_elt( ; CHECK-NEXT: [[T3:%.*]] = sdiv <4 x i32> [[V0:%.*]], ; CHECK-NEXT: ret <4 x i32> [[T3]] ; @@ -387,8 +695,30 @@ define <4 x i32> @sdiv_sdiv(<4 x i32> %v0) { ret <4 x i32> %t3 } +define <4 x i32> @sdiv_sdiv_exact_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @sdiv_sdiv_exact_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv exact <4 x i32> %v0, + %t2 = sdiv exact <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + define <4 x i32> @urem_urem(<4 x i32> %v0) { ; CHECK-LABEL: @urem_urem( +; CHECK-NEXT: [[T3:%.*]] = urem <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = urem <4 x i32> , %v0 + %t2 = urem <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @urem_urem_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @urem_urem_undef_mask_elt( ; CHECK-NEXT: [[T3:%.*]] = urem <4 x i32> , [[V0:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T3]] ; @@ -409,6 +739,17 @@ define <4 x i32> @srem_srem(<4 x i32> %v0) { ret <4 x i32> %t3 } +define <4 x i32> @srem_srem_undef_mask_elt(<4 x i32> %v0) { +; CHECK-LABEL: @srem_srem_undef_mask_elt( +; CHECK-NEXT: [[T3:%.*]] = srem <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = srem <4 x i32> , %v0 + %t2 = srem <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + ; Try FP ops/types. define <4 x float> @fadd_fadd(<4 x float> %v0) { @@ -498,18 +839,94 @@ define <4 x i32> @sub_2_vars(<4 x i32> %v0, <4 x i32> %v1) { ret <4 x i32> %t3 } +define <4 x i32> @sub_2_vars_nsw(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @sub_2_vars_nsw( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = sub nsw <4 x i32> , [[TMP1]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub nsw <4 x i32> , %v0 + %t2 = sub nsw <4 x i32> , %v1 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @sub_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @sub_2_vars_undef_mask_elt( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = sub <4 x i32> , [[TMP1]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub <4 x i32> , %v0 + %t2 = sub <4 x i32> , %v1 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Poison flags must be dropped or undef must be replaced with safe constant. + +define <4 x i32> @sub_2_vars_nsw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @sub_2_vars_nsw_undef_mask_elt( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = sub nsw <4 x i32> , [[TMP1]] +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub nsw <4 x i32> , %v0 + %t2 = sub nsw <4 x i32> , %v1 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + ; If any element of the shuffle mask operand is undef, that element of the result is undef. ; The shuffle is eliminated in this transform, but we can replace a constant element with undef. define <4 x i32> @mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) { ; CHECK-LABEL: @mul_2_vars( -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> -; CHECK-NEXT: [[T3:%.*]] = mul <4 x i32> [[TMP1]], +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = mul <4 x i32> [[TMP1]], ; CHECK-NEXT: ret <4 x i32> [[T3]] ; %t1 = mul <4 x i32> %v0, %t2 = mul <4 x i32> %v1, - %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @mul_2_vars_nuw(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @mul_2_vars_nuw( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = mul nuw <4 x i32> %v0, + %t2 = mul nuw <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @mul_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @mul_2_vars_undef_mask_elt( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = mul <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = mul <4 x i32> %v0, + %t2 = mul <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Poison flags must be dropped or undef must be replaced with safe constant. + +define <4 x i32> @mul_2_vars_nuw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @mul_2_vars_nuw_undef_mask_elt( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = mul nuw <4 x i32> %v0, + %t2 = mul nuw <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> ret <4 x i32> %t3 } @@ -517,6 +934,46 @@ define <4 x i32> @mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) { define <4 x i32> @shl_2_vars(<4 x i32> %v0, <4 x i32> %v1) { ; CHECK-LABEL: @shl_2_vars( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = shl <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl <4 x i32> %v0, + %t2 = shl <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @shl_2_vars_nsw(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @shl_2_vars_nsw( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = shl nsw <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl nsw <4 x i32> %v0, + %t2 = shl nsw <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Shift by undef is poison. Undef must be replaced by safe constant. + +define <4 x i32> @shl_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @shl_2_vars_undef_mask_elt( +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> +; CHECK-NEXT: [[T3:%.*]] = shl <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl <4 x i32> %v0, + %t2 = shl <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; FIXME: Shift by undef is poison. Undef must be replaced by safe constant. + +define <4 x i32> @shl_2_vars_nsw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @shl_2_vars_nsw_undef_mask_elt( ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> ; CHECK-NEXT: [[T3:%.*]] = shl nsw <4 x i32> [[TMP1]], ; CHECK-NEXT: ret <4 x i32> [[T3]] @@ -609,6 +1066,32 @@ define <4 x i32> @udiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) { ; CHECK-LABEL: @udiv_2_vars( ; CHECK-NEXT: [[T1:%.*]] = udiv <4 x i32> , [[V0:%.*]] ; CHECK-NEXT: [[T2:%.*]] = udiv <4 x i32> , [[V1:%.*]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = udiv <4 x i32> , %v0 + %t2 = udiv <4 x i32> , %v1 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @udiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @udiv_2_vars_exact( +; CHECK-NEXT: [[T1:%.*]] = udiv exact <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = udiv exact <4 x i32> , [[V1:%.*]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = udiv exact <4 x i32> , %v0 + %t2 = udiv exact <4 x i32> , %v1 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @udiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @udiv_2_vars_undef_mask_elt( +; CHECK-NEXT: [[T1:%.*]] = udiv <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = udiv <4 x i32> , [[V1:%.*]] ; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[T3]] ; @@ -618,6 +1101,19 @@ define <4 x i32> @udiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) { ret <4 x i32> %t3 } +define <4 x i32> @udiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @udiv_2_vars_exact_undef_mask_elt( +; CHECK-NEXT: [[T1:%.*]] = udiv exact <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = udiv exact <4 x i32> , [[V1:%.*]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = udiv exact <4 x i32> , %v0 + %t2 = udiv exact <4 x i32> , %v1 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + ; TODO: If the shuffle has no undefs, it's safe to shuffle the variables first. define <4 x i32> @sdiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) { @@ -633,6 +1129,45 @@ define <4 x i32> @sdiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) { ret <4 x i32> %t3 } +define <4 x i32> @sdiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @sdiv_2_vars_exact( +; CHECK-NEXT: [[T1:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = sdiv exact <4 x i32> [[V1:%.*]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv exact <4 x i32> %v0, + %t2 = sdiv exact <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @sdiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @sdiv_2_vars_undef_mask_elt( +; CHECK-NEXT: [[T1:%.*]] = sdiv <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = sdiv <4 x i32> [[V1:%.*]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv <4 x i32> %v0, + %t2 = sdiv <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @sdiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) { +; CHECK-LABEL: @sdiv_2_vars_exact_undef_mask_elt( +; CHECK-NEXT: [[T1:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = sdiv exact <4 x i32> [[V1:%.*]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv exact <4 x i32> %v0, + %t2 = sdiv exact <4 x i32> %v1, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + ; TODO: If the shuffle has no undefs, it's safe to shuffle the variables first. define <4 x i32> @urem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {