#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
unsigned char *calloc(size_t, int);
int /*<<< orphan*/ free(unsigned char *);
size_t index_to_offset(size_t, size_t *, size_t *);
unsigned char *malloc(size_t);
int /*<<< orphan*/ memcpy(unsigned char *, unsigned char *, size_t);
int /*<<< orphan*/ offset_to_index(size_t, size_t const *, size_t, size_t *);
void restructure_array(size_t ndims, unsigned char *array,
                       const size_t *lengths_perm, size_t el_size,
                       const int *map, const int *dir) {
  size_t index[1000];
  size_t index_perm[1000];
  size_t lengths[1000];
  unsigned char *temp;
  size_t offset_start;
  size_t offset_next;
  size_t offset;
  unsigned char *bitmap;
  size_t total;
  size_t i;
  if ((temp = malloc(el_size)) == NULL) {
    return;
  }
  for (i = 0; i < ndims; i++) {
    lengths[map[i]] = lengths_perm[i];
  }
  total = 1;
  for (i = 0; i < ndims; i++) {
    total *= lengths[i];
  }
  bitmap = calloc((total + 8 - 1) / 8, 1);
  if (bitmap == NULL) {
    free(temp);
    return;
  }
  for (offset_start = 0; offset_start < total; offset_start++) {
    if (!(bitmap[(offset_start) / 8] & (1 << ((offset_start) % 8)))) {
      offset_next = -1;
      memcpy(temp, array + (offset_start * el_size), el_size);
      (bitmap[(offset_start) / 8] |= (1 << ((offset_start) % 8)));
      offset = offset_start;
      while (offset_next != offset_start) {
        offset_to_index(ndims, lengths_perm, offset, index_perm);
        for (i = 0; i < ndims; i++) {
          if (dir[i] < 0) {
            index[map[i]] = lengths[map[i]] - index_perm[i] - 1;
          } else {
            index[map[i]] = index_perm[i];
          }
        }
        offset_next = index_to_offset(ndims, lengths, index);
        if (offset_next != offset_start) {
          (bitmap[(offset_next) / 8] |= (1 << ((offset_next) % 8)));
          memcpy(array + (offset * el_size), array + (offset_next * el_size),
                 el_size);
          offset = offset_next;
        }
      }
      memcpy(array + (offset * el_size), temp, el_size);
    }
  }
  free(bitmap);
  free(temp);
}


x86 assembly (clang, -O0):
<restructure_array>:
push   %rbp
mov    %rsp,%rbp
sub    $0x5e30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    %r9,-0x30(%rbp)
mov    -0x20(%rbp),%rdi
call   1080 <malloc@plt>
mov    %rax,-0x5df8(%rbp)
cmp    $0x0,%rax
jne    11a2 <restructure_array+0x42>
jmp    153b <restructure_array+0x3db>
movq   $0x0,-0x5e28(%rbp)
mov    -0x5e28(%rbp),%rax
cmp    -0x8(%rbp),%rax
jae    11fb <restructure_array+0x9b>
mov    -0x18(%rbp),%rax
mov    -0x5e28(%rbp),%rcx
mov    (%rax,%rcx,8),%rcx
mov    -0x28(%rbp),%rax
mov    -0x5e28(%rbp),%rdx
movslq (%rax,%rdx,4),%rax
mov    %rcx,-0x5df0(%rbp,%rax,8)
ff
mov    -0x5e28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x5e28(%rbp)
jmp    11ad <restructure_array+0x4d>
movq   $0x1,-0x5e20(%rbp)
movq   $0x0,-0x5e28(%rbp)
mov    -0x5e28(%rbp),%rax
cmp    -0x8(%rbp),%rax
jae    1257 <restructure_array+0xf7>
mov    -0x5e28(%rbp),%rax
mov    -0x5df0(%rbp,%rax,8),%rax
ff
imul   -0x5e20(%rbp),%rax
ff
mov    %rax,-0x5e20(%rbp)
mov    -0x5e28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x5e28(%rbp)
jmp    1211 <restructure_array+0xb1>
mov    -0x5e20(%rbp),%rdi
add    $0x8,%rdi
sub    $0x1,%rdi
shr    $0x3,%rdi
mov    $0x1,%esi
call   1060 <calloc@plt>
mov    %rax,-0x5e18(%rbp)
cmpq   $0x0,-0x5e18(%rbp)
jne    129a <restructure_array+0x13a>
mov    -0x5df8(%rbp),%rdi
call   1030 <free@plt>
jmp    153b <restructure_array+0x3db>
movq   $0x0,-0x5e00(%rbp)
mov    -0x5e00(%rbp),%rax
cmp    -0x5e20(%rbp),%rax
jae    1523 <restructure_array+0x3c3>
mov    -0x5e18(%rbp),%rax
mov    -0x5e00(%rbp),%rcx
shr    $0x3,%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x5e00(%rbp),%rcx
and    $0x7,%rcx
mov    $0x1,%edx
shl    %cl,%edx
mov    %edx,%ecx
and    %ecx,%eax
cmp    $0x0,%eax
jne    1507 <restructure_array+0x3a7>
movq   $0xffffffffffffffff,-0x5e08(%rbp)
ff ff ff ff
mov    -0x5df8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    -0x5e00(%rbp),%rax
imul   -0x20(%rbp),%rax
add    %rax,%rsi
mov    -0x20(%rbp),%rdx
call   1070 <memcpy@plt>
mov    -0x5e00(%rbp),%rax
and    $0x7,%rax
mov    %eax,%ecx
mov    $0x1,%esi
shl    %cl,%esi
mov    -0x5e18(%rbp),%rax
mov    -0x5e00(%rbp),%rcx
shr    $0x3,%rcx
movzbl (%rax,%rcx,1),%edx
or     %esi,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x5e00(%rbp),%rax
mov    %rax,-0x5e10(%rbp)
mov    -0x5e08(%rbp),%rax
cmp    -0x5e00(%rbp),%rax
je     14e4 <restructure_array+0x384>
mov    -0x8(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    -0x5e10(%rbp),%rdx
lea    -0x3eb0(%rbp),%rcx
call   1050 <offset_to_index@plt>
movq   $0x0,-0x5e28(%rbp)
mov    -0x5e28(%rbp),%rax
cmp    -0x8(%rbp),%rax
jae    1441 <restructure_array+0x2e1>
mov    -0x30(%rbp),%rax
mov    -0x5e28(%rbp),%rcx
cmpl   $0x0,(%rax,%rcx,4)
jge    13ff <restructure_array+0x29f>
mov    -0x28(%rbp),%rax
mov    -0x5e28(%rbp),%rcx
movslq (%rax,%rcx,4),%rax
mov    -0x5df0(%rbp,%rax,8),%rcx
ff
mov    -0x5e28(%rbp),%rax
sub    -0x3eb0(%rbp,%rax,8),%rcx
ff
sub    $0x1,%rcx
mov    -0x28(%rbp),%rax
mov    -0x5e28(%rbp),%rdx
movslq (%rax,%rdx,4),%rax
mov    %rcx,-0x1f70(%rbp,%rax,8)
ff
jmp    1425 <restructure_array+0x2c5>
mov    -0x5e28(%rbp),%rax
mov    -0x3eb0(%rbp,%rax,8),%rcx
ff
mov    -0x28(%rbp),%rax
mov    -0x5e28(%rbp),%rdx
movslq (%rax,%rdx,4),%rax
mov    %rcx,-0x1f70(%rbp,%rax,8)
ff
jmp    142a <restructure_array+0x2ca>
mov    -0x5e28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x5e28(%rbp)
jmp    1393 <restructure_array+0x233>
mov    -0x8(%rbp),%rdi
lea    -0x5df0(%rbp),%rsi
lea    -0x1f70(%rbp),%rdx
call   1040 <index_to_offset@plt>
mov    %rax,-0x5e08(%rbp)
mov    -0x5e08(%rbp),%rax
cmp    -0x5e00(%rbp),%rax
je     14df <restructure_array+0x37f>
mov    -0x5e08(%rbp),%rax
and    $0x7,%rax
mov    %eax,%ecx
mov    $0x1,%esi
shl    %cl,%esi
mov    -0x5e18(%rbp),%rax
mov    -0x5e08(%rbp),%rcx
shr    $0x3,%rcx
movzbl (%rax,%rcx,1),%edx
or     %esi,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x10(%rbp),%rdi
mov    -0x5e10(%rbp),%rax
imul   -0x20(%rbp),%rax
add    %rax,%rdi
mov    -0x10(%rbp),%rsi
mov    -0x5e08(%rbp),%rax
imul   -0x20(%rbp),%rax
add    %rax,%rsi
mov    -0x20(%rbp),%rdx
call   1070 <memcpy@plt>
mov    -0x5e08(%rbp),%rax
mov    %rax,-0x5e10(%rbp)
jmp    1359 <restructure_array+0x1f9>
mov    -0x10(%rbp),%rdi
mov    -0x5e10(%rbp),%rax
imul   -0x20(%rbp),%rax
add    %rax,%rdi
mov    -0x5df8(%rbp),%rsi
mov    -0x20(%rbp),%rdx
call   1070 <memcpy@plt>
jmp    150c <restructure_array+0x3ac>
mov    -0x5e00(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x5e00(%rbp)
jmp    12a5 <restructure_array+0x145>
mov    -0x5e18(%rbp),%rdi
call   1030 <free@plt>
mov    -0x5df8(%rbp),%rdi
call   1030 <free@plt>
add    $0x5e30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<restructure_array>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x5df8,%rsp
mov    %r9,%r14
mov    %r8,%rbx
mov    %rdx,%r15
mov    %rsi,0x10(%rsp)
mov    %rdi,%r12
mov    %rcx,0x18(%rsp)
mov    %rcx,%rdi
call   1080 <malloc@plt>
mov    %rax,(%rsp)
test   %rax,%rax
je     1487 <restructure_array+0x327>
mov    $0x1,%eax
test   %r12,%r12
je     12de <restructure_array+0x17e>
lea    -0x1(%r12),%r8
mov    %r12d,%r9d
and    $0x3,%r9d
cmp    $0x3,%r8
jae    11c0 <restructure_array+0x60>
xor    %edx,%edx
jmp    1213 <restructure_array+0xb3>
mov    %r12,%rsi
and    $0xfffffffffffffffc,%rsi
xor    %edx,%edx
nopl   0x0(%rax)
mov    (%r15,%rdx,8),%rcx
movslq (%rbx,%rdx,4),%rdi
mov    %rcx,0x30(%rsp,%rdi,8)
mov    0x8(%r15,%rdx,8),%rcx
movslq 0x4(%rbx,%rdx,4),%rdi
mov    %rcx,0x30(%rsp,%rdi,8)
mov    0x10(%r15,%rdx,8),%rcx
movslq 0x8(%rbx,%rdx,4),%rdi
mov    %rcx,0x30(%rsp,%rdi,8)
mov    0x18(%r15,%rdx,8),%rcx
movslq 0xc(%rbx,%rdx,4),%rdi
mov    %rcx,0x30(%rsp,%rdi,8)
add    $0x4,%rdx
cmp    %rdx,%rsi
jne    11d0 <restructure_array+0x70>
test   %r9,%r9
je     1246 <restructure_array+0xe6>
lea    (%rbx,%rdx,4),%rsi
lea    (%r15,%rdx,8),%rdx
xor    %edi,%edi
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
mov    (%rdx,%rdi,8),%rbp
movslq (%rsi,%rdi,4),%rcx
mov    %rbp,0x30(%rsp,%rcx,8)
add    $0x1,%rdi
cmp    %rdi,%r9
jne    1230 <restructure_array+0xd0>
test   %r12,%r12
je     12de <restructure_array+0x17e>
mov    %r12d,%esi
and    $0x7,%esi
cmp    $0x7,%r8
jae    1264 <restructure_array+0x104>
mov    $0x1,%eax
xor    %ecx,%ecx
jmp    12b9 <restructure_array+0x159>
mov    %r12,%rdx
and    $0xfffffffffffffff8,%rdx
mov    $0x1,%eax
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
imul   0x30(%rsp,%rcx,8),%rax
imul   0x38(%rsp,%rcx,8),%rax
imul   0x40(%rsp,%rcx,8),%rax
imul   0x48(%rsp,%rcx,8),%rax
imul   0x50(%rsp,%rcx,8),%rax
imul   0x58(%rsp,%rcx,8),%rax
imul   0x60(%rsp,%rcx,8),%rax
imul   0x68(%rsp,%rcx,8),%rax
add    $0x8,%rcx
cmp    %rcx,%rdx
jne    1280 <restructure_array+0x120>
test   %rsi,%rsi
je     12de <restructure_array+0x17e>
lea    (%rsp,%rcx,8),%rcx
add    $0x30,%rcx
xor    %edx,%edx
nopl   0x0(%rax,%rax,1)
imul   (%rcx,%rdx,8),%rax
add    $0x1,%rdx
cmp    %rdx,%rsi
jne    12d0 <restructure_array+0x170>
lea    0x7(%rax),%rdi
shr    $0x3,%rdi
mov    $0x1,%esi
mov    %rax,%rbp
call   1060 <calloc@plt>
mov    %rax,0x8(%rsp)
test   %rax,%rax
je     1499 <restructure_array+0x339>
mov    %r15,0x28(%rsp)
test   %rbp,%rbp
je     1474 <restructure_array+0x314>
mov    %rbp,%rdx
xor    %r15d,%r15d
mov    %rbp,0x20(%rsp)
jmp    134c <restructure_array+0x1ec>
nopl   0x0(%rax)
mov    0x18(%rsp),%rdx
imul   %rdx,%r13
add    0x10(%rsp),%r13
mov    %r13,%rdi
mov    (%rsp),%rsi
call   1070 <memcpy@plt>
mov    0x20(%rsp),%rdx
add    $0x1,%r15
cmp    %rdx,%r15
je     1474 <restructure_array+0x314>
mov    %r15,%rbp
mov    %r15d,%ecx
and    $0x7,%cl
mov    $0x1,%r13d
shl    %cl,%r13d
shr    $0x3,%rbp
mov    0x8(%rsp),%rax
movzbl (%rax,%rbp,1),%eax
movzbl %cl,%ecx
bt     %ecx,%eax
jb     133f <restructure_array+0x1df>
mov    %r15,%rsi
mov    0x18(%rsp),%rdx
imul   %rdx,%rsi
add    0x10(%rsp),%rsi
mov    (%rsp),%rdi
call   1070 <memcpy@plt>
mov    0x8(%rsp),%rax
or     %r13b,(%rax,%rbp,1)
mov    %r15,%r13
nopl   0x0(%rax)
mov    %r12,%rdi
mov    0x28(%rsp),%rsi
mov    %r13,%rdx
lea    0x1f70(%rsp),%rcx
call   1050 <offset_to_index@plt>
test   %r12,%r12
je     1410 <restructure_array+0x2b0>
xor    %eax,%eax
jmp    13ed <restructure_array+0x28d>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    0x1f70(%rsp,%rax,8),%rdx
movslq (%rbx,%rax,4),%rcx
mov    %rdx,0x3eb0(%rsp,%rcx,8)
add    $0x1,%rax
cmp    %rax,%r12
je     1410 <restructure_array+0x2b0>
cmpl   $0x0,(%r14,%rax,4)
jns    13d0 <restructure_array+0x270>
movslq (%rbx,%rax,4),%rcx
mov    0x1f70(%rsp,%rax,8),%rdx
not    %rdx
add    0x30(%rsp,%rcx,8),%rdx
jmp    13dc <restructure_array+0x27c>
nopw   0x0(%rax,%rax,1)
mov    %r12,%rdi
lea    0x30(%rsp),%rsi
lea    0x3eb0(%rsp),%rdx
call   1040 <index_to_offset@plt>
cmp    %r15,%rax
je     1320 <restructure_array+0x1c0>
mov    %rax,%rbp
mov    %ebp,%ecx
and    $0x7,%cl
mov    $0x1,%al
shl    %cl,%al
mov    %rbp,%rcx
shr    $0x3,%rcx
mov    0x8(%rsp),%rdx
or     %al,(%rdx,%rcx,1)
mov    0x18(%rsp),%rdx
imul   %rdx,%r13
mov    0x10(%rsp),%rax
add    %rax,%r13
mov    %rbp,%rsi
imul   %rdx,%rsi
add    %rax,%rsi
mov    %r13,%rdi
call   1070 <memcpy@plt>
mov    %rbp,%r13
jmp    13a0 <restructure_array+0x240>
mov    0x8(%rsp),%rdi
call   1030 <free@plt>
mov    (%rsp),%rdi
call   1030 <free@plt>
add    $0x5df8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret
mov    (%rsp),%rdi
add    $0x5df8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
jmp    1030 <free@plt>

LLVM IR (-O0):
define void @restructure_array(i64 %0, i8* %1, i64* %2, i64 %3, i32* %4, i32* %5) {
%7 = alloca i64
%8 = alloca i8*
%9 = alloca i64*
%10 = alloca i64
%11 = alloca i32*
%12 = alloca i32*
%13 = alloca [1000 x i64]
%14 = alloca [1000 x i64]
%15 = alloca [1000 x i64]
%16 = alloca i8*
%17 = alloca i64
%18 = alloca i64
%19 = alloca i64
%20 = alloca i8*
%21 = alloca i64
%22 = alloca i64
store i64 %0, i64* %7
store i8* %1, i8** %8
store i64* %2, i64** %9
store i64 %3, i64* %10
store i32* %4, i32** %11
store i32* %5, i32** %12
%23 = load i64, i64* %10
%24 = call i8* @malloc(i64 %23)
store i8* %24, i8** %16
%25 = icmp eq i8* %24, null
br i1 %25, label %26, label %27
26: ; preds = %6
br label %217
27: ; preds = %6
store i64 0, i64* %22
br label %28
28: ; preds = %43, %27
%29 = load i64, i64* %22
%30 = load i64, i64* %7
%31 = icmp ult i64 %29, %30
br i1 %31, label %32, label %46
32: ; preds = %28
%33 = load i64*, i64** %9
%34 = load i64, i64* %22
%35 = getelementptr inbounds i64, i64* %33, i64 %34
%36 = load i64, i64* %35
%37 = load i32*, i32** %11
%38 = load i64, i64* %22
%39 = getelementptr inbounds i32, i32* %37, i64 %38
%40 = load i32, i32* %39
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds [1000 x i64], [1000 x i64]* %15, i64 0, i64 %41
store i64 %36, i64* %42
br label %43
43: ; preds = %32
%44 = load i64, i64* %22
%45 = add i64 %44, 1
store i64 %45, i64* %22
br label %28
46: ; preds = %28
store i64 1, i64* %21
store i64 0, i64* %22
br label %47
47: ; preds = %57, %46
%48 = load i64, i64* %22
%49 = load i64, i64* %7
%50 = icmp ult i64 %48, %49
br i1 %50, label %51, label %60
51: ; preds = %47
%52 = load i64, i64* %22
%53 = getelementptr inbounds [1000 x i64], [1000 x i64]* %15, i64 0, i64 %52
%54 = load i64, i64* %53
%55 = load i64, i64* %21
%56 = mul i64 %55, %54
store i64 %56, i64* %21
br label %57
57: ; preds = %51
%58 = load i64, i64* %22
%59 = add i64 %58, 1
store i64 %59, i64* %22
br label %47
60: ; preds = %47
%61 = load i64, i64* %21
%62 = add i64 %61, 8
%63 = sub i64 %62, 1
%64 = udiv i64 %63, 8
%65 = call i8* @calloc(i64 %64, i32 1)
store i8* %65, i8** %20
%66 = load i8*, i8** %20
%67 = icmp eq i8* %66, null
br i1 %67, label %68, label %71
68: ; preds = %60
%69 = load i8*, i8** %16
%70 = call i32 @free(i8* %69)
br label %217
71: ; preds = %60
store i64 0, i64* %17
br label %72
72: ; preds = %209, %71
%73 = load i64, i64* %17
%74 = load i64, i64* %21
%75 = icmp ult i64 %73, %74
br i1 %75, label %76, label %212
76: ; preds = %72
%77 = load i8*, i8** %20
%78 = load i64, i64* %17
%79 = udiv i64 %78, 8
%80 = getelementptr inbounds i8, i8* %77, i64 %79
%81 = load i8, i8* %80
%82 = zext i8 %81 to i32
%83 = load i64, i64* %17
%84 = urem i64 %83, 8
%85 = trunc i64 %84 to i32
%86 = shl i32 1, %85
%87 = and i32 %82, %86
%88 = icmp ne i32 %87, 0
br i1 %88, label %208, label %89
89: ; preds = %76
store i64 -1, i64* %18
%90 = load i8*, i8** %16
%91 = load i8*, i8** %8
%92 = load i64, i64* %17
%93 = load i64, i64* %10
%94 = mul i64 %92, %93
%95 = getelementptr inbounds i8, i8* %91, i64 %94
%96 = load i64, i64* %10
%97 = call i32 @memcpy(i8* %90, i8* %95, i64 %96)
%98 = load i64, i64* %17
%99 = urem i64 %98, 8
%100 = trunc i64 %99 to i32
%101 = shl i32 1, %100
%102 = load i8*, i8** %20
%103 = load i64, i64* %17
%104 = udiv i64 %103, 8
%105 = getelementptr inbounds i8, i8* %102, i64 %104
%106 = load i8, i8* %105
%107 = zext i8 %106 to i32
%108 = or i32 %107, %101
%109 = trunc i32 %108 to i8
store i8 %109, i8* %105
%110 = load i64, i64* %17
store i64 %110, i64* %19
br label %111
111: ; preds = %198, %89
%112 = load i64, i64* %18
%113 = load i64, i64* %17
%114 = icmp ne i64 %112, %113
br i1 %114, label %115, label %199
115: ; preds = %111
%116 = load i64, i64* %7
%117 = load i64*, i64** %9
%118 = load i64, i64* %19
%119 = getelementptr inbounds [1000 x i64], [1000 x i64]* %14, i64 0, i64 0
%120 = call i32 @offset_to_index(i64 %116, i64* %117, i64 %118, i64* %119)
store i64 0, i64* %22
br label %121
121: ; preds = %161, %115
%122 = load i64, i64* %22
%123 = load i64, i64* %7
%124 = icmp ult i64 %122, %123
br i1 %124, label %125, label %164
125: ; preds = %121
%126 = load i32*, i32** %12
%127 = load i64, i64* %22
%128 = getelementptr inbounds i32, i32* %126, i64 %127
%129 = load i32, i32* %128
%130 = icmp slt i32 %129, 0
br i1 %130, label %131, label %150
131: ; preds = %125
%132 = load i32*, i32** %11
%133 = load i64, i64* %22
%134 = getelementptr inbounds i32, i32* %132, i64 %133
%135 = load i32, i32* %134
%136 = sext i32 %135 to i64
%137 = getelementptr inbounds [1000 x i64], [1000 x i64]* %15, i64 0, i64 %136
%138 = load i64, i64* %137
%139 = load i64, i64* %22
%140 = getelementptr inbounds [1000 x i64], [1000 x i64]* %14, i64 0, i64 %139
%141 = load i64, i64* %140
%142 = sub i64 %138, %141
%143 = sub i64 %142, 1
%144 = load i32*, i32** %11
%145 = load i64, i64* %22
%146 = getelementptr inbounds i32, i32* %144, i64 %145
%147 = load i32, i32* %146
%148 = sext i32 %147 to i64
%149 = getelementptr inbounds [1000 x i64], [1000 x i64]* %13, i64 0, i64 %148
store i64 %143, i64* %149
br label %160
150: ; preds = %125
%151 = load i64, i64* %22
%152 = getelementptr inbounds [1000 x i64], [1000 x i64]* %14, i64 0, i64 %151
%153 = load i64, i64* %152
%154 = load i32*, i32** %11
%155 = load i64, i64* %22
%156 = getelementptr inbounds i32, i32* %154, i64 %155
%157 = load i32, i32* %156
%158 = sext i32 %157 to i64
%159 = getelementptr inbounds [1000 x i64], [1000 x i64]* %13, i64 0, i64 %158
store i64 %153, i64* %159
br label %160
160: ; preds = %150, %131
br label %161
161: ; preds = %160
%162 = load i64, i64* %22
%163 = add i64 %162, 1
store i64 %163, i64* %22
br label %121
164: ; preds = %121
%165 = load i64, i64* %7
%166 = getelementptr inbounds [1000 x i64], [1000 x i64]* %15, i64 0, i64 0
%167 = getelementptr inbounds [1000 x i64], [1000 x i64]* %13, i64 0, i64 0
%168 = call i64 @index_to_offset(i64 %165, i64* %166, i64* %167)
store i64 %168, i64* %18
%169 = load i64, i64* %18
%170 = load i64, i64* %17
%171 = icmp ne i64 %169, %170
br i1 %171, label %172, label %198
172: ; preds = %164
%173 = load i64, i64* %18
%174 = urem i64 %173, 8
%175 = trunc i64 %174 to i32
%176 = shl i32 1, %175
%177 = load i8*, i8** %20
%178 = load i64, i64* %18
%179 = udiv i64 %178, 8
%180 = getelementptr inbounds i8, i8* %177, i64 %179
%181 = load i8, i8* %180
%182 = zext i8 %181 to i32
%183 = or i32 %182, %176
%184 = trunc i32 %183 to i8
store i8 %184, i8* %180
%185 = load i8*, i8** %8
%186 = load i64, i64* %19
%187 = load i64, i64* %10
%188 = mul i64 %186, %187
%189 = getelementptr inbounds i8, i8* %185, i64 %188
%190 = load i8*, i8** %8
%191 = load i64, i64* %18
%192 = load i64, i64* %10
%193 = mul i64 %191, %192
%194 = getelementptr inbounds i8, i8* %190, i64 %193
%195 = load i64, i64* %10
%196 = call i32 @memcpy(i8* %189, i8* %194, i64 %195)
%197 = load i64, i64* %18
store i64 %197, i64* %19
br label %198
198: ; preds = %172, %164
br label %111
199: ; preds = %111
%200 = load i8*, i8** %8
%201 = load i64, i64* %19
%202 = load i64, i64* %10
%203 = mul i64 %201, %202
%204 = getelementptr inbounds i8, i8* %200, i64 %203
%205 = load i8*, i8** %16
%206 = load i64, i64* %10
%207 = call i32 @memcpy(i8* %204, i8* %205, i64 %206)
br label %208
208: ; preds = %199, %76
br label %209
209: ; preds = %208
%210 = load i64, i64* %17
%211 = add i64 %210, 1
store i64 %211, i64* %17
br label %72
212: ; preds = %72
%213 = load i8*, i8** %20
%214 = call i32 @free(i8* %213)
%215 = load i8*, i8** %16
%216 = call i32 @free(i8* %215)
br label %217
217: ; preds = %212, %68, %26
ret void
}

LLVM IR (-O2):
define void @restructure_array(i64 %0, i8* %1, i64* %2, i64 %3, i32* nocapture %4, i32* nocapture %5) {
%7 = alloca [1000 x i64]
%8 = alloca [1000 x i64]
%9 = alloca [1000 x i64]
%10 = bitcast [1000 x i64]* %7 to i8*
%11 = bitcast [1000 x i64]* %8 to i8*
%12 = bitcast [1000 x i64]* %9 to i8*
%13 = tail call i8* @malloc(i64 %3)
%14 = icmp eq i8* %13, null
br i1 %14, label %218, label %15
15: ; preds = %6
%16 = icmp eq i64 %0, 0
br i1 %16, label %130, label %17
17: ; preds = %15
%18 = add i64 %0, -1
%19 = and i64 %0, 3
%20 = icmp ult i64 %18, 3
br i1 %20, label %23, label %21
21: ; preds = %17
%22 = and i64 %0, -4
br label %44
23: ; preds = %44, %17
%24 = phi i64 [ 0, %17 ], [ %74, %44 ]
%25 = icmp eq i64 %19, 0
br i1 %25, label %38, label %26
26: ; preds = %23, %26
%27 = phi i64 [ %35, %26 ], [ %24, %23 ]
%28 = phi i64 [ %36, %26 ], [ 0, %23 ]
%29 = getelementptr inbounds i64, i64* %2, i64 %27
%30 = load i64, i64* %29
%31 = getelementptr inbounds i32, i32* %4, i64 %27
%32 = load i32, i32* %31
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %33
store i64 %30, i64* %34
%35 = add nuw i64 %27, 1
%36 = add i64 %28, 1
%37 = icmp eq i64 %36, %19
br i1 %37, label %38, label %26
38: ; preds = %26, %23
br i1 %16, label %130, label %39
39: ; preds = %38
%40 = and i64 %0, 7
%41 = icmp ult i64 %18, 7
br i1 %41, label %115, label %42
42: ; preds = %39
%43 = and i64 %0, -8
br label %77
44: ; preds = %44, %21
%45 = phi i64 [ 0, %21 ], [ %74, %44 ]
%46 = phi i64 [ 0, %21 ], [ %75, %44 ]
%47 = getelementptr inbounds i64, i64* %2, i64 %45
%48 = load i64, i64* %47
%49 = getelementptr inbounds i32, i32* %4, i64 %45
%50 = load i32, i32* %49
%51 = sext i32 %50 to i64
%52 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %51
store i64 %48, i64* %52
%53 = or i64 %45, 1
%54 = getelementptr inbounds i64, i64* %2, i64 %53
%55 = load i64, i64* %54
%56 = getelementptr inbounds i32, i32* %4, i64 %53
%57 = load i32, i32* %56
%58 = sext i32 %57 to i64
%59 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %58
store i64 %55, i64* %59
%60 = or i64 %45, 2
%61 = getelementptr inbounds i64, i64* %2, i64 %60
%62 = load i64, i64* %61
%63 = getelementptr inbounds i32, i32* %4, i64 %60
%64 = load i32, i32* %63
%65 = sext i32 %64 to i64
%66 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %65
store i64 %62, i64* %66
%67 = or i64 %45, 3
%68 = getelementptr inbounds i64, i64* %2, i64 %67
%69 = load i64, i64* %68
%70 = getelementptr inbounds i32, i32* %4, i64 %67
%71 = load i32, i32* %70
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %72
store i64 %69, i64* %73
%74 = add nuw i64 %45, 4
%75 = add i64 %46, 4
%76 = icmp eq i64 %75, %22
br i1 %76, label %23, label %44
77: ; preds = %77, %42
%78 = phi i64 [ 0, %42 ], [ %112, %77 ]
%79 = phi i64 [ 1, %42 ], [ %111, %77 ]
%80 = phi i64 [ 0, %42 ], [ %113, %77 ]
%81 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %78
%82 = load i64, i64* %81
%83 = mul i64 %82, %79
%84 = or i64 %78, 1
%85 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %84
%86 = load i64, i64* %85
%87 = mul i64 %86, %83
%88 = or i64 %78, 2
%89 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %88
%90 = load i64, i64* %89
%91 = mul i64 %90, %87
%92 = or i64 %78, 3
%93 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %92
%94 = load i64, i64* %93
%95 = mul i64 %94, %91
%96 = or i64 %78, 4
%97 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %96
%98 = load i64, i64* %97
%99 = mul i64 %98, %95
%100 = or i64 %78, 5
%101 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %100
%102 = load i64, i64* %101
%103 = mul i64 %102, %99
%104 = or i64 %78, 6
%105 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %104
%106 = load i64, i64* %105
%107 = mul i64 %106, %103
%108 = or i64 %78, 7
%109 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %108
%110 = load i64, i64* %109
%111 = mul i64 %110, %107
%112 = add nuw i64 %78, 8
%113 = add i64 %80, 8
%114 = icmp eq i64 %113, %43
br i1 %114, label %115, label %77
115: ; preds = %77, %39
%116 = phi i64 [ undef, %39 ], [ %111, %77 ]
%117 = phi i64 [ 0, %39 ], [ %112, %77 ]
%118 = phi i64 [ 1, %39 ], [ %111, %77 ]
%119 = icmp eq i64 %40, 0
br i1 %119, label %130, label %120
120: ; preds = %115, %120
%121 = phi i64 [ %127, %120 ], [ %117, %115 ]
%122 = phi i64 [ %126, %120 ], [ %118, %115 ]
%123 = phi i64 [ %128, %120 ], [ 0, %115 ]
%124 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %121
%125 = load i64, i64* %124
%126 = mul i64 %125, %122
%127 = add nuw i64 %121, 1
%128 = add i64 %123, 1
%129 = icmp eq i64 %128, %40
br i1 %129, label %130, label %120
130: ; preds = %115, %120, %15, %38
%131 = phi i64 [ 1, %38 ], [ 1, %15 ], [ %116, %115 ], [ %126, %120 ]
%132 = add i64 %131, 7
%133 = lshr i64 %132, 3
%134 = tail call i8* @calloc(i64 %133, i32 1)
%135 = icmp eq i8* %134, null
br i1 %135, label %142, label %136
136: ; preds = %130
%137 = icmp eq i64 %131, 0
br i1 %137, label %215, label %138
138: ; preds = %136
%139 = getelementptr inbounds [1000 x i64], [1000 x i64]* %8, i64 0, i64 0
%140 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 0
%141 = getelementptr inbounds [1000 x i64], [1000 x i64]* %7, i64 0, i64 0
br label %144
142: ; preds = %130
%143 = tail call i32 @free(i8* %13)
br label %218
144: ; preds = %138, %212
%145 = phi i64 [ 0, %138 ], [ %213, %212 ]
%146 = lshr i64 %145, 3
%147 = getelementptr inbounds i8, i8* %134, i64 %146
%148 = load i8, i8* %147
%149 = zext i8 %148 to i32
%150 = trunc i64 %145 to i32
%151 = and i32 %150, 7
%152 = shl nuw nsw i32 1, %151
%153 = and i32 %152, %149
%154 = icmp eq i32 %153, 0
br i1 %154, label %155, label %212
155: ; preds = %144
%156 = mul i64 %145, %3
%157 = getelementptr inbounds i8, i8* %1, i64 %156
%158 = call i32 @memcpy(i8* %13, i8* %157, i64 %3)
%159 = load i8, i8* %147
%160 = trunc i32 %152 to i8
%161 = or i8 %159, %160
store i8 %161, i8* %147
br label %162
162: ; preds = %195, %155
%163 = phi i64 [ %193, %195 ], [ %145, %155 ]
%164 = call i32 @offset_to_index(i64 %0, i64* %2, i64 %163, i64* %139)
br i1 %16, label %192, label %165
165: ; preds = %162, %186
%166 = phi i64 [ %190, %186 ], [ 0, %162 ]
%167 = getelementptr inbounds i32, i32* %5, i64 %166
%168 = load i32, i32* %167
%169 = icmp slt i32 %168, 0
br i1 %169, label %170, label %180
170: ; preds = %165
%171 = getelementptr inbounds i32, i32* %4, i64 %166
%172 = load i32, i32* %171
%173 = sext i32 %172 to i64
%174 = getelementptr inbounds [1000 x i64], [1000 x i64]* %9, i64 0, i64 %173
%175 = load i64, i64* %174
%176 = getelementptr inbounds [1000 x i64], [1000 x i64]* %8, i64 0, i64 %166
%177 = load i64, i64* %176
%178 = xor i64 %177, -1
%179 = add i64 %175, %178
br label %186
180: ; preds = %165
%181 = getelementptr inbounds [1000 x i64], [1000 x i64]* %8, i64 0, i64 %166
%182 = load i64, i64* %181
%183 = getelementptr inbounds i32, i32* %4, i64 %166
%184 = load i32, i32* %183
%185 = sext i32 %184 to i64
br label %186
186: ; preds = %170, %180
%187 = phi i64 [ %173, %170 ], [ %185, %180 ]
%188 = phi i64 [ %179, %170 ], [ %182, %180 ]
%189 = getelementptr inbounds [1000 x i64], [1000 x i64]* %7, i64 0, i64 %187
store i64 %188, i64* %189
%190 = add nuw i64 %166, 1
%191 = icmp eq i64 %190, %0
br i1 %191, label %192, label %165
192: ; preds = %186, %162
%193 = call i64 @index_to_offset(i64 %0, i64* %140, i64* %141)
%194 = icmp eq i64 %193, %145
br i1 %194, label %208, label %195
195: ; preds = %192
%196 = trunc i64 %193 to i8
%197 = and i8 %196, 7
%198 = shl nuw i8 1, %197
%199 = lshr i64 %193, 3
%200 = getelementptr inbounds i8, i8* %134, i64 %199
%201 = load i8, i8* %200
%202 = or i8 %201, %198
store i8 %202, i8* %200
%203 = mul i64 %163, %3
%204 = getelementptr inbounds i8, i8* %1, i64 %203
%205 = mul i64 %193, %3
%206 = getelementptr inbounds i8, i8* %1, i64 %205
%207 = call i32 @memcpy(i8* %204, i8* %206, i64 %3)
br label %162
208: ; preds = %192
%209 = mul i64 %163, %3
%210 = getelementptr inbounds i8, i8* %1, i64 %209
%211 = call i32 @memcpy(i8* %210, i8* %13, i64 %3)
br label %212
212: ; preds = %144, %208
%213 = add nuw i64 %145, 1
%214 = icmp eq i64 %213, %131
br i1 %214, label %215, label %144
215: ; preds = %212, %136
%216 = call i32 @free(i8* %134)
%217 = call i32 @free(i8* %13)
br label %218
218: ; preds = %6, %215, %142
ret void
}