void foo(int i_width, char *dst, char *src1, char *src2) {
  char *dstn = dst + i_width;
  for (; dst < dstn;) {
    *dst++ = (*src1++ + *src2++ + 1) >> 1;
  }
}


x86 assembly (clang, -O0):
<foo>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x4(%rbp),%rcx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rax
cmp    -0x28(%rbp),%rax
jae    1174 <foo+0x74>
mov    -0x18(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x18(%rbp)
movsbl (%rax),%eax
mov    -0x20(%rbp),%rcx
mov    %rcx,%rdx
add    $0x1,%rdx
mov    %rdx,-0x20(%rbp)
movsbl (%rcx),%ecx
add    %ecx,%eax
add    $0x1,%eax
sar    $0x1,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
jmp    1122 <foo+0x22>
pop    %rbp
ret

x86 assembly (clang, -O2):
<foo>:
push   %r14
push   %rbx
test   %edi,%edi
jle    13c3 <foo+0x2c3>
movslq %edi,%r10
add    %rsi,%r10
lea    0x1(%rsi),%r8
cmp    %r8,%r10
mov    %r8,%r9
cmova  %r10,%r9
sub    %rsi,%r9
cmp    $0x8,%r9
jb     1386 <foo+0x286>
cmp    %r8,%r10
mov    %r8,%rdi
cmova  %r10,%rdi
mov    %rdi,%rax
sub    %rsi,%rax
lea    (%rdx,%rax,1),%rbx
add    %rcx,%rax
cmp    %rsi,%rbx
seta   %r11b
cmp    %rdx,%rdi
seta   %bl
cmp    %rsi,%rax
seta   %al
cmp    %rcx,%rdi
seta   %dil
test   %bl,%r11b
jne    1386 <foo+0x286>
and    %dil,%al
jne    1386 <foo+0x286>
cmp    $0x10,%r9
jae    1200 <foo+0x100>
xor    %r14d,%r14d
cmp    %r8,%r10
cmova  %r10,%r8
sub    %rsi,%r8
mov    %r8,%r9
and    $0xfffffffffffffff8,%r9
lea    (%rsi,%r9,1),%rax
lea    (%rcx,%r9,1),%rbx
lea    (%rdx,%r9,1),%rdi
pcmpeqd %xmm0,%xmm0
movdqa 0xe5b(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
nop
movq   (%rdx,%r14,1),%xmm2
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movq   (%rcx,%r14,1),%xmm3
punpcklbw %xmm3,%xmm3
psraw  $0x8,%xmm3
paddw  %xmm2,%xmm3
psubw  %xmm0,%xmm3
psrlw  $0x1,%xmm3
pand   %xmm1,%xmm3
packuswb %xmm3,%xmm3
movq   %xmm3,(%rsi,%r14,1)
add    $0x8,%r14
cmp    %r14,%r9
jne    11b0 <foo+0xb0>
cmp    %r9,%r8
jne    138f <foo+0x28f>
jmp    13c3 <foo+0x2c3>
mov    %r9,%r14
and    $0xfffffffffffffff0,%r14
lea    -0x10(%r14),%rax
mov    %rax,%r11
shr    $0x4,%r11
add    $0x1,%r11
test   %rax,%rax
je     13c7 <foo+0x2c7>
mov    %r11,%rbx
and    $0xfffffffffffffffe,%rbx
xor    %eax,%eax
pcmpeqd %xmm0,%xmm0
movdqa 0xdcc(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movdqu (%rdx,%rax,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movdqu (%rcx,%rax,1),%xmm4
punpckhbw %xmm4,%xmm5
psraw  $0x8,%xmm5
paddw  %xmm3,%xmm5
punpcklbw %xmm4,%xmm3
psraw  $0x8,%xmm3
paddw  %xmm2,%xmm3
psubw  %xmm0,%xmm5
psubw  %xmm0,%xmm3
psrlw  $0x1,%xmm3
psrlw  $0x1,%xmm5
pand   %xmm1,%xmm5
pand   %xmm1,%xmm3
packuswb %xmm5,%xmm3
movdqu %xmm3,(%rsi,%rax,1)
movdqu 0x10(%rdx,%rax,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movdqu 0x10(%rcx,%rax,1),%xmm4
punpckhbw %xmm4,%xmm5
psraw  $0x8,%xmm5
paddw  %xmm3,%xmm5
punpcklbw %xmm4,%xmm3
psraw  $0x8,%xmm3
paddw  %xmm2,%xmm3
psubw  %xmm0,%xmm5
psubw  %xmm0,%xmm3
psrlw  $0x1,%xmm3
psrlw  $0x1,%xmm5
pand   %xmm1,%xmm5
pand   %xmm1,%xmm3
packuswb %xmm5,%xmm3
movdqu %xmm3,0x10(%rsi,%rax,1)
add    $0x20,%rax
add    $0xfffffffffffffffe,%rbx
jne    1240 <foo+0x140>
test   $0x1,%r11b
je     136e <foo+0x26e>
movdqu (%rdx,%rax,1),%xmm0
punpckhbw %xmm0,%xmm1
psraw  $0x8,%xmm1
punpcklbw %xmm0,%xmm0
psraw  $0x8,%xmm0
movdqu (%rcx,%rax,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
paddw  %xmm1,%xmm3
punpcklbw %xmm2,%xmm1
psraw  $0x8,%xmm1
paddw  %xmm0,%xmm1
pcmpeqd %xmm0,%xmm0
psubw  %xmm0,%xmm3
psubw  %xmm0,%xmm1
psrlw  $0x1,%xmm1
psrlw  $0x1,%xmm3
movdqa 0xca3(%rip),%xmm0
pand   %xmm0,%xmm3
pand   %xmm0,%xmm1
packuswb %xmm3,%xmm1
movdqu %xmm1,(%rsi,%rax,1)
cmp    %r14,%r9
je     13c3 <foo+0x2c3>
test   $0x8,%r9b
jne    117c <foo+0x7c>
add    %r14,%rdx
add    %r14,%rcx
add    %r14,%rsi
mov    %rsi,%rax
mov    %rcx,%rbx
mov    %rdx,%rdi
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movsbl (%rdi,%rcx,1),%edx
movsbl (%rbx,%rcx,1),%esi
add    %esi,%edx
add    $0x1,%edx
shr    %edx
mov    %dl,(%rax,%rcx,1)
lea    (%rax,%rcx,1),%rdx
add    $0x1,%rdx
add    $0x1,%rcx
cmp    %r10,%rdx
jb     13a0 <foo+0x2a0>
pop    %rbx
pop    %r14
ret
xor    %eax,%eax
test   $0x1,%r11b
jne    1309 <foo+0x209>
jmp    136e <foo+0x26e>

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

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