int atoi(char *s) {
  int rv = 0;
  char sign = 0;
  while (*s) {
    if (*s <= '9' && *s >= '0')
      break;
    if (*s == '-' || *s == '+')
      break;
    s++;
  }
  if (*s == '-')
    sign = 1;
  if (*s == '-' || *s == '+')
    s++;
  while (*s && *s >= '0' && *s <= '9') {
    rv = (rv * 10) + (*s - '0');
    s++;
  }
  if (sign)
    return (-rv);
  else
    return (rv);
}


x86 assembly (clang, -O0):
<atoi>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
movb   $0x0,-0x15(%rbp)
mov    -0x10(%rbp),%rax
cmpb   $0x0,(%rax)
je     117b <atoi+0x7b>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x39,%eax
jg     1145 <atoi+0x45>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x30,%eax
jl     1145 <atoi+0x45>
jmp    117b <atoi+0x7b>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2d,%eax
je     1165 <atoi+0x65>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2b,%eax
jne    116a <atoi+0x6a>
jmp    117b <atoi+0x7b>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
jmp    1113 <atoi+0x13>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2d,%eax
jne    118f <atoi+0x8f>
movb   $0x1,-0x15(%rbp)
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2d,%eax
je     11af <atoi+0xaf>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x2b,%eax
jne    11bb <atoi+0xbb>
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
jmp    11c0 <atoi+0xc0>
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0x0,%ecx
mov    %al,-0x16(%rbp)
je     11fa <atoi+0xfa>
mov    -0x10(%rbp),%rax
movsbl (%rax),%ecx
xor    %eax,%eax
cmp    $0x30,%ecx
mov    %al,-0x16(%rbp)
jl     11fa <atoi+0xfa>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x39,%eax
setle  %al
mov    %al,-0x16(%rbp)
mov    -0x16(%rbp),%al
test   $0x1,%al
jne    120a <atoi+0x10a>
jmp    122e <atoi+0x12e>
imul   $0xa,-0x14(%rbp),%eax
mov    -0x10(%rbp),%rcx
movsbl (%rcx),%ecx
sub    $0x30,%ecx
add    %ecx,%eax
mov    %eax,-0x14(%rbp)
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
jmp    11c0 <atoi+0xc0>
cmpb   $0x0,-0x15(%rbp)
je     1245 <atoi+0x145>
xor    %eax,%eax
sub    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    124b <atoi+0x14b>
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<atoi>:
mov    (%rdi),%cl
xor    %eax,%eax
test   %cl,%cl
je     112d <atoi+0x2d>
add    $0x1,%rdi
nopl   0x0(%rax)
lea    -0x30(%rcx),%edx
cmp    $0xa,%dl
jb     112e <atoi+0x2e>
cmp    $0x2b,%cl
je     112e <atoi+0x2e>
cmp    $0x2d,%cl
je     112e <atoi+0x2e>
movzbl (%rdi),%ecx
add    $0x1,%rdi
test   %cl,%cl
jne    1110 <atoi+0x10>
ret
cmp    $0x2b,%cl
je     1138 <atoi+0x38>
cmp    $0x2d,%cl
jne    113c <atoi+0x3c>
mov    (%rdi),%al
jmp    1142 <atoi+0x42>
add    $0xffffffffffffffff,%rdi
mov    %ecx,%eax
lea    -0x30(%rax),%esi
xor    %edx,%edx
cmp    $0x9,%sil
ja     117c <atoi+0x7c>
add    $0x1,%rdi
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzbl %al,%eax
lea    (%rdx,%rdx,4),%edx
lea    (%rax,%rdx,2),%edx
add    $0xffffffd0,%edx
movzbl (%rdi),%eax
lea    -0x30(%rax),%esi
add    $0x1,%rdi
cmp    $0xa,%sil
jb     1160 <atoi+0x60>
mov    %edx,%eax
neg    %eax
cmp    $0x2d,%cl
cmovne %edx,%eax
ret

LLVM IR (-O0):
define i32 @atoi(i8* %0) {
%2 = alloca i32
%3 = alloca i8*
%4 = alloca i32
%5 = alloca i8
store i8* %0, i8** %3
store i32 0, i32* %4
store i8 0, i8* %5
br label %6
6: ; preds = %32, %1
%7 = load i8*, i8** %3
%8 = load i8, i8* %7
%9 = icmp ne i8 %8, 0
br i1 %9, label %10, label %35
10: ; preds = %6
%11 = load i8*, i8** %3
%12 = load i8, i8* %11
%13 = sext i8 %12 to i32
%14 = icmp sle i32 %13, 57
br i1 %14, label %15, label %21
15: ; preds = %10
%16 = load i8*, i8** %3
%17 = load i8, i8* %16
%18 = sext i8 %17 to i32
%19 = icmp sge i32 %18, 48
br i1 %19, label %20, label %21
20: ; preds = %15
br label %35
21: ; preds = %15, %10
%22 = load i8*, i8** %3
%23 = load i8, i8* %22
%24 = sext i8 %23 to i32
%25 = icmp eq i32 %24, 45
br i1 %25, label %31, label %26
26: ; preds = %21
%27 = load i8*, i8** %3
%28 = load i8, i8* %27
%29 = sext i8 %28 to i32
%30 = icmp eq i32 %29, 43
br i1 %30, label %31, label %32
31: ; preds = %26, %21
br label %35
32: ; preds = %26
%33 = load i8*, i8** %3
%34 = getelementptr inbounds i8, i8* %33, i32 1
store i8* %34, i8** %3
br label %6
35: ; preds = %31, %20, %6
%36 = load i8*, i8** %3
%37 = load i8, i8* %36
%38 = sext i8 %37 to i32
%39 = icmp eq i32 %38, 45
br i1 %39, label %40, label %41
40: ; preds = %35
store i8 1, i8* %5
br label %41
41: ; preds = %40, %35
%42 = load i8*, i8** %3
%43 = load i8, i8* %42
%44 = sext i8 %43 to i32
%45 = icmp eq i32 %44, 45
br i1 %45, label %51, label %46
46: ; preds = %41
%47 = load i8*, i8** %3
%48 = load i8, i8* %47
%49 = sext i8 %48 to i32
%50 = icmp eq i32 %49, 43
br i1 %50, label %51, label %54
51: ; preds = %46, %41
%52 = load i8*, i8** %3
%53 = getelementptr inbounds i8, i8* %52, i32 1
store i8* %53, i8** %3
br label %54
54: ; preds = %51, %46
br label %55
55: ; preds = %72, %54
%56 = load i8*, i8** %3
%57 = load i8, i8* %56
%58 = sext i8 %57 to i32
%59 = icmp ne i32 %58, 0
br i1 %59, label %60, label %70
60: ; preds = %55
%61 = load i8*, i8** %3
%62 = load i8, i8* %61
%63 = sext i8 %62 to i32
%64 = icmp sge i32 %63, 48
br i1 %64, label %65, label %70
65: ; preds = %60
%66 = load i8*, i8** %3
%67 = load i8, i8* %66
%68 = sext i8 %67 to i32
%69 = icmp sle i32 %68, 57
br label %70
70: ; preds = %65, %60, %55
%71 = phi i1 [ false, %60 ], [ false, %55 ], [ %69, %65 ]
br i1 %71, label %72, label %82
72: ; preds = %70
%73 = load i32, i32* %4
%74 = mul nsw i32 %73, 10
%75 = load i8*, i8** %3
%76 = load i8, i8* %75
%77 = sext i8 %76 to i32
%78 = sub nsw i32 %77, 48
%79 = add nsw i32 %74, %78
store i32 %79, i32* %4
%80 = load i8*, i8** %3
%81 = getelementptr inbounds i8, i8* %80, i32 1
store i8* %81, i8** %3
br label %55
82: ; preds = %70
%83 = load i8, i8* %5
%84 = icmp ne i8 %83, 0
br i1 %84, label %85, label %88
85: ; preds = %82
%86 = load i32, i32* %4
%87 = sub nsw i32 0, %86
store i32 %87, i32* %2
br label %90
88: ; preds = %82
%89 = load i32, i32* %4
store i32 %89, i32* %2
br label %90
90: ; preds = %88, %85
%91 = load i32, i32* %2
ret i32 %91
}

LLVM IR (-O2):
define i32 @atoi(i8* nocapture %0) {
%2 = load i8, i8* %0
%3 = icmp eq i8 %2, 0
br i1 %3, label %40, label %4
4: ; preds = %1, %10
%5 = phi i8 [ %12, %10 ], [ %2, %1 ]
%6 = phi i8* [ %11, %10 ], [ %0, %1 ]
%7 = add i8 %5, -48
%8 = icmp ult i8 %7, 10
br i1 %8, label %14, label %9
9: ; preds = %4
switch i8 %5, label %10 [
i8 45, label %14
i8 43, label %14
]
10: ; preds = %9
%11 = getelementptr inbounds i8, i8* %6, i64 1
%12 = load i8, i8* %11
%13 = icmp eq i8 %12, 0
br i1 %13, label %40, label %4
14: ; preds = %9, %9, %4
%15 = icmp eq i8 %5, 45
switch i8 %5, label %19 [
i8 45, label %16
i8 43, label %16
]
16: ; preds = %14, %14
%17 = getelementptr inbounds i8, i8* %6, i64 1
%18 = load i8, i8* %17
br label %19
19: ; preds = %14, %16
%20 = phi i8 [ %18, %16 ], [ %5, %14 ]
%21 = phi i8* [ %17, %16 ], [ %6, %14 ]
%22 = add i8 %20, -48
%23 = icmp ult i8 %22, 10
br i1 %23, label %24, label %36
24: ; preds = %19, %24
%25 = phi i8 [ %33, %24 ], [ %20, %19 ]
%26 = phi i32 [ %31, %24 ], [ 0, %19 ]
%27 = phi i8* [ %32, %24 ], [ %21, %19 ]
%28 = zext i8 %25 to i32
%29 = mul nsw i32 %26, 10
%30 = add i32 %29, -48
%31 = add i32 %30, %28
%32 = getelementptr inbounds i8, i8* %27, i64 1
%33 = load i8, i8* %32
%34 = add i8 %33, -48
%35 = icmp ult i8 %34, 10
br i1 %35, label %24, label %36
36: ; preds = %24, %19
%37 = phi i32 [ 0, %19 ], [ %31, %24 ]
%38 = sub nsw i32 0, %37
%39 = select i1 %15, i32 %38, i32 %37
br label %40
40: ; preds = %10, %36, %1
%41 = phi i32 [ 0, %1 ], [ %39, %36 ], [ 0, %10 ]
ret i32 %41
}