#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 */
typedef double GLint;
typedef double GLdouble;

/* Variables and functions */
double GL_FALSE;
double GL_TRUE;
int /*<<< orphan*/ __gluMultMatrixVecd(double const *, double *, double *);
GLint gluProject(GLdouble objx, GLdouble objy, GLdouble objz,
                 const GLdouble modelMatrix[16], const GLdouble projMatrix[16],
                 const GLint viewport[4], GLdouble *winx, GLdouble *winy,
                 GLdouble *winz) {
  double in[4];
  double out[4];
  in[0] = objx;
  in[1] = objy;
  in[2] = objz;
  in[3] = 1.0;
  __gluMultMatrixVecd(modelMatrix, in, out);
  __gluMultMatrixVecd(projMatrix, out, in);
  if (in[3] == 0.0)
    return (GL_FALSE);
  in[0] /= in[3];
  in[1] /= in[3];
  in[2] /= in[3];
  in[0] = in[0] * 0.5 + 0.5;
  in[1] = in[1] * 0.5 + 0.5;
  in[2] = in[2] * 0.5 + 0.5;
  in[0] = in[0] * viewport[2] + viewport[0];
  in[1] = in[1] * viewport[3] + viewport[1];
  *winx = in[0];
  *winy = in[1];
  *winz = in[2];
  return (GL_TRUE);
}


x86 assembly (clang, -O0):
<gluProject>:
push   %rbp
mov    %rsp,%rbp
sub    $0x90,%rsp
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
movsd  %xmm2,-0x20(%rbp)
mov    %rdi,-0x28(%rbp)
mov    %rsi,-0x30(%rbp)
mov    %rdx,-0x38(%rbp)
mov    %rcx,-0x40(%rbp)
mov    %r8,-0x48(%rbp)
mov    %r9,-0x50(%rbp)
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  0xe98(%rip),%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x28(%rbp),%rdi
lea    -0x70(%rbp),%rsi
lea    -0x90(%rbp),%rdx
call   1030 <__gluMultMatrixVecd@plt>
mov    -0x30(%rbp),%rdi
lea    -0x90(%rbp),%rsi
lea    -0x70(%rbp),%rdx
call   1030 <__gluMultMatrixVecd@plt>
movsd  -0x58(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11c2 <gluProject+0xb2>
jp     11c2 <gluProject+0xb2>
mov    0x2e34(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    12c7 <gluProject+0x1b7>
movsd  -0x58(%rbp),%xmm1
movsd  -0x70(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x58(%rbp),%xmm1
movsd  -0x68(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x58(%rbp),%xmm1
movsd  -0x60(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x70(%rbp),%xmm0
movsd  0xe00(%rip),%xmm1
mulsd  %xmm1,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x68(%rbp),%xmm0
movsd  0xde6(%rip),%xmm1
mulsd  %xmm1,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x60(%rbp),%xmm0
movsd  0xdcc(%rip),%xmm1
mulsd  %xmm1,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x70(%rbp),%xmm0
mov    -0x38(%rbp),%rax
movsd  0x10(%rax),%xmm2
mov    -0x38(%rbp),%rax
movsd  (%rax),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x70(%rbp)
movsd  -0x68(%rbp),%xmm0
mov    -0x38(%rbp),%rax
movsd  0x18(%rax),%xmm2
mov    -0x38(%rbp),%rax
movsd  0x8(%rax),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x70(%rbp),%xmm0
mov    -0x40(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x68(%rbp),%xmm0
mov    -0x48(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x60(%rbp),%xmm0
mov    -0x50(%rbp),%rax
movsd  %xmm0,(%rax)
mov    0x2d1a(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x90,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<gluProject>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x58,%rsp
mov    %r9,0x28(%rsp)
mov    %r8,%r15
mov    %rcx,%r12
mov    %rdx,%r13
mov    %rsi,%rbx
movsd  %xmm0,(%rsp)
movsd  %xmm1,0x8(%rsp)
movsd  %xmm2,0x10(%rsp)
movabs $0x3ff0000000000000,%rax
mov    %rax,0x18(%rsp)
mov    %rsp,%rbp
lea    0x30(%rsp),%r14
mov    %rbp,%rsi
mov    %r14,%rdx
call   1030 <__gluMultMatrixVecd@plt>
mov    %rbx,%rdi
mov    %r14,%rsi
mov    %rbp,%rdx
call   1030 <__gluMultMatrixVecd@plt>
movsd  0x18(%rsp),%xmm0
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    118b <gluProject+0x7b>
jp     118b <gluProject+0x7b>
mov    0x2e5f(%rip),%rax
jmp    11fb <gluProject+0xeb>
movsd  (%rsp),%xmm1
movsd  0x8(%rsp),%xmm2
divsd  %xmm0,%xmm1
divsd  %xmm0,%xmm2
movsd  0x10(%rsp),%xmm3
divsd  %xmm0,%xmm3
movsd  0xe50(%rip),%xmm0
mulsd  %xmm0,%xmm1
addsd  %xmm0,%xmm1
mulsd  %xmm0,%xmm2
addsd  %xmm0,%xmm2
mulsd  %xmm0,%xmm3
addsd  %xmm0,%xmm3
mulsd  0x10(%r13),%xmm1
addsd  0x0(%r13),%xmm1
mulsd  0x18(%r13),%xmm2
addsd  0x8(%r13),%xmm2
movsd  %xmm1,(%r12)
movsd  %xmm2,(%r15)
mov    0x28(%rsp),%rax
movsd  %xmm3,(%rax)
mov    0x2ddd(%rip),%rax
movsd  (%rax),%xmm0
add    $0x58,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
@GL_FALSE = global double 0.000000e+00
@GL_TRUE = global double 0.000000e+00
define double @gluProject(double %0, double %1, double %2, double* %3, double* %4, double* nocapture %5, double* nocapture writeonly %6, double* nocapture writeonly %7, double* nocapture writeonly %8) {
%10 = alloca [4 x double]
%11 = alloca [4 x double]
%12 = bitcast [4 x double]* %10 to i8*
%13 = bitcast [4 x double]* %11 to i8*
%14 = getelementptr inbounds [4 x double], [4 x double]* %10, i64 0, i64 0
store double %0, double* %14
%15 = getelementptr inbounds [4 x double], [4 x double]* %10, i64 0, i64 1
store double %1, double* %15
%16 = getelementptr inbounds [4 x double], [4 x double]* %10, i64 0, i64 2
store double %2, double* %16
%17 = getelementptr inbounds [4 x double], [4 x double]* %10, i64 0, i64 3
store double 1.000000e+00, double* %17
%18 = getelementptr inbounds [4 x double], [4 x double]* %11, i64 0, i64 0
%19 = call i32 @__gluMultMatrixVecd(double* %3, double* %14, double* %18)
%20 = call i32 @__gluMultMatrixVecd(double* %4, double* %18, double* %14)
%21 = load double, double* %17
%22 = fcmp oeq double %21, 0.000000e+00
br i1 %22, label %42, label %23
23: ; preds = %9
%24 = load double, double* %14
%25 = fdiv double %24, %21
%26 = load double, double* %15
%27 = fdiv double %26, %21
%28 = load double, double* %16
%29 = fdiv double %28, %21
%30 = call double @llvm.fmuladd.f64(double %25, double 5.000000e-01, double 5.000000e-01)
%31 = call double @llvm.fmuladd.f64(double %27, double 5.000000e-01, double 5.000000e-01)
%32 = call double @llvm.fmuladd.f64(double %29, double 5.000000e-01, double 5.000000e-01)
%33 = getelementptr inbounds double, double* %5, i64 2
%34 = load double, double* %33
%35 = load double, double* %5
%36 = call double @llvm.fmuladd.f64(double %30, double %34, double %35)
%37 = getelementptr inbounds double, double* %5, i64 3
%38 = load double, double* %37
%39 = getelementptr inbounds double, double* %5, i64 1
%40 = load double, double* %39
%41 = call double @llvm.fmuladd.f64(double %31, double %38, double %40)
store double %36, double* %6
store double %41, double* %7
store double %32, double* %8
br label %42
42: ; preds = %9, %23
%43 = phi double* [ @GL_TRUE, %23 ], [ @GL_FALSE, %9 ]
%44 = load double, double* %43
ret double %44
}