#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*/ matrix_product(int, int, double **, int, int, double **,
                                  double **);
void vector_transform(double matrix[][3], double u[]) {
  double mat_u[][1] = {{u[0]}, {u[1]}, {u[2]}};
  double mat_u_res[3][1];
  matrix_product(3, 3, matrix, 3, 1, mat_u, mat_u_res);
  u[0] = mat_u_res[0][0];
  u[1] = mat_u_res[1][0];
  u[2] = mat_u_res[2][0];
}


x86 assembly (clang, -O0):
<vector_transform>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm0
movsd  %xmm0,-0x20(%rbp)
mov    -0x8(%rbp),%rdx
lea    -0x30(%rbp),%r9
lea    -0x50(%rbp),%rax
mov    $0x3,%ecx
mov    $0x1,%r8d
mov    %ecx,%edi
mov    %ecx,%esi
mov    %rax,(%rsp)
call   1030 <matrix_product@plt>
movsd  -0x50(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,(%rax)
movsd  -0x48(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x8(%rax)
movsd  -0x40(%rbp),%xmm0
mov    -0x10(%rbp),%rax
movsd  %xmm0,0x10(%rax)
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<vector_transform>:
push   %rbx
sub    $0x50,%rsp
mov    %rsi,%rbx
mov    %rdi,%rdx
movups (%rsi),%xmm0
movaps %xmm0,0x30(%rsp)
movsd  0x10(%rsi),%xmm0
movsd  %xmm0,0x40(%rsp)
lea    0x10(%rsp),%rax
mov    %rax,(%rsp)
lea    0x30(%rsp),%r9
mov    $0x3,%edi
mov    $0x3,%esi
mov    $0x3,%ecx
mov    $0x1,%r8d
call   1030 <matrix_product@plt>
movaps 0x10(%rsp),%xmm0
movups %xmm0,(%rbx)
movsd  0x20(%rsp),%xmm0
movsd  %xmm0,0x10(%rbx)
add    $0x50,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define void @vector_transform([3 x double]* %0, double* %1) {
%3 = alloca [3 x double]*
%4 = alloca double*
%5 = alloca [3 x [1 x double]]
%6 = alloca [3 x [1 x double]]
store [3 x double]* %0, [3 x double]** %3
store double* %1, double** %4
%7 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %5, i64 0, i64 0
%8 = getelementptr inbounds [1 x double], [1 x double]* %7, i64 0, i64 0
%9 = load double*, double** %4
%10 = getelementptr inbounds double, double* %9, i64 0
%11 = load double, double* %10
store double %11, double* %8
%12 = getelementptr inbounds [1 x double], [1 x double]* %7, i64 1
%13 = getelementptr inbounds [1 x double], [1 x double]* %12, i64 0, i64 0
%14 = load double*, double** %4
%15 = getelementptr inbounds double, double* %14, i64 1
%16 = load double, double* %15
store double %16, double* %13
%17 = getelementptr inbounds [1 x double], [1 x double]* %12, i64 1
%18 = getelementptr inbounds [1 x double], [1 x double]* %17, i64 0, i64 0
%19 = load double*, double** %4
%20 = getelementptr inbounds double, double* %19, i64 2
%21 = load double, double* %20
store double %21, double* %18
%22 = load [3 x double]*, [3 x double]** %3
%23 = bitcast [3 x double]* %22 to double**
%24 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %5, i64 0, i64 0
%25 = bitcast [1 x double]* %24 to double**
%26 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %6, i64 0, i64 0
%27 = bitcast [1 x double]* %26 to double**
%28 = call i32 @matrix_product(i32 3, i32 3, double** %23, i32 3, i32 1, double** %25, double** %27)
%29 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %6, i64 0, i64 0
%30 = getelementptr inbounds [1 x double], [1 x double]* %29, i64 0, i64 0
%31 = load double, double* %30
%32 = load double*, double** %4
%33 = getelementptr inbounds double, double* %32, i64 0
store double %31, double* %33
%34 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %6, i64 0, i64 1
%35 = getelementptr inbounds [1 x double], [1 x double]* %34, i64 0, i64 0
%36 = load double, double* %35
%37 = load double*, double** %4
%38 = getelementptr inbounds double, double* %37, i64 1
store double %36, double* %38
%39 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %6, i64 0, i64 2
%40 = getelementptr inbounds [1 x double], [1 x double]* %39, i64 0, i64 0
%41 = load double, double* %40
%42 = load double*, double** %4
%43 = getelementptr inbounds double, double* %42, i64 2
store double %41, double* %43
ret void
}

LLVM IR (-O2):
define void @vector_transform([3 x double]* %0, double* nocapture %1) {
%3 = alloca [3 x [1 x double]]
%4 = alloca [3 x [1 x double]]
%5 = bitcast [3 x [1 x double]]* %3 to i8*
%6 = bitcast double* %1 to <2 x double>*
%7 = load <2 x double>, <2 x double>* %6
%8 = bitcast [3 x [1 x double]]* %3 to <2 x double>*
store <2 x double> %7, <2 x double>* %8
%9 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %3, i64 0, i64 2, i64 0
%10 = getelementptr inbounds double, double* %1, i64 2
%11 = load double, double* %10
store double %11, double* %9
%12 = bitcast [3 x [1 x double]]* %4 to i8*
%13 = bitcast [3 x double]* %0 to double**
%14 = bitcast [3 x [1 x double]]* %3 to double**
%15 = bitcast [3 x [1 x double]]* %4 to double**
%16 = call i32 @matrix_product(i32 3, i32 3, double** %13, i32 3, i32 1, double** %14, double** %15)
%17 = bitcast [3 x [1 x double]]* %4 to <2 x double>*
%18 = load <2 x double>, <2 x double>* %17
%19 = bitcast double* %1 to <2 x double>*
store <2 x double> %18, <2 x double>* %19
%20 = getelementptr inbounds [3 x [1 x double]], [3 x [1 x double]]* %4, i64 0, i64 2, i64 0
%21 = load double, double* %20
store double %21, double* %10
ret void
}