#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 const get_A(int, int);
void eval_At_times_u(int N, const double u[], double Au[]) {
  int i, j, n4;
  double t0, t1, t2, t3;
  n4 = N & ~3;
  for (i = 0; i < n4; i += 4) {
    t0 = 0;
    t1 = 0;
    t2 = 0;
    t3 = 0;
    for (j = 0; j < N; j++) {
      t0 += get_A(j, i) * u[j];
      t1 += get_A(j, i + 1) * u[j];
      t2 += get_A(j, i + 2) * u[j];
      t3 += get_A(j, i + 3) * u[j];
    }
    Au[i] = t0;
    Au[i + 1] = t1;
    Au[i + 2] = t2;
    Au[i + 3] = t3;
  }
  for (; i < N; i++) {
    t0 = 0;
    for (j = 0; j < N; j++) {
      t0 += get_A(j, i) * u[j];
    }
    Au[i] = t0;
  }
}


x86 assembly (clang, -O0):
<eval_At_times_u>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x4(%rbp),%eax
and    $0xfffffffc,%eax
mov    %eax,-0x24(%rbp)
movl   $0x0,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x24(%rbp),%eax
jge    1296 <eval_At_times_u+0x186>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x30(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x38(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x40(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x48(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1231 <eval_At_times_u+0x121>
mov    -0x20(%rbp),%edi
mov    -0x1c(%rbp),%esi
call   1030 <get_A@plt>
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x30(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x20(%rbp),%edi
mov    -0x1c(%rbp),%esi
add    $0x1,%esi
call   1030 <get_A@plt>
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x20(%rbp),%edi
mov    -0x1c(%rbp),%esi
add    $0x2,%esi
call   1030 <get_A@plt>
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x40(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x20(%rbp),%edi
mov    -0x1c(%rbp),%esi
add    $0x3,%esi
call   1030 <get_A@plt>
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x48(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    1166 <eval_At_times_u+0x56>
movsd  -0x30(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x1c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
movsd  -0x38(%rbp),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
movsd  -0x40(%rbp),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
movsd  -0x48(%rbp),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x1c(%rbp),%eax
add    $0x4,%eax
mov    %eax,-0x1c(%rbp)
jmp    1133 <eval_At_times_u+0x23>
jmp    129b <eval_At_times_u+0x18b>
mov    -0x1c(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    131a <eval_At_times_u+0x20a>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x30(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    12fa <eval_At_times_u+0x1ea>
mov    -0x20(%rbp),%edi
mov    -0x1c(%rbp),%esi
call   1030 <get_A@plt>
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x30(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    12b6 <eval_At_times_u+0x1a6>
movsd  -0x30(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x1c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    129b <eval_At_times_u+0x18b>
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<eval_At_times_u>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x98,%rsp
mov    %rdx,%r15
mov    %rsi,%rbx
mov    %edi,%eax
mov    %edi,0xc(%rsp)
mov    %edi,%r12d
and    $0xfffffffc,%eax
jle    129c <eval_At_times_u+0x18c>
mov    %r12,0x28(%rsp)
mov    %eax,%eax
mov    %rax,0x48(%rsp)
xor    %ebp,%ebp
mov    %r15,0x40(%rsp)
mov    0x28(%rsp),%r12
jmp    1183 <eval_At_times_u+0x73>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
xorpd  %xmm0,%xmm0
xorpd  %xmm3,%xmm3
movupd %xmm0,(%r15,%rbp,8)
movupd %xmm3,(%r15,%r13,8)
add    $0x4,%rbp
cmp    0x48(%rsp),%rbp
jae    128f <eval_At_times_u+0x17f>
mov    %rbp,%r13
or     $0x2,%r13
cmpl   $0x0,0xc(%rsp)
jle    1160 <eval_At_times_u+0x50>
mov    %ebp,%eax
or     $0x1,%eax
mov    %eax,0x24(%rsp)
mov    %ebp,%r15d
or     $0x3,%r15d
xorps  %xmm2,%xmm2
xor    %r14d,%r14d
xorps  %xmm0,%xmm0
nopw   0x0(%rax,%rax,1)
movaps %xmm0,0x80(%rsp)
movaps %xmm2,0x50(%rsp)
mov    %r14d,%edi
mov    %ebp,%esi
call   1030 <get_A@plt>
movaps %xmm0,0x30(%rsp)
movsd  (%rbx,%r14,8),%xmm0
movapd %xmm0,0x10(%rsp)
mov    %r14d,%edi
mov    0x24(%rsp),%esi
call   1030 <get_A@plt>
movapd 0x30(%rsp),%xmm1
unpcklpd %xmm0,%xmm1
movapd 0x10(%rsp),%xmm0
movhpd (%rbx,%r14,8),%xmm0
mulpd  %xmm1,%xmm0
movapd %xmm0,0x10(%rsp)
addpd  0x50(%rsp),%xmm0
movapd %xmm0,0x30(%rsp)
mov    %r14d,%edi
mov    %r13d,%esi
call   1030 <get_A@plt>
movapd %xmm0,0x70(%rsp)
movsd  (%rbx,%r14,8),%xmm0
movapd %xmm0,0x60(%rsp)
mov    %r14d,%edi
mov    %r15d,%esi
call   1030 <get_A@plt>
movapd 0x60(%rsp),%xmm3
movaps 0x30(%rsp),%xmm2
movapd 0x80(%rsp),%xmm1
movapd 0x70(%rsp),%xmm4
unpcklpd %xmm0,%xmm4
movhpd (%rbx,%r14,8),%xmm3
mulpd  %xmm4,%xmm3
movapd %xmm3,%xmm0
addpd  %xmm1,%xmm0
add    $0x1,%r14
cmp    %r14,%r12
jne    11b0 <eval_At_times_u+0xa0>
addpd  %xmm1,%xmm3
movapd 0x10(%rsp),%xmm0
addpd  0x50(%rsp),%xmm0
mov    0x40(%rsp),%r15
jmp    1168 <eval_At_times_u+0x58>
mov    0x28(%rsp),%r12
cmp    0xc(%rsp),%ebp
jl     12a4 <eval_At_times_u+0x194>
jmp    1306 <eval_At_times_u+0x1f6>
xor    %ebp,%ebp
cmp    0xc(%rsp),%ebp
jge    1306 <eval_At_times_u+0x1f6>
mov    %ebp,%r14d
jmp    12c3 <eval_At_times_u+0x1b3>
nopl   0x0(%rax)
xorpd  %xmm0,%xmm0
movsd  %xmm0,(%r15,%r14,8)
add    $0x1,%r14
cmp    %r12,%r14
je     1306 <eval_At_times_u+0x1f6>
cmpl   $0x0,0xc(%rsp)
jle    12b0 <eval_At_times_u+0x1a0>
xorpd  %xmm0,%xmm0
xor    %ebp,%ebp
movsd  %xmm0,0x10(%rsp)
mov    %ebp,%edi
mov    %r14d,%esi
call   1030 <get_A@plt>
mulsd  (%rbx,%rbp,8),%xmm0
movsd  0x10(%rsp),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%rsp)
movsd  0x10(%rsp),%xmm0
add    $0x1,%rbp
cmp    %rbp,%r12
jne    12d0 <eval_At_times_u+0x1c0>
jmp    12b4 <eval_At_times_u+0x1a4>
add    $0x98,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
define void @eval_At_times_u(i32 %0, double* nocapture %1, double* nocapture writeonly %2) {
%4 = and i32 %0, -4
%5 = icmp sgt i32 %4, 0
br i1 %5, label %6, label %22
6: ; preds = %3
%7 = icmp sgt i32 %0, 0
%8 = zext i32 %4 to i64
%9 = zext i32 %0 to i64
br label %10
10: ; preds = %6, %58
%11 = phi i64 [ 0, %6 ], [ %65, %58 ]
%12 = or i64 %11, 2
br i1 %7, label %13, label %58
13: ; preds = %10
%14 = trunc i64 %11 to i32
%15 = trunc i64 %11 to i32
%16 = or i32 %15, 1
%17 = trunc i64 %12 to i32
%18 = trunc i64 %11 to i32
%19 = or i32 %18, 3
br label %29
20: ; preds = %58
%21 = trunc i64 %65 to i32
br label %22
22: ; preds = %20, %3
%23 = phi i32 [ 0, %3 ], [ %21, %20 ]
%24 = icmp slt i32 %23, %0
br i1 %24, label %25, label %86
25: ; preds = %22
%26 = icmp sgt i32 %0, 0
%27 = zext i32 %23 to i64
%28 = zext i32 %0 to i64
br label %67
29: ; preds = %13, %29
%30 = phi i64 [ 0, %13 ], [ %53, %29 ]
%31 = phi <2 x double> [ zeroinitializer, %13 ], [ %43, %29 ]
%32 = phi <2 x double> [ zeroinitializer, %13 ], [ %52, %29 ]
%33 = trunc i64 %30 to i32
%34 = tail call double @get_A(i32 %33, i32 %14)
%35 = getelementptr inbounds double, double* %1, i64 %30
%36 = load double, double* %35
%37 = tail call double @get_A(i32 %33, i32 %16)
%38 = load double, double* %35
%39 = insertelement <2 x double> poison, double %34, i64 0
%40 = insertelement <2 x double> %39, double %37, i64 1
%41 = insertelement <2 x double> poison, double %36, i64 0
%42 = insertelement <2 x double> %41, double %38, i64 1
%43 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %40, <2 x double> %42, <2 x double> %31)
%44 = tail call double @get_A(i32 %33, i32 %17)
%45 = load double, double* %35
%46 = tail call double @get_A(i32 %33, i32 %19)
%47 = load double, double* %35
%48 = insertelement <2 x double> poison, double %44, i64 0
%49 = insertelement <2 x double> %48, double %46, i64 1
%50 = insertelement <2 x double> poison, double %45, i64 0
%51 = insertelement <2 x double> %50, double %47, i64 1
%52 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %49, <2 x double> %51, <2 x double> %32)
%53 = add nuw nsw i64 %30, 1
%54 = icmp eq i64 %53, %9
br i1 %54, label %55, label %29
55: ; preds = %29
%56 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %49, <2 x double> %51, <2 x double> %32)
%57 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %40, <2 x double> %42, <2 x double> %31)
br label %58
58: ; preds = %55, %10
%59 = phi <2 x double> [ zeroinitializer, %10 ], [ %57, %55 ]
%60 = phi <2 x double> [ zeroinitializer, %10 ], [ %56, %55 ]
%61 = getelementptr inbounds double, double* %2, i64 %11
%62 = bitcast double* %61 to <2 x double>*
store <2 x double> %59, <2 x double>* %62
%63 = getelementptr inbounds double, double* %2, i64 %12
%64 = bitcast double* %63 to <2 x double>*
store <2 x double> %60, <2 x double>* %64
%65 = add nuw nsw i64 %11, 4
%66 = icmp ult i64 %65, %8
br i1 %66, label %10, label %20
67: ; preds = %25, %81
%68 = phi i64 [ %27, %25 ], [ %84, %81 ]
br i1 %26, label %69, label %81
69: ; preds = %67
%70 = trunc i64 %68 to i32
br label %71
71: ; preds = %69, %71
%72 = phi i64 [ 0, %69 ], [ %79, %71 ]
%73 = phi double [ 0.000000e+00, %69 ], [ %78, %71 ]
%74 = trunc i64 %72 to i32
%75 = tail call double @get_A(i32 %74, i32 %70)
%76 = getelementptr inbounds double, double* %1, i64 %72
%77 = load double, double* %76
%78 = tail call double @llvm.fmuladd.f64(double %75, double %77, double %73)
%79 = add nuw nsw i64 %72, 1
%80 = icmp eq i64 %79, %28
br i1 %80, label %81, label %71
81: ; preds = %71, %67
%82 = phi double [ 0.000000e+00, %67 ], [ %78, %71 ]
%83 = getelementptr inbounds double, double* %2, i64 %68
store double %82, double* %83
%84 = add nuw nsw i64 %68, 1
%85 = icmp eq i64 %84, %28
br i1 %85, label %86, label %67
86: ; preds = %81, %22
ret void
}