#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 */
typedef double ssize_t;

/* Variables and functions */
double EINVAL;
double ERANGE;
double HUGE_VAL;
int INT64_C(int);
double strtod(char const *, char **);
int tolower(char);
ssize_t pfl_humantonum(const char *s) {
  ssize_t m = 1;
  char *endp;
  double sz;
  sz = strtod(s, &endp);
  if (s == endp || sz == HUGE_VAL)
    return (-EINVAL);
  if (sz < 0)
    return (-ERANGE);
  switch (tolower(*endp)) {
  case 'k':
    m = 1024;
    break;
  case 'm':
    m = 1024 * 1024;
    break;
  case 'g':
    m = 1024 * 1024 * 1024;
    break;
  case 't':
    m = 1024 * 1024 * 1024 * INT64_C(1024);
    break;
  case '\0':
    break;
  default:
    return (-EINVAL);
  }
  if (sz * m < sz)
    return (-ERANGE);
  return (sz * m);
}


x86 assembly (clang, -O0):
<pfl_humantonum>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x10(%rbp)
movsd  0xebc(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x10(%rbp),%rdi
lea    -0x20(%rbp),%rsi
call   1030 <strtod@plt>
movsd  %xmm0,-0x28(%rbp)
mov    -0x10(%rbp),%rax
cmp    -0x20(%rbp),%rax
je     1185 <pfl_humantonum+0x55>
movsd  -0x28(%rbp),%xmm0
mov    0x2e73(%rip),%rax
ucomisd (%rax),%xmm0
jne    11b1 <pfl_humantonum+0x81>
jp     11b1 <pfl_humantonum+0x81>
mov    0x2e44(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1323 <pfl_humantonum+0x1f3>
xorps  %xmm0,%xmm0
ucomisd -0x28(%rbp),%xmm0
jbe    11eb <pfl_humantonum+0xbb>
mov    0x2e1a(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1323 <pfl_humantonum+0x1f3>
mov    -0x20(%rbp),%rax
movsbl (%rax),%edi
call   1050 <tolower@plt>
mov    %eax,%ecx
mov    %ecx,-0x2c(%rbp)
test   %eax,%eax
je     129e <pfl_humantonum+0x16e>
jmp    1209 <pfl_humantonum+0xd9>
mov    -0x2c(%rbp),%eax
sub    $0x67,%eax
je     1271 <pfl_humantonum+0x141>
jmp    121a <pfl_humantonum+0xea>
mov    -0x2c(%rbp),%eax
sub    $0x6b,%eax
je     124d <pfl_humantonum+0x11d>
jmp    122b <pfl_humantonum+0xfb>
mov    -0x2c(%rbp),%eax
sub    $0x6d,%eax
je     125f <pfl_humantonum+0x12f>
jmp    123c <pfl_humantonum+0x10c>
mov    -0x2c(%rbp),%eax
sub    $0x74,%eax
je     1283 <pfl_humantonum+0x153>
jmp    12a3 <pfl_humantonum+0x173>
movsd  0xdc3(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    12cf <pfl_humantonum+0x19f>
movsd  0xda9(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    12cf <pfl_humantonum+0x19f>
movsd  0xd8f(%rip),%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    12cf <pfl_humantonum+0x19f>
mov    $0x400,%edi
call   1040 <INT64_C@plt>
shl    $0x1e,%eax
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x18(%rbp)
jmp    12cf <pfl_humantonum+0x19f>
jmp    12cf <pfl_humantonum+0x19f>
mov    0x2d26(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1323 <pfl_humantonum+0x1f3>
movsd  -0x28(%rbp),%xmm1
mulsd  -0x18(%rbp),%xmm1
movsd  -0x28(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jbe    1314 <pfl_humantonum+0x1e4>
mov    0x2cf1(%rip),%rax
movsd  (%rax),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1323 <pfl_humantonum+0x1f3>
movsd  -0x28(%rbp),%xmm0
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<pfl_humantonum>:
push   %rbx
sub    $0x10,%rsp
mov    %rdi,%rbx
lea    0x8(%rsp),%rsi
call   1030 <strtod@plt>
mov    0x8(%rsp),%rax
cmp    %rbx,%rax
je     11a2 <pfl_humantonum+0x72>
mov    0x2e95(%rip),%rcx
ucomisd (%rcx),%xmm0
jne    115b <pfl_humantonum+0x2b>
jnp    11a2 <pfl_humantonum+0x72>
xorpd  %xmm1,%xmm1
ucomisd %xmm0,%xmm1
ja     11e2 <pfl_humantonum+0xb2>
movsd  %xmm0,(%rsp)
movsbl (%rax),%edi
call   1050 <tolower@plt>
lea    -0x67(%rax),%ecx
cmp    $0xd,%ecx
ja     1194 <pfl_humantonum+0x64>
lea    0xeaf(%rip),%rax
movslq (%rax,%rcx,4),%rcx
add    %rax,%rcx
jmp    *%rcx
movsd  0xe76(%rip),%xmm0
jmp    11d3 <pfl_humantonum+0xa3>
test   %eax,%eax
jne    11a2 <pfl_humantonum+0x72>
movsd  0xe60(%rip),%xmm0
jmp    11d3 <pfl_humantonum+0xa3>
mov    0x2e27(%rip),%rax
jmp    11e9 <pfl_humantonum+0xb9>
movsd  0xe65(%rip),%xmm0
jmp    11d3 <pfl_humantonum+0xa3>
movsd  0xe53(%rip),%xmm0
jmp    11d3 <pfl_humantonum+0xa3>
mov    $0x400,%edi
call   1040 <INT64_C@plt>
shl    $0x1e,%eax
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  (%rsp),%xmm1
mulsd  %xmm1,%xmm0
ucomisd %xmm0,%xmm1
jbe    11f5 <pfl_humantonum+0xc5>
mov    0x2df7(%rip),%rax
movsd  (%rax),%xmm0
xorpd  0xe2b(%rip),%xmm0
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
@HUGE_VAL = global double 0.000000e+00
@EINVAL = global double 0.000000e+00
@ERANGE = global double 0.000000e+00
define double @pfl_humantonum(i8* %0) {
%2 = alloca double
%3 = alloca i8*
%4 = alloca double
%5 = alloca i8*
%6 = alloca double
store i8* %0, i8** %3
store double 1.000000e+00, double* %4
%7 = load i8*, i8** %3
%8 = call double @strtod(i8* %7, i8** %5)
store double %8, double* %6
%9 = load i8*, i8** %3
%10 = load i8*, i8** %5
%11 = icmp eq i8* %9, %10
br i1 %11, label %16, label %12
12: ; preds = %1
%13 = load double, double* %6
%14 = load double, double* @HUGE_VAL
%15 = fcmp oeq double %13, %14
br i1 %15, label %16, label %19
16: ; preds = %12, %1
%17 = load double, double* @EINVAL
%18 = fneg double %17
store double %18, double* %2
br label %53
19: ; preds = %12
%20 = load double, double* %6
%21 = fcmp olt double %20, 0.000000e+00
br i1 %21, label %22, label %25
22: ; preds = %19
%23 = load double, double* @ERANGE
%24 = fneg double %23
store double %24, double* %2
br label %53
25: ; preds = %19
%26 = load i8*, i8** %5
%27 = load i8, i8* %26
%28 = call i32 @tolower(i8 signext %27)
switch i32 %28, label %37 [
i32 107, label %29
i32 109, label %30
i32 103, label %31
i32 116, label %32
i32 0, label %36
]
29: ; preds = %25
store double 1.024000e+03, double* %4
br label %40
30: ; preds = %25
store double 0x4130000000000000, double* %4
br label %40
31: ; preds = %25
store double 0x41D0000000000000, double* %4
br label %40
32: ; preds = %25
%33 = call i32 @INT64_C(i32 1024)
%34 = mul nsw i32 1073741824, %33
%35 = sitofp i32 %34 to double
store double %35, double* %4
br label %40
36: ; preds = %25
br label %40
37: ; preds = %25
%38 = load double, double* @EINVAL
%39 = fneg double %38
store double %39, double* %2
br label %53
40: ; preds = %36, %32, %31, %30, %29
%41 = load double, double* %6
%42 = load double, double* %4
%43 = fmul double %41, %42
%44 = load double, double* %6
%45 = fcmp olt double %43, %44
br i1 %45, label %46, label %49
46: ; preds = %40
%47 = load double, double* @ERANGE
%48 = fneg double %47
store double %48, double* %2
br label %53
49: ; preds = %40
%50 = load double, double* %6
%51 = load double, double* %4
%52 = fmul double %50, %51
store double %52, double* %2
br label %53
53: ; preds = %49, %46, %37, %22, %16
%54 = load double, double* %2
ret double %54
}

LLVM IR (-O2):
@HUGE_VAL = global double 0.000000e+00
@EINVAL = global double 0.000000e+00
@ERANGE = global double 0.000000e+00
define double @pfl_humantonum(i8* %0) {
%2 = alloca i8*
%3 = bitcast i8** %2 to i8*
%4 = call double @strtod(i8* %0, i8** %2)
%5 = load i8*, i8** %2
%6 = icmp eq i8* %5, %0
%7 = load double, double* @HUGE_VAL
%8 = fcmp oeq double %4, %7
%9 = select i1 %6, i1 true, i1 %8
br i1 %9, label %10, label %13
10: ; preds = %1
%11 = load double, double* @EINVAL
%12 = fneg double %11
br label %38
13: ; preds = %1
%14 = fcmp olt double %4, 0.000000e+00
br i1 %14, label %15, label %18
15: ; preds = %13
%16 = load double, double* @ERANGE
%17 = fneg double %16
br label %38
18: ; preds = %13
%19 = load i8, i8* %5
%20 = tail call i32 @tolower(i8 signext %19)
switch i32 %20, label %28 [
i32 107, label %21
i32 109, label %22
i32 103, label %23
i32 116, label %24
i32 0, label %31
]
21: ; preds = %18
br label %31
22: ; preds = %18
br label %31
23: ; preds = %18
br label %31
24: ; preds = %18
%25 = tail call i32 @INT64_C(i32 1024)
%26 = shl nsw i32 %25, 30
%27 = sitofp i32 %26 to double
br label %31
28: ; preds = %18
%29 = load double, double* @EINVAL
%30 = fneg double %29
br label %38
31: ; preds = %18, %24, %23, %22, %21
%32 = phi double [ 1.000000e+00, %18 ], [ %27, %24 ], [ 0x41D0000000000000, %23 ], [ 0x4130000000000000, %22 ], [ 1.024000e+03, %21 ]
%33 = fmul double %4, %32
%34 = fcmp olt double %33, %4
br i1 %34, label %35, label %38
35: ; preds = %31
%36 = load double, double* @ERANGE
%37 = fneg double %36
br label %38
38: ; preds = %31, %35, %28, %15, %10
%39 = phi double [ %12, %10 ], [ %17, %15 ], [ %30, %28 ], [ %37, %35 ], [ %33, %31 ]
ret double %39
}