brintos

brintos / llvm-project-archived public Read only

0
0
Text · 73.3 KiB · 21765f7 Raw
1656 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:    call void @use_v4i32(<4 x i32> [[T1]])1075; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1076; CHECK-NEXT:    [[T3:%.*]] = or <4 x i32> [[TMP1]], <i32 5, i32 6, i32 3, i32 4>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  call void @use_v4i32(<4 x i32> %t1)1081  %t2 = or <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1082  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1083  ret <4 x i32> %t31084}1085 1086define <4 x i32> @or_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1087; CHECK-LABEL: @or_2_vars_undef_mask_elt(1088; CHECK-NEXT:    [[T1:%.*]] = or <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>1089; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])1090; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>1091; CHECK-NEXT:    [[T3:%.*]] = or <4 x i32> [[TMP1]], <i32 5, i32 6, i32 3, i32 undef>1092; CHECK-NEXT:    ret <4 x i32> [[T3]]1093;1094  %t1 = or <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1095  call void @use_v4i32(<4 x i32> %t1)1096  %t2 = or <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1097  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 undef>1098  ret <4 x i32> %t31099}1100 1101; But we don't transform if both intermediate values have extra uses.1102 1103define <4 x i32> @xor_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1104; CHECK-LABEL: @xor_2_vars(1105; CHECK-NEXT:    [[T1:%.*]] = xor <4 x i32> [[V0:%.*]], <i32 1, i32 2, i32 3, i32 4>1106; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T1]])1107; CHECK-NEXT:    [[T2:%.*]] = xor <4 x i32> [[V1:%.*]], <i32 5, i32 6, i32 7, i32 8>1108; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[T2]])1109; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 0, i32 5, i32 2, i32 3>1110; CHECK-NEXT:    ret <4 x i32> [[T3]]1111;1112  %t1 = xor <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1113  call void @use_v4i32(<4 x i32> %t1)1114  %t2 = xor <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1115  call void @use_v4i32(<4 x i32> %t2)1116  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 5, i32 2, i32 3>1117  ret <4 x i32> %t31118}1119 1120; Div/rem need special handling if the shuffle has undef elements.1121 1122define <4 x i32> @udiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1123; CHECK-LABEL: @udiv_2_vars(1124; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>1125; CHECK-NEXT:    [[T3:%.*]] = udiv <4 x i32> <i32 5, i32 2, i32 3, i32 8>, [[TMP1]]1126; CHECK-NEXT:    ret <4 x i32> [[T3]]1127;1128  %t1 = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01129  %t2 = udiv <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11130  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 1, i32 2, i32 7>1131  ret <4 x i32> %t31132}1133 1134define <4 x i32> @udiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {1135; CHECK-LABEL: @udiv_2_vars_exact(1136; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>1137; CHECK-NEXT:    [[T3:%.*]] = udiv exact <4 x i32> <i32 5, i32 2, i32 3, i32 8>, [[TMP1]]1138; CHECK-NEXT:    ret <4 x i32> [[T3]]1139;1140  %t1 = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01141  %t2 = udiv exact <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 4, 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_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1149; CHECK-LABEL: @udiv_2_vars_undef_mask_elt(1150; CHECK-NEXT:    [[T1:%.*]] = udiv <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1151; CHECK-NEXT:    [[T2:%.*]] = udiv <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 <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01156  %t2 = udiv <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; TODO: This could be transformed using a safe constant.1162 1163define <4 x i32> @udiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1164; CHECK-LABEL: @udiv_2_vars_exact_undef_mask_elt(1165; CHECK-NEXT:    [[T1:%.*]] = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1166; CHECK-NEXT:    [[T2:%.*]] = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1167; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 poison, i32 1, i32 2, i32 7>1168; CHECK-NEXT:    ret <4 x i32> [[T3]]1169;1170  %t1 = udiv exact <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01171  %t2 = udiv exact <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11172  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 undef, i32 1, i32 2, i32 7>1173  ret <4 x i32> %t31174}1175 1176; If the shuffle has no undefs, it's safe to shuffle the variables first.1177 1178define <4 x i32> @sdiv_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1179; CHECK-LABEL: @sdiv_2_vars(1180; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>1181; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 4>1182; CHECK-NEXT:    ret <4 x i32> [[T3]]1183;1184  %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1185  %t2 = sdiv <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1186  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>1187  ret <4 x i32> %t31188}1189 1190define <4 x i32> @sdiv_2_vars_exact(<4 x i32> %v0, <4 x i32> %v1) {1191; CHECK-LABEL: @sdiv_2_vars_exact(1192; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 3>1193; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 4>1194; CHECK-NEXT:    ret <4 x i32> [[T3]]1195;1196  %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1197  %t2 = sdiv exact <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1198  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 3>1199  ret <4 x i32> %t31200}1201 1202; Div by undef is UB. Undef is replaced by safe constant.1203 1204define <4 x i32> @sdiv_2_vars_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1205; CHECK-LABEL: @sdiv_2_vars_undef_mask_elt(1206; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>1207; CHECK-NEXT:    [[T3:%.*]] = sdiv <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 1>1208; CHECK-NEXT:    ret <4 x i32> [[T3]]1209;1210  %t1 = sdiv <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1211  %t2 = sdiv <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1212  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>1213  ret <4 x i32> %t31214}1215 1216; Div by undef is UB. Undef is replaced by safe constant.1217 1218define <4 x i32> @sdiv_2_vars_exact_undef_mask_elt(<4 x i32> %v0, <4 x i32> %v1) {1219; CHECK-LABEL: @sdiv_2_vars_exact_undef_mask_elt(1220; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 poison>1221; CHECK-NEXT:    [[T3:%.*]] = sdiv exact <4 x i32> [[TMP1]], <i32 1, i32 2, i32 7, i32 1>1222; CHECK-NEXT:    ret <4 x i32> [[T3]]1223;1224  %t1 = sdiv exact <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1225  %t2 = sdiv exact <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1226  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 undef>1227  ret <4 x i32> %t31228}1229 1230; If the shuffle has no undefs, it's safe to shuffle the variables first.1231 1232define <4 x i32> @urem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1233; CHECK-LABEL: @urem_2_vars(1234; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0:%.*]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1235; CHECK-NEXT:    [[T3:%.*]] = urem <4 x i32> <i32 1, i32 2, i32 7, i32 8>, [[TMP1]]1236; CHECK-NEXT:    ret <4 x i32> [[T3]]1237;1238  %t1 = urem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01239  %t2 = urem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11240  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1241  ret <4 x i32> %t31242}1243 1244define <4 x i32> @srem_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1245; CHECK-LABEL: @srem_2_vars(1246; CHECK-NEXT:    [[T1:%.*]] = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1247; CHECK-NEXT:    [[T2:%.*]] = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, [[V1:%.*]]1248; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> <i32 0, i32 poison, i32 6, i32 3>1249; CHECK-NEXT:    ret <4 x i32> [[T3]]1250;1251  %t1 = srem <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01252  %t2 = srem <4 x i32> <i32 5, i32 6, i32 7, i32 8>, %v11253  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 0, i32 undef, i32 6, i32 3>1254  ret <4 x i32> %t31255}1256 1257; Try FP ops/types.1258 1259define <4 x float> @fadd_2_vars(<4 x float> %v0, <4 x float> %v1) {1260; CHECK-LABEL: @fadd_2_vars(1261; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[V0:%.*]], <4 x float> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1262; CHECK-NEXT:    [[T3:%.*]] = fadd <4 x float> [[TMP1]], <float 1.000000e+00, float 2.000000e+00, float 7.000000e+00, float 8.000000e+00>1263; CHECK-NEXT:    ret <4 x float> [[T3]]1264;1265  %t1 = fadd <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>1266  %t2 = fadd <4 x float> %v1, <float 5.0, float 6.0, float 7.0, float 8.0>1267  %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1268  ret <4 x float> %t31269}1270 1271define <4 x double> @fsub_2_vars(<4 x double> %v0, <4 x double> %v1) {1272; CHECK-LABEL: @fsub_2_vars(1273; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>1274; CHECK-NEXT:    [[T3:%.*]] = fsub <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[TMP1]]1275; CHECK-NEXT:    ret <4 x double> [[T3]]1276;1277  %t1 = fsub <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v01278  %t2 = fsub <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v11279  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>1280  ret <4 x double> %t31281}1282 1283; Intersect any FMF.1284 1285define <4 x float> @fmul_2_vars(<4 x float> %v0, <4 x float> %v1) {1286; CHECK-LABEL: @fmul_2_vars(1287; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x float> [[V0:%.*]], <4 x float> [[V1:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>1288; 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>1289; CHECK-NEXT:    ret <4 x float> [[T3]]1290;1291  %t1 = fmul reassoc nsz <4 x float> %v0, <float 1.0, float 2.0, float 3.0, float 4.0>1292  %t2 = fmul reassoc nsz <4 x float> %v1, <float 5.0, float 6.0, float 7.0, float 8.0>1293  %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> <i32 0, i32 5, i32 6, i32 7>1294  ret <4 x float> %t31295}1296 1297define <4 x double> @frem_2_vars(<4 x double> %v0, <4 x double> %v1) {1298; CHECK-LABEL: @frem_2_vars(1299; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[V0:%.*]], <4 x double> [[V1:%.*]], <4 x i32> <i32 poison, i32 1, i32 6, i32 7>1300; CHECK-NEXT:    [[T3:%.*]] = frem <4 x double> <double undef, double 2.000000e+00, double 7.000000e+00, double 8.000000e+00>, [[TMP1]]1301; CHECK-NEXT:    ret <4 x double> [[T3]]1302;1303  %t1 = frem nnan ninf <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v01304  %t2 = frem nnan arcp <4 x double> <double 5.0, double 6.0, double 7.0, double 8.0>, %v11305  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 undef, i32 1, i32 6, i32 7>1306  ret <4 x double> %t31307}1308 1309; The variable operand must be either the first operand or second operand in both binops.1310 1311define <4 x double> @fdiv_2_vars(<4 x double> %v0, <4 x double> %v1) {1312; CHECK-LABEL: @fdiv_2_vars(1313; CHECK-NEXT:    [[T1:%.*]] = fdiv <4 x double> <double 1.000000e+00, double 2.000000e+00, double poison, double poison>, [[V0:%.*]]1314; CHECK-NEXT:    [[T2:%.*]] = fdiv <4 x double> [[V1:%.*]], <double poison, double poison, double 7.000000e+00, double 8.000000e+00>1315; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1316; CHECK-NEXT:    ret <4 x double> [[T3]]1317;1318  %t1 = fdiv <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>, %v01319  %t2 = fdiv <4 x double> %v1, <double 5.0, double 6.0, double 7.0, double 8.0>1320  %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1321  ret <4 x double> %t31322}1323 1324; Shift-left with constant shift amount can be converted to mul to enable the fold.1325 1326define <4 x i32> @mul_shl(<4 x i32> %v0) {1327; CHECK-LABEL: @mul_shl(1328; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[V0:%.*]], <i32 32, i32 64, i32 3, i32 4>1329; CHECK-NEXT:    ret <4 x i32> [[T3]]1330;1331  %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1332  %t2 = shl nuw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1333  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1334  ret <4 x i32> %t31335}1336 1337; Try with shift as operand 0 of the shuffle; 'nsw' is dropped for safety, but that could be improved.1338 1339define <4 x i32> @shl_mul(<4 x i32> %v0) {1340; CHECK-LABEL: @shl_mul(1341; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[V0:%.*]], <i32 5, i32 undef, i32 8, i32 16>1342; CHECK-NEXT:    ret <4 x i32> [[T3]]1343;1344  %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1345  %t2 = mul nsw <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1346  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 undef, i32 2, i32 3>1347  ret <4 x i32> %t31348}1349 1350; Demanded elements + simplification can remove the mul alone, but that's not the best case.1351 1352define <4 x i32> @mul_is_nop_shl(<4 x i32> %v0) {1353; CHECK-LABEL: @mul_is_nop_shl(1354; CHECK-NEXT:    [[T3:%.*]] = shl <4 x i32> [[V0:%.*]], <i32 0, i32 6, i32 7, i32 8>1355; CHECK-NEXT:    ret <4 x i32> [[T3]]1356;1357  %t1 = mul <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1358  %t2 = shl <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 0, i32 5, i32 6, i32 7>1360  ret <4 x i32> %t31361}1362 1363; Negative test: shift amount (operand 1) must be constant.1364 1365define <4 x i32> @shl_mul_not_constant_shift_amount(<4 x i32> %v0) {1366; CHECK-LABEL: @shl_mul_not_constant_shift_amount(1367; CHECK-NEXT:    [[T1:%.*]] = shl <4 x i32> <i32 1, i32 2, i32 3, i32 4>, [[V0:%.*]]1368; CHECK-NEXT:    [[T2:%.*]] = mul <4 x i32> [[V0]], <i32 5, i32 6, i32 poison, i32 poison>1369; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i32> [[T2]], <4 x i32> [[T1]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1370; CHECK-NEXT:    ret <4 x i32> [[T3]]1371;1372  %t1 = shl <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %v01373  %t2 = mul <4 x i32> %v0, <i32 5, i32 6, i32 7, i32 8>1374  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1375  ret <4 x i32> %t31376}1377 1378; Try with 2 variable inputs.1379 1380define <4 x i32> @mul_shl_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1381; CHECK-LABEL: @mul_shl_2_vars(1382; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1383; CHECK-NEXT:    [[T3:%.*]] = mul nuw <4 x i32> [[TMP1]], <i32 32, i32 64, i32 3, i32 4>1384; CHECK-NEXT:    ret <4 x i32> [[T3]]1385;1386  %t1 = mul nuw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1387  %t2 = shl nuw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1388  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1389  ret <4 x i32> %t31390}1391 1392define <4 x i32> @shl_mul_2_vars(<4 x i32> %v0, <4 x i32> %v1) {1393; CHECK-LABEL: @shl_mul_2_vars(1394; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V1:%.*]], <4 x i32> [[V0:%.*]], <4 x i32> <i32 0, i32 poison, i32 6, i32 7>1395; CHECK-NEXT:    [[T3:%.*]] = mul <4 x i32> [[TMP1]], <i32 5, i32 undef, i32 8, i32 16>1396; CHECK-NEXT:    ret <4 x i32> [[T3]]1397;1398  %t1 = shl nsw <4 x i32> %v0, <i32 1, i32 2, i32 3, i32 4>1399  %t2 = mul nsw <4 x i32> %v1, <i32 5, i32 6, i32 7, i32 8>1400  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 undef, i32 2, i32 3>1401  ret <4 x i32> %t31402}1403 1404; Negate can be converted to mul to enable the fold.1405 1406define <4 x i32> @mul_neg(<4 x i32> %x) {1407; CHECK-LABEL: @mul_neg(1408; CHECK-NEXT:    [[R:%.*]] = mul <4 x i32> [[X:%.*]], <i32 257, i32 -3, i32 -1, i32 -9>1409; CHECK-NEXT:    ret <4 x i32> [[R]]1410;1411  %m = mul <4 x i32> %x, <i32 257, i32 -3, i32 poison, i32 -9>1412  %n = sub <4 x i32> <i32 poison, i32 poison, i32 0, i32 poison>, %x1413  %r = shufflevector <4 x i32> %m, <4 x i32> %n, <4 x i32> <i32 0, i32 1, i32 6, i32 3>1414  ret <4 x i32> %r1415}1416 1417define <3 x i79> @neg_mul(<3 x i79> %x) {1418; CHECK-LABEL: @neg_mul(1419; CHECK-NEXT:    [[R:%.*]] = mul nsw <3 x i79> [[X:%.*]], <i79 -1, i79 -3, i79 -1>1420; CHECK-NEXT:    ret <3 x i79> [[R]]1421;1422  %n = sub nsw <3 x i79> <i79 0, i79 poison, i79 0>, %x1423  %m = mul nsw <3 x i79> %x, <i79 poison, i79 -3, i79 poison>1424  %r = shufflevector <3 x i79> %n, <3 x i79> %m, <3 x i32> <i32 0, i32 4, i32 2>1425  ret <3 x i79> %r1426}1427 1428define <4 x i32> @mul_neg_2_vars(<4 x i32> %x, <4 x i32> %y) {1429; CHECK-LABEL: @mul_neg_2_vars(1430; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <4 x i32> <i32 0, i32 5, i32 6, i32 3>1431; CHECK-NEXT:    [[R:%.*]] = mul <4 x i32> [[TMP1]], <i32 42, i32 -1, i32 -1, i32 6>1432; CHECK-NEXT:    ret <4 x i32> [[R]]1433;1434  %m = mul nuw <4 x i32> %x, <i32 42, i32 poison, i32 poison, i32 6>1435  %n = sub nsw <4 x i32> <i32 poison, i32 0, i32 0, i32 poison>, %y1436  %r = shufflevector <4 x i32> %m, <4 x i32> %n, <4 x i32> <i32 0, i32 5, i32 6, i32 3>1437  ret <4 x i32> %r1438}1439 1440define <4 x i32> @neg_mul_2_vars(<4 x i32> %x, <4 x i32> %y) {1441; CHECK-LABEL: @neg_mul_2_vars(1442; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> [[X:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>1443; CHECK-NEXT:    [[R:%.*]] = mul nsw <4 x i32> [[TMP1]], <i32 -1, i32 42, i32 -1, i32 6>1444; CHECK-NEXT:    ret <4 x i32> [[R]]1445;1446  %n = sub nsw <4 x i32> <i32 0, i32 poison, i32 0, i32 poison>, %y1447  %m = mul nuw nsw <4 x i32> %x, <i32 poison, i32 42, i32 poison, i32 6>1448  %r = shufflevector <4 x i32> %n, <4 x i32> %m, <4 x i32> <i32 0, i32 5, i32 2, i32 7>1449  ret <4 x i32> %r1450}1451 1452; Or with constant can be converted to add to enable the fold.1453; The 'shl' is here to allow analysis to determine that the 'or' can be transformed to 'add'.1454; TODO: The 'or' constant is limited to a splat.1455 1456define <4 x i32> @add_or(<4 x i32> %v) {1457; CHECK-LABEL: @add_or(1458; CHECK-NEXT:    [[V0:%.*]] = shl <4 x i32> [[V:%.*]], splat (i32 5)1459; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V0]], <i32 31, i32 31, i32 65536, i32 65537>1460; CHECK-NEXT:    ret <4 x i32> [[T3]]1461;1462  %v0 = shl <4 x i32> %v, <i32 5, i32 5, i32 5, i32 5>                   ; clear the bottom bits1463  %t1 = add <4 x i32> %v0, <i32 65534, i32 65535, i32 65536, i32 65537>  ; this can't be converted to 'or'1464  %t2 = or <4 x i32> %v0, <i32 31, i32 31, i32 31, i32 31>               ; set the bottom bits1465  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1466  ret <4 x i32> %t31467}1468 1469define <4 x i32> @add_or_disjoint(<4 x i32> %v) {1470; CHECK-LABEL: @add_or_disjoint(1471; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[V:%.*]], <i32 31, i32 31, i32 65536, i32 65537>1472; CHECK-NEXT:    ret <4 x i32> [[T3]]1473;1474  %t1 = add <4 x i32> %v, <i32 65534, i32 65535, i32 65536, i32 65537>1475  %t2 = or disjoint <4 x i32> %v, <i32 31, i32 31, i32 31, i32 31>1476  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1477  ret <4 x i32> %t31478}1479 1480; Try with 'or' as operand 0 of the shuffle.1481 1482define <4 x i8> @or_add(<4 x i8> %v) {1483; CHECK-LABEL: @or_add(1484; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], splat (i8 3)1485; CHECK-NEXT:    [[T3:%.*]] = add nuw nsw <4 x i8> [[V0]], <i8 1, i8 2, i8 -64, i8 -64>1486; CHECK-NEXT:    ret <4 x i8> [[T3]]1487;1488  %v0 = lshr <4 x i8> %v, <i8 3, i8 3, i8 3, i8 3>          ; clear the top bits1489  %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits1490  %t2 = add nsw nuw <4 x i8> %v0, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'1491  %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1492  ret <4 x i8> %t31493}1494 1495; Negative test: not all 'or' insts can be converted to 'add'.1496 1497define <4 x i8> @or_add_not_enough_masking(<4 x i8> %v) {1498; CHECK-LABEL: @or_add_not_enough_masking(1499; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], splat (i8 1)1500; CHECK-NEXT:    [[T1:%.*]] = or <4 x i8> [[V0]], <i8 poison, i8 poison, i8 -64, i8 -64>1501; CHECK-NEXT:    [[T2:%.*]] = add nuw nsw <4 x i8> [[V0]], <i8 1, i8 2, i8 poison, i8 poison>1502; CHECK-NEXT:    [[T3:%.*]] = shufflevector <4 x i8> [[T2]], <4 x i8> [[T1]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1503; CHECK-NEXT:    ret <4 x i8> [[T3]]1504;1505  %v0 = lshr <4 x i8> %v, <i8 1, i8 1, i8 1, i8 1>          ; clear not enough top bits1506  %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits1507  %t2 = add nsw nuw <4 x i8> %v0, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'1508  %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1509  ret <4 x i8> %t31510}1511 1512; Try with 2 variable inputs.1513 1514define <4 x i32> @add_or_2_vars(<4 x i32> %v, <4 x i32> %v1) {1515; CHECK-LABEL: @add_or_2_vars(1516; CHECK-NEXT:    [[V0:%.*]] = shl <4 x i32> [[V:%.*]], splat (i32 5)1517; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i32> [[V0]], <4 x i32> [[V1:%.*]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1518; CHECK-NEXT:    [[T3:%.*]] = add <4 x i32> [[TMP1]], <i32 31, i32 31, i32 65536, i32 65537>1519; CHECK-NEXT:    ret <4 x i32> [[T3]]1520;1521  %v0 = shl <4 x i32> %v, <i32 5, i32 5, i32 5, i32 5>                   ; clear the bottom bits1522  %t1 = add <4 x i32> %v1, <i32 65534, i32 65535, i32 65536, i32 65537>  ; this can't be converted to 'or'1523  %t2 = or <4 x i32> %v0, <i32 31, i32 31, i32 31, i32 31>               ; set the bottom bits1524  %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1525  ret <4 x i32> %t31526}1527 1528define <4 x i8> @or_add_2_vars(<4 x i8> %v, <4 x i8> %v1) {1529; CHECK-LABEL: @or_add_2_vars(1530; CHECK-NEXT:    [[V0:%.*]] = lshr <4 x i8> [[V:%.*]], splat (i8 3)1531; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i8> [[V1:%.*]], <4 x i8> [[V0]], <4 x i32> <i32 0, i32 1, i32 6, i32 7>1532; CHECK-NEXT:    [[T3:%.*]] = add nuw nsw <4 x i8> [[TMP1]], <i8 1, i8 2, i8 -64, i8 -64>1533; CHECK-NEXT:    ret <4 x i8> [[T3]]1534;1535  %v0 = lshr <4 x i8> %v, <i8 3, i8 3, i8 3, i8 3>          ; clear the top bits1536  %t1 = or <4 x i8> %v0, <i8 192, i8 192, i8 192, i8 192>   ; set some top bits1537  %t2 = add nsw nuw <4 x i8> %v1, <i8 1, i8 2, i8 3, i8 4>  ; this can't be converted to 'or'1538  %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <4 x i32> <i32 4, i32 5, i32 2, i32 3>1539  ret <4 x i8> %t31540}1541 1542; The undef operand is used to simplify the shuffle mask, but don't assert that too soon.1543 1544define <4 x i32> @PR41419(<4 x i32> %v) {1545; CHECK-LABEL: @PR41419(1546; CHECK-NEXT:    [[S:%.*]] = shufflevector <4 x i32> [[V:%.*]], <4 x i32> <i32 undef, i32 undef, i32 poison, i32 undef>, <4 x i32> <i32 4, i32 5, i32 2, i32 7>1547; CHECK-NEXT:    ret <4 x i32> [[S]]1548;1549  %s = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 4, i32 5, i32 2, i32 7>1550  ret <4 x i32> %s1551}1552 1553; The shuffle masks in the next 4 tests are identical to make it easier1554; to see that we are choosing the correct elements in the new shuffle.1555 1556define <5 x i4> @sel_common_op_commute0(<5 x i4> %x, <5 x i4> %y) {1557; CHECK-LABEL: @sel_common_op_commute0(1558; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[X:%.*]], <5 x i4> [[Y:%.*]], <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 4>1559; CHECK-NEXT:    ret <5 x i4> [[S2]]1560;1561  %s1 = shufflevector <5 x i4> %x, <5 x i4> %y, <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 9>1562  %s2 = shufflevector <5 x i4> %x, <5 x i4> %s1, <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 4>1563  ret <5 x i4> %s21564}1565 1566define <5 x i4> @sel_common_op_commute1(<5 x i4> %x, <5 x i4> %y) {1567; CHECK-LABEL: @sel_common_op_commute1(1568; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[X:%.*]], <5 x i4> [[Y:%.*]], <5 x i32> <i32 0, i32 1, i32 7, i32 3, i32 4>1569; CHECK-NEXT:    ret <5 x i4> [[S2]]1570;1571  %s1 = shufflevector <5 x i4> %y, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 9>1572  %s2 = shufflevector <5 x i4> %x, <5 x i4> %s1, <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 4>1573  ret <5 x i4> %s21574}1575 1576define <5 x i4> @sel_common_op_commute2(<5 x i4> %x, <5 x i4> %y) {1577; CHECK-LABEL: @sel_common_op_commute2(1578; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[X:%.*]], <5 x i4> [[Y:%.*]], <5 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9>1579; CHECK-NEXT:    ret <5 x i4> [[S2]]1580;1581  %s1 = shufflevector <5 x i4> %x, <5 x i4> %y, <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 9>1582  %s2 = shufflevector <5 x i4> %s1, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 4>1583  ret <5 x i4> %s21584}1585 1586define <5 x i4> @sel_common_op_commute3(<5 x i4> %x, <5 x i4> %y) {1587; CHECK-LABEL: @sel_common_op_commute3(1588; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[Y:%.*]], <5 x i4> [[X:%.*]], <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 9>1589; CHECK-NEXT:    ret <5 x i4> [[S2]]1590;1591  %s1 = shufflevector <5 x i4> %y, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 9>1592  %s2 = shufflevector <5 x i4> %s1, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 4>1593  ret <5 x i4> %s21594}1595 1596define <5 x i4> @sel_common_op_commute3_poison_mask_elts(<5 x i4> %x, <5 x i4> %y) {1597; CHECK-LABEL: @sel_common_op_commute3_poison_mask_elts(1598; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[Y:%.*]], <5 x i4> [[X:%.*]], <5 x i32> <i32 0, i32 6, i32 poison, i32 poison, i32 9>1599; CHECK-NEXT:    ret <5 x i4> [[S2]]1600;1601  %s1 = shufflevector <5 x i4> %y, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 2, i32 poison, i32 9>1602  %s2 = shufflevector <5 x i4> %s1, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 poison, i32 3, i32 4>1603  ret <5 x i4> %s21604}1605 1606; negative test - need shared operand1607 1608define <5 x i4> @sel_not_common_op_commute3(<5 x i4> %x, <5 x i4> %y, <5 x i4> %z) {1609; CHECK-LABEL: @sel_not_common_op_commute3(1610; CHECK-NEXT:    [[S1:%.*]] = shufflevector <5 x i4> [[Y:%.*]], <5 x i4> [[Z:%.*]], <5 x i32> <i32 0, i32 poison, i32 poison, i32 3, i32 9>1611; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[S1]], <5 x i4> [[X:%.*]], <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 4>1612; CHECK-NEXT:    ret <5 x i4> [[S2]]1613;1614  %s1 = shufflevector <5 x i4> %y, <5 x i4> %z, <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 9>1615  %s2 = shufflevector <5 x i4> %s1, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 7, i32 3, i32 4>1616  ret <5 x i4> %s21617}1618 1619; negative test - need "select" shuffle, no lane changes1620 1621define <5 x i4> @not_sel_common_op(<5 x i4> %x, <5 x i4> %y) {1622; CHECK-LABEL: @not_sel_common_op(1623; CHECK-NEXT:    [[S1:%.*]] = shufflevector <5 x i4> [[Y:%.*]], <5 x i4> [[X:%.*]], <5 x i32> <i32 poison, i32 6, i32 poison, i32 3, i32 9>1624; CHECK-NEXT:    [[S2:%.*]] = shufflevector <5 x i4> [[S1]], <5 x i4> [[X]], <5 x i32> <i32 1, i32 6, i32 7, i32 3, i32 4>1625; CHECK-NEXT:    ret <5 x i4> [[S2]]1626;1627  %s1 = shufflevector <5 x i4> %y, <5 x i4> %x, <5 x i32> <i32 0, i32 6, i32 2, i32 3, i32 9>1628  %s2 = shufflevector <5 x i4> %s1, <5 x i4> %x, <5 x i32> <i32 1, i32 6, i32 7, i32 3, i32 4>1629  ret <5 x i4> %s21630}1631 1632; extra use is ok1633 1634define <4 x i32> @sel_common_op_extra_use(<4 x i32> %x, <4 x i32> %y) {1635; CHECK-LABEL: @sel_common_op_extra_use(1636; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x i32> [[Y:%.*]], <4 x i32> [[X:%.*]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>1637; CHECK-NEXT:    call void @use_v4i32(<4 x i32> [[S1]])1638; CHECK-NEXT:    [[S2:%.*]] = shufflevector <4 x i32> [[Y]], <4 x i32> [[X]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>1639; CHECK-NEXT:    ret <4 x i32> [[S2]]1640;1641  %s1 = shufflevector <4 x i32> %y, <4 x i32> %x, <4 x i32> <i32 0, i32 5, i32 2, i32 7>1642  call void @use_v4i32(<4 x i32> %s1)1643  %s2 = shufflevector <4 x i32> %s1, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 6, i32 7>1644  ret <4 x i32> %s21645}1646 1647define <4 x float> @identity_mask(<4 x float>%x, <4 x float> %y) {1648; CHECK-LABEL: @identity_mask(1649; CHECK-NEXT:    [[S2:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <4 x i32> <i32 0, i32 poison, i32 2, i32 3>1650; CHECK-NEXT:    ret <4 x float> [[S2]]1651;1652  %s1 = shufflevector <4 x float> %x, <4 x float> %y, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef>1653  %s2 = shufflevector <4 x float> %s1, <4 x float> %x, <4 x i32> <i32 0, i32 undef, i32 6, i32 7>1654  ret <4 x float> %s21655}1656