#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 round(float);
double geom_cross2d(const double a[2], const double b[2]) {
  float dot = a[0] * b[0] + a[1] * b[1];
  float cross = a[0] * b[1] - a[1] * b[0];
  if (cross > dot) {
    return cross;
  } else {
    const double s = round(dot / (a[0] * a[0] + a[1] * a[1]));
    double bb[2] = {b[0] - a[0] * s, b[1] - a[1] * s};
    return a[0] * bb[1] - a[1] * bb[0];
  }
}


x86 assembly (clang, -O0):
<geom_cross2d>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movsd  (%rax),%xmm2
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x18(%rbp),%rax
mulsd  0x8(%rax),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x1c(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movsd  0x8(%rax),%xmm2
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x18(%rbp),%rax
mulsd  (%rax),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x20(%rbp)
movss  -0x20(%rbp),%xmm0
ucomiss -0x1c(%rbp),%xmm0
jbe    11bf <geom_cross2d+0xaf>
movss  -0x20(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    12b7 <geom_cross2d+0x1a7>
movss  -0x1c(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm3
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm2
mov    -0x10(%rbp),%rax
mulsd  0x8(%rax),%xmm2
mulsd  %xmm3,%xmm1
addsd  %xmm2,%xmm1
divsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
call   1030 <round@plt>
movsd  %xmm0,-0x28(%rbp)
mov    -0x18(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  -0x28(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x18(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
movsd  -0x28(%rbp),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  -0x38(%rbp),%xmm2
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm1
mulsd  -0x40(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<geom_cross2d>:
push   %r14
push   %rbx
push   %rax
movsd  (%rdi),%xmm0
movsd  0x8(%rdi),%xmm1
movupd (%rsi),%xmm2
movapd 0xed7(%rip),%xmm3
xorpd  %xmm1,%xmm3
unpcklpd %xmm1,%xmm3
mulpd  %xmm2,%xmm3
shufpd $0x1,%xmm2,%xmm2
movapd %xmm0,%xmm4
unpcklpd %xmm0,%xmm4
mulpd  %xmm2,%xmm4
addpd  %xmm3,%xmm4
cvtpd2ps %xmm4,%xmm2
movapd %xmm2,%xmm3
shufps $0x55,%xmm2,%xmm3
ucomiss %xmm3,%xmm2
jbe    1164 <geom_cross2d+0x54>
xorps  %xmm0,%xmm0
cvtss2sd %xmm2,%xmm0
jmp    11c5 <geom_cross2d+0xb5>
mov    %rsi,%r14
mov    %rdi,%rbx
xorps  %xmm2,%xmm2
cvtss2sd %xmm3,%xmm2
mulsd  %xmm1,%xmm1
mulsd  %xmm0,%xmm0
addsd  %xmm1,%xmm0
divsd  %xmm0,%xmm2
xorps  %xmm0,%xmm0
cvtsd2ss %xmm2,%xmm0
call   1030 <round@plt>
movsd  (%rbx),%xmm2
movsd  0x8(%rbx),%xmm3
movapd %xmm2,%xmm1
mulsd  %xmm0,%xmm1
movsd  (%r14),%xmm4
subsd  %xmm1,%xmm4
movsd  0x8(%r14),%xmm1
mulsd  %xmm3,%xmm0
subsd  %xmm0,%xmm1
mulsd  %xmm3,%xmm4
mulsd  %xmm2,%xmm1
subsd  %xmm4,%xmm1
movapd %xmm1,%xmm0
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define double @geom_cross2d(double* %0, double* %1) {
%3 = alloca double
%4 = alloca double*
%5 = alloca double*
%6 = alloca float
%7 = alloca float
%8 = alloca double
%9 = alloca [2 x double]
store double* %0, double** %4
store double* %1, double** %5
%10 = load double*, double** %4
%11 = getelementptr inbounds double, double* %10, i64 0
%12 = load double, double* %11
%13 = load double*, double** %5
%14 = getelementptr inbounds double, double* %13, i64 0
%15 = load double, double* %14
%16 = load double*, double** %4
%17 = getelementptr inbounds double, double* %16, i64 1
%18 = load double, double* %17
%19 = load double*, double** %5
%20 = getelementptr inbounds double, double* %19, i64 1
%21 = load double, double* %20
%22 = fmul double %18, %21
%23 = call double @llvm.fmuladd.f64(double %12, double %15, double %22)
%24 = fptrunc double %23 to float
store float %24, float* %6
%25 = load double*, double** %4
%26 = getelementptr inbounds double, double* %25, i64 0
%27 = load double, double* %26
%28 = load double*, double** %5
%29 = getelementptr inbounds double, double* %28, i64 1
%30 = load double, double* %29
%31 = load double*, double** %4
%32 = getelementptr inbounds double, double* %31, i64 1
%33 = load double, double* %32
%34 = load double*, double** %5
%35 = getelementptr inbounds double, double* %34, i64 0
%36 = load double, double* %35
%37 = fmul double %33, %36
%38 = fneg double %37
%39 = call double @llvm.fmuladd.f64(double %27, double %30, double %38)
%40 = fptrunc double %39 to float
store float %40, float* %7
%41 = load float, float* %7
%42 = load float, float* %6
%43 = fcmp ogt float %41, %42
br i1 %43, label %44, label %47
44: ; preds = %2
%45 = load float, float* %7
%46 = fpext float %45 to double
store double %46, double* %3
br label %100
47: ; preds = %2
%48 = load float, float* %6
%49 = fpext float %48 to double
%50 = load double*, double** %4
%51 = getelementptr inbounds double, double* %50, i64 0
%52 = load double, double* %51
%53 = load double*, double** %4
%54 = getelementptr inbounds double, double* %53, i64 0
%55 = load double, double* %54
%56 = load double*, double** %4
%57 = getelementptr inbounds double, double* %56, i64 1
%58 = load double, double* %57
%59 = load double*, double** %4
%60 = getelementptr inbounds double, double* %59, i64 1
%61 = load double, double* %60
%62 = fmul double %58, %61
%63 = call double @llvm.fmuladd.f64(double %52, double %55, double %62)
%64 = fdiv double %49, %63
%65 = fptrunc double %64 to float
%66 = call double @round(float %65)
store double %66, double* %8
%67 = getelementptr inbounds [2 x double], [2 x double]* %9, i64 0, i64 0
%68 = load double*, double** %5
%69 = getelementptr inbounds double, double* %68, i64 0
%70 = load double, double* %69
%71 = load double*, double** %4
%72 = getelementptr inbounds double, double* %71, i64 0
%73 = load double, double* %72
%74 = load double, double* %8
%75 = fneg double %73
%76 = call double @llvm.fmuladd.f64(double %75, double %74, double %70)
store double %76, double* %67
%77 = getelementptr inbounds double, double* %67, i64 1
%78 = load double*, double** %5
%79 = getelementptr inbounds double, double* %78, i64 1
%80 = load double, double* %79
%81 = load double*, double** %4
%82 = getelementptr inbounds double, double* %81, i64 1
%83 = load double, double* %82
%84 = load double, double* %8
%85 = fneg double %83
%86 = call double @llvm.fmuladd.f64(double %85, double %84, double %80)
store double %86, double* %77
%87 = load double*, double** %4
%88 = getelementptr inbounds double, double* %87, i64 0
%89 = load double, double* %88
%90 = getelementptr inbounds [2 x double], [2 x double]* %9, i64 0, i64 1
%91 = load double, double* %90
%92 = load double*, double** %4
%93 = getelementptr inbounds double, double* %92, i64 1
%94 = load double, double* %93
%95 = getelementptr inbounds [2 x double], [2 x double]* %9, i64 0, i64 0
%96 = load double, double* %95
%97 = fmul double %94, %96
%98 = fneg double %97
%99 = call double @llvm.fmuladd.f64(double %89, double %91, double %98)
store double %99, double* %3
br label %100
100: ; preds = %47, %44
%101 = load double, double* %3
ret double %101
}

LLVM IR (-O2):
define double @geom_cross2d(double* nocapture %0, double* nocapture %1) {
%3 = load double, double* %0
%4 = getelementptr inbounds double, double* %0, i64 1
%5 = load double, double* %4
%6 = bitcast double* %1 to <2 x double>*
%7 = load <2 x double>, <2 x double>* %6
%8 = shufflevector <2 x double> %7, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%9 = fneg double %5
%10 = insertelement <2 x double> poison, double %9, i64 0
%11 = insertelement <2 x double> %10, double %5, i64 1
%12 = fmul <2 x double> %7, %11
%13 = insertelement <2 x double> poison, double %3, i64 0
%14 = shufflevector <2 x double> %13, <2 x double> poison, <2 x i32> zeroinitializer
%15 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %14, <2 x double> %8, <2 x double> %12)
%16 = fptrunc <2 x double> %15 to <2 x float>
%17 = extractelement <2 x float> %16, i64 0
%18 = extractelement <2 x float> %16, i64 1
%19 = fcmp ogt float %17, %18
br i1 %19, label %20, label %22
20: ; preds = %2
%21 = fpext float %17 to double
br label %40
22: ; preds = %2
%23 = getelementptr inbounds double, double* %1, i64 1
%24 = fpext float %18 to double
%25 = fmul double %5, %5
%26 = tail call double @llvm.fmuladd.f64(double %3, double %3, double %25)
%27 = fdiv double %24, %26
%28 = fptrunc double %27 to float
%29 = tail call double @round(float %28)
%30 = load double, double* %1
%31 = load double, double* %0
%32 = fneg double %31
%33 = tail call double @llvm.fmuladd.f64(double %32, double %29, double %30)
%34 = load double, double* %23
%35 = load double, double* %4
%36 = fneg double %35
%37 = tail call double @llvm.fmuladd.f64(double %36, double %29, double %34)
%38 = fmul double %33, %36
%39 = tail call double @llvm.fmuladd.f64(double %31, double %37, double %38)
br label %40
40: ; preds = %22, %20
%41 = phi double [ %21, %20 ], [ %39, %22 ]
ret double %41
}