#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*/ compute(int, double **, double **, double *, int);
int /*<<< orphan*/ load(int, double **, double *, int);
void workload(double m1[1024 * 1024], double m2[1024 * 1024],
              double prod[1024 * 1024]) {
#pragma HLS INTERFACE m_axi port = m1 offset = slave bundle = gmem
#pragma HLS INTERFACE m_axi port = m2 offset = slave bundle = gmem
#pragma HLS INTERFACE m_axi port = prod offset = slave bundle = gmem
#pragma HLS INTERFACE s_axilite port = m1 bundle = control
#pragma HLS INTERFACE s_axilite port = m2 bundle = control
#pragma HLS INTERFACE s_axilite port = prod bundle = control
#pragma HLS INTERFACE s_axilite port = return bundle = control
  double local_col[1024][32];
  double local_rows_x[2][1024];
#pragma HLS array_partition variable = local_rows_x dim = 1 complete
  double local_rows_y[2][1024];
#pragma HLS array_partition variable = local_rows_y dim = 1 complete
  int i, j, k;
  for (i = 0; i < 1024; i += 32) {
    for (j = 0; j < 1024; j++) {
      for (k = 0; k < 32; k++) {
#pragma HLS pipeline
        local_col[j][k] = m2[j * 1024 + i + k];
      }
    }
    int num_batches = (1024 + 2 - 1) / 2;
    int tail_size = num_batches % 2;
    if (tail_size == 0)
      tail_size = 2;
    for (j = 0; j < num_batches + 1; j++) {
      int load_flag = j < num_batches;
      int compute_flag = j > 0;
      int load_rows = j == num_batches - 1 ? tail_size : 2;
      int compute_rows = j == num_batches ? tail_size : 2;
      if (j % 2 == 0) {
        load(load_flag, local_rows_x, m1 + j * 1024 * 2, load_rows);
        compute(compute_flag, local_rows_y, local_col,
                prod + (j - 1) * 1024 + i, compute_rows);
      } else {
        load(load_flag, local_rows_y, m1 + j * 1024 * 2, load_rows);
        compute(compute_flag, local_rows_x, local_col,
                prod + (j - 1) * 1024 + i, compute_rows);
      }
    }
  }
  return;
}


x86 assembly (clang, -O0):
<workload>:
push   %rbp
mov    %rsp,%rbp
sub    $0x48050,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movl   $0x0,-0x48024(%rbp)
cmpl   $0x400,-0x48024(%rbp)
jge    1437 <workload+0x317>
movl   $0x0,-0x48028(%rbp)
cmpl   $0x400,-0x48028(%rbp)
jge    11f1 <workload+0xd1>
movl   $0x0,-0x4802c(%rbp)
cmpl   $0x20,-0x4802c(%rbp)
jge    11d8 <workload+0xb8>
mov    -0x10(%rbp),%rax
mov    -0x48028(%rbp),%ecx
shl    $0xa,%ecx
add    -0x48024(%rbp),%ecx
add    -0x4802c(%rbp),%ecx
movslq %ecx,%rcx
movsd  (%rax,%rcx,8),%xmm0
movslq -0x48028(%rbp),%rcx
lea    -0x40020(%rbp),%rax
shl    $0x8,%rcx
add    %rcx,%rax
movslq -0x4802c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x4802c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x4802c(%rbp)
jmp    1175 <workload+0x55>
jmp    11dd <workload+0xbd>
mov    -0x48028(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x48028(%rbp)
jmp    115b <workload+0x3b>
movl   $0x200,-0x48030(%rbp)
mov    -0x48030(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
mov    %edx,-0x48034(%rbp)
cmpl   $0x0,-0x48034(%rbp)
jne    1226 <workload+0x106>
movl   $0x2,-0x48034(%rbp)
movl   $0x0,-0x48028(%rbp)
mov    -0x48028(%rbp),%eax
mov    -0x48030(%rbp),%ecx
add    $0x1,%ecx
cmp    %ecx,%eax
jge    141e <workload+0x2fe>
mov    -0x48028(%rbp),%eax
cmp    -0x48030(%rbp),%eax
setl   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x48038(%rbp)
cmpl   $0x0,-0x48028(%rbp)
setg   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x4803c(%rbp)
mov    -0x48028(%rbp),%eax
mov    -0x48030(%rbp),%ecx
sub    $0x1,%ecx
cmp    %ecx,%eax
jne    129e <workload+0x17e>
mov    -0x48034(%rbp),%eax
mov    %eax,-0x48048(%rbp)
jmp    12ae <workload+0x18e>
mov    $0x2,%eax
mov    %eax,-0x48048(%rbp)
jmp    12ae <workload+0x18e>
mov    -0x48048(%rbp),%eax
mov    %eax,-0x48040(%rbp)
mov    -0x48028(%rbp),%eax
cmp    -0x48030(%rbp),%eax
jne    12dd <workload+0x1bd>
mov    -0x48034(%rbp),%eax
mov    %eax,-0x4804c(%rbp)
jmp    12ed <workload+0x1cd>
mov    $0x2,%eax
mov    %eax,-0x4804c(%rbp)
jmp    12ed <workload+0x1cd>
mov    -0x4804c(%rbp),%eax
mov    %eax,-0x48044(%rbp)
mov    -0x48028(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
cmp    $0x0,%edx
jne    138d <workload+0x26d>
mov    -0x48038(%rbp),%edi
lea    -0x44020(%rbp),%rsi
mov    -0x8(%rbp),%rdx
mov    -0x48028(%rbp),%eax
shl    $0xa,%eax
shl    $0x1,%eax
cltq
shl    $0x3,%rax
add    %rax,%rdx
mov    -0x48040(%rbp),%ecx
call   1030 <load@plt>
mov    -0x4803c(%rbp),%edi
lea    -0x48020(%rbp),%rsi
lea    -0x40020(%rbp),%rdx
mov    -0x18(%rbp),%rcx
mov    -0x48028(%rbp),%eax
sub    $0x1,%eax
shl    $0xa,%eax
cltq
shl    $0x3,%rax
add    %rax,%rcx
movslq -0x48024(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rcx
mov    -0x48044(%rbp),%r8d
call   1040 <compute@plt>
jmp    1405 <workload+0x2e5>
mov    -0x48038(%rbp),%edi
lea    -0x48020(%rbp),%rsi
mov    -0x8(%rbp),%rdx
mov    -0x48028(%rbp),%eax
shl    $0xa,%eax
shl    $0x1,%eax
cltq
shl    $0x3,%rax
add    %rax,%rdx
mov    -0x48040(%rbp),%ecx
call   1030 <load@plt>
mov    -0x4803c(%rbp),%edi
lea    -0x44020(%rbp),%rsi
lea    -0x40020(%rbp),%rdx
mov    -0x18(%rbp),%rcx
mov    -0x48028(%rbp),%eax
sub    $0x1,%eax
shl    $0xa,%eax
cltq
shl    $0x3,%rax
add    %rax,%rcx
movslq -0x48024(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rcx
mov    -0x48044(%rbp),%r8d
call   1040 <compute@plt>
jmp    140a <workload+0x2ea>
mov    -0x48028(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x48028(%rbp)
jmp    1230 <workload+0x110>
jmp    1423 <workload+0x303>
mov    -0x48024(%rbp),%eax
add    $0x20,%eax
mov    %eax,-0x48024(%rbp)
jmp    1141 <workload+0x21>
add    $0x48050,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<workload>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x48048,%rsp
mov    %rsi,%rbx
mov    %rdi,0x10(%rsp)
lea    0x8140(%rsp),%r13
add    $0x2000,%rbx
mov    %rdx,0x18(%rsp)
lea    -0x2000(%rdx),%rax
mov    %rax,0x8(%rsp)
xor    %r15d,%r15d
xor    %eax,%eax
jmp    11a1 <workload+0x71>
mov    0x28(%rsp),%r15
add    $0x20,%r15
mov    0x20(%rsp),%rax
add    $0x1,%rax
mov    0x30(%rsp),%rbx
add    $0x100,%rbx
addq   $0x100,0x8(%rsp)
cmp    $0x20,%rax
je     12d0 <workload+0x1a0>
mov    %rax,0x20(%rsp)
mov    %rbx,0x30(%rsp)
xor    %ebp,%ebp
nopl   (%rax)
mov    %r13,%r14
add    %rbp,%r14
lea    -0x100(,%rbp,1),%rdi
ff
add    %r13,%rdi
lea    -0x2000(%rbx),%rsi
mov    $0x100,%edx
call   1030 <memcpy@plt>
mov    $0x100,%edx
mov    %r14,%rdi
mov    %rbx,%rsi
call   1030 <memcpy@plt>
add    $0x200,%rbp
add    $0x4000,%rbx
cmp    $0x40000,%rbp
jne    11b0 <workload+0x80>
mov    0x18(%rsp),%rax
mov    %r15,0x28(%rsp)
lea    (%rax,%r15,8),%rax
mov    %rax,0x38(%rsp)
mov    $0xfffffc00,%ebp
mov    0x10(%rsp),%r15
mov    0x8(%rsp),%r14
xor    %ebx,%ebx
jmp    1286 <workload+0x156>
nop
lea    0x40(%rsp),%rsi
mov    %r15,%rdx
mov    $0x2,%ecx
call   1040 <load@plt>
mov    %ebp,%eax
and    $0xfffffc00,%eax
mov    0x38(%rsp),%rcx
lea    (%rcx,%rax,8),%rcx
mov    %r12d,%edi
lea    0x4040(%rsp),%rsi
lea    0x8040(%rsp),%rdx
mov    $0x2,%r8d
call   1050 <compute@plt>
add    $0x1,%rbx
add    $0x400,%rbp
add    $0x2000,%r14
add    $0x4000,%r15
cmp    $0x201,%rbx
je     1170 <workload+0x40>
xor    %edi,%edi
cmp    $0x200,%rbx
setne  %dil
xor    %r12d,%r12d
test   %rbx,%rbx
setne  %r12b
test   $0x1,%bl
jne    1220 <workload+0xf0>
lea    0x4040(%rsp),%rsi
mov    %r15,%rdx
mov    $0x2,%ecx
call   1040 <load@plt>
mov    %r12d,%edi
lea    0x40(%rsp),%rsi
lea    0x8040(%rsp),%rdx
mov    %r14,%rcx
jmp    1255 <workload+0x125>
add    $0x48048,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @workload(double* %0, double* %1, double* %2) {
%4 = alloca double*
%5 = alloca double*
%6 = alloca double*
%7 = alloca [1024 x [32 x double]]
%8 = alloca [2 x [1024 x double]]
%9 = alloca [2 x [1024 x double]]
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
%15 = alloca i32
%16 = alloca i32
%17 = alloca i32
%18 = alloca i32
store double* %0, double** %4
store double* %1, double** %5
store double* %2, double** %6
store i32 0, i32* %10
br label %19
19: ; preds = %155, %3
%20 = load i32, i32* %10
%21 = icmp slt i32 %20, 1024
br i1 %21, label %22, label %158
22: ; preds = %19
store i32 0, i32* %11
br label %23
23: ; preds = %51, %22
%24 = load i32, i32* %11
%25 = icmp slt i32 %24, 1024
br i1 %25, label %26, label %54
26: ; preds = %23
store i32 0, i32* %12
br label %27
27: ; preds = %47, %26
%28 = load i32, i32* %12
%29 = icmp slt i32 %28, 32
br i1 %29, label %30, label %50
30: ; preds = %27
%31 = load double*, double** %5
%32 = load i32, i32* %11
%33 = mul nsw i32 %32, 1024
%34 = load i32, i32* %10
%35 = add nsw i32 %33, %34
%36 = load i32, i32* %12
%37 = add nsw i32 %35, %36
%38 = sext i32 %37 to i64
%39 = getelementptr inbounds double, double* %31, i64 %38
%40 = load double, double* %39
%41 = load i32, i32* %11
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds [1024 x [32 x double]], [1024 x [32 x double]]* %7, i64 0, i64 %42
%44 = load i32, i32* %12
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds [32 x double], [32 x double]* %43, i64 0, i64 %45
store double %40, double* %46
br label %47
47: ; preds = %30
%48 = load i32, i32* %12
%49 = add nsw i32 %48, 1
store i32 %49, i32* %12
br label %27
50: ; preds = %27
br label %51
51: ; preds = %50
%52 = load i32, i32* %11
%53 = add nsw i32 %52, 1
store i32 %53, i32* %11
br label %23
54: ; preds = %23
store i32 512, i32* %13
%55 = load i32, i32* %13
%56 = srem i32 %55, 2
store i32 %56, i32* %14
%57 = load i32, i32* %14
%58 = icmp eq i32 %57, 0
br i1 %58, label %59, label %60
59: ; preds = %54
store i32 2, i32* %14
br label %60
60: ; preds = %59, %54
store i32 0, i32* %11
br label %61
61: ; preds = %151, %60
%62 = load i32, i32* %11
%63 = load i32, i32* %13
%64 = add nsw i32 %63, 1
%65 = icmp slt i32 %62, %64
br i1 %65, label %66, label %154
66: ; preds = %61
%67 = load i32, i32* %11
%68 = load i32, i32* %13
%69 = icmp slt i32 %67, %68
%70 = zext i1 %69 to i32
store i32 %70, i32* %15
%71 = load i32, i32* %11
%72 = icmp sgt i32 %71, 0
%73 = zext i1 %72 to i32
store i32 %73, i32* %16
%74 = load i32, i32* %11
%75 = load i32, i32* %13
%76 = sub nsw i32 %75, 1
%77 = icmp eq i32 %74, %76
br i1 %77, label %78, label %80
78: ; preds = %66
%79 = load i32, i32* %14
br label %81
80: ; preds = %66
br label %81
81: ; preds = %80, %78
%82 = phi i32 [ %79, %78 ], [ 2, %80 ]
store i32 %82, i32* %17
%83 = load i32, i32* %11
%84 = load i32, i32* %13
%85 = icmp eq i32 %83, %84
br i1 %85, label %86, label %88
86: ; preds = %81
%87 = load i32, i32* %14
br label %89
88: ; preds = %81
br label %89
89: ; preds = %88, %86
%90 = phi i32 [ %87, %86 ], [ 2, %88 ]
store i32 %90, i32* %18
%91 = load i32, i32* %11
%92 = srem i32 %91, 2
%93 = icmp eq i32 %92, 0
br i1 %93, label %94, label %122
94: ; preds = %89
%95 = load i32, i32* %15
%96 = getelementptr inbounds [2 x [1024 x double]], [2 x [1024 x double]]* %8, i64 0, i64 0
%97 = bitcast [1024 x double]* %96 to double**
%98 = load double*, double** %4
%99 = load i32, i32* %11
%100 = mul nsw i32 %99, 1024
%101 = mul nsw i32 %100, 2
%102 = sext i32 %101 to i64
%103 = getelementptr inbounds double, double* %98, i64 %102
%104 = load i32, i32* %17
%105 = call i32 @load(i32 %95, double** %97, double* %103, i32 %104)
%106 = load i32, i32* %16
%107 = getelementptr inbounds [2 x [1024 x double]], [2 x [1024 x double]]* %9, i64 0, i64 0
%108 = bitcast [1024 x double]* %107 to double**
%109 = getelementptr inbounds [1024 x [32 x double]], [1024 x [32 x double]]* %7, i64 0, i64 0
%110 = bitcast [32 x double]* %109 to double**
%111 = load double*, double** %6
%112 = load i32, i32* %11
%113 = sub nsw i32 %112, 1
%114 = mul nsw i32 %113, 1024
%115 = sext i32 %114 to i64
%116 = getelementptr inbounds double, double* %111, i64 %115
%117 = load i32, i32* %10
%118 = sext i32 %117 to i64
%119 = getelementptr inbounds double, double* %116, i64 %118
%120 = load i32, i32* %18
%121 = call i32 @compute(i32 %106, double** %108, double** %110, double* %119, i32 %120)
br label %150
122: ; preds = %89
%123 = load i32, i32* %15
%124 = getelementptr inbounds [2 x [1024 x double]], [2 x [1024 x double]]* %9, i64 0, i64 0
%125 = bitcast [1024 x double]* %124 to double**
%126 = load double*, double** %4
%127 = load i32, i32* %11
%128 = mul nsw i32 %127, 1024
%129 = mul nsw i32 %128, 2
%130 = sext i32 %129 to i64
%131 = getelementptr inbounds double, double* %126, i64 %130
%132 = load i32, i32* %17
%133 = call i32 @load(i32 %123, double** %125, double* %131, i32 %132)
%134 = load i32, i32* %16
%135 = getelementptr inbounds [2 x [1024 x double]], [2 x [1024 x double]]* %8, i64 0, i64 0
%136 = bitcast [1024 x double]* %135 to double**
%137 = getelementptr inbounds [1024 x [32 x double]], [1024 x [32 x double]]* %7, i64 0, i64 0
%138 = bitcast [32 x double]* %137 to double**
%139 = load double*, double** %6
%140 = load i32, i32* %11
%141 = sub nsw i32 %140, 1
%142 = mul nsw i32 %141, 1024
%143 = sext i32 %142 to i64
%144 = getelementptr inbounds double, double* %139, i64 %143
%145 = load i32, i32* %10
%146 = sext i32 %145 to i64
%147 = getelementptr inbounds double, double* %144, i64 %146
%148 = load i32, i32* %18
%149 = call i32 @compute(i32 %134, double** %136, double** %138, double* %147, i32 %148)
br label %150
150: ; preds = %122, %94
br label %151
151: ; preds = %150
%152 = load i32, i32* %11
%153 = add nsw i32 %152, 1
store i32 %153, i32* %11
br label %61
154: ; preds = %61
br label %155
155: ; preds = %154
%156 = load i32, i32* %10
%157 = add nsw i32 %156, 32
store i32 %157, i32* %10
br label %19
158: ; preds = %19
ret void
}

LLVM IR (-O2):
define void @workload(double* %0, double* nocapture %1, double* %2) {
%4 = alloca [1024 x [32 x double]]
%5 = alloca [2 x [1024 x double]]
%6 = alloca [2 x [1024 x double]]
%7 = bitcast [1024 x [32 x double]]* %4 to i8*
%8 = bitcast [2 x [1024 x double]]* %5 to i8*
%9 = bitcast [2 x [1024 x double]]* %6 to i8*
%10 = bitcast [2 x [1024 x double]]* %6 to double**
%11 = bitcast [2 x [1024 x double]]* %5 to double**
%12 = bitcast [1024 x [32 x double]]* %4 to double**
br label %13
13: ; preds = %3, %63
%14 = phi i64 [ 0, %3 ], [ %64, %63 ]
%15 = phi i64 [ 0, %3 ], [ %65, %63 ]
%16 = shl nuw nsw i64 %15, 5
br label %20
17: ; preds = %20
%18 = getelementptr inbounds double, double* %2, i64 %14
%19 = getelementptr inbounds double, double* %2, i64 %14
br label %37
20: ; preds = %20, %13
%21 = phi i64 [ 0, %13 ], [ %35, %20 ]
%22 = getelementptr [1024 x [32 x double]], [1024 x [32 x double]]* %4, i64 0, i64 %21, i64 0
%23 = bitcast double* %22 to i8*
%24 = shl nuw nsw i64 %21, 10
%25 = add nuw nsw i64 %16, %24
%26 = getelementptr double, double* %1, i64 %25
%27 = bitcast double* %26 to i8*
%28 = or i64 %21, 1
%29 = getelementptr [1024 x [32 x double]], [1024 x [32 x double]]* %4, i64 0, i64 %28, i64 0
%30 = bitcast double* %29 to i8*
%31 = shl nuw nsw i64 %28, 10
%32 = add nuw nsw i64 %16, %31
%33 = getelementptr double, double* %1, i64 %32
%34 = bitcast double* %33 to i8*
%35 = add nuw nsw i64 %21, 2
%36 = icmp eq i64 %35, 1024
br i1 %36, label %17, label %20
37: ; preds = %17, %60
%38 = phi i64 [ 0, %17 ], [ %61, %60 ]
%39 = icmp ne i64 %38, 512
%40 = zext i1 %39 to i32
%41 = icmp ne i64 %38, 0
%42 = zext i1 %41 to i32
%43 = and i64 %38, 1
%44 = icmp eq i64 %43, 0
%45 = shl nuw nsw i64 %38, 11
%46 = getelementptr inbounds double, double* %0, i64 %45
br i1 %44, label %47, label %53
47: ; preds = %37
%48 = call i32 @load(i32 %40, double** %11, double* %46, i32 2)
%49 = shl nuw nsw i64 %38, 10
%50 = add nsw i64 %49, -1024
%51 = getelementptr inbounds double, double* %19, i64 %50
%52 = call i32 @compute(i32 %42, double** %10, double** %12, double* %51, i32 2)
br label %60
53: ; preds = %37
%54 = call i32 @load(i32 %40, double** %10, double* %46, i32 2)
%55 = shl i64 %38, 10
%56 = add i64 %55, 4294966272
%57 = and i64 %56, 4294966272
%58 = getelementptr inbounds double, double* %18, i64 %57
%59 = call i32 @compute(i32 %42, double** %11, double** %12, double* %58, i32 2)
br label %60
60: ; preds = %53, %47
%61 = add nuw nsw i64 %38, 1
%62 = icmp eq i64 %61, 513
br i1 %62, label %63, label %37
63: ; preds = %60
%64 = add nuw nsw i64 %14, 32
%65 = add nuw nsw i64 %15, 1
%66 = icmp eq i64 %65, 32
br i1 %66, label %67, label %13
67: ; preds = %63
ret void
}