858 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse | FileCheck %s -check-prefixes=SSE,SSE23; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+sse4.1 | FileCheck %s -check-prefixes=SSE,SSE44; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx | FileCheck %s -check-prefixes=AVX,AVX15; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=+avx2 | FileCheck %s -check-prefixes=AVX,AVX26; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=x86-64-v4 | FileCheck %s -check-prefixes=AVX,AVX5127 8; Verify that each of the following test cases is folded into a single9; instruction which performs a blend operation.10 11define <2 x i64> @test1(<2 x i64> %a, <2 x i64> %b) {12; SSE2-LABEL: test1:13; SSE2: # %bb.0:14; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]15; SSE2-NEXT: retq16;17; SSE4-LABEL: test1:18; SSE4: # %bb.0:19; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]20; SSE4-NEXT: retq21;22; AVX-LABEL: test1:23; AVX: # %bb.0:24; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]25; AVX-NEXT: retq26 %shuf1 = shufflevector <2 x i64> %a, <2 x i64> zeroinitializer, <2 x i32><i32 0, i32 2>27 %shuf2 = shufflevector <2 x i64> %b, <2 x i64> zeroinitializer, <2 x i32><i32 2, i32 1>28 %or = or <2 x i64> %shuf1, %shuf229 ret <2 x i64> %or30}31 32 33define <4 x i32> @test2(<4 x i32> %a, <4 x i32> %b) {34; SSE-LABEL: test2:35; SSE: # %bb.0:36; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]37; SSE-NEXT: retq38;39; AVX-LABEL: test2:40; AVX: # %bb.0:41; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]42; AVX-NEXT: retq43 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 4, i32 2, i32 3>44 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 1, i32 4, i32 4>45 %or = or <4 x i32> %shuf1, %shuf246 ret <4 x i32> %or47}48 49 50define <2 x i64> @test3(<2 x i64> %a, <2 x i64> %b) {51; SSE-LABEL: test3:52; SSE: # %bb.0:53; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]54; SSE-NEXT: retq55;56; AVX-LABEL: test3:57; AVX: # %bb.0:58; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]59; AVX-NEXT: retq60 %shuf1 = shufflevector <2 x i64> %a, <2 x i64> zeroinitializer, <2 x i32><i32 2, i32 1>61 %shuf2 = shufflevector <2 x i64> %b, <2 x i64> zeroinitializer, <2 x i32><i32 0, i32 2>62 %or = or <2 x i64> %shuf1, %shuf263 ret <2 x i64> %or64}65 66 67define <4 x i32> @test4(<4 x i32> %a, <4 x i32> %b) {68; SSE2-LABEL: test4:69; SSE2: # %bb.0:70; SSE2-NEXT: movss {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3]71; SSE2-NEXT: movaps %xmm1, %xmm072; SSE2-NEXT: retq73;74; SSE4-LABEL: test4:75; SSE4: # %bb.0:76; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]77; SSE4-NEXT: retq78;79; AVX1-LABEL: test4:80; AVX1: # %bb.0:81; AVX1-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]82; AVX1-NEXT: retq83;84; AVX2-LABEL: test4:85; AVX2: # %bb.0:86; AVX2-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]87; AVX2-NEXT: retq88;89; AVX512-LABEL: test4:90; AVX512: # %bb.0:91; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]92; AVX512-NEXT: retq93 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 4, i32 4, i32 4>94 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 1, i32 2, i32 3>95 %or = or <4 x i32> %shuf1, %shuf296 ret <4 x i32> %or97}98 99 100define <4 x i32> @test5(<4 x i32> %a, <4 x i32> %b) {101; SSE-LABEL: test5:102; SSE: # %bb.0:103; SSE-NEXT: movss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]104; SSE-NEXT: retq105;106; AVX1-LABEL: test5:107; AVX1: # %bb.0:108; AVX1-NEXT: vmovss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]109; AVX1-NEXT: retq110;111; AVX2-LABEL: test5:112; AVX2: # %bb.0:113; AVX2-NEXT: vmovss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]114; AVX2-NEXT: retq115;116; AVX512-LABEL: test5:117; AVX512: # %bb.0:118; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]119; AVX512-NEXT: retq120 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 1, i32 2, i32 3>121 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 4, i32 4, i32 4>122 %or = or <4 x i32> %shuf1, %shuf2123 ret <4 x i32> %or124}125 126 127define <4 x i32> @test6(<4 x i32> %a, <4 x i32> %b) {128; SSE2-LABEL: test6:129; SSE2: # %bb.0:130; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]131; SSE2-NEXT: retq132;133; SSE4-LABEL: test6:134; SSE4: # %bb.0:135; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]136; SSE4-NEXT: retq137;138; AVX-LABEL: test6:139; AVX: # %bb.0:140; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]141; AVX-NEXT: retq142 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 1, i32 4, i32 4>143 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 4, i32 2, i32 3>144 %or = or <4 x i32> %shuf1, %shuf2145 ret <4 x i32> %or146}147 148 149define <4 x i32> @test7(<4 x i32> %a, <4 x i32> %b) {150; SSE2-LABEL: test7:151; SSE2: # %bb.0:152; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]153; SSE2-NEXT: retq154;155; SSE4-LABEL: test7:156; SSE4: # %bb.0:157; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]158; SSE4-NEXT: retq159;160; AVX-LABEL: test7:161; AVX: # %bb.0:162; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]163; AVX-NEXT: retq164 %and1 = and <4 x i32> %a, <i32 -1, i32 -1, i32 0, i32 0>165 %and2 = and <4 x i32> %b, <i32 0, i32 0, i32 -1, i32 -1>166 %or = or <4 x i32> %and1, %and2167 ret <4 x i32> %or168}169 170 171define <2 x i64> @test8(<2 x i64> %a, <2 x i64> %b) {172; SSE2-LABEL: test8:173; SSE2: # %bb.0:174; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]175; SSE2-NEXT: retq176;177; SSE4-LABEL: test8:178; SSE4: # %bb.0:179; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]180; SSE4-NEXT: retq181;182; AVX-LABEL: test8:183; AVX: # %bb.0:184; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3]185; AVX-NEXT: retq186 %and1 = and <2 x i64> %a, <i64 -1, i64 0>187 %and2 = and <2 x i64> %b, <i64 0, i64 -1>188 %or = or <2 x i64> %and1, %and2189 ret <2 x i64> %or190}191 192 193define <4 x i32> @test9(<4 x i32> %a, <4 x i32> %b) {194; SSE-LABEL: test9:195; SSE: # %bb.0:196; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]197; SSE-NEXT: retq198;199; AVX-LABEL: test9:200; AVX: # %bb.0:201; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]202; AVX-NEXT: retq203 %and1 = and <4 x i32> %a, <i32 0, i32 0, i32 -1, i32 -1>204 %and2 = and <4 x i32> %b, <i32 -1, i32 -1, i32 0, i32 0>205 %or = or <4 x i32> %and1, %and2206 ret <4 x i32> %or207}208 209 210define <2 x i64> @test10(<2 x i64> %a, <2 x i64> %b) {211; SSE-LABEL: test10:212; SSE: # %bb.0:213; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]214; SSE-NEXT: retq215;216; AVX-LABEL: test10:217; AVX: # %bb.0:218; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]219; AVX-NEXT: retq220 %and1 = and <2 x i64> %a, <i64 0, i64 -1>221 %and2 = and <2 x i64> %b, <i64 -1, i64 0>222 %or = or <2 x i64> %and1, %and2223 ret <2 x i64> %or224}225 226 227define <4 x i32> @test11(<4 x i32> %a, <4 x i32> %b) {228; SSE2-LABEL: test11:229; SSE2: # %bb.0:230; SSE2-NEXT: movss {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3]231; SSE2-NEXT: movaps %xmm1, %xmm0232; SSE2-NEXT: retq233;234; SSE4-LABEL: test11:235; SSE4: # %bb.0:236; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]237; SSE4-NEXT: retq238;239; AVX1-LABEL: test11:240; AVX1: # %bb.0:241; AVX1-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]242; AVX1-NEXT: retq243;244; AVX2-LABEL: test11:245; AVX2: # %bb.0:246; AVX2-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]247; AVX2-NEXT: retq248;249; AVX512-LABEL: test11:250; AVX512: # %bb.0:251; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]252; AVX512-NEXT: retq253 %and1 = and <4 x i32> %a, <i32 -1, i32 0, i32 0, i32 0>254 %and2 = and <4 x i32> %b, <i32 0, i32 -1, i32 -1, i32 -1>255 %or = or <4 x i32> %and1, %and2256 ret <4 x i32> %or257}258 259 260define <4 x i32> @test12(<4 x i32> %a, <4 x i32> %b) {261; SSE-LABEL: test12:262; SSE: # %bb.0:263; SSE-NEXT: movss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]264; SSE-NEXT: retq265;266; AVX1-LABEL: test12:267; AVX1: # %bb.0:268; AVX1-NEXT: vmovss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]269; AVX1-NEXT: retq270;271; AVX2-LABEL: test12:272; AVX2: # %bb.0:273; AVX2-NEXT: vmovss {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]274; AVX2-NEXT: retq275;276; AVX512-LABEL: test12:277; AVX512: # %bb.0:278; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]279; AVX512-NEXT: retq280 %and1 = and <4 x i32> %a, <i32 0, i32 -1, i32 -1, i32 -1>281 %and2 = and <4 x i32> %b, <i32 -1, i32 0, i32 0, i32 0>282 %or = or <4 x i32> %and1, %and2283 ret <4 x i32> %or284}285 286 287; Verify that the following test cases are folded into single shuffles.288 289define <4 x i32> @test13(<4 x i32> %a, <4 x i32> %b) {290; SSE-LABEL: test13:291; SSE: # %bb.0:292; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1],xmm1[2,3]293; SSE-NEXT: retq294;295; AVX-LABEL: test13:296; AVX: # %bb.0:297; AVX-NEXT: vshufps {{.*#+}} xmm0 = xmm0[1,1],xmm1[2,3]298; AVX-NEXT: retq299 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 1, i32 1, i32 4, i32 4>300 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 4, i32 2, i32 3>301 %or = or <4 x i32> %shuf1, %shuf2302 ret <4 x i32> %or303}304 305 306define <2 x i64> @test14(<2 x i64> %a, <2 x i64> %b) {307; SSE-LABEL: test14:308; SSE: # %bb.0:309; SSE-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]310; SSE-NEXT: retq311;312; AVX-LABEL: test14:313; AVX: # %bb.0:314; AVX-NEXT: vmovlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]315; AVX-NEXT: retq316 %shuf1 = shufflevector <2 x i64> %a, <2 x i64> zeroinitializer, <2 x i32><i32 0, i32 2>317 %shuf2 = shufflevector <2 x i64> %b, <2 x i64> zeroinitializer, <2 x i32><i32 2, i32 0>318 %or = or <2 x i64> %shuf1, %shuf2319 ret <2 x i64> %or320}321 322 323define <4 x i32> @test15(<4 x i32> %a, <4 x i32> %b) {324; SSE-LABEL: test15:325; SSE: # %bb.0:326; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[2,1],xmm0[2,1]327; SSE-NEXT: movaps %xmm1, %xmm0328; SSE-NEXT: retq329;330; AVX-LABEL: test15:331; AVX: # %bb.0:332; AVX-NEXT: vshufps {{.*#+}} xmm0 = xmm1[2,1],xmm0[2,1]333; AVX-NEXT: retq334 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 4, i32 2, i32 1>335 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 2, i32 1, i32 4, i32 4>336 %or = or <4 x i32> %shuf1, %shuf2337 ret <4 x i32> %or338}339 340 341define <2 x i64> @test16(<2 x i64> %a, <2 x i64> %b) {342; SSE-LABEL: test16:343; SSE: # %bb.0:344; SSE-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm0[0]345; SSE-NEXT: movaps %xmm1, %xmm0346; SSE-NEXT: retq347;348; AVX-LABEL: test16:349; AVX: # %bb.0:350; AVX-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0]351; AVX-NEXT: retq352 %shuf1 = shufflevector <2 x i64> %a, <2 x i64> zeroinitializer, <2 x i32><i32 2, i32 0>353 %shuf2 = shufflevector <2 x i64> %b, <2 x i64> zeroinitializer, <2 x i32><i32 0, i32 2>354 %or = or <2 x i64> %shuf1, %shuf2355 ret <2 x i64> %or356}357 358 359; Verify that the dag-combiner does not fold a OR of two shuffles into a single360; shuffle instruction when the shuffle indexes are not compatible.361 362define <4 x i32> @test17(<4 x i32> %a, <4 x i32> %b) {363; SSE-LABEL: test17:364; SSE: # %bb.0:365; SSE-NEXT: psllq $32, %xmm0366; SSE-NEXT: movq {{.*#+}} xmm1 = xmm1[0],zero367; SSE-NEXT: por %xmm1, %xmm0368; SSE-NEXT: retq369;370; AVX-LABEL: test17:371; AVX: # %bb.0:372; AVX-NEXT: vpsllq $32, %xmm0, %xmm0373; AVX-NEXT: vmovq {{.*#+}} xmm1 = xmm1[0],zero374; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0375; AVX-NEXT: retq376 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 0, i32 4, i32 2>377 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 1, i32 4, i32 4>378 %or = or <4 x i32> %shuf1, %shuf2379 ret <4 x i32> %or380}381 382 383define <4 x i32> @test18(<4 x i32> %a, <4 x i32> %b) {384; SSE2-LABEL: test18:385; SSE2: # %bb.0:386; SSE2-NEXT: xorps %xmm2, %xmm2387; SSE2-NEXT: xorps %xmm3, %xmm3388; SSE2-NEXT: movss {{.*#+}} xmm3 = xmm0[0],xmm3[1,2,3]389; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[1,0,1,1]390; SSE2-NEXT: movss {{.*#+}} xmm2 = xmm1[0],xmm2[1,2,3]391; SSE2-NEXT: orps %xmm0, %xmm2392; SSE2-NEXT: movaps %xmm2, %xmm0393; SSE2-NEXT: retq394;395; SSE4-LABEL: test18:396; SSE4: # %bb.0:397; SSE4-NEXT: pxor %xmm2, %xmm2398; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3,4,5,6,7]399; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,0,1,1]400; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm1[0,1],xmm2[2,3,4,5,6,7]401; SSE4-NEXT: por %xmm0, %xmm2402; SSE4-NEXT: movdqa %xmm2, %xmm0403; SSE4-NEXT: retq404;405; AVX1-LABEL: test18:406; AVX1: # %bb.0:407; AVX1-NEXT: vxorps %xmm2, %xmm2, %xmm2408; AVX1-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm2[1,2,3]409; AVX1-NEXT: vshufps {{.*#+}} xmm0 = xmm0[1,0,1,1]410; AVX1-NEXT: vmovss {{.*#+}} xmm1 = xmm1[0],xmm2[1,2,3]411; AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0412; AVX1-NEXT: retq413;414; AVX2-LABEL: test18:415; AVX2: # %bb.0:416; AVX2-NEXT: vxorps %xmm2, %xmm2, %xmm2417; AVX2-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm2[1,2,3]418; AVX2-NEXT: vshufps {{.*#+}} xmm0 = xmm0[1,0,1,1]419; AVX2-NEXT: vmovss {{.*#+}} xmm1 = xmm1[0],xmm2[1,2,3]420; AVX2-NEXT: vorps %xmm1, %xmm0, %xmm0421; AVX2-NEXT: retq422;423; AVX512-LABEL: test18:424; AVX512: # %bb.0:425; AVX512-NEXT: vpshufb {{.*#+}} xmm0 = zero,zero,zero,zero,xmm0[0,1,2,3],zero,zero,zero,zero,zero,zero,zero,zero426; AVX512-NEXT: vpxor %xmm2, %xmm2, %xmm2427; AVX512-NEXT: vpblendd {{.*#+}} xmm1 = xmm1[0],xmm2[1,2,3]428; AVX512-NEXT: vpor %xmm1, %xmm0, %xmm0429; AVX512-NEXT: retq430 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 0, i32 4, i32 4>431 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 4, i32 4, i32 4>432 %or = or <4 x i32> %shuf1, %shuf2433 ret <4 x i32> %or434}435 436 437define <4 x i32> @test19(<4 x i32> %a, <4 x i32> %b) {438; SSE2-LABEL: test19:439; SSE2: # %bb.0:440; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,3,2,3]441; SSE2-NEXT: pxor %xmm2, %xmm2442; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]443; SSE2-NEXT: movdqa %xmm1, %xmm0444; SSE2-NEXT: pslldq {{.*#+}} xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]445; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[2,0],xmm1[2,2]446; SSE2-NEXT: orps %xmm2, %xmm0447; SSE2-NEXT: retq448;449; SSE4-LABEL: test19:450; SSE4: # %bb.0:451; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm0[0,0,2,3]452; SSE4-NEXT: pxor %xmm3, %xmm3453; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm3[0,1],xmm2[2,3],xmm3[4,5],xmm2[6,7]454; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,1,2,2]455; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5,6,7]456; SSE4-NEXT: por %xmm2, %xmm0457; SSE4-NEXT: retq458;459; AVX1-LABEL: test19:460; AVX1: # %bb.0:461; AVX1-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,0,2,3]462; AVX1-NEXT: vxorps %xmm2, %xmm2, %xmm2463; AVX1-NEXT: vblendps {{.*#+}} xmm0 = xmm2[0],xmm0[1],xmm2[2],xmm0[3]464; AVX1-NEXT: vshufps {{.*#+}} xmm1 = xmm1[0,1,2,2]465; AVX1-NEXT: vblendps {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2,3]466; AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0467; AVX1-NEXT: retq468;469; AVX2-LABEL: test19:470; AVX2: # %bb.0:471; AVX2-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,0,2,3]472; AVX2-NEXT: vxorps %xmm2, %xmm2, %xmm2473; AVX2-NEXT: vblendps {{.*#+}} xmm0 = xmm2[0],xmm0[1],xmm2[2],xmm0[3]474; AVX2-NEXT: vshufps {{.*#+}} xmm1 = xmm1[0,1,2,2]475; AVX2-NEXT: vblendps {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2,3]476; AVX2-NEXT: vorps %xmm1, %xmm0, %xmm0477; AVX2-NEXT: retq478;479; AVX512-LABEL: test19:480; AVX512: # %bb.0:481; AVX512-NEXT: vpshufb {{.*#+}} xmm0 = zero,zero,zero,zero,xmm0[0,1,2,3],zero,zero,zero,zero,xmm0[12,13,14,15]482; AVX512-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[0,1,2,3],zero,zero,zero,zero,xmm1[8,9,10,11,8,9,10,11]483; AVX512-NEXT: vpor %xmm1, %xmm0, %xmm0484; AVX512-NEXT: retq485 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 0, i32 4, i32 3>486 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 4, i32 2, i32 2>487 %or = or <4 x i32> %shuf1, %shuf2488 ret <4 x i32> %or489}490 491 492define <2 x i64> @test20(<2 x i64> %a, <2 x i64> %b) {493; SSE-LABEL: test20:494; SSE: # %bb.0:495; SSE-NEXT: por %xmm1, %xmm0496; SSE-NEXT: movq {{.*#+}} xmm0 = xmm0[0],zero497; SSE-NEXT: retq498;499; AVX-LABEL: test20:500; AVX: # %bb.0:501; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0502; AVX-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero503; AVX-NEXT: retq504 %shuf1 = shufflevector <2 x i64> %a, <2 x i64> zeroinitializer, <2 x i32><i32 0, i32 2>505 %shuf2 = shufflevector <2 x i64> %b, <2 x i64> zeroinitializer, <2 x i32><i32 0, i32 2>506 %or = or <2 x i64> %shuf1, %shuf2507 ret <2 x i64> %or508}509 510 511define <2 x i64> @test21(<2 x i64> %a, <2 x i64> %b) {512; SSE-LABEL: test21:513; SSE: # %bb.0:514; SSE-NEXT: por %xmm1, %xmm0515; SSE-NEXT: pslldq {{.*#+}} xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]516; SSE-NEXT: retq517;518; AVX1-LABEL: test21:519; AVX1: # %bb.0:520; AVX1-NEXT: vpor %xmm1, %xmm0, %xmm0521; AVX1-NEXT: vpslldq {{.*#+}} xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]522; AVX1-NEXT: retq523;524; AVX2-LABEL: test21:525; AVX2: # %bb.0:526; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm0527; AVX2-NEXT: vpslldq {{.*#+}} xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]528; AVX2-NEXT: retq529;530; AVX512-LABEL: test21:531; AVX512: # %bb.0:532; AVX512-NEXT: vorpd %xmm1, %xmm0, %xmm0533; AVX512-NEXT: vpslldq {{.*#+}} xmm0 = zero,zero,zero,zero,zero,zero,zero,zero,xmm0[0,1,2,3,4,5,6,7]534; AVX512-NEXT: retq535 %shuf1 = shufflevector <2 x i64> %a, <2 x i64> zeroinitializer, <2 x i32><i32 2, i32 0>536 %shuf2 = shufflevector <2 x i64> %b, <2 x i64> zeroinitializer, <2 x i32><i32 2, i32 0>537 %or = or <2 x i64> %shuf1, %shuf2538 ret <2 x i64> %or539}540 541 542; Verify that the dag-combiner keeps the correct domain for float/double vectors543; bitcast to use the mask-or blend combine.544 545define <2 x double> @test22(<2 x double> %a0, <2 x double> %a1) {546; SSE-LABEL: test22:547; SSE: # %bb.0:548; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]549; SSE-NEXT: retq550;551; AVX1-LABEL: test22:552; AVX1: # %bb.0:553; AVX1-NEXT: vmovsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]554; AVX1-NEXT: retq555;556; AVX2-LABEL: test22:557; AVX2: # %bb.0:558; AVX2-NEXT: vmovsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]559; AVX2-NEXT: retq560;561; AVX512-LABEL: test22:562; AVX512: # %bb.0:563; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]564; AVX512-NEXT: retq565 %bc1 = bitcast <2 x double> %a0 to <2 x i64>566 %bc2 = bitcast <2 x double> %a1 to <2 x i64>567 %and1 = and <2 x i64> %bc1, <i64 0, i64 -1>568 %and2 = and <2 x i64> %bc2, <i64 -1, i64 0>569 %or = or <2 x i64> %and1, %and2570 %bc3 = bitcast <2 x i64> %or to <2 x double>571 ret <2 x double> %bc3572}573 574 575define <4 x float> @test23(<4 x float> %a0, <4 x float> %a1) {576; SSE2-LABEL: test23:577; SSE2: # %bb.0:578; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,2],xmm1[0,3]579; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[2,0,1,3]580; SSE2-NEXT: retq581;582; SSE4-LABEL: test23:583; SSE4: # %bb.0:584; SSE4-NEXT: blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2],xmm1[3]585; SSE4-NEXT: retq586;587; AVX-LABEL: test23:588; AVX: # %bb.0:589; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2],xmm1[3]590; AVX-NEXT: retq591 %bc1 = bitcast <4 x float> %a0 to <4 x i32>592 %bc2 = bitcast <4 x float> %a1 to <4 x i32>593 %and1 = and <4 x i32> %bc1, <i32 0, i32 -1, i32 -1, i32 0>594 %and2 = and <4 x i32> %bc2, <i32 -1, i32 0, i32 0, i32 -1>595 %or = or <4 x i32> %and1, %and2596 %bc3 = bitcast <4 x i32> %or to <4 x float>597 ret <4 x float> %bc3598}599 600 601define <4 x float> @test24(<4 x float> %a0, <4 x float> %a1) {602; SSE-LABEL: test24:603; SSE: # %bb.0:604; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]605; SSE-NEXT: retq606;607; AVX1-LABEL: test24:608; AVX1: # %bb.0:609; AVX1-NEXT: vmovsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]610; AVX1-NEXT: retq611;612; AVX2-LABEL: test24:613; AVX2: # %bb.0:614; AVX2-NEXT: vmovsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]615; AVX2-NEXT: retq616;617; AVX512-LABEL: test24:618; AVX512: # %bb.0:619; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]620; AVX512-NEXT: retq621 %bc1 = bitcast <4 x float> %a0 to <2 x i64>622 %bc2 = bitcast <4 x float> %a1 to <2 x i64>623 %and1 = and <2 x i64> %bc1, <i64 0, i64 -1>624 %and2 = and <2 x i64> %bc2, <i64 -1, i64 0>625 %or = or <2 x i64> %and1, %and2626 %bc3 = bitcast <2 x i64> %or to <4 x float>627 ret <4 x float> %bc3628}629 630 631define <4 x float> @test25(<4 x float> %a0) {632; SSE2-LABEL: test25:633; SSE2: # %bb.0:634; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,2],mem[0,3]635; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[2,0,1,3]636; SSE2-NEXT: retq637;638; SSE4-LABEL: test25:639; SSE4: # %bb.0:640; SSE4-NEXT: blendps {{.*#+}} xmm0 = mem[0],xmm0[1,2],mem[3]641; SSE4-NEXT: retq642;643; AVX1-LABEL: test25:644; AVX1: # %bb.0:645; AVX1-NEXT: vblendps {{.*#+}} xmm0 = mem[0],xmm0[1,2],mem[3]646; AVX1-NEXT: retq647;648; AVX2-LABEL: test25:649; AVX2: # %bb.0:650; AVX2-NEXT: vbroadcastss {{.*#+}} xmm1 = [1.0E+0,1.0E+0,1.0E+0,1.0E+0]651; AVX2-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2],xmm1[3]652; AVX2-NEXT: retq653;654; AVX512-LABEL: test25:655; AVX512: # %bb.0:656; AVX512-NEXT: vbroadcastss {{.*#+}} xmm1 = [1.0E+0,1.0E+0,1.0E+0,1.0E+0]657; AVX512-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2],xmm1[3]658; AVX512-NEXT: retq659 %bc1 = bitcast <4 x float> %a0 to <4 x i32>660 %bc2 = bitcast <4 x float> <float 1.0, float 1.0, float 1.0, float 1.0> to <4 x i32>661 %and1 = and <4 x i32> %bc1, <i32 0, i32 -1, i32 -1, i32 0>662 %and2 = and <4 x i32> %bc2, <i32 -1, i32 0, i32 0, i32 -1>663 %or = or <4 x i32> %and1, %and2664 %bc3 = bitcast <4 x i32> %or to <4 x float>665 ret <4 x float> %bc3666}667 668 669; Verify that the DAGCombiner doesn't crash in the attempt to check if a shuffle670; with illegal type has a legal mask. Method 'isShuffleMaskLegal' only knows how to671; handle legal vector value types.672define <4 x i8> @test_crash(<4 x i8> %a, <4 x i8> %b) {673; SSE2-LABEL: test_crash:674; SSE2: # %bb.0:675; SSE2-NEXT: movaps {{.*#+}} xmm2 = [65535,0,65535,65535,65535,65535,65535,65535]676; SSE2-NEXT: andps %xmm2, %xmm1677; SSE2-NEXT: andnps %xmm0, %xmm2678; SSE2-NEXT: orps %xmm1, %xmm2679; SSE2-NEXT: movaps %xmm2, %xmm0680; SSE2-NEXT: retq681;682; SSE4-LABEL: test_crash:683; SSE4: # %bb.0:684; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2,3,4,5,6,7]685; SSE4-NEXT: retq686;687; AVX-LABEL: test_crash:688; AVX: # %bb.0:689; AVX-NEXT: vpblendw {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2,3,4,5,6,7]690; AVX-NEXT: retq691 %shuf1 = shufflevector <4 x i8> %a, <4 x i8> zeroinitializer, <4 x i32><i32 4, i32 4, i32 2, i32 3>692 %shuf2 = shufflevector <4 x i8> %b, <4 x i8> zeroinitializer, <4 x i32><i32 0, i32 1, i32 4, i32 4>693 %or = or <4 x i8> %shuf1, %shuf2694 ret <4 x i8> %or695}696 697; Verify that we can fold regardless of which operand is the zeroinitializer698 699define <4 x i32> @test2b(<4 x i32> %a, <4 x i32> %b) {700; SSE-LABEL: test2b:701; SSE: # %bb.0:702; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]703; SSE-NEXT: retq704;705; AVX-LABEL: test2b:706; AVX: # %bb.0:707; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]708; AVX-NEXT: retq709 %shuf1 = shufflevector <4 x i32> zeroinitializer, <4 x i32> %a, <4 x i32><i32 0, i32 0, i32 6, i32 7>710 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> zeroinitializer, <4 x i32><i32 0, i32 1, i32 4, i32 4>711 %or = or <4 x i32> %shuf1, %shuf2712 ret <4 x i32> %or713}714 715define <4 x i32> @test2c(<4 x i32> %a, <4 x i32> %b) {716; SSE-LABEL: test2c:717; SSE: # %bb.0:718; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]719; SSE-NEXT: retq720;721; AVX-LABEL: test2c:722; AVX: # %bb.0:723; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]724; AVX-NEXT: retq725 %shuf1 = shufflevector <4 x i32> zeroinitializer, <4 x i32> %a, <4 x i32><i32 0, i32 0, i32 6, i32 7>726 %shuf2 = shufflevector <4 x i32> zeroinitializer, <4 x i32> %b, <4 x i32><i32 4, i32 5, i32 0, i32 0>727 %or = or <4 x i32> %shuf1, %shuf2728 ret <4 x i32> %or729}730 731 732define <4 x i32> @test2d(<4 x i32> %a, <4 x i32> %b) {733; SSE-LABEL: test2d:734; SSE: # %bb.0:735; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]736; SSE-NEXT: retq737;738; AVX-LABEL: test2d:739; AVX: # %bb.0:740; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]741; AVX-NEXT: retq742 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> zeroinitializer, <4 x i32><i32 4, i32 4, i32 2, i32 3>743 %shuf2 = shufflevector <4 x i32> zeroinitializer, <4 x i32> %b, <4 x i32><i32 4, i32 5, i32 0, i32 0>744 %or = or <4 x i32> %shuf1, %shuf2745 ret <4 x i32> %or746}747 748; Make sure we can have an undef where an index pointing to the zero vector should be749 750define <4 x i32> @test2e(<4 x i32> %a, <4 x i32> %b) {751; SSE-LABEL: test2e:752; SSE: # %bb.0:753; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]754; SSE-NEXT: retq755;756; AVX-LABEL: test2e:757; AVX: # %bb.0:758; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]759; AVX-NEXT: retq760 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>, <4 x i32><i32 undef, i32 4, i32 2, i32 3>761 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>, <4 x i32><i32 0, i32 1, i32 4, i32 4>762 %or = or <4 x i32> %shuf1, %shuf2763 ret <4 x i32> %or764}765 766define <4 x i32> @test2f(<4 x i32> %a, <4 x i32> %b) {767; SSE-LABEL: test2f:768; SSE: # %bb.0:769; SSE-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1]770; SSE-NEXT: retq771;772; AVX-LABEL: test2f:773; AVX: # %bb.0:774; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3]775; AVX-NEXT: retq776 %shuf1 = shufflevector <4 x i32> %a, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>, <4 x i32><i32 4, i32 4, i32 2, i32 3>777 %shuf2 = shufflevector <4 x i32> %b, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>, <4 x i32><i32 undef, i32 1, i32 4, i32 4>778 %or = or <4 x i32> %shuf1, %shuf2779 ret <4 x i32> %or780}781 782; (or (and X, c1), c2) -> (and (or X, c2), c1|c2) iff (c1 & c2) != 0783 784define <2 x i64> @or_and_v2i64(<2 x i64> %a0) {785; SSE-LABEL: or_and_v2i64:786; SSE: # %bb.0:787; SSE-NEXT: orps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0788; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0789; SSE-NEXT: retq790;791; AVX1-LABEL: or_and_v2i64:792; AVX1: # %bb.0:793; AVX1-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0794; AVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0795; AVX1-NEXT: retq796;797; AVX2-LABEL: or_and_v2i64:798; AVX2: # %bb.0:799; AVX2-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0800; AVX2-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0801; AVX2-NEXT: retq802;803; AVX512-LABEL: or_and_v2i64:804; AVX512: # %bb.0:805; AVX512-NEXT: vpbroadcastq {{.*#+}} xmm1 = [7,7]806; AVX512-NEXT: vpternlogq {{.*#+}} xmm0 = xmm1 & (xmm0 | m64bcst)807; AVX512-NEXT: retq808 %1 = and <2 x i64> %a0, <i64 7, i64 7>809 %2 = or <2 x i64> %1, <i64 3, i64 3>810 ret <2 x i64> %2811}812 813define <4 x i32> @or_and_v4i32(<4 x i32> %a0) {814; SSE-LABEL: or_and_v4i32:815; SSE: # %bb.0:816; SSE-NEXT: orps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0817; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0818; SSE-NEXT: retq819;820; AVX1-LABEL: or_and_v4i32:821; AVX1: # %bb.0:822; AVX1-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0823; AVX1-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0824; AVX1-NEXT: retq825;826; AVX2-LABEL: or_and_v4i32:827; AVX2: # %bb.0:828; AVX2-NEXT: vorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0829; AVX2-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0830; AVX2-NEXT: retq831;832; AVX512-LABEL: or_and_v4i32:833; AVX512: # %bb.0:834; AVX512-NEXT: vmovdqa {{.*#+}} xmm1 = [3,3,15,7]835; AVX512-NEXT: vpternlogd {{.*#+}} xmm0 = xmm1 & (xmm0 | mem)836; AVX512-NEXT: retq837 %1 = and <4 x i32> %a0, <i32 1, i32 3, i32 5, i32 7>838 %2 = or <4 x i32> %1, <i32 3, i32 2, i32 15, i32 2>839 ret <4 x i32> %2840}841 842; If all masked bits are going to be set, that's a constant fold.843 844define <4 x i32> @or_and_v4i32_fold(<4 x i32> %a0) {845; SSE-LABEL: or_and_v4i32_fold:846; SSE: # %bb.0:847; SSE-NEXT: movaps {{.*#+}} xmm0 = [3,3,3,3]848; SSE-NEXT: retq849;850; AVX-LABEL: or_and_v4i32_fold:851; AVX: # %bb.0:852; AVX-NEXT: vbroadcastss {{.*#+}} xmm0 = [3,3,3,3]853; AVX-NEXT: retq854 %1 = and <4 x i32> %a0, <i32 1, i32 1, i32 1, i32 1>855 %2 = or <4 x i32> %1, <i32 3, i32 3, i32 3, i32 3>856 ret <4 x i32> %2857}858