#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 */
struct timeval {
  int tv_sec;
  double tv_usec;
};

/* Variables and functions */
int /*<<< orphan*/ acc_device_default;
int /*<<< orphan*/ acc_init(int /*<<< orphan*/);
int /*<<< orphan*/ gettimeofday(struct timeval *, int /*<<< orphan*/ *);
scalar_t__ malloc(int);
int /*<<< orphan*/ printf(char *, ...);
int rand();
int /*<<< orphan*/ srand(unsigned int);
scalar_t__ time(int /*<<< orphan*/);
int main() {
  int i, j, k;
  int sum, known_sum;
  int NI, NJ, NK;
  int error;
  int *input, *temp;
  struct timeval tim;
  double start, end;
  NK = 1 << 20;
  NJ = 2;
  NI = 32;
  input = (int *)malloc(NK * NJ * NI * sizeof(int));
  temp = (int *)malloc(NK * NJ * NI * sizeof(int));
  error = 0;
  acc_init(acc_device_default);
  srand((unsigned)time(0));
  for (k = 0; k < NK; k++) {
    for (j = 0; j < NJ; j++) {
      for (i = 0; i < NI; i++) {
        input[k * NJ * NI + j * NI + i] = rand() % 5 + 1;
      }
    }
  }
  int product = 1;
  gettimeofday(&tim, NULL);
  start = tim.tv_sec * 1000 + (tim.tv_usec / 1000.0);
#pragma acc parallel copyin(input [0:NK * NJ * NI])                            \
    create(temp [0:NK * NJ * NI]) num_gangs(192) num_workers(8)                \
        vector_length(128)
  {
#pragma acc loop gang reduction(* : product)
    for (k = 0; k < NK; k++) {
#pragma acc loop worker
      for (j = 0; j < NJ; j++) {
#pragma acc loop vector
        for (i = 0; i < NI; i++)
          temp[k * NJ * NI + j * NI + i] = input[k * NJ * NI + j * NI + i];
      }
      product *= temp[k * NJ * NI];
    }
  }
  gettimeofday(&tim, NULL);
  end = tim.tv_sec * 1000 + (tim.tv_usec / 1000.0);
  int known_product = 1;
  for (k = 0; k < NK; k++)
    known_product *= input[k * NJ * NI];
  if (product != known_product) {
    error++;
    printf("gang * FAILED! product=%d, known_product=%d\n", product,
           known_product);
  }
  printf("gang * execution time is :%.2lf: ms\n", end - start);
  if (error == 0)
    printf("gang * SUCCESS!\n");
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movl   $0x0,-0x4(%rbp)
movl   $0x100000,-0x24(%rbp)
movl   $0x2,-0x20(%rbp)
movl   $0x20,-0x1c(%rbp)
mov    -0x24(%rbp),%eax
imul   -0x20(%rbp),%eax
imul   -0x1c(%rbp),%eax
cltq
shl    $0x2,%rax
mov    %eax,%edi
call   1070 <malloc@plt>
mov    %rax,-0x30(%rbp)
mov    -0x24(%rbp),%eax
imul   -0x20(%rbp),%eax
imul   -0x1c(%rbp),%eax
cltq
shl    $0x2,%rax
mov    %eax,%edi
call   1070 <malloc@plt>
mov    %rax,-0x38(%rbp)
movl   $0x0,-0x28(%rbp)
mov    0x2e06(%rip),%rax
mov    (%rax),%edi
call   1080 <acc_init@plt>
xor    %edi,%edi
call   1060 <time@plt>
mov    %eax,%edi
call   1050 <srand@plt>
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    128f <main+0x11f>
movl   $0x0,-0xc(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    127c <main+0x10c>
movl   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    1269 <main+0xf9>
mov    $0x0,%al
call   1090 <rand@plt>
mov    $0x5,%ecx
cltd
idiv   %ecx
add    $0x1,%edx
mov    -0x30(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
mov    -0xc(%rbp),%esi
imul   -0x1c(%rbp),%esi
add    %esi,%ecx
add    -0x8(%rbp),%ecx
movslq %ecx,%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    121c <main+0xac>
jmp    126e <main+0xfe>
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    1209 <main+0x99>
jmp    1281 <main+0x111>
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    11f6 <main+0x86>
movl   $0x1,-0x5c(%rbp)
lea    -0x48(%rbp),%rdi
xor    %eax,%eax
mov    %eax,%esi
call   1040 <gettimeofday@plt>
imul   $0x3e8,-0x48(%rbp),%eax
cvtsi2sd %eax,%xmm0
movsd  -0x40(%rbp),%xmm1
movsd  0xd45(%rip),%xmm2
divsd  %xmm2,%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x50(%rbp)
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    138e <main+0x21e>
movl   $0x0,-0xc(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    1364 <main+0x1f4>
movl   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    1351 <main+0x1e1>
mov    -0x30(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
mov    -0xc(%rbp),%edx
imul   -0x1c(%rbp),%edx
add    %edx,%ecx
add    -0x8(%rbp),%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%edx
mov    -0x38(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
mov    -0xc(%rbp),%esi
imul   -0x1c(%rbp),%esi
add    %esi,%ecx
add    -0x8(%rbp),%ecx
movslq %ecx,%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x8(%rbp)
jmp    12f5 <main+0x185>
jmp    1356 <main+0x1e6>
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    12e2 <main+0x172>
mov    -0x38(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
imul   -0x5c(%rbp),%eax
mov    %eax,-0x5c(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    12cf <main+0x15f>
lea    -0x48(%rbp),%rdi
xor    %eax,%eax
mov    %eax,%esi
call   1040 <gettimeofday@plt>
imul   $0x3e8,-0x48(%rbp),%eax
cvtsi2sd %eax,%xmm0
movsd  -0x40(%rbp),%xmm1
movsd  0xc4d(%rip),%xmm2
divsd  %xmm2,%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movl   $0x1,-0x60(%rbp)
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    1404 <main+0x294>
mov    -0x30(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
imul   -0x60(%rbp),%eax
mov    %eax,-0x60(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    13ce <main+0x25e>
mov    -0x5c(%rbp),%eax
cmp    -0x60(%rbp),%eax
je     142d <main+0x2bd>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
mov    -0x5c(%rbp),%esi
mov    -0x60(%rbp),%edx
lea    0xbe2(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
movsd  -0x58(%rbp),%xmm0
subsd  -0x50(%rbp),%xmm0
lea    0xbf7(%rip),%rdi
mov    $0x1,%al
call   1030 <printf@plt>
cmpl   $0x0,-0x28(%rbp)
jne    145d <main+0x2ed>
lea    0xc04(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
mov    -0x4(%rbp),%eax
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x28,%rsp
mov    $0x10000000,%edi
call   1080 <malloc@plt>
mov    %rax,%r12
mov    $0x10000000,%edi
call   1080 <malloc@plt>
mov    %rax,%r14
mov    0x2e31(%rip),%rax
mov    (%rax),%edi
call   1090 <acc_init@plt>
xor    %edi,%edi
call   1070 <time@plt>
mov    %eax,%edi
call   1060 <srand@plt>
mov    %r12,%rbx
xor    %r15d,%r15d
nopw   0x0(%rax,%rax,1)
xor    %ebp,%ebp
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
xor    %eax,%eax
call   10a0 <rand@plt>
cltq
imul   $0x66666667,%rax,%rcx
mov    %rcx,%rdx
shr    $0x3f,%rdx
sar    $0x21,%rcx
add    %edx,%ecx
lea    (%rcx,%rcx,4),%ecx
neg    %ecx
add    %ecx,%eax
add    $0x1,%eax
mov    %eax,(%rbx,%rbp,4)
add    $0x1,%rbp
cmp    $0x20,%rbp
jne    11e0 <main+0x60>
mov    $0x20,%ebp
nopl   0x0(%rax)
xor    %eax,%eax
call   10a0 <rand@plt>
cltq
imul   $0x66666667,%rax,%rcx
mov    %rcx,%rdx
shr    $0x3f,%rdx
sar    $0x21,%rcx
add    %edx,%ecx
lea    (%rcx,%rcx,4),%ecx
neg    %ecx
add    %ecx,%eax
add    $0x1,%eax
mov    %eax,(%rbx,%rbp,4)
add    $0x1,%rbp
cmp    $0x40,%rbp
jne    1220 <main+0xa0>
add    $0x1,%r15
add    $0x100,%rbx
cmp    $0x100000,%r15
jne    11d0 <main+0x50>
xor    %r13d,%r13d
lea    0x18(%rsp),%rdi
xor    %esi,%esi
call   1050 <gettimeofday@plt>
imul   $0x3e8,0x18(%rsp),%r8d
movsd  0x20(%rsp),%xmm1
divsd  0xd6e(%rip),%xmm1
lea    0xc(%r14),%rcx
lea    0xc(%r12),%rdx
lea    0x8c(%r14),%rsi
lea    0x8c(%r12),%rdi
mov    $0x1,%r15d
jmp    1393 <main+0x213>
cs nopw 0x0(%rax,%rax,1)
nop
mov    %r11,%rax
or     $0x20,%rax
movups (%r12,%rax,4),%xmm0
movups %xmm0,(%r14,%rax,4)
lea    0x0(,%r11,4),%rax
mov    %rax,%rbp
or     $0x90,%rbp
movups (%r12,%rbp,1),%xmm0
movups %xmm0,(%r14,%rbp,1)
mov    %rax,%rbp
or     $0xa0,%rbp
movups (%r12,%rbp,1),%xmm0
movups %xmm0,(%r14,%rbp,1)
mov    %rax,%rbp
or     $0xb0,%rbp
movups (%r12,%rbp,1),%xmm0
movups %xmm0,(%r14,%rbp,1)
mov    %rax,%rbp
or     $0xc0,%rbp
movups (%r12,%rbp,1),%xmm0
movups %xmm0,(%r14,%rbp,1)
mov    %rax,%rbp
or     $0xd0,%rbp
movups (%r12,%rbp,1),%xmm0
movups %xmm0,(%r14,%rbp,1)
mov    %rax,%rbp
or     $0xe0,%rbp
movups (%r12,%rbp,1),%xmm0
movups %xmm0,(%r14,%rbp,1)
or     $0xf0,%rax
movups (%r12,%rax,1),%xmm0
movups %xmm0,(%r14,%rax,1)
imul   (%r14,%r11,4),%r15d
add    $0x1,%r13
add    $0x100,%rcx
add    $0x100,%rdx
add    $0x100,%rsi
add    $0x100,%rdi
cmp    $0x100000,%r13
je     14dd <main+0x35d>
mov    %r13,%r11
shl    $0x6,%r11
mov    %r13,%rbp
shl    $0x8,%rbp
lea    (%r14,%rbp,1),%r10
add    $0x80,%r10
lea    (%r12,%rbp,1),%r9
add    $0x80,%r9
lea    (%r14,%rbp,1),%rax
cmp    %r9,%rax
jae    1400 <main+0x280>
lea    (%r12,%rbp,1),%rax
cmp    %r10,%rax
jae    1400 <main+0x280>
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
mov    -0xc(%rdx,%rax,4),%ebx
mov    %ebx,-0xc(%rcx,%rax,4)
mov    -0x8(%rdx,%rax,4),%ebx
mov    %ebx,-0x8(%rcx,%rax,4)
mov    -0x4(%rdx,%rax,4),%ebx
mov    %ebx,-0x4(%rcx,%rax,4)
mov    (%rdx,%rax,4),%ebx
mov    %ebx,(%rcx,%rax,4)
add    $0x4,%rax
cmp    $0x20,%rax
jne    13d0 <main+0x250>
jmp    1486 <main+0x306>
nopl   (%rax)
lea    0x0(,%r11,4),%rax
movups (%r12,%r11,4),%xmm0
movups %xmm0,(%r14,%r11,4)
mov    %rax,%rbx
or     $0x10,%rbx
movups (%r12,%rbx,1),%xmm0
movups %xmm0,(%r14,%rbx,1)
mov    %rax,%rbx
or     $0x20,%rbx
movups (%r12,%rbx,1),%xmm0
movups %xmm0,(%r14,%rbx,1)
mov    %rax,%rbx
or     $0x30,%rbx
movups (%r12,%rbx,1),%xmm0
movups %xmm0,(%r14,%rbx,1)
mov    %rax,%rbx
or     $0x40,%rbx
movups (%r12,%rbx,1),%xmm0
movups %xmm0,(%r14,%rbx,1)
mov    %rax,%rbx
or     $0x50,%rbx
movups (%r12,%rbx,1),%xmm0
movups %xmm0,(%r14,%rbx,1)
mov    %rax,%rbx
or     $0x60,%rbx
movups (%r12,%rbx,1),%xmm0
movups %xmm0,(%r14,%rbx,1)
or     $0x70,%rax
movups (%r12,%rax,1),%xmm0
movups %xmm0,(%r14,%rax,1)
lea    (%r12,%rbp,1),%rax
add    $0x100,%rax
cmp    %rax,%r10
jae    12c0 <main+0x140>
lea    (%r14,%rbp,1),%rax
add    $0x100,%rax
cmp    %rax,%r9
jae    12c0 <main+0x140>
xor    %eax,%eax
xchg   %ax,%ax
mov    -0xc(%rdi,%rax,4),%ebp
mov    %ebp,-0xc(%rsi,%rax,4)
mov    -0x8(%rdi,%rax,4),%ebp
mov    %ebp,-0x8(%rsi,%rax,4)
mov    -0x4(%rdi,%rax,4),%ebp
mov    %ebp,-0x4(%rsi,%rax,4)
mov    (%rdi,%rax,4),%ebp
mov    %ebp,(%rsi,%rax,4)
add    $0x4,%rax
cmp    $0x20,%rax
jne    14b0 <main+0x330>
jmp    1361 <main+0x1e1>
movsd  %xmm1,0x10(%rsp)
xorps  %xmm0,%xmm0
cvtsi2sd %r8d,%xmm0
movsd  %xmm0,0x8(%rsp)
xor    %ebx,%ebx
lea    0x18(%rsp),%rdi
xor    %esi,%esi
call   1050 <gettimeofday@plt>
imul   $0x3e8,0x18(%rsp),%eax
movsd  0x20(%rsp),%xmm0
divsd  0xaeb(%rip),%xmm0
mov    $0x1,%edx
nopw   0x0(%rax,%rax,1)
imul   (%r12,%rbx,1),%edx
imul   0x100(%r12,%rbx,1),%edx
imul   0x200(%r12,%rbx,1),%edx
imul   0x300(%r12,%rbx,1),%edx
add    $0x400,%rbx
cmp    $0x10000000,%rbx
jne    1520 <main+0x3a0>
movsd  0x10(%rsp),%xmm1
addsd  0x8(%rsp),%xmm1
cvtsi2sd %eax,%xmm2
addsd  %xmm2,%xmm0
cmp    %edx,%r15d
jne    1589 <main+0x409>
subsd  %xmm1,%xmm0
lea    0xac1(%rip),%rdi
mov    $0x1,%al
call   1040 <printf@plt>
lea    0xad8(%rip),%rdi
call   1030 <puts@plt>
jmp    15c0 <main+0x440>
lea    0xa78(%rip),%rdi
mov    %r15d,%esi
xor    %eax,%eax
movsd  %xmm1,0x10(%rsp)
movsd  %xmm0,0x8(%rsp)
call   1040 <printf@plt>
movsd  0x8(%rsp),%xmm0
subsd  0x10(%rsp),%xmm0
lea    0xa7c(%rip),%rdi
mov    $0x1,%al
call   1040 <printf@plt>
xor    %eax,%eax
add    $0x28,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
%struct.timeval = type { i32, double }
@acc_device_default = global i32 0
@.str = [45 x i8] c"gang * FAILED! product=%d, known_product=%d\0A\00"
@.str.1 = [37 x i8] c"gang * execution time is :%.2lf: ms\0A\00"
@str = [16 x i8] c"gang * SUCCESS!\00"
define i32 @main() {
%1 = alloca %struct.timeval
%2 = bitcast %struct.timeval* %1 to i8*
%3 = tail call i64 @malloc(i32 268435456)
%4 = inttoptr i64 %3 to i32*
%5 = tail call i64 @malloc(i32 268435456)
%6 = load i32, i32* @acc_device_default
%7 = tail call i32 @acc_init(i32 %6)
%8 = tail call i64 @time(i32 0)
%9 = trunc i64 %8 to i32
%10 = tail call i32 @srand(i32 %9)
br label %11
11: ; preds = %0, %34
%12 = phi i64 [ 0, %0 ], [ %35, %34 ]
%13 = shl nsw i64 %12, 6
br label %14
14: ; preds = %11, %14
%15 = phi i64 [ 0, %11 ], [ %21, %14 ]
%16 = tail call i32 (...) @rand()
%17 = srem i32 %16, 5
%18 = add nsw i32 %17, 1
%19 = add nuw nsw i64 %13, %15
%20 = getelementptr inbounds i32, i32* %4, i64 %19
store i32 %18, i32* %20
%21 = add nuw nsw i64 %15, 1
%22 = icmp eq i64 %21, 32
br i1 %22, label %23, label %14
23: ; preds = %14
%24 = or i64 %13, 32
br label %25
25: ; preds = %25, %23
%26 = phi i64 [ 0, %23 ], [ %32, %25 ]
%27 = tail call i32 (...) @rand()
%28 = srem i32 %27, 5
%29 = add nsw i32 %28, 1
%30 = add nuw nsw i64 %24, %26
%31 = getelementptr inbounds i32, i32* %4, i64 %30
store i32 %29, i32* %31
%32 = add nuw nsw i64 %26, 1
%33 = icmp eq i64 %32, 32
br i1 %33, label %34, label %25
34: ; preds = %25
%35 = add nuw nsw i64 %12, 1
%36 = icmp eq i64 %35, 1048576
br i1 %36, label %37, label %11
37: ; preds = %34
%38 = inttoptr i64 %5 to i32*
%39 = call i32 @gettimeofday(%struct.timeval* %1, i32* null)
%40 = getelementptr inbounds %struct.timeval, %struct.timeval* %1, i64 0, i32 0
%41 = load i32, i32* %40
%42 = mul nsw i32 %41, 1000
%43 = getelementptr inbounds %struct.timeval, %struct.timeval* %1, i64 0, i32 1
%44 = load double, double* %43
%45 = fdiv double %44, 1.000000e+03
br label %46
46: ; preds = %37, %213
%47 = phi i64 [ 0, %37 ], [ %217, %213 ]
%48 = phi i32 [ 1, %37 ], [ %216, %213 ]
%49 = shl nuw nsw i64 %47, 6
%50 = or i64 %49, 32
%51 = shl nuw nsw i64 %47, 6
%52 = or i64 %51, 32
%53 = getelementptr i32, i32* %38, i64 %52
%54 = add nuw i64 %51, 64
%55 = getelementptr i32, i32* %38, i64 %54
%56 = getelementptr i32, i32* %4, i64 %52
%57 = getelementptr i32, i32* %4, i64 %54
%58 = shl nsw i64 %47, 6
%59 = getelementptr i32, i32* %4, i64 %50
%60 = getelementptr i32, i32* %4, i64 %49
%61 = getelementptr i32, i32* %38, i64 %50
%62 = getelementptr i32, i32* %38, i64 %49
%63 = icmp ult i32* %62, %59
%64 = icmp ult i32* %60, %61
%65 = and i1 %63, %64
br i1 %65, label %114, label %66
66: ; preds = %46
%67 = getelementptr inbounds i32, i32* %4, i64 %58
%68 = bitcast i32* %67 to <4 x i32>*
%69 = load <4 x i32>, <4 x i32>* %68
%70 = getelementptr inbounds i32, i32* %38, i64 %58
%71 = bitcast i32* %70 to <4 x i32>*
store <4 x i32> %69, <4 x i32>* %71
%72 = or i64 %58, 4
%73 = getelementptr inbounds i32, i32* %4, i64 %72
%74 = bitcast i32* %73 to <4 x i32>*
%75 = load <4 x i32>, <4 x i32>* %74
%76 = getelementptr inbounds i32, i32* %38, i64 %72
%77 = bitcast i32* %76 to <4 x i32>*
store <4 x i32> %75, <4 x i32>* %77
%78 = or i64 %58, 8
%79 = getelementptr inbounds i32, i32* %4, i64 %78
%80 = bitcast i32* %79 to <4 x i32>*
%81 = load <4 x i32>, <4 x i32>* %80
%82 = getelementptr inbounds i32, i32* %38, i64 %78
%83 = bitcast i32* %82 to <4 x i32>*
store <4 x i32> %81, <4 x i32>* %83
%84 = or i64 %58, 12
%85 = getelementptr inbounds i32, i32* %4, i64 %84
%86 = bitcast i32* %85 to <4 x i32>*
%87 = load <4 x i32>, <4 x i32>* %86
%88 = getelementptr inbounds i32, i32* %38, i64 %84
%89 = bitcast i32* %88 to <4 x i32>*
store <4 x i32> %87, <4 x i32>* %89
%90 = or i64 %58, 16
%91 = getelementptr inbounds i32, i32* %4, i64 %90
%92 = bitcast i32* %91 to <4 x i32>*
%93 = load <4 x i32>, <4 x i32>* %92
%94 = getelementptr inbounds i32, i32* %38, i64 %90
%95 = bitcast i32* %94 to <4 x i32>*
store <4 x i32> %93, <4 x i32>* %95
%96 = or i64 %58, 20
%97 = getelementptr inbounds i32, i32* %4, i64 %96
%98 = bitcast i32* %97 to <4 x i32>*
%99 = load <4 x i32>, <4 x i32>* %98
%100 = getelementptr inbounds i32, i32* %38, i64 %96
%101 = bitcast i32* %100 to <4 x i32>*
store <4 x i32> %99, <4 x i32>* %101
%102 = or i64 %58, 24
%103 = getelementptr inbounds i32, i32* %4, i64 %102
%104 = bitcast i32* %103 to <4 x i32>*
%105 = load <4 x i32>, <4 x i32>* %104
%106 = getelementptr inbounds i32, i32* %38, i64 %102
%107 = bitcast i32* %106 to <4 x i32>*
store <4 x i32> %105, <4 x i32>* %107
%108 = or i64 %58, 28
%109 = getelementptr inbounds i32, i32* %4, i64 %108
%110 = bitcast i32* %109 to <4 x i32>*
%111 = load <4 x i32>, <4 x i32>* %110
%112 = getelementptr inbounds i32, i32* %38, i64 %108
%113 = bitcast i32* %112 to <4 x i32>*
store <4 x i32> %111, <4 x i32>* %113
br label %137
114: ; preds = %46, %114
%115 = phi i64 [ %135, %114 ], [ 0, %46 ]
%116 = add nuw nsw i64 %58, %115
%117 = getelementptr inbounds i32, i32* %4, i64 %116
%118 = load i32, i32* %117
%119 = getelementptr inbounds i32, i32* %38, i64 %116
store i32 %118, i32* %119
%120 = or i64 %115, 1
%121 = add nuw nsw i64 %58, %120
%122 = getelementptr inbounds i32, i32* %4, i64 %121
%123 = load i32, i32* %122
%124 = getelementptr inbounds i32, i32* %38, i64 %121
store i32 %123, i32* %124
%125 = or i64 %115, 2
%126 = add nuw nsw i64 %58, %125
%127 = getelementptr inbounds i32, i32* %4, i64 %126
%128 = load i32, i32* %127
%129 = getelementptr inbounds i32, i32* %38, i64 %126
store i32 %128, i32* %129
%130 = or i64 %115, 3
%131 = add nuw nsw i64 %58, %130
%132 = getelementptr inbounds i32, i32* %4, i64 %131
%133 = load i32, i32* %132
%134 = getelementptr inbounds i32, i32* %38, i64 %131
store i32 %133, i32* %134
%135 = add nuw nsw i64 %115, 4
%136 = icmp eq i64 %135, 32
br i1 %136, label %137, label %114
137: ; preds = %114, %66
%138 = or i64 %58, 32
%139 = icmp ult i32* %53, %57
%140 = icmp ult i32* %56, %55
%141 = and i1 %139, %140
br i1 %141, label %190, label %142
142: ; preds = %137
%143 = getelementptr inbounds i32, i32* %4, i64 %138
%144 = bitcast i32* %143 to <4 x i32>*
%145 = load <4 x i32>, <4 x i32>* %144
%146 = getelementptr inbounds i32, i32* %38, i64 %138
%147 = bitcast i32* %146 to <4 x i32>*
store <4 x i32> %145, <4 x i32>* %147
%148 = or i64 %58, 36
%149 = getelementptr inbounds i32, i32* %4, i64 %148
%150 = bitcast i32* %149 to <4 x i32>*
%151 = load <4 x i32>, <4 x i32>* %150
%152 = getelementptr inbounds i32, i32* %38, i64 %148
%153 = bitcast i32* %152 to <4 x i32>*
store <4 x i32> %151, <4 x i32>* %153
%154 = or i64 %58, 40
%155 = getelementptr inbounds i32, i32* %4, i64 %154
%156 = bitcast i32* %155 to <4 x i32>*
%157 = load <4 x i32>, <4 x i32>* %156
%158 = getelementptr inbounds i32, i32* %38, i64 %154
%159 = bitcast i32* %158 to <4 x i32>*
store <4 x i32> %157, <4 x i32>* %159
%160 = or i64 %58, 44
%161 = getelementptr inbounds i32, i32* %4, i64 %160
%162 = bitcast i32* %161 to <4 x i32>*
%163 = load <4 x i32>, <4 x i32>* %162
%164 = getelementptr inbounds i32, i32* %38, i64 %160
%165 = bitcast i32* %164 to <4 x i32>*
store <4 x i32> %163, <4 x i32>* %165
%166 = or i64 %58, 48
%167 = getelementptr inbounds i32, i32* %4, i64 %166
%168 = bitcast i32* %167 to <4 x i32>*
%169 = load <4 x i32>, <4 x i32>* %168
%170 = getelementptr inbounds i32, i32* %38, i64 %166
%171 = bitcast i32* %170 to <4 x i32>*
store <4 x i32> %169, <4 x i32>* %171
%172 = or i64 %58, 52
%173 = getelementptr inbounds i32, i32* %4, i64 %172
%174 = bitcast i32* %173 to <4 x i32>*
%175 = load <4 x i32>, <4 x i32>* %174
%176 = getelementptr inbounds i32, i32* %38, i64 %172
%177 = bitcast i32* %176 to <4 x i32>*
store <4 x i32> %175, <4 x i32>* %177
%178 = or i64 %58, 56
%179 = getelementptr inbounds i32, i32* %4, i64 %178
%180 = bitcast i32* %179 to <4 x i32>*
%181 = load <4 x i32>, <4 x i32>* %180
%182 = getelementptr inbounds i32, i32* %38, i64 %178
%183 = bitcast i32* %182 to <4 x i32>*
store <4 x i32> %181, <4 x i32>* %183
%184 = or i64 %58, 60
%185 = getelementptr inbounds i32, i32* %4, i64 %184
%186 = bitcast i32* %185 to <4 x i32>*
%187 = load <4 x i32>, <4 x i32>* %186
%188 = getelementptr inbounds i32, i32* %38, i64 %184
%189 = bitcast i32* %188 to <4 x i32>*
store <4 x i32> %187, <4 x i32>* %189
br label %213
190: ; preds = %137, %190
%191 = phi i64 [ %211, %190 ], [ 0, %137 ]
%192 = add nuw nsw i64 %138, %191
%193 = getelementptr inbounds i32, i32* %4, i64 %192
%194 = load i32, i32* %193
%195 = getelementptr inbounds i32, i32* %38, i64 %192
store i32 %194, i32* %195
%196 = or i64 %191, 1
%197 = add nuw nsw i64 %138, %196
%198 = getelementptr inbounds i32, i32* %4, i64 %197
%199 = load i32, i32* %198
%200 = getelementptr inbounds i32, i32* %38, i64 %197
store i32 %199, i32* %200
%201 = or i64 %191, 2
%202 = add nuw nsw i64 %138, %201
%203 = getelementptr inbounds i32, i32* %4, i64 %202
%204 = load i32, i32* %203
%205 = getelementptr inbounds i32, i32* %38, i64 %202
store i32 %204, i32* %205
%206 = or i64 %191, 3
%207 = add nuw nsw i64 %138, %206
%208 = getelementptr inbounds i32, i32* %4, i64 %207
%209 = load i32, i32* %208
%210 = getelementptr inbounds i32, i32* %38, i64 %207
store i32 %209, i32* %210
%211 = add nuw nsw i64 %191, 4
%212 = icmp eq i64 %211, 32
br i1 %212, label %213, label %190
213: ; preds = %190, %142
%214 = getelementptr inbounds i32, i32* %38, i64 %58
%215 = load i32, i32* %214
%216 = mul nsw i32 %215, %48
%217 = add nuw nsw i64 %47, 1
%218 = icmp eq i64 %217, 1048576
br i1 %218, label %219, label %46
219: ; preds = %213
%220 = sitofp i32 %42 to double
%221 = call i32 @gettimeofday(%struct.timeval* %1, i32* null)
%222 = load i32, i32* %40
%223 = mul nsw i32 %222, 1000
%224 = load double, double* %43
%225 = fdiv double %224, 1.000000e+03
br label %226
226: ; preds = %226, %219
%227 = phi i64 [ 0, %219 ], [ %248, %226 ]
%228 = phi i32 [ 1, %219 ], [ %247, %226 ]
%229 = shl nuw nsw i64 %227, 6
%230 = getelementptr inbounds i32, i32* %4, i64 %229
%231 = load i32, i32* %230
%232 = mul nsw i32 %231, %228
%233 = shl i64 %227, 6
%234 = or i64 %233, 64
%235 = getelementptr inbounds i32, i32* %4, i64 %234
%236 = load i32, i32* %235
%237 = mul nsw i32 %236, %232
%238 = shl i64 %227, 6
%239 = or i64 %238, 128
%240 = getelementptr inbounds i32, i32* %4, i64 %239
%241 = load i32, i32* %240
%242 = mul nsw i32 %241, %237
%243 = shl i64 %227, 6
%244 = or i64 %243, 192
%245 = getelementptr inbounds i32, i32* %4, i64 %244
%246 = load i32, i32* %245
%247 = mul nsw i32 %246, %242
%248 = add nuw nsw i64 %227, 4
%249 = icmp eq i64 %248, 1048576
br i1 %249, label %250, label %226
250: ; preds = %226
%251 = fadd double %45, %220
%252 = sitofp i32 %223 to double
%253 = fadd double %225, %252
%254 = icmp eq i32 %216, %247
br i1 %254, label %259, label %255
255: ; preds = %250
%256 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([45 x i8], [45 x i8]* @.str, i64 0, i64 0), i32 %216, i32 %247)
%257 = fsub double %253, %251
%258 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([37 x i8], [37 x i8]* @.str.1, i64 0, i64 0), double %257)
br label %263
259: ; preds = %250
%260 = fsub double %253, %251
%261 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([37 x i8], [37 x i8]* @.str.1, i64 0, i64 0), double %260)
%262 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0))
br label %263
263: ; preds = %255, %259
ret i32 0
}