void memrcpy(unsigned char *out, unsigned char *in, unsigned n) {
  int i;
  for (i = 0; i < n; i++)
    out[i] = ~in[i];
}


x86 assembly (clang, -O0):
<memrcpy>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jae    114c <memrcpy+0x4c>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
xor    $0xffffffff,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1116 <memrcpy+0x16>
pop    %rbp
ret

x86 assembly (clang, -O2):
<memrcpy>:
test   %edx,%edx
je     1193 <memrcpy+0x93>
mov    %edx,%r9d
cmp    $0x8,%edx
jb     1122 <memrcpy+0x22>
lea    (%rsi,%r9,1),%rax
cmp    %rdi,%rax
jbe    1194 <memrcpy+0x94>
lea    (%rdi,%r9,1),%rax
cmp    %rsi,%rax
jbe    1194 <memrcpy+0x94>
xor    %ecx,%ecx
mov    %rcx,%r8
not    %r8
add    %r9,%r8
mov    %r9,%rdx
and    $0x3,%rdx
je     1153 <memrcpy+0x53>
cs nopw 0x0(%rax,%rax,1)
movzbl (%rsi,%rcx,1),%eax
not    %al
mov    %al,(%rdi,%rcx,1)
add    $0x1,%rcx
add    $0xffffffffffffffff,%rdx
jne    1140 <memrcpy+0x40>
cmp    $0x3,%r8
jb     1193 <memrcpy+0x93>
nopl   0x0(%rax)
movzbl (%rsi,%rcx,1),%eax
not    %al
mov    %al,(%rdi,%rcx,1)
movzbl 0x1(%rsi,%rcx,1),%eax
not    %al
mov    %al,0x1(%rdi,%rcx,1)
movzbl 0x2(%rsi,%rcx,1),%eax
not    %al
mov    %al,0x2(%rdi,%rcx,1)
movzbl 0x3(%rsi,%rcx,1),%eax
not    %al
mov    %al,0x3(%rdi,%rcx,1)
add    $0x4,%rcx
cmp    %rcx,%r9
jne    1160 <memrcpy+0x60>
ret
cmp    $0x20,%edx
jae    11a0 <memrcpy+0xa0>
xor    %ecx,%ecx
jmp    1253 <memrcpy+0x153>
mov    %r9d,%ecx
and    $0xffffffe0,%ecx
lea    -0x20(%rcx),%rax
mov    %rax,%r8
shr    $0x5,%r8
add    $0x1,%r8
test   %rax,%rax
je     1285 <memrcpy+0x185>
mov    %r8,%rax
and    $0xfffffffffffffffe,%rax
xor    %edx,%edx
pcmpeqd %xmm0,%xmm0
nopl   0x0(%rax,%rax,1)
movdqu (%rsi,%rdx,1),%xmm1
movdqu 0x10(%rsi,%rdx,1),%xmm2
pxor   %xmm0,%xmm1
pxor   %xmm0,%xmm2
movdqu %xmm1,(%rdi,%rdx,1)
movdqu %xmm2,0x10(%rdi,%rdx,1)
movdqu 0x20(%rsi,%rdx,1),%xmm1
movdqu 0x30(%rsi,%rdx,1),%xmm2
pxor   %xmm0,%xmm1
pxor   %xmm0,%xmm2
movdqu %xmm1,0x20(%rdi,%rdx,1)
movdqu %xmm2,0x30(%rdi,%rdx,1)
add    $0x40,%rdx
add    $0xfffffffffffffffe,%rax
jne    11d0 <memrcpy+0xd0>
test   $0x1,%r8b
je     1240 <memrcpy+0x140>
movdqu (%rsi,%rdx,1),%xmm0
movdqu 0x10(%rsi,%rdx,1),%xmm1
pcmpeqd %xmm2,%xmm2
pxor   %xmm2,%xmm0
pxor   %xmm2,%xmm1
movdqu %xmm0,(%rdi,%rdx,1)
movdqu %xmm1,0x10(%rdi,%rdx,1)
cmp    %r9,%rcx
je     1193 <memrcpy+0x93>
test   $0x18,%r9b
je     1124 <memrcpy+0x24>
mov    %rcx,%rax
mov    %r9d,%ecx
and    $0xfffffff8,%ecx
pcmpeqd %xmm0,%xmm0
movq   (%rsi,%rax,1),%xmm1
pxor   %xmm0,%xmm1
movq   %xmm1,(%rdi,%rax,1)
add    $0x8,%rax
cmp    %rax,%rcx
jne    1260 <memrcpy+0x160>
cmp    %r9,%rcx
je     1193 <memrcpy+0x93>
jmp    1124 <memrcpy+0x24>
xor    %edx,%edx
test   $0x1,%r8b
jne    121e <memrcpy+0x11e>
jmp    1240 <memrcpy+0x140>

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

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