#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 */
struct sockaddr_in6 {
  int /*<<< orphan*/ sin6_addr;
};
struct sockaddr_in {
  int /*<<< orphan*/ sin_addr;
};
struct sockaddr {
  int sa_family;
};

/* Variables and functions */
#define AF_INET 129
#define AF_INET6 128
scalar_t__ memcmp(unsigned char *, unsigned char *, unsigned int);
int match_address(struct sockaddr *a, struct sockaddr *b, unsigned prefixlen) {
  unsigned char *abits, *bbits;
  if (a->sa_family != b->sa_family) {
    return 0;
  }
  switch (a->sa_family) {
  case AF_INET:
    abits = (unsigned char *)&((struct sockaddr_in *)a)->sin_addr;
    bbits = (unsigned char *)&((struct sockaddr_in *)b)->sin_addr;
    break;
  case AF_INET6:
    abits = (unsigned char *)&((struct sockaddr_in6 *)a)->sin6_addr;
    bbits = (unsigned char *)&((struct sockaddr_in6 *)b)->sin6_addr;
    break;
  default:
    return 0;
  }
  if (prefixlen >= 8) {
    if (memcmp(abits, bbits, prefixlen >> 3)) {
      return 0;
    }
  }
  if ((prefixlen & 7) == 0) {
    return 1;
  }
  return ((abits[prefixlen >> 3] ^ bbits[prefixlen >> 3]) &
          (0xff00 >> (prefixlen & 7))) == 0;
}


x86 assembly (clang, -O0):
<match_address>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %edx,-0x1c(%rbp)
mov    -0x10(%rbp),%rax
mov    (%rax),%eax
mov    -0x18(%rbp),%rcx
cmp    (%rcx),%eax
je     1141 <match_address+0x31>
movl   $0x0,-0x4(%rbp)
jmp    1237 <match_address+0x127>
mov    -0x10(%rbp),%rax
mov    (%rax),%eax
mov    %eax,-0x34(%rbp)
sub    $0x80,%eax
je     1182 <match_address+0x72>
jmp    115a <match_address+0x4a>
mov    -0x34(%rbp),%eax
sub    $0x81,%eax
jne    1197 <match_address+0x87>
jmp    116d <match_address+0x5d>
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x30(%rbp)
jmp    11a3 <match_address+0x93>
mov    -0x10(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x30(%rbp)
jmp    11a3 <match_address+0x93>
movl   $0x0,-0x4(%rbp)
jmp    1237 <match_address+0x127>
cmpl   $0x8,-0x1c(%rbp)
jb     11db <match_address+0xcb>
mov    -0x28(%rbp),%rdi
mov    -0x30(%rbp),%rsi
mov    -0x1c(%rbp),%edx
shr    $0x3,%edx
call   1030 <memcmp@plt>
cmp    $0x0,%rax
je     11d6 <match_address+0xc6>
movl   $0x0,-0x4(%rbp)
jmp    1237 <match_address+0x127>
jmp    11db <match_address+0xcb>
mov    -0x1c(%rbp),%eax
and    $0x7,%eax
cmp    $0x0,%eax
jne    11f6 <match_address+0xe6>
movl   $0x1,-0x4(%rbp)
jmp    1237 <match_address+0x127>
mov    -0x28(%rbp),%rax
mov    -0x1c(%rbp),%ecx
shr    $0x3,%ecx
mov    %ecx,%ecx
movzbl (%rax,%rcx,1),%eax
mov    -0x30(%rbp),%rcx
mov    -0x1c(%rbp),%edx
shr    $0x3,%edx
mov    %edx,%edx
movzbl (%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    -0x1c(%rbp),%ecx
and    $0x7,%ecx
mov    $0xff00,%edx
sar    %cl,%edx
mov    %edx,%ecx
and    %ecx,%eax
cmp    $0x0,%eax
sete   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<match_address>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
mov    (%rdi),%eax
xor    %ebx,%ebx
cmp    (%rsi),%eax
jne    1176 <match_address+0x66>
and    $0xfffffffe,%eax
cmp    $0x80,%eax
jne    1176 <match_address+0x66>
mov    %edx,%ebp
mov    %rsi,%r15
mov    %rdi,%r14
cmp    $0x8,%edx
jb     114b <match_address+0x3b>
mov    %ebp,%edx
shr    $0x3,%edx
mov    %r14,%rdi
mov    %r15,%rsi
call   1030 <memcmp@plt>
test   %rax,%rax
jne    1176 <match_address+0x66>
mov    %ebp,%ecx
and    $0x7,%ecx
je     1171 <match_address+0x61>
mov    %ebp,%eax
shr    $0x3,%rax
mov    (%r15,%rax,1),%dl
xor    (%r14,%rax,1),%dl
movzbl %dl,%eax
shl    %cl,%eax
xor    %ebx,%ebx
test   $0xff00,%eax
sete   %bl
jmp    1176 <match_address+0x66>
mov    $0x1,%ebx
mov    %ebx,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.sockaddr = type { i32 }
%struct.sockaddr_in = type { i32 }
%struct.sockaddr_in6 = type { i32 }
define i32 @match_address(%struct.sockaddr* %0, %struct.sockaddr* %1, i32 %2) {
%4 = alloca i32
%5 = alloca %struct.sockaddr*
%6 = alloca %struct.sockaddr*
%7 = alloca i32
%8 = alloca i8*
%9 = alloca i8*
store %struct.sockaddr* %0, %struct.sockaddr** %5
store %struct.sockaddr* %1, %struct.sockaddr** %6
store i32 %2, i32* %7
%10 = load %struct.sockaddr*, %struct.sockaddr** %5
%11 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %10, i32 0, i32 0
%12 = load i32, i32* %11
%13 = load %struct.sockaddr*, %struct.sockaddr** %6
%14 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %13, i32 0, i32 0
%15 = load i32, i32* %14
%16 = icmp ne i32 %12, %15
br i1 %16, label %17, label %18
17: ; preds = %3
store i32 0, i32* %4
br label %80
18: ; preds = %3
%19 = load %struct.sockaddr*, %struct.sockaddr** %5
%20 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %19, i32 0, i32 0
%21 = load i32, i32* %20
switch i32 %21, label %40 [
i32 129, label %22
i32 128, label %31
]
22: ; preds = %18
%23 = load %struct.sockaddr*, %struct.sockaddr** %5
%24 = bitcast %struct.sockaddr* %23 to %struct.sockaddr_in*
%25 = getelementptr inbounds %struct.sockaddr_in, %struct.sockaddr_in* %24, i32 0, i32 0
%26 = bitcast i32* %25 to i8*
store i8* %26, i8** %8
%27 = load %struct.sockaddr*, %struct.sockaddr** %6
%28 = bitcast %struct.sockaddr* %27 to %struct.sockaddr_in*
%29 = getelementptr inbounds %struct.sockaddr_in, %struct.sockaddr_in* %28, i32 0, i32 0
%30 = bitcast i32* %29 to i8*
store i8* %30, i8** %9
br label %41
31: ; preds = %18
%32 = load %struct.sockaddr*, %struct.sockaddr** %5
%33 = bitcast %struct.sockaddr* %32 to %struct.sockaddr_in6*
%34 = getelementptr inbounds %struct.sockaddr_in6, %struct.sockaddr_in6* %33, i32 0, i32 0
%35 = bitcast i32* %34 to i8*
store i8* %35, i8** %8
%36 = load %struct.sockaddr*, %struct.sockaddr** %6
%37 = bitcast %struct.sockaddr* %36 to %struct.sockaddr_in6*
%38 = getelementptr inbounds %struct.sockaddr_in6, %struct.sockaddr_in6* %37, i32 0, i32 0
%39 = bitcast i32* %38 to i8*
store i8* %39, i8** %9
br label %41
40: ; preds = %18
store i32 0, i32* %4
br label %80
41: ; preds = %31, %22
%42 = load i32, i32* %7
%43 = icmp uge i32 %42, 8
br i1 %43, label %44, label %53
44: ; preds = %41
%45 = load i8*, i8** %8
%46 = load i8*, i8** %9
%47 = load i32, i32* %7
%48 = lshr i32 %47, 3
%49 = call i64 @memcmp(i8* %45, i8* %46, i32 %48)
%50 = icmp ne i64 %49, 0
br i1 %50, label %51, label %52
51: ; preds = %44
store i32 0, i32* %4
br label %80
52: ; preds = %44
br label %53
53: ; preds = %52, %41
%54 = load i32, i32* %7
%55 = and i32 %54, 7
%56 = icmp eq i32 %55, 0
br i1 %56, label %57, label %58
57: ; preds = %53
store i32 1, i32* %4
br label %80
58: ; preds = %53
%59 = load i8*, i8** %8
%60 = load i32, i32* %7
%61 = lshr i32 %60, 3
%62 = zext i32 %61 to i64
%63 = getelementptr inbounds i8, i8* %59, i64 %62
%64 = load i8, i8* %63
%65 = zext i8 %64 to i32
%66 = load i8*, i8** %9
%67 = load i32, i32* %7
%68 = lshr i32 %67, 3
%69 = zext i32 %68 to i64
%70 = getelementptr inbounds i8, i8* %66, i64 %69
%71 = load i8, i8* %70
%72 = zext i8 %71 to i32
%73 = xor i32 %65, %72
%74 = load i32, i32* %7
%75 = and i32 %74, 7
%76 = ashr i32 65280, %75
%77 = and i32 %73, %76
%78 = icmp eq i32 %77, 0
%79 = zext i1 %78 to i32
store i32 %79, i32* %4
br label %80
80: ; preds = %58, %57, %51, %40, %17
%81 = load i32, i32* %4
ret i32 %81
}

LLVM IR (-O2):
%struct.sockaddr = type { i32 }
define i32 @match_address(%struct.sockaddr* %0, %struct.sockaddr* %1, i32 %2) {
%4 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %0, i64 0, i32 0
%5 = load i32, i32* %4
%6 = getelementptr inbounds %struct.sockaddr, %struct.sockaddr* %1, i64 0, i32 0
%7 = load i32, i32* %6
%8 = icmp eq i32 %5, %7
%9 = and i32 %5, -2
%10 = icmp eq i32 %9, 128
%11 = and i1 %8, %10
br i1 %11, label %12, label %36
12: ; preds = %3
%13 = bitcast %struct.sockaddr* %1 to i8*
%14 = bitcast %struct.sockaddr* %0 to i8*
%15 = icmp ugt i32 %2, 7
br i1 %15, label %16, label %20
16: ; preds = %12
%17 = lshr i32 %2, 3
%18 = tail call i64 @memcmp(i8* %14, i8* %13, i32 %17)
%19 = icmp eq i64 %18, 0
br i1 %19, label %20, label %36
20: ; preds = %16, %12
%21 = and i32 %2, 7
%22 = icmp eq i32 %21, 0
br i1 %22, label %36, label %23
23: ; preds = %20
%24 = lshr i32 %2, 3
%25 = zext i32 %24 to i64
%26 = getelementptr inbounds i8, i8* %14, i64 %25
%27 = load i8, i8* %26
%28 = getelementptr inbounds i8, i8* %13, i64 %25
%29 = load i8, i8* %28
%30 = xor i8 %29, %27
%31 = zext i8 %30 to i32
%32 = lshr i32 65280, %21
%33 = and i32 %32, %31
%34 = icmp eq i32 %33, 0
%35 = zext i1 %34 to i32
br label %36
36: ; preds = %20, %16, %3, %23
%37 = phi i32 [ %35, %23 ], [ 0, %3 ], [ 0, %16 ], [ 1, %20 ]
ret i32 %37
}