double serd_strtod(const char *str, char **endptr) {
  double result = 0.0;
  const char *s = str;
  while (is_space(*s)) {
    ++s;
  }
  const double sign = read_sign(&s);
  for (; is_digit(*s); ++s) {
    result = (result * 10.0) + (*s - '0');
  }
  if (*s == '.') {
    double denom = 10.0;
    for (++s; is_digit(*s); ++s) {
      result += (*s - '0') / denom;
      denom *= 10.0;
    }
  }
  if (*s == 'e' || *s == 'E') {
    ++s;
    double expt = 0.0;
    double expt_sign = read_sign(&s);
    for (; is_digit(*s); ++s) {
      expt = (expt * 10.0) + (*s - '0');
    }
    result *= pow(10, expt * expt_sign);
  }
  if (endptr) {
    *endptr = (char *)s;
  }
  return result * sign;
}


x86 assembly (clang, -O0):
<serd_strtod>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
movsbl (%rax),%edi
mov    $0x0,%al
call   1060 <is_space@plt>
cmp    $0x0,%eax
je     1188 <serd_strtod+0x48>
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    1160 <serd_strtod+0x20>
lea    -0x20(%rbp),%rdi
mov    $0x0,%al
call   1050 <read_sign@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x20(%rbp),%rax
movsbl (%rax),%edi
mov    $0x0,%al
call   1030 <is_digit@plt>
cmp    $0x0,%eax
je     11ec <serd_strtod+0xac>
movsd  -0x18(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
sub    $0x30,%eax
cvtsi2sd %eax,%xmm1
movsd  0xe32(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    119c <serd_strtod+0x5c>
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2e,%eax
jne    1271 <serd_strtod+0x131>
movsd  0xdfc(%rip),%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
movsbl (%rax),%edi
mov    $0x0,%al
call   1030 <is_digit@plt>
cmp    $0x0,%eax
je     126c <serd_strtod+0x12c>
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
sub    $0x30,%eax
cvtsi2sd %eax,%xmm0
divsd  -0x30(%rbp),%xmm0
addsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
movsd  0xdaf(%rip),%xmm0
mulsd  -0x30(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    1215 <serd_strtod+0xd5>
jmp    1271 <serd_strtod+0x131>
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x65,%eax
je     1291 <serd_strtod+0x151>
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x45,%eax
jne    132a <serd_strtod+0x1ea>
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x38(%rbp)
lea    -0x20(%rbp),%rdi
mov    $0x0,%al
call   1050 <read_sign@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x40(%rbp)
mov    -0x20(%rbp),%rax
movsbl (%rax),%edi
mov    $0x0,%al
call   1030 <is_digit@plt>
cmp    $0x0,%eax
je     1309 <serd_strtod+0x1c9>
movsd  -0x38(%rbp),%xmm0
mov    -0x20(%rbp),%rax
movsbl (%rax),%eax
sub    $0x30,%eax
cvtsi2sd %eax,%xmm1
movsd  0xd15(%rip),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    12b9 <serd_strtod+0x179>
movsd  -0x38(%rbp),%xmm1
mulsd  -0x40(%rbp),%xmm1
movsd  0xce5(%rip),%xmm0
call   1040 <pow@plt>
mulsd  -0x18(%rbp),%xmm0
movsd  %xmm0,-0x18(%rbp)
cmpq   $0x0,-0x10(%rbp)
je     1340 <serd_strtod+0x200>
mov    -0x20(%rbp),%rcx
mov    -0x10(%rbp),%rax
mov    %rcx,(%rax)
movsd  -0x18(%rbp),%xmm0
mulsd  -0x28(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<serd_strtod>:
push   %rbp
push   %rbx
sub    $0x28,%rsp
mov    %rsi,%rbx
mov    %rdi,%rbp
mov    %rdi,0x8(%rsp)
movsbl (%rdi),%edi
xor    %eax,%eax
call   1060 <is_space@plt>
test   %eax,%eax
je     1178 <serd_strtod+0x38>
nop
movsbl 0x1(%rbp),%edi
add    $0x1,%rbp
xor    %eax,%eax
call   1060 <is_space@plt>
test   %eax,%eax
jne    1160 <serd_strtod+0x20>
mov    %rbp,0x8(%rsp)
lea    0x8(%rsp),%rdi
xor    %eax,%eax
call   1050 <read_sign@plt>
mov    %eax,%ebp
mov    0x8(%rsp),%rax
movsbl (%rax),%edi
xor    %eax,%eax
call   1030 <is_digit@plt>
xorpd  %xmm1,%xmm1
test   %eax,%eax
je     11e2 <serd_strtod+0xa2>
nopl   (%rax)
mov    0x8(%rsp),%rax
movsbl (%rax),%ecx
add    $0xffffffd0,%ecx
xorps  %xmm0,%xmm0
cvtsi2sd %ecx,%xmm0
mulsd  0xe46(%rip),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%rsp)
lea    0x1(%rax),%rcx
mov    %rcx,0x8(%rsp)
movsbl 0x1(%rax),%edi
xor    %eax,%eax
call   1030 <is_digit@plt>
movsd  0x10(%rsp),%xmm1
test   %eax,%eax
jne    11a0 <serd_strtod+0x60>
mov    0x8(%rsp),%rax
cmpb   $0x2e,(%rax)
jne    127a <serd_strtod+0x13a>
movsd  %xmm1,0x10(%rsp)
lea    0x1(%rax),%rcx
mov    %rcx,0x8(%rsp)
movsbl 0x1(%rax),%edi
xor    %eax,%eax
call   1030 <is_digit@plt>
test   %eax,%eax
je     1274 <serd_strtod+0x134>
movsd  0xdea(%rip),%xmm2
movsd  0x10(%rsp),%xmm1
nopl   0x0(%rax)
mov    0x8(%rsp),%rax
movsbl (%rax),%ecx
add    $0xffffffd0,%ecx
xorps  %xmm0,%xmm0
cvtsi2sd %ecx,%xmm0
divsd  %xmm2,%xmm0
addsd  %xmm0,%xmm1
movsd  %xmm1,0x10(%rsp)
mulsd  0xdb8(%rip),%xmm2
movsd  %xmm2,0x18(%rsp)
lea    0x1(%rax),%rcx
mov    %rcx,0x8(%rsp)
movsbl 0x1(%rax),%edi
xor    %eax,%eax
call   1030 <is_digit@plt>
movsd  0x18(%rsp),%xmm2
movsd  0x10(%rsp),%xmm1
test   %eax,%eax
jne    1220 <serd_strtod+0xe0>
jmp    127a <serd_strtod+0x13a>
movsd  0x10(%rsp),%xmm1
mov    0x8(%rsp),%rax
mov    (%rax),%cl
or     $0x20,%cl
cmp    $0x65,%cl
jne    132f <serd_strtod+0x1ef>
movsd  %xmm1,0x10(%rsp)
add    $0x1,%rax
mov    %rax,0x8(%rsp)
lea    0x8(%rsp),%rdi
xor    %eax,%eax
call   1050 <read_sign@plt>
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
movsd  %xmm0,0x20(%rsp)
mov    0x8(%rsp),%rax
movsbl (%rax),%edi
xor    %eax,%eax
call   1030 <is_digit@plt>
xorpd  %xmm1,%xmm1
test   %eax,%eax
je     1312 <serd_strtod+0x1d2>
nopl   0x0(%rax)
mov    0x8(%rsp),%rax
movsbl (%rax),%ecx
add    $0xffffffd0,%ecx
xorps  %xmm0,%xmm0
cvtsi2sd %ecx,%xmm0
mulsd  0xd16(%rip),%xmm1
addsd  %xmm0,%xmm1
movsd  %xmm1,0x18(%rsp)
lea    0x1(%rax),%rcx
mov    %rcx,0x8(%rsp)
movsbl 0x1(%rax),%edi
xor    %eax,%eax
call   1030 <is_digit@plt>
movsd  0x18(%rsp),%xmm1
test   %eax,%eax
jne    12d0 <serd_strtod+0x190>
mulsd  0x20(%rsp),%xmm1
movsd  0xce0(%rip),%xmm0
call   1040 <pow@plt>
movsd  0x10(%rsp),%xmm1
mulsd  %xmm0,%xmm1
test   %rbx,%rbx
je     133c <serd_strtod+0x1fc>
mov    0x8(%rsp),%rax
mov    %rax,(%rbx)
xorps  %xmm0,%xmm0
cvtsi2sd %ebp,%xmm0
mulsd  %xmm0,%xmm1
movapd %xmm1,%xmm0
add    $0x28,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define double @serd_strtod(i8* %0, i8** %1) {
%3 = alloca i8*
%4 = alloca i8**
%5 = alloca double
%6 = alloca i8*
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca double
store i8* %0, i8** %3
store i8** %1, i8*** %4
store double 0.000000e+00, double* %5
%11 = load i8*, i8** %3
store i8* %11, i8** %6
br label %12
12: ; preds = %18, %2
%13 = load i8*, i8** %6
%14 = load i8, i8* %13
%15 = sext i8 %14 to i32
%16 = call i32 (i32, ...) bitcast (i32 (...)* @is_space to i32 (i32, ...)*)(i32 %15)
%17 = icmp ne i32 %16, 0
br i1 %17, label %18, label %21
18: ; preds = %12
%19 = load i8*, i8** %6
%20 = getelementptr inbounds i8, i8* %19, i32 1
store i8* %20, i8** %6
br label %12
21: ; preds = %12
%22 = call i32 (i8**, ...) bitcast (i32 (...)* @read_sign to i32 (i8**, ...)*)(i8** %6)
%23 = sitofp i32 %22 to double
store double %23, double* %7
br label %24
24: ; preds = %38, %21
%25 = load i8*, i8** %6
%26 = load i8, i8* %25
%27 = sext i8 %26 to i32
%28 = call i32 (i32, ...) bitcast (i32 (...)* @is_digit to i32 (i32, ...)*)(i32 %27)
%29 = icmp ne i32 %28, 0
br i1 %29, label %30, label %41
30: ; preds = %24
%31 = load double, double* %5
%32 = load i8*, i8** %6
%33 = load i8, i8* %32
%34 = sext i8 %33 to i32
%35 = sub nsw i32 %34, 48
%36 = sitofp i32 %35 to double
%37 = call double @llvm.fmuladd.f64(double %31, double 1.000000e+01, double %36)
store double %37, double* %5
br label %38
38: ; preds = %30
%39 = load i8*, i8** %6
%40 = getelementptr inbounds i8, i8* %39, i32 1
store i8* %40, i8** %6
br label %24
41: ; preds = %24
%42 = load i8*, i8** %6
%43 = load i8, i8* %42
%44 = sext i8 %43 to i32
%45 = icmp eq i32 %44, 46
br i1 %45, label %46, label %71
46: ; preds = %41
store double 1.000000e+01, double* %8
%47 = load i8*, i8** %6
%48 = getelementptr inbounds i8, i8* %47, i32 1
store i8* %48, i8** %6
br label %49
49: ; preds = %67, %46
%50 = load i8*, i8** %6
%51 = load i8, i8* %50
%52 = sext i8 %51 to i32
%53 = call i32 (i32, ...) bitcast (i32 (...)* @is_digit to i32 (i32, ...)*)(i32 %52)
%54 = icmp ne i32 %53, 0
br i1 %54, label %55, label %70
55: ; preds = %49
%56 = load i8*, i8** %6
%57 = load i8, i8* %56
%58 = sext i8 %57 to i32
%59 = sub nsw i32 %58, 48
%60 = sitofp i32 %59 to double
%61 = load double, double* %8
%62 = fdiv double %60, %61
%63 = load double, double* %5
%64 = fadd double %63, %62
store double %64, double* %5
%65 = load double, double* %8
%66 = fmul double %65, 1.000000e+01
store double %66, double* %8
br label %67
67: ; preds = %55
%68 = load i8*, i8** %6
%69 = getelementptr inbounds i8, i8* %68, i32 1
store i8* %69, i8** %6
br label %49
70: ; preds = %49
br label %71
71: ; preds = %70, %41
%72 = load i8*, i8** %6
%73 = load i8, i8* %72
%74 = sext i8 %73 to i32
%75 = icmp eq i32 %74, 101
br i1 %75, label %81, label %76
76: ; preds = %71
%77 = load i8*, i8** %6
%78 = load i8, i8* %77
%79 = sext i8 %78 to i32
%80 = icmp eq i32 %79, 69
br i1 %80, label %81, label %110
81: ; preds = %76, %71
%82 = load i8*, i8** %6
%83 = getelementptr inbounds i8, i8* %82, i32 1
store i8* %83, i8** %6
store double 0.000000e+00, double* %9
%84 = call i32 (i8**, ...) bitcast (i32 (...)* @read_sign to i32 (i8**, ...)*)(i8** %6)
%85 = sitofp i32 %84 to double
store double %85, double* %10
br label %86
86: ; preds = %100, %81
%87 = load i8*, i8** %6
%88 = load i8, i8* %87
%89 = sext i8 %88 to i32
%90 = call i32 (i32, ...) bitcast (i32 (...)* @is_digit to i32 (i32, ...)*)(i32 %89)
%91 = icmp ne i32 %90, 0
br i1 %91, label %92, label %103
92: ; preds = %86
%93 = load double, double* %9
%94 = load i8*, i8** %6
%95 = load i8, i8* %94
%96 = sext i8 %95 to i32
%97 = sub nsw i32 %96, 48
%98 = sitofp i32 %97 to double
%99 = call double @llvm.fmuladd.f64(double %93, double 1.000000e+01, double %98)
store double %99, double* %9
br label %100
100: ; preds = %92
%101 = load i8*, i8** %6
%102 = getelementptr inbounds i8, i8* %101, i32 1
store i8* %102, i8** %6
br label %86
103: ; preds = %86
%104 = load double, double* %9
%105 = load double, double* %10
%106 = fmul double %104, %105
%107 = call double @pow(double 1.000000e+01, double %106)
%108 = load double, double* %5
%109 = fmul double %108, %107
store double %109, double* %5
br label %110
110: ; preds = %103, %76
%111 = load i8**, i8*** %4
%112 = icmp ne i8** %111, null
br i1 %112, label %113, label %116
113: ; preds = %110
%114 = load i8*, i8** %6
%115 = load i8**, i8*** %4
store i8* %114, i8** %115
br label %116
116: ; preds = %113, %110
%117 = load double, double* %5
%118 = load double, double* %7
%119 = fmul double %117, %118
ret double %119
}

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