323 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefix=SSE3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=AVX4 5; First, check the generic pattern for any 2 vector constants. Then, check special cases where6; the constants are all off-by-one. Finally, check the extra special cases where the constants7; include 0 or -1.8; Each minimal select test is repeated with a more typical pattern that includes a compare to9; generate the condition value.10 11; TODO: If we don't have blendv, this can definitely be improved. There's also a selection of12; chips where it makes sense to transform the general case blendv to 2 bit-ops. That should be13; a uarch-specfic transform. At some point (Ryzen?), the implementation should catch up to the14; architecture, so blendv is as fast as a single bit-op.15 16define <4 x i32> @sel_C1_or_C2_vec(<4 x i1> %cond) {17; SSE-LABEL: sel_C1_or_C2_vec:18; SSE: # %bb.0:19; SSE-NEXT: pslld $31, %xmm020; SSE-NEXT: psrad $31, %xmm021; SSE-NEXT: movdqa %xmm0, %xmm122; SSE-NEXT: pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm123; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm024; SSE-NEXT: por %xmm1, %xmm025; SSE-NEXT: retq26;27; AVX-LABEL: sel_C1_or_C2_vec:28; AVX: # %bb.0:29; AVX-NEXT: vpslld $31, %xmm0, %xmm030; AVX-NEXT: vmovaps {{.*#+}} xmm1 = [42,0,4294967294,4294967295]31; AVX-NEXT: vblendvps %xmm0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm032; AVX-NEXT: retq33 %add = select <4 x i1> %cond, <4 x i32> <i32 3000, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>34 ret <4 x i32> %add35}36 37define <4 x i32> @cmp_sel_C1_or_C2_vec(<4 x i32> %x, <4 x i32> %y) {38; SSE-LABEL: cmp_sel_C1_or_C2_vec:39; SSE: # %bb.0:40; SSE-NEXT: pcmpeqd %xmm1, %xmm041; SSE-NEXT: movdqa %xmm0, %xmm142; SSE-NEXT: pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm143; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm044; SSE-NEXT: por %xmm1, %xmm045; SSE-NEXT: retq46;47; AVX-LABEL: cmp_sel_C1_or_C2_vec:48; AVX: # %bb.0:49; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm050; AVX-NEXT: vmovaps {{.*#+}} xmm1 = [42,0,4294967294,4294967295]51; AVX-NEXT: vblendvps %xmm0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm052; AVX-NEXT: retq53 %cond = icmp eq <4 x i32> %x, %y54 %add = select <4 x i1> %cond, <4 x i32> <i32 3000, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>55 ret <4 x i32> %add56}57 58define <4 x i32> @sel_Cplus1_or_C_vec(<4 x i1> %cond) {59; SSE-LABEL: sel_Cplus1_or_C_vec:60; SSE: # %bb.0:61; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm062; SSE-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm063; SSE-NEXT: retq64;65; AVX-LABEL: sel_Cplus1_or_C_vec:66; AVX: # %bb.0:67; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm068; AVX-NEXT: vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm069; AVX-NEXT: retq70 %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>71 ret <4 x i32> %add72}73 74define <4 x i32> @cmp_sel_Cplus1_or_C_vec(<4 x i32> %x, <4 x i32> %y) {75; SSE-LABEL: cmp_sel_Cplus1_or_C_vec:76; SSE: # %bb.0:77; SSE-NEXT: pcmpeqd %xmm1, %xmm078; SSE-NEXT: movdqa {{.*#+}} xmm1 = [42,0,4294967294,4294967295]79; SSE-NEXT: psubd %xmm0, %xmm180; SSE-NEXT: movdqa %xmm1, %xmm081; SSE-NEXT: retq82;83; AVX-LABEL: cmp_sel_Cplus1_or_C_vec:84; AVX: # %bb.0:85; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm086; AVX-NEXT: vpmovsxbq {{.*#+}} xmm1 = [42,18446744073709551614]87; AVX-NEXT: vpsubd %xmm0, %xmm1, %xmm088; AVX-NEXT: retq89 %cond = icmp eq <4 x i32> %x, %y90 %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>91 ret <4 x i32> %add92}93 94define <4 x i32> @sel_Cminus1_or_C_vec(<4 x i1> %cond) {95; SSE-LABEL: sel_Cminus1_or_C_vec:96; SSE: # %bb.0:97; SSE-NEXT: pslld $31, %xmm098; SSE-NEXT: psrad $31, %xmm099; SSE-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0100; SSE-NEXT: retq101;102; AVX-LABEL: sel_Cminus1_or_C_vec:103; AVX: # %bb.0:104; AVX-NEXT: vpslld $31, %xmm0, %xmm0105; AVX-NEXT: vpsrad $31, %xmm0, %xmm0106; AVX-NEXT: vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0107; AVX-NEXT: retq108 %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 44, i32 2, i32 0, i32 1>109 ret <4 x i32> %add110}111 112define <4 x i32> @cmp_sel_Cminus1_or_C_vec(<4 x i32> %x, <4 x i32> %y) {113; SSE-LABEL: cmp_sel_Cminus1_or_C_vec:114; SSE: # %bb.0:115; SSE-NEXT: pcmpeqd %xmm1, %xmm0116; SSE-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0117; SSE-NEXT: retq118;119; AVX-LABEL: cmp_sel_Cminus1_or_C_vec:120; AVX: # %bb.0:121; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0122; AVX-NEXT: vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0123; AVX-NEXT: retq124 %cond = icmp eq <4 x i32> %x, %y125 %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 44, i32 2, i32 0, i32 1>126 ret <4 x i32> %add127}128 129define <4 x i32> @sel_minus1_or_0_vec(<4 x i1> %cond) {130; SSE-LABEL: sel_minus1_or_0_vec:131; SSE: # %bb.0:132; SSE-NEXT: pslld $31, %xmm0133; SSE-NEXT: psrad $31, %xmm0134; SSE-NEXT: retq135;136; AVX-LABEL: sel_minus1_or_0_vec:137; AVX: # %bb.0:138; AVX-NEXT: vpslld $31, %xmm0, %xmm0139; AVX-NEXT: vpsrad $31, %xmm0, %xmm0140; AVX-NEXT: retq141 %add = select <4 x i1> %cond, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>142 ret <4 x i32> %add143}144 145define <4 x i32> @cmp_sel_minus1_or_0_vec(<4 x i32> %x, <4 x i32> %y) {146; SSE-LABEL: cmp_sel_minus1_or_0_vec:147; SSE: # %bb.0:148; SSE-NEXT: pcmpeqd %xmm1, %xmm0149; SSE-NEXT: retq150;151; AVX-LABEL: cmp_sel_minus1_or_0_vec:152; AVX: # %bb.0:153; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0154; AVX-NEXT: retq155 %cond = icmp eq <4 x i32> %x, %y156 %add = select <4 x i1> %cond, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>157 ret <4 x i32> %add158}159 160define <4 x i32> @sel_0_or_minus1_vec(<4 x i1> %cond) {161; SSE-LABEL: sel_0_or_minus1_vec:162; SSE: # %bb.0:163; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0164; SSE-NEXT: pcmpeqd %xmm1, %xmm1165; SSE-NEXT: paddd %xmm1, %xmm0166; SSE-NEXT: retq167;168; AVX-LABEL: sel_0_or_minus1_vec:169; AVX: # %bb.0:170; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0171; AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1172; AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0173; AVX-NEXT: retq174 %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>175 ret <4 x i32> %add176}177 178define <4 x i32> @cmp_sel_0_or_minus1_vec(<4 x i32> %x, <4 x i32> %y) {179; SSE-LABEL: cmp_sel_0_or_minus1_vec:180; SSE: # %bb.0:181; SSE-NEXT: pcmpeqd %xmm1, %xmm0182; SSE-NEXT: pcmpeqd %xmm1, %xmm1183; SSE-NEXT: pxor %xmm1, %xmm0184; SSE-NEXT: retq185;186; AVX-LABEL: cmp_sel_0_or_minus1_vec:187; AVX: # %bb.0:188; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0189; AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1190; AVX-NEXT: vpxor %xmm1, %xmm0, %xmm0191; AVX-NEXT: retq192 %cond = icmp eq <4 x i32> %x, %y193 %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>194 ret <4 x i32> %add195}196 197define <4 x i32> @sel_1_or_0_vec(<4 x i1> %cond) {198; SSE-LABEL: sel_1_or_0_vec:199; SSE: # %bb.0:200; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0201; SSE-NEXT: retq202;203; AVX-LABEL: sel_1_or_0_vec:204; AVX: # %bb.0:205; AVX-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0206; AVX-NEXT: retq207 %add = select <4 x i1> %cond, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>208 ret <4 x i32> %add209}210 211define <4 x i32> @cmp_sel_1_or_0_vec(<4 x i32> %x, <4 x i32> %y) {212; SSE-LABEL: cmp_sel_1_or_0_vec:213; SSE: # %bb.0:214; SSE-NEXT: pcmpeqd %xmm1, %xmm0215; SSE-NEXT: psrld $31, %xmm0216; SSE-NEXT: retq217;218; AVX-LABEL: cmp_sel_1_or_0_vec:219; AVX: # %bb.0:220; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0221; AVX-NEXT: vpsrld $31, %xmm0, %xmm0222; AVX-NEXT: retq223 %cond = icmp eq <4 x i32> %x, %y224 %add = select <4 x i1> %cond, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>225 ret <4 x i32> %add226}227 228define <4 x i32> @sel_0_or_1_vec(<4 x i1> %cond) {229; SSE-LABEL: sel_0_or_1_vec:230; SSE: # %bb.0:231; SSE-NEXT: andnps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0232; SSE-NEXT: retq233;234; AVX-LABEL: sel_0_or_1_vec:235; AVX: # %bb.0:236; AVX-NEXT: vandnps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0237; AVX-NEXT: retq238 %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>239 ret <4 x i32> %add240}241 242define <4 x i32> @cmp_sel_0_or_1_vec(<4 x i32> %x, <4 x i32> %y) {243; SSE-LABEL: cmp_sel_0_or_1_vec:244; SSE: # %bb.0:245; SSE-NEXT: pcmpeqd %xmm1, %xmm0246; SSE-NEXT: pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0247; SSE-NEXT: retq248;249; AVX-LABEL: cmp_sel_0_or_1_vec:250; AVX: # %bb.0:251; AVX-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0252; AVX-NEXT: vpandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0253; AVX-NEXT: retq254 %cond = icmp eq <4 x i32> %x, %y255 %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>256 ret <4 x i32> %add257}258 259; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21167260define <2 x i37> @ossfuzz21167(<2 x i37> %x, <2 x i37> %y) {261; SSE-LABEL: ossfuzz21167:262; SSE: # %bb.0: # %BB263; SSE-NEXT: xorps %xmm0, %xmm0264; SSE-NEXT: retq265;266; AVX-LABEL: ossfuzz21167:267; AVX: # %bb.0: # %BB268; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0269; AVX-NEXT: retq270BB:271 %c0 = icmp sgt <2 x i37> %y, zeroinitializer272 %xor_x = xor <2 x i37> undef, undef273 %smax96 = select <2 x i1> %c0, <2 x i37> %xor_x, <2 x i37> zeroinitializer274 ret <2 x i37> %smax96275}276 277; PR53401278 279define i32 @wrong_min_signbits(<2 x i16> %x) {280; SSE-LABEL: wrong_min_signbits:281; SSE: # %bb.0:282; SSE-NEXT: pxor %xmm1, %xmm1283; SSE-NEXT: pcmpeqw %xmm0, %xmm1284; SSE-NEXT: movd {{.*#+}} xmm0 = [1,0,0,0]285; SSE-NEXT: pand %xmm1, %xmm0286; SSE-NEXT: pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1287; SSE-NEXT: por %xmm0, %xmm1288; SSE-NEXT: movd %xmm1, %eax289; SSE-NEXT: retq290;291; AVX-LABEL: wrong_min_signbits:292; AVX: # %bb.0:293; AVX-NEXT: vpxor %xmm1, %xmm1, %xmm1294; AVX-NEXT: vpcmpeqw %xmm1, %xmm0, %xmm0295; AVX-NEXT: vpmovsxbq {{.*#+}} xmm1 = [2,0]296; AVX-NEXT: vpblendvb %xmm0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0297; AVX-NEXT: vmovd %xmm0, %eax298; AVX-NEXT: retq299 %true_true = icmp ne <2 x i16> %x, zeroinitializer300 %true_false = and <2 x i1> %true_true, <i1 true, i1 false>301 %sel = select <2 x i1> %true_false, <2 x i16> <i16 2, i16 0>, <2 x i16> <i16 1, i16 0>302 %t1 = bitcast <2 x i16> %sel to i32303 ret i32 %t1304}305 306define i32 @pr129181() {307; SSE-LABEL: pr129181:308; SSE: # %bb.0: # %entry309; SSE-NEXT: xorl %eax, %eax310; SSE-NEXT: retq311;312; AVX-LABEL: pr129181:313; AVX: # %bb.0: # %entry314; AVX-NEXT: xorl %eax, %eax315; AVX-NEXT: retq316entry:317 %x = insertelement <4 x i32> zeroinitializer, i32 0, i32 0318 %cmp = icmp ult <4 x i32> %x, splat (i32 1)319 %sel = select <4 x i1> %cmp, <4 x i32> zeroinitializer, <4 x i32> <i32 0, i32 0, i32 1, i32 poison>320 %reduce = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %sel)321 ret i32 %reduce322}323