#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 */
int omp_get_num_threads();
int omp_get_thread_num();
int /*<<< orphan*/ printf(char *, double, ...);
double reduce(double *);
double shubert(double, double);
int main() {
  const int MAX_STEPS = 8;
  const int LOWER_BOUND = -2;
  const double STEP_SIZE = 0.5;
  int threadCount, tid, i = 0;
  double x1, x2, y, min = 0;
  double minima[8];
#pragma omp parallel for private(tid)
  for (i = 0; i <= MAX_STEPS; i++) {
    if (tid == 0 && i == 1) {
      threadCount = omp_get_num_threads();
      printf("Number of threads = %d\n", threadCount);
    }
    tid = omp_get_thread_num();
    x1 = STEP_SIZE * i + LOWER_BOUND;
    printf("Thread #%d, i = %d\n", tid, i);
    for (x2 = -2; x2 <= 2; x2 += 0.5) {
      y = shubert(x1, x2);
      minima[tid] = (y < minima[tid]) ? y : minima[tid];
    }
  }
  min = reduce(minima);
  printf("Global min = %.2f\n", min);
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0xa0,%rsp
movl   $0x0,-0x4(%rbp)
movl   $0x8,-0x8(%rbp)
movl   $0xfffffffe,-0xc(%rbp)
movsd  0xe88(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
movl   $0x0,-0x24(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x48(%rbp)
movl   $0x0,-0x24(%rbp)
cmpl   $0x8,-0x24(%rbp)
jg     12c6 <main+0x176>
cmpl   $0x0,-0x20(%rbp)
jne    11ce <main+0x7e>
cmpl   $0x1,-0x24(%rbp)
jne    11ce <main+0x7e>
mov    $0x0,%al
call   1060 <omp_get_num_threads@plt>
mov    %eax,-0x1c(%rbp)
cvtsi2sdl -0x1c(%rbp),%xmm0
lea    0xe51(%rip),%rdi
mov    $0x1,%al
call   1050 <printf@plt>
mov    $0x0,%al
call   1030 <omp_get_thread_num@plt>
mov    %eax,-0x20(%rbp)
cvtsi2sdl -0x24(%rbp),%xmm0
movsd  0xe1b(%rip),%xmm1
mulsd  %xmm1,%xmm0
movsd  0xe17(%rip),%xmm1
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
cvtsi2sdl -0x20(%rbp),%xmm0
mov    -0x24(%rbp),%esi
lea    0xe27(%rip),%rdi
mov    $0x1,%al
call   1050 <printf@plt>
movsd  0xdf0(%rip),%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  0xdeb(%rip),%xmm0
ucomisd -0x38(%rbp),%xmm0
jb     12b3 <main+0x163>
movsd  -0x30(%rbp),%xmm0
movsd  -0x38(%rbp),%xmm1
call   1070 <shubert@plt>
movsd  %xmm0,-0x40(%rbp)
movsd  -0x40(%rbp),%xmm1
movslq -0x20(%rbp),%rax
movsd  -0x90(%rbp,%rax,8),%xmm0
ff ff
ucomisd %xmm1,%xmm0
jbe    1272 <main+0x122>
movsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x98(%rbp)
ff
jmp    1287 <main+0x137>
movslq -0x20(%rbp),%rax
movsd  -0x90(%rbp,%rax,8),%xmm0
ff ff
movsd  %xmm0,-0x98(%rbp)
ff
movsd  -0x98(%rbp),%xmm0
ff
movslq -0x20(%rbp),%rax
movsd  %xmm0,-0x90(%rbp,%rax,8)
ff ff
movsd  0xd5c(%rip),%xmm0
addsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x38(%rbp)
jmp    121d <main+0xcd>
jmp    12b8 <main+0x168>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    1193 <main+0x43>
lea    -0x90(%rbp),%rdi
call   1040 <reduce@plt>
movsd  %xmm0,-0x48(%rbp)
movsd  -0x48(%rbp),%xmm0
lea    0xd61(%rip),%rdi
mov    $0x1,%al
call   1050 <printf@plt>
xor    %eax,%eax
add    $0xa0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x60,%rsp
xorpd  %xmm0,%xmm0
movsd  %xmm0,0x18(%rsp)
lea    0xed3(%rip),%r14
lea    0xee4(%rip),%r15
xor    %ebp,%ebp
jmp    12f3 <main+0x1a3>
nopl   0x0(%rax,%rax,1)
xor    %eax,%eax
call   1030 <omp_get_thread_num@plt>
mov    %eax,%ebx
movsd  0x18(%rsp),%xmm1
movsd  0xe69(%rip),%xmm0
mulsd  %xmm0,%xmm1
movsd  0xe65(%rip),%xmm0
addsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%rsp)
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
mov    %r15,%rdi
mov    %ebp,%esi
mov    $0x1,%al
call   1050 <printf@plt>
movslq %ebx,%r12
movsd  0x10(%rsp),%xmm0
movsd  0xe37(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x20(%rsp,%r12,8),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xe1f(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xe08(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xdf1(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
xorps  %xmm1,%xmm1
movsd  0x10(%rsp),%xmm0
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xd98(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xda1(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xd8a(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x8(%rsp)
movsd  0x10(%rsp),%xmm0
movsd  0xd73(%rip),%xmm1
call   1070 <shubert@plt>
minsd  0x8(%rsp),%xmm0
movsd  %xmm0,0x20(%rsp,%r12,8)
movsd  0x18(%rsp),%xmm0
addsd  0xd43(%rip),%xmm0
movsd  %xmm0,0x18(%rsp)
add    $0x1,%ebp
cmp    $0x9,%ebp
je     1321 <main+0x1d1>
test   %ebx,%ebx
jne    1180 <main+0x30>
cmp    $0x1,%ebp
jne    1180 <main+0x30>
xor    %eax,%eax
call   1060 <omp_get_num_threads@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
mov    %r14,%rdi
mov    $0x1,%al
call   1050 <printf@plt>
jmp    1180 <main+0x30>
lea    0x20(%rsp),%rdi
call   1040 <reduce@plt>
lea    0xd3a(%rip),%rdi
mov    $0x1,%al
call   1050 <printf@plt>
xor    %eax,%eax
add    $0x60,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@.str = [24 x i8] c"Number of threads = %d\0A\00"
@.str.1 = [20 x i8] c"Thread #%d, i = %d\0A\00"
@.str.2 = [19 x i8] c"Global min = %.2f\0A\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca i32
%3 = alloca i32
%4 = alloca double
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca double
%9 = alloca double
%10 = alloca double
%11 = alloca double
%12 = alloca [8 x double]
store i32 0, i32* %1
store i32 8, i32* %2
store i32 -2, i32* %3
store double 5.000000e-01, double* %4
store i32 0, i32* %7
store double 0.000000e+00, double* %11
store i32 0, i32* %7
br label %13
13: ; preds = %65, %0
%14 = load i32, i32* %7
%15 = icmp sle i32 %14, 8
br i1 %15, label %16, label %68
16: ; preds = %13
%17 = load i32, i32* %6
%18 = icmp eq i32 %17, 0
br i1 %18, label %19, label %27
19: ; preds = %16
%20 = load i32, i32* %7
%21 = icmp eq i32 %20, 1
br i1 %21, label %22, label %27
22: ; preds = %19
%23 = call i32 (...) @omp_get_num_threads()
store i32 %23, i32* %5
%24 = load i32, i32* %5
%25 = sitofp i32 %24 to double
%26 = call i32 (i8*, double, ...) @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i64 0, i64 0), double %25)
br label %27
27: ; preds = %22, %19, %16
%28 = call i32 (...) @omp_get_thread_num()
store i32 %28, i32* %6
%29 = load i32, i32* %7
%30 = sitofp i32 %29 to double
%31 = call double @llvm.fmuladd.f64(double 5.000000e-01, double %30, double -2.000000e+00)
store double %31, double* %8
%32 = load i32, i32* %6
%33 = sitofp i32 %32 to double
%34 = load i32, i32* %7
%35 = call i32 (i8*, double, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.1, i64 0, i64 0), double %33, i32 %34)
store double -2.000000e+00, double* %9
br label %36
36: ; preds = %61, %27
%37 = load double, double* %9
%38 = fcmp ole double %37, 2.000000e+00
br i1 %38, label %39, label %64
39: ; preds = %36
%40 = load double, double* %8
%41 = load double, double* %9
%42 = call double @shubert(double %40, double %41)
store double %42, double* %10
%43 = load double, double* %10
%44 = load i32, i32* %6
%45 = sext i32 %44 to i64
%46 = getelementptr inbounds [8 x double], [8 x double]* %12, i64 0, i64 %45
%47 = load double, double* %46
%48 = fcmp olt double %43, %47
br i1 %48, label %49, label %51
49: ; preds = %39
%50 = load double, double* %10
br label %56
51: ; preds = %39
%52 = load i32, i32* %6
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds [8 x double], [8 x double]* %12, i64 0, i64 %53
%55 = load double, double* %54
br label %56
56: ; preds = %51, %49
%57 = phi double [ %50, %49 ], [ %55, %51 ]
%58 = load i32, i32* %6
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds [8 x double], [8 x double]* %12, i64 0, i64 %59
store double %57, double* %60
br label %61
61: ; preds = %56
%62 = load double, double* %9
%63 = fadd double %62, 5.000000e-01
store double %63, double* %9
br label %36
64: ; preds = %36
br label %65
65: ; preds = %64
%66 = load i32, i32* %7
%67 = add nsw i32 %66, 1
store i32 %67, i32* %7
br label %13
68: ; preds = %13
%69 = getelementptr inbounds [8 x double], [8 x double]* %12, i64 0, i64 0
%70 = call double @reduce(double* %69)
store double %70, double* %11
%71 = load double, double* %11
%72 = call i32 (i8*, double, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.2, i64 0, i64 0), double %71)
ret i32 0
}

LLVM IR (-O2):
@.str = [24 x i8] c"Number of threads = %d\0A\00"
@.str.1 = [20 x i8] c"Thread #%d, i = %d\0A\00"
@.str.2 = [19 x i8] c"Global min = %.2f\0A\00"
define i32 @main() {
%1 = alloca [8 x double]
%2 = bitcast [8 x double]* %1 to i8*
br label %3
3: ; preds = %0, %13
%4 = phi i32 [ undef, %0 ], [ %14, %13 ]
%5 = phi i32 [ 0, %0 ], [ %49, %13 ]
%6 = icmp eq i32 %4, 0
%7 = icmp eq i32 %5, 1
%8 = select i1 %6, i1 %7, i1 false
br i1 %8, label %9, label %13
9: ; preds = %3
%10 = tail call i32 (...) @omp_get_num_threads()
%11 = sitofp i32 %10 to double
%12 = tail call i32 (i8*, double, ...) @printf(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @.str, i64 0, i64 0), double %11)
br label %13
13: ; preds = %9, %3
%14 = tail call i32 (...) @omp_get_thread_num()
%15 = sitofp i32 %5 to double
%16 = tail call double @llvm.fmuladd.f64(double %15, double 5.000000e-01, double -2.000000e+00)
%17 = sitofp i32 %14 to double
%18 = tail call i32 (i8*, double, ...) @printf(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str.1, i64 0, i64 0), double %17, i32 %5)
%19 = sext i32 %14 to i64
%20 = getelementptr inbounds [8 x double], [8 x double]* %1, i64 0, i64 %19
%21 = tail call double @shubert(double %16, double -2.000000e+00)
%22 = load double, double* %20
%23 = fcmp olt double %21, %22
%24 = select i1 %23, double %21, double %22
%25 = tail call double @shubert(double %16, double -1.500000e+00)
%26 = fcmp olt double %25, %24
%27 = select i1 %26, double %25, double %24
%28 = tail call double @shubert(double %16, double -1.000000e+00)
%29 = fcmp olt double %28, %27
%30 = select i1 %29, double %28, double %27
%31 = tail call double @shubert(double %16, double -5.000000e-01)
%32 = fcmp olt double %31, %30
%33 = select i1 %32, double %31, double %30
%34 = tail call double @shubert(double %16, double 0.000000e+00)
%35 = fcmp olt double %34, %33
%36 = select i1 %35, double %34, double %33
%37 = tail call double @shubert(double %16, double 5.000000e-01)
%38 = fcmp olt double %37, %36
%39 = select i1 %38, double %37, double %36
%40 = tail call double @shubert(double %16, double 1.000000e+00)
%41 = fcmp olt double %40, %39
%42 = select i1 %41, double %40, double %39
%43 = tail call double @shubert(double %16, double 1.500000e+00)
%44 = fcmp olt double %43, %42
%45 = select i1 %44, double %43, double %42
%46 = tail call double @shubert(double %16, double 2.000000e+00)
%47 = fcmp olt double %46, %45
%48 = select i1 %47, double %46, double %45
store double %48, double* %20
%49 = add nuw nsw i32 %5, 1
%50 = icmp eq i32 %49, 9
br i1 %50, label %51, label %3
51: ; preds = %13
%52 = getelementptr inbounds [8 x double], [8 x double]* %1, i64 0, i64 0
%53 = call double @reduce(double* %52)
%54 = call i32 (i8*, double, ...) @printf(i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.2, i64 0, i64 0), double %53)
ret i32 0
}