int xmlDecodeUri(unsigned char *out, unsigned int olen, const unsigned char *in,
                 unsigned int ilen) {
  int len;
  unsigned char c;
  len = 0;
  for (; ilen--;)
    switch (*in) {
    case '%':
      if (!(in++, ilen--))
        goto err;
      else
        switch (*in) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
          c = *in - '0';
          goto nxtH;
        case 'A':
        case 'B':
        case 'C':
        case 'D':
        case 'E':
        case 'F':
          c = 10 + (*in - 'A');
          goto nxtH;
        case 'a':
        case 'b':
        case 'c':
        case 'd':
        case 'e':
        case 'f':
          c = 10 + (*in - 'a');
        nxtH:
          if (!(in++, ilen--))
            goto err;
          else
            switch (*in) {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
              c *= 16;
              c += *in - '0';
              break;
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
              c *= 16;
              c += 10 + (*in - 'A');
              break;
            case 'a':
            case 'b':
            case 'c':
            case 'd':
            case 'e':
            case 'f':
              c *= 16;
              c += 10 + (*in - 'a');
              break;
            default:
              goto err;
            }
          if (olen > 0) {
            *out++ = c;
            olen--;
          }
          in++, len++;
          break;
        default:
          goto err;
        }
      break;
    default:
      if (olen > 0) {
        *out++ = *in;
        olen--;
      }
      in++, len++;
      break;
    }
  return (len);
err:
  return (-1);
}


x86 assembly (clang, -O0):
<xmlDecodeUri>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %ecx,-0x24(%rbp)
movl   $0x0,-0x28(%rbp)
mov    -0x24(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x24(%rbp)
cmp    $0x0,%eax
je     1351 <xmlDecodeUri+0x251>
mov    -0x20(%rbp),%rax
mov    (%rax),%al
sub    $0x25,%al
jne    130d <xmlDecodeUri+0x20d>
jmp    1140 <xmlDecodeUri+0x40>
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x24(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x24(%rbp)
cmp    $0x0,%eax
jne    1165 <xmlDecodeUri+0x65>
jmp    135c <xmlDecodeUri+0x25c>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
mov    %eax,-0x30(%rbp)
add    $0xffffffd0,%eax
sub    $0xa,%eax
jb     11a8 <xmlDecodeUri+0xa8>
jmp    1180 <xmlDecodeUri+0x80>
mov    -0x30(%rbp),%eax
add    $0xffffffbf,%eax
sub    $0x6,%eax
jb     11ba <xmlDecodeUri+0xba>
jmp    1194 <xmlDecodeUri+0x94>
mov    -0x30(%rbp),%eax
add    $0xffffff9f,%eax
sub    $0x6,%eax
jb     11cf <xmlDecodeUri+0xcf>
jmp    12fe <xmlDecodeUri+0x1fe>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
sub    $0x30,%eax
mov    %al,-0x29(%rbp)
jmp    11df <xmlDecodeUri+0xdf>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
sub    $0x41,%eax
add    $0xa,%eax
mov    %al,-0x29(%rbp)
jmp    11df <xmlDecodeUri+0xdf>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
sub    $0x61,%eax
add    $0xa,%eax
mov    %al,-0x29(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x24(%rbp),%eax
mov    %eax,%ecx
add    $0xffffffff,%ecx
mov    %ecx,-0x24(%rbp)
cmp    $0x0,%eax
jne    1204 <xmlDecodeUri+0x104>
jmp    135c <xmlDecodeUri+0x25c>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
mov    %eax,-0x34(%rbp)
add    $0xffffffd0,%eax
sub    $0xa,%eax
jb     1247 <xmlDecodeUri+0x147>
jmp    121f <xmlDecodeUri+0x11f>
mov    -0x34(%rbp),%eax
add    $0xffffffbf,%eax
sub    $0x6,%eax
jb     1269 <xmlDecodeUri+0x169>
jmp    1233 <xmlDecodeUri+0x133>
mov    -0x34(%rbp),%eax
add    $0xffffff9f,%eax
sub    $0x6,%eax
jb     128e <xmlDecodeUri+0x18e>
jmp    12b3 <xmlDecodeUri+0x1b3>
movzbl -0x29(%rbp),%eax
shl    $0x4,%eax
mov    %al,-0x29(%rbp)
mov    -0x20(%rbp),%rax
movzbl (%rax),%ecx
sub    $0x30,%ecx
movzbl -0x29(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x29(%rbp)
jmp    12b8 <xmlDecodeUri+0x1b8>
movzbl -0x29(%rbp),%eax
shl    $0x4,%eax
mov    %al,-0x29(%rbp)
mov    -0x20(%rbp),%rax
movzbl (%rax),%ecx
sub    $0x41,%ecx
add    $0xa,%ecx
movzbl -0x29(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x29(%rbp)
jmp    12b8 <xmlDecodeUri+0x1b8>
movzbl -0x29(%rbp),%eax
shl    $0x4,%eax
mov    %al,-0x29(%rbp)
mov    -0x20(%rbp),%rax
movzbl (%rax),%ecx
sub    $0x61,%ecx
add    $0xa,%ecx
movzbl -0x29(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x29(%rbp)
jmp    12b8 <xmlDecodeUri+0x1b8>
jmp    135c <xmlDecodeUri+0x25c>
jmp    12bd <xmlDecodeUri+0x1bd>
cmpl   $0x0,-0x14(%rbp)
jbe    12e4 <xmlDecodeUri+0x1e4>
mov    -0x29(%rbp),%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1303 <xmlDecodeUri+0x203>
jmp    135c <xmlDecodeUri+0x25c>
jmp    1308 <xmlDecodeUri+0x208>
jmp    134c <xmlDecodeUri+0x24c>
cmpl   $0x0,-0x14(%rbp)
jbe    1337 <xmlDecodeUri+0x237>
mov    -0x20(%rbp),%rax
mov    (%rax),%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1119 <xmlDecodeUri+0x19>
mov    -0x28(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1363 <xmlDecodeUri+0x263>
movl   $0xffffffff,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<xmlDecodeUri>:
push   %rbp
push   %r15
push   %r14
push   %rbx
test   %ecx,%ecx
je     11e5 <xmlDecodeUri+0xe5>
xor    %r8d,%r8d
movabs $0x7e0000007e03ff,%r9
lea    0xede(%rip),%r10
jmp    115b <xmlDecodeUri+0x5b>
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
mov    $0x1,%eax
test   %esi,%esi
je     11d0 <xmlDecodeUri+0xd0>
mov    %ebx,%ecx
mov    %r11b,(%rdi)
add    $0x1,%rdi
add    $0xffffffff,%esi
add    %rax,%rdx
add    $0x1,%r8d
mov    %r8d,%eax
test   %ecx,%ecx
je     11e7 <xmlDecodeUri+0xe7>
lea    -0x1(%rcx),%ebx
movzbl (%rdx),%r11d
cmp    $0x25,%r11b
jne    1130 <xmlDecodeUri+0x30>
mov    $0xffffffff,%eax
test   %ebx,%ebx
je     11e7 <xmlDecodeUri+0xe7>
movzbl 0x1(%rdx),%r11d
lea    -0x30(%r11),%r15d
cmp    $0x36,%r15b
ja     11e7 <xmlDecodeUri+0xe7>
movzbl %r15b,%ebp
bt     %rbp,%r9
jae    11e7 <xmlDecodeUri+0xe7>
cmp    $0x2,%ecx
je     11e7 <xmlDecodeUri+0xe7>
movzbl 0x2(%rdx),%r14d
lea    -0x30(%r14),%ebp
cmp    $0x36,%bpl
ja     11e7 <xmlDecodeUri+0xe7>
movzbl %bpl,%ebx
bt     %rbx,%r9
jae    11e7 <xmlDecodeUri+0xe7>
add    $0xfffffffd,%ecx
test   %esi,%esi
je     11d9 <xmlDecodeUri+0xd9>
movsbq %r15b,%rax
add    (%rax,%r10,1),%r11b
movsbq %bpl,%rax
shl    $0x4,%r11b
add    (%rax,%r10,1),%r11b
add    %r14b,%r11b
mov    $0x3,%eax
jmp    113f <xmlDecodeUri+0x3f>
xor    %esi,%esi
mov    %ebx,%ecx
jmp    1149 <xmlDecodeUri+0x49>
xor    %esi,%esi
mov    $0x3,%eax
jmp    1149 <xmlDecodeUri+0x49>
xor    %eax,%eax
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32 @xmlDecodeUri(i8* %0, i32 %1, i8* %2, i32 %3) {
%5 = alloca i32
%6 = alloca i8*
%7 = alloca i32
%8 = alloca i8*
%9 = alloca i32
%10 = alloca i32
%11 = alloca i8
store i8* %0, i8** %6
store i32 %1, i32* %7
store i8* %2, i8** %8
store i32 %3, i32* %9
store i32 0, i32* %10
br label %12
12: ; preds = %137, %4
%13 = load i32, i32* %9
%14 = add i32 %13, -1
store i32 %14, i32* %9
%15 = icmp ne i32 %13, 0
br i1 %15, label %16, label %138
16: ; preds = %12
%17 = load i8*, i8** %8
%18 = load i8, i8* %17
%19 = zext i8 %18 to i32
switch i32 %19, label %122 [
i32 37, label %20
]
20: ; preds = %16
%21 = load i8*, i8** %8
%22 = getelementptr inbounds i8, i8* %21, i32 1
store i8* %22, i8** %8
%23 = load i32, i32* %9
%24 = add i32 %23, -1
store i32 %24, i32* %9
%25 = icmp ne i32 %23, 0
br i1 %25, label %27, label %26
26: ; preds = %20
br label %140
27: ; preds = %20
%28 = load i8*, i8** %8
%29 = load i8, i8* %28
%30 = zext i8 %29 to i32
switch i32 %30, label %119 [
i32 48, label %31
i32 49, label %31
i32 50, label %31
i32 51, label %31
i32 52, label %31
i32 53, label %31
i32 54, label %31
i32 55, label %31
i32 56, label %31
i32 57, label %31
i32 65, label %37
i32 66, label %37
i32 67, label %37
i32 68, label %37
i32 69, label %37
i32 70, label %37
i32 97, label %44
i32 98, label %44
i32 99, label %44
i32 100, label %44
i32 101, label %44
i32 102, label %44
]
31: ; preds = %27, %27, %27, %27, %27, %27, %27, %27, %27, %27
%32 = load i8*, i8** %8
%33 = load i8, i8* %32
%34 = zext i8 %33 to i32
%35 = sub nsw i32 %34, 48
%36 = trunc i32 %35 to i8
store i8 %36, i8* %11
br label %51
37: ; preds = %27, %27, %27, %27, %27, %27
%38 = load i8*, i8** %8
%39 = load i8, i8* %38
%40 = zext i8 %39 to i32
%41 = sub nsw i32 %40, 65
%42 = add nsw i32 10, %41
%43 = trunc i32 %42 to i8
store i8 %43, i8* %11
br label %51
44: ; preds = %27, %27, %27, %27, %27, %27
%45 = load i8*, i8** %8
%46 = load i8, i8* %45
%47 = zext i8 %46 to i32
%48 = sub nsw i32 %47, 97
%49 = add nsw i32 10, %48
%50 = trunc i32 %49 to i8
store i8 %50, i8* %11
br label %51
51: ; preds = %44, %37, %31
%52 = load i8*, i8** %8
%53 = getelementptr inbounds i8, i8* %52, i32 1
store i8* %53, i8** %8
%54 = load i32, i32* %9
%55 = add i32 %54, -1
store i32 %55, i32* %9
%56 = icmp ne i32 %54, 0
br i1 %56, label %58, label %57
57: ; preds = %51
br label %140
58: ; preds = %51
%59 = load i8*, i8** %8
%60 = load i8, i8* %59
%61 = zext i8 %60 to i32
switch i32 %61, label %103 [
i32 48, label %62
i32 49, label %62
i32 50, label %62
i32 51, label %62
i32 52, label %62
i32 53, label %62
i32 54, label %62
i32 55, label %62
i32 56, label %62
i32 57, label %62
i32 65, label %75
i32 66, label %75
i32 67, label %75
i32 68, label %75
i32 69, label %75
i32 70, label %75
i32 97, label %89
i32 98, label %89
i32 99, label %89
i32 100, label %89
i32 101, label %89
i32 102, label %89
]
62: ; preds = %58, %58, %58, %58, %58, %58, %58, %58, %58, %58
%63 = load i8, i8* %11
%64 = zext i8 %63 to i32
%65 = mul nsw i32 %64, 16
%66 = trunc i32 %65 to i8
store i8 %66, i8* %11
%67 = load i8*, i8** %8
%68 = load i8, i8* %67
%69 = zext i8 %68 to i32
%70 = sub nsw i32 %69, 48
%71 = load i8, i8* %11
%72 = zext i8 %71 to i32
%73 = add nsw i32 %72, %70
%74 = trunc i32 %73 to i8
store i8 %74, i8* %11
br label %104
75: ; preds = %58, %58, %58, %58, %58, %58
%76 = load i8, i8* %11
%77 = zext i8 %76 to i32
%78 = mul nsw i32 %77, 16
%79 = trunc i32 %78 to i8
store i8 %79, i8* %11
%80 = load i8*, i8** %8
%81 = load i8, i8* %80
%82 = zext i8 %81 to i32
%83 = sub nsw i32 %82, 65
%84 = add nsw i32 10, %83
%85 = load i8, i8* %11
%86 = zext i8 %85 to i32
%87 = add nsw i32 %86, %84
%88 = trunc i32 %87 to i8
store i8 %88, i8* %11
br label %104
89: ; preds = %58, %58, %58, %58, %58, %58
%90 = load i8, i8* %11
%91 = zext i8 %90 to i32
%92 = mul nsw i32 %91, 16
%93 = trunc i32 %92 to i8
store i8 %93, i8* %11
%94 = load i8*, i8** %8
%95 = load i8, i8* %94
%96 = zext i8 %95 to i32
%97 = sub nsw i32 %96, 97
%98 = add nsw i32 10, %97
%99 = load i8, i8* %11
%100 = zext i8 %99 to i32
%101 = add nsw i32 %100, %98
%102 = trunc i32 %101 to i8
store i8 %102, i8* %11
br label %104
103: ; preds = %58
br label %140
104: ; preds = %89, %75, %62
br label %105
105: ; preds = %104
%106 = load i32, i32* %7
%107 = icmp ugt i32 %106, 0
br i1 %107, label %108, label %114
108: ; preds = %105
%109 = load i8, i8* %11
%110 = load i8*, i8** %6
%111 = getelementptr inbounds i8, i8* %110, i32 1
store i8* %111, i8** %6
store i8 %109, i8* %110
%112 = load i32, i32* %7
%113 = add i32 %112, -1
store i32 %113, i32* %7
br label %114
114: ; preds = %108, %105
%115 = load i8*, i8** %8
%116 = getelementptr inbounds i8, i8* %115, i32 1
store i8* %116, i8** %8
%117 = load i32, i32* %10
%118 = add nsw i32 %117, 1
store i32 %118, i32* %10
br label %120
119: ; preds = %27
br label %140
120: ; preds = %114
br label %121
121: ; preds = %120
br label %137
122: ; preds = %16
%123 = load i32, i32* %7
%124 = icmp ugt i32 %123, 0
br i1 %124, label %125, label %132
125: ; preds = %122
%126 = load i8*, i8** %8
%127 = load i8, i8* %126
%128 = load i8*, i8** %6
%129 = getelementptr inbounds i8, i8* %128, i32 1
store i8* %129, i8** %6
store i8 %127, i8* %128
%130 = load i32, i32* %7
%131 = add i32 %130, -1
store i32 %131, i32* %7
br label %132
132: ; preds = %125, %122
%133 = load i8*, i8** %8
%134 = getelementptr inbounds i8, i8* %133, i32 1
store i8* %134, i8** %8
%135 = load i32, i32* %10
%136 = add nsw i32 %135, 1
store i32 %136, i32* %10
br label %137
137: ; preds = %132, %121
br label %12
138: ; preds = %12
%139 = load i32, i32* %10
store i32 %139, i32* %5
br label %141
140: ; preds = %119, %103, %57, %26
store i32 -1, i32* %5
br label %141
141: ; preds = %140, %138
%142 = load i32, i32* %5
ret i32 %142
}

LLVM IR (-O2):
@switch.table.xmlDecodeUri.1 = [55 x i8] c"\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\C9\C9\C9\C9\C9\C9\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\D0\A9\A9\A9\A9\A9\A9"
define i32 @xmlDecodeUri(i8* nocapture writeonly %0, i32 %1, i8* nocapture %2, i32 %3) {
%5 = icmp eq i32 %3, 0
br i1 %5, label %69, label %6
6: ; preds = %4, %61
%7 = phi i32 [ %67, %61 ], [ 0, %4 ]
%8 = phi i32 [ %65, %61 ], [ %3, %4 ]
%9 = phi i8* [ %66, %61 ], [ %2, %4 ]
%10 = phi i32 [ %64, %61 ], [ %1, %4 ]
%11 = phi i8* [ %63, %61 ], [ %0, %4 ]
%12 = add i32 %8, -1
%13 = load i8, i8* %9
%14 = icmp eq i8 %13, 37
br i1 %14, label %15, label %53
15: ; preds = %6
%16 = icmp eq i32 %12, 0
br i1 %16, label %69, label %17
17: ; preds = %15
%18 = getelementptr inbounds i8, i8* %9, i64 1
%19 = load i8, i8* %18
%20 = add i8 %19, -48
%21 = icmp ult i8 %20, 55
br i1 %21, label %22, label %69
22: ; preds = %17
%23 = zext i8 %20 to i64
%24 = lshr i64 35465847073801215, %23
%25 = and i64 %24, 1
%26 = icmp eq i64 %25, 0
br i1 %26, label %69, label %27
27: ; preds = %22
%28 = sext i8 %20 to i64
%29 = getelementptr inbounds [55 x i8], [55 x i8]* @switch.table.xmlDecodeUri.1, i64 0, i64 %28
%30 = load i8, i8* %29
%31 = add nsw i8 %19, %30
%32 = add i32 %8, -3
%33 = icmp eq i32 %8, 2
br i1 %33, label %69, label %34
34: ; preds = %27
%35 = getelementptr inbounds i8, i8* %9, i64 2
%36 = load i8, i8* %35
%37 = add i8 %36, -48
%38 = icmp ult i8 %37, 55
br i1 %38, label %39, label %69
39: ; preds = %34
%40 = zext i8 %37 to i64
%41 = lshr i64 35465847073801215, %40
%42 = and i64 %41, 1
%43 = icmp eq i64 %42, 0
br i1 %43, label %69, label %44
44: ; preds = %39
%45 = icmp eq i32 %10, 0
br i1 %45, label %61, label %46
46: ; preds = %44
%47 = sext i8 %37 to i64
%48 = getelementptr inbounds [55 x i8], [55 x i8]* @switch.table.xmlDecodeUri.1, i64 0, i64 %47
%49 = load i8, i8* %48
%50 = shl nuw i8 %31, 4
%51 = add i8 %50, %49
%52 = add i8 %51, %36
br label %55
53: ; preds = %6
%54 = icmp eq i32 %10, 0
br i1 %54, label %61, label %55
55: ; preds = %53, %46
%56 = phi i8 [ %52, %46 ], [ %13, %53 ]
%57 = phi i64 [ 3, %46 ], [ 1, %53 ]
%58 = phi i32 [ %32, %46 ], [ %12, %53 ]
%59 = getelementptr inbounds i8, i8* %11, i64 1
store i8 %56, i8* %11
%60 = add i32 %10, -1
br label %61
61: ; preds = %55, %53, %44
%62 = phi i64 [ 3, %44 ], [ 1, %53 ], [ %57, %55 ]
%63 = phi i8* [ %11, %44 ], [ %11, %53 ], [ %59, %55 ]
%64 = phi i32 [ 0, %44 ], [ 0, %53 ], [ %60, %55 ]
%65 = phi i32 [ %32, %44 ], [ %12, %53 ], [ %58, %55 ]
%66 = getelementptr inbounds i8, i8* %9, i64 %62
%67 = add nuw nsw i32 %7, 1
%68 = icmp eq i32 %65, 0
br i1 %68, label %69, label %6
69: ; preds = %61, %27, %15, %17, %22, %34, %39, %4
%70 = phi i32 [ 0, %4 ], [ -1, %39 ], [ -1, %22 ], [ -1, %15 ], [ -1, %27 ], [ -1, %34 ], [ -1, %17 ], [ %67, %61 ]
ret i32 %70
}