1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare <2 x half> @llvm.fabs.v2f16(<2 x half>) 5declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 6declare <4 x float> @llvm.fabs.v4f32(<4 x float>) 7declare <2 x double> @llvm.fabs.v2f64(<2 x double>) 8declare <4 x double> @llvm.fabs.v4f64(<4 x double>) 9 10define <4 x float> @test1(<4 x float> %v1) { 11; CHECK-LABEL: @test1( 12; CHECK-NEXT: ret <4 x float> [[V1:%.*]] 13; 14 %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 15 ret <4 x float> %v2 16} 17 18define <4 x float> @test2(<4 x float> %v1) { 19; CHECK-LABEL: @test2( 20; CHECK-NEXT: ret <4 x float> [[V1:%.*]] 21; 22 %v2 = shufflevector <4 x float> %v1, <4 x float> %v1, <4 x i32> <i32 0, i32 5, i32 2, i32 7> 23 ret <4 x float> %v2 24} 25 26define float @test3(<4 x float> %A, <4 x float> %B, float %f) { 27; CHECK-LABEL: @test3( 28; CHECK-NEXT: ret float [[F:%.*]] 29; 30 %C = insertelement <4 x float> %A, float %f, i32 0 31 %D = shufflevector <4 x float> %C, <4 x float> %B, <4 x i32> <i32 5, i32 0, i32 2, i32 7> 32 %E = extractelement <4 x float> %D, i32 1 33 ret float %E 34} 35 36define i32 @test4(<4 x i32> %X) { 37; CHECK-LABEL: @test4( 38; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[X:%.*]], i64 0 39; CHECK-NEXT: ret i32 [[R]] 40; 41 %t = shufflevector <4 x i32> %X, <4 x i32> undef, <4 x i32> zeroinitializer 42 %r = extractelement <4 x i32> %t, i32 0 43 ret i32 %r 44} 45 46define i32 @test5(<4 x i32> %X) { 47; CHECK-LABEL: @test5( 48; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[X:%.*]], i64 3 49; CHECK-NEXT: ret i32 [[R]] 50; 51 %t = shufflevector <4 x i32> %X, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 undef, i32 undef> 52 %r = extractelement <4 x i32> %t, i32 0 53 ret i32 %r 54} 55 56define float @test6(<4 x float> %X) { 57; CHECK-LABEL: @test6( 58; CHECK-NEXT: [[R:%.*]] = extractelement <4 x float> [[X:%.*]], i64 0 59; CHECK-NEXT: ret float [[R]] 60; 61 %X1 = bitcast <4 x float> %X to <4 x i32> 62 %t = shufflevector <4 x i32> %X1, <4 x i32> undef, <4 x i32> zeroinitializer 63 %t2 = bitcast <4 x i32> %t to <4 x float> 64 %r = extractelement <4 x float> %t2, i32 0 65 ret float %r 66} 67 68define float @testvscale6(<vscale x 4 x float> %X) { 69; CHECK-LABEL: @testvscale6( 70; CHECK-NEXT: [[T2:%.*]] = shufflevector <vscale x 4 x float> [[X:%.*]], <vscale x 4 x float> poison, <vscale x 4 x i32> zeroinitializer 71; CHECK-NEXT: [[R:%.*]] = extractelement <vscale x 4 x float> [[T2]], i64 0 72; CHECK-NEXT: ret float [[R]] 73; 74 %X1 = bitcast <vscale x 4 x float> %X to <vscale x 4 x i32> 75 %t = shufflevector <vscale x 4 x i32> %X1, <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer 76 %t2 = bitcast <vscale x 4 x i32> %t to <vscale x 4 x float> 77 %r = extractelement <vscale x 4 x float> %t2, i32 0 78 ret float %r 79} 80 81 82define <4 x float> @test7(<4 x float> %x) { 83; CHECK-LABEL: @test7( 84; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> <float poison, float poison, float undef, float undef>, <4 x i32> <i32 0, i32 1, i32 6, i32 7> 85; CHECK-NEXT: ret <4 x float> [[R]] 86; 87 %r = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> < i32 0, i32 1, i32 6, i32 7 > 88 ret <4 x float> %r 89} 90 91; This should not turn into a single shuffle. 92define <4 x float> @test8(<4 x float> %x, <4 x float> %y) { 93; CHECK-LABEL: @test8( 94; CHECK-NEXT: [[T132:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> <float poison, float undef, float poison, float poison>, <4 x i32> <i32 1, i32 5, i32 3, i32 poison> 95; CHECK-NEXT: [[T134:%.*]] = shufflevector <4 x float> [[T132]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 4> 96; CHECK-NEXT: ret <4 x float> [[T134]] 97; 98 %t4 = extractelement <4 x float> %x, i32 1 99 %t2 = extractelement <4 x float> %x, i32 3 100 %t1 = extractelement <4 x float> %y, i32 0 101 %t128 = insertelement <4 x float> undef, float %t4, i32 0 102 %t130 = insertelement <4 x float> %t128, float undef, i32 1 103 %t132 = insertelement <4 x float> %t130, float %t2, i32 2 104 %t134 = insertelement <4 x float> %t132, float %t1, i32 3 105 ret <4 x float> %t134 106} 107 108; Test fold of two shuffles where the first shuffle vectors inputs are a 109; different length then the second. 110define <4 x i8> @test9(<16 x i8> %t6) { 111; CHECK-LABEL: @test9( 112; CHECK-NEXT: [[T9:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> poison, <4 x i32> <i32 13, i32 9, i32 4, i32 13> 113; CHECK-NEXT: ret <4 x i8> [[T9]] 114; 115 %t7 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> < i32 13, i32 9, i32 4, i32 13 > 116 %t9 = shufflevector <4 x i8> %t7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 > 117 ret <4 x i8> %t9 118} 119 120; Same as test9, but make sure that "undef" mask values are not confused with 121; mask values of 2*N, where N is the mask length. These shuffles should not 122; be folded (because [8,9,4,8] may not be a mask supported by the target). 123 124define <4 x i8> @test9a(<16 x i8> %t6) { 125; CHECK-LABEL: @test9a( 126; CHECK-NEXT: [[T7:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> poison, <4 x i32> <i32 poison, i32 9, i32 4, i32 8> 127; CHECK-NEXT: [[T9:%.*]] = shufflevector <4 x i8> [[T7]], <4 x i8> poison, <4 x i32> <i32 3, i32 1, i32 2, i32 poison> 128; CHECK-NEXT: ret <4 x i8> [[T9]] 129; 130 %t7 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> < i32 undef, i32 9, i32 4, i32 8 > 131 %t9 = shufflevector <4 x i8> %t7, <4 x i8> undef, <4 x i32> < i32 3, i32 1, i32 2, i32 0 > 132 ret <4 x i8> %t9 133} 134 135; Test fold of two shuffles where the first shuffle vectors inputs are a 136; different length then the second. 137define <4 x i8> @test9b(<4 x i8> %t6, <4 x i8> %t7) { 138; CHECK-LABEL: @test9b( 139; CHECK-NEXT: [[T9:%.*]] = shufflevector <4 x i8> [[T6:%.*]], <4 x i8> [[T7:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 140; CHECK-NEXT: ret <4 x i8> [[T9]] 141; 142 %t1 = shufflevector <4 x i8> %t6, <4 x i8> %t7, <8 x i32> <i32 0, i32 1, i32 4, i32 5, i32 4, i32 5, i32 2, i32 3> 143 %t9 = shufflevector <8 x i8> %t1, <8 x i8> undef, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 144 ret <4 x i8> %t9 145} 146 147; Redundant vector splats should be removed. Radar 8597790. 148define <4 x i32> @test10(<4 x i32> %t5) { 149; CHECK-LABEL: @test10( 150; CHECK-NEXT: [[T7:%.*]] = shufflevector <4 x i32> [[T5:%.*]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1> 151; CHECK-NEXT: ret <4 x i32> [[T7]] 152; 153 %t6 = shufflevector <4 x i32> %t5, <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef> 154 %t7 = shufflevector <4 x i32> %t6, <4 x i32> undef, <4 x i32> zeroinitializer 155 ret <4 x i32> %t7 156} 157 158; Test fold of two shuffles where the two shufflevector inputs's op1 are the same. 159 160define <8 x i8> @test11(<16 x i8> %t6) { 161; CHECK-LABEL: @test11( 162; CHECK-NEXT: [[T3:%.*]] = shufflevector <16 x i8> [[T6:%.*]], <16 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 163; CHECK-NEXT: ret <8 x i8> [[T3]] 164; 165 %t1 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 166 %t2 = shufflevector <16 x i8> %t6, <16 x i8> undef, <4 x i32> <i32 4, i32 5, i32 6, i32 7> 167 %t3 = shufflevector <4 x i8> %t1, <4 x i8> %t2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> 168 ret <8 x i8> %t3 169} 170 171; Test fold of two shuffles where the first shufflevector's inputs are the same as the second. 172 173define <8 x i8> @test12(<8 x i8> %t6, <8 x i8> %t2) { 174; CHECK-LABEL: @test12( 175; CHECK-NEXT: [[T3:%.*]] = shufflevector <8 x i8> [[T6:%.*]], <8 x i8> [[T2:%.*]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12> 176; CHECK-NEXT: ret <8 x i8> [[T3]] 177; 178 %t1 = shufflevector <8 x i8> %t6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7> 179 %t3 = shufflevector <8 x i8> %t1, <8 x i8> %t2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 9, i32 8, i32 11, i32 12> 180 ret <8 x i8> %t3 181} 182 183; Test fold of two shuffles where the first shufflevector's inputs are the same as the second. 184 185define <8 x i8> @test12a(<8 x i8> %t6, <8 x i8> %t2) { 186; CHECK-LABEL: @test12a( 187; CHECK-NEXT: [[T3:%.*]] = shufflevector <8 x i8> [[T2:%.*]], <8 x i8> [[T6:%.*]], <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11> 188; CHECK-NEXT: ret <8 x i8> [[T3]] 189; 190 %t1 = shufflevector <8 x i8> %t6, <8 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 5, i32 4, i32 undef, i32 7> 191 %t3 = shufflevector <8 x i8> %t2, <8 x i8> %t1, <8 x i32> <i32 0, i32 3, i32 1, i32 4, i32 8, i32 9, i32 10, i32 11> 192 ret <8 x i8> %t3 193} 194 195; The mask length of the 1st shuffle can be reduced to eliminate the 2nd shuffle. 196 197define <2 x i8> @extract_subvector_of_shuffle(<2 x i8> %x, <2 x i8> %y) { 198; CHECK-LABEL: @extract_subvector_of_shuffle( 199; CHECK-NEXT: [[EXTRACT_SUBV:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 2> 200; CHECK-NEXT: ret <2 x i8> [[EXTRACT_SUBV]] 201; 202 %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <3 x i32> <i32 0, i32 2, i32 0> 203 %extract_subv = shufflevector <3 x i8> %shuf, <3 x i8> undef, <2 x i32> <i32 0, i32 1> 204 ret <2 x i8> %extract_subv 205} 206 207; Undef elements in either mask are ok. Undefs from the 2nd shuffle mask should propagate to the new shuffle. 208; The type of the inputs does not have to match the output type. 209 210define <4 x i8> @extract_subvector_of_shuffle_undefs_types(<2 x i8> %x, <2 x i8> %y) { 211; CHECK-LABEL: @extract_subvector_of_shuffle_undefs_types( 212; CHECK-NEXT: [[EXTRACT_SUBV:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <4 x i32> <i32 poison, i32 2, i32 0, i32 poison> 213; CHECK-NEXT: ret <4 x i8> [[EXTRACT_SUBV]] 214; 215 %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0> 216 %extract_subv = shufflevector <5 x i8> %shuf, <5 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> 217 ret <4 x i8> %extract_subv 218} 219 220; Extra uses are not ok - we only do the transform when we can eliminate an instruction. 221 222declare void @use_v5i8(<5 x i8>) 223 224define <4 x i8> @extract_subvector_of_shuffle_extra_use(<2 x i8> %x, <2 x i8> %y) { 225; CHECK-LABEL: @extract_subvector_of_shuffle_extra_use( 226; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <5 x i32> <i32 poison, i32 2, i32 0, i32 1, i32 0> 227; CHECK-NEXT: call void @use_v5i8(<5 x i8> [[SHUF]]) 228; CHECK-NEXT: [[EXTRACT_SUBV:%.*]] = shufflevector <5 x i8> [[SHUF]], <5 x i8> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 poison> 229; CHECK-NEXT: ret <4 x i8> [[EXTRACT_SUBV]] 230; 231 %shuf = shufflevector <2 x i8> %x, <2 x i8> %y, <5 x i32> <i32 undef, i32 2, i32 0, i32 1, i32 0> 232 call void @use_v5i8(<5 x i8> %shuf) 233 %extract_subv = shufflevector <5 x i8> %shuf, <5 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef> 234 ret <4 x i8> %extract_subv 235} 236 237define <2 x i8> @test13a(i8 %x1, i8 %x2) { 238; CHECK-LABEL: @test13a( 239; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[X2:%.*]], i64 0 240; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[X1:%.*]], i64 1 241; CHECK-NEXT: [[D:%.*]] = add <2 x i8> [[TMP2]], <i8 7, i8 5> 242; CHECK-NEXT: ret <2 x i8> [[D]] 243; 244 %A = insertelement <2 x i8> undef, i8 %x1, i32 0 245 %B = insertelement <2 x i8> %A, i8 %x2, i32 1 246 %C = add <2 x i8> %B, <i8 5, i8 7> 247 %D = shufflevector <2 x i8> %C, <2 x i8> undef, <2 x i32> <i32 1, i32 0> 248 ret <2 x i8> %D 249} 250 251; Increasing length of vector ops is not a good canonicalization. 252 253define <3 x i32> @add_wider(i32 %y, i32 %z) { 254; CHECK-LABEL: @add_wider( 255; CHECK-NEXT: [[I0:%.*]] = insertelement <2 x i32> poison, i32 [[Y:%.*]], i64 0 256; CHECK-NEXT: [[I1:%.*]] = insertelement <2 x i32> [[I0]], i32 [[Z:%.*]], i64 1 257; CHECK-NEXT: [[A:%.*]] = add <2 x i32> [[I1]], splat (i32 255) 258; CHECK-NEXT: [[EXT:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> poison, <3 x i32> <i32 0, i32 1, i32 poison> 259; CHECK-NEXT: ret <3 x i32> [[EXT]] 260; 261 %i0 = insertelement <2 x i32> undef, i32 %y, i32 0 262 %i1 = insertelement <2 x i32> %i0, i32 %z, i32 1 263 %a = add <2 x i32> %i1, <i32 255, i32 255> 264 %ext = shufflevector <2 x i32> %a, <2 x i32> undef, <3 x i32> <i32 0, i32 1, i32 undef> 265 ret <3 x i32> %ext 266} 267 268; Increasing length of vector ops must be safe from illegal undef propagation. 269 270define <3 x i32> @div_wider(i32 %y, i32 %z) { 271; CHECK-LABEL: @div_wider( 272; CHECK-NEXT: [[I0:%.*]] = insertelement <2 x i32> poison, i32 [[Y:%.*]], i64 0 273; CHECK-NEXT: [[I1:%.*]] = insertelement <2 x i32> [[I0]], i32 [[Z:%.*]], i64 1 274; CHECK-NEXT: [[A:%.*]] = sdiv <2 x i32> [[I1]], splat (i32 255) 275; CHECK-NEXT: [[EXT:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> poison, <3 x i32> <i32 0, i32 1, i32 poison> 276; CHECK-NEXT: ret <3 x i32> [[EXT]] 277; 278 %i0 = insertelement <2 x i32> undef, i32 %y, i32 0 279 %i1 = insertelement <2 x i32> %i0, i32 %z, i32 1 280 %a = sdiv <2 x i32> %i1, <i32 255, i32 255> 281 %ext = shufflevector <2 x i32> %a, <2 x i32> undef, <3 x i32> <i32 0, i32 1, i32 undef> 282 ret <3 x i32> %ext 283} 284 285; Increasing length of insertelements (no math ops) is a good canonicalization. 286 287define <3 x i8> @fold_inselts_with_widening_shuffle(i8 %x, i8 %y) { 288; CHECK-LABEL: @fold_inselts_with_widening_shuffle( 289; CHECK-NEXT: [[TMP1:%.*]] = insertelement <3 x i8> poison, i8 [[X:%.*]], i64 0 290; CHECK-NEXT: [[WIDEN:%.*]] = insertelement <3 x i8> [[TMP1]], i8 [[Y:%.*]], i64 1 291; CHECK-NEXT: ret <3 x i8> [[WIDEN]] 292; 293 %ins0 = insertelement <2 x i8> undef, i8 %x, i32 0 294 %ins1 = insertelement <2 x i8> %ins0, i8 %y, i32 1 295 %widen = shufflevector <2 x i8> %ins1, <2 x i8> undef, <3 x i32> <i32 0, i32 1, i32 undef> 296 ret <3 x i8> %widen 297} 298 299define <2 x i8> @test13b(i8 %x) { 300; CHECK-LABEL: @test13b( 301; CHECK-NEXT: [[B:%.*]] = insertelement <2 x i8> poison, i8 [[X:%.*]], i64 1 302; CHECK-NEXT: ret <2 x i8> [[B]] 303; 304 %A = insertelement <2 x i8> undef, i8 %x, i32 0 305 %B = shufflevector <2 x i8> %A, <2 x i8> undef, <2 x i32> <i32 undef, i32 0> 306 ret <2 x i8> %B 307} 308 309define <2 x i8> @test13c(i8 %x1, i8 %x2) { 310; CHECK-LABEL: @test13c( 311; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[X1:%.*]], i64 0 312; CHECK-NEXT: [[C:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[X2:%.*]], i64 1 313; CHECK-NEXT: ret <2 x i8> [[C]] 314; 315 %A = insertelement <4 x i8> undef, i8 %x1, i32 0 316 %B = insertelement <4 x i8> %A, i8 %x2, i32 2 317 %C = shufflevector <4 x i8> %B, <4 x i8> undef, <2 x i32> <i32 0, i32 2> 318 ret <2 x i8> %C 319} 320 321define void @test14(i16 %conv10) { 322; CHECK-LABEL: @test14( 323; CHECK-NEXT: store <4 x i16> <i16 undef, i16 undef, i16 undef, i16 23>, ptr undef, align 8 324; CHECK-NEXT: ret void 325; 326 %t = alloca <4 x i16>, align 8 327 %vecinit6 = insertelement <4 x i16> undef, i16 23, i32 3 328 store <4 x i16> %vecinit6, ptr undef 329 %t1 = load <4 x i16>, ptr undef 330 %vecinit11 = insertelement <4 x i16> undef, i16 %conv10, i32 3 331 %div = udiv <4 x i16> %t1, %vecinit11 332 store <4 x i16> %div, ptr %t 333 %t4 = load <4 x i16>, ptr %t 334 %t5 = shufflevector <4 x i16> %t4, <4 x i16> undef, <2 x i32> <i32 2, i32 0> 335 %cmp = icmp ule <2 x i16> %t5, undef 336 %sext = sext <2 x i1> %cmp to <2 x i16> 337 ret void 338} 339 340; Check that sequences of insert/extract element are 341; collapsed into valid shuffle instruction with correct shuffle indexes. 342 343define <4 x float> @test15a(<4 x float> %LHS, <4 x float> %RHS) { 344; CHECK-LABEL: @test15a( 345; CHECK-NEXT: [[T4:%.*]] = shufflevector <4 x float> [[LHS:%.*]], <4 x float> [[RHS:%.*]], <4 x i32> <i32 4, i32 0, i32 6, i32 6> 346; CHECK-NEXT: ret <4 x float> [[T4]] 347; 348 %t1 = extractelement <4 x float> %LHS, i32 0 349 %t2 = insertelement <4 x float> %RHS, float %t1, i32 1 350 %t3 = extractelement <4 x float> %RHS, i32 2 351 %t4 = insertelement <4 x float> %t2, float %t3, i32 3 352 ret <4 x float> %t4 353} 354 355define <4 x float> @test15b(<4 x float> %LHS, <4 x float> %RHS) { 356; CHECK-LABEL: @test15b( 357; CHECK-NEXT: [[T5:%.*]] = shufflevector <4 x float> [[LHS:%.*]], <4 x float> [[RHS:%.*]], <4 x i32> <i32 4, i32 3, i32 6, i32 6> 358; CHECK-NEXT: ret <4 x float> [[T5]] 359; 360 %t0 = extractelement <4 x float> %LHS, i32 3 361 %t1 = insertelement <4 x float> %RHS, float %t0, i32 0 362 %t2 = extractelement <4 x float> %t1, i32 0 363 %t3 = insertelement <4 x float> %RHS, float %t2, i32 1 364 %t4 = extractelement <4 x float> %RHS, i32 2 365 %t5 = insertelement <4 x float> %t3, float %t4, i32 3 366 ret <4 x float> %t5 367} 368 369define <1 x i32> @test16a(i32 %ele) { 370; CHECK-LABEL: @test16a( 371; CHECK-NEXT: ret <1 x i32> splat (i32 2) 372; 373 %t0 = insertelement <2 x i32> <i32 1, i32 undef>, i32 %ele, i32 1 374 %t1 = shl <2 x i32> %t0, <i32 1, i32 1> 375 %t2 = shufflevector <2 x i32> %t1, <2 x i32> undef, <1 x i32> <i32 0> 376 ret <1 x i32> %t2 377} 378 379define <4 x i8> @test16b(i8 %ele) { 380; CHECK-LABEL: @test16b( 381; CHECK-NEXT: ret <4 x i8> splat (i8 2) 382; 383 %t0 = insertelement <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 undef, i8 1>, i8 %ele, i32 6 384 %t1 = shl <8 x i8> %t0, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> 385 %t2 = shufflevector <8 x i8> %t1, <8 x i8> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 4> 386 ret <4 x i8> %t2 387} 388 389; If composition of two shuffles is identity, shuffles can be removed. 390define <4 x i32> @shuffle_17ident(<4 x i32> %v) { 391; CHECK-LABEL: @shuffle_17ident( 392; CHECK-NEXT: ret <4 x i32> [[V:%.*]] 393; 394 %shuffle = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 395 %shuffle2 = shufflevector <4 x i32> %shuffle, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 0, i32 1, i32 2> 396 ret <4 x i32> %shuffle2 397} 398 399; swizzle can be put after operation 400define <4 x i32> @shuffle_17and(<4 x i32> %v1, <4 x i32> %v2) { 401; CHECK-LABEL: @shuffle_17and( 402; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[V1:%.*]], [[V2:%.*]] 403; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 404; CHECK-NEXT: ret <4 x i32> [[R]] 405; 406 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 407 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 408 %r = and <4 x i32> %t1, %t2 409 ret <4 x i32> %r 410} 411 412declare void @use(<2 x float>) 413declare void @use4(<4 x float>) 414 415; One extra use is ok to transform. 416 417define <2 x float> @shuffle_fadd_multiuse(<2 x float> %v1, <2 x float> %v2) { 418; CHECK-LABEL: @shuffle_fadd_multiuse( 419; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 420; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x float> [[V1]], [[V2:%.*]] 421; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 422; CHECK-NEXT: call void @use(<2 x float> [[T1]]) 423; CHECK-NEXT: ret <2 x float> [[R]] 424; 425 %t1 = shufflevector <2 x float> %v1, <2 x float> undef, <2 x i32> <i32 1, i32 0> 426 %t2 = shufflevector <2 x float> %v2, <2 x float> undef, <2 x i32> <i32 1, i32 0> 427 %r = fadd <2 x float> %t1, %t2 428 call void @use(<2 x float> %t1) 429 ret <2 x float> %r 430} 431 432define <2 x float> @shuffle_fdiv_multiuse(<2 x float> %v1, <2 x float> %v2) { 433; CHECK-LABEL: @shuffle_fdiv_multiuse( 434; CHECK-NEXT: [[T2:%.*]] = shufflevector <2 x float> [[V2:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 435; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> [[V1:%.*]], [[V2]] 436; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 437; CHECK-NEXT: call void @use(<2 x float> [[T2]]) 438; CHECK-NEXT: ret <2 x float> [[R]] 439; 440 %t1 = shufflevector <2 x float> %v1, <2 x float> undef, <2 x i32> <i32 1, i32 0> 441 %t2 = shufflevector <2 x float> %v2, <2 x float> undef, <2 x i32> <i32 1, i32 0> 442 %r = fdiv <2 x float> %t1, %t2 443 call void @use(<2 x float> %t2) 444 ret <2 x float> %r 445} 446 447; But 2 extra uses would require an extra instruction. 448 449define <2 x float> @shuffle_fsub_multiuse(<2 x float> %v1, <2 x float> %v2) { 450; CHECK-LABEL: @shuffle_fsub_multiuse( 451; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V1:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 452; CHECK-NEXT: [[T2:%.*]] = shufflevector <2 x float> [[V2:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 453; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[T1]], [[T2]] 454; CHECK-NEXT: call void @use(<2 x float> [[T1]]) 455; CHECK-NEXT: call void @use(<2 x float> [[T2]]) 456; CHECK-NEXT: ret <2 x float> [[R]] 457; 458 %t1 = shufflevector <2 x float> %v1, <2 x float> undef, <2 x i32> <i32 1, i32 0> 459 %t2 = shufflevector <2 x float> %v2, <2 x float> undef, <2 x i32> <i32 1, i32 0> 460 %r = fsub <2 x float> %t1, %t2 461 call void @use(<2 x float> %t1) 462 call void @use(<2 x float> %t2) 463 ret <2 x float> %r 464} 465 466define <4 x i32> @shuffle_17add(<4 x i32> %v1, <4 x i32> %v2) { 467; CHECK-LABEL: @shuffle_17add( 468; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[V1:%.*]], [[V2:%.*]] 469; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 470; CHECK-NEXT: ret <4 x i32> [[R]] 471; 472 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 473 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 474 %r = add <4 x i32> %t1, %t2 475 ret <4 x i32> %r 476} 477 478define <4 x i32> @shuffle_17addnsw(<4 x i32> %v1, <4 x i32> %v2) { 479; CHECK-LABEL: @shuffle_17addnsw( 480; CHECK-NEXT: [[TMP1:%.*]] = add nsw <4 x i32> [[V1:%.*]], [[V2:%.*]] 481; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 482; CHECK-NEXT: ret <4 x i32> [[R]] 483; 484 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 485 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 486 %r = add nsw <4 x i32> %t1, %t2 487 ret <4 x i32> %r 488} 489 490define <4 x i32> @shuffle_17addnuw(<4 x i32> %v1, <4 x i32> %v2) { 491; CHECK-LABEL: @shuffle_17addnuw( 492; CHECK-NEXT: [[TMP1:%.*]] = add nuw <4 x i32> [[V1:%.*]], [[V2:%.*]] 493; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 494; CHECK-NEXT: ret <4 x i32> [[R]] 495; 496 %t1 = shufflevector <4 x i32> %v1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 497 %t2 = shufflevector <4 x i32> %v2, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 498 %r = add nuw <4 x i32> %t1, %t2 499 ret <4 x i32> %r 500} 501 502define <4 x float> @shuffle_17fsub_fast(<4 x float> %v1, <4 x float> %v2) { 503; CHECK-LABEL: @shuffle_17fsub_fast( 504; CHECK-NEXT: [[TMP1:%.*]] = fsub fast <4 x float> [[V1:%.*]], [[V2:%.*]] 505; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 506; CHECK-NEXT: ret <4 x float> [[R]] 507; 508 %t1 = shufflevector <4 x float> %v1, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 509 %t2 = shufflevector <4 x float> %v2, <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 510 %r = fsub fast <4 x float> %t1, %t2 511 ret <4 x float> %r 512} 513 514define <4 x i32> @add_const(<4 x i32> %v) { 515; CHECK-LABEL: @add_const( 516; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[V:%.*]], <i32 44, i32 41, i32 42, i32 43> 517; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 518; CHECK-NEXT: ret <4 x i32> [[R]] 519; 520 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 521 %r = add <4 x i32> %t1, <i32 41, i32 42, i32 43, i32 44> 522 ret <4 x i32> %r 523} 524 525define <4 x i32> @sub_const(<4 x i32> %v) { 526; CHECK-LABEL: @sub_const( 527; CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i32> <i32 44, i32 43, i32 42, i32 41>, [[V:%.*]] 528; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 529; CHECK-NEXT: ret <4 x i32> [[R]] 530; 531 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 532 %r = sub <4 x i32> <i32 41, i32 42, i32 43, i32 44>, %t1 533 ret <4 x i32> %r 534} 535 536; Math before shuffle requires an extra shuffle. 537 538define <2 x float> @fadd_const_multiuse(<2 x float> %v) { 539; CHECK-LABEL: @fadd_const_multiuse( 540; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 541; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[T1]], <float 4.100000e+01, float 4.200000e+01> 542; CHECK-NEXT: call void @use(<2 x float> [[T1]]) 543; CHECK-NEXT: ret <2 x float> [[R]] 544; 545 %t1 = shufflevector <2 x float> %v, <2 x float> undef, <2 x i32> <i32 1, i32 0> 546 %r = fadd <2 x float> %t1, <float 41.0, float 42.0> 547 call void @use(<2 x float> %t1) 548 ret <2 x float> %r 549} 550 551; Math before splat allows replacing constant elements with undef lanes. 552 553define <4 x i32> @mul_const_splat(<4 x i32> %v) { 554; CHECK-LABEL: @mul_const_splat( 555; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i32> [[V:%.*]], <i32 poison, i32 42, i32 poison, i32 poison> 556; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1> 557; CHECK-NEXT: ret <4 x i32> [[R]] 558; 559 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1> 560 %r = mul <4 x i32> <i32 42, i32 42, i32 42, i32 42>, %t1 561 ret <4 x i32> %r 562} 563 564; Take 2 elements of a vector and shift each of those by a different amount 565 566define <4 x i32> @lshr_const_half_splat(<4 x i32> %v) { 567; CHECK-LABEL: @lshr_const_half_splat( 568; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> <i32 poison, i32 8, i32 9, i32 poison>, [[V:%.*]] 569; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 2> 570; CHECK-NEXT: ret <4 x i32> [[R]] 571; 572 %t1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 2> 573 %r = lshr <4 x i32> <i32 8, i32 8, i32 9, i32 9>, %t1 574 ret <4 x i32> %r 575} 576 577; We can't change this because there's no pre-shuffle version of the fmul constant. 578 579define <2 x float> @fmul_const_invalid_constant(<2 x float> %v) { 580; CHECK-LABEL: @fmul_const_invalid_constant( 581; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x float> [[V:%.*]], <2 x float> poison, <2 x i32> zeroinitializer 582; CHECK-NEXT: [[R:%.*]] = fmul <2 x float> [[T1]], <float 4.100000e+01, float 4.200000e+01> 583; CHECK-NEXT: ret <2 x float> [[R]] 584; 585 %t1 = shufflevector <2 x float> %v, <2 x float> undef, <2 x i32> <i32 0, i32 0> 586 %r = fmul <2 x float> %t1, <float 41.0, float 42.0> 587 ret <2 x float> %r 588} 589 590; Reduce the width of the binop by moving it ahead of a shuffle. 591 592define <4 x i8> @widening_shuffle_add_1(<2 x i8> %x) { 593; CHECK-LABEL: @widening_shuffle_add_1( 594; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 42, i8 43> 595; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 596; CHECK-NEXT: ret <4 x i8> [[R]] 597; 598 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> 599 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45> 600 ret <4 x i8> %r 601} 602 603; Reduce the width of the binop by moving it ahead of a shuffle. 604 605define <4 x i8> @widening_shuffle_add_2(<2 x i8> %x) { 606; CHECK-LABEL: @widening_shuffle_add_2( 607; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 43, i8 42> 608; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32> <i32 1, i32 0, i32 poison, i32 poison> 609; CHECK-NEXT: ret <4 x i8> [[R]] 610; 611 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef> 612 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45> 613 ret <4 x i8> %r 614} 615 616; Negative test - widening shuffles have the same mask/constant constraint as non-size-changing shuffles. 617 618define <4 x i8> @widening_shuffle_add_invalid_constant(<2 x i8> %x) { 619; CHECK-LABEL: @widening_shuffle_add_invalid_constant( 620; CHECK-NEXT: [[WIDEX:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> poison, <4 x i32> <i32 1, i32 1, i32 poison, i32 poison> 621; CHECK-NEXT: [[R:%.*]] = add <4 x i8> [[WIDEX]], <i8 42, i8 43, i8 44, i8 45> 622; CHECK-NEXT: ret <4 x i8> [[R]] 623; 624 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 1, i32 1, i32 undef, i32 undef> 625 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45> 626 ret <4 x i8> %r 627} 628 629; Negative test - widening shuffles have an additional constraint: they must not extend with anything but undefs. 630 631define <4 x i8> @widening_shuffle_add_invalid_mask(<2 x i8> %x) { 632; CHECK-LABEL: @widening_shuffle_add_invalid_mask( 633; CHECK-NEXT: [[WIDEX:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 0> 634; CHECK-NEXT: [[R:%.*]] = add <4 x i8> [[WIDEX]], <i8 42, i8 43, i8 44, i8 45> 635; CHECK-NEXT: ret <4 x i8> [[R]] 636; 637 %widex = shufflevector <2 x i8> %x, <2 x i8> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 0> 638 %r = add <4 x i8> %widex, <i8 42, i8 43, i8 44, i8 45> 639 ret <4 x i8> %r 640} 641 642; A binop that produces undef in the high lanes can be moved before the shuffle. 643; This is ok because 'shl C, undef --> undef'. 644 645define <4 x i16> @widening_shuffle_shl_constant_op0(<2 x i16> %v) { 646; CHECK-LABEL: @widening_shuffle_shl_constant_op0( 647; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> <i16 42, i16 -42>, [[V:%.*]] 648; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 649; CHECK-NEXT: ret <4 x i16> [[BO]] 650; 651 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> 652 %bo = shl <4 x i16> <i16 42, i16 -42, i16 -1, i16 -1>, %shuf 653 ret <4 x i16> %bo 654} 655 656; A binop that produces undef in the high lanes can be moved before the shuffle. 657; This is ok because 'shl undef, 0 --> undef'. 658 659define <4 x i16> @widening_shuffle_shl_constant_op1(<2 x i16> %v) { 660; CHECK-LABEL: @widening_shuffle_shl_constant_op1( 661; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4> 662; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 663; CHECK-NEXT: ret <4 x i16> [[BO]] 664; 665 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> 666 %bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 0, i16 0> 667 ret <4 x i16> %bo 668} 669 670; This is valid for poison, but would not be valid for undef. 671 672define <4 x i16> @widening_shuffle_shl_constant_op1_non0(<2 x i16> %v) { 673; CHECK-LABEL: @widening_shuffle_shl_constant_op1_non0( 674; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i16> [[V:%.*]], <i16 2, i16 4> 675; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 676; CHECK-NEXT: ret <4 x i16> [[BO]] 677; 678 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> 679 %bo = shl <4 x i16> %shuf, <i16 2, i16 4, i16 1, i16 2> 680 ret <4 x i16> %bo 681} 682 683; A binop that does not produce undef in the high lanes can not be moved before the shuffle. 684; This is not ok because 'or -1, undef --> -1' but moving the shuffle results in undef instead. 685 686define <4 x i16> @widening_shuffle_or(<2 x i16> %v) { 687; CHECK-LABEL: @widening_shuffle_or( 688; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i16> [[V:%.*]], <i16 42, i16 -42> 689; CHECK-NEXT: [[BO:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 690; CHECK-NEXT: ret <4 x i16> [[BO]] 691; 692 %shuf = shufflevector <2 x i16> %v, <2 x i16> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> 693 %bo = or <4 x i16> %shuf, <i16 42, i16 -42, i16 -1, i16 -1> 694 ret <4 x i16> %bo 695} 696 697define <4 x i32> @shuffle_17add2(<4 x i32> %v) { 698; CHECK-LABEL: @shuffle_17add2( 699; CHECK-NEXT: [[TMP1:%.*]] = shl <4 x i32> [[V:%.*]], splat (i32 1) 700; CHECK-NEXT: ret <4 x i32> [[TMP1]] 701; 702 %t1 = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 703 %t2 = add <4 x i32> %t1, %t1 704 %r = shufflevector <4 x i32> %t2, <4 x i32> zeroinitializer, <4 x i32> <i32 3, i32 2, i32 1, i32 0> 705 ret <4 x i32> %r 706} 707 708define <4 x i32> @shuffle_17mulsplat(<4 x i32> %v) { 709; CHECK-LABEL: @shuffle_17mulsplat( 710; CHECK-NEXT: [[TMP1:%.*]] = mul <4 x i32> [[V:%.*]], [[V]] 711; CHECK-NEXT: [[M1:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer 712; CHECK-NEXT: ret <4 x i32> [[M1]] 713; 714 %s1 = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer 715 %m1 = mul <4 x i32> %s1, %s1 716 %s2 = shufflevector <4 x i32> %m1, <4 x i32> zeroinitializer, <4 x i32> <i32 1, i32 1, i32 1, i32 1> 717 ret <4 x i32> %s2 718} 719 720; Do not reorder shuffle and binop if LHS of shuffles are of different size 721define <2 x i32> @pr19717(<4 x i32> %in0, <2 x i32> %in1) { 722; CHECK-LABEL: @pr19717( 723; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i32> [[IN0:%.*]], <4 x i32> poison, <2 x i32> zeroinitializer 724; CHECK-NEXT: [[SHUFFLE4:%.*]] = shufflevector <2 x i32> [[IN1:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer 725; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i32> [[SHUFFLE]], [[SHUFFLE4]] 726; CHECK-NEXT: ret <2 x i32> [[MUL]] 727; 728 %shuffle = shufflevector <4 x i32> %in0, <4 x i32> %in0, <2 x i32> zeroinitializer 729 %shuffle4 = shufflevector <2 x i32> %in1, <2 x i32> %in1, <2 x i32> zeroinitializer 730 %mul = mul <2 x i32> %shuffle, %shuffle4 731 ret <2 x i32> %mul 732} 733 734define <4 x i16> @pr19717a(<8 x i16> %in0, <8 x i16> %in1) { 735; CHECK-LABEL: @pr19717a( 736; CHECK-NEXT: [[TMP1:%.*]] = mul <8 x i16> [[IN0:%.*]], [[IN1:%.*]] 737; CHECK-NEXT: [[MUL:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <4 x i32> <i32 5, i32 5, i32 5, i32 5> 738; CHECK-NEXT: ret <4 x i16> [[MUL]] 739; 740 %shuffle = shufflevector <8 x i16> %in0, <8 x i16> %in0, <4 x i32> <i32 5, i32 5, i32 5, i32 5> 741 %shuffle1 = shufflevector <8 x i16> %in1, <8 x i16> %in1, <4 x i32> <i32 5, i32 5, i32 5, i32 5> 742 %mul = mul <4 x i16> %shuffle, %shuffle1 743 ret <4 x i16> %mul 744} 745 746define <8 x i8> @pr19730(<16 x i8> %in0) { 747; CHECK-LABEL: @pr19730( 748; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <16 x i8> [[IN0:%.*]], <16 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0> 749; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <8 x i8> [[SHUFFLE]], <8 x i8> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0> 750; CHECK-NEXT: ret <8 x i8> [[SHUFFLE1]] 751; 752 %shuffle = shufflevector <16 x i8> %in0, <16 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0> 753 %shuffle1 = shufflevector <8 x i8> %shuffle, <8 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0> 754 ret <8 x i8> %shuffle1 755} 756 757define i32 @pr19737(<4 x i32> %in0) { 758; CHECK-LABEL: @pr19737( 759; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i32> [[IN0:%.*]], i64 0 760; CHECK-NEXT: ret i32 [[TMP1]] 761; 762 %shuffle.i = shufflevector <4 x i32> zeroinitializer, <4 x i32> %in0, <4 x i32> <i32 0, i32 4, i32 2, i32 6> 763 %neg.i = xor <4 x i32> %shuffle.i, <i32 -1, i32 -1, i32 -1, i32 -1> 764 %and.i = and <4 x i32> %in0, %neg.i 765 %rv = extractelement <4 x i32> %and.i, i32 0 766 ret i32 %rv 767} 768 769; In PR20059 ( http://llvm.org/pr20059 ), shufflevector operations are reordered/removed 770; for an srem operation. This is not a valid optimization because it may cause a trap 771; on div-by-zero. 772 773define <4 x i32> @pr20059(<4 x i32> %p1, <4 x i32> %p2) { 774; CHECK-LABEL: @pr20059( 775; CHECK-NEXT: [[SPLAT1:%.*]] = shufflevector <4 x i32> [[P1:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer 776; CHECK-NEXT: [[SPLAT2:%.*]] = shufflevector <4 x i32> [[P2:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer 777; CHECK-NEXT: [[RETVAL:%.*]] = srem <4 x i32> [[SPLAT1]], [[SPLAT2]] 778; CHECK-NEXT: ret <4 x i32> [[RETVAL]] 779; 780 %splat1 = shufflevector <4 x i32> %p1, <4 x i32> undef, <4 x i32> zeroinitializer 781 %splat2 = shufflevector <4 x i32> %p2, <4 x i32> undef, <4 x i32> zeroinitializer 782 %retval = srem <4 x i32> %splat1, %splat2 783 ret <4 x i32> %retval 784} 785 786define <4 x i32> @pr20114(<4 x i32> %__mask) { 787; CHECK-LABEL: @pr20114( 788; CHECK-NEXT: [[MASK01_I:%.*]] = shufflevector <4 x i32> [[__MASK:%.*]], <4 x i32> poison, <4 x i32> <i32 0, i32 0, i32 1, i32 1> 789; CHECK-NEXT: [[MASKED_NEW_I_I_I:%.*]] = and <4 x i32> [[MASK01_I]], bitcast (<2 x i64> <i64 ptrtoint (ptr @pr20114 to i64), i64 ptrtoint (ptr @pr20114 to i64)> to <4 x i32>) 790; CHECK-NEXT: ret <4 x i32> [[MASKED_NEW_I_I_I]] 791; 792 %mask01.i = shufflevector <4 x i32> %__mask, <4 x i32> undef, <4 x i32> <i32 0, i32 0, i32 1, i32 1> 793 %masked_new.i.i.i = and <4 x i32> bitcast (<2 x i64> <i64 ptrtoint (ptr @pr20114 to i64), i64 ptrtoint (ptr @pr20114 to i64)> to <4 x i32>), %mask01.i 794 ret <4 x i32> %masked_new.i.i.i 795} 796 797define <2 x ptr> @pr23113(<4 x ptr> %A) { 798; CHECK-LABEL: @pr23113( 799; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x ptr> [[A:%.*]], <4 x ptr> poison, <2 x i32> <i32 0, i32 1> 800; CHECK-NEXT: ret <2 x ptr> [[TMP1]] 801; 802 %1 = shufflevector <4 x ptr> %A, <4 x ptr> undef, <2 x i32> <i32 0, i32 1> 803 ret <2 x ptr> %1 804} 805 806; Unused lanes in the new binop should not kill the entire op (although it may simplify anyway as shown here). 807 808define <2 x i32> @PR37648(<2 x i32> %x) { 809; CHECK-LABEL: @PR37648( 810; CHECK-NEXT: ret <2 x i32> zeroinitializer 811; 812 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 813 %r = urem <2 x i32> %splat, <i32 1, i32 1> 814 ret <2 x i32> %r 815} 816 817; Test shuffle followed by binop with splat constant for all 18 binop opcodes. 818; Test with constant as operand 0 and operand 1 for non-commutative opcodes. 819 820define <2 x i32> @add_splat_constant(<2 x i32> %x) { 821; CHECK-LABEL: @add_splat_constant( 822; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 42, i32 poison> 823; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 824; CHECK-NEXT: ret <2 x i32> [[R]] 825; 826 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 827 %r = add <2 x i32> %splat, <i32 42, i32 42> 828 ret <2 x i32> %r 829} 830 831define <2 x i32> @sub_splat_constant0(<2 x i32> %x) { 832; CHECK-LABEL: @sub_splat_constant0( 833; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i32> <i32 42, i32 poison>, [[X:%.*]] 834; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 835; CHECK-NEXT: ret <2 x i32> [[R]] 836; 837 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 838 %r = sub <2 x i32> <i32 42, i32 42>, %splat 839 ret <2 x i32> %r 840} 841 842define <2 x i32> @sub_splat_constant1(<2 x i32> %x) { 843; CHECK-LABEL: @sub_splat_constant1( 844; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 -42, i32 poison> 845; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 846; CHECK-NEXT: ret <2 x i32> [[R]] 847; 848 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 849 %r = sub <2 x i32> %splat, <i32 42, i32 42> 850 ret <2 x i32> %r 851} 852 853define <2 x i32> @mul_splat_constant(<2 x i32> %x) { 854; CHECK-LABEL: @mul_splat_constant( 855; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], <i32 42, i32 poison> 856; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 857; CHECK-NEXT: ret <2 x i32> [[R]] 858; 859 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 860 %r = mul <2 x i32> %splat, <i32 42, i32 42> 861 ret <2 x i32> %r 862} 863 864define <2 x i32> @shl_splat_constant0(<2 x i32> %x) { 865; CHECK-LABEL: @shl_splat_constant0( 866; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 5, i32 poison>, [[X:%.*]] 867; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 868; CHECK-NEXT: ret <2 x i32> [[R]] 869; 870 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 871 %r = shl <2 x i32> <i32 5, i32 5>, %splat 872 ret <2 x i32> %r 873} 874 875define <2 x i32> @shl_splat_constant1(<2 x i32> %x) { 876; CHECK-LABEL: @shl_splat_constant1( 877; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[X:%.*]], <i32 5, i32 0> 878; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 879; CHECK-NEXT: ret <2 x i32> [[R]] 880; 881 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 882 %r = shl <2 x i32> %splat, <i32 5, i32 5> 883 ret <2 x i32> %r 884} 885 886define <2 x i32> @ashr_splat_constant0(<2 x i32> %x) { 887; CHECK-LABEL: @ashr_splat_constant0( 888; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]] 889; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 890; CHECK-NEXT: ret <2 x i32> [[R]] 891; 892 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 893 %r = ashr <2 x i32> <i32 5, i32 5>, %splat 894 ret <2 x i32> %r 895} 896 897define <2 x i32> @ashr_splat_constant1(<2 x i32> %x) { 898; CHECK-LABEL: @ashr_splat_constant1( 899; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 0> 900; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 901; CHECK-NEXT: ret <2 x i32> [[R]] 902; 903 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 904 %r = ashr <2 x i32> %splat, <i32 5, i32 5> 905 ret <2 x i32> %r 906} 907 908define <2 x i32> @lshr_splat_constant0(<2 x i32> %x) { 909; CHECK-LABEL: @lshr_splat_constant0( 910; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> <i32 5, i32 poison>, [[X:%.*]] 911; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 912; CHECK-NEXT: ret <2 x i32> [[R]] 913; 914 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 915 %r = lshr <2 x i32> <i32 5, i32 5>, %splat 916 ret <2 x i32> %r 917} 918 919define <2 x i32> @lshr_splat_constant1(<2 x i32> %x) { 920; CHECK-LABEL: @lshr_splat_constant1( 921; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 0> 922; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 923; CHECK-NEXT: ret <2 x i32> [[R]] 924; 925 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 926 %r = lshr <2 x i32> %splat, <i32 5, i32 5> 927 ret <2 x i32> %r 928} 929 930define <2 x i32> @urem_splat_constant0(<2 x i32> %x) { 931; CHECK-LABEL: @urem_splat_constant0( 932; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer 933; CHECK-NEXT: [[R:%.*]] = urem <2 x i32> splat (i32 42), [[SPLAT]] 934; CHECK-NEXT: ret <2 x i32> [[R]] 935; 936 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 937 %r = urem <2 x i32> <i32 42, i32 42>, %splat 938 ret <2 x i32> %r 939} 940 941define <2 x i32> @urem_splat_constant1(<2 x i32> %x) { 942; CHECK-LABEL: @urem_splat_constant1( 943; CHECK-NEXT: [[TMP1:%.*]] = urem <2 x i32> [[X:%.*]], <i32 42, i32 1> 944; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 945; CHECK-NEXT: ret <2 x i32> [[R]] 946; 947 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 948 %r = urem <2 x i32> %splat, <i32 42, i32 42> 949 ret <2 x i32> %r 950} 951 952define <2 x i32> @srem_splat_constant0(<2 x i32> %x) { 953; CHECK-LABEL: @srem_splat_constant0( 954; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer 955; CHECK-NEXT: [[R:%.*]] = srem <2 x i32> splat (i32 42), [[SPLAT]] 956; CHECK-NEXT: ret <2 x i32> [[R]] 957; 958 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 959 %r = srem <2 x i32> <i32 42, i32 42>, %splat 960 ret <2 x i32> %r 961} 962 963define <2 x i32> @srem_splat_constant1(<2 x i32> %x) { 964; CHECK-LABEL: @srem_splat_constant1( 965; CHECK-NEXT: [[TMP1:%.*]] = srem <2 x i32> [[X:%.*]], <i32 42, i32 1> 966; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 967; CHECK-NEXT: ret <2 x i32> [[R]] 968; 969 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 970 %r = srem <2 x i32> %splat, <i32 42, i32 42> 971 ret <2 x i32> %r 972} 973 974define <2 x i32> @udiv_splat_constant0(<2 x i32> %x) { 975; CHECK-LABEL: @udiv_splat_constant0( 976; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer 977; CHECK-NEXT: [[R:%.*]] = udiv <2 x i32> splat (i32 42), [[SPLAT]] 978; CHECK-NEXT: ret <2 x i32> [[R]] 979; 980 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 981 %r = udiv <2 x i32> <i32 42, i32 42>, %splat 982 ret <2 x i32> %r 983} 984 985define <2 x i32> @udiv_splat_constant1(<2 x i32> %x) { 986; CHECK-LABEL: @udiv_splat_constant1( 987; CHECK-NEXT: [[TMP1:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 42, i32 1> 988; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 989; CHECK-NEXT: ret <2 x i32> [[R]] 990; 991 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 992 %r = udiv <2 x i32> %splat, <i32 42, i32 42> 993 ret <2 x i32> %r 994} 995 996define <2 x i32> @sdiv_splat_constant0(<2 x i32> %x) { 997; CHECK-LABEL: @sdiv_splat_constant0( 998; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> zeroinitializer 999; CHECK-NEXT: [[R:%.*]] = sdiv <2 x i32> splat (i32 42), [[SPLAT]] 1000; CHECK-NEXT: ret <2 x i32> [[R]] 1001; 1002 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 1003 %r = sdiv <2 x i32> <i32 42, i32 42>, %splat 1004 ret <2 x i32> %r 1005} 1006 1007define <2 x i32> @sdiv_splat_constant1(<2 x i32> %x) { 1008; CHECK-LABEL: @sdiv_splat_constant1( 1009; CHECK-NEXT: [[TMP1:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 42, i32 1> 1010; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 1011; CHECK-NEXT: ret <2 x i32> [[R]] 1012; 1013 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 1014 %r = sdiv <2 x i32> %splat, <i32 42, i32 42> 1015 ret <2 x i32> %r 1016} 1017 1018define <2 x i32> @and_splat_constant(<2 x i32> %x) { 1019; CHECK-LABEL: @and_splat_constant( 1020; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 42, i32 poison> 1021; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 1022; CHECK-NEXT: ret <2 x i32> [[R]] 1023; 1024 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 1025 %r = and <2 x i32> %splat, <i32 42, i32 42> 1026 ret <2 x i32> %r 1027} 1028 1029define <4 x i16> @and_constant_mask_poison(<4 x i16> %add) { 1030; CHECK-LABEL: @and_constant_mask_poison( 1031; CHECK-NEXT: entry: 1032; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1> 1033; CHECK-NEXT: ret <4 x i16> [[AND]] 1034; 1035entry: 1036 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1> 1037 %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1> 1038 ret <4 x i16> %and 1039} 1040 1041define <4 x i16> @and_constant_mask_poison_2(<4 x i16> %add) { 1042; CHECK-LABEL: @and_constant_mask_poison_2( 1043; CHECK-NEXT: entry: 1044; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 poison> 1045; CHECK-NEXT: ret <4 x i16> [[AND]] 1046; 1047entry: 1048 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 undef> 1049 %and = and <4 x i16> %shuffle, <i16 -1, i16 -1, i16 -1, i16 -0> 1050 ret <4 x i16> %and 1051} 1052 1053; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes. 1054define <4 x i16> @and_constant_mask_poison_3(<4 x i16> %add) { 1055; CHECK-LABEL: @and_constant_mask_poison_3( 1056; CHECK-NEXT: entry: 1057; CHECK-NEXT: ret <4 x i16> <i16 0, i16 0, i16 0, i16 undef> 1058; 1059entry: 1060 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef> 1061 %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 0, i16 -1> 1062 ret <4 x i16> %and 1063} 1064 1065; We can move the AND across the shuffle, as -1 (AND identity value) is used for undef lanes. 1066define <4 x i16> @and_constant_mask_poison_4(<4 x i16> %add) { 1067; CHECK-LABEL: @and_constant_mask_poison_4( 1068; CHECK-NEXT: entry: 1069; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 9, i16 20, i16 poison, i16 poison> 1070; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 poison> 1071; CHECK-NEXT: ret <4 x i16> [[AND]] 1072; 1073entry: 1074 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 0, i32 1, i32 1, i32 undef> 1075 %and = and <4 x i16> %shuffle, <i16 9, i16 20, i16 20, i16 -1> 1076 ret <4 x i16> %and 1077} 1078 1079define <4 x i16> @and_constant_mask_not_undef(<4 x i16> %add) { 1080; CHECK-LABEL: @and_constant_mask_not_undef( 1081; CHECK-NEXT: entry: 1082; CHECK-NEXT: [[TMP0:%.*]] = and <4 x i16> [[ADD:%.*]], <i16 poison, i16 -1, i16 0, i16 0> 1083; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 1> 1084; CHECK-NEXT: ret <4 x i16> [[AND]] 1085; 1086entry: 1087 %shuffle = shufflevector <4 x i16> %add, <4 x i16> undef, <4 x i32> <i32 2, i32 3, i32 1, i32 1> 1088 %and = and <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1> 1089 ret <4 x i16> %and 1090} 1091 1092define <4 x i16> @or_constant_mask_poison(<4 x i16> %in) { 1093; CHECK-LABEL: @or_constant_mask_poison( 1094; CHECK-NEXT: entry: 1095; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1> 1096; CHECK-NEXT: ret <4 x i16> [[OR]] 1097; 1098entry: 1099 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1> 1100 %or = or <4 x i16> %shuffle, <i16 -1, i16 -1, i16 0, i16 0> 1101 ret <4 x i16> %or 1102} 1103 1104define <4 x i16> @or_constant_mask_poison_2(<4 x i16> %in) { 1105; CHECK-LABEL: @or_constant_mask_poison_2( 1106; CHECK-NEXT: entry: 1107; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison> 1108; CHECK-NEXT: ret <4 x i16> [[OR]] 1109; 1110entry: 1111 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef> 1112 %or = or <4 x i16> %shuffle, <i16 -1, i16 0, i16 0, i16 -1> 1113 ret <4 x i16> %or 1114} 1115 1116; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes. 1117define <4 x i16> @or_constant_mask_poison_3(<4 x i16> %in) { 1118; CHECK-LABEL: @or_constant_mask_poison_3( 1119; CHECK-NEXT: entry: 1120; CHECK-NEXT: ret <4 x i16> <i16 undef, i16 -1, i16 -1, i16 undef> 1121; 1122entry: 1123 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef> 1124 %or = or <4 x i16> %shuffle, <i16 0, i16 -1, i16 -1, i16 0> 1125 ret <4 x i16> %or 1126} 1127 1128; We can move the OR across the shuffle, as 0 (OR identity value) is used for undef lanes. 1129define <4 x i16> @or_constant_mask_poison_4(<4 x i16> %in) { 1130; CHECK-LABEL: @or_constant_mask_poison_4( 1131; CHECK-NEXT: entry: 1132; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 99, i16 poison, i16 poison> 1133; CHECK-NEXT: [[OR:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 poison, i32 1, i32 1, i32 poison> 1134; CHECK-NEXT: ret <4 x i16> [[OR]] 1135; 1136entry: 1137 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 1, i32 1, i32 undef> 1138 %or = or <4 x i16> %shuffle, <i16 0, i16 99, i16 99, i16 0> 1139 ret <4 x i16> %or 1140} 1141 1142define <4 x i16> @or_constant_mask_not_undef(<4 x i16> %in) { 1143; CHECK-LABEL: @or_constant_mask_not_undef( 1144; CHECK-NEXT: entry: 1145; CHECK-NEXT: [[TMP0:%.*]] = or <4 x i16> [[IN:%.*]], <i16 poison, i16 -1, i16 0, i16 0> 1146; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 2, i32 3, i32 1, i32 1> 1147; CHECK-NEXT: ret <4 x i16> [[AND]] 1148; 1149entry: 1150 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 2, i32 3, i32 1, i32 1> 1151 %and = or <4 x i16> %shuffle, <i16 0, i16 0, i16 -1, i16 -1> 1152 ret <4 x i16> %and 1153} 1154 1155define <4 x i16> @shl_constant_mask_undef(<4 x i16> %in) { 1156; CHECK-LABEL: @shl_constant_mask_undef( 1157; CHECK-NEXT: entry: 1158; CHECK-NEXT: [[TMP0:%.*]] = shl <4 x i16> [[IN:%.*]], <i16 10, i16 0, i16 0, i16 0> 1159; CHECK-NEXT: [[SHL:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 0, i32 poison, i32 1, i32 1> 1160; CHECK-NEXT: ret <4 x i16> [[SHL]] 1161; 1162entry: 1163 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 0, i32 undef, i32 1, i32 1> 1164 %shl = shl <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0> 1165 ret <4 x i16> %shl 1166} 1167 1168define <4 x i16> @add_constant_mask_undef(<4 x i16> %in) { 1169; CHECK-LABEL: @add_constant_mask_undef( 1170; CHECK-NEXT: entry: 1171; CHECK-NEXT: [[ADD:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1> 1172; CHECK-NEXT: ret <4 x i16> [[ADD]] 1173; 1174entry: 1175 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1> 1176 %add = add <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0> 1177 ret <4 x i16> %add 1178} 1179 1180define <4 x i16> @add_constant_mask_undef_2(<4 x i16> %in) { 1181; CHECK-LABEL: @add_constant_mask_undef_2( 1182; CHECK-NEXT: entry: 1183; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[IN:%.*]], <i16 poison, i16 0, i16 3, i16 poison> 1184; CHECK-NEXT: [[ADD:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 poison, i32 2, i32 1, i32 1> 1185; CHECK-NEXT: ret <4 x i16> [[ADD]] 1186; 1187entry: 1188 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 2, i32 1, i32 1> 1189 %add = add <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0> 1190 ret <4 x i16> %add 1191} 1192 1193define <4 x i16> @sub_constant_mask_undef(<4 x i16> %in) { 1194; CHECK-LABEL: @sub_constant_mask_undef( 1195; CHECK-NEXT: entry: 1196; CHECK-NEXT: [[SUB:%.*]] = shufflevector <4 x i16> [[IN:%.*]], <4 x i16> poison, <4 x i32> <i32 poison, i32 poison, i32 1, i32 1> 1197; CHECK-NEXT: ret <4 x i16> [[SUB]] 1198; 1199entry: 1200 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 undef, i32 undef, i32 1, i32 1> 1201 %sub = sub <4 x i16> %shuffle, <i16 10, i16 3, i16 0, i16 0> 1202 ret <4 x i16> %sub 1203} 1204 1205define <4 x i16> @sub_constant_mask_undef_2(<4 x i16> %in) { 1206; CHECK-LABEL: @sub_constant_mask_undef_2( 1207; CHECK-NEXT: entry: 1208; CHECK-NEXT: [[TMP0:%.*]] = add <4 x i16> [[IN:%.*]], <i16 poison, i16 0, i16 -10, i16 poison> 1209; CHECK-NEXT: [[SUB:%.*]] = shufflevector <4 x i16> [[TMP0]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 2, i32 poison> 1210; CHECK-NEXT: ret <4 x i16> [[SUB]] 1211; 1212entry: 1213 %shuffle = shufflevector <4 x i16> %in, <4 x i16> undef, <4 x i32> <i32 1, i32 1, i32 2, i32 undef> 1214 %sub = sub <4 x i16> %shuffle, <i16 0, i16 0, i16 10, i16 99> 1215 ret <4 x i16> %sub 1216} 1217 1218define <2 x i32> @or_splat_constant(<2 x i32> %x) { 1219; CHECK-LABEL: @or_splat_constant( 1220; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[X:%.*]], <i32 42, i32 poison> 1221; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 1222; CHECK-NEXT: ret <2 x i32> [[R]] 1223; 1224 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 1225 %r = or <2 x i32> %splat, <i32 42, i32 42> 1226 ret <2 x i32> %r 1227} 1228 1229define <2 x i32> @xor_splat_constant(<2 x i32> %x) { 1230; CHECK-LABEL: @xor_splat_constant( 1231; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], <i32 42, i32 poison> 1232; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> poison, <2 x i32> zeroinitializer 1233; CHECK-NEXT: ret <2 x i32> [[R]] 1234; 1235 %splat = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> zeroinitializer 1236 %r = xor <2 x i32> %splat, <i32 42, i32 42> 1237 ret <2 x i32> %r 1238} 1239 1240define <2 x float> @fadd_splat_constant(<2 x float> %x) { 1241; CHECK-LABEL: @fadd_splat_constant( 1242; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x float> [[X:%.*]], <float 4.200000e+01, float poison> 1243; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1244; CHECK-NEXT: ret <2 x float> [[R]] 1245; 1246 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1247 %r = fadd <2 x float> %splat, <float 42.0, float 42.0> 1248 ret <2 x float> %r 1249} 1250 1251define <2 x float> @fsub_splat_constant0(<2 x float> %x) { 1252; CHECK-LABEL: @fsub_splat_constant0( 1253; CHECK-NEXT: [[TMP1:%.*]] = fsub <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]] 1254; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1255; CHECK-NEXT: ret <2 x float> [[R]] 1256; 1257 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1258 %r = fsub <2 x float> <float 42.0, float 42.0>, %splat 1259 ret <2 x float> %r 1260} 1261 1262define <2 x float> @fsub_splat_constant1(<2 x float> %x) { 1263; CHECK-LABEL: @fsub_splat_constant1( 1264; CHECK-NEXT: [[TMP1:%.*]] = fadd <2 x float> [[X:%.*]], <float -4.200000e+01, float poison> 1265; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1266; CHECK-NEXT: ret <2 x float> [[R]] 1267; 1268 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1269 %r = fsub <2 x float> %splat, <float 42.0, float 42.0> 1270 ret <2 x float> %r 1271} 1272 1273define <2 x float> @fneg(<2 x float> %x) { 1274; CHECK-LABEL: @fneg( 1275; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> zeroinitializer 1276; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] 1277; CHECK-NEXT: ret <2 x float> [[R]] 1278; 1279 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1280 %r = fsub <2 x float> <float -0.0, float -0.0>, %splat 1281 ret <2 x float> %r 1282} 1283 1284define <2 x float> @fneg_not_single_source(<2 x float> %x) { 1285; CHECK-LABEL: @fneg_not_single_source( 1286; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]] 1287; CHECK-NEXT: [[SPLAT1:%.*]] = insertelement <2 x float> [[NEG]], float undef, i64 1 1288; CHECK-NEXT: ret <2 x float> [[SPLAT1]] 1289; 1290 %neg = fneg <2 x float> %x 1291 %splat = shufflevector <2 x float> %neg, <2 x float> undef, <2 x i32> <i32 0, i32 2> 1292 ret <2 x float> %splat 1293} 1294 1295define <2 x float> @fmul_splat_constant(<2 x float> %x) { 1296; CHECK-LABEL: @fmul_splat_constant( 1297; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], <float 4.200000e+01, float poison> 1298; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1299; CHECK-NEXT: ret <2 x float> [[R]] 1300; 1301 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1302 %r = fmul <2 x float> %splat, <float 42.0, float 42.0> 1303 ret <2 x float> %r 1304} 1305 1306define <2 x float> @fdiv_splat_constant0(<2 x float> %x) { 1307; CHECK-LABEL: @fdiv_splat_constant0( 1308; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]] 1309; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1310; CHECK-NEXT: ret <2 x float> [[R]] 1311; 1312 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1313 %r = fdiv <2 x float> <float 42.0, float 42.0>, %splat 1314 ret <2 x float> %r 1315} 1316 1317define <2 x float> @fdiv_splat_constant1(<2 x float> %x) { 1318; CHECK-LABEL: @fdiv_splat_constant1( 1319; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.200000e+01, float poison> 1320; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1321; CHECK-NEXT: ret <2 x float> [[R]] 1322; 1323 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1324 %r = fdiv <2 x float> %splat, <float 42.0, float 42.0> 1325 ret <2 x float> %r 1326} 1327 1328define <2 x float> @frem_splat_constant0(<2 x float> %x) { 1329; CHECK-LABEL: @frem_splat_constant0( 1330; CHECK-NEXT: [[TMP1:%.*]] = frem <2 x float> <float 4.200000e+01, float poison>, [[X:%.*]] 1331; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1332; CHECK-NEXT: ret <2 x float> [[R]] 1333; 1334 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1335 %r = frem <2 x float> <float 42.0, float 42.0>, %splat 1336 ret <2 x float> %r 1337} 1338 1339define <2 x float> @frem_splat_constant1(<2 x float> %x) { 1340; CHECK-LABEL: @frem_splat_constant1( 1341; CHECK-NEXT: [[TMP1:%.*]] = frem <2 x float> [[X:%.*]], <float 4.200000e+01, float poison> 1342; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> zeroinitializer 1343; CHECK-NEXT: ret <2 x float> [[R]] 1344; 1345 %splat = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1346 %r = frem <2 x float> %splat, <float 42.0, float 42.0> 1347 ret <2 x float> %r 1348} 1349 1350; Equivalent shuffle masks, but only one is a narrowing op. 1351 1352define <2 x i1> @PR40734(<1 x i1> %x, <4 x i1> %y) { 1353; CHECK-LABEL: @PR40734( 1354; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <1 x i1> zeroinitializer, <1 x i1> [[X:%.*]], <2 x i32> <i32 0, i32 1> 1355; CHECK-NEXT: [[NARROW:%.*]] = shufflevector <4 x i1> [[Y:%.*]], <4 x i1> poison, <2 x i32> <i32 0, i32 1> 1356; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[WIDEN]], [[NARROW]] 1357; CHECK-NEXT: ret <2 x i1> [[R]] 1358; 1359 %widen = shufflevector <1 x i1> zeroinitializer, <1 x i1> %x, <2 x i32> <i32 0, i32 1> 1360 %narrow = shufflevector <4 x i1> %y, <4 x i1> undef, <2 x i32> <i32 0, i32 1> 1361 %r = and <2 x i1> %widen, %narrow 1362 ret <2 x i1> %r 1363} 1364 1365; Negative test - do not transform non-power-of-2 unless we know the backend handles these sequences identically. 1366 1367define <7 x i8> @insert_subvector_shuffles(<3 x i8> %x, <3 x i8> %y) { 1368; CHECK-LABEL: @insert_subvector_shuffles( 1369; CHECK-NEXT: [[S1:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <7 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> 1370; CHECK-NEXT: [[S2:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <7 x i32> <i32 poison, i32 1, i32 2, i32 poison, i32 poison, i32 poison, i32 poison> 1371; CHECK-NEXT: [[S3:%.*]] = shufflevector <7 x i8> [[S1]], <7 x i8> [[S2]], <7 x i32> <i32 0, i32 8, i32 1, i32 poison, i32 8, i32 1, i32 9> 1372; CHECK-NEXT: ret <7 x i8> [[S3]] 1373; 1374 %s1 = shufflevector <3 x i8> %x, <3 x i8> undef, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 1375 %s2 = shufflevector <3 x i8> %y, <3 x i8> undef, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef> 1376 %s3 = shufflevector <7 x i8> %s1, <7 x i8> %s2, <7 x i32> <i32 0, i32 8, i32 1, i32 undef, i32 8, i32 1, i32 9> 1377 ret <7 x i8> %s3 1378} 1379 1380define <8 x i8> @insert_subvector_shuffles_pow2elts(<2 x i8> %x, <2 x i8> %y) { 1381; CHECK-LABEL: @insert_subvector_shuffles_pow2elts( 1382; CHECK-NEXT: [[S3:%.*]] = shufflevector <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]], <8 x i32> <i32 0, i32 2, i32 1, i32 poison, i32 2, i32 1, i32 3, i32 0> 1383; CHECK-NEXT: ret <8 x i8> [[S3]] 1384; 1385 %s1 = shufflevector <2 x i8> %x, <2 x i8> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 1386 %s2 = shufflevector <2 x i8> %y, <2 x i8> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 1387 %s3 = shufflevector <8 x i8> %s1, <8 x i8> %s2, <8 x i32> <i32 0, i32 8, i32 1, i32 undef, i32 8, i32 1, i32 9, i32 0> 1388 ret <8 x i8> %s3 1389} 1390 1391; The last shuffle may change the vector type. 1392; Negative test - do not transform non-power-of-2 unless we know the backend handles these sequences identically. 1393 1394define <2 x i8> @insert_subvector_shuffles_narrowing(<3 x i8> %x, <3 x i8> %y) { 1395; CHECK-LABEL: @insert_subvector_shuffles_narrowing( 1396; CHECK-NEXT: [[S1:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <7 x i32> <i32 0, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> 1397; CHECK-NEXT: [[S2:%.*]] = shufflevector <3 x i8> [[Y:%.*]], <3 x i8> poison, <7 x i32> <i32 poison, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> 1398; CHECK-NEXT: [[S3:%.*]] = shufflevector <7 x i8> [[S1]], <7 x i8> [[S2]], <2 x i32> <i32 0, i32 8> 1399; CHECK-NEXT: ret <2 x i8> [[S3]] 1400; 1401 %s1 = shufflevector <3 x i8> %x, <3 x i8> undef, <7 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 1402 %s2 = shufflevector <3 x i8> %y, <3 x i8> undef, <7 x i32> <i32 undef, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef> 1403 %s3 = shufflevector <7 x i8> %s1, <7 x i8> %s2, <2 x i32> <i32 0, i32 8> 1404 ret <2 x i8> %s3 1405} 1406 1407define <2 x i8> @insert_subvector_shuffles_narrowing_pow2elts(<4 x i8> %x, <4 x i8> %y) { 1408; CHECK-LABEL: @insert_subvector_shuffles_narrowing_pow2elts( 1409; CHECK-NEXT: [[S3:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 4> 1410; CHECK-NEXT: ret <2 x i8> [[S3]] 1411; 1412 %s1 = shufflevector <4 x i8> %x, <4 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> 1413 %s2 = shufflevector <4 x i8> %y, <4 x i8> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 3, i32 undef, i32 undef, i32 undef, i32 undef> 1414 %s3 = shufflevector <8 x i8> %s1, <8 x i8> %s2, <2 x i32> <i32 0, i32 8> 1415 ret <2 x i8> %s3 1416} 1417 1418; Similar to above, but this reduces to a widen with undefs of 'x'. 1419 1420define <4 x double> @insert_subvector_shuffles_identity(<2 x double> %x) { 1421; CHECK-LABEL: @insert_subvector_shuffles_identity( 1422; CHECK-NEXT: [[S3:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 1423; CHECK-NEXT: ret <4 x double> [[S3]] 1424; 1425 %s1 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef> 1426 %s2 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef> 1427 %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef> 1428 ret <4 x double> %s3 1429} 1430 1431; Negative test - not identity with padding (although this could be folded with better analysis). 1432 1433define <4 x double> @not_insert_subvector_shuffle(<2 x double> %x) { 1434; CHECK-LABEL: @not_insert_subvector_shuffle( 1435; CHECK-NEXT: [[S1:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 1> 1436; CHECK-NEXT: [[S2:%.*]] = shufflevector <2 x double> [[X]], <2 x double> poison, <4 x i32> <i32 0, i32 poison, i32 poison, i32 poison> 1437; CHECK-NEXT: [[S3:%.*]] = shufflevector <4 x double> [[S2]], <4 x double> [[S1]], <4 x i32> <i32 0, i32 5, i32 7, i32 poison> 1438; CHECK-NEXT: ret <4 x double> [[S3]] 1439; 1440 %s1 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 1> 1441 %s2 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef> 1442 %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 7, i32 undef> 1443 ret <4 x double> %s3 1444} 1445 1446; Negative test - operands are not the same size (although this could be partly folded with better analysis). 1447 1448define <4 x double> @not_insert_subvector_shuffles_with_same_size(<2 x double> %x, <3 x double> %y) { 1449; CHECK-LABEL: @not_insert_subvector_shuffles_with_same_size( 1450; CHECK-NEXT: [[S1:%.*]] = shufflevector <2 x double> [[X:%.*]], <2 x double> poison, <4 x i32> <i32 poison, i32 1, i32 poison, i32 poison> 1451; CHECK-NEXT: [[S2:%.*]] = shufflevector <3 x double> [[Y:%.*]], <3 x double> poison, <4 x i32> <i32 0, i32 poison, i32 poison, i32 poison> 1452; CHECK-NEXT: [[S3:%.*]] = shufflevector <4 x double> [[S2]], <4 x double> [[S1]], <4 x i32> <i32 0, i32 5, i32 poison, i32 poison> 1453; CHECK-NEXT: ret <4 x double> [[S3]] 1454; 1455 %s1 = shufflevector <2 x double> %x, <2 x double> undef, <4 x i32> <i32 undef, i32 1, i32 undef, i32 undef> 1456 %s2 = shufflevector <3 x double> %y, <3 x double> undef, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef> 1457 %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> <i32 0, i32 5, i32 undef, i32 undef> 1458 ret <4 x double> %s3 1459} 1460 1461; Demanded vector elements may not be able to simplify a shuffle mask 1462; before we try to narrow it. This used to crash. 1463 1464define <4 x float> @insert_subvector_crash_invalid_mask_elt(<2 x float> %x, ptr %p) { 1465; CHECK-LABEL: @insert_subvector_crash_invalid_mask_elt( 1466; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 1467; CHECK-NEXT: [[I:%.*]] = shufflevector <2 x float> [[X]], <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> 1468; CHECK-NEXT: store <4 x float> [[I]], ptr [[P:%.*]], align 16 1469; CHECK-NEXT: ret <4 x float> [[WIDEN]] 1470; 1471 %widen = shufflevector <2 x float> %x, <2 x float> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> 1472 %ext2 = extractelement <2 x float> %x, i32 0 1473 %I = insertelement <4 x float> %widen, float %ext2, i16 0 1474 store <4 x float> %I, ptr %p 1475 ret <4 x float> %widen 1476} 1477 1478define <4 x i32> @splat_assoc_add(<4 x i32> %x, <4 x i32> %y) { 1479; CHECK-LABEL: @splat_assoc_add( 1480; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 317426, i32 poison, i32 poison, i32 poison> 1481; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer 1482; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]] 1483; CHECK-NEXT: ret <4 x i32> [[R]] 1484; 1485 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 1486 %a = add <4 x i32> %y, <i32 317426, i32 317426, i32 317426, i32 317426> 1487 %r = add <4 x i32> %splatx, %a 1488 ret <4 x i32> %r 1489} 1490 1491define <vscale x 4 x i32> @vsplat_assoc_add(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) { 1492; CHECK-LABEL: @vsplat_assoc_add( 1493; CHECK-NEXT: [[TMP1:%.*]] = add <vscale x 4 x i32> [[X:%.*]], splat (i32 317426) 1494; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <vscale x 4 x i32> [[TMP1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer 1495; CHECK-NEXT: [[R:%.*]] = add <vscale x 4 x i32> [[TMP2]], [[Y:%.*]] 1496; CHECK-NEXT: ret <vscale x 4 x i32> [[R]] 1497; 1498 1499 %splatx = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> undef, <vscale x 4 x i32> zeroinitializer 1500 %a = add <vscale x 4 x i32> %y, splat (i32 317426) 1501 %r = add <vscale x 4 x i32> %splatx, %a 1502 ret <vscale x 4 x i32> %r 1503} 1504 1505; Undefs in splat mask are replaced with defined splat index 1506 1507define <4 x i32> @splat_assoc_add_undef_mask_elts(<4 x i32> %x, <4 x i32> %y) { 1508; CHECK-LABEL: @splat_assoc_add_undef_mask_elts( 1509; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 poison, i32 poison, i32 poison> 1510; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer 1511; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]] 1512; CHECK-NEXT: ret <4 x i32> [[R]] 1513; 1514 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 0, i32 undef, i32 undef> 1515 %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42> 1516 %r = add <4 x i32> %splatx, %a 1517 ret <4 x i32> %r 1518} 1519 1520; Undefs in splat mask are replaced with defined splat index 1521 1522define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) { 1523; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index( 1524; CHECK-NEXT: [[TMP1:%.*]] = add <4 x i32> [[X:%.*]], <i32 42, i32 poison, i32 poison, i32 poison> 1525; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer 1526; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[TMP2]], [[Y:%.*]] 1527; CHECK-NEXT: ret <4 x i32> [[R]] 1528; 1529 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0> 1530 %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42> 1531 %r = add <4 x i32> %splatx, %a 1532 ret <4 x i32> %r 1533} 1534 1535define <4 x i32> @splat_assoc_add_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) { 1536; CHECK-LABEL: @splat_assoc_add_undef_constant_elts( 1537; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer 1538; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42> 1539; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]] 1540; CHECK-NEXT: ret <4 x i32> [[R]] 1541; 1542 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 1543 %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42> 1544 %r = add <4 x i32> %splatx, %a 1545 ret <4 x i32> %r 1546} 1547 1548define <4 x i32> @splat_assoc_add_undef_constant_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) { 1549; CHECK-LABEL: @splat_assoc_add_undef_constant_elt_at_splat_index( 1550; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer 1551; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 undef, i32 42, i32 undef, i32 42> 1552; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]] 1553; CHECK-NEXT: ret <4 x i32> [[R]] 1554; 1555 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 1556 %a = add <4 x i32> %y, <i32 undef, i32 42, i32 undef, i32 42> 1557 %r = add <4 x i32> %splatx, %a 1558 ret <4 x i32> %r 1559} 1560 1561define <4 x i32> @splat_assoc_add_undef_mask_elts_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) { 1562; CHECK-LABEL: @splat_assoc_add_undef_mask_elts_undef_constant_elts( 1563; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 0, i32 poison, i32 0, i32 poison> 1564; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42> 1565; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]] 1566; CHECK-NEXT: ret <4 x i32> [[R]] 1567; 1568 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 0, i32 undef, i32 0, i32 undef> 1569 %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42> 1570 %r = add <4 x i32> %splatx, %a 1571 ret <4 x i32> %r 1572} 1573 1574define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elts(<4 x i32> %x, <4 x i32> %y) { 1575; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elts( 1576; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 0, i32 0, i32 0> 1577; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 42, i32 undef, i32 undef, i32 42> 1578; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]] 1579; CHECK-NEXT: ret <4 x i32> [[R]] 1580; 1581 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0> 1582 %a = add <4 x i32> %y, <i32 42, i32 undef, i32 undef, i32 42> 1583 %r = add <4 x i32> %splatx, %a 1584 ret <4 x i32> %r 1585} 1586 1587define <4 x i32> @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elt_at_splat_index(<4 x i32> %x, <4 x i32> %y) { 1588; CHECK-LABEL: @splat_assoc_add_undef_mask_elt_at_splat_index_undef_constant_elt_at_splat_index( 1589; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 0, i32 0, i32 0> 1590; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], <i32 undef, i32 42, i32 undef, i32 42> 1591; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[SPLATX]], [[A]] 1592; CHECK-NEXT: ret <4 x i32> [[R]] 1593; 1594 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 0, i32 0> 1595 %a = add <4 x i32> %y, <i32 undef, i32 42, i32 undef, i32 42> 1596 %r = add <4 x i32> %splatx, %a 1597 ret <4 x i32> %r 1598} 1599 1600; Non-zero splat index; commute operands; FMF intersect 1601 1602define <2 x float> @splat_assoc_fmul(<2 x float> %x, <2 x float> %y) { 1603; CHECK-LABEL: @splat_assoc_fmul( 1604; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz <2 x float> [[X:%.*]], <float poison, float 3.000000e+00> 1605; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 1> 1606; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz <2 x float> [[TMP2]], [[Y:%.*]] 1607; CHECK-NEXT: ret <2 x float> [[R]] 1608; 1609 %splatx = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> <i32 1, i32 1> 1610 %a = fmul reassoc nsz <2 x float> %y, <float 3.0, float 3.0> 1611 %r = fmul reassoc nsz nnan <2 x float> %a, %splatx 1612 ret <2 x float> %r 1613} 1614 1615; Two splat shuffles; drop poison-generating flags 1616 1617define <3 x i8> @splat_assoc_mul(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 1618; CHECK-LABEL: @splat_assoc_mul( 1619; CHECK-NEXT: [[TMP1:%.*]] = mul <3 x i8> [[X:%.*]], [[Z:%.*]] 1620; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2> 1621; CHECK-NEXT: [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]] 1622; CHECK-NEXT: ret <3 x i8> [[R]] 1623; 1624 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1625 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1626 %a = mul nsw <3 x i8> %y, %splatz 1627 %r = mul <3 x i8> %a, %splatx 1628 ret <3 x i8> %r 1629} 1630 1631define <3 x i8> @splat_assoc_mul_undef_elt1(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 1632; CHECK-LABEL: @splat_assoc_mul_undef_elt1( 1633; CHECK-NEXT: [[TMP1:%.*]] = mul <3 x i8> [[X:%.*]], [[Z:%.*]] 1634; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2> 1635; CHECK-NEXT: [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]] 1636; CHECK-NEXT: ret <3 x i8> [[R]] 1637; 1638 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 undef, i32 2, i32 2> 1639 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1640 %a = mul nsw <3 x i8> %y, %splatz 1641 %r = mul nsw nuw <3 x i8> %a, %splatx 1642 ret <3 x i8> %r 1643} 1644 1645define <3 x i8> @splat_assoc_mul_undef_elt2(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 1646; CHECK-LABEL: @splat_assoc_mul_undef_elt2( 1647; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2> 1648; CHECK-NEXT: [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> poison, <3 x i32> <i32 poison, i32 2, i32 2> 1649; CHECK-NEXT: [[A:%.*]] = mul nsw <3 x i8> [[Y:%.*]], [[SPLATZ]] 1650; CHECK-NEXT: [[R:%.*]] = mul nuw nsw <3 x i8> [[A]], [[SPLATX]] 1651; CHECK-NEXT: ret <3 x i8> [[R]] 1652; 1653 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1654 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 undef, i32 2, i32 2> 1655 %a = mul nsw <3 x i8> %y, %splatz 1656 %r = mul nsw nuw <3 x i8> %a, %splatx 1657 ret <3 x i8> %r 1658} 1659 1660define <3 x i8> @splat_assoc_mul_undef_elt_at_splat_index1(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 1661; CHECK-LABEL: @splat_assoc_mul_undef_elt_at_splat_index1( 1662; CHECK-NEXT: [[TMP1:%.*]] = mul <3 x i8> [[X:%.*]], [[Z:%.*]] 1663; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <3 x i8> [[TMP1]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2> 1664; CHECK-NEXT: [[R:%.*]] = mul <3 x i8> [[TMP2]], [[Y:%.*]] 1665; CHECK-NEXT: ret <3 x i8> [[R]] 1666; 1667 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 undef> 1668 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1669 %a = mul nsw <3 x i8> %y, %splatz 1670 %r = mul nsw nuw <3 x i8> %a, %splatx 1671 ret <3 x i8> %r 1672} 1673 1674define <3 x i8> @splat_assoc_mul_undef_elt_at_splat_index2(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 1675; CHECK-LABEL: @splat_assoc_mul_undef_elt_at_splat_index2( 1676; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2> 1677; CHECK-NEXT: [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 poison> 1678; CHECK-NEXT: [[A:%.*]] = mul nsw <3 x i8> [[Y:%.*]], [[SPLATZ]] 1679; CHECK-NEXT: [[R:%.*]] = mul nuw nsw <3 x i8> [[A]], [[SPLATX]] 1680; CHECK-NEXT: ret <3 x i8> [[R]] 1681; 1682 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1683 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 undef> 1684 %a = mul nsw <3 x i8> %y, %splatz 1685 %r = mul nsw nuw <3 x i8> %a, %splatx 1686 ret <3 x i8> %r 1687} 1688 1689; Negative test - mismatched splat elements 1690 1691define <3 x i8> @splat_assoc_or(<3 x i8> %x, <3 x i8> %y, <3 x i8> %z) { 1692; CHECK-LABEL: @splat_assoc_or( 1693; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <3 x i8> [[X:%.*]], <3 x i8> poison, <3 x i32> <i32 1, i32 1, i32 1> 1694; CHECK-NEXT: [[SPLATZ:%.*]] = shufflevector <3 x i8> [[Z:%.*]], <3 x i8> poison, <3 x i32> <i32 2, i32 2, i32 2> 1695; CHECK-NEXT: [[A:%.*]] = or <3 x i8> [[Y:%.*]], [[SPLATZ]] 1696; CHECK-NEXT: [[R:%.*]] = or <3 x i8> [[A]], [[SPLATX]] 1697; CHECK-NEXT: ret <3 x i8> [[R]] 1698; 1699 %splatx = shufflevector <3 x i8> %x, <3 x i8> undef, <3 x i32> <i32 1, i32 1, i32 1> 1700 %splatz = shufflevector <3 x i8> %z, <3 x i8> undef, <3 x i32> <i32 2, i32 2, i32 2> 1701 %a = or <3 x i8> %y, %splatz 1702 %r = or <3 x i8> %a, %splatx 1703 ret <3 x i8> %r 1704} 1705 1706; Negative test - not associative 1707 1708define <2 x float> @splat_assoc_fdiv(<2 x float> %x, <2 x float> %y) { 1709; CHECK-LABEL: @splat_assoc_fdiv( 1710; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> zeroinitializer 1711; CHECK-NEXT: [[A:%.*]] = fdiv reassoc nsz <2 x float> [[Y:%.*]], splat (float 3.000000e+00) 1712; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nsz <2 x float> [[A]], [[SPLATX]] 1713; CHECK-NEXT: ret <2 x float> [[R]] 1714; 1715 %splatx = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> zeroinitializer 1716 %a = fdiv reassoc nsz <2 x float> %y, <float 3.0, float 3.0> 1717 %r = fdiv reassoc nsz <2 x float> %a, %splatx 1718 ret <2 x float> %r 1719} 1720 1721; Negative test - extra use 1722 1723define <2 x float> @splat_assoc_fadd(<2 x float> %x, <2 x float> %y) { 1724; CHECK-LABEL: @splat_assoc_fadd( 1725; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 1> 1726; CHECK-NEXT: [[A:%.*]] = fadd fast <2 x float> [[Y:%.*]], splat (float 3.000000e+00) 1727; CHECK-NEXT: call void @use(<2 x float> [[A]]) 1728; CHECK-NEXT: [[R:%.*]] = fadd fast <2 x float> [[A]], [[SPLATX]] 1729; CHECK-NEXT: ret <2 x float> [[R]] 1730; 1731 %splatx = shufflevector <2 x float> %x, <2 x float> undef, <2 x i32> <i32 1, i32 1> 1732 %a = fadd fast <2 x float> %y, <float 3.0, float 3.0> 1733 call void @use(<2 x float> %a) 1734 %r = fadd fast <2 x float> %a, %splatx 1735 ret <2 x float> %r 1736} 1737 1738; Negative test - narrowing splat 1739 1740define <3 x i32> @splat_assoc_and(<4 x i32> %x, <3 x i32> %y) { 1741; CHECK-LABEL: @splat_assoc_and( 1742; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <3 x i32> zeroinitializer 1743; CHECK-NEXT: [[A:%.*]] = and <3 x i32> [[Y:%.*]], splat (i32 42) 1744; CHECK-NEXT: [[R:%.*]] = and <3 x i32> [[SPLATX]], [[A]] 1745; CHECK-NEXT: ret <3 x i32> [[R]] 1746; 1747 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <3 x i32> zeroinitializer 1748 %a = and <3 x i32> %y, <i32 42, i32 42, i32 42> 1749 %r = and <3 x i32> %splatx, %a 1750 ret <3 x i32> %r 1751} 1752 1753; Negative test - widening splat 1754 1755define <5 x i32> @splat_assoc_xor(<4 x i32> %x, <5 x i32> %y) { 1756; CHECK-LABEL: @splat_assoc_xor( 1757; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <5 x i32> zeroinitializer 1758; CHECK-NEXT: [[TMP1:%.*]] = xor <5 x i32> [[Y:%.*]], [[SPLATX]] 1759; CHECK-NEXT: [[R:%.*]] = xor <5 x i32> [[TMP1]], splat (i32 42) 1760; CHECK-NEXT: ret <5 x i32> [[R]] 1761; 1762 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <5 x i32> zeroinitializer 1763 %a = xor <5 x i32> %y, <i32 42, i32 42, i32 42, i32 42, i32 42> 1764 %r = xor <5 x i32> %splatx, %a 1765 ret <5 x i32> %r 1766} 1767 1768; Negative test - opcode mismatch 1769 1770define <4 x i32> @splat_assoc_add_mul(<4 x i32> %x, <4 x i32> %y) { 1771; CHECK-LABEL: @splat_assoc_add_mul( 1772; CHECK-NEXT: [[SPLATX:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> zeroinitializer 1773; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[Y:%.*]], splat (i32 42) 1774; CHECK-NEXT: [[R:%.*]] = mul <4 x i32> [[SPLATX]], [[A]] 1775; CHECK-NEXT: ret <4 x i32> [[R]] 1776; 1777 %splatx = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> zeroinitializer 1778 %a = add <4 x i32> %y, <i32 42, i32 42, i32 42, i32 42> 1779 %r = mul <4 x i32> %splatx, %a 1780 ret <4 x i32> %r 1781} 1782 1783 1784; Do not crash on constant expressions. 1785 1786define <4 x i32> @PR46872(<4 x i32> %x) { 1787; CHECK-LABEL: @PR46872( 1788; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 poison, i32 0, i32 1, i32 1> 1789; CHECK-NEXT: [[A:%.*]] = and <4 x i32> [[S]], bitcast (<2 x i64> <i64 ptrtoint (ptr @PR46872 to i64), i64 ptrtoint (ptr @PR46872 to i64)> to <4 x i32>) 1790; CHECK-NEXT: ret <4 x i32> [[A]] 1791; 1792 %s = shufflevector <4 x i32> %x, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 1, i32 1> 1793 %a = and <4 x i32> %s, bitcast (<2 x i64> <i64 ptrtoint (ptr @PR46872 to i64), i64 ptrtoint (ptr @PR46872 to i64)> to <4 x i32>) 1794 ret <4 x i32> %a 1795} 1796 1797define <2 x float> @fabs_unary_shuf(<2 x float> %x) { 1798; CHECK-LABEL: @fabs_unary_shuf( 1799; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 1800; CHECK-NEXT: [[R:%.*]] = call nnan nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[TMP1]]) 1801; CHECK-NEXT: ret <2 x float> [[R]] 1802; 1803 %nx = call nsz nnan <2 x float> @llvm.fabs.v2f32(<2 x float> %x) 1804 %r = shufflevector <2 x float> %nx, <2 x float> poison, <2 x i32> <i32 1, i32 0> 1805 ret <2 x float> %r 1806} 1807 1808define <4 x half> @fabs_unary_shuf_widen(<2 x half> %x) { 1809; CHECK-LABEL: @fabs_unary_shuf_widen( 1810; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x half> [[X:%.*]], <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 1811; CHECK-NEXT: [[R:%.*]] = call ninf <4 x half> @llvm.fabs.v4f16(<4 x half> [[TMP1]]) 1812; CHECK-NEXT: ret <4 x half> [[R]] 1813; 1814 %nx = call ninf <2 x half> @llvm.fabs.v2f16(<2 x half> %x) 1815 %r = shufflevector <2 x half> %nx, <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 1816 ret <4 x half> %r 1817} 1818 1819define <2 x double> @fabs_unary_shuf_narrow(<4 x double> %x) { 1820; CHECK-LABEL: @fabs_unary_shuf_narrow( 1821; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[X:%.*]], <4 x double> poison, <2 x i32> <i32 3, i32 0> 1822; CHECK-NEXT: [[R:%.*]] = call nsz <2 x double> @llvm.fabs.v2f64(<2 x double> [[TMP1]]) 1823; CHECK-NEXT: ret <2 x double> [[R]] 1824; 1825 %nx = call nsz <4 x double> @llvm.fabs.v4f64(<4 x double> %x) 1826 %r = shufflevector <4 x double> %nx, <4 x double> poison, <2 x i32> <i32 3, i32 0> 1827 ret <2 x double> %r 1828} 1829 1830; negative test - extra use prevents canonicalization 1831 1832define <2 x float> @fabs_unary_shuf_use(<2 x float> %x) { 1833; CHECK-LABEL: @fabs_unary_shuf_use( 1834; CHECK-NEXT: [[NX:%.*]] = call nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 1835; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 1836; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> poison, <2 x i32> <i32 poison, i32 0> 1837; CHECK-NEXT: ret <2 x float> [[R]] 1838; 1839 %nx = call nsz <2 x float> @llvm.fabs.v2f32(<2 x float> %x) 1840 call void @use(<2 x float> %nx) 1841 %r = shufflevector <2 x float> %nx, <2 x float> poison, <2 x i32> <i32 3, i32 0> 1842 ret <2 x float> %r 1843} 1844 1845; intersect FMF 1846 1847define <4 x float> @fabs_shuf(<4 x float> %x, <4 x float> %y) { 1848; CHECK-LABEL: @fabs_shuf( 1849; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 1850; CHECK-NEXT: [[R:%.*]] = call ninf <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP1]]) 1851; CHECK-NEXT: ret <4 x float> [[R]] 1852; 1853 %nx = call nsz ninf <4 x float> @llvm.fabs.v4f32(<4 x float> %x) 1854 %ny = call nnan ninf <4 x float> @llvm.fabs.v4f32(<4 x float> %y) 1855 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 1856 ret <4 x float> %r 1857} 1858 1859; length-changing shuffle and extra use are ok 1860 1861define <4 x float> @fabs_shuf_widen_use1(<2 x float> %x, <2 x float> %y) { 1862; CHECK-LABEL: @fabs_shuf_widen_use1( 1863; CHECK-NEXT: [[NX:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 1864; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 1865; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X]], <2 x float> [[Y:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 3> 1866; CHECK-NEXT: [[R:%.*]] = call nnan <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP1]]) 1867; CHECK-NEXT: ret <4 x float> [[R]] 1868; 1869 %nx = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> %x) 1870 call void @use(<2 x float> %nx) 1871 %ny = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> %y) 1872 %r = shufflevector <2 x float> %nx, <2 x float> %ny, <4 x i32> <i32 poison, i32 1, i32 2, i32 3> 1873 ret <4 x float> %r 1874} 1875 1876; length-changing shuffle and extra use are ok 1877 1878define <2 x float> @fabs_shuf_narrow_use2(<4 x float> %x, <4 x float> %y) { 1879; CHECK-LABEL: @fabs_shuf_narrow_use2( 1880; CHECK-NEXT: [[NY:%.*]] = call nnan nsz <4 x float> @llvm.fabs.v4f32(<4 x float> [[Y:%.*]]) 1881; CHECK-NEXT: call void @use4(<4 x float> [[NY]]) 1882; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y]], <2 x i32> <i32 3, i32 5> 1883; CHECK-NEXT: [[R:%.*]] = call nnan nsz <2 x float> @llvm.fabs.v2f32(<2 x float> [[TMP1]]) 1884; CHECK-NEXT: ret <2 x float> [[R]] 1885; 1886 %nx = call nsz nnan <4 x float> @llvm.fabs.v4f32(<4 x float> %x) 1887 %ny = call nsz nnan <4 x float> @llvm.fabs.v4f32(<4 x float> %y) 1888 call void @use4(<4 x float> %ny) 1889 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <2 x i32> <i32 3, i32 5> 1890 ret <2 x float> %r 1891} 1892 1893; negative test - too many extra uses 1894 1895define <2 x float> @fabs_shuf_use3(<2 x float> %x, <2 x float> %y) { 1896; CHECK-LABEL: @fabs_shuf_use3( 1897; CHECK-NEXT: [[NX:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) 1898; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 1899; CHECK-NEXT: [[NY:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[Y:%.*]]) 1900; CHECK-NEXT: call void @use(<2 x float> [[NY]]) 1901; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> [[NY]], <2 x i32> <i32 1, i32 2> 1902; CHECK-NEXT: ret <2 x float> [[R]] 1903; 1904 %nx = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> %x) 1905 call void @use(<2 x float> %nx) 1906 %ny = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> %y) 1907 call void @use(<2 x float> %ny) 1908 %r = shufflevector <2 x float> %nx, <2 x float> %ny, <2 x i32> <i32 1, i32 2> 1909 ret <2 x float> %r 1910} 1911 1912define <2 x float> @fneg_unary_shuf(<2 x float> %x) { 1913; CHECK-LABEL: @fneg_unary_shuf( 1914; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 1915; CHECK-NEXT: [[R:%.*]] = fneg nnan nsz <2 x float> [[TMP1]] 1916; CHECK-NEXT: ret <2 x float> [[R]] 1917; 1918 %nx = fneg nsz nnan <2 x float> %x 1919 %r = shufflevector <2 x float> %nx, <2 x float> poison, <2 x i32> <i32 1, i32 0> 1920 ret <2 x float> %r 1921} 1922 1923define <4 x half> @fneg_unary_shuf_widen(<2 x half> %x) { 1924; CHECK-LABEL: @fneg_unary_shuf_widen( 1925; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x half> [[X:%.*]], <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 1926; CHECK-NEXT: [[R:%.*]] = fneg ninf <4 x half> [[TMP1]] 1927; CHECK-NEXT: ret <4 x half> [[R]] 1928; 1929 %nx = fneg ninf <2 x half> %x 1930 %r = shufflevector <2 x half> %nx, <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 1931 ret <4 x half> %r 1932} 1933 1934define <2 x double> @fneg_unary_shuf_narrow(<4 x double> %x) { 1935; CHECK-LABEL: @fneg_unary_shuf_narrow( 1936; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[X:%.*]], <4 x double> poison, <2 x i32> <i32 3, i32 0> 1937; CHECK-NEXT: [[R:%.*]] = fneg nsz <2 x double> [[TMP1]] 1938; CHECK-NEXT: ret <2 x double> [[R]] 1939; 1940 %nx = fneg nsz <4 x double> %x 1941 %r = shufflevector <4 x double> %nx, <4 x double> poison, <2 x i32> <i32 3, i32 0> 1942 ret <2 x double> %r 1943} 1944 1945; negative test - extra use prevents canonicalization 1946 1947define <2 x float> @fneg_unary_shuf_use(<2 x float> %x) { 1948; CHECK-LABEL: @fneg_unary_shuf_use( 1949; CHECK-NEXT: [[NX:%.*]] = fneg nsz <2 x float> [[X:%.*]] 1950; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 1951; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> poison, <2 x i32> <i32 poison, i32 0> 1952; CHECK-NEXT: ret <2 x float> [[R]] 1953; 1954 %nx = fneg nsz <2 x float> %x 1955 call void @use(<2 x float> %nx) 1956 %r = shufflevector <2 x float> %nx, <2 x float> poison, <2 x i32> <i32 3, i32 0> 1957 ret <2 x float> %r 1958} 1959 1960; intersect FMF 1961 1962define <4 x float> @fneg_shuf(<4 x float> %x, <4 x float> %y) { 1963; CHECK-LABEL: @fneg_shuf( 1964; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 1965; CHECK-NEXT: [[R:%.*]] = fneg ninf <4 x float> [[TMP1]] 1966; CHECK-NEXT: ret <4 x float> [[R]] 1967; 1968 %nx = fneg nsz ninf <4 x float> %x 1969 %ny = fneg nnan ninf <4 x float> %y 1970 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 1971 ret <4 x float> %r 1972} 1973 1974; length-changing shuffle and extra use are ok 1975 1976define <4 x float> @fneg_shuf_widen_use1(<2 x float> %x, <2 x float> %y) { 1977; CHECK-LABEL: @fneg_shuf_widen_use1( 1978; CHECK-NEXT: [[NX:%.*]] = fneg nnan <2 x float> [[X:%.*]] 1979; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 1980; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[X]], <2 x float> [[Y:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 3> 1981; CHECK-NEXT: [[R:%.*]] = fneg nnan <4 x float> [[TMP1]] 1982; CHECK-NEXT: ret <4 x float> [[R]] 1983; 1984 %nx = fneg nnan <2 x float> %x 1985 call void @use(<2 x float> %nx) 1986 %ny = fneg nnan <2 x float> %y 1987 %r = shufflevector <2 x float> %nx, <2 x float> %ny, <4 x i32> <i32 poison, i32 1, i32 2, i32 3> 1988 ret <4 x float> %r 1989} 1990 1991; length-changing shuffle and extra use still ok 1992 1993define <2 x float> @fneg_shuf_narrow_use2(<4 x float> %x, <4 x float> %y) { 1994; CHECK-LABEL: @fneg_shuf_narrow_use2( 1995; CHECK-NEXT: [[NY:%.*]] = fneg nnan nsz <4 x float> [[Y:%.*]] 1996; CHECK-NEXT: call void @use4(<4 x float> [[NY]]) 1997; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y]], <2 x i32> <i32 3, i32 5> 1998; CHECK-NEXT: [[R:%.*]] = fneg nnan nsz <2 x float> [[TMP1]] 1999; CHECK-NEXT: ret <2 x float> [[R]] 2000; 2001 %nx = fneg nsz nnan <4 x float> %x 2002 %ny = fneg nsz nnan <4 x float> %y 2003 call void @use4(<4 x float> %ny) 2004 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <2 x i32> <i32 3, i32 5> 2005 ret <2 x float> %r 2006} 2007 2008; negative test - too many extra uses 2009 2010define <2 x float> @fneg_shuf_use3(<2 x float> %x, <2 x float> %y) { 2011; CHECK-LABEL: @fneg_shuf_use3( 2012; CHECK-NEXT: [[NX:%.*]] = fneg nnan <2 x float> [[X:%.*]] 2013; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 2014; CHECK-NEXT: [[NY:%.*]] = fneg nnan <2 x float> [[Y:%.*]] 2015; CHECK-NEXT: call void @use(<2 x float> [[NY]]) 2016; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> [[NY]], <2 x i32> <i32 1, i32 2> 2017; CHECK-NEXT: ret <2 x float> [[R]] 2018; 2019 %nx = fneg nnan <2 x float> %x 2020 call void @use(<2 x float> %nx) 2021 %ny = fneg nnan <2 x float> %y 2022 call void @use(<2 x float> %ny) 2023 %r = shufflevector <2 x float> %nx, <2 x float> %ny, <2 x i32> <i32 1, i32 2> 2024 ret <2 x float> %r 2025} 2026 2027; negative test - mixed opcodes 2028 2029define <4 x float> @fabs_fneg_shuf(<4 x float> %x, <4 x float> %y) { 2030; CHECK-LABEL: @fabs_fneg_shuf( 2031; CHECK-NEXT: [[NX:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> [[X:%.*]]) 2032; CHECK-NEXT: [[NY:%.*]] = fneg nnan ninf <4 x float> [[Y:%.*]] 2033; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[NX]], <4 x float> [[NY]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2034; CHECK-NEXT: ret <4 x float> [[R]] 2035; 2036 %nx = call <4 x float> @llvm.fabs.v4f32(<4 x float> %x) 2037 %ny = fneg nnan ninf <4 x float> %y 2038 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2039 ret <4 x float> %r 2040} 2041 2042define <2 x i32> @fptosi_unary_shuf(<2 x float> %x) { 2043; CHECK-LABEL: @fptosi_unary_shuf( 2044; CHECK-NEXT: [[NX:%.*]] = fptosi <2 x float> [[X:%.*]] to <2 x i32> 2045; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[NX]], <2 x i32> poison, <2 x i32> <i32 1, i32 0> 2046; CHECK-NEXT: ret <2 x i32> [[R]] 2047; 2048 %nx = fptosi <2 x float> %x to <2 x i32> 2049 %r = shufflevector <2 x i32> %nx, <2 x i32> poison, <2 x i32> <i32 1, i32 0> 2050 ret <2 x i32> %r 2051} 2052 2053define <2 x i64> @fptoui_unary_shuf_widen_elts(<2 x float> %x) { 2054; CHECK-LABEL: @fptoui_unary_shuf_widen_elts( 2055; CHECK-NEXT: [[NX:%.*]] = fptoui <2 x float> [[X:%.*]] to <2 x i64> 2056; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i64> [[NX]], <2 x i64> poison, <2 x i32> <i32 1, i32 0> 2057; CHECK-NEXT: ret <2 x i64> [[R]] 2058; 2059 %nx = fptoui <2 x float> %x to <2 x i64> 2060 %r = shufflevector <2 x i64> %nx, <2 x i64> poison, <2 x i32> <i32 1, i32 0> 2061 ret <2 x i64> %r 2062} 2063 2064define <2 x half> @sitofp_unary_shuf_narrow_elts(<2 x i32> %x) { 2065; CHECK-LABEL: @sitofp_unary_shuf_narrow_elts( 2066; CHECK-NEXT: [[NX:%.*]] = sitofp <2 x i32> [[X:%.*]] to <2 x half> 2067; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x half> [[NX]], <2 x half> poison, <2 x i32> <i32 1, i32 0> 2068; CHECK-NEXT: ret <2 x half> [[R]] 2069; 2070 %nx = sitofp <2 x i32> %x to <2 x half> 2071 %r = shufflevector <2 x half> %nx, <2 x half> poison, <2 x i32> <i32 1, i32 0> 2072 ret <2 x half> %r 2073} 2074 2075define <2 x float> @uitofp_unary_shuf(<2 x i32> %x) { 2076; CHECK-LABEL: @uitofp_unary_shuf( 2077; CHECK-NEXT: [[NX:%.*]] = uitofp <2 x i32> [[X:%.*]] to <2 x float> 2078; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 2079; CHECK-NEXT: ret <2 x float> [[R]] 2080; 2081 %nx = uitofp <2 x i32> %x to <2 x float> 2082 %r = shufflevector <2 x float> %nx, <2 x float> poison, <2 x i32> <i32 1, i32 0> 2083 ret <2 x float> %r 2084} 2085 2086define <4 x i16> @fptosi_unary_shuf_widen(<2 x half> %x) { 2087; CHECK-LABEL: @fptosi_unary_shuf_widen( 2088; CHECK-NEXT: [[NX:%.*]] = fptosi <2 x half> [[X:%.*]] to <2 x i16> 2089; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i16> [[NX]], <2 x i16> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2090; CHECK-NEXT: ret <4 x i16> [[R]] 2091; 2092 %nx = fptosi <2 x half> %x to <2 x i16> 2093 %r = shufflevector <2 x i16> %nx, <2 x i16> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2094 ret <4 x i16> %r 2095} 2096 2097define <4 x i32> @fptoui_unary_shuf_widen_widen_elts(<2 x half> %x) { 2098; CHECK-LABEL: @fptoui_unary_shuf_widen_widen_elts( 2099; CHECK-NEXT: [[NX:%.*]] = fptoui <2 x half> [[X:%.*]] to <2 x i32> 2100; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[NX]], <2 x i32> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2101; CHECK-NEXT: ret <4 x i32> [[R]] 2102; 2103 %nx = fptoui <2 x half> %x to <2 x i32> 2104 %r = shufflevector <2 x i32> %nx, <2 x i32> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2105 ret <4 x i32> %r 2106} 2107 2108define <4 x half> @sitofp_unary_shuf_widen_narrow_elts(<2 x i32> %x) { 2109; CHECK-LABEL: @sitofp_unary_shuf_widen_narrow_elts( 2110; CHECK-NEXT: [[NX:%.*]] = sitofp <2 x i32> [[X:%.*]] to <2 x half> 2111; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x half> [[NX]], <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2112; CHECK-NEXT: ret <4 x half> [[R]] 2113; 2114 %nx = sitofp <2 x i32> %x to <2 x half> 2115 %r = shufflevector <2 x half> %nx, <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2116 ret <4 x half> %r 2117} 2118 2119define <4 x half> @uitofp_unary_shuf_widen(<2 x i16> %x) { 2120; CHECK-LABEL: @uitofp_unary_shuf_widen( 2121; CHECK-NEXT: [[NX:%.*]] = uitofp <2 x i16> [[X:%.*]] to <2 x half> 2122; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x half> [[NX]], <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2123; CHECK-NEXT: ret <4 x half> [[R]] 2124; 2125 %nx = uitofp <2 x i16> %x to <2 x half> 2126 %r = shufflevector <2 x half> %nx, <2 x half> poison, <4 x i32> <i32 1, i32 0, i32 0, i32 poison> 2127 ret <4 x half> %r 2128} 2129 2130define <2 x i16> @fptosi_unary_shuf_narrow(<4 x half> %x) { 2131; CHECK-LABEL: @fptosi_unary_shuf_narrow( 2132; CHECK-NEXT: [[NX:%.*]] = fptosi <4 x half> [[X:%.*]] to <4 x i16> 2133; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i16> [[NX]], <4 x i16> poison, <2 x i32> <i32 1, i32 0> 2134; CHECK-NEXT: ret <2 x i16> [[R]] 2135; 2136 %nx = fptosi <4 x half> %x to <4 x i16> 2137 %r = shufflevector <4 x i16> %nx, <4 x i16> poison, <2 x i32> <i32 1, i32 0> 2138 ret <2 x i16> %r 2139} 2140 2141define <2 x i32> @fptoui_unary_shuf_narrow_widen_elts(<4 x half> %x) { 2142; CHECK-LABEL: @fptoui_unary_shuf_narrow_widen_elts( 2143; CHECK-NEXT: [[NX:%.*]] = fptoui <4 x half> [[X:%.*]] to <4 x i32> 2144; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[NX]], <4 x i32> poison, <2 x i32> <i32 3, i32 0> 2145; CHECK-NEXT: ret <2 x i32> [[R]] 2146; 2147 %nx = fptoui <4 x half> %x to <4 x i32> 2148 %r = shufflevector <4 x i32> %nx, <4 x i32> poison, <2 x i32> <i32 3, i32 0> 2149 ret <2 x i32> %r 2150} 2151 2152define <2 x double> @sitofp_unary_shuf_narrow(<4 x i64> %x) { 2153; CHECK-LABEL: @sitofp_unary_shuf_narrow( 2154; CHECK-NEXT: [[NX:%.*]] = sitofp <4 x i64> [[X:%.*]] to <4 x double> 2155; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x double> [[NX]], <4 x double> poison, <2 x i32> <i32 2, i32 1> 2156; CHECK-NEXT: ret <2 x double> [[R]] 2157; 2158 %nx = sitofp <4 x i64> %x to <4 x double> 2159 %r = shufflevector <4 x double> %nx, <4 x double> poison, <2 x i32> <i32 2, i32 1> 2160 ret <2 x double> %r 2161} 2162 2163define <2 x half> @uitofp_unary_shuf_narrow_narrow_elts(<4 x i32> %x) { 2164; CHECK-LABEL: @uitofp_unary_shuf_narrow_narrow_elts( 2165; CHECK-NEXT: [[NX:%.*]] = uitofp <4 x i32> [[X:%.*]] to <4 x half> 2166; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x half> [[NX]], <4 x half> poison, <2 x i32> <i32 3, i32 1> 2167; CHECK-NEXT: ret <2 x half> [[R]] 2168; 2169 %nx = uitofp <4 x i32> %x to <4 x half> 2170 %r = shufflevector <4 x half> %nx, <4 x half> poison, <2 x i32> <i32 3, i32 1> 2171 ret <2 x half> %r 2172} 2173 2174define <4 x i32> @fptosi_shuf(<4 x float> %x, <4 x float> %y) { 2175; CHECK-LABEL: @fptosi_shuf( 2176; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2177; CHECK-NEXT: [[R:%.*]] = fptosi <4 x float> [[TMP1]] to <4 x i32> 2178; CHECK-NEXT: ret <4 x i32> [[R]] 2179; 2180 %nx = fptosi <4 x float> %x to <4 x i32> 2181 %ny = fptosi <4 x float> %y to <4 x i32> 2182 %r = shufflevector <4 x i32> %nx, <4 x i32> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2183 ret <4 x i32> %r 2184} 2185 2186define <3 x i16> @fptoui_shuf(<3 x half> %x, <3 x half> %y) { 2187; CHECK-LABEL: @fptoui_shuf( 2188; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <3 x half> [[X:%.*]], <3 x half> [[Y:%.*]], <3 x i32> <i32 0, i32 poison, i32 4> 2189; CHECK-NEXT: [[R:%.*]] = fptoui <3 x half> [[TMP1]] to <3 x i16> 2190; CHECK-NEXT: ret <3 x i16> [[R]] 2191; 2192 %nx = fptoui <3 x half> %x to <3 x i16> 2193 %ny = fptoui <3 x half> %y to <3 x i16> 2194 %r = shufflevector <3 x i16> %nx, <3 x i16> %ny, <3 x i32> <i32 0, i32 poison, i32 4> 2195 ret <3 x i16> %r 2196} 2197 2198; negative test - must have same source types 2199 2200define <3 x i16> @fptoui_shuf_different_source_types(<3 x float> %x, <3 x half> %y) { 2201; CHECK-LABEL: @fptoui_shuf_different_source_types( 2202; CHECK-NEXT: [[NX:%.*]] = fptoui <3 x float> [[X:%.*]] to <3 x i16> 2203; CHECK-NEXT: [[NY:%.*]] = fptoui <3 x half> [[Y:%.*]] to <3 x i16> 2204; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x i16> [[NX]], <3 x i16> [[NY]], <3 x i32> <i32 0, i32 2, i32 4> 2205; CHECK-NEXT: ret <3 x i16> [[R]] 2206; 2207 %nx = fptoui <3 x float> %x to <3 x i16> 2208 %ny = fptoui <3 x half> %y to <3 x i16> 2209 %r = shufflevector <3 x i16> %nx, <3 x i16> %ny, <3 x i32> <i32 0, i32 2, i32 4> 2210 ret <3 x i16> %r 2211} 2212 2213define <4 x i32> @fptoui_shuf_widen_elts(<4 x half> %x, <4 x half> %y) { 2214; CHECK-LABEL: @fptoui_shuf_widen_elts( 2215; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x half> [[X:%.*]], <4 x half> [[Y:%.*]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2216; CHECK-NEXT: [[R:%.*]] = fptosi <4 x half> [[TMP1]] to <4 x i32> 2217; CHECK-NEXT: ret <4 x i32> [[R]] 2218; 2219 %nx = fptosi <4 x half> %x to <4 x i32> 2220 %ny = fptosi <4 x half> %y to <4 x i32> 2221 %r = shufflevector <4 x i32> %nx, <4 x i32> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2222 ret <4 x i32> %r 2223} 2224 2225; negative test - must have same or smaller size source elements 2226 2227define <4 x float> @sitofp_shuf_narrow_elts(<4 x i64> %x, <4 x i64> %y) { 2228; CHECK-LABEL: @sitofp_shuf_narrow_elts( 2229; CHECK-NEXT: [[NX:%.*]] = sitofp <4 x i64> [[X:%.*]] to <4 x float> 2230; CHECK-NEXT: [[NY:%.*]] = sitofp <4 x i64> [[Y:%.*]] to <4 x float> 2231; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x float> [[NX]], <4 x float> [[NY]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2232; CHECK-NEXT: ret <4 x float> [[R]] 2233; 2234 %nx = sitofp <4 x i64> %x to <4 x float> 2235 %ny = sitofp <4 x i64> %y to <4 x float> 2236 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2237 ret <4 x float> %r 2238} 2239 2240; one extra use is ok 2241 2242define <4 x float> @uitofp_shuf_extra_use1(<4 x i32> %x, <4 x i32> %y) { 2243; CHECK-LABEL: @uitofp_shuf_extra_use1( 2244; CHECK-NEXT: [[NX:%.*]] = uitofp <4 x i32> [[X:%.*]] to <4 x float> 2245; CHECK-NEXT: call void @use4(<4 x float> [[NX]]) 2246; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[X]], <4 x i32> [[Y:%.*]], <4 x i32> <i32 0, i32 0, i32 4, i32 5> 2247; CHECK-NEXT: [[R:%.*]] = uitofp <4 x i32> [[TMP1]] to <4 x float> 2248; CHECK-NEXT: ret <4 x float> [[R]] 2249; 2250 %nx = uitofp <4 x i32> %x to <4 x float> 2251 call void @use4(<4 x float> %nx) 2252 %ny = uitofp <4 x i32> %y to <4 x float> 2253 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <4 x i32> <i32 0, i32 0, i32 4, i32 5> 2254 ret <4 x float> %r 2255} 2256 2257; one extra use is ok 2258 2259define <4 x float> @sitofp_shuf_extra_use2(<4 x i32> %x, <4 x i32> %y) { 2260; CHECK-LABEL: @sitofp_shuf_extra_use2( 2261; CHECK-NEXT: [[NY:%.*]] = sitofp <4 x i32> [[Y:%.*]] to <4 x float> 2262; CHECK-NEXT: call void @use4(<4 x float> [[NY]]) 2263; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y]], <4 x i32> <i32 7, i32 1, i32 4, i32 0> 2264; CHECK-NEXT: [[R:%.*]] = sitofp <4 x i32> [[TMP1]] to <4 x float> 2265; CHECK-NEXT: ret <4 x float> [[R]] 2266; 2267 %nx = sitofp <4 x i32> %x to <4 x float> 2268 %ny = sitofp <4 x i32> %y to <4 x float> 2269 call void @use4(<4 x float> %ny) 2270 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <4 x i32> <i32 7, i32 1, i32 4, i32 0> 2271 ret <4 x float> %r 2272} 2273 2274; negative test - both ops have extra uses 2275 2276define <2 x float> @sitofp_shuf_extra_use3(<2 x i32> %x, <2 x i32> %y) { 2277; CHECK-LABEL: @sitofp_shuf_extra_use3( 2278; CHECK-NEXT: [[NX:%.*]] = sitofp <2 x i32> [[X:%.*]] to <2 x float> 2279; CHECK-NEXT: call void @use(<2 x float> [[NX]]) 2280; CHECK-NEXT: [[NY:%.*]] = sitofp <2 x i32> [[Y:%.*]] to <2 x float> 2281; CHECK-NEXT: call void @use(<2 x float> [[NY]]) 2282; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> [[NY]], <2 x i32> <i32 3, i32 1> 2283; CHECK-NEXT: ret <2 x float> [[R]] 2284; 2285 %nx = sitofp <2 x i32> %x to <2 x float> 2286 call void @use(<2 x float> %nx) 2287 %ny = sitofp <2 x i32> %y to <2 x float> 2288 call void @use(<2 x float> %ny) 2289 %r = shufflevector <2 x float> %nx, <2 x float> %ny, <2 x i32> <i32 3, i32 1> 2290 ret <2 x float> %r 2291} 2292 2293; negative test - mismatched casts 2294 2295define <4 x i32> @fptoi_shuf(<4 x float> %x, <4 x float> %y) { 2296; CHECK-LABEL: @fptoi_shuf( 2297; CHECK-NEXT: [[NX:%.*]] = fptoui <4 x float> [[X:%.*]] to <4 x i32> 2298; CHECK-NEXT: [[NY:%.*]] = fptosi <4 x float> [[Y:%.*]] to <4 x i32> 2299; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i32> [[NX]], <4 x i32> [[NY]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2300; CHECK-NEXT: ret <4 x i32> [[R]] 2301; 2302 %nx = fptoui <4 x float> %x to <4 x i32> 2303 %ny = fptosi <4 x float> %y to <4 x i32> 2304 %r = shufflevector <4 x i32> %nx, <4 x i32> %ny, <4 x i32> <i32 0, i32 1, i32 4, i32 5> 2305 ret <4 x i32> %r 2306} 2307 2308; negative test - length-increasing shuffle 2309 2310define <4 x float> @sitofp_shuf_widen(<2 x i32> %x, <2 x i32> %y) { 2311; CHECK-LABEL: @sitofp_shuf_widen( 2312; CHECK-NEXT: [[NX:%.*]] = sitofp <2 x i32> [[X:%.*]] to <2 x float> 2313; CHECK-NEXT: [[NY:%.*]] = sitofp <2 x i32> [[Y:%.*]] to <2 x float> 2314; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[NX]], <2 x float> [[NY]], <4 x i32> <i32 poison, i32 1, i32 2, i32 3> 2315; CHECK-NEXT: ret <4 x float> [[R]] 2316; 2317 %nx = sitofp <2 x i32> %x to <2 x float> 2318 %ny = sitofp <2 x i32> %y to <2 x float> 2319 %r = shufflevector <2 x float> %nx, <2 x float> %ny, <4 x i32> <i32 poison, i32 1, i32 2, i32 3> 2320 ret <4 x float> %r 2321} 2322 2323define <2 x float> @uitofp_shuf_narrow(<4 x i32> %x, <4 x i32> %y) { 2324; CHECK-LABEL: @uitofp_shuf_narrow( 2325; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> [[Y:%.*]], <2 x i32> <i32 3, i32 5> 2326; CHECK-NEXT: [[R:%.*]] = uitofp <2 x i32> [[TMP1]] to <2 x float> 2327; CHECK-NEXT: ret <2 x float> [[R]] 2328; 2329 %nx = uitofp <4 x i32> %x to <4 x float> 2330 %ny = uitofp <4 x i32> %y to <4 x float> 2331 %r = shufflevector <4 x float> %nx, <4 x float> %ny, <2 x i32> <i32 3, i32 5> 2332 ret <2 x float> %r 2333} 2334 2335define <4 x i16> @blend_elements_from_load(ptr align 8 %_0) { 2336; CHECK-LABEL: @blend_elements_from_load( 2337; CHECK-NEXT: [[LOAD:%.*]] = load <3 x i16>, ptr [[_0:%.*]], align 8 2338; CHECK-NEXT: [[RV:%.*]] = shufflevector <3 x i16> <i16 0, i16 undef, i16 poison>, <3 x i16> [[LOAD]], <4 x i32> <i32 0, i32 1, i32 3, i32 5> 2339; CHECK-NEXT: ret <4 x i16> [[RV]] 2340; 2341 %load = load <3 x i16>, ptr %_0, align 8 2342 %rv = shufflevector <3 x i16> <i16 0, i16 undef, i16 undef>, <3 x i16> %load, <4 x i32> <i32 0, i32 1, i32 3, i32 5> 2343 ret <4 x i16> %rv 2344} 2345 2346define i16 @pr92887(<2 x i16> %v) { 2347; CHECK-LABEL: @pr92887( 2348; CHECK-NEXT: ret i16 undef 2349; 2350 %v0 = extractelement <2 x i16> %v, i64 0 2351 %v0lo = and i16 %v0, 1 2352 %v1 = extractelement <2 x i16> %v, i64 1 2353 %v1lo = and i16 %v1, 1 2354 %ins1 = insertelement <4 x i16> poison, i16 %v0lo, i64 0 2355 %ins2 = insertelement <4 x i16> %ins1, i16 %v1lo, i64 1 2356 %shuf = shufflevector <4 x i16> %ins2, <4 x i16> <i16 poison, i16 poison, i16 undef, i16 undef>, <4 x i32> <i32 0, i32 1, i32 6, i32 7> 2357 %extract = extractelement <4 x i16> %shuf, i32 2 2358 ret i16 %extract 2359} 2360 2361define <2 x i32> @not_splat_shuffle1(i32 %x) { 2362; CHECK-LABEL: @not_splat_shuffle1( 2363; CHECK-NEXT: [[SHUF:%.*]] = insertelement <2 x i32> <i32 poison, i32 undef>, i32 [[X:%.*]], i64 0 2364; CHECK-NEXT: ret <2 x i32> [[SHUF]] 2365; 2366 %vec = insertelement <2 x i32> undef, i32 %x, i32 1 2367 %shuf = shufflevector <2 x i32> %vec, <2 x i32> poison, <2 x i32> <i32 1, i32 0> 2368 ret <2 x i32> %shuf 2369} 2370 2371define <2 x i32> @not_splat_shuffle2(i32 %x) { 2372; CHECK-LABEL: @not_splat_shuffle2( 2373; CHECK-NEXT: [[SHUF:%.*]] = insertelement <2 x i32> <i32 poison, i32 undef>, i32 [[X:%.*]], i64 0 2374; CHECK-NEXT: ret <2 x i32> [[SHUF]] 2375; 2376 %vec = insertelement <2 x i32> poison, i32 %x, i32 1 2377 %shuf = shufflevector <2 x i32> %vec, <2 x i32> undef, <2 x i32> <i32 1, i32 3> 2378 ret <2 x i32> %shuf 2379} 2380define <2 x i32> @foldselect0(i1 %c) { 2381; CHECK-LABEL: @foldselect0( 2382; CHECK-NEXT: [[SHUF:%.*]] = select i1 [[C:%.*]], <2 x i32> <i32 7, i32 42>, <2 x i32> <i32 1, i32 0> 2383; CHECK-NEXT: ret <2 x i32> [[SHUF]] 2384; 2385 %sel = select i1 %c, <2 x i32> <i32 42, i32 7>, <2 x i32> <i32 0, i32 1> 2386 %shuf = shufflevector <2 x i32> %sel, <2 x i32> poison, <2 x i32> <i32 1, i32 0> 2387 ret <2 x i32> %shuf 2388} 2389 2390; Make sure we do not crash in this case. 2391define <4 x float> @shuf_larger_length_vec_select(<2 x i1> %cond) { 2392; CHECK-LABEL: @shuf_larger_length_vec_select( 2393; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x float> zeroinitializer, <2 x float> splat (float 1.000000e+00) 2394; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <2 x float> [[SEL]], <2 x float> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 2395; CHECK-NEXT: ret <4 x float> [[SHUF]] 2396; 2397 %sel = select <2 x i1> %cond, <2 x float> zeroinitializer, <2 x float> splat(float 1.000000e+00) 2398 %shuf = shufflevector <2 x float> %sel, <2 x float> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 2399 ret <4 x float> %shuf 2400} 2401 2402; Make sure we do not fold in this case. 2403define <4 x i32> @shuf_same_length_vec_select(<4 x i1> %cond) { 2404; CHECK-LABEL: @shuf_same_length_vec_select( 2405; CHECK-NEXT: [[SEL:%.*]] = select <4 x i1> [[COND:%.*]], <4 x i32> <i32 poison, i32 1, i32 2, i32 3>, <4 x i32> <i32 poison, i32 5, i32 6, i32 7> 2406; CHECK-NEXT: [[SHUF:%.*]] = shufflevector <4 x i32> [[SEL]], <4 x i32> <i32 poison, i32 9, i32 poison, i32 poison>, <4 x i32> <i32 2, i32 1, i32 3, i32 5> 2407; CHECK-NEXT: ret <4 x i32> [[SHUF]] 2408; 2409 %sel = select <4 x i1> %cond, <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32> <i32 4, i32 5, i32 6, i32 7> 2410 %shuf = shufflevector <4 x i32> %sel, <4 x i32> <i32 8, i32 9, i32 10, i32 11>, <4 x i32> <i32 2, i32 1, i32 3, i32 5> 2411 ret <4 x i32> %shuf 2412} 2413 2414; Make sure we do not fold in this case. 2415define <4 x i8> @shuf_cmp_may_be_poison(<4 x i8> %x, <4 x i8> %y, i1 %cmp) { 2416; CHECK-LABEL: @shuf_cmp_may_be_poison( 2417; CHECK-NEXT: [[Y:%.*]] = select i1 [[CMP:%.*]], <4 x i8> [[Y1:%.*]], <4 x i8> <i8 0, i8 poison, i8 0, i8 poison> 2418; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i8> [[Y]], <4 x i8> <i8 poison, i8 1, i8 poison, i8 3>, <4 x i32> <i32 0, i32 5, i32 2, i32 7> 2419; CHECK-NEXT: ret <4 x i8> [[TMP1]] 2420; 2421 %sel = select i1 %cmp, <4 x i8> %y, <4 x i8> <i8 0, i8 poison, i8 0, i8 poison> 2422 %shuf = shufflevector <4 x i8> %sel, <4 x i8> <i8 poison, i8 1, i8 poison, i8 3>, <4 x i32> <i32 0, i32 5, i32 2, i32 7> 2423 ret <4 x i8> %shuf 2424} 2425 2426declare i1 @cond() 2427declare <4 x i32> @value() 2428 2429define <4 x i32> @foldphi1() { 2430; CHECK-LABEL: @foldphi1( 2431; CHECK-NEXT: entry: 2432; CHECK-NEXT: br label [[LOOP:%.*]] 2433; CHECK: loop: 2434; CHECK-NEXT: [[V:%.*]] = phi <4 x i32> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[XOR:%.*]], [[LOOP]] ] 2435; CHECK-NEXT: [[VAL:%.*]] = call <4 x i32> @value() 2436; CHECK-NEXT: [[XOR]] = xor <4 x i32> [[V]], [[VAL]] 2437; CHECK-NEXT: [[C:%.*]] = call i1 @cond() 2438; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 2439; CHECK: exit: 2440; CHECK-NEXT: [[SHUF1:%.*]] = shufflevector <4 x i32> [[XOR]], <4 x i32> poison, <4 x i32> <i32 3, i32 0, i32 1, i32 2> 2441; CHECK-NEXT: ret <4 x i32> [[SHUF1]] 2442; 2443entry: 2444 br label %loop 2445 2446loop: 2447 %v = phi <4 x i32> [zeroinitializer, %entry], [%shuf1, %loop] 2448 2449 %shuf0 = shufflevector <4 x i32> %v, <4 x i32> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 0> 2450 %val = call <4 x i32> @value() 2451 %xor = xor <4 x i32> %shuf0, %val 2452 %shuf1 = shufflevector <4 x i32> %xor, <4 x i32> poison, <4 x i32> <i32 3, i32 0, i32 1, i32 2> 2453 2454 %c = call i1 @cond() 2455 br i1 %c, label %loop, label %exit 2456 2457exit: 2458 ret <4 x i32> %shuf1 2459} 2460