void phex(unsigned x, char *c) {
  int i;
  c[8] = 0;
  for (i = 7; i >= 0; i--) {
    switch (x & 0xf) {
    case 0x0:
      c[i] = '0';
      break;
    case 0x1:
      c[i] = '1';
      break;
    case 0x2:
      c[i] = '2';
      break;
    case 0x3:
      c[i] = '3';
      break;
    case 0x4:
      c[i] = '4';
      break;
    case 0x5:
      c[i] = '5';
      break;
    case 0x6:
      c[i] = '6';
      break;
    case 0x7:
      c[i] = '7';
      break;
    case 0x8:
      c[i] = '8';
      break;
    case 0x9:
      c[i] = '9';
      break;
    case 0xa:
      c[i] = 'a';
      break;
    case 0xb:
      c[i] = 'b';
      break;
    case 0xc:
      c[i] = 'c';
      break;
    case 0xd:
      c[i] = 'd';
      break;
    case 0xe:
      c[i] = 'e';
      break;
    case 0xf:
      c[i] = 'f';
      break;
    }
    x = x >> 4;
  }
}


x86 assembly (clang, -O0):
<phex>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x10(%rbp),%rax
movb   $0x0,0x8(%rax)
movl   $0x7,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jl     126d <phex+0x16d>
mov    -0x4(%rbp),%eax
and    $0xf,%eax
mov    %rax,-0x20(%rbp)
sub    $0xf,%eax
ja     1256 <phex+0x156>
mov    -0x20(%rbp),%rax
lea    0xebe(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x30,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x31,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x32,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x33,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x34,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x35,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x36,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x37,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x38,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x39,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x61,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x62,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x63,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x64,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x65,(%rax,%rcx,1)
jmp    1256 <phex+0x156>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x66,(%rax,%rcx,1)
mov    -0x4(%rbp),%eax
shr    $0x4,%eax
mov    %eax,-0x4(%rbp)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
jmp    111a <phex+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<phex>:
movb   $0x0,0x8(%rsi)
mov    %edi,%eax
mov    %eax,%edx
and    $0xf,%edx
lea    0xeee(%rip),%rcx
mov    (%rdx,%rcx,1),%dl
mov    %dl,0x7(%rsi)
mov    %edi,%edx
shr    $0x4,%edx
and    $0xf,%edx
mov    (%rdx,%rcx,1),%dl
mov    %dl,0x6(%rsi)
mov    %edi,%edx
shr    $0x8,%edx
and    $0xf,%edx
mov    (%rdx,%rcx,1),%dl
mov    %dl,0x5(%rsi)
mov    %edi,%edx
shr    $0xc,%edx
and    $0xf,%edx
mov    (%rdx,%rcx,1),%dl
mov    %dl,0x4(%rsi)
mov    %edi,%edx
shr    $0x10,%edx
and    $0xf,%edx
mov    (%rdx,%rcx,1),%dl
mov    %dl,0x3(%rsi)
mov    %edi,%edx
shr    $0x14,%edx
and    $0xf,%edx
mov    (%rdx,%rcx,1),%dl
mov    %dl,0x2(%rsi)
shr    $0x18,%edi
and    $0xf,%edi
mov    (%rdi,%rcx,1),%dl
mov    %dl,0x1(%rsi)
shr    $0x1c,%rax
mov    (%rax,%rcx,1),%al
mov    %al,(%rsi)
ret

LLVM IR (-O0):
define void @phex(i32 %0, i8* %1) {
%3 = alloca i32
%4 = alloca i8*
%5 = alloca i32
store i32 %0, i32* %3
store i8* %1, i8** %4
%6 = load i8*, i8** %4
%7 = getelementptr inbounds i8, i8* %6, i64 8
store i8 0, i8* %7
store i32 7, i32* %5
br label %8
8: ; preds = %97, %2
%9 = load i32, i32* %5
%10 = icmp sge i32 %9, 0
br i1 %10, label %11, label %100
11: ; preds = %8
%12 = load i32, i32* %3
%13 = and i32 %12, 15
switch i32 %13, label %94 [
i32 0, label %14
i32 1, label %19
i32 2, label %24
i32 3, label %29
i32 4, label %34
i32 5, label %39
i32 6, label %44
i32 7, label %49
i32 8, label %54
i32 9, label %59
i32 10, label %64
i32 11, label %69
i32 12, label %74
i32 13, label %79
i32 14, label %84
i32 15, label %89
]
14: ; preds = %11
%15 = load i8*, i8** %4
%16 = load i32, i32* %5
%17 = sext i32 %16 to i64
%18 = getelementptr inbounds i8, i8* %15, i64 %17
store i8 48, i8* %18
br label %94
19: ; preds = %11
%20 = load i8*, i8** %4
%21 = load i32, i32* %5
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds i8, i8* %20, i64 %22
store i8 49, i8* %23
br label %94
24: ; preds = %11
%25 = load i8*, i8** %4
%26 = load i32, i32* %5
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds i8, i8* %25, i64 %27
store i8 50, i8* %28
br label %94
29: ; preds = %11
%30 = load i8*, i8** %4
%31 = load i32, i32* %5
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds i8, i8* %30, i64 %32
store i8 51, i8* %33
br label %94
34: ; preds = %11
%35 = load i8*, i8** %4
%36 = load i32, i32* %5
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds i8, i8* %35, i64 %37
store i8 52, i8* %38
br label %94
39: ; preds = %11
%40 = load i8*, i8** %4
%41 = load i32, i32* %5
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds i8, i8* %40, i64 %42
store i8 53, i8* %43
br label %94
44: ; preds = %11
%45 = load i8*, i8** %4
%46 = load i32, i32* %5
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds i8, i8* %45, i64 %47
store i8 54, i8* %48
br label %94
49: ; preds = %11
%50 = load i8*, i8** %4
%51 = load i32, i32* %5
%52 = sext i32 %51 to i64
%53 = getelementptr inbounds i8, i8* %50, i64 %52
store i8 55, i8* %53
br label %94
54: ; preds = %11
%55 = load i8*, i8** %4
%56 = load i32, i32* %5
%57 = sext i32 %56 to i64
%58 = getelementptr inbounds i8, i8* %55, i64 %57
store i8 56, i8* %58
br label %94
59: ; preds = %11
%60 = load i8*, i8** %4
%61 = load i32, i32* %5
%62 = sext i32 %61 to i64
%63 = getelementptr inbounds i8, i8* %60, i64 %62
store i8 57, i8* %63
br label %94
64: ; preds = %11
%65 = load i8*, i8** %4
%66 = load i32, i32* %5
%67 = sext i32 %66 to i64
%68 = getelementptr inbounds i8, i8* %65, i64 %67
store i8 97, i8* %68
br label %94
69: ; preds = %11
%70 = load i8*, i8** %4
%71 = load i32, i32* %5
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds i8, i8* %70, i64 %72
store i8 98, i8* %73
br label %94
74: ; preds = %11
%75 = load i8*, i8** %4
%76 = load i32, i32* %5
%77 = sext i32 %76 to i64
%78 = getelementptr inbounds i8, i8* %75, i64 %77
store i8 99, i8* %78
br label %94
79: ; preds = %11
%80 = load i8*, i8** %4
%81 = load i32, i32* %5
%82 = sext i32 %81 to i64
%83 = getelementptr inbounds i8, i8* %80, i64 %82
store i8 100, i8* %83
br label %94
84: ; preds = %11
%85 = load i8*, i8** %4
%86 = load i32, i32* %5
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds i8, i8* %85, i64 %87
store i8 101, i8* %88
br label %94
89: ; preds = %11
%90 = load i8*, i8** %4
%91 = load i32, i32* %5
%92 = sext i32 %91 to i64
%93 = getelementptr inbounds i8, i8* %90, i64 %92
store i8 102, i8* %93
br label %94
94: ; preds = %11, %89, %84, %79, %74, %69, %64, %59, %54, %49, %44, %39, %34, %29, %24, %19, %14
%95 = load i32, i32* %3
%96 = lshr i32 %95, 4
store i32 %96, i32* %3
br label %97
97: ; preds = %94
%98 = load i32, i32* %5
%99 = add nsw i32 %98, -1
store i32 %99, i32* %5
br label %8
100: ; preds = %8
ret void
}

LLVM IR (-O2):
@switch.table.phex = [16 x i8] c"0123456789abcdef"
define void @phex(i32 %0, i8* nocapture writeonly %1) {
%3 = getelementptr inbounds i8, i8* %1, i64 8
store i8 0, i8* %3
%4 = and i32 %0, 15
%5 = zext i32 %4 to i64
%6 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %5
%7 = load i8, i8* %6
%8 = getelementptr inbounds i8, i8* %1, i64 7
store i8 %7, i8* %8
%9 = lshr i32 %0, 4
%10 = and i32 %9, 15
%11 = zext i32 %10 to i64
%12 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %11
%13 = load i8, i8* %12
%14 = getelementptr inbounds i8, i8* %1, i64 6
store i8 %13, i8* %14
%15 = lshr i32 %0, 8
%16 = and i32 %15, 15
%17 = zext i32 %16 to i64
%18 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %17
%19 = load i8, i8* %18
%20 = getelementptr inbounds i8, i8* %1, i64 5
store i8 %19, i8* %20
%21 = lshr i32 %0, 12
%22 = and i32 %21, 15
%23 = zext i32 %22 to i64
%24 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %23
%25 = load i8, i8* %24
%26 = getelementptr inbounds i8, i8* %1, i64 4
store i8 %25, i8* %26
%27 = lshr i32 %0, 16
%28 = and i32 %27, 15
%29 = zext i32 %28 to i64
%30 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %29
%31 = load i8, i8* %30
%32 = getelementptr inbounds i8, i8* %1, i64 3
store i8 %31, i8* %32
%33 = lshr i32 %0, 20
%34 = and i32 %33, 15
%35 = zext i32 %34 to i64
%36 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %35
%37 = load i8, i8* %36
%38 = getelementptr inbounds i8, i8* %1, i64 2
store i8 %37, i8* %38
%39 = lshr i32 %0, 24
%40 = and i32 %39, 15
%41 = zext i32 %40 to i64
%42 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %41
%43 = load i8, i8* %42
%44 = getelementptr inbounds i8, i8* %1, i64 1
store i8 %43, i8* %44
%45 = lshr i32 %0, 28
%46 = zext i32 %45 to i64
%47 = getelementptr inbounds [16 x i8], [16 x i8]* @switch.table.phex, i64 0, i64 %46
%48 = load i8, i8* %47
store i8 %48, i8* %1
ret void
}