#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 /*<<< orphan*/ memset(double *, int /*<<< orphan*/, int);
int /*<<< orphan*/ printf(char *, double);
int main() {
  double sum[4000], pi, total = 0;
  memset(sum, 0, sizeof(double) * 4000);
  double step = 1.0 / (double)4000;
#pragma omp parallel for schedule(static) check
  for (int i = 0; i < 4000; ++i) {
    double x = (i + 0.5) * step;
    sum[i] = 4.0 / (1.0 + x * x);
  }
  for (int j = 0; j < 4000; ++j) {
    total += sum[j];
  }
  pi = step * total;
  printf("PI: %f\n", pi);
  return pi;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x7d40,%rsp
movl   $0x0,-0x4(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x7d20(%rbp)
ff
lea    -0x7d10(%rbp),%rdi
xor    %esi,%esi
mov    $0x7d00,%edx
call   1040 <memset@plt>
movsd  0xea8(%rip),%xmm0
movsd  %xmm0,-0x7d28(%rbp)
ff
movl   $0x0,-0x7d2c(%rbp)
cmpl   $0xfa0,-0x7d2c(%rbp)
jge    11ee <main+0xce>
cvtsi2sdl -0x7d2c(%rbp),%xmm0
ff
movsd  0xe8e(%rip),%xmm1
addsd  %xmm1,%xmm0
mulsd  -0x7d28(%rbp),%xmm0
ff
movsd  %xmm0,-0x7d38(%rbp)
ff
movsd  -0x7d38(%rbp),%xmm1
ff
movsd  -0x7d38(%rbp),%xmm0
ff
mulsd  %xmm0,%xmm1
movsd  0xe56(%rip),%xmm0
addsd  %xmm0,%xmm1
movsd  0xe42(%rip),%xmm0
divsd  %xmm1,%xmm0
movslq -0x7d2c(%rbp),%rax
movsd  %xmm0,-0x7d10(%rbp,%rax,8)
ff ff
mov    -0x7d2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x7d2c(%rbp)
jmp    116a <main+0x4a>
movl   $0x0,-0x7d3c(%rbp)
cmpl   $0xfa0,-0x7d3c(%rbp)
jge    123c <main+0x11c>
movslq -0x7d3c(%rbp),%rax
movsd  -0x7d10(%rbp,%rax,8),%xmm0
ff ff
addsd  -0x7d20(%rbp),%xmm0
ff
movsd  %xmm0,-0x7d20(%rbp)
ff
mov    -0x7d3c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x7d3c(%rbp)
jmp    11f8 <main+0xd8>
movsd  -0x7d28(%rbp),%xmm0
ff
mulsd  -0x7d20(%rbp),%xmm0
ff
movsd  %xmm0,-0x7d18(%rbp)
ff
movsd  -0x7d18(%rbp),%xmm0
ff
lea    0xdbd(%rip),%rdi
call   1030 <printf@plt>
cvttsd2si -0x7d18(%rbp),%eax
ff
add    $0x7d40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
sub    $0x7d18,%rsp
lea    0x10(%rsp),%rdi
xor    %esi,%esi
mov    $0x7d00,%edx
call   1040 <memset@plt>
movdqa 0xec0(%rip),%xmm5
mov    $0x2,%eax
movapd 0xec3(%rip),%xmm1
movapd 0xecb(%rip),%xmm2
movapd 0xed3(%rip),%xmm3
movapd 0xedb(%rip),%xmm6
movdqa 0xee2(%rip),%xmm8
movdqa 0xee9(%rip),%xmm9
nopw   0x0(%rax,%rax,1)
cvtdq2pd %xmm5,%xmm7
addpd  %xmm1,%xmm7
movdqa %xmm5,%xmm0
mulpd  %xmm2,%xmm7
paddd  %xmm8,%xmm0
cvtdq2pd %xmm0,%xmm0
mulpd  %xmm7,%xmm7
addpd  %xmm3,%xmm7
movapd %xmm6,%xmm4
addpd  %xmm1,%xmm0
mulpd  %xmm2,%xmm0
divpd  %xmm7,%xmm4
mulpd  %xmm0,%xmm0
addpd  %xmm3,%xmm0
movapd %xmm6,%xmm7
divpd  %xmm0,%xmm7
movapd %xmm4,(%rsp,%rax,8)
movapd %xmm7,0x10(%rsp,%rax,8)
paddd  %xmm9,%xmm5
add    $0x4,%rax
cmp    $0xfa2,%rax
jne    1180 <main+0x60>
xorpd  %xmm0,%xmm0
mov    $0x7,%eax
cs nopw 0x0(%rax,%rax,1)
addsd  -0x28(%rsp,%rax,8),%xmm0
addsd  -0x20(%rsp,%rax,8),%xmm0
addsd  -0x18(%rsp,%rax,8),%xmm0
addsd  -0x10(%rsp,%rax,8),%xmm0
addsd  -0x8(%rsp,%rax,8),%xmm0
addsd  (%rsp,%rax,8),%xmm0
addsd  0x8(%rsp,%rax,8),%xmm0
addsd  0x10(%rsp,%rax,8),%xmm0
add    $0x8,%rax
cmp    $0xfa7,%rax
jne    11f0 <main+0xd0>
mulsd  0xe3d(%rip),%xmm0
lea    0xe3e(%rip),%rdi
movsd  %xmm0,0x8(%rsp)
call   1030 <printf@plt>
cvttsd2si 0x8(%rsp),%eax
add    $0x7d18,%rsp
ret

LLVM IR (-O0):
@.str = [8 x i8] c"PI: %f\0A\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca [4000 x double]
%3 = alloca double
%4 = alloca double
%5 = alloca double
%6 = alloca i32
%7 = alloca double
%8 = alloca i32
store i32 0, i32* %1
store double 0.000000e+00, double* %4
%9 = getelementptr inbounds [4000 x double], [4000 x double]* %2, i64 0, i64 0
%10 = call i32 @memset(double* %9, i32 0, i32 32000)
store double 2.500000e-04, double* %5
store i32 0, i32* %6
br label %11
11: ; preds = %27, %0
%12 = load i32, i32* %6
%13 = icmp slt i32 %12, 4000
br i1 %13, label %14, label %30
14: ; preds = %11
%15 = load i32, i32* %6
%16 = sitofp i32 %15 to double
%17 = fadd double %16, 5.000000e-01
%18 = load double, double* %5
%19 = fmul double %17, %18
store double %19, double* %7
%20 = load double, double* %7
%21 = load double, double* %7
%22 = call double @llvm.fmuladd.f64(double %20, double %21, double 1.000000e+00)
%23 = fdiv double 4.000000e+00, %22
%24 = load i32, i32* %6
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds [4000 x double], [4000 x double]* %2, i64 0, i64 %25
store double %23, double* %26
br label %27
27: ; preds = %14
%28 = load i32, i32* %6
%29 = add nsw i32 %28, 1
store i32 %29, i32* %6
br label %11
30: ; preds = %11
store i32 0, i32* %8
br label %31
31: ; preds = %41, %30
%32 = load i32, i32* %8
%33 = icmp slt i32 %32, 4000
br i1 %33, label %34, label %44
34: ; preds = %31
%35 = load i32, i32* %8
%36 = sext i32 %35 to i64
%37 = getelementptr inbounds [4000 x double], [4000 x double]* %2, i64 0, i64 %36
%38 = load double, double* %37
%39 = load double, double* %4
%40 = fadd double %39, %38
store double %40, double* %4
br label %41
41: ; preds = %34
%42 = load i32, i32* %8
%43 = add nsw i32 %42, 1
store i32 %43, i32* %8
br label %31
44: ; preds = %31
%45 = load double, double* %5
%46 = load double, double* %4
%47 = fmul double %45, %46
store double %47, double* %3
%48 = load double, double* %3
%49 = call i32 @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), double %48)
%50 = load double, double* %3
%51 = fptosi double %50 to i32
ret i32 %51
}

LLVM IR (-O2):
@.str = [8 x i8] c"PI: %f\0A\00"
define i32 @main() {
%1 = alloca [4000 x double]
%2 = bitcast [4000 x double]* %1 to i8*
%3 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 0
%4 = call i32 @memset(double* %3, i32 0, i32 32000)
br label %5
5: ; preds = %5, %0
%6 = phi i64 [ 0, %0 ], [ %24, %5 ]
%7 = phi <2 x i32> [ <i32 0, i32 1>, %0 ], [ %25, %5 ]
%8 = sitofp <2 x i32> %7 to <2 x double>
%9 = fadd <2 x double> %8, <double 5.000000e-01, double 5.000000e-01>
%10 = fmul <2 x double> %9, <double 2.500000e-04, double 2.500000e-04>
%11 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %10, <2 x double> %10, <2 x double> <double 1.000000e+00, double 1.000000e+00>)
%12 = fdiv <2 x double> <double 4.000000e+00, double 4.000000e+00>, %11
%13 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %6
%14 = bitcast double* %13 to <2 x double>*
store <2 x double> %12, <2 x double>* %14
%15 = or i64 %6, 2
%16 = add <2 x i32> %7, <i32 2, i32 2>
%17 = sitofp <2 x i32> %16 to <2 x double>
%18 = fadd <2 x double> %17, <double 5.000000e-01, double 5.000000e-01>
%19 = fmul <2 x double> %18, <double 2.500000e-04, double 2.500000e-04>
%20 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %19, <2 x double> %19, <2 x double> <double 1.000000e+00, double 1.000000e+00>)
%21 = fdiv <2 x double> <double 4.000000e+00, double 4.000000e+00>, %20
%22 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %15
%23 = bitcast double* %22 to <2 x double>*
store <2 x double> %21, <2 x double>* %23
%24 = add nuw nsw i64 %6, 4
%25 = add <2 x i32> %7, <i32 4, i32 4>
%26 = icmp eq i64 %24, 4000
br i1 %26, label %31, label %5
27: ; preds = %31
%28 = fmul double %64, 2.500000e-04
%29 = call i32 @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), double %28)
%30 = fptosi double %28 to i32
ret i32 %30
31: ; preds = %5, %31
%32 = phi i64 [ %65, %31 ], [ 0, %5 ]
%33 = phi double [ %64, %31 ], [ 0.000000e+00, %5 ]
%34 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %32
%35 = load double, double* %34
%36 = fadd double %33, %35
%37 = or i64 %32, 1
%38 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %37
%39 = load double, double* %38
%40 = fadd double %36, %39
%41 = or i64 %32, 2
%42 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %41
%43 = load double, double* %42
%44 = fadd double %40, %43
%45 = or i64 %32, 3
%46 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %45
%47 = load double, double* %46
%48 = fadd double %44, %47
%49 = or i64 %32, 4
%50 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %49
%51 = load double, double* %50
%52 = fadd double %48, %51
%53 = or i64 %32, 5
%54 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %53
%55 = load double, double* %54
%56 = fadd double %52, %55
%57 = or i64 %32, 6
%58 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %57
%59 = load double, double* %58
%60 = fadd double %56, %59
%61 = or i64 %32, 7
%62 = getelementptr inbounds [4000 x double], [4000 x double]* %1, i64 0, i64 %61
%63 = load double, double* %62
%64 = fadd double %60, %63
%65 = add nuw nsw i64 %32, 8
%66 = icmp eq i64 %65, 4000
br i1 %66, label %27, label %31
}