void f(unsigned char *p, short *s, int c) {
  short or = 0;
  while (c) {
    or = or | s[c];
    c--;
  }
  *p = (unsigned char) or ;
}


x86 assembly (clang, -O0):
<f>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movw   $0x0,-0x16(%rbp)
cmpl   $0x0,-0x14(%rbp)
je     1143 <f+0x43>
movswl -0x16(%rbp),%eax
mov    -0x10(%rbp),%rcx
movslq -0x14(%rbp),%rdx
movswl (%rcx,%rdx,2),%ecx
or     %ecx,%eax
mov    %ax,-0x16(%rbp)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
jmp    1115 <f+0x15>
mov    -0x16(%rbp),%ax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %cl,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<f>:
test   %edx,%edx
je     1116 <f+0x16>
movslq %edx,%rax
add    $0xffffffff,%edx
cmp    $0xf,%edx
jae    111b <f+0x1b>
xor    %ecx,%ecx
jmp    1250 <f+0x150>
xor    %ecx,%ecx
mov    %cl,(%rdi)
ret
add    $0x1,%rdx
mov    %rdx,%r8
and    $0xfffffffffffffff0,%r8
lea    -0x10(%r8),%rcx
mov    %rcx,%r9
shr    $0x4,%r9
add    $0x1,%r9
test   %rcx,%rcx
je     125f <f+0x15f>
mov    %r9,%r10
and    $0xfffffffffffffffe,%r10
lea    (%rsi,%rax,2),%r11
add    $0xfffffffffffffff2,%r11
pxor   %xmm0,%xmm0
xor    %ecx,%ecx
pxor   %xmm1,%xmm1
nopw   0x0(%rax,%rax,1)
movdqu -0x30(%r11,%rcx,2),%xmm2
movdqu -0x20(%r11,%rcx,2),%xmm3
movdqu -0x10(%r11,%rcx,2),%xmm4
movdqu (%r11,%rcx,2),%xmm5
pshufd $0x4e,%xmm5,%xmm5
pshuflw $0x1b,%xmm5,%xmm5
pshufhw $0x1b,%xmm5,%xmm5
por    %xmm0,%xmm5
pshufd $0x4e,%xmm4,%xmm0
pshuflw $0x1b,%xmm0,%xmm0
pshufhw $0x1b,%xmm0,%xmm4
por    %xmm1,%xmm4
pshufd $0x4e,%xmm3,%xmm0
pshuflw $0x1b,%xmm0,%xmm0
pshufhw $0x1b,%xmm0,%xmm0
por    %xmm5,%xmm0
pshufd $0x4e,%xmm2,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
por    %xmm4,%xmm1
add    $0xffffffffffffffe0,%rcx
add    $0xfffffffffffffffe,%r10
jne    1160 <f+0x60>
neg    %rcx
test   $0x1,%r9b
je     1214 <f+0x114>
mov    %rax,%r9
sub    %rcx,%r9
movdqu -0x1e(%rsi,%r9,2),%xmm2
movdqu -0xe(%rsi,%r9,2),%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
por    %xmm3,%xmm0
pshufd $0x4e,%xmm2,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
pshufhw $0x1b,%xmm2,%xmm2
por    %xmm2,%xmm1
por    %xmm1,%xmm0
pshufd $0xee,%xmm0,%xmm1
por    %xmm0,%xmm1
pshufd $0x55,%xmm1,%xmm0
por    %xmm1,%xmm0
movdqa %xmm0,%xmm1
psrld  $0x10,%xmm1
por    %xmm0,%xmm1
movd   %xmm1,%ecx
cmp    %r8,%rdx
je     125c <f+0x15c>
sub    %r8,%rax
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
or     (%rsi,%rax,2),%cx
add    $0xffffffffffffffff,%rax
test   %eax,%eax
jne    1250 <f+0x150>
mov    %cl,(%rdi)
ret
pxor   %xmm0,%xmm0
xor    %ecx,%ecx
pxor   %xmm1,%xmm1
test   $0x1,%r9b
jne    11da <f+0xda>
jmp    1214 <f+0x114>

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

LLVM IR (-O2):
define void @f(i8* nocapture writeonly %0, i16* nocapture %1, i32 %2) {
%4 = icmp eq i32 %2, 0
br i1 %4, label %98, label %5
5: ; preds = %3
%6 = sext i32 %2 to i64
%7 = add i32 %2, -1
%8 = zext i32 %7 to i64
%9 = add nuw nsw i64 %8, 1
%10 = icmp ult i32 %7, 15
br i1 %10, label %83, label %11
11: ; preds = %5
%12 = and i64 %9, 8589934576
%13 = sub nsw i64 %6, %12
%14 = add nsw i64 %12, -16
%15 = lshr exact i64 %14, 4
%16 = add nuw nsw i64 %15, 1
%17 = and i64 %16, 1
%18 = icmp eq i64 %14, 0
br i1 %18, label %56, label %19
19: ; preds = %11
%20 = and i64 %16, 2305843009213693950
br label %21
21: ; preds = %21, %19
%22 = phi i64 [ 0, %19 ], [ %53, %21 ]
%23 = phi <8 x i16> [ zeroinitializer, %19 ], [ %51, %21 ]
%24 = phi <8 x i16> [ zeroinitializer, %19 ], [ %52, %21 ]
%25 = phi i64 [ 0, %19 ], [ %54, %21 ]
%26 = sub i64 %6, %22
%27 = getelementptr inbounds i16, i16* %1, i64 %26
%28 = getelementptr inbounds i16, i16* %27, i64 -7
%29 = bitcast i16* %28 to <8 x i16>*
%30 = load <8 x i16>, <8 x i16>* %29
%31 = shufflevector <8 x i16> %30, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%32 = getelementptr inbounds i16, i16* %27, i64 -8
%33 = getelementptr inbounds i16, i16* %32, i64 -7
%34 = bitcast i16* %33 to <8 x i16>*
%35 = load <8 x i16>, <8 x i16>* %34
%36 = shufflevector <8 x i16> %35, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%37 = or <8 x i16> %31, %23
%38 = or <8 x i16> %36, %24
%39 = or i64 %22, 16
%40 = sub i64 %6, %39
%41 = getelementptr inbounds i16, i16* %1, i64 %40
%42 = getelementptr inbounds i16, i16* %41, i64 -7
%43 = bitcast i16* %42 to <8 x i16>*
%44 = load <8 x i16>, <8 x i16>* %43
%45 = shufflevector <8 x i16> %44, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%46 = getelementptr inbounds i16, i16* %41, i64 -8
%47 = getelementptr inbounds i16, i16* %46, i64 -7
%48 = bitcast i16* %47 to <8 x i16>*
%49 = load <8 x i16>, <8 x i16>* %48
%50 = shufflevector <8 x i16> %49, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%51 = or <8 x i16> %45, %37
%52 = or <8 x i16> %50, %38
%53 = add nuw i64 %22, 32
%54 = add i64 %25, 2
%55 = icmp eq i64 %54, %20
br i1 %55, label %56, label %21
56: ; preds = %21, %11
%57 = phi <8 x i16> [ undef, %11 ], [ %51, %21 ]
%58 = phi <8 x i16> [ undef, %11 ], [ %52, %21 ]
%59 = phi i64 [ 0, %11 ], [ %53, %21 ]
%60 = phi <8 x i16> [ zeroinitializer, %11 ], [ %51, %21 ]
%61 = phi <8 x i16> [ zeroinitializer, %11 ], [ %52, %21 ]
%62 = icmp eq i64 %17, 0
br i1 %62, label %77, label %63
63: ; preds = %56
%64 = sub i64 %6, %59
%65 = getelementptr inbounds i16, i16* %1, i64 %64
%66 = getelementptr inbounds i16, i16* %65, i64 -7
%67 = bitcast i16* %66 to <8 x i16>*
%68 = load <8 x i16>, <8 x i16>* %67
%69 = shufflevector <8 x i16> %68, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%70 = getelementptr inbounds i16, i16* %65, i64 -8
%71 = getelementptr inbounds i16, i16* %70, i64 -7
%72 = bitcast i16* %71 to <8 x i16>*
%73 = load <8 x i16>, <8 x i16>* %72
%74 = shufflevector <8 x i16> %73, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%75 = or <8 x i16> %69, %60
%76 = or <8 x i16> %74, %61
br label %77
77: ; preds = %56, %63
%78 = phi <8 x i16> [ %57, %56 ], [ %75, %63 ]
%79 = phi <8 x i16> [ %58, %56 ], [ %76, %63 ]
%80 = or <8 x i16> %79, %78
%81 = call i16 @llvm.vector.reduce.or.v8i16(<8 x i16> %80)
%82 = icmp eq i64 %9, %12
br i1 %82, label %95, label %83
83: ; preds = %5, %77
%84 = phi i64 [ %6, %5 ], [ %13, %77 ]
%85 = phi i16 [ 0, %5 ], [ %81, %77 ]
br label %86
86: ; preds = %83, %86
%87 = phi i64 [ %92, %86 ], [ %84, %83 ]
%88 = phi i16 [ %91, %86 ], [ %85, %83 ]
%89 = getelementptr inbounds i16, i16* %1, i64 %87
%90 = load i16, i16* %89
%91 = or i16 %90, %88
%92 = add nsw i64 %87, -1
%93 = trunc i64 %92 to i32
%94 = icmp eq i32 %93, 0
br i1 %94, label %95, label %86
95: ; preds = %86, %77
%96 = phi i16 [ %81, %77 ], [ %91, %86 ]
%97 = trunc i16 %96 to i8
br label %98
98: ; preds = %95, %3
%99 = phi i8 [ 0, %3 ], [ %97, %95 ]
store i8 %99, i8* %0
ret void
}