__attribute__((unused)) void *memcpy(void *dest, const void *src,
                                     unsigned int n) {
  void *tmp = dest;
  unsigned int i0, i1, i2;
  asm volatile("cld" ::: "memory");
  if (n % 4) {
    asm volatile("rep movsb"
                 : "=&S"(i0), "=&D"(i1), "=&c"(i2)
                 : "0"(src), "1"(dest), "2"(n));
  } else {
    asm volatile("rep movsl"
                 : "=&S"(i0), "=&D"(i1), "=&c"(i2)
                 : "0"(src), "1"(dest), "2"(n / 4));
  }
  return tmp;
}


x86 assembly (clang, -O0):
<memcpy>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
cld
mov    -0x14(%rbp),%eax
and    $0x3,%eax
cmp    $0x0,%eax
je     1146 <memcpy+0x46>
mov    -0x10(%rbp),%rsi
mov    -0x8(%rbp),%rdi
mov    -0x14(%rbp),%ecx
rep movsb %ds:(%rsi),%es:(%rdi)
mov    %esi,%eax
mov    %eax,-0x24(%rbp)
mov    %edi,%eax
mov    %eax,-0x28(%rbp)
mov    %ecx,-0x2c(%rbp)
jmp    1163 <memcpy+0x63>
mov    -0x10(%rbp),%rsi
mov    -0x8(%rbp),%rdi
mov    -0x14(%rbp),%ecx
shr    $0x2,%ecx
rep movsl %ds:(%rsi),%es:(%rdi)
mov    %esi,%eax
mov    %eax,-0x24(%rbp)
mov    %edi,%eax
mov    %eax,-0x28(%rbp)
mov    %ecx,-0x2c(%rbp)
mov    -0x20(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<memcpy>:
mov    %edx,%ecx
mov    %rdi,%rax
cld
test   $0x3,%cl
je     1111 <memcpy+0x11>
mov    %rax,%rdi
rep movsb %ds:(%rsi),%es:(%rdi)
ret
shr    $0x2,%ecx
mov    %rax,%rdi
rep movsl %ds:(%rsi),%es:(%rdi)
ret

LLVM IR (-O0):
define i8* @memcpy(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i8*
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%11 = load i8*, i8** %4
store i8* %11, i8** %7
%12 = load i32, i32* %6
%13 = urem i32 %12, 4
%14 = icmp ne i32 %13, 0
br i1 %14, label %15, label %27
15: ; preds = %3
%16 = load i8*, i8** %5
%17 = load i8*, i8** %4
%18 = load i32, i32* %6
%19 = call { i8*, i8*, i32 } asm sideeffect "rep movsb", "=&{si},=&{di},=&{cx},0,1,2,~{dirflag},~{fpsr},~{flags}"(i8* %16, i8* %17, i32 %18)
%20 = extractvalue { i8*, i8*, i32 } %19, 0
%21 = extractvalue { i8*, i8*, i32 } %19, 1
%22 = extractvalue { i8*, i8*, i32 } %19, 2
%23 = ptrtoint i8* %20 to i64
%24 = trunc i64 %23 to i32
store i32 %24, i32* %8
%25 = ptrtoint i8* %21 to i64
%26 = trunc i64 %25 to i32
store i32 %26, i32* %9
store i32 %22, i32* %10
br label %40
27: ; preds = %3
%28 = load i8*, i8** %5
%29 = load i8*, i8** %4
%30 = load i32, i32* %6
%31 = udiv i32 %30, 4
%32 = call { i8*, i8*, i32 } asm sideeffect "rep movsl", "=&{si},=&{di},=&{cx},0,1,2,~{dirflag},~{fpsr},~{flags}"(i8* %28, i8* %29, i32 %31)
%33 = extractvalue { i8*, i8*, i32 } %32, 0
%34 = extractvalue { i8*, i8*, i32 } %32, 1
%35 = extractvalue { i8*, i8*, i32 } %32, 2
%36 = ptrtoint i8* %33 to i64
%37 = trunc i64 %36 to i32
store i32 %37, i32* %8
%38 = ptrtoint i8* %34 to i64
%39 = trunc i64 %38 to i32
store i32 %39, i32* %9
store i32 %35, i32* %10
br label %40
40: ; preds = %27, %15
%41 = load i8*, i8** %7
ret i8* %41
}

LLVM IR (-O2):
define i8* @memcpy(i8* returned %0, i8* %1, i32 %2) {
tail call void asm sideeffect "cld", "~{memory},~{dirflag},~{fpsr},~{flags}"()
%4 = and i32 %2, 3
%5 = icmp eq i32 %4, 0
br i1 %5, label %8, label %6
6: ; preds = %3
%7 = tail call { i8*, i8*, i32 } asm sideeffect "rep movsb", "=&{si},=&{di},=&{cx},0,1,2,~{dirflag},~{fpsr},~{flags}"(i8* %1, i8* %0, i32 %2)
br label %11
8: ; preds = %3
%9 = lshr i32 %2, 2
%10 = tail call { i8*, i8*, i32 } asm sideeffect "rep movsl", "=&{si},=&{di},=&{cx},0,1,2,~{dirflag},~{fpsr},~{flags}"(i8* %1, i8* %0, i32 %9)
br label %11
11: ; preds = %8, %6
ret i8* %0
}