; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,X86-SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,X64-SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX2 ; Only bottom 16 bits are set - upper 48 bits are zero. define <2 x i64> @combine_psadbw_shift(<16 x i8> %0, <16 x i8> %1) nounwind { ; SSE-LABEL: combine_psadbw_shift: ; SSE: # %bb.0: ; SSE-NEXT: xorps %xmm0, %xmm0 ; SSE-NEXT: ret{{[l|q]}} ; ; AVX2-LABEL: combine_psadbw_shift: ; AVX2: # %bb.0: ; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 ; AVX2-NEXT: retq %3 = tail call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %0, <16 x i8> %1) %4 = lshr <2 x i64> %3, ret <2 x i64> %4 } ; Propagate the demanded result elements to the 8 aliasing source elements. define i64 @combine_psadbw_demandedelt(<16 x i8> %0, <16 x i8> %1) nounwind { ; X86-SSE-LABEL: combine_psadbw_demandedelt: ; X86-SSE: # %bb.0: ; X86-SSE-NEXT: psadbw %xmm1, %xmm0 ; X86-SSE-NEXT: movd %xmm0, %eax ; X86-SSE-NEXT: xorl %edx, %edx ; X86-SSE-NEXT: retl ; ; X64-SSE-LABEL: combine_psadbw_demandedelt: ; X64-SSE: # %bb.0: ; X64-SSE-NEXT: psadbw %xmm1, %xmm0 ; X64-SSE-NEXT: movq %xmm0, %rax ; X64-SSE-NEXT: retq ; ; AVX2-LABEL: combine_psadbw_demandedelt: ; AVX2: # %bb.0: ; AVX2-NEXT: vpsadbw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vmovq %xmm0, %rax ; AVX2-NEXT: retq %3 = shufflevector <16 x i8> %0, <16 x i8> %0, <16 x i32> %4 = shufflevector <16 x i8> %1, <16 x i8> %1, <16 x i32> %5 = tail call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %3, <16 x i8> %4) %6 = extractelement <2 x i64> %5, i32 0 ret i64 %6 } ; TODO: Each PSADBW source element has a maximum value of 3 - so max sum-of-diffs for each <8 x i8> should be 24. define <2 x i64> @combine_psadbw_cmp_knownbits(<16 x i8> %a0) nounwind { ; X86-SSE-LABEL: combine_psadbw_cmp_knownbits: ; X86-SSE: # %bb.0: ; X86-SSE-NEXT: xorps %xmm0, %xmm0 ; X86-SSE-NEXT: retl ; ; X64-SSE-LABEL: combine_psadbw_cmp_knownbits: ; X64-SSE: # %bb.0: ; X64-SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-SSE-NEXT: pxor %xmm1, %xmm1 ; X64-SSE-NEXT: psadbw %xmm1, %xmm0 ; X64-SSE-NEXT: pcmpgtd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-SSE-NEXT: retq ; ; AVX2-LABEL: combine_psadbw_cmp_knownbits: ; AVX2: # %bb.0: ; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpsadbw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpcmpgtq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-NEXT: retq %mask = and <16 x i8> %a0, %sad = tail call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %mask, <16 x i8> zeroinitializer) %cmp = icmp sgt <2 x i64> %sad, %ext = sext <2 x i1> %cmp to <2 x i64> ret <2 x i64> %ext } ; No need to scalarize the sitofp as the PSADBW results are smaller than i32. define <2 x double> @combine_psadbw_sitofp_knownbits(<16 x i8> %a0) nounwind { ; X86-SSE-LABEL: combine_psadbw_sitofp_knownbits: ; X86-SSE: # %bb.0: ; X86-SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 ; X86-SSE-NEXT: pxor %xmm1, %xmm1 ; X86-SSE-NEXT: psadbw %xmm0, %xmm1 ; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] ; X86-SSE-NEXT: cvtdq2pd %xmm0, %xmm0 ; X86-SSE-NEXT: retl ; ; X64-SSE-LABEL: combine_psadbw_sitofp_knownbits: ; X64-SSE: # %bb.0: ; X64-SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-SSE-NEXT: pxor %xmm1, %xmm1 ; X64-SSE-NEXT: psadbw %xmm0, %xmm1 ; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] ; X64-SSE-NEXT: cvtdq2pd %xmm0, %xmm0 ; X64-SSE-NEXT: retq ; ; AVX2-LABEL: combine_psadbw_sitofp_knownbits: ; AVX2: # %bb.0: ; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpsadbw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,2,2,3] ; AVX2-NEXT: vcvtdq2pd %xmm0, %xmm0 ; AVX2-NEXT: retq %mask = and <16 x i8> %a0, %sad = tail call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %mask, <16 x i8> zeroinitializer) %cvt = sitofp <2 x i64> %sad to <2 x double> ret <2 x double> %cvt } ; Convert from uitofp to sitofp as the PSADBW results are zero-extended. define <2 x double> @combine_psadbw_uitofp_knownbits(<16 x i8> %a0) nounwind { ; X86-SSE-LABEL: combine_psadbw_uitofp_knownbits: ; X86-SSE: # %bb.0: ; X86-SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 ; X86-SSE-NEXT: pxor %xmm1, %xmm1 ; X86-SSE-NEXT: psadbw %xmm0, %xmm1 ; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] ; X86-SSE-NEXT: cvtdq2pd %xmm0, %xmm0 ; X86-SSE-NEXT: retl ; ; X64-SSE-LABEL: combine_psadbw_uitofp_knownbits: ; X64-SSE: # %bb.0: ; X64-SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; X64-SSE-NEXT: pxor %xmm1, %xmm1 ; X64-SSE-NEXT: psadbw %xmm0, %xmm1 ; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] ; X64-SSE-NEXT: cvtdq2pd %xmm0, %xmm0 ; X64-SSE-NEXT: retq ; ; AVX2-LABEL: combine_psadbw_uitofp_knownbits: ; AVX2: # %bb.0: ; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpsadbw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,2,2,3] ; AVX2-NEXT: vcvtdq2pd %xmm0, %xmm0 ; AVX2-NEXT: retq %mask = and <16 x i8> %a0, %sad = tail call <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8> %mask, <16 x i8> zeroinitializer) %cvt = uitofp <2 x i64> %sad to <2 x double> ret <2 x double> %cvt } declare <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8>, <16 x i8>)