int card(const char *array, int size) {
  const char *end = array + size;
  int i = 0;
  while (array < end)
    if (*array++)
      i++;
  return (i);
}


x86 assembly (clang, -O0):
<card>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
add    %rcx,%rax
mov    %rax,-0x18(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x8(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    1155 <card+0x55>
mov    -0x8(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x8(%rbp)
cmpb   $0x0,(%rax)
je     1150 <card+0x50>
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1121 <card+0x21>
mov    -0x1c(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<card>:
test   %esi,%esi
jle    1283 <card+0x183>
movslq %esi,%rcx
add    %rdi,%rcx
lea    0x1(%rdi),%rdx
cmp    %rdx,%rcx
cmova  %rcx,%rdx
sub    %rdi,%rdx
xor    %eax,%eax
cmp    $0x8,%rdx
jb     1270 <card+0x170>
mov    %rdx,%r8
and    $0xfffffffffffffff8,%r8
lea    -0x8(%r8),%rax
mov    %rax,%r9
shr    $0x3,%r9
add    $0x1,%r9
test   %rax,%rax
je     1286 <card+0x186>
mov    %r9,%rax
and    $0xfffffffffffffffe,%rax
pxor   %xmm2,%xmm2
xor    %esi,%esi
pcmpeqd %xmm3,%xmm3
movdqa 0xea0(%rip),%xmm4
pxor   %xmm0,%xmm0
pxor   %xmm1,%xmm1
nopl   0x0(%rax,%rax,1)
movd   (%rdi,%rsi,1),%xmm6
movd   0x4(%rdi,%rsi,1),%xmm5
pcmpeqb %xmm2,%xmm6
pxor   %xmm3,%xmm6
punpcklbw %xmm6,%xmm6
punpcklwd %xmm6,%xmm6
pand   %xmm4,%xmm6
paddd  %xmm0,%xmm6
pcmpeqb %xmm2,%xmm5
pxor   %xmm3,%xmm5
punpcklbw %xmm5,%xmm5
punpcklwd %xmm5,%xmm5
pand   %xmm4,%xmm5
paddd  %xmm1,%xmm5
movd   0x8(%rdi,%rsi,1),%xmm0
movd   0xc(%rdi,%rsi,1),%xmm1
pcmpeqb %xmm2,%xmm0
pxor   %xmm3,%xmm0
punpcklbw %xmm0,%xmm0
punpcklwd %xmm0,%xmm0
pand   %xmm4,%xmm0
paddd  %xmm6,%xmm0
pcmpeqb %xmm2,%xmm1
pxor   %xmm3,%xmm1
punpcklbw %xmm1,%xmm1
punpcklwd %xmm1,%xmm1
pand   %xmm4,%xmm1
paddd  %xmm5,%xmm1
add    $0x10,%rsi
add    $0xfffffffffffffffe,%rax
jne    1170 <card+0x70>
test   $0x1,%r9b
je     1246 <card+0x146>
movd   (%rdi,%rsi,1),%xmm2
movd   0x4(%rdi,%rsi,1),%xmm3
pxor   %xmm4,%xmm4
pcmpeqb %xmm4,%xmm2
pcmpeqd %xmm5,%xmm5
pxor   %xmm5,%xmm2
punpcklbw %xmm2,%xmm2
punpcklwd %xmm2,%xmm2
movdqa 0xdda(%rip),%xmm6
pand   %xmm6,%xmm2
paddd  %xmm2,%xmm0
pcmpeqb %xmm4,%xmm3
pxor   %xmm5,%xmm3
punpcklbw %xmm3,%xmm3
punpcklwd %xmm3,%xmm3
pand   %xmm6,%xmm3
paddd  %xmm3,%xmm1
paddd  %xmm1,%xmm0
pshufd $0xee,%xmm0,%xmm1
paddd  %xmm0,%xmm1
pshufd $0x55,%xmm1,%xmm0
paddd  %xmm1,%xmm0
movd   %xmm0,%eax
cmp    %r8,%rdx
je     1282 <card+0x182>
add    %r8,%rdi
nopl   0x0(%rax,%rax,1)
cmpb   $0x1,(%rdi)
lea    0x1(%rdi),%rdx
sbb    $0xffffffff,%eax
mov    %rdx,%rdi
cmp    %rcx,%rdx
jb     1270 <card+0x170>
ret
xor    %eax,%eax
ret
pxor   %xmm0,%xmm0
xor    %esi,%esi
pxor   %xmm1,%xmm1
test   $0x1,%r9b
jne    11fb <card+0xfb>
jmp    1246 <card+0x146>

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

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