void Uncompress_Read(int len, char *s) {
  int i, tlen, byte;
  char *s0, *s1, *s2, *s3;
  char *t;
  s0 = s;
  s1 = s0 + 1;
  s2 = s1 + 1;
  s3 = s2 + 1;
  tlen = (len - 1) / 4;
  t = s + tlen;
  for (i = tlen * 4; i >= 0; i -= 4) {
    byte = *t--;
    s0[i] = (char)((byte >> 6) & 0x3);
    s1[i] = (char)((byte >> 4) & 0x3);
    s2[i] = (char)((byte >> 2) & 0x3);
    s3[i] = (char)(byte & 0x3);
  }
  s[len] = 4;
}


x86 assembly (clang, -O0):
<Uncompress_Read>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x38(%rbp)
mov    -0x38(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x40(%rbp)
mov    -0x4(%rbp),%eax
sub    $0x1,%eax
mov    $0x4,%ecx
cltd
idiv   %ecx
mov    %eax,-0x18(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
add    %rcx,%rax
mov    %rax,-0x48(%rbp)
mov    -0x18(%rbp),%eax
shl    $0x2,%eax
mov    %eax,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jl     11e2 <Uncompress_Read+0xe2>
mov    -0x48(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x48(%rbp)
movsbl (%rax),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
sar    $0x6,%eax
and    $0x3,%eax
mov    %al,%dl
mov    -0x28(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
sar    $0x4,%eax
and    $0x3,%eax
mov    %al,%dl
mov    -0x30(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
sar    $0x2,%eax
and    $0x3,%eax
mov    %al,%dl
mov    -0x38(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x1c(%rbp),%eax
and    $0x3,%eax
mov    %al,%dl
mov    -0x40(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
sub    $0x4,%eax
mov    %eax,-0x14(%rbp)
jmp    1160 <Uncompress_Read+0x60>
mov    -0x10(%rbp),%rax
movslq -0x4(%rbp),%rcx
movb   $0x4,(%rax,%rcx,1)
pop    %rbp
ret

x86 assembly (clang, -O2):
<Uncompress_Read>:
lea    -0x1(%rdi),%ecx
lea    0x2(%rdi),%r8d
test   %ecx,%ecx
cmovns %ecx,%r8d
cmp    $0xfffffffe,%edi
jl     115d <Uncompress_Read+0x5d>
sar    $0x2,%r8d
movslq %r8d,%r9
shl    $0x2,%r8d
add    %rsi,%r9
movzbl (%r9),%edx
add    $0xffffffffffffffff,%r9
mov    %edx,%eax
shr    $0x6,%al
mov    %r8d,%ecx
mov    %al,(%rsi,%rcx,1)
mov    %edx,%eax
shr    $0x4,%al
and    $0x3,%al
mov    %al,0x1(%rsi,%rcx,1)
mov    %edx,%eax
shr    $0x2,%al
and    $0x3,%al
mov    %al,0x2(%rsi,%rcx,1)
and    $0x3,%dl
mov    %dl,0x3(%rsi,%rcx,1)
lea    -0x4(%r8),%eax
cmp    $0x3,%r8d
mov    %eax,%r8d
jg     1120 <Uncompress_Read+0x20>
movslq %edi,%rax
movb   $0x4,(%rsi,%rax,1)
ret

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

LLVM IR (-O2):
define void @Uncompress_Read(i32 %0, i8* nocapture %1) {
%3 = getelementptr inbounds i8, i8* %1, i64 1
%4 = getelementptr inbounds i8, i8* %1, i64 2
%5 = getelementptr inbounds i8, i8* %1, i64 3
%6 = add nsw i32 %0, -1
%7 = sdiv i32 %6, 4
%8 = icmp sgt i32 %0, -3
br i1 %8, label %9, label %31
9: ; preds = %2
%10 = shl nsw i32 %7, 2
%11 = sext i32 %7 to i64
%12 = getelementptr inbounds i8, i8* %1, i64 %11
br label %13
13: ; preds = %9, %13
%14 = phi i8* [ %16, %13 ], [ %12, %9 ]
%15 = phi i32 [ %29, %13 ], [ %10, %9 ]
%16 = getelementptr inbounds i8, i8* %14, i64 -1
%17 = load i8, i8* %14
%18 = lshr i8 %17, 6
%19 = zext i32 %15 to i64
%20 = getelementptr inbounds i8, i8* %1, i64 %19
store i8 %18, i8* %20
%21 = lshr i8 %17, 4
%22 = and i8 %21, 3
%23 = getelementptr inbounds i8, i8* %3, i64 %19
store i8 %22, i8* %23
%24 = lshr i8 %17, 2
%25 = and i8 %24, 3
%26 = getelementptr inbounds i8, i8* %4, i64 %19
store i8 %25, i8* %26
%27 = and i8 %17, 3
%28 = getelementptr inbounds i8, i8* %5, i64 %19
store i8 %27, i8* %28
%29 = add nsw i32 %15, -4
%30 = icmp sgt i32 %15, 3
br i1 %30, label %13, label %31
31: ; preds = %13, %2
%32 = sext i32 %0 to i64
%33 = getelementptr inbounds i8, i8* %1, i64 %32
store i8 4, i8* %33
ret void
}