#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 */
scalar_t__ imatrix_solve_n_m(double *, double *, double *, int, int, char *);
int itransform_perspective(double *m, const double src[], const double dst[]) {
  char buffer[(sizeof(int) * 8 + sizeof(double) * (1 * 8 + 8 * 8))];
  double a[8][8], b[8], x[8];
  int i;
  for (i = 0; i < 4; i++) {
    a[i][0] = a[i + 4][3] = src[i * 2 + 0];
    a[i][1] = a[i + 4][4] = src[i * 2 + 1];
    a[i][2] = a[i + 4][5] = 1;
    a[i][3] = a[i][4] = a[i][5] = 0;
    a[i + 4][0] = a[i + 4][1] = a[i + 4][2] = 0;
    a[i][6] = -src[i * 2 + 0] * dst[i * 2 + 0];
    a[i][7] = -src[i * 2 + 1] * dst[i * 2 + 0];
    a[i + 4][6] = -src[i * 2 + 0] * dst[i * 2 + 1];
    a[i + 4][7] = -src[i * 2 + 1] * dst[i * 2 + 1];
    b[i] = dst[i * 2 + 0];
    b[i + 4] = dst[i * 2 + 1];
  }
  if (imatrix_solve_n_m(&a[0][0], b, x, 8, 1, buffer) != 0)
    return -1;
  for (i = 0; i < 8; i++)
    m[i] = x[i];
  m[8] = 1.0;
  return 0;
}


x86 assembly (clang, -O0):
<itransform_perspective>:
push   %rbp
mov    %rsp,%rbp
sub    $0x510,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
movl   $0x0,-0x504(%rbp)
cmpl   $0x4,-0x504(%rbp)
jge    14da <itransform_perspective+0x3ca>
mov    -0x18(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x18(%rax)
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,(%rax)
mov    -0x18(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x20(%rax)
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x8(%rax)
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  0xdff(%rip),%xmm0
movsd  %xmm0,0x28(%rax)
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  0xddd(%rip),%xmm0
movsd  %xmm0,0x10(%rax)
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x28(%rax)
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x20(%rax)
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x18(%rax)
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x10(%rax)
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,0x8(%rax)
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax)
mov    -0x18(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x20(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
mulsd  (%rax,%rcx,8),%xmm0
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x30(%rax)
mov    -0x18(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x20(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
mulsd  (%rax,%rcx,8),%xmm0
movslq -0x504(%rbp),%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x38(%rax)
mov    -0x18(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x20(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mulsd  (%rax,%rcx,8),%xmm0
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x30(%rax)
mov    -0x18(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mov    -0x20(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mulsd  (%rax,%rcx,8),%xmm0
mov    -0x504(%rbp),%eax
add    $0x4,%eax
movslq %eax,%rcx
lea    -0x480(%rbp),%rax
shl    $0x6,%rcx
add    %rcx,%rax
movsd  %xmm0,0x38(%rax)
mov    -0x20(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movslq -0x504(%rbp),%rax
movsd  %xmm0,-0x4c0(%rbp,%rax,8)
ff ff
mov    -0x20(%rbp),%rax
mov    -0x504(%rbp),%ecx
shl    $0x1,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x504(%rbp),%eax
add    $0x4,%eax
cltq
movsd  %xmm0,-0x4c0(%rbp,%rax,8)
ff ff
mov    -0x504(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x504(%rbp)
jmp    1131 <itransform_perspective+0x21>
lea    -0x480(%rbp),%rdi
lea    -0x4c0(%rbp),%rsi
lea    -0x500(%rbp),%rdx
lea    -0x280(%rbp),%r9
mov    $0x8,%ecx
mov    $0x1,%r8d
call   1030 <imatrix_solve_n_m@plt>
cmp    $0x0,%rax
je     151c <itransform_perspective+0x40c>
movl   $0xffffffff,-0x4(%rbp)
jmp    157f <itransform_perspective+0x46f>
movl   $0x0,-0x504(%rbp)
cmpl   $0x8,-0x504(%rbp)
jge    1567 <itransform_perspective+0x457>
movslq -0x504(%rbp),%rax
movsd  -0x500(%rbp,%rax,8),%xmm0
ff ff
mov    -0x10(%rbp),%rax
movslq -0x504(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x504(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x504(%rbp)
jmp    1526 <itransform_perspective+0x416>
mov    -0x10(%rbp),%rax
movsd  0xa8d(%rip),%xmm0
movsd  %xmm0,0x40(%rax)
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x510,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<itransform_perspective>:
push   %r14
push   %rbx
sub    $0x4e8,%rsp
mov    %rdi,%r14
movupd (%rsi),%xmm2
movupd %xmm2,0x158(%rsp)
movapd %xmm2,0x40(%rsp)
movabs $0x3ff0000000000000,%rbx
mov    %rbx,0x168(%rsp)
mov    %rbx,0x50(%rsp)
xorps  %xmm0,%xmm0
movups %xmm0,0x58(%rsp)
movq   $0x0,0x68(%rsp)
movaps %xmm0,0x140(%rsp)
movq   $0x0,0x150(%rsp)
movsd  (%rdx),%xmm3
movapd 0xe88(%rip),%xmm1
xorpd  %xmm1,%xmm2
movapd %xmm3,%xmm4
unpcklpd %xmm3,%xmm4
mulpd  %xmm2,%xmm4
movapd %xmm4,0x70(%rsp)
movsd  0x8(%rdx),%xmm4
movsd  %xmm3,(%rsp)
movsd  %xmm4,0x20(%rsp)
unpcklpd %xmm4,%xmm4
mulpd  %xmm2,%xmm4
movapd %xmm4,0x170(%rsp)
movupd 0x10(%rsi),%xmm2
movupd %xmm2,0x198(%rsp)
movapd %xmm2,0x80(%rsp)
mov    %rbx,0x1a8(%rsp)
mov    %rbx,0x90(%rsp)
movups %xmm0,0x98(%rsp)
movq   $0x0,0xa8(%rsp)
movaps %xmm0,0x180(%rsp)
movq   $0x0,0x190(%rsp)
movsd  0x10(%rdx),%xmm3
xorpd  %xmm1,%xmm2
movapd %xmm3,%xmm4
unpcklpd %xmm3,%xmm4
mulpd  %xmm2,%xmm4
movapd %xmm4,0xb0(%rsp)
movsd  0x18(%rdx),%xmm4
movsd  %xmm3,0x8(%rsp)
movsd  %xmm4,0x28(%rsp)
unpcklpd %xmm4,%xmm4
mulpd  %xmm2,%xmm4
movapd %xmm4,0x1b0(%rsp)
movupd 0x20(%rsi),%xmm2
movupd %xmm2,0x1d8(%rsp)
movapd %xmm2,0xc0(%rsp)
mov    %rbx,0x1e8(%rsp)
mov    %rbx,0xd0(%rsp)
movups %xmm0,0xd8(%rsp)
movq   $0x0,0xe8(%rsp)
movaps %xmm0,0x1c0(%rsp)
movq   $0x0,0x1d0(%rsp)
movsd  0x20(%rdx),%xmm3
xorpd  %xmm1,%xmm2
movapd %xmm3,%xmm4
unpcklpd %xmm3,%xmm4
mulpd  %xmm2,%xmm4
movapd %xmm4,0xf0(%rsp)
movsd  0x28(%rdx),%xmm4
movsd  %xmm3,0x10(%rsp)
movsd  %xmm4,0x30(%rsp)
unpcklpd %xmm4,%xmm4
mulpd  %xmm2,%xmm4
movapd %xmm4,0x1f0(%rsp)
movupd 0x30(%rsi),%xmm2
movupd %xmm2,0x218(%rsp)
movapd %xmm2,0x100(%rsp)
mov    %rbx,0x228(%rsp)
mov    %rbx,0x110(%rsp)
movups %xmm0,0x118(%rsp)
movq   $0x0,0x128(%rsp)
movaps %xmm0,0x200(%rsp)
movq   $0x0,0x210(%rsp)
movsd  0x30(%rdx),%xmm0
xorpd  %xmm1,%xmm2
movapd %xmm0,%xmm1
unpcklpd %xmm0,%xmm1
mulpd  %xmm2,%xmm1
movapd %xmm1,0x130(%rsp)
movsd  0x38(%rdx),%xmm1
movsd  %xmm0,0x18(%rsp)
movsd  %xmm1,0x38(%rsp)
unpcklpd %xmm1,%xmm1
mulpd  %xmm2,%xmm1
movapd %xmm1,0x230(%rsp)
lea    0x40(%rsp),%rdi
mov    %rsp,%rsi
lea    0x240(%rsp),%rdx
lea    0x280(%rsp),%r9
mov    $0x8,%ecx
mov    $0x1,%r8d
call   1030 <imatrix_solve_n_m@plt>
mov    %rax,%rcx
mov    $0xffffffff,%eax
test   %rcx,%rcx
jne    13d2 <itransform_perspective+0x2c2>
movapd 0x240(%rsp),%xmm0
movapd 0x250(%rsp),%xmm1
movapd 0x260(%rsp),%xmm2
movapd 0x270(%rsp),%xmm3
movupd %xmm3,0x30(%r14)
movupd %xmm2,0x20(%r14)
movupd %xmm1,0x10(%r14)
movupd %xmm0,(%r14)
mov    %rbx,0x40(%r14)
xor    %eax,%eax
add    $0x4e8,%rsp
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define i32 @itransform_perspective(double* %0, double* %1, double* %2) {
%4 = alloca i32
%5 = alloca double*
%6 = alloca double*
%7 = alloca double*
%8 = alloca [608 x i8]
%9 = alloca [8 x [8 x double]]
%10 = alloca [8 x double]
%11 = alloca [8 x double]
%12 = alloca i32
store double* %0, double** %5
store double* %1, double** %6
store double* %2, double** %7
store i32 0, i32* %12
br label %13
13: ; preds = %188, %3
%14 = load i32, i32* %12
%15 = icmp slt i32 %14, 4
br i1 %15, label %16, label %191
16: ; preds = %13
%17 = load double*, double** %6
%18 = load i32, i32* %12
%19 = mul nsw i32 %18, 2
%20 = add nsw i32 %19, 0
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds double, double* %17, i64 %21
%23 = load double, double* %22
%24 = load i32, i32* %12
%25 = add nsw i32 %24, 4
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %26
%28 = getelementptr inbounds [8 x double], [8 x double]* %27, i64 0, i64 3
store double %23, double* %28
%29 = load i32, i32* %12
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %30
%32 = getelementptr inbounds [8 x double], [8 x double]* %31, i64 0, i64 0
store double %23, double* %32
%33 = load double*, double** %6
%34 = load i32, i32* %12
%35 = mul nsw i32 %34, 2
%36 = add nsw i32 %35, 1
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds double, double* %33, i64 %37
%39 = load double, double* %38
%40 = load i32, i32* %12
%41 = add nsw i32 %40, 4
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %42
%44 = getelementptr inbounds [8 x double], [8 x double]* %43, i64 0, i64 4
store double %39, double* %44
%45 = load i32, i32* %12
%46 = sext i32 %45 to i64
%47 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %46
%48 = getelementptr inbounds [8 x double], [8 x double]* %47, i64 0, i64 1
store double %39, double* %48
%49 = load i32, i32* %12
%50 = add nsw i32 %49, 4
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %51
%53 = getelementptr inbounds [8 x double], [8 x double]* %52, i64 0, i64 5
store double 1.000000e+00, double* %53
%54 = load i32, i32* %12
%55 = sext i32 %54 to i64
%56 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %55
%57 = getelementptr inbounds [8 x double], [8 x double]* %56, i64 0, i64 2
store double 1.000000e+00, double* %57
%58 = load i32, i32* %12
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %59
%61 = getelementptr inbounds [8 x double], [8 x double]* %60, i64 0, i64 5
store double 0.000000e+00, double* %61
%62 = load i32, i32* %12
%63 = sext i32 %62 to i64
%64 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %63
%65 = getelementptr inbounds [8 x double], [8 x double]* %64, i64 0, i64 4
store double 0.000000e+00, double* %65
%66 = load i32, i32* %12
%67 = sext i32 %66 to i64
%68 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %67
%69 = getelementptr inbounds [8 x double], [8 x double]* %68, i64 0, i64 3
store double 0.000000e+00, double* %69
%70 = load i32, i32* %12
%71 = add nsw i32 %70, 4
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %72
%74 = getelementptr inbounds [8 x double], [8 x double]* %73, i64 0, i64 2
store double 0.000000e+00, double* %74
%75 = load i32, i32* %12
%76 = add nsw i32 %75, 4
%77 = sext i32 %76 to i64
%78 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %77
%79 = getelementptr inbounds [8 x double], [8 x double]* %78, i64 0, i64 1
store double 0.000000e+00, double* %79
%80 = load i32, i32* %12
%81 = add nsw i32 %80, 4
%82 = sext i32 %81 to i64
%83 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %82
%84 = getelementptr inbounds [8 x double], [8 x double]* %83, i64 0, i64 0
store double 0.000000e+00, double* %84
%85 = load double*, double** %6
%86 = load i32, i32* %12
%87 = mul nsw i32 %86, 2
%88 = add nsw i32 %87, 0
%89 = sext i32 %88 to i64
%90 = getelementptr inbounds double, double* %85, i64 %89
%91 = load double, double* %90
%92 = fneg double %91
%93 = load double*, double** %7
%94 = load i32, i32* %12
%95 = mul nsw i32 %94, 2
%96 = add nsw i32 %95, 0
%97 = sext i32 %96 to i64
%98 = getelementptr inbounds double, double* %93, i64 %97
%99 = load double, double* %98
%100 = fmul double %92, %99
%101 = load i32, i32* %12
%102 = sext i32 %101 to i64
%103 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %102
%104 = getelementptr inbounds [8 x double], [8 x double]* %103, i64 0, i64 6
store double %100, double* %104
%105 = load double*, double** %6
%106 = load i32, i32* %12
%107 = mul nsw i32 %106, 2
%108 = add nsw i32 %107, 1
%109 = sext i32 %108 to i64
%110 = getelementptr inbounds double, double* %105, i64 %109
%111 = load double, double* %110
%112 = fneg double %111
%113 = load double*, double** %7
%114 = load i32, i32* %12
%115 = mul nsw i32 %114, 2
%116 = add nsw i32 %115, 0
%117 = sext i32 %116 to i64
%118 = getelementptr inbounds double, double* %113, i64 %117
%119 = load double, double* %118
%120 = fmul double %112, %119
%121 = load i32, i32* %12
%122 = sext i32 %121 to i64
%123 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %122
%124 = getelementptr inbounds [8 x double], [8 x double]* %123, i64 0, i64 7
store double %120, double* %124
%125 = load double*, double** %6
%126 = load i32, i32* %12
%127 = mul nsw i32 %126, 2
%128 = add nsw i32 %127, 0
%129 = sext i32 %128 to i64
%130 = getelementptr inbounds double, double* %125, i64 %129
%131 = load double, double* %130
%132 = fneg double %131
%133 = load double*, double** %7
%134 = load i32, i32* %12
%135 = mul nsw i32 %134, 2
%136 = add nsw i32 %135, 1
%137 = sext i32 %136 to i64
%138 = getelementptr inbounds double, double* %133, i64 %137
%139 = load double, double* %138
%140 = fmul double %132, %139
%141 = load i32, i32* %12
%142 = add nsw i32 %141, 4
%143 = sext i32 %142 to i64
%144 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %143
%145 = getelementptr inbounds [8 x double], [8 x double]* %144, i64 0, i64 6
store double %140, double* %145
%146 = load double*, double** %6
%147 = load i32, i32* %12
%148 = mul nsw i32 %147, 2
%149 = add nsw i32 %148, 1
%150 = sext i32 %149 to i64
%151 = getelementptr inbounds double, double* %146, i64 %150
%152 = load double, double* %151
%153 = fneg double %152
%154 = load double*, double** %7
%155 = load i32, i32* %12
%156 = mul nsw i32 %155, 2
%157 = add nsw i32 %156, 1
%158 = sext i32 %157 to i64
%159 = getelementptr inbounds double, double* %154, i64 %158
%160 = load double, double* %159
%161 = fmul double %153, %160
%162 = load i32, i32* %12
%163 = add nsw i32 %162, 4
%164 = sext i32 %163 to i64
%165 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 %164
%166 = getelementptr inbounds [8 x double], [8 x double]* %165, i64 0, i64 7
store double %161, double* %166
%167 = load double*, double** %7
%168 = load i32, i32* %12
%169 = mul nsw i32 %168, 2
%170 = add nsw i32 %169, 0
%171 = sext i32 %170 to i64
%172 = getelementptr inbounds double, double* %167, i64 %171
%173 = load double, double* %172
%174 = load i32, i32* %12
%175 = sext i32 %174 to i64
%176 = getelementptr inbounds [8 x double], [8 x double]* %10, i64 0, i64 %175
store double %173, double* %176
%177 = load double*, double** %7
%178 = load i32, i32* %12
%179 = mul nsw i32 %178, 2
%180 = add nsw i32 %179, 1
%181 = sext i32 %180 to i64
%182 = getelementptr inbounds double, double* %177, i64 %181
%183 = load double, double* %182
%184 = load i32, i32* %12
%185 = add nsw i32 %184, 4
%186 = sext i32 %185 to i64
%187 = getelementptr inbounds [8 x double], [8 x double]* %10, i64 0, i64 %186
store double %183, double* %187
br label %188
188: ; preds = %16
%189 = load i32, i32* %12
%190 = add nsw i32 %189, 1
store i32 %190, i32* %12
br label %13
191: ; preds = %13
%192 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %9, i64 0, i64 0
%193 = getelementptr inbounds [8 x double], [8 x double]* %192, i64 0, i64 0
%194 = getelementptr inbounds [8 x double], [8 x double]* %10, i64 0, i64 0
%195 = getelementptr inbounds [8 x double], [8 x double]* %11, i64 0, i64 0
%196 = getelementptr inbounds [608 x i8], [608 x i8]* %8, i64 0, i64 0
%197 = call i64 @imatrix_solve_n_m(double* %193, double* %194, double* %195, i32 8, i32 1, i8* %196)
%198 = icmp ne i64 %197, 0
br i1 %198, label %199, label %200
199: ; preds = %191
store i32 -1, i32* %4
br label %219
200: ; preds = %191
store i32 0, i32* %12
br label %201
201: ; preds = %213, %200
%202 = load i32, i32* %12
%203 = icmp slt i32 %202, 8
br i1 %203, label %204, label %216
204: ; preds = %201
%205 = load i32, i32* %12
%206 = sext i32 %205 to i64
%207 = getelementptr inbounds [8 x double], [8 x double]* %11, i64 0, i64 %206
%208 = load double, double* %207
%209 = load double*, double** %5
%210 = load i32, i32* %12
%211 = sext i32 %210 to i64
%212 = getelementptr inbounds double, double* %209, i64 %211
store double %208, double* %212
br label %213
213: ; preds = %204
%214 = load i32, i32* %12
%215 = add nsw i32 %214, 1
store i32 %215, i32* %12
br label %201
216: ; preds = %201
%217 = load double*, double** %5
%218 = getelementptr inbounds double, double* %217, i64 8
store double 1.000000e+00, double* %218
store i32 0, i32* %4
br label %219
219: ; preds = %216, %199
%220 = load i32, i32* %4
ret i32 %220
}

LLVM IR (-O2):
define i32 @itransform_perspective(double* nocapture writeonly %0, double* nocapture %1, double* nocapture %2) {
%4 = bitcast double* %0 to i8*
%5 = alloca [608 x i8]
%6 = alloca [8 x [8 x double]]
%7 = alloca [8 x double]
%8 = alloca [8 x double]
%9 = bitcast [8 x double]* %8 to i8*
%10 = getelementptr inbounds [608 x i8], [608 x i8]* %5, i64 0, i64 0
%11 = bitcast [8 x [8 x double]]* %6 to i8*
%12 = bitcast [8 x double]* %7 to i8*
%13 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 4, i64 3
%14 = bitcast double* %1 to <2 x double>*
%15 = load <2 x double>, <2 x double>* %14
%16 = bitcast double* %13 to <2 x double>*
store <2 x double> %15, <2 x double>* %16
%17 = bitcast [8 x [8 x double]]* %6 to <2 x double>*
store <2 x double> %15, <2 x double>* %17
%18 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 4, i64 5
store double 1.000000e+00, double* %18
%19 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 0, i64 2
store double 1.000000e+00, double* %19
%20 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 0, i64 3
%21 = bitcast double* %20 to i8*
%22 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 4, i64 0
%23 = bitcast double* %22 to i8*
%24 = load double, double* %2
%25 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 0, i64 6
%26 = fneg <2 x double> %15
%27 = insertelement <2 x double> poison, double %24, i64 0
%28 = shufflevector <2 x double> %27, <2 x double> poison, <2 x i32> zeroinitializer
%29 = fmul <2 x double> %28, %26
%30 = bitcast double* %25 to <2 x double>*
store <2 x double> %29, <2 x double>* %30
%31 = getelementptr inbounds double, double* %2, i64 1
%32 = load double, double* %31
%33 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 4, i64 6
%34 = insertelement <2 x double> poison, double %32, i64 0
%35 = shufflevector <2 x double> %34, <2 x double> poison, <2 x i32> zeroinitializer
%36 = fmul <2 x double> %35, %26
%37 = bitcast double* %33 to <2 x double>*
store <2 x double> %36, <2 x double>* %37
%38 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 0
store double %24, double* %38
%39 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 4
store double %32, double* %39
%40 = getelementptr inbounds double, double* %1, i64 2
%41 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 5, i64 3
%42 = bitcast double* %40 to <2 x double>*
%43 = load <2 x double>, <2 x double>* %42
%44 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 1, i64 0
%45 = bitcast double* %41 to <2 x double>*
store <2 x double> %43, <2 x double>* %45
%46 = bitcast double* %44 to <2 x double>*
store <2 x double> %43, <2 x double>* %46
%47 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 5, i64 5
store double 1.000000e+00, double* %47
%48 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 1, i64 2
store double 1.000000e+00, double* %48
%49 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 1, i64 3
%50 = bitcast double* %49 to i8*
%51 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 5, i64 0
%52 = getelementptr inbounds double, double* %2, i64 2
%53 = bitcast double* %51 to i8*
%54 = load double, double* %52
%55 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 1, i64 6
%56 = fneg <2 x double> %43
%57 = insertelement <2 x double> poison, double %54, i64 0
%58 = shufflevector <2 x double> %57, <2 x double> poison, <2 x i32> zeroinitializer
%59 = fmul <2 x double> %58, %56
%60 = bitcast double* %55 to <2 x double>*
store <2 x double> %59, <2 x double>* %60
%61 = getelementptr inbounds double, double* %2, i64 3
%62 = load double, double* %61
%63 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 5, i64 6
%64 = insertelement <2 x double> poison, double %62, i64 0
%65 = shufflevector <2 x double> %64, <2 x double> poison, <2 x i32> zeroinitializer
%66 = fmul <2 x double> %65, %56
%67 = bitcast double* %63 to <2 x double>*
store <2 x double> %66, <2 x double>* %67
%68 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 1
store double %54, double* %68
%69 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 5
store double %62, double* %69
%70 = getelementptr inbounds double, double* %1, i64 4
%71 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 6, i64 3
%72 = bitcast double* %70 to <2 x double>*
%73 = load <2 x double>, <2 x double>* %72
%74 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 2, i64 0
%75 = bitcast double* %71 to <2 x double>*
store <2 x double> %73, <2 x double>* %75
%76 = bitcast double* %74 to <2 x double>*
store <2 x double> %73, <2 x double>* %76
%77 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 6, i64 5
store double 1.000000e+00, double* %77
%78 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 2, i64 2
store double 1.000000e+00, double* %78
%79 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 2, i64 3
%80 = bitcast double* %79 to i8*
%81 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 6, i64 0
%82 = getelementptr inbounds double, double* %2, i64 4
%83 = bitcast double* %81 to i8*
%84 = load double, double* %82
%85 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 2, i64 6
%86 = fneg <2 x double> %73
%87 = insertelement <2 x double> poison, double %84, i64 0
%88 = shufflevector <2 x double> %87, <2 x double> poison, <2 x i32> zeroinitializer
%89 = fmul <2 x double> %88, %86
%90 = bitcast double* %85 to <2 x double>*
store <2 x double> %89, <2 x double>* %90
%91 = getelementptr inbounds double, double* %2, i64 5
%92 = load double, double* %91
%93 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 6, i64 6
%94 = insertelement <2 x double> poison, double %92, i64 0
%95 = shufflevector <2 x double> %94, <2 x double> poison, <2 x i32> zeroinitializer
%96 = fmul <2 x double> %95, %86
%97 = bitcast double* %93 to <2 x double>*
store <2 x double> %96, <2 x double>* %97
%98 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 2
store double %84, double* %98
%99 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 6
store double %92, double* %99
%100 = getelementptr inbounds double, double* %1, i64 6
%101 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 7, i64 3
%102 = bitcast double* %100 to <2 x double>*
%103 = load <2 x double>, <2 x double>* %102
%104 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 3, i64 0
%105 = bitcast double* %101 to <2 x double>*
store <2 x double> %103, <2 x double>* %105
%106 = bitcast double* %104 to <2 x double>*
store <2 x double> %103, <2 x double>* %106
%107 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 7, i64 5
store double 1.000000e+00, double* %107
%108 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 3, i64 2
store double 1.000000e+00, double* %108
%109 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 3, i64 3
%110 = bitcast double* %109 to i8*
%111 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 7, i64 0
%112 = getelementptr inbounds double, double* %2, i64 6
%113 = bitcast double* %111 to i8*
%114 = load double, double* %112
%115 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 3, i64 6
%116 = fneg <2 x double> %103
%117 = insertelement <2 x double> poison, double %114, i64 0
%118 = shufflevector <2 x double> %117, <2 x double> poison, <2 x i32> zeroinitializer
%119 = fmul <2 x double> %118, %116
%120 = bitcast double* %115 to <2 x double>*
store <2 x double> %119, <2 x double>* %120
%121 = getelementptr inbounds double, double* %2, i64 7
%122 = load double, double* %121
%123 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 7, i64 6
%124 = insertelement <2 x double> poison, double %122, i64 0
%125 = shufflevector <2 x double> %124, <2 x double> poison, <2 x i32> zeroinitializer
%126 = fmul <2 x double> %125, %116
%127 = bitcast double* %123 to <2 x double>*
store <2 x double> %126, <2 x double>* %127
%128 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 3
store double %114, double* %128
%129 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 7
store double %122, double* %129
%130 = getelementptr inbounds [8 x [8 x double]], [8 x [8 x double]]* %6, i64 0, i64 0, i64 0
%131 = getelementptr inbounds [8 x double], [8 x double]* %7, i64 0, i64 0
%132 = getelementptr inbounds [8 x double], [8 x double]* %8, i64 0, i64 0
%133 = call i64 @imatrix_solve_n_m(double* %130, double* %131, double* %132, i32 8, i32 1, i8* %10)
%134 = icmp eq i64 %133, 0
br i1 %134, label %135, label %137
135: ; preds = %3
%136 = getelementptr inbounds double, double* %0, i64 8
store double 1.000000e+00, double* %136
br label %137
137: ; preds = %3, %135
%138 = phi i32 [ 0, %135 ], [ -1, %3 ]
ret i32 %138
}