// File: /workspace/github_c_makefile_star2_O3/baileywjohnson[P]mpi-matrix-mult/MyMPI.c
// Function: read_checkerboard_matrix
void read_checkerboard_matrix (
   char *s,              /* IN - File name */
   void ***subs,         /* OUT - 2D array */
   void **storage,       /* OUT - Array elements */
   MPI_Datatype dtype,   /* IN - Element type */
   int *m,               /* OUT - Array rows */
   int *n,               /* OUT - Array cols */
   MPI_Comm grid_comm)   /* IN - Communicator */
{
   void      *buffer;         /* File buffer */
   int        coords[2];      /* Coords of proc receiving
                                 next row of matrix */
   int        datum_size;     /* Bytes per elements */
   int        dest_id;        /* Rank of receiving proc */
   int        grid_coord[2];  /* Process coords */
   int        grid_id;        /* Process rank */
   int        grid_period[2]; /* Wraparound */
   int        grid_size[2];   /* Dimensions of grid */
   int        i, j, k;
   FILE      *infileptr;      /* Input file pointer */
   void      *laddr;          /* Used when proc 0 gets row */
   int        local_cols;     /* Matrix cols on this proc */
   int        local_rows;     /* Matrix rows on this proc */
   void     **lptr;           /* Pointer into 'subs' */
   int        p;              /* Number of processes */
   void      *raddr;          /* Address of first element
                                 to send */
   void      *rptr;           /* Pointer into 'storage' */
   MPI_Status status;         /* Results of read */

   MPI_Comm_rank (grid_comm, &grid_id);
   MPI_Comm_size (grid_comm, &p);
   datum_size = get_size (dtype);

   /* Process 0 opens file, gets number of rows and
      number of cols, and broadcasts this information
      to the other processes. */

   if (grid_id == 0) {
      infileptr = fopen (s, "r");
      if (infileptr == NULL) *m = 0;
      else {
         fread (m, sizeof(int), 1, infileptr);
         fread (n, sizeof(int), 1, infileptr);
      }
   }
   MPI_Bcast (m, 1, MPI_INT, 0, grid_comm);

   if (!(*m)) MPI_Abort (MPI_COMM_WORLD, OPEN_FILE_ERROR);

   MPI_Bcast (n, 1, MPI_INT, 0, grid_comm);

   /* Each process determines the size of the submatrix
      it is responsible for. */

   MPI_Cart_get (grid_comm, 2, grid_size, grid_period,
      grid_coord);
   local_rows = BLOCK_SIZE(grid_coord[0],grid_size[0],*m);
   local_cols = BLOCK_SIZE(grid_coord[1],grid_size[1],*n);

   /* Dynamically allocate two-dimensional matrix 'subs' */

   *storage = my_malloc (grid_id,
      local_rows * local_cols * datum_size);
   *subs = (void **) my_malloc (grid_id,local_rows*PTR_SIZE);
   lptr = (void *) *subs;
   rptr = (void *) *storage;
   for (i = 0; i < local_rows; i++) {
      *(lptr++) = (void *) rptr;
      rptr += local_cols * datum_size;
   }

   /* Grid process 0 reads in the matrix one row at a time
      and distributes each row among the MPI processes. */

   if (grid_id == 0)
      buffer = my_malloc (grid_id, *n * datum_size);

   /* For each row of processes in the process grid... */
   for (i = 0; i < grid_size[0]; i++) {
      coords[0] = i;

      /* For each matrix row controlled by this proc row...*/
      for (j = 0; j < BLOCK_SIZE(i,grid_size[0],*m); j++) {

         /* Read in a row of the matrix */

         if (grid_id == 0) {
            fread (buffer, datum_size, *n, infileptr);
         }

         /* Distribute it among process in the grid row */

         for (k = 0; k < grid_size[1]; k++) {
            coords[1] = k;

            /* Find address of first element to send */
            raddr = buffer +
               BLOCK_LOW(k,grid_size[1],*n) * datum_size;

            /* Determine the grid ID of the process getting
               the subrow */
            MPI_Cart_rank (grid_comm, coords, &dest_id);

            /* Process 0 is responsible for sending...*/
            if (grid_id == 0) {

               /* It is sending (copying) to itself */
               if (dest_id == 0) {
                  laddr = (*subs)[j];
                  memcpy (laddr, raddr,
                     local_cols * datum_size);

               /* It is sending to another process */
               } else {
                  MPI_Send (raddr,
                     BLOCK_SIZE(k,grid_size[1],*n), dtype,
                  dest_id, 0, grid_comm);
               }

            /* Process 'dest_id' is responsible for
               receiving... */
            } else if (grid_id == dest_id) {
               MPI_Recv ((*subs)[j], local_cols, dtype, 0,
                  0, grid_comm,&status);
            }
         }
      }
   }
   if (grid_id == 0) free (buffer);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %r9, %rbx
movq %r8, %r13
movq %rcx, %rbp
movq %rdx, 0x18(%rsp)
movq %rsi, 0x28(%rsp)
movq %rdi, %r12
movq 0xe0(%rsp), %r14
leaq 0x10(%rsp), %r15
movq %r14, %rdi
movq %r15, %rsi
callq 0x1170
leaq 0x7c(%rsp), %rsi
movq %r14, %rdi
callq 0x1100
movq %rbp, 0x40(%rsp)
movq %rbp, %rdi
callq 0x1b80
movl %eax, 0x14(%rsp)
cmpl $0x0, (%r15)
jne 0x1f11
leaq 0x22b3(%rip), %rsi      # 0x4172
movq %r12, %rdi
callq 0x10c0
testq %rax, %rax
je 0x1f00
movq %rax, %r15
movl $0x4, %esi
movl $0x1, %edx
movq %r13, %rdi
movq %rax, %rcx
callq 0x1160
movl $0x4, %esi
movl $0x1, %edx
movq %rbx, %rdi
movq %r15, 0x38(%rsp)
movq %r15, %rcx
callq 0x1160
jmp 0x1f11
movl $0x0, (%r13)
movq $0x0, 0x38(%rsp)
movq 0x4090(%rip), %rdx      # 0x5fa8
movq %r13, %rdi
movl $0x1, %esi
xorl %ecx, %ecx
movq %r14, %r8
callq 0x1180
cmpl $0x0, (%r13)
movq %r14, %rbp
jne 0x1f45
movq 0x409d(%rip), %rdi      # 0x5fd8
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x1120
movq 0x405c(%rip), %rdx      # 0x5fa8
movq %rbx, %rdi
movl $0x1, %esi
xorl %ecx, %ecx
movq %rbp, %r8
callq 0x1180
leaq 0x20(%rsp), %r15
leaq 0x80(%rsp), %rcx
leaq 0x88(%rsp), %r12
movq %rbp, %r14
movq %rbp, %rdi
movl $0x2, %esi
movq %r15, %rdx
movq %r12, %r8
callq 0x1110
movl (%r12), %r8d
movl 0x4(%r12), %esi
leal 0x1(%r8), %eax
movl (%r13), %ecx
imull %ecx, %eax
movl (%r15), %r9d
movl 0x4(%r15), %edi
cltd
idivl %r9d
movl %eax, %r12d
imull %r8d, %ecx
movl %ecx, %eax
cltd
idivl %r9d
subl %eax, %r12d
leal 0x1(%rsi), %eax
movl (%rbx), %ecx
imull %ecx, %eax
cltd
idivl %edi
movl %eax, %ebp
imull %esi, %ecx
movl %ecx, %eax
cltd
idivl %edi
subl %eax, %ebp
movl 0x10(%rsp), %edi
movl %ebp, 0x30(%rsp)
imull 0x14(%rsp), %ebp
movl %ebp, %esi
imull %r12d, %esi
callq 0x1bf2
movq 0x18(%rsp), %r15
movq %rax, (%r15)
movl 0x10(%rsp), %edi
leal (,%r12,8), %esi
callq 0x1bf2
movq 0x28(%rsp), %rcx
movq %rax, (%rcx)
movslq %ebp, %rdi
testl %r12d, %r12d
jle 0x2026
movq (%r15), %rcx
movl %r12d, %edx
xorl %esi, %esi
movq %rcx, (%rax,%rsi,8)
addq %rdi, %rcx
incq %rsi
cmpl %esi, %edx
jne 0x2018
movq %rdi, 0x70(%rsp)
cmpl $0x0, 0x10(%rsp)
jne 0x2045
movl (%rbx), %esi
imull 0x14(%rsp), %esi
xorl %edi, %edi
callq 0x1bf2
movq %rax, 0x18(%rsp)
movl 0x20(%rsp), %esi
testl %esi, %esi
jle 0x21e7
movslq 0x14(%rsp), %rax
movq %rax, 0x50(%rsp)
movl (%r13), %edi
xorl %r8d, %r8d
leaq 0x34(%rsp), %r12
movq %r13, 0x58(%rsp)
movl %r8d, %r9d
movl %r8d, 0x48(%rsp)
leal 0x1(%r9), %r8d
movl %edi, %eax
imull %r8d, %eax
cltd
idivl %esi
movl %eax, %ecx
movl %edi, %eax
movq %r9, 0x68(%rsp)
imull %r9d, %eax
cltd
idivl %esi
subl %eax, %ecx
testl %ecx, %ecx
jle 0x21de
xorl %ebp, %ebp
movq %r8, 0x60(%rsp)
cmpl $0x0, 0x10(%rsp)
jne 0x20c0
movslq (%rbx), %rdx
movq 0x18(%rsp), %rdi
movq 0x50(%rsp), %rsi
movq 0x38(%rsp), %rcx
callq 0x1160
movl 0x24(%rsp), %ecx
testl %ecx, %ecx
jle 0x21a6
xorl %r13d, %r13d
movl %r13d, 0x4c(%rsp)
movl (%rbx), %eax
imull %r13d, %eax
cltd
idivl %ecx
movl %eax, %r15d
movq %r14, %rdi
leaq 0x48(%rsp), %rsi
movq %r12, %rdx
callq 0x11d0
movl 0x10(%rsp), %eax
movl 0x34(%rsp), %ecx
testl %eax, %eax
je 0x2134
cmpl %ecx, %eax
jne 0x2196
movq 0x28(%rsp), %rax
movq (%rax), %rax
movq (%rax,%rbp,8), %rdi
leaq 0x90(%rsp), %rax
movq %rax, (%rsp)
movl 0x30(%rsp), %esi
movq 0x40(%rsp), %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
movq %r14, %r9
callq 0x1140
jmp 0x2196
imull 0x14(%rsp), %r15d
movslq %r15d, %rsi
addq 0x18(%rsp), %rsi
testl %ecx, %ecx
je 0x2180
leal 0x1(%r13), %eax
movl (%rbx), %edi
imull %edi, %eax
movl 0x24(%rsp), %r9d
cltd
idivl %r9d
movl %eax, %r8d
imull %r13d, %edi
movl %edi, %eax
cltd
idivl %r9d
subl %eax, %r8d
movq %rsi, %rdi
movl %r8d, %esi
movq 0x40(%rsp), %rdx
xorl %r8d, %r8d
movq %r14, %r9
callq 0x1040
jmp 0x2196
movq 0x28(%rsp), %rax
movq (%rax), %rax
movq (%rax,%rbp,8), %rdi
movq 0x70(%rsp), %rdx
callq 0x1220
incl %r13d
movl 0x24(%rsp), %ecx
cmpl %ecx, %r13d
jl 0x20cf
incq %rbp
movq 0x58(%rsp), %r13
movl (%r13), %edi
movl %edi, %eax
movq 0x60(%rsp), %r8
imull %r8d, %eax
movl 0x20(%rsp), %esi
cltd
idivl %esi
movl %eax, %ecx
movl %edi, %eax
imull 0x68(%rsp), %eax
cltd
idivl %esi
subl %eax, %ecx
movslq %ecx, %rax
cmpq %rax, %rbp
jl 0x20a2
cmpl %esi, %r8d
jl 0x206c
cmpl $0x0, 0x10(%rsp)
jne 0x21f8
movq 0x18(%rsp), %rdi
callq 0x10f0
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq