char *_xtoa(unsigned long long v, char *string, int r, int is_neg) {
  char *start = string;
  char buf[33], *p;
  p = buf;
  do {
    *p++ = "0123456789abcdef"[(v % r) & 0xf];
  } while (v /= r);
  if (is_neg) {
    *p++ = '-';
  }
  do {
    *string++ = *--p;
  } while (buf != p);
  *string = '\0';
  return start;
}


x86 assembly (clang, -O0):
<_xtoa>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x20(%rbp)
lea    -0x50(%rbp),%rax
mov    %rax,-0x58(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
xor    %edx,%edx
div    %rcx
and    $0xf,%rdx
lea    0xec6(%rip),%rax
mov    (%rax,%rdx,1),%cl
mov    -0x58(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x58(%rbp)
mov    %cl,(%rax)
movslq -0x14(%rbp),%rcx
mov    -0x8(%rbp),%rax
xor    %edx,%edx
div    %rcx
mov    %rax,-0x8(%rbp)
cmp    $0x0,%rax
jne    1122 <_xtoa+0x22>
cmpl   $0x0,-0x18(%rbp)
je     1185 <_xtoa+0x85>
mov    -0x58(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x58(%rbp)
movb   $0x2d,(%rax)
jmp    118a <_xtoa+0x8a>
mov    -0x58(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x58(%rbp)
mov    -0x1(%rax),%cl
mov    -0x10(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x10(%rbp)
mov    %cl,(%rax)
lea    -0x50(%rbp),%rax
cmp    -0x58(%rbp),%rax
jne    118a <_xtoa+0x8a>
mov    -0x10(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x20(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<_xtoa>:
mov    %edx,%r8d
mov    %rsi,%r9
lea    -0x28(%rsp),%rsi
movslq %edx,%r10
lea    0xeeb(%rip),%r11
jmp    113e <_xtoa+0x3e>
nopw   0x0(%rax,%rax,1)
mov    %rdi,%rax
xor    %edx,%edx
div    %r10
and    $0xf,%edx
movzbl (%rdx,%r11,1),%edx
mov    %dl,(%rsi)
add    $0x1,%rsi
cmp    %r10,%rdi
mov    %rax,%rdi
jb     1153 <_xtoa+0x53>
mov    %rdi,%rax
or     %r10,%rax
shr    $0x20,%rax
jne    1120 <_xtoa+0x20>
mov    %edi,%eax
xor    %edx,%edx
div    %r8d
jmp    1128 <_xtoa+0x28>
test   %ecx,%ecx
je     115e <_xtoa+0x5e>
movb   $0x2d,(%rsi)
add    $0x1,%rsi
lea    -0x28(%rsp),%r8
mov    %rsi,%r10
sub    %r8,%r10
cmp    $0x20,%r10
jb     1185 <_xtoa+0x85>
cmp    %r9,%rsi
jbe    1209 <_xtoa+0x109>
lea    (%r9,%r10,1),%rax
cmp    %rax,%r8
jae    1209 <_xtoa+0x109>
mov    %r9,%rcx
mov    %rsi,%rdx
mov    %r8,%rdi
not    %rdi
add    %rdx,%rdi
mov    %rdx,%rsi
and    $0x7,%rsi
je     11b4 <_xtoa+0xb4>
nopl   (%rax)
movzbl -0x1(%rdx),%eax
add    $0xffffffffffffffff,%rdx
mov    %al,(%rcx)
add    $0x1,%rcx
add    $0xffffffffffffffff,%rsi
jne    11a0 <_xtoa+0xa0>
cmp    $0x7,%rdi
jb     12b8 <_xtoa+0x1b8>
xchg   %ax,%ax
movzbl -0x1(%rdx),%eax
mov    %al,(%rcx)
movzbl -0x2(%rdx),%eax
mov    %al,0x1(%rcx)
movzbl -0x3(%rdx),%eax
mov    %al,0x2(%rcx)
movzbl -0x4(%rdx),%eax
mov    %al,0x3(%rcx)
movzbl -0x5(%rdx),%eax
mov    %al,0x4(%rcx)
movzbl -0x6(%rdx),%eax
mov    %al,0x5(%rcx)
movzbl -0x7(%rdx),%eax
mov    %al,0x6(%rcx)
movzbl -0x8(%rdx),%eax
add    $0xfffffffffffffff8,%rdx
mov    %al,0x7(%rcx)
add    $0x8,%rcx
cmp    %r8,%rdx
jne    11c0 <_xtoa+0xc0>
jmp    12b8 <_xtoa+0x1b8>
mov    %r10,%rdi
and    $0xffffffffffffffe0,%rdi
lea    (%r9,%rdi,1),%rcx
mov    %rsi,%rdx
sub    %rdi,%rdx
add    $0xfffffffffffffff0,%rsi
xor    %eax,%eax
pxor   %xmm0,%xmm0
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movdqu -0x10(%rsi),%xmm1
movdqu (%rsi),%xmm2
movdqa %xmm2,%xmm3
punpcklbw %xmm0,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
punpckhbw %xmm0,%xmm2
pshufd $0x4e,%xmm2,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
pshufhw $0x1b,%xmm2,%xmm2
packuswb %xmm3,%xmm2
movdqa %xmm1,%xmm3
punpcklbw %xmm0,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
punpckhbw %xmm0,%xmm1
pshufd $0x4e,%xmm1,%xmm1
pshuflw $0x1b,%xmm1,%xmm1
pshufhw $0x1b,%xmm1,%xmm1
packuswb %xmm3,%xmm1
movdqu %xmm2,(%r9,%rax,1)
movdqu %xmm1,0x10(%r9,%rax,1)
add    $0x20,%rax
add    $0xffffffffffffffe0,%rsi
cmp    %rax,%rdi
jne    1230 <_xtoa+0x130>
cmp    %rdi,%r10
jne    118b <_xtoa+0x8b>
movb   $0x0,(%rcx)
mov    %r9,%rax
ret

LLVM IR (-O0):
@.str = [17 x i8] c"0123456789abcdef\00"
define i8* @_xtoa(i64 %0, i8* %1, i32 %2, i32 %3) {
%5 = alloca i64
%6 = alloca i8*
%7 = alloca i32
%8 = alloca i32
%9 = alloca i8*
%10 = alloca [33 x i8]
%11 = alloca i8*
store i64 %0, i64* %5
store i8* %1, i8** %6
store i32 %2, i32* %7
store i32 %3, i32* %8
%12 = load i8*, i8** %6
store i8* %12, i8** %9
%13 = getelementptr inbounds [33 x i8], [33 x i8]* %10, i64 0, i64 0
store i8* %13, i8** %11
br label %14
14: ; preds = %24, %4
%15 = load i64, i64* %5
%16 = load i32, i32* %7
%17 = sext i32 %16 to i64
%18 = urem i64 %15, %17
%19 = and i64 %18, 15
%20 = getelementptr inbounds [17 x i8], [17 x i8]* @.str, i64 0, i64 %19
%21 = load i8, i8* %20
%22 = load i8*, i8** %11
%23 = getelementptr inbounds i8, i8* %22, i32 1
store i8* %23, i8** %11
store i8 %21, i8* %22
br label %24
24: ; preds = %14
%25 = load i32, i32* %7
%26 = sext i32 %25 to i64
%27 = load i64, i64* %5
%28 = udiv i64 %27, %26
store i64 %28, i64* %5
%29 = icmp ne i64 %28, 0
br i1 %29, label %14, label %30
30: ; preds = %24
%31 = load i32, i32* %8
%32 = icmp ne i32 %31, 0
br i1 %32, label %33, label %36
33: ; preds = %30
%34 = load i8*, i8** %11
%35 = getelementptr inbounds i8, i8* %34, i32 1
store i8* %35, i8** %11
store i8 45, i8* %34
br label %36
36: ; preds = %33, %30
br label %37
37: ; preds = %43, %36
%38 = load i8*, i8** %11
%39 = getelementptr inbounds i8, i8* %38, i32 -1
store i8* %39, i8** %11
%40 = load i8, i8* %39
%41 = load i8*, i8** %6
%42 = getelementptr inbounds i8, i8* %41, i32 1
store i8* %42, i8** %6
store i8 %40, i8* %41
br label %43
43: ; preds = %37
%44 = getelementptr inbounds [33 x i8], [33 x i8]* %10, i64 0, i64 0
%45 = load i8*, i8** %11
%46 = icmp ne i8* %44, %45
br i1 %46, label %37, label %47
47: ; preds = %43
%48 = load i8*, i8** %6
store i8 0, i8* %48
%49 = load i8*, i8** %9
ret i8* %49
}

LLVM IR (-O2):
@.str = [17 x i8] c"0123456789abcdef\00"
define i8* @_xtoa(i64 %0, i8* returned writeonly %1, i32 %2, i32 %3) {
%5 = alloca [33 x i8]
%6 = ptrtoint [33 x i8]* %5 to i64
%7 = getelementptr inbounds [33 x i8], [33 x i8]* %5, i64 0, i64 0
%8 = sext i32 %2 to i64
br label %9
9: ; preds = %9, %4
%10 = phi i64 [ %0, %4 ], [ %17, %9 ]
%11 = phi i8* [ %7, %4 ], [ %16, %9 ]
%12 = urem i64 %10, %8
%13 = and i64 %12, 15
%14 = getelementptr inbounds [17 x i8], [17 x i8]* @.str, i64 0, i64 %13
%15 = load i8, i8* %14
%16 = getelementptr inbounds i8, i8* %11, i64 1
store i8 %15, i8* %11
%17 = udiv i64 %10, %8
%18 = icmp ult i64 %10, %8
br i1 %18, label %19, label %9
19: ; preds = %9
%20 = icmp eq i32 %3, 0
br i1 %20, label %23, label %21
21: ; preds = %19
%22 = getelementptr inbounds i8, i8* %11, i64 2
store i8 45, i8* %16
br label %23
23: ; preds = %21, %19
%24 = phi i8* [ %22, %21 ], [ %16, %19 ]
%25 = ptrtoint i8* %24 to i64
%26 = sub i64 %25, %6
%27 = icmp ult i64 %26, 32
br i1 %27, label %63, label %28
28: ; preds = %23
%29 = sub i64 %25, %6
%30 = getelementptr i8, i8* %1, i64 %29
%31 = sub i64 %6, %25
%32 = getelementptr i8, i8* %24, i64 %31
%33 = icmp ugt i8* %24, %1
%34 = icmp ult i8* %32, %30
%35 = and i1 %33, %34
br i1 %35, label %63, label %36
36: ; preds = %28
%37 = and i64 %26, -32
%38 = getelementptr i8, i8* %1, i64 %37
%39 = sub i64 0, %37
%40 = getelementptr i8, i8* %24, i64 %39
%41 = getelementptr i8, i8* %24, i64 -1
br label %42
42: ; preds = %42, %36
%43 = phi i64 [ 0, %36 ], [ %59, %42 ]
%44 = getelementptr i8, i8* %1, i64 %43
%45 = sub i64 0, %43
%46 = getelementptr inbounds i8, i8* %41, i64 %45
%47 = getelementptr inbounds i8, i8* %46, i64 -15
%48 = bitcast i8* %47 to <16 x i8>*
%49 = load <16 x i8>, <16 x i8>* %48
%50 = shufflevector <16 x i8> %49, <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>
%51 = getelementptr inbounds i8, i8* %46, i64 -16
%52 = getelementptr inbounds i8, i8* %51, i64 -15
%53 = bitcast i8* %52 to <16 x i8>*
%54 = load <16 x i8>, <16 x i8>* %53
%55 = shufflevector <16 x i8> %54, <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>
%56 = bitcast i8* %44 to <16 x i8>*
store <16 x i8> %50, <16 x i8>* %56
%57 = getelementptr i8, i8* %44, i64 16
%58 = bitcast i8* %57 to <16 x i8>*
store <16 x i8> %55, <16 x i8>* %58
%59 = add nuw i64 %43, 32
%60 = icmp eq i64 %59, %37
br i1 %60, label %61, label %42
61: ; preds = %42
%62 = icmp eq i64 %26, %37
br i1 %62, label %113, label %63
63: ; preds = %28, %23, %61
%64 = phi i8* [ %1, %28 ], [ %1, %23 ], [ %38, %61 ]
%65 = phi i8* [ %24, %28 ], [ %24, %23 ], [ %40, %61 ]
%66 = ptrtoint i8* %65 to i64
%67 = xor i64 %6, -1
%68 = add i64 %67, %66
%69 = and i64 %66, 7
%70 = icmp eq i64 %69, 0
br i1 %70, label %80, label %71
71: ; preds = %63, %71
%72 = phi i8* [ %77, %71 ], [ %64, %63 ]
%73 = phi i8* [ %75, %71 ], [ %65, %63 ]
%74 = phi i64 [ %78, %71 ], [ 0, %63 ]
%75 = getelementptr inbounds i8, i8* %73, i64 -1
%76 = load i8, i8* %75
%77 = getelementptr inbounds i8, i8* %72, i64 1
store i8 %76, i8* %72
%78 = add i64 %74, 1
%79 = icmp eq i64 %78, %69
br i1 %79, label %80, label %71
80: ; preds = %71, %63
%81 = phi i8* [ undef, %63 ], [ %77, %71 ]
%82 = phi i8* [ %64, %63 ], [ %77, %71 ]
%83 = phi i8* [ %65, %63 ], [ %75, %71 ]
%84 = icmp ult i64 %68, 7
br i1 %84, label %113, label %85
85: ; preds = %80, %85
%86 = phi i8* [ %111, %85 ], [ %82, %80 ]
%87 = phi i8* [ %109, %85 ], [ %83, %80 ]
%88 = getelementptr inbounds i8, i8* %87, i64 -1
%89 = load i8, i8* %88
%90 = getelementptr inbounds i8, i8* %86, i64 1
store i8 %89, i8* %86
%91 = getelementptr inbounds i8, i8* %87, i64 -2
%92 = load i8, i8* %91
%93 = getelementptr inbounds i8, i8* %86, i64 2
store i8 %92, i8* %90
%94 = getelementptr inbounds i8, i8* %87, i64 -3
%95 = load i8, i8* %94
%96 = getelementptr inbounds i8, i8* %86, i64 3
store i8 %95, i8* %93
%97 = getelementptr inbounds i8, i8* %87, i64 -4
%98 = load i8, i8* %97
%99 = getelementptr inbounds i8, i8* %86, i64 4
store i8 %98, i8* %96
%100 = getelementptr inbounds i8, i8* %87, i64 -5
%101 = load i8, i8* %100
%102 = getelementptr inbounds i8, i8* %86, i64 5
store i8 %101, i8* %99
%103 = getelementptr inbounds i8, i8* %87, i64 -6
%104 = load i8, i8* %103
%105 = getelementptr inbounds i8, i8* %86, i64 6
store i8 %104, i8* %102
%106 = getelementptr inbounds i8, i8* %87, i64 -7
%107 = load i8, i8* %106
%108 = getelementptr inbounds i8, i8* %86, i64 7
store i8 %107, i8* %105
%109 = getelementptr inbounds i8, i8* %87, i64 -8
%110 = load i8, i8* %109
%111 = getelementptr inbounds i8, i8* %86, i64 8
store i8 %110, i8* %108
%112 = icmp eq i8* %7, %109
br i1 %112, label %113, label %85
113: ; preds = %80, %85, %61
%114 = phi i8* [ %38, %61 ], [ %81, %80 ], [ %111, %85 ]
store i8 0, i8* %114
ret i8* %1
}