#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*/ m_multiply(float *, float *, float *);
int /*<<< orphan*/ m_translate(float *, float *);
int /*<<< orphan*/ v_cross(float const *, float *, float *);
int /*<<< orphan*/ v_normalize(float *, float *);
void m_look_at(const float *eye, const float *dir, const float *up,
               float *out) {
  float x[3], y[3], z[3], ieye[3], m1[16], m2[16];
  {
    (z)[0] = (eye)[0] - (dir)[0];
    (z)[1] = (eye)[1] - (dir)[1];
    (z)[2] = (eye)[2] - (dir)[2];
  };
  v_normalize(z, z);
  v_cross(up, z, x);
  v_cross(z, x, y);
  v_normalize(x, x);
  v_normalize(y, y);
  m1[0] = x[0];
  m1[4] = x[1];
  m1[8] = x[2];
  m1[12] = 0.0;
  m1[1] = y[0];
  m1[5] = y[1];
  m1[9] = y[2];
  m1[13] = 0.0;
  m1[2] = z[0];
  m1[6] = z[1];
  m1[10] = z[2];
  m1[14] = 0.0;
  m1[3] = 0.0;
  m1[7] = 0.0;
  m1[11] = 0.0;
  m1[15] = 1.0;
  {
    (ieye)[0] = (eye)[0] * (-1);
    (ieye)[1] = (eye)[1] * (-1);
    (ieye)[2] = (eye)[2] * (-1);
  };
  m_translate(ieye, m2);
  m_multiply(m1, m2, out);
}


x86 assembly (clang, -O0):
<m_look_at>:
push   %rbp
mov    %rsp,%rbp
sub    $0xd0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm0
mov    -0x10(%rbp),%rax
subss  (%rax),%xmm0
movss  %xmm0,-0x44(%rbp)
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm0
mov    -0x10(%rbp),%rax
subss  0x4(%rax),%xmm0
movss  %xmm0,-0x40(%rbp)
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm0
mov    -0x10(%rbp),%rax
subss  0x8(%rax),%xmm0
movss  %xmm0,-0x3c(%rbp)
lea    -0x44(%rbp),%rdi
lea    -0x44(%rbp),%rsi
call   1060 <v_normalize@plt>
mov    -0x18(%rbp),%rdi
lea    -0x44(%rbp),%rsi
lea    -0x2c(%rbp),%rdx
call   1040 <v_cross@plt>
lea    -0x44(%rbp),%rdi
lea    -0x2c(%rbp),%rsi
lea    -0x38(%rbp),%rdx
call   1040 <v_cross@plt>
lea    -0x2c(%rbp),%rdi
lea    -0x2c(%rbp),%rsi
call   1060 <v_normalize@plt>
lea    -0x38(%rbp),%rdi
lea    -0x38(%rbp),%rsi
call   1060 <v_normalize@plt>
movss  -0x2c(%rbp),%xmm0
movss  %xmm0,-0x90(%rbp)
ff
movss  -0x28(%rbp),%xmm0
movss  %xmm0,-0x80(%rbp)
movss  -0x24(%rbp),%xmm0
movss  %xmm0,-0x70(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x60(%rbp)
movss  -0x38(%rbp),%xmm0
movss  %xmm0,-0x8c(%rbp)
ff
movss  -0x34(%rbp),%xmm0
movss  %xmm0,-0x7c(%rbp)
movss  -0x30(%rbp),%xmm0
movss  %xmm0,-0x6c(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x5c(%rbp)
movss  -0x44(%rbp),%xmm0
movss  %xmm0,-0x88(%rbp)
ff
movss  -0x40(%rbp),%xmm0
movss  %xmm0,-0x78(%rbp)
movss  -0x3c(%rbp),%xmm0
movss  %xmm0,-0x68(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x58(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x84(%rbp)
ff
xorps  %xmm0,%xmm0
movss  %xmm0,-0x74(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x64(%rbp)
movss  0xd7f(%rip),%xmm0
movss  %xmm0,-0x54(%rbp)
mov    -0x8(%rbp),%rax
movss  0xd6a(%rip),%xmm0
mulss  (%rax),%xmm0
movss  %xmm0,-0x50(%rbp)
mov    -0x8(%rbp),%rax
movss  0xd55(%rip),%xmm0
mulss  0x4(%rax),%xmm0
movss  %xmm0,-0x4c(%rbp)
mov    -0x8(%rbp),%rax
movss  0xd3f(%rip),%xmm0
mulss  0x8(%rax),%xmm0
movss  %xmm0,-0x48(%rbp)
lea    -0x50(%rbp),%rdi
lea    -0xd0(%rbp),%rsi
call   1050 <m_translate@plt>
lea    -0x90(%rbp),%rdi
lea    -0xd0(%rbp),%rsi
mov    -0x20(%rbp),%rdx
call   1030 <m_multiply@plt>
add    $0xd0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<m_look_at>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0xb0,%rsp
mov    %rcx,%r14
mov    %rdx,%r15
mov    %rdi,%rbx
movss  (%rdi),%xmm0
subss  (%rsi),%xmm0
movss  %xmm0,(%rsp)
movss  0x4(%rdi),%xmm0
subss  0x4(%rsi),%xmm0
movss  %xmm0,0x4(%rsp)
movss  0x8(%rdi),%xmm0
subss  0x8(%rsi),%xmm0
movss  %xmm0,0x8(%rsp)
mov    %rsp,%r12
mov    %r12,%rdi
mov    %r12,%rsi
call   1060 <v_normalize@plt>
lea    0x24(%rsp),%r13
mov    %r15,%rdi
mov    %r12,%rsi
mov    %r13,%rdx
call   1040 <v_cross@plt>
lea    0x18(%rsp),%r15
mov    %r12,%rdi
mov    %r13,%rsi
mov    %r15,%rdx
call   1040 <v_cross@plt>
mov    %r13,%rdi
mov    %r13,%rsi
call   1060 <v_normalize@plt>
mov    %r15,%rdi
mov    %r15,%rsi
call   1060 <v_normalize@plt>
movss  0x24(%rsp),%xmm0
movss  0x28(%rsp),%xmm1
movss  %xmm0,0x30(%rsp)
movss  %xmm1,0x40(%rsp)
movss  0x2c(%rsp),%xmm0
movss  %xmm0,0x50(%rsp)
movss  0x18(%rsp),%xmm0
movss  0x1c(%rsp),%xmm1
movss  %xmm0,0x34(%rsp)
movss  %xmm1,0x44(%rsp)
movss  0x20(%rsp),%xmm0
movss  %xmm0,0x54(%rsp)
movss  (%rsp),%xmm0
movss  0x4(%rsp),%xmm1
movss  %xmm0,0x38(%rsp)
movss  %xmm1,0x48(%rsp)
movss  0x8(%rsp),%xmm0
movss  %xmm0,0x58(%rsp)
movl   $0x0,0x3c(%rsp)
movl   $0x0,0x4c(%rsp)
xorps  %xmm0,%xmm0
movups %xmm0,0x5c(%rsp)
movl   $0x3f800000,0x6c(%rsp)
3f
movss  (%rbx),%xmm0
movaps 0xd9a(%rip),%xmm1
xorps  %xmm1,%xmm0
movss  %xmm0,0xc(%rsp)
movss  0x4(%rbx),%xmm0
xorps  %xmm1,%xmm0
movss  %xmm0,0x10(%rsp)
movss  0x8(%rbx),%xmm0
xorps  %xmm1,%xmm0
movss  %xmm0,0x14(%rsp)
lea    0xc(%rsp),%rdi
lea    0x70(%rsp),%rbx
mov    %rbx,%rsi
call   1050 <m_translate@plt>
lea    0x30(%rsp),%rdi
mov    %rbx,%rsi
mov    %r14,%rdx
call   1030 <m_multiply@plt>
add    $0xb0,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @m_look_at(float* %0, float* %1, float* %2, float* %3) {
%5 = alloca float*
%6 = alloca float*
%7 = alloca float*
%8 = alloca float*
%9 = alloca [3 x float]
%10 = alloca [3 x float]
%11 = alloca [3 x float]
%12 = alloca [3 x float]
%13 = alloca [16 x float]
%14 = alloca [16 x float]
store float* %0, float** %5
store float* %1, float** %6
store float* %2, float** %7
store float* %3, float** %8
%15 = load float*, float** %5
%16 = getelementptr inbounds float, float* %15, i64 0
%17 = load float, float* %16
%18 = load float*, float** %6
%19 = getelementptr inbounds float, float* %18, i64 0
%20 = load float, float* %19
%21 = fsub float %17, %20
%22 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 0
store float %21, float* %22
%23 = load float*, float** %5
%24 = getelementptr inbounds float, float* %23, i64 1
%25 = load float, float* %24
%26 = load float*, float** %6
%27 = getelementptr inbounds float, float* %26, i64 1
%28 = load float, float* %27
%29 = fsub float %25, %28
%30 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 1
store float %29, float* %30
%31 = load float*, float** %5
%32 = getelementptr inbounds float, float* %31, i64 2
%33 = load float, float* %32
%34 = load float*, float** %6
%35 = getelementptr inbounds float, float* %34, i64 2
%36 = load float, float* %35
%37 = fsub float %33, %36
%38 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 2
store float %37, float* %38
%39 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 0
%40 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 0
%41 = call i32 @v_normalize(float* %39, float* %40)
%42 = load float*, float** %7
%43 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 0
%44 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 0
%45 = call i32 @v_cross(float* %42, float* %43, float* %44)
%46 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 0
%47 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 0
%48 = getelementptr inbounds [3 x float], [3 x float]* %10, i64 0, i64 0
%49 = call i32 @v_cross(float* %46, float* %47, float* %48)
%50 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 0
%51 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 0
%52 = call i32 @v_normalize(float* %50, float* %51)
%53 = getelementptr inbounds [3 x float], [3 x float]* %10, i64 0, i64 0
%54 = getelementptr inbounds [3 x float], [3 x float]* %10, i64 0, i64 0
%55 = call i32 @v_normalize(float* %53, float* %54)
%56 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 0
%57 = load float, float* %56
%58 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 0
store float %57, float* %58
%59 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 1
%60 = load float, float* %59
%61 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 4
store float %60, float* %61
%62 = getelementptr inbounds [3 x float], [3 x float]* %9, i64 0, i64 2
%63 = load float, float* %62
%64 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 8
store float %63, float* %64
%65 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 12
store float 0.000000e+00, float* %65
%66 = getelementptr inbounds [3 x float], [3 x float]* %10, i64 0, i64 0
%67 = load float, float* %66
%68 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 1
store float %67, float* %68
%69 = getelementptr inbounds [3 x float], [3 x float]* %10, i64 0, i64 1
%70 = load float, float* %69
%71 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 5
store float %70, float* %71
%72 = getelementptr inbounds [3 x float], [3 x float]* %10, i64 0, i64 2
%73 = load float, float* %72
%74 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 9
store float %73, float* %74
%75 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 13
store float 0.000000e+00, float* %75
%76 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 0
%77 = load float, float* %76
%78 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 2
store float %77, float* %78
%79 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 1
%80 = load float, float* %79
%81 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 6
store float %80, float* %81
%82 = getelementptr inbounds [3 x float], [3 x float]* %11, i64 0, i64 2
%83 = load float, float* %82
%84 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 10
store float %83, float* %84
%85 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 14
store float 0.000000e+00, float* %85
%86 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 3
store float 0.000000e+00, float* %86
%87 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 7
store float 0.000000e+00, float* %87
%88 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 11
store float 0.000000e+00, float* %88
%89 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 15
store float 1.000000e+00, float* %89
%90 = load float*, float** %5
%91 = getelementptr inbounds float, float* %90, i64 0
%92 = load float, float* %91
%93 = fmul float %92, -1.000000e+00
%94 = getelementptr inbounds [3 x float], [3 x float]* %12, i64 0, i64 0
store float %93, float* %94
%95 = load float*, float** %5
%96 = getelementptr inbounds float, float* %95, i64 1
%97 = load float, float* %96
%98 = fmul float %97, -1.000000e+00
%99 = getelementptr inbounds [3 x float], [3 x float]* %12, i64 0, i64 1
store float %98, float* %99
%100 = load float*, float** %5
%101 = getelementptr inbounds float, float* %100, i64 2
%102 = load float, float* %101
%103 = fmul float %102, -1.000000e+00
%104 = getelementptr inbounds [3 x float], [3 x float]* %12, i64 0, i64 2
store float %103, float* %104
%105 = getelementptr inbounds [3 x float], [3 x float]* %12, i64 0, i64 0
%106 = getelementptr inbounds [16 x float], [16 x float]* %14, i64 0, i64 0
%107 = call i32 @m_translate(float* %105, float* %106)
%108 = getelementptr inbounds [16 x float], [16 x float]* %13, i64 0, i64 0
%109 = getelementptr inbounds [16 x float], [16 x float]* %14, i64 0, i64 0
%110 = load float*, float** %8
%111 = call i32 @m_multiply(float* %108, float* %109, float* %110)
ret void
}

LLVM IR (-O2):
define void @m_look_at(float* nocapture %0, float* nocapture %1, float* %2, float* %3) {
%5 = alloca [3 x float]
%6 = alloca [3 x float]
%7 = alloca [3 x float]
%8 = alloca [3 x float]
%9 = alloca [16 x float]
%10 = alloca [16 x float]
%11 = bitcast [3 x float]* %5 to i8*
%12 = bitcast [3 x float]* %6 to i8*
%13 = bitcast [3 x float]* %7 to i8*
%14 = bitcast [3 x float]* %8 to i8*
%15 = bitcast [16 x float]* %9 to i8*
%16 = bitcast [16 x float]* %10 to i8*
%17 = load float, float* %0
%18 = load float, float* %1
%19 = fsub float %17, %18
%20 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 0
store float %19, float* %20
%21 = getelementptr inbounds float, float* %0, i64 1
%22 = load float, float* %21
%23 = getelementptr inbounds float, float* %1, i64 1
%24 = load float, float* %23
%25 = fsub float %22, %24
%26 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 1
store float %25, float* %26
%27 = getelementptr inbounds float, float* %0, i64 2
%28 = load float, float* %27
%29 = getelementptr inbounds float, float* %1, i64 2
%30 = load float, float* %29
%31 = fsub float %28, %30
%32 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 2
store float %31, float* %32
%33 = call i32 @v_normalize(float* %20, float* %20)
%34 = getelementptr inbounds [3 x float], [3 x float]* %5, i64 0, i64 0
%35 = call i32 @v_cross(float* %2, float* %20, float* %34)
%36 = getelementptr inbounds [3 x float], [3 x float]* %6, i64 0, i64 0
%37 = call i32 @v_cross(float* %20, float* %34, float* %36)
%38 = call i32 @v_normalize(float* %34, float* %34)
%39 = call i32 @v_normalize(float* %36, float* %36)
%40 = load float, float* %34
%41 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 0
store float %40, float* %41
%42 = getelementptr inbounds [3 x float], [3 x float]* %5, i64 0, i64 1
%43 = load float, float* %42
%44 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 4
store float %43, float* %44
%45 = getelementptr inbounds [3 x float], [3 x float]* %5, i64 0, i64 2
%46 = load float, float* %45
%47 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 8
store float %46, float* %47
%48 = load float, float* %36
%49 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 1
store float %48, float* %49
%50 = getelementptr inbounds [3 x float], [3 x float]* %6, i64 0, i64 1
%51 = load float, float* %50
%52 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 5
store float %51, float* %52
%53 = getelementptr inbounds [3 x float], [3 x float]* %6, i64 0, i64 2
%54 = load float, float* %53
%55 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 9
store float %54, float* %55
%56 = load float, float* %20
%57 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 2
store float %56, float* %57
%58 = load float, float* %26
%59 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 6
store float %58, float* %59
%60 = load float, float* %32
%61 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 10
store float %60, float* %61
%62 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 3
store float 0.000000e+00, float* %62
%63 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 7
store float 0.000000e+00, float* %63
%64 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 11
%65 = bitcast float* %64 to <4 x float>*
store <4 x float> zeroinitializer, <4 x float>* %65
%66 = getelementptr inbounds [16 x float], [16 x float]* %9, i64 0, i64 15
store float 1.000000e+00, float* %66
%67 = load float, float* %0
%68 = fneg float %67
%69 = getelementptr inbounds [3 x float], [3 x float]* %8, i64 0, i64 0
store float %68, float* %69
%70 = load float, float* %21
%71 = fneg float %70
%72 = getelementptr inbounds [3 x float], [3 x float]* %8, i64 0, i64 1
store float %71, float* %72
%73 = load float, float* %27
%74 = fneg float %73
%75 = getelementptr inbounds [3 x float], [3 x float]* %8, i64 0, i64 2
store float %74, float* %75
%76 = getelementptr inbounds [16 x float], [16 x float]* %10, i64 0, i64 0
%77 = call i32 @m_translate(float* %69, float* %76)
%78 = call i32 @m_multiply(float* %41, float* %76, float* %3)
ret void
}