double act(double a, double b, char op) {
  if (op == '+')
    return a + b;
  if (op == '-')
    return a - b;
  if (op == '*')
    return a * b;
  if (op == '/')
    return a / b;
  if (op == '^') {
    while (b--)
      a *= a;
    return a;
  }
}


x86 assembly (clang, -O0):
<act>:
push   %rbp
mov    %rsp,%rbp
mov    %dil,%al
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
mov    %al,-0x19(%rbp)
movsbl -0x19(%rbp),%eax
cmp    $0x2b,%eax
jne    1135 <act+0x35>
movsd  -0x10(%rbp),%xmm0
addsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11f9 <act+0xf9>
movsbl -0x19(%rbp),%eax
cmp    $0x2d,%eax
jne    1156 <act+0x56>
movsd  -0x10(%rbp),%xmm0
subsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11f9 <act+0xf9>
movsbl -0x19(%rbp),%eax
cmp    $0x2a,%eax
jne    1177 <act+0x77>
movsd  -0x10(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11f9 <act+0xf9>
movsbl -0x19(%rbp),%eax
cmp    $0x2f,%eax
jne    1198 <act+0x98>
movsd  -0x10(%rbp),%xmm0
divsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    11f9 <act+0xf9>
movsbl -0x19(%rbp),%eax
cmp    $0x5e,%eax
jne    11f9 <act+0xf9>
jmp    11aa <act+0xaa>
movsd  -0x18(%rbp),%xmm0
movsd  0xe49(%rip),%xmm2
movaps %xmm0,%xmm1
addsd  %xmm2,%xmm1
movsd  %xmm1,-0x18(%rbp)
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11db <act+0xdb>
jp     11db <act+0xdb>
jmp    11ef <act+0xef>
movsd  -0x10(%rbp),%xmm0
mulsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x10(%rbp)
jmp    11aa <act+0xaa>
movsd  -0x10(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<act>:
lea    -0x2a(%rdi),%eax
cmp    $0x5,%al
ja     111f <act+0x1f>
movzbl %al,%eax
lea    0xef7(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mulsd  %xmm1,%xmm0
ret
cmp    $0x5e,%dil
jne    1150 <act+0x50>
xorpd  %xmm2,%xmm2
ucomisd %xmm2,%xmm1
jne    1131 <act+0x31>
jnp    1150 <act+0x50>
movsd  0xec7(%rip),%xmm3
nopl   0x0(%rax)
addsd  %xmm3,%xmm1
mulsd  %xmm0,%xmm0
ucomisd %xmm2,%xmm1
jne    1140 <act+0x40>
jp     1140 <act+0x40>
ret
addsd  %xmm1,%xmm0
ret
subsd  %xmm1,%xmm0
ret
divsd  %xmm1,%xmm0
ret

LLVM IR (-O0):
define double @act(double %0, double %1, i8 signext %2) {
%4 = alloca double
%5 = alloca double
%6 = alloca double
%7 = alloca i8
store double %0, double* %5
store double %1, double* %6
store i8 %2, i8* %7
%8 = load i8, i8* %7
%9 = sext i8 %8 to i32
%10 = icmp eq i32 %9, 43
br i1 %10, label %11, label %15
11: ; preds = %3
%12 = load double, double* %5
%13 = load double, double* %6
%14 = fadd double %12, %13
store double %14, double* %4
br label %54
15: ; preds = %3
%16 = load i8, i8* %7
%17 = sext i8 %16 to i32
%18 = icmp eq i32 %17, 45
br i1 %18, label %19, label %23
19: ; preds = %15
%20 = load double, double* %5
%21 = load double, double* %6
%22 = fsub double %20, %21
store double %22, double* %4
br label %54
23: ; preds = %15
%24 = load i8, i8* %7
%25 = sext i8 %24 to i32
%26 = icmp eq i32 %25, 42
br i1 %26, label %27, label %31
27: ; preds = %23
%28 = load double, double* %5
%29 = load double, double* %6
%30 = fmul double %28, %29
store double %30, double* %4
br label %54
31: ; preds = %23
%32 = load i8, i8* %7
%33 = sext i8 %32 to i32
%34 = icmp eq i32 %33, 47
br i1 %34, label %35, label %39
35: ; preds = %31
%36 = load double, double* %5
%37 = load double, double* %6
%38 = fdiv double %36, %37
store double %38, double* %4
br label %54
39: ; preds = %31
%40 = load i8, i8* %7
%41 = sext i8 %40 to i32
%42 = icmp eq i32 %41, 94
br i1 %42, label %43, label %54
43: ; preds = %39
br label %44
44: ; preds = %48, %43
%45 = load double, double* %6
%46 = fadd double %45, -1.000000e+00
store double %46, double* %6
%47 = fcmp une double %45, 0.000000e+00
br i1 %47, label %48, label %52
48: ; preds = %44
%49 = load double, double* %5
%50 = load double, double* %5
%51 = fmul double %50, %49
store double %51, double* %5
br label %44
52: ; preds = %44
%53 = load double, double* %5
store double %53, double* %4
br label %54
54: ; preds = %11, %19, %27, %35, %52, %39
%55 = load double, double* %4
ret double %55
}

LLVM IR (-O2):
define double @act(double %0, double %1, i8 signext %2) {
switch i8 %2, label %20 [
i8 43, label %6
i8 45, label %8
i8 42, label %10
i8 47, label %12
i8 94, label %4
]
4: ; preds = %3
%5 = fcmp une double %1, 0.000000e+00
br i1 %5, label %14, label %20
6: ; preds = %3
%7 = fadd double %0, %1
br label %20
8: ; preds = %3
%9 = fsub double %0, %1
br label %20
10: ; preds = %3
%11 = fmul double %0, %1
br label %20
12: ; preds = %3
%13 = fdiv double %0, %1
br label %20
14: ; preds = %4, %14
%15 = phi double [ %17, %14 ], [ %1, %4 ]
%16 = phi double [ %18, %14 ], [ %0, %4 ]
%17 = fadd double %15, -1.000000e+00
%18 = fmul double %16, %16
%19 = fcmp une double %17, 0.000000e+00
br i1 %19, label %14, label %20
20: ; preds = %14, %4, %3, %6, %8, %10, %12
%21 = phi double [ %7, %6 ], [ %9, %8 ], [ %11, %10 ], [ %13, %12 ], [ undef, %3 ], [ %0, %4 ], [ %18, %14 ]
ret double %21
}