void quat_rotate(const float q[4], float a, float x, float y, float z,
                 float out[4]) {
  float other[4];
  quat_from_axis(other, a, x, y, z);
  quat_mul(q, other, out);
}


x86 assembly (clang, -O0):
<quat_rotate>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
movss  %xmm0,-0xc(%rbp)
movss  %xmm1,-0x10(%rbp)
movss  %xmm2,-0x14(%rbp)
movss  %xmm3,-0x18(%rbp)
mov    %rsi,-0x20(%rbp)
lea    -0x30(%rbp),%rdi
movss  -0xc(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movss  -0x10(%rbp),%xmm1
cvtss2sd %xmm1,%xmm1
movss  -0x14(%rbp),%xmm2
cvtss2sd %xmm2,%xmm2
movss  -0x18(%rbp),%xmm3
cvtss2sd %xmm3,%xmm3
mov    $0x4,%al
call   1030 <quat_from_axis@plt>
mov    -0x8(%rbp),%rdi
lea    -0x30(%rbp),%rsi
mov    -0x20(%rbp),%rdx
mov    $0x0,%al
call   1040 <quat_mul@plt>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<quat_rotate>:
push   %r15
push   %r14
push   %rbx
sub    $0x10,%rsp
mov    %rsi,%r14
mov    %rdi,%rbx
cvtss2sd %xmm0,%xmm0
cvtss2sd %xmm1,%xmm1
cvtss2sd %xmm2,%xmm2
cvtss2sd %xmm3,%xmm3
mov    %rsp,%r15
mov    %r15,%rdi
mov    $0x4,%al
call   1030 <quat_from_axis@plt>
mov    %rbx,%rdi
mov    %r15,%rsi
mov    %r14,%rdx
xor    %eax,%eax
call   1040 <quat_mul@plt>
add    $0x10,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @quat_rotate(float* %0, float %1, float %2, float %3, float %4, float* %5) {
%7 = alloca float*
%8 = alloca float
%9 = alloca float
%10 = alloca float
%11 = alloca float
%12 = alloca float*
%13 = alloca [4 x float]
store float* %0, float** %7
store float %1, float* %8
store float %2, float* %9
store float %3, float* %10
store float %4, float* %11
store float* %5, float** %12
%14 = getelementptr inbounds [4 x float], [4 x float]* %13, i64 0, i64 0
%15 = load float, float* %8
%16 = fpext float %15 to double
%17 = load float, float* %9
%18 = fpext float %17 to double
%19 = load float, float* %10
%20 = fpext float %19 to double
%21 = load float, float* %11
%22 = fpext float %21 to double
%23 = call i32 (float*, double, double, double, double, ...) bitcast (i32 (...)* @quat_from_axis to i32 (float*, double, double, double, double, ...)*)(float* %14, double %16, double %18, double %20, double %22)
%24 = load float*, float** %7
%25 = getelementptr inbounds [4 x float], [4 x float]* %13, i64 0, i64 0
%26 = load float*, float** %12
%27 = call i32 (float*, float*, float*, ...) bitcast (i32 (...)* @quat_mul to i32 (float*, float*, float*, ...)*)(float* %24, float* %25, float* %26)
ret void
}

LLVM IR (-O2):
define void @quat_rotate(float* %0, float %1, float %2, float %3, float %4, float* %5) {
%7 = alloca [4 x float]
%8 = bitcast [4 x float]* %7 to i8*
%9 = getelementptr inbounds [4 x float], [4 x float]* %7, i64 0, i64 0
%10 = fpext float %1 to double
%11 = fpext float %2 to double
%12 = fpext float %3 to double
%13 = fpext float %4 to double
%14 = call i32 (float*, double, double, double, double, ...) bitcast (i32 (...)* @quat_from_axis to i32 (float*, double, double, double, double, ...)*)(float* %9, double %10, double %11, double %12, double %13)
%15 = call i32 (float*, float*, float*, ...) bitcast (i32 (...)* @quat_mul to i32 (float*, float*, float*, ...)*)(float* %0, float* %9, float* %5)
ret void
}