void memcopy(void *from, void *to, unsigned nbytes) {
  unsigned *src = (unsigned *)from;
  unsigned *dst = (unsigned *)to;
  unsigned nwords = nbytes / sizeof(int);
  while (nwords-- > 0)
    *dst++ = *src++;
}


x86 assembly (clang, -O0):
<memcopy>:
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)
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x14(%rbp),%eax
shr    $0x2,%rax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x2c(%rbp)
cmp    $0x0,%eax
jbe    1164 <memcopy+0x64>
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x20(%rbp)
mov    (%rax),%ecx
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0x4,%rdx
mov    %rdx,-0x28(%rbp)
mov    %ecx,(%rax)
jmp    1129 <memcopy+0x29>
pop    %rbp
ret

x86 assembly (clang, -O2):
<memcopy>:
cmp    $0x4,%edx
jb     1296 <memcopy+0x196>
shr    $0x2,%edx
lea    -0x1(%rdx),%r9d
cmp    $0x7,%r9d
jb     1221 <memcopy+0x121>
lea    (%rdi,%r9,4),%rax
add    $0x4,%rax
cmp    %rsi,%rax
jbe    1138 <memcopy+0x38>
lea    (%rsi,%r9,4),%rax
add    $0x4,%rax
cmp    %rdi,%rax
ja     1221 <memcopy+0x121>
add    $0x1,%r9
mov    %r9,%r8
and    $0xfffffffffffffff8,%r8
lea    -0x8(%r8),%rax
mov    %rax,%rcx
shr    $0x3,%rcx
add    $0x1,%rcx
mov    %ecx,%r10d
and    $0x3,%r10d
cmp    $0x18,%rax
jae    1163 <memcopy+0x63>
xor    %eax,%eax
jmp    11c8 <memcopy+0xc8>
and    $0xfffffffffffffffc,%rcx
xor    %eax,%eax
nopl   0x0(%rax)
movups (%rdi,%rax,4),%xmm0
movups 0x10(%rdi,%rax,4),%xmm1
movups %xmm0,(%rsi,%rax,4)
movups %xmm1,0x10(%rsi,%rax,4)
movups 0x20(%rdi,%rax,4),%xmm0
movups 0x30(%rdi,%rax,4),%xmm1
movups %xmm0,0x20(%rsi,%rax,4)
movups %xmm1,0x30(%rsi,%rax,4)
movups 0x40(%rdi,%rax,4),%xmm0
movups 0x50(%rdi,%rax,4),%xmm1
movups %xmm0,0x40(%rsi,%rax,4)
movups %xmm1,0x50(%rsi,%rax,4)
movups 0x60(%rdi,%rax,4),%xmm0
movups 0x70(%rdi,%rax,4),%xmm1
movups %xmm0,0x60(%rsi,%rax,4)
movups %xmm1,0x70(%rsi,%rax,4)
add    $0x20,%rax
add    $0xfffffffffffffffc,%rcx
jne    1170 <memcopy+0x70>
test   %r10,%r10
je     120d <memcopy+0x10d>
lea    (%rdi,%rax,4),%r11
add    $0x10,%r11
lea    (%rsi,%rax,4),%rax
add    $0x10,%rax
shl    $0x5,%r10
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movups -0x10(%r11,%rcx,1),%xmm0
movups (%r11,%rcx,1),%xmm1
movups %xmm0,-0x10(%rax,%rcx,1)
movups %xmm1,(%rax,%rcx,1)
add    $0x20,%rcx
cmp    %rcx,%r10
jne    11f0 <memcopy+0xf0>
cmp    %r8,%r9
je     1296 <memcopy+0x196>
sub    %r8d,%edx
lea    (%rsi,%r8,4),%rsi
lea    (%rdi,%r8,4),%rdi
lea    -0x1(%rdx),%r8d
mov    %edx,%r9d
and    $0x7,%r9d
je     1246 <memcopy+0x146>
xor    %eax,%eax
mov    (%rdi),%ecx
add    $0x4,%rdi
mov    %ecx,(%rsi)
add    $0x4,%rsi
add    $0x1,%eax
cmp    %eax,%r9d
jne    1230 <memcopy+0x130>
sub    %eax,%edx
cmp    $0x7,%r8d
jb     1296 <memcopy+0x196>
mov    %edx,%eax
xor    %ecx,%ecx
mov    (%rdi,%rcx,4),%edx
mov    %edx,(%rsi,%rcx,4)
mov    0x4(%rdi,%rcx,4),%edx
mov    %edx,0x4(%rsi,%rcx,4)
mov    0x8(%rdi,%rcx,4),%edx
mov    %edx,0x8(%rsi,%rcx,4)
mov    0xc(%rdi,%rcx,4),%edx
mov    %edx,0xc(%rsi,%rcx,4)
mov    0x10(%rdi,%rcx,4),%edx
mov    %edx,0x10(%rsi,%rcx,4)
mov    0x14(%rdi,%rcx,4),%edx
mov    %edx,0x14(%rsi,%rcx,4)
mov    0x18(%rdi,%rcx,4),%edx
mov    %edx,0x18(%rsi,%rcx,4)
mov    0x1c(%rdi,%rcx,4),%edx
mov    %edx,0x1c(%rsi,%rcx,4)
add    $0x8,%rcx
cmp    %ecx,%eax
jne    1250 <memcopy+0x150>
ret

LLVM IR (-O0):
define void @memcopy(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32*
%8 = alloca i32*
%9 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
%10 = load i8*, i8** %4
%11 = bitcast i8* %10 to i32*
store i32* %11, i32** %7
%12 = load i8*, i8** %5
%13 = bitcast i8* %12 to i32*
store i32* %13, i32** %8
%14 = load i32, i32* %6
%15 = zext i32 %14 to i64
%16 = udiv i64 %15, 4
%17 = trunc i64 %16 to i32
store i32 %17, i32* %9
br label %18
18: ; preds = %22, %3
%19 = load i32, i32* %9
%20 = add i32 %19, -1
store i32 %20, i32* %9
%21 = icmp ugt i32 %19, 0
br i1 %21, label %22, label %28
22: ; preds = %18
%23 = load i32*, i32** %7
%24 = getelementptr inbounds i32, i32* %23, i32 1
store i32* %24, i32** %7
%25 = load i32, i32* %23
%26 = load i32*, i32** %8
%27 = getelementptr inbounds i32, i32* %26, i32 1
store i32* %27, i32** %8
store i32 %25, i32* %26
br label %18
28: ; preds = %18
ret void
}

LLVM IR (-O2):
define void @memcopy(i8* nocapture %0, i8* nocapture writeonly %1, i32 %2) {
%4 = icmp ult i32 %2, 4
br i1 %4, label %159, label %5
5: ; preds = %3
%6 = lshr i32 %2, 2
%7 = bitcast i8* %1 to i32*
%8 = bitcast i8* %0 to i32*
%9 = add nsw i32 %6, -1
%10 = zext i32 %9 to i64
%11 = add nuw nsw i64 %10, 1
%12 = icmp ult i32 %9, 7
br i1 %12, label %106, label %13
13: ; preds = %5
%14 = add nsw i32 %6, -1
%15 = zext i32 %14 to i64
%16 = shl nuw nsw i64 %15, 2
%17 = add nuw nsw i64 %16, 4
%18 = getelementptr i8, i8* %1, i64 %17
%19 = getelementptr i8, i8* %0, i64 %17
%20 = icmp ugt i8* %19, %1
%21 = icmp ugt i8* %18, %0
%22 = and i1 %20, %21
br i1 %22, label %106, label %23
23: ; preds = %13
%24 = and i64 %11, 8589934584
%25 = trunc i64 %24 to i32
%26 = sub i32 %6, %25
%27 = getelementptr i32, i32* %7, i64 %24
%28 = getelementptr i32, i32* %8, i64 %24
%29 = add nsw i64 %24, -8
%30 = lshr exact i64 %29, 3
%31 = add nuw nsw i64 %30, 1
%32 = and i64 %31, 3
%33 = icmp ult i64 %29, 24
br i1 %33, label %85, label %34
34: ; preds = %23
%35 = and i64 %31, 4611686018427387900
br label %36
36: ; preds = %36, %34
%37 = phi i64 [ 0, %34 ], [ %82, %36 ]
%38 = phi i64 [ 0, %34 ], [ %83, %36 ]
%39 = getelementptr i32, i32* %7, i64 %37
%40 = getelementptr i32, i32* %8, i64 %37
%41 = bitcast i32* %40 to <4 x i32>*
%42 = load <4 x i32>, <4 x i32>* %41
%43 = getelementptr i32, i32* %40, i64 4
%44 = bitcast i32* %43 to <4 x i32>*
%45 = load <4 x i32>, <4 x i32>* %44
%46 = bitcast i32* %39 to <4 x i32>*
store <4 x i32> %42, <4 x i32>* %46
%47 = getelementptr i32, i32* %39, i64 4
%48 = bitcast i32* %47 to <4 x i32>*
store <4 x i32> %45, <4 x i32>* %48
%49 = or i64 %37, 8
%50 = getelementptr i32, i32* %7, i64 %49
%51 = getelementptr i32, i32* %8, i64 %49
%52 = bitcast i32* %51 to <4 x i32>*
%53 = load <4 x i32>, <4 x i32>* %52
%54 = getelementptr i32, i32* %51, i64 4
%55 = bitcast i32* %54 to <4 x i32>*
%56 = load <4 x i32>, <4 x i32>* %55
%57 = bitcast i32* %50 to <4 x i32>*
store <4 x i32> %53, <4 x i32>* %57
%58 = getelementptr i32, i32* %50, i64 4
%59 = bitcast i32* %58 to <4 x i32>*
store <4 x i32> %56, <4 x i32>* %59
%60 = or i64 %37, 16
%61 = getelementptr i32, i32* %7, i64 %60
%62 = getelementptr i32, i32* %8, i64 %60
%63 = bitcast i32* %62 to <4 x i32>*
%64 = load <4 x i32>, <4 x i32>* %63
%65 = getelementptr i32, i32* %62, i64 4
%66 = bitcast i32* %65 to <4 x i32>*
%67 = load <4 x i32>, <4 x i32>* %66
%68 = bitcast i32* %61 to <4 x i32>*
store <4 x i32> %64, <4 x i32>* %68
%69 = getelementptr i32, i32* %61, i64 4
%70 = bitcast i32* %69 to <4 x i32>*
store <4 x i32> %67, <4 x i32>* %70
%71 = or i64 %37, 24
%72 = getelementptr i32, i32* %7, i64 %71
%73 = getelementptr i32, i32* %8, i64 %71
%74 = bitcast i32* %73 to <4 x i32>*
%75 = load <4 x i32>, <4 x i32>* %74
%76 = getelementptr i32, i32* %73, i64 4
%77 = bitcast i32* %76 to <4 x i32>*
%78 = load <4 x i32>, <4 x i32>* %77
%79 = bitcast i32* %72 to <4 x i32>*
store <4 x i32> %75, <4 x i32>* %79
%80 = getelementptr i32, i32* %72, i64 4
%81 = bitcast i32* %80 to <4 x i32>*
store <4 x i32> %78, <4 x i32>* %81
%82 = add nuw i64 %37, 32
%83 = add i64 %38, 4
%84 = icmp eq i64 %83, %35
br i1 %84, label %85, label %36
85: ; preds = %36, %23
%86 = phi i64 [ 0, %23 ], [ %82, %36 ]
%87 = icmp eq i64 %32, 0
br i1 %87, label %104, label %88
88: ; preds = %85, %88
%89 = phi i64 [ %101, %88 ], [ %86, %85 ]
%90 = phi i64 [ %102, %88 ], [ 0, %85 ]
%91 = getelementptr i32, i32* %7, i64 %89
%92 = getelementptr i32, i32* %8, i64 %89
%93 = bitcast i32* %92 to <4 x i32>*
%94 = load <4 x i32>, <4 x i32>* %93
%95 = getelementptr i32, i32* %92, i64 4
%96 = bitcast i32* %95 to <4 x i32>*
%97 = load <4 x i32>, <4 x i32>* %96
%98 = bitcast i32* %91 to <4 x i32>*
store <4 x i32> %94, <4 x i32>* %98
%99 = getelementptr i32, i32* %91, i64 4
%100 = bitcast i32* %99 to <4 x i32>*
store <4 x i32> %97, <4 x i32>* %100
%101 = add nuw i64 %89, 8
%102 = add i64 %90, 1
%103 = icmp eq i64 %102, %32
br i1 %103, label %104, label %88
104: ; preds = %88, %85
%105 = icmp eq i64 %11, %24
br i1 %105, label %159, label %106
106: ; preds = %13, %5, %104
%107 = phi i32 [ %6, %13 ], [ %6, %5 ], [ %26, %104 ]
%108 = phi i32* [ %7, %13 ], [ %7, %5 ], [ %27, %104 ]
%109 = phi i32* [ %8, %13 ], [ %8, %5 ], [ %28, %104 ]
%110 = add i32 %107, -1
%111 = and i32 %107, 7
%112 = icmp eq i32 %111, 0
br i1 %112, label %124, label %113
113: ; preds = %106, %113
%114 = phi i32 [ %118, %113 ], [ %107, %106 ]
%115 = phi i32* [ %121, %113 ], [ %108, %106 ]
%116 = phi i32* [ %119, %113 ], [ %109, %106 ]
%117 = phi i32 [ %122, %113 ], [ 0, %106 ]
%118 = add nsw i32 %114, -1
%119 = getelementptr inbounds i32, i32* %116, i64 1
%120 = load i32, i32* %116
%121 = getelementptr inbounds i32, i32* %115, i64 1
store i32 %120, i32* %115
%122 = add i32 %117, 1
%123 = icmp eq i32 %122, %111
br i1 %123, label %124, label %113
124: ; preds = %113, %106
%125 = phi i32 [ %107, %106 ], [ %118, %113 ]
%126 = phi i32* [ %108, %106 ], [ %121, %113 ]
%127 = phi i32* [ %109, %106 ], [ %119, %113 ]
%128 = icmp ult i32 %110, 7
br i1 %128, label %159, label %129
129: ; preds = %124, %129
%130 = phi i32 [ %154, %129 ], [ %125, %124 ]
%131 = phi i32* [ %157, %129 ], [ %126, %124 ]
%132 = phi i32* [ %155, %129 ], [ %127, %124 ]
%133 = getelementptr inbounds i32, i32* %132, i64 1
%134 = load i32, i32* %132
%135 = getelementptr inbounds i32, i32* %131, i64 1
store i32 %134, i32* %131
%136 = getelementptr inbounds i32, i32* %132, i64 2
%137 = load i32, i32* %133
%138 = getelementptr inbounds i32, i32* %131, i64 2
store i32 %137, i32* %135
%139 = getelementptr inbounds i32, i32* %132, i64 3
%140 = load i32, i32* %136
%141 = getelementptr inbounds i32, i32* %131, i64 3
store i32 %140, i32* %138
%142 = getelementptr inbounds i32, i32* %132, i64 4
%143 = load i32, i32* %139
%144 = getelementptr inbounds i32, i32* %131, i64 4
store i32 %143, i32* %141
%145 = getelementptr inbounds i32, i32* %132, i64 5
%146 = load i32, i32* %142
%147 = getelementptr inbounds i32, i32* %131, i64 5
store i32 %146, i32* %144
%148 = getelementptr inbounds i32, i32* %132, i64 6
%149 = load i32, i32* %145
%150 = getelementptr inbounds i32, i32* %131, i64 6
store i32 %149, i32* %147
%151 = getelementptr inbounds i32, i32* %132, i64 7
%152 = load i32, i32* %148
%153 = getelementptr inbounds i32, i32* %131, i64 7
store i32 %152, i32* %150
%154 = add nsw i32 %130, -8
%155 = getelementptr inbounds i32, i32* %132, i64 8
%156 = load i32, i32* %151
%157 = getelementptr inbounds i32, i32* %131, i64 8
store i32 %156, i32* %153
%158 = icmp eq i32 %154, 0
br i1 %158, label %159, label %129
159: ; preds = %124, %129, %104, %3
ret void
}