#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 *align_p(float *);
int /*<<< orphan*/ init(float *, float *);
float *malloc(int);
double omp_get_wtime();
int /*<<< orphan*/ printf(char *, double);
int /*<<< orphan*/ simple_transpose(float *, float *, int);
int /*<<< orphan*/ transpose(float *, float *, int);
int /*<<< orphan*/ verify(float *);
int main(void) {
  float *a = malloc(sizeof(float) * 1600 * 1600 + 15);
  float *b = malloc(sizeof(float) * 1600 * 1600 + 15);
  float *c = malloc(sizeof(float) * 1600 * 1600 + 15);
  float *d = malloc(sizeof(float) * 1600 * 1600 + 15);
  a = align_p(a);
  b = align_p(b);
  c = align_p(c);
  d = align_p(d);
  int i;
  double t;
  init(c, d);
  simple_transpose(c, d, 64);
  verify(c);
  t = omp_get_wtime();
  for (i = 0; i < 500; i++)
    simple_transpose(c, d, 64);
  printf("normal: %lf\n", omp_get_wtime() - t);
  init(a, b);
  transpose(a, b, 64);
  verify(a);
  t = omp_get_wtime();
  for (i = 0; i < 500; i++)
    transpose(a, b, 64);
  printf("sse: %lf\n", omp_get_wtime() - t);
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
movl   $0x0,-0x4(%rbp)
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,-0x10(%rbp)
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,-0x18(%rbp)
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,-0x20(%rbp)
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rdi
call   1030 <align_p@plt>
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rdi
call   1030 <align_p@plt>
mov    %rax,-0x18(%rbp)
mov    -0x20(%rbp),%rdi
call   1030 <align_p@plt>
mov    %rax,-0x20(%rbp)
mov    -0x28(%rbp),%rdi
call   1030 <align_p@plt>
mov    %rax,-0x28(%rbp)
mov    -0x20(%rbp),%rdi
mov    -0x28(%rbp),%rsi
call   1080 <init@plt>
mov    -0x20(%rbp),%rdi
mov    -0x28(%rbp),%rsi
mov    $0x40,%edx
call   1060 <simple_transpose@plt>
mov    -0x20(%rbp),%rdi
call   10a0 <verify@plt>
mov    $0x0,%al
call   1040 <omp_get_wtime@plt>
movsd  %xmm0,-0x38(%rbp)
movl   $0x0,-0x2c(%rbp)
cmpl   $0x1f4,-0x2c(%rbp)
jge    1263 <main+0xe3>
mov    -0x20(%rbp),%rdi
mov    -0x28(%rbp),%rsi
mov    $0x40,%edx
call   1060 <simple_transpose@plt>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1236 <main+0xb6>
mov    $0x0,%al
call   1040 <omp_get_wtime@plt>
subsd  -0x38(%rbp),%xmm0
lea    0xd8a(%rip),%rdi
call   1050 <printf@plt>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rsi
call   1080 <init@plt>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    $0x40,%edx
call   1070 <transpose@plt>
mov    -0x10(%rbp),%rdi
call   10a0 <verify@plt>
mov    $0x0,%al
call   1040 <omp_get_wtime@plt>
movsd  %xmm0,-0x38(%rbp)
movl   $0x0,-0x2c(%rbp)
cmpl   $0x1f4,-0x2c(%rbp)
jge    12e3 <main+0x163>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    $0x40,%edx
call   1070 <transpose@plt>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    12b6 <main+0x136>
mov    $0x0,%al
call   1040 <omp_get_wtime@plt>
subsd  -0x38(%rbp),%xmm0
lea    0xd17(%rip),%rdi
call   1050 <printf@plt>
xor    %eax,%eax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,%rbx
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,%r15
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,%r12
mov    $0x9c400f,%edi
call   1090 <malloc@plt>
mov    %rax,%r13
mov    %rbx,%rdi
call   1030 <align_p@plt>
mov    %rax,%r14
mov    %r15,%rdi
call   1030 <align_p@plt>
mov    %rax,%r15
mov    %r12,%rdi
call   1030 <align_p@plt>
mov    %rax,%r12
mov    %r13,%rdi
call   1030 <align_p@plt>
mov    %rax,%rbx
mov    %r12,%rdi
mov    %rax,%rsi
call   1080 <init@plt>
mov    %r12,%rdi
mov    %rbx,%rsi
mov    $0x40,%edx
call   1060 <simple_transpose@plt>
mov    %r12,%rdi
call   10a0 <verify@plt>
xor    %eax,%eax
call   1040 <omp_get_wtime@plt>
movsd  %xmm0,(%rsp)
mov    $0x1f4,%ebp
nop
mov    %r12,%rdi
mov    %rbx,%rsi
mov    $0x40,%edx
call   1060 <simple_transpose@plt>
add    $0xffffffff,%ebp
jne    1220 <main+0xa0>
xor    %eax,%eax
call   1040 <omp_get_wtime@plt>
subsd  (%rsp),%xmm0
lea    0xdb8(%rip),%rdi
call   1050 <printf@plt>
mov    %r14,%rdi
mov    %r15,%rsi
call   1080 <init@plt>
mov    %r14,%rdi
mov    %r15,%rsi
mov    $0x40,%edx
call   1070 <transpose@plt>
mov    %r14,%rdi
call   10a0 <verify@plt>
xor    %eax,%eax
call   1040 <omp_get_wtime@plt>
movsd  %xmm0,(%rsp)
mov    $0x1f4,%ebx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    %r14,%rdi
mov    %r15,%rsi
mov    $0x40,%edx
call   1070 <transpose@plt>
add    $0xffffffff,%ebx
jne    1290 <main+0x110>
xor    %eax,%eax
call   1040 <omp_get_wtime@plt>
subsd  (%rsp),%xmm0
lea    0xd55(%rip),%rdi
call   1050 <printf@plt>
xor    %eax,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@.str = [13 x i8] c"normal: %lf\0A\00"
@.str.1 = [10 x i8] c"sse: %lf\0A\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca float*
%3 = alloca float*
%4 = alloca float*
%5 = alloca float*
%6 = alloca i32
%7 = alloca double
store i32 0, i32* %1
%8 = call float* @malloc(i32 10240015)
store float* %8, float** %2
%9 = call float* @malloc(i32 10240015)
store float* %9, float** %3
%10 = call float* @malloc(i32 10240015)
store float* %10, float** %4
%11 = call float* @malloc(i32 10240015)
store float* %11, float** %5
%12 = load float*, float** %2
%13 = call float* @align_p(float* %12)
store float* %13, float** %2
%14 = load float*, float** %3
%15 = call float* @align_p(float* %14)
store float* %15, float** %3
%16 = load float*, float** %4
%17 = call float* @align_p(float* %16)
store float* %17, float** %4
%18 = load float*, float** %5
%19 = call float* @align_p(float* %18)
store float* %19, float** %5
%20 = load float*, float** %4
%21 = load float*, float** %5
%22 = call i32 @init(float* %20, float* %21)
%23 = load float*, float** %4
%24 = load float*, float** %5
%25 = call i32 @simple_transpose(float* %23, float* %24, i32 64)
%26 = load float*, float** %4
%27 = call i32 @verify(float* %26)
%28 = call double (...) @omp_get_wtime()
store double %28, double* %7
store i32 0, i32* %6
br label %29
29: ; preds = %36, %0
%30 = load i32, i32* %6
%31 = icmp slt i32 %30, 500
br i1 %31, label %32, label %39
32: ; preds = %29
%33 = load float*, float** %4
%34 = load float*, float** %5
%35 = call i32 @simple_transpose(float* %33, float* %34, i32 64)
br label %36
36: ; preds = %32
%37 = load i32, i32* %6
%38 = add nsw i32 %37, 1
store i32 %38, i32* %6
br label %29
39: ; preds = %29
%40 = call double (...) @omp_get_wtime()
%41 = load double, double* %7
%42 = fsub double %40, %41
%43 = call i32 @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0), double %42)
%44 = load float*, float** %2
%45 = load float*, float** %3
%46 = call i32 @init(float* %44, float* %45)
%47 = load float*, float** %2
%48 = load float*, float** %3
%49 = call i32 @transpose(float* %47, float* %48, i32 64)
%50 = load float*, float** %2
%51 = call i32 @verify(float* %50)
%52 = call double (...) @omp_get_wtime()
store double %52, double* %7
store i32 0, i32* %6
br label %53
53: ; preds = %60, %39
%54 = load i32, i32* %6
%55 = icmp slt i32 %54, 500
br i1 %55, label %56, label %63
56: ; preds = %53
%57 = load float*, float** %2
%58 = load float*, float** %3
%59 = call i32 @transpose(float* %57, float* %58, i32 64)
br label %60
60: ; preds = %56
%61 = load i32, i32* %6
%62 = add nsw i32 %61, 1
store i32 %62, i32* %6
br label %53
63: ; preds = %53
%64 = call double (...) @omp_get_wtime()
%65 = load double, double* %7
%66 = fsub double %64, %65
%67 = call i32 @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0), double %66)
ret i32 0
}

LLVM IR (-O2):
@.str = [13 x i8] c"normal: %lf\0A\00"
@.str.1 = [10 x i8] c"sse: %lf\0A\00"
define i32 @main() {
%1 = tail call float* @malloc(i32 10240015)
%2 = tail call float* @malloc(i32 10240015)
%3 = tail call float* @malloc(i32 10240015)
%4 = tail call float* @malloc(i32 10240015)
%5 = tail call float* @align_p(float* %1)
%6 = tail call float* @align_p(float* %2)
%7 = tail call float* @align_p(float* %3)
%8 = tail call float* @align_p(float* %4)
%9 = tail call i32 @init(float* %7, float* %8)
%10 = tail call i32 @simple_transpose(float* %7, float* %8, i32 64)
%11 = tail call i32 @verify(float* %7)
%12 = tail call double (...) @omp_get_wtime()
br label %13
13: ; preds = %0, %13
%14 = phi i32 [ 0, %0 ], [ %16, %13 ]
%15 = tail call i32 @simple_transpose(float* %7, float* %8, i32 64)
%16 = add nuw nsw i32 %14, 1
%17 = icmp eq i32 %16, 500
br i1 %17, label %18, label %13
18: ; preds = %13
%19 = tail call double (...) @omp_get_wtime()
%20 = fsub double %19, %12
%21 = tail call i32 @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0), double %20)
%22 = tail call i32 @init(float* %5, float* %6)
%23 = tail call i32 @transpose(float* %5, float* %6, i32 64)
%24 = tail call i32 @verify(float* %5)
%25 = tail call double (...) @omp_get_wtime()
br label %26
26: ; preds = %18, %26
%27 = phi i32 [ 0, %18 ], [ %29, %26 ]
%28 = tail call i32 @transpose(float* %5, float* %6, i32 64)
%29 = add nuw nsw i32 %27, 1
%30 = icmp eq i32 %29, 500
br i1 %30, label %31, label %26
31: ; preds = %26
%32 = tail call double (...) @omp_get_wtime()
%33 = fsub double %32, %25
%34 = tail call i32 @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0), double %33)
ret i32 0
}