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


x86 assembly (clang, -O0):
<shiftright>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
cmpl   $0x0,-0x14(%rbp)
jne    112f <shiftright+0x2f>
mov    -0x10(%rbp),%rax
movzbl 0x13(%rax),%ecx
sar    $0x1,%ecx
mov    %cl,0x13(%rax)
movl   $0x0,-0x4(%rbp)
jmp    1248 <shiftright+0x148>
mov    -0x10(%rbp),%rax
mov    $0x13,%ecx
sub    -0x14(%rbp),%ecx
movslq %ecx,%rcx
movzbl (%rax,%rcx,1),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     115a <shiftright+0x5a>
movl   $0x1,-0x24(%rbp)
jmp    1161 <shiftright+0x61>
movl   $0x0,-0x24(%rbp)
mov    -0x10(%rbp),%rax
mov    $0x13,%ecx
sub    -0x14(%rbp),%ecx
movslq %ecx,%rcx
movzbl (%rax,%rcx,1),%edx
sar    $0x1,%edx
mov    %dl,(%rax,%rcx,1)
mov    $0x13,%eax
sub    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
cmpl   $0x13,-0x18(%rbp)
jg     1202 <shiftright+0x102>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     11b6 <shiftright+0xb6>
movl   $0x1,-0x20(%rbp)
jmp    11bd <shiftright+0xbd>
movl   $0x0,-0x20(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
sar    $0x1,%edx
mov    %dl,(%rax,%rcx,1)
cmpl   $0x0,-0x24(%rbp)
je     11ee <shiftright+0xee>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
or     $0x80,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x20(%rbp),%eax
mov    %eax,-0x24(%rbp)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1188 <shiftright+0x88>
mov    -0x10(%rbp),%rax
mov    $0x13,%ecx
sub    -0x14(%rbp),%ecx
movslq %ecx,%rcx
movzbl (%rax,%rcx,1),%eax
cmp    $0x0,%eax
jg     1242 <shiftright+0x142>
mov    -0x10(%rbp),%rax
mov    $0x13,%ecx
sub    -0x14(%rbp),%ecx
movslq %ecx,%rcx
movb   $0x0,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
mov    %eax,-0x4(%rbp)
jmp    1248 <shiftright+0x148>
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<shiftright>:
test   %esi,%esi
je     1136 <shiftright+0x36>
mov    %esi,%eax
movslq %esi,%rcx
mov    $0x13,%r9d
sub    %rcx,%r9
neg    %rcx
mov    0x13(%rdi,%rcx,1),%cl
mov    %ecx,%edx
shr    %dl
mov    %dl,(%rdi,%r9,1)
mov    $0x14,%esi
sub    %eax,%esi
cmp    $0x13,%esi
jle    113c <shiftright+0x3c>
test   %dl,%dl
je     124a <shiftright+0x14a>
ret
shrb   0x13(%rdi)
xor    %eax,%eax
ret
movslq %esi,%rsi
lea    -0x1(%rax),%r8d
cmp    $0x1f,%r8d
jae    1151 <shiftright+0x51>
mov    %rsi,%r11
jmp    1220 <shiftright+0x120>
add    $0x1,%r8
mov    %r8,%r10
and    $0xffffffffffffffe0,%r10
lea    (%r10,%rsi,1),%r11
movzbl %cl,%ecx
movd   %ecx,%xmm0
pslldq $0xf,%xmm0
lea    (%rsi,%rdi,1),%rcx
add    $0x10,%rcx
xor    %esi,%esi
movdqa 0xe82(%rip),%xmm1
xchg   %ax,%ax
movdqa %xmm0,%xmm2
movdqu -0x10(%rcx,%rsi,1),%xmm3
movdqu (%rcx,%rsi,1),%xmm0
movdqa %xmm3,%xmm4
pslldq $0x1,%xmm4
psrldq $0xf,%xmm2
por    %xmm4,%xmm2
movdqa %xmm3,%xmm4
psrldq $0xf,%xmm4
movdqa %xmm0,%xmm5
pslldq $0x1,%xmm5
por    %xmm4,%xmm5
psrlw  $0x1,%xmm3
movdqa %xmm1,%xmm4
pandn  %xmm3,%xmm4
psllw  $0x7,%xmm2
pand   %xmm1,%xmm2
por    %xmm4,%xmm2
psllw  $0x7,%xmm5
pand   %xmm1,%xmm5
movdqa %xmm0,%xmm3
psrlw  $0x1,%xmm3
movdqa %xmm1,%xmm4
pandn  %xmm3,%xmm4
por    %xmm5,%xmm4
movdqu %xmm2,-0x10(%rcx,%rsi,1)
movdqu %xmm4,(%rcx,%rsi,1)
add    $0x20,%rsi
cmp    %rsi,%r10
jne    1180 <shiftright+0x80>
cmp    %r10,%r8
je     123e <shiftright+0x13e>
pextrw $0x7,%xmm0,%ecx
shr    $0x8,%ecx
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movzbl (%rdi,%r11,1),%esi
mov    %esi,%edx
shr    %dl
shl    $0x7,%cl
or     %dl,%cl
mov    %cl,(%rdi,%r11,1)
add    $0x1,%r11
mov    %esi,%ecx
cmp    $0x14,%r11d
jne    1220 <shiftright+0x120>
mov    (%rdi,%r9,1),%dl
test   %dl,%dl
jne    1135 <shiftright+0x35>
movb   $0x0,(%rdi,%r9,1)
add    $0xffffffff,%eax
ret

LLVM IR (-O0):
define i32 @shiftright(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 %19
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 = ashr i32 %16, 1
%18 = trunc i32 %17 to i8
store i8 %18, i8* %14
store i32 0, i32* %3
br label %102
19: ; preds = %2
%20 = load i8*, i8** %4
%21 = load i32, i32* %5
%22 = sub nsw i32 19, %21
%23 = sext i32 %22 to i64
%24 = getelementptr inbounds i8, i8* %20, i64 %23
%25 = load i8, i8* %24
%26 = zext i8 %25 to i32
%27 = and i32 %26, 1
%28 = icmp ne i32 %27, 0
br i1 %28, label %29, label %30
29: ; preds = %19
store i32 1, i32* %9
br label %31
30: ; preds = %19
store i32 0, i32* %9
br label %31
31: ; preds = %30, %29
%32 = load i8*, i8** %4
%33 = load i32, i32* %5
%34 = sub nsw i32 19, %33
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds i8, i8* %32, i64 %35
%37 = load i8, i8* %36
%38 = zext i8 %37 to i32
%39 = ashr i32 %38, 1
%40 = trunc i32 %39 to i8
store i8 %40, i8* %36
%41 = load i32, i32* %5
%42 = sub nsw i32 19, %41
%43 = add nsw i32 %42, 1
store i32 %43, i32* %6
br label %44
44: ; preds = %80, %31
%45 = load i32, i32* %6
%46 = icmp sle i32 %45, 19
br i1 %46, label %47, label %83
47: ; preds = %44
%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, 1
%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 = ashr 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, 128
%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 %44
83: ; preds = %44
%84 = load i8*, i8** %4
%85 = load i32, i32* %5
%86 = sub nsw i32 19, %85
%87 = sext i32 %86 to i64
%88 = getelementptr inbounds i8, i8* %84, i64 %87
%89 = load i8, i8* %88
%90 = zext i8 %89 to i32
%91 = icmp sle i32 %90, 0
br i1 %91, label %92, label %100
92: ; preds = %83
%93 = load i8*, i8** %4
%94 = load i32, i32* %5
%95 = sub nsw i32 19, %94
%96 = sext i32 %95 to i64
%97 = getelementptr inbounds i8, i8* %93, i64 %96
store i8 0, i8* %97
%98 = load i32, i32* %5
%99 = add nsw i32 %98, -1
store i32 %99, i32* %5
store i32 %99, i32* %3
br label %102
100: ; preds = %83
%101 = load i32, i32* %5
store i32 %101, i32* %3
br label %102
102: ; preds = %100, %92, %12
%103 = load i32, i32* %3
ret i32 %103
}

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