#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
void cvthex(const unsigned char *bin, size_t len, char *hex) {
  size_t i;
  unsigned int j;
  for (i = 0; i < len; ++i) {
    j = (bin[i] >> 4) & 0x0f;
    hex[i * 2] = j <= 9 ? (j + '0') : (j + 'a' - 10);
    j = bin[i] & 0x0f;
    hex[i * 2 + 1] = j <= 9 ? (j + '0') : (j + 'a' - 10);
  }
  hex[len * 2] = '\0';
}


x86 assembly (clang, -O0):
<cvthex>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movq   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%rax
cmp    -0x10(%rbp),%rax
jae    11cf <cvthex+0xcf>
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
sar    $0x4,%eax
and    $0xf,%eax
mov    %eax,-0x24(%rbp)
cmpl   $0x9,-0x24(%rbp)
ja     1153 <cvthex+0x53>
mov    -0x24(%rbp),%eax
add    $0x30,%eax
mov    %eax,-0x28(%rbp)
jmp    115f <cvthex+0x5f>
mov    -0x24(%rbp),%eax
add    $0x61,%eax
sub    $0xa,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%rcx
shl    $0x1,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
mov    -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
and    $0xf,%eax
mov    %eax,-0x24(%rbp)
cmpl   $0x9,-0x24(%rbp)
ja     119d <cvthex+0x9d>
mov    -0x24(%rbp),%eax
add    $0x30,%eax
mov    %eax,-0x2c(%rbp)
jmp    11a9 <cvthex+0xa9>
mov    -0x24(%rbp),%eax
add    $0x61,%eax
sub    $0xa,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
mov    -0x20(%rbp),%rcx
shl    $0x1,%rcx
mov    %dl,0x1(%rax,%rcx,1)
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    1118 <cvthex+0x18>
mov    -0x18(%rbp),%rax
mov    -0x10(%rbp),%rcx
shl    $0x1,%rcx
movb   $0x0,(%rax,%rcx,1)
pop    %rbp
ret

x86 assembly (clang, -O2):
<cvthex>:
test   %rsi,%rsi
je     1279 <cvthex+0x179>
cmp    $0x8,%rsi
jae    1117 <cvthex+0x17>
xor    %r10d,%r10d
jmp    1230 <cvthex+0x130>
lea    -0x1(%rsi),%rcx
add    %rcx,%rcx
setb   %r8b
lea    (%rdx,%rcx,1),%r9
xor    %r10d,%r10d
cmp    %rdx,%r9
jb     1230 <cvthex+0x130>
test   %r8b,%r8b
jne    1230 <cvthex+0x130>
lea    0x1(%rdx),%r9
add    %rdx,%rcx
add    $0x1,%rcx
cmp    %r9,%rcx
jb     1230 <cvthex+0x130>
test   %r8b,%r8b
jne    1230 <cvthex+0x130>
lea    (%rdi,%rsi,1),%rax
cmp    %rdx,%rax
jbe    1172 <cvthex+0x72>
lea    (%rdx,%rsi,2),%rax
cmp    %rdi,%rax
jbe    1172 <cvthex+0x72>
xor    %r10d,%r10d
jmp    1230 <cvthex+0x130>
mov    %rsi,%r10
and    $0xfffffffffffffff8,%r10
xor    %ecx,%ecx
movdqa 0xe7c(%rip),%xmm8
movdqa 0xe83(%rip),%xmm9
movdqa 0xe8b(%rip),%xmm2
movdqa 0xe93(%rip),%xmm3
movdqa 0xe9b(%rip),%xmm4
movdqa 0xea3(%rip),%xmm5
nopl   (%rax)
movq   (%rdi,%rcx,1),%xmm6
movdqa %xmm6,%xmm7
psrlw  $0x4,%xmm7
pand   %xmm8,%xmm7
movdqa %xmm6,%xmm0
pmaxub %xmm9,%xmm0
pcmpeqb %xmm6,%xmm0
movdqa %xmm7,%xmm1
por    %xmm2,%xmm1
paddb  %xmm3,%xmm7
pand   %xmm0,%xmm7
pandn  %xmm1,%xmm0
por    %xmm7,%xmm0
pand   %xmm4,%xmm6
movdqa %xmm6,%xmm1
pmaxub %xmm5,%xmm1
pcmpeqb %xmm6,%xmm1
movdqa %xmm6,%xmm7
por    %xmm2,%xmm7
paddb  %xmm3,%xmm6
pand   %xmm1,%xmm6
pandn  %xmm7,%xmm1
por    %xmm6,%xmm1
punpcklbw %xmm1,%xmm0
movdqu %xmm0,(%rdx,%rcx,2)
add    $0x8,%rcx
cmp    %rcx,%r10
jne    11b0 <cvthex+0xb0>
cmp    %rsi,%r10
je     1279 <cvthex+0x179>
nopw   0x0(%rax,%rax,1)
movzbl (%rdi,%r10,1),%ecx
mov    %ecx,%eax
shr    $0x4,%al
lea    0x30(%rax),%r8d
add    $0x57,%al
cmp    $0xa0,%cl
movzbl %r8b,%ecx
movzbl %al,%eax
cmovb  %ecx,%eax
mov    %al,(%rdx,%r10,2)
movzbl (%rdi,%r10,1),%eax
and    $0xf,%al
lea    0x30(%rax),%r8d
lea    0x57(%rax),%ecx
cmp    $0xa,%al
movzbl %r8b,%eax
movzbl %cl,%ecx
cmovb  %eax,%ecx
mov    %cl,0x1(%rdx,%r10,2)
add    $0x1,%r10
cmp    %r10,%rsi
jne    1230 <cvthex+0x130>
movb   $0x0,(%rdx,%rsi,2)
ret

LLVM IR (-O0):
define void @cvthex(i8* %0, i64 %1, i8* %2) {
%4 = alloca i8*
%5 = alloca i64
%6 = alloca i8*
%7 = alloca i64
%8 = alloca i32
store i8* %0, i8** %4
store i64 %1, i64* %5
store i8* %2, i8** %6
store i64 0, i64* %7
br label %9
9: ; preds = %60, %3
%10 = load i64, i64* %7
%11 = load i64, i64* %5
%12 = icmp ult i64 %10, %11
br i1 %12, label %13, label %63
13: ; preds = %9
%14 = load i8*, i8** %4
%15 = load i64, i64* %7
%16 = getelementptr inbounds i8, i8* %14, i64 %15
%17 = load i8, i8* %16
%18 = zext i8 %17 to i32
%19 = ashr i32 %18, 4
%20 = and i32 %19, 15
store i32 %20, i32* %8
%21 = load i32, i32* %8
%22 = icmp ule i32 %21, 9
br i1 %22, label %23, label %26
23: ; preds = %13
%24 = load i32, i32* %8
%25 = add i32 %24, 48
br label %30
26: ; preds = %13
%27 = load i32, i32* %8
%28 = add i32 %27, 97
%29 = sub i32 %28, 10
br label %30
30: ; preds = %26, %23
%31 = phi i32 [ %25, %23 ], [ %29, %26 ]
%32 = trunc i32 %31 to i8
%33 = load i8*, i8** %6
%34 = load i64, i64* %7
%35 = mul i64 %34, 2
%36 = getelementptr inbounds i8, i8* %33, i64 %35
store i8 %32, i8* %36
%37 = load i8*, i8** %4
%38 = load i64, i64* %7
%39 = getelementptr inbounds i8, i8* %37, i64 %38
%40 = load i8, i8* %39
%41 = zext i8 %40 to i32
%42 = and i32 %41, 15
store i32 %42, i32* %8
%43 = load i32, i32* %8
%44 = icmp ule i32 %43, 9
br i1 %44, label %45, label %48
45: ; preds = %30
%46 = load i32, i32* %8
%47 = add i32 %46, 48
br label %52
48: ; preds = %30
%49 = load i32, i32* %8
%50 = add i32 %49, 97
%51 = sub i32 %50, 10
br label %52
52: ; preds = %48, %45
%53 = phi i32 [ %47, %45 ], [ %51, %48 ]
%54 = trunc i32 %53 to i8
%55 = load i8*, i8** %6
%56 = load i64, i64* %7
%57 = mul i64 %56, 2
%58 = add i64 %57, 1
%59 = getelementptr inbounds i8, i8* %55, i64 %58
store i8 %54, i8* %59
br label %60
60: ; preds = %52
%61 = load i64, i64* %7
%62 = add i64 %61, 1
store i64 %62, i64* %7
br label %9
63: ; preds = %9
%64 = load i8*, i8** %6
%65 = load i64, i64* %5
%66 = mul i64 %65, 2
%67 = getelementptr inbounds i8, i8* %64, i64 %66
store i8 0, i8* %67
ret void
}

LLVM IR (-O2):
define void @cvthex(i8* nocapture %0, i64 %1, i8* nocapture writeonly %2) {
%4 = icmp eq i64 %1, 0
br i1 %4, label %82, label %5
5: ; preds = %3
%6 = icmp ult i64 %1, 8
br i1 %6, label %59, label %7
7: ; preds = %5
%8 = add i64 %1, -1
%9 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %8, i64 2)
%10 = extractvalue { i64, i1 } %9, 0
%11 = extractvalue { i64, i1 } %9, 1
%12 = getelementptr i8, i8* %2, i64 %10
%13 = icmp ult i8* %12, %2
%14 = or i1 %13, %11
%15 = getelementptr i8, i8* %2, i64 1
%16 = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %8, i64 2)
%17 = extractvalue { i64, i1 } %16, 0
%18 = extractvalue { i64, i1 } %16, 1
%19 = getelementptr i8, i8* %15, i64 %17
%20 = icmp ult i8* %19, %15
%21 = or i1 %20, %18
%22 = or i1 %14, %21
br i1 %22, label %59, label %23
23: ; preds = %7
%24 = shl i64 %1, 1
%25 = getelementptr i8, i8* %2, i64 %24
%26 = getelementptr i8, i8* %0, i64 %1
%27 = icmp ugt i8* %26, %2
%28 = icmp ugt i8* %25, %0
%29 = and i1 %27, %28
br i1 %29, label %59, label %30
30: ; preds = %23
%31 = and i64 %1, -8
%32 = getelementptr inbounds i8, i8* %2, i64 -1
br label %33
33: ; preds = %33, %30
%34 = phi i64 [ 0, %30 ], [ %55, %33 ]
%35 = getelementptr inbounds i8, i8* %0, i64 %34
%36 = bitcast i8* %35 to <8 x i8>*
%37 = load <8 x i8>, <8 x i8>* %36
%38 = lshr <8 x i8> %37, <i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4>
%39 = icmp ult <8 x i8> %37, <i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96, i8 -96>
%40 = or <8 x i8> %38, <i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48>
%41 = add nuw nsw <8 x i8> %38, <i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87>
%42 = select <8 x i1> %39, <8 x i8> %40, <8 x i8> %41
%43 = shl i64 %34, 1
%44 = bitcast i8* %35 to <8 x i8>*
%45 = load <8 x i8>, <8 x i8>* %44
%46 = and <8 x i8> %45, <i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15>
%47 = icmp ult <8 x i8> %46, <i8 10, i8 10, i8 10, i8 10, i8 10, i8 10, i8 10, i8 10>
%48 = or <8 x i8> %46, <i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48, i8 48>
%49 = add nuw nsw <8 x i8> %46, <i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87, i8 87>
%50 = select <8 x i1> %47, <8 x i8> %48, <8 x i8> %49
%51 = or i64 %43, 1
%52 = getelementptr inbounds i8, i8* %32, i64 %51
%53 = bitcast i8* %52 to <16 x i8>*
%54 = shufflevector <8 x i8> %42, <8 x i8> %50, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %54, <16 x i8>* %53
%55 = add nuw i64 %34, 8
%56 = icmp eq i64 %55, %31
br i1 %56, label %57, label %33
57: ; preds = %33
%58 = icmp eq i64 %31, %1
br i1 %58, label %82, label %59
59: ; preds = %23, %7, %5, %57
%60 = phi i64 [ 0, %23 ], [ 0, %7 ], [ 0, %5 ], [ %31, %57 ]
br label %61
61: ; preds = %59, %61
%62 = phi i64 [ %80, %61 ], [ %60, %59 ]
%63 = getelementptr inbounds i8, i8* %0, i64 %62
%64 = load i8, i8* %63
%65 = lshr i8 %64, 4
%66 = icmp ult i8 %64, -96
%67 = or i8 %65, 48
%68 = add nuw nsw i8 %65, 87
%69 = select i1 %66, i8 %67, i8 %68
%70 = shl i64 %62, 1
%71 = getelementptr inbounds i8, i8* %2, i64 %70
store i8 %69, i8* %71
%72 = load i8, i8* %63
%73 = and i8 %72, 15
%74 = icmp ult i8 %73, 10
%75 = or i8 %73, 48
%76 = add nuw nsw i8 %73, 87
%77 = select i1 %74, i8 %75, i8 %76
%78 = or i64 %70, 1
%79 = getelementptr inbounds i8, i8* %2, i64 %78
store i8 %77, i8* %79
%80 = add nuw i64 %62, 1
%81 = icmp eq i64 %80, %1
br i1 %81, label %82, label %61
82: ; preds = %61, %57, %3
%83 = shl i64 %1, 1
%84 = getelementptr inbounds i8, i8* %2, i64 %83
store i8 0, i8* %84
ret void
}