int shiftleft(unsigned char *a, int a_len) {
  int i, j, front, lastfront;
  if ((a_len == 0) && ((a[20 - 1] & 0x80) != 0x80)) {
    a[20 - 1] <<= 1;
    return 0;
  }
  if (a[20 - 1] & 0x80) {
    lastfront = 1;
    front = 1;
  } else
    lastfront = 0;
  a[20 - 1] <<= 1;
  for (i = 20 - 1 - 1; i >= 20 - 1 - a_len; i--) {
    if (a[i] & 0x80)
      front = 1;
    else
      front = 0;
    a[i] <<= 1;
    if (lastfront)
      a[i] |= 0x1;
    lastfront = front;
  }
  if (front) {
    a_len++;
    a[20 - 1 - a_len] = 1;
  }
  return a_len;
}


x86 assembly (clang, -O0):
<shiftleft>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jne    1147 <shiftleft+0x47>
mov    -0x10(%rbp),%rax
movzbl 0x13(%rax),%eax
and    $0x80,%eax
cmp    $0x80,%eax
je     1147 <shiftleft+0x47>
mov    -0x10(%rbp),%rax
movzbl 0x13(%rax),%ecx
shl    $0x1,%ecx
mov    %cl,0x13(%rax)
movl   $0x0,-0x4(%rbp)
jmp    123a <shiftleft+0x13a>
mov    -0x10(%rbp),%rax
movzbl 0x13(%rax),%eax
and    $0x80,%eax
cmp    $0x0,%eax
je     1170 <shiftleft+0x70>
movl   $0x1,-0x24(%rbp)
movl   $0x1,-0x20(%rbp)
jmp    1177 <shiftleft+0x77>
movl   $0x0,-0x24(%rbp)
mov    -0x10(%rbp),%rax
movzbl 0x13(%rax),%ecx
shl    $0x1,%ecx
mov    %cl,0x13(%rax)
movl   $0x12,-0x18(%rbp)
mov    -0x18(%rbp),%eax
mov    $0x13,%ecx
sub    -0x14(%rbp),%ecx
cmp    %ecx,%eax
jl     120e <shiftleft+0x10e>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
and    $0x80,%eax
cmp    $0x0,%eax
je     11c5 <shiftleft+0xc5>
movl   $0x1,-0x20(%rbp)
jmp    11cc <shiftleft+0xcc>
movl   $0x0,-0x20(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
shl    $0x1,%edx
mov    %dl,(%rax,%rcx,1)
cmpl   $0x0,-0x24(%rbp)
je     11fa <shiftleft+0xfa>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
or     $0x1,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x20(%rbp),%eax
mov    %eax,-0x24(%rbp)
mov    -0x18(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x18(%rbp)
jmp    118c <shiftleft+0x8c>
cmpl   $0x0,-0x20(%rbp)
je     1234 <shiftleft+0x134>
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
mov    -0x10(%rbp),%rax
mov    $0x13,%ecx
sub    -0x14(%rbp),%ecx
movslq %ecx,%rcx
movb   $0x1,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<shiftleft>:
mov    %esi,%eax
mov    0x13(%rdi),%r10b
test   %esi,%esi
je     1246 <shiftleft+0x146>
lea    (%r10,%r10,1),%ecx
mov    %cl,0x13(%rdi)
test   %eax,%eax
jle    125c <shiftleft+0x15c>
mov    $0x12,%ecx
cmp    $0x10,%eax
jb     120e <shiftleft+0x10e>
movslq %eax,%r8
mov    %r8,%r9
and    $0xfffffffffffffff0,%r9
mov    $0x12,%ecx
sub    %r9,%rcx
movzbl %r10b,%edx
movd   %edx,%xmm2
pslldq $0xf,%xmm2
mov    %r9,%rdx
neg    %rdx
xor    %esi,%esi
pxor   %xmm0,%xmm0
movdqa 0xea2(%rip),%xmm1
xchg   %ax,%ax
movdqu 0x3(%rdi,%rsi,1),%xmm3
movdqa %xmm3,%xmm4
punpcklbw %xmm0,%xmm4
pshufd $0x4e,%xmm4,%xmm4
pshuflw $0x1b,%xmm4,%xmm4
pshufhw $0x1b,%xmm4,%xmm5
movdqa %xmm3,%xmm4
punpckhbw %xmm0,%xmm4
pshufd $0x4e,%xmm4,%xmm4
pshuflw $0x1b,%xmm4,%xmm4
pshufhw $0x1b,%xmm4,%xmm4
packuswb %xmm5,%xmm4
movdqa %xmm4,%xmm5
pslldq $0x1,%xmm5
psrldq $0xf,%xmm2
por    %xmm5,%xmm2
movdqa %xmm4,%xmm5
paddb  %xmm4,%xmm5
psrlw  $0x7,%xmm2
pand   %xmm1,%xmm2
por    %xmm5,%xmm2
movdqa %xmm2,%xmm5
punpcklbw %xmm0,%xmm5
pshufd $0x4e,%xmm5,%xmm5
pshuflw $0x1b,%xmm5,%xmm5
pshufhw $0x1b,%xmm5,%xmm5
punpckhbw %xmm0,%xmm2
pshufd $0x4e,%xmm2,%xmm2
pshuflw $0x1b,%xmm2,%xmm2
pshufhw $0x1b,%xmm2,%xmm2
packuswb %xmm5,%xmm2
movdqu %xmm2,0x3(%rdi,%rsi,1)
add    $0xfffffffffffffff0,%rsi
movdqa %xmm4,%xmm2
cmp    %rsi,%rdx
jne    1160 <shiftleft+0x60>
movd   %xmm3,%r10d
cmp    %r8,%r9
je     1240 <shiftleft+0x140>
mov    $0x13,%edx
sub    %eax,%edx
movslq %edx,%r8
add    $0x1,%rcx
mov    %r10d,%edx
nop
movzbl -0x1(%rdi,%rcx,1),%r10d
lea    (%r10,%r10,1),%esi
shr    $0x7,%dl
or     %sil,%dl
mov    %dl,-0x1(%rdi,%rcx,1)
add    $0xffffffffffffffff,%rcx
mov    %r10d,%edx
cmp    %r8,%rcx
jg     1220 <shiftleft+0x120>
test   %r10b,%r10b
js     125c <shiftleft+0x15c>
ret
test   %r10b,%r10b
js     1255 <shiftleft+0x155>
add    %r10b,%r10b
mov    %r10b,0x13(%rdi)
xor    %eax,%eax
ret
add    %r10b,%r10b
mov    %r10b,0x13(%rdi)
mov    $0x12,%ecx
sub    %eax,%ecx
add    $0x1,%eax
movslq %ecx,%rcx
movb   $0x1,(%rdi,%rcx,1)
ret

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

LLVM IR (-O2):
define i32 @shiftleft(i8* nocapture %0, i32 %1) {
%3 = icmp eq i32 %1, 0
%4 = getelementptr inbounds i8, i8* %0, i64 19
%5 = load i8, i8* %4
br i1 %3, label %6, label %13
6: ; preds = %2
%7 = icmp sgt i8 %5, -1
br i1 %7, label %11, label %8
8: ; preds = %6
%9 = getelementptr inbounds i8, i8* %0, i64 19
%10 = shl i8 %5, 1
store i8 %10, i8* %9
br label %59
11: ; preds = %6
%12 = shl nuw i8 %5, 1
store i8 %12, i8* %4
br label %64
13: ; preds = %2
%14 = getelementptr inbounds i8, i8* %0, i64 19
%15 = shl i8 %5, 1
store i8 %15, i8* %14
%16 = icmp slt i32 %1, 1
br i1 %16, label %59, label %17
17: ; preds = %13
%18 = sub nsw i32 19, %1
%19 = sext i32 %18 to i64
%20 = sext i32 %1 to i64
%21 = icmp ult i32 %1, 16
br i1 %21, label %45, label %22
22: ; preds = %17
%23 = and i64 %20, -16
%24 = sub nsw i64 18, %23
%25 = insertelement <16 x i8> poison, i8 %5, i64 15
%26 = getelementptr inbounds i8, i8* %0, i64 -15
br label %27
27: ; preds = %27, %22
%28 = phi i64 [ 0, %22 ], [ %39, %27 ]
%29 = phi <16 x i8> [ %25, %22 ], [ %34, %27 ]
%30 = sub i64 18, %28
%31 = getelementptr inbounds i8, i8* %26, i64 %30
%32 = bitcast i8* %31 to <16 x i8>*
%33 = load <16 x i8>, <16 x i8>* %32
%34 = shufflevector <16 x i8> %33, <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>
%35 = shufflevector <16 x i8> %29, <16 x i8> %34, <16 x i32> <i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
%36 = call <16 x i8> @llvm.fshl.v16i8(<16 x i8> %34, <16 x i8> %35, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
%37 = shufflevector <16 x i8> %36, <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>
%38 = bitcast i8* %31 to <16 x i8>*
store <16 x i8> %37, <16 x i8>* %38
%39 = add nuw i64 %28, 16
%40 = icmp eq i64 %39, %23
br i1 %40, label %41, label %27
41: ; preds = %27
%42 = icmp eq i64 %23, %20
%43 = extractelement <16 x i8> %33, i64 0
%44 = extractelement <16 x i8> %33, i64 0
br i1 %42, label %56, label %45
45: ; preds = %17, %41
%46 = phi i64 [ %24, %41 ], [ 18, %17 ]
%47 = phi i8 [ %43, %41 ], [ %5, %17 ]
br label %48
48: ; preds = %45, %48
%49 = phi i64 [ %54, %48 ], [ %46, %45 ]
%50 = phi i8 [ %52, %48 ], [ %47, %45 ]
%51 = getelementptr inbounds i8, i8* %0, i64 %49
%52 = load i8, i8* %51
%53 = call i8 @llvm.fshl.i8(i8 %52, i8 %50, i8 1)
store i8 %53, i8* %51
%54 = add nsw i64 %49, -1
%55 = icmp sgt i64 %49, %19
br i1 %55, label %48, label %56
56: ; preds = %48, %41
%57 = phi i8 [ %44, %41 ], [ %52, %48 ]
%58 = icmp sgt i8 %57, -1
br i1 %58, label %64, label %59
59: ; preds = %8, %13, %56
%60 = add nsw i32 %1, 1
%61 = sub i32 18, %1
%62 = sext i32 %61 to i64
%63 = getelementptr inbounds i8, i8* %0, i64 %62
store i8 1, i8* %63
br label %64
64: ; preds = %56, %59, %11
%65 = phi i32 [ 0, %11 ], [ %60, %59 ], [ %1, %56 ]
ret i32 %65
}