int hash_con(int key_len, char *key) {
  int i = 0;
  char hash[sizeof(int)] = {
      0,
  };
  for (i = 0; i < key_len; ++i)
    hash[i % sizeof(int)] = hash[i % sizeof(int)] ^ key[i];
  i = (*((int *)hash));
  i &= 16 - 1;
  return i;
}


x86 assembly (clang, -O0):
<hash_con>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %edi,-0x4(%rbp)
mov    %rsi,-0x10(%rbp)
movl   $0x0,-0x14(%rbp)
lea    -0x18(%rbp),%rdi
xor    %esi,%esi
mov    $0x4,%edx
call   1030 <memset@plt>
movl   $0x0,-0x14(%rbp)
mov    -0x14(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1180 <hash_con+0x70>
movslq -0x14(%rbp),%rax
and    $0x3,%rax
movsbl -0x18(%rbp,%rax,1),%eax
mov    -0x10(%rbp),%rcx
movslq -0x14(%rbp),%rdx
movsbl (%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    %al,%cl
movslq -0x14(%rbp),%rax
and    $0x3,%rax
mov    %cl,-0x18(%rbp,%rax,1)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    113d <hash_con+0x2d>
mov    -0x18(%rbp),%eax
mov    %eax,-0x14(%rbp)
mov    -0x14(%rbp),%eax
and    $0xf,%eax
mov    %eax,-0x14(%rbp)
mov    -0x14(%rbp),%eax
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<hash_con>:
movl   $0x0,-0x8(%rsp)
test   %edi,%edi
jle    1134 <hash_con+0x34>
mov    %edi,%r9d
xor    %ecx,%ecx
cmp    $0x8,%edi
jb     11fb <hash_con+0xfb>
lea    -0x5(%r9),%rdx
cmp    $0xfffffffffffffffc,%rdx
jb     11fb <hash_con+0xfb>
cmp    $0x20,%edi
jae    1137 <hash_con+0x37>
xor    %ecx,%ecx
jmp    11d1 <hash_con+0xd1>
xor    %eax,%eax
ret
mov    %r9d,%ecx
and    $0xffffffe0,%ecx
lea    -0x20(%rcx),%rdx
mov    %rdx,%r8
shr    $0x5,%r8
add    $0x1,%r8
test   %rdx,%rdx
je     124d <hash_con+0x14d>
mov    %r8,%rdx
and    $0xfffffffffffffffe,%rdx
movaps -0x8(%rsp),%xmm1
movaps 0x8(%rsp),%xmm0
xor    %edi,%edi
nopl   0x0(%rax,%rax,1)
movups (%rsi,%rdi,1),%xmm2
xorps  %xmm1,%xmm2
movups 0x10(%rsi,%rdi,1),%xmm3
xorps  %xmm0,%xmm3
movups 0x20(%rsi,%rdi,1),%xmm1
xorps  %xmm2,%xmm1
movups 0x30(%rsi,%rdi,1),%xmm0
xorps  %xmm3,%xmm0
add    $0x40,%rdi
add    $0xfffffffffffffffe,%rdx
jne    1170 <hash_con+0x70>
movaps %xmm1,-0x8(%rsp)
movaps %xmm0,0x8(%rsp)
test   $0x1,%r8b
je     11c6 <hash_con+0xc6>
movups (%rsi,%rdi,1),%xmm0
movups 0x10(%rsi,%rdi,1),%xmm1
xorps  -0x8(%rsp),%xmm0
xorps  0x8(%rsp),%xmm1
movaps %xmm0,-0x8(%rsp)
movaps %xmm1,0x8(%rsp)
cmp    %r9,%rcx
je     1245 <hash_con+0x145>
test   $0x18,%r9b
je     11fb <hash_con+0xfb>
mov    %rcx,%rdx
mov    %r9d,%ecx
and    $0xfffffff8,%ecx
movsd  -0x8(%rsp),%xmm0
movsd  (%rsi,%rdx,1),%xmm1
xorps  %xmm1,%xmm0
add    $0x8,%rdx
cmp    %rdx,%rcx
jne    11e0 <hash_con+0xe0>
movlps %xmm0,-0x8(%rsp)
cmp    %r9,%rcx
je     1245 <hash_con+0x145>
mov    %rcx,%rdx
not    %rdx
test   $0x1,%r9b
je     1212 <hash_con+0x112>
mov    (%rsi,%rcx,1),%al
xor    %al,-0x8(%rsp)
or     $0x1,%rcx
add    %r9,%rdx
je     1245 <hash_con+0x145>
nopw   0x0(%rax,%rax,1)
mov    %ecx,%eax
and    $0x3,%eax
movzbl (%rsi,%rcx,1),%edx
xor    %dl,-0x8(%rsp,%rax,1)
lea    0x1(%rcx),%eax
and    $0x3,%eax
movzbl 0x1(%rsi,%rcx,1),%edx
xor    %dl,-0x8(%rsp,%rax,1)
add    $0x2,%rcx
cmp    %rcx,%r9
jne    1220 <hash_con+0x120>
mov    -0x8(%rsp),%eax
and    $0xf,%eax
ret
xor    %edi,%edi
test   $0x1,%r8b
jne    11a9 <hash_con+0xa9>
jmp    11c6 <hash_con+0xc6>

LLVM IR (-O0):
define i32 @hash_con(i32 %0, i8* %1) {
%3 = alloca i32
%4 = alloca i8*
%5 = alloca i32
%6 = alloca [4 x i8]
store i32 %0, i32* %3
store i8* %1, i8** %4
store i32 0, i32* %5
%7 = bitcast [4 x i8]* %6 to i8*
store i32 0, i32* %5
br label %8
8: ; preds = %31, %2
%9 = load i32, i32* %5
%10 = load i32, i32* %3
%11 = icmp slt i32 %9, %10
br i1 %11, label %12, label %34
12: ; preds = %8
%13 = load i32, i32* %5
%14 = sext i32 %13 to i64
%15 = urem i64 %14, 4
%16 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 %15
%17 = load i8, i8* %16
%18 = sext i8 %17 to i32
%19 = load i8*, i8** %4
%20 = load i32, i32* %5
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds i8, i8* %19, i64 %21
%23 = load i8, i8* %22
%24 = sext i8 %23 to i32
%25 = xor i32 %18, %24
%26 = trunc i32 %25 to i8
%27 = load i32, i32* %5
%28 = sext i32 %27 to i64
%29 = urem i64 %28, 4
%30 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 %29
store i8 %26, i8* %30
br label %31
31: ; preds = %12
%32 = load i32, i32* %5
%33 = add nsw i32 %32, 1
store i32 %33, i32* %5
br label %8
34: ; preds = %8
%35 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 0
%36 = bitcast i8* %35 to i32*
%37 = load i32, i32* %36
store i32 %37, i32* %5
%38 = load i32, i32* %5
%39 = and i32 %38, 15
store i32 %39, i32* %5
%40 = load i32, i32* %5
ret i32 %40
}

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