brintos

brintos / llvm-project-archived public Read only

0
0
Text · 64.9 KiB · 3ed7fc2 Raw
1479 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Try to eliminate binops and shuffles when the shuffle is a select in disguise:5; PR37806 - https://bugs.llvm.org/show_bug.cgi?id=378066 7define <4 x i32> @add(<4 x i32> %v) {8; CHECK-LABEL: @add(9; CHECK-NEXT:    [[S:%.*]] = add <4 x i32> [[V:%.*]], <i32 11, i32 0, i32 13, i32 0>10; CHECK-NEXT:    ret <4 x i32> [[S]]11;12  %b = add <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>13  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 5, i32 2, i32 7>14  ret <4 x i32> %s15}16 17; Propagate flags when possible.18 19define <4 x i32> @add_nuw_nsw(<4 x i32> %v) {20; CHECK-LABEL: @add_nuw_nsw(21; CHECK-NEXT:    [[S:%.*]] = add nuw nsw <4 x i32> [[V:%.*]], <i32 11, i32 0, i32 13, i32 0>22; CHECK-NEXT:    ret <4 x i32> [[S]]23;24  %b = add nuw nsw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>25  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 5, i32 2, i32 7>26  ret <4 x i32> %s27}28 29define <4 x i32> @add_undef_mask_elt(<4 x i32> %v) {30; CHECK-LABEL: @add_undef_mask_elt(31; CHECK-NEXT:    [[S:%.*]] = add <4 x i32> [[V:%.*]], <i32 11, i32 0, i32 undef, i32 0>32; CHECK-NEXT:    ret <4 x i32> [[S]]33;34  %b = add <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>35  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 5, i32 undef, i32 7>36  ret <4 x i32> %s37}38 39; Poison flags must be dropped or undef must be replaced with safe constant.40 41define <4 x i32> @add_nuw_nsw_undef_mask_elt(<4 x i32> %v) {42; CHECK-LABEL: @add_nuw_nsw_undef_mask_elt(43; CHECK-NEXT:    [[S:%.*]] = add <4 x i32> [[V:%.*]], <i32 11, i32 undef, i32 13, i32 0>44; CHECK-NEXT:    ret <4 x i32> [[S]]45;46  %b = add nuw nsw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>47  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>48  ret <4 x i32> %s49}50 51; Constant operand 0 (LHS) could work for some non-commutative binops?52 53define <4 x i32> @sub(<4 x i32> %v) {54; CHECK-LABEL: @sub(55; CHECK-NEXT:    [[B:%.*]] = sub <4 x i32> <i32 poison, i32 poison, i32 poison, i32 14>, [[V:%.*]]56; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>57; CHECK-NEXT:    ret <4 x i32> [[S]]58;59  %b = sub <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v60  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 7>61  ret <4 x i32> %s62}63 64; If any element of the shuffle mask operand is undef, that element of the result is undef.65; The shuffle is eliminated in this transform, but we can replace a constant element with undef.66; Preserve flags when possible. It's not safe to propagate poison-generating flags with undef constants.67 68define <4 x i32> @mul(<4 x i32> %v) {69; CHECK-LABEL: @mul(70; CHECK-NEXT:    [[S:%.*]] = mul <4 x i32> [[V:%.*]], <i32 undef, i32 12, i32 1, i32 14>71; CHECK-NEXT:    ret <4 x i32> [[S]]72;73  %b = mul nsw nuw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>74  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>75  ret <4 x i32> %s76}77 78define <4 x i32> @shl(<4 x i32> %v) {79; CHECK-LABEL: @shl(80; CHECK-NEXT:    [[S:%.*]] = shl <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>81; CHECK-NEXT:    ret <4 x i32> [[S]]82;83  %b = shl <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>84  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 4, i32 1, i32 2, i32 7>85  ret <4 x i32> %s86}87 88define <4 x i32> @shl_nsw(<4 x i32> %v) {89; CHECK-LABEL: @shl_nsw(90; CHECK-NEXT:    [[S:%.*]] = shl nsw <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>91; CHECK-NEXT:    ret <4 x i32> [[S]]92;93  %b = shl nsw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>94  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 4, i32 1, i32 2, i32 7>95  ret <4 x i32> %s96}97 98define <4 x i32> @shl_undef_mask_elt(<4 x i32> %v) {99; CHECK-LABEL: @shl_undef_mask_elt(100; CHECK-NEXT:    [[S:%.*]] = shl <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>101; CHECK-NEXT:    ret <4 x i32> [[S]]102;103  %b = shl <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>104  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>105  ret <4 x i32> %s106}107 108define <4 x i32> @shl_nuw_undef_mask_elt(<4 x i32> %v) {109; CHECK-LABEL: @shl_nuw_undef_mask_elt(110; CHECK-NEXT:    [[S:%.*]] = shl nuw <4 x i32> [[V:%.*]], <i32 0, i32 0, i32 13, i32 0>111; CHECK-NEXT:    ret <4 x i32> [[S]]112;113  %b = shl nuw <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>114  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>115  ret <4 x i32> %s116}117 118define <4 x i32> @lshr_constant_op0(<4 x i32> %v) {119; CHECK-LABEL: @lshr_constant_op0(120; CHECK-NEXT:    [[S:%.*]] = lshr <4 x i32> [[V:%.*]], <i32 11, i32 12, i32 0, i32 14>121; CHECK-NEXT:    ret <4 x i32> [[S]]122;123  %b = lshr <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>124  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 5, i32 2, i32 7>125  ret <4 x i32> %s126}127 128define <4 x i32> @lshr_exact_constant_op0(<4 x i32> %v) {129; CHECK-LABEL: @lshr_exact_constant_op0(130; CHECK-NEXT:    [[S:%.*]] = lshr exact <4 x i32> [[V:%.*]], <i32 11, i32 12, i32 0, i32 14>131; CHECK-NEXT:    ret <4 x i32> [[S]]132;133  %b = lshr exact <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>134  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 5, i32 2, i32 7>135  ret <4 x i32> %s136}137 138define <4 x i32> @lshr_undef_mask_elt(<4 x i32> %v) {139; CHECK-LABEL: @lshr_undef_mask_elt(140; CHECK-NEXT:    [[S:%.*]] = shl <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 13, i32 0>141; CHECK-NEXT:    ret <4 x i32> [[S]]142;143  %b = shl <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>144  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>145  ret <4 x i32> %s146}147 148define <4 x i32> @lshr_exact_undef_mask_elt(<4 x i32> %v) {149; CHECK-LABEL: @lshr_exact_undef_mask_elt(150; CHECK-NEXT:    [[S:%.*]] = lshr exact <4 x i32> [[V:%.*]], <i32 0, i32 0, i32 13, i32 0>151; CHECK-NEXT:    ret <4 x i32> [[S]]152;153  %b = lshr exact  <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>154  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>155  ret <4 x i32> %s156}157 158define <4 x i32> @lshr_constant_op1(<4 x i32> %v) {159; CHECK-LABEL: @lshr_constant_op1(160; CHECK-NEXT:    [[B:%.*]] = lshr exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]161; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>162; CHECK-NEXT:    ret <4 x i32> [[S]]163;164  %b = lshr exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v165  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 5, i32 2, i32 7>166  ret <4 x i32> %s167}168 169; Try weird types.170 171define <3 x i32> @ashr(<3 x i32> %v) {172; CHECK-LABEL: @ashr(173; CHECK-NEXT:    [[S:%.*]] = ashr <3 x i32> [[V:%.*]], <i32 0, i32 12, i32 13>174; CHECK-NEXT:    ret <3 x i32> [[S]]175;176  %b = ashr <3 x i32> %v, <i32 11, i32 12, i32 13>177  %s = shufflevector <3 x i32> %b, <3 x i32> %v, <3 x i32> <i32 3, i32 1, i32 2>178  ret <3 x i32> %s179}180 181define <3 x i42> @and(<3 x i42> %v) {182; CHECK-LABEL: @and(183; CHECK-NEXT:    [[S:%.*]] = and <3 x i42> [[V:%.*]], <i42 -1, i42 12, i42 undef>184; CHECK-NEXT:    ret <3 x i42> [[S]]185;186  %b = and <3 x i42> %v, <i42 11, i42 12, i42 13>187  %s = shufflevector <3 x i42> %v, <3 x i42> %b, <3 x i32> <i32 0, i32 4, i32 undef>188  ret <3 x i42> %s189}190 191; It doesn't matter if the intermediate op has extra uses.192 193declare void @use_v4i32(<4 x i32>)194 195define <4 x i32> @or(<4 x i32> %v) {196; CHECK-LABEL: @or(197; CHECK-NEXT:    [[B:%.*]] = or <4 x i32> [[V:%.*]], <i32 11, i32 12, i32 13, i32 14>198; CHECK-NEXT:    [[S:%.*]] = or <4 x i32> [[V]], <i32 0, i32 0, i32 13, i32 14>199; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[B]])200; CHECK-NEXT:    ret <4 x i32> [[S]]201;202  %b = or <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>203  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 4, i32 5, i32 2, i32 3>204  call void @use_v4i32(<4 x i32> %b)205  ret <4 x i32> %s206}207 208define <4 x i32> @xor(<4 x i32> %v) {209; CHECK-LABEL: @xor(210; CHECK-NEXT:    [[S:%.*]] = xor <4 x i32> [[V:%.*]], <i32 0, i32 12, i32 0, i32 0>211; CHECK-NEXT:    ret <4 x i32> [[S]]212;213  %b = xor <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>214  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 0, i32 5, i32 2, i32 3>215  ret <4 x i32> %s216}217 218define <4 x i32> @udiv(<4 x i32> %v) {219; CHECK-LABEL: @udiv(220; CHECK-NEXT:    [[B:%.*]] = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]221; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>222; CHECK-NEXT:    ret <4 x i32> [[S]]223;224  %b = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v225  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 2, i32 7>226  ret <4 x i32> %s227}228 229define <4 x i32> @udiv_exact(<4 x i32> %v) {230; CHECK-LABEL: @udiv_exact(231; CHECK-NEXT:    [[B:%.*]] = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]232; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>233; CHECK-NEXT:    ret <4 x i32> [[S]]234;235  %b = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v236  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 2, i32 7>237  ret <4 x i32> %s238}239 240define <4 x i32> @udiv_undef_mask_elt(<4 x i32> %v) {241; CHECK-LABEL: @udiv_undef_mask_elt(242; CHECK-NEXT:    [[B:%.*]] = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]243; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>244; CHECK-NEXT:    ret <4 x i32> [[S]]245;246  %b = udiv <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v247  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>248  ret <4 x i32> %s249}250 251define <4 x i32> @udiv_exact_undef_mask_elt(<4 x i32> %v) {252; CHECK-LABEL: @udiv_exact_undef_mask_elt(253; CHECK-NEXT:    [[B:%.*]] = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]254; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>255; CHECK-NEXT:    ret <4 x i32> [[S]]256;257  %b = udiv exact <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v258  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>259  ret <4 x i32> %s260}261 262define <4 x i32> @sdiv(<4 x i32> %v) {263; CHECK-LABEL: @sdiv(264; CHECK-NEXT:    [[S:%.*]] = sdiv <4 x i32> [[V:%.*]], <i32 11, i32 1, i32 13, i32 1>265; CHECK-NEXT:    ret <4 x i32> [[S]]266;267  %b = sdiv <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>268  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>269  ret <4 x i32> %s270}271 272define <4 x i32> @sdiv_exact(<4 x i32> %v) {273; CHECK-LABEL: @sdiv_exact(274; CHECK-NEXT:    [[S:%.*]] = sdiv exact <4 x i32> [[V:%.*]], <i32 11, i32 1, i32 13, i32 1>275; CHECK-NEXT:    ret <4 x i32> [[S]]276;277  %b = sdiv exact <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>278  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 4, i32 1, i32 6, i32 3>279  ret <4 x i32> %s280}281 282; Div/rem need special handling if the shuffle has undef elements.283 284define <4 x i32> @sdiv_undef_mask_elt(<4 x i32> %v) {285; CHECK-LABEL: @sdiv_undef_mask_elt(286; CHECK-NEXT:    [[S:%.*]] = sdiv <4 x i32> [[V:%.*]], <i32 1, i32 1, i32 13, i32 1>287; CHECK-NEXT:    ret <4 x i32> [[S]]288;289  %b = sdiv <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>290  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>291  ret <4 x i32> %s292}293 294define <4 x i32> @sdiv_exact_undef_mask_elt(<4 x i32> %v) {295; CHECK-LABEL: @sdiv_exact_undef_mask_elt(296; CHECK-NEXT:    [[S:%.*]] = sdiv exact <4 x i32> [[V:%.*]], <i32 1, i32 1, i32 13, i32 1>297; CHECK-NEXT:    ret <4 x i32> [[S]]298;299  %b = sdiv exact <4 x i32> %v, <i32 11, i32 12, i32 13, i32 14>300  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>301  ret <4 x i32> %s302}303 304define <4 x i32> @urem(<4 x i32> %v) {305; CHECK-LABEL: @urem(306; CHECK-NEXT:    [[B:%.*]] = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]307; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>308; CHECK-NEXT:    ret <4 x i32> [[S]]309;310  %b = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v311  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>312  ret <4 x i32> %s313}314 315define <4 x i32> @urem_undef_mask_elt(<4 x i32> %v) {316; CHECK-LABEL: @urem_undef_mask_elt(317; CHECK-NEXT:    [[B:%.*]] = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]318; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>319; CHECK-NEXT:    ret <4 x i32> [[S]]320;321  %b = urem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v322  %s = shufflevector <4 x i32> %b, <4 x i32> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>323  ret <4 x i32> %s324}325 326define <4 x i32> @srem(<4 x i32> %v) {327; CHECK-LABEL: @srem(328; CHECK-NEXT:    [[B:%.*]] = srem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, [[V:%.*]]329; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V]], <4 x i32> [[B]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>330; CHECK-NEXT:    ret <4 x i32> [[S]]331;332  %b = srem <4 x i32> <i32 11, i32 12, i32 13, i32 14>, %v333  %s = shufflevector <4 x i32> %v, <4 x i32> %b, <4 x i32> <i32 0, i32 1, i32 6, i32 3>334  ret <4 x i32> %s335}336 337; Try FP ops/types.338 339define <4 x float> @fadd_maybe_nan(<4 x float> %v) {340; CHECK-LABEL: @fadd_maybe_nan(341; CHECK-NEXT:    [[B:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float poison, float poison>342; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x float> [[B]], <4 x float> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>343; CHECK-NEXT:    ret <4 x float> [[S]]344;345  %b = fadd <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>346  %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>347  ret <4 x float> %s348}349 350define <4 x float> @fadd(<4 x float> nofpclass(nan) %v) {351; CHECK-LABEL: @fadd(352; CHECK-NEXT:    [[S:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float -0.000000e+00, float -0.000000e+00>353; CHECK-NEXT:    ret <4 x float> [[S]]354;355  %b = fadd <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>356  %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>357  ret <4 x float> %s358}359 360define <4 x double> @fsub(<4 x double> %v) {361; CHECK-LABEL: @fsub(362; CHECK-NEXT:    [[B:%.*]] = fsub <4 x double> <double poison, double poison, double 4.300000e+01, double 4.400000e+01>, [[V:%.*]]363; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x double> [[V]], <4 x double> [[B]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>364; CHECK-NEXT:    ret <4 x double> [[S]]365;366  %b = fsub <4 x double> <double 41.0, double 42.0, double 43.0, double 44.0>, %v367  %s = shufflevector <4 x double> %v, <4 x double> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>368  ret <4 x double> %s369}370 371; Propagate any FMF.372 373define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) {374; CHECK-LABEL: @fmul(375; CHECK-NEXT:    [[S:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>376; CHECK-NEXT:    ret <4 x float> [[S]]377;378  %b = fmul nnan ninf <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0>379  %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 5, i32 6, i32 7>380  ret <4 x float> %s381}382 383define <4 x double> @fdiv_constant_op0(<4 x double> %v) {384; CHECK-LABEL: @fdiv_constant_op0(385; CHECK-NEXT:    [[B:%.*]] = fdiv fast <4 x double> <double poison, double poison, double 4.300000e+01, double 4.400000e+01>, [[V:%.*]]386; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x double> [[V]], <4 x double> [[B]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>387; CHECK-NEXT:    ret <4 x double> [[S]]388;389  %b = fdiv fast <4 x double> <double 41.0, double 42.0, double 43.0, double 44.0>, %v390  %s = shufflevector <4 x double> %v, <4 x double> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>391  ret <4 x double> %s392}393 394define <4 x double> @fdiv_constant_op1(<4 x double> nofpclass(nan) %v) {395; CHECK-LABEL: @fdiv_constant_op1(396; CHECK-NEXT:    [[S:%.*]] = fdiv reassoc <4 x double> [[V:%.*]], <double undef, double 1.000000e+00, double 4.300000e+01, double 4.400000e+01>397; CHECK-NEXT:    ret <4 x double> [[S]]398;399  %b = fdiv reassoc <4 x double> %v, <double 41.0, double 42.0, double 43.0, double 44.0>400  %s = shufflevector <4 x double> %v, <4 x double> %b, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>401  ret <4 x double> %s402}403 404define <4 x double> @frem(<4 x double> %v) {405; CHECK-LABEL: @frem(406; CHECK-NEXT:    [[B:%.*]] = frem <4 x double> <double 4.100000e+01, double 4.200000e+01, double poison, double poison>, [[V:%.*]]407; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x double> [[B]], <4 x double> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>408; CHECK-NEXT:    ret <4 x double> [[S]]409;410  %b = frem <4 x double> <double 41.0, double 42.0, double 43.0, double 44.0>, %v411  %s = shufflevector <4 x double> %b, <4 x double> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7>412  ret <4 x double> %s413}414 415; Tests where both operands of the shuffle are binops with the same opcode.416 417define <4 x i32> @add_add(<4 x i32> %v0) {418; CHECK-LABEL: @add_add(419; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 3, i32 8>420; CHECK-NEXT:    ret <4 x i32> [[T3]]421;422  %t1 = add <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>423  %t2 = add <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>424  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>425  ret <4 x i32> %t3426}427 428define <4 x i32> @add_add_nsw(<4 x i32> %v0) {429; CHECK-LABEL: @add_add_nsw(430; CHECK-NEXT:    [[T3:%.*]] = add nsw <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 3, i32 8>431; CHECK-NEXT:    ret <4 x i32> [[T3]]432;433  %t1 = add nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>434  %t2 = add nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>435  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>436  ret <4 x i32> %t3437}438 439define <4 x i32> @add_add_undef_mask_elt(<4 x i32> %v0) {440; CHECK-LABEL: @add_add_undef_mask_elt(441; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 undef, i32 8>442; CHECK-NEXT:    ret <4 x i32> [[T3]]443;444  %t1 = add <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>445  %t2 = add <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>446  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 undef, i32 7>447  ret <4 x i32> %t3448}449 450; Poison flags must be dropped or undef must be replaced with safe constant.451 452define <4 x i32> @add_add_nsw_undef_mask_elt(<4 x i32> %v0) {453; CHECK-LABEL: @add_add_nsw_undef_mask_elt(454; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0:%.*]], <i32 1, i32 6, i32 undef, i32 8>455; CHECK-NEXT:    ret <4 x i32> [[T3]]456;457  %t1 = add nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>458  %t2 = add nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>459  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 undef, i32 7>460  ret <4 x i32> %t3461}462 463; Constant operand 0 (LHS) also works.464 465define <4 x i32> @sub_sub(<4 x i32> %v0) {466; CHECK-LABEL: @sub_sub(467; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[V0:%.*]]468; CHECK-NEXT:    ret <4 x i32> [[T3]]469;470  %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0471  %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0472  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>473  ret <4 x i32> %t3474}475 476define <4 x i32> @sub_sub_nuw(<4 x i32> %v0) {477; CHECK-LABEL: @sub_sub_nuw(478; CHECK-NEXT:    [[T3:%.*]] = sub nuw <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[V0:%.*]]479; CHECK-NEXT:    ret <4 x i32> [[T3]]480;481  %t1 = sub nuw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0482  %t2 = sub nuw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0483  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>484  ret <4 x i32> %t3485}486 487define <4 x i32> @sub_sub_undef_mask_elt(<4 x i32> %v0) {488; CHECK-LABEL: @sub_sub_undef_mask_elt(489; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[V0:%.*]]490; CHECK-NEXT:    ret <4 x i32> [[T3]]491;492  %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0493  %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0494  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>495  ret <4 x i32> %t3496}497 498; Poison flags must be dropped or undef must be replaced with safe constant.499 500define <4 x i32> @sub_sub_nuw_undef_mask_elt(<4 x i32> %v0) {501; CHECK-LABEL: @sub_sub_nuw_undef_mask_elt(502; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[V0:%.*]]503; CHECK-NEXT:    ret <4 x i32> [[T3]]504;505  %t1 = sub nuw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0506  %t2 = sub nuw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0507  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>508  ret <4 x i32> %t3509}510 511; If any element of the shuffle mask operand is undef, that element of the result is undef.512; The shuffle is eliminated in this transform, but we can replace a constant element with undef.513 514define <4 x i32> @mul_mul(<4 x i32> %v0) {515; CHECK-LABEL: @mul_mul(516; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[V0:%.*]], <i32 undef, i32 6, i32 3, i32 8>517; CHECK-NEXT:    ret <4 x i32> [[T3]]518;519  %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>520  %t2 = mul <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>521  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>522  ret <4 x i32> %t3523}524 525; Preserve flags when possible.526 527define <4 x i32> @shl_shl(<4 x i32> %v0) {528; CHECK-LABEL: @shl_shl(529; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 5, i32 6, i32 3, i32 4>530; CHECK-NEXT:    ret <4 x i32> [[T3]]531;532  %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>533  %t2 = shl <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>534  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>535  ret <4 x i32> %t3536}537 538define <4 x i32> @shl_shl_nuw(<4 x i32> %v0) {539; CHECK-LABEL: @shl_shl_nuw(540; CHECK-NEXT:    [[T3:%.*]] = shl nuw <4 x i32> [[V0:%.*]], <i32 5, i32 6, i32 3, i32 4>541; CHECK-NEXT:    ret <4 x i32> [[T3]]542;543  %t1 = shl nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>544  %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>545  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>546  ret <4 x i32> %t3547}548 549; Shift by undef is poison. Undef must be replaced by safe constant.550 551define <4 x i32> @shl_shl_undef_mask_elt(<4 x i32> %v0) {552; CHECK-LABEL: @shl_shl_undef_mask_elt(553; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 3, i32 0>554; CHECK-NEXT:    ret <4 x i32> [[T3]]555;556  %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>557  %t2 = shl <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>558  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>559  ret <4 x i32> %t3560}561 562; Shift by undef is poison. Undef must be replaced by safe constant.563 564define <4 x i32> @shl_shl_nuw_undef_mask_elt(<4 x i32> %v0) {565; CHECK-LABEL: @shl_shl_nuw_undef_mask_elt(566; CHECK-NEXT:    [[T3:%.*]] = shl nuw <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 3, i32 0>567; CHECK-NEXT:    ret <4 x i32> [[T3]]568;569  %t1 = shl nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>570  %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>571  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>572  ret <4 x i32> %t3573}574 575; Can't propagate the flag here.576 577define <4 x i32> @lshr_lshr(<4 x i32> %v0) {578; CHECK-LABEL: @lshr_lshr(579; CHECK-NEXT:    [[T3:%.*]] = lshr <4 x i32> <i32 5, i32 6, i32 3, i32 8>, [[V0:%.*]]580; CHECK-NEXT:    ret <4 x i32> [[T3]]581;582  %t1 = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0583  %t2 = lshr <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0584  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 7>585  ret <4 x i32> %t3586}587 588; Try weird types.589 590define <3 x i32> @ashr_ashr(<3 x i32> %v0) {591; CHECK-LABEL: @ashr_ashr(592; CHECK-NEXT:    [[T3:%.*]] = ashr <3 x i32> [[V0:%.*]], <i32 4, i32 2, i32 3>593; CHECK-NEXT:    ret <3 x i32> [[T3]]594;595  %t1 = ashr <3 x i32> %v0, <i32 1, i32 2, i32 3>596  %t2 = ashr <3 x i32> %v0, <i32 4, i32 5, i32 6>597  %t3 = shufflevector <3 x i32> %t1, <3 x i32> %t2, <3 x i32> <i32 3, i32 1, i32 2>598  ret <3 x i32> %t3599}600 601define <3 x i42> @and_and(<3 x i42> %v0) {602; CHECK-LABEL: @and_and(603; CHECK-NEXT:    [[T3:%.*]] = and <3 x i42> [[V0:%.*]], <i42 1, i42 5, i42 undef>604; CHECK-NEXT:    ret <3 x i42> [[T3]]605;606  %t1 = and <3 x i42> %v0, <i42 1, i42 2, i42 3>607  %t2 = and <3 x i42> %v0, <i42 4, i42 5, i42 6>608  %t3 = shufflevector <3 x i42> %t1, <3 x i42> %t2, <3 x i32> <i32 0, i32 4, i32 undef>609  ret <3 x i42> %t3610}611 612; It doesn't matter if the intermediate ops have extra uses.613 614define <4 x i32> @or_or(<4 x i32> %v0) {615; CHECK-LABEL: @or_or(616; CHECK-NEXT:    [[T1:%.*]] = or <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>617; CHECK-NEXT:    [[T3:%.*]] = or <4 x i32> [[V0]], <i32 5, i32 6, i32 3, i32 4>618; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])619; CHECK-NEXT:    ret <4 x i32> [[T3]]620;621  %t1 = or <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>622  %t2 = or <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>623  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>624  call void @use_v4i32(<4 x i32> %t1)625  ret <4 x i32> %t3626}627 628define <4 x i32> @xor_xor(<4 x i32> %v0) {629; CHECK-LABEL: @xor_xor(630; CHECK-NEXT:    [[T2:%.*]] = xor <4 x i32> [[V0:%.*]], <i32 5, i32 6, i32 7, i32 8>631; CHECK-NEXT:    [[T3:%.*]] = xor <4 x i32> [[V0]], <i32 1, i32 6, i32 3, i32 4>632; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])633; CHECK-NEXT:    ret <4 x i32> [[T3]]634;635  %t1 = xor <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>636  %t2 = xor <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>637  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>638  call void @use_v4i32(<4 x i32> %t2)639  ret <4 x i32> %t3640}641 642define <4 x i32> @udiv_udiv(<4 x i32> %v0) {643; CHECK-LABEL: @udiv_udiv(644; CHECK-NEXT:    [[T1:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]645; CHECK-NEXT:    [[T2:%.*]] = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V0]]646; CHECK-NEXT:    [[T3:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[V0]]647; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])648; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])649; CHECK-NEXT:    ret <4 x i32> [[T3]]650;651  %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0652  %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0653  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>654  call void @use_v4i32(<4 x i32> %t1)655  call void @use_v4i32(<4 x i32> %t2)656  ret <4 x i32> %t3657}658 659; Div/rem need special handling if the shuffle has undef elements.660 661define <4 x i32> @sdiv_sdiv(<4 x i32> %v0) {662; CHECK-LABEL: @sdiv_sdiv(663; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 8>664; CHECK-NEXT:    ret <4 x i32> [[T3]]665;666  %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>667  %t2 = sdiv <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>668  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>669  ret <4 x i32> %t3670}671 672define <4 x i32> @sdiv_sdiv_exact(<4 x i32> %v0) {673; CHECK-LABEL: @sdiv_sdiv_exact(674; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 8>675; CHECK-NEXT:    ret <4 x i32> [[T3]]676;677  %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>678  %t2 = sdiv exact <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>679  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>680  ret <4 x i32> %t3681}682 683define <4 x i32> @sdiv_sdiv_undef_mask_elt(<4 x i32> %v0) {684; CHECK-LABEL: @sdiv_sdiv_undef_mask_elt(685; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 1>686; CHECK-NEXT:    ret <4 x i32> [[T3]]687;688  %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>689  %t2 = sdiv <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>690  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>691  ret <4 x i32> %t3692}693 694define <4 x i32> @sdiv_sdiv_exact_undef_mask_elt(<4 x i32> %v0) {695; CHECK-LABEL: @sdiv_sdiv_exact_undef_mask_elt(696; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 7, i32 1>697; CHECK-NEXT:    ret <4 x i32> [[T3]]698;699  %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>700  %t2 = sdiv exact <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>701  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 undef>702  ret <4 x i32> %t3703}704 705define <4 x i32> @urem_urem(<4 x i32> %v0) {706; CHECK-LABEL: @urem_urem(707; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 8>, [[V0:%.*]]708; CHECK-NEXT:    ret <4 x i32> [[T3]]709;710  %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0711  %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0712  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>713  ret <4 x i32> %t3714}715 716; This is folded by using a safe constant.717 718define <4 x i32> @urem_urem_undef_mask_elt(<4 x i32> %v0) {719; CHECK-LABEL: @urem_urem_undef_mask_elt(720; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 0>, [[V0:%.*]]721; CHECK-NEXT:    ret <4 x i32> [[T3]]722;723  %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0724  %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0725  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>726  ret <4 x i32> %t3727}728 729define <4 x i32> @srem_srem(<4 x i32> %v0) {730; CHECK-LABEL: @srem_srem(731; CHECK-NEXT:    [[T3:%.*]] = srem <4 x i32> <i32 1, i32 2, i32 7, i32 4>, [[V0:%.*]]732; CHECK-NEXT:    ret <4 x i32> [[T3]]733;734  %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0735  %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0736  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>737  ret <4 x i32> %t3738}739 740; This is folded by using a safe constant.741 742define <4 x i32> @srem_srem_undef_mask_elt(<4 x i32> %v0) {743; CHECK-LABEL: @srem_srem_undef_mask_elt(744; CHECK-NEXT:    [[T3:%.*]] = srem <4 x i32> <i32 1, i32 0, i32 7, i32 4>, [[V0:%.*]]745; CHECK-NEXT:    ret <4 x i32> [[T3]]746;747  %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0748  %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v0749  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 6, i32 3>750  ret <4 x i32> %t3751}752 753; Try FP ops/types.754 755define <4 x float> @fadd_fadd(<4 x float> %v0) {756; CHECK-LABEL: @fadd_fadd(757; CHECK-NEXT:    [[T3:%.*]] = fadd <4 x float> [[V0:%.*]], <float 1.000000e+00, float 2.000000e+00, float 7.000000e+00, float 8.000000e+00>758; CHECK-NEXT:    ret <4 x float> [[T3]]759;760  %t1 = fadd <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>761  %t2 = fadd <4 x float> %v0, <float 5.0, float 6.0, float 7.0, float 8.0>762  %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>763  ret <4 x float> %t3764}765 766define <4 x double> @fsub_fsub(<4 x double> %v0) {767; CHECK-LABEL: @fsub_fsub(768; CHECK-NEXT:    [[T3:%.*]] = fsub <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[V0:%.*]]769; CHECK-NEXT:    ret <4 x double> [[T3]]770;771  %t1 = fsub <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0772  %t2 = fsub <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v0773  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>774  ret <4 x double> %t3775}776 777; Intersect any FMF.778 779define <4 x float> @fmul_fmul(<4 x float> %v0) {780; CHECK-LABEL: @fmul_fmul(781; CHECK-NEXT:    [[T3:%.*]] = fmul nnan ninf <4 x float> [[V0:%.*]], <float 1.000000e+00, float 6.000000e+00, float 7.000000e+00, float 8.000000e+00>782; CHECK-NEXT:    ret <4 x float> [[T3]]783;784  %t1 = fmul nnan ninf <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>785  %t2 = fmul nnan ninf <4 x float> %v0, <float 5.0, float 6.0, float 7.0, float 8.0>786  %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>787  ret <4 x float> %t3788}789 790define <4 x double> @fdiv_fdiv(<4 x double> %v0) {791; CHECK-LABEL: @fdiv_fdiv(792; CHECK-NEXT:    [[T3:%.*]] = fdiv arcp <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[V0:%.*]]793; CHECK-NEXT:    ret <4 x double> [[T3]]794;795  %t1 = fdiv fast <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0796  %t2 = fdiv nnan arcp <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v0797  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>798  ret <4 x double> %t3799}800 801; The variable operand must be either the first operand or second operand in both binops.802 803define <4 x double> @frem_frem(<4 x double> %v0) {804; CHECK-LABEL: @frem_frem(805; CHECK-NEXT:    [[T1:%.*]] = frem <4 x double> <double 1.000000e+00, double 2.000000e+00, double poison, double poison>, [[V0:%.*]]806; CHECK-NEXT:    [[T2:%.*]] = frem <4 x double> [[V0]], <double poison, double poison, double 7.000000e+00, double 8.000000e+00>807; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>808; CHECK-NEXT:    ret <4 x double> [[T3]]809;810  %t1 = frem <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v0811  %t2 = frem <4 x double> %v0, <double 5.0, double 6.0, double 7.0, double 8.0>812  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>813  ret <4 x double> %t3814}815 816define <4 x i32> @add_2_vars(<4 x i32> %v0, <4 x i32> %v1) {817; CHECK-LABEL: @add_2_vars(818; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>819; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 8>820; CHECK-NEXT:    ret <4 x i32> [[T3]]821;822  %t1 = add <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>823  %t2 = add <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>824  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>825  ret <4 x i32> %t3826}827 828; Constant operand 0 (LHS) also works.829 830define <4 x i32> @sub_2_vars(<4 x i32> %v0, <4 x i32> %v1) {831; CHECK-LABEL: @sub_2_vars(832; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>833; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[TMP1]]834; CHECK-NEXT:    ret <4 x i32> [[T3]]835;836  %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0837  %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1838  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>839  ret <4 x i32> %t3840}841 842define <4 x i32> @sub_2_vars_nsw(<4 x i32> %v0, <4 x i32> %v1) {843; CHECK-LABEL: @sub_2_vars_nsw(844; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>845; CHECK-NEXT:    [[T3:%.*]] = sub nsw <4 x i32> <i32 1, i32 2, i32 3, i32 8>, [[TMP1]]846; CHECK-NEXT:    ret <4 x i32> [[T3]]847;848  %t1 = sub nsw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0849  %t2 = sub nsw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1850  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 2, i32 7>851  ret <4 x i32> %t3852}853 854define <4 x i32> @sub_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {855; CHECK-LABEL: @sub_2_vars_undef_mask_elt(856; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>857; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[TMP1]]858; CHECK-NEXT:    ret <4 x i32> [[T3]]859;860  %t1 = sub <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0861  %t2 = sub <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1862  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>863  ret <4 x i32> %t3864}865 866; Poison flags must be dropped or undef must be replaced with safe constant.867 868define <4 x i32> @sub_2_vars_nsw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {869; CHECK-LABEL: @sub_2_vars_nsw_undef_mask_elt(870; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>871; CHECK-NEXT:    [[T3:%.*]] = sub <4 x i32> <i32 undef, i32 2, i32 3, i32 8>, [[TMP1]]872; CHECK-NEXT:    ret <4 x i32> [[T3]]873;874  %t1 = sub nsw <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0875  %t2 = sub nsw <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1876  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>877  ret <4 x i32> %t3878}879 880; If any element of the shuffle mask operand is undef, that element of the result is undef.881; The shuffle is eliminated in this transform, but we can replace a constant element with undef.882 883define <4 x i32> @mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) {884; CHECK-LABEL: @mul_2_vars(885; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>886; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 8>887; CHECK-NEXT:    ret <4 x i32> [[T3]]888;889  %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>890  %t2 = mul <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>891  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>892  ret <4 x i32> %t3893}894 895define <4 x i32> @mul_2_vars_nuw(<4 x i32> %v0, <4 x i32> %v1) {896; CHECK-LABEL: @mul_2_vars_nuw(897; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>898; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 8>899; CHECK-NEXT:    ret <4 x i32> [[T3]]900;901  %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>902  %t2 = mul nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>903  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 7>904  ret <4 x i32> %t3905}906 907define <4 x i32> @mul_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {908; CHECK-LABEL: @mul_2_vars_undef_mask_elt(909; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>910; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 1, i32 undef, i32 3, i32 8>911; CHECK-NEXT:    ret <4 x i32> [[T3]]912;913  %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>914  %t2 = mul <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>915  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>916  ret <4 x i32> %t3917}918 919; Poison flags must be dropped or undef must be replaced with safe constant.920 921define <4 x i32> @mul_2_vars_nuw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {922; CHECK-LABEL: @mul_2_vars_nuw_undef_mask_elt(923; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 poison, i32 2, i32 7>924; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 1, i32 undef, i32 3, i32 8>925; CHECK-NEXT:    ret <4 x i32> [[T3]]926;927  %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>928  %t2 = mul nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>929  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 2, i32 7>930  ret <4 x i32> %t3931}932 933; Preserve flags when possible.934 935define <4 x i32> @shl_2_vars(<4 x i32> %v0, <4 x i32> %v1) {936; CHECK-LABEL: @shl_2_vars(937; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>938; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 4>939; CHECK-NEXT:    ret <4 x i32> [[T3]]940;941  %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>942  %t2 = shl <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>943  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>944  ret <4 x i32> %t3945}946 947define <4 x i32> @shl_2_vars_nsw(<4 x i32> %v0, <4 x i32> %v1) {948; CHECK-LABEL: @shl_2_vars_nsw(949; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>950; CHECK-NEXT:    [[T3:%.*]] = shl nsw <4 x i32> [[TMP1]], <i32 1, i32 6, i32 3, i32 4>951; CHECK-NEXT:    ret <4 x i32> [[T3]]952;953  %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>954  %t2 = shl nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>955  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>956  ret <4 x i32> %t3957}958 959; Shift by undef is poison. Undef is replaced by safe constant.960 961define <4 x i32> @shl_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {962; CHECK-LABEL: @shl_2_vars_undef_mask_elt(963; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 5, i32 2, i32 poison>964; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[TMP1]], <i32 0, i32 6, i32 3, i32 0>965; CHECK-NEXT:    ret <4 x i32> [[T3]]966;967  %t1 = shl <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>968  %t2 = shl <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>969  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>970  ret <4 x i32> %t3971}972 973; Shift by undef is poison. Undef is replaced by safe constant.974 975define <4 x i32> @shl_2_vars_nsw_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {976; CHECK-LABEL: @shl_2_vars_nsw_undef_mask_elt(977; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 poison, i32 5, i32 2, i32 poison>978; CHECK-NEXT:    [[T3:%.*]] = shl nsw <4 x i32> [[TMP1]], <i32 0, i32 6, i32 3, i32 0>979; CHECK-NEXT:    ret <4 x i32> [[T3]]980;981  %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>982  %t2 = shl nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>983  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 undef>984  ret <4 x i32> %t3985}986 987; Can't propagate the flag here.988 989define <4 x i32> @lshr_2_vars(<4 x i32> %v0, <4 x i32> %v1) {990; CHECK-LABEL: @lshr_2_vars(991; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>992; CHECK-NEXT:    [[T3:%.*]] = lshr <4 x i32> <i32 5, i32 6, i32 3, i32 8>, [[TMP1]]993; CHECK-NEXT:    ret <4 x i32> [[T3]]994;995  %t1 = lshr <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v0996  %t2 = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v1997  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 7>998  ret <4 x i32> %t3999}1000 1001define <4 x i32> @lshr_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {1002; CHECK-LABEL: @lshr_2_vars_exact(1003; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>1004; CHECK-NEXT:    [[T3:%.*]] = lshr exact <4 x i32> <i32 5, i32 6, i32 3, i32 8>, [[TMP1]]1005; CHECK-NEXT:    ret <4 x i32> [[T3]]1006;1007  %t1 = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01008  %t2 = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11009  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 7>1010  ret <4 x i32> %t31011}1012 1013; TODO: This would require a new shuffle mask (replace undef with op0 or op1 lane). Otherwise, we have shift-by-undef.1014 1015define <4 x i32> @lshr_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1016; CHECK-LABEL: @lshr_2_vars_undef_mask_elt(1017; CHECK-NEXT:    [[T1:%.*]] = lshr <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1018; CHECK-NEXT:    [[T2:%.*]] = lshr <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1019; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 5, i32 2, i32 7>1020; CHECK-NEXT:    ret <4 x i32> [[T3]]1021;1022  %t1 = lshr <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01023  %t2 = lshr <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11024  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>1025  ret <4 x i32> %t31026}1027 1028; TODO: This would require a new shuffle mask (replace undef with op0 or op1 lane). Otherwise, we have shift-by-undef.1029 1030define <4 x i32> @lshr_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1031; CHECK-LABEL: @lshr_2_vars_exact_undef_mask_elt(1032; CHECK-NEXT:    [[T1:%.*]] = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1033; CHECK-NEXT:    [[T2:%.*]] = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1034; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 5, i32 2, i32 7>1035; CHECK-NEXT:    ret <4 x i32> [[T3]]1036;1037  %t1 = lshr exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01038  %t2 = lshr exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11039  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 5, i32 2, i32 7>1040  ret <4 x i32> %t31041}1042 1043; Try weird types.1044 1045define <3 x i32> @ashr_2_vars(<3 x i32> %v0, <3 x i32> %v1) {1046; CHECK-LABEL: @ashr_2_vars(1047; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <3 x i32> [[V1:%.*]], <3 x i32> [[V0:%.*]], <3 x i32> <i32 0, i32 4, i32 5>1048; CHECK-NEXT:    [[T3:%.*]] = ashr <3 x i32> [[TMP1]], <i32 4, i32 2, i32 3>1049; CHECK-NEXT:    ret <3 x i32> [[T3]]1050;1051  %t1 = ashr <3 x i32> %v0, <i32 1, i32 2, i32 3>1052  %t2 = ashr <3 x i32> %v1, <i32 4, i32 5, i32 6>1053  %t3 = shufflevector <3 x i32> %t1, <3 x i32> %t2, <3 x i32> <i32 3, i32 1, i32 2>1054  ret <3 x i32> %t31055}1056 1057define <3 x i42> @and_2_vars(<3 x i42> %v0, <3 x i42> %v1) {1058; CHECK-LABEL: @and_2_vars(1059; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <3 x i42> [[V0:%.*]], <3 x i42> [[V1:%.*]], <3 x i32> <i32 0, i32 4, i32 poison>1060; CHECK-NEXT:    [[T3:%.*]] = and <3 x i42> [[TMP1]], <i42 1, i42 5, i42 undef>1061; CHECK-NEXT:    ret <3 x i42> [[T3]]1062;1063  %t1 = and <3 x i42> %v0, <i42 1, i42 2, i42 3>1064  %t2 = and <3 x i42> %v1, <i42 4, i42 5, i42 6>1065  %t3 = shufflevector <3 x i42> %t1, <3 x i42> %t2, <3 x i32> <i32 0, i32 4, i32 undef>1066  ret <3 x i42> %t31067}1068 1069; It doesn't matter if only one intermediate op has extra uses.1070 1071define <4 x i32> @or_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1072; CHECK-LABEL: @or_2_vars(1073; CHECK-NEXT:    [[T1:%.*]] = or <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>1074; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1075; CHECK-NEXT:    [[T3:%.*]] = or <4 x i32> [[TMP1]], <i32 5, i32 6, i32 3, i32 4>1076; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])1077; CHECK-NEXT:    ret <4 x i32> [[T3]]1078;1079  %t1 = or <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1080  %t2 = or <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1081  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1082  call void @use_v4i32(<4 x i32> %t1)1083  ret <4 x i32> %t31084}1085 1086; But we don't transform if both intermediate values have extra uses.1087 1088define <4 x i32> @xor_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1089; CHECK-LABEL: @xor_2_vars(1090; CHECK-NEXT:    [[T1:%.*]] = xor <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>1091; CHECK-NEXT:    [[T2:%.*]] = xor <4 x i32> [[V1:%.*]], <i32 5, i32 6, i32 7, i32 8>1092; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>1093; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])1094; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])1095; CHECK-NEXT:    ret <4 x i32> [[T3]]1096;1097  %t1 = xor <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1098  %t2 = xor <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1099  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>1100  call void @use_v4i32(<4 x i32> %t1)1101  call void @use_v4i32(<4 x i32> %t2)1102  ret <4 x i32> %t31103}1104 1105; Div/rem need special handling if the shuffle has undef elements.1106 1107define <4 x i32> @udiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1108; CHECK-LABEL: @udiv_2_vars(1109; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>1110; CHECK-NEXT:    [[T3:%.*]] = udiv <4 x i32> <i32 5, i32 2, i32 3, i32 8>, [[TMP1]]1111; CHECK-NEXT:    ret <4 x i32> [[T3]]1112;1113  %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01114  %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11115  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 1, i32 2, i32 7>1116  ret <4 x i32> %t31117}1118 1119define <4 x i32> @udiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {1120; CHECK-LABEL: @udiv_2_vars_exact(1121; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>1122; CHECK-NEXT:    [[T3:%.*]] = udiv exact <4 x i32> <i32 5, i32 2, i32 3, i32 8>, [[TMP1]]1123; CHECK-NEXT:    ret <4 x i32> [[T3]]1124;1125  %t1 = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01126  %t2 = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11127  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 1, i32 2, i32 7>1128  ret <4 x i32> %t31129}1130 1131; TODO: This could be transformed using a safe constant.1132 1133define <4 x i32> @udiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1134; CHECK-LABEL: @udiv_2_vars_undef_mask_elt(1135; CHECK-NEXT:    [[T1:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1136; CHECK-NEXT:    [[T2:%.*]] = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1137; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>1138; CHECK-NEXT:    ret <4 x i32> [[T3]]1139;1140  %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01141  %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11142  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>1143  ret <4 x i32> %t31144}1145 1146; TODO: This could be transformed using a safe constant.1147 1148define <4 x i32> @udiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1149; CHECK-LABEL: @udiv_2_vars_exact_undef_mask_elt(1150; CHECK-NEXT:    [[T1:%.*]] = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1151; CHECK-NEXT:    [[T2:%.*]] = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1152; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>1153; CHECK-NEXT:    ret <4 x i32> [[T3]]1154;1155  %t1 = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01156  %t2 = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11157  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>1158  ret <4 x i32> %t31159}1160 1161; If the shuffle has no undefs, it's safe to shuffle the variables first.1162 1163define <4 x i32> @sdiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1164; CHECK-LABEL: @sdiv_2_vars(1165; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>1166; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 4>1167; CHECK-NEXT:    ret <4 x i32> [[T3]]1168;1169  %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1170  %t2 = sdiv <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1171  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>1172  ret <4 x i32> %t31173}1174 1175define <4 x i32> @sdiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {1176; CHECK-LABEL: @sdiv_2_vars_exact(1177; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>1178; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 4>1179; CHECK-NEXT:    ret <4 x i32> [[T3]]1180;1181  %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1182  %t2 = sdiv exact <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1183  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>1184  ret <4 x i32> %t31185}1186 1187; Div by undef is UB. Undef is replaced by safe constant.1188 1189define <4 x i32> @sdiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1190; CHECK-LABEL: @sdiv_2_vars_undef_mask_elt(1191; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>1192; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 1>1193; CHECK-NEXT:    ret <4 x i32> [[T3]]1194;1195  %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1196  %t2 = sdiv <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1197  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>1198  ret <4 x i32> %t31199}1200 1201; Div by undef is UB. Undef is replaced by safe constant.1202 1203define <4 x i32> @sdiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1204; CHECK-LABEL: @sdiv_2_vars_exact_undef_mask_elt(1205; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>1206; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 1>1207; CHECK-NEXT:    ret <4 x i32> [[T3]]1208;1209  %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1210  %t2 = sdiv exact <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1211  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>1212  ret <4 x i32> %t31213}1214 1215; If the shuffle has no undefs, it's safe to shuffle the variables first.1216 1217define <4 x i32> @urem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1218; CHECK-LABEL: @urem_2_vars(1219; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1220; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 8>, [[TMP1]]1221; CHECK-NEXT:    ret <4 x i32> [[T3]]1222;1223  %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01224  %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11225  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1226  ret <4 x i32> %t31227}1228 1229define <4 x i32> @srem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1230; CHECK-LABEL: @srem_2_vars(1231; CHECK-NEXT:    [[T1:%.*]] = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1232; CHECK-NEXT:    [[T2:%.*]] = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1233; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 0, i32 poison, i32 6, i32 3>1234; CHECK-NEXT:    ret <4 x i32> [[T3]]1235;1236  %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01237  %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11238  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 6, i32 3>1239  ret <4 x i32> %t31240}1241 1242; Try FP ops/types.1243 1244define <4 x float> @fadd_2_vars(<4 x float> %v0, <4 x float> %v1) {1245; CHECK-LABEL: @fadd_2_vars(1246; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[V0:%.*]], <4 x float> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1247; CHECK-NEXT:    [[T3:%.*]] = fadd <4 x float> [[TMP1]], <float 1.000000e+00, float 2.000000e+00, float 7.000000e+00, float 8.000000e+00>1248; CHECK-NEXT:    ret <4 x float> [[T3]]1249;1250  %t1 = fadd <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>1251  %t2 = fadd <4 x float> %v1, <float 5.0, float 6.0, float 7.0, float 8.0>1252  %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1253  ret <4 x float> %t31254}1255 1256define <4 x double> @fsub_2_vars(<4 x double> %v0, <4 x double> %v1) {1257; CHECK-LABEL: @fsub_2_vars(1258; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>1259; CHECK-NEXT:    [[T3:%.*]] = fsub <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[TMP1]]1260; CHECK-NEXT:    ret <4 x double> [[T3]]1261;1262  %t1 = fsub <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v01263  %t2 = fsub <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v11264  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>1265  ret <4 x double> %t31266}1267 1268; Intersect any FMF.1269 1270define <4 x float> @fmul_2_vars(<4 x float> %v0, <4 x float> %v1) {1271; CHECK-LABEL: @fmul_2_vars(1272; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[V0:%.*]], <4 x float> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>1273; CHECK-NEXT:    [[T3:%.*]] = fmul reassoc nsz <4 x float> [[TMP1]], <float 1.000000e+00, float 6.000000e+00, float 7.000000e+00, float 8.000000e+00>1274; CHECK-NEXT:    ret <4 x float> [[T3]]1275;1276  %t1 = fmul reassoc nsz <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>1277  %t2 = fmul reassoc nsz <4 x float> %v1, <float 5.0, float 6.0, float 7.0, float 8.0>1278  %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>1279  ret <4 x float> %t31280}1281 1282define <4 x double> @frem_2_vars(<4 x double> %v0, <4 x double> %v1) {1283; CHECK-LABEL: @frem_2_vars(1284; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>1285; CHECK-NEXT:    [[T3:%.*]] = frem <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[TMP1]]1286; CHECK-NEXT:    ret <4 x double> [[T3]]1287;1288  %t1 = frem nnan ninf <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v01289  %t2 = frem nnan arcp <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v11290  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>1291  ret <4 x double> %t31292}1293 1294; The variable operand must be either the first operand or second operand in both binops.1295 1296define <4 x double> @fdiv_2_vars(<4 x double> %v0, <4 x double> %v1) {1297; CHECK-LABEL: @fdiv_2_vars(1298; CHECK-NEXT:    [[T1:%.*]] = fdiv <4 x double> <double 1.000000e+00, double 2.000000e+00, double poison, double poison>, [[V0:%.*]]1299; CHECK-NEXT:    [[T2:%.*]] = fdiv <4 x double> [[V1:%.*]], <double poison, double poison, double 7.000000e+00, double 8.000000e+00>1300; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1301; CHECK-NEXT:    ret <4 x double> [[T3]]1302;1303  %t1 = fdiv <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v01304  %t2 = fdiv <4 x double> %v1, <double 5.0, double 6.0, double 7.0, double 8.0>1305  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1306  ret <4 x double> %t31307}1308 1309; Shift-left with constant shift amount can be converted to mul to enable the fold.1310 1311define <4 x i32> @mul_shl(<4 x i32> %v0) {1312; CHECK-LABEL: @mul_shl(1313; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[V0:%.*]], <i32 32, i32 64, i32 3, i32 4>1314; CHECK-NEXT:    ret <4 x i32> [[T3]]1315;1316  %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1317  %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1318  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1319  ret <4 x i32> %t31320}1321 1322; Try with shift as operand 0 of the shuffle; 'nsw' is dropped for safety, but that could be improved.1323 1324define <4 x i32> @shl_mul(<4 x i32> %v0) {1325; CHECK-LABEL: @shl_mul(1326; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[V0:%.*]], <i32 5, i32 undef, i32 8, i32 16>1327; CHECK-NEXT:    ret <4 x i32> [[T3]]1328;1329  %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1330  %t2 = mul nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1331  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 undef, i32 2, i32 3>1332  ret <4 x i32> %t31333}1334 1335; Demanded elements + simplification can remove the mul alone, but that's not the best case.1336 1337define <4 x i32> @mul_is_nop_shl(<4 x i32> %v0) {1338; CHECK-LABEL: @mul_is_nop_shl(1339; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 7, i32 8>1340; CHECK-NEXT:    ret <4 x i32> [[T3]]1341;1342  %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1343  %t2 = shl <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1344  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>1345  ret <4 x i32> %t31346}1347 1348; Negative test: shift amount (operand 1) must be constant.1349 1350define <4 x i32> @shl_mul_not_constant_shift_amount(<4 x i32> %v0) {1351; CHECK-LABEL: @shl_mul_not_constant_shift_amount(1352; CHECK-NEXT:    [[T1:%.*]] = shl <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1353; CHECK-NEXT:    [[T2:%.*]] = mul <4 x i32> [[V0]], <i32 5, i32 6, i32 poison, i32 poison>1354; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T2]], <4 x i32> [[T1]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1355; CHECK-NEXT:    ret <4 x i32> [[T3]]1356;1357  %t1 = shl <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01358  %t2 = mul <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1359  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1360  ret <4 x i32> %t31361}1362 1363; Try with 2 variable inputs.1364 1365define <4 x i32> @mul_shl_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1366; CHECK-LABEL: @mul_shl_2_vars(1367; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1368; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], <i32 32, i32 64, i32 3, i32 4>1369; CHECK-NEXT:    ret <4 x i32> [[T3]]1370;1371  %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1372  %t2 = shl nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1373  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1374  ret <4 x i32> %t31375}1376 1377define <4 x i32> @shl_mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1378; CHECK-LABEL: @shl_mul_2_vars(1379; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 poison, i32 6, i32 7>1380; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 5, i32 undef, i32 8, i32 16>1381; CHECK-NEXT:    ret <4 x i32> [[T3]]1382;1383  %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1384  %t2 = mul nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1385  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 undef, i32 2, i32 3>1386  ret <4 x i32> %t31387}1388 1389; Or with constant can be converted to add to enable the fold.1390; The 'shl' is here to allow analysis to determine that the 'or' can be transformed to 'add'.1391; TODO: The 'or' constant is limited to a splat.1392 1393define <4 x i32> @add_or(<4 x i32> %v) {1394; CHECK-LABEL: @add_or(1395; CHECK-NEXT:    [[V0:%.*]] = shl <4 x i32> [[V:%.*]], splat (i32 5)1396; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0]], <i32 31, i32 31, i32 65536, i32 65537>1397; CHECK-NEXT:    ret <4 x i32> [[T3]]1398;1399  %v0 = shl <4 x i32> %v, <i32 5, i32 5, i32 5, i32 5>                   ; clear the bottom bits1400  %t1 = add <4 x i32> %v0, <i32 65534, i32 65535, i32 65536, i32 65537>  ; this can't be converted to 'or'1401  %t2 = or <4 x i32> %v0, <i32 31, i32 31, i32 31, i32 31>               ; set the bottom bits1402  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1403  ret <4 x i32> %t31404}1405 1406; Try with 'or' as operand 0 of the shuffle.1407 1408define <4 x i8> @or_add(<4 x i8> %v) {1409; CHECK-LABEL: @or_add(1410; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], splat (i8 3)1411; CHECK-NEXT:    [[T3:%.*]] = add nuw nsw <4 x i8> [[V0]], <i8 1, i8 2, i8 -64, i8 -64>1412; CHECK-NEXT:    ret <4 x i8> [[T3]]1413;1414  %v0 = lshr <4 x i8> %v, <i8 3, i8 3, i8 3, i8 3>          ; clear the top bits1415  %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits1416  %t2 = add nsw nuw <4 x i8> %v0, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'1417  %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1418  ret <4 x i8> %t31419}1420 1421; Negative test: not all 'or' insts can be converted to 'add'.1422 1423define <4 x i8> @or_add_not_enough_masking(<4 x i8> %v) {1424; CHECK-LABEL: @or_add_not_enough_masking(1425; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], splat (i8 1)1426; CHECK-NEXT:    [[T1:%.*]] = or <4 x i8> [[V0]], <i8 poison, i8 poison, i8 -64, i8 -64>1427; CHECK-NEXT:    [[T2:%.*]] = add nuw nsw <4 x i8> [[V0]], <i8 1, i8 2, i8 poison, i8 poison>1428; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i8> [[T2]], <4 x i8> [[T1]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1429; CHECK-NEXT:    ret <4 x i8> [[T3]]1430;1431  %v0 = lshr <4 x i8> %v, <i8 1, i8 1, i8 1, i8 1>          ; clear not enough top bits1432  %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits1433  %t2 = add nsw nuw <4 x i8> %v0, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'1434  %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1435  ret <4 x i8> %t31436}1437 1438; Try with 2 variable inputs.1439 1440define <4 x i32> @add_or_2_vars(<4 x i32> %v, <4 x i32> %v1) {1441; CHECK-LABEL: @add_or_2_vars(1442; CHECK-NEXT:    [[V0:%.*]] = shl <4 x i32> [[V:%.*]], splat (i32 5)1443; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1444; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[TMP1]], <i32 31, i32 31, i32 65536, i32 65537>1445; CHECK-NEXT:    ret <4 x i32> [[T3]]1446;1447  %v0 = shl <4 x i32> %v, <i32 5, i32 5, i32 5, i32 5>                   ; clear the bottom bits1448  %t1 = add <4 x i32> %v1, <i32 65534, i32 65535, i32 65536, i32 65537>  ; this can't be converted to 'or'1449  %t2 = or <4 x i32> %v0, <i32 31, i32 31, i32 31, i32 31>               ; set the bottom bits1450  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1451  ret <4 x i32> %t31452}1453 1454define <4 x i8> @or_add_2_vars(<4 x i8> %v, <4 x i8> %v1) {1455; CHECK-LABEL: @or_add_2_vars(1456; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], splat (i8 3)1457; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i8> [[V1:%.*]], <4 x i8> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1458; CHECK-NEXT:    [[T3:%.*]] = add nuw nsw <4 x i8> [[TMP1]], <i8 1, i8 2, i8 -64, i8 -64>1459; CHECK-NEXT:    ret <4 x i8> [[T3]]1460;1461  %v0 = lshr <4 x i8> %v, <i8 3, i8 3, i8 3, i8 3>          ; clear the top bits1462  %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits1463  %t2 = add nsw nuw <4 x i8> %v1, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'1464  %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1465  ret <4 x i8> %t31466}1467 1468; The undef operand is used to simplify the shuffle mask, but don't assert that too soon.1469 1470define <4 x i32> @PR41419(<4 x i32> %v) {1471; CHECK-LABEL: @PR41419(1472; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 poison, i32 2, i32 poison>1473; CHECK-NEXT:    ret <4 x i32> [[S]]1474;1475  %s = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 4, i32 5, i32 2, i32 7>1476  ret <4 x i32> %s1477}1478 1479