int *count_serial(double min, double max, int *vet, int nbins, double h,
                  double *val, int nval, int nthreads, int threadnum) {
  int i, j, accum;
  double min_t, max_t;
  int j_min = nbins / nthreads * threadnum;
  int j_max = nbins / nthreads * (threadnum + 1);
  for (j = j_min; j < j_max; j++) {
    accum = 0;
    min_t = min + j * h;
    max_t = min + (j + 1) * h;
    for (i = 0; i < nval; i++) {
      if (val[i] <= max_t && val[i] > min_t) {
        accum++;
      }
    }
    vet[j] = accum;
  }
  return vet;
}


x86 assembly (clang, -O0):
<count_serial>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
mov    %rdi,-0x18(%rbp)
mov    %esi,-0x1c(%rbp)
movsd  %xmm2,-0x28(%rbp)
mov    %rdx,-0x30(%rbp)
mov    %ecx,-0x34(%rbp)
mov    %r8d,-0x38(%rbp)
mov    %r9d,-0x3c(%rbp)
mov    -0x1c(%rbp),%eax
cltd
idivl  -0x38(%rbp)
imul   -0x3c(%rbp),%eax
mov    %eax,-0x5c(%rbp)
mov    -0x1c(%rbp),%eax
cltd
idivl  -0x38(%rbp)
mov    -0x3c(%rbp),%ecx
add    $0x1,%ecx
imul   %ecx,%eax
mov    %eax,-0x60(%rbp)
mov    -0x5c(%rbp),%eax
mov    %eax,-0x44(%rbp)
mov    -0x44(%rbp),%eax
cmp    -0x60(%rbp),%eax
jge    121f <count_serial+0x11f>
movl   $0x0,-0x48(%rbp)
movsd  -0x8(%rbp),%xmm1
cvtsi2sdl -0x44(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x8(%rbp),%xmm1
mov    -0x44(%rbp),%eax
add    $0x1,%eax
cvtsi2sd %eax,%xmm0
movsd  -0x28(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movl   $0x0,-0x40(%rbp)
mov    -0x40(%rbp),%eax
cmp    -0x34(%rbp),%eax
jge    1203 <count_serial+0x103>
mov    -0x30(%rbp),%rax
movslq -0x40(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  -0x58(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jb     11f0 <count_serial+0xf0>
mov    -0x30(%rbp),%rax
movslq -0x40(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
ucomisd -0x50(%rbp),%xmm0
jbe    11f0 <count_serial+0xf0>
mov    -0x48(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x48(%rbp)
jmp    11f5 <count_serial+0xf5>
mov    -0x40(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x40(%rbp)
jmp    11a7 <count_serial+0xa7>
mov    -0x48(%rbp),%edx
mov    -0x18(%rbp),%rax
movslq -0x44(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x44(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x44(%rbp)
jmp    1150 <count_serial+0x50>
mov    -0x18(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<count_serial>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %rdx,%r10
mov    %esi,%eax
mov    %rdi,%r12
cltd
idiv   %r8d
mov    %eax,%edx
imul   %r9d,%edx
add    $0x1,%r9d
imul   %eax,%r9d
cmp    %r9d,%edx
jge    135d <count_serial+0x25d>
movslq %edx,%r13
movslq %r9d,%r15
mov    %ecx,%esi
mov    %esi,%r8d
and    $0xfffffffc,%r8d
lea    -0x4(%r8),%r9
mov    %r9,%r11
shr    $0x2,%r11
add    $0x1,%r11
mov    %r11,%r14
and    $0xfffffffffffffffe,%r14
jmp    116d <count_serial+0x6d>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
mov    %eax,(%r12,%rbp,4)
cmp    %r15,%r13
je     135d <count_serial+0x25d>
mov    %r13,%rbp
add    $0x1,%r13
mov    $0x0,%eax
test   %ecx,%ecx
jle    1160 <count_serial+0x60>
xorps  %xmm8,%xmm8
cvtsi2sd %ebp,%xmm8
mulsd  %xmm2,%xmm8
xorps  %xmm9,%xmm9
cvtsi2sd %r13d,%xmm9
addsd  %xmm0,%xmm8
mulsd  %xmm2,%xmm9
addsd  %xmm0,%xmm9
cmp    $0x4,%ecx
jae    11c0 <count_serial+0xc0>
xor    %edi,%edi
xor    %eax,%eax
jmp    1320 <count_serial+0x220>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movapd %xmm9,%xmm10
unpcklpd %xmm9,%xmm10
movapd %xmm8,%xmm11
unpcklpd %xmm8,%xmm11
pxor   %xmm12,%xmm12
test   %r9,%r9
je     134b <count_serial+0x24b>
mov    %r14,%rdi
xor    %eax,%eax
pxor   %xmm7,%xmm7
nopl   0x0(%rax,%rax,1)
movupd (%r10,%rax,8),%xmm4
movupd 0x10(%r10,%rax,8),%xmm5
movupd 0x20(%r10,%rax,8),%xmm3
movupd 0x30(%r10,%rax,8),%xmm1
movapd %xmm11,%xmm6
cmpltpd %xmm4,%xmm6
cmplepd %xmm10,%xmm4
andpd  %xmm6,%xmm4
movapd %xmm11,%xmm6
cmpltpd %xmm5,%xmm6
cmplepd %xmm10,%xmm5
andpd  %xmm6,%xmm5
psrlq  $0x3f,%xmm4
psrlq  $0x3f,%xmm5
pshufd $0xe8,%xmm4,%xmm4
paddd  %xmm12,%xmm4
pshufd $0xe8,%xmm5,%xmm5
paddd  %xmm7,%xmm5
movapd %xmm11,%xmm6
cmpltpd %xmm3,%xmm6
cmplepd %xmm10,%xmm3
andpd  %xmm6,%xmm3
movapd %xmm11,%xmm6
cmpltpd %xmm1,%xmm6
cmplepd %xmm10,%xmm1
andpd  %xmm6,%xmm1
psrlq  $0x3f,%xmm3
psrlq  $0x3f,%xmm1
pshufd $0xe8,%xmm3,%xmm12
paddd  %xmm4,%xmm12
pshufd $0xe8,%xmm1,%xmm7
paddd  %xmm5,%xmm7
add    $0x8,%rax
add    $0xfffffffffffffffe,%rdi
jne    11f0 <count_serial+0xf0>
test   $0x1,%r11b
je     12f9 <count_serial+0x1f9>
movupd (%r10,%rax,8),%xmm1
movupd 0x10(%r10,%rax,8),%xmm3
movapd %xmm11,%xmm4
cmpltpd %xmm1,%xmm4
cmplepd %xmm10,%xmm1
andpd  %xmm4,%xmm1
cmpltpd %xmm3,%xmm11
cmplepd %xmm10,%xmm3
andpd  %xmm11,%xmm3
psrlq  $0x3f,%xmm1
psrlq  $0x3f,%xmm3
pshufd $0xe8,%xmm1,%xmm1
paddd  %xmm1,%xmm12
pshufd $0xe8,%xmm3,%xmm1
paddd  %xmm1,%xmm7
paddd  %xmm7,%xmm12
pshufd $0x55,%xmm12,%xmm1
paddd  %xmm12,%xmm1
movd   %xmm1,%eax
mov    %r8,%rdi
cmp    %rsi,%r8
je     1160 <count_serial+0x60>
nopl   0x0(%rax)
movsd  (%r10,%rdi,8),%xmm1
ucomisd %xmm1,%xmm9
setae  %bl
ucomisd %xmm8,%xmm1
seta   %dl
and    %bl,%dl
movzbl %dl,%edx
add    %edx,%eax
add    $0x1,%rdi
cmp    %rdi,%rsi
jne    1320 <count_serial+0x220>
jmp    1160 <count_serial+0x60>
xor    %eax,%eax
pxor   %xmm7,%xmm7
test   $0x1,%r11b
jne    12aa <count_serial+0x1aa>
jmp    12f9 <count_serial+0x1f9>
mov    %r12,%rax
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32* @count_serial(double %0, double %1, i32* %2, i32 %3, double %4, double* %5, i32 %6, i32 %7, i32 %8) {
%10 = alloca double
%11 = alloca double
%12 = alloca i32*
%13 = alloca i32
%14 = alloca double
%15 = alloca double*
%16 = alloca i32
%17 = alloca i32
%18 = alloca i32
%19 = alloca i32
%20 = alloca i32
%21 = alloca i32
%22 = alloca double
%23 = alloca double
%24 = alloca i32
%25 = alloca i32
store double %0, double* %10
store double %1, double* %11
store i32* %2, i32** %12
store i32 %3, i32* %13
store double %4, double* %14
store double* %5, double** %15
store i32 %6, i32* %16
store i32 %7, i32* %17
store i32 %8, i32* %18
%26 = load i32, i32* %13
%27 = load i32, i32* %17
%28 = sdiv i32 %26, %27
%29 = load i32, i32* %18
%30 = mul nsw i32 %28, %29
store i32 %30, i32* %24
%31 = load i32, i32* %13
%32 = load i32, i32* %17
%33 = sdiv i32 %31, %32
%34 = load i32, i32* %18
%35 = add nsw i32 %34, 1
%36 = mul nsw i32 %33, %35
store i32 %36, i32* %25
%37 = load i32, i32* %24
store i32 %37, i32* %20
br label %38
38: ; preds = %87, %9
%39 = load i32, i32* %20
%40 = load i32, i32* %25
%41 = icmp slt i32 %39, %40
br i1 %41, label %42, label %90
42: ; preds = %38
store i32 0, i32* %21
%43 = load double, double* %10
%44 = load i32, i32* %20
%45 = sitofp i32 %44 to double
%46 = load double, double* %14
%47 = call double @llvm.fmuladd.f64(double %45, double %46, double %43)
store double %47, double* %22
%48 = load double, double* %10
%49 = load i32, i32* %20
%50 = add nsw i32 %49, 1
%51 = sitofp i32 %50 to double
%52 = load double, double* %14
%53 = call double @llvm.fmuladd.f64(double %51, double %52, double %48)
store double %53, double* %23
store i32 0, i32* %19
br label %54
54: ; preds = %78, %42
%55 = load i32, i32* %19
%56 = load i32, i32* %16
%57 = icmp slt i32 %55, %56
br i1 %57, label %58, label %81
58: ; preds = %54
%59 = load double*, double** %15
%60 = load i32, i32* %19
%61 = sext i32 %60 to i64
%62 = getelementptr inbounds double, double* %59, i64 %61
%63 = load double, double* %62
%64 = load double, double* %23
%65 = fcmp ole double %63, %64
br i1 %65, label %66, label %77
66: ; preds = %58
%67 = load double*, double** %15
%68 = load i32, i32* %19
%69 = sext i32 %68 to i64
%70 = getelementptr inbounds double, double* %67, i64 %69
%71 = load double, double* %70
%72 = load double, double* %22
%73 = fcmp ogt double %71, %72
br i1 %73, label %74, label %77
74: ; preds = %66
%75 = load i32, i32* %21
%76 = add nsw i32 %75, 1
store i32 %76, i32* %21
br label %77
77: ; preds = %74, %66, %58
br label %78
78: ; preds = %77
%79 = load i32, i32* %19
%80 = add nsw i32 %79, 1
store i32 %80, i32* %19
br label %54
81: ; preds = %54
%82 = load i32, i32* %21
%83 = load i32*, i32** %12
%84 = load i32, i32* %20
%85 = sext i32 %84 to i64
%86 = getelementptr inbounds i32, i32* %83, i64 %85
store i32 %82, i32* %86
br label %87
87: ; preds = %81
%88 = load i32, i32* %20
%89 = add nsw i32 %88, 1
store i32 %89, i32* %20
br label %38
90: ; preds = %38
%91 = load i32*, i32** %12
ret i32* %91
}

LLVM IR (-O2):
define i32* @count_serial(double %0, double %1, i32* returned writeonly %2, i32 %3, double %4, double* nocapture %5, i32 %6, i32 %7, i32 %8) {
%10 = sdiv i32 %3, %7
%11 = mul i32 %10, %8
%12 = add nsw i32 %8, 1
%13 = mul i32 %10, %12
%14 = icmp slt i32 %11, %13
br i1 %14, label %15, label %138
15: ; preds = %9
%16 = icmp sgt i32 %6, 0
%17 = sext i32 %11 to i64
%18 = sext i32 %13 to i64
%19 = zext i32 %6 to i64
%20 = and i64 %19, 4294967292
%21 = add nsw i64 %20, -4
%22 = lshr exact i64 %21, 2
%23 = add nuw nsw i64 %22, 1
%24 = icmp ult i32 %6, 4
%25 = and i64 %19, 4294967292
%26 = and i64 %23, 1
%27 = icmp eq i64 %21, 0
%28 = and i64 %23, 9223372036854775806
%29 = icmp eq i64 %26, 0
%30 = icmp eq i64 %25, %19
br label %31
31: ; preds = %15, %134
%32 = phi i64 [ %17, %15 ], [ %36, %134 ]
%33 = trunc i64 %32 to i32
%34 = sitofp i32 %33 to double
%35 = tail call double @llvm.fmuladd.f64(double %34, double %4, double %0)
%36 = add nsw i64 %32, 1
%37 = trunc i64 %36 to i32
%38 = sitofp i32 %37 to double
%39 = tail call double @llvm.fmuladd.f64(double %38, double %4, double %0)
br i1 %16, label %40, label %134
40: ; preds = %31
br i1 %24, label %119, label %41
41: ; preds = %40
%42 = insertelement <2 x double> poison, double %39, i64 0
%43 = shufflevector <2 x double> %42, <2 x double> poison, <2 x i32> zeroinitializer
%44 = insertelement <2 x double> poison, double %39, i64 0
%45 = shufflevector <2 x double> %44, <2 x double> poison, <2 x i32> zeroinitializer
%46 = insertelement <2 x double> poison, double %35, i64 0
%47 = shufflevector <2 x double> %46, <2 x double> poison, <2 x i32> zeroinitializer
%48 = insertelement <2 x double> poison, double %35, i64 0
%49 = shufflevector <2 x double> %48, <2 x double> poison, <2 x i32> zeroinitializer
br i1 %27, label %91, label %50
50: ; preds = %41, %50
%51 = phi i64 [ %88, %50 ], [ 0, %41 ]
%52 = phi <2 x i32> [ %86, %50 ], [ zeroinitializer, %41 ]
%53 = phi <2 x i32> [ %87, %50 ], [ zeroinitializer, %41 ]
%54 = phi i64 [ %89, %50 ], [ 0, %41 ]
%55 = getelementptr inbounds double, double* %5, i64 %51
%56 = bitcast double* %55 to <2 x double>*
%57 = load <2 x double>, <2 x double>* %56
%58 = getelementptr inbounds double, double* %55, i64 2
%59 = bitcast double* %58 to <2 x double>*
%60 = load <2 x double>, <2 x double>* %59
%61 = fcmp ole <2 x double> %57, %43
%62 = fcmp ole <2 x double> %60, %45
%63 = fcmp ogt <2 x double> %57, %47
%64 = fcmp ogt <2 x double> %60, %49
%65 = select <2 x i1> %61, <2 x i1> %63, <2 x i1> zeroinitializer
%66 = select <2 x i1> %62, <2 x i1> %64, <2 x i1> zeroinitializer
%67 = zext <2 x i1> %65 to <2 x i32>
%68 = zext <2 x i1> %66 to <2 x i32>
%69 = add <2 x i32> %52, %67
%70 = add <2 x i32> %53, %68
%71 = or i64 %51, 4
%72 = getelementptr inbounds double, double* %5, i64 %71
%73 = bitcast double* %72 to <2 x double>*
%74 = load <2 x double>, <2 x double>* %73
%75 = getelementptr inbounds double, double* %72, i64 2
%76 = bitcast double* %75 to <2 x double>*
%77 = load <2 x double>, <2 x double>* %76
%78 = fcmp ole <2 x double> %74, %43
%79 = fcmp ole <2 x double> %77, %45
%80 = fcmp ogt <2 x double> %74, %47
%81 = fcmp ogt <2 x double> %77, %49
%82 = select <2 x i1> %78, <2 x i1> %80, <2 x i1> zeroinitializer
%83 = select <2 x i1> %79, <2 x i1> %81, <2 x i1> zeroinitializer
%84 = zext <2 x i1> %82 to <2 x i32>
%85 = zext <2 x i1> %83 to <2 x i32>
%86 = add <2 x i32> %69, %84
%87 = add <2 x i32> %70, %85
%88 = add nuw i64 %51, 8
%89 = add i64 %54, 2
%90 = icmp eq i64 %89, %28
br i1 %90, label %91, label %50
91: ; preds = %50, %41
%92 = phi <2 x i32> [ undef, %41 ], [ %86, %50 ]
%93 = phi <2 x i32> [ undef, %41 ], [ %87, %50 ]
%94 = phi i64 [ 0, %41 ], [ %88, %50 ]
%95 = phi <2 x i32> [ zeroinitializer, %41 ], [ %86, %50 ]
%96 = phi <2 x i32> [ zeroinitializer, %41 ], [ %87, %50 ]
br i1 %29, label %114, label %97
97: ; preds = %91
%98 = getelementptr inbounds double, double* %5, i64 %94
%99 = bitcast double* %98 to <2 x double>*
%100 = load <2 x double>, <2 x double>* %99
%101 = getelementptr inbounds double, double* %98, i64 2
%102 = bitcast double* %101 to <2 x double>*
%103 = load <2 x double>, <2 x double>* %102
%104 = fcmp ole <2 x double> %100, %43
%105 = fcmp ole <2 x double> %103, %45
%106 = fcmp ogt <2 x double> %100, %47
%107 = fcmp ogt <2 x double> %103, %49
%108 = select <2 x i1> %104, <2 x i1> %106, <2 x i1> zeroinitializer
%109 = select <2 x i1> %105, <2 x i1> %107, <2 x i1> zeroinitializer
%110 = zext <2 x i1> %108 to <2 x i32>
%111 = zext <2 x i1> %109 to <2 x i32>
%112 = add <2 x i32> %95, %110
%113 = add <2 x i32> %96, %111
br label %114
114: ; preds = %91, %97
%115 = phi <2 x i32> [ %92, %91 ], [ %112, %97 ]
%116 = phi <2 x i32> [ %93, %91 ], [ %113, %97 ]
%117 = add <2 x i32> %116, %115
%118 = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %117)
br i1 %30, label %134, label %119
119: ; preds = %40, %114
%120 = phi i64 [ 0, %40 ], [ %25, %114 ]
%121 = phi i32 [ 0, %40 ], [ %118, %114 ]
br label %122
122: ; preds = %119, %122
%123 = phi i64 [ %132, %122 ], [ %120, %119 ]
%124 = phi i32 [ %131, %122 ], [ %121, %119 ]
%125 = getelementptr inbounds double, double* %5, i64 %123
%126 = load double, double* %125
%127 = fcmp ole double %126, %39
%128 = fcmp ogt double %126, %35
%129 = select i1 %127, i1 %128, i1 false
%130 = zext i1 %129 to i32
%131 = add nuw nsw i32 %124, %130
%132 = add nuw nsw i64 %123, 1
%133 = icmp eq i64 %132, %19
br i1 %133, label %134, label %122
134: ; preds = %122, %114, %31
%135 = phi i32 [ 0, %31 ], [ %118, %114 ], [ %131, %122 ]
%136 = getelementptr inbounds i32, i32* %2, i64 %32
store i32 %135, i32* %136
%137 = icmp eq i64 %36, %18
br i1 %137, label %138, label %31
138: ; preds = %134, %9
ret i32* %2
}