int ema(int sensor, int current) {
  static float alpha = 0.3;
  static float lastema[10];
  static short initialized[10] = {0};
  float ema;
  if (initialized[sensor] == 0) {
    ema = current;
    initialized[sensor] = 1;
  } else {
    ema = (alpha * current + (1 - alpha) * lastema[sensor]);
  }
  lastema[sensor] = ema;
  return (int)ema;
}


x86 assembly (clang, -O0):
<ema>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
movslq -0x4(%rbp),%rcx
lea    0x2f5b(%rip),%rax
movswl (%rax,%rcx,2),%eax
cmp    $0x0,%eax
jne    1142 <ema+0x42>
cvtsi2ssl -0x8(%rbp),%xmm0
movss  %xmm0,-0xc(%rbp)
movslq -0x4(%rbp),%rcx
lea    0x2f39(%rip),%rax
movw   $0x1,(%rax,%rcx,2)
jmp    117c <ema+0x7c>
movss  0x2ed6(%rip),%xmm0
cvtsi2ssl -0x8(%rbp),%xmm2
movss  0xea9(%rip),%xmm1
subss  0x2ec1(%rip),%xmm1
movslq -0x4(%rbp),%rcx
lea    0x2ed6(%rip),%rax
mulss  (%rax,%rcx,4),%xmm1
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0xc(%rbp)
movss  -0xc(%rbp),%xmm0
movslq -0x4(%rbp),%rcx
lea    0x2eb4(%rip),%rax
movss  %xmm0,(%rax,%rcx,4)
cvttss2si -0xc(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<ema>:
movslq %edi,%rax
lea    0x2f56(%rip),%rcx
cmpw   $0x0,(%rcx,%rax,2)
cvtsi2ss %esi,%xmm0
je     1137 <ema+0x37>
lea    0x2f14(%rip),%rcx
movss  (%rcx,%rax,4),%xmm1
mulss  0xed7(%rip),%xmm1
mulss  0xed3(%rip),%xmm0
addss  %xmm1,%xmm0
jmp    113d <ema+0x3d>
movw   $0x1,(%rcx,%rax,2)
lea    0x2eec(%rip),%rcx
movss  %xmm0,(%rcx,%rax,4)
cvttss2si %xmm0,%eax
ret

LLVM IR (-O0):
@ema.alpha = internal global float 0x3FD3333340000000
@ema.lastema = internal global [10 x float] zeroinitializer
@ema.initialized = internal global [10 x i16] zeroinitializer
define i32 @ema(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca float
store i32 %0, i32* %3
store i32 %1, i32* %4
%6 = load i32, i32* %3
%7 = sext i32 %6 to i64
%8 = getelementptr inbounds [10 x i16], [10 x i16]* @ema.initialized, i64 0, i64 %7
%9 = load i16, i16* %8
%10 = sext i16 %9 to i32
%11 = icmp eq i32 %10, 0
br i1 %11, label %12, label %18
12: ; preds = %2
%13 = load i32, i32* %4
%14 = sitofp i32 %13 to float
store float %14, float* %5
%15 = load i32, i32* %3
%16 = sext i32 %15 to i64
%17 = getelementptr inbounds [10 x i16], [10 x i16]* @ema.initialized, i64 0, i64 %16
store i16 1, i16* %17
br label %30
18: ; preds = %2
%19 = load float, float* @ema.alpha
%20 = load i32, i32* %4
%21 = sitofp i32 %20 to float
%22 = load float, float* @ema.alpha
%23 = fsub float 1.000000e+00, %22
%24 = load i32, i32* %3
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds [10 x float], [10 x float]* @ema.lastema, i64 0, i64 %25
%27 = load float, float* %26
%28 = fmul float %23, %27
%29 = call float @llvm.fmuladd.f32(float %19, float %21, float %28)
store float %29, float* %5
br label %30
30: ; preds = %18, %12
%31 = load float, float* %5
%32 = load i32, i32* %3
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [10 x float], [10 x float]* @ema.lastema, i64 0, i64 %33
store float %31, float* %34
%35 = load float, float* %5
%36 = fptosi float %35 to i32
ret i32 %36
}

LLVM IR (-O2):
@ema.lastema = internal unnamed_addr global [10 x float] zeroinitializer
@ema.initialized = internal unnamed_addr global [10 x i16] zeroinitializer
define i32 @ema(i32 %0, i32 %1) {
%3 = sext i32 %0 to i64
%4 = getelementptr inbounds [10 x i16], [10 x i16]* @ema.initialized, i64 0, i64 %3
%5 = load i16, i16* %4
%6 = icmp eq i16 %5, 0
%7 = sitofp i32 %1 to float
br i1 %6, label %8, label %9
8: ; preds = %2
store i16 1, i16* %4
br label %14
9: ; preds = %2
%10 = getelementptr inbounds [10 x float], [10 x float]* @ema.lastema, i64 0, i64 %3
%11 = load float, float* %10
%12 = fmul float %11, 0x3FE6666660000000
%13 = tail call float @llvm.fmuladd.f32(float %7, float 0x3FD3333340000000, float %12)
br label %14
14: ; preds = %9, %8
%15 = phi float [ %7, %8 ], [ %13, %9 ]
%16 = getelementptr inbounds [10 x float], [10 x float]* @ema.lastema, i64 0, i64 %3
store float %15, float* %16
%17 = fptosi float %15 to i32
ret i32 %17
}