unsigned char getmask(unsigned char *OutData, unsigned char *Mask,
                      unsigned char I, unsigned char J) {
  unsigned char K, B, M, M1, D, DI, MI;
  K = I ^ J;
  DI = 7;
  if ((K & 4) == 4) {
    K ^= 7;
    DI ^= 7;
  }
  MI = 3;
  MI &= J;
  K ^= MI;
  K += MI;
  if ((K & 4) == 4) {
    return 0;
  }
  DI ^= J;
  D = OutData[DI];
  MI = 0;
  MI += J;
  M1 = Mask[MI];
  MI ^= 4;
  M = Mask[MI];
  B = 0;
  for (K = 0; K <= 7; K++) {
    if ((D & 1) == 1) {
      B += M;
    }
    D = (D >> 1) + ((B & 1) << 7);
    B = B >> 1;
  }
  return D ^ M1;
}


x86 assembly (clang, -O0):
<getmask>:
push   %rbp
mov    %rsp,%rbp
mov    %cl,%al
mov    %dl,%cl
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %cl,-0x19(%rbp)
mov    %al,-0x1a(%rbp)
movzbl -0x19(%rbp),%eax
movzbl -0x1a(%rbp),%ecx
xor    %ecx,%eax
mov    %al,-0x1b(%rbp)
movb   $0x7,-0x20(%rbp)
movzbl -0x1b(%rbp),%eax
and    $0x4,%eax
cmp    $0x4,%eax
jne    114b <getmask+0x4b>
movzbl -0x1b(%rbp),%eax
xor    $0x7,%eax
mov    %al,-0x1b(%rbp)
movzbl -0x20(%rbp),%eax
xor    $0x7,%eax
mov    %al,-0x20(%rbp)
movb   $0x3,-0x21(%rbp)
movzbl -0x1a(%rbp),%ecx
movzbl -0x21(%rbp),%eax
and    %ecx,%eax
mov    %al,-0x21(%rbp)
movzbl -0x21(%rbp),%ecx
movzbl -0x1b(%rbp),%eax
xor    %ecx,%eax
mov    %al,-0x1b(%rbp)
movzbl -0x21(%rbp),%ecx
movzbl -0x1b(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x1b(%rbp)
movzbl -0x1b(%rbp),%eax
and    $0x4,%eax
cmp    $0x4,%eax
jne    118f <getmask+0x8f>
movb   $0x0,-0x1(%rbp)
jmp    124d <getmask+0x14d>
movzbl -0x1a(%rbp),%ecx
movzbl -0x20(%rbp),%eax
xor    %ecx,%eax
mov    %al,-0x20(%rbp)
mov    -0x10(%rbp),%rax
movzbl -0x20(%rbp),%ecx
mov    (%rax,%rcx,1),%al
mov    %al,-0x1f(%rbp)
movb   $0x0,-0x21(%rbp)
movzbl -0x1a(%rbp),%ecx
movzbl -0x21(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x21(%rbp)
mov    -0x18(%rbp),%rax
movzbl -0x21(%rbp),%ecx
mov    (%rax,%rcx,1),%al
mov    %al,-0x1e(%rbp)
movzbl -0x21(%rbp),%eax
xor    $0x4,%eax
mov    %al,-0x21(%rbp)
mov    -0x18(%rbp),%rax
movzbl -0x21(%rbp),%ecx
mov    (%rax,%rcx,1),%al
mov    %al,-0x1d(%rbp)
movb   $0x0,-0x1c(%rbp)
movb   $0x0,-0x1b(%rbp)
movzbl -0x1b(%rbp),%eax
cmp    $0x7,%eax
jg     1240 <getmask+0x140>
movzbl -0x1f(%rbp),%eax
and    $0x1,%eax
cmp    $0x1,%eax
jne    1213 <getmask+0x113>
movzbl -0x1d(%rbp),%ecx
movzbl -0x1c(%rbp),%eax
add    %ecx,%eax
mov    %al,-0x1c(%rbp)
movzbl -0x1f(%rbp),%eax
sar    $0x1,%eax
movzbl -0x1c(%rbp),%ecx
and    $0x1,%ecx
shl    $0x7,%ecx
add    %ecx,%eax
mov    %al,-0x1f(%rbp)
movzbl -0x1c(%rbp),%eax
sar    $0x1,%eax
mov    %al,-0x1c(%rbp)
mov    -0x1b(%rbp),%al
add    $0x1,%al
mov    %al,-0x1b(%rbp)
jmp    11e9 <getmask+0xe9>
movzbl -0x1f(%rbp),%eax
movzbl -0x1e(%rbp),%ecx
xor    %ecx,%eax
mov    %al,-0x1(%rbp)
movzbl -0x1(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<getmask>:
xor    %ecx,%edx
mov    %edx,%eax
shr    $0x2,%al
and    $0x1,%al
neg    %al
mov    %ecx,%r8d
and    $0x3,%r8b
mov    %r8d,%r9d
xor    %dl,%r9b
xor    %al,%r9b
add    %r8b,%r9b
xor    %eax,%eax
test   $0x4,%r9b
jne    1200 <getmask+0x100>
test   $0x4,%dl
mov    $0x7,%edx
cmove  %edx,%eax
xor    %cl,%al
movzbl %al,%eax
mov    (%rdi,%rax,1),%dil
movzbl %cl,%r8d
mov    %r8,%rdx
xor    $0x4,%rdx
mov    (%rsi,%rdx,1),%r9b
mov    %edi,%eax
and    $0x1,%al
neg    %al
and    %r9b,%al
shr    %dil
mov    %eax,%edx
shl    $0x7,%dl
or     %dil,%dl
shr    %al
mov    %edx,%ecx
and    $0x1,%cl
neg    %cl
and    %r9b,%cl
add    %al,%cl
shr    %dl
mov    %ecx,%eax
shl    $0x7,%al
or     %dl,%al
shr    %cl
mov    %eax,%edx
and    $0x1,%dl
neg    %dl
and    %r9b,%dl
add    %cl,%dl
shr    %al
mov    %edx,%ecx
shl    $0x7,%cl
or     %al,%cl
shr    %dl
mov    %ecx,%eax
and    $0x1,%al
neg    %al
and    %r9b,%al
add    %dl,%al
shr    %cl
mov    %eax,%edx
shl    $0x7,%dl
or     %cl,%dl
shr    %al
mov    %edx,%ecx
and    $0x1,%cl
neg    %cl
and    %r9b,%cl
add    %al,%cl
shr    %dl
mov    %ecx,%edi
shl    $0x7,%dil
or     %dl,%dil
shr    %cl
mov    %edi,%edx
and    $0x1,%dl
neg    %dl
and    %r9b,%dl
add    %cl,%dl
shr    %dil
mov    %edx,%eax
shl    $0x7,%al
or     %dil,%al
shr    %dl
mov    %eax,%ecx
and    $0x1,%cl
neg    %cl
and    %r9b,%cl
add    %dl,%cl
shr    %al
mov    %ecx,%edx
shl    $0x7,%dl
or     %al,%dl
shr    %cl
and    %r9b,%al
add    %cl,%al
shr    %dl
shl    $0x7,%al
or     %dl,%al
xor    (%rsi,%r8,1),%al
ret

LLVM IR (-O0):
define zeroext i8 @getmask(i8* %0, i8* %1, i8 zeroext %2, i8 zeroext %3) {
%5 = alloca i8
%6 = alloca i8*
%7 = alloca i8*
%8 = alloca i8
%9 = alloca i8
%10 = alloca i8
%11 = alloca i8
%12 = alloca i8
%13 = alloca i8
%14 = alloca i8
%15 = alloca i8
%16 = alloca i8
store i8* %0, i8** %6
store i8* %1, i8** %7
store i8 %2, i8* %8
store i8 %3, i8* %9
%17 = load i8, i8* %8
%18 = zext i8 %17 to i32
%19 = load i8, i8* %9
%20 = zext i8 %19 to i32
%21 = xor i32 %18, %20
%22 = trunc i32 %21 to i8
store i8 %22, i8* %10
store i8 7, i8* %15
%23 = load i8, i8* %10
%24 = zext i8 %23 to i32
%25 = and i32 %24, 4
%26 = icmp eq i32 %25, 4
br i1 %26, label %27, label %36
27: ; preds = %4
%28 = load i8, i8* %10
%29 = zext i8 %28 to i32
%30 = xor i32 %29, 7
%31 = trunc i32 %30 to i8
store i8 %31, i8* %10
%32 = load i8, i8* %15
%33 = zext i8 %32 to i32
%34 = xor i32 %33, 7
%35 = trunc i32 %34 to i8
store i8 %35, i8* %15
br label %36
36: ; preds = %27, %4
store i8 3, i8* %16
%37 = load i8, i8* %9
%38 = zext i8 %37 to i32
%39 = load i8, i8* %16
%40 = zext i8 %39 to i32
%41 = and i32 %40, %38
%42 = trunc i32 %41 to i8
store i8 %42, i8* %16
%43 = load i8, i8* %16
%44 = zext i8 %43 to i32
%45 = load i8, i8* %10
%46 = zext i8 %45 to i32
%47 = xor i32 %46, %44
%48 = trunc i32 %47 to i8
store i8 %48, i8* %10
%49 = load i8, i8* %16
%50 = zext i8 %49 to i32
%51 = load i8, i8* %10
%52 = zext i8 %51 to i32
%53 = add nsw i32 %52, %50
%54 = trunc i32 %53 to i8
store i8 %54, i8* %10
%55 = load i8, i8* %10
%56 = zext i8 %55 to i32
%57 = and i32 %56, 4
%58 = icmp eq i32 %57, 4
br i1 %58, label %59, label %60
59: ; preds = %36
store i8 0, i8* %5
br label %132
60: ; preds = %36
%61 = load i8, i8* %9
%62 = zext i8 %61 to i32
%63 = load i8, i8* %15
%64 = zext i8 %63 to i32
%65 = xor i32 %64, %62
%66 = trunc i32 %65 to i8
store i8 %66, i8* %15
%67 = load i8*, i8** %6
%68 = load i8, i8* %15
%69 = zext i8 %68 to i64
%70 = getelementptr inbounds i8, i8* %67, i64 %69
%71 = load i8, i8* %70
store i8 %71, i8* %14
store i8 0, i8* %16
%72 = load i8, i8* %9
%73 = zext i8 %72 to i32
%74 = load i8, i8* %16
%75 = zext i8 %74 to i32
%76 = add nsw i32 %75, %73
%77 = trunc i32 %76 to i8
store i8 %77, i8* %16
%78 = load i8*, i8** %7
%79 = load i8, i8* %16
%80 = zext i8 %79 to i64
%81 = getelementptr inbounds i8, i8* %78, i64 %80
%82 = load i8, i8* %81
store i8 %82, i8* %13
%83 = load i8, i8* %16
%84 = zext i8 %83 to i32
%85 = xor i32 %84, 4
%86 = trunc i32 %85 to i8
store i8 %86, i8* %16
%87 = load i8*, i8** %7
%88 = load i8, i8* %16
%89 = zext i8 %88 to i64
%90 = getelementptr inbounds i8, i8* %87, i64 %89
%91 = load i8, i8* %90
store i8 %91, i8* %12
store i8 0, i8* %11
store i8 0, i8* %10
br label %92
92: ; preds = %122, %60
%93 = load i8, i8* %10
%94 = zext i8 %93 to i32
%95 = icmp sle i32 %94, 7
br i1 %95, label %96, label %125
96: ; preds = %92
%97 = load i8, i8* %14
%98 = zext i8 %97 to i32
%99 = and i32 %98, 1
%100 = icmp eq i32 %99, 1
br i1 %100, label %101, label %108
101: ; preds = %96
%102 = load i8, i8* %12
%103 = zext i8 %102 to i32
%104 = load i8, i8* %11
%105 = zext i8 %104 to i32
%106 = add nsw i32 %105, %103
%107 = trunc i32 %106 to i8
store i8 %107, i8* %11
br label %108
108: ; preds = %101, %96
%109 = load i8, i8* %14
%110 = zext i8 %109 to i32
%111 = ashr i32 %110, 1
%112 = load i8, i8* %11
%113 = zext i8 %112 to i32
%114 = and i32 %113, 1
%115 = shl i32 %114, 7
%116 = add nsw i32 %111, %115
%117 = trunc i32 %116 to i8
store i8 %117, i8* %14
%118 = load i8, i8* %11
%119 = zext i8 %118 to i32
%120 = ashr i32 %119, 1
%121 = trunc i32 %120 to i8
store i8 %121, i8* %11
br label %122
122: ; preds = %108
%123 = load i8, i8* %10
%124 = add i8 %123, 1
store i8 %124, i8* %10
br label %92
125: ; preds = %92
%126 = load i8, i8* %14
%127 = zext i8 %126 to i32
%128 = load i8, i8* %13
%129 = zext i8 %128 to i32
%130 = xor i32 %127, %129
%131 = trunc i32 %130 to i8
store i8 %131, i8* %5
br label %132
132: ; preds = %125, %59
%133 = load i8, i8* %5
ret i8 %133
}

LLVM IR (-O2):
define zeroext i8 @getmask(i8* nocapture %0, i8* nocapture %1, i8 zeroext %2, i8 zeroext %3) {
%5 = xor i8 %3, %2
%6 = and i8 %5, 4
%7 = icmp eq i8 %6, 0
%8 = xor i1 %7, true
%9 = sext i1 %8 to i8
%10 = and i8 %3, 3
%11 = xor i8 %10, %5
%12 = xor i8 %11, %9
%13 = add i8 %12, %10
%14 = and i8 %13, 4
%15 = icmp eq i8 %14, 0
br i1 %15, label %16, label %76
16: ; preds = %4
%17 = select i1 %7, i8 7, i8 0
%18 = xor i8 %17, %3
%19 = zext i8 %18 to i64
%20 = getelementptr inbounds i8, i8* %0, i64 %19
%21 = load i8, i8* %20
%22 = zext i8 %3 to i64
%23 = getelementptr inbounds i8, i8* %1, i64 %22
%24 = load i8, i8* %23
%25 = xor i8 %3, 4
%26 = zext i8 %25 to i64
%27 = getelementptr inbounds i8, i8* %1, i64 %26
%28 = load i8, i8* %27
%29 = and i8 %21, 1
%30 = icmp eq i8 %29, 0
%31 = select i1 %30, i8 0, i8 %28
%32 = tail call i8 @llvm.fshl.i8(i8 %31, i8 %21, i8 7)
%33 = lshr i8 %31, 1
%34 = and i8 %32, 1
%35 = icmp eq i8 %34, 0
%36 = select i1 %35, i8 0, i8 %28
%37 = add i8 %36, %33
%38 = tail call i8 @llvm.fshl.i8(i8 %37, i8 %32, i8 7)
%39 = lshr i8 %37, 1
%40 = and i8 %38, 1
%41 = icmp eq i8 %40, 0
%42 = select i1 %41, i8 0, i8 %28
%43 = add i8 %42, %39
%44 = tail call i8 @llvm.fshl.i8(i8 %43, i8 %38, i8 7)
%45 = lshr i8 %43, 1
%46 = and i8 %44, 1
%47 = icmp eq i8 %46, 0
%48 = select i1 %47, i8 0, i8 %28
%49 = add i8 %48, %45
%50 = tail call i8 @llvm.fshl.i8(i8 %49, i8 %44, i8 7)
%51 = lshr i8 %49, 1
%52 = and i8 %50, 1
%53 = icmp eq i8 %52, 0
%54 = select i1 %53, i8 0, i8 %28
%55 = add i8 %54, %51
%56 = tail call i8 @llvm.fshl.i8(i8 %55, i8 %50, i8 7)
%57 = lshr i8 %55, 1
%58 = and i8 %56, 1
%59 = icmp eq i8 %58, 0
%60 = select i1 %59, i8 0, i8 %28
%61 = add i8 %60, %57
%62 = tail call i8 @llvm.fshl.i8(i8 %61, i8 %56, i8 7)
%63 = lshr i8 %61, 1
%64 = and i8 %62, 1
%65 = icmp eq i8 %64, 0
%66 = select i1 %65, i8 0, i8 %28
%67 = add i8 %66, %63
%68 = tail call i8 @llvm.fshl.i8(i8 %67, i8 %62, i8 7)
%69 = lshr i8 %67, 1
%70 = and i8 %68, 1
%71 = icmp eq i8 %70, 0
%72 = select i1 %71, i8 0, i8 %28
%73 = add i8 %72, %69
%74 = tail call i8 @llvm.fshl.i8(i8 %73, i8 %68, i8 7)
%75 = xor i8 %74, %24
br label %76
76: ; preds = %4, %16
%77 = phi i8 [ %75, %16 ], [ 0, %4 ]
ret i8 %77
}