repo: sharvil/flingfd

decompiled_code:
int __fastcall flingfd_send(__int64 a1, int a2)
{
int result; // eax
_DWORD *v3; // rax
struct sockaddr v4[6]; // [rsp+0h] [rbp-F8h] BYREF
char v5; // [rsp+6Dh] [rbp-8Bh]
char v6[32]; // [rsp+70h] [rbp-88h] BYREF
__int64 v7; // [rsp+90h] [rbp-68h] BYREF
struct msghdr message; // [rsp+A0h] [rbp-58h] BYREF

if ( !a1 || a2 == -1 )
{
*_errno_location() = 22;
return -1;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v4[0].sa_family = 1;
strncpy(v4[0].sa_data, *(const char **)(a1 + 8), 0x6BuLL);
v5 = 0;
result = connect(*(_DWORD *)a1, v4, 0x6Eu);
if ( result == -1 )
return result;
*(_BYTE *)(a1 + 16) = 1;
}
flingfd_init_msg_((__int64)&message, &v7, (__int64)v6, 24LL);
v3 = 0LL;
if ( message.msg_controllen > 0xF )
v3 = message.msg_control;
v3[2] = 1;
v3[3] = 1;
*(_QWORD *)v3 = 20LL;
v3[4] = a2;
return sendmsg(*(_DWORD *)a1, &message, 0);
}

canonical_decompiled_code:
int __fastcall func1(__int64 a1, int a2)
{
int result; // eax
_DWORD *v3; // rax
struct sockaddr v4[6]; // [rsp+0h] [rbp-F8h] BYREF
char v5; // [rsp+6Dh] [rbp-8Bh]
char v6[32]; // [rsp+70h] [rbp-88h] BYREF
__int64 v7; // [rsp+90h] [rbp-68h] BYREF
struct msghdr message; // [rsp+A0h] [rbp-58h] BYREF

if ( !a1 || a2 == -1 )
{
*_errno_location() = 22;
return -1;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v4[0].sa_family = 1;
strncpy(v4[0].sa_data, *(const char **)(a1 + 8), 0x6BuLL);
v5 = 0;
result = connect(*(_DWORD *)a1, v4, 0x6Eu);
if ( result == -1 )
return result;
*(_BYTE *)(a1 + 16) = 1;
}
func0((__int64)&message, &v7, (__int64)v6, 24LL);
v3 = 0LL;
if ( message.msg_controllen > 0xF )
v3 = message.msg_control;
v3[2] = 1;
v3[3] = 1;
*(_QWORD *)v3 = 20LL;
v3[4] = a2;
return sendmsg(*(_DWORD *)a1, &message, 0);
}

original_code:
int flingfd_send(flingfd_t *handle, int fd) {
  if (!handle || fd == -1) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    if (connect(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[((((sizeof(int)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0);
  header->cmsg_level = 1;
  header->cmsg_type = SCM_RIGHTS;
  header->cmsg_len = ((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (sizeof(int)));
  *(int *)((header)->__cmsg_data) = fd;
  return sendmsg(handle->fd, &msg, 0);
}

canonical_original_code:
int flingfd_send(struct flingfd_t *handle, int fd) {
  if (!handle || fd == -1) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    if (connect(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[-1];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0);
  header->cmsg_level = 1;
  header->cmsg_type = SCM_RIGHTS;
  header->cmsg_len = ((((sizeof (struct cmsghdr)) + sizeof (unsigned long) - 1) & (unsigned long) ~(sizeof (unsigned long) - 1)) + (sizeof(int)));
  *(int *)((header)->__cmsg_data) = fd;
  return sendmsg(handle->fd, &msg, 0);
}

variable_types: struct flingfd_t { int fd; char *path; _Bool is_bound; } *

variable_types: fd int

variable_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

variable_types: struct msghdr { void *msg_name; unsigned int msg_namelen; struct iovec { void *iov_base; unsigned long iov_len; } *msg_iov; unsigned long msg_iovlen; void *msg_control; unsigned long msg_controllen; int msg_flags; }

variable_types:
buf
char [-1]

variable_types: struct cmsghdr { unsigned long cmsg_len; int cmsg_level; int cmsg_type; unsigned char __cmsg_data[]; } *

user_defined_types: struct msghdr { void *msg_name; unsigned int msg_namelen; struct iovec *msg_iov; unsigned long msg_iovlen; void *msg_control; unsigned long msg_controllen; int msg_flags; }

user_defined_types: struct sockaddr { unsigned short sa_family; char sa_data[14]; }


decompiled_code:
bool __fastcall flingfd_socket_send(int a1, int a2)
{
int v3; // [rsp+0h] [rbp-28h] BYREF
__int64 v4; // [rsp+8h] [rbp-20h]
char v5; // [rsp+10h] [rbp-18h]

v3 = a1;
v4 = 0LL;
v5 = 1;
return flingfd_send((__int64)&v3, a2) != -1;
}

canonical_decompiled_code:
bool __fastcall func2(int a1, int a2)
{
int v3; // [rsp+0h] [rbp-28h] BYREF
__int64 v4; // [rsp+8h] [rbp-20h]
char v5; // [rsp+10h] [rbp-18h]

v3 = a1;
v4 = 0LL;
v5 = 1;
return func1((__int64)&v3, a2) != -1;
}

original_code:
_Bool flingfd_socket_send(int socket_fd, int fd) {
  flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_send(&handle, fd) != -1;
}

canonical_original_code:
_Bool flingfd_socket_send(int socket_fd, int fd) {
  struct flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_send(&handle, fd) != -1;
}

variable_types: struct flingfd_t { int fd; char *path; _Bool is_bound; }


decompiled_code:
__int64 __fastcall flingfd_recv(__int64 a1)
{
unsigned int v1; // er12
char *v2; // rbx
char v3; // r15
int *v4; // rbp
unsigned __int64 v5; // rax
__int64 v6; // r13
struct sockaddr v8[6]; // [rsp+0h] [rbp-118h] BYREF
char v9; // [rsp+6Dh] [rbp-ABh]
char v10[32]; // [rsp+70h] [rbp-A8h] BYREF
__int64 v11; // [rsp+90h] [rbp-88h] BYREF
struct msghdr message; // [rsp+A0h] [rbp-78h] BYREF

if ( !a1 )
{
*_errno_location() = 22;
return (unsigned int)-1;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v8[0].sa_family = 1;
strncpy(v8[0].sa_data, *(const char **)(a1 + 8), 0x6BuLL);
v9 = 0;
unlink(v8[0].sa_data);
v1 = bind(*(_DWORD *)a1, v8, 0x6Eu);
if ( v1 == -1 )
return v1;
*(_BYTE *)(a1 + 16) = 1;
}
flingfd_init_msg_((__int64)&message, &v11, (__int64)v10, 24LL);
if ( recvmsg(*(_DWORD *)a1, &message, 0) == -1 )
return (unsigned int)-1;
if ( message.msg_controllen <= 0xF )
goto LABEL_22;
v2 = (char *)message.msg_control;
if ( !message.msg_control )
goto LABEL_22;
v3 = 0;
v1 = -1;
do
{
if ( *((_QWORD *)v2 + 1) == 0x100000001LL )
{
v5 = (unsigned __int64)(*(_QWORD *)v2 - 16LL) >> 2;
if ( (int)v5 > 0 )
{
v4 = (int *)(v2 + 16);
v6 = (__int64)&v2[4 * (unsigned int)(v5 - 1) + 20];
do
{
if ( v1 == -1 )
{
v1 = *v4;
}
else
{
close(*v4);
v3 = 1;
}
++v4;
}
while ( (int *)v6 != v4 );
}
}
v2 = (char *)_cmsg_nxthdr(&message, (struct cmsghdr *)v2);
}
while ( v2 );
if ( v3 )
{
close(v1);
*_errno_location() = 74;
return (unsigned int)-1;
}
if ( v1 == -1 )
{
LABEL_22:
*_errno_location() = 2;
v1 = -1;
}
return v1;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
unsigned int v1; // er12
char *v2; // rbx
char v3; // r15
int *v4; // rbp
unsigned __int64 v5; // rax
__int64 v6; // r13
struct sockaddr v8[6]; // [rsp+0h] [rbp-118h] BYREF
char v9; // [rsp+6Dh] [rbp-ABh]
char v10[32]; // [rsp+70h] [rbp-A8h] BYREF
__int64 v11; // [rsp+90h] [rbp-88h] BYREF
struct msghdr message; // [rsp+A0h] [rbp-78h] BYREF

if ( !a1 )
{
*_errno_location() = 22;
return (unsigned int)-1;
}
if ( !*(_BYTE *)(a1 + 16) )
{
v8[0].sa_family = 1;
strncpy(v8[0].sa_data, *(const char **)(a1 + 8), 0x6BuLL);
v9 = 0;
unlink(v8[0].sa_data);
v1 = bind(*(_DWORD *)a1, v8, 0x6Eu);
if ( v1 == -1 )
return v1;
*(_BYTE *)(a1 + 16) = 1;
}
func0((__int64)&message, &v11, (__int64)v10, 24LL);
if ( recvmsg(*(_DWORD *)a1, &message, 0) == -1 )
return (unsigned int)-1;
if ( message.msg_controllen <= 0xF )
goto LABEL_22;
v2 = (char *)message.msg_control;
if ( !message.msg_control )
goto LABEL_22;
v3 = 0;
v1 = -1;
do
{
if ( *((_QWORD *)v2 + 1) == 0x100000001LL )
{
v5 = (unsigned __int64)(*(_QWORD *)v2 - 16LL) >> 2;
if ( (int)v5 > 0 )
{
v4 = (int *)(v2 + 16);
v6 = (__int64)&v2[4 * (unsigned int)(v5 - 1) + 20];
do
{
if ( v1 == -1 )
{
v1 = *v4;
}
else
{
close(*v4);
v3 = 1;
}
++v4;
}
while ( (int *)v6 != v4 );
}
}
v2 = (char *)_cmsg_nxthdr(&message, (struct cmsghdr *)v2);
}
while ( v2 );
if ( v3 )
{
close(v1);
*_errno_location() = 74;
return (unsigned int)-1;
}
if ( v1 == -1 )
{
LABEL_22:
*_errno_location() = 2;
v1 = -1;
}
return v1;
}

original_code:
int flingfd_recv(flingfd_t *handle) {
  if (!handle) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    unlink(addr.sun_path);
    if (bind(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[((((sizeof(int)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  if (recvmsg(handle->fd, &msg, 0) == -1)
    return -1;
  int found_fd = -1;
  _Bool oh_noes = 0;
  for (struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0); header != ((void *)0); header = __cmsg_nxthdr (&msg, header))
    if (header->cmsg_level == 1 && header->cmsg_type == SCM_RIGHTS) {
      int count = (header->cmsg_len - (((header)->__cmsg_data) - (unsigned char *)header)) / sizeof(int);
      for (int i = 0; i < count; ++i) {
        int fd = ((int *)((header)->__cmsg_data))[i];
        if (found_fd == -1) {
          found_fd = fd;
        } else {
          close(fd);
          oh_noes = 1;
        }
      }
    }
  if (oh_noes) {
    close(found_fd);
    (*__errno_location ()) = 74;
    return -1;
  }
  if (found_fd == -1)
    (*__errno_location ()) = 2;
  return found_fd;
}

canonical_original_code:
int flingfd_recv(struct flingfd_t *handle) {
  if (!handle) {
    (*__errno_location ()) = 22;
    return -1;
  }
  if (!handle->is_bound) {
    struct sockaddr_un addr;
    addr.sun_family = 1;
    strncpy(addr.sun_path, handle->path, sizeof(addr.sun_path));
    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
    unlink(addr.sun_path);
    if (bind(handle->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
      return -1;
    handle->is_bound = 1;
  }
  struct msghdr msg;
  struct iovec iov;
  char buf[-1];
  flingfd_init_msg_(&msg, &iov, buf, sizeof(buf));
  if (recvmsg(handle->fd, &msg, 0) == -1)
    return -1;
  int found_fd = -1;
  _Bool oh_noes = 0;
  for (struct cmsghdr *header = ((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0); header != ((void *)0); header = __cmsg_nxthdr (&msg, header))
    if (header->cmsg_level == 1 && header->cmsg_type == SCM_RIGHTS) {
      int count = (header->cmsg_len - (((header)->__cmsg_data) - (unsigned char *)header)) / sizeof(int);
      for (int i = 0; i < count; ++i) {
        int fd = ((int *)((header)->__cmsg_data))[i];
        if (found_fd == -1) {
          found_fd = fd;
        } else {
          close(fd);
          oh_noes = 1;
        }
      }
    }
  if (oh_noes) {
    close(found_fd);
    (*__errno_location ()) = 74;
    return -1;
  }
  if (found_fd == -1)
    (*__errno_location ()) = 2;
  return found_fd;
}

variable_types: struct iovec { void *iov_base; unsigned long iov_len; }

variable_types: count int

variable_types: i int

return_type: int

user_defined_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

user_defined_types: struct flingfd_t { int fd; char *path; _Bool is_bound; }

user_defined_types: struct cmsghdr { unsigned long cmsg_len; int cmsg_level; int cmsg_type; unsigned char __cmsg_data[]; }


decompiled_code:
__int64 __fastcall flingfd_socket_recv(int a1)
{
int v2; // [rsp+0h] [rbp-28h] BYREF
__int64 v3; // [rsp+8h] [rbp-20h]
char v4; // [rsp+10h] [rbp-18h]

v2 = a1;
v3 = 0LL;
v4 = 1;
return flingfd_recv((__int64)&v2);
}

canonical_decompiled_code:
__int64 __fastcall func4(int a1)
{
int v2; // [rsp+0h] [rbp-28h] BYREF
__int64 v3; // [rsp+8h] [rbp-20h]
char v4; // [rsp+10h] [rbp-18h]

v2 = a1;
v3 = 0LL;
v4 = 1;
return func3((__int64)&v2);
}

original_code:
int flingfd_socket_recv(int socket_fd) {
  flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_recv(&handle);
}

canonical_original_code:
int flingfd_socket_recv(int socket_fd) {
  struct flingfd_t handle;
  handle.fd = socket_fd;
  handle.path = ((void *)0);
  handle.is_bound = 1;
  return flingfd_recv(&handle);
}


decompiled_code:
void __fastcall flingfd_close(void **a1)
{
int *v1; // rax

if ( a1 )
{
v1 = (int *)*a1;
if ( *a1 )
{
if ( *v1 != -1 )
close(*v1);
free(*((void **)*a1 + 1));
free(*a1);
*a1 = 0LL;
}
}
}

original_code:
void flingfd_close(flingfd_t **handle) {
  if (handle == ((void *)0) || *handle == ((void *)0))
    return;
  if ((*handle)->fd != -1)
    close((*handle)->fd);
  free((*handle)->path);
  free(*handle);
  *handle = ((void *)0);
}

canonical_original_code:
void flingfd_close(struct flingfd_t **handle) {
  if (handle == ((void *)0) || *handle == ((void *)0))
    return;
  if ((*handle)->fd != -1)
    close((*handle)->fd);
  free((*handle)->path);
  free(*handle);
  *handle = ((void *)0);
}

variable_types: struct flingfd_t { int fd; char *path; _Bool is_bound; } **

return_type: void


decompiled_code:
__int64 __fastcall flingfd_simple_send(char *a1, int a2)
{
_QWORD *v2; // rax
unsigned int v3; // ebp
void *v5; // [rsp+8h] [rbp-20h] BYREF

v2 = flingfd_open(a1);
v5 = v2;
v3 = 0;
if ( v2 )
{
LOBYTE(v3) = flingfd_send((__int64)v2, a2) != -1;
flingfd_close(&v5);
}
return v3;
}

canonical_decompiled_code:
__int64 __fastcall func6(char *a1, int a2)
{
_QWORD *v2; // rax
unsigned int v3; // ebp
void *v5; // [rsp+8h] [rbp-20h] BYREF

v2 = flingfd_open(a1);
v5 = v2;
v3 = 0;
if ( v2 )
{
LOBYTE(v3) = func1((__int64)v2, a2) != -1;
func5(&v5);
}
return v3;
}

original_code:
_Bool flingfd_simple_send(const char *path, int fd) {
  flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return 0;
  _Bool success = (flingfd_send(handle, fd) != -1);
  flingfd_close(&handle);
  return success;
}

canonical_original_code:
_Bool flingfd_simple_send(char *path, int fd) {
  struct flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return 0;
  _Bool success = (flingfd_send(handle, fd) != -1);
  flingfd_close(&handle);
  return success;
}

variable_types:
path
char *


decompiled_code:
__int64 __fastcall flingfd_simple_recv(char *a1)
{
_QWORD *v1; // rax
unsigned int v2; // ebx
void *v4; // [rsp+8h] [rbp-10h] BYREF

v1 = flingfd_open(a1);
v4 = v1;
if ( !v1 )
return (unsigned int)-1;
v2 = flingfd_recv((__int64)v1);
flingfd_close(&v4);
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func7(char *a1)
{
_QWORD *v1; // rax
unsigned int v2; // ebx
void *v4; // [rsp+8h] [rbp-10h] BYREF

v1 = flingfd_open(a1);
v4 = v1;
if ( !v1 )
return (unsigned int)-1;
v2 = func3((__int64)v1);
func5(&v4);
return v2;
}

original_code:
int flingfd_simple_recv(const char *path) {
  flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return -1;
  int ret = flingfd_recv(handle);
  flingfd_close(&handle);
  return ret;
}

canonical_original_code:
int flingfd_simple_recv(char *path) {
  struct flingfd_t *handle = flingfd_open(path);
  if (!handle)
    return -1;
  int ret = flingfd_recv(handle);
  flingfd_close(&handle);
  return ret;
}

variable_types: ret int


decompiled_code:
__int64 __fastcall is_power_of_two(int a1)
{
return ((a1 & (a1 - 1)) == 0) & (unsigned __int8)(a1 > 0);
}

canonical_decompiled_code:
__int64 __fastcall func7(int a1)
{
return ((a1 & (a1 - 1)) == 0) & (unsigned __int8)(a1 > 0);
}

original_code:
static int
is_power_of_two(int val)
{
        return ((((val)&(val-1)) == 0) && (val > 0));
}

variable_types: val int


decompiled_code:
int print_info()
{
puts("**** Runtime parameters ****");
printf("Grid size is: %d x %d\n", (unsigned int)gs_size, (unsigned int)gs_size);
printf("Iterations : %d\n", (unsigned int)gs_iterations);
printf("Tolerance : %f\n", *(double *)&gs_tolerance);
printf("Pad = %d elements\n", (unsigned int)gs_pad);
if ( gsi_is_parallel )
printf("Number of threads : %d\n", (unsigned int)gs_nthreads);
printf("Matrix using %dx%d * sizeof(double) bytes of memory\n", (unsigned int)gs_size, (unsigned int)gs_width);
return puts("*****************************");
}

canonical_decompiled_code:
int func9()
{
puts("**** Runtime parameters ****");
printf("Grid size is: %d x %d\n", (unsigned int)gs_size, (unsigned int)gs_size);
printf("Iterations : %d\n", (unsigned int)gs_iterations);
printf("Tolerance : %f\n", *(double *)&gs_tolerance);
printf("Pad = %d elements\n", (unsigned int)gs_pad);
if ( gsi_is_parallel )
printf("Number of threads : %d\n", (unsigned int)gs_nthreads);
printf("Matrix using %dx%d * sizeof(double) bytes of memory\n", (unsigned int)gs_size, (unsigned int)gs_width);
return puts("*****************************");
}

original_code:
static void
print_info()
{
        printf("****  Runtime parameters ****\n");
        printf("Grid size is: %d x %d\n", gs_size, gs_size);
        printf("Iterations : %d\n", gs_iterations);
        printf("Tolerance : %f\n", gs_tolerance);
        printf("Pad = %d elements\n", gs_pad);
        if (gsi_is_parallel)
                printf("Number of threads : %d\n", gs_nthreads);
        printf("Matrix using %dx%d * sizeof(double) bytes of memory\n",
               gs_size, gs_width);
        printf("*****************************\n");
}


decompiled_code:
int gs_verbose_printf(const char *a1, ...)
{
int result; // eax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

va_start(arg, a1);
result = (int)arg[0].reg_save_area;
if ( gs_verbose )
result = vprintf(a1, arg);
return result;
}

canonical_decompiled_code:
int func10(const char *a1, ...)
{
int result; // eax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

va_start(arg, a1);
result = (int)arg[0].reg_save_area;
if ( gs_verbose )
result = vprintf(a1, arg);
return result;
}

original_code:
void
gs_verbose_printf(const char *fmt, ...)
{
        va_list ap;
        __builtin_va_start(ap,fmt);
        if (gs_verbose)
                vprintf(fmt, ap);
        __builtin_va_end(ap);
}

canonical_original_code:
void gs_verbose_printf(char *fmt, ...)
{
        __builtin_va_list ap;
        __builtin_va_start(ap,fmt);
        if (gs_verbose)
                vprintf(fmt, ap);
        __builtin_va_end(ap);
}

variable_types:
fmt
char *


decompiled_code:
size_t run_gs()
{
double v0; // rbx
_BYTE v2[24]; // [rsp+0h] [rbp-18h] BYREF

gs_verbose_printf("\t**** Initializing... ****\n");
if ( posix_memalign(&gs_matrix, 0x1000uLL, 8LL * gs_width * gs_size) )
{
fwrite("Error: Failed to allocate memory for matrix.\n", 1uLL, 0x2DuLL, stderr);
exit(1);
}
init_matrix();
gsi_init();
gs_verbose_printf("\t**** Running GS... ****\n");
timing_start(v2);
gsi_calculate();
v0 = timing_stop(v2);
if ( gs_output )
write_matrix(gs_output);
gs_verbose_printf("\t**** Cleaning up... ****\n");
gsi_finish();
free(gs_matrix);
fwrite("**** Summary ****\n", 1uLL, 0x12uLL, stdout);
fprintf(stdout, " Execution time: %f s\n", v0);
return fwrite("*****************\n", 1uLL, 0x12uLL, stdout);
}

canonical_decompiled_code:
size_t func13()
{
double v0; // rbx
_BYTE v2[24]; // [rsp+0h] [rbp-18h] BYREF

func10("\t**** Initializing... ****\n");
if ( posix_memalign(&gs_matrix, 0x1000uLL, 8LL * gs_width * gs_size) )
{
fwrite("Error: Failed to allocate memory for matrix.\n", 1uLL, 0x2DuLL, stderr);
exit(1);
}
func11();
func15();
func10("\t**** Running GS... ****\n");
func20(v2);
func17();
v0 = func21(v2);
if ( gs_output )
func12(gs_output);
func10("\t**** Cleaning up... ****\n");
func16();
free(gs_matrix);
fwrite("**** Summary ****\n", 1uLL, 0x12uLL, stdout);
fprintf(stdout, " Execution time: %f s\n", v0);
return fwrite("*****************\n", 1uLL, 0x12uLL, stdout);
}

original_code:
static void
run_gs()
{
        struct timespec ts;
        double exec_time;
        gs_verbose_printf("\t****  Initializing...  ****\n");
                if (posix_memalign((void **)&gs_matrix, 0x1000,
                                   gs_size * gs_width * sizeof(double)) != 0) {
                        fprintf(stderr,
                                "Error: Failed to allocate memory for matrix.\n");
                        exit(1);
                }
                init_matrix();
                gsi_init();
                gs_verbose_printf("\t****  Running GS...  ****\n");
                timing_start(&ts);
                gsi_calculate();
                exec_time = timing_stop(&ts);
                if (gs_output)
                        write_matrix(gs_output);
                gs_verbose_printf("\t****  Cleaning up...  ****\n");
                gsi_finish();
                free(gs_matrix);
                fprintf(stdout,"**** Summary ****\n");
                fprintf(stdout,"   Execution time: %f s\n", exec_time);
                fprintf(stdout,"*****************\n");
        }

variable_types: struct timespec { long tv_sec; long tv_nsec; }


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // er13
int v5; // eax
int v6; // edi
int v7; // eax

v4 = 0;
while ( 1 )
{
v5 = getopt(argc, (char *const *)argv, "vhi:e:s:t:p:o:");
if ( v5 == -1 )
break;
switch ( v5 )
{
case ':':
fprintf(stderr, "%s: option -%c requries an operand\n", *argv, (unsigned int)optopt);
v4 = 1;
break;
case '?':
fprintf(stderr, "%s: illegal option -- %c\n", *argv, (unsigned int)optopt);
v4 = 1;
break;
case 'e':
gs_tolerance = atof(optarg);
break;
case 'h':
usage(stdout, *argv);
exit(0);
case 'i':
gs_iterations = atoi(optarg);
if ( gs_iterations <= 0 )
{
fwrite("Number of iterations must be strictly greater than 1.\n", 1uLL, 0x36uLL, stderr);
v4 = 1;
}
break;
case 'o':
gs_output = fopen(optarg, "w");
if ( !gs_output )
{
perror("Failed to open output");
v4 = 1;
}
break;
case 'p':
gs_pad = atoi(optarg);
if ( gs_pad < 0 )
{
fwrite("Padding must be greater or equal to 0.\n", 1uLL, 0x27uLL, stderr);
v4 = 1;
}
break;
case 's':
v6 = atoi(optarg);
gs_size = v6;
if ( v6 <= 0 )
{
fwrite("Size must be larger than 1.\n", 1uLL, 0x1CuLL, stderr);
v4 = 1;
}
else if ( !(unsigned int)is_power_of_two(v6) )
{
fwrite("Size is not a power of two.\n", 1uLL, 0x1CuLL, stderr);
v4 = 1;
}
break;
case 't':
v7 = atoi(optarg);
gs_nthreads = v7;
if ( gsi_is_parallel )
{
if ( v7 <= 0 )
{
fwrite("Number of threads must be positive.\n", 1uLL, 0x24uLL, stderr);
v4 = 1;
}
else if ( !(unsigned int)is_power_of_two(v7) )
{
fwrite("Number is not a power of two.\n", 1uLL, 0x1EuLL, stderr);
v4 = 1;
}
}
else
{
fwrite("This is the sequential version -- -t doesn't make sense!\n", 1uLL, 0x39uLL, stderr);
v4 = 1;
}
break;
case 'v':
gs_verbose = 1;
break;
default:
abort();
}
}
if ( v4 )
{
usage(stderr, *argv);
exit(1);
}
gs_width = gs_size + gs_pad;
if ( gs_verbose )
print_info();
run_gs();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // er13
int v5; // eax
int v6; // edi
int v7; // eax

v4 = 0;
while ( 1 )
{
v5 = getopt(argc, (char *const *)argv, "vhi:e:s:t:p:o:");
if ( v5 == -1 )
break;
switch ( v5 )
{
case ':':
fprintf(stderr, "%s: option -%c requries an operand\n", *argv, (unsigned int)optopt);
v4 = 1;
break;
case '?':
fprintf(stderr, "%s: illegal option -- %c\n", *argv, (unsigned int)optopt);
v4 = 1;
break;
case 'e':
gs_tolerance = atof(optarg);
break;
case 'h':
func8(stdout, *argv);
exit(0);
case 'i':
gs_iterations = atoi(optarg);
if ( gs_iterations <= 0 )
{
fwrite("Number of iterations must be strictly greater than 1.\n", 1uLL, 0x36uLL, stderr);
v4 = 1;
}
break;
case 'o':
gs_output = fopen(optarg, "w");
if ( !gs_output )
{
perror("Failed to open output");
v4 = 1;
}
break;
case 'p':
gs_pad = atoi(optarg);
if ( gs_pad < 0 )
{
fwrite("Padding must be greater or equal to 0.\n", 1uLL, 0x27uLL, stderr);
v4 = 1;
}
break;
case 's':
v6 = atoi(optarg);
gs_size = v6;
if ( v6 <= 0 )
{
fwrite("Size must be larger than 1.\n", 1uLL, 0x1CuLL, stderr);
v4 = 1;
}
else if ( !(unsigned int)func7(v6) )
{
fwrite("Size is not a power of two.\n", 1uLL, 0x1CuLL, stderr);
v4 = 1;
}
break;
case 't':
v7 = atoi(optarg);
gs_nthreads = v7;
if ( gsi_is_parallel )
{
if ( v7 <= 0 )
{
fwrite("Number of threads must be positive.\n", 1uLL, 0x24uLL, stderr);
v4 = 1;
}
else if ( !(unsigned int)func7(v7) )
{
fwrite("Number is not a power of two.\n", 1uLL, 0x1EuLL, stderr);
v4 = 1;
}
}
else
{
fwrite("This is the sequential version -- -t doesn't make sense!\n", 1uLL, 0x39uLL, stderr);
v4 = 1;
}
break;
case 'v':
gs_verbose = 1;
break;
default:
abort();
}
}
if ( v4 )
{
func8(stderr, *argv);
exit(1);
}
gs_width = gs_size + gs_pad;
if ( gs_verbose )
func9();
func13();
return 0;
}

original_code:
int
                main(int argc, char *argv[])
        {
                int c;
                int errexit = 0;
                extern char *optarg;
                extern int optind, optopt, opterr;
                while ((c = getopt(argc, argv, "vhi:e:s:t:p:o:")) != -1) {
                        switch (c) {
                        case 'v':
                                gs_verbose = 1;
                                break;
                        case 'i':
                                gs_iterations = atoi(optarg);
                                if (gs_iterations <= 0) {
                                        fprintf(stderr,
                                                "Number of iterations must be "
                                                "strictly greater than 1.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'e':
                                gs_tolerance = atof(optarg);
                                break;
                        case 's':
                                gs_size = atoi(optarg);
                                if (gs_size <= 0) {
                                        fprintf(stderr,
                                                "Size must be larger than 1.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_size)) {
                                        fprintf(stderr,
                                                "Size is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 't':
                                gs_nthreads = atoi(optarg);
                                if (!gsi_is_parallel) {
                                        fprintf(stderr,
                                                "This is the sequential version "
                                                "-- -t doesn't make sense!\n");
                                        errexit = 1;
                                } else if (gs_nthreads <= 0) {
                                        fprintf(stderr,
                                                "Number of threads must be "
                                                "positive.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_nthreads)) {
                                        fprintf(stderr,
                                                "Number is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'p':
                                gs_pad = atoi(optarg);
                                if (gs_pad < 0) {
                                        fprintf(stderr,
                                                "Padding must be greater or equal "
                                                "to 0.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'o':
                                gs_output = fopen(optarg, "w");
                                if (!gs_output) {
                                        perror("Failed to open output");
                                        errexit = 1;
                                }
                                break;
                        case 'h':
                                usage(stdout, argv[0]);
                                exit(0);
                        case ':':
                                fprintf(stderr,
                                        "%s: option -%c requries an operand\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        case '?':
                                fprintf(stderr,
                                        "%s: illegal option -- %c\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        default:
                                abort();
                        }
                }
                if (errexit) {
                        usage(stderr, argv[0]);
                        exit(1);
                }
                gs_width = gs_size + gs_pad;
                if (gs_verbose)
                        print_info();
                run_gs();
                return 0;
        }

canonical_original_code:
int main(int argc, char *argv[])
        {
                int c;
                int errexit = 0;
                extern char *optarg;
                extern int optind; extern int optopt; extern int opterr;
                while ((c = getopt(argc, argv, "vhi:e:s:t:p:o:")) != -1) {
                        switch (c) {
                        case 'v':
                                gs_verbose = 1;
                                break;
                        case 'i':
                                gs_iterations = atoi(optarg);
                                if (gs_iterations <= 0) {
                                        fprintf(stderr,
                                                "Number of iterations must be "
                                                "strictly greater than 1.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'e':
                                gs_tolerance = atof(optarg);
                                break;
                        case 's':
                                gs_size = atoi(optarg);
                                if (gs_size <= 0) {
                                        fprintf(stderr,
                                                "Size must be larger than 1.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_size)) {
                                        fprintf(stderr,
                                                "Size is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 't':
                                gs_nthreads = atoi(optarg);
                                if (!gsi_is_parallel) {
                                        fprintf(stderr,
                                                "This is the sequential version "
                                                "-- -t doesn't make sense!\n");
                                        errexit = 1;
                                } else if (gs_nthreads <= 0) {
                                        fprintf(stderr,
                                                "Number of threads must be "
                                                "positive.\n");
                                        errexit = 1;
                                } else if (!is_power_of_two(gs_nthreads)) {
                                        fprintf(stderr,
                                                "Number is not a power of two.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'p':
                                gs_pad = atoi(optarg);
                                if (gs_pad < 0) {
                                        fprintf(stderr,
                                                "Padding must be greater or equal "
                                                "to 0.\n");
                                        errexit = 1;
                                }
                                break;
                        case 'o':
                                gs_output = fopen(optarg, "w");
                                if (!gs_output) {
                                        perror("Failed to open output");
                                        errexit = 1;
                                }
                                break;
                        case 'h':
                                usage(stdout, argv[0]);
                                exit(0);
                        case ':':
                                fprintf(stderr,
                                        "%s: option -%c requries an operand\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        case '?':
                                fprintf(stderr,
                                        "%s: illegal option -- %c\n",
                                        argv[0], optopt);
                                errexit = 1;
                                break;
                        default:
                                abort();
                        }
                }
                if (errexit) {
                        usage(stderr, argv[0]);
                        exit(1);
                }
                gs_width = gs_size + gs_pad;
                if (gs_verbose)
                        print_info();
                run_gs();
                return 0;
        }

variable_types: argc int

variable_types:
argv
char *[]

variable_types: c int

variable_types: errexit int

variable_types:
optarg
char *

variable_types: optind int

variable_types: optopt int

variable_types: opterr int


decompiled_code:
int __fastcall monotonic_time(struct timespec *tp)
{
int result; // eax

result = clock_gettime(1, tp);
if ( result )
{
perror("clock_gettime failed");
abort();
}
return result;
}

canonical_decompiled_code:
int __fastcall func0(struct timespec *tp)
{
int result; // eax

result = clock_gettime(1, tp);
if ( result )
{
perror("clock_gettime failed");
abort();
}
return result;
}

original_code:
static void
monotonic_time(struct timespec *ts)
{
        if (clock_gettime(1, ts) != 0) {
                perror("clock_gettime failed");
                abort();
        }
}

variable_types: struct timespec { long tv_sec; long tv_nsec; } *


decompiled_code:
double __fastcall time_diff(_QWORD *a1, _QWORD *a2)
{
if ( *a2 <= *a1 && (*a2 != *a1 || a2[1] < a1[1]) )
_assert_fail(
"ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)",
"lab2.c",
0x4Fu,
"time_diff");
return (double)(*((_DWORD *)a2 + 2) - *((_DWORD *)a1 + 2)) * 0.000000001 + (double)(int)(*a2 - *a1);
}

canonical_decompiled_code:
double __fastcall func1(_QWORD *a1, _QWORD *a2)
{
if ( *a2 <= *a1 && (*a2 != *a1 || a2[1] < a1[1]) )
_assert_fail(
"ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)",
"lab2.c",
0x4Fu,
"time_diff");
return (double)(*((_DWORD *)a2 + 2) - *((_DWORD *)a1 + 2)) * 0.000000001 + (double)(int)(*a2 - *a1);
}

original_code:
static double
time_diff(struct timespec *ts_start, struct timespec *ts_stop)
{
        ((ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)) ? (void) (0) : __assert_fail ("ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)", "lab2.c", 79, __extension__ __PRETTY_FUNCTION__));
        return ts_stop->tv_sec - ts_start->tv_sec +
                (ts_stop->tv_nsec - ts_start->tv_nsec) * 1E-9;
}

return_type: double

user_defined_types: struct timespec { long tv_sec; long tv_nsec; }


decompiled_code:
void *__fastcall call_test_impl(void *a1)
{
struct timespec v2; // [rsp+0h] [rbp-28h] BYREF
struct timespec tp; // [rsp+10h] [rbp-18h] BYREF

monotonic_time(&tp);
(*((void (__fastcall **)(_QWORD, _QWORD, int *))a1 + 2))(
*((unsigned int *)a1 + 2),
(unsigned int)iterations,
&shared_data);
monotonic_time(&v2);
*((double *)a1 + 3) = time_diff(&tp, &v2);
return 0LL;
}

canonical_decompiled_code:
void *__fastcall func2(void *a1)
{
struct timespec v2; // [rsp+0h] [rbp-28h] BYREF
struct timespec tp; // [rsp+10h] [rbp-18h] BYREF

func0(&tp);
(*((void (__fastcall **)(_QWORD, _QWORD, int *))a1 + 2))(
*((unsigned int *)a1 + 2),
(unsigned int)iterations,
&shared_data);
func0(&v2);
*((double *)a1 + 3) = func1(&tp, &v2);
return 0LL;
}

original_code:
void *
call_test_impl(void *_conf)
{
        thread_conf_t *conf = (thread_conf_t *)_conf;
        struct timespec ts_start, ts_stop;
        monotonic_time(&ts_start);
        conf->func(conf->thread_id, iterations, &shared_data);
        monotonic_time(&ts_stop);
        conf->run_time = time_diff(&ts_start, &ts_stop);
        return ((void *)0);
}

canonical_original_code:
void *call_test_impl(void *_conf)
{
        struct thread_conf_t *conf = (thread_conf_t *)_conf;
        struct timespec ts_start; struct timespec ts_stop;
        monotonic_time(&ts_start);
        conf->func(conf->thread_id, iterations, &shared_data);
        monotonic_time(&ts_stop);
        conf->run_time = time_diff(&ts_start, &ts_stop);
        return ((void *)0);
}

variable_types: struct thread_conf_t { unsigned long thread; int thread_id; void (*func)(int thread, int iterations, int *data); double run_time; } *

return_type: void *


decompiled_code:
int __fastcall print_stats(__int64 a1)
{
int v1; // er13
double *v2; // rbx
unsigned int v3; // ebp
double v4; // r12

v1 = *((_DWORD *)test_impl + 4);
puts("Statistics:");
if ( v1 <= 0 )
{
v4 = *(double *)&LC4;
}
else
{
v2 = (double *)(a1 + 24);
v3 = 0;
v4 = *(double *)&LC4;
do
{
printf("\tThread %i: %.4f s (%.4e iterations/s)\n", v3, *v2, (double)iterations / *v2);
v4 = v4 + *v2;
++v3;
v2 += 4;
}
while ( v1 != v3 );
}
return printf(
"\tAverage execution time: %.4f s\n\tAvergage iterations/second: %.4e\n",
v4 / (double)v1,
(double)(iterations * v1) / v4);
}

canonical_decompiled_code:
int __fastcall func3(__int64 a1)
{
int v1; // er13
double *v2; // rbx
unsigned int v3; // ebp
double v4; // r12

v1 = *((_DWORD *)test_impl + 4);
puts("Statistics:");
if ( v1 <= 0 )
{
v4 = *(double *)&LC4;
}
else
{
v2 = (double *)(a1 + 24);
v3 = 0;
v4 = *(double *)&LC4;
do
{
printf("\tThread %i: %.4f s (%.4e iterations/s)\n", v3, *v2, (double)iterations / *v2);
v4 = v4 + *v2;
++v3;
v2 += 4;
}
while ( v1 != v3 );
}
return printf(
"\tAverage execution time: %.4f s\n\tAvergage iterations/second: %.4e\n",
v4 / (double)v1,
(double)(iterations * v1) / v4);
}

original_code:
static void
print_stats(thread_conf_t *threads)
{
        double run_time_sum = 0;
        int num_threads = test_impl->num_threads;
        printf("Statistics:\n");
        for (int i = 0; i < num_threads; i++) {
                thread_conf_t *t = &threads[i];
                printf("\tThread %i: %.4f s (%.4e iterations/s)\n",
                       i, t->run_time,
                       iterations / t->run_time);
                run_time_sum += t->run_time;
        }
        printf("\tAverage execution time: %.4f s\n"
               "\tAvergage iterations/second: %.4e\n",
               run_time_sum / num_threads,
               num_threads * iterations / run_time_sum);
}

canonical_original_code:
static void print_stats(struct thread_conf_t *threads)
{
        double run_time_sum = 0;
        int num_threads = test_impl->num_threads;
        printf("Statistics:\n");
        for (int i = 0; i < num_threads; i++) {
                struct thread_conf_t *t = &threads[i];
                printf("\tThread %i: %.4f s (%.4e iterations/s)\n",
                       i, t->run_time,
                       iterations / t->run_time);
                run_time_sum += t->run_time;
        }
        printf("\tAverage execution time: %.4f s\n"
               "\tAvergage iterations/second: %.4e\n",
               run_time_sum / num_threads,
               num_threads * iterations / run_time_sum);
}

variable_types: i int

user_defined_types: struct thread_conf_t { unsigned long thread; int thread_id; void (*func)(int thread, int iterations, int *data); double run_time; }


decompiled_code:
__int64 __fastcall set_cs_impl(char *s2)
{
const char **v1; // rbx
const char ***v2; // rbp
__int64 result; // rax
const char **v4; // rax
void **v5; // rbx
const char *v6; // rdx

if ( !strcmp("help", s2) )
{
puts("Critical section implementations:");
v4 = (const char **)cs_impls;
if ( cs_impls )
{
v5 = &cs_impls;
do
{
v6 = v4[1];
if ( v6 )
printf("\t%s - %s\n", *v4, v6);
else
printf("\t%s\n", *v4);
v4 = (const char **)*++v5;
}
while ( *v5 );
}
exit(0);
}
v1 = (const char **)cs_impls;
v2 = (const char ***)&cs_impls;
if ( cs_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = *++v2;
if ( !*v2 )
goto LABEL_5;
}
cs_impl = v1;
result = 1LL;
}
else
{
LABEL_5:
fwrite(
"Invalid critical section implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x61uLL,
stderr);
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(char *s2)
{
const char **v1; // rbx
const char ***v2; // rbp
__int64 result; // rax
const char **v4; // rax
void **v5; // rbx
const char *v6; // rdx

if ( !strcmp("help", s2) )
{
puts("Critical section implementations:");
v4 = (const char **)cs_impls;
if ( cs_impls )
{
v5 = &cs_impls;
do
{
v6 = v4[1];
if ( v6 )
printf("\t%s - %s\n", *v4, v6);
else
printf("\t%s\n", *v4);
v4 = (const char **)*++v5;
}
while ( *v5 );
}
exit(0);
}
v1 = (const char **)cs_impls;
v2 = (const char ***)&cs_impls;
if ( cs_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = *++v2;
if ( !*v2 )
goto LABEL_5;
}
cs_impl = v1;
result = 1LL;
}
else
{
LABEL_5:
fwrite(
"Invalid critical section implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x61uLL,
stderr);
result = 0LL;
}
return result;
}

original_code:
static int
set_cs_impl(const char *name)
{
        if (!strcmp("help", name)) {
                printf("Critical section implementations:\n");
                for (critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                cs_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid critical section implementation specified, "
                        "use 'help' to list available implementations.\n");
                return 0;
        }
}

canonical_original_code:
static int set_cs_impl(char *name)
{
        if (!strcmp("help", name)) {
                printf("Critical section implementations:\n");
                for (struct critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (struct critical_section_impl_t **impl = cs_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                cs_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid critical section implementation specified, "
                        "use 'help' to list available implementations.\n");
                return 0;
        }
}

variable_types:
name
char *

variable_types: struct critical_section_impl_t { char *name; char *desc; unsigned int max_threads; void (*init)(int num_threads); void (*fini)(); void (*enter)(int thread); void (*exit)(int thread); } **


decompiled_code:
__int64 __fastcall set_test_impl(char *s2)
{
const char **v1; // rbx
const char ***v2; // rbp
__int64 result; // rax
const char **v4; // rax
void **v5; // rbx
const char *v6; // rdx

if ( !strcmp("help", s2) )
{
puts("Test implementations:");
v4 = (const char **)test_impls;
if ( test_impls )
{
v5 = &test_impls;
do
{
v6 = v4[1];
if ( v6 )
printf("\t%s - %s\n", *v4, v6);
else
printf("\t%s\n", *v4);
v4 = (const char **)*++v5;
}
while ( *v5 );
}
exit(0);
}
v1 = (const char **)test_impls;
v2 = (const char ***)&test_impls;
if ( test_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = *++v2;
if ( !*v2 )
goto LABEL_5;
}
test_impl = v1;
result = 1LL;
}
else
{
LABEL_5:
fwrite(
"Invalid test implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x55uLL,
stderr);
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(char *s2)
{
const char **v1; // rbx
const char ***v2; // rbp
__int64 result; // rax
const char **v4; // rax
void **v5; // rbx
const char *v6; // rdx

if ( !strcmp("help", s2) )
{
puts("Test implementations:");
v4 = (const char **)test_impls;
if ( test_impls )
{
v5 = &test_impls;
do
{
v6 = v4[1];
if ( v6 )
printf("\t%s - %s\n", *v4, v6);
else
printf("\t%s\n", *v4);
v4 = (const char **)*++v5;
}
while ( *v5 );
}
exit(0);
}
v1 = (const char **)test_impls;
v2 = (const char ***)&test_impls;
if ( test_impls )
{
while ( strcmp(*v1, s2) )
{
v1 = *++v2;
if ( !*v2 )
goto LABEL_5;
}
test_impl = v1;
result = 1LL;
}
else
{
LABEL_5:
fwrite(
"Invalid test implementation specified, use 'help' to list available implementations.\n",
1uLL,
0x55uLL,
stderr);
result = 0LL;
}
return result;
}

original_code:
static int
set_test_impl(const char *name)
{
        if (!strcmp("help", name)) {
                printf("Test implementations:\n");
                for (test_impl_t **impl = test_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (test_impl_t **impl = test_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                test_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid test implementation specified, use 'help' "
                        "to list available implementations.\n");
                return 0;
        }
}

canonical_original_code:
static int set_test_impl(char *name)
{
        if (!strcmp("help", name)) {
                printf("Test implementations:\n");
                for (struct test_impl_t **impl = test_impls; *impl; impl++) {
                        if ((**impl).desc)
                                printf("\t%s - %s\n",
                                       (**impl).name, (**impl).desc);
                        else
                                printf("\t%s\n", (**impl).name);
                }
                exit(0);
        } else {
                for (struct test_impl_t **impl = test_impls; *impl; impl++) {
                        if (!strcmp((**impl).name, name)) {
                                test_impl = *impl;
                                return 1;
                        }
                }
                fprintf(stderr,
                        "Invalid test implementation specified, use 'help' "
                        "to list available implementations.\n");
                return 0;
        }
}

variable_types: struct test_impl_t { char *name; char *desc; int num_threads; void (*test[])(int thread, int iterations, int *data); } **


decompiled_code:
int start_threads()
{
int v0; // er13
pthread_t *v1; // rax
pthread_t *v2; // r14
pthread_t *v3; // r12
pthread_t *v4; // rbx
int v5; // ebp
pthread_t *v6; // r13
int result; // eax

v0 = *((_DWORD *)test_impl + 4);
v1 = (pthread_t *)malloc(32LL * v0);
if ( !v1 )
abort();
v2 = v1;
v3 = v1;
v4 = v1;
v5 = 0;
if ( v0 > 0 )
{
do
{
*((_DWORD *)v4 + 2) = v5;
v4[2] = *((_QWORD *)test_impl + v5 + 3);
if ( pthread_create(v4, 0LL, call_test_impl, v4) )
abort();
++v5;
v4 += 4;
}
while ( v0 != v5 );
v6 = &v2[4 * (unsigned int)v0];
do
{
pthread_join(*v3, 0LL);
v3 += 4;
}
while ( v3 != v6 );
}
print_stats((__int64)v2);
putchar(10);
free(v2);
if ( shared_data )
result = printf(
"INCONSISTENCY after %d iterations - data = %d, but started at 0\n",
(unsigned int)iterations,
(unsigned int)shared_data);
else
result = printf("NO INCONSISTENCY after %d iterations\n", (unsigned int)iterations);
return result;
}

canonical_decompiled_code:
int func7()
{
int v0; // er13
pthread_t *v1; // rax
pthread_t *v2; // r14
pthread_t *v3; // r12
pthread_t *v4; // rbx
int v5; // ebp
pthread_t *v6; // r13
int result; // eax

v0 = *((_DWORD *)test_impl + 4);
v1 = (pthread_t *)malloc(32LL * v0);
if ( !v1 )
abort();
v2 = v1;
v3 = v1;
v4 = v1;
v5 = 0;
if ( v0 > 0 )
{
do
{
*((_DWORD *)v4 + 2) = v5;
v4[2] = *((_QWORD *)test_impl + v5 + 3);
if ( pthread_create(v4, 0LL, call_test_impl, v4) )
abort();
++v5;
v4 += 4;
}
while ( v0 != v5 );
v6 = &v2[4 * (unsigned int)v0];
do
{
pthread_join(*v3, 0LL);
v3 += 4;
}
while ( v3 != v6 );
}
func3((__int64)v2);
putchar(10);
free(v2);
if ( shared_data )
result = printf(
"INCONSISTENCY after %d iterations - data = %d, but started at 0\n",
(unsigned int)iterations,
(unsigned int)shared_data);
else
result = printf("NO INCONSISTENCY after %d iterations\n", (unsigned int)iterations);
return result;
}

original_code:
static void
start_threads()
{
        int num_threads = test_impl->num_threads;
        thread_conf_t *threads;
        if (!(threads = malloc(sizeof(*threads) * num_threads)))
                abort();
        for (int i = 0; i < num_threads; i++) {
                thread_conf_t *t = &threads[i];
                t->thread_id = i;
                t->func = test_impl->test[i];
                if (pthread_create(&t->thread, ((void *)0),
                                   &call_test_impl, t))
                        abort();
        }
        for (int i = 0; i < num_threads; i++)
                pthread_join(threads[i].thread, ((void *)0));
        print_stats(threads);
        printf("\n");
        free(threads);
        if (shared_data)
                printf("INCONSISTENCY after %d iterations - "
                       "data = %d, but started at 0\n",
                       iterations, shared_data);
        else
                printf("NO INCONSISTENCY after %d iterations\n",
                       iterations);
}

canonical_original_code:
static void start_threads()
{
        int num_threads = test_impl->num_threads;
        struct thread_conf_t *threads;
        if (!(threads = malloc(sizeof(*threads) * num_threads)))
                abort();
        for (int i = 0; i < num_threads; i++) {
                struct thread_conf_t *t = &threads[i];
                t->thread_id = i;
                t->func = test_impl->test[i];
                if (pthread_create(&t->thread, ((void *)0),
                                   &call_test_impl, t))
                        abort();
        }
        for (int i = 0; i < num_threads; i++)
                pthread_join(threads[i].thread, ((void *)0));
        print_stats(threads);
        printf("\n");
        free(threads);
        if (shared_data)
                printf("INCONSISTENCY after %d iterations - "
                       "data = %d, but started at 0\n",
                       iterations, shared_data);
        else
                printf("NO INCONSISTENCY after %d iterations\n",
                       iterations);
}


decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
int v4; // eax
char *v5; // r14
void (__fastcall *v6)(_QWORD); // rax
void (*v7)(void); // rdx

v3 = 0;
while ( 1 )
{
v4 = getopt(argc, (char *const *)argv, "c:t:i:h");
if ( v4 == -1 )
break;
if ( v4 == 104 )
{
usage(stdout, *argv);
exit(0);
}
if ( v4 <= 104 )
{
if ( v4 == 99 )
{
if ( !(unsigned int)set_cs_impl(optarg) )
v3 = 1;
}
else if ( v4 > 99 || (v3 = 1, v4 != 58) && v4 != 63 )
{
LABEL_20:
abort();
}
}
else if ( v4 == 105 )
{
v5 = optarg;
iterations = atoi(optarg);
if ( iterations <= 0 )
{
fprintf(stderr, "Invalid argument '%s'. Number of iterations must be positive.\n", v5);
v3 = 1;
}
}
else
{
if ( v4 != 116 )
goto LABEL_20;
if ( !(unsigned int)set_test_impl(optarg) )
v3 = 1;
}
}
if ( v3 )
{
usage(stderr, *argv);
exit(1);
}
v6 = (void (__fastcall *)(_QWORD))*((_QWORD *)cs_impl + 3);
if ( v6 )
v6(*((unsigned int *)test_impl + 4));
enter_critical = *((_QWORD *)cs_impl + 5);
exit_critical = *((_QWORD *)cs_impl + 6);
printf(
"Configuration:\n\tTest implementation: %s\n\tCritical sections implementation: %s\n\tIterations: %i\n\n",
*(const char **)test_impl,
*(const char **)cs_impl,
(unsigned int)iterations);
start_threads();
v7 = (void (*)(void))*((_QWORD *)cs_impl + 4);
if ( v7 )
v7();
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
int v4; // eax
char *v5; // r14
void (__fastcall *v6)(_QWORD); // rax
void (*v7)(void); // rdx

v3 = 0;
while ( 1 )
{
v4 = getopt(argc, (char *const *)argv, "c:t:i:h");
if ( v4 == -1 )
break;
if ( v4 == 104 )
{
func6(stdout, *argv);
exit(0);
}
if ( v4 <= 104 )
{
if ( v4 == 99 )
{
if ( !(unsigned int)func4(optarg) )
v3 = 1;
}
else if ( v4 > 99 || (v3 = 1, v4 != 58) && v4 != 63 )
{
LABEL_20:
abort();
}
}
else if ( v4 == 105 )
{
v5 = optarg;
iterations = atoi(optarg);
if ( iterations <= 0 )
{
fprintf(stderr, "Invalid argument '%s'. Number of iterations must be positive.\n", v5);
v3 = 1;
}
}
else
{
if ( v4 != 116 )
goto LABEL_20;
if ( !(unsigned int)func5(optarg) )
v3 = 1;
}
}
if ( v3 )
{
func6(stderr, *argv);
exit(1);
}
v6 = (void (__fastcall *)(_QWORD))*((_QWORD *)cs_impl + 3);
if ( v6 )
v6(*((unsigned int *)test_impl + 4));
enter_critical = *((_QWORD *)cs_impl + 5);
exit_critical = *((_QWORD *)cs_impl + 6);
printf(
"Configuration:\n\tTest implementation: %s\n\tCritical sections implementation: %s\n\tIterations: %i\n\n",
*(const char **)test_impl,
*(const char **)cs_impl,
(unsigned int)iterations);
func7();
v7 = (void (*)(void))*((_QWORD *)cs_impl + 4);
if ( v7 )
v7();
return 0;
}

original_code:
int
main(int argc, char *argv[])
{
        int opt;
        int errexit = 0;
        extern char *optarg;
        extern int optind, optopt;
        while ((opt = getopt(argc, argv, "c:t:i:h")) != -1) {
                switch (opt) {
                case 'c':
                        if (!set_cs_impl(optarg))
                                errexit = 1;
                        break;
                case 't':
                        if (!set_test_impl(optarg))
                                errexit = 1;
                        break;
                case 'i':
                        iterations = atoi(optarg);
                        if(iterations <= 0){
                                fprintf(stderr,
                                        "Invalid argument '%s'. Number of iterations "
                                        "must be positive.\n",
                                        optarg);
                                errexit = 1;
                        }
                        break;
                case 'h':
                        usage(stdout, argv[0]);
                        exit(0);
                case ':':
                case '?':
                        errexit = 1;
                        break;
                default:
                        abort();
                }
        }
        if (errexit) {
                usage(stderr, argv[0]);
                exit(1);
        }
        if (cs_impl->init)
                cs_impl->init(test_impl->num_threads);
        enter_critical = cs_impl->enter;
        exit_critical = cs_impl->exit;
        printf("Configuration:\n"
               "\tTest implementation: %s\n"
               "\tCritical sections implementation: %s\n"
               "\tIterations: %i\n"
               "\n",
               test_impl->name, cs_impl->name, iterations);
        start_threads();
        if (cs_impl->fini)
                cs_impl->fini();
        return 0;
}

canonical_original_code:
int main(int argc, char *argv[])
{
        int opt;
        int errexit = 0;
        extern char *optarg;
        extern int optind; extern int optopt;
        while ((opt = getopt(argc, argv, "c:t:i:h")) != -1) {
                switch (opt) {
                case 'c':
                        if (!set_cs_impl(optarg))
                                errexit = 1;
                        break;
                case 't':
                        if (!set_test_impl(optarg))
                                errexit = 1;
                        break;
                case 'i':
                        iterations = atoi(optarg);
                        if(iterations <= 0){
                                fprintf(stderr,
                                        "Invalid argument '%s'. Number of iterations "
                                        "must be positive.\n",
                                        optarg);
                                errexit = 1;
                        }
                        break;
                case 'h':
                        usage(stdout, argv[0]);
                        exit(0);
                case ':':
                case '?':
                        errexit = 1;
                        break;
                default:
                        abort();
                }
        }
        if (errexit) {
                usage(stderr, argv[0]);
                exit(1);
        }
        if (cs_impl->init)
                cs_impl->init(test_impl->num_threads);
        enter_critical = cs_impl->enter;
        exit_critical = cs_impl->exit;
        printf("Configuration:\n"
               "\tTest implementation: %s\n"
               "\tCritical sections implementation: %s\n"
               "\tIterations: %i\n"
               "\n",
               test_impl->name, cs_impl->name, iterations);
        start_threads();
        if (cs_impl->fini)
                cs_impl->fini();
        return 0;
}

variable_types: opt int


variable_types: jj int

variable_types: kk int

variable_types: j int

variable_types: k int

variable_types: B int

variable_types: r double


decompiled_code:
double *matmul_ref()
{
double *v0; // rcx
__int64 i; // r9
__int64 *v2; // rsi
__int64 *v3; // rdi
double v4; // xmm1_8
double *result; // rax
double *v6; // rdx

v0 = (double *)((char *)&unk_1E84800 + (_QWORD)mat_b);
for ( i = 0LL; i != 2000; ++i )
{
v2 = &mat_ref[i];
v3 = mat_a;
do
{
v4 = *(double *)v2;
result = (double *)&mat_b[i];
v6 = (double *)v3;
do
{
v4 = v4 + *v6++ * *result;
result += 2000;
}
while ( result != v0 );
*(double *)v2 = v4;
v2 += 2000;
v3 += 2000;
}
while ( v2 != &mat_c[i] );
++v0;
}
return result;
}

canonical_decompiled_code:
double *func8()
{
double *v0; // rcx
__int64 i; // r9
__int64 *v2; // rsi
__int64 *v3; // rdi
double v4; // xmm1_8
double *result; // rax
double *v6; // rdx

v0 = (double *)((char *)&unk_1E84800 + (_QWORD)mat_b);
for ( i = 0LL; i != 2000; ++i )
{
v2 = &mat_ref[i];
v3 = mat_a;
do
{
v4 = *(double *)v2;
result = (double *)&mat_b[i];
v6 = (double *)v3;
do
{
v4 = v4 + *v6++ * *result;
result += 2000;
}
while ( result != v0 );
*(double *)v2 = v4;
v2 += 2000;
v3 += 2000;
}
while ( v2 != &mat_c[i] );
++v0;
}
return result;
}


original_code:
static void
init_matrices()
{
        int i, j;
        for (i = 0; i < 2000; i++) {
                for (j = 0; j < 2000; j++) {
                        mat_a[i][j] = ((i + j) & 0x0F) * 0x1P-4;
                        mat_b[i][j] = (((i << 1) + (j >> 1)) & 0x0F) * 0x1P-4;
                }
        }
        memset(mat_c, 0, sizeof(mat_c));
        memset(mat_ref, 0, sizeof(mat_ref));
}

canonical_original_code:
static void init_matrices()
{
        int i; int j;
        for (i = 0; i < 2000; i++) {
                for (j = 0; j < 2000; j++) {
                        mat_a[i][j] = ((i + j) & 0x0F) * 0x1P-4;
                        mat_b[i][j] = (((i << 1) + (j >> 1)) & 0x0F) * 0x1P-4;
                }
        }
        memset(mat_c, 0, sizeof(mat_c));
        memset(mat_ref, 0, sizeof(mat_ref));
}


decompiled_code:
double get_time()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

if ( gettimeofday(&v1, 0LL) )
{
fwrite("gettimeofday failed. Aborting.\n", 1uLL, 0x1FuLL, stderr);
abort();
}
return (double)SLODWORD(v1.tv_usec) * 0.000001 + (double)SLODWORD(v1.tv_sec);
}

canonical_decompiled_code:
double func12()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

if ( gettimeofday(&v1, 0LL) )
{
fwrite("gettimeofday failed. Aborting.\n", 1uLL, 0x1FuLL, stderr);
abort();
}
return (double)SLODWORD(v1.tv_usec) * 0.000001 + (double)SLODWORD(v1.tv_sec);
}

original_code:
static double
get_time()
{
        struct timeval tv;
        if (gettimeofday(&tv, ((void *)0))) {
                fprintf(stderr, "gettimeofday failed. Aborting.\n");
                abort();
        }
        return tv.tv_sec + tv.tv_usec * 1E-6;
}

variable_types: struct timeval { long tv_sec; long tv_usec; }


original_code:
static int
verify_result()
{
        double e_sum;
        int i, j;
        e_sum = 0;
        for (i = 0; i < 2000; i++) {
                for (j = 0; j < 2000; j++) {
                        e_sum += mat_c[i][j] < mat_ref[i][j] ?
                                mat_ref[i][j] - mat_c[i][j] :
                                mat_c[i][j] - mat_ref[i][j];
                }
        }
        return e_sum < 1E-6;
}

canonical_original_code:
static int verify_result()
{
        double e_sum;
        int i; int j;
        e_sum = 0;
        for (i = 0; i < 2000; i++) {
                for (j = 0; j < 2000; j++) {
                        e_sum += mat_c[i][j] < mat_ref[i][j] ?
                                mat_ref[i][j] - mat_c[i][j] :
                                mat_c[i][j] - mat_ref[i][j];
                }
        }
        return e_sum < 1E-6;
}


decompiled_code:
int __fastcall run_multiply(int a1)
{
double v1; // r14
double v2; // xmm0_8
int result; // eax
double v4; // r14
double v5; // xmm0_8

v1 = get_time();
matmul_opt();
v2 = get_time();
result = printf("Time: %.4f\n", v2 - v1);
if ( a1 )
{
printf("Verifying solution... ");
v4 = get_time();
matmul_ref();
v5 = get_time();
if ( verify_result() )
puts("OK");
else
puts("MISMATCH");
result = printf("Reference runtime: %f\n", v5 - v4);
}
return result;
}

canonical_decompiled_code:
int __fastcall func13(int a1)
{
double v1; // r14
double v2; // xmm0_8
int result; // eax
double v4; // r14
double v5; // xmm0_8

v1 = func12();
func7();
v2 = func12();
result = printf("Time: %.4f\n", v2 - v1);
if ( a1 )
{
printf("Verifying solution... ");
v4 = func12();
func8();
v5 = func12();
if ( func9() )
puts("OK");
else
puts("MISMATCH");
result = printf("Reference runtime: %f\n", v5 - v4);
}
return result;
}

original_code:
static void
run_multiply(int verify)
{
        double time_start, time_stop;
        time_start = get_time();
        matmul_opt();
        time_stop = get_time();
        printf("Time: %.4f\n", time_stop - time_start);
        if (verify) {
                printf("Verifying solution... ");
                time_start = get_time();
                matmul_ref();
                time_stop = get_time();
                if (verify_result())
                        printf("OK\n");
                else
                        printf("MISMATCH\n");
                printf("Reference runtime: %f\n", time_stop - time_start);
        }
}

canonical_original_code:
static void run_multiply(int verify)
{
        double time_start; double time_stop;
        time_start = get_time();
        matmul_opt();
        time_stop = get_time();
        printf("Time: %.4f\n", time_stop - time_start);
        if (verify) {
                printf("Verifying solution... ");
                time_start = get_time();
                matmul_ref();
                time_stop = get_time();
                if (verify_result())
                        printf("OK\n");
                else
                        printf("MISMATCH\n");
                printf("Reference runtime: %f\n", time_stop - time_start);
        }
}

variable_types: verify int


decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er13
int v4; // er14
int v5; // eax

v3 = 0;
v4 = 0;
while ( 1 )
{
v5 = getopt(argc, (char *const *)argv, "vh");
if ( v5 == -1 )
break;
if ( v5 == 104 )
{
usage((FILE *)stdout, *argv);
exit(0);
}
if ( v5 > 104 )
{
v3 = 1;
if ( v5 != 118 )
goto LABEL_12;
}
else
{
if ( v5 == 58 )
{
fprintf(stderr, "%s: option -%c requries an operand\n", *argv, (unsigned int)optopt);
}
else
{
if ( v5 != 63 )
LABEL_12:
abort();
fprintf(stderr, "%s: illegal option -- %c\n", *argv, (unsigned int)optopt);
}
v4 = 1;
}
}
if ( v4 )
{
usage(stderr, *argv);
exit(2);
}
init_matrices();
run_multiply(v3);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er13
int v4; // er14
int v5; // eax

v3 = 0;
v4 = 0;
while ( 1 )
{
v5 = getopt(argc, (char *const *)argv, "vh");
if ( v5 == -1 )
break;
if ( v5 == 104 )
{
func10((FILE *)stdout, *argv);
exit(0);
}
if ( v5 > 104 )
{
v3 = 1;
if ( v5 != 118 )
goto LABEL_12;
}
else
{
if ( v5 == 58 )
{
fprintf(stderr, "%s: option -%c requries an operand\n", *argv, (unsigned int)optopt);
}
else
{
if ( v5 != 63 )
LABEL_12:
abort();
fprintf(stderr, "%s: illegal option -- %c\n", *argv, (unsigned int)optopt);
}
v4 = 1;
}
}
if ( v4 )
{
func10(stderr, *argv);
exit(2);
}
func11();
func13(v3);
return 0;
}

original_code:
int
main(int argc, char *argv[])
{
        int c;
        int errexit;
        int verify;
        extern char *optarg;
        extern int optind, optopt, opterr;
        errexit = 0;
        verify = 0;
        while ((c = getopt(argc, argv, "vh")) != -1) {
                switch (c) {
                case 'v':
                        verify = 1;
                        break;
                case 'h':
                        usage(stdout, argv[0]);
                        exit(0);
                        break;
                case ':':
                        fprintf(stderr, "%s: option -%c requries an operand\n",
                                argv[0], optopt);
                        errexit = 1;
                        break;
                case '?':
                        fprintf(stderr, "%s: illegal option -- %c\n",
                                argv[0], optopt);
                        errexit = 1;
                        break;
                default:
                        abort();
                }
        }
        if (errexit) {
                usage(stderr, argv[0]);
                exit(2);
        }
        init_matrices();
        run_multiply(verify);
        return 0;
}

canonical_original_code:
int main(int argc, char *argv[])
{
        int c;
        int errexit;
        int verify;
        extern char *optarg;
        extern int optind; extern int optopt; extern int opterr;
        errexit = 0;
        verify = 0;
        while ((c = getopt(argc, argv, "vh")) != -1) {
                switch (c) {
                case 'v':
                        verify = 1;
                        break;
                case 'h':
                        usage(stdout, argv[0]);
                        exit(0);
                        break;
                case ':':
                        fprintf(stderr, "%s: option -%c requries an operand\n",
                                argv[0], optopt);
                        errexit = 1;
                        break;
                case '?':
                        fprintf(stderr, "%s: illegal option -- %c\n",
                                argv[0], optopt);
                        errexit = 1;
                        break;
                default:
                        abort();
                }
        }
        if (errexit) {
                usage(stderr, argv[0]);
                exit(2);
        }
        init_matrices();
        run_multiply(verify);
        return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types: c int

variable_types: errexit int

variable_types:
optarg
char *

variable_types: optind int

variable_types: optopt int


canonical_decompiled_code:
void func2()
{
free(lh_threads);
free(lock_cells);
}

original_code:
static void
impl_fini()
{
        free(lh_threads);
        free(lock_cells);
}


decompiled_code:
char *__fastcall impl_init(int a1)
{
_QWORD *v1; // rbx
char *result; // rax
_QWORD *v3; // rdx
char *v4; // rcx

num_threads = a1;
v1 = malloc((__int64)a1 << 12);
lh_threads = v1;
result = (char *)malloc((__int64)a1 << 12);
lock_cells = result;
if ( !result || !v1 )
_assert_fail("lh_threads && lock_cells", "cs_queue.c", 0x64u, "impl_init");
lock_l = (__int64)&lock_cell0;
if ( a1 > 0 )
{
v3 = v1 + 1;
v4 = &result[4096 * (unsigned __int64)(unsigned int)a1];
do
{
*(v3 - 1) = result;
*v3 = result;
result += 4096;
v3 += 512;
}
while ( result != v4 );
}
return result;
}

canonical_decompiled_code:
char *__fastcall func3(int a1)
{
_QWORD *v1; // rbx
char *result; // rax
_QWORD *v3; // rdx
char *v4; // rcx

num_threads = a1;
v1 = malloc((__int64)a1 << 12);
lh_threads = v1;
result = (char *)malloc((__int64)a1 << 12);
lock_cells = result;
if ( !result || !v1 )
_assert_fail("lh_threads && lock_cells", "cs_queue.c", 0x64u, "impl_init");
lock_l = (__int64)&lock_cell0;
if ( a1 > 0 )
{
v3 = v1 + 1;
v4 = &result[4096 * (unsigned __int64)(unsigned int)a1];
do
{
*(v3 - 1) = result;
*v3 = result;
result += 4096;
v3 += 512;
}
while ( result != v4 );
}
return result;
}

original_code:
static void
impl_init(int _num_threads)
{
        num_threads = _num_threads;
        lh_threads = malloc(sizeof(*lh_threads) * num_threads);
        lock_cells = malloc(sizeof(*lock_cells) * num_threads);
        ((lh_threads && lock_cells) ? (void) (0) : __assert_fail ("lh_threads && lock_cells", "cs_queue.c", 100, __extension__ __PRETTY_FUNCTION__));
        lock_l = &lock_cell0;
        for (int i = 0; i < num_threads; i++) {
                lh_threads[i].i = &lock_cells[i].v;
                lh_threads[i].p = lh_threads[i].i;
        }
}

variable_types: i int


decompiled_code:
__int64 __fastcall impl_enter_critical(int a1)
{
if ( a1 < 0 || num_threads <= a1 )
_assert_fail("thread >= 0 && thread < num_threads", "cs_queue.c", 0x77u, "impl_enter_critical");
return lh_acquire(&lock_l, (__int64 *)lh_threads + 512 * (__int64)a1, (_QWORD *)lh_threads + 512 * (__int64)a1 + 1);
}

canonical_decompiled_code:
__int64 __fastcall func1(int a1)
{
if ( a1 < 0 || num_threads <= a1 )
_assert_fail("thread >= 0 && thread < num_threads", "cs_queue.c", 0x77u, "impl_enter_critical");
return func0(&lock_l, (__int64 *)lh_threads + 512 * (__int64)a1, (_QWORD *)lh_threads + 512 * (__int64)a1 + 1);
}

original_code:
static void
impl_enter_critical(int thread)
{
        ((thread >= 0 && thread < num_threads) ? (void) (0) : __assert_fail ("thread >= 0 && thread < num_threads", "cs_queue.c", 119, __extension__ __PRETTY_FUNCTION__));
        lh_acquire((int ** volatile)&lock_l,
                   (int ** volatile)&lh_threads[thread].i,
                   (volatile int **)&lh_threads[thread].p);
}

canonical_original_code:
static void impl_enter_critical(int thread)
{
        ((thread >= 0 && thread < num_threads) ? (void) (0) : __assert_fail ("thread >= 0 && thread < num_threads", "cs_queue.c", 119, __extension__ __PRETTY_FUNCTION__));
        lh_acquire((int **)&lock_l,
                   (int **)&lh_threads[thread].i,
                   (int **)&lh_threads[thread].p);
}

variable_types: thread int


decompiled_code:
__int64 matvec_ref()
{
__int64 v0; // r8
__int64 v1; // rdi
float *v2; // rcx
int i; // er9
__int64 result; // rax

v0 = mat_a;
v1 = vec_b;
v2 = (float *)vec_ref;
for ( i = 0; i != 0x10000000; i += 0x4000 )
{
for ( result = 0LL; result != 0x4000; ++result )
*v2 = (float)(*(float *)(v0 + 4LL * (int)(result | i)) * *(float *)(v1 + 4 * result)) + *v2;
++v2;
}
return result;
}

canonical_decompiled_code:
__int64 func7()
{
__int64 v0; // r8
__int64 v1; // rdi
float *v2; // rcx
int i; // er9
__int64 result; // rax

v0 = mat_a;
v1 = vec_b;
v2 = (float *)vec_ref;
for ( i = 0; i != 0x10000000; i += 0x4000 )
{
for ( result = 0LL; result != 0x4000; ++result )
*v2 = (float)(*(float *)(v0 + 4LL * (int)(result | i)) * *(float *)(v1 + 4 * result)) + *v2;
++v2;
}
return result;
}


init

canonical_original_code:
static void init()
{
        int i; int j;
        mat_a = _mm_malloc(sizeof(*mat_a) * (1 << 14) * (1 << 14), 16);
        vec_b = _mm_malloc(sizeof(*vec_b) * (1 << 14), 16);
        vec_c = _mm_malloc(sizeof(*vec_c) * (1 << 14), 16);
        vec_ref = _mm_malloc(sizeof(*vec_ref) * (1 << 14), 16);
        if (!mat_a || !vec_b || !vec_c || !vec_ref) {
                fprintf(stderr, "Memory allocation failed\n");
                abort();
        }
        for (i = 0; i < (1 << 14); i++) {
                for (j = 0; j < (1 << 14); j++)
                        mat_a[(((i) << 14) | (j))] = ((7 * i + j) & 0x0F) * 0x1P-2F;
                vec_b[i] = ((i * 17) & 0x0F) * 0x1P-2F;
        }
        memset(vec_c, 0, sizeof(*vec_c) * (1 << 14));
        memset(vec_ref, 0, sizeof(*vec_ref) * (1 << 14));
}


decompiled_code:
int __fastcall util_monotonic_time(struct timespec *tp)
{
int result; // eax

result = clock_gettime(1, tp);
if ( result )
{
perror("clock_gettime failed");
abort();
}
return result;
}

canonical_decompiled_code:
int __fastcall func14(struct timespec *tp)
{
int result; // eax

result = clock_gettime(1, tp);
if ( result )
{
perror("clock_gettime failed");
abort();
}
return result;
}

original_code:
void
util_monotonic_time(struct timespec *ts)
{
        if (clock_gettime(1, ts) != 0) {
                perror("clock_gettime failed");
                abort();
        }
}

variable_types: struct timespec { long tv_sec; long tv_nsec; } *


decompiled_code:
double __fastcall util_time_diff(_QWORD *a1, _QWORD *a2)
{
if ( *a2 <= *a1 && (*a2 != *a1 || a2[1] < a1[1]) )
__assert_fail(
"ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)",
"util.c",
0x27u,
"util_time_diff");
return (double)(*((_DWORD *)a2 + 2) - *((_DWORD *)a1 + 2)) * 0.000000001 + (double)(int)(*a2 - *a1);
}

canonical_decompiled_code:
double __fastcall func15(_QWORD *a1, _QWORD *a2)
{
if ( *a2 <= *a1 && (*a2 != *a1 || a2[1] < a1[1]) )
__assert_fail(
"ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)",
"util.c",
0x27u,
"util_time_diff");
return (double)(*((_DWORD *)a2 + 2) - *((_DWORD *)a1 + 2)) * 0.000000001 + (double)(int)(*a2 - *a1);
}

original_code:
double
util_time_diff(struct timespec *ts_start, struct timespec *ts_stop)
{
        ((void) sizeof ((ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)) ? 1 : 0), __extension__ ({ if (ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)) ; else __assert_fail ("ts_stop->tv_sec > ts_start->tv_sec || (ts_stop->tv_sec == ts_start->tv_sec && ts_stop->tv_nsec >= ts_start->tv_nsec)", "util.c", 39, __extension__ __PRETTY_FUNCTION__); }));
        return ts_stop->tv_sec - ts_start->tv_sec +
                (ts_stop->tv_nsec - ts_start->tv_nsec) * 1E-9;
}


decompiled_code:
int __fastcall print_vector_epi8(__m128i a1)
{
__int64 v1; // r14
__int64 v3; // [rsp-D0h] [rbp-120h]
__int64 v4; // [rsp-C8h] [rbp-118h]
__int64 v5; // [rsp-C0h] [rbp-110h]
__int64 v6; // [rsp-B8h] [rbp-108h]
__int64 v7; // [rsp-A8h] [rbp-F8h]
__int64 v8; // [rsp-A0h] [rbp-F0h]
__int64 v9; // [rsp-98h] [rbp-E8h]
__int64 v10; // [rsp-90h] [rbp-E0h]
__int64 v11; // [rsp-88h] [rbp-D8h]
__int64 v12; // [rsp-80h] [rbp-D0h]
__int64 v13; // [rsp-78h] [rbp-C8h]
__int64 v14; // [rsp-70h] [rbp-C0h]
__int64 v15; // [rsp-68h] [rbp-B8h]
__int64 v16; // [rsp-60h] [rbp-B0h]
unsigned int v17; // [rsp+14h] [rbp-3Ch]

v17 = (char)_mm_extract_epi8(a1, 5);
v16 = (unsigned int)(char)_mm_extract_epi8(a1, 4);
v15 = (unsigned int)(char)_mm_extract_epi8(a1, 3);
v14 = (unsigned int)(char)_mm_extract_epi8(a1, 2);
v13 = (unsigned int)(char)_mm_extract_epi8(a1, 1);
v12 = (unsigned int)(char)_mm_extract_epi8(a1, 0);
v11 = (unsigned int)(char)_mm_extract_epi8(a1, 15);
v10 = (unsigned int)(char)_mm_extract_epi8(a1, 14);
v9 = (unsigned int)(char)_mm_extract_epi8(a1, 13);
v8 = (unsigned int)(char)_mm_extract_epi8(a1, 12);
v7 = (unsigned int)(char)_mm_extract_epi8(a1, 11);
v1 = (unsigned int)(char)_mm_extract_epi8(a1, 10);
v6 = (unsigned int)(char)_mm_extract_epi8(a1, 9);
v5 = (unsigned int)(char)_mm_extract_epi8(a1, 8);
v4 = (unsigned int)(char)_mm_extract_epi8(a1, 7);
v3 = (unsigned int)(char)_mm_extract_epi8(a1, 6);
return printf(
"%.2hhx%.2hhx%.2hhx%.2hhx %.2hhx%.2hhx%.2hhx%.2hhx %.2hhx%.2hhx%.2hhx%.2hhx %.2hhx%.2hhx%.2hhx%.2hhx %c%c%c%c "
"%c%c%c%c %c%c%c%c %c%c%c%c\n",
v12,
v13,
v14,
v15,
v16,
v17,
v3,
v4,
v5,
v6,
v1,
v7,
v8,
v9,
v10,
v11,
v12,
v13,
v14,
v15,
v16,
v17,
v3,
v4,
v5,
v6,
v1,
v7,
v8,
v9,
v10,
v11);
}

canonical_decompiled_code:
int __fastcall func16(__m128i a1)
{
__int64 v1; // r14
__int64 v3; // [rsp-D0h] [rbp-120h]
__int64 v4; // [rsp-C8h] [rbp-118h]
__int64 v5; // [rsp-C0h] [rbp-110h]
__int64 v6; // [rsp-B8h] [rbp-108h]
__int64 v7; // [rsp-A8h] [rbp-F8h]
__int64 v8; // [rsp-A0h] [rbp-F0h]
__int64 v9; // [rsp-98h] [rbp-E8h]
__int64 v10; // [rsp-90h] [rbp-E0h]
__int64 v11; // [rsp-88h] [rbp-D8h]
__int64 v12; // [rsp-80h] [rbp-D0h]
__int64 v13; // [rsp-78h] [rbp-C8h]
__int64 v14; // [rsp-70h] [rbp-C0h]
__int64 v15; // [rsp-68h] [rbp-B8h]
__int64 v16; // [rsp-60h] [rbp-B0h]
unsigned int v17; // [rsp+14h] [rbp-3Ch]

v17 = (char)_mm_extract_epi8(a1, 5);
v16 = (unsigned int)(char)_mm_extract_epi8(a1, 4);
v15 = (unsigned int)(char)_mm_extract_epi8(a1, 3);
v14 = (unsigned int)(char)_mm_extract_epi8(a1, 2);
v13 = (unsigned int)(char)_mm_extract_epi8(a1, 1);
v12 = (unsigned int)(char)_mm_extract_epi8(a1, 0);
v11 = (unsigned int)(char)_mm_extract_epi8(a1, 15);
v10 = (unsigned int)(char)_mm_extract_epi8(a1, 14);
v9 = (unsigned int)(char)_mm_extract_epi8(a1, 13);
v8 = (unsigned int)(char)_mm_extract_epi8(a1, 12);
v7 = (unsigned int)(char)_mm_extract_epi8(a1, 11);
v1 = (unsigned int)(char)_mm_extract_epi8(a1, 10);
v6 = (unsigned int)(char)_mm_extract_epi8(a1, 9);
v5 = (unsigned int)(char)_mm_extract_epi8(a1, 8);
v4 = (unsigned int)(char)_mm_extract_epi8(a1, 7);
v3 = (unsigned int)(char)_mm_extract_epi8(a1, 6);
return printf(
"%.2hhx%.2hhx%.2hhx%.2hhx %.2hhx%.2hhx%.2hhx%.2hhx %.2hhx%.2hhx%.2hhx%.2hhx %.2hhx%.2hhx%.2hhx%.2hhx %c%c%c%c "
"%c%c%c%c %c%c%c%c %c%c%c%c\n",
v12,
v13,
v14,
v15,
v16,
v17,
v3,
v4,
v5,
v6,
v1,
v7,
v8,
v9,
v10,
v11,
v12,
v13,
v14,
v15,
v16,
v17,
v3,
v4,
v5,
v6,
v1,
v7,
v8,
v9,
v10,
v11);
}

variable_types:
v
long long

variable_types:
cv
char *


decompiled_code:
int __fastcall print_vector_pd(__m128d a1)
{
return printf("%f %f\n", a1.m128d_f64[0], _mm_unpackhi_pd(a1, a1).m128d_f64[0]);
}

canonical_decompiled_code:
int __fastcall func17(__m128d a1)
{
return printf("%f %f\n", a1.m128d_f64[0], _mm_unpackhi_pd(a1, a1).m128d_f64[0]);
}

original_code:
void
print_vector_pd(__m128d v)
{
        const double *dv = (double *)&v;
        printf("%f %f\n", dv[0], dv[1]);
}

canonical_original_code:
void print_vector_pd(double v)
{
        double *dv = (double *)&v;
        printf("%f %f\n", dv[0], dv[1]);
}

variable_types: v double

variable_types:
dv
double *


original_code:
void
print_vector_ps(__m128 v)
{
        const float *sv = (float *)&v;
        printf("%f %f %f %f\n",
               sv[0], sv[1], sv[2], sv[3]);
}

canonical_original_code:
void print_vector_ps(float v)
{
        float *sv = (float *)&v;
        printf("%f %f %f %f\n",
               sv[0], sv[1], sv[2], sv[3]);
}

variable_types: v float

variable_types:
sv
float *


original_code:
static int
verify_result()
{
        float e_sum;
        int i;
        e_sum = 0;
        for (i = 0; i < (1 << 14); i++) {
                e_sum += vec_c[i] < vec_ref[i] ?
                        vec_ref[i] - vec_c[i] :
                        vec_c[i] - vec_ref[i];
        }
        printf("e_sum: %.e\n", e_sum);
        return e_sum < 1E-6;
}


decompiled_code:
int run_multiply()
{
double v0; // r14
double v1; // rbx
int result; // eax
struct timespec v3; // [rsp+0h] [rbp-38h] BYREF
struct timespec tp; // [rsp+10h] [rbp-28h] BYREF

puts("Starting SSE run...");
util_monotonic_time(&tp);
matvec_sse();
util_monotonic_time(&v3);
v0 = util_time_diff(&tp, &v3);
printf("SSE run completed in %.2f s\n", v0);
puts("Starting reference run...");
util_monotonic_time(&tp);
matvec_ref();
util_monotonic_time(&v3);
v1 = util_time_diff(&tp, &v3);
printf("Reference run completed in %.2f s\n", v1);
printf("Speedup: %.2f\n", v1 / v0);
if ( verify_result() )
result = puts("OK");
else
result = puts("MISMATCH");
return result;
}

canonical_decompiled_code:
int func12()
{
double v0; // r14
double v1; // rbx
int result; // eax
struct timespec v3; // [rsp+0h] [rbp-38h] BYREF
struct timespec tp; // [rsp+10h] [rbp-28h] BYREF

puts("Starting SSE run...");
func14(&tp);
func11();
func14(&v3);
v0 = func15(&tp, &v3);
printf("SSE run completed in %.2f s\n", v0);
puts("Starting reference run...");
func14(&tp);
func7();
func14(&v3);
v1 = func15(&tp, &v3);
printf("Reference run completed in %.2f s\n", v1);
printf("Speedup: %.2f\n", v1 / v0);
if ( func10() )
result = puts("OK");
else
result = puts("MISMATCH");
return result;
}

original_code:
static void
run_multiply()
{
        struct timespec ts_start, ts_stop;
        double runtime_ref, runtime_sse;
        printf("Starting SSE run...\n");
        util_monotonic_time(&ts_start);
        matvec_sse();
        util_monotonic_time(&ts_stop);
        runtime_sse = util_time_diff(&ts_start, &ts_stop);
        printf("SSE run completed in %.2f s\n",
               runtime_sse);
        printf("Starting reference run...\n");
        util_monotonic_time(&ts_start);
 matvec_ref();
        util_monotonic_time(&ts_stop);
        runtime_ref = util_time_diff(&ts_start, &ts_stop);
        printf("Reference run completed in %.2f s\n",
               runtime_ref);
        printf("Speedup: %.2f\n",
               runtime_ref / runtime_sse);
 if (verify_result())
     printf("OK\n");
 else
     printf("MISMATCH\n");
}

canonical_original_code:
static void run_multiply()
{
        struct timespec ts_start; struct timespec ts_stop;
        double runtime_ref; double runtime_sse;
        printf("Starting SSE run...\n");
        util_monotonic_time(&ts_start);
        matvec_sse();
        util_monotonic_time(&ts_stop);
        runtime_sse = util_time_diff(&ts_start, &ts_stop);
        printf("SSE run completed in %.2f s\n",
               runtime_sse);
        printf("Starting reference run...\n");
        util_monotonic_time(&ts_start);
 matvec_ref();
        util_monotonic_time(&ts_stop);
        runtime_ref = util_time_diff(&ts_start, &ts_stop);
        printf("Reference run completed in %.2f s\n",
               runtime_ref);
        printf("Speedup: %.2f\n",
               runtime_ref / runtime_sse);
 if (verify_result())
     printf("OK\n");
 else
     printf("MISMATCH\n");
}

variable_types: struct timespec { long tv_sec; long tv_nsec; }


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
init();
run_multiply();
mm_free((void *)mat_a);
mm_free((void *)vec_b);
mm_free((void *)vec_c);
mm_free((void *)vec_ref);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
func9();
func12();
func13((void *)mat_a);
func13((void *)vec_b);
func13((void *)vec_c);
func13((void *)vec_ref);
return 0;
}

original_code:
int
main(int argc, char *argv[])
{
        init();
        run_multiply();
        _mm_free(mat_a);
        _mm_free(vec_b);
        _mm_free(vec_c);
        _mm_free(vec_ref);
        return 0;
}

variable_types: argc int


decompiled_code:
void *__fastcall thread_compute(void *a1)
{
unsigned int v1; // ebp
unsigned int v2; // er13
unsigned int v3; // er12
unsigned int v4; // er12
__int64 v5; // rdx
int v6; // ebx
double *v7; // rdx
double v8; // xmm0_8

v1 = *(_DWORD *)a1;
v2 = *(_DWORD *)a1 * (gs_size / (int)gs_nthreads);
v3 = gs_size / (int)gs_nthreads + v2;
if ( !*(_DWORD *)a1 )
v2 = 1;
v4 = v3 - (gs_nthreads - 1 == v1);
gs_verbose_printf("%i: lbound: %i, rbound: %i\n", v1, v2, v4);
v5 = gs_iterations;
if ( gs_iterations > 0 )
{
v6 = 0;
do
{
if ( *(double *)&global_error <= gs_tolerance )
break;
thread_sweep(v1, (unsigned int)v6, v2, v4);
if ( gs_nthreads - 1 == v1 )
{
global_error = 0LL;
if ( (int)gs_nthreads > 0 )
{
v7 = (double *)threads;
v8 = 0.0;
do
{
v8 = v8 + v7[2];
v7 += 10;
}
while ( v7 != (double *)((char *)threads + 80 * gs_nthreads) );
global_error = *(_QWORD *)&v8;
}
}
pthread_barrier_wait(&barrier);
*((_DWORD *)threads + 20 * (int)v1 + 6) = 0;
pthread_barrier_wait(&barrier);
++v6;
v5 = gs_iterations;
}
while ( gs_iterations > v6 );
}
gs_verbose_printf("\t**** Thread %d done after %d iterations ****\n", v1, v5);
return 0LL;
}

canonical_decompiled_code:
void *__fastcall func1(void *a1)
{
unsigned int v1; // ebp
unsigned int v2; // er13
unsigned int v3; // er12
unsigned int v4; // er12
__int64 v5; // rdx
int v6; // ebx
double *v7; // rdx
double v8; // xmm0_8

v1 = *(_DWORD *)a1;
v2 = *(_DWORD *)a1 * (gs_size / (int)gs_nthreads);
v3 = gs_size / (int)gs_nthreads + v2;
if ( !*(_DWORD *)a1 )
v2 = 1;
v4 = v3 - (gs_nthreads - 1 == v1);
gs_verbose_printf("%i: lbound: %i, rbound: %i\n", v1, v2, v4);
v5 = gs_iterations;
if ( gs_iterations > 0 )
{
v6 = 0;
do
{
if ( *(double *)&global_error <= gs_tolerance )
break;
func0(v1, (unsigned int)v6, v2, v4);
if ( gs_nthreads - 1 == v1 )
{
global_error = 0LL;
if ( (int)gs_nthreads > 0 )
{
v7 = (double *)threads;
v8 = 0.0;
do
{
v8 = v8 + v7[2];
v7 += 10;
}
while ( v7 != (double *)((char *)threads + 80 * gs_nthreads) );
global_error = *(_QWORD *)&v8;
}
}
pthread_barrier_wait(&barrier);
*((_DWORD *)threads + 20 * (int)v1 + 6) = 0;
pthread_barrier_wait(&barrier);
++v6;
v5 = gs_iterations;
}
while ( gs_iterations > v6 );
}
gs_verbose_printf("\t**** Thread %d done after %d iterations ****\n", v1, v5);
return 0LL;
}

original_code:
static void *
thread_compute(void *_self)
{
        thread_info_t *self = (thread_info_t *)_self;
        const int tid = self->thread_id;
        int lbound = (gs_size/gs_nthreads)*tid;
 int rbound = lbound + gs_size/gs_nthreads;
 if (tid == 0)
  lbound++;
 if (tid == gs_nthreads-1)
  rbound--;
        gs_verbose_printf("%i: lbound: %i, rbound: %i\n",
                          tid, lbound, rbound);
        for (int iter = 0;
             iter < gs_iterations && global_error > gs_tolerance;
             iter++) {
                if (0) fprintf(stderr, "%i: Starting iteration %i\n", tid, iter);
                thread_sweep(tid, iter, lbound, rbound);
  if(tid == (gs_nthreads - 1)) {
   global_error = 0;
   for (int i=0;i<gs_nthreads;i++)
    global_error+=threads[i].error;
  }
                if (0) fprintf(stderr, "%d: iteration %d done\n", tid, iter);
  pthread_barrier_wait(&barrier);
  threads[tid].c_row = 0;
  pthread_barrier_wait(&barrier);
        }
        gs_verbose_printf(
                "\t****  Thread %d done after %d iterations ****\n",
                tid, gs_iterations);
        return ((void *)0);
}

canonical_original_code:
static void *thread_compute(void *_self)
{
        struct thread_info_t *self = (thread_info_t *)_self;
        int tid = self->thread_id;
        int lbound = (gs_size/gs_nthreads)*tid;
 int rbound = lbound + gs_size/gs_nthreads;
 if (tid == 0)
  lbound++;
 if (tid == gs_nthreads-1)
  rbound--;
        gs_verbose_printf("%i: lbound: %i, rbound: %i\n",
                          tid, lbound, rbound);
        for (int iter = 0;
             iter < gs_iterations && global_error > gs_tolerance;
             iter++) {
                if (0) fprintf(stderr, "%i: Starting iteration %i\n", tid, iter);
                thread_sweep(tid, iter, lbound, rbound);
  if(tid == (gs_nthreads - 1)) {
   global_error = 0;
   for (int i = 0;i<gs_nthreads;i++)
    global_error+=threads[i].error;
  }
                if (0) fprintf(stderr, "%d: iteration %d done\n", tid, iter);
  pthread_barrier_wait(&barrier);
  threads[tid].c_row = 0;
  pthread_barrier_wait(&barrier);
        }
        gs_verbose_printf(
                "\t****  Thread %d done after %d iterations ****\n",
                tid, gs_iterations);
        return ((void *)0);
}

variable_types: struct thread_info_t { int thread_id; unsigned long thread; double error; int c_row; double padding[6]; } *

variable_types: tid int

variable_types: lbound int

variable_types: rbound int

variable_types: iter int


decompiled_code:
int gsi_init()
{
_DWORD *v0; // rax
unsigned int v1; // esi
_DWORD *v2; // rdx

gs_verbose_printf("\t**** Initializing the environment ****\n");
v0 = malloc(80LL * (int)gs_nthreads);
threads = v0;
if ( !v0 )
{
fwrite("Failed to allocate memory for thread information.\n", 1uLL, 0x32uLL, stderr);
exit(1);
}
*(double *)&global_error = gs_tolerance + 1.0;
v1 = gs_nthreads;
if ( (int)gs_nthreads > 0 )
{
v2 = &v0[20 * gs_nthreads];
do
{
v0[6] = 0;
v0 += 20;
}
while ( v0 != v2 );
}
return pthread_barrier_init(&barrier, 0LL, v1);
}

canonical_decompiled_code:
int func2()
{
_DWORD *v0; // rax
unsigned int v1; // esi
_DWORD *v2; // rdx

gs_verbose_printf("\t**** Initializing the environment ****\n");
v0 = malloc(80LL * (int)gs_nthreads);
threads = v0;
if ( !v0 )
{
fwrite("Failed to allocate memory for thread information.\n", 1uLL, 0x32uLL, stderr);
exit(1);
}
*(double *)&global_error = gs_tolerance + 1.0;
v1 = gs_nthreads;
if ( (int)gs_nthreads > 0 )
{
v2 = &v0[20 * gs_nthreads];
do
{
v0[6] = 0;
v0 += 20;
}
while ( v0 != v2 );
}
return pthread_barrier_init(&barrier, 0LL, v1);
}

original_code:
void
gsi_init()
{
        gs_verbose_printf("\t****  Initializing the  environment ****\n");
        threads = (thread_info_t *)malloc(gs_nthreads * sizeof(thread_info_t));
        if (!threads) {
                fprintf(stderr,
                        "Failed to allocate memory for thread information.\n");
                exit(1);
        }
        global_error = gs_tolerance + 1;
 for (int i=0;i<gs_nthreads;i++)
  threads[i].c_row = 0;
 pthread_barrier_init(&barrier,((void *)0),gs_nthreads);
}

canonical_original_code:
void gsi_init()
{
        gs_verbose_printf("\t****  Initializing the  environment ****\n");
        threads = (struct thread_info_t *)malloc(gs_nthreads * sizeof(thread_info_t));
        if (!threads) {
                fprintf(stderr,
                        "Failed to allocate memory for thread information.\n");
                exit(1);
        }
        global_error = gs_tolerance + 1;
 for (int i = 0;i<gs_nthreads;i++)
  threads[i].c_row = 0;
 pthread_barrier_init(&barrier,((void *)0),gs_nthreads);
}

user_defined_types: struct thread_info_t { int thread_id; unsigned long thread; double error; int c_row; double padding[6]; }


decompiled_code:
int gsi_finish()
{
gs_verbose_printf("\t**** Cleaning environment ****\n");
if ( threads )
free(threads);
return pthread_barrier_destroy(&barrier);
}

canonical_decompiled_code:
int func3()
{
gs_verbose_printf("\t**** Cleaning environment ****\n");
if ( threads )
free(threads);
return pthread_barrier_destroy(&barrier);
}

original_code:
void
gsi_finish()
{
        gs_verbose_printf("\t****  Cleaning environment ****\n");
        if (threads)
                free(threads);
 pthread_barrier_destroy(&barrier);
}


decompiled_code:
int gsi_calculate()
{
__int64 v0; // r12
unsigned int v1; // ebp
unsigned int v2; // eax
signed int v3; // ebx
__int64 v4; // rbp
unsigned int v5; // eax

if ( (int)gs_nthreads > 0 )
{
v0 = 0LL;
v1 = 0;
do
{
gs_verbose_printf("\tSpawning thread %d\n", v1);
*(_DWORD *)((char *)threads + v0) = v1;
v2 = pthread_create((pthread_t *)((char *)threads + v0 + 8), 0LL, thread_compute, (char *)threads + v0);
v3 = v2;
if ( v2 )
{
fprintf(stderr, "Error: pthread_create() failed: %d, thread %d\n", v2, v1);
exit(1);
}
++v1;
v0 += 80LL;
}
while ( (int)gs_nthreads > (int)v1 );
if ( (int)gs_nthreads > 0 )
{
v4 = 0LL;
do
{
v5 = pthread_join(*(_QWORD *)((char *)threads + v4 + 8), 0LL);
if ( v5 )
{
fprintf(stderr, "Error: pthread_join() failed: %d, thread %d\n", v5, (unsigned int)v3);
exit(1);
}
++v3;
v4 += 80LL;
}
while ( (int)gs_nthreads > v3 );
}
}
if ( gs_tolerance >= *(double *)&global_error )
return puts("Solution converged!");
puts("Solution did NOT converge.");
return puts("Note: This is normal if you are using the default settings.");
}

canonical_decompiled_code:
int func4()
{
__int64 v0; // r12
unsigned int v1; // ebp
unsigned int v2; // eax
signed int v3; // ebx
__int64 v4; // rbp
unsigned int v5; // eax

if ( (int)gs_nthreads > 0 )
{
v0 = 0LL;
v1 = 0;
do
{
gs_verbose_printf("\tSpawning thread %d\n", v1);
*(_DWORD *)((char *)threads + v0) = v1;
v2 = pthread_create((pthread_t *)((char *)threads + v0 + 8), 0LL, thread_compute, (char *)threads + v0);
v3 = v2;
if ( v2 )
{
fprintf(stderr, "Error: pthread_create() failed: %d, thread %d\n", v2, v1);
exit(1);
}
++v1;
v0 += 80LL;
}
while ( (int)gs_nthreads > (int)v1 );
if ( (int)gs_nthreads > 0 )
{
v4 = 0LL;
do
{
v5 = pthread_join(*(_QWORD *)((char *)threads + v4 + 8), 0LL);
if ( v5 )
{
fprintf(stderr, "Error: pthread_join() failed: %d, thread %d\n", v5, (unsigned int)v3);
exit(1);
}
++v3;
v4 += 80LL;
}
while ( (int)gs_nthreads > v3 );
}
}
if ( gs_tolerance >= *(double *)&global_error )
return puts("Solution converged!");
puts("Solution did NOT converge.");
return puts("Note: This is normal if you are using the default settings.");
}

original_code:
void
gsi_calculate()
{
        int err;
        for (int t = 0; t < gs_nthreads; t++) {
                gs_verbose_printf("\tSpawning thread %d\n",t);
                threads[t].thread_id = t;
                err = pthread_create(&threads[t].thread, ((void *)0),
                                     thread_compute, &threads[t]);
                if (err) {
                        fprintf(stderr,
                                "Error: pthread_create() failed: %d, "
                                "thread %d\n",
                                err, t);
                        exit(1);
                }
        }
        for (int t = 0; t < gs_nthreads; t++) {
                err = pthread_join(threads[t].thread, ((void *)0));
                if (err) {
                        fprintf(stderr,
                                "Error: pthread_join() failed: %d, "
                                "thread %d\n",
                                err, t);
                        exit(1);
                }
        }
        if (global_error <= gs_tolerance)
                printf("Solution converged!\n");
        else {
                printf("Solution did NOT converge.\n");
                printf("Note: This is normal if you are using the "
                       "default settings.\n");
        }
}

variable_types: err int

variable_types: t int