#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);
float geom_cross2f(const float a[2], const float 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_cross2f>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  (%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x18(%rbp),%rax
mulss  0x4(%rax),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x1c(%rbp)
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x18(%rbp),%rax
movss  0x4(%rax),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm1
mov    -0x18(%rbp),%rax
mulss  (%rax),%xmm1
movd   %xmm1,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x20(%rbp)
movss  -0x20(%rbp),%xmm0
ucomiss -0x1c(%rbp),%xmm0
jbe    11a9 <geom_cross2f+0x99>
movss  -0x20(%rbp),%xmm0
movss  %xmm0,-0x4(%rbp)
jmp    12b5 <geom_cross2f+0x1a5>
movss  -0x1c(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm1
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm3
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm2
mov    -0x10(%rbp),%rax
mulss  0x4(%rax),%xmm2
mulss  %xmm3,%xmm1
addss  %xmm2,%xmm1
divss  %xmm1,%xmm0
call   1030 <round@plt>
movsd  %xmm0,-0x28(%rbp)
mov    -0x18(%rbp),%rax
movss  (%rax),%xmm0
cvtss2sd %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movss  (%rax),%xmm0
cvtss2sd %xmm0,%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
movss  0x4(%rax),%xmm0
cvtss2sd %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm0
cvtss2sd %xmm0,%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
movss  (%rax),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  -0x38(%rbp),%xmm2
mov    -0x10(%rbp),%rax
movss  0x4(%rax),%xmm1
cvtss2sd %xmm1,%xmm1
mulsd  -0x40(%rbp),%xmm1
movq   %xmm1,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x4(%rbp)
movss  -0x4(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<geom_cross2f>:
push   %r14
push   %rbx
push   %rax
movss  (%rdi),%xmm2
movss  0x4(%rdi),%xmm3
movsd  (%rsi),%xmm0
movaps 0xed8(%rip),%xmm1
xorps  %xmm3,%xmm1
unpcklps %xmm3,%xmm1
mulps  %xmm0,%xmm1
movaps %xmm0,%xmm4
shufps $0xe1,%xmm0,%xmm4
movaps %xmm2,%xmm0
shufps $0x0,%xmm2,%xmm0
mulps  %xmm4,%xmm0
addps  %xmm1,%xmm0
movaps %xmm0,%xmm1
shufps $0x55,%xmm0,%xmm1
ucomiss %xmm1,%xmm0
ja     11b9 <geom_cross2f+0xa9>
mov    %rsi,%r14
mov    %rdi,%rbx
mulss  %xmm3,%xmm3
mulss  %xmm2,%xmm2
addss  %xmm3,%xmm2
divss  %xmm2,%xmm1
movaps %xmm1,%xmm0
call   1030 <round@plt>
movss  (%r14),%xmm1
movss  0x4(%r14),%xmm2
cvtss2sd %xmm1,%xmm1
movss  (%rbx),%xmm3
movss  0x4(%rbx),%xmm4
cvtss2sd %xmm3,%xmm3
movaps %xmm3,%xmm5
mulsd  %xmm0,%xmm5
subsd  %xmm5,%xmm1
cvtss2sd %xmm2,%xmm2
cvtss2sd %xmm4,%xmm4
mulsd  %xmm4,%xmm0
subsd  %xmm0,%xmm2
mulsd  %xmm4,%xmm1
mulsd  %xmm3,%xmm2
subsd  %xmm1,%xmm2
xorps  %xmm0,%xmm0
cvtsd2ss %xmm2,%xmm0
add    $0x8,%rsp
pop    %rbx
pop    %r14
ret

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

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