char *ltoa(char *p, unsigned long num, int radix, char first_hex_letter) {
  int i;
  char *q;
  q = p + 32;
  do {
    i = (int)(num % radix);
    if (i >= 10) {
      i += first_hex_letter - 10;
    } else {
      i += '0';
    }
    *--q = i;
  } while ((num = num / radix) != 0);
  i = (int)(p + 32 - q);
  do {
    *p++ = *q++;
  } while (--i);
  return (p);
}


x86 assembly (clang, -O0):
<ltoa>:
push   %rbp
mov    %rsp,%rbp
mov    %cl,%al
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %al,-0x15(%rbp)
mov    -0x8(%rbp),%rax
add    $0x20,%rax
mov    %rax,-0x28(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
xor    %edx,%edx
div    %rcx
mov    %edx,%eax
mov    %eax,-0x1c(%rbp)
cmpl   $0xa,-0x1c(%rbp)
jl     114e <ltoa+0x4e>
movsbl -0x15(%rbp),%eax
sub    $0xa,%eax
add    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
jmp    1157 <ltoa+0x57>
mov    -0x1c(%rbp),%eax
add    $0x30,%eax
mov    %eax,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %rax,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,-0x28(%rbp)
mov    %cl,-0x1(%rax)
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
xor    %edx,%edx
div    %rcx
mov    %rax,-0x10(%rbp)
cmp    $0x0,%rax
jne    1120 <ltoa+0x20>
mov    -0x8(%rbp),%rax
add    $0x20,%rax
mov    -0x28(%rbp),%rcx
sub    %rcx,%rax
mov    %eax,-0x1c(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%cl
mov    -0x8(%rbp),%rax
mov    %rax,%rdx
add    $0x1,%rdx
mov    %rdx,-0x8(%rbp)
mov    %cl,(%rax)
mov    -0x1c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x1c(%rbp)
cmp    $0x0,%eax
jne    119b <ltoa+0x9b>
mov    -0x8(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<ltoa>:
push   %r14
push   %rbx
mov    %edx,%r8d
movslq %edx,%r9
movzbl %cl,%r11d
add    $0xf6,%r11d
mov    $0xfffffffe,%ecx
xor    %r10d,%r10d
jmp    114a <ltoa+0x4a>
xchg   %ax,%ax
mov    %rsi,%rax
xor    %edx,%edx
div    %r9
cmp    $0xa,%edx
mov    $0x30,%ebx
cmovge %r11d,%ebx
add    %edx,%ebx
mov    %bl,0x1f(%rdi,%r10,1)
add    $0xffffffffffffffff,%r10
add    $0x1,%ecx
cmp    %r9,%rsi
mov    %rax,%rsi
jb     115f <ltoa+0x5f>
mov    %rsi,%rax
or     %r9,%rax
shr    $0x20,%rax
jne    1120 <ltoa+0x20>
mov    %esi,%eax
xor    %edx,%edx
div    %r8d
jmp    1128 <ltoa+0x28>
lea    0x1(%rdi),%rax
mov    %bl,(%rdi)
cmp    $0xffffffff,%r10d
je     13a1 <ltoa+0x2a1>
mov    %r10,%rbx
not    %rbx
lea    (%rdi,%r10,1),%rdx
add    $0x21,%rdx
mov    $0xfffffffe,%esi
mov    $0xfffffffe,%r9d
sub    %r10d,%r9d
cmp    $0x1e,%r9d
jbe    1304 <ltoa+0x204>
mov    %ecx,%r8d
lea    (%rdi,%r8,1),%rcx
add    %r10,%rcx
add    $0x22,%rcx
cmp    %rcx,%rax
jae    11bc <ltoa+0xbc>
sub    %r10d,%esi
lea    (%rsi,%rdi,1),%rcx
add    $0x2,%rcx
cmp    %rcx,%rdx
jb     1304 <ltoa+0x204>
mov    $0xfffffffffffffffe,%rsi
sub    %r10,%rsi
add    $0x1,%r9
mov    %r9,%r11
and    $0xffffffffffffffe0,%r11
lea    -0x20(%r11),%rcx
mov    %rcx,%r14
shr    $0x5,%r14
add    $0x1,%r14
cmp    $0x60,%rcx
jae    11ed <ltoa+0xed>
xor    %edx,%edx
jmp    1275 <ltoa+0x175>
lea    (%rdi,%r10,1),%rbx
add    $0x91,%rbx
mov    %esi,%ecx
add    $0x1,%rcx
and    $0xffffffffffffffe0,%rcx
add    $0xffffffffffffffe0,%rcx
shr    $0x5,%rcx
add    $0x1,%rcx
and    $0xfffffffffffffffc,%rcx
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movups -0x70(%rbx),%xmm0
movups -0x60(%rbx),%xmm1
movups %xmm0,0x1(%rdi,%rdx,1)
movups %xmm1,0x11(%rdi,%rdx,1)
movups -0x50(%rbx),%xmm0
movups -0x40(%rbx),%xmm1
movups %xmm0,0x21(%rdi,%rdx,1)
movups %xmm1,0x31(%rdi,%rdx,1)
movups -0x30(%rbx),%xmm0
movups -0x20(%rbx),%xmm1
movups %xmm0,0x41(%rdi,%rdx,1)
movups %xmm1,0x51(%rdi,%rdx,1)
movups -0x10(%rbx),%xmm0
movups (%rbx),%xmm1
movups %xmm0,0x61(%rdi,%rdx,1)
movups %xmm1,0x71(%rdi,%rdx,1)
sub    $0xffffffffffffff80,%rdx
sub    $0xffffffffffffff80,%rbx
add    $0xfffffffffffffffc,%rcx
jne    1220 <ltoa+0x120>
test   $0x3,%r14b
je     12d1 <ltoa+0x1d1>
lea    (%rdx,%rdi,1),%rcx
add    $0x11,%rcx
add    $0x1,%sil
and    $0x60,%sil
add    $0xe0,%sil
shr    $0x5,%sil
add    $0x1,%sil
movzbl %sil,%r14d
and    $0x3,%r14d
shl    $0x5,%r14
add    %rdi,%rdx
add    $0x31,%rdx
xor    %ebx,%ebx
nopl   0x0(%rax)
lea    (%rdx,%rbx,1),%rsi
movups -0x10(%r10,%rsi,1),%xmm0
movups (%r10,%rsi,1),%xmm1
movups %xmm0,-0x10(%rcx,%rbx,1)
movups %xmm1,(%rcx,%rbx,1)
add    $0x20,%rbx
cmp    %rbx,%r14
jne    12b0 <ltoa+0x1b0>
add    %r11,%rax
cmp    %r11,%r9
je     13a1 <ltoa+0x2a1>
add    $0x1,%r8
shr    $0x5,%r8
mov    %r8d,%ebx
shl    $0x5,%ebx
xor    $0xffffffe0,%ebx
shl    $0x5,%r8
sub    %r10,%rbx
add    %r8,%rdi
add    $0x1f,%rbx
lea    (%r10,%rdi,1),%rdx
add    $0x21,%rdx
lea    -0x1(%rbx),%r8d
test   $0x7,%bl
je     1337 <ltoa+0x237>
mov    %ebx,%esi
and    $0x7,%esi
xor    %edi,%edi
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movzbl (%rdx,%rdi,1),%ecx
mov    %cl,(%rax,%rdi,1)
add    $0x1,%rdi
cmp    %edi,%esi
jne    1320 <ltoa+0x220>
sub    %edi,%ebx
add    %rdi,%rax
add    %rdi,%rdx
cmp    $0x7,%r8d
jb     13a1 <ltoa+0x2a1>
mov    %ebx,%esi
xor    %ecx,%ecx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movzbl (%rdx,%rcx,1),%ebx
mov    %bl,(%rax,%rcx,1)
movzbl 0x1(%rdx,%rcx,1),%ebx
mov    %bl,0x1(%rax,%rcx,1)
movzbl 0x2(%rdx,%rcx,1),%ebx
mov    %bl,0x2(%rax,%rcx,1)
movzbl 0x3(%rdx,%rcx,1),%ebx
mov    %bl,0x3(%rax,%rcx,1)
movzbl 0x4(%rdx,%rcx,1),%ebx
mov    %bl,0x4(%rax,%rcx,1)
movzbl 0x5(%rdx,%rcx,1),%ebx
mov    %bl,0x5(%rax,%rcx,1)
movzbl 0x6(%rdx,%rcx,1),%ebx
mov    %bl,0x6(%rax,%rcx,1)
movzbl 0x7(%rdx,%rcx,1),%ebx
mov    %bl,0x7(%rax,%rcx,1)
add    $0x8,%rcx
cmp    %ecx,%esi
jne    1350 <ltoa+0x250>
add    %rcx,%rax
pop    %rbx
pop    %r14
ret

LLVM IR (-O0):
define i8* @ltoa(i8* %0, i64 %1, i32 %2, i8 signext %3) {
%5 = alloca i8*
%6 = alloca i64
%7 = alloca i32
%8 = alloca i8
%9 = alloca i32
%10 = alloca i8*
store i8* %0, i8** %5
store i64 %1, i64* %6
store i32 %2, i32* %7
store i8 %3, i8* %8
%11 = load i8*, i8** %5
%12 = getelementptr inbounds i8, i8* %11, i64 32
store i8* %12, i8** %10
br label %13
13: ; preds = %35, %4
%14 = load i64, i64* %6
%15 = load i32, i32* %7
%16 = sext i32 %15 to i64
%17 = urem i64 %14, %16
%18 = trunc i64 %17 to i32
store i32 %18, i32* %9
%19 = load i32, i32* %9
%20 = icmp sge i32 %19, 10
br i1 %20, label %21, label %27
21: ; preds = %13
%22 = load i8, i8* %8
%23 = sext i8 %22 to i32
%24 = sub nsw i32 %23, 10
%25 = load i32, i32* %9
%26 = add nsw i32 %25, %24
store i32 %26, i32* %9
br label %30
27: ; preds = %13
%28 = load i32, i32* %9
%29 = add nsw i32 %28, 48
store i32 %29, i32* %9
br label %30
30: ; preds = %27, %21
%31 = load i32, i32* %9
%32 = trunc i32 %31 to i8
%33 = load i8*, i8** %10
%34 = getelementptr inbounds i8, i8* %33, i32 -1
store i8* %34, i8** %10
store i8 %32, i8* %34
br label %35
35: ; preds = %30
%36 = load i64, i64* %6
%37 = load i32, i32* %7
%38 = sext i32 %37 to i64
%39 = udiv i64 %36, %38
store i64 %39, i64* %6
%40 = icmp ne i64 %39, 0
br i1 %40, label %13, label %41
41: ; preds = %35
%42 = load i8*, i8** %5
%43 = getelementptr inbounds i8, i8* %42, i64 32
%44 = load i8*, i8** %10
%45 = ptrtoint i8* %43 to i64
%46 = ptrtoint i8* %44 to i64
%47 = sub i64 %45, %46
%48 = trunc i64 %47 to i32
store i32 %48, i32* %9
br label %49
49: ; preds = %55, %41
%50 = load i8*, i8** %10
%51 = getelementptr inbounds i8, i8* %50, i32 1
store i8* %51, i8** %10
%52 = load i8, i8* %50
%53 = load i8*, i8** %5
%54 = getelementptr inbounds i8, i8* %53, i32 1
store i8* %54, i8** %5
store i8 %52, i8* %53
br label %55
55: ; preds = %49
%56 = load i32, i32* %9
%57 = add nsw i32 %56, -1
store i32 %57, i32* %9
%58 = icmp ne i32 %57, 0
br i1 %58, label %49, label %59
59: ; preds = %55
%60 = load i8*, i8** %5
ret i8* %60
}

LLVM IR (-O2):
define i8* @ltoa(i8* %0, i64 %1, i32 %2, i8 signext %3) {
%5 = getelementptr inbounds i8, i8* %0, i64 32
%6 = sext i32 %2 to i64
%7 = zext i8 %3 to i32
%8 = add nuw nsw i32 %7, 246
br label %9
9: ; preds = %9, %4
%10 = phi i64 [ %1, %4 ], [ %19, %9 ]
%11 = phi i8* [ %5, %4 ], [ %18, %9 ]
%12 = urem i64 %10, %6
%13 = trunc i64 %12 to i32
%14 = icmp sgt i32 %13, 9
%15 = select i1 %14, i32 %8, i32 48
%16 = add i32 %15, %13
%17 = trunc i32 %16 to i8
%18 = getelementptr inbounds i8, i8* %11, i64 -1
store i8 %17, i8* %18
%19 = udiv i64 %10, %6
%20 = icmp ult i64 %10, %6
br i1 %20, label %21, label %9
21: ; preds = %9
%22 = trunc i32 %16 to i8
%23 = ptrtoint i8* %5 to i64
%24 = ptrtoint i8* %18 to i64
%25 = sub i64 %23, %24
%26 = trunc i64 %25 to i32
%27 = getelementptr i8, i8* %0, i64 1
store i8 %22, i8* %0
%28 = add nsw i32 %26, -1
%29 = icmp eq i32 %28, 0
br i1 %29, label %183, label %30
30: ; preds = %21
%31 = add i64 %23, 4294967294
%32 = sub i64 %31, %24
%33 = and i64 %32, 4294967295
%34 = add nuw nsw i64 %33, 1
%35 = icmp ult i64 %33, 31
br i1 %35, label %129, label %36
36: ; preds = %30
%37 = add i64 %23, 4294967294
%38 = sub i64 %37, %24
%39 = and i64 %38, 4294967295
%40 = add nuw nsw i64 %39, 2
%41 = getelementptr i8, i8* %0, i64 %40
%42 = getelementptr i8, i8* %18, i64 %40
%43 = icmp ult i8* %27, %42
%44 = icmp ult i8* %11, %41
%45 = and i1 %43, %44
br i1 %45, label %129, label %46
46: ; preds = %36
%47 = and i64 %34, 8589934560
%48 = trunc i64 %47 to i32
%49 = sub i32 %28, %48
%50 = getelementptr i8, i8* %27, i64 %47
%51 = getelementptr i8, i8* %11, i64 %47
%52 = add nsw i64 %47, -32
%53 = lshr exact i64 %52, 5
%54 = add nuw nsw i64 %53, 1
%55 = and i64 %54, 3
%56 = icmp ult i64 %52, 96
br i1 %56, label %108, label %57
57: ; preds = %46
%58 = and i64 %54, 1152921504606846972
br label %59
59: ; preds = %59, %57
%60 = phi i64 [ 0, %57 ], [ %105, %59 ]
%61 = phi i64 [ 0, %57 ], [ %106, %59 ]
%62 = getelementptr i8, i8* %27, i64 %60
%63 = getelementptr i8, i8* %11, i64 %60
%64 = bitcast i8* %63 to <16 x i8>*
%65 = load <16 x i8>, <16 x i8>* %64
%66 = getelementptr i8, i8* %63, i64 16
%67 = bitcast i8* %66 to <16 x i8>*
%68 = load <16 x i8>, <16 x i8>* %67
%69 = bitcast i8* %62 to <16 x i8>*
store <16 x i8> %65, <16 x i8>* %69
%70 = getelementptr i8, i8* %62, i64 16
%71 = bitcast i8* %70 to <16 x i8>*
store <16 x i8> %68, <16 x i8>* %71
%72 = or i64 %60, 32
%73 = getelementptr i8, i8* %27, i64 %72
%74 = getelementptr i8, i8* %11, i64 %72
%75 = bitcast i8* %74 to <16 x i8>*
%76 = load <16 x i8>, <16 x i8>* %75
%77 = getelementptr i8, i8* %74, i64 16
%78 = bitcast i8* %77 to <16 x i8>*
%79 = load <16 x i8>, <16 x i8>* %78
%80 = bitcast i8* %73 to <16 x i8>*
store <16 x i8> %76, <16 x i8>* %80
%81 = getelementptr i8, i8* %73, i64 16
%82 = bitcast i8* %81 to <16 x i8>*
store <16 x i8> %79, <16 x i8>* %82
%83 = or i64 %60, 64
%84 = getelementptr i8, i8* %27, i64 %83
%85 = getelementptr i8, i8* %11, i64 %83
%86 = bitcast i8* %85 to <16 x i8>*
%87 = load <16 x i8>, <16 x i8>* %86
%88 = getelementptr i8, i8* %85, i64 16
%89 = bitcast i8* %88 to <16 x i8>*
%90 = load <16 x i8>, <16 x i8>* %89
%91 = bitcast i8* %84 to <16 x i8>*
store <16 x i8> %87, <16 x i8>* %91
%92 = getelementptr i8, i8* %84, i64 16
%93 = bitcast i8* %92 to <16 x i8>*
store <16 x i8> %90, <16 x i8>* %93
%94 = or i64 %60, 96
%95 = getelementptr i8, i8* %27, i64 %94
%96 = getelementptr i8, i8* %11, i64 %94
%97 = bitcast i8* %96 to <16 x i8>*
%98 = load <16 x i8>, <16 x i8>* %97
%99 = getelementptr i8, i8* %96, i64 16
%100 = bitcast i8* %99 to <16 x i8>*
%101 = load <16 x i8>, <16 x i8>* %100
%102 = bitcast i8* %95 to <16 x i8>*
store <16 x i8> %98, <16 x i8>* %102
%103 = getelementptr i8, i8* %95, i64 16
%104 = bitcast i8* %103 to <16 x i8>*
store <16 x i8> %101, <16 x i8>* %104
%105 = add nuw i64 %60, 128
%106 = add i64 %61, 4
%107 = icmp eq i64 %106, %58
br i1 %107, label %108, label %59
108: ; preds = %59, %46
%109 = phi i64 [ 0, %46 ], [ %105, %59 ]
%110 = icmp eq i64 %55, 0
br i1 %110, label %127, label %111
111: ; preds = %108, %111
%112 = phi i64 [ %124, %111 ], [ %109, %108 ]
%113 = phi i64 [ %125, %111 ], [ 0, %108 ]
%114 = getelementptr i8, i8* %27, i64 %112
%115 = getelementptr i8, i8* %11, i64 %112
%116 = bitcast i8* %115 to <16 x i8>*
%117 = load <16 x i8>, <16 x i8>* %116
%118 = getelementptr i8, i8* %115, i64 16
%119 = bitcast i8* %118 to <16 x i8>*
%120 = load <16 x i8>, <16 x i8>* %119
%121 = bitcast i8* %114 to <16 x i8>*
store <16 x i8> %117, <16 x i8>* %121
%122 = getelementptr i8, i8* %114, i64 16
%123 = bitcast i8* %122 to <16 x i8>*
store <16 x i8> %120, <16 x i8>* %123
%124 = add nuw i64 %112, 32
%125 = add i64 %113, 1
%126 = icmp eq i64 %125, %55
br i1 %126, label %127, label %111
127: ; preds = %111, %108
%128 = icmp eq i64 %34, %47
br i1 %128, label %183, label %129
129: ; preds = %36, %30, %127
%130 = phi i32 [ %28, %36 ], [ %28, %30 ], [ %49, %127 ]
%131 = phi i8* [ %27, %36 ], [ %27, %30 ], [ %50, %127 ]
%132 = phi i8* [ %11, %36 ], [ %11, %30 ], [ %51, %127 ]
%133 = add i32 %130, -1
%134 = and i32 %130, 7
%135 = icmp eq i32 %134, 0
br i1 %135, label %147, label %136
136: ; preds = %129, %136
%137 = phi i32 [ %144, %136 ], [ %130, %129 ]
%138 = phi i8* [ %143, %136 ], [ %131, %129 ]
%139 = phi i8* [ %142, %136 ], [ %132, %129 ]
%140 = phi i32 [ %145, %136 ], [ 0, %129 ]
%141 = load i8, i8* %139
%142 = getelementptr inbounds i8, i8* %139, i64 1
%143 = getelementptr inbounds i8, i8* %138, i64 1
store i8 %141, i8* %138
%144 = add nsw i32 %137, -1
%145 = add i32 %140, 1
%146 = icmp eq i32 %145, %134
br i1 %146, label %147, label %136
147: ; preds = %136, %129
%148 = phi i8* [ undef, %129 ], [ %143, %136 ]
%149 = phi i32 [ %130, %129 ], [ %144, %136 ]
%150 = phi i8* [ %131, %129 ], [ %143, %136 ]
%151 = phi i8* [ %132, %129 ], [ %142, %136 ]
%152 = icmp ult i32 %133, 7
br i1 %152, label %183, label %153
153: ; preds = %147, %153
%154 = phi i32 [ %181, %153 ], [ %149, %147 ]
%155 = phi i8* [ %180, %153 ], [ %150, %147 ]
%156 = phi i8* [ %179, %153 ], [ %151, %147 ]
%157 = load i8, i8* %156
%158 = getelementptr inbounds i8, i8* %156, i64 1
%159 = getelementptr inbounds i8, i8* %155, i64 1
store i8 %157, i8* %155
%160 = load i8, i8* %158
%161 = getelementptr inbounds i8, i8* %156, i64 2
%162 = getelementptr inbounds i8, i8* %155, i64 2
store i8 %160, i8* %159
%163 = load i8, i8* %161
%164 = getelementptr inbounds i8, i8* %156, i64 3
%165 = getelementptr inbounds i8, i8* %155, i64 3
store i8 %163, i8* %162
%166 = load i8, i8* %164
%167 = getelementptr inbounds i8, i8* %156, i64 4
%168 = getelementptr inbounds i8, i8* %155, i64 4
store i8 %166, i8* %165
%169 = load i8, i8* %167
%170 = getelementptr inbounds i8, i8* %156, i64 5
%171 = getelementptr inbounds i8, i8* %155, i64 5
store i8 %169, i8* %168
%172 = load i8, i8* %170
%173 = getelementptr inbounds i8, i8* %156, i64 6
%174 = getelementptr inbounds i8, i8* %155, i64 6
store i8 %172, i8* %171
%175 = load i8, i8* %173
%176 = getelementptr inbounds i8, i8* %156, i64 7
%177 = getelementptr inbounds i8, i8* %155, i64 7
store i8 %175, i8* %174
%178 = load i8, i8* %176
%179 = getelementptr inbounds i8, i8* %156, i64 8
%180 = getelementptr inbounds i8, i8* %155, i64 8
store i8 %178, i8* %177
%181 = add nsw i32 %154, -8
%182 = icmp eq i32 %181, 0
br i1 %182, label %183, label %153
183: ; preds = %147, %153, %127, %21
%184 = phi i8* [ %27, %21 ], [ %50, %127 ], [ %148, %147 ], [ %180, %153 ]
ret i8* %184
}