#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*/ addv(double, double const *, double, double *, int const,
                        double *);
int /*<<< orphan*/ copyv(double *, int const, double *);
double dot(double *, double *, int const);
int /*<<< orphan*/ free(double *);
scalar_t__ malloc(int);
int /*<<< orphan*/ matvec(double const *, double *, int const, double *);
double sqrt(double);
void cgm(const double *A, const double *b, const int n, int *max_iter,
         double *tol, double *x) {
  double *r = (double *)malloc(sizeof(double) * n);
  double *p = (double *)malloc(sizeof(double) * n);
  double *ap = (double *)malloc(sizeof(double) * n);
  matvec(A, x, n, r);
  addv(1.0, b, -1.0, r, n, r);
  copyv(r, n, p);
  double rr = dot(r, r, n);
  int k;
  for (k = 0; k < *max_iter; k++) {
    matvec(A, p, n, ap);
    double alpha = rr / dot(p, ap, n);
    addv(1.0, x, alpha, p, n, x);
    addv(1.0, r, -alpha, ap, n, r);
    double newrr = dot(r, r, n);
    if (sqrt(newrr) < *tol) {
      rr = newrr;
      k++;
      break;
    }
    addv(1.0, r, newrr / rr, p, n, p);
    rr = newrr;
  }
  *max_iter = k;
  *tol = sqrt(rr);
  free(r);
  free(p);
  free(ap);
}


x86 assembly (clang, -O0):
<cgm>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
mov    %r9,-0x30(%rbp)
movslq -0x14(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1060 <malloc@plt>
mov    %rax,-0x38(%rbp)
movslq -0x14(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1060 <malloc@plt>
mov    %rax,-0x40(%rbp)
movslq -0x14(%rbp),%rax
shl    $0x3,%rax
mov    %eax,%edi
call   1060 <malloc@plt>
mov    %rax,-0x48(%rbp)
mov    -0x8(%rbp),%rdi
mov    -0x30(%rbp),%rsi
mov    -0x14(%rbp),%edx
mov    -0x38(%rbp),%rcx
call   1080 <matvec@plt>
mov    -0x10(%rbp),%rdi
mov    -0x38(%rbp),%rsi
mov    -0x14(%rbp),%edx
mov    -0x38(%rbp),%rcx
movsd  0xe0d(%rip),%xmm0
movsd  0xe0d(%rip),%xmm1
call   1090 <addv@plt>
mov    -0x38(%rbp),%rdi
mov    -0x14(%rbp),%esi
mov    -0x40(%rbp),%rdx
call   1050 <copyv@plt>
mov    -0x38(%rbp),%rdi
mov    -0x38(%rbp),%rsi
mov    -0x14(%rbp),%edx
call   1030 <dot@plt>
movsd  %xmm0,-0x50(%rbp)
movl   $0x0,-0x54(%rbp)
mov    -0x54(%rbp),%eax
mov    -0x20(%rbp),%rcx
cmp    (%rcx),%eax
jge    135d <cgm+0x1ed>
mov    -0x8(%rbp),%rdi
mov    -0x40(%rbp),%rsi
mov    -0x14(%rbp),%edx
mov    -0x48(%rbp),%rcx
call   1080 <matvec@plt>
movsd  -0x50(%rbp),%xmm0
movsd  %xmm0,-0x70(%rbp)
mov    -0x40(%rbp),%rdi
mov    -0x48(%rbp),%rsi
mov    -0x14(%rbp),%edx
call   1030 <dot@plt>
movaps %xmm0,%xmm1
movsd  -0x70(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x30(%rbp),%rdi
movsd  -0x60(%rbp),%xmm1
mov    -0x40(%rbp),%rsi
mov    -0x14(%rbp),%edx
mov    -0x30(%rbp),%rcx
movsd  0xd6a(%rip),%xmm0
call   1090 <addv@plt>
mov    -0x38(%rbp),%rdi
movsd  -0x60(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm1
mov    -0x48(%rbp),%rsi
mov    -0x14(%rbp),%edx
mov    -0x38(%rbp),%rcx
movsd  0xd32(%rip),%xmm0
call   1090 <addv@plt>
mov    -0x38(%rbp),%rdi
mov    -0x38(%rbp),%rsi
mov    -0x14(%rbp),%edx
call   1030 <dot@plt>
movsd  %xmm0,-0x68(%rbp)
movsd  -0x68(%rbp),%xmm0
call   1070 <sqrt@plt>
movaps %xmm0,%xmm1
mov    -0x28(%rbp),%rax
movsd  (%rax),%xmm0
ucomisd %xmm1,%xmm0
jbe    131f <cgm+0x1af>
movsd  -0x68(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0x54(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x54(%rbp)
jmp    135d <cgm+0x1ed>
mov    -0x38(%rbp),%rdi
movsd  -0x68(%rbp),%xmm1
divsd  -0x50(%rbp),%xmm1
mov    -0x40(%rbp),%rsi
mov    -0x14(%rbp),%edx
mov    -0x40(%rbp),%rcx
movsd  0xcc0(%rip),%xmm0
call   1090 <addv@plt>
movsd  -0x68(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0x54(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x54(%rbp)
jmp    122c <cgm+0xbc>
mov    -0x54(%rbp),%ecx
mov    -0x20(%rbp),%rax
mov    %ecx,(%rax)
movsd  -0x50(%rbp),%xmm0
call   1070 <sqrt@plt>
mov    -0x28(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x38(%rbp),%rdi
call   1040 <free@plt>
mov    -0x40(%rbp),%rdi
call   1040 <free@plt>
mov    -0x48(%rbp),%rdi
call   1040 <free@plt>
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<cgm>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x38,%rsp
mov    %r9,%rbp
mov    %r8,0x18(%rsp)
mov    %rcx,0x10(%rsp)
mov    %edx,%r14d
mov    %rsi,0x8(%rsp)
mov    %rdi,%r13
lea    0x0(,%r14,8),%r12d
mov    %r12d,%edi
call   1060 <malloc@plt>
mov    %rax,%rbx
mov    %r12d,%edi
call   1060 <malloc@plt>
mov    %rax,%r15
mov    %r12d,%edi
call   1060 <malloc@plt>
mov    %rax,%r12
mov    %r13,0x30(%rsp)
mov    %r13,%rdi
mov    %rbp,%rsi
mov    %r14d,%edx
mov    %rbx,%rcx
call   1080 <matvec@plt>
movsd  0xe23(%rip),%xmm0
movsd  0xe23(%rip),%xmm1
mov    0x8(%rsp),%rdi
mov    %rbx,%rsi
mov    %r14d,%edx
mov    %rbx,%rcx
call   1090 <addv@plt>
mov    %rbx,%rdi
mov    %r14d,%esi
mov    %r15,%rdx
call   1050 <copyv@plt>
mov    %rbx,%rdi
mov    %rbx,%rsi
mov    %r14d,%edx
call   1030 <dot@plt>
mov    0x10(%rsp),%rax
cmpl   $0x0,(%rax)
jle    133c <cgm+0x1cc>
mov    $0x1,%r13d
nopl   0x0(%rax,%rax,1)
movsd  %xmm0,0x8(%rsp)
mov    0x30(%rsp),%rdi
mov    %r15,%rsi
mov    %r14d,%edx
mov    %r12,%rcx
call   1080 <matvec@plt>
mov    %r15,%rdi
mov    %r12,%rsi
mov    %r14d,%edx
call   1030 <dot@plt>
movsd  0x8(%rsp),%xmm1
divsd  %xmm0,%xmm1
movapd %xmm1,0x20(%rsp)
movsd  0xd91(%rip),%xmm0
mov    %rbp,%rdi
mov    %r15,%rsi
mov    %r14d,%edx
mov    %rbp,%rcx
call   1090 <addv@plt>
movaps 0x20(%rsp),%xmm1
xorps  0xd94(%rip),%xmm1
movsd  0xd6c(%rip),%xmm0
mov    %rbx,%rdi
mov    %r12,%rsi
mov    %r14d,%edx
mov    %rbx,%rcx
call   1090 <addv@plt>
mov    %rbx,%rdi
mov    %rbx,%rsi
mov    %r14d,%edx
call   1030 <dot@plt>
movapd %xmm0,%xmm2
ucomisd 0xd51(%rip),%xmm0
movsd  %xmm0,0x20(%rsp)
jb     12d0 <cgm+0x160>
xorps  %xmm0,%xmm0
sqrtsd %xmm2,%xmm0
jmp    12df <cgm+0x16f>
movapd %xmm2,%xmm0
call   1070 <sqrt@plt>
movsd  0x20(%rsp),%xmm2
mov    0x18(%rsp),%rax
movsd  (%rax),%xmm1
ucomisd %xmm0,%xmm1
movsd  0xd0c(%rip),%xmm0
ja     1341 <cgm+0x1d1>
movapd %xmm2,%xmm1
divsd  0x8(%rsp),%xmm1
mov    %rbx,%rdi
mov    %r15,%rsi
mov    %r14d,%edx
mov    %r15,%rcx
call   1090 <addv@plt>
movsd  0x20(%rsp),%xmm1
lea    0x1(%r13),%eax
movapd %xmm1,%xmm0
mov    0x10(%rsp),%rcx
cmp    (%rcx),%r13d
mov    %eax,%r13d
jl     1230 <cgm+0xc0>
add    $0xffffffff,%eax
mov    %eax,%r13d
movapd %xmm1,%xmm0
jmp    1345 <cgm+0x1d5>
xor    %r13d,%r13d
jmp    1345 <cgm+0x1d5>
movapd %xmm2,%xmm0
mov    0x10(%rsp),%rax
mov    %r13d,(%rax)
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jb     135d <cgm+0x1ed>
sqrtsd %xmm0,%xmm0
jmp    1362 <cgm+0x1f2>
call   1070 <sqrt@plt>
mov    0x18(%rsp),%rax
movsd  %xmm0,(%rax)
mov    %rbx,%rdi
call   1040 <free@plt>
mov    %r15,%rdi
call   1040 <free@plt>
mov    %r12,%rdi
add    $0x38,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
jmp    1040 <free@plt>

LLVM IR (-O0):
define void @cgm(double* %0, double* %1, i32 %2, i32* %3, double* %4, double* %5) {
%7 = alloca double*
%8 = alloca double*
%9 = alloca i32
%10 = alloca i32*
%11 = alloca double*
%12 = alloca double*
%13 = alloca double*
%14 = alloca double*
%15 = alloca double*
%16 = alloca double
%17 = alloca i32
%18 = alloca double
%19 = alloca double
store double* %0, double** %7
store double* %1, double** %8
store i32 %2, i32* %9
store i32* %3, i32** %10
store double* %4, double** %11
store double* %5, double** %12
%20 = load i32, i32* %9
%21 = sext i32 %20 to i64
%22 = mul i64 8, %21
%23 = trunc i64 %22 to i32
%24 = call i64 @malloc(i32 %23)
%25 = inttoptr i64 %24 to double*
store double* %25, double** %13
%26 = load i32, i32* %9
%27 = sext i32 %26 to i64
%28 = mul i64 8, %27
%29 = trunc i64 %28 to i32
%30 = call i64 @malloc(i32 %29)
%31 = inttoptr i64 %30 to double*
store double* %31, double** %14
%32 = load i32, i32* %9
%33 = sext i32 %32 to i64
%34 = mul i64 8, %33
%35 = trunc i64 %34 to i32
%36 = call i64 @malloc(i32 %35)
%37 = inttoptr i64 %36 to double*
store double* %37, double** %15
%38 = load double*, double** %7
%39 = load double*, double** %12
%40 = load i32, i32* %9
%41 = load double*, double** %13
%42 = call i32 @matvec(double* %38, double* %39, i32 %40, double* %41)
%43 = load double*, double** %8
%44 = load double*, double** %13
%45 = load i32, i32* %9
%46 = load double*, double** %13
%47 = call i32 @addv(double 1.000000e+00, double* %43, double -1.000000e+00, double* %44, i32 %45, double* %46)
%48 = load double*, double** %13
%49 = load i32, i32* %9
%50 = load double*, double** %14
%51 = call i32 @copyv(double* %48, i32 %49, double* %50)
%52 = load double*, double** %13
%53 = load double*, double** %13
%54 = load i32, i32* %9
%55 = call double @dot(double* %52, double* %53, i32 %54)
store double %55, double* %16
store i32 0, i32* %17
br label %56
56: ; preds = %109, %6
%57 = load i32, i32* %17
%58 = load i32*, i32** %10
%59 = load i32, i32* %58
%60 = icmp slt i32 %57, %59
br i1 %60, label %61, label %112
61: ; preds = %56
%62 = load double*, double** %7
%63 = load double*, double** %14
%64 = load i32, i32* %9
%65 = load double*, double** %15
%66 = call i32 @matvec(double* %62, double* %63, i32 %64, double* %65)
%67 = load double, double* %16
%68 = load double*, double** %14
%69 = load double*, double** %15
%70 = load i32, i32* %9
%71 = call double @dot(double* %68, double* %69, i32 %70)
%72 = fdiv double %67, %71
store double %72, double* %18
%73 = load double*, double** %12
%74 = load double, double* %18
%75 = load double*, double** %14
%76 = load i32, i32* %9
%77 = load double*, double** %12
%78 = call i32 @addv(double 1.000000e+00, double* %73, double %74, double* %75, i32 %76, double* %77)
%79 = load double*, double** %13
%80 = load double, double* %18
%81 = fneg double %80
%82 = load double*, double** %15
%83 = load i32, i32* %9
%84 = load double*, double** %13
%85 = call i32 @addv(double 1.000000e+00, double* %79, double %81, double* %82, i32 %83, double* %84)
%86 = load double*, double** %13
%87 = load double*, double** %13
%88 = load i32, i32* %9
%89 = call double @dot(double* %86, double* %87, i32 %88)
store double %89, double* %19
%90 = load double, double* %19
%91 = call double @sqrt(double %90)
%92 = load double*, double** %11
%93 = load double, double* %92
%94 = fcmp olt double %91, %93
br i1 %94, label %95, label %99
95: ; preds = %61
%96 = load double, double* %19
store double %96, double* %16
%97 = load i32, i32* %17
%98 = add nsw i32 %97, 1
store i32 %98, i32* %17
br label %112
99: ; preds = %61
%100 = load double*, double** %13
%101 = load double, double* %19
%102 = load double, double* %16
%103 = fdiv double %101, %102
%104 = load double*, double** %14
%105 = load i32, i32* %9
%106 = load double*, double** %14
%107 = call i32 @addv(double 1.000000e+00, double* %100, double %103, double* %104, i32 %105, double* %106)
%108 = load double, double* %19
store double %108, double* %16
br label %109
109: ; preds = %99
%110 = load i32, i32* %17
%111 = add nsw i32 %110, 1
store i32 %111, i32* %17
br label %56
112: ; preds = %95, %56
%113 = load i32, i32* %17
%114 = load i32*, i32** %10
store i32 %113, i32* %114
%115 = load double, double* %16
%116 = call double @sqrt(double %115)
%117 = load double*, double** %11
store double %116, double* %117
%118 = load double*, double** %13
%119 = call i32 @free(double* %118)
%120 = load double*, double** %14
%121 = call i32 @free(double* %120)
%122 = load double*, double** %15
%123 = call i32 @free(double* %122)
ret void
}

LLVM IR (-O2):
define void @cgm(double* %0, double* %1, i32 %2, i32* nocapture %3, double* nocapture %4, double* %5) {
%7 = shl i32 %2, 3
%8 = tail call i64 @malloc(i32 %7)
%9 = inttoptr i64 %8 to double*
%10 = tail call i64 @malloc(i32 %7)
%11 = inttoptr i64 %10 to double*
%12 = tail call i64 @malloc(i32 %7)
%13 = inttoptr i64 %12 to double*
%14 = tail call i32 @matvec(double* %0, double* %5, i32 %2, double* %9)
%15 = tail call i32 @addv(double 1.000000e+00, double* %1, double -1.000000e+00, double* %9, i32 %2, double* %9)
%16 = tail call i32 @copyv(double* %9, i32 %2, double* %11)
%17 = tail call double @dot(double* %9, double* %9, i32 %2)
%18 = load i32, i32* %3
%19 = icmp sgt i32 %18, 0
br i1 %19, label %20, label %41
20: ; preds = %6, %35
%21 = phi double [ %29, %35 ], [ %17, %6 ]
%22 = phi i32 [ %38, %35 ], [ 0, %6 ]
%23 = tail call i32 @matvec(double* %0, double* %11, i32 %2, double* %13)
%24 = tail call double @dot(double* %11, double* %13, i32 %2)
%25 = fdiv double %21, %24
%26 = tail call i32 @addv(double 1.000000e+00, double* %5, double %25, double* %11, i32 %2, double* %5)
%27 = fneg double %25
%28 = tail call i32 @addv(double 1.000000e+00, double* %9, double %27, double* %13, i32 %2, double* %9)
%29 = tail call double @dot(double* %9, double* %9, i32 %2)
%30 = tail call double @sqrt(double %29)
%31 = load double, double* %4
%32 = fcmp olt double %30, %31
br i1 %32, label %33, label %35
33: ; preds = %20
%34 = add nuw nsw i32 %22, 1
br label %41
35: ; preds = %20
%36 = fdiv double %29, %21
%37 = tail call i32 @addv(double 1.000000e+00, double* %9, double %36, double* %11, i32 %2, double* %11)
%38 = add nuw nsw i32 %22, 1
%39 = load i32, i32* %3
%40 = icmp slt i32 %38, %39
br i1 %40, label %20, label %41
41: ; preds = %35, %6, %33
%42 = phi i32 [ %34, %33 ], [ 0, %6 ], [ %38, %35 ]
%43 = phi double [ %29, %33 ], [ %17, %6 ], [ %29, %35 ]
store i32 %42, i32* %3
%44 = tail call double @sqrt(double %43)
store double %44, double* %4
%45 = tail call i32 @free(double* %9)
%46 = tail call i32 @free(double* %11)
%47 = tail call i32 @free(double* %13)
ret void
}