1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ssse3 | FileCheck %s --check-prefixes=SSE3,SSE3-SLOW 3; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ssse3,fast-hops | FileCheck %s --check-prefixes=SSE3,SSE3-FAST 4; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX-SLOW,AVX1-SLOW 5; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx,fast-hops | FileCheck %s --check-prefixes=AVX,AVX-FAST,AVX1-FAST 6; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX-SLOW,AVX2-SLOW 7; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2,fast-hops | FileCheck %s --check-prefixes=AVX,AVX-FAST,AVX2-FAST 8; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX-SLOW,AVX512-SLOW 9; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx512vl,fast-hops | FileCheck %s --check-prefixes=AVX,AVX-FAST,AVX512-FAST 10 11; 128-bit vectors, 16/32-bit, add/sub 12 13define i32 @extract_extract_v4i32_add_i32(<4 x i32> %x) { 14; SSE3-LABEL: extract_extract_v4i32_add_i32: 15; SSE3: # %bb.0: 16; SSE3-NEXT: movd %xmm0, %ecx 17; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 18; SSE3-NEXT: movd %xmm0, %eax 19; SSE3-NEXT: addl %ecx, %eax 20; SSE3-NEXT: retq 21; 22; AVX-LABEL: extract_extract_v4i32_add_i32: 23; AVX: # %bb.0: 24; AVX-NEXT: vmovd %xmm0, %ecx 25; AVX-NEXT: vpextrd $1, %xmm0, %eax 26; AVX-NEXT: addl %ecx, %eax 27; AVX-NEXT: retq 28 %x0 = extractelement <4 x i32> %x, i32 0 29 %x1 = extractelement <4 x i32> %x, i32 1 30 %x01 = add i32 %x0, %x1 31 ret i32 %x01 32} 33 34define i32 @extract_extract_v4i32_add_i32_commute(<4 x i32> %x) { 35; SSE3-LABEL: extract_extract_v4i32_add_i32_commute: 36; SSE3: # %bb.0: 37; SSE3-NEXT: movd %xmm0, %ecx 38; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 39; SSE3-NEXT: movd %xmm0, %eax 40; SSE3-NEXT: addl %ecx, %eax 41; SSE3-NEXT: retq 42; 43; AVX-LABEL: extract_extract_v4i32_add_i32_commute: 44; AVX: # %bb.0: 45; AVX-NEXT: vmovd %xmm0, %ecx 46; AVX-NEXT: vpextrd $1, %xmm0, %eax 47; AVX-NEXT: addl %ecx, %eax 48; AVX-NEXT: retq 49 %x0 = extractelement <4 x i32> %x, i32 0 50 %x1 = extractelement <4 x i32> %x, i32 1 51 %x01 = add i32 %x1, %x0 52 ret i32 %x01 53} 54 55define i16 @extract_extract_v8i16_add_i16(<8 x i16> %x) { 56; SSE3-LABEL: extract_extract_v8i16_add_i16: 57; SSE3: # %bb.0: 58; SSE3-NEXT: movd %xmm0, %ecx 59; SSE3-NEXT: pextrw $1, %xmm0, %eax 60; SSE3-NEXT: addl %ecx, %eax 61; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 62; SSE3-NEXT: retq 63; 64; AVX-LABEL: extract_extract_v8i16_add_i16: 65; AVX: # %bb.0: 66; AVX-NEXT: vmovd %xmm0, %ecx 67; AVX-NEXT: vpextrw $1, %xmm0, %eax 68; AVX-NEXT: addl %ecx, %eax 69; AVX-NEXT: # kill: def $ax killed $ax killed $eax 70; AVX-NEXT: retq 71 %x0 = extractelement <8 x i16> %x, i32 0 72 %x1 = extractelement <8 x i16> %x, i32 1 73 %x01 = add i16 %x0, %x1 74 ret i16 %x01 75} 76 77define i16 @extract_extract_v8i16_add_i16_commute(<8 x i16> %x) { 78; SSE3-LABEL: extract_extract_v8i16_add_i16_commute: 79; SSE3: # %bb.0: 80; SSE3-NEXT: movd %xmm0, %ecx 81; SSE3-NEXT: pextrw $1, %xmm0, %eax 82; SSE3-NEXT: addl %ecx, %eax 83; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 84; SSE3-NEXT: retq 85; 86; AVX-LABEL: extract_extract_v8i16_add_i16_commute: 87; AVX: # %bb.0: 88; AVX-NEXT: vmovd %xmm0, %ecx 89; AVX-NEXT: vpextrw $1, %xmm0, %eax 90; AVX-NEXT: addl %ecx, %eax 91; AVX-NEXT: # kill: def $ax killed $ax killed $eax 92; AVX-NEXT: retq 93 %x0 = extractelement <8 x i16> %x, i32 0 94 %x1 = extractelement <8 x i16> %x, i32 1 95 %x01 = add i16 %x1, %x0 96 ret i16 %x01 97} 98 99define i32 @extract_extract_v4i32_sub_i32(<4 x i32> %x) { 100; SSE3-LABEL: extract_extract_v4i32_sub_i32: 101; SSE3: # %bb.0: 102; SSE3-NEXT: movd %xmm0, %eax 103; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 104; SSE3-NEXT: movd %xmm0, %ecx 105; SSE3-NEXT: subl %ecx, %eax 106; SSE3-NEXT: retq 107; 108; AVX-LABEL: extract_extract_v4i32_sub_i32: 109; AVX: # %bb.0: 110; AVX-NEXT: vmovd %xmm0, %eax 111; AVX-NEXT: vpextrd $1, %xmm0, %ecx 112; AVX-NEXT: subl %ecx, %eax 113; AVX-NEXT: retq 114 %x0 = extractelement <4 x i32> %x, i32 0 115 %x1 = extractelement <4 x i32> %x, i32 1 116 %x01 = sub i32 %x0, %x1 117 ret i32 %x01 118} 119 120define i32 @extract_extract_v4i32_sub_i32_commute(<4 x i32> %x) { 121; SSE3-LABEL: extract_extract_v4i32_sub_i32_commute: 122; SSE3: # %bb.0: 123; SSE3-NEXT: movd %xmm0, %ecx 124; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 125; SSE3-NEXT: movd %xmm0, %eax 126; SSE3-NEXT: subl %ecx, %eax 127; SSE3-NEXT: retq 128; 129; AVX-LABEL: extract_extract_v4i32_sub_i32_commute: 130; AVX: # %bb.0: 131; AVX-NEXT: vmovd %xmm0, %ecx 132; AVX-NEXT: vpextrd $1, %xmm0, %eax 133; AVX-NEXT: subl %ecx, %eax 134; AVX-NEXT: retq 135 %x0 = extractelement <4 x i32> %x, i32 0 136 %x1 = extractelement <4 x i32> %x, i32 1 137 %x01 = sub i32 %x1, %x0 138 ret i32 %x01 139} 140 141define i16 @extract_extract_v8i16_sub_i16(<8 x i16> %x) { 142; SSE3-LABEL: extract_extract_v8i16_sub_i16: 143; SSE3: # %bb.0: 144; SSE3-NEXT: movd %xmm0, %eax 145; SSE3-NEXT: pextrw $1, %xmm0, %ecx 146; SSE3-NEXT: subl %ecx, %eax 147; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 148; SSE3-NEXT: retq 149; 150; AVX-LABEL: extract_extract_v8i16_sub_i16: 151; AVX: # %bb.0: 152; AVX-NEXT: vmovd %xmm0, %eax 153; AVX-NEXT: vpextrw $1, %xmm0, %ecx 154; AVX-NEXT: subl %ecx, %eax 155; AVX-NEXT: # kill: def $ax killed $ax killed $eax 156; AVX-NEXT: retq 157 %x0 = extractelement <8 x i16> %x, i32 0 158 %x1 = extractelement <8 x i16> %x, i32 1 159 %x01 = sub i16 %x0, %x1 160 ret i16 %x01 161} 162 163define i16 @extract_extract_v8i16_sub_i16_commute(<8 x i16> %x) { 164; SSE3-LABEL: extract_extract_v8i16_sub_i16_commute: 165; SSE3: # %bb.0: 166; SSE3-NEXT: movd %xmm0, %ecx 167; SSE3-NEXT: pextrw $1, %xmm0, %eax 168; SSE3-NEXT: subl %ecx, %eax 169; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 170; SSE3-NEXT: retq 171; 172; AVX-LABEL: extract_extract_v8i16_sub_i16_commute: 173; AVX: # %bb.0: 174; AVX-NEXT: vmovd %xmm0, %ecx 175; AVX-NEXT: vpextrw $1, %xmm0, %eax 176; AVX-NEXT: subl %ecx, %eax 177; AVX-NEXT: # kill: def $ax killed $ax killed $eax 178; AVX-NEXT: retq 179 %x0 = extractelement <8 x i16> %x, i32 0 180 %x1 = extractelement <8 x i16> %x, i32 1 181 %x01 = sub i16 %x1, %x0 182 ret i16 %x01 183} 184 185; 256-bit vectors, i32/i16, add/sub 186 187define i32 @extract_extract_v8i32_add_i32(<8 x i32> %x) { 188; SSE3-LABEL: extract_extract_v8i32_add_i32: 189; SSE3: # %bb.0: 190; SSE3-NEXT: movd %xmm0, %ecx 191; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 192; SSE3-NEXT: movd %xmm0, %eax 193; SSE3-NEXT: addl %ecx, %eax 194; SSE3-NEXT: retq 195; 196; AVX-LABEL: extract_extract_v8i32_add_i32: 197; AVX: # %bb.0: 198; AVX-NEXT: vmovd %xmm0, %ecx 199; AVX-NEXT: vpextrd $1, %xmm0, %eax 200; AVX-NEXT: addl %ecx, %eax 201; AVX-NEXT: vzeroupper 202; AVX-NEXT: retq 203 %x0 = extractelement <8 x i32> %x, i32 0 204 %x1 = extractelement <8 x i32> %x, i32 1 205 %x01 = add i32 %x0, %x1 206 ret i32 %x01 207} 208 209define i32 @extract_extract_v8i32_add_i32_commute(<8 x i32> %x) { 210; SSE3-LABEL: extract_extract_v8i32_add_i32_commute: 211; SSE3: # %bb.0: 212; SSE3-NEXT: movd %xmm0, %ecx 213; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 214; SSE3-NEXT: movd %xmm0, %eax 215; SSE3-NEXT: addl %ecx, %eax 216; SSE3-NEXT: retq 217; 218; AVX-LABEL: extract_extract_v8i32_add_i32_commute: 219; AVX: # %bb.0: 220; AVX-NEXT: vmovd %xmm0, %ecx 221; AVX-NEXT: vpextrd $1, %xmm0, %eax 222; AVX-NEXT: addl %ecx, %eax 223; AVX-NEXT: vzeroupper 224; AVX-NEXT: retq 225 %x0 = extractelement <8 x i32> %x, i32 0 226 %x1 = extractelement <8 x i32> %x, i32 1 227 %x01 = add i32 %x1, %x0 228 ret i32 %x01 229} 230 231define i16 @extract_extract_v16i16_add_i16(<16 x i16> %x) { 232; SSE3-LABEL: extract_extract_v16i16_add_i16: 233; SSE3: # %bb.0: 234; SSE3-NEXT: movd %xmm0, %ecx 235; SSE3-NEXT: pextrw $1, %xmm0, %eax 236; SSE3-NEXT: addl %ecx, %eax 237; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 238; SSE3-NEXT: retq 239; 240; AVX-LABEL: extract_extract_v16i16_add_i16: 241; AVX: # %bb.0: 242; AVX-NEXT: vmovd %xmm0, %ecx 243; AVX-NEXT: vpextrw $1, %xmm0, %eax 244; AVX-NEXT: addl %ecx, %eax 245; AVX-NEXT: # kill: def $ax killed $ax killed $eax 246; AVX-NEXT: vzeroupper 247; AVX-NEXT: retq 248 %x0 = extractelement <16 x i16> %x, i32 0 249 %x1 = extractelement <16 x i16> %x, i32 1 250 %x01 = add i16 %x0, %x1 251 ret i16 %x01 252} 253 254define i16 @extract_extract_v16i16_add_i16_commute(<16 x i16> %x) { 255; SSE3-LABEL: extract_extract_v16i16_add_i16_commute: 256; SSE3: # %bb.0: 257; SSE3-NEXT: movd %xmm0, %ecx 258; SSE3-NEXT: pextrw $1, %xmm0, %eax 259; SSE3-NEXT: addl %ecx, %eax 260; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 261; SSE3-NEXT: retq 262; 263; AVX-LABEL: extract_extract_v16i16_add_i16_commute: 264; AVX: # %bb.0: 265; AVX-NEXT: vmovd %xmm0, %ecx 266; AVX-NEXT: vpextrw $1, %xmm0, %eax 267; AVX-NEXT: addl %ecx, %eax 268; AVX-NEXT: # kill: def $ax killed $ax killed $eax 269; AVX-NEXT: vzeroupper 270; AVX-NEXT: retq 271 %x0 = extractelement <16 x i16> %x, i32 0 272 %x1 = extractelement <16 x i16> %x, i32 1 273 %x01 = add i16 %x1, %x0 274 ret i16 %x01 275} 276 277define i32 @extract_extract_v8i32_sub_i32(<8 x i32> %x) { 278; SSE3-LABEL: extract_extract_v8i32_sub_i32: 279; SSE3: # %bb.0: 280; SSE3-NEXT: movd %xmm0, %eax 281; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 282; SSE3-NEXT: movd %xmm0, %ecx 283; SSE3-NEXT: subl %ecx, %eax 284; SSE3-NEXT: retq 285; 286; AVX-LABEL: extract_extract_v8i32_sub_i32: 287; AVX: # %bb.0: 288; AVX-NEXT: vmovd %xmm0, %eax 289; AVX-NEXT: vpextrd $1, %xmm0, %ecx 290; AVX-NEXT: subl %ecx, %eax 291; AVX-NEXT: vzeroupper 292; AVX-NEXT: retq 293 %x0 = extractelement <8 x i32> %x, i32 0 294 %x1 = extractelement <8 x i32> %x, i32 1 295 %x01 = sub i32 %x0, %x1 296 ret i32 %x01 297} 298 299; Negative test...or get hoppy and negate? 300 301define i32 @extract_extract_v8i32_sub_i32_commute(<8 x i32> %x) { 302; SSE3-LABEL: extract_extract_v8i32_sub_i32_commute: 303; SSE3: # %bb.0: 304; SSE3-NEXT: movd %xmm0, %ecx 305; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 306; SSE3-NEXT: movd %xmm0, %eax 307; SSE3-NEXT: subl %ecx, %eax 308; SSE3-NEXT: retq 309; 310; AVX-LABEL: extract_extract_v8i32_sub_i32_commute: 311; AVX: # %bb.0: 312; AVX-NEXT: vmovd %xmm0, %ecx 313; AVX-NEXT: vpextrd $1, %xmm0, %eax 314; AVX-NEXT: subl %ecx, %eax 315; AVX-NEXT: vzeroupper 316; AVX-NEXT: retq 317 %x0 = extractelement <8 x i32> %x, i32 0 318 %x1 = extractelement <8 x i32> %x, i32 1 319 %x01 = sub i32 %x1, %x0 320 ret i32 %x01 321} 322 323define i16 @extract_extract_v16i16_sub_i16(<16 x i16> %x) { 324; SSE3-LABEL: extract_extract_v16i16_sub_i16: 325; SSE3: # %bb.0: 326; SSE3-NEXT: movd %xmm0, %eax 327; SSE3-NEXT: pextrw $1, %xmm0, %ecx 328; SSE3-NEXT: subl %ecx, %eax 329; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 330; SSE3-NEXT: retq 331; 332; AVX-LABEL: extract_extract_v16i16_sub_i16: 333; AVX: # %bb.0: 334; AVX-NEXT: vmovd %xmm0, %eax 335; AVX-NEXT: vpextrw $1, %xmm0, %ecx 336; AVX-NEXT: subl %ecx, %eax 337; AVX-NEXT: # kill: def $ax killed $ax killed $eax 338; AVX-NEXT: vzeroupper 339; AVX-NEXT: retq 340 %x0 = extractelement <16 x i16> %x, i32 0 341 %x1 = extractelement <16 x i16> %x, i32 1 342 %x01 = sub i16 %x0, %x1 343 ret i16 %x01 344} 345 346; Negative test...or get hoppy and negate? 347 348define i16 @extract_extract_v16i16_sub_i16_commute(<16 x i16> %x) { 349; SSE3-LABEL: extract_extract_v16i16_sub_i16_commute: 350; SSE3: # %bb.0: 351; SSE3-NEXT: movd %xmm0, %ecx 352; SSE3-NEXT: pextrw $1, %xmm0, %eax 353; SSE3-NEXT: subl %ecx, %eax 354; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 355; SSE3-NEXT: retq 356; 357; AVX-LABEL: extract_extract_v16i16_sub_i16_commute: 358; AVX: # %bb.0: 359; AVX-NEXT: vmovd %xmm0, %ecx 360; AVX-NEXT: vpextrw $1, %xmm0, %eax 361; AVX-NEXT: subl %ecx, %eax 362; AVX-NEXT: # kill: def $ax killed $ax killed $eax 363; AVX-NEXT: vzeroupper 364; AVX-NEXT: retq 365 %x0 = extractelement <16 x i16> %x, i32 0 366 %x1 = extractelement <16 x i16> %x, i32 1 367 %x01 = sub i16 %x1, %x0 368 ret i16 %x01 369} 370 371; 512-bit vectors, i32/i16, add/sub 372 373define i32 @extract_extract_v16i32_add_i32(<16 x i32> %x) { 374; SSE3-LABEL: extract_extract_v16i32_add_i32: 375; SSE3: # %bb.0: 376; SSE3-NEXT: movd %xmm0, %ecx 377; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 378; SSE3-NEXT: movd %xmm0, %eax 379; SSE3-NEXT: addl %ecx, %eax 380; SSE3-NEXT: retq 381; 382; AVX-LABEL: extract_extract_v16i32_add_i32: 383; AVX: # %bb.0: 384; AVX-NEXT: vmovd %xmm0, %ecx 385; AVX-NEXT: vpextrd $1, %xmm0, %eax 386; AVX-NEXT: addl %ecx, %eax 387; AVX-NEXT: vzeroupper 388; AVX-NEXT: retq 389 %x0 = extractelement <16 x i32> %x, i32 0 390 %x1 = extractelement <16 x i32> %x, i32 1 391 %x01 = add i32 %x0, %x1 392 ret i32 %x01 393} 394 395define i32 @extract_extract_v16i32_add_i32_commute(<16 x i32> %x) { 396; SSE3-LABEL: extract_extract_v16i32_add_i32_commute: 397; SSE3: # %bb.0: 398; SSE3-NEXT: movd %xmm0, %ecx 399; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 400; SSE3-NEXT: movd %xmm0, %eax 401; SSE3-NEXT: addl %ecx, %eax 402; SSE3-NEXT: retq 403; 404; AVX-LABEL: extract_extract_v16i32_add_i32_commute: 405; AVX: # %bb.0: 406; AVX-NEXT: vmovd %xmm0, %ecx 407; AVX-NEXT: vpextrd $1, %xmm0, %eax 408; AVX-NEXT: addl %ecx, %eax 409; AVX-NEXT: vzeroupper 410; AVX-NEXT: retq 411 %x0 = extractelement <16 x i32> %x, i32 0 412 %x1 = extractelement <16 x i32> %x, i32 1 413 %x01 = add i32 %x1, %x0 414 ret i32 %x01 415} 416 417define i16 @extract_extract_v32i16_add_i16(<32 x i16> %x) { 418; SSE3-LABEL: extract_extract_v32i16_add_i16: 419; SSE3: # %bb.0: 420; SSE3-NEXT: movd %xmm0, %ecx 421; SSE3-NEXT: pextrw $1, %xmm0, %eax 422; SSE3-NEXT: addl %ecx, %eax 423; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 424; SSE3-NEXT: retq 425; 426; AVX-LABEL: extract_extract_v32i16_add_i16: 427; AVX: # %bb.0: 428; AVX-NEXT: vmovd %xmm0, %ecx 429; AVX-NEXT: vpextrw $1, %xmm0, %eax 430; AVX-NEXT: addl %ecx, %eax 431; AVX-NEXT: # kill: def $ax killed $ax killed $eax 432; AVX-NEXT: vzeroupper 433; AVX-NEXT: retq 434 %x0 = extractelement <32 x i16> %x, i32 0 435 %x1 = extractelement <32 x i16> %x, i32 1 436 %x01 = add i16 %x0, %x1 437 ret i16 %x01 438} 439 440define i16 @extract_extract_v32i16_add_i16_commute(<32 x i16> %x) { 441; SSE3-LABEL: extract_extract_v32i16_add_i16_commute: 442; SSE3: # %bb.0: 443; SSE3-NEXT: movd %xmm0, %ecx 444; SSE3-NEXT: pextrw $1, %xmm0, %eax 445; SSE3-NEXT: addl %ecx, %eax 446; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 447; SSE3-NEXT: retq 448; 449; AVX-LABEL: extract_extract_v32i16_add_i16_commute: 450; AVX: # %bb.0: 451; AVX-NEXT: vmovd %xmm0, %ecx 452; AVX-NEXT: vpextrw $1, %xmm0, %eax 453; AVX-NEXT: addl %ecx, %eax 454; AVX-NEXT: # kill: def $ax killed $ax killed $eax 455; AVX-NEXT: vzeroupper 456; AVX-NEXT: retq 457 %x0 = extractelement <32 x i16> %x, i32 0 458 %x1 = extractelement <32 x i16> %x, i32 1 459 %x01 = add i16 %x1, %x0 460 ret i16 %x01 461} 462 463define i32 @extract_extract_v16i32_sub_i32(<16 x i32> %x) { 464; SSE3-LABEL: extract_extract_v16i32_sub_i32: 465; SSE3: # %bb.0: 466; SSE3-NEXT: movd %xmm0, %eax 467; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 468; SSE3-NEXT: movd %xmm0, %ecx 469; SSE3-NEXT: subl %ecx, %eax 470; SSE3-NEXT: retq 471; 472; AVX-LABEL: extract_extract_v16i32_sub_i32: 473; AVX: # %bb.0: 474; AVX-NEXT: vmovd %xmm0, %eax 475; AVX-NEXT: vpextrd $1, %xmm0, %ecx 476; AVX-NEXT: subl %ecx, %eax 477; AVX-NEXT: vzeroupper 478; AVX-NEXT: retq 479 %x0 = extractelement <16 x i32> %x, i32 0 480 %x1 = extractelement <16 x i32> %x, i32 1 481 %x01 = sub i32 %x0, %x1 482 ret i32 %x01 483} 484 485define i32 @extract_extract_v16i32_sub_i32_commute(<16 x i32> %x) { 486; SSE3-LABEL: extract_extract_v16i32_sub_i32_commute: 487; SSE3: # %bb.0: 488; SSE3-NEXT: movd %xmm0, %ecx 489; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 490; SSE3-NEXT: movd %xmm0, %eax 491; SSE3-NEXT: subl %ecx, %eax 492; SSE3-NEXT: retq 493; 494; AVX-LABEL: extract_extract_v16i32_sub_i32_commute: 495; AVX: # %bb.0: 496; AVX-NEXT: vmovd %xmm0, %ecx 497; AVX-NEXT: vpextrd $1, %xmm0, %eax 498; AVX-NEXT: subl %ecx, %eax 499; AVX-NEXT: vzeroupper 500; AVX-NEXT: retq 501 %x0 = extractelement <16 x i32> %x, i32 0 502 %x1 = extractelement <16 x i32> %x, i32 1 503 %x01 = sub i32 %x1, %x0 504 ret i32 %x01 505} 506 507define i16 @extract_extract_v32i16_sub_i16(<32 x i16> %x) { 508; SSE3-LABEL: extract_extract_v32i16_sub_i16: 509; SSE3: # %bb.0: 510; SSE3-NEXT: movd %xmm0, %eax 511; SSE3-NEXT: pextrw $1, %xmm0, %ecx 512; SSE3-NEXT: subl %ecx, %eax 513; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 514; SSE3-NEXT: retq 515; 516; AVX-LABEL: extract_extract_v32i16_sub_i16: 517; AVX: # %bb.0: 518; AVX-NEXT: vmovd %xmm0, %eax 519; AVX-NEXT: vpextrw $1, %xmm0, %ecx 520; AVX-NEXT: subl %ecx, %eax 521; AVX-NEXT: # kill: def $ax killed $ax killed $eax 522; AVX-NEXT: vzeroupper 523; AVX-NEXT: retq 524 %x0 = extractelement <32 x i16> %x, i32 0 525 %x1 = extractelement <32 x i16> %x, i32 1 526 %x01 = sub i16 %x0, %x1 527 ret i16 %x01 528} 529 530define i16 @extract_extract_v32i16_sub_i16_commute(<32 x i16> %x) { 531; SSE3-LABEL: extract_extract_v32i16_sub_i16_commute: 532; SSE3: # %bb.0: 533; SSE3-NEXT: movd %xmm0, %ecx 534; SSE3-NEXT: pextrw $1, %xmm0, %eax 535; SSE3-NEXT: subl %ecx, %eax 536; SSE3-NEXT: # kill: def $ax killed $ax killed $eax 537; SSE3-NEXT: retq 538; 539; AVX-LABEL: extract_extract_v32i16_sub_i16_commute: 540; AVX: # %bb.0: 541; AVX-NEXT: vmovd %xmm0, %ecx 542; AVX-NEXT: vpextrw $1, %xmm0, %eax 543; AVX-NEXT: subl %ecx, %eax 544; AVX-NEXT: # kill: def $ax killed $ax killed $eax 545; AVX-NEXT: vzeroupper 546; AVX-NEXT: retq 547 %x0 = extractelement <32 x i16> %x, i32 0 548 %x1 = extractelement <32 x i16> %x, i32 1 549 %x01 = sub i16 %x1, %x0 550 ret i16 %x01 551} 552 553; Check output when 1 or both extracts have extra uses. 554 555define i32 @extract_extract_v4i32_add_i32_uses1(<4 x i32> %x, i32* %p) { 556; SSE3-LABEL: extract_extract_v4i32_add_i32_uses1: 557; SSE3: # %bb.0: 558; SSE3-NEXT: movd %xmm0, %ecx 559; SSE3-NEXT: movd %xmm0, (%rdi) 560; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 561; SSE3-NEXT: movd %xmm0, %eax 562; SSE3-NEXT: addl %ecx, %eax 563; SSE3-NEXT: retq 564; 565; AVX-LABEL: extract_extract_v4i32_add_i32_uses1: 566; AVX: # %bb.0: 567; AVX-NEXT: vmovd %xmm0, %ecx 568; AVX-NEXT: vmovd %xmm0, (%rdi) 569; AVX-NEXT: vpextrd $1, %xmm0, %eax 570; AVX-NEXT: addl %ecx, %eax 571; AVX-NEXT: retq 572 %x0 = extractelement <4 x i32> %x, i32 0 573 store i32 %x0, i32* %p 574 %x1 = extractelement <4 x i32> %x, i32 1 575 %x01 = add i32 %x0, %x1 576 ret i32 %x01 577} 578 579define i32 @extract_extract_v4i32_add_i32_uses2(<4 x i32> %x, i32* %p) { 580; SSE3-LABEL: extract_extract_v4i32_add_i32_uses2: 581; SSE3: # %bb.0: 582; SSE3-NEXT: movd %xmm0, %ecx 583; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 584; SSE3-NEXT: movd %xmm0, %eax 585; SSE3-NEXT: addl %ecx, %eax 586; SSE3-NEXT: movd %xmm0, (%rdi) 587; SSE3-NEXT: retq 588; 589; AVX-LABEL: extract_extract_v4i32_add_i32_uses2: 590; AVX: # %bb.0: 591; AVX-NEXT: vmovd %xmm0, %ecx 592; AVX-NEXT: vpextrd $1, %xmm0, %eax 593; AVX-NEXT: addl %ecx, %eax 594; AVX-NEXT: vpextrd $1, %xmm0, (%rdi) 595; AVX-NEXT: retq 596 %x0 = extractelement <4 x i32> %x, i32 0 597 %x1 = extractelement <4 x i32> %x, i32 1 598 store i32 %x1, i32* %p 599 %x01 = add i32 %x0, %x1 600 ret i32 %x01 601} 602 603define i32 @extract_extract_v4i32_add_i32_uses3(<4 x i32> %x, i32* %p1, i32* %p2) { 604; SSE3-LABEL: extract_extract_v4i32_add_i32_uses3: 605; SSE3: # %bb.0: 606; SSE3-NEXT: movd %xmm0, %ecx 607; SSE3-NEXT: movd %xmm0, (%rdi) 608; SSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] 609; SSE3-NEXT: movd %xmm0, %eax 610; SSE3-NEXT: addl %ecx, %eax 611; SSE3-NEXT: movd %xmm0, (%rsi) 612; SSE3-NEXT: retq 613; 614; AVX-LABEL: extract_extract_v4i32_add_i32_uses3: 615; AVX: # %bb.0: 616; AVX-NEXT: vmovd %xmm0, %ecx 617; AVX-NEXT: vmovd %xmm0, (%rdi) 618; AVX-NEXT: vpextrd $1, %xmm0, %eax 619; AVX-NEXT: addl %ecx, %eax 620; AVX-NEXT: vpextrd $1, %xmm0, (%rsi) 621; AVX-NEXT: retq 622 %x0 = extractelement <4 x i32> %x, i32 0 623 store i32 %x0, i32* %p1 624 %x1 = extractelement <4 x i32> %x, i32 1 625 store i32 %x1, i32* %p2 626 %x01 = add i32 %x0, %x1 627 ret i32 %x01 628} 629 630