void foo(int i_width, char *dst, char *src1, char *src2) {
  int x;
  for (x = 0; x < i_width; x++) {
    *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)
movl   $0x0,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1173 <foo+0x73>
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)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    111a <foo+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<foo>:
push   %rbp
push   %r14
push   %rbx
test   %edi,%edi
jle    13f3 <foo+0x2f3>
lea    -0x1(%rdi),%r8d
xor    %r9d,%r9d
cmp    $0x7,%r8d
jb     137d <foo+0x27d>
lea    (%rdx,%r8,1),%rax
add    $0x1,%rax
cmp    %rsi,%rax
seta   %r11b
lea    (%rsi,%r8,1),%rbx
add    $0x1,%rbx
cmp    %rdx,%rbx
seta   %bpl
lea    (%rcx,%r8,1),%rax
add    $0x1,%rax
cmp    %rsi,%rax
seta   %al
cmp    %rcx,%rbx
seta   %r10b
test   %bpl,%r11b
jne    137d <foo+0x27d>
and    %r10b,%al
jne    137d <foo+0x27d>
movabs $0x1fffffff0,%r9
cmp    $0xf,%r8d
jae    11ed <foo+0xed>
xor    %eax,%eax
add    $0x1,%r8
add    $0x8,%r9
and    %r8,%r9
lea    (%rcx,%r9,1),%r10
lea    (%rdx,%r9,1),%r11
lea    (%rsi,%r9,1),%rbx
pcmpeqd %xmm0,%xmm0
movdqa 0xe69(%rip),%xmm1
nopw   0x0(%rax,%rax,1)
movq   (%rdx,%rax,1),%xmm2
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movq   (%rcx,%rax,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,%rax,1)
add    $0x8,%rax
cmp    %rax,%r9
jne    11a0 <foo+0xa0>
cmp    %r9,%r8
jne    1386 <foo+0x286>
jmp    13f3 <foo+0x2f3>
lea    0x1(%r8),%r10
mov    %r10,%rax
and    %r9,%rax
lea    -0x10(%rax),%rbx
mov    %rbx,%r11
shr    $0x4,%r11
add    $0x1,%r11
test   %rbx,%rbx
je     13f8 <foo+0x2f8>
mov    %r11,%r14
and    $0xfffffffffffffffe,%r14
xor    %ebx,%ebx
pcmpeqd %xmm0,%xmm0
movdqa 0xddc(%rip),%xmm1
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movdqu (%rdx,%rbx,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movdqu (%rcx,%rbx,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,%rbx,1)
movdqu 0x10(%rdx,%rbx,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movdqu 0x10(%rcx,%rbx,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,%rbx,1)
add    $0x20,%rbx
add    $0xfffffffffffffffe,%r14
jne    1230 <foo+0x130>
test   $0x1,%r11b
je     135e <foo+0x25e>
movdqu (%rdx,%rbx,1),%xmm0
punpckhbw %xmm0,%xmm1
psraw  $0x8,%xmm1
punpcklbw %xmm0,%xmm0
psraw  $0x8,%xmm0
movdqu (%rcx,%rbx,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 0xcb3(%rip),%xmm0
pand   %xmm0,%xmm3
pand   %xmm0,%xmm1
packuswb %xmm3,%xmm1
movdqu %xmm1,(%rsi,%rbx,1)
cmp    %rax,%r10
je     13f3 <foo+0x2f3>
test   $0x8,%r10b
jne    1174 <foo+0x74>
add    %rax,%rsi
add    %rax,%rdx
add    %rax,%rcx
mov    %eax,%r9d
mov    %rcx,%r10
mov    %rdx,%r11
mov    %rsi,%rbx
mov    %edi,%ecx
sub    %r9d,%ecx
mov    %r9d,%eax
not    %eax
test   $0x1,%cl
je     13b6 <foo+0x2b6>
movsbl (%r11),%ecx
add    $0x1,%r11
movsbl (%r10),%edx
add    $0x1,%r10
add    %edx,%ecx
add    $0x1,%ecx
shr    %ecx
mov    %cl,(%rbx)
add    $0x1,%rbx
add    $0x1,%r9d
add    %edi,%eax
je     13f3 <foo+0x2f3>
sub    %r9d,%edi
xor    %eax,%eax
nop
movsbl (%r11,%rax,1),%ecx
movsbl (%r10,%rax,1),%edx
add    %edx,%ecx
add    $0x1,%ecx
shr    %ecx
mov    %cl,(%rbx,%rax,1)
movsbl 0x1(%r11,%rax,1),%ecx
movsbl 0x1(%r10,%rax,1),%edx
add    %edx,%ecx
add    $0x1,%ecx
shr    %ecx
mov    %cl,0x1(%rbx,%rax,1)
add    $0x2,%rax
cmp    %eax,%edi
jne    13c0 <foo+0x2c0>
pop    %rbx
pop    %r14
pop    %rbp
ret
xor    %ebx,%ebx
test   $0x1,%r11b
jne    12f9 <foo+0x1f9>
jmp    135e <foo+0x25e>

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 i32
store i32 %0, i32* %5
store i8* %1, i8** %6
store i8* %2, i8** %7
store i8* %3, i8** %8
store i32 0, i32* %9
br label %10
10: ; preds = %29, %4
%11 = load i32, i32* %9
%12 = load i32, i32* %5
%13 = icmp slt i32 %11, %12
br i1 %13, label %14, label %32
14: ; preds = %10
%15 = load i8*, i8** %7
%16 = getelementptr inbounds i8, i8* %15, i32 1
store i8* %16, i8** %7
%17 = load i8, i8* %15
%18 = sext i8 %17 to i32
%19 = load i8*, i8** %8
%20 = getelementptr inbounds i8, i8* %19, i32 1
store i8* %20, i8** %8
%21 = load i8, i8* %19
%22 = sext i8 %21 to i32
%23 = add nsw i32 %18, %22
%24 = add nsw i32 %23, 1
%25 = ashr i32 %24, 1
%26 = trunc i32 %25 to i8
%27 = load i8*, i8** %6
%28 = getelementptr inbounds i8, i8* %27, i32 1
store i8* %28, i8** %6
store i8 %26, i8* %27
br label %29
29: ; preds = %14
%30 = load i32, i32* %9
%31 = add nsw i32 %30, 1
store i32 %31, i32* %9
br label %10
32: ; preds = %10
ret void
}

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