void chi(unsigned short *A) {
  unsigned int x, y;
  unsigned short C[5];
  for (y = 0; y < 5; y++) {
    for (x = 0; x < 5; x++)
      C[x] = A[(((x) % 5) + 5 * ((y) % 5))] ^
             ((~A[(((x + 1) % 5) + 5 * ((y) % 5))]) &
              A[(((x + 2) % 5) + 5 * ((y) % 5))]);
    for (x = 0; x < 5; x++)
      A[(((x) % 5) + 5 * ((y) % 5))] = C[x];
  }
}


x86 assembly (clang, -O0):
<chi>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movl   $0x0,-0x10(%rbp)
cmpl   $0x5,-0x10(%rbp)
jae    126c <chi+0x16c>
movl   $0x0,-0xc(%rbp)
cmpl   $0x5,-0xc(%rbp)
jae    11f7 <chi+0xf7>
mov    -0x8(%rbp),%rax
mov    %rax,-0x48(%rbp)
mov    -0xc(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,-0x3c(%rbp)
mov    -0x10(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    -0x48(%rbp),%rax
mov    %edx,%ecx
mov    -0x3c(%rbp),%edx
imul   $0x5,%ecx,%ecx
add    %ecx,%edx
mov    %edx,%ecx
movzwl (%rax,%rcx,2),%eax
mov    %eax,-0x2c(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,-0x30(%rbp)
mov    -0x10(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    -0x38(%rbp),%rax
mov    %edx,%ecx
mov    -0x30(%rbp),%edx
imul   $0x5,%ecx,%ecx
add    %ecx,%edx
mov    %edx,%ecx
movzwl (%rax,%rcx,2),%ecx
xor    $0xffffffff,%ecx
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0xc(%rbp),%eax
add    $0x2,%eax
mov    $0x5,%esi
xor    %edx,%edx
div    %esi
mov    %edx,%esi
mov    -0x10(%rbp),%eax
mov    $0x5,%edi
xor    %edx,%edx
div    %edi
mov    -0x2c(%rbp),%eax
mov    %edx,%edi
mov    -0x28(%rbp),%rdx
imul   $0x5,%edi,%edi
add    %edi,%esi
mov    %esi,%esi
movzwl (%rdx,%rsi,2),%edx
and    %edx,%ecx
xor    %ecx,%eax
mov    %ax,%cx
mov    -0xc(%rbp),%eax
mov    %cx,-0x1a(%rbp,%rax,2)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    1120 <chi+0x20>
movl   $0x0,-0xc(%rbp)
cmpl   $0x5,-0xc(%rbp)
jae    1259 <chi+0x159>
mov    -0xc(%rbp),%eax
mov    -0x1a(%rbp,%rax,2),%ax
mov    %ax,-0x4a(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x58(%rbp)
mov    -0xc(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,%ecx
mov    -0x10(%rbp),%eax
mov    $0x5,%esi
xor    %edx,%edx
div    %esi
mov    -0x58(%rbp),%rax
mov    %edx,%esi
mov    -0x4a(%rbp),%dx
imul   $0x5,%esi,%esi
add    %esi,%ecx
mov    %ecx,%ecx
mov    %dx,(%rax,%rcx,2)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    11fe <chi+0xfe>
jmp    125e <chi+0x15e>
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    110f <chi+0xf>
pop    %rbp
ret

x86 assembly (clang, -O2):
<chi>:
movzwl (%rdi),%eax
movzwl 0x2(%rdi),%r8d
mov    %r8d,%ecx
not    %ecx
movzwl 0x4(%rdi),%r9d
and    %r9d,%ecx
xor    %eax,%ecx
movzwl 0x6(%rdi),%r10d
mov    %r10d,%edx
not    %edx
movzwl 0x8(%rdi),%r11d
and    %r11d,%edx
xor    %r9d,%edx
not    %r9d
and    %r10d,%r9d
xor    %r8d,%r9d
mov    %r11d,%esi
not    %esi
and    %eax,%esi
xor    %r10d,%esi
not    %eax
and    %r8d,%eax
xor    %r11d,%eax
mov    %cx,(%rdi)
mov    %r9w,0x2(%rdi)
mov    %dx,0x4(%rdi)
mov    %si,0x6(%rdi)
mov    %ax,0x8(%rdi)
movzwl 0xa(%rdi),%eax
movzwl 0xc(%rdi),%r8d
mov    %r8d,%ecx
not    %ecx
movzwl 0xe(%rdi),%r9d
and    %r9d,%ecx
xor    %eax,%ecx
movzwl 0x10(%rdi),%r10d
mov    %r10d,%edx
not    %edx
movzwl 0x12(%rdi),%r11d
and    %r11d,%edx
xor    %r9d,%edx
not    %r9d
and    %r10d,%r9d
xor    %r8d,%r9d
mov    %r11d,%esi
not    %esi
and    %eax,%esi
xor    %r10d,%esi
not    %eax
and    %r8d,%eax
xor    %r11d,%eax
mov    %cx,0xa(%rdi)
mov    %r9w,0xc(%rdi)
mov    %dx,0xe(%rdi)
mov    %si,0x10(%rdi)
mov    %ax,0x12(%rdi)
movzwl 0x14(%rdi),%eax
movzwl 0x16(%rdi),%r8d
mov    %r8d,%ecx
not    %ecx
movzwl 0x18(%rdi),%r9d
and    %r9d,%ecx
xor    %eax,%ecx
movzwl 0x1a(%rdi),%r10d
mov    %r10d,%edx
not    %edx
movzwl 0x1c(%rdi),%r11d
and    %r11d,%edx
xor    %r9d,%edx
not    %r9d
and    %r10d,%r9d
xor    %r8d,%r9d
mov    %r11d,%esi
not    %esi
and    %eax,%esi
xor    %r10d,%esi
not    %eax
and    %r8d,%eax
xor    %r11d,%eax
mov    %cx,0x14(%rdi)
mov    %r9w,0x16(%rdi)
mov    %dx,0x18(%rdi)
mov    %si,0x1a(%rdi)
mov    %ax,0x1c(%rdi)
movzwl 0x1e(%rdi),%eax
movzwl 0x20(%rdi),%r8d
mov    %r8d,%ecx
not    %ecx
movzwl 0x22(%rdi),%r9d
and    %r9d,%ecx
xor    %eax,%ecx
movzwl 0x24(%rdi),%r10d
mov    %r10d,%edx
not    %edx
movzwl 0x26(%rdi),%r11d
and    %r11d,%edx
xor    %r9d,%edx
not    %r9d
and    %r10d,%r9d
xor    %r8d,%r9d
mov    %r11d,%esi
not    %esi
and    %eax,%esi
xor    %r10d,%esi
not    %eax
and    %r8d,%eax
xor    %r11d,%eax
mov    %cx,0x1e(%rdi)
mov    %r9w,0x20(%rdi)
mov    %dx,0x22(%rdi)
mov    %si,0x24(%rdi)
mov    %ax,0x26(%rdi)
movzwl 0x28(%rdi),%eax
movzwl 0x2a(%rdi),%r8d
mov    %r8d,%ecx
not    %ecx
movzwl 0x2c(%rdi),%r9d
and    %r9d,%ecx
xor    %eax,%ecx
movzwl 0x2e(%rdi),%r10d
mov    %r10d,%edx
not    %edx
movzwl 0x30(%rdi),%r11d
and    %r11d,%edx
xor    %r9d,%edx
not    %r9d
and    %r10d,%r9d
xor    %r8d,%r9d
mov    %r11d,%esi
not    %esi
and    %eax,%esi
xor    %r10d,%esi
not    %eax
and    %r8d,%eax
xor    %r11d,%eax
mov    %cx,0x28(%rdi)
mov    %r9w,0x2a(%rdi)
mov    %dx,0x2c(%rdi)
mov    %si,0x2e(%rdi)
mov    %ax,0x30(%rdi)
ret

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

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