#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 /*<<< orphan*/ cross(double *, double *, double *);
double dot(double *, double *, int);
int /*<<< orphan*/ normalize(double *, double *, int);
int /*<<< orphan*/ sub(double *, double *, double *, int);
void plane_from_3points(double *coeffs, double *p0, double *p1, double *p2) {
  double diff1[3], diff2[3];
  sub(diff1, p1, p0, 3);
  sub(diff2, p2, p0, 3);
  double normal[3];
  cross(normal, diff1, diff2);
  normalize(normal, normal, 3);
  double flip = normal[2] > 0.0 ? -1.0 : 1.0;
  coeffs[0] = normal[0] * flip;
  coeffs[1] = normal[1] * flip;
  coeffs[2] = normal[2] * flip;
  coeffs[3] = -dot(normal, p0, 3) * flip;
}


x86 assembly (clang, -O0):
<plane_from_3points>:
push   %rbp
mov    %rsp,%rbp
sub    $0x90,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
lea    -0x40(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    -0x10(%rbp),%rdx
mov    $0x3,%ecx
call   1060 <sub@plt>
lea    -0x60(%rbp),%rdi
mov    -0x20(%rbp),%rsi
mov    -0x10(%rbp),%rdx
mov    $0x3,%ecx
call   1060 <sub@plt>
lea    -0x80(%rbp),%rdi
lea    -0x40(%rbp),%rsi
lea    -0x60(%rbp),%rdx
call   1050 <cross@plt>
lea    -0x80(%rbp),%rdi
lea    -0x80(%rbp),%rsi
mov    $0x3,%edx
call   1040 <normalize@plt>
movsd  -0x70(%rbp),%xmm1
movsd  0xe49(%rip),%xmm3
movsd  0xe49(%rip),%xmm2
xorps  %xmm0,%xmm0
cmpltsd %xmm1,%xmm0
movaps %xmm0,%xmm1
andpd  %xmm3,%xmm1
andnpd %xmm2,%xmm0
orpd   %xmm1,%xmm0
movsd  %xmm0,-0x88(%rbp)
ff
movsd  -0x80(%rbp),%xmm0
mulsd  -0x88(%rbp),%xmm0
ff
mov    -0x8(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x78(%rbp),%xmm0
mulsd  -0x88(%rbp),%xmm0
ff
mov    -0x8(%rbp),%rax
movsd  %xmm0,0x8(%rax)
movsd  -0x70(%rbp),%xmm0
mulsd  -0x88(%rbp),%xmm0
ff
mov    -0x8(%rbp),%rax
movsd  %xmm0,0x10(%rax)
lea    -0x80(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    $0x3,%edx
call   1030 <dot@plt>
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  -0x88(%rbp),%xmm0
ff
mov    -0x8(%rbp),%rax
movsd  %xmm0,0x18(%rax)
add    $0x90,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<plane_from_3points>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x70,%rsp
mov    %rcx,%r15
mov    %rsi,%rbx
mov    %rdi,%r14
lea    0x50(%rsp),%r12
mov    %r12,%rdi
mov    %rdx,%rsi
mov    %rbx,%rdx
mov    $0x3,%ecx
call   1060 <sub@plt>
lea    0x30(%rsp),%r13
mov    %r13,%rdi
mov    %r15,%rsi
mov    %rbx,%rdx
mov    $0x3,%ecx
call   1060 <sub@plt>
lea    0x10(%rsp),%r15
mov    %r15,%rdi
mov    %r12,%rsi
mov    %r13,%rdx
call   1050 <cross@plt>
mov    %r15,%rdi
mov    %r15,%rsi
mov    $0x3,%edx
call   1040 <normalize@plt>
movsd  0x20(%rsp),%xmm0
xorpd  %xmm1,%xmm1
xor    %eax,%eax
ucomisd %xmm1,%xmm0
seta   %al
lea    0xe3d(%rip),%rcx
movsd  (%rcx,%rax,8),%xmm2
movapd %xmm2,(%rsp)
movapd %xmm2,%xmm1
unpcklpd %xmm2,%xmm1
mulpd  0x10(%rsp),%xmm1
movupd %xmm1,(%r14)
mulsd  %xmm2,%xmm0
movsd  %xmm0,0x10(%r14)
mov    %r15,%rdi
mov    %rbx,%rsi
mov    $0x3,%edx
call   1030 <dot@plt>
xorpd  0xe0e(%rip),%xmm0
mulsd  (%rsp),%xmm0
movsd  %xmm0,0x18(%r14)
add    $0x70,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @plane_from_3points(double* %0, double* %1, double* %2, double* %3) {
%5 = alloca double*
%6 = alloca double*
%7 = alloca double*
%8 = alloca double*
%9 = alloca [3 x double]
%10 = alloca [3 x double]
%11 = alloca [3 x double]
%12 = alloca double
store double* %0, double** %5
store double* %1, double** %6
store double* %2, double** %7
store double* %3, double** %8
%13 = getelementptr inbounds [3 x double], [3 x double]* %9, i64 0, i64 0
%14 = load double*, double** %7
%15 = load double*, double** %6
%16 = call i32 @sub(double* %13, double* %14, double* %15, i32 3)
%17 = getelementptr inbounds [3 x double], [3 x double]* %10, i64 0, i64 0
%18 = load double*, double** %8
%19 = load double*, double** %6
%20 = call i32 @sub(double* %17, double* %18, double* %19, i32 3)
%21 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%22 = getelementptr inbounds [3 x double], [3 x double]* %9, i64 0, i64 0
%23 = getelementptr inbounds [3 x double], [3 x double]* %10, i64 0, i64 0
%24 = call i32 @cross(double* %21, double* %22, double* %23)
%25 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%26 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%27 = call i32 @normalize(double* %25, double* %26, i32 3)
%28 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 2
%29 = load double, double* %28
%30 = fcmp ogt double %29, 0.000000e+00
%31 = zext i1 %30 to i64
%32 = select i1 %30, double -1.000000e+00, double 1.000000e+00
store double %32, double* %12
%33 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%34 = load double, double* %33
%35 = load double, double* %12
%36 = fmul double %34, %35
%37 = load double*, double** %5
%38 = getelementptr inbounds double, double* %37, i64 0
store double %36, double* %38
%39 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 1
%40 = load double, double* %39
%41 = load double, double* %12
%42 = fmul double %40, %41
%43 = load double*, double** %5
%44 = getelementptr inbounds double, double* %43, i64 1
store double %42, double* %44
%45 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 2
%46 = load double, double* %45
%47 = load double, double* %12
%48 = fmul double %46, %47
%49 = load double*, double** %5
%50 = getelementptr inbounds double, double* %49, i64 2
store double %48, double* %50
%51 = getelementptr inbounds [3 x double], [3 x double]* %11, i64 0, i64 0
%52 = load double*, double** %6
%53 = call double @dot(double* %51, double* %52, i32 3)
%54 = fneg double %53
%55 = load double, double* %12
%56 = fmul double %54, %55
%57 = load double*, double** %5
%58 = getelementptr inbounds double, double* %57, i64 3
store double %56, double* %58
ret void
}

LLVM IR (-O2):
define void @plane_from_3points(double* nocapture writeonly %0, double* %1, double* %2, double* %3) {
%5 = alloca [3 x double]
%6 = alloca [3 x double]
%7 = alloca [3 x double]
%8 = bitcast [3 x double]* %5 to i8*
%9 = bitcast [3 x double]* %6 to i8*
%10 = getelementptr inbounds [3 x double], [3 x double]* %5, i64 0, i64 0
%11 = call i32 @sub(double* %10, double* %2, double* %1, i32 3)
%12 = getelementptr inbounds [3 x double], [3 x double]* %6, i64 0, i64 0
%13 = call i32 @sub(double* %12, double* %3, double* %1, i32 3)
%14 = bitcast [3 x double]* %7 to i8*
%15 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 0
%16 = call i32 @cross(double* %15, double* %10, double* %12)
%17 = call i32 @normalize(double* %15, double* %15, i32 3)
%18 = getelementptr inbounds [3 x double], [3 x double]* %7, i64 0, i64 2
%19 = load double, double* %18
%20 = fcmp ogt double %19, 0.000000e+00
%21 = select i1 %20, double -1.000000e+00, double 1.000000e+00
%22 = bitcast [3 x double]* %7 to <2 x double>*
%23 = load <2 x double>, <2 x double>* %22
%24 = insertelement <2 x double> poison, double %21, i64 0
%25 = shufflevector <2 x double> %24, <2 x double> poison, <2 x i32> zeroinitializer
%26 = fmul <2 x double> %23, %25
%27 = bitcast double* %0 to <2 x double>*
store <2 x double> %26, <2 x double>* %27
%28 = fmul double %19, %21
%29 = getelementptr inbounds double, double* %0, i64 2
store double %28, double* %29
%30 = call double @dot(double* %15, double* %1, i32 3)
%31 = fneg double %30
%32 = fmul double %21, %31
%33 = getelementptr inbounds double, double* %0, i64 3
store double %32, double* %33
ret void
}