#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 rhash_byte_to_hex(char *dst, const unsigned char *src, size_t length,
                       int upper_case) {
  const char hex_add = (upper_case ? 'A' - 10 : 'a' - 10);
  for (; length > 0; src++, length--) {
    const unsigned char hi = (*src >> 4) & 15;
    const unsigned char lo = *src & 15;
    *dst++ = (hi > 9 ? hi + hex_add : hi + '0');
    *dst++ = (lo > 9 ? lo + hex_add : lo + '0');
  }
  *dst = '\0';
}


x86 assembly (clang, -O0):
<rhash_byte_to_hex>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
mov    -0x1c(%rbp),%edx
mov    $0x57,%eax
mov    $0x37,%ecx
cmp    $0x0,%edx
cmovne %ecx,%eax
mov    %al,-0x1d(%rbp)
cmpq   $0x0,-0x18(%rbp)
jbe    11ec <rhash_byte_to_hex+0xec>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
sar    $0x4,%eax
and    $0xf,%eax
mov    %al,-0x1e(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
and    $0xf,%eax
mov    %al,-0x1f(%rbp)
movzbl -0x1e(%rbp),%eax
cmp    $0x9,%eax
jle    1170 <rhash_byte_to_hex+0x70>
movzbl -0x1e(%rbp),%eax
movsbl -0x1d(%rbp),%ecx
add    %ecx,%eax
mov    %eax,-0x24(%rbp)
jmp    117a <rhash_byte_to_hex+0x7a>
movzbl -0x1e(%rbp),%eax
add    $0x30,%eax
mov    %eax,-0x24(%rbp)
mov    -0x24(%rbp),%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
movzbl -0x1f(%rbp),%eax
cmp    $0x9,%eax
jle    11af <rhash_byte_to_hex+0xaf>
movzbl -0x1f(%rbp),%eax
movsbl -0x1d(%rbp),%ecx
add    %ecx,%eax
mov    %eax,-0x28(%rbp)
jmp    11b9 <rhash_byte_to_hex+0xb9>
movzbl -0x1f(%rbp),%eax
add    $0x30,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
mov    %al,%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
mov    -0x10(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x10(%rbp)
mov    -0x18(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x18(%rbp)
jmp    1129 <rhash_byte_to_hex+0x29>
mov    -0x8(%rbp),%rax
movb   $0x0,(%rax)
pop    %rbp
ret

x86 assembly (clang, -O2):
<rhash_byte_to_hex>:
push   %rbx
test   %ecx,%ecx
sete   %r11b
test   %rdx,%rdx
je     1191 <rhash_byte_to_hex+0x91>
shl    $0x5,%r11b
add    $0x37,%r11b
cmp    $0x8,%rdx
jb     1130 <rhash_byte_to_hex+0x30>
lea    (%rsi,%rdx,1),%rax
cmp    %rdi,%rax
jbe    1199 <rhash_byte_to_hex+0x99>
lea    (%rdi,%rdx,2),%rax
cmp    %rsi,%rax
jbe    1199 <rhash_byte_to_hex+0x99>
mov    %rdi,%rbx
mov    %rsi,%r8
mov    %rdx,%r9
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
movzbl (%r8,%rax,1),%edx
mov    %edx,%esi
shr    $0x4,%sil
mov    %edx,%edi
and    $0xf,%dil
lea    (%rsi,%r11,1),%ecx
or     $0x30,%sil
cmp    $0xa0,%dl
movzbl %cl,%ecx
movzbl %sil,%edx
cmovae %ecx,%edx
mov    %dl,(%rbx)
lea    (%rdi,%r11,1),%ecx
lea    0x30(%rdi),%edx
cmp    $0xa,%dil
movzbl %cl,%ecx
movzbl %dl,%edx
cmovae %ecx,%edx
mov    %dl,0x1(%rbx)
add    $0x2,%rbx
add    $0x1,%rax
cmp    %rax,%r9
jne    1140 <rhash_byte_to_hex+0x40>
jmp    126b <rhash_byte_to_hex+0x16b>
mov    %rdi,%rbx
jmp    126b <rhash_byte_to_hex+0x16b>
mov    %rdx,%r10
and    $0xfffffffffffffff8,%r10
lea    (%rdi,%r10,2),%rbx
lea    (%rsi,%r10,1),%r8
mov    %edx,%r9d
and    $0x7,%r9d
movzbl %r11b,%eax
movd   %eax,%xmm0
punpcklbw %xmm0,%xmm0
pshuflw $0x0,%xmm0,%xmm0
xor    %eax,%eax
movdqa 0xe35(%rip),%xmm8
movdqa 0xe3c(%rip),%xmm9
movdqa 0xe44(%rip),%xmm3
movdqa 0xe4c(%rip),%xmm4
movdqa 0xe54(%rip),%xmm5
nopl   0x0(%rax)
movq   (%rsi,%rax,1),%xmm1
movdqa %xmm1,%xmm7
movdqa %xmm1,%xmm6
pminub %xmm3,%xmm6
pcmpeqb %xmm1,%xmm6
psrlw  $0x4,%xmm1
pand   %xmm8,%xmm1
pand   %xmm9,%xmm7
movdqa %xmm1,%xmm2
paddb  %xmm0,%xmm2
por    %xmm4,%xmm1
pand   %xmm6,%xmm1
pandn  %xmm2,%xmm6
por    %xmm1,%xmm6
movdqa %xmm7,%xmm1
pminub %xmm5,%xmm1
pcmpeqb %xmm7,%xmm1
movdqa %xmm7,%xmm2
paddb  %xmm0,%xmm2
por    %xmm4,%xmm7
pand   %xmm1,%xmm7
pandn  %xmm2,%xmm1
por    %xmm7,%xmm1
punpcklbw %xmm1,%xmm6
movdqu %xmm6,(%rdi,%rax,2)
add    $0x8,%rax
cmp    %rax,%r10
jne    11f0 <rhash_byte_to_hex+0xf0>
cmp    %rdx,%r10
jne    1139 <rhash_byte_to_hex+0x39>
movb   $0x0,(%rbx)
pop    %rbx
ret

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

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