#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 DBL_EPSILON;
double BesselI0(double x) {
  const double x_squared = x * x;
  double term = 1.0;
  double sum = 1.0;
  int k;
  for (k = 2; k < 80; k += 2) {
    term *= x_squared / (k * k);
    if (term < DBL_EPSILON * sum) {
      break;
    }
    sum += term;
  }
  return sum;
}


x86 assembly (clang, -O0):
<BesselI0>:
push   %rbp
mov    %rsp,%rbp
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
mulsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  0xee0(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xed3(%rip),%xmm0
movsd  %xmm0,-0x20(%rbp)
movl   $0x2,-0x24(%rbp)
cmpl   $0x50,-0x24(%rbp)
jge    11a2 <BesselI0+0xa2>
movsd  -0x10(%rbp),%xmm0
mov    -0x24(%rbp),%eax
imul   -0x24(%rbp),%eax
cvtsi2sd %eax,%xmm1
divsd  %xmm1,%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  -0x18(%rbp),%xmm1
mov    0x2e7b(%rip),%rax
movsd  (%rax),%xmm0
mulsd  -0x20(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jbe    1185 <BesselI0+0x85>
jmp    11a2 <BesselI0+0xa2>
movsd  -0x18(%rbp),%xmm0
addsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x24(%rbp),%eax
add    $0x2,%eax
mov    %eax,-0x24(%rbp)
jmp    1139 <BesselI0+0x39>
movsd  -0x20(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<BesselI0>:
movapd %xmm0,%xmm1
mulsd  %xmm0,%xmm1
mov    0x2ed9(%rip),%rax
movsd  (%rax),%xmm2
movsd  0xee5(%rip),%xmm0
mov    $0x2,%eax
movapd %xmm0,%xmm3
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movapd %xmm3,%xmm4
mov    %eax,%ecx
imul   %eax,%ecx
xorps  %xmm5,%xmm5
cvtsi2sd %ecx,%xmm5
movapd %xmm1,%xmm3
divsd  %xmm5,%xmm3
mulsd  %xmm4,%xmm3
movapd %xmm0,%xmm4
mulsd  %xmm2,%xmm4
ucomisd %xmm3,%xmm4
ja     1193 <BesselI0+0x93>
addsd  %xmm3,%xmm0
cmp    $0x4d,%eax
ja     1193 <BesselI0+0x93>
lea    0x2(%rax),%ecx
imul   %ecx,%ecx
xorps  %xmm4,%xmm4
cvtsi2sd %ecx,%xmm4
movapd %xmm1,%xmm5
divsd  %xmm4,%xmm5
mulsd  %xmm5,%xmm3
movapd %xmm0,%xmm4
mulsd  %xmm2,%xmm4
ucomisd %xmm3,%xmm4
ja     1193 <BesselI0+0x93>
addsd  %xmm3,%xmm0
add    $0x4,%eax
jmp    1130 <BesselI0+0x30>
ret

LLVM IR (-O0):
@DBL_EPSILON = global double 0.000000e+00
define double @BesselI0(double %0) {
%2 = alloca double
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca i32
store double %0, double* %2
%7 = load double, double* %2
%8 = load double, double* %2
%9 = fmul double %7, %8
store double %9, double* %3
store double 1.000000e+00, double* %4
store double 1.000000e+00, double* %5
store i32 2, i32* %6
br label %10
10: ; preds = %32, %1
%11 = load i32, i32* %6
%12 = icmp slt i32 %11, 80
br i1 %12, label %13, label %35
13: ; preds = %10
%14 = load double, double* %3
%15 = load i32, i32* %6
%16 = load i32, i32* %6
%17 = mul nsw i32 %15, %16
%18 = sitofp i32 %17 to double
%19 = fdiv double %14, %18
%20 = load double, double* %4
%21 = fmul double %20, %19
store double %21, double* %4
%22 = load double, double* %4
%23 = load double, double* @DBL_EPSILON
%24 = load double, double* %5
%25 = fmul double %23, %24
%26 = fcmp olt double %22, %25
br i1 %26, label %27, label %28
27: ; preds = %13
br label %35
28: ; preds = %13
%29 = load double, double* %4
%30 = load double, double* %5
%31 = fadd double %30, %29
store double %31, double* %5
br label %32
32: ; preds = %28
%33 = load i32, i32* %6
%34 = add nsw i32 %33, 2
store i32 %34, i32* %6
br label %10
35: ; preds = %27, %10
%36 = load double, double* %5
ret double %36
}

LLVM IR (-O2):
@DBL_EPSILON = global double 0.000000e+00
define double @BesselI0(double %0) {
%2 = fmul double %0, %0
%3 = load double, double* @DBL_EPSILON
br label %4
4: ; preds = %25, %1
%5 = phi i32 [ 2, %1 ], [ %27, %25 ]
%6 = phi double [ 1.000000e+00, %1 ], [ %26, %25 ]
%7 = phi double [ 1.000000e+00, %1 ], [ %22, %25 ]
%8 = mul nuw nsw i32 %5, %5
%9 = sitofp i32 %8 to double
%10 = fdiv double %2, %9
%11 = fmul double %7, %10
%12 = fmul double %6, %3
%13 = fcmp olt double %11, %12
br i1 %13, label %28, label %14
14: ; preds = %4
%15 = fadd double %6, %11
%16 = icmp ult i32 %5, 78
br i1 %16, label %17, label %28
17: ; preds = %14
%18 = add nuw nsw i32 %5, 2
%19 = mul nuw nsw i32 %18, %18
%20 = sitofp i32 %19 to double
%21 = fdiv double %2, %20
%22 = fmul double %11, %21
%23 = fmul double %15, %3
%24 = fcmp olt double %22, %23
br i1 %24, label %28, label %25
25: ; preds = %17
%26 = fadd double %15, %22
%27 = add nuw nsw i32 %5, 4
br label %4
28: ; preds = %17, %4, %14
%29 = phi double [ %6, %4 ], [ %15, %14 ], [ %15, %17 ]
ret double %29
}