#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double log(double);
double kldist(double *a, double *b, int n) {
  double q, d;
  int i;
  d = 0;
  for (i = 0; i < n; i++) {
    q = (a[i] + b[i]) / 2.0;
    if (q > 0) {
      if (a[i] > 0)
        d += a[i] * log(a[i] / q);
      if (b[i] > 0)
        d += b[i] * log(b[i] / q);
    }
  }
  return d;
}


x86 assembly (clang, -O0):
<kldist>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    124d <kldist+0x13d>
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm0
movsd  0xea0(%rip),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    123a <kldist+0x12a>
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    11d8 <kldist+0xc8>
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
divsd  -0x20(%rbp),%xmm0
call   1030 <log@plt>
movaps %xmm0,%xmm2
movsd  -0x38(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    1235 <kldist+0x125>
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
divsd  -0x20(%rbp),%xmm0
call   1030 <log@plt>
movaps %xmm0,%xmm2
movsd  -0x40(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
jmp    123a <kldist+0x12a>
jmp    123f <kldist+0x12f>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1132 <kldist+0x22>
movsd  -0x28(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<kldist>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x18,%rsp
test   %edx,%edx
jle    11fc <kldist+0xec>
mov    %rsi,%r12
mov    %rdi,%r14
mov    %edx,%r15d
xorpd  %xmm1,%xmm1
xor    %ebx,%ebx
movsd  0xec6(%rip),%xmm2
xorps  %xmm0,%xmm0
jmp    1155 <kldist+0x45>
nop
movsd  0xeb8(%rip),%xmm2
add    $0x1,%rbx
cmp    %rbx,%r15
je     11ff <kldist+0xef>
movsd  (%r14,%rbx,8),%xmm5
movsd  (%r12,%rbx,8),%xmm4
movapd %xmm5,%xmm3
addsd  %xmm4,%xmm3
mulsd  %xmm2,%xmm3
ucomisd %xmm1,%xmm3
jbe    1148 <kldist+0x38>
ucomisd %xmm1,%xmm5
movsd  %xmm3,0x8(%rsp)
jbe    11ba <kldist+0xaa>
movsd  %xmm0,(%rsp)
movapd %xmm5,%xmm0
divsd  %xmm3,%xmm0
movsd  %xmm5,0x10(%rsp)
call   1030 <log@plt>
mulsd  0x10(%rsp),%xmm0
movsd  (%rsp),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%rsp)
xorpd  %xmm1,%xmm1
movsd  (%rsp),%xmm0
movsd  (%r12,%rbx,8),%xmm4
ucomisd %xmm1,%xmm4
jbe    1140 <kldist+0x30>
movsd  %xmm0,(%rsp)
movapd %xmm4,%xmm0
divsd  0x8(%rsp),%xmm0
movsd  %xmm4,0x8(%rsp)
call   1030 <log@plt>
mulsd  0x8(%rsp),%xmm0
movsd  (%rsp),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%rsp)
xorpd  %xmm1,%xmm1
movsd  (%rsp),%xmm0
jmp    1140 <kldist+0x30>
xorps  %xmm0,%xmm0
add    $0x18,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

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

LLVM IR (-O2):
define double @kldist(double* nocapture %0, double* nocapture %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %36
5: ; preds = %3
%6 = zext i32 %2 to i64
br label %7
7: ; preds = %5, %32
%8 = phi i64 [ 0, %5 ], [ %34, %32 ]
%9 = phi double [ 0.000000e+00, %5 ], [ %33, %32 ]
%10 = getelementptr inbounds double, double* %0, i64 %8
%11 = load double, double* %10
%12 = getelementptr inbounds double, double* %1, i64 %8
%13 = load double, double* %12
%14 = fadd double %11, %13
%15 = fmul double %14, 5.000000e-01
%16 = fcmp ogt double %15, 0.000000e+00
br i1 %16, label %17, label %32
17: ; preds = %7
%18 = fcmp ogt double %11, 0.000000e+00
br i1 %18, label %19, label %24
19: ; preds = %17
%20 = fdiv double %11, %15
%21 = tail call double @log(double %20)
%22 = tail call double @llvm.fmuladd.f64(double %11, double %21, double %9)
%23 = load double, double* %12
br label %24
24: ; preds = %19, %17
%25 = phi double [ %23, %19 ], [ %13, %17 ]
%26 = phi double [ %22, %19 ], [ %9, %17 ]
%27 = fcmp ogt double %25, 0.000000e+00
br i1 %27, label %28, label %32
28: ; preds = %24
%29 = fdiv double %25, %15
%30 = tail call double @log(double %29)
%31 = tail call double @llvm.fmuladd.f64(double %25, double %30, double %26)
br label %32
32: ; preds = %7, %28, %24
%33 = phi double [ %31, %28 ], [ %26, %24 ], [ %9, %7 ]
%34 = add nuw nsw i64 %8, 1
%35 = icmp eq i64 %34, %6
br i1 %35, label %36, label %7
36: ; preds = %32, %3
%37 = phi double [ 0.000000e+00, %3 ], [ %33, %32 ]
ret double %37
}