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