char MungeHexDigit(char *one_hexdigit) {
  char r = -1;
  char c = *one_hexdigit;
  if (c >= '0' && c <= '9') {
    r = c - '0';
  } else if (c >= 'A' && c <= 'F') {
    r = c - 'A' + 10;
  } else if (c >= 'a' && c <= 'F') {
    r = c - 'a' + 10;
  }
  return r;
}


x86 assembly (clang, -O0):
<MungeHexDigit>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movb   $0xff,-0x9(%rbp)
mov    -0x8(%rbp),%rax
mov    (%rax),%al
mov    %al,-0xa(%rbp)
movsbl -0xa(%rbp),%eax
cmp    $0x30,%eax
jl     113e <MungeHexDigit+0x3e>
movsbl -0xa(%rbp),%eax
cmp    $0x39,%eax
jg     113e <MungeHexDigit+0x3e>
movsbl -0xa(%rbp),%eax
sub    $0x30,%eax
mov    %al,-0x9(%rbp)
jmp    119b <MungeHexDigit+0x9b>
movsbl -0xa(%rbp),%eax
cmp    $0x41,%eax
jl     116a <MungeHexDigit+0x6a>
movsbl -0xa(%rbp),%eax
cmp    $0x46,%eax
jg     116a <MungeHexDigit+0x6a>
movsbl -0xa(%rbp),%eax
sub    $0x41,%eax
add    $0xa,%eax
mov    %al,-0x9(%rbp)
jmp    1196 <MungeHexDigit+0x96>
movsbl -0xa(%rbp),%eax
cmp    $0x61,%eax
jl     1191 <MungeHexDigit+0x91>
movsbl -0xa(%rbp),%eax
cmp    $0x46,%eax
jg     1191 <MungeHexDigit+0x91>
movsbl -0xa(%rbp),%eax
sub    $0x61,%eax
add    $0xa,%eax
mov    %al,-0x9(%rbp)
jmp    1196 <MungeHexDigit+0x96>
jmp    119b <MungeHexDigit+0x9b>
movsbl -0x9(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<MungeHexDigit>:
mov    (%rdi),%al
lea    -0x30(%rax),%ecx
lea    -0x41(%rax),%edx
add    $0xc9,%al
cmp    $0x6,%dl
movzbl %al,%eax
mov    $0xff,%edx
cmovb  %eax,%edx
cmp    $0xa,%cl
movzbl %cl,%eax
cmovae %edx,%eax
ret

LLVM IR (-O0):
define signext i8 @MungeHexDigit(i8* %0) {
%2 = alloca i8*
%3 = alloca i8
%4 = alloca i8
store i8* %0, i8** %2
store i8 -1, i8* %3
%5 = load i8*, i8** %2
%6 = load i8, i8* %5
store i8 %6, i8* %4
%7 = load i8, i8* %4
%8 = sext i8 %7 to i32
%9 = icmp sge i32 %8, 48
br i1 %9, label %10, label %19
10: ; preds = %1
%11 = load i8, i8* %4
%12 = sext i8 %11 to i32
%13 = icmp sle i32 %12, 57
br i1 %13, label %14, label %19
14: ; preds = %10
%15 = load i8, i8* %4
%16 = sext i8 %15 to i32
%17 = sub nsw i32 %16, 48
%18 = trunc i32 %17 to i8
store i8 %18, i8* %3
br label %49
19: ; preds = %10, %1
%20 = load i8, i8* %4
%21 = sext i8 %20 to i32
%22 = icmp sge i32 %21, 65
br i1 %22, label %23, label %33
23: ; preds = %19
%24 = load i8, i8* %4
%25 = sext i8 %24 to i32
%26 = icmp sle i32 %25, 70
br i1 %26, label %27, label %33
27: ; preds = %23
%28 = load i8, i8* %4
%29 = sext i8 %28 to i32
%30 = sub nsw i32 %29, 65
%31 = add nsw i32 %30, 10
%32 = trunc i32 %31 to i8
store i8 %32, i8* %3
br label %48
33: ; preds = %23, %19
%34 = load i8, i8* %4
%35 = sext i8 %34 to i32
%36 = icmp sge i32 %35, 97
br i1 %36, label %37, label %47
37: ; preds = %33
%38 = load i8, i8* %4
%39 = sext i8 %38 to i32
%40 = icmp sle i32 %39, 70
br i1 %40, label %41, label %47
41: ; preds = %37
%42 = load i8, i8* %4
%43 = sext i8 %42 to i32
%44 = sub nsw i32 %43, 97
%45 = add nsw i32 %44, 10
%46 = trunc i32 %45 to i8
store i8 %46, i8* %3
br label %47
47: ; preds = %41, %37, %33
br label %48
48: ; preds = %47, %27
br label %49
49: ; preds = %48, %14
%50 = load i8, i8* %3
ret i8 %50
}

LLVM IR (-O2):
define signext i8 @MungeHexDigit(i8* nocapture %0) {
%2 = load i8, i8* %0
%3 = add i8 %2, -48
%4 = icmp ult i8 %3, 10
%5 = add i8 %2, -65
%6 = icmp ult i8 %5, 6
%7 = add i8 %2, -55
%8 = select i1 %6, i8 %7, i8 -1
%9 = select i1 %4, i8 %3, i8 %8
ret i8 %9
}