void RightShift(unsigned char *pc, int s, int n) {
  int i;
  for (i = 0; i < s - 1; ++i) {
    pc[i] >>= n;
    pc[i] |= (pc[i + 1] << (8 - n));
  }
  pc[i] >>= n;
}


x86 assembly (clang, -O0):
<RightShift>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
mov    -0x14(%rbp),%eax
mov    -0xc(%rbp),%ecx
sub    $0x1,%ecx
cmp    %ecx,%eax
jge    117c <RightShift+0x7c>
mov    -0x10(%rbp),%ecx
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rdx
mov    %rdx,-0x20(%rbp)
movzbl (%rax,%rdx,1),%edx
sar    %cl,%edx
mov    -0x20(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movzbl (%rax,%rcx,1),%esi
mov    $0x8,%ecx
sub    -0x10(%rbp),%ecx
shl    %cl,%esi
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
or     %esi,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    1115 <RightShift+0x15>
mov    -0x10(%rbp),%ecx
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rdx
mov    %rdx,-0x28(%rbp)
movzbl (%rax,%rdx,1),%edx
sar    %cl,%edx
mov    -0x28(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
pop    %rbp
ret

x86 assembly (clang, -O2):
<RightShift>:
mov    %edx,%r8d
cmp    $0x2,%esi
jl     1126 <RightShift+0x26>
add    $0xffffffff,%esi
mov    $0x8,%r9d
sub    %r8d,%r9d
mov    %esi,%r10d
mov    (%rdi),%r11b
cmp    $0x10,%esi
jae    112e <RightShift+0x2e>
xor    %esi,%esi
jmp    1260 <RightShift+0x160>
xor    %r10d,%r10d
jmp    1288 <RightShift+0x188>
mov    %r10d,%esi
and    $0xfffffff0,%esi
movzbl %r11b,%eax
movd   %eax,%xmm12
pslldq $0xf,%xmm12
movd   %r8d,%xmm0
movd   %r9d,%xmm3
xor    %ecx,%ecx
pxor   %xmm11,%xmm11
xorps  %xmm9,%xmm9
movss  %xmm0,%xmm9
xorps  %xmm10,%xmm10
movss  %xmm3,%xmm10
movdqa 0xe91(%rip),%xmm8
nop
movdqa %xmm12,%xmm5
movdqu 0x1(%rdi,%rcx,1),%xmm12
movdqa %xmm12,%xmm7
pslldq $0x1,%xmm7
psrldq $0xf,%xmm5
por    %xmm7,%xmm5
punpcklbw %xmm11,%xmm5
movdqa %xmm5,%xmm6
punpcklwd %xmm11,%xmm6
punpckhwd %xmm11,%xmm5
punpckhbw %xmm11,%xmm7
movdqa %xmm7,%xmm1
punpcklwd %xmm11,%xmm1
punpckhwd %xmm11,%xmm7
psrld  %xmm9,%xmm7
psrld  %xmm9,%xmm1
psrld  %xmm9,%xmm5
psrld  %xmm9,%xmm6
movdqa %xmm12,%xmm0
punpcklbw %xmm11,%xmm0
movdqa %xmm0,%xmm4
punpcklwd %xmm11,%xmm4
punpckhwd %xmm11,%xmm0
movdqa %xmm12,%xmm3
punpckhbw %xmm11,%xmm3
movdqa %xmm3,%xmm2
punpcklwd %xmm11,%xmm2
punpckhwd %xmm11,%xmm3
pslld  %xmm10,%xmm3
por    %xmm7,%xmm3
pslld  %xmm10,%xmm2
por    %xmm1,%xmm2
pslld  %xmm10,%xmm0
pslld  %xmm10,%xmm4
por    %xmm5,%xmm0
por    %xmm6,%xmm4
pand   %xmm8,%xmm3
pand   %xmm8,%xmm2
packuswb %xmm3,%xmm2
pand   %xmm8,%xmm0
pand   %xmm8,%xmm4
packuswb %xmm0,%xmm4
packuswb %xmm2,%xmm4
movdqu %xmm4,(%rdi,%rcx,1)
add    $0x10,%rcx
cmp    %rcx,%rsi
jne    1170 <RightShift+0x70>
cmp    %r10,%rsi
je     1288 <RightShift+0x188>
pextrw $0x7,%xmm12,%r11d
shr    $0x8,%r11d
xchg   %ax,%ax
movzbl %r11b,%edx
mov    %r8d,%ecx
shr    %cl,%edx
movzbl 0x1(%rdi,%rsi,1),%r11d
mov    %r11d,%eax
mov    %r9d,%ecx
shl    %cl,%eax
or     %edx,%eax
mov    %al,(%rdi,%rsi,1)
lea    0x1(%rsi),%rax
mov    %rax,%rsi
cmp    %rax,%r10
jne    1260 <RightShift+0x160>
movzbl (%rdi,%r10,1),%eax
mov    %r8d,%ecx
shr    %cl,%eax
mov    %al,(%rdi,%r10,1)
ret

LLVM IR (-O0):
define void @RightShift(i8* %0, i32 %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
store i8* %0, i8** %4
store i32 %1, i32* %5
store i32 %2, i32* %6
store i32 0, i32* %7
br label %8
8: ; preds = %41, %3
%9 = load i32, i32* %7
%10 = load i32, i32* %5
%11 = sub nsw i32 %10, 1
%12 = icmp slt i32 %9, %11
br i1 %12, label %13, label %44
13: ; preds = %8
%14 = load i32, i32* %6
%15 = load i8*, i8** %4
%16 = load i32, i32* %7
%17 = sext i32 %16 to i64
%18 = getelementptr inbounds i8, i8* %15, i64 %17
%19 = load i8, i8* %18
%20 = zext i8 %19 to i32
%21 = ashr i32 %20, %14
%22 = trunc i32 %21 to i8
store i8 %22, i8* %18
%23 = load i8*, i8** %4
%24 = load i32, i32* %7
%25 = add nsw i32 %24, 1
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds i8, i8* %23, i64 %26
%28 = load i8, i8* %27
%29 = zext i8 %28 to i32
%30 = load i32, i32* %6
%31 = sub nsw i32 8, %30
%32 = shl i32 %29, %31
%33 = load i8*, i8** %4
%34 = load i32, i32* %7
%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 = or i32 %38, %32
%40 = trunc i32 %39 to i8
store i8 %40, i8* %36
br label %41
41: ; preds = %13
%42 = load i32, i32* %7
%43 = add nsw i32 %42, 1
store i32 %43, i32* %7
br label %8
44: ; preds = %8
%45 = load i32, i32* %6
%46 = load i8*, i8** %4
%47 = load i32, i32* %7
%48 = sext i32 %47 to i64
%49 = getelementptr inbounds i8, i8* %46, i64 %48
%50 = load i8, i8* %49
%51 = zext i8 %50 to i32
%52 = ashr i32 %51, %45
%53 = trunc i32 %52 to i8
store i8 %53, i8* %49
ret void
}

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