// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xe0, %rsp
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq 0x10(%rbp), %rdi
leaq -0x54(%rbp), %rsi
callq 0x1160
movq 0x10(%rbp), %rdi
leaq -0x94(%rbp), %rsi
callq 0x10f0
movq -0x20(%rbp), %rdi
callq 0x1f70
movl %eax, -0x44(%rbp)
cmpl $0x0, -0x54(%rbp)
jne 0x244d
movq -0x8(%rbp), %rdi
leaq 0x1d9d(%rip), %rsi      # 0x419e
callq 0x10b0
movq %rax, -0x78(%rbp)
cmpq $0x0, -0x78(%rbp)
jne 0x241d
movq -0x28(%rbp), %rax
movl $0x0, (%rax)
jmp 0x244b
movq -0x28(%rbp), %rdi
movq -0x78(%rbp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x1150
movq -0x30(%rbp), %rdi
movq -0x78(%rbp), %rcx
movl $0x4, %esi
movl $0x1, %edx
callq 0x1150
jmp 0x244d
movq -0x28(%rbp), %rdi
movq 0x10(%rbp), %r8
movl $0x1, %esi
movq 0x3b47(%rip), %rdx      # 0x5fa8
xorl %ecx, %ecx
callq 0x1170
movq -0x28(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x2482
movq 0x3b60(%rip), %rdi      # 0x5fd8
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x1110
movq -0x30(%rbp), %rdi
movq 0x10(%rbp), %r8
movl $0x1, %esi
movq 0x3b12(%rip), %rdx      # 0x5fa8
xorl %ecx, %ecx
callq 0x1170
movq 0x10(%rbp), %rdi
leaq -0x64(%rbp), %rdx
leaq -0x5c(%rbp), %rcx
leaq -0x50(%rbp), %r8
movl $0x2, %esi
callq 0x1100
movl -0x50(%rbp), %eax
addl $0x1, %eax
movq -0x28(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x64(%rbp)
subl $0x1, %eax
movl %eax, -0xc8(%rbp)
movl -0x50(%rbp), %eax
movq -0x28(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x64(%rbp)
movl %eax, %ecx
movl -0xc8(%rbp), %eax
subl %ecx, %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
movl -0x4c(%rbp), %eax
addl $0x1, %eax
movq -0x30(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x60(%rbp)
subl $0x1, %eax
movl %eax, -0xc4(%rbp)
movl -0x4c(%rbp), %eax
movq -0x30(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x60(%rbp)
movl %eax, %ecx
movl -0xc4(%rbp), %eax
subl %ecx, %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
movl -0x54(%rbp), %edi
movl -0x88(%rbp), %esi
imull -0x84(%rbp), %esi
imull -0x44(%rbp), %esi
callq 0x2020
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movl -0x54(%rbp), %edi
movslq -0x88(%rbp), %rax
shlq $0x3, %rax
movl %eax, %esi
callq 0x2020
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x90(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xa8(%rbp)
movl $0x0, -0x68(%rbp)
movl -0x68(%rbp), %eax
cmpl -0x88(%rbp), %eax
jge 0x25e5
movq -0xa8(%rbp), %rcx
movq -0x90(%rbp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, -0x90(%rbp)
movq %rcx, (%rax)
movl -0x84(%rbp), %ecx
imull -0x44(%rbp), %ecx
movq -0xa8(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x2592
cmpl $0x0, -0x54(%rbp)
jne 0x2601
movl -0x54(%rbp), %edi
movq -0x30(%rbp), %rax
movl (%rax), %esi
imull -0x44(%rbp), %esi
callq 0x2020
movq %rax, -0x38(%rbp)
movl $0x0, -0x68(%rbp)
movl -0x68(%rbp), %eax
cmpl -0x64(%rbp), %eax
jge 0x27ce
movl -0x68(%rbp), %eax
movl %eax, -0x40(%rbp)
movl $0x0, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
movl %eax, -0xcc(%rbp)
movl -0x68(%rbp), %eax
addl $0x1, %eax
movq -0x28(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x64(%rbp)
movl %eax, %ecx
subl $0x1, %ecx
movl -0x68(%rbp), %eax
movq -0x28(%rbp), %rdx
imull (%rdx), %eax
cltd
idivl -0x64(%rbp)
movl %eax, %edx
movl -0xcc(%rbp), %eax
subl %edx, %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x27be
cmpl $0x0, -0x54(%rbp)
jne 0x2681
movq -0x38(%rbp), %rdi
movslq -0x44(%rbp), %rsi
movq -0x30(%rbp), %rax
movslq (%rax), %rdx
movq -0x78(%rbp), %rcx
callq 0x1150
movl $0x0, -0x70(%rbp)
movl -0x70(%rbp), %eax
cmpl -0x60(%rbp), %eax
jge 0x27ae
movl -0x70(%rbp), %eax
movl %eax, -0x3c(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0xd8(%rbp)
movl -0x70(%rbp), %eax
movq -0x30(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x60(%rbp)
movl %eax, %ecx
movq -0xd8(%rbp), %rax
imull -0x44(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0xa0(%rbp)
movq 0x10(%rbp), %rdi
leaq -0x40(%rbp), %rsi
leaq -0x48(%rbp), %rdx
callq 0x11c0
cmpl $0x0, -0x54(%rbp)
jne 0x2761
cmpl $0x0, -0x48(%rbp)
jne 0x271c
movq -0x10(%rbp), %rax
movq (%rax), %rax
movslq -0x6c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rdi
movq -0xa0(%rbp), %rsi
movl -0x84(%rbp), %eax
imull -0x44(%rbp), %eax
movslq %eax, %rdx
callq 0x1210
jmp 0x275f
movq -0xa0(%rbp), %rdi
movl -0x70(%rbp), %eax
addl $0x1, %eax
movq -0x30(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x60(%rbp)
movl %eax, %esi
subl $0x1, %esi
movl -0x70(%rbp), %eax
movq -0x30(%rbp), %rcx
imull (%rcx), %eax
cltd
idivl -0x60(%rbp)
subl %eax, %esi
addl $0x1, %esi
movq -0x20(%rbp), %rdx
movl -0x48(%rbp), %ecx
movq 0x10(%rbp), %r9
xorl %r8d, %r8d
callq 0x1040
jmp 0x279e
movl -0x54(%rbp), %eax
cmpl -0x48(%rbp), %eax
jne 0x279c
movq -0x10(%rbp), %rax
movq (%rax), %rax
movslq -0x6c(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
movl -0x84(%rbp), %esi
movq -0x20(%rbp), %rdx
movq 0x10(%rbp), %r9
xorl %r8d, %r8d
leaq -0xc0(%rbp), %rax
movl %r8d, %ecx
movq %rax, (%rsp)
callq 0x1130
jmp 0x279e
jmp 0x27a0
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x2688
jmp 0x27b0
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x2621
jmp 0x27c0
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x2608
cmpl $0x0, -0x54(%rbp)
jne 0x27dd
movq -0x38(%rbp), %rdi
callq 0x10e0
addq $0xe0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)