#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 */
int sqrt(int);
double od_rsqrt_table(int i) {
  static double table[16] = {1.000000, 0.707107, 0.577350, 0.500000,
                             0.447214, 0.408248, 0.377964, 0.353553,
                             0.333333, 0.316228, 0.301511, 0.288675,
                             0.277350, 0.267261, 0.258199, 0.250000};
  if (i <= 16)
    return table[i - 1];
  else
    return 1. / sqrt(i);
}


x86 assembly (clang, -O0):
<od_rsqrt_table>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %edi,-0xc(%rbp)
cmpl   $0x10,-0xc(%rbp)
jg     1144 <od_rsqrt_table+0x34>
mov    -0xc(%rbp),%eax
sub    $0x1,%eax
movslq %eax,%rcx
lea    0x2efb(%rip),%rax
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1161 <od_rsqrt_table+0x51>
mov    -0xc(%rbp),%edi
call   1030 <sqrt@plt>
cvtsi2sd %eax,%xmm1
movsd  0xea8(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<od_rsqrt_table>:
push   %rax
cmp    $0x10,%edi
jg     1128 <od_rsqrt_table+0x18>
movslq %edi,%rax
lea    0xef0(%rip),%rcx
movsd  -0x8(%rcx,%rax,8),%xmm0
pop    %rax
ret
call   1030 <sqrt@plt>
cvtsi2sd %eax,%xmm1
movsd  0xec7(%rip),%xmm0
divsd  %xmm1,%xmm0
pop    %rax
ret

LLVM IR (-O0):
@od_rsqrt_table.table = internal global [16 x double] [double 1.000000e+00, double 7.071070e-01, double 5.773500e-01, double 5.000000e-01, double 4.472140e-01, double 4.082480e-01, double 3.779640e-01, double 3.535530e-01, double 3.333330e-01, double 3.162280e-01, double 3.015110e-01, double 2.886750e-01, double 2.773500e-01, double 2.672610e-01, double 2.581990e-01, double 2.500000e-01]
define double @od_rsqrt_table(i32 %0) {
%2 = alloca double
%3 = alloca i32
store i32 %0, i32* %3
%4 = load i32, i32* %3
%5 = icmp sle i32 %4, 16
br i1 %5, label %6, label %12
6: ; preds = %1
%7 = load i32, i32* %3
%8 = sub nsw i32 %7, 1
%9 = sext i32 %8 to i64
%10 = getelementptr inbounds [16 x double], [16 x double]* @od_rsqrt_table.table, i64 0, i64 %9
%11 = load double, double* %10
store double %11, double* %2
br label %17
12: ; preds = %1
%13 = load i32, i32* %3
%14 = call i32 @sqrt(i32 %13)
%15 = sitofp i32 %14 to double
%16 = fdiv double 1.000000e+00, %15
store double %16, double* %2
br label %17
17: ; preds = %12, %6
%18 = load double, double* %2
ret double %18
}

LLVM IR (-O2):
@od_rsqrt_table.table = internal unnamed_addr constant [16 x double] [double 1.000000e+00, double 7.071070e-01, double 5.773500e-01, double 5.000000e-01, double 4.472140e-01, double 4.082480e-01, double 3.779640e-01, double 3.535530e-01, double 3.333330e-01, double 3.162280e-01, double 3.015110e-01, double 2.886750e-01, double 2.773500e-01, double 2.672610e-01, double 2.581990e-01, double 2.500000e-01]
define double @od_rsqrt_table(i32 %0) {
%2 = icmp slt i32 %0, 17
br i1 %2, label %3, label %8
3: ; preds = %1
%4 = add nsw i32 %0, -1
%5 = sext i32 %4 to i64
%6 = getelementptr inbounds [16 x double], [16 x double]* @od_rsqrt_table.table, i64 0, i64 %5
%7 = load double, double* %6
br label %12
8: ; preds = %1
%9 = tail call i32 @sqrt(i32 %0)
%10 = sitofp i32 %9 to double
%11 = fdiv double 1.000000e+00, %10
br label %12
12: ; preds = %8, %3
%13 = phi double [ %7, %3 ], [ %11, %8 ]
ret double %13
}