#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*/ free(int *);
int /*<<< orphan*/ gettimeofday(struct timeval *, int /*<<< orphan*/ *);
scalar_t__ malloc(int);
int /*<<< orphan*/ printf(char *, ...);
int main() {
  int i, j, k;
  int sum, known_sum;
  int NI, NJ, NK;
  int *input, *temp;
  struct timeval tim;
  double start, end;
  NI = 1024;
  NJ = 512;
  NK = 128;
  input = (int *)malloc(NK * NJ * NI * sizeof(int));
  temp = (int *)malloc(NK * NJ * NI * sizeof(int));
  acc_init(acc_device_default);
  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] = (k + j + i) % 10;
    }
  }
  sum = 0;
  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])
  {
#pragma acc loop gang reduction(+ : sum)
    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];
      }
      sum += temp[k * NJ * NI];
    }
  }
  gettimeofday(&tim, NULL);
  end = tim.tv_sec * 1000 + (tim.tv_usec / 1000.0);
  known_sum = 0;
  for (k = 0; k < NK; k++) {
    known_sum += input[k * NJ * NI];
  }
  printf("Test for gang reduction \n");
  if (sum == known_sum)
    printf("Success!\n");
  else
    printf("Int + failed! sum=%d, known_sum=%d\n", sum, known_sum);
  printf("Execution time: %.2lf ms\n", end - start);
  free(input);
  free(temp);
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
movl   $0x0,-0x4(%rbp)
movl   $0x400,-0x1c(%rbp)
movl   $0x200,-0x20(%rbp)
movl   $0x80,-0x24(%rbp)
mov    -0x24(%rbp),%eax
imul   -0x20(%rbp),%eax
imul   -0x1c(%rbp),%eax
cltq
shl    $0x2,%rax
mov    %eax,%edi
call   1060 <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   1060 <malloc@plt>
mov    %rax,-0x38(%rbp)
mov    0x2e2d(%rip),%rax
mov    (%rax),%edi
call   1070 <acc_init@plt>
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    1259 <main+0x109>
movl   $0x0,-0xc(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    1246 <main+0xf6>
movl   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    1233 <main+0xe3>
mov    -0x10(%rbp),%eax
add    -0xc(%rbp),%eax
add    -0x8(%rbp),%eax
mov    $0xa,%ecx
cltd
idiv   %ecx
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    11e7 <main+0x97>
jmp    1238 <main+0xe8>
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    11d4 <main+0x84>
jmp    124b <main+0xfb>
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    11c1 <main+0x71>
movl   $0x0,-0x14(%rbp)
lea    -0x48(%rbp),%rdi
xor    %eax,%eax
mov    %eax,%esi
call   1050 <gettimeofday@plt>
imul   $0x3e8,-0x48(%rbp),%eax
cvtsi2sd %eax,%xmm0
movsd  -0x40(%rbp),%xmm1
movsd  0xd7b(%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    1357 <main+0x207>
movl   $0x0,-0xc(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    132e <main+0x1de>
movl   $0x0,-0x8(%rbp)
mov    -0x8(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    131b <main+0x1cb>
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    12bf <main+0x16f>
jmp    1320 <main+0x1d0>
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    12ac <main+0x15c>
mov    -0x38(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
add    -0x14(%rbp),%eax
mov    %eax,-0x14(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    1299 <main+0x149>
lea    -0x48(%rbp),%rdi
xor    %eax,%eax
mov    %eax,%esi
call   1050 <gettimeofday@plt>
imul   $0x3e8,-0x48(%rbp),%eax
cvtsi2sd %eax,%xmm0
movsd  -0x40(%rbp),%xmm1
movsd  0xc84(%rip),%xmm2
divsd  %xmm2,%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x58(%rbp)
movl   $0x0,-0x18(%rbp)
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    13cc <main+0x27c>
mov    -0x30(%rbp),%rax
mov    -0x10(%rbp),%ecx
imul   -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
add    -0x18(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    1397 <main+0x247>
lea    0xc35(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x14(%rbp),%eax
cmp    -0x18(%rbp),%eax
jne    13f9 <main+0x2a9>
lea    0xc35(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    140d <main+0x2bd>
mov    -0x14(%rbp),%esi
mov    -0x18(%rbp),%edx
lea    0xc26(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
movsd  -0x58(%rbp),%xmm0
subsd  -0x50(%rbp),%xmm0
lea    0xc32(%rip),%rdi
mov    $0x1,%al
call   1040 <printf@plt>
mov    -0x30(%rbp),%rdi
call   1030 <free@plt>
mov    -0x38(%rbp),%rdi
call   1030 <free@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    $0x68,%rsp
mov    $0x10000000,%edi
call   1070 <malloc@plt>
mov    %rax,%r13
mov    $0x10000000,%edi
call   1070 <malloc@plt>
mov    %rax,%r14
mov    0x2e51(%rip),%rax
mov    (%rax),%edi
call   1080 <acc_init@plt>
lea    0x10(%r13),%rax
xor    %ecx,%ecx
movdqa 0xe5b(%rip),%xmm8
movdqa 0xe62(%rip),%xmm9
movdqa 0xe69(%rip),%xmm11
movdqa 0xe70(%rip),%xmm12
movdqa 0xe77(%rip),%xmm10
nopl   0x0(%rax)
mov    %rax,%rdx
xor    %esi,%esi
cs nopw 0x0(%rax,%rax,1)
nop
lea    (%rsi,%rcx,1),%rdi
movq   %rdi,%xmm0
pshufd $0x44,%xmm0,%xmm13
lea    (%rsi,%rcx,1),%rdi
add    $0x4,%rdi
movq   %rdi,%xmm0
pshufd $0x44,%xmm0,%xmm14
xor    %edi,%edi
movdqa %xmm9,%xmm7
movdqa %xmm8,%xmm0
xchg   %ax,%ax
movdqa %xmm13,%xmm5
paddq  %xmm7,%xmm5
movdqa %xmm13,%xmm3
paddq  %xmm0,%xmm3
movdqa %xmm14,%xmm6
paddq  %xmm7,%xmm6
movdqa %xmm14,%xmm2
paddq  %xmm0,%xmm2
movdqa %xmm5,%xmm1
shufps $0x88,%xmm3,%xmm1
movdqa %xmm6,%xmm4
shufps $0x88,%xmm2,%xmm4
punpckhqdq %xmm3,%xmm5
pmuludq %xmm11,%xmm5
pshufd $0xed,%xmm5,%xmm3
movaps %xmm1,%xmm5
pmuludq %xmm11,%xmm5
pshufd $0xed,%xmm5,%xmm5
punpckldq %xmm3,%xmm5
psrld  $0x3,%xmm5
pshufd $0xf5,%xmm5,%xmm3
pmuludq %xmm12,%xmm5
pshufd $0xe8,%xmm5,%xmm5
pmuludq %xmm12,%xmm3
pshufd $0xe8,%xmm3,%xmm3
punpckldq %xmm3,%xmm5
psubd  %xmm5,%xmm1
punpckhqdq %xmm2,%xmm6
pmuludq %xmm11,%xmm6
pshufd $0xed,%xmm6,%xmm2
movaps %xmm4,%xmm3
pmuludq %xmm11,%xmm3
pshufd $0xed,%xmm3,%xmm3
punpckldq %xmm2,%xmm3
psrld  $0x3,%xmm3
pshufd $0xf5,%xmm3,%xmm2
pmuludq %xmm12,%xmm3
pshufd $0xe8,%xmm3,%xmm3
pmuludq %xmm12,%xmm2
pshufd $0xe8,%xmm2,%xmm2
punpckldq %xmm2,%xmm3
psubd  %xmm3,%xmm4
movdqu %xmm1,-0x10(%rdx,%rdi,4)
movdqu %xmm4,(%rdx,%rdi,4)
add    $0x8,%rdi
paddq  %xmm10,%xmm7
paddq  %xmm10,%xmm0
cmp    $0x400,%rdi
jne    1210 <main+0xb0>
add    $0x1,%rsi
add    $0x1000,%rdx
cmp    $0x200,%rsi
jne    11e0 <main+0x80>
add    $0x1,%rcx
add    $0x200000,%rax
cmp    $0x80,%rcx
jne    11d0 <main+0x70>
xor    %ebp,%ebp
lea    0x10(%rsp),%rdi
xor    %esi,%esi
call   1060 <gettimeofday@plt>
mov    0x10(%rsp),%eax
mov    %eax,0xc(%rsp)
movsd  0x18(%rsp),%xmm0
movaps %xmm0,0x50(%rsp)
lea    0x70(%r14),%rax
lea    0x70(%r13),%rcx
lea    0xc(%r14),%r10
lea    0xc(%r13),%r11
xor    %ebx,%ebx
jmp    13a3 <main+0x243>
nopl   0x0(%rax,%rax,1)
mov    0x20(%rsp),%ebx
add    (%r14,%r9,4),%ebx
mov    0x48(%rsp),%rbp
add    $0x1,%rbp
mov    0x40(%rsp),%rax
add    $0x200000,%rax
mov    0x38(%rsp),%rcx
add    $0x200000,%rcx
add    $0x200000,%r10
add    $0x200000,%r11
cmp    $0x80,%rbp
je     1503 <main+0x3a3>
mov    %ebx,0x20(%rsp)
mov    %rbp,0x48(%rsp)
mov    %rbp,%r9
shl    $0x13,%r9
lea    0x400(%r9),%r8
mov    %r11,%rsi
mov    %r10,%rdx
mov    %rcx,0x38(%rsp)
mov    %rax,0x40(%rsp)
mov    %rax,%rbp
xor    %r12d,%r12d
jmp    140d <main+0x2ad>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
add    $0x1,%r12
add    $0x1000,%rbp
add    $0x1000,%rcx
add    $0x1000,%rdx
add    $0x1000,%rsi
cmp    $0x200,%r12
je     1360 <main+0x200>
mov    %r12,%rbx
shl    $0xa,%rbx
lea    (%r9,%rbx,1),%rax
add    %r8,%rbx
lea    0x0(,%rbx,4),%r15
add    %r13,%r15
lea    (%r14,%rax,4),%rdi
cmp    %r15,%rdi
jae    1480 <main+0x320>
lea    0x0(,%rax,4),%rax
add    %r13,%rax
lea    (%r14,%rbx,4),%rdi
cmp    %rdi,%rax
jae    1480 <main+0x320>
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
nop
mov    -0xc(%rsi,%rbx,4),%eax
mov    %eax,-0xc(%rdx,%rbx,4)
mov    -0x8(%rsi,%rbx,4),%eax
mov    %eax,-0x8(%rdx,%rbx,4)
mov    -0x4(%rsi,%rbx,4),%eax
mov    %eax,-0x4(%rdx,%rbx,4)
mov    (%rsi,%rbx,4),%eax
mov    %eax,(%rdx,%rbx,4)
add    $0x4,%rbx
cmp    $0x400,%rbx
jne    1450 <main+0x2f0>
jmp    13e0 <main+0x280>
xor    %r15d,%r15d
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movups -0x70(%rcx,%r15,4),%xmm0
movups -0x60(%rcx,%r15,4),%xmm1
movups %xmm0,-0x70(%rbp,%r15,4)
movups %xmm1,-0x60(%rbp,%r15,4)
movups -0x50(%rcx,%r15,4),%xmm0
movups -0x40(%rcx,%r15,4),%xmm1
movups %xmm0,-0x50(%rbp,%r15,4)
movups %xmm1,-0x40(%rbp,%r15,4)
movups -0x30(%rcx,%r15,4),%xmm0
movups -0x20(%rcx,%r15,4),%xmm1
movups %xmm0,-0x30(%rbp,%r15,4)
movups %xmm1,-0x20(%rbp,%r15,4)
movups -0x10(%rcx,%r15,4),%xmm0
movdqu (%rcx,%r15,4),%xmm1
movups %xmm0,-0x10(%rbp,%r15,4)
movdqu %xmm1,0x0(%rbp,%r15,4)
add    $0x20,%r15
cmp    $0x400,%r15
jne    1490 <main+0x330>
jmp    13e0 <main+0x280>
xor    %ebp,%ebp
lea    0x10(%rsp),%rdi
xor    %esi,%esi
call   1060 <gettimeofday@plt>
mov    $0x600000,%eax
movaps 0x10(%rsp),%xmm0
movaps %xmm0,0x20(%rsp)
add    -0x600000(%r13,%rax,1),%ebp
ff
add    -0x400000(%r13,%rax,1),%ebp
ff
add    -0x200000(%r13,%rax,1),%ebp
ff
add    0x0(%r13,%rax,1),%ebp
add    $0x800000,%rax
cmp    $0x10600000,%rax
jne    1520 <main+0x3c0>
lea    0xb5c(%rip),%rdi
call   1040 <puts@plt>
cmp    %ebp,%ebx
jne    1569 <main+0x409>
lea    0xb65(%rip),%rdi
call   1040 <puts@plt>
jmp    157b <main+0x41b>
lea    0xb00(%rip),%rdi
mov    %ebx,%esi
mov    %ebp,%edx
xor    %eax,%eax
call   1050 <printf@plt>
movd   0xc(%rsp),%xmm3
movdqa 0xac7(%rip),%xmm1
movdqa 0x20(%rsp),%xmm0
movdqa %xmm0,%xmm2
pmuludq %xmm1,%xmm2
pmuludq %xmm1,%xmm3
punpckldq %xmm3,%xmm2
cvtdq2pd %xmm2,%xmm1
shufpd $0x1,0x50(%rsp),%xmm0
divpd  0xaae(%rip),%xmm0
addpd  %xmm1,%xmm0
movapd %xmm0,%xmm1
unpckhpd %xmm0,%xmm1
subsd  %xmm1,%xmm0
lea    0xacb(%rip),%rdi
mov    $0x1,%al
call   1050 <printf@plt>
mov    %r13,%rdi
call   1030 <free@plt>
mov    %r14,%rdi
call   1030 <free@plt>
xor    %eax,%eax
add    $0x68,%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 = [26 x i8] c"Test for gang reduction \0A\00"
@.str.1 = [10 x i8] c"Success!\0A\00"
@.str.2 = [36 x i8] c"Int + failed! sum=%d, known_sum=%d\0A\00"
@.str.3 = [26 x i8] c"Execution time: %.2lf ms\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 %struct.timeval
%13 = alloca double
%14 = alloca double
store i32 0, i32* %1
store i32 1024, i32* %7
store i32 512, i32* %8
store i32 128, i32* %9
%15 = load i32, i32* %9
%16 = load i32, i32* %8
%17 = mul nsw i32 %15, %16
%18 = load i32, i32* %7
%19 = mul nsw i32 %17, %18
%20 = sext i32 %19 to i64
%21 = mul i64 %20, 4
%22 = trunc i64 %21 to i32
%23 = call i64 @malloc(i32 %22)
%24 = inttoptr i64 %23 to i32*
store i32* %24, i32** %10
%25 = load i32, i32* %9
%26 = load i32, i32* %8
%27 = mul nsw i32 %25, %26
%28 = load i32, i32* %7
%29 = mul nsw i32 %27, %28
%30 = sext i32 %29 to i64
%31 = mul i64 %30, 4
%32 = trunc i64 %31 to i32
%33 = call i64 @malloc(i32 %32)
%34 = inttoptr i64 %33 to i32*
store i32* %34, i32** %11
%35 = load i32, i32* @acc_device_default
%36 = call i32 @acc_init(i32 %35)
store i32 0, i32* %4
br label %37
37: ; preds = %80, %0
%38 = load i32, i32* %4
%39 = load i32, i32* %9
%40 = icmp slt i32 %38, %39
br i1 %40, label %41, label %83
41: ; preds = %37
store i32 0, i32* %3
br label %42
42: ; preds = %76, %41
%43 = load i32, i32* %3
%44 = load i32, i32* %8
%45 = icmp slt i32 %43, %44
br i1 %45, label %46, label %79
46: ; preds = %42
store i32 0, i32* %2
br label %47
47: ; preds = %72, %46
%48 = load i32, i32* %2
%49 = load i32, i32* %7
%50 = icmp slt i32 %48, %49
br i1 %50, label %51, label %75
51: ; preds = %47
%52 = load i32, i32* %4
%53 = load i32, i32* %3
%54 = add nsw i32 %52, %53
%55 = load i32, i32* %2
%56 = add nsw i32 %54, %55
%57 = srem i32 %56, 10
%58 = load i32*, i32** %10
%59 = load i32, i32* %4
%60 = load i32, i32* %8
%61 = mul nsw i32 %59, %60
%62 = load i32, i32* %7
%63 = mul nsw i32 %61, %62
%64 = load i32, i32* %3
%65 = load i32, i32* %7
%66 = mul nsw i32 %64, %65
%67 = add nsw i32 %63, %66
%68 = load i32, i32* %2
%69 = add nsw i32 %67, %68
%70 = sext i32 %69 to i64
%71 = getelementptr inbounds i32, i32* %58, i64 %70
store i32 %57, i32* %71
br label %72
72: ; preds = %51
%73 = load i32, i32* %2
%74 = add nsw i32 %73, 1
store i32 %74, i32* %2
br label %47
75: ; preds = %47
br label %76
76: ; preds = %75
%77 = load i32, i32* %3
%78 = add nsw i32 %77, 1
store i32 %78, i32* %3
br label %42
79: ; preds = %42
br label %80
80: ; preds = %79
%81 = load i32, i32* %4
%82 = add nsw i32 %81, 1
store i32 %82, i32* %4
br label %37
83: ; preds = %37
store i32 0, i32* %5
%84 = call i32 @gettimeofday(%struct.timeval* %12, i32* null)
%85 = getelementptr inbounds %struct.timeval, %struct.timeval* %12, i32 0, i32 0
%86 = load i32, i32* %85
%87 = mul nsw i32 %86, 1000
%88 = sitofp i32 %87 to double
%89 = getelementptr inbounds %struct.timeval, %struct.timeval* %12, i32 0, i32 1
%90 = load double, double* %89
%91 = fdiv double %90, 1.000000e+03
%92 = fadd double %88, %91
store double %92, double* %13
store i32 0, i32* %4
br label %93
93: ; preds = %156, %83
%94 = load i32, i32* %4
%95 = load i32, i32* %9
%96 = icmp slt i32 %94, %95
br i1 %96, label %97, label %159
97: ; preds = %93
store i32 0, i32* %3
br label %98
98: ; preds = %141, %97
%99 = load i32, i32* %3
%100 = load i32, i32* %8
%101 = icmp slt i32 %99, %100
br i1 %101, label %102, label %144
102: ; preds = %98
store i32 0, i32* %2
br label %103
103: ; preds = %137, %102
%104 = load i32, i32* %2
%105 = load i32, i32* %7
%106 = icmp slt i32 %104, %105
br i1 %106, label %107, label %140
107: ; preds = %103
%108 = load i32*, i32** %10
%109 = load i32, i32* %4
%110 = load i32, i32* %8
%111 = mul nsw i32 %109, %110
%112 = load i32, i32* %7
%113 = mul nsw i32 %111, %112
%114 = load i32, i32* %3
%115 = load i32, i32* %7
%116 = mul nsw i32 %114, %115
%117 = add nsw i32 %113, %116
%118 = load i32, i32* %2
%119 = add nsw i32 %117, %118
%120 = sext i32 %119 to i64
%121 = getelementptr inbounds i32, i32* %108, i64 %120
%122 = load i32, i32* %121
%123 = load i32*, i32** %11
%124 = load i32, i32* %4
%125 = load i32, i32* %8
%126 = mul nsw i32 %124, %125
%127 = load i32, i32* %7
%128 = mul nsw i32 %126, %127
%129 = load i32, i32* %3
%130 = load i32, i32* %7
%131 = mul nsw i32 %129, %130
%132 = add nsw i32 %128, %131
%133 = load i32, i32* %2
%134 = add nsw i32 %132, %133
%135 = sext i32 %134 to i64
%136 = getelementptr inbounds i32, i32* %123, i64 %135
store i32 %122, i32* %136
br label %137
137: ; preds = %107
%138 = load i32, i32* %2
%139 = add nsw i32 %138, 1
store i32 %139, i32* %2
br label %103
140: ; preds = %103
br label %141
141: ; preds = %140
%142 = load i32, i32* %3
%143 = add nsw i32 %142, 1
store i32 %143, i32* %3
br label %98
144: ; preds = %98
%145 = load i32*, i32** %11
%146 = load i32, i32* %4
%147 = load i32, i32* %8
%148 = mul nsw i32 %146, %147
%149 = load i32, i32* %7
%150 = mul nsw i32 %148, %149
%151 = sext i32 %150 to i64
%152 = getelementptr inbounds i32, i32* %145, i64 %151
%153 = load i32, i32* %152
%154 = load i32, i32* %5
%155 = add nsw i32 %154, %153
store i32 %155, i32* %5
br label %156
156: ; preds = %144
%157 = load i32, i32* %4
%158 = add nsw i32 %157, 1
store i32 %158, i32* %4
br label %93
159: ; preds = %93
%160 = call i32 @gettimeofday(%struct.timeval* %12, i32* null)
%161 = getelementptr inbounds %struct.timeval, %struct.timeval* %12, i32 0, i32 0
%162 = load i32, i32* %161
%163 = mul nsw i32 %162, 1000
%164 = sitofp i32 %163 to double
%165 = getelementptr inbounds %struct.timeval, %struct.timeval* %12, i32 0, i32 1
%166 = load double, double* %165
%167 = fdiv double %166, 1.000000e+03
%168 = fadd double %164, %167
store double %168, double* %14
store i32 0, i32* %6
store i32 0, i32* %4
br label %169
169: ; preds = %185, %159
%170 = load i32, i32* %4
%171 = load i32, i32* %9
%172 = icmp slt i32 %170, %171
br i1 %172, label %173, label %188
173: ; preds = %169
%174 = load i32*, i32** %10
%175 = load i32, i32* %4
%176 = load i32, i32* %8
%177 = mul nsw i32 %175, %176
%178 = load i32, i32* %7
%179 = mul nsw i32 %177, %178
%180 = sext i32 %179 to i64
%181 = getelementptr inbounds i32, i32* %174, i64 %180
%182 = load i32, i32* %181
%183 = load i32, i32* %6
%184 = add nsw i32 %183, %182
store i32 %184, i32* %6
br label %185
185: ; preds = %173
%186 = load i32, i32* %4
%187 = add nsw i32 %186, 1
store i32 %187, i32* %4
br label %169
188: ; preds = %169
%189 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str, i64 0, i64 0))
%190 = load i32, i32* %5
%191 = load i32, i32* %6
%192 = icmp eq i32 %190, %191
br i1 %192, label %193, label %195
193: ; preds = %188
%194 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0))
br label %199
195: ; preds = %188
%196 = load i32, i32* %5
%197 = load i32, i32* %6
%198 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([36 x i8], [36 x i8]* @.str.2, i64 0, i64 0), i32 %196, i32 %197)
br label %199
199: ; preds = %195, %193
%200 = load double, double* %14
%201 = load double, double* %13
%202 = fsub double %200, %201
%203 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str.3, i64 0, i64 0), double %202)
%204 = load i32*, i32** %10
%205 = call i32 @free(i32* %204)
%206 = load i32*, i32** %11
%207 = call i32 @free(i32* %206)
%208 = load i32, i32* %1
ret i32 %208
}

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