unsigned char atox(char *buf) {
  unsigned char sixteens, ones, value;
  if (buf[2] > 47 && buf[2] < 58) {
    sixteens = (buf[2] - 48) * 16;
  } else if (buf[2] > 64 && buf[2] < 71) {
    sixteens = (buf[2] - 55) * 16;
  }
  if (buf[3] > 47 && buf[3] < 58) {
    ones = (buf[3] - 48);
  } else if (buf[3] > 64 && buf[3] < 71) {
    ones = (buf[3] - 55);
  }
  value = sixteens + ones;
  return value;
}


x86 assembly (clang, -O0):
<atox>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rax
movsbl 0x2(%rax),%eax
cmp    $0x2f,%eax
jle    1140 <atox+0x40>
mov    -0x8(%rbp),%rax
movsbl 0x2(%rax),%eax
cmp    $0x3a,%eax
jge    1140 <atox+0x40>
mov    -0x8(%rbp),%rax
movsbl 0x2(%rax),%eax
sub    $0x30,%eax
shl    $0x4,%eax
mov    %al,-0x9(%rbp)
jmp    1178 <atox+0x78>
mov    -0x8(%rbp),%rax
movsbl 0x2(%rax),%eax
cmp    $0x40,%eax
jle    1173 <atox+0x73>
mov    -0x8(%rbp),%rax
movsbl 0x2(%rax),%eax
cmp    $0x47,%eax
jge    1173 <atox+0x73>
mov    -0x8(%rbp),%rax
movsbl 0x2(%rax),%eax
sub    $0x37,%eax
shl    $0x4,%eax
mov    %al,-0x9(%rbp)
jmp    1178 <atox+0x78>
mov    -0x8(%rbp),%rax
movsbl 0x3(%rax),%eax
cmp    $0x2f,%eax
jle    11ad <atox+0xad>
mov    -0x8(%rbp),%rax
movsbl 0x3(%rax),%eax
cmp    $0x3a,%eax
jge    11ad <atox+0xad>
mov    -0x8(%rbp),%rax
movsbl 0x3(%rax),%eax
sub    $0x30,%eax
mov    %al,-0xa(%rbp)
jmp    11e2 <atox+0xe2>
mov    -0x8(%rbp),%rax
movsbl 0x3(%rax),%eax
cmp    $0x40,%eax
jle    11dd <atox+0xdd>
mov    -0x8(%rbp),%rax
movsbl 0x3(%rax),%eax
cmp    $0x47,%eax
jge    11dd <atox+0xdd>
mov    -0x8(%rbp),%rax
movsbl 0x3(%rax),%eax
sub    $0x37,%eax
mov    %al,-0xa(%rbp)
jmp    11e2 <atox+0xe2>
movzbl -0x9(%rbp),%eax
movzbl -0xa(%rbp),%ecx
add    %ecx,%eax
mov    %al,-0xb(%rbp)
movzbl -0xb(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<atox>:
mov    0x2(%rdi),%al
lea    -0x30(%rax),%ecx
cmp    $0x9,%cl
ja     1110 <atox+0x10>
shl    $0x4,%al
jmp    1121 <atox+0x21>
lea    -0x41(%rax),%ecx
cmp    $0x5,%cl
ja     111f <atox+0x1f>
shl    $0x4,%al
add    $0x90,%al
jmp    1121 <atox+0x21>
xor    %eax,%eax
mov    0x3(%rdi),%cl
lea    -0x30(%rcx),%edx
lea    -0x41(%rcx),%esi
add    $0xc9,%cl
xor    %edi,%edi
cmp    $0x6,%sil
movzbl %cl,%ecx
cmovae %edi,%ecx
cmp    $0xa,%dl
movzbl %dl,%edx
cmovae %ecx,%edx
and    $0xf0,%al
add    %dl,%al
ret

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

LLVM IR (-O2):
define zeroext i8 @atox(i8* nocapture %0) {
%2 = getelementptr inbounds i8, i8* %0, i64 2
%3 = load i8, i8* %2
%4 = add i8 %3, -48
%5 = icmp ult i8 %4, 10
br i1 %5, label %6, label %8
6: ; preds = %1
%7 = shl i8 %3, 4
br label %14
8: ; preds = %1
%9 = add i8 %3, -65
%10 = icmp ult i8 %9, 6
br i1 %10, label %11, label %14
11: ; preds = %8
%12 = shl i8 %3, 4
%13 = add nuw nsw i8 %12, -112
br label %14
14: ; preds = %8, %11, %6
%15 = phi i8 [ %7, %6 ], [ %13, %11 ], [ 0, %8 ]
%16 = getelementptr inbounds i8, i8* %0, i64 3
%17 = load i8, i8* %16
%18 = add i8 %17, -48
%19 = icmp ult i8 %18, 10
%20 = add i8 %17, -65
%21 = icmp ult i8 %20, 6
%22 = add i8 %17, -55
%23 = select i1 %21, i8 %22, i8 0
%24 = select i1 %19, i8 %18, i8 %23
%25 = and i8 %15, -16
%26 = add nuw i8 %24, %25
ret i8 %26
}