#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 */
double fabs(double);
int /*<<< orphan*/ relax_ab(double *, int, int, int, double *, double *);
double relax_dot(double *, int, double *, int, int);
double relax_graddesc(double *A, int m, int n, int stride, double *x0,
                      double *res, double *ares) {
  double a, restmp, maxres;
  int i;
  relax_ab(A, m, n, stride, res, ares);
  a = relax_dot(res, 1, res, 1, n) / relax_dot(res, 1, ares, 1, n);
  x0[0] = x0[0] + a * res[0];
  res[0] = res[0] - a * ares[0];
  maxres = fabs(res[0]);
  for (i = 1; i < m; i++) {
    x0[i] = x0[i] + a * res[i];
    res[i] = res[i] - a * ares[i];
    restmp = fabs(res[i]);
    maxres = maxres > restmp ? maxres : restmp;
  }
  return maxres;
}


x86 assembly (clang, -O0):
<relax_graddesc>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    0x10(%rbp),%rax
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %ecx,-0x14(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
mov    -0x8(%rbp),%rdi
mov    -0xc(%rbp),%esi
mov    -0x10(%rbp),%edx
mov    -0x14(%rbp),%ecx
mov    -0x28(%rbp),%r8
mov    0x10(%rbp),%r9
call   1030 <relax_ab@plt>
mov    -0x28(%rbp),%rdi
mov    -0x28(%rbp),%rdx
mov    -0x10(%rbp),%r8d
mov    $0x1,%ecx
mov    %ecx,%esi
call   1040 <relax_dot@plt>
movsd  %xmm0,-0x50(%rbp)
mov    -0x28(%rbp),%rdi
mov    0x10(%rbp),%rdx
mov    -0x10(%rbp),%r8d
mov    $0x1,%ecx
mov    %ecx,%esi
call   1040 <relax_dot@plt>
movaps %xmm0,%xmm1
movsd  -0x50(%rbp),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm1
movsd  -0x30(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x28(%rbp),%rax
movsd  (%rax),%xmm1
movsd  -0x30(%rbp),%xmm0
mov    0x10(%rbp),%rax
movsd  (%rax),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x28(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x28(%rbp),%rax
movsd  (%rax),%xmm0
movaps 0xdef(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movl   $0x1,-0x44(%rbp)
mov    -0x44(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    130a <relax_graddesc+0x1ea>
mov    -0x20(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  -0x30(%rbp),%xmm0
mov    -0x28(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  -0x30(%rbp),%xmm0
mov    0x10(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x28(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
movslq -0x44(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movaps 0xd40(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
movsd  -0x40(%rbp),%xmm0
ucomisd -0x38(%rbp),%xmm0
jbe    12e8 <relax_graddesc+0x1c8>
movsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
jmp    12f2 <relax_graddesc+0x1d2>
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x58(%rbp),%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x44(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x44(%rbp)
jmp    1221 <relax_graddesc+0x101>
movsd  -0x40(%rbp),%xmm0
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<relax_graddesc>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x10,%rsp
mov    %r9,%rbx
mov    %r8,%r14
mov    %edx,%ebp
mov    %esi,%r12d
mov    0x40(%rsp),%r15
mov    %r9,%r8
mov    %r15,%r9
call   1030 <relax_ab@plt>
mov    %rbx,%rdi
mov    $0x1,%esi
mov    %rbx,%rdx
mov    $0x1,%ecx
mov    %ebp,%r8d
call   1040 <relax_dot@plt>
movapd %xmm0,(%rsp)
mov    %rbx,%rdi
mov    $0x1,%esi
mov    %r15,%rdx
mov    $0x1,%ecx
mov    %ebp,%r8d
call   1040 <relax_dot@plt>
movapd (%rsp),%xmm4
divsd  %xmm0,%xmm4
movsd  (%rbx),%xmm0
mulsd  %xmm4,%xmm0
addsd  (%r14),%xmm0
movsd  %xmm0,(%r14)
movsd  (%rbx),%xmm0
movsd  (%r15),%xmm1
mulsd  %xmm4,%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,(%rbx)
andpd  0xe5c(%rip),%xmm0
cmp    $0x2,%r12d
jl     121a <relax_graddesc+0xfa>
movapd 0xe3e(%rip),%xmm1
xorpd  %xmm4,%xmm1
mov    %r12d,%eax
mov    $0x1,%ecx
movapd 0xe3a(%rip),%xmm2
cs nopw 0x0(%rax,%rax,1)
movsd  (%rbx,%rcx,8),%xmm3
mulsd  %xmm4,%xmm3
addsd  (%r14,%rcx,8),%xmm3
movsd  %xmm3,(%r14,%rcx,8)
movsd  (%r15,%rcx,8),%xmm3
mulsd  %xmm1,%xmm3
addsd  (%rbx,%rcx,8),%xmm3
movsd  %xmm3,(%rbx,%rcx,8)
andpd  %xmm2,%xmm3
maxsd  %xmm3,%xmm0
add    $0x1,%rcx
cmp    %rcx,%rax
jne    11e0 <relax_graddesc+0xc0>
add    $0x10,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
define double @relax_graddesc(double* %0, i32 %1, i32 %2, i32 %3, double* nocapture %4, double* %5, double* %6) {
%8 = tail call i32 @relax_ab(double* %0, i32 %1, i32 %2, i32 %3, double* %5, double* %6)
%9 = tail call double @relax_dot(double* %5, i32 1, double* %5, i32 1, i32 %2)
%10 = tail call double @relax_dot(double* %5, i32 1, double* %6, i32 1, i32 %2)
%11 = fdiv double %9, %10
%12 = load double, double* %4
%13 = load double, double* %5
%14 = tail call double @llvm.fmuladd.f64(double %11, double %13, double %12)
store double %14, double* %4
%15 = load double, double* %5
%16 = load double, double* %6
%17 = fneg double %11
%18 = tail call double @llvm.fmuladd.f64(double %17, double %16, double %15)
store double %18, double* %5
%19 = tail call double @llvm.fabs.f64(double %18)
%20 = icmp sgt i32 %1, 1
br i1 %20, label %21, label %40
21: ; preds = %7
%22 = zext i32 %1 to i64
br label %23
23: ; preds = %21, %23
%24 = phi i64 [ 1, %21 ], [ %38, %23 ]
%25 = phi double [ %19, %21 ], [ %37, %23 ]
%26 = getelementptr inbounds double, double* %4, i64 %24
%27 = load double, double* %26
%28 = getelementptr inbounds double, double* %5, i64 %24
%29 = load double, double* %28
%30 = tail call double @llvm.fmuladd.f64(double %11, double %29, double %27)
store double %30, double* %26
%31 = load double, double* %28
%32 = getelementptr inbounds double, double* %6, i64 %24
%33 = load double, double* %32
%34 = tail call double @llvm.fmuladd.f64(double %17, double %33, double %31)
store double %34, double* %28
%35 = tail call double @llvm.fabs.f64(double %34)
%36 = fcmp ogt double %25, %35
%37 = select i1 %36, double %25, double %35
%38 = add nuw nsw i64 %24, 1
%39 = icmp eq i64 %38, %22
br i1 %39, label %40, label %23
40: ; preds = %23, %7
%41 = phi double [ %19, %7 ], [ %37, %23 ]
ret double %41
}