#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 */
float cubicInterpolate(float *, double);
double sqrt(double);
float cubicMinimum(float p[4], float *out_pmin, float *out_xmin) {
  float pmin, xmin;
  if (p[1] < p[2]) {
    pmin = p[1];
    xmin = 0.0;
  } else {
    pmin = p[2];
    xmin = 1.0;
  }
  double a, b, c, z1, z2, discr;
  a = 0.5 * 3.0 * (3.0 * (p[1] - p[2]) + p[3] - p[0]);
  b = 2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3];
  c = 0.5 * (p[2] - p[0]);
  discr = b * b - 4.0 * a * c;
  if (discr >= 0) {
    z1 = (-b + sqrt(discr)) / (2.0 * a);
    z2 = (-b - sqrt(discr)) / (2.0 * a);
    if (z1 > 0.0 && z1 < 1.0) {
      float tmp = cubicInterpolate(p, z1);
      if (tmp < pmin) {
        pmin = tmp;
        xmin = z1;
      }
    }
    if (z2 > 0.0 && z2 < 1.0) {
      float tmp = cubicInterpolate(p, z2);
      if (tmp < pmin) {
        pmin = tmp;
        xmin = z2;
      }
    }
  }
  *out_pmin = pmin;
  *out_xmin = xmin;
  return pmin;
}


x86 assembly (clang, -O0):
<cubicMinimum>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm0
ucomiss %xmm1,%xmm0
jbe    116a <cubicMinimum+0x4a>
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm0
movss  %xmm0,-0x1c(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x20(%rbp)
jmp    1185 <cubicMinimum+0x65>
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm0
movss  %xmm0,-0x1c(%rbp)
movss  0xe80(%rip),%xmm0
movss  %xmm0,-0x20(%rbp)
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm0
mov    -0x8(%rbp),%rax
subss  0x8(%rax),%xmm0
cvtss2sd %xmm0,%xmm1
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  0xe78(%rip),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
cvtss2sd %xmm0,%xmm0
subsd  %xmm0,%xmm1
movsd  0xe50(%rip),%xmm0
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
cvtss2sd %xmm0,%xmm1
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm0
cvtss2sd %xmm0,%xmm2
movsd  0xe1e(%rip),%xmm0
mulsd  %xmm2,%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
addsd  %xmm1,%xmm1
addsd  %xmm0,%xmm1
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  0xdd6(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm1
cvtss2sd %xmm1,%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm0
mov    -0x8(%rbp),%rax
subss  (%rax),%xmm0
cvtss2sd %xmm0,%xmm1
movsd  0xda3(%rip),%xmm0
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  -0x30(%rbp),%xmm2
movsd  0xd80(%rip),%xmm1
mulsd  -0x28(%rbp),%xmm1
mulsd  -0x38(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x50(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     1437 <cubicMinimum+0x317>
movsd  -0x30(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x50(%rbp),%xmm0
call   1040 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  -0x68(%rbp),%xmm0
addsd  %xmm1,%xmm0
movsd  0xd29(%rip),%xmm1
mulsd  -0x28(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x30(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x50(%rbp),%xmm0
call   1040 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  -0x60(%rbp),%xmm0
subsd  %xmm1,%xmm0
movsd  0xcdc(%rip),%xmm1
mulsd  -0x28(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x40(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    13ca <cubicMinimum+0x2aa>
movsd  0xcbc(%rip),%xmm0
ucomisd -0x40(%rbp),%xmm0
jbe    13ca <cubicMinimum+0x2aa>
mov    -0x8(%rbp),%rdi
movsd  -0x40(%rbp),%xmm0
call   1030 <cubicInterpolate@plt>
movss  %xmm0,-0x54(%rbp)
movss  -0x54(%rbp),%xmm1
movss  -0x1c(%rbp),%xmm0
ucomiss %xmm1,%xmm0
jbe    13c5 <cubicMinimum+0x2a5>
movss  -0x54(%rbp),%xmm0
movss  %xmm0,-0x1c(%rbp)
movsd  -0x40(%rbp),%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x20(%rbp)
jmp    13ca <cubicMinimum+0x2aa>
movsd  -0x48(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    1432 <cubicMinimum+0x312>
movsd  0xc54(%rip),%xmm0
ucomisd -0x48(%rbp),%xmm0
jbe    1432 <cubicMinimum+0x312>
mov    -0x8(%rbp),%rdi
movsd  -0x48(%rbp),%xmm0
call   1030 <cubicInterpolate@plt>
movss  %xmm0,-0x58(%rbp)
movss  -0x58(%rbp),%xmm1
movss  -0x1c(%rbp),%xmm0
ucomiss %xmm1,%xmm0
jbe    142d <cubicMinimum+0x30d>
movss  -0x58(%rbp),%xmm0
movss  %xmm0,-0x1c(%rbp)
movsd  -0x48(%rbp),%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x20(%rbp)
jmp    1432 <cubicMinimum+0x312>
jmp    1437 <cubicMinimum+0x317>
movss  -0x1c(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x20(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movss  %xmm0,(%rax)
movss  -0x1c(%rbp),%xmm0
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<cubicMinimum>:
push   %r15
push   %r14
push   %rbx
sub    $0x60,%rsp
mov    %rdx,%r14
mov    %rsi,%r15
movss  (%rdi),%xmm0
movss  0x4(%rdi),%xmm2
movss  0x8(%rdi),%xmm1
movaps %xmm2,%xmm6
cmpltss %xmm1,%xmm6
movss  0xeb3(%rip),%xmm3
andnps %xmm3,%xmm6
movaps %xmm2,%xmm5
xorps  %xmm3,%xmm3
cvtss2sd %xmm2,%xmm3
subss  %xmm1,%xmm2
cvtss2sd %xmm2,%xmm7
movss  0xc(%rdi),%xmm2
mulsd  0xe99(%rip),%xmm7
cvtss2sd %xmm2,%xmm2
addsd  %xmm2,%xmm7
cvtss2sd %xmm0,%xmm4
subsd  %xmm4,%xmm7
mulsd  0xe89(%rip),%xmm7
mulsd  0xe89(%rip),%xmm3
minss  %xmm1,%xmm5
addsd  %xmm4,%xmm4
addsd  %xmm3,%xmm4
xorps  %xmm3,%xmm3
cvtss2sd %xmm1,%xmm3
mulsd  0xe76(%rip),%xmm3
addsd  %xmm4,%xmm3
subsd  %xmm2,%xmm3
subss  %xmm0,%xmm1
xorps  %xmm0,%xmm0
cvtss2sd %xmm1,%xmm0
mulsd  0xe63(%rip),%xmm0
movsd  0xe63(%rip),%xmm1
mulsd  %xmm7,%xmm1
mulsd  %xmm0,%xmm1
movapd %xmm3,%xmm4
mulsd  %xmm3,%xmm4
addsd  %xmm1,%xmm4
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm4
jb     1381 <cubicMinimum+0x261>
mov    %rdi,%rbx
movapd 0xe46(%rip),%xmm1
xorpd  %xmm3,%xmm1
sqrtsd %xmm4,%xmm8
ucomisd %xmm0,%xmm4
movapd %xmm8,%xmm2
movss  %xmm5,0x4(%rsp)
movaps %xmm6,0x10(%rsp)
movapd %xmm1,0x20(%rsp)
jae    126f <cubicMinimum+0x14f>
movapd %xmm4,%xmm0
movsd  %xmm7,0x8(%rsp)
movapd %xmm3,0x30(%rsp)
movapd %xmm4,0x50(%rsp)
movsd  %xmm8,0x48(%rsp)
call   1040 <sqrt@plt>
movsd  0x48(%rsp),%xmm8
movapd 0x50(%rsp),%xmm4
movapd 0x30(%rsp),%xmm3
movsd  0x8(%rsp),%xmm7
movapd 0x20(%rsp),%xmm1
movaps 0x10(%rsp),%xmm6
movss  0x4(%rsp),%xmm5
movapd %xmm0,%xmm2
subsd  %xmm3,%xmm2
addsd  %xmm7,%xmm7
divsd  %xmm7,%xmm2
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm4
movsd  %xmm2,0x30(%rsp)
jae    12c0 <cubicMinimum+0x1a0>
movapd %xmm4,%xmm0
movsd  %xmm7,0x8(%rsp)
call   1040 <sqrt@plt>
movsd  0x30(%rsp),%xmm2
movsd  0x8(%rsp),%xmm7
movapd 0x20(%rsp),%xmm1
movaps 0x10(%rsp),%xmm6
movss  0x4(%rsp),%xmm5
movapd %xmm0,%xmm8
xorpd  %xmm0,%xmm0
subsd  %xmm8,%xmm1
divsd  %xmm7,%xmm1
ucomisd %xmm0,%xmm2
movapd %xmm1,0x20(%rsp)
jbe    1324 <cubicMinimum+0x204>
movsd  0xd5b(%rip),%xmm0
ucomisd %xmm2,%xmm0
jbe    1324 <cubicMinimum+0x204>
mov    %rbx,%rdi
movapd %xmm2,%xmm0
call   1030 <cubicInterpolate@plt>
movapd %xmm0,%xmm5
movsd  0x30(%rsp),%xmm1
cvtsd2ss %xmm1,%xmm1
movapd %xmm0,%xmm2
movss  0x4(%rsp),%xmm3
cmpltss %xmm3,%xmm2
andps  %xmm2,%xmm1
andnps 0x10(%rsp),%xmm2
orps   %xmm1,%xmm2
movapd 0x20(%rsp),%xmm1
minss  %xmm3,%xmm5
movaps %xmm2,%xmm6
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm1
jbe    1381 <cubicMinimum+0x261>
movsd  0xd02(%rip),%xmm0
ucomisd %xmm1,%xmm0
jbe    1381 <cubicMinimum+0x261>
mov    %rbx,%rdi
movapd %xmm1,%xmm0
movss  %xmm5,0x4(%rsp)
movaps %xmm6,0x10(%rsp)
call   1030 <cubicInterpolate@plt>
movapd %xmm0,%xmm5
movaps 0x20(%rsp),%xmm1
cvtsd2ss %xmm1,%xmm1
movapd %xmm0,%xmm2
movss  0x4(%rsp),%xmm3
cmpltss %xmm3,%xmm2
andps  %xmm2,%xmm1
andnps 0x10(%rsp),%xmm2
orps   %xmm1,%xmm2
minss  %xmm3,%xmm5
movaps %xmm2,%xmm6
movss  %xmm5,(%r15)
movss  %xmm6,(%r14)
movaps %xmm5,%xmm0
add    $0x60,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define float @cubicMinimum(float* %0, float* %1, float* %2) {
%4 = alloca float*
%5 = alloca float*
%6 = alloca float*
%7 = alloca float
%8 = alloca float
%9 = alloca double
%10 = alloca double
%11 = alloca double
%12 = alloca double
%13 = alloca double
%14 = alloca double
%15 = alloca float
%16 = alloca float
store float* %0, float** %4
store float* %1, float** %5
store float* %2, float** %6
%17 = load float*, float** %4
%18 = getelementptr inbounds float, float* %17, i64 1
%19 = load float, float* %18
%20 = load float*, float** %4
%21 = getelementptr inbounds float, float* %20, i64 2
%22 = load float, float* %21
%23 = fcmp olt float %19, %22
br i1 %23, label %24, label %28
24: ; preds = %3
%25 = load float*, float** %4
%26 = getelementptr inbounds float, float* %25, i64 1
%27 = load float, float* %26
store float %27, float* %7
store float 0.000000e+00, float* %8
br label %32
28: ; preds = %3
%29 = load float*, float** %4
%30 = getelementptr inbounds float, float* %29, i64 2
%31 = load float, float* %30
store float %31, float* %7
store float 1.000000e+00, float* %8
br label %32
32: ; preds = %28, %24
%33 = load float*, float** %4
%34 = getelementptr inbounds float, float* %33, i64 1
%35 = load float, float* %34
%36 = load float*, float** %4
%37 = getelementptr inbounds float, float* %36, i64 2
%38 = load float, float* %37
%39 = fsub float %35, %38
%40 = fpext float %39 to double
%41 = load float*, float** %4
%42 = getelementptr inbounds float, float* %41, i64 3
%43 = load float, float* %42
%44 = fpext float %43 to double
%45 = call double @llvm.fmuladd.f64(double 3.000000e+00, double %40, double %44)
%46 = load float*, float** %4
%47 = getelementptr inbounds float, float* %46, i64 0
%48 = load float, float* %47
%49 = fpext float %48 to double
%50 = fsub double %45, %49
%51 = fmul double 1.500000e+00, %50
store double %51, double* %9
%52 = load float*, float** %4
%53 = getelementptr inbounds float, float* %52, i64 0
%54 = load float, float* %53
%55 = fpext float %54 to double
%56 = load float*, float** %4
%57 = getelementptr inbounds float, float* %56, i64 1
%58 = load float, float* %57
%59 = fpext float %58 to double
%60 = fmul double 5.000000e+00, %59
%61 = fneg double %60
%62 = call double @llvm.fmuladd.f64(double 2.000000e+00, double %55, double %61)
%63 = load float*, float** %4
%64 = getelementptr inbounds float, float* %63, i64 2
%65 = load float, float* %64
%66 = fpext float %65 to double
%67 = call double @llvm.fmuladd.f64(double 4.000000e+00, double %66, double %62)
%68 = load float*, float** %4
%69 = getelementptr inbounds float, float* %68, i64 3
%70 = load float, float* %69
%71 = fpext float %70 to double
%72 = fsub double %67, %71
store double %72, double* %10
%73 = load float*, float** %4
%74 = getelementptr inbounds float, float* %73, i64 2
%75 = load float, float* %74
%76 = load float*, float** %4
%77 = getelementptr inbounds float, float* %76, i64 0
%78 = load float, float* %77
%79 = fsub float %75, %78
%80 = fpext float %79 to double
%81 = fmul double 5.000000e-01, %80
store double %81, double* %11
%82 = load double, double* %10
%83 = load double, double* %10
%84 = load double, double* %9
%85 = fmul double 4.000000e+00, %84
%86 = load double, double* %11
%87 = fmul double %85, %86
%88 = fneg double %87
%89 = call double @llvm.fmuladd.f64(double %82, double %83, double %88)
store double %89, double* %14
%90 = load double, double* %14
%91 = fcmp oge double %90, 0.000000e+00
br i1 %91, label %92, label %145
92: ; preds = %32
%93 = load double, double* %10
%94 = fneg double %93
%95 = load double, double* %14
%96 = call double @sqrt(double %95)
%97 = fadd double %94, %96
%98 = load double, double* %9
%99 = fmul double 2.000000e+00, %98
%100 = fdiv double %97, %99
store double %100, double* %12
%101 = load double, double* %10
%102 = fneg double %101
%103 = load double, double* %14
%104 = call double @sqrt(double %103)
%105 = fsub double %102, %104
%106 = load double, double* %9
%107 = fmul double 2.000000e+00, %106
%108 = fdiv double %105, %107
store double %108, double* %13
%109 = load double, double* %12
%110 = fcmp ogt double %109, 0.000000e+00
br i1 %110, label %111, label %126
111: ; preds = %92
%112 = load double, double* %12
%113 = fcmp olt double %112, 1.000000e+00
br i1 %113, label %114, label %126
114: ; preds = %111
%115 = load float*, float** %4
%116 = load double, double* %12
%117 = call float @cubicInterpolate(float* %115, double %116)
store float %117, float* %15
%118 = load float, float* %15
%119 = load float, float* %7
%120 = fcmp olt float %118, %119
br i1 %120, label %121, label %125
121: ; preds = %114
%122 = load float, float* %15
store float %122, float* %7
%123 = load double, double* %12
%124 = fptrunc double %123 to float
store float %124, float* %8
br label %125
125: ; preds = %121, %114
br label %126
126: ; preds = %125, %111, %92
%127 = load double, double* %13
%128 = fcmp ogt double %127, 0.000000e+00
br i1 %128, label %129, label %144
129: ; preds = %126
%130 = load double, double* %13
%131 = fcmp olt double %130, 1.000000e+00
br i1 %131, label %132, label %144
132: ; preds = %129
%133 = load float*, float** %4
%134 = load double, double* %13
%135 = call float @cubicInterpolate(float* %133, double %134)
store float %135, float* %16
%136 = load float, float* %16
%137 = load float, float* %7
%138 = fcmp olt float %136, %137
br i1 %138, label %139, label %143
139: ; preds = %132
%140 = load float, float* %16
store float %140, float* %7
%141 = load double, double* %13
%142 = fptrunc double %141 to float
store float %142, float* %8
br label %143
143: ; preds = %139, %132
br label %144
144: ; preds = %143, %129, %126
br label %145
145: ; preds = %144, %32
%146 = load float, float* %7
%147 = load float*, float** %5
store float %146, float* %147
%148 = load float, float* %8
%149 = load float*, float** %6
store float %148, float* %149
%150 = load float, float* %7
ret float %150
}

LLVM IR (-O2):
define float @cubicMinimum(float* %0, float* nocapture writeonly %1, float* nocapture writeonly %2) {
%4 = getelementptr inbounds float, float* %0, i64 1
%5 = load float, float* %4
%6 = getelementptr inbounds float, float* %0, i64 2
%7 = load float, float* %6
%8 = fcmp olt float %5, %7
%9 = select i1 %8, float 0.000000e+00, float 1.000000e+00
%10 = select i1 %8, float %5, float %7
%11 = fsub float %5, %7
%12 = fpext float %11 to double
%13 = getelementptr inbounds float, float* %0, i64 3
%14 = load float, float* %13
%15 = fpext float %14 to double
%16 = tail call double @llvm.fmuladd.f64(double %12, double 3.000000e+00, double %15)
%17 = load float, float* %0
%18 = fpext float %17 to double
%19 = fsub double %16, %18
%20 = fmul double %19, 1.500000e+00
%21 = fpext float %5 to double
%22 = fmul double %21, -5.000000e+00
%23 = tail call double @llvm.fmuladd.f64(double %18, double 2.000000e+00, double %22)
%24 = fpext float %7 to double
%25 = tail call double @llvm.fmuladd.f64(double %24, double 4.000000e+00, double %23)
%26 = fsub double %25, %15
%27 = fsub float %7, %17
%28 = fpext float %27 to double
%29 = fmul double %28, 5.000000e-01
%30 = fmul double %20, -4.000000e+00
%31 = fmul double %29, %30
%32 = tail call double @llvm.fmuladd.f64(double %26, double %26, double %31)
%33 = fcmp ult double %32, 0.000000e+00
br i1 %33, label %64, label %34
34: ; preds = %3
%35 = fneg double %26
%36 = tail call double @sqrt(double %32)
%37 = fsub double %36, %26
%38 = fmul double %20, 2.000000e+00
%39 = fdiv double %37, %38
%40 = tail call double @sqrt(double %32)
%41 = fsub double %35, %40
%42 = fdiv double %41, %38
%43 = fcmp ogt double %39, 0.000000e+00
%44 = fcmp olt double %39, 1.000000e+00
%45 = and i1 %43, %44
br i1 %45, label %46, label %52
46: ; preds = %34
%47 = tail call float @cubicInterpolate(float* %0, double %39)
%48 = fcmp olt float %47, %10
%49 = fptrunc double %39 to float
%50 = select i1 %48, float %49, float %9
%51 = select i1 %48, float %47, float %10
br label %52
52: ; preds = %46, %34
%53 = phi float [ %50, %46 ], [ %9, %34 ]
%54 = phi float [ %51, %46 ], [ %10, %34 ]
%55 = fcmp ogt double %42, 0.000000e+00
%56 = fcmp olt double %42, 1.000000e+00
%57 = and i1 %55, %56
br i1 %57, label %58, label %64
58: ; preds = %52
%59 = tail call float @cubicInterpolate(float* %0, double %42)
%60 = fcmp olt float %59, %54
%61 = fptrunc double %42 to float
%62 = select i1 %60, float %61, float %53
%63 = select i1 %60, float %59, float %54
br label %64
64: ; preds = %52, %58, %3
%65 = phi float [ %62, %58 ], [ %53, %52 ], [ %9, %3 ]
%66 = phi float [ %63, %58 ], [ %54, %52 ], [ %10, %3 ]
store float %66, float* %1
store float %65, float* %2
ret float %66
}