#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
void ocb_block_lshift(const unsigned char *in, size_t shift,
                      unsigned char *out) {
  unsigned char shift_mask;
  int i;
  unsigned char mask[15];
  shift_mask = 0xff;
  shift_mask <<= (8 - shift);
  for (i = 15; i >= 0; i--) {
    if (i > 0) {
      mask[i - 1] = in[i] & shift_mask;
      mask[i - 1] >>= 8 - shift;
    }
    out[i] = in[i] << shift;
    if (i != 15) {
      out[i] ^= mask[i];
    }
  }
}


x86 assembly (clang, -O0):
<ocb_block_lshift>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movb   $0xff,-0x19(%rbp)
mov    $0x8,%ecx
sub    -0x10(%rbp),%rcx
movzbl -0x19(%rbp),%eax
shl    %cl,%eax
mov    %al,-0x19(%rbp)
movl   $0xf,-0x20(%rbp)
cmpl   $0x0,-0x20(%rbp)
jl     11d5 <ocb_block_lshift+0xd5>
cmpl   $0x0,-0x20(%rbp)
jle    117f <ocb_block_lshift+0x7f>
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
movzbl -0x19(%rbp),%ecx
and    %ecx,%eax
mov    %al,%cl
mov    -0x20(%rbp),%eax
sub    $0x1,%eax
cltq
mov    %cl,-0x2f(%rbp,%rax,1)
mov    $0x8,%ecx
sub    -0x10(%rbp),%rcx
mov    -0x20(%rbp),%eax
sub    $0x1,%eax
cltq
movzbl -0x2f(%rbp,%rax,1),%edx
sar    %cl,%edx
mov    %edx,%ecx
mov    %cl,-0x2f(%rbp,%rax,1)
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x10(%rbp),%rcx
shl    %cl,%eax
mov    %al,%dl
mov    -0x18(%rbp),%rax
movslq -0x20(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
cmpl   $0xf,-0x20(%rbp)
je     11c2 <ocb_block_lshift+0xc2>
movslq -0x20(%rbp),%rax
movzbl -0x2f(%rbp,%rax,1),%esi
mov    -0x18(%rbp),%rax
movslq -0x20(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
xor    %esi,%edx
mov    %dl,(%rax,%rcx,1)
jmp    11c7 <ocb_block_lshift+0xc7>
mov    -0x20(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x20(%rbp)
jmp    112d <ocb_block_lshift+0x2d>
pop    %rbp
ret

x86 assembly (clang, -O2):
<ocb_block_lshift>:
push   %rbx
mov    %rsi,%r8
mov    $0x8,%r9d
sub    %r8d,%r9d
mov    $0xff,%r10d
mov    %r9d,%ecx
shl    %cl,%r10d
movzbl 0xf(%rdi),%esi
mov    %r10d,%eax
and    %esi,%eax
shr    %cl,%eax
movzbl %r10b,%r10d
mov    %r8d,%ecx
shl    %cl,%esi
mov    %al,-0x1(%rsp)
mov    %sil,0xf(%rdx)
mov    $0xe,%eax
mov    $0xe,%r11d
movzbl (%rdi,%rax,1),%esi
mov    %esi,%ebx
and    %r10d,%ebx
mov    %r9d,%ecx
shr    %cl,%ebx
mov    %bl,-0x10(%rsp,%rax,1)
mov    %r8d,%ecx
shl    %cl,%esi
xor    -0xf(%rsp,%rax,1),%sil
mov    %sil,(%rdx,%rax,1)
movzbl -0x1(%rdi,%rax,1),%esi
mov    %esi,%ebx
and    %r10d,%ebx
mov    %r9d,%ecx
shr    %cl,%ebx
mov    %r8d,%ecx
shl    %cl,%esi
xor    -0x10(%rsp,%rax,1),%sil
mov    %bl,-0x11(%rsp,%rax,1)
mov    %sil,-0x1(%rdx,%rax,1)
add    $0xfffffffffffffffe,%r11
mov    %r11,%rax
jne    1140 <ocb_block_lshift+0x40>
movzbl (%rdi),%eax
mov    %r8d,%ecx
shl    %cl,%eax
xor    -0xf(%rsp),%al
mov    %al,(%rdx)
pop    %rbx
ret

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

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