#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 const fabs(double const);
int /*<<< orphan*/ frexp(double, int *);
double ldexp(double const, int);
int _sao_fcmp(const double x1, const double x2, const double epsilon) {
  int result;
  if (x1 == x2) {
    result = 0;
  } else if (0 == x1 || 0 == x2) {
    if (fabs(x1 - x2) < epsilon)
      result = 0;
    else {
      if (x1 > x2)
        result = 1;
      else
        result = -1;
    }
  } else {
    int exponent;
    double delta, difference;
    {
      double max = (fabs(x1) > fabs(x2)) ? x1 : x2;
      frexp(max, &exponent);
    }
    delta = ldexp(epsilon, exponent);
    difference = x1 - x2;
    if (difference > delta) {
      result = 1;
    } else if (difference < -delta) {
      result = -1;
    } else {
      result = 0;
    }
  }
  return result;
}


x86 assembly (clang, -O0):
<_sao_fcmp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
movsd  %xmm0,-0x8(%rbp)
movsd  %xmm1,-0x10(%rbp)
movsd  %xmm2,-0x18(%rbp)
movsd  -0x8(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jne    1169 <_sao_fcmp+0x39>
jp     1169 <_sao_fcmp+0x39>
movl   $0x0,-0x1c(%rbp)
jmp    12d6 <_sao_fcmp+0x1a6>
xorps  %xmm0,%xmm0
ucomisd -0x8(%rbp),%xmm0
jne    1182 <_sao_fcmp+0x52>
jp     1182 <_sao_fcmp+0x52>
jmp    1196 <_sao_fcmp+0x66>
xorps  %xmm0,%xmm0
ucomisd -0x10(%rbp),%xmm0
jne    11f0 <_sao_fcmp+0xc0>
jp     11f0 <_sao_fcmp+0xc0>
movsd  -0x8(%rbp),%xmm0
subsd  -0x10(%rbp),%xmm0
call   1050 <fabs@plt>
movaps %xmm0,%xmm1
movsd  -0x18(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jbe    11c3 <_sao_fcmp+0x93>
movl   $0x0,-0x1c(%rbp)
jmp    11eb <_sao_fcmp+0xbb>
movsd  -0x8(%rbp),%xmm0
ucomisd -0x10(%rbp),%xmm0
jbe    11df <_sao_fcmp+0xaf>
movl   $0x1,-0x1c(%rbp)
jmp    11e6 <_sao_fcmp+0xb6>
movl   $0xffffffff,-0x1c(%rbp)
jmp    11eb <_sao_fcmp+0xbb>
jmp    12d1 <_sao_fcmp+0x1a1>
movsd  -0x8(%rbp),%xmm0
call   1050 <fabs@plt>
movsd  %xmm0,-0x40(%rbp)
movsd  -0x10(%rbp),%xmm0
call   1050 <fabs@plt>
movaps %xmm0,%xmm1
movsd  -0x40(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jbe    122a <_sao_fcmp+0xfa>
movsd  -0x8(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
jmp    1234 <_sao_fcmp+0x104>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x48(%rbp)
movsd  -0x48(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x38(%rbp),%xmm0
lea    -0x20(%rbp),%rdi
call   1040 <frexp@plt>
movsd  -0x18(%rbp),%xmm0
mov    -0x20(%rbp),%edi
call   1030 <ldexp@plt>
movsd  %xmm0,-0x28(%rbp)
movsd  -0x8(%rbp),%xmm0
subsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x30(%rbp),%xmm0
ucomisd -0x28(%rbp),%xmm0
jbe    1289 <_sao_fcmp+0x159>
movl   $0x1,-0x1c(%rbp)
jmp    12cc <_sao_fcmp+0x19c>
movsd  -0x30(%rbp),%xmm1
movsd  -0x28(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
ucomisd %xmm1,%xmm0
jbe    12c0 <_sao_fcmp+0x190>
movl   $0xffffffff,-0x1c(%rbp)
jmp    12c7 <_sao_fcmp+0x197>
movl   $0x0,-0x1c(%rbp)
jmp    12cc <_sao_fcmp+0x19c>
jmp    12d1 <_sao_fcmp+0x1a1>
jmp    12d6 <_sao_fcmp+0x1a6>
mov    -0x1c(%rbp),%eax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_sao_fcmp>:
sub    $0x38,%rsp
xor    %eax,%eax
ucomisd %xmm1,%xmm0
jne    1133 <_sao_fcmp+0x13>
jp     1133 <_sao_fcmp+0x13>
add    $0x38,%rsp
ret
movapd %xmm0,%xmm3
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm3
jne    1147 <_sao_fcmp+0x27>
jnp    11db <_sao_fcmp+0xbb>
ucomisd %xmm0,%xmm1
jne    1153 <_sao_fcmp+0x33>
jnp    11db <_sao_fcmp+0xbb>
movapd 0xea5(%rip),%xmm0
movapd %xmm3,%xmm4
movapd %xmm3,0x20(%rsp)
andpd  %xmm0,%xmm3
andpd  %xmm1,%xmm0
cmpltsd %xmm3,%xmm0
movapd %xmm0,%xmm3
andpd  %xmm4,%xmm3
andnpd %xmm1,%xmm0
orpd   %xmm3,%xmm0
lea    0x4(%rsp),%rdi
movapd %xmm1,0x10(%rsp)
movsd  %xmm2,0x8(%rsp)
call   1040 <frexp@plt>
mov    0x4(%rsp),%edi
movsd  0x8(%rsp),%xmm0
call   1030 <ldexp@plt>
movapd 0x20(%rsp),%xmm2
subsd  0x10(%rsp),%xmm2
movapd 0xe55(%rip),%xmm1
xorpd  %xmm0,%xmm1
xor    %ecx,%ecx
ucomisd %xmm2,%xmm1
seta   %cl
neg    %ecx
ucomisd %xmm0,%xmm2
mov    $0x1,%eax
cmovbe %ecx,%eax
add    $0x38,%rsp
ret
movapd %xmm3,%xmm0
subsd  %xmm1,%xmm0
andpd  0xe15(%rip),%xmm0
ucomisd %xmm0,%xmm2
ja     112e <_sao_fcmp+0xe>
xor    %eax,%eax
ucomisd %xmm1,%xmm3
seta   %al
add    %eax,%eax
add    $0xffffffff,%eax
add    $0x38,%rsp
ret

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

LLVM IR (-O2):
define i32 @_sao_fcmp(double %0, double %1, double %2) {
%4 = alloca i32
%5 = fcmp oeq double %0, %1
br i1 %5, label %32, label %6
6: ; preds = %3
%7 = fcmp oeq double %0, 0.000000e+00
%8 = fcmp oeq double %1, 0.000000e+00
%9 = or i1 %7, %8
br i1 %9, label %10, label %17
10: ; preds = %6
%11 = fsub double %0, %1
%12 = tail call double @llvm.fabs.f64(double %11)
%13 = fcmp olt double %12, %2
br i1 %13, label %32, label %14
14: ; preds = %10
%15 = fcmp ogt double %0, %1
%16 = select i1 %15, i32 1, i32 -1
br label %32
17: ; preds = %6
%18 = bitcast i32* %4 to i8*
%19 = tail call double @llvm.fabs.f64(double %0)
%20 = tail call double @llvm.fabs.f64(double %1)
%21 = fcmp ogt double %19, %20
%22 = select i1 %21, double %0, double %1
%23 = call i32 @frexp(double %22, i32* %4)
%24 = load i32, i32* %4
%25 = tail call double @ldexp(double %2, i32 %24)
%26 = fsub double %0, %1
%27 = fcmp ogt double %26, %25
%28 = fneg double %25
%29 = fcmp olt double %26, %28
%30 = sext i1 %29 to i32
%31 = select i1 %27, i32 1, i32 %30
br label %32
32: ; preds = %14, %10, %3, %17
%33 = phi i32 [ %31, %17 ], [ 0, %3 ], [ 0, %10 ], [ %16, %14 ]
ret i32 %33
}