void mc2b(double *mc, double *b, int m, const double a) {
  b[m] = mc[m];
  for (m--; m >= 0; m--)
    b[m] = mc[m] - a * b[m + 1];
  return;
}


x86 assembly (clang, -O0):
<mc2b>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movsd  %xmm0,-0x20(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jl     119f <mc2b+0x9f>
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movsd  -0x20(%rbp),%xmm0
mov    -0x10(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%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    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
jmp    1137 <mc2b+0x37>
pop    %rbp
ret

x86 assembly (clang, -O2):
<mc2b>:
push   %rbp
push   %rbx
movslq %edx,%rax
movsd  (%rdi,%rax,8),%xmm1
movsd  %xmm1,(%rsi,%rax,8)
test   %eax,%eax
jle    1151 <mc2b+0x51>
mov    %edx,%ecx
xorpd  0xee3(%rip),%xmm0
mov    %edx,%r9d
cmp    $0x4,%edx
jae    1154 <mc2b+0x54>
mov    %r9,%rax
add    $0x1,%rax
nopl   0x0(%rax)
lea    -0x2(%rax),%ecx
movsd  -0x8(%rsi,%rax,8),%xmm1
mulsd  %xmm0,%xmm1
addsd  (%rdi,%rcx,8),%xmm1
movsd  %xmm1,(%rsi,%rcx,8)
add    $0xffffffffffffffff,%rax
cmp    $0x1,%rax
ja     1130 <mc2b+0x30>
pop    %rbx
pop    %rbp
ret
lea    -0x1(%r9),%r8
add    $0xffffffff,%ecx
mov    $0x8,%edx
mov    %r8,%rax
mul    %rdx
seto   %r10b
cmp    %r8d,%ecx
jb     1125 <mc2b+0x25>
mov    %r8,%rbx
shr    $0x20,%rbx
jne    1125 <mc2b+0x25>
lea    (%rsi,%rcx,8),%rdx
mov    %rdx,%rbx
sub    %rax,%rbx
cmp    %rdx,%rbx
ja     1125 <mc2b+0x25>
test   %r10b,%r10b
jne    1125 <mc2b+0x25>
lea    (%rdi,%rcx,8),%rbx
mov    %rbx,%rdx
sub    %rax,%rdx
cmp    %rbx,%rdx
ja     1125 <mc2b+0x25>
test   %r10b,%r10b
jne    1125 <mc2b+0x25>
lea    (%rsi,%r9,8),%rbx
mov    %rbx,%rdx
sub    %rax,%rdx
cmp    %rbx,%rdx
ja     1125 <mc2b+0x25>
test   %r10b,%r10b
jne    1125 <mc2b+0x25>
lea    0x1(%rcx),%rax
sub    %r9,%rax
lea    (%rsi,%rax,8),%rdx
lea    (%rsi,%rcx,8),%rbx
add    $0x8,%rbx
lea    (%rdi,%rax,8),%r11
lea    (%rdi,%rcx,8),%rcx
add    $0x8,%rcx
lea    0x8(%rsi),%r10
lea    (%rsi,%r9,8),%rax
add    $0x8,%rax
cmp    %rcx,%rdx
setb   %bpl
cmp    %rbx,%r11
setb   %cl
cmp    %rax,%rdx
setb   %al
cmp    %rbx,%r10
setb   %dl
test   %cl,%bpl
jne    1125 <mc2b+0x25>
and    %dl,%al
jne    1125 <mc2b+0x25>
mov    %r9d,%r10d
and    $0xfffffffc,%r10d
mov    %r9d,%eax
and    $0x3,%eax
movapd %xmm0,%xmm1
unpcklpd %xmm0,%xmm1
mov    %r10,%r11
neg    %r11
mov    $0xffffffff,%ebx
add    %r9,%rbx
lea    (%rsi,%r8,8),%rdx
xor    %ecx,%ecx
shufpd $0x1,%xmm1,%xmm1
nop
lea    (%rbx,%rcx,1),%ebp
movupd -0x18(%rdi,%rbp,8),%xmm2
movupd -0x8(%rdi,%rbp,8),%xmm3
movupd -0x10(%rdx,%rcx,8),%xmm4
movupd (%rdx,%rcx,8),%xmm5
mulpd  %xmm1,%xmm5
addpd  %xmm3,%xmm5
movupd %xmm5,-0x8(%rsi,%rbp,8)
mulpd  %xmm1,%xmm4
addpd  %xmm2,%xmm4
movupd %xmm4,-0x18(%rsi,%rbp,8)
add    $0xfffffffffffffffc,%rcx
cmp    %rcx,%r11
jne    1240 <mc2b+0x140>
cmp    %r9,%r10
jne    1128 <mc2b+0x28>
jmp    1151 <mc2b+0x51>

LLVM IR (-O0):
define void @mc2b(double* %0, double* %1, i32 %2, double %3) {
%5 = alloca double*
%6 = alloca double*
%7 = alloca i32
%8 = alloca double
store double* %0, double** %5
store double* %1, double** %6
store i32 %2, i32* %7
store double %3, double* %8
%9 = load double*, double** %5
%10 = load i32, i32* %7
%11 = sext i32 %10 to i64
%12 = getelementptr inbounds double, double* %9, i64 %11
%13 = load double, double* %12
%14 = load double*, double** %6
%15 = load i32, i32* %7
%16 = sext i32 %15 to i64
%17 = getelementptr inbounds double, double* %14, i64 %16
store double %13, double* %17
%18 = load i32, i32* %7
%19 = add nsw i32 %18, -1
store i32 %19, i32* %7
br label %20
20: ; preds = %42, %4
%21 = load i32, i32* %7
%22 = icmp sge i32 %21, 0
br i1 %22, label %23, label %45
23: ; preds = %20
%24 = load double*, double** %5
%25 = load i32, i32* %7
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds double, double* %24, i64 %26
%28 = load double, double* %27
%29 = load double, double* %8
%30 = load double*, double** %6
%31 = load i32, i32* %7
%32 = add nsw i32 %31, 1
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds double, double* %30, i64 %33
%35 = load double, double* %34
%36 = fneg double %29
%37 = call double @llvm.fmuladd.f64(double %36, double %35, double %28)
%38 = load double*, double** %6
%39 = load i32, i32* %7
%40 = sext i32 %39 to i64
%41 = getelementptr inbounds double, double* %38, i64 %40
store double %37, double* %41
br label %42
42: ; preds = %23
%43 = load i32, i32* %7
%44 = add nsw i32 %43, -1
store i32 %44, i32* %7
br label %20
45: ; preds = %20
ret void
}

LLVM IR (-O2):
define void @mc2b(double* nocapture %0, double* nocapture %1, i32 %2, double %3) {
%5 = sext i32 %2 to i64
%6 = getelementptr inbounds double, double* %0, i64 %5
%7 = load double, double* %6
%8 = getelementptr inbounds double, double* %1, i64 %5
store double %7, double* %8
%9 = icmp sgt i32 %2, 0
br i1 %9, label %10, label %131
10: ; preds = %4
%11 = fneg double %3
%12 = zext i32 %2 to i64
%13 = icmp ult i32 %2, 4
br i1 %13, label %118, label %14
14: ; preds = %10
%15 = add nsw i64 %12, -1
%16 = add i32 %2, -1
%17 = trunc i64 %15 to i32
%18 = icmp ult i32 %16, %17
%19 = icmp ugt i64 %15, 4294967295
%20 = or i1 %18, %19
%21 = zext i32 %16 to i64
%22 = getelementptr double, double* %1, i64 %21
%23 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %15, i64 8)
%24 = extractvalue { i64, i1 } %23, 0
%25 = extractvalue { i64, i1 } %23, 1
%26 = bitcast double* %22 to i8*
%27 = sub i64 0, %24
%28 = getelementptr i8, i8* %26, i64 %27
%29 = icmp ugt i8* %28, %26
%30 = or i1 %29, %25
%31 = getelementptr double, double* %0, i64 %21
%32 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %15, i64 8)
%33 = extractvalue { i64, i1 } %32, 0
%34 = extractvalue { i64, i1 } %32, 1
%35 = bitcast double* %31 to i8*
%36 = sub i64 0, %33
%37 = getelementptr i8, i8* %35, i64 %36
%38 = icmp ugt i8* %37, %35
%39 = or i1 %38, %34
%40 = getelementptr double, double* %1, i64 %12
%41 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %15, i64 8)
%42 = extractvalue { i64, i1 } %41, 0
%43 = extractvalue { i64, i1 } %41, 1
%44 = bitcast double* %40 to i8*
%45 = sub i64 0, %42
%46 = getelementptr i8, i8* %44, i64 %45
%47 = icmp ugt i8* %46, %44
%48 = or i1 %47, %43
%49 = or i1 %20, %30
%50 = or i1 %49, %39
%51 = or i1 %50, %48
br i1 %51, label %118, label %52
52: ; preds = %14
%53 = add i32 %2, -1
%54 = zext i32 %53 to i64
%55 = add nuw nsw i64 %54, 1
%56 = sub nsw i64 %55, %12
%57 = getelementptr double, double* %1, i64 %56
%58 = add nuw nsw i64 %54, 1
%59 = getelementptr double, double* %1, i64 %58
%60 = getelementptr double, double* %0, i64 %56
%61 = getelementptr double, double* %0, i64 %58
%62 = getelementptr double, double* %1, i64 1
%63 = add nuw nsw i64 %12, 1
%64 = getelementptr double, double* %1, i64 %63
%65 = icmp ult double* %57, %61
%66 = icmp ult double* %60, %59
%67 = and i1 %65, %66
%68 = icmp ult double* %57, %64
%69 = icmp ult double* %62, %59
%70 = and i1 %68, %69
%71 = or i1 %67, %70
br i1 %71, label %118, label %72
72: ; preds = %52
%73 = and i64 %12, 4294967292
%74 = and i64 %12, 3
%75 = insertelement <2 x double> poison, double %11, i64 0
%76 = shufflevector <2 x double> %75, <2 x double> poison, <2 x i32> zeroinitializer
%77 = insertelement <2 x double> poison, double %11, i64 0
%78 = shufflevector <2 x double> %77, <2 x double> poison, <2 x i32> zeroinitializer
br label %79
79: ; preds = %79, %72
%80 = phi i64 [ 0, %72 ], [ %114, %79 ]
%81 = sub i64 %12, %80
%82 = add i64 %81, 4294967295
%83 = and i64 %82, 4294967295
%84 = getelementptr inbounds double, double* %0, i64 %83
%85 = getelementptr inbounds double, double* %84, i64 -1
%86 = bitcast double* %85 to <2 x double>*
%87 = load <2 x double>, <2 x double>* %86
%88 = shufflevector <2 x double> %87, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%89 = getelementptr inbounds double, double* %84, i64 -2
%90 = getelementptr inbounds double, double* %89, i64 -1
%91 = bitcast double* %90 to <2 x double>*
%92 = load <2 x double>, <2 x double>* %91
%93 = shufflevector <2 x double> %92, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%94 = getelementptr inbounds double, double* %1, i64 %81
%95 = getelementptr inbounds double, double* %94, i64 -1
%96 = bitcast double* %95 to <2 x double>*
%97 = load <2 x double>, <2 x double>* %96
%98 = shufflevector <2 x double> %97, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%99 = getelementptr inbounds double, double* %94, i64 -2
%100 = getelementptr inbounds double, double* %99, i64 -1
%101 = bitcast double* %100 to <2 x double>*
%102 = load <2 x double>, <2 x double>* %101
%103 = shufflevector <2 x double> %102, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%104 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %76, <2 x double> %98, <2 x double> %88)
%105 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %78, <2 x double> %103, <2 x double> %93)
%106 = getelementptr inbounds double, double* %1, i64 %83
%107 = shufflevector <2 x double> %104, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%108 = getelementptr inbounds double, double* %106, i64 -1
%109 = bitcast double* %108 to <2 x double>*
store <2 x double> %107, <2 x double>* %109
%110 = shufflevector <2 x double> %105, <2 x double> poison, <2 x i32> <i32 1, i32 0>
%111 = getelementptr inbounds double, double* %106, i64 -2
%112 = getelementptr inbounds double, double* %111, i64 -1
%113 = bitcast double* %112 to <2 x double>*
store <2 x double> %110, <2 x double>* %113
%114 = add nuw i64 %80, 4
%115 = icmp eq i64 %114, %73
br i1 %115, label %116, label %79
116: ; preds = %79
%117 = icmp eq i64 %73, %12
br i1 %117, label %131, label %118
118: ; preds = %52, %14, %10, %116
%119 = phi i64 [ %12, %52 ], [ %12, %14 ], [ %12, %10 ], [ %74, %116 ]
br label %120
120: ; preds = %118, %120
%121 = phi i64 [ %122, %120 ], [ %119, %118 ]
%122 = add nsw i64 %121, -1
%123 = and i64 %122, 4294967295
%124 = getelementptr inbounds double, double* %0, i64 %123
%125 = load double, double* %124
%126 = getelementptr inbounds double, double* %1, i64 %121
%127 = load double, double* %126
%128 = tail call double @llvm.fmuladd.f64(double %11, double %127, double %125)
%129 = getelementptr inbounds double, double* %1, i64 %123
store double %128, double* %129
%130 = icmp ugt i64 %121, 1
br i1 %130, label %120, label %131
131: ; preds = %120, %116, %4
ret void
}