void Jacobi(double **u_previous, double **u_current, int X_min, int X_max,
            int Y_min, int Y_max) {
  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 - 1][j] + u_previous[i + 1][j] +
                         u_previous[i][j - 1] + u_previous[i][j + 1]) /
                        4.0;
}


x86 assembly (clang, -O0):
<Jacobi>:
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)
mov    -0x14(%rbp),%eax
mov    %eax,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x18(%rbp),%eax
jge    11e8 <Jacobi+0xe8>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    11d5 <Jacobi+0xd5>
mov    -0x8(%rbp),%rax
mov    -0x24(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x8(%rbp),%rax
mov    -0x24(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x28(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm0
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x28(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm0
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x28(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
addsd  (%rax,%rcx,8),%xmm0
movsd  0xe52(%rip),%xmm1
divsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movslq -0x24(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x28(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1132 <Jacobi+0x32>
jmp    11da <Jacobi+0xda>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    1120 <Jacobi+0x20>
pop    %rbp
ret

x86 assembly (clang, -O2):
<Jacobi>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %r8d,-0x54(%rsp)
mov    %rsi,-0x8(%rsp)
mov    %rdi,-0x10(%rsp)
cmp    %ecx,%edx
jge    13c6 <Jacobi+0x2c6>
movslq -0x54(%rsp),%rdi
movslq %edx,%rax
movslq %ecx,%r12
movslq %r9d,%r8
lea    -0x1(%rdi),%rcx
mov    %rcx,-0x20(%rsp)
lea    0x1(%r8),%rcx
mov    %rcx,-0x28(%rsp)
mov    %r8,%r14
sub    %rdi,%r14
mov    %r14,-0x48(%rsp)
and    $0xfffffffffffffffc,%r14
lea    (%r14,%rdi,1),%rcx
mov    %rcx,-0x30(%rsp)
mov    %r8,%rcx
neg    %rcx
mov    %rcx,-0x18(%rsp)
lea    0x2(%rdi),%rcx
mov    %rcx,-0x38(%rsp)
lea    0x3(%rdi),%rcx
mov    %rcx,-0x40(%rsp)
movsd  0xe92(%rip),%xmm0
movapd 0xe7a(%rip),%xmm1
mov    %rdi,-0x50(%rsp)
jmp    11a3 <Jacobi+0xa3>
nopl   (%rax)
add    $0x1,%rax
mov    %rax,%r15
mov    %r15,%rax
cmp    %r12,%r15
je     13c6 <Jacobi+0x2c6>
cmp    %r9d,-0x54(%rsp)
jge    1190 <Jacobi+0x90>
lea    0x1(%rax),%r15
mov    -0x10(%rsp),%rcx
mov    -0x8(%rcx,%rax,8),%rbp
mov    (%rcx,%rax,8),%r10
mov    0x8(%rcx,%rax,8),%r11
mov    -0x8(%rsp),%rcx
mov    (%rcx,%rax,8),%r13
mov    %rdi,%rax
cmpq   $0x4,-0x48(%rsp)
jb     1310 <Jacobi+0x210>
lea    0x0(,%rdi,8),%rax
add    %r13,%rax
lea    0x0(%r13,%r8,8),%rsi
lea    0x0(,%rdi,8),%rcx
add    %rbp,%rcx
lea    0x0(,%r8,8),%rdx
add    %rbp,%rdx
lea    (%r11,%rdi,8),%rbx
cmp    %rdx,%rax
setb   -0x55(%rsp)
cmp    %rsi,%rcx
lea    (%r11,%r8,8),%rcx
mov    %r9d,%edi
setb   %r9b
cmp    %rcx,%rax
setb   %dl
cmp    %rsi,%rbx
mov    -0x28(%rsp),%rcx
lea    (%r10,%rcx,8),%rcx
setb   %bl
cmp    %rcx,%rax
mov    -0x20(%rsp),%rax
lea    (%r10,%rax,8),%rax
setb   %cl
cmp    %rsi,%rax
setb   %sil
mov    -0x50(%rsp),%rax
test   %r9b,-0x55(%rsp)
mov    %edi,%r9d
mov    -0x50(%rsp),%rdi
jne    1310 <Jacobi+0x210>
mov    %rdi,%rax
and    %bl,%dl
jne    1310 <Jacobi+0x210>
mov    %rdi,%rax
and    %sil,%cl
jne    1310 <Jacobi+0x210>
mov    -0x38(%rsp),%rdx
lea    0x0(,%rdx,8),%rax
add    %rbp,%rax
lea    (%r11,%rdx,8),%rcx
mov    -0x40(%rsp),%rsi
lea    (%r10,%rsi,8),%rsi
lea    0x0(,%rdx,8),%rbx
add    %r13,%rbx
xor    %edx,%edx
nopl   (%rax)
movupd -0x10(%rax,%rdx,8),%xmm2
movupd (%rax,%rdx,8),%xmm3
movupd -0x10(%rcx,%rdx,8),%xmm4
addpd  %xmm2,%xmm4
movupd (%rcx,%rdx,8),%xmm2
addpd  %xmm3,%xmm2
movupd -0x20(%rsi,%rdx,8),%xmm3
addpd  %xmm4,%xmm3
movupd -0x10(%rsi,%rdx,8),%xmm4
movupd (%rsi,%rdx,8),%xmm5
addpd  %xmm4,%xmm2
addpd  %xmm5,%xmm2
addpd  %xmm4,%xmm3
mulpd  %xmm1,%xmm3
mulpd  %xmm1,%xmm2
movupd %xmm3,-0x10(%rbx,%rdx,8)
movupd %xmm2,(%rbx,%rdx,8)
add    $0x4,%rdx
cmp    %rdx,%r14
jne    12a0 <Jacobi+0x1a0>
mov    -0x30(%rsp),%rax
cmp    %r14,-0x48(%rsp)
je     1197 <Jacobi+0x97>
nopl   0x0(%rax,%rax,1)
mov    %r12,%rdx
mov    %r9d,%ecx
sub    %eax,%ecx
mov    %rax,%r12
test   $0x1,%cl
je     1349 <Jacobi+0x249>
movsd  0x0(%rbp,%rax,8),%xmm2
addsd  (%r11,%rax,8),%xmm2
addsd  -0x8(%r10,%rax,8),%xmm2
lea    0x1(%rax),%r12
addsd  0x8(%r10,%rax,8),%xmm2
mulsd  %xmm0,%xmm2
movsd  %xmm2,0x0(%r13,%rax,8)
not    %rax
cmp    -0x18(%rsp),%rax
je     13b9 <Jacobi+0x2b9>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movsd  0x0(%rbp,%r12,8),%xmm2
addsd  (%r11,%r12,8),%xmm2
addsd  -0x8(%r10,%r12,8),%xmm2
addsd  0x8(%r10,%r12,8),%xmm2
mulsd  %xmm0,%xmm2
movsd  %xmm2,0x0(%r13,%r12,8)
movsd  0x8(%rbp,%r12,8),%xmm2
addsd  0x8(%r11,%r12,8),%xmm2
addsd  (%r10,%r12,8),%xmm2
addsd  0x10(%r10,%r12,8),%xmm2
mulsd  %xmm0,%xmm2
movsd  %xmm2,0x8(%r13,%r12,8)
lea    0x2(%r12),%rax
mov    %rax,%r12
cmp    %rax,%r8
jne    1360 <Jacobi+0x260>
mov    -0x50(%rsp),%rdi
mov    %rdx,%r12
jmp    1197 <Jacobi+0x97>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @Jacobi(double** %0, double** %1, i32 %2, i32 %3, i32 %4, i32 %5) {
%7 = alloca double**
%8 = alloca double**
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
store double** %0, double*** %7
store double** %1, double*** %8
store i32 %2, i32* %9
store i32 %3, i32* %10
store i32 %4, i32* %11
store i32 %5, i32* %12
%15 = load i32, i32* %9
store i32 %15, i32* %13
br label %16
16: ; preds = %83, %6
%17 = load i32, i32* %13
%18 = load i32, i32* %10
%19 = icmp slt i32 %17, %18
br i1 %19, label %20, label %86
20: ; preds = %16
%21 = load i32, i32* %11
store i32 %21, i32* %14
br label %22
22: ; preds = %79, %20
%23 = load i32, i32* %14
%24 = load i32, i32* %12
%25 = icmp slt i32 %23, %24
br i1 %25, label %26, label %82
26: ; preds = %22
%27 = load double**, double*** %7
%28 = load i32, i32* %13
%29 = sub nsw i32 %28, 1
%30 = sext i32 %29 to i64
%31 = getelementptr inbounds double*, double** %27, i64 %30
%32 = load double*, double** %31
%33 = load i32, i32* %14
%34 = sext i32 %33 to i64
%35 = getelementptr inbounds double, double* %32, i64 %34
%36 = load double, double* %35
%37 = load double**, double*** %7
%38 = load i32, i32* %13
%39 = add nsw i32 %38, 1
%40 = sext i32 %39 to i64
%41 = getelementptr inbounds double*, double** %37, i64 %40
%42 = load double*, double** %41
%43 = load i32, i32* %14
%44 = sext i32 %43 to i64
%45 = getelementptr inbounds double, double* %42, i64 %44
%46 = load double, double* %45
%47 = fadd double %36, %46
%48 = load double**, double*** %7
%49 = load i32, i32* %13
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds double*, double** %48, i64 %50
%52 = load double*, double** %51
%53 = load i32, i32* %14
%54 = sub nsw i32 %53, 1
%55 = sext i32 %54 to i64
%56 = getelementptr inbounds double, double* %52, i64 %55
%57 = load double, double* %56
%58 = fadd double %47, %57
%59 = load double**, double*** %7
%60 = load i32, i32* %13
%61 = sext i32 %60 to i64
%62 = getelementptr inbounds double*, double** %59, i64 %61
%63 = load double*, double** %62
%64 = load i32, i32* %14
%65 = add 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 = fdiv double %69, 4.000000e+00
%71 = load double**, double*** %8
%72 = load i32, i32* %13
%73 = sext i32 %72 to i64
%74 = getelementptr inbounds double*, double** %71, i64 %73
%75 = load double*, double** %74
%76 = load i32, i32* %14
%77 = sext i32 %76 to i64
%78 = getelementptr inbounds double, double* %75, i64 %77
store double %70, double* %78
br label %79
79: ; preds = %26
%80 = load i32, i32* %14
%81 = add nsw i32 %80, 1
store i32 %81, i32* %14
br label %22
82: ; preds = %22
br label %83
83: ; preds = %82
%84 = load i32, i32* %13
%85 = add nsw i32 %84, 1
store i32 %85, i32* %13
br label %16
86: ; preds = %16
ret void
}

LLVM IR (-O2):
define void @Jacobi(double** nocapture %0, double** nocapture %1, i32 %2, i32 %3, i32 %4, i32 %5) {
%7 = icmp slt i32 %2, %3
br i1 %7, label %8, label %161
8: ; preds = %6
%9 = icmp slt i32 %4, %5
%10 = sext i32 %4 to i64
%11 = sext i32 %2 to i64
%12 = sext i32 %3 to i64
%13 = sext i32 %5 to i64
%14 = add nsw i64 %10, -1
%15 = add nsw i64 %13, 1
%16 = sub nsw i64 %13, %10
%17 = icmp ult i64 %16, 4
%18 = and i64 %16, -4
%19 = add nsw i64 %18, %10
%20 = icmp eq i64 %16, %18
%21 = sub nsw i64 0, %13
br label %22
22: ; preds = %8, %158
%23 = phi i64 [ %11, %8 ], [ %159, %158 ]
br i1 %9, label %26, label %24
24: ; preds = %22
%25 = add nsw i64 %23, 1
br label %158
26: ; preds = %22
%27 = add nsw i64 %23, -1
%28 = getelementptr inbounds double*, double** %0, i64 %27
%29 = load double*, double** %28
%30 = add nsw i64 %23, 1
%31 = getelementptr inbounds double*, double** %0, i64 %30
%32 = load double*, double** %31
%33 = getelementptr inbounds double*, double** %0, i64 %23
%34 = load double*, double** %33
%35 = getelementptr inbounds double*, double** %1, i64 %23
%36 = load double*, double** %35
br i1 %17, label %101, label %37
37: ; preds = %26
%38 = getelementptr double, double* %36, i64 %10
%39 = getelementptr double, double* %36, i64 %13
%40 = getelementptr double, double* %29, i64 %10
%41 = getelementptr double, double* %29, i64 %13
%42 = getelementptr double, double* %32, i64 %10
%43 = getelementptr double, double* %32, i64 %13
%44 = getelementptr double, double* %34, i64 %14
%45 = getelementptr double, double* %34, i64 %15
%46 = icmp ult double* %38, %41
%47 = icmp ult double* %40, %39
%48 = and i1 %46, %47
%49 = icmp ult double* %38, %43
%50 = icmp ult double* %42, %39
%51 = and i1 %49, %50
%52 = or i1 %48, %51
%53 = icmp ult double* %38, %45
%54 = icmp ult double* %44, %39
%55 = and i1 %53, %54
%56 = or i1 %52, %55
br i1 %56, label %101, label %57
57: ; preds = %37, %57
%58 = phi i64 [ %98, %57 ], [ 0, %37 ]
%59 = add i64 %58, %10
%60 = getelementptr inbounds double, double* %29, i64 %59
%61 = bitcast double* %60 to <2 x double>*
%62 = load <2 x double>, <2 x double>* %61
%63 = getelementptr inbounds double, double* %60, i64 2
%64 = bitcast double* %63 to <2 x double>*
%65 = load <2 x double>, <2 x double>* %64
%66 = getelementptr inbounds double, double* %32, i64 %59
%67 = bitcast double* %66 to <2 x double>*
%68 = load <2 x double>, <2 x double>* %67
%69 = getelementptr inbounds double, double* %66, i64 2
%70 = bitcast double* %69 to <2 x double>*
%71 = load <2 x double>, <2 x double>* %70
%72 = fadd <2 x double> %62, %68
%73 = fadd <2 x double> %65, %71
%74 = add nsw i64 %59, -1
%75 = getelementptr inbounds double, double* %34, i64 %74
%76 = bitcast double* %75 to <2 x double>*
%77 = load <2 x double>, <2 x double>* %76
%78 = getelementptr inbounds double, double* %75, i64 2
%79 = bitcast double* %78 to <2 x double>*
%80 = load <2 x double>, <2 x double>* %79
%81 = fadd <2 x double> %72, %77
%82 = fadd <2 x double> %73, %80
%83 = add nsw i64 %59, 1
%84 = getelementptr inbounds double, double* %34, i64 %83
%85 = bitcast double* %84 to <2 x double>*
%86 = load <2 x double>, <2 x double>* %85
%87 = getelementptr inbounds double, double* %84, i64 2
%88 = bitcast double* %87 to <2 x double>*
%89 = load <2 x double>, <2 x double>* %88
%90 = fadd <2 x double> %81, %86
%91 = fadd <2 x double> %82, %89
%92 = fmul <2 x double> %90, <double 2.500000e-01, double 2.500000e-01>
%93 = fmul <2 x double> %91, <double 2.500000e-01, double 2.500000e-01>
%94 = getelementptr inbounds double, double* %36, i64 %59
%95 = bitcast double* %94 to <2 x double>*
store <2 x double> %92, <2 x double>* %95
%96 = getelementptr inbounds double, double* %94, i64 2
%97 = bitcast double* %96 to <2 x double>*
store <2 x double> %93, <2 x double>* %97
%98 = add nuw i64 %58, 4
%99 = icmp eq i64 %98, %18
br i1 %99, label %100, label %57
100: ; preds = %57
br i1 %20, label %158, label %101
101: ; preds = %37, %26, %100
%102 = phi i64 [ %10, %37 ], [ %10, %26 ], [ %19, %100 ]
%103 = sub nsw i64 %13, %102
%104 = xor i64 %102, -1
%105 = and i64 %103, 1
%106 = icmp eq i64 %105, 0
br i1 %106, label %123, label %107
107: ; preds = %101
%108 = getelementptr inbounds double, double* %29, i64 %102
%109 = load double, double* %108
%110 = getelementptr inbounds double, double* %32, i64 %102
%111 = load double, double* %110
%112 = fadd double %109, %111
%113 = add nsw i64 %102, -1
%114 = getelementptr inbounds double, double* %34, i64 %113
%115 = load double, double* %114
%116 = fadd double %112, %115
%117 = add nsw i64 %102, 1
%118 = getelementptr inbounds double, double* %34, i64 %117
%119 = load double, double* %118
%120 = fadd double %116, %119
%121 = fmul double %120, 2.500000e-01
%122 = getelementptr inbounds double, double* %36, i64 %102
store double %121, double* %122
br label %123
123: ; preds = %107, %101
%124 = phi i64 [ %102, %101 ], [ %117, %107 ]
%125 = icmp eq i64 %104, %21
br i1 %125, label %158, label %126
126: ; preds = %123, %126
%127 = phi i64 [ %151, %126 ], [ %124, %123 ]
%128 = getelementptr inbounds double, double* %29, i64 %127
%129 = load double, double* %128
%130 = getelementptr inbounds double, double* %32, i64 %127
%131 = load double, double* %130
%132 = fadd double %129, %131
%133 = add nsw i64 %127, -1
%134 = getelementptr inbounds double, double* %34, i64 %133
%135 = load double, double* %134
%136 = fadd double %132, %135
%137 = add nsw i64 %127, 1
%138 = getelementptr inbounds double, double* %34, i64 %137
%139 = load double, double* %138
%140 = fadd double %136, %139
%141 = fmul double %140, 2.500000e-01
%142 = getelementptr inbounds double, double* %36, i64 %127
store double %141, double* %142
%143 = getelementptr inbounds double, double* %29, i64 %137
%144 = load double, double* %143
%145 = getelementptr inbounds double, double* %32, i64 %137
%146 = load double, double* %145
%147 = fadd double %144, %146
%148 = getelementptr inbounds double, double* %34, i64 %127
%149 = load double, double* %148
%150 = fadd double %147, %149
%151 = add nsw i64 %127, 2
%152 = getelementptr inbounds double, double* %34, i64 %151
%153 = load double, double* %152
%154 = fadd double %150, %153
%155 = fmul double %154, 2.500000e-01
%156 = getelementptr inbounds double, double* %36, i64 %137
store double %155, double* %156
%157 = icmp eq i64 %151, %13
br i1 %157, label %158, label %126
158: ; preds = %123, %126, %100, %24
%159 = phi i64 [ %25, %24 ], [ %30, %100 ], [ %30, %126 ], [ %30, %123 ]
%160 = icmp eq i64 %159, %12
br i1 %160, label %161, label %22
161: ; preds = %158, %6
ret void
}