#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 */
typedef int uint8_t;

/* Variables and functions */
void memselect(void *out, const void *pa, const void *pb, size_t max,
               int flag) {
  uint8_t *a = (uint8_t *)pa;
  uint8_t *b = (uint8_t *)pb;
  uint8_t *p = (uint8_t *)out;
  uint8_t *endp = p + max;
  uint8_t mB = (flag & 1) - 1;
  uint8_t mA = ~mB;
  while (p < endp)
    *p++ = (mA & *a++) ^ (mB & *b++);
}


x86 assembly (clang, -O0):
<memselect>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8d,-0x24(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    -0x20(%rbp),%rcx
shl    $0x2,%rcx
add    %rcx,%rax
mov    %rax,-0x48(%rbp)
mov    -0x24(%rbp),%eax
and    $0x1,%eax
sub    $0x1,%eax
mov    %eax,-0x4c(%rbp)
mov    -0x4c(%rbp),%eax
xor    $0xffffffff,%eax
mov    %eax,-0x50(%rbp)
mov    -0x40(%rbp),%rax
cmp    -0x48(%rbp),%rax
jae    11a6 <memselect+0xa6>
mov    -0x50(%rbp),%ecx
mov    -0x30(%rbp),%rax
mov    %rax,%rdx
add    $0x4,%rdx
mov    %rdx,-0x30(%rbp)
and    (%rax),%ecx
mov    -0x4c(%rbp),%eax
mov    -0x38(%rbp),%rdx
mov    %rdx,%rsi
add    $0x4,%rsi
mov    %rsi,-0x38(%rbp)
and    (%rdx),%eax
xor    %eax,%ecx
mov    -0x40(%rbp),%rax
mov    %rax,%rdx
add    $0x4,%rdx
mov    %rdx,-0x40(%rbp)
mov    %ecx,(%rax)
jmp    1158 <memselect+0x58>
pop    %rbp
ret

x86 assembly (clang, -O2):
<memselect>:
push   %rbp
push   %r14
push   %rbx
lea    (%rdi,%rcx,4),%rax
cmp    %rdi,%rax
jbe    1162 <memselect+0x62>
and    $0x1,%r8d
lea    -0x1(%r8),%r11d
neg    %r8d
lea    0x4(%rdi),%rcx
cmp    %rcx,%rax
mov    %rcx,%r9
cmova  %rax,%r9
mov    %rdi,%rbx
not    %rbx
add    %rbx,%r9
cmp    $0x1c,%r9
jae    1167 <memselect+0x67>
xor    %ecx,%ecx
nopw   0x0(%rax,%rax,1)
mov    (%rsi,%rcx,1),%ebp
and    %r8d,%ebp
mov    (%rdx,%rcx,1),%ebx
and    %r11d,%ebx
xor    %ebp,%ebx
mov    %ebx,(%rdi,%rcx,1)
lea    (%rdi,%rcx,1),%rbp
add    $0x4,%rbp
add    $0x4,%rcx
cmp    %rax,%rbp
jb     1140 <memselect+0x40>
pop    %rbx
pop    %r14
pop    %rbp
ret
cmp    %rcx,%rax
cmova  %rax,%rcx
add    %rbx,%rcx
add    $0x4,%rcx
and    $0xfffffffffffffffc,%rcx
lea    (%rdi,%rcx,1),%rbx
lea    (%rsi,%rcx,1),%r10
add    %rdx,%rcx
cmp    %rdi,%r10
seta   %r10b
cmp    %rsi,%rbx
seta   %bpl
cmp    %rdi,%rcx
seta   %cl
cmp    %rdx,%rbx
seta   %bl
test   %bpl,%r10b
jne    1135 <memselect+0x35>
and    %bl,%cl
jne    1135 <memselect+0x35>
shr    $0x2,%r9
add    $0x1,%r9
mov    %r9,%r10
and    $0xfffffffffffffff8,%r10
movd   %r8d,%xmm0
pshufd $0x0,%xmm0,%xmm1
movd   %r11d,%xmm0
pshufd $0x0,%xmm0,%xmm0
lea    -0x8(%r10),%rcx
mov    %rcx,%r14
shr    $0x3,%r14
add    $0x1,%r14
test   %rcx,%rcx
je     12c8 <memselect+0x1c8>
mov    %r14,%rbx
and    $0xfffffffffffffffe,%rbx
xor    %ecx,%ecx
nopl   0x0(%rax,%rax,1)
movdqu (%rsi,%rcx,4),%xmm2
movdqu 0x10(%rsi,%rcx,4),%xmm3
pand   %xmm1,%xmm2
pand   %xmm1,%xmm3
movdqu (%rdx,%rcx,4),%xmm4
movdqu 0x10(%rdx,%rcx,4),%xmm5
pand   %xmm0,%xmm4
pxor   %xmm2,%xmm4
pand   %xmm0,%xmm5
pxor   %xmm3,%xmm5
movdqu %xmm4,(%rdi,%rcx,4)
movdqu %xmm5,0x10(%rdi,%rcx,4)
movdqu 0x20(%rsi,%rcx,4),%xmm2
movdqu 0x30(%rsi,%rcx,4),%xmm3
pand   %xmm1,%xmm2
pand   %xmm1,%xmm3
movdqu 0x20(%rdx,%rcx,4),%xmm4
movdqu 0x30(%rdx,%rcx,4),%xmm5
pand   %xmm0,%xmm4
pxor   %xmm2,%xmm4
pand   %xmm0,%xmm5
pxor   %xmm3,%xmm5
movdqu %xmm4,0x20(%rdi,%rcx,4)
movdqu %xmm5,0x30(%rdi,%rcx,4)
add    $0x10,%rcx
add    $0xfffffffffffffffe,%rbx
jne    11f0 <memselect+0xf0>
test   $0x1,%r14b
je     12ae <memselect+0x1ae>
movdqu (%rsi,%rcx,4),%xmm2
movdqu 0x10(%rsi,%rcx,4),%xmm3
pand   %xmm1,%xmm2
pand   %xmm1,%xmm3
movdqu (%rdx,%rcx,4),%xmm1
movdqu 0x10(%rdx,%rcx,4),%xmm4
pand   %xmm0,%xmm1
pxor   %xmm2,%xmm1
pand   %xmm0,%xmm4
pxor   %xmm3,%xmm4
movdqu %xmm1,(%rdi,%rcx,4)
movdqu %xmm4,0x10(%rdi,%rcx,4)
cmp    %r10,%r9
je     1162 <memselect+0x62>
lea    (%rsi,%r10,4),%rsi
lea    (%rdx,%r10,4),%rdx
lea    (%rdi,%r10,4),%rdi
jmp    1135 <memselect+0x35>
xor    %ecx,%ecx
test   $0x1,%r14b
jne    1275 <memselect+0x175>
jmp    12ae <memselect+0x1ae>

LLVM IR (-O0):
define void @memselect(i8* %0, i8* %1, i8* %2, i64 %3, i32 %4) {
%6 = alloca i8*
%7 = alloca i8*
%8 = alloca i8*
%9 = alloca i64
%10 = alloca i32
%11 = alloca i32*
%12 = alloca i32*
%13 = alloca i32*
%14 = alloca i32*
%15 = alloca i32
%16 = alloca i32
store i8* %0, i8** %6
store i8* %1, i8** %7
store i8* %2, i8** %8
store i64 %3, i64* %9
store i32 %4, i32* %10
%17 = load i8*, i8** %7
%18 = bitcast i8* %17 to i32*
store i32* %18, i32** %11
%19 = load i8*, i8** %8
%20 = bitcast i8* %19 to i32*
store i32* %20, i32** %12
%21 = load i8*, i8** %6
%22 = bitcast i8* %21 to i32*
store i32* %22, i32** %13
%23 = load i32*, i32** %13
%24 = load i64, i64* %9
%25 = getelementptr inbounds i32, i32* %23, i64 %24
store i32* %25, i32** %14
%26 = load i32, i32* %10
%27 = and i32 %26, 1
%28 = sub nsw i32 %27, 1
store i32 %28, i32* %15
%29 = load i32, i32* %15
%30 = xor i32 %29, -1
store i32 %30, i32* %16
br label %31
31: ; preds = %35, %5
%32 = load i32*, i32** %13
%33 = load i32*, i32** %14
%34 = icmp ult i32* %32, %33
br i1 %34, label %35, label %49
35: ; preds = %31
%36 = load i32, i32* %16
%37 = load i32*, i32** %11
%38 = getelementptr inbounds i32, i32* %37, i32 1
store i32* %38, i32** %11
%39 = load i32, i32* %37
%40 = and i32 %36, %39
%41 = load i32, i32* %15
%42 = load i32*, i32** %12
%43 = getelementptr inbounds i32, i32* %42, i32 1
store i32* %43, i32** %12
%44 = load i32, i32* %42
%45 = and i32 %41, %44
%46 = xor i32 %40, %45
%47 = load i32*, i32** %13
%48 = getelementptr inbounds i32, i32* %47, i32 1
store i32* %48, i32** %13
store i32 %46, i32* %47
br label %31
49: ; preds = %31
ret void
}

LLVM IR (-O2):
define void @memselect(i8* writeonly %0, i8* nocapture %1, i8* nocapture %2, i64 %3, i32 %4) {
%6 = ptrtoint i8* %0 to i64
%7 = bitcast i8* %0 to i32*
%8 = getelementptr inbounds i32, i32* %7, i64 %3
%9 = and i32 %4, 1
%10 = add nsw i32 %9, -1
%11 = sub nsw i32 0, %9
%12 = icmp ugt i32* %8, %7
br i1 %12, label %13, label %160
13: ; preds = %5
%14 = bitcast i8* %2 to i32*
%15 = bitcast i8* %1 to i32*
%16 = shl i64 %3, 2
%17 = add i64 %16, %6
%18 = add i64 %6, 4
%19 = call i64 @llvm.umax.i64(i64 %17, i64 %18)
%20 = xor i64 %6, -1
%21 = add i64 %19, %20
%22 = lshr i64 %21, 2
%23 = add nuw nsw i64 %22, 1
%24 = icmp ult i64 %21, 28
br i1 %24, label %143, label %25
25: ; preds = %13
%26 = shl i64 %3, 2
%27 = add i64 %26, %6
%28 = add i64 %6, 4
%29 = call i64 @llvm.umax.i64(i64 %27, i64 %28)
%30 = xor i64 %6, -1
%31 = add i64 %29, %30
%32 = add i64 %31, 4
%33 = and i64 %32, -4
%34 = getelementptr i8, i8* %0, i64 %33
%35 = getelementptr i8, i8* %1, i64 %33
%36 = getelementptr i8, i8* %2, i64 %33
%37 = icmp ugt i8* %35, %0
%38 = icmp ugt i8* %34, %1
%39 = and i1 %37, %38
%40 = icmp ugt i8* %36, %0
%41 = icmp ugt i8* %34, %2
%42 = and i1 %40, %41
%43 = or i1 %39, %42
br i1 %43, label %143, label %44
44: ; preds = %25
%45 = and i64 %23, 9223372036854775800
%46 = getelementptr i32, i32* %15, i64 %45
%47 = getelementptr i32, i32* %14, i64 %45
%48 = getelementptr i32, i32* %7, i64 %45
%49 = insertelement <4 x i32> poison, i32 %11, i64 0
%50 = shufflevector <4 x i32> %49, <4 x i32> poison, <4 x i32> zeroinitializer
%51 = insertelement <4 x i32> poison, i32 %11, i64 0
%52 = shufflevector <4 x i32> %51, <4 x i32> poison, <4 x i32> zeroinitializer
%53 = insertelement <4 x i32> poison, i32 %10, i64 0
%54 = shufflevector <4 x i32> %53, <4 x i32> poison, <4 x i32> zeroinitializer
%55 = insertelement <4 x i32> poison, i32 %10, i64 0
%56 = shufflevector <4 x i32> %55, <4 x i32> poison, <4 x i32> zeroinitializer
%57 = add nsw i64 %45, -8
%58 = lshr exact i64 %57, 3
%59 = add nuw nsw i64 %58, 1
%60 = and i64 %59, 1
%61 = icmp eq i64 %57, 0
br i1 %61, label %115, label %62
62: ; preds = %44
%63 = and i64 %59, 4611686018427387902
br label %64
64: ; preds = %64, %62
%65 = phi i64 [ 0, %62 ], [ %112, %64 ]
%66 = phi i64 [ 0, %62 ], [ %113, %64 ]
%67 = getelementptr i32, i32* %15, i64 %65
%68 = getelementptr i32, i32* %14, i64 %65
%69 = getelementptr i32, i32* %7, i64 %65
%70 = bitcast i32* %67 to <4 x i32>*
%71 = load <4 x i32>, <4 x i32>* %70
%72 = getelementptr i32, i32* %67, i64 4
%73 = bitcast i32* %72 to <4 x i32>*
%74 = load <4 x i32>, <4 x i32>* %73
%75 = and <4 x i32> %71, %50
%76 = and <4 x i32> %74, %52
%77 = bitcast i32* %68 to <4 x i32>*
%78 = load <4 x i32>, <4 x i32>* %77
%79 = getelementptr i32, i32* %68, i64 4
%80 = bitcast i32* %79 to <4 x i32>*
%81 = load <4 x i32>, <4 x i32>* %80
%82 = and <4 x i32> %78, %54
%83 = and <4 x i32> %81, %56
%84 = xor <4 x i32> %82, %75
%85 = xor <4 x i32> %83, %76
%86 = bitcast i32* %69 to <4 x i32>*
store <4 x i32> %84, <4 x i32>* %86
%87 = getelementptr i32, i32* %69, i64 4
%88 = bitcast i32* %87 to <4 x i32>*
store <4 x i32> %85, <4 x i32>* %88
%89 = or i64 %65, 8
%90 = getelementptr i32, i32* %15, i64 %89
%91 = getelementptr i32, i32* %14, i64 %89
%92 = getelementptr i32, i32* %7, i64 %89
%93 = bitcast i32* %90 to <4 x i32>*
%94 = load <4 x i32>, <4 x i32>* %93
%95 = getelementptr i32, i32* %90, i64 4
%96 = bitcast i32* %95 to <4 x i32>*
%97 = load <4 x i32>, <4 x i32>* %96
%98 = and <4 x i32> %94, %50
%99 = and <4 x i32> %97, %52
%100 = bitcast i32* %91 to <4 x i32>*
%101 = load <4 x i32>, <4 x i32>* %100
%102 = getelementptr i32, i32* %91, i64 4
%103 = bitcast i32* %102 to <4 x i32>*
%104 = load <4 x i32>, <4 x i32>* %103
%105 = and <4 x i32> %101, %54
%106 = and <4 x i32> %104, %56
%107 = xor <4 x i32> %105, %98
%108 = xor <4 x i32> %106, %99
%109 = bitcast i32* %92 to <4 x i32>*
store <4 x i32> %107, <4 x i32>* %109
%110 = getelementptr i32, i32* %92, i64 4
%111 = bitcast i32* %110 to <4 x i32>*
store <4 x i32> %108, <4 x i32>* %111
%112 = add nuw i64 %65, 16
%113 = add i64 %66, 2
%114 = icmp eq i64 %113, %63
br i1 %114, label %115, label %64
115: ; preds = %64, %44
%116 = phi i64 [ 0, %44 ], [ %112, %64 ]
%117 = icmp eq i64 %60, 0
br i1 %117, label %141, label %118
118: ; preds = %115
%119 = getelementptr i32, i32* %15, i64 %116
%120 = getelementptr i32, i32* %14, i64 %116
%121 = getelementptr i32, i32* %7, i64 %116
%122 = bitcast i32* %119 to <4 x i32>*
%123 = load <4 x i32>, <4 x i32>* %122
%124 = getelementptr i32, i32* %119, i64 4
%125 = bitcast i32* %124 to <4 x i32>*
%126 = load <4 x i32>, <4 x i32>* %125
%127 = and <4 x i32> %123, %50
%128 = and <4 x i32> %126, %52
%129 = bitcast i32* %120 to <4 x i32>*
%130 = load <4 x i32>, <4 x i32>* %129
%131 = getelementptr i32, i32* %120, i64 4
%132 = bitcast i32* %131 to <4 x i32>*
%133 = load <4 x i32>, <4 x i32>* %132
%134 = and <4 x i32> %130, %54
%135 = and <4 x i32> %133, %56
%136 = xor <4 x i32> %134, %127
%137 = xor <4 x i32> %135, %128
%138 = bitcast i32* %121 to <4 x i32>*
store <4 x i32> %136, <4 x i32>* %138
%139 = getelementptr i32, i32* %121, i64 4
%140 = bitcast i32* %139 to <4 x i32>*
store <4 x i32> %137, <4 x i32>* %140
br label %141
141: ; preds = %115, %118
%142 = icmp eq i64 %23, %45
br i1 %142, label %160, label %143
143: ; preds = %25, %13, %141
%144 = phi i32* [ %15, %25 ], [ %15, %13 ], [ %46, %141 ]
%145 = phi i32* [ %14, %25 ], [ %14, %13 ], [ %47, %141 ]
%146 = phi i32* [ %7, %25 ], [ %7, %13 ], [ %48, %141 ]
br label %147
147: ; preds = %143, %147
%148 = phi i32* [ %151, %147 ], [ %144, %143 ]
%149 = phi i32* [ %154, %147 ], [ %145, %143 ]
%150 = phi i32* [ %158, %147 ], [ %146, %143 ]
%151 = getelementptr inbounds i32, i32* %148, i64 1
%152 = load i32, i32* %148
%153 = and i32 %152, %11
%154 = getelementptr inbounds i32, i32* %149, i64 1
%155 = load i32, i32* %149
%156 = and i32 %155, %10
%157 = xor i32 %156, %153
%158 = getelementptr inbounds i32, i32* %150, i64 1
store i32 %157, i32* %150
%159 = icmp ult i32* %158, %8
br i1 %159, label %147, label %160
160: ; preds = %147, %141, %5
ret void
}