#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 cubic_interpolation_cell(double *, double);
double bicubic_interpolation_cell(double p[4][4], double x, double y) {
  double v[4];
  v[0] = cubic_interpolation_cell(p[0], y);
  v[1] = cubic_interpolation_cell(p[1], y);
  v[2] = cubic_interpolation_cell(p[2], y);
  v[3] = cubic_interpolation_cell(p[3], y);
  return cubic_interpolation_cell(v, x);
}


x86 assembly (clang, -O0):
<bicubic_interpolation_cell>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
mov    -0x8(%rbp),%rdi
movsd  -0x18(%rbp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,-0x40(%rbp)
mov    -0x8(%rbp),%rdi
add    $0x20,%rdi
movsd  -0x18(%rbp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,-0x38(%rbp)
mov    -0x8(%rbp),%rdi
add    $0x40,%rdi
movsd  -0x18(%rbp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,-0x30(%rbp)
mov    -0x8(%rbp),%rdi
add    $0x60,%rdi
movsd  -0x18(%rbp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,-0x28(%rbp)
lea    -0x40(%rbp),%rdi
movsd  -0x10(%rbp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<bicubic_interpolation_cell>:
push   %rbx
sub    $0x30,%rsp
movsd  %xmm1,(%rsp)
movsd  %xmm0,0x8(%rsp)
mov    %rdi,%rbx
movaps %xmm1,%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,0x10(%rsp)
lea    0x20(%rbx),%rdi
movsd  (%rsp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,0x18(%rsp)
lea    0x40(%rbx),%rdi
movsd  (%rsp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,0x20(%rsp)
add    $0x60,%rbx
mov    %rbx,%rdi
movsd  (%rsp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
movsd  %xmm0,0x28(%rsp)
lea    0x10(%rsp),%rdi
movsd  0x8(%rsp),%xmm0
call   1030 <cubic_interpolation_cell@plt>
add    $0x30,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define double @bicubic_interpolation_cell([4 x double]* %0, double %1, double %2) {
%4 = alloca [4 x double]*
%5 = alloca double
%6 = alloca double
%7 = alloca [4 x double]
store [4 x double]* %0, [4 x double]** %4
store double %1, double* %5
store double %2, double* %6
%8 = load [4 x double]*, [4 x double]** %4
%9 = getelementptr inbounds [4 x double], [4 x double]* %8, i64 0
%10 = getelementptr inbounds [4 x double], [4 x double]* %9, i64 0, i64 0
%11 = load double, double* %6
%12 = call double @cubic_interpolation_cell(double* %10, double %11)
%13 = getelementptr inbounds [4 x double], [4 x double]* %7, i64 0, i64 0
store double %12, double* %13
%14 = load [4 x double]*, [4 x double]** %4
%15 = getelementptr inbounds [4 x double], [4 x double]* %14, i64 1
%16 = getelementptr inbounds [4 x double], [4 x double]* %15, i64 0, i64 0
%17 = load double, double* %6
%18 = call double @cubic_interpolation_cell(double* %16, double %17)
%19 = getelementptr inbounds [4 x double], [4 x double]* %7, i64 0, i64 1
store double %18, double* %19
%20 = load [4 x double]*, [4 x double]** %4
%21 = getelementptr inbounds [4 x double], [4 x double]* %20, i64 2
%22 = getelementptr inbounds [4 x double], [4 x double]* %21, i64 0, i64 0
%23 = load double, double* %6
%24 = call double @cubic_interpolation_cell(double* %22, double %23)
%25 = getelementptr inbounds [4 x double], [4 x double]* %7, i64 0, i64 2
store double %24, double* %25
%26 = load [4 x double]*, [4 x double]** %4
%27 = getelementptr inbounds [4 x double], [4 x double]* %26, i64 3
%28 = getelementptr inbounds [4 x double], [4 x double]* %27, i64 0, i64 0
%29 = load double, double* %6
%30 = call double @cubic_interpolation_cell(double* %28, double %29)
%31 = getelementptr inbounds [4 x double], [4 x double]* %7, i64 0, i64 3
store double %30, double* %31
%32 = getelementptr inbounds [4 x double], [4 x double]* %7, i64 0, i64 0
%33 = load double, double* %5
%34 = call double @cubic_interpolation_cell(double* %32, double %33)
ret double %34
}

LLVM IR (-O2):
define double @bicubic_interpolation_cell([4 x double]* %0, double %1, double %2) {
%4 = alloca [4 x double]
%5 = bitcast [4 x double]* %4 to i8*
%6 = getelementptr inbounds [4 x double], [4 x double]* %0, i64 0, i64 0
%7 = tail call double @cubic_interpolation_cell(double* %6, double %2)
%8 = getelementptr inbounds [4 x double], [4 x double]* %4, i64 0, i64 0
store double %7, double* %8
%9 = getelementptr inbounds [4 x double], [4 x double]* %0, i64 1, i64 0
%10 = tail call double @cubic_interpolation_cell(double* %9, double %2)
%11 = getelementptr inbounds [4 x double], [4 x double]* %4, i64 0, i64 1
store double %10, double* %11
%12 = getelementptr inbounds [4 x double], [4 x double]* %0, i64 2, i64 0
%13 = tail call double @cubic_interpolation_cell(double* %12, double %2)
%14 = getelementptr inbounds [4 x double], [4 x double]* %4, i64 0, i64 2
store double %13, double* %14
%15 = getelementptr inbounds [4 x double], [4 x double]* %0, i64 3, i64 0
%16 = tail call double @cubic_interpolation_cell(double* %15, double %2)
%17 = getelementptr inbounds [4 x double], [4 x double]* %4, i64 0, i64 3
store double %16, double* %17
%18 = call double @cubic_interpolation_cell(double* %8, double %1)
ret double %18
}