void apply_rotate(double *q_in, double *R, int n_dim, int transpose,
                  double *q_out) {
  if (n_dim == 3) {
    if (transpose == 0) {
      q_out[0] = q_out[0] + R[0] * q_in[0] + R[1] * q_in[1] + R[2] * q_in[2];
      q_out[1] = q_out[1] + R[3] * q_in[0] + R[4] * q_in[1] + R[5] * q_in[2];
      q_out[2] = q_out[2] + R[6] * q_in[0] + R[7] * q_in[1] + R[8] * q_in[2];
    } else {
      q_out[0] = q_out[0] + R[0] * q_in[0] + R[3] * q_in[1] + R[6] * q_in[2];
      q_out[1] = q_out[1] + R[1] * q_in[0] + R[4] * q_in[1] + R[7] * q_in[2];
      q_out[2] = q_out[2] + R[2] * q_in[0] + R[5] * q_in[1] + R[8] * q_in[2];
    }
  } else if (n_dim == 2) {
    if (transpose == 0) {
      q_out[0] = q_out[0] + R[0] * q_in[0] + R[1] * q_in[1];
      q_out[1] = q_out[1] + R[2] * q_in[0] + R[3] * q_in[1];
    } else {
      q_out[0] = q_out[0] + R[0] * q_in[0] + R[2] * q_in[1];
      q_out[1] = q_out[1] + R[1] * q_in[0] + R[3] * q_in[1];
    }
  } else {
    for (int j = 0; j < n_dim; j++)
      q_out[j] = q_out[j] + q_in[j];
  }
}


x86 assembly (clang, -O0):
<apply_rotate>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
cmpl   $0x3,-0x14(%rbp)
jne    1368 <apply_rotate+0x268>
cmpl   $0x0,-0x18(%rbp)
jne    1249 <apply_rotate+0x149>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  0x18(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  0x20(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x28(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x8(%rax)
mov    -0x20(%rbp),%rax
movsd  0x10(%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  0x30(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  0x38(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x40(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x10(%rax)
jmp    1363 <apply_rotate+0x263>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  0x18(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x30(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  0x20(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x38(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x8(%rax)
mov    -0x20(%rbp),%rax
movsd  0x10(%rax),%xmm1
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movsd  0x28(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x40(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x10(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x10(%rax)
jmp    14e6 <apply_rotate+0x3e6>
cmpl   $0x2,-0x14(%rbp)
jne    1494 <apply_rotate+0x394>
cmpl   $0x0,-0x18(%rbp)
jne    1408 <apply_rotate+0x308>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
movsd  0x8(%rax),%xmm0
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x18(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x8(%rax)
jmp    148f <apply_rotate+0x38f>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x10(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,(%rax)
mov    -0x20(%rbp),%rax
movsd  0x8(%rax),%xmm0
mov    -0x10(%rbp),%rax
movsd  0x8(%rax),%xmm1
mov    -0x8(%rbp),%rax
movsd  (%rax),%xmm2
mulsd  %xmm2,%xmm1
addsd  %xmm0,%xmm1
mov    -0x10(%rbp),%rax
movsd  0x18(%rax),%xmm0
mov    -0x8(%rbp),%rax
movsd  0x8(%rax),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
movsd  %xmm0,0x8(%rax)
jmp    14e1 <apply_rotate+0x3e1>
movl   $0x0,-0x24(%rbp)
mov    -0x24(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    14dc <apply_rotate+0x3dc>
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
addsd  (%rax,%rcx,8),%xmm0
mov    -0x20(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    149b <apply_rotate+0x39b>
jmp    14e1 <apply_rotate+0x3e1>
jmp    14e6 <apply_rotate+0x3e6>
pop    %rbp
ret

x86 assembly (clang, -O2):
<apply_rotate>:
cmp    $0x2,%edx
je     11a3 <apply_rotate+0xa3>
cmp    $0x3,%edx
jne    11e8 <apply_rotate+0xe8>
movsd  (%rsi),%xmm0
mulsd  (%rdi),%xmm0
addsd  (%r8),%xmm0
test   %ecx,%ecx
je     12b7 <apply_rotate+0x1b7>
movsd  0x18(%rsi),%xmm1
movsd  0x30(%rsi),%xmm2
mulsd  0x8(%rdi),%xmm1
addsd  %xmm0,%xmm1
mulsd  0x10(%rdi),%xmm2
addsd  %xmm1,%xmm2
movsd  %xmm2,(%r8)
movsd  0x8(%rsi),%xmm0
movsd  0x20(%rsi),%xmm1
mulsd  (%rdi),%xmm0
addsd  0x8(%r8),%xmm0
mulsd  0x8(%rdi),%xmm1
lea    0x10(%rdi),%rax
movsd  0x38(%rsi),%xmm2
mulsd  0x10(%rdi),%xmm2
addsd  %xmm0,%xmm1
addsd  %xmm1,%xmm2
movsd  %xmm2,0x8(%r8)
movsd  0x10(%rsi),%xmm0
mulsd  (%rdi),%xmm0
addsd  0x10(%r8),%xmm0
add    $0x8,%rdi
add    $0x10,%r8
mov    $0x8,%ecx
mov    $0x5,%edx
jmp    135b <apply_rotate+0x25b>
movsd  (%rsi),%xmm0
mulsd  (%rdi),%xmm0
addsd  (%r8),%xmm0
test   %ecx,%ecx
je     1330 <apply_rotate+0x230>
movsd  0x10(%rsi),%xmm1
lea    0x8(%rdi),%rax
mulsd  0x8(%rdi),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%r8)
movsd  0x8(%r8),%xmm0
add    $0x8,%r8
mov    $0x3,%ecx
mov    $0x1,%edx
jmp    135b <apply_rotate+0x25b>
test   %edx,%edx
jle    12b6 <apply_rotate+0x1b6>
mov    %edx,%eax
cmp    $0x4,%edx
jb     1211 <apply_rotate+0x111>
lea    (%rdi,%rax,8),%rcx
cmp    %r8,%rcx
jbe    137b <apply_rotate+0x27b>
lea    (%r8,%rax,8),%rcx
cmp    %rdi,%rcx
jbe    137b <apply_rotate+0x27b>
xor    %ecx,%ecx
mov    %rcx,%rdx
not    %rdx
add    %rax,%rdx
mov    %rax,%rsi
and    $0x3,%rsi
je     124b <apply_rotate+0x14b>
cs nopw 0x0(%rax,%rax,1)
nop
movsd  (%r8,%rcx,8),%xmm0
addsd  (%rdi,%rcx,8),%xmm0
movsd  %xmm0,(%r8,%rcx,8)
add    $0x1,%rcx
add    $0xffffffffffffffff,%rsi
jne    1230 <apply_rotate+0x130>
cmp    $0x3,%rdx
jb     12b6 <apply_rotate+0x1b6>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movsd  (%r8,%rcx,8),%xmm0
addsd  (%rdi,%rcx,8),%xmm0
movsd  0x8(%r8,%rcx,8),%xmm1
movsd  %xmm0,(%r8,%rcx,8)
addsd  0x8(%rdi,%rcx,8),%xmm1
movsd  %xmm1,0x8(%r8,%rcx,8)
movsd  0x10(%r8,%rcx,8),%xmm0
addsd  0x10(%rdi,%rcx,8),%xmm0
movsd  %xmm0,0x10(%r8,%rcx,8)
movsd  0x18(%r8,%rcx,8),%xmm0
addsd  0x18(%rdi,%rcx,8),%xmm0
movsd  %xmm0,0x18(%r8,%rcx,8)
add    $0x4,%rcx
cmp    %rcx,%rax
jne    1260 <apply_rotate+0x160>
ret
movsd  0x8(%rsi),%xmm1
movsd  0x10(%rsi),%xmm2
mulsd  0x8(%rdi),%xmm1
addsd  %xmm0,%xmm1
mulsd  0x10(%rdi),%xmm2
addsd  %xmm1,%xmm2
movsd  %xmm2,(%r8)
movsd  0x18(%rsi),%xmm0
movsd  0x20(%rsi),%xmm1
mulsd  (%rdi),%xmm0
addsd  0x8(%r8),%xmm0
mulsd  0x8(%rdi),%xmm1
lea    0x10(%rdi),%rax
movsd  0x28(%rsi),%xmm2
mulsd  0x10(%rdi),%xmm2
addsd  %xmm0,%xmm1
addsd  %xmm1,%xmm2
movsd  %xmm2,0x8(%r8)
movsd  0x30(%rsi),%xmm0
mulsd  (%rdi),%xmm0
addsd  0x10(%r8),%xmm0
add    $0x8,%rdi
add    $0x10,%r8
mov    $0x8,%ecx
mov    $0x7,%edx
jmp    135b <apply_rotate+0x25b>
movsd  0x8(%rsi),%xmm1
lea    0x8(%rdi),%rax
mulsd  0x8(%rdi),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,(%r8)
movsd  0x8(%r8),%xmm0
add    $0x8,%r8
mov    $0x3,%ecx
mov    $0x2,%edx
movsd  (%rsi,%rdx,8),%xmm1
mulsd  (%rdi),%xmm1
addsd  %xmm0,%xmm1
movsd  (%rsi,%rcx,8),%xmm0
mulsd  (%rax),%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%r8)
ret
mov    %eax,%ecx
and    $0xfffffffc,%ecx
lea    -0x4(%rcx),%rdx
mov    %rdx,%r9
shr    $0x2,%r9
add    $0x1,%r9
test   %rdx,%rdx
je     1458 <apply_rotate+0x358>
mov    %r9,%rsi
and    $0xfffffffffffffffe,%rsi
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movupd (%rdi,%rdx,8),%xmm0
movupd 0x10(%rdi,%rdx,8),%xmm1
movupd (%r8,%rdx,8),%xmm2
addpd  %xmm0,%xmm2
movupd 0x10(%r8,%rdx,8),%xmm0
addpd  %xmm1,%xmm0
movupd 0x20(%r8,%rdx,8),%xmm1
movupd 0x30(%r8,%rdx,8),%xmm3
movupd %xmm2,(%r8,%rdx,8)
movupd %xmm0,0x10(%r8,%rdx,8)
movupd 0x20(%rdi,%rdx,8),%xmm0
addpd  %xmm1,%xmm0
movupd 0x30(%rdi,%rdx,8),%xmm1
addpd  %xmm3,%xmm1
movupd %xmm0,0x20(%r8,%rdx,8)
movupd %xmm1,0x30(%r8,%rdx,8)
add    $0x8,%rdx
add    $0xfffffffffffffffe,%rsi
jne    13b0 <apply_rotate+0x2b0>
test   $0x1,%r9b
je     144a <apply_rotate+0x34a>
movupd (%r8,%rdx,8),%xmm0
movupd 0x10(%r8,%rdx,8),%xmm1
movupd (%rdi,%rdx,8),%xmm2
addpd  %xmm0,%xmm2
movupd 0x10(%rdi,%rdx,8),%xmm0
addpd  %xmm1,%xmm0
movupd %xmm2,(%r8,%rdx,8)
movupd %xmm0,0x10(%r8,%rdx,8)
cmp    %rax,%rcx
je     12b6 <apply_rotate+0x1b6>
jmp    1213 <apply_rotate+0x113>
xor    %edx,%edx
test   $0x1,%r9b
jne    141d <apply_rotate+0x31d>
jmp    144a <apply_rotate+0x34a>

LLVM IR (-O0):
define void @apply_rotate(double* %0, double* %1, i32 %2, i32 %3, double* %4) {
%6 = alloca double*
%7 = alloca double*
%8 = alloca i32
%9 = alloca i32
%10 = alloca double*
%11 = alloca i32
store double* %0, double** %6
store double* %1, double** %7
store i32 %2, i32* %8
store i32 %3, i32* %9
store double* %4, double** %10
%12 = load i32, i32* %8
%13 = icmp eq i32 %12, 3
br i1 %13, label %14, label %176
14: ; preds = %5
%15 = load i32, i32* %9
%16 = icmp eq i32 %15, 0
br i1 %16, label %17, label %96
17: ; preds = %14
%18 = load double*, double** %10
%19 = getelementptr inbounds double, double* %18, i64 0
%20 = load double, double* %19
%21 = load double*, double** %7
%22 = getelementptr inbounds double, double* %21, i64 0
%23 = load double, double* %22
%24 = load double*, double** %6
%25 = getelementptr inbounds double, double* %24, i64 0
%26 = load double, double* %25
%27 = call double @llvm.fmuladd.f64(double %23, double %26, double %20)
%28 = load double*, double** %7
%29 = getelementptr inbounds double, double* %28, i64 1
%30 = load double, double* %29
%31 = load double*, double** %6
%32 = getelementptr inbounds double, double* %31, i64 1
%33 = load double, double* %32
%34 = call double @llvm.fmuladd.f64(double %30, double %33, double %27)
%35 = load double*, double** %7
%36 = getelementptr inbounds double, double* %35, i64 2
%37 = load double, double* %36
%38 = load double*, double** %6
%39 = getelementptr inbounds double, double* %38, i64 2
%40 = load double, double* %39
%41 = call double @llvm.fmuladd.f64(double %37, double %40, double %34)
%42 = load double*, double** %10
%43 = getelementptr inbounds double, double* %42, i64 0
store double %41, double* %43
%44 = load double*, double** %10
%45 = getelementptr inbounds double, double* %44, i64 1
%46 = load double, double* %45
%47 = load double*, double** %7
%48 = getelementptr inbounds double, double* %47, i64 3
%49 = load double, double* %48
%50 = load double*, double** %6
%51 = getelementptr inbounds double, double* %50, i64 0
%52 = load double, double* %51
%53 = call double @llvm.fmuladd.f64(double %49, double %52, double %46)
%54 = load double*, double** %7
%55 = getelementptr inbounds double, double* %54, i64 4
%56 = load double, double* %55
%57 = load double*, double** %6
%58 = getelementptr inbounds double, double* %57, i64 1
%59 = load double, double* %58
%60 = call double @llvm.fmuladd.f64(double %56, double %59, double %53)
%61 = load double*, double** %7
%62 = getelementptr inbounds double, double* %61, i64 5
%63 = load double, double* %62
%64 = load double*, double** %6
%65 = getelementptr inbounds double, double* %64, i64 2
%66 = load double, double* %65
%67 = call double @llvm.fmuladd.f64(double %63, double %66, double %60)
%68 = load double*, double** %10
%69 = getelementptr inbounds double, double* %68, i64 1
store double %67, double* %69
%70 = load double*, double** %10
%71 = getelementptr inbounds double, double* %70, i64 2
%72 = load double, double* %71
%73 = load double*, double** %7
%74 = getelementptr inbounds double, double* %73, i64 6
%75 = load double, double* %74
%76 = load double*, double** %6
%77 = getelementptr inbounds double, double* %76, i64 0
%78 = load double, double* %77
%79 = call double @llvm.fmuladd.f64(double %75, double %78, double %72)
%80 = load double*, double** %7
%81 = getelementptr inbounds double, double* %80, i64 7
%82 = load double, double* %81
%83 = load double*, double** %6
%84 = getelementptr inbounds double, double* %83, i64 1
%85 = load double, double* %84
%86 = call double @llvm.fmuladd.f64(double %82, double %85, double %79)
%87 = load double*, double** %7
%88 = getelementptr inbounds double, double* %87, i64 8
%89 = load double, double* %88
%90 = load double*, double** %6
%91 = getelementptr inbounds double, double* %90, i64 2
%92 = load double, double* %91
%93 = call double @llvm.fmuladd.f64(double %89, double %92, double %86)
%94 = load double*, double** %10
%95 = getelementptr inbounds double, double* %94, i64 2
store double %93, double* %95
br label %175
96: ; preds = %14
%97 = load double*, double** %10
%98 = getelementptr inbounds double, double* %97, i64 0
%99 = load double, double* %98
%100 = load double*, double** %7
%101 = getelementptr inbounds double, double* %100, i64 0
%102 = load double, double* %101
%103 = load double*, double** %6
%104 = getelementptr inbounds double, double* %103, i64 0
%105 = load double, double* %104
%106 = call double @llvm.fmuladd.f64(double %102, double %105, double %99)
%107 = load double*, double** %7
%108 = getelementptr inbounds double, double* %107, i64 3
%109 = load double, double* %108
%110 = load double*, double** %6
%111 = getelementptr inbounds double, double* %110, i64 1
%112 = load double, double* %111
%113 = call double @llvm.fmuladd.f64(double %109, double %112, double %106)
%114 = load double*, double** %7
%115 = getelementptr inbounds double, double* %114, i64 6
%116 = load double, double* %115
%117 = load double*, double** %6
%118 = getelementptr inbounds double, double* %117, i64 2
%119 = load double, double* %118
%120 = call double @llvm.fmuladd.f64(double %116, double %119, double %113)
%121 = load double*, double** %10
%122 = getelementptr inbounds double, double* %121, i64 0
store double %120, double* %122
%123 = load double*, double** %10
%124 = getelementptr inbounds double, double* %123, i64 1
%125 = load double, double* %124
%126 = load double*, double** %7
%127 = getelementptr inbounds double, double* %126, i64 1
%128 = load double, double* %127
%129 = load double*, double** %6
%130 = getelementptr inbounds double, double* %129, i64 0
%131 = load double, double* %130
%132 = call double @llvm.fmuladd.f64(double %128, double %131, double %125)
%133 = load double*, double** %7
%134 = getelementptr inbounds double, double* %133, i64 4
%135 = load double, double* %134
%136 = load double*, double** %6
%137 = getelementptr inbounds double, double* %136, i64 1
%138 = load double, double* %137
%139 = call double @llvm.fmuladd.f64(double %135, double %138, double %132)
%140 = load double*, double** %7
%141 = getelementptr inbounds double, double* %140, i64 7
%142 = load double, double* %141
%143 = load double*, double** %6
%144 = getelementptr inbounds double, double* %143, i64 2
%145 = load double, double* %144
%146 = call double @llvm.fmuladd.f64(double %142, double %145, double %139)
%147 = load double*, double** %10
%148 = getelementptr inbounds double, double* %147, i64 1
store double %146, double* %148
%149 = load double*, double** %10
%150 = getelementptr inbounds double, double* %149, i64 2
%151 = load double, double* %150
%152 = load double*, double** %7
%153 = getelementptr inbounds double, double* %152, i64 2
%154 = load double, double* %153
%155 = load double*, double** %6
%156 = getelementptr inbounds double, double* %155, i64 0
%157 = load double, double* %156
%158 = call double @llvm.fmuladd.f64(double %154, double %157, double %151)
%159 = load double*, double** %7
%160 = getelementptr inbounds double, double* %159, i64 5
%161 = load double, double* %160
%162 = load double*, double** %6
%163 = getelementptr inbounds double, double* %162, i64 1
%164 = load double, double* %163
%165 = call double @llvm.fmuladd.f64(double %161, double %164, double %158)
%166 = load double*, double** %7
%167 = getelementptr inbounds double, double* %166, i64 8
%168 = load double, double* %167
%169 = load double*, double** %6
%170 = getelementptr inbounds double, double* %169, i64 2
%171 = load double, double* %170
%172 = call double @llvm.fmuladd.f64(double %168, double %171, double %165)
%173 = load double*, double** %10
%174 = getelementptr inbounds double, double* %173, i64 2
store double %172, double* %174
br label %175
175: ; preds = %96, %17
br label %287
176: ; preds = %5
%177 = load i32, i32* %8
%178 = icmp eq i32 %177, 2
br i1 %178, label %179, label %261
179: ; preds = %176
%180 = load i32, i32* %9
%181 = icmp eq i32 %180, 0
br i1 %181, label %182, label %221
182: ; preds = %179
%183 = load double*, double** %10
%184 = getelementptr inbounds double, double* %183, i64 0
%185 = load double, double* %184
%186 = load double*, double** %7
%187 = getelementptr inbounds double, double* %186, i64 0
%188 = load double, double* %187
%189 = load double*, double** %6
%190 = getelementptr inbounds double, double* %189, i64 0
%191 = load double, double* %190
%192 = call double @llvm.fmuladd.f64(double %188, double %191, double %185)
%193 = load double*, double** %7
%194 = getelementptr inbounds double, double* %193, i64 1
%195 = load double, double* %194
%196 = load double*, double** %6
%197 = getelementptr inbounds double, double* %196, i64 1
%198 = load double, double* %197
%199 = call double @llvm.fmuladd.f64(double %195, double %198, double %192)
%200 = load double*, double** %10
%201 = getelementptr inbounds double, double* %200, i64 0
store double %199, double* %201
%202 = load double*, double** %10
%203 = getelementptr inbounds double, double* %202, i64 1
%204 = load double, double* %203
%205 = load double*, double** %7
%206 = getelementptr inbounds double, double* %205, i64 2
%207 = load double, double* %206
%208 = load double*, double** %6
%209 = getelementptr inbounds double, double* %208, i64 0
%210 = load double, double* %209
%211 = call double @llvm.fmuladd.f64(double %207, double %210, double %204)
%212 = load double*, double** %7
%213 = getelementptr inbounds double, double* %212, i64 3
%214 = load double, double* %213
%215 = load double*, double** %6
%216 = getelementptr inbounds double, double* %215, i64 1
%217 = load double, double* %216
%218 = call double @llvm.fmuladd.f64(double %214, double %217, double %211)
%219 = load double*, double** %10
%220 = getelementptr inbounds double, double* %219, i64 1
store double %218, double* %220
br label %260
221: ; preds = %179
%222 = load double*, double** %10
%223 = getelementptr inbounds double, double* %222, i64 0
%224 = load double, double* %223
%225 = load double*, double** %7
%226 = getelementptr inbounds double, double* %225, i64 0
%227 = load double, double* %226
%228 = load double*, double** %6
%229 = getelementptr inbounds double, double* %228, i64 0
%230 = load double, double* %229
%231 = call double @llvm.fmuladd.f64(double %227, double %230, double %224)
%232 = load double*, double** %7
%233 = getelementptr inbounds double, double* %232, i64 2
%234 = load double, double* %233
%235 = load double*, double** %6
%236 = getelementptr inbounds double, double* %235, i64 1
%237 = load double, double* %236
%238 = call double @llvm.fmuladd.f64(double %234, double %237, double %231)
%239 = load double*, double** %10
%240 = getelementptr inbounds double, double* %239, i64 0
store double %238, double* %240
%241 = load double*, double** %10
%242 = getelementptr inbounds double, double* %241, i64 1
%243 = load double, double* %242
%244 = load double*, double** %7
%245 = getelementptr inbounds double, double* %244, i64 1
%246 = load double, double* %245
%247 = load double*, double** %6
%248 = getelementptr inbounds double, double* %247, i64 0
%249 = load double, double* %248
%250 = call double @llvm.fmuladd.f64(double %246, double %249, double %243)
%251 = load double*, double** %7
%252 = getelementptr inbounds double, double* %251, i64 3
%253 = load double, double* %252
%254 = load double*, double** %6
%255 = getelementptr inbounds double, double* %254, i64 1
%256 = load double, double* %255
%257 = call double @llvm.fmuladd.f64(double %253, double %256, double %250)
%258 = load double*, double** %10
%259 = getelementptr inbounds double, double* %258, i64 1
store double %257, double* %259
br label %260
260: ; preds = %221, %182
br label %286
261: ; preds = %176
store i32 0, i32* %11
br label %262
262: ; preds = %282, %261
%263 = load i32, i32* %11
%264 = load i32, i32* %8
%265 = icmp slt i32 %263, %264
br i1 %265, label %266, label %285
266: ; preds = %262
%267 = load double*, double** %10
%268 = load i32, i32* %11
%269 = sext i32 %268 to i64
%270 = getelementptr inbounds double, double* %267, i64 %269
%271 = load double, double* %270
%272 = load double*, double** %6
%273 = load i32, i32* %11
%274 = sext i32 %273 to i64
%275 = getelementptr inbounds double, double* %272, i64 %274
%276 = load double, double* %275
%277 = fadd double %271, %276
%278 = load double*, double** %10
%279 = load i32, i32* %11
%280 = sext i32 %279 to i64
%281 = getelementptr inbounds double, double* %278, i64 %280
store double %277, double* %281
br label %282
282: ; preds = %266
%283 = load i32, i32* %11
%284 = add nsw i32 %283, 1
store i32 %284, i32* %11
br label %262
285: ; preds = %262
br label %286
286: ; preds = %285, %260
br label %287
287: ; preds = %286, %175
ret void
}

LLVM IR (-O2):
define void @apply_rotate(double* nocapture %0, double* %1, i32 %2, i32 %3, double* nocapture %4) {
switch i32 %2, label %6 [
i32 3, label %107
i32 2, label %175
]
6: ; preds = %5
%7 = icmp sgt i32 %2, 0
br i1 %7, label %8, label %239
8: ; preds = %6
%9 = zext i32 %2 to i64
%10 = icmp ult i32 %2, 4
br i1 %10, label %87, label %11
11: ; preds = %8
%12 = getelementptr double, double* %4, i64 %9
%13 = getelementptr double, double* %0, i64 %9
%14 = icmp ugt double* %13, %4
%15 = icmp ugt double* %12, %0
%16 = and i1 %14, %15
br i1 %16, label %87, label %17
17: ; preds = %11
%18 = and i64 %9, 4294967292
%19 = add nsw i64 %18, -4
%20 = lshr exact i64 %19, 2
%21 = add nuw nsw i64 %20, 1
%22 = and i64 %21, 1
%23 = icmp eq i64 %19, 0
br i1 %23, label %65, label %24
24: ; preds = %17
%25 = and i64 %21, 9223372036854775806
br label %26
26: ; preds = %26, %24
%27 = phi i64 [ 0, %24 ], [ %62, %26 ]
%28 = phi i64 [ 0, %24 ], [ %63, %26 ]
%29 = getelementptr inbounds double, double* %4, i64 %27
%30 = bitcast double* %29 to <2 x double>*
%31 = load <2 x double>, <2 x double>* %30
%32 = getelementptr inbounds double, double* %29, i64 2
%33 = bitcast double* %32 to <2 x double>*
%34 = load <2 x double>, <2 x double>* %33
%35 = getelementptr inbounds double, double* %0, i64 %27
%36 = bitcast double* %35 to <2 x double>*
%37 = load <2 x double>, <2 x double>* %36
%38 = getelementptr inbounds double, double* %35, i64 2
%39 = bitcast double* %38 to <2 x double>*
%40 = load <2 x double>, <2 x double>* %39
%41 = fadd <2 x double> %31, %37
%42 = fadd <2 x double> %34, %40
%43 = bitcast double* %29 to <2 x double>*
store <2 x double> %41, <2 x double>* %43
%44 = bitcast double* %32 to <2 x double>*
store <2 x double> %42, <2 x double>* %44
%45 = or i64 %27, 4
%46 = getelementptr inbounds double, double* %4, i64 %45
%47 = bitcast double* %46 to <2 x double>*
%48 = load <2 x double>, <2 x double>* %47
%49 = getelementptr inbounds double, double* %46, i64 2
%50 = bitcast double* %49 to <2 x double>*
%51 = load <2 x double>, <2 x double>* %50
%52 = getelementptr inbounds double, double* %0, i64 %45
%53 = bitcast double* %52 to <2 x double>*
%54 = load <2 x double>, <2 x double>* %53
%55 = getelementptr inbounds double, double* %52, i64 2
%56 = bitcast double* %55 to <2 x double>*
%57 = load <2 x double>, <2 x double>* %56
%58 = fadd <2 x double> %48, %54
%59 = fadd <2 x double> %51, %57
%60 = bitcast double* %46 to <2 x double>*
store <2 x double> %58, <2 x double>* %60
%61 = bitcast double* %49 to <2 x double>*
store <2 x double> %59, <2 x double>* %61
%62 = add nuw i64 %27, 8
%63 = add i64 %28, 2
%64 = icmp eq i64 %63, %25
br i1 %64, label %65, label %26
65: ; preds = %26, %17
%66 = phi i64 [ 0, %17 ], [ %62, %26 ]
%67 = icmp eq i64 %22, 0
br i1 %67, label %85, label %68
68: ; preds = %65
%69 = getelementptr inbounds double, double* %4, i64 %66
%70 = bitcast double* %69 to <2 x double>*
%71 = load <2 x double>, <2 x double>* %70
%72 = getelementptr inbounds double, double* %69, i64 2
%73 = bitcast double* %72 to <2 x double>*
%74 = load <2 x double>, <2 x double>* %73
%75 = getelementptr inbounds double, double* %0, i64 %66
%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> %71, %77
%82 = fadd <2 x double> %74, %80
%83 = bitcast double* %69 to <2 x double>*
store <2 x double> %81, <2 x double>* %83
%84 = bitcast double* %72 to <2 x double>*
store <2 x double> %82, <2 x double>* %84
br label %85
85: ; preds = %65, %68
%86 = icmp eq i64 %18, %9
br i1 %86, label %239, label %87
87: ; preds = %11, %8, %85
%88 = phi i64 [ 0, %11 ], [ 0, %8 ], [ %18, %85 ]
%89 = xor i64 %88, -1
%90 = add nsw i64 %89, %9
%91 = and i64 %9, 3
%92 = icmp eq i64 %91, 0
br i1 %92, label %104, label %93
93: ; preds = %87, %93
%94 = phi i64 [ %101, %93 ], [ %88, %87 ]
%95 = phi i64 [ %102, %93 ], [ 0, %87 ]
%96 = getelementptr inbounds double, double* %4, i64 %94
%97 = load double, double* %96
%98 = getelementptr inbounds double, double* %0, i64 %94
%99 = load double, double* %98
%100 = fadd double %97, %99
store double %100, double* %96
%101 = add nuw nsw i64 %94, 1
%102 = add i64 %95, 1
%103 = icmp eq i64 %102, %91
br i1 %103, label %104, label %93
104: ; preds = %93, %87
%105 = phi i64 [ %88, %87 ], [ %101, %93 ]
%106 = icmp ult i64 %90, 3
br i1 %106, label %239, label %197
107: ; preds = %5
%108 = icmp eq i32 %3, 0
%109 = load double, double* %4
%110 = load double, double* %1
%111 = load double, double* %0
%112 = tail call double @llvm.fmuladd.f64(double %110, double %111, double %109)
br i1 %108, label %113, label %144
113: ; preds = %107
%114 = getelementptr inbounds double, double* %1, i64 1
%115 = load double, double* %114
%116 = getelementptr inbounds double, double* %0, i64 1
%117 = load double, double* %116
%118 = tail call double @llvm.fmuladd.f64(double %115, double %117, double %112)
%119 = getelementptr inbounds double, double* %1, i64 2
%120 = load double, double* %119
%121 = getelementptr inbounds double, double* %0, i64 2
%122 = load double, double* %121
%123 = tail call double @llvm.fmuladd.f64(double %120, double %122, double %118)
store double %123, double* %4
%124 = getelementptr inbounds double, double* %4, i64 1
%125 = load double, double* %124
%126 = getelementptr inbounds double, double* %1, i64 3
%127 = load double, double* %126
%128 = load double, double* %0
%129 = tail call double @llvm.fmuladd.f64(double %127, double %128, double %125)
%130 = getelementptr inbounds double, double* %1, i64 4
%131 = load double, double* %130
%132 = load double, double* %116
%133 = tail call double @llvm.fmuladd.f64(double %131, double %132, double %129)
%134 = getelementptr inbounds double, double* %1, i64 5
%135 = load double, double* %134
%136 = load double, double* %121
%137 = tail call double @llvm.fmuladd.f64(double %135, double %136, double %133)
store double %137, double* %124
%138 = getelementptr inbounds double, double* %4, i64 2
%139 = load double, double* %138
%140 = getelementptr inbounds double, double* %1, i64 6
%141 = load double, double* %140
%142 = load double, double* %0
%143 = tail call double @llvm.fmuladd.f64(double %141, double %142, double %139)
br label %224
144: ; preds = %107
%145 = getelementptr inbounds double, double* %1, i64 3
%146 = load double, double* %145
%147 = getelementptr inbounds double, double* %0, i64 1
%148 = load double, double* %147
%149 = tail call double @llvm.fmuladd.f64(double %146, double %148, double %112)
%150 = getelementptr inbounds double, double* %1, i64 6
%151 = load double, double* %150
%152 = getelementptr inbounds double, double* %0, i64 2
%153 = load double, double* %152
%154 = tail call double @llvm.fmuladd.f64(double %151, double %153, double %149)
store double %154, double* %4
%155 = getelementptr inbounds double, double* %4, i64 1
%156 = load double, double* %155
%157 = getelementptr inbounds double, double* %1, i64 1
%158 = load double, double* %157
%159 = load double, double* %0
%160 = tail call double @llvm.fmuladd.f64(double %158, double %159, double %156)
%161 = getelementptr inbounds double, double* %1, i64 4
%162 = load double, double* %161
%163 = load double, double* %147
%164 = tail call double @llvm.fmuladd.f64(double %162, double %163, double %160)
%165 = getelementptr inbounds double, double* %1, i64 7
%166 = load double, double* %165
%167 = load double, double* %152
%168 = tail call double @llvm.fmuladd.f64(double %166, double %167, double %164)
store double %168, double* %155
%169 = getelementptr inbounds double, double* %4, i64 2
%170 = load double, double* %169
%171 = getelementptr inbounds double, double* %1, i64 2
%172 = load double, double* %171
%173 = load double, double* %0
%174 = tail call double @llvm.fmuladd.f64(double %172, double %173, double %170)
br label %224
175: ; preds = %5
%176 = icmp eq i32 %3, 0
%177 = load double, double* %4
%178 = load double, double* %1
%179 = load double, double* %0
%180 = tail call double @llvm.fmuladd.f64(double %178, double %179, double %177)
br i1 %176, label %181, label %189
181: ; preds = %175
%182 = getelementptr inbounds double, double* %1, i64 1
%183 = load double, double* %182
%184 = getelementptr inbounds double, double* %0, i64 1
%185 = load double, double* %184
%186 = tail call double @llvm.fmuladd.f64(double %183, double %185, double %180)
store double %186, double* %4
%187 = getelementptr inbounds double, double* %4, i64 1
%188 = load double, double* %187
br label %224
189: ; preds = %175
%190 = getelementptr inbounds double, double* %1, i64 2
%191 = load double, double* %190
%192 = getelementptr inbounds double, double* %0, i64 1
%193 = load double, double* %192
%194 = tail call double @llvm.fmuladd.f64(double %191, double %193, double %180)
store double %194, double* %4
%195 = getelementptr inbounds double, double* %4, i64 1
%196 = load double, double* %195
br label %224
197: ; preds = %104, %197
%198 = phi i64 [ %222, %197 ], [ %105, %104 ]
%199 = getelementptr inbounds double, double* %4, i64 %198
%200 = load double, double* %199
%201 = getelementptr inbounds double, double* %0, i64 %198
%202 = load double, double* %201
%203 = fadd double %200, %202
store double %203, double* %199
%204 = add nuw nsw i64 %198, 1
%205 = getelementptr inbounds double, double* %4, i64 %204
%206 = load double, double* %205
%207 = getelementptr inbounds double, double* %0, i64 %204
%208 = load double, double* %207
%209 = fadd double %206, %208
store double %209, double* %205
%210 = add nuw nsw i64 %198, 2
%211 = getelementptr inbounds double, double* %4, i64 %210
%212 = load double, double* %211
%213 = getelementptr inbounds double, double* %0, i64 %210
%214 = load double, double* %213
%215 = fadd double %212, %214
store double %215, double* %211
%216 = add nuw nsw i64 %198, 3
%217 = getelementptr inbounds double, double* %4, i64 %216
%218 = load double, double* %217
%219 = getelementptr inbounds double, double* %0, i64 %216
%220 = load double, double* %219
%221 = fadd double %218, %220
store double %221, double* %217
%222 = add nuw nsw i64 %198, 4
%223 = icmp eq i64 %222, %9
br i1 %223, label %239, label %197
224: ; preds = %144, %113, %181, %189
%225 = phi i64 [ 1, %189 ], [ 2, %181 ], [ 7, %113 ], [ 5, %144 ]
%226 = phi double* [ %0, %189 ], [ %0, %181 ], [ %116, %113 ], [ %147, %144 ]
%227 = phi double [ %196, %189 ], [ %188, %181 ], [ %143, %113 ], [ %174, %144 ]
%228 = phi i64 [ 3, %189 ], [ 3, %181 ], [ 8, %113 ], [ 8, %144 ]
%229 = phi double* [ %192, %189 ], [ %184, %181 ], [ %121, %113 ], [ %152, %144 ]
%230 = phi double* [ %195, %189 ], [ %187, %181 ], [ %138, %113 ], [ %169, %144 ]
%231 = getelementptr inbounds double, double* %1, i64 %225
%232 = load double, double* %231
%233 = load double, double* %226
%234 = tail call double @llvm.fmuladd.f64(double %232, double %233, double %227)
%235 = getelementptr inbounds double, double* %1, i64 %228
%236 = load double, double* %235
%237 = load double, double* %229
%238 = tail call double @llvm.fmuladd.f64(double %236, double %237, double %234)
store double %238, double* %230
br label %239
239: ; preds = %104, %197, %85, %224, %6
ret void
}