void foo(int i_width, char *dst, char *src1, char *src2) {
  int x;
  for (x = 0; x < i_width; x++) {
    dst[x] = (src1[x] + src2[x] + 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    1161 <foo+0x61>
mov    -0x18(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
mov    -0x20(%rbp),%rcx
movslq -0x24(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
add    %ecx,%eax
add    $0x1,%eax
sar    $0x1,%eax
mov    %al,%dl
mov    -0x10(%rbp),%rax
movslq -0x24(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    111a <foo+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<foo>:
push   %rbx
test   %edi,%edi
jle    1172 <foo+0x72>
mov    %edi,%r8d
cmp    $0x8,%edi
jae    1174 <foo+0x74>
xor    %eax,%eax
mov    %rax,%rdi
not    %rdi
test   $0x1,%r8b
je     1133 <foo+0x33>
movsbl (%rdx,%rax,1),%r9d
movsbl (%rcx,%rax,1),%ebx
add    %r9d,%ebx
add    $0x1,%ebx
shr    %ebx
mov    %bl,(%rsi,%rax,1)
or     $0x1,%rax
add    %r8,%rdi
je     1172 <foo+0x72>
nopl   0x0(%rax,%rax,1)
movsbl (%rdx,%rax,1),%edi
movsbl (%rcx,%rax,1),%ebx
add    %ebx,%edi
add    $0x1,%edi
shr    %edi
mov    %dil,(%rsi,%rax,1)
movsbl 0x1(%rdx,%rax,1),%edi
movsbl 0x1(%rcx,%rax,1),%ebx
add    %ebx,%edi
add    $0x1,%edi
shr    %edi
mov    %dil,0x1(%rsi,%rax,1)
add    $0x2,%rax
cmp    %rax,%r8
jne    1140 <foo+0x40>
pop    %rbx
ret
lea    (%rsi,%r8,1),%r10
lea    (%rdx,%r8,1),%rax
cmp    %rsi,%rax
seta   %r11b
lea    (%rcx,%r8,1),%rax
cmp    %rdx,%r10
seta   %bl
cmp    %rsi,%rax
seta   %r9b
cmp    %rcx,%r10
seta   %r10b
xor    %eax,%eax
test   %bl,%r11b
jne    110f <foo+0xf>
and    %r10b,%r9b
jne    110f <foo+0xf>
cmp    $0x10,%edi
jae    121d <foo+0x11d>
xor    %eax,%eax
mov    %rax,%rdi
mov    %r8d,%eax
and    $0xfffffff8,%eax
pcmpeqd %xmm0,%xmm0
movdqa 0xe35(%rip),%xmm1
nopl   0x0(%rax,%rax,1)
movq   (%rdx,%rdi,1),%xmm2
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movq   (%rcx,%rdi,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,%rdi,1)
add    $0x8,%rdi
cmp    %rdi,%rax
jne    11d0 <foo+0xd0>
cmp    %r8,%rax
jne    110f <foo+0xf>
jmp    1172 <foo+0x72>
mov    %r8d,%eax
and    $0xfffffff0,%eax
lea    -0x10(%rax),%rdi
mov    %rdi,%r9
shr    $0x4,%r9
add    $0x1,%r9
test   %rdi,%rdi
je     1396 <foo+0x296>
mov    %r9,%r10
and    $0xfffffffffffffffe,%r10
xor    %edi,%edi
pcmpeqd %xmm0,%xmm0
movdqa 0xdb0(%rip),%xmm1
movdqu (%rdx,%rdi,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movdqu (%rcx,%rdi,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,%rdi,1)
movdqu 0x10(%rdx,%rdi,1),%xmm2
punpckhbw %xmm2,%xmm3
psraw  $0x8,%xmm3
punpcklbw %xmm2,%xmm2
psraw  $0x8,%xmm2
movdqu 0x10(%rcx,%rdi,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,%rdi,1)
add    $0x20,%rdi
add    $0xfffffffffffffffe,%r10
jne    1250 <foo+0x150>
test   $0x1,%r9b
je     137e <foo+0x27e>
movdqu (%rdx,%rdi,1),%xmm0
punpckhbw %xmm0,%xmm1
psraw  $0x8,%xmm1
punpcklbw %xmm0,%xmm0
psraw  $0x8,%xmm0
movdqu (%rcx,%rdi,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 0xc93(%rip),%xmm0
pand   %xmm0,%xmm3
pand   %xmm0,%xmm1
packuswb %xmm3,%xmm1
movdqu %xmm1,(%rsi,%rdi,1)
cmp    %r8,%rax
je     1172 <foo+0x72>
test   $0x8,%r8b
je     110f <foo+0xf>
jmp    11b6 <foo+0xb6>
xor    %edi,%edi
test   $0x1,%r9b
jne    1319 <foo+0x219>
jmp    137e <foo+0x27e>

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