double _atof(const char **stringPtr) {
  const char *string;
  float sign;
  float value;
  int c;
  string = *stringPtr;
  while (*string <= ' ') {
    if (!*string) {
      *stringPtr = string;
      return 0;
    }
    string++;
  }
  switch (*string) {
  case '+':
    string++;
    sign = 1;
    break;
  case '-':
    string++;
    sign = -1;
    break;
  default:
    sign = 1;
    break;
  }
  value = 0;
  if (string[0] != '.') {
    do {
      c = *string++;
      if (c < '0' || c > '9') {
        break;
      }
      c -= '0';
      value = value * 10 + c;
    } while (1);
  }
  if (c == '.') {
    double fraction;
    fraction = 0.1;
    do {
      c = *string++;
      if (c < '0' || c > '9') {
        break;
      }
      c -= '0';
      value += c * fraction;
      fraction *= 0.1;
    } while (1);
  }
  *stringPtr = string;
  return value * sign;
}


x86 assembly (clang, -O0):
<_atof>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    -0x10(%rbp),%rax
mov    (%rax),%rax
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x20,%eax
jg     1159 <_atof+0x59>
mov    -0x18(%rbp),%rax
cmpb   $0x0,(%rax)
jne    1148 <_atof+0x48>
mov    -0x18(%rbp),%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,(%rax)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1308 <_atof+0x208>
mov    -0x18(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x18(%rbp)
jmp    1113 <_atof+0x13>
mov    -0x18(%rbp),%rax
movsbl (%rax),%eax
mov    %eax,-0x34(%rbp)
sub    $0x2b,%eax
je     1182 <_atof+0x82>
jmp    1171 <_atof+0x71>
mov    -0x34(%rbp),%eax
sub    $0x2d,%eax
je     11a0 <_atof+0xa0>
jmp    11be <_atof+0xbe>
mov    -0x18(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x18(%rbp)
movss  0xe6e(%rip),%xmm0
movss  %xmm0,-0x1c(%rbp)
jmp    11cb <_atof+0xcb>
mov    -0x18(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x18(%rbp)
movss  0xe4c(%rip),%xmm0
movss  %xmm0,-0x1c(%rbp)
jmp    11cb <_atof+0xcb>
movss  0xe3e(%rip),%xmm0
movss  %xmm0,-0x1c(%rbp)
xorps  %xmm0,%xmm0
movss  %xmm0,-0x20(%rbp)
mov    -0x18(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2e,%eax
je     1252 <_atof+0x152>
jmp    11e8 <_atof+0xe8>
mov    -0x18(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x18(%rbp)
movsbl (%rax),%eax
mov    %eax,-0x24(%rbp)
cmpl   $0x30,-0x24(%rbp)
jl     1211 <_atof+0x111>
cmpl   $0x39,-0x24(%rbp)
jle    1216 <_atof+0x116>
jmp    124d <_atof+0x14d>
mov    -0x24(%rbp),%eax
sub    $0x30,%eax
mov    %eax,-0x24(%rbp)
movss  -0x20(%rbp),%xmm0
cvtsi2ssl -0x24(%rbp),%xmm1
movss  0xdd7(%rip),%xmm2
mulss  %xmm2,%xmm0
addss  %xmm1,%xmm0
movss  %xmm0,-0x20(%rbp)
mov    $0x1,%al
test   $0x1,%al
jne    11e8 <_atof+0xe8>
jmp    124d <_atof+0x14d>
jmp    1252 <_atof+0x152>
cmpl   $0x2e,-0x24(%rbp)
jne    12ea <_atof+0x1ea>
movsd  0xdac(%rip),%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x18(%rbp)
movsbl (%rax),%eax
mov    %eax,-0x24(%rbp)
cmpl   $0x30,-0x24(%rbp)
jl     1292 <_atof+0x192>
cmpl   $0x39,-0x24(%rbp)
jle    1297 <_atof+0x197>
jmp    12e5 <_atof+0x1e5>
mov    -0x24(%rbp),%eax
sub    $0x30,%eax
mov    %eax,-0x24(%rbp)
cvtsi2sdl -0x24(%rbp),%xmm0
movsd  -0x30(%rbp),%xmm2
movss  -0x20(%rbp),%xmm1
cvtss2sd %xmm1,%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x20(%rbp)
movsd  0xd44(%rip),%xmm0
mulsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    $0x1,%al
test   $0x1,%al
jne    1269 <_atof+0x169>
jmp    12e5 <_atof+0x1e5>
jmp    12ea <_atof+0x1ea>
mov    -0x18(%rbp),%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,(%rax)
movss  -0x20(%rbp),%xmm0
mulss  -0x1c(%rbp),%xmm0
cvtss2sd %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<_atof>:
mov    (%rdi),%rax
mov    (%rax),%cl
cmp    $0x20,%cl
jg     1125 <_atof+0x25>
nopw   0x0(%rax,%rax,1)
test   %cl,%cl
je     11ff <_atof+0xff>
movzbl 0x1(%rax),%ecx
add    $0x1,%rax
cmp    $0x21,%cl
jl     1110 <_atof+0x10>
movss  0xed3(%rip),%xmm0
cmp    $0x2b,%cl
je     113f <_atof+0x3f>
cmp    $0x2d,%cl
jne    1146 <_atof+0x46>
movss  0xec5(%rip),%xmm0
mov    0x1(%rax),%cl
add    $0x1,%rax
xorps  %xmm1,%xmm1
cmp    $0x2e,%cl
je     1199 <_atof+0x99>
add    $0x1,%rax
lea    -0x3a(%rcx),%edx
xorps  %xmm1,%xmm1
cmp    $0xf6,%dl
jb     1194 <_atof+0x94>
xorps  %xmm1,%xmm1
movss  0xea0(%rip),%xmm2
nopl   0x0(%rax,%rax,1)
movzbl %cl,%ecx
add    $0xffffffd0,%ecx
xorps  %xmm3,%xmm3
cvtsi2ss %ecx,%xmm3
mulss  %xmm2,%xmm1
addss  %xmm3,%xmm1
movzbl (%rax),%ecx
add    $0x1,%rax
lea    -0x3a(%rcx),%edx
cmp    $0xf5,%dl
ja     1170 <_atof+0x70>
cmp    $0x2e,%cl
jne    11f3 <_atof+0xf3>
mov    (%rax),%cl
add    $0x1,%rax
lea    -0x3a(%rcx),%edx
cmp    $0xf6,%dl
jb     11f3 <_atof+0xf3>
movsd  0xe61(%rip),%xmm2
movapd %xmm2,%xmm3
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzbl %cl,%ecx
add    $0xffffffd0,%ecx
xorps  %xmm4,%xmm4
cvtsi2sd %ecx,%xmm4
cvtss2sd %xmm1,%xmm1
mulsd  %xmm3,%xmm4
addsd  %xmm1,%xmm4
xorps  %xmm1,%xmm1
cvtsd2ss %xmm4,%xmm1
mulsd  %xmm2,%xmm3
movzbl (%rax),%ecx
add    $0x1,%rax
lea    -0x3a(%rcx),%edx
cmp    $0xf5,%dl
ja     11c0 <_atof+0xc0>
mulss  %xmm1,%xmm0
mov    %rax,(%rdi)
cvtss2sd %xmm0,%xmm0
ret
mov    %rax,(%rdi)
xorps  %xmm0,%xmm0
ret

LLVM IR (-O0):
define double @_atof(i8** %0) {
%2 = alloca double
%3 = alloca i8**
%4 = alloca i8*
%5 = alloca float
%6 = alloca float
%7 = alloca i32
%8 = alloca double
store i8** %0, i8*** %3
%9 = load i8**, i8*** %3
%10 = load i8*, i8** %9
store i8* %10, i8** %4
br label %11
11: ; preds = %23, %1
%12 = load i8*, i8** %4
%13 = load i8, i8* %12
%14 = sext i8 %13 to i32
%15 = icmp sle i32 %14, 32
br i1 %15, label %16, label %26
16: ; preds = %11
%17 = load i8*, i8** %4
%18 = load i8, i8* %17
%19 = icmp ne i8 %18, 0
br i1 %19, label %23, label %20
20: ; preds = %16
%21 = load i8*, i8** %4
%22 = load i8**, i8*** %3
store i8* %21, i8** %22
store double 0.000000e+00, double* %2
br label %100
23: ; preds = %16
%24 = load i8*, i8** %4
%25 = getelementptr inbounds i8, i8* %24, i32 1
store i8* %25, i8** %4
br label %11
26: ; preds = %11
%27 = load i8*, i8** %4
%28 = load i8, i8* %27
%29 = sext i8 %28 to i32
switch i32 %29, label %36 [
i32 43, label %30
i32 45, label %33
]
30: ; preds = %26
%31 = load i8*, i8** %4
%32 = getelementptr inbounds i8, i8* %31, i32 1
store i8* %32, i8** %4
store float 1.000000e+00, float* %5
br label %37
33: ; preds = %26
%34 = load i8*, i8** %4
%35 = getelementptr inbounds i8, i8* %34, i32 1
store i8* %35, i8** %4
store float -1.000000e+00, float* %5
br label %37
36: ; preds = %26
store float 1.000000e+00, float* %5
br label %37
37: ; preds = %36, %33, %30
store float 0.000000e+00, float* %6
%38 = load i8*, i8** %4
%39 = getelementptr inbounds i8, i8* %38, i64 0
%40 = load i8, i8* %39
%41 = sext i8 %40 to i32
%42 = icmp ne i32 %41, 46
br i1 %42, label %43, label %64
43: ; preds = %37
br label %44
44: ; preds = %62, %43
%45 = load i8*, i8** %4
%46 = getelementptr inbounds i8, i8* %45, i32 1
store i8* %46, i8** %4
%47 = load i8, i8* %45
%48 = sext i8 %47 to i32
store i32 %48, i32* %7
%49 = load i32, i32* %7
%50 = icmp slt i32 %49, 48
br i1 %50, label %54, label %51
51: ; preds = %44
%52 = load i32, i32* %7
%53 = icmp sgt i32 %52, 57
br i1 %53, label %54, label %55
54: ; preds = %51, %44
br label %63
55: ; preds = %51
%56 = load i32, i32* %7
%57 = sub nsw i32 %56, 48
store i32 %57, i32* %7
%58 = load float, float* %6
%59 = load i32, i32* %7
%60 = sitofp i32 %59 to float
%61 = call float @llvm.fmuladd.f32(float %58, float 1.000000e+01, float %60)
store float %61, float* %6
br label %62
62: ; preds = %55
br i1 true, label %44, label %63
63: ; preds = %62, %54
br label %64
64: ; preds = %63, %37
%65 = load i32, i32* %7
%66 = icmp eq i32 %65, 46
br i1 %66, label %67, label %93
67: ; preds = %64
store double 1.000000e-01, double* %8
br label %68
68: ; preds = %91, %67
%69 = load i8*, i8** %4
%70 = getelementptr inbounds i8, i8* %69, i32 1
store i8* %70, i8** %4
%71 = load i8, i8* %69
%72 = sext i8 %71 to i32
store i32 %72, i32* %7
%73 = load i32, i32* %7
%74 = icmp slt i32 %73, 48
br i1 %74, label %78, label %75
75: ; preds = %68
%76 = load i32, i32* %7
%77 = icmp sgt i32 %76, 57
br i1 %77, label %78, label %79
78: ; preds = %75, %68
br label %92
79: ; preds = %75
%80 = load i32, i32* %7
%81 = sub nsw i32 %80, 48
store i32 %81, i32* %7
%82 = load i32, i32* %7
%83 = sitofp i32 %82 to double
%84 = load double, double* %8
%85 = load float, float* %6
%86 = fpext float %85 to double
%87 = call double @llvm.fmuladd.f64(double %83, double %84, double %86)
%88 = fptrunc double %87 to float
store float %88, float* %6
%89 = load double, double* %8
%90 = fmul double %89, 1.000000e-01
store double %90, double* %8
br label %91
91: ; preds = %79
br i1 true, label %68, label %92
92: ; preds = %91, %78
br label %93
93: ; preds = %92, %64
%94 = load i8*, i8** %4
%95 = load i8**, i8*** %3
store i8* %94, i8** %95
%96 = load float, float* %6
%97 = load float, float* %5
%98 = fmul float %96, %97
%99 = fpext float %98 to double
store double %99, double* %2
br label %100
100: ; preds = %93, %20
%101 = load double, double* %2
ret double %101
}

LLVM IR (-O2):
define double @_atof(i8** nocapture %0) {
%2 = load i8*, i8** %0
%3 = load i8, i8* %2
%4 = icmp slt i8 %3, 33
br i1 %4, label %5, label %14
5: ; preds = %1, %10
%6 = phi i8 [ %12, %10 ], [ %3, %1 ]
%7 = phi i8* [ %11, %10 ], [ %2, %1 ]
%8 = icmp eq i8 %6, 0
br i1 %8, label %9, label %10
9: ; preds = %5
store i8* %7, i8** %0
br label %76
10: ; preds = %5
%11 = getelementptr inbounds i8, i8* %7, i64 1
%12 = load i8, i8* %11
%13 = icmp slt i8 %12, 33
br i1 %13, label %5, label %14
14: ; preds = %10, %1
%15 = phi i8* [ %2, %1 ], [ %11, %10 ]
%16 = phi i8 [ %3, %1 ], [ %12, %10 ]
switch i8 %16, label %22 [
i8 43, label %18
i8 45, label %17
]
17: ; preds = %14
br label %18
18: ; preds = %14, %17
%19 = phi float [ -1.000000e+00, %17 ], [ 1.000000e+00, %14 ]
%20 = getelementptr inbounds i8, i8* %15, i64 1
%21 = load i8, i8* %20
br label %22
22: ; preds = %18, %14
%23 = phi i8 [ %21, %18 ], [ %16, %14 ]
%24 = phi i8* [ %20, %18 ], [ %15, %14 ]
%25 = phi float [ %19, %18 ], [ 1.000000e+00, %14 ]
%26 = icmp eq i8 %23, 46
br i1 %26, label %48, label %27
27: ; preds = %22
%28 = getelementptr inbounds i8, i8* %24, i64 1
%29 = add i8 %23, -58
%30 = icmp ult i8 %29, -10
br i1 %30, label %43, label %31
31: ; preds = %27, %31
%32 = phi i8 [ %40, %31 ], [ %23, %27 ]
%33 = phi i8* [ %39, %31 ], [ %28, %27 ]
%34 = phi float [ %38, %31 ], [ 0.000000e+00, %27 ]
%35 = zext i8 %32 to i32
%36 = add nsw i32 %35, -48
%37 = sitofp i32 %36 to float
%38 = tail call float @llvm.fmuladd.f32(float %34, float 1.000000e+01, float %37)
%39 = getelementptr inbounds i8, i8* %33, i64 1
%40 = load i8, i8* %33
%41 = add i8 %40, -58
%42 = icmp ult i8 %41, -10
br i1 %42, label %43, label %31
43: ; preds = %31, %27
%44 = phi i8 [ %23, %27 ], [ %40, %31 ]
%45 = phi float [ 0.000000e+00, %27 ], [ %38, %31 ]
%46 = phi i8* [ %28, %27 ], [ %39, %31 ]
%47 = icmp eq i8 %44, 46
br i1 %47, label %48, label %71
48: ; preds = %22, %43
%49 = phi float [ %45, %43 ], [ 0.000000e+00, %22 ]
%50 = phi i8* [ %46, %43 ], [ %24, %22 ]
%51 = getelementptr inbounds i8, i8* %50, i64 1
%52 = load i8, i8* %50
%53 = add i8 %52, -58
%54 = icmp ult i8 %53, -10
br i1 %54, label %71, label %55
55: ; preds = %48, %55
%56 = phi i8 [ %68, %55 ], [ %52, %48 ]
%57 = phi i8* [ %67, %55 ], [ %51, %48 ]
%58 = phi double [ %66, %55 ], [ 1.000000e-01, %48 ]
%59 = phi float [ %65, %55 ], [ %49, %48 ]
%60 = zext i8 %56 to i32
%61 = add nsw i32 %60, -48
%62 = sitofp i32 %61 to double
%63 = fpext float %59 to double
%64 = tail call double @llvm.fmuladd.f64(double %62, double %58, double %63)
%65 = fptrunc double %64 to float
%66 = fmul double %58, 1.000000e-01
%67 = getelementptr inbounds i8, i8* %57, i64 1
%68 = load i8, i8* %57
%69 = add i8 %68, -58
%70 = icmp ult i8 %69, -10
br i1 %70, label %71, label %55
71: ; preds = %55, %48, %43
%72 = phi i8* [ %46, %43 ], [ %51, %48 ], [ %67, %55 ]
%73 = phi float [ %45, %43 ], [ %49, %48 ], [ %65, %55 ]
store i8* %72, i8** %0
%74 = fmul float %25, %73
%75 = fpext float %74 to double
br label %76
76: ; preds = %71, %9
%77 = phi double [ 0.000000e+00, %9 ], [ %75, %71 ]
ret double %77
}