void hexstuff(char *dest, int value, int len) {
  int i;
  for (i = 0; i < len; i++) {
    char c;
    int h = (value >> 4 * i) & 0xF;
    c = h < 10 ? h + '0' : h - 10 + 'a';
    dest[len - i - 1] = c;
  }
}


x86 assembly (clang, -O0):
<hexstuff>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
mov    -0x14(%rbp),%eax
cmp    -0x10(%rbp),%eax
jge    1180 <hexstuff+0x80>
mov    -0xc(%rbp),%eax
mov    -0x14(%rbp),%ecx
shl    $0x2,%ecx
sar    %cl,%eax
and    $0xf,%eax
mov    %eax,-0x1c(%rbp)
cmpl   $0xa,-0x1c(%rbp)
jge    114a <hexstuff+0x4a>
mov    -0x1c(%rbp),%eax
add    $0x30,%eax
mov    %eax,-0x20(%rbp)
jmp    1156 <hexstuff+0x56>
mov    -0x1c(%rbp),%eax
sub    $0xa,%eax
add    $0x61,%eax
mov    %eax,-0x20(%rbp)
mov    -0x20(%rbp),%eax
mov    %al,-0x15(%rbp)
mov    -0x15(%rbp),%dl
mov    -0x8(%rbp),%rax
mov    -0x10(%rbp),%ecx
sub    -0x14(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    1115 <hexstuff+0x15>
pop    %rbp
ret

x86 assembly (clang, -O2):
<hexstuff>:
test   %edx,%edx
jle    149a <hexstuff+0x39a>
mov    %edx,%r8d
cmp    $0x10,%edx
jae    1118 <hexstuff+0x18>
xor    %r10d,%r10d
jmp    13f3 <hexstuff+0x2f3>
lea    -0x1(%r8),%r9
lea    -0x1(%rdx),%ecx
mov    %ecx,%eax
sub    %r9d,%eax
xor    %r10d,%r10d
cmp    %ecx,%eax
jg     13f3 <hexstuff+0x2f3>
shr    $0x20,%r9
jne    13f3 <hexstuff+0x2f3>
mov    %r8d,%r10d
and    $0xfffffff0,%r10d
movd   %esi,%xmm0
pshufd $0x0,%xmm0,%xmm9
movdqa 0xead(%rip),%xmm14
movdqa 0xeb4(%rip),%xmm15
movdqa 0xebb(%rip),%xmm10
movdqa 0xec2(%rip),%xmm11
movdqa 0xed9(%rip),%xmm12
movdqa 0xf00(%rip),%xmm13
mov    %r10,%r9
movdqa 0xed5(%rip),%xmm4
nopl   0x0(%rax,%rax,1)
movdqa %xmm15,%xmm2
pslld  $0x2,%xmm2
movdqa %xmm14,%xmm1
pslld  $0x2,%xmm1
movdqa %xmm11,%xmm6
pslld  $0x2,%xmm6
movdqa %xmm10,%xmm5
pslld  $0x2,%xmm5
pshuflw $0xfe,%xmm5,%xmm0
movdqa %xmm9,%xmm7
psrad  %xmm0,%xmm7
pshuflw $0x54,%xmm5,%xmm8
movdqa %xmm9,%xmm0
psrad  %xmm8,%xmm0
punpcklqdq %xmm7,%xmm0
pshufd $0xee,%xmm5,%xmm5
pshuflw $0xfe,%xmm5,%xmm7
movdqa %xmm9,%xmm3
psrad  %xmm7,%xmm3
pshuflw $0x54,%xmm5,%xmm5
movdqa %xmm9,%xmm7
psrad  %xmm5,%xmm7
punpckhqdq %xmm3,%xmm7
shufps $0xcc,%xmm7,%xmm0
pshuflw $0xfe,%xmm6,%xmm3
movdqa %xmm9,%xmm7
psrad  %xmm3,%xmm7
pshuflw $0x54,%xmm6,%xmm3
movdqa %xmm9,%xmm5
psrad  %xmm3,%xmm5
punpcklqdq %xmm7,%xmm5
pshufd $0xee,%xmm6,%xmm3
pshuflw $0xfe,%xmm3,%xmm6
movdqa %xmm9,%xmm7
psrad  %xmm6,%xmm7
pshuflw $0x54,%xmm3,%xmm3
movdqa %xmm9,%xmm6
psrad  %xmm3,%xmm6
punpckhqdq %xmm7,%xmm6
shufps $0xcc,%xmm6,%xmm5
pshuflw $0xfe,%xmm1,%xmm3
movdqa %xmm9,%xmm7
psrad  %xmm3,%xmm7
pshuflw $0x54,%xmm1,%xmm3
movdqa %xmm9,%xmm6
psrad  %xmm3,%xmm6
punpcklqdq %xmm7,%xmm6
pshufd $0xee,%xmm1,%xmm1
pshuflw $0xfe,%xmm1,%xmm3
movdqa %xmm9,%xmm7
psrad  %xmm3,%xmm7
pshuflw $0x54,%xmm1,%xmm1
movdqa %xmm9,%xmm3
psrad  %xmm1,%xmm3
punpckhqdq %xmm7,%xmm3
shufps $0xcc,%xmm3,%xmm6
pshuflw $0xfe,%xmm2,%xmm1
movdqa %xmm9,%xmm3
psrad  %xmm1,%xmm3
pshuflw $0x54,%xmm2,%xmm7
movdqa %xmm9,%xmm1
psrad  %xmm7,%xmm1
punpcklqdq %xmm3,%xmm1
pshufd $0xee,%xmm2,%xmm2
pshuflw $0xfe,%xmm2,%xmm3
movdqa %xmm9,%xmm7
psrad  %xmm3,%xmm7
pshuflw $0x54,%xmm2,%xmm2
movdqa %xmm9,%xmm3
psrad  %xmm2,%xmm3
punpckhqdq %xmm7,%xmm3
shufps $0xcc,%xmm3,%xmm1
movaps 0xd5a(%rip),%xmm8
andps  %xmm8,%xmm1
andps  %xmm8,%xmm6
movdqa %xmm12,%xmm2
pcmpgtd %xmm1,%xmm2
movdqa %xmm1,%xmm3
por    %xmm4,%xmm3
movdqa 0xd69(%rip),%xmm7
paddd  %xmm7,%xmm1
pand   %xmm2,%xmm3
pandn  %xmm1,%xmm2
movdqa %xmm12,%xmm1
pcmpgtd %xmm6,%xmm1
por    %xmm3,%xmm2
movdqa %xmm6,%xmm3
por    %xmm4,%xmm3
paddd  %xmm7,%xmm6
pand   %xmm1,%xmm3
pandn  %xmm6,%xmm1
andps  %xmm8,%xmm5
andps  %xmm8,%xmm0
por    %xmm3,%xmm1
movdqa %xmm12,%xmm3
pcmpgtd %xmm5,%xmm3
packuswb %xmm1,%xmm2
movdqa %xmm5,%xmm1
por    %xmm4,%xmm1
paddd  %xmm7,%xmm5
pand   %xmm3,%xmm1
pandn  %xmm5,%xmm3
movdqa %xmm12,%xmm5
pcmpgtd %xmm0,%xmm5
por    %xmm1,%xmm3
movdqa %xmm0,%xmm1
por    %xmm4,%xmm1
paddd  %xmm7,%xmm0
pand   %xmm5,%xmm1
pandn  %xmm0,%xmm5
por    %xmm1,%xmm5
packuswb %xmm5,%xmm3
packuswb %xmm2,%xmm3
movdqa %xmm3,%xmm0
pxor   %xmm1,%xmm1
punpcklbw %xmm1,%xmm0
pshufd $0x4e,%xmm0,%xmm0
pshuflw $0x1b,%xmm0,%xmm0
pshufhw $0x1b,%xmm0,%xmm0
punpckhbw %xmm1,%xmm3
pshufd $0x4e,%xmm3,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm0,%xmm1
movslq %ecx,%rcx
movdqu %xmm1,-0xf(%rdi,%rcx,1)
paddd  %xmm13,%xmm11
paddd  %xmm13,%xmm10
paddd  %xmm13,%xmm15
paddd  %xmm13,%xmm14
add    $0xfffffff0,%ecx
add    $0xfffffffffffffff0,%r9
jne    1190 <hexstuff+0x90>
cmp    %r8,%r10
je     149a <hexstuff+0x39a>
mov    %r10,%rax
not    %rax
test   $0x1,%r8b
je     142d <hexstuff+0x32d>
mov    %esi,%ecx
and    $0xf,%ecx
lea    0x57(%rcx),%r9d
lea    0x30(%rcx),%r11d
cmp    $0xa,%ecx
movzbl %r11b,%r11d
movzbl %r9b,%r9d
cmovb  %r11d,%r9d
mov    %r10d,%ecx
not    %ecx
add    %edx,%ecx
movslq %ecx,%rcx
mov    %r9b,(%rdi,%rcx,1)
or     $0x1,%r10
add    %r8,%rax
je     149a <hexstuff+0x39a>
sub    %r10,%r8
mov    %r10d,%eax
not    %eax
add    %edx,%eax
shl    $0x2,%r10d
mov    %esi,%edx
mov    %r10d,%ecx
sar    %cl,%edx
and    $0xf,%edx
lea    0x57(%rdx),%r9d
lea    0x30(%rdx),%ecx
cmp    $0xa,%edx
movzbl %cl,%ecx
movzbl %r9b,%r9d
cmovb  %ecx,%r9d
lea    0x4(%r10),%ecx
mov    %esi,%edx
sar    %cl,%edx
cltq
mov    %r9b,(%rdi,%rax,1)
and    $0xf,%edx
lea    0x57(%rdx),%r9d
lea    0x30(%rdx),%ecx
cmp    $0xa,%edx
movzbl %cl,%ecx
movzbl %r9b,%edx
cmovb  %ecx,%edx
lea    -0x1(%rax),%ecx
movslq %ecx,%rcx
mov    %dl,(%rdi,%rcx,1)
add    $0xfffffffe,%eax
add    $0x8,%r10d
add    $0xfffffffffffffffe,%r8
jne    1440 <hexstuff+0x340>
ret

LLVM IR (-O0):
define void @hexstuff(i8* %0, i32 %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i8
%9 = alloca i32
store i8* %0, i8** %4
store i32 %1, i32* %5
store i32 %2, i32* %6
store i32 0, i32* %7
br label %10
10: ; preds = %40, %3
%11 = load i32, i32* %7
%12 = load i32, i32* %6
%13 = icmp slt i32 %11, %12
br i1 %13, label %14, label %43
14: ; preds = %10
%15 = load i32, i32* %5
%16 = load i32, i32* %7
%17 = mul nsw i32 4, %16
%18 = ashr i32 %15, %17
%19 = and i32 %18, 15
store i32 %19, i32* %9
%20 = load i32, i32* %9
%21 = icmp slt i32 %20, 10
br i1 %21, label %22, label %25
22: ; preds = %14
%23 = load i32, i32* %9
%24 = add nsw i32 %23, 48
br label %29
25: ; preds = %14
%26 = load i32, i32* %9
%27 = sub nsw i32 %26, 10
%28 = add nsw i32 %27, 97
br label %29
29: ; preds = %25, %22
%30 = phi i32 [ %24, %22 ], [ %28, %25 ]
%31 = trunc i32 %30 to i8
store i8 %31, i8* %8
%32 = load i8, i8* %8
%33 = load i8*, i8** %4
%34 = load i32, i32* %6
%35 = load i32, i32* %7
%36 = sub nsw i32 %34, %35
%37 = sub nsw i32 %36, 1
%38 = sext i32 %37 to i64
%39 = getelementptr inbounds i8, i8* %33, i64 %38
store i8 %32, i8* %39
br label %40
40: ; preds = %29
%41 = load i32, i32* %7
%42 = add nsw i32 %41, 1
store i32 %42, i32* %7
br label %10
43: ; preds = %10
ret void
}

LLVM IR (-O2):
define void @hexstuff(i8* nocapture writeonly %0, i32 %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %99
5: ; preds = %3
%6 = zext i32 %2 to i64
%7 = icmp ult i32 %2, 16
br i1 %7, label %44, label %8
8: ; preds = %5
%9 = add nsw i64 %6, -1
%10 = add i32 %2, -1
%11 = trunc i64 %9 to i32
%12 = sub i32 %10, %11
%13 = icmp sgt i32 %12, %10
%14 = icmp ugt i64 %9, 4294967295
%15 = or i1 %13, %14
br i1 %15, label %44, label %16
16: ; preds = %8
%17 = and i64 %6, 4294967280
%18 = insertelement <16 x i32> poison, i32 %1, i64 0
%19 = shufflevector <16 x i32> %18, <16 x i32> poison, <16 x i32> zeroinitializer
%20 = getelementptr inbounds i8, i8* %0, i64 -15
br label %21
21: ; preds = %21, %16
%22 = phi i64 [ 0, %16 ], [ %39, %21 ]
%23 = phi <16 x i32> [ <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>, %16 ], [ %40, %21 ]
%24 = trunc i64 %22 to i32
%25 = shl nsw <16 x i32> %23, <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
%26 = ashr <16 x i32> %19, %25
%27 = and <16 x i32> %26, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
%28 = icmp ult <16 x i32> %27, <i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10, i32 10>
%29 = or <16 x i32> %27, <i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48, i32 48>
%30 = add nuw nsw <16 x i32> %27, <i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87, i32 87>
%31 = select <16 x i1> %28, <16 x i32> %29, <16 x i32> %30
%32 = trunc <16 x i32> %31 to <16 x i8>
%33 = xor i32 %24, -1
%34 = add i32 %33, %2
%35 = sext i32 %34 to i64
%36 = shufflevector <16 x i8> %32, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%37 = getelementptr inbounds i8, i8* %20, i64 %35
%38 = bitcast i8* %37 to <16 x i8>*
store <16 x i8> %36, <16 x i8>* %38
%39 = add nuw i64 %22, 16
%40 = add <16 x i32> %23, <i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16, i32 16>
%41 = icmp eq i64 %39, %17
br i1 %41, label %42, label %21
42: ; preds = %21
%43 = icmp eq i64 %17, %6
br i1 %43, label %99, label %44
44: ; preds = %8, %5, %42
%45 = phi i64 [ 0, %8 ], [ 0, %5 ], [ %17, %42 ]
%46 = xor i64 %45, -1
%47 = and i64 %6, 1
%48 = icmp eq i64 %47, 0
br i1 %48, label %62, label %49
49: ; preds = %44
%50 = and i32 %1, 15
%51 = icmp ult i32 %50, 10
%52 = or i32 %50, 48
%53 = add nuw nsw i32 %50, 87
%54 = select i1 %51, i32 %52, i32 %53
%55 = trunc i32 %54 to i8
%56 = trunc i64 %45 to i32
%57 = xor i32 %56, -1
%58 = add i32 %57, %2
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds i8, i8* %0, i64 %59
store i8 %55, i8* %60
%61 = or i64 %45, 1
br label %62
62: ; preds = %49, %44
%63 = phi i64 [ %45, %44 ], [ %61, %49 ]
%64 = sub nsw i64 0, %6
%65 = icmp eq i64 %46, %64
br i1 %65, label %99, label %66
66: ; preds = %62, %66
%67 = phi i64 [ %97, %66 ], [ %63, %62 ]
%68 = trunc i64 %67 to i32
%69 = shl nsw i32 %68, 2
%70 = ashr i32 %1, %69
%71 = and i32 %70, 15
%72 = icmp ult i32 %71, 10
%73 = or i32 %71, 48
%74 = add nuw nsw i32 %71, 87
%75 = select i1 %72, i32 %73, i32 %74
%76 = trunc i32 %75 to i8
%77 = trunc i64 %67 to i32
%78 = xor i32 %77, -1
%79 = add i32 %78, %2
%80 = sext i32 %79 to i64
%81 = getelementptr inbounds i8, i8* %0, i64 %80
store i8 %76, i8* %81
%82 = add nuw nsw i64 %67, 1
%83 = trunc i64 %82 to i32
%84 = shl nsw i32 %83, 2
%85 = ashr i32 %1, %84
%86 = and i32 %85, 15
%87 = icmp ult i32 %86, 10
%88 = or i32 %86, 48
%89 = add nuw nsw i32 %86, 87
%90 = select i1 %87, i32 %88, i32 %89
%91 = trunc i32 %90 to i8
%92 = trunc i64 %82 to i32
%93 = xor i32 %92, -1
%94 = add i32 %93, %2
%95 = sext i32 %94 to i64
%96 = getelementptr inbounds i8, i8* %0, i64 %95
store i8 %91, i8* %96
%97 = add nuw nsw i64 %67, 2
%98 = icmp eq i64 %97, %6
br i1 %98, label %99, label %66
99: ; preds = %62, %66, %42, %3
ret void
}