]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Tuned loops with non-temporal access. andros/avx512f-mem
authorAndrew Senkevich <andrew.senkevich@intel.com>
Fri, 15 Jan 2016 20:03:44 +0000 (23:03 +0300)
committerAndrew Senkevich <andrew.senkevich@intel.com>
Fri, 15 Jan 2016 20:03:44 +0000 (23:03 +0300)
    * sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S: Tuned
    prefetch.

sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S

index cc02934a82640d7d08c41870921075f9aded879b..75bc836d0cac11a5d007edc8ce765563c908a649 100644 (file)
-/* memcpy optimized with AVX512 for KNL hardware.\r
-   Copyright (C) 2016 Free Software Foundation, Inc.\r
-   This file is part of the GNU C Library.\r
-\r
-   The GNU C Library is free software; you can redistribute it and/or\r
-   modify it under the terms of the GNU Lesser General Public\r
-   License as published by the Free Software Foundation; either\r
-   version 2.1 of the License, or (at your option) any later version.\r
-\r
-   The GNU C Library is distributed in the hope that it will be useful,\r
-   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-   Lesser General Public License for more details.\r
-\r
-   You should have received a copy of the GNU Lesser General Public\r
-   License along with the GNU C Library; if not, see\r
-   <http://www.gnu.org/licenses/>.  */\r
-\r
-#include <sysdep.h>\r
-\r
-#if defined HAVE_AVX512_ASM_SUPPORT && IS_IN (libc) \\r
-    && (defined SHARED \\r
-       || defined USE_AS_MEMMOVE \\r
-       || !defined USE_MULTIARCH)\r
-\r
-#include "asm-syntax.h"\r
-#ifndef MEMCPY\r
-# define MEMCPY                __memcpy_avx512_no_vzeroupper\r
-# define MEMCPY_CHK    __memcpy_chk_avx512_no_vzeroupper\r
-#endif\r
-\r
-       .section .text,"ax",@progbits\r
-#if !defined USE_AS_BCOPY\r
-ENTRY (MEMCPY_CHK)\r
-       cmpq    %rdx, %rcx\r
-       jb      HIDDEN_JUMPTARGET (__chk_fail)\r
-END (MEMCPY_CHK)\r
-#endif\r
-\r
-ENTRY (MEMCPY)\r
-       mov     %rdi, %rax\r
-#ifdef USE_AS_MEMPCPY\r
-       add     %rdx, %rax\r
-#endif\r
-       lea     (%rsi, %rdx), %rcx\r
-       lea     (%rdi, %rdx), %r9\r
-       cmp     $512, %rdx\r
-       ja      L(512bytesormore)\r
-\r
-L(check):\r
-       cmp     $16, %rdx\r
-       jbe     L(less_16bytes)\r
-       cmp     $256, %rdx\r
-       jb      L(less_256bytes)\r
-       vmovups (%rsi), %zmm0\r
-       vmovups 0x40(%rsi), %zmm1\r
-       vmovups 0x80(%rsi), %zmm2\r
-       vmovups 0xC0(%rsi), %zmm3\r
-       vmovups -0x100(%rcx), %zmm4\r
-       vmovups -0xC0(%rcx), %zmm5\r
-       vmovups -0x80(%rcx), %zmm6\r
-       vmovups -0x40(%rcx), %zmm7\r
-       vmovups %zmm0, (%rdi)\r
-       vmovups %zmm1, 0x40(%rdi)\r
-       vmovups %zmm2, 0x80(%rdi)\r
-       vmovups %zmm3, 0xC0(%rdi)\r
-       vmovups %zmm4, -0x100(%r9)\r
-       vmovups %zmm5, -0xC0(%r9)\r
-       vmovups %zmm6, -0x80(%r9)\r
-       vmovups %zmm7, -0x40(%r9)\r
-       ret\r
-\r
-L(less_256bytes):\r
-       cmp     $128, %dl\r
-       jb      L(less_128bytes)\r
-       vmovups (%rsi), %zmm0\r
-       vmovups 0x40(%rsi), %zmm1\r
-       vmovups -0x80(%rcx), %zmm2\r
-       vmovups -0x40(%rcx), %zmm3\r
-       vmovups %zmm0, (%rdi)\r
-       vmovups %zmm1, 0x40(%rdi)\r
-       vmovups %zmm2, -0x80(%r9)\r
-       vmovups %zmm3, -0x40(%r9)\r
-       ret\r
-\r
-L(less_128bytes):\r
-       cmp     $64, %dl\r
-       jb      L(less_64bytes)\r
-       vmovdqu (%rsi), %ymm0\r
-       vmovdqu 0x20(%rsi), %ymm1\r
-       vmovdqu -0x40(%rcx), %ymm2\r
-       vmovdqu -0x20(%rcx), %ymm3\r
-       vmovdqu %ymm0, (%rdi)\r
-       vmovdqu %ymm1, 0x20(%rdi)\r
-       vmovdqu %ymm2, -0x40(%r9)\r
-       vmovdqu %ymm3, -0x20(%r9)\r
-       ret\r
-\r
-L(less_64bytes):\r
-       cmp     $32, %dl\r
-       jb      L(less_32bytes)\r
-       vmovdqu (%rsi), %ymm0\r
-       vmovdqu -0x20(%rcx), %ymm1\r
-       vmovdqu %ymm0, (%rdi)\r
-       vmovdqu %ymm1, -0x20(%r9)\r
-       ret\r
-\r
-L(less_32bytes):\r
-       vmovdqu (%rsi), %xmm0\r
-       vmovdqu -0x10(%rcx), %xmm1\r
-       vmovdqu %xmm0, (%rdi)\r
-       vmovdqu %xmm1, -0x10(%r9)\r
-       ret\r
-\r
-L(less_16bytes):\r
-       cmp     $8, %dl\r
-       jb      L(less_8bytes)\r
-       movq    (%rsi), %rsi\r
-       movq    -0x8(%rcx), %rcx\r
-       movq    %rsi, (%rdi)\r
-       movq    %rcx, -0x8(%r9)\r
-       ret\r
-\r
-L(less_8bytes):\r
-       cmp     $4, %dl\r
-       jb      L(less_4bytes)\r
-       mov     (%rsi), %esi\r
-       mov     -0x4(%rcx), %ecx\r
-       mov     %esi, (%rdi)\r
-       mov     %ecx, -0x4(%r9)\r
-       ret\r
-\r
-L(less_4bytes):\r
-       cmp     $2, %dl\r
-       jb      L(less_2bytes)\r
-       mov     (%rsi), %si\r
-       mov     -0x2(%rcx), %cx\r
-       mov     %si, (%rdi)\r
-       mov     %cx, -0x2(%r9)\r
-       ret\r
-\r
-L(less_2bytes):\r
-       cmp     $1, %dl\r
-       jb      L(less_1bytes)  \r
-       mov     (%rsi), %cl\r
-       mov     %cl, (%rdi)\r
-L(less_1bytes):\r
-       ret\r
-\r
-L(512bytesormore):\r
-#ifdef SHARED_CACHE_SIZE_HALF\r
-       mov     $SHARED_CACHE_SIZE_HALF, %r8\r
-#else\r
-       mov     __x86_shared_cache_size_half(%rip), %r8\r
-#endif\r
-       cmp     %r8, %rdx\r
-       jae     L(preloop_large)\r
-       cmp     $1024, %rdx\r
-       ja      L(1024bytesormore)\r
-       prefetcht1 (%rsi)\r
-       prefetcht1 0x40(%rsi)\r
-       prefetcht1 0x80(%rsi)\r
-       prefetcht1 0xC0(%rsi)\r
-       prefetcht1 0x100(%rsi)\r
-       prefetcht1 0x140(%rsi)\r
-       prefetcht1 0x180(%rsi)\r
-       prefetcht1 0x1C0(%rsi)\r
-       prefetcht1 -0x200(%rcx)\r
-       prefetcht1 -0x1C0(%rcx)\r
-       prefetcht1 -0x180(%rcx)\r
-       prefetcht1 -0x140(%rcx)\r
-       prefetcht1 -0x100(%rcx)\r
-       prefetcht1 -0xC0(%rcx)\r
-       prefetcht1 -0x80(%rcx)\r
-       prefetcht1 -0x40(%rcx)  \r
-       vmovups (%rsi), %zmm0\r
-       vmovups 0x40(%rsi), %zmm1\r
-       vmovups 0x80(%rsi), %zmm2\r
-       vmovups 0xC0(%rsi), %zmm3\r
-       vmovups 0x100(%rsi), %zmm4\r
-       vmovups 0x140(%rsi), %zmm5\r
-       vmovups 0x180(%rsi), %zmm6\r
-       vmovups 0x1C0(%rsi), %zmm7\r
-       vmovups -0x200(%rcx), %zmm8\r
-       vmovups -0x1C0(%rcx), %zmm9\r
-       vmovups -0x180(%rcx), %zmm10\r
-       vmovups -0x140(%rcx), %zmm11\r
-       vmovups -0x100(%rcx), %zmm12\r
-       vmovups -0xC0(%rcx), %zmm13\r
-       vmovups -0x80(%rcx), %zmm14\r
-       vmovups -0x40(%rcx), %zmm15\r
-       vmovups %zmm0, (%rdi)\r
-       vmovups %zmm1, 0x40(%rdi)\r
-       vmovups %zmm2, 0x80(%rdi)\r
-       vmovups %zmm3, 0xC0(%rdi)\r
-       vmovups %zmm4, 0x100(%rdi)\r
-       vmovups %zmm5, 0x140(%rdi)\r
-       vmovups %zmm6, 0x180(%rdi)\r
-       vmovups %zmm7, 0x1C0(%rdi)\r
-       vmovups %zmm8, -0x200(%r9)\r
-       vmovups %zmm9, -0x1C0(%r9)\r
-       vmovups %zmm10, -0x180(%r9)\r
-       vmovups %zmm11, -0x140(%r9)\r
-       vmovups %zmm12, -0x100(%r9)\r
-       vmovups %zmm13, -0xC0(%r9)\r
-       vmovups %zmm14, -0x80(%r9)\r
-       vmovups %zmm15, -0x40(%r9)\r
-       ret\r
-\r
-L(1024bytesormore):\r
-       cmp     %rsi, %rdi\r
-       ja      L(1024bytesormore_bkw)\r
-       sub     $512, %r9\r
-       vmovups -0x200(%rcx), %zmm8\r
-       vmovups -0x1C0(%rcx), %zmm9\r
-       vmovups -0x180(%rcx), %zmm10\r
-       vmovups -0x140(%rcx), %zmm11\r
-       vmovups -0x100(%rcx), %zmm12\r
-       vmovups -0xC0(%rcx), %zmm13\r
-       vmovups -0x80(%rcx), %zmm14\r
-       vmovups -0x40(%rcx), %zmm15\r
-       prefetcht1 (%rsi)\r
-       prefetcht1 0x40(%rsi)\r
-       prefetcht1 0x80(%rsi)\r
-       prefetcht1 0xC0(%rsi)\r
-       prefetcht1 0x100(%rsi)\r
-       prefetcht1 0x140(%rsi)\r
-       prefetcht1 0x180(%rsi)\r
-       prefetcht1 0x1C0(%rsi)\r
-\r
-/* Loop with unaligned memory access.  */\r
-L(gobble_512bytes_loop):\r
-       vmovups (%rsi), %zmm0\r
-       vmovups 0x40(%rsi), %zmm1\r
-       vmovups 0x80(%rsi), %zmm2\r
-       vmovups 0xC0(%rsi), %zmm3\r
-       vmovups 0x100(%rsi), %zmm4\r
-       vmovups 0x140(%rsi), %zmm5\r
-       vmovups 0x180(%rsi), %zmm6\r
-       vmovups 0x1C0(%rsi), %zmm7\r
-       add     $512, %rsi\r
-       prefetcht1 (%rsi)\r
-       prefetcht1 0x40(%rsi)\r
-       prefetcht1 0x80(%rsi)\r
-       prefetcht1 0xC0(%rsi)\r
-       prefetcht1 0x100(%rsi)\r
-       prefetcht1 0x140(%rsi)\r
-       prefetcht1 0x180(%rsi)\r
-       prefetcht1 0x1C0(%rsi)\r
-       vmovups %zmm0, (%rdi)\r
-       vmovups %zmm1, 0x40(%rdi)\r
-       vmovups %zmm2, 0x80(%rdi)\r
-       vmovups %zmm3, 0xC0(%rdi)\r
-       vmovups %zmm4, 0x100(%rdi)\r
-       vmovups %zmm5, 0x140(%rdi)\r
-       vmovups %zmm6, 0x180(%rdi)\r
-       vmovups %zmm7, 0x1C0(%rdi)\r
-       add     $512, %rdi\r
-       cmp     %r9, %rdi\r
-       jb      L(gobble_512bytes_loop)\r
-       vmovups %zmm8, (%r9)\r
-       vmovups %zmm9, 0x40(%r9)\r
-       vmovups %zmm10, 0x80(%r9)\r
-       vmovups %zmm11, 0xC0(%r9)\r
-       vmovups %zmm12, 0x100(%r9)\r
-       vmovups %zmm13, 0x140(%r9)\r
-       vmovups %zmm14, 0x180(%r9)\r
-       vmovups %zmm15, 0x1C0(%r9)\r
-       ret\r
-\r
-L(1024bytesormore_bkw):\r
-       add     $512, %rdi\r
-       vmovups 0x1C0(%rsi), %zmm8\r
-       vmovups 0x180(%rsi), %zmm9\r
-       vmovups 0x140(%rsi), %zmm10\r
-       vmovups 0x100(%rsi), %zmm11\r
-       vmovups 0xC0(%rsi), %zmm12\r
-       vmovups 0x80(%rsi), %zmm13\r
-       vmovups 0x40(%rsi), %zmm14\r
-       vmovups (%rsi), %zmm15\r
-       prefetcht1 -0x40(%rcx)\r
-       prefetcht1 -0x80(%rcx)\r
-       prefetcht1 -0xC0(%rcx)\r
-       prefetcht1 -0x100(%rcx)\r
-       prefetcht1 -0x140(%rcx)\r
-       prefetcht1 -0x180(%rcx)\r
-       prefetcht1 -0x1C0(%rcx)\r
-       prefetcht1 -0x200(%rcx)\r
-       \r
-/* Backward loop with unaligned memory access.  */\r
-L(gobble_512bytes_loop_bkw):\r
-       vmovups -0x40(%rcx), %zmm0\r
-       vmovups -0x80(%rcx), %zmm1\r
-       vmovups -0xC0(%rcx), %zmm2\r
-       vmovups -0x100(%rcx), %zmm3\r
-       vmovups -0x140(%rcx), %zmm4\r
-       vmovups -0x180(%rcx), %zmm5\r
-       vmovups -0x1C0(%rcx), %zmm6\r
-       vmovups -0x200(%rcx), %zmm7\r
-       sub     $512, %rcx\r
-       prefetcht1 -0x40(%rcx)\r
-       prefetcht1 -0x80(%rcx)\r
-       prefetcht1 -0xC0(%rcx)\r
-       prefetcht1 -0x100(%rcx)\r
-       prefetcht1 -0x140(%rcx)\r
-       prefetcht1 -0x180(%rcx)\r
-       prefetcht1 -0x1C0(%rcx)\r
-       prefetcht1 -0x200(%rcx)\r
-       vmovups %zmm0, -0x40(%r9)       \r
-       vmovups %zmm1, -0x80(%r9)       \r
-       vmovups %zmm2, -0xC0(%r9)       \r
-       vmovups %zmm3, -0x100(%r9)      \r
-       vmovups %zmm4, -0x140(%r9)      \r
-       vmovups %zmm5, -0x180(%r9)      \r
-       vmovups %zmm6, -0x1C0(%r9)\r
-       vmovups %zmm7, -0x200(%r9)      \r
-       sub     $512, %r9\r
-       cmp     %rdi, %r9\r
-       ja      L(gobble_512bytes_loop_bkw)\r
-       vmovups %zmm8, -0x40(%rdi)\r
-       vmovups %zmm9, -0x80(%rdi)\r
-       vmovups %zmm10, -0xC0(%rdi)\r
-       vmovups %zmm11, -0x100(%rdi)\r
-       vmovups %zmm12, -0x140(%rdi)\r
-       vmovups %zmm13, -0x180(%rdi)\r
-       vmovups %zmm14, -0x1C0(%rdi)\r
-       vmovups %zmm15, -0x200(%rdi)\r
-       ret\r
-\r
-L(preloop_large):\r
-       cmp     %rsi, %rdi\r
-       ja      L(preloop_large_bkw)\r
-       vmovups (%rsi), %zmm4\r
-       vmovups 0x40(%rsi), %zmm5\r
-\r
-/* Align destination for access with non-temporal stores in the loop.  */\r
-       mov     %rdi, %r8\r
-       and     $-0x80, %rdi\r
-       add     $0x80, %rdi\r
-       sub     %rdi, %r8       \r
-       sub     %r8, %rsi\r
-       add     %r8, %rdx\r
-       prefetcht1 (%rsi)\r
-       prefetcht1 0x40(%rsi)\r
-       prefetcht1 0x80(%rsi)\r
-       prefetcht1 0xC0(%rsi)\r
-L(gobble_256bytes_nt_loop):\r
-       vmovups (%rsi), %zmm0\r
-       prefetcht1 0x100(%rsi)\r
-       vmovups 0x40(%rsi), %zmm1\r
-       prefetcht1 0x140(%rsi)\r
-       vmovups 0x80(%rsi), %zmm2\r
-       prefetcht1 0x180(%rsi)\r
-       vmovups 0xC0(%rsi), %zmm3\r
-       prefetcht1 0x1C0(%rsi)\r
-       vmovntdq %zmm0, (%rdi)\r
-       vmovntdq %zmm1, 0x40(%rdi)\r
-       vmovntdq %zmm2, 0x80(%rdi)\r
-       vmovntdq %zmm3, 0xC0(%rdi)\r
-       sub     $256, %rdx\r
-       add     $256, %rsi\r
-       add     $256, %rdi\r
-       cmp     $256, %rdx\r
-       ja      L(gobble_256bytes_nt_loop)\r
-       sfence\r
-       vmovups %zmm4, (%rax)\r
-       vmovups %zmm5, 0x40(%rax)\r
-       jmp     L(check)\r
-\r
-L(preloop_large_bkw):\r
-       vmovups -0x80(%rcx), %zmm4\r
-       vmovups -0x40(%rcx), %zmm5\r
-\r
-/* Align end of destination for access with non-temporal stores.  */\r
-       mov     %r9, %r8\r
-       and     $-0x80, %r9\r
-       sub     %r9, %r8\r
-       sub     %r8, %rcx\r
-       sub     %r8, %rdx\r
-       add     %r9, %r8\r
-       prefetcht1 -0x100(%rcx)\r
-       prefetcht1 -0xC0(%rcx)\r
-       prefetcht1 -0x80(%rcx)\r
-       prefetcht1 -0x40(%rcx)\r
-L(gobble_256bytes_nt_loop_bkw):\r
-       vmovups -0x100(%rcx), %zmm0\r
-       prefetcht1 -0x200(%rcx)\r
-       vmovups -0xC0(%rcx), %zmm1\r
-       prefetcht1 -0x1C0(%rcx)\r
-       vmovups -0x80(%rcx), %zmm2\r
-       prefetcht1 -0x180(%rcx)\r
-       vmovups -0x40(%rcx), %zmm3\r
-       prefetcht1 -0x140(%rcx)\r
-       vmovntdq %zmm0, -0x100(%r9)\r
-       vmovntdq %zmm1, -0xC0(%r9)\r
-       vmovntdq %zmm2, -0x80(%r9)\r
-       vmovntdq %zmm3, -0x40(%r9)\r
-       sub     $256, %rdx\r
-       sub     $256, %rcx\r
-       sub     $256, %r9\r
-       cmp     $256, %rdx\r
-       ja      L(gobble_256bytes_nt_loop_bkw)\r
-       sfence\r
-       vmovups %zmm4, -0x80(%r8)\r
-       vmovups %zmm5, -0x40(%r8)\r
-       jmp     L(check)\r
-\r
-END (MEMCPY)\r
-\r
-#endif\r
+/* memcpy optimized with AVX512 for KNL hardware.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+
+#if defined HAVE_AVX512_ASM_SUPPORT && IS_IN (libc) \
+    && (defined SHARED \
+       || defined USE_AS_MEMMOVE \
+       || !defined USE_MULTIARCH)
+
+#include "asm-syntax.h"
+#ifndef MEMCPY
+# define MEMCPY                __memcpy_avx512_no_vzeroupper
+# define MEMCPY_CHK    __memcpy_chk_avx512_no_vzeroupper
+#endif
+
+       .section .text,"ax",@progbits
+#if !defined USE_AS_BCOPY
+ENTRY (MEMCPY_CHK)
+       cmpq    %rdx, %rcx
+       jb      HIDDEN_JUMPTARGET (__chk_fail)
+END (MEMCPY_CHK)
+#endif
+
+ENTRY (MEMCPY)
+       mov     %rdi, %rax
+#ifdef USE_AS_MEMPCPY
+       add     %rdx, %rax
+#endif
+       lea     (%rsi, %rdx), %rcx
+       lea     (%rdi, %rdx), %r9
+       cmp     $512, %rdx
+       ja      L(512bytesormore)
+
+L(check):
+       cmp     $16, %rdx
+       jbe     L(less_16bytes)
+       cmp     $256, %rdx
+       jb      L(less_256bytes)
+       vmovups (%rsi), %zmm0
+       vmovups 0x40(%rsi), %zmm1
+       vmovups 0x80(%rsi), %zmm2
+       vmovups 0xC0(%rsi), %zmm3
+       vmovups -0x100(%rcx), %zmm4
+       vmovups -0xC0(%rcx), %zmm5
+       vmovups -0x80(%rcx), %zmm6
+       vmovups -0x40(%rcx), %zmm7
+       vmovups %zmm0, (%rdi)
+       vmovups %zmm1, 0x40(%rdi)
+       vmovups %zmm2, 0x80(%rdi)
+       vmovups %zmm3, 0xC0(%rdi)
+       vmovups %zmm4, -0x100(%r9)
+       vmovups %zmm5, -0xC0(%r9)
+       vmovups %zmm6, -0x80(%r9)
+       vmovups %zmm7, -0x40(%r9)
+       ret
+
+L(less_256bytes):
+       cmp     $128, %dl
+       jb      L(less_128bytes)
+       vmovups (%rsi), %zmm0
+       vmovups 0x40(%rsi), %zmm1
+       vmovups -0x80(%rcx), %zmm2
+       vmovups -0x40(%rcx), %zmm3
+       vmovups %zmm0, (%rdi)
+       vmovups %zmm1, 0x40(%rdi)
+       vmovups %zmm2, -0x80(%r9)
+       vmovups %zmm3, -0x40(%r9)
+       ret
+
+L(less_128bytes):
+       cmp     $64, %dl
+       jb      L(less_64bytes)
+       vmovdqu (%rsi), %ymm0
+       vmovdqu 0x20(%rsi), %ymm1
+       vmovdqu -0x40(%rcx), %ymm2
+       vmovdqu -0x20(%rcx), %ymm3
+       vmovdqu %ymm0, (%rdi)
+       vmovdqu %ymm1, 0x20(%rdi)
+       vmovdqu %ymm2, -0x40(%r9)
+       vmovdqu %ymm3, -0x20(%r9)
+       ret
+
+L(less_64bytes):
+       cmp     $32, %dl
+       jb      L(less_32bytes)
+       vmovdqu (%rsi), %ymm0
+       vmovdqu -0x20(%rcx), %ymm1
+       vmovdqu %ymm0, (%rdi)
+       vmovdqu %ymm1, -0x20(%r9)
+       ret
+
+L(less_32bytes):
+       vmovdqu (%rsi), %xmm0
+       vmovdqu -0x10(%rcx), %xmm1
+       vmovdqu %xmm0, (%rdi)
+       vmovdqu %xmm1, -0x10(%r9)
+       ret
+
+L(less_16bytes):
+       cmp     $8, %dl
+       jb      L(less_8bytes)
+       movq    (%rsi), %rsi
+       movq    -0x8(%rcx), %rcx
+       movq    %rsi, (%rdi)
+       movq    %rcx, -0x8(%r9)
+       ret
+
+L(less_8bytes):
+       cmp     $4, %dl
+       jb      L(less_4bytes)
+       mov     (%rsi), %esi
+       mov     -0x4(%rcx), %ecx
+       mov     %esi, (%rdi)
+       mov     %ecx, -0x4(%r9)
+       ret
+
+L(less_4bytes):
+       cmp     $2, %dl
+       jb      L(less_2bytes)
+       mov     (%rsi), %si
+       mov     -0x2(%rcx), %cx
+       mov     %si, (%rdi)
+       mov     %cx, -0x2(%r9)
+       ret
+
+L(less_2bytes):
+       cmp     $1, %dl
+       jb      L(less_1bytes)
+       mov     (%rsi), %cl
+       mov     %cl, (%rdi)
+L(less_1bytes):
+       ret
+
+L(512bytesormore):
+#ifdef SHARED_CACHE_SIZE_HALF
+       mov     $SHARED_CACHE_SIZE_HALF, %r8
+#else
+       mov     __x86_shared_cache_size_half(%rip), %r8
+#endif
+       cmp     %r8, %rdx
+       jae     L(preloop_large)
+       cmp     $1024, %rdx
+       ja      L(1024bytesormore)
+       prefetcht1 (%rsi)
+       prefetcht1 0x40(%rsi)
+       prefetcht1 0x80(%rsi)
+       prefetcht1 0xC0(%rsi)
+       prefetcht1 0x100(%rsi)
+       prefetcht1 0x140(%rsi)
+       prefetcht1 0x180(%rsi)
+       prefetcht1 0x1C0(%rsi)
+       prefetcht1 -0x200(%rcx)
+       prefetcht1 -0x1C0(%rcx)
+       prefetcht1 -0x180(%rcx)
+       prefetcht1 -0x140(%rcx)
+       prefetcht1 -0x100(%rcx)
+       prefetcht1 -0xC0(%rcx)
+       prefetcht1 -0x80(%rcx)
+       prefetcht1 -0x40(%rcx)
+       vmovups (%rsi), %zmm0
+       vmovups 0x40(%rsi), %zmm1
+       vmovups 0x80(%rsi), %zmm2
+       vmovups 0xC0(%rsi), %zmm3
+       vmovups 0x100(%rsi), %zmm4
+       vmovups 0x140(%rsi), %zmm5
+       vmovups 0x180(%rsi), %zmm6
+       vmovups 0x1C0(%rsi), %zmm7
+       vmovups -0x200(%rcx), %zmm8
+       vmovups -0x1C0(%rcx), %zmm9
+       vmovups -0x180(%rcx), %zmm10
+       vmovups -0x140(%rcx), %zmm11
+       vmovups -0x100(%rcx), %zmm12
+       vmovups -0xC0(%rcx), %zmm13
+       vmovups -0x80(%rcx), %zmm14
+       vmovups -0x40(%rcx), %zmm15
+       vmovups %zmm0, (%rdi)
+       vmovups %zmm1, 0x40(%rdi)
+       vmovups %zmm2, 0x80(%rdi)
+       vmovups %zmm3, 0xC0(%rdi)
+       vmovups %zmm4, 0x100(%rdi)
+       vmovups %zmm5, 0x140(%rdi)
+       vmovups %zmm6, 0x180(%rdi)
+       vmovups %zmm7, 0x1C0(%rdi)
+       vmovups %zmm8, -0x200(%r9)
+       vmovups %zmm9, -0x1C0(%r9)
+       vmovups %zmm10, -0x180(%r9)
+       vmovups %zmm11, -0x140(%r9)
+       vmovups %zmm12, -0x100(%r9)
+       vmovups %zmm13, -0xC0(%r9)
+       vmovups %zmm14, -0x80(%r9)
+       vmovups %zmm15, -0x40(%r9)
+       ret
+
+L(1024bytesormore):
+       cmp     %rsi, %rdi
+       ja      L(1024bytesormore_bkw)
+       sub     $512, %r9
+       vmovups -0x200(%rcx), %zmm8
+       vmovups -0x1C0(%rcx), %zmm9
+       vmovups -0x180(%rcx), %zmm10
+       vmovups -0x140(%rcx), %zmm11
+       vmovups -0x100(%rcx), %zmm12
+       vmovups -0xC0(%rcx), %zmm13
+       vmovups -0x80(%rcx), %zmm14
+       vmovups -0x40(%rcx), %zmm15
+       prefetcht1 (%rsi)
+       prefetcht1 0x40(%rsi)
+       prefetcht1 0x80(%rsi)
+       prefetcht1 0xC0(%rsi)
+       prefetcht1 0x100(%rsi)
+       prefetcht1 0x140(%rsi)
+       prefetcht1 0x180(%rsi)
+       prefetcht1 0x1C0(%rsi)
+
+/* Loop with unaligned memory access.  */
+L(gobble_512bytes_loop):
+       vmovups (%rsi), %zmm0
+       vmovups 0x40(%rsi), %zmm1
+       vmovups 0x80(%rsi), %zmm2
+       vmovups 0xC0(%rsi), %zmm3
+       vmovups 0x100(%rsi), %zmm4
+       vmovups 0x140(%rsi), %zmm5
+       vmovups 0x180(%rsi), %zmm6
+       vmovups 0x1C0(%rsi), %zmm7
+       add     $512, %rsi
+       prefetcht1 (%rsi)
+       prefetcht1 0x40(%rsi)
+       prefetcht1 0x80(%rsi)
+       prefetcht1 0xC0(%rsi)
+       prefetcht1 0x100(%rsi)
+       prefetcht1 0x140(%rsi)
+       prefetcht1 0x180(%rsi)
+       prefetcht1 0x1C0(%rsi)
+       vmovups %zmm0, (%rdi)
+       vmovups %zmm1, 0x40(%rdi)
+       vmovups %zmm2, 0x80(%rdi)
+       vmovups %zmm3, 0xC0(%rdi)
+       vmovups %zmm4, 0x100(%rdi)
+       vmovups %zmm5, 0x140(%rdi)
+       vmovups %zmm6, 0x180(%rdi)
+       vmovups %zmm7, 0x1C0(%rdi)
+       add     $512, %rdi
+       cmp     %r9, %rdi
+       jb      L(gobble_512bytes_loop)
+       vmovups %zmm8, (%r9)
+       vmovups %zmm9, 0x40(%r9)
+       vmovups %zmm10, 0x80(%r9)
+       vmovups %zmm11, 0xC0(%r9)
+       vmovups %zmm12, 0x100(%r9)
+       vmovups %zmm13, 0x140(%r9)
+       vmovups %zmm14, 0x180(%r9)
+       vmovups %zmm15, 0x1C0(%r9)
+       ret
+
+L(1024bytesormore_bkw):
+       add     $512, %rdi
+       vmovups 0x1C0(%rsi), %zmm8
+       vmovups 0x180(%rsi), %zmm9
+       vmovups 0x140(%rsi), %zmm10
+       vmovups 0x100(%rsi), %zmm11
+       vmovups 0xC0(%rsi), %zmm12
+       vmovups 0x80(%rsi), %zmm13
+       vmovups 0x40(%rsi), %zmm14
+       vmovups (%rsi), %zmm15
+       prefetcht1 -0x40(%rcx)
+       prefetcht1 -0x80(%rcx)
+       prefetcht1 -0xC0(%rcx)
+       prefetcht1 -0x100(%rcx)
+       prefetcht1 -0x140(%rcx)
+       prefetcht1 -0x180(%rcx)
+       prefetcht1 -0x1C0(%rcx)
+       prefetcht1 -0x200(%rcx)
+
+/* Backward loop with unaligned memory access.  */
+L(gobble_512bytes_loop_bkw):
+       vmovups -0x40(%rcx), %zmm0
+       vmovups -0x80(%rcx), %zmm1
+       vmovups -0xC0(%rcx), %zmm2
+       vmovups -0x100(%rcx), %zmm3
+       vmovups -0x140(%rcx), %zmm4
+       vmovups -0x180(%rcx), %zmm5
+       vmovups -0x1C0(%rcx), %zmm6
+       vmovups -0x200(%rcx), %zmm7
+       sub     $512, %rcx
+       prefetcht1 -0x40(%rcx)
+       prefetcht1 -0x80(%rcx)
+       prefetcht1 -0xC0(%rcx)
+       prefetcht1 -0x100(%rcx)
+       prefetcht1 -0x140(%rcx)
+       prefetcht1 -0x180(%rcx)
+       prefetcht1 -0x1C0(%rcx)
+       prefetcht1 -0x200(%rcx)
+       vmovups %zmm0, -0x40(%r9)
+       vmovups %zmm1, -0x80(%r9)
+       vmovups %zmm2, -0xC0(%r9)
+       vmovups %zmm3, -0x100(%r9)
+       vmovups %zmm4, -0x140(%r9)
+       vmovups %zmm5, -0x180(%r9)
+       vmovups %zmm6, -0x1C0(%r9)
+       vmovups %zmm7, -0x200(%r9)
+       sub     $512, %r9
+       cmp     %rdi, %r9
+       ja      L(gobble_512bytes_loop_bkw)
+       vmovups %zmm8, -0x40(%rdi)
+       vmovups %zmm9, -0x80(%rdi)
+       vmovups %zmm10, -0xC0(%rdi)
+       vmovups %zmm11, -0x100(%rdi)
+       vmovups %zmm12, -0x140(%rdi)
+       vmovups %zmm13, -0x180(%rdi)
+       vmovups %zmm14, -0x1C0(%rdi)
+       vmovups %zmm15, -0x200(%rdi)
+       ret
+
+L(preloop_large):
+       cmp     %rsi, %rdi
+       ja      L(preloop_large_bkw)
+       vmovups (%rsi), %zmm4
+       vmovups 0x40(%rsi), %zmm5
+
+/* Align destination for access with non-temporal stores in the loop.  */
+       mov     %rdi, %r8
+       and     $-0x80, %rdi
+       add     $0x80, %rdi
+       sub     %rdi, %r8
+       sub     %r8, %rsi
+       add     %r8, %rdx
+       prefetcht1 (%rsi)
+       prefetcht1 0x40(%rsi)
+       prefetcht1 0x80(%rsi)
+       prefetcht1 0xC0(%rsi)
+L(gobble_256bytes_nt_loop):
+       prefetcht1 0x200(%rsi)
+       prefetcht1 0x240(%rsi)
+       prefetcht1 0x280(%rsi)
+       prefetcht1 0x2C0(%rsi)
+       prefetchnta 0x300(%rsi)
+       prefetchnta 0x340(%rsi)
+       prefetchnta 0x380(%rsi)
+       prefetchnta 0x3C0(%rsi)
+       vmovups (%rsi), %zmm0
+       vmovups 0x40(%rsi), %zmm1
+       vmovups 0x80(%rsi), %zmm2
+       vmovups 0xC0(%rsi), %zmm3
+       vmovntdq %zmm0, (%rdi)
+       vmovntdq %zmm1, 0x40(%rdi)
+       vmovntdq %zmm2, 0x80(%rdi)
+       vmovntdq %zmm3, 0xC0(%rdi)
+       sub     $256, %rdx
+       add     $256, %rsi
+       add     $256, %rdi
+       cmp     $256, %rdx
+       ja      L(gobble_256bytes_nt_loop)
+       sfence
+       vmovups %zmm4, (%rax)
+       vmovups %zmm5, 0x40(%rax)
+       jmp     L(check)
+
+L(preloop_large_bkw):
+       vmovups -0x80(%rcx), %zmm4
+       vmovups -0x40(%rcx), %zmm5
+
+/* Align end of destination for access with non-temporal stores.  */
+       mov     %r9, %r8
+       and     $-0x80, %r9
+       sub     %r9, %r8
+       sub     %r8, %rcx
+       sub     %r8, %rdx
+       add     %r9, %r8
+L(gobble_256bytes_nt_loop_bkw):
+       prefetcht1 -0x300(%rcx)
+       prefetcht1 -0x2C0(%rcx)
+       prefetcht1 -0x280(%rcx)
+       prefetcht1 -0x240(%rcx)
+       prefetchnta -0x400(%rcx)
+       prefetchnta -0x3C0(%rcx)
+       prefetchnta -0x380(%rcx)
+       prefetchnta -0x340(%rcx)
+       vmovups -0x100(%rcx), %zmm0
+       vmovups -0xC0(%rcx), %zmm1
+       vmovups -0x80(%rcx), %zmm2
+       vmovups -0x40(%rcx), %zmm3
+       vmovntdq %zmm0, -0x100(%r9)
+       vmovntdq %zmm1, -0xC0(%r9)
+       vmovntdq %zmm2, -0x80(%r9)
+       vmovntdq %zmm3, -0x40(%r9)
+       sub     $256, %rdx
+       sub     $256, %rcx
+       sub     $256, %r9
+       cmp     $256, %rdx
+       ja      L(gobble_256bytes_nt_loop_bkw)
+       sfence
+       vmovups %zmm4, -0x80(%r8)
+       vmovups %zmm5, -0x40(%r8)
+       jmp     L(check)
+END (MEMCPY)
+#endif