int shiftright(unsigned char *a, int a_len) {
  int i, j, odd, lastback;
  if (a_len == 0) {
    a[a_len] >>= 1;
    return 0;
  }
  if (a[a_len] & 0x1)
    lastback = 1;
  else
    lastback = 0;
  a[a_len] >>= 1;
  for (i = a_len - 1; i >= 0; i--) {
    if (a[i] & 0x1)
      odd = 1;
    else
      odd = 0;
    a[i] >>= 1;
    if (lastback == 1)
      a[i] |= 0x80;
    lastback = odd;
  }
  if (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    1133 <shiftright+0x33>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
sar    $0x1,%edx
mov    %dl,(%rax,%rcx,1)
movl   $0x0,-0x4(%rbp)
jmp    121f <shiftright+0x11f>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     1157 <shiftright+0x57>
movl   $0x1,-0x24(%rbp)
jmp    115e <shiftright+0x5e>
movl   $0x0,-0x24(%rbp)
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
sar    $0x1,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
sub    $0x1,%eax
mov    %eax,-0x18(%rbp)
cmpl   $0x0,-0x18(%rbp)
jl     11f3 <shiftright+0xf3>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     11a7 <shiftright+0xa7>
movl   $0x1,-0x20(%rbp)
jmp    11ae <shiftright+0xae>
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   $0x1,-0x24(%rbp)
jne    11df <shiftright+0xdf>
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    $0xffffffff,%eax
mov    %eax,-0x18(%rbp)
jmp    1179 <shiftright+0x79>
mov    -0x10(%rbp),%rax
movslq -0x14(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
cmp    $0x0,%eax
jne    1219 <shiftright+0x119>
mov    -0x14(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x14(%rbp)
mov    %eax,-0x4(%rbp)
jmp    121f <shiftright+0x11f>
mov    -0x14(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<shiftright>:
push   %r14
push   %rbx
test   %esi,%esi
je     1248 <shiftright+0x148>
mov    %esi,%eax
movslq %esi,%r9
mov    (%rdi,%r9,1),%cl
mov    %ecx,%edx
shr    %dl
mov    %dl,(%rdi,%r9,1)
test   %esi,%esi
jle    1288 <shiftright+0x188>
mov    %eax,%r8d
cmp    $0x10,%eax
jb     124e <shiftright+0x14e>
lea    -0x1(%r8),%rdx
lea    -0x1(%rax),%r10d
cmp    %edx,%r10d
jb     124e <shiftright+0x14e>
shr    $0x20,%rdx
jne    124e <shiftright+0x14e>
mov    %r8d,%r11d
and    $0xfffffff0,%r11d
mov    %r8d,%r14d
and    $0xf,%r14d
mov    %eax,%esi
sub    %r11d,%esi
movzbl %cl,%ecx
movd   %ecx,%xmm4
pslldq $0xf,%xmm4
pxor   %xmm0,%xmm0
movdqa 0xe8a(%rip),%xmm1
movdqa 0xe92(%rip),%xmm2
mov    %r11,%rcx
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
mov    %r10d,%ebx
movdqu -0xf(%rdi,%rbx,1),%xmm3
movdqa %xmm3,%xmm5
punpcklbw %xmm0,%xmm5
pshufd $0x4e,%xmm5,%xmm5
pshuflw $0x1b,%xmm5,%xmm5
pshufhw $0x1b,%xmm5,%xmm6
movdqa %xmm3,%xmm5
punpckhbw %xmm0,%xmm5
pshufd $0x4e,%xmm5,%xmm5
pshuflw $0x1b,%xmm5,%xmm5
pshufhw $0x1b,%xmm5,%xmm5
packuswb %xmm6,%xmm5
movdqa %xmm5,%xmm6
pslldq $0x1,%xmm6
psrldq $0xf,%xmm4
por    %xmm6,%xmm4
movdqa %xmm5,%xmm6
psrlw  $0x1,%xmm6
pand   %xmm1,%xmm6
psllw  $0x7,%xmm4
pand   %xmm2,%xmm4
por    %xmm6,%xmm4
movdqa %xmm4,%xmm6
punpcklbw %xmm0,%xmm6
pshufd $0x4e,%xmm6,%xmm6
pshuflw $0x1b,%xmm6,%xmm6
pshufhw $0x1b,%xmm6,%xmm6
punpckhbw %xmm0,%xmm4
pshufd $0x4e,%xmm4,%xmm4
pshuflw $0x1b,%xmm4,%xmm4
pshufhw $0x1b,%xmm4,%xmm4
packuswb %xmm6,%xmm4
movdqu %xmm4,-0xf(%rdi,%rbx,1)
add    $0xfffffff0,%r10d
movdqa %xmm5,%xmm4
add    $0xfffffffffffffff0,%rcx
jne    1190 <shiftright+0x90>
cmp    %r8,%r11
je     1284 <shiftright+0x184>
movd   %xmm3,%ecx
jmp    1253 <shiftright+0x153>
shrb   (%rdi)
xor    %eax,%eax
jmp    128e <shiftright+0x18e>
mov    %r8,%r14
mov    %eax,%esi
add    $0x1,%r14
add    $0xffffffff,%esi
nopw   0x0(%rax,%rax,1)
mov    %esi,%ebx
movzbl (%rdi,%rbx,1),%r8d
mov    %r8d,%edx
shr    %dl
shl    $0x7,%cl
or     %dl,%cl
mov    %cl,(%rdi,%rbx,1)
add    $0xffffffffffffffff,%r14
add    $0xffffffff,%esi
mov    %r8d,%ecx
cmp    $0x1,%r14
ja     1260 <shiftright+0x160>
mov    (%rdi,%r9,1),%dl
cmp    $0x1,%dl
sbb    $0x0,%eax
pop    %rbx
pop    %r14
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 %21
12: ; preds = %2
%13 = load i8*, i8** %4
%14 = load i32, i32* %5
%15 = sext i32 %14 to i64
%16 = getelementptr inbounds i8, i8* %13, i64 %15
%17 = load i8, i8* %16
%18 = zext i8 %17 to i32
%19 = ashr i32 %18, 1
%20 = trunc i32 %19 to i8
store i8 %20, i8* %16
store i32 0, i32* %3
br label %95
21: ; preds = %2
%22 = load i8*, i8** %4
%23 = load i32, i32* %5
%24 = sext i32 %23 to i64
%25 = getelementptr inbounds i8, i8* %22, i64 %24
%26 = load i8, i8* %25
%27 = zext i8 %26 to i32
%28 = and i32 %27, 1
%29 = icmp ne i32 %28, 0
br i1 %29, label %30, label %31
30: ; preds = %21
store i32 1, i32* %9
br label %32
31: ; preds = %21
store i32 0, i32* %9
br label %32
32: ; preds = %31, %30
%33 = load i8*, i8** %4
%34 = load i32, i32* %5
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds i8, i8* %33, 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 %41, 1
store i32 %42, i32* %6
br label %43
43: ; preds = %79, %32
%44 = load i32, i32* %6
%45 = icmp sge i32 %44, 0
br i1 %45, label %46, label %82
46: ; preds = %43
%47 = load i8*, i8** %4
%48 = load i32, i32* %6
%49 = sext i32 %48 to i64
%50 = getelementptr inbounds i8, i8* %47, i64 %49
%51 = load i8, i8* %50
%52 = zext i8 %51 to i32
%53 = and i32 %52, 1
%54 = icmp ne i32 %53, 0
br i1 %54, label %55, label %56
55: ; preds = %46
store i32 1, i32* %8
br label %57
56: ; preds = %46
store i32 0, i32* %8
br label %57
57: ; preds = %56, %55
%58 = load i8*, i8** %4
%59 = load i32, i32* %6
%60 = sext i32 %59 to i64
%61 = getelementptr inbounds i8, i8* %58, i64 %60
%62 = load i8, i8* %61
%63 = zext i8 %62 to i32
%64 = ashr i32 %63, 1
%65 = trunc i32 %64 to i8
store i8 %65, i8* %61
%66 = load i32, i32* %9
%67 = icmp eq i32 %66, 1
br i1 %67, label %68, label %77
68: ; preds = %57
%69 = load i8*, i8** %4
%70 = load i32, i32* %6
%71 = sext i32 %70 to i64
%72 = getelementptr inbounds i8, i8* %69, i64 %71
%73 = load i8, i8* %72
%74 = zext i8 %73 to i32
%75 = or i32 %74, 128
%76 = trunc i32 %75 to i8
store i8 %76, i8* %72
br label %77
77: ; preds = %68, %57
%78 = load i32, i32* %8
store i32 %78, i32* %9
br label %79
79: ; preds = %77
%80 = load i32, i32* %6
%81 = add nsw i32 %80, -1
store i32 %81, i32* %6
br label %43
82: ; preds = %43
%83 = load i8*, i8** %4
%84 = load i32, i32* %5
%85 = sext i32 %84 to i64
%86 = getelementptr inbounds i8, i8* %83, i64 %85
%87 = load i8, i8* %86
%88 = zext i8 %87 to i32
%89 = icmp eq i32 %88, 0
br i1 %89, label %90, label %93
90: ; preds = %82
%91 = load i32, i32* %5
%92 = add nsw i32 %91, -1
store i32 %92, i32* %5
store i32 %92, i32* %3
br label %95
93: ; preds = %82
%94 = load i32, i32* %5
store i32 %94, i32* %3
br label %95
95: ; preds = %93, %90, %12
%96 = load i32, i32* %3
ret i32 %96
}

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