void GaussSeidel(double **u_previous, double **u_current, int X_min, int X_max,
                 int Y_min, int Y_max, double omega) {
  int i, j;
  for (i = X_min; i < X_max; i++)
    for (j = Y_min; j < Y_max; j++)
      u_current[i][j] =
          u_previous[i][j] +
          (u_current[i - 1][j] + u_previous[i + 1][j] + u_current[i][j - 1] +
           u_previous[i][j + 1] - 4 * u_previous[i][j]) *
              omega / 4.0;
}


x86 assembly (clang, -O0):
<GaussSeidel>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    %r8d,-0x1c(%rbp)
mov    %r9d,-0x20(%rbp)
movsd  %xmm0,-0x28(%rbp)
mov    -0x14(%rbp),%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x18(%rbp),%eax
jge    1230 <GaussSeidel+0x130>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    121d <GaussSeidel+0x11d>
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mov    -0x8(%rbp),%rax
mov    -0x2c(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm2
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x30(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm2
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x30(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm2
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  0xe2b(%rip),%xmm3
mulsd  %xmm3,%xmm1
addsd  %xmm2,%xmm1
mulsd  -0x28(%rbp),%xmm1
movsd  0xe0e(%rip),%xmm2
divsd  %xmm2,%xmm1
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1137 <GaussSeidel+0x37>
jmp    1222 <GaussSeidel+0x122>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1125 <GaussSeidel+0x25>
pop    %rbp
ret

x86 assembly (clang, -O2):
<GaussSeidel>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
cmp    %ecx,%edx
jge    11a7 <GaussSeidel+0xa7>
movslq %r8d,%r10
movslq %edx,%r14
movslq %ecx,%r11
movslq %r9d,%r15
movsd  0xedb(%rip),%xmm1
movsd  0xedb(%rip),%xmm2
jmp    1139 <GaussSeidel+0x39>
nop
add    $0x1,%r14
cmp    %r11,%r14
je     11a7 <GaussSeidel+0xa7>
cmp    %r9d,%r8d
jge    1130 <GaussSeidel+0x30>
mov    (%rdi,%r14,8),%rcx
mov    0x8(%rdi,%r14,8),%r12
mov    -0x8(%rsi,%r14,8),%r13
mov    (%rsi,%r14,8),%rax
add    $0x1,%r14
movsd  -0x8(%rax,%r10,8),%xmm3
mov    %r10,%rbx
xchg   %ax,%ax
movsd  0x0(%r13,%rbx,8),%xmm4
addsd  (%r12,%rbx,8),%xmm4
movsd  (%rcx,%rbx,8),%xmm5
addsd  %xmm3,%xmm4
addsd  0x8(%rcx,%rbx,8),%xmm4
movapd %xmm5,%xmm3
mulsd  %xmm1,%xmm3
addsd  %xmm4,%xmm3
mulsd  %xmm0,%xmm3
mulsd  %xmm2,%xmm3
addsd  %xmm5,%xmm3
movsd  %xmm3,(%rax,%rbx,8)
lea    0x1(%rbx),%rdx
mov    %rdx,%rbx
cmp    %rdx,%r15
jne    1160 <GaussSeidel+0x60>
jmp    1134 <GaussSeidel+0x34>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

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

LLVM IR (-O2):
define void @GaussSeidel(double** nocapture %0, double** nocapture %1, i32 %2, i32 %3, i32 %4, i32 %5, double %6) {
%8 = icmp slt i32 %2, %3
br i1 %8, label %9, label %57
9: ; preds = %7
%10 = icmp slt i32 %4, %5
%11 = sext i32 %4 to i64
%12 = sext i32 %2 to i64
%13 = sext i32 %3 to i64
%14 = sext i32 %5 to i64
%15 = add nsw i64 %11, -1
br label %16
16: ; preds = %9, %54
%17 = phi i64 [ %12, %9 ], [ %55, %54 ]
br i1 %10, label %20, label %18
18: ; preds = %16
%19 = add nsw i64 %17, 1
br label %54
20: ; preds = %16
%21 = getelementptr inbounds double*, double** %0, i64 %17
%22 = load double*, double** %21
%23 = add nsw i64 %17, -1
%24 = getelementptr inbounds double*, double** %1, i64 %23
%25 = load double*, double** %24
%26 = add nsw i64 %17, 1
%27 = getelementptr inbounds double*, double** %0, i64 %26
%28 = load double*, double** %27
%29 = getelementptr inbounds double*, double** %1, i64 %17
%30 = load double*, double** %29
%31 = getelementptr double, double* %30, i64 %15
%32 = load double, double* %31
br label %33
33: ; preds = %20, %33
%34 = phi double [ %32, %20 ], [ %51, %33 ]
%35 = phi i64 [ %11, %20 ], [ %44, %33 ]
%36 = getelementptr inbounds double, double* %22, i64 %35
%37 = load double, double* %36
%38 = getelementptr inbounds double, double* %25, i64 %35
%39 = load double, double* %38
%40 = getelementptr inbounds double, double* %28, i64 %35
%41 = load double, double* %40
%42 = fadd double %39, %41
%43 = fadd double %42, %34
%44 = add nsw i64 %35, 1
%45 = getelementptr inbounds double, double* %22, i64 %44
%46 = load double, double* %45
%47 = fadd double %43, %46
%48 = tail call double @llvm.fmuladd.f64(double %37, double -4.000000e+00, double %47)
%49 = fmul double %48, %6
%50 = fmul double %49, 2.500000e-01
%51 = fadd double %37, %50
%52 = getelementptr inbounds double, double* %30, i64 %35
store double %51, double* %52
%53 = icmp eq i64 %44, %14
br i1 %53, label %54, label %33
54: ; preds = %33, %18
%55 = phi i64 [ %19, %18 ], [ %26, %33 ]
%56 = icmp eq i64 %55, %13
br i1 %56, label %57, label %16
57: ; preds = %54, %7
ret void
}