#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int /*<<< orphan*/ Vector3Scale(float const *, double, float *);
float *UpdateQuaternion(float quat[4], const float angular_rate[3], float dt) {
  float dpqr[3];
  Vector3Scale(angular_rate, 0.5 * dt, dpqr);
  float d_quat[4];
  d_quat[0] = -dpqr[0] * quat[1] - dpqr[1] * quat[2] - dpqr[2] * quat[3];
  d_quat[1] = dpqr[0] * quat[0] - dpqr[1] * quat[3] + dpqr[2] * quat[2];
  d_quat[2] = dpqr[0] * quat[3] + dpqr[1] * quat[0] - dpqr[2] * quat[1];
  d_quat[3] = -dpqr[0] * quat[2] + dpqr[1] * quat[1] + dpqr[2] * quat[0];
  quat[0] += d_quat[0];
  quat[1] += d_quat[1];
  quat[2] += d_quat[2];
  quat[3] += d_quat[3];
  return quat;
}


x86 assembly (clang, -O0):
<UpdateQuaternion>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movss  %xmm0,-0x14(%rbp)
mov    -0x10(%rbp),%rdi
movss  -0x14(%rbp),%xmm0
cvtss2sd %xmm0,%xmm1
movsd  0xec6(%rip),%xmm0
mulsd  %xmm1,%xmm0
lea    -0x20(%rbp),%rsi
call   1030 <Vector3Scale@plt>
movss  -0x20(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm1
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm2
movss  -0x1c(%rbp),%xmm0
mov    -0x8(%rbp),%rax
mulss  0x8(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  -0x18(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm2
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x30(%rbp)
movss  -0x20(%rbp),%xmm1
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm2
movss  -0x1c(%rbp),%xmm0
mov    -0x8(%rbp),%rax
mulss  0xc(%rax),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  -0x18(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x2c(%rbp)
movss  -0x20(%rbp),%xmm1
mov    -0x8(%rbp),%rax
movss  0xc(%rax),%xmm2
movss  -0x1c(%rbp),%xmm0
mov    -0x8(%rbp),%rax
mulss  (%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  -0x18(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  0x4(%rax),%xmm2
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm0
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x28(%rbp)
movss  -0x20(%rbp),%xmm0
movd   %xmm0,%eax
xor    $0x80000000,%eax
movd   %eax,%xmm1
mov    -0x8(%rbp),%rax
movss  0x8(%rax),%xmm2
movss  -0x1c(%rbp),%xmm0
mov    -0x8(%rbp),%rax
mulss  0x4(%rax),%xmm0
mulss  %xmm2,%xmm1
addss  %xmm0,%xmm1
movss  -0x18(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movss  (%rax),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x24(%rbp)
movss  -0x30(%rbp),%xmm0
mov    -0x8(%rbp),%rax
addss  (%rax),%xmm0
movss  %xmm0,(%rax)
movss  -0x2c(%rbp),%xmm0
mov    -0x8(%rbp),%rax
addss  0x4(%rax),%xmm0
movss  %xmm0,0x4(%rax)
movss  -0x28(%rbp),%xmm0
mov    -0x8(%rbp),%rax
addss  0x8(%rax),%xmm0
movss  %xmm0,0x8(%rax)
movss  -0x24(%rbp),%xmm0
mov    -0x8(%rbp),%rax
addss  0xc(%rax),%xmm0
movss  %xmm0,0xc(%rax)
mov    -0x8(%rbp),%rax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<UpdateQuaternion>:
push   %rbx
sub    $0x10,%rsp
mov    %rsi,%rax
mov    %rdi,%rbx
cvtss2sd %xmm0,%xmm0
mulsd  0xed9(%rip),%xmm0
lea    0x4(%rsp),%rsi
mov    %rax,%rdi
call   1030 <Vector3Scale@plt>
movaps 0xed5(%rip),%xmm0
movss  0x4(%rsp),%xmm1
movss  0x8(%rsp),%xmm2
movss  0xc(%rsp),%xmm3
movaps %xmm1,%xmm4
xorps  %xmm0,%xmm4
movups (%rbx),%xmm5
movaps %xmm5,%xmm6
movss  %xmm2,%xmm6
movaps %xmm5,%xmm7
unpcklps %xmm2,%xmm7
xorps  %xmm0,%xmm2
xorps  %xmm3,%xmm0
shufps $0x4,%xmm2,%xmm7
mulps  %xmm6,%xmm7
unpcklps %xmm4,%xmm1
shufps $0x14,%xmm1,%xmm1
movaps %xmm5,%xmm2
shufps $0x1b,%xmm5,%xmm2
mulps  %xmm2,%xmm1
addps  %xmm7,%xmm1
shufps $0x4e,%xmm1,%xmm1
unpcklps %xmm3,%xmm0
movlhps %xmm0,%xmm0
mulps  %xmm2,%xmm0
addps  %xmm1,%xmm0
addps  %xmm5,%xmm0
movups %xmm0,(%rbx)
mov    %rbx,%rax
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define float* @UpdateQuaternion(float* %0, float* %1, float %2) {
%4 = alloca float*
%5 = alloca float*
%6 = alloca float
%7 = alloca [3 x float]
%8 = alloca [4 x float]
store float* %0, float** %4
store float* %1, float** %5
store float %2, float* %6
%9 = load float*, float** %5
%10 = load float, float* %6
%11 = fpext float %10 to double
%12 = fmul double 5.000000e-01, %11
%13 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 0
%14 = call i32 @Vector3Scale(float* %9, double %12, float* %13)
%15 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 0
%16 = load float, float* %15
%17 = fneg float %16
%18 = load float*, float** %4
%19 = getelementptr inbounds float, float* %18, i64 1
%20 = load float, float* %19
%21 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 1
%22 = load float, float* %21
%23 = load float*, float** %4
%24 = getelementptr inbounds float, float* %23, i64 2
%25 = load float, float* %24
%26 = fmul float %22, %25
%27 = fneg float %26
%28 = call float @llvm.fmuladd.f32(float %17, float %20, float %27)
%29 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 2
%30 = load float, float* %29
%31 = load float*, float** %4
%32 = getelementptr inbounds float, float* %31, i64 3
%33 = load float, float* %32
%34 = fneg float %30
%35 = call float @llvm.fmuladd.f32(float %34, float %33, float %28)
%36 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 0
store float %35, float* %36
%37 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 0
%38 = load float, float* %37
%39 = load float*, float** %4
%40 = getelementptr inbounds float, float* %39, i64 0
%41 = load float, float* %40
%42 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 1
%43 = load float, float* %42
%44 = load float*, float** %4
%45 = getelementptr inbounds float, float* %44, i64 3
%46 = load float, float* %45
%47 = fmul float %43, %46
%48 = fneg float %47
%49 = call float @llvm.fmuladd.f32(float %38, float %41, float %48)
%50 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 2
%51 = load float, float* %50
%52 = load float*, float** %4
%53 = getelementptr inbounds float, float* %52, i64 2
%54 = load float, float* %53
%55 = call float @llvm.fmuladd.f32(float %51, float %54, float %49)
%56 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 1
store float %55, float* %56
%57 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 0
%58 = load float, float* %57
%59 = load float*, float** %4
%60 = getelementptr inbounds float, float* %59, i64 3
%61 = load float, float* %60
%62 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 1
%63 = load float, float* %62
%64 = load float*, float** %4
%65 = getelementptr inbounds float, float* %64, i64 0
%66 = load float, float* %65
%67 = fmul float %63, %66
%68 = call float @llvm.fmuladd.f32(float %58, float %61, float %67)
%69 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 2
%70 = load float, float* %69
%71 = load float*, float** %4
%72 = getelementptr inbounds float, float* %71, i64 1
%73 = load float, float* %72
%74 = fneg float %70
%75 = call float @llvm.fmuladd.f32(float %74, float %73, float %68)
%76 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 2
store float %75, float* %76
%77 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 0
%78 = load float, float* %77
%79 = fneg float %78
%80 = load float*, float** %4
%81 = getelementptr inbounds float, float* %80, i64 2
%82 = load float, float* %81
%83 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 1
%84 = load float, float* %83
%85 = load float*, float** %4
%86 = getelementptr inbounds float, float* %85, i64 1
%87 = load float, float* %86
%88 = fmul float %84, %87
%89 = call float @llvm.fmuladd.f32(float %79, float %82, float %88)
%90 = getelementptr inbounds [3 x float], [3 x float]* %7, i64 0, i64 2
%91 = load float, float* %90
%92 = load float*, float** %4
%93 = getelementptr inbounds float, float* %92, i64 0
%94 = load float, float* %93
%95 = call float @llvm.fmuladd.f32(float %91, float %94, float %89)
%96 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 3
store float %95, float* %96
%97 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 0
%98 = load float, float* %97
%99 = load float*, float** %4
%100 = getelementptr inbounds float, float* %99, i64 0
%101 = load float, float* %100
%102 = fadd float %101, %98
store float %102, float* %100
%103 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 1
%104 = load float, float* %103
%105 = load float*, float** %4
%106 = getelementptr inbounds float, float* %105, i64 1
%107 = load float, float* %106
%108 = fadd float %107, %104
store float %108, float* %106
%109 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 2
%110 = load float, float* %109
%111 = load float*, float** %4
%112 = getelementptr inbounds float, float* %111, i64 2
%113 = load float, float* %112
%114 = fadd float %113, %110
store float %114, float* %112
%115 = getelementptr inbounds [4 x float], [4 x float]* %8, i64 0, i64 3
%116 = load float, float* %115
%117 = load float*, float** %4
%118 = getelementptr inbounds float, float* %117, i64 3
%119 = load float, float* %118
%120 = fadd float %119, %116
store float %120, float* %118
%121 = load float*, float** %4
ret float* %121
}

LLVM IR (-O2):
define float* @UpdateQuaternion(float* returned %0, float* %1, float %2) {
%4 = alloca [3 x float]
%5 = bitcast [3 x float]* %4 to i8*
%6 = fpext float %2 to double
%7 = fmul double %6, 5.000000e-01
%8 = getelementptr inbounds [3 x float], [3 x float]* %4, i64 0, i64 0
%9 = call i32 @Vector3Scale(float* %1, double %7, float* %8)
%10 = load float, float* %8
%11 = fneg float %10
%12 = getelementptr inbounds [3 x float], [3 x float]* %4, i64 0, i64 1
%13 = load float, float* %12
%14 = fneg float %13
%15 = getelementptr inbounds [3 x float], [3 x float]* %4, i64 0, i64 2
%16 = load float, float* %15
%17 = fneg float %16
%18 = bitcast float* %0 to <4 x float>*
%19 = load <4 x float>, <4 x float>* %18
%20 = insertelement <4 x float> %19, float %13, i64 0
%21 = insertelement <4 x float> %19, float %13, i64 1
%22 = insertelement <4 x float> %21, float %14, i64 2
%23 = insertelement <4 x float> %22, float %14, i64 3
%24 = fmul <4 x float> %20, %23
%25 = insertelement <4 x float> poison, float %10, i64 0
%26 = insertelement <4 x float> %25, float %11, i64 1
%27 = shufflevector <4 x float> %26, <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 0>
%28 = shufflevector <4 x float> %19, <4 x float> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
%29 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %27, <4 x float> %28, <4 x float> %24)
%30 = shufflevector <4 x float> %29, <4 x float> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 1>
%31 = insertelement <4 x float> poison, float %17, i64 0
%32 = insertelement <4 x float> %31, float %16, i64 1
%33 = shufflevector <4 x float> %32, <4 x float> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
%34 = call <4 x float> @llvm.fmuladd.v4f32(<4 x float> %33, <4 x float> %28, <4 x float> %30)
%35 = fadd <4 x float> %19, %34
%36 = bitcast float* %0 to <4 x float>*
store <4 x float> %35, <4 x float>* %36
ret float* %0
}