int shiftright(unsigned char *a, int a_len) {
  int i, j, odd, lastback;
  if (a_len == 0) {
    a[0] >>= 1;
    return 0;
  }
  if (a[0] & 0x1)
    lastback = 1;
  else
    lastback = 0;
  a[0] >>= 1;
  for (i = 1; i <= a_len; i++) {
    if (a[i] & 0x1)
      odd = 1;
    else
      odd = 0;
    a[i] >>= 1;
    if (lastback)
      a[i] |= 0x80;
    lastback = odd;
  }
  if (a[0] <= 0) {
    for (i = 0, j = 1; j <= a_len; i++, j++)
      a[i] = a[j];
    a[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    112d <shiftright+0x2d>
mov    -0x10(%rbp),%rax
movzbl (%rax),%ecx
sar    $0x1,%ecx
mov    %cl,(%rax)
movl   $0x0,-0x4(%rbp)
jmp    125c <shiftright+0x15c>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     114c <shiftright+0x4c>
movl   $0x1,-0x24(%rbp)
jmp    1153 <shiftright+0x53>
movl   $0x0,-0x24(%rbp)
mov    -0x10(%rbp),%rax
movzbl (%rax),%ecx
sar    $0x1,%ecx
mov    %cl,(%rax)
movl   $0x1,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jg     11e2 <shiftright+0xe2>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     1196 <shiftright+0x96>
movl   $0x1,-0x20(%rbp)
jmp    119d <shiftright+0x9d>
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     11ce <shiftright+0xce>
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    1166 <shiftright+0x66>
mov    -0x10(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x0,%eax
jg     1256 <shiftright+0x156>
movl   $0x0,-0x18(%rbp)
movl   $0x1,-0x1c(%rbp)
mov    -0x1c(%rbp),%eax
cmp    -0x14(%rbp),%eax
jg     1239 <shiftright+0x139>
mov    -0x10(%rbp),%rax
movslq -0x1c(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
mov    -0x1c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1c(%rbp)
jmp    1200 <shiftright+0x100>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movb   $0x0,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
mov    %eax,-0x4(%rbp)
jmp    125c <shiftright+0x15c>
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<shiftright>:
push   %rbp
push   %r14
push   %rbx
mov    (%rdi),%r8b
mov    %r8d,%ecx
shr    %cl
mov    %cl,(%rdi)
test   %esi,%esi
je     1249 <shiftright+0x139>
mov    %esi,%r14d
mov    %rdi,%rbp
jle    124e <shiftright+0x13e>
mov    %r14d,%edx
mov    $0x1,%ecx
mov    %r8d,%esi
cmp    $0x20,%r14d
jb     1206 <shiftright+0xf6>
mov    %edx,%esi
and    $0xffffffe0,%esi
lea    0x1(%rsi),%rcx
movzbl %r8b,%edi
movd   %edi,%xmm0
pslldq $0xf,%xmm0
xor    %edi,%edi
movdqa 0xe99(%rip),%xmm1
nopw   0x0(%rax,%rax,1)
movdqa %xmm0,%xmm2
movdqu 0x1(%rbp,%rdi,1),%xmm3
movdqu 0x11(%rbp,%rdi,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,0x1(%rbp,%rdi,1)
movdqu %xmm4,0x11(%rbp,%rdi,1)
add    $0x20,%rdi
cmp    %rdi,%rsi
jne    1170 <shiftright+0x60>
cmp    %rsi,%rdx
je     1230 <shiftright+0x120>
pextrw $0x7,%xmm0,%esi
shr    $0x8,%esi
lea    0x1(%rdx),%rdi
nopw   0x0(%rax,%rax,1)
movzbl 0x0(%rbp,%rcx,1),%ebx
mov    %ebx,%eax
shr    %al
shl    $0x7,%sil
or     %al,%sil
mov    %sil,0x0(%rbp,%rcx,1)
add    $0x1,%rcx
mov    %ebx,%esi
cmp    %rcx,%rdi
jne    1210 <shiftright+0x100>
cmp    $0x2,%r8b
jae    1260 <shiftright+0x150>
test   %r14d,%r14d
jle    1254 <shiftright+0x144>
lea    0x1(%rbp),%rsi
mov    %rbp,%rdi
call   1030 <memmove@plt>
jmp    1254 <shiftright+0x144>
xor    %r14d,%r14d
jmp    1260 <shiftright+0x150>
cmp    $0x2,%r8b
jae    1260 <shiftright+0x150>
movslq %r14d,%rax
movb   $0x0,0x0(%rbp,%rax,1)
add    $0xffffffff,%r14d
mov    %r14d,%eax
pop    %rbx
pop    %r14
pop    %rbp
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 0
%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 %110
19: ; preds = %2
%20 = load i8*, i8** %4
%21 = getelementptr inbounds i8, i8* %20, i64 0
%22 = load i8, i8* %21
%23 = zext i8 %22 to i32
%24 = and i32 %23, 1
%25 = icmp ne i32 %24, 0
br i1 %25, label %26, label %27
26: ; preds = %19
store i32 1, i32* %9
br label %28
27: ; preds = %19
store i32 0, i32* %9
br label %28
28: ; preds = %27, %26
%29 = load i8*, i8** %4
%30 = getelementptr inbounds i8, i8* %29, i64 0
%31 = load i8, i8* %30
%32 = zext i8 %31 to i32
%33 = ashr i32 %32, 1
%34 = trunc i32 %33 to i8
store i8 %34, i8* %30
store i32 1, i32* %6
br label %35
35: ; preds = %72, %28
%36 = load i32, i32* %6
%37 = load i32, i32* %5
%38 = icmp sle i32 %36, %37
br i1 %38, label %39, label %75
39: ; preds = %35
%40 = load i8*, i8** %4
%41 = load i32, i32* %6
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds i8, i8* %40, i64 %42
%44 = load i8, i8* %43
%45 = zext i8 %44 to i32
%46 = and i32 %45, 1
%47 = icmp ne i32 %46, 0
br i1 %47, label %48, label %49
48: ; preds = %39
store i32 1, i32* %8
br label %50
49: ; preds = %39
store i32 0, i32* %8
br label %50
50: ; preds = %49, %48
%51 = load i8*, i8** %4
%52 = load i32, i32* %6
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds i8, i8* %51, i64 %53
%55 = load i8, i8* %54
%56 = zext i8 %55 to i32
%57 = ashr i32 %56, 1
%58 = trunc i32 %57 to i8
store i8 %58, i8* %54
%59 = load i32, i32* %9
%60 = icmp ne i32 %59, 0
br i1 %60, label %61, label %70
61: ; preds = %50
%62 = load i8*, i8** %4
%63 = load i32, i32* %6
%64 = sext i32 %63 to i64
%65 = getelementptr inbounds i8, i8* %62, i64 %64
%66 = load i8, i8* %65
%67 = zext i8 %66 to i32
%68 = or i32 %67, 128
%69 = trunc i32 %68 to i8
store i8 %69, i8* %65
br label %70
70: ; preds = %61, %50
%71 = load i32, i32* %8
store i32 %71, i32* %9
br label %72
72: ; preds = %70
%73 = load i32, i32* %6
%74 = add nsw i32 %73, 1
store i32 %74, i32* %6
br label %35
75: ; preds = %35
%76 = load i8*, i8** %4
%77 = getelementptr inbounds i8, i8* %76, i64 0
%78 = load i8, i8* %77
%79 = zext i8 %78 to i32
%80 = icmp sle i32 %79, 0
br i1 %80, label %81, label %108
81: ; preds = %75
store i32 0, i32* %6
store i32 1, i32* %7
br label %82
82: ; preds = %96, %81
%83 = load i32, i32* %7
%84 = load i32, i32* %5
%85 = icmp sle i32 %83, %84
br i1 %85, label %86, label %101
86: ; preds = %82
%87 = load i8*, i8** %4
%88 = load i32, i32* %7
%89 = sext i32 %88 to i64
%90 = getelementptr inbounds i8, i8* %87, i64 %89
%91 = load i8, i8* %90
%92 = load i8*, i8** %4
%93 = load i32, i32* %6
%94 = sext i32 %93 to i64
%95 = getelementptr inbounds i8, i8* %92, i64 %94
store i8 %91, i8* %95
br label %96
96: ; preds = %86
%97 = load i32, i32* %6
%98 = add nsw i32 %97, 1
store i32 %98, i32* %6
%99 = load i32, i32* %7
%100 = add nsw i32 %99, 1
store i32 %100, i32* %7
br label %82
101: ; preds = %82
%102 = load i8*, i8** %4
%103 = load i32, i32* %5
%104 = sext i32 %103 to i64
%105 = getelementptr inbounds i8, i8* %102, i64 %104
store i8 0, i8* %105
%106 = load i32, i32* %5
%107 = add nsw i32 %106, -1
store i32 %107, i32* %5
store i32 %107, i32* %3
br label %110
108: ; preds = %75
%109 = load i32, i32* %5
store i32 %109, i32* %3
br label %110
110: ; preds = %108, %101, %12
%111 = load i32, i32* %3
ret i32 %111
}

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