#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 */
float frand(int, int);
int /*<<< orphan*/ initfrand();
int /*<<< orphan*/ matvec_mult(float *, float *, float *);
int /*<<< orphan*/ print_vec_float(float *);
int /*<<< orphan*/ printf(char *);
int /*<<< orphan*/ sse_matvec_mult(float *, float *, float *);
int main() {
  int i;
  float mat[4 * 4], vec[4], res1[4], res2[4], err[4];
  initfrand();
  for (i = 0; i < 16; i++)
    mat[i] = frand(-1000, 1000);
  for (i = 0; i < 4; i++)
    vec[i] = frand(-1000, 1000);
  sse_matvec_mult(mat, vec, res2);
  matvec_mult(mat, vec, res1);
  for (i = 0; i < 4; i++)
    err[i] = 100.0 * (1.0 - res1[i] / res2[i]);
  printf("    ref = ");
  print_vec_float(res1);
  printf("    SSE = ");
  print_vec_float(res2);
  printf("err [%%] = ");
  print_vec_float(err);
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x90,%rsp
movl   $0x0,-0x4(%rbp)
mov    $0x0,%al
call   1040 <initfrand@plt>
movl   $0x0,-0x8(%rbp)
cmpl   $0x10,-0x8(%rbp)
jge    11b1 <main+0x51>
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movslq -0x8(%rbp),%rax
movss  %xmm0,-0x50(%rbp,%rax,4)
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    1180 <main+0x20>
movl   $0x0,-0x8(%rbp)
cmpl   $0x4,-0x8(%rbp)
jge    11e9 <main+0x89>
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movslq -0x8(%rbp),%rax
movss  %xmm0,-0x60(%rbp,%rax,4)
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    11b8 <main+0x58>
lea    -0x50(%rbp),%rdi
lea    -0x60(%rbp),%rsi
lea    -0x80(%rbp),%rdx
call   1080 <sse_matvec_mult@plt>
lea    -0x50(%rbp),%rdi
lea    -0x60(%rbp),%rsi
lea    -0x70(%rbp),%rdx
call   1050 <matvec_mult@plt>
movl   $0x0,-0x8(%rbp)
cmpl   $0x4,-0x8(%rbp)
jge    126b <main+0x10b>
movslq -0x8(%rbp),%rax
movss  -0x70(%rbp,%rax,4),%xmm0
movslq -0x8(%rbp),%rax
divss  -0x80(%rbp,%rax,4),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  0xdcc(%rip),%xmm1
subsd  %xmm0,%xmm1
movsd  0xdb8(%rip),%xmm0
mulsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movslq -0x8(%rbp),%rax
movss  %xmm0,-0x90(%rbp,%rax,4)
ff ff
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    1212 <main+0xb2>
lea    0xd9e(%rip),%rdi
call   1030 <printf@plt>
lea    -0x70(%rbp),%rdi
call   1070 <print_vec_float@plt>
lea    0xd94(%rip),%rdi
call   1030 <printf@plt>
lea    -0x80(%rbp),%rdi
call   1070 <print_vec_float@plt>
lea    0xd8a(%rip),%rdi
call   1030 <printf@plt>
lea    -0x90(%rbp),%rdi
call   1070 <print_vec_float@plt>
xor    %eax,%eax
add    $0x90,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x88,%rsp
xor    %eax,%eax
call   1040 <initfrand@plt>
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x10(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x14(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x18(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x1c(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x20(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x24(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x28(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x2c(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x30(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x34(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x38(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x3c(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x40(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x44(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x48(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x4c(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x4(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0x8(%rsp)
mov    $0xfffffc18,%edi
mov    $0x3e8,%esi
call   1060 <frand@plt>
movss  %xmm0,0xc(%rsp)
lea    0x10(%rsp),%rbx
mov    %rsp,%r12
lea    0x60(%rsp),%r14
mov    %rbx,%rdi
mov    %r12,%rsi
mov    %r14,%rdx
call   1080 <sse_matvec_mult@plt>
lea    0x70(%rsp),%r15
mov    %rbx,%rdi
mov    %r12,%rsi
mov    %r15,%rdx
call   1050 <matvec_mult@plt>
movaps 0x70(%rsp),%xmm0
divps  0x60(%rsp),%xmm0
cvtps2pd %xmm0,%xmm1
movhlps %xmm0,%xmm0
cvtps2pd %xmm0,%xmm0
movapd 0xc9f(%rip),%xmm2
movapd %xmm2,%xmm3
subpd  %xmm1,%xmm3
subpd  %xmm0,%xmm2
movapd 0xc9b(%rip),%xmm0
mulpd  %xmm0,%xmm2
mulpd  %xmm0,%xmm3
cvtpd2ps %xmm3,%xmm0
cvtpd2ps %xmm2,%xmm1
unpcklpd %xmm1,%xmm0
movapd %xmm0,0x50(%rsp)
lea    0xc8a(%rip),%rdi
call   1030 <printf@plt>
mov    %r15,%rdi
call   1070 <print_vec_float@plt>
lea    0xc81(%rip),%rdi
call   1030 <printf@plt>
mov    %r14,%rdi
call   1070 <print_vec_float@plt>
lea    0xc78(%rip),%rdi
call   1030 <printf@plt>
lea    0x50(%rsp),%rdi
call   1070 <print_vec_float@plt>
xor    %eax,%eax
add    $0x88,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@.str = [11 x i8] c" ref = \00"
@.str.1 = [11 x i8] c" SSE = \00"
@.str.2 = [12 x i8] c"err [%%] = \00"
define i32 @main() {
%1 = alloca i32
%2 = alloca i32
%3 = alloca [16 x float]
%4 = alloca [4 x float]
%5 = alloca [4 x float]
%6 = alloca [4 x float]
%7 = alloca [4 x float]
store i32 0, i32* %1
%8 = call i32 (...) @initfrand()
store i32 0, i32* %2
br label %9
9: ; preds = %17, %0
%10 = load i32, i32* %2
%11 = icmp slt i32 %10, 16
br i1 %11, label %12, label %20
12: ; preds = %9
%13 = call float @frand(i32 -1000, i32 1000)
%14 = load i32, i32* %2
%15 = sext i32 %14 to i64
%16 = getelementptr inbounds [16 x float], [16 x float]* %3, i64 0, i64 %15
store float %13, float* %16
br label %17
17: ; preds = %12
%18 = load i32, i32* %2
%19 = add nsw i32 %18, 1
store i32 %19, i32* %2
br label %9
20: ; preds = %9
store i32 0, i32* %2
br label %21
21: ; preds = %29, %20
%22 = load i32, i32* %2
%23 = icmp slt i32 %22, 4
br i1 %23, label %24, label %32
24: ; preds = %21
%25 = call float @frand(i32 -1000, i32 1000)
%26 = load i32, i32* %2
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds [4 x float], [4 x float]* %4, i64 0, i64 %27
store float %25, float* %28
br label %29
29: ; preds = %24
%30 = load i32, i32* %2
%31 = add nsw i32 %30, 1
store i32 %31, i32* %2
br label %21
32: ; preds = %21
%33 = getelementptr inbounds [16 x float], [16 x float]* %3, i64 0, i64 0
%34 = getelementptr inbounds [4 x float], [4 x float]* %4, i64 0, i64 0
%35 = getelementptr inbounds [4 x float], [4 x float]* %6, i64 0, i64 0
%36 = call i32 @sse_matvec_mult(float* %33, float* %34, float* %35)
%37 = getelementptr inbounds [16 x float], [16 x float]* %3, i64 0, i64 0
%38 = getelementptr inbounds [4 x float], [4 x float]* %4, i64 0, i64 0
%39 = getelementptr inbounds [4 x float], [4 x float]* %5, i64 0, i64 0
%40 = call i32 @matvec_mult(float* %37, float* %38, float* %39)
store i32 0, i32* %2
br label %41
41: ; preds = %61, %32
%42 = load i32, i32* %2
%43 = icmp slt i32 %42, 4
br i1 %43, label %44, label %64
44: ; preds = %41
%45 = load i32, i32* %2
%46 = sext i32 %45 to i64
%47 = getelementptr inbounds [4 x float], [4 x float]* %5, i64 0, i64 %46
%48 = load float, float* %47
%49 = load i32, i32* %2
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds [4 x float], [4 x float]* %6, i64 0, i64 %50
%52 = load float, float* %51
%53 = fdiv float %48, %52
%54 = fpext float %53 to double
%55 = fsub double 1.000000e+00, %54
%56 = fmul double 1.000000e+02, %55
%57 = fptrunc double %56 to float
%58 = load i32, i32* %2
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds [4 x float], [4 x float]* %7, i64 0, i64 %59
store float %57, float* %60
br label %61
61: ; preds = %44
%62 = load i32, i32* %2
%63 = add nsw i32 %62, 1
store i32 %63, i32* %2
br label %41
64: ; preds = %41
%65 = call i32 @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i64 0, i64 0))
%66 = getelementptr inbounds [4 x float], [4 x float]* %5, i64 0, i64 0
%67 = call i32 @print_vec_float(float* %66)
%68 = call i32 @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i64 0, i64 0))
%69 = getelementptr inbounds [4 x float], [4 x float]* %6, i64 0, i64 0
%70 = call i32 @print_vec_float(float* %69)
%71 = call i32 @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.2, i64 0, i64 0))
%72 = getelementptr inbounds [4 x float], [4 x float]* %7, i64 0, i64 0
%73 = call i32 @print_vec_float(float* %72)
ret i32 0
}

LLVM IR (-O2):
@.str = [11 x i8] c" ref = \00"
@.str.1 = [11 x i8] c" SSE = \00"
@.str.2 = [12 x i8] c"err [%%] = \00"
define i32 @main() {
%1 = alloca [16 x float]
%2 = alloca [4 x float]
%3 = alloca <4 x float>
%4 = alloca <4 x float>
%5 = alloca <4 x float>
%6 = bitcast [16 x float]* %1 to i8*
%7 = bitcast [4 x float]* %2 to i8*
%8 = bitcast <4 x float>* %3 to i8*
%9 = bitcast <4 x float>* %4 to i8*
%10 = bitcast <4 x float>* %5 to i8*
%11 = tail call i32 (...) @initfrand()
%12 = tail call float @frand(i32 -1000, i32 1000)
%13 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 0
store float %12, float* %13
%14 = tail call float @frand(i32 -1000, i32 1000)
%15 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 1
store float %14, float* %15
%16 = tail call float @frand(i32 -1000, i32 1000)
%17 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 2
store float %16, float* %17
%18 = tail call float @frand(i32 -1000, i32 1000)
%19 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 3
store float %18, float* %19
%20 = tail call float @frand(i32 -1000, i32 1000)
%21 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 4
store float %20, float* %21
%22 = tail call float @frand(i32 -1000, i32 1000)
%23 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 5
store float %22, float* %23
%24 = tail call float @frand(i32 -1000, i32 1000)
%25 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 6
store float %24, float* %25
%26 = tail call float @frand(i32 -1000, i32 1000)
%27 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 7
store float %26, float* %27
%28 = tail call float @frand(i32 -1000, i32 1000)
%29 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 8
store float %28, float* %29
%30 = tail call float @frand(i32 -1000, i32 1000)
%31 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 9
store float %30, float* %31
%32 = tail call float @frand(i32 -1000, i32 1000)
%33 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 10
store float %32, float* %33
%34 = tail call float @frand(i32 -1000, i32 1000)
%35 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 11
store float %34, float* %35
%36 = tail call float @frand(i32 -1000, i32 1000)
%37 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 12
store float %36, float* %37
%38 = tail call float @frand(i32 -1000, i32 1000)
%39 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 13
store float %38, float* %39
%40 = tail call float @frand(i32 -1000, i32 1000)
%41 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 14
store float %40, float* %41
%42 = tail call float @frand(i32 -1000, i32 1000)
%43 = getelementptr inbounds [16 x float], [16 x float]* %1, i64 0, i64 15
store float %42, float* %43
%44 = tail call float @frand(i32 -1000, i32 1000)
%45 = getelementptr inbounds [4 x float], [4 x float]* %2, i64 0, i64 0
store float %44, float* %45
%46 = tail call float @frand(i32 -1000, i32 1000)
%47 = getelementptr inbounds [4 x float], [4 x float]* %2, i64 0, i64 1
store float %46, float* %47
%48 = tail call float @frand(i32 -1000, i32 1000)
%49 = getelementptr inbounds [4 x float], [4 x float]* %2, i64 0, i64 2
store float %48, float* %49
%50 = tail call float @frand(i32 -1000, i32 1000)
%51 = getelementptr inbounds [4 x float], [4 x float]* %2, i64 0, i64 3
store float %50, float* %51
%52 = getelementptr inbounds <4 x float>, <4 x float>* %4, i64 0, i64 0
%53 = call i32 @sse_matvec_mult(float* %13, float* %45, float* %52)
%54 = getelementptr inbounds <4 x float>, <4 x float>* %3, i64 0, i64 0
%55 = call i32 @matvec_mult(float* %13, float* %45, float* %54)
%56 = getelementptr inbounds <4 x float>, <4 x float>* %5, i64 0, i64 0
%57 = load <4 x float>, <4 x float>* %3
%58 = load <4 x float>, <4 x float>* %4
%59 = fdiv <4 x float> %57, %58
%60 = fpext <4 x float> %59 to <4 x double>
%61 = fsub <4 x double> <double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00>, %60
%62 = fmul <4 x double> %61, <double 1.000000e+02, double 1.000000e+02, double 1.000000e+02, double 1.000000e+02>
%63 = fptrunc <4 x double> %62 to <4 x float>
store <4 x float> %63, <4 x float>* %5
%64 = call i32 @printf(i8* dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i64 0, i64 0))
%65 = call i32 @print_vec_float(float* %54)
%66 = call i32 @printf(i8* dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.1, i64 0, i64 0))
%67 = call i32 @print_vec_float(float* %52)
%68 = call i32 @printf(i8* dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.2, i64 0, i64 0))
%69 = call i32 @print_vec_float(float* %56)
ret i32 0
}