#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 gss(double a, double b, double (*f)(double)) {
  double r = (sqrt(5) - 1) / 2, eps = 1e-7;
  double x1 = b - r * (b - a), x2 = a + r * (b - a);
  double f1 = f(x1), f2 = f(x2);
  while (b - a > eps)
    if (f1 < f2) {
      b = x2;
      x2 = x1;
      f2 = f1;
      x1 = b - r * (b - a);
      f1 = f(x1);
    } else {
      a = x1;
      x1 = x2;
      f1 = f2;
      x2 = a + r * (b - a);
      f2 = f(x2);
    }
  return a;
}


x86 assembly (clang, -O0):
<gss>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
mov    %rdi,-0x18(%rbp)
mov    $0x5,%edi
call   1030 <sqrt@plt>
sub    $0x1,%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x20(%rbp)
movsd  0xeb4(%rip),%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x10(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm0
movsd  -0x10(%rbp),%xmm2
subsd  -0x8(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x8(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm0
movsd  -0x10(%rbp),%xmm2
subsd  -0x8(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x18(%rbp),%rax
movsd  -0x30(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x40(%rbp)
mov    -0x18(%rbp),%rax
movsd  -0x38(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm0
subsd  -0x8(%rbp),%xmm0
ucomisd -0x28(%rbp),%xmm0
jbe    12b2 <gss+0x1a2>
movsd  -0x40(%rbp),%xmm1
movsd  -0x48(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jbe    125e <gss+0x14e>
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x10(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm0
movsd  -0x10(%rbp),%xmm2
subsd  -0x8(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x18(%rbp),%rax
movsd  -0x30(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x40(%rbp)
jmp    12ad <gss+0x19d>
movsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x8(%rbp),%xmm1
movsd  -0x20(%rbp),%xmm0
movsd  -0x10(%rbp),%xmm2
subsd  -0x8(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x18(%rbp),%rax
movsd  -0x38(%rbp),%xmm0
call   *%rax
movsd  %xmm0,-0x48(%rbp)
jmp    11ca <gss+0xba>
movsd  -0x8(%rbp),%xmm0
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<gss>:
push   %rbx
sub    $0x70,%rsp
mov    %rdi,%rbx
movsd  %xmm1,0x28(%rsp)
movsd  %xmm0,0x18(%rsp)
mov    $0x5,%edi
call   1030 <sqrt@plt>
mov    %eax,%ecx
add    $0xffffffff,%ecx
shr    $0x1f,%ecx
add    %ecx,%eax
add    $0xffffffff,%eax
sar    %eax
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  0x28(%rsp),%xmm2
movapd %xmm2,%xmm3
movsd  0x18(%rsp),%xmm1
subsd  %xmm1,%xmm3
movsd  %xmm3,0x10(%rsp)
movapd %xmm0,0x50(%rsp)
movapd %xmm0,%xmm4
mulsd  %xmm3,%xmm4
movapd %xmm2,%xmm0
subsd  %xmm4,%xmm0
addsd  %xmm1,%xmm4
movapd %xmm4,0x30(%rsp)
movsd  %xmm0,0x20(%rsp)
call   *%rbx
movsd  %xmm0,0x8(%rsp)
movapd 0x30(%rsp),%xmm0
call   *%rbx
movapd %xmm0,%xmm5
movsd  0x10(%rsp),%xmm0
ucomisd 0xe6a(%rip),%xmm0
jbe    12be <gss+0x1ae>
movapd 0xe4c(%rip),%xmm0
movapd 0x50(%rsp),%xmm2
xorpd  %xmm2,%xmm0
movapd %xmm0,0x60(%rsp)
movsd  0x20(%rsp),%xmm1
movapd 0x30(%rsp),%xmm3
movsd  0x8(%rsp),%xmm4
jmp    124e <gss+0x13e>
nopl   0x0(%rax,%rax,1)
movsd  0x28(%rsp),%xmm4
subsd  %xmm1,%xmm4
movsd  %xmm4,0x10(%rsp)
movapd %xmm2,%xmm0
mulsd  %xmm4,%xmm0
addsd  %xmm1,%xmm0
movapd %xmm0,0x40(%rsp)
movsd  %xmm5,0x8(%rsp)
call   *%rbx
movsd  0x10(%rsp),%xmm6
movsd  0x8(%rsp),%xmm5
movapd 0x30(%rsp),%xmm1
movapd 0x50(%rsp),%xmm2
movapd %xmm0,%xmm4
movsd  0x20(%rsp),%xmm0
movsd  %xmm0,0x18(%rsp)
movapd 0x40(%rsp),%xmm3
movapd %xmm5,%xmm0
ucomisd 0xdcc(%rip),%xmm6
movapd %xmm4,%xmm5
movapd %xmm0,%xmm4
jbe    12be <gss+0x1ae>
ucomisd %xmm4,%xmm5
movsd  %xmm1,0x20(%rsp)
movapd %xmm3,0x30(%rsp)
jbe    11e0 <gss+0xd0>
movapd %xmm3,%xmm2
subsd  0x18(%rsp),%xmm2
movsd  %xmm2,0x10(%rsp)
movapd 0x60(%rsp),%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm3,%xmm0
movsd  %xmm0,0x40(%rsp)
movsd  %xmm4,0x8(%rsp)
call   *%rbx
movsd  0x10(%rsp),%xmm6
movsd  0x8(%rsp),%xmm4
movsd  0x20(%rsp),%xmm3
movapd 0x50(%rsp),%xmm2
movapd %xmm0,%xmm5
movaps 0x30(%rsp),%xmm0
movsd  %xmm0,0x28(%rsp)
movsd  0x40(%rsp),%xmm1
jmp    1238 <gss+0x128>
movsd  0x18(%rsp),%xmm0
add    $0x70,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define double @gss(double %0, double %1, double (double)* %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double (double)*
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = alloca double
%12 = alloca double
store double %0, double* %4
store double %1, double* %5
store double (double)* %2, double (double)** %6
%13 = call i32 @sqrt(i32 5)
%14 = sub nsw i32 %13, 1
%15 = sdiv i32 %14, 2
%16 = sitofp i32 %15 to double
store double %16, double* %7
store double 0x3E7AD7F29ABCAF48, double* %8
%17 = load double, double* %5
%18 = load double, double* %7
%19 = load double, double* %5
%20 = load double, double* %4
%21 = fsub double %19, %20
%22 = fneg double %18
%23 = call double @llvm.fmuladd.f64(double %22, double %21, double %17)
store double %23, double* %9
%24 = load double, double* %4
%25 = load double, double* %7
%26 = load double, double* %5
%27 = load double, double* %4
%28 = fsub double %26, %27
%29 = call double @llvm.fmuladd.f64(double %25, double %28, double %24)
store double %29, double* %10
%30 = load double (double)*, double (double)** %6
%31 = load double, double* %9
%32 = call double %30(double %31)
store double %32, double* %11
%33 = load double (double)*, double (double)** %6
%34 = load double, double* %10
%35 = call double %33(double %34)
store double %35, double* %12
br label %36
36: ; preds = %73, %3
%37 = load double, double* %5
%38 = load double, double* %4
%39 = fsub double %37, %38
%40 = load double, double* %8
%41 = fcmp ogt double %39, %40
br i1 %41, label %42, label %74
42: ; preds = %36
%43 = load double, double* %11
%44 = load double, double* %12
%45 = fcmp olt double %43, %44
br i1 %45, label %46, label %60
46: ; preds = %42
%47 = load double, double* %10
store double %47, double* %5
%48 = load double, double* %9
store double %48, double* %10
%49 = load double, double* %11
store double %49, double* %12
%50 = load double, double* %5
%51 = load double, double* %7
%52 = load double, double* %5
%53 = load double, double* %4
%54 = fsub double %52, %53
%55 = fneg double %51
%56 = call double @llvm.fmuladd.f64(double %55, double %54, double %50)
store double %56, double* %9
%57 = load double (double)*, double (double)** %6
%58 = load double, double* %9
%59 = call double %57(double %58)
store double %59, double* %11
br label %73
60: ; preds = %42
%61 = load double, double* %9
store double %61, double* %4
%62 = load double, double* %10
store double %62, double* %9
%63 = load double, double* %12
store double %63, double* %11
%64 = load double, double* %4
%65 = load double, double* %7
%66 = load double, double* %5
%67 = load double, double* %4
%68 = fsub double %66, %67
%69 = call double @llvm.fmuladd.f64(double %65, double %68, double %64)
store double %69, double* %10
%70 = load double (double)*, double (double)** %6
%71 = load double, double* %10
%72 = call double %70(double %71)
store double %72, double* %12
br label %73
73: ; preds = %60, %46
br label %36
74: ; preds = %36
%75 = load double, double* %4
ret double %75
}

LLVM IR (-O2):
define double @gss(double %0, double %1, double (double)* nocapture %2) {
%4 = tail call i32 @sqrt(i32 5)
%5 = add nsw i32 %4, -1
%6 = sdiv i32 %5, 2
%7 = sitofp i32 %6 to double
%8 = fsub double %1, %0
%9 = fneg double %7
%10 = tail call double @llvm.fmuladd.f64(double %9, double %8, double %1)
%11 = tail call double @llvm.fmuladd.f64(double %7, double %8, double %0)
%12 = tail call double %2(double %10)
%13 = tail call double %2(double %11)
%14 = fcmp ogt double %8, 0x3E7AD7F29ABCAF48
br i1 %14, label %15, label %40
15: ; preds = %3, %31
%16 = phi double [ %38, %31 ], [ %13, %3 ]
%17 = phi double [ %37, %31 ], [ %12, %3 ]
%18 = phi double [ %36, %31 ], [ %11, %3 ]
%19 = phi double [ %35, %31 ], [ %10, %3 ]
%20 = phi double [ %34, %31 ], [ %0, %3 ]
%21 = phi double [ %33, %31 ], [ %1, %3 ]
%22 = fcmp olt double %17, %16
br i1 %22, label %23, label %27
23: ; preds = %15
%24 = fsub double %18, %20
%25 = tail call double @llvm.fmuladd.f64(double %9, double %24, double %18)
%26 = tail call double %2(double %25)
br label %31
27: ; preds = %15
%28 = fsub double %21, %19
%29 = tail call double @llvm.fmuladd.f64(double %7, double %28, double %19)
%30 = tail call double %2(double %29)
br label %31
31: ; preds = %27, %23
%32 = phi double [ %28, %27 ], [ %24, %23 ]
%33 = phi double [ %21, %27 ], [ %18, %23 ]
%34 = phi double [ %19, %27 ], [ %20, %23 ]
%35 = phi double [ %18, %27 ], [ %25, %23 ]
%36 = phi double [ %29, %27 ], [ %19, %23 ]
%37 = phi double [ %16, %27 ], [ %26, %23 ]
%38 = phi double [ %30, %27 ], [ %17, %23 ]
%39 = fcmp ogt double %32, 0x3E7AD7F29ABCAF48
br i1 %39, label %15, label %40
40: ; preds = %31, %3
%41 = phi double [ %0, %3 ], [ %34, %31 ]
ret double %41
}