void chi(unsigned char *A) {
  unsigned int x, y;
  unsigned char 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    1266 <chi+0x166>
movl   $0x0,-0xc(%rbp)
cmpl   $0x5,-0xc(%rbp)
jae    11f5 <chi+0xf5>
mov    -0x8(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0xc(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,-0x34(%rbp)
mov    -0x10(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    -0x40(%rbp),%rax
mov    %edx,%ecx
mov    -0x34(%rbp),%edx
imul   $0x5,%ecx,%ecx
add    %ecx,%edx
mov    %edx,%ecx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x24(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    %edx,-0x28(%rbp)
mov    -0x10(%rbp),%eax
mov    $0x5,%ecx
xor    %edx,%edx
div    %ecx
mov    -0x30(%rbp),%rax
mov    %edx,%ecx
mov    -0x28(%rbp),%edx
imul   $0x5,%ecx,%ecx
add    %ecx,%edx
mov    %edx,%ecx
movzbl (%rax,%rcx,1),%ecx
xor    $0xffffffff,%ecx
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%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    -0x24(%rbp),%eax
mov    %edx,%edi
mov    -0x20(%rbp),%rdx
imul   $0x5,%edi,%edi
add    %edi,%esi
mov    %esi,%esi
movzbl (%rdx,%rsi,1),%edx
and    %edx,%ecx
xor    %ecx,%eax
mov    %al,%cl
mov    -0xc(%rbp),%eax
mov    %cl,-0x15(%rbp,%rax,1)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    1120 <chi+0x20>
movl   $0x0,-0xc(%rbp)
cmpl   $0x5,-0xc(%rbp)
jae    1253 <chi+0x153>
mov    -0xc(%rbp),%eax
mov    -0x15(%rbp,%rax,1),%al
mov    %al,-0x41(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x50(%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    -0x50(%rbp),%rax
mov    %edx,%esi
mov    -0x41(%rbp),%dl
imul   $0x5,%esi,%esi
add    %esi,%ecx
mov    %ecx,%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    11fc <chi+0xfc>
jmp    1258 <chi+0x158>
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    110f <chi+0xf>
pop    %rbp
ret

x86 assembly (clang, -O2):
<chi>:
mov    (%rdi),%al
mov    0x1(%rdi),%sil
mov    %esi,%r11d
not    %r11b
mov    0x2(%rdi),%r8b
and    %r8b,%r11b
xor    %al,%r11b
mov    0x3(%rdi),%r9b
mov    %r9d,%edx
not    %dl
mov    0x4(%rdi),%r10b
and    %r10b,%dl
xor    %r8b,%dl
not    %r8b
and    %r9b,%r8b
xor    %sil,%r8b
mov    %r10d,%ecx
not    %cl
and    %al,%cl
xor    %r9b,%cl
not    %al
and    %sil,%al
xor    %r10b,%al
mov    %r11b,(%rdi)
mov    %r8b,0x1(%rdi)
mov    %dl,0x2(%rdi)
mov    %cl,0x3(%rdi)
mov    %al,0x4(%rdi)
mov    0x5(%rdi),%al
mov    0x6(%rdi),%sil
mov    %esi,%r11d
not    %r11b
mov    0x7(%rdi),%r8b
and    %r8b,%r11b
xor    %al,%r11b
mov    0x8(%rdi),%r9b
mov    %r9d,%edx
not    %dl
mov    0x9(%rdi),%r10b
and    %r10b,%dl
xor    %r8b,%dl
not    %r8b
and    %r9b,%r8b
xor    %sil,%r8b
mov    %r10d,%ecx
not    %cl
and    %al,%cl
xor    %r9b,%cl
not    %al
and    %sil,%al
xor    %r10b,%al
mov    %r11b,0x5(%rdi)
mov    %r8b,0x6(%rdi)
mov    %dl,0x7(%rdi)
mov    %cl,0x8(%rdi)
mov    %al,0x9(%rdi)
mov    0xa(%rdi),%al
mov    0xb(%rdi),%sil
mov    %esi,%r11d
not    %r11b
mov    0xc(%rdi),%r8b
and    %r8b,%r11b
xor    %al,%r11b
mov    0xd(%rdi),%r9b
mov    %r9d,%edx
not    %dl
mov    0xe(%rdi),%r10b
and    %r10b,%dl
xor    %r8b,%dl
not    %r8b
and    %r9b,%r8b
xor    %sil,%r8b
mov    %r10d,%ecx
not    %cl
and    %al,%cl
xor    %r9b,%cl
not    %al
and    %sil,%al
xor    %r10b,%al
mov    %r11b,0xa(%rdi)
mov    %r8b,0xb(%rdi)
mov    %dl,0xc(%rdi)
mov    %cl,0xd(%rdi)
mov    %al,0xe(%rdi)
mov    0xf(%rdi),%al
mov    0x10(%rdi),%sil
mov    %esi,%r11d
not    %r11b
mov    0x11(%rdi),%r8b
and    %r8b,%r11b
xor    %al,%r11b
mov    0x12(%rdi),%r9b
mov    %r9d,%edx
not    %dl
mov    0x13(%rdi),%r10b
and    %r10b,%dl
xor    %r8b,%dl
not    %r8b
and    %r9b,%r8b
xor    %sil,%r8b
mov    %r10d,%ecx
not    %cl
and    %al,%cl
xor    %r9b,%cl
not    %al
and    %sil,%al
xor    %r10b,%al
mov    %r11b,0xf(%rdi)
mov    %r8b,0x10(%rdi)
mov    %dl,0x11(%rdi)
mov    %cl,0x12(%rdi)
mov    %al,0x13(%rdi)
mov    0x14(%rdi),%al
mov    0x15(%rdi),%sil
mov    %esi,%r11d
not    %r11b
mov    0x16(%rdi),%r8b
and    %r8b,%r11b
xor    %al,%r11b
mov    0x17(%rdi),%r9b
mov    %r9d,%edx
not    %dl
mov    0x18(%rdi),%r10b
and    %r10b,%dl
xor    %r8b,%dl
not    %r8b
and    %r9b,%r8b
xor    %sil,%r8b
mov    %r10d,%ecx
not    %cl
and    %al,%cl
xor    %r9b,%cl
not    %al
and    %sil,%al
xor    %r10b,%al
mov    %r11b,0x14(%rdi)
mov    %r8b,0x15(%rdi)
mov    %dl,0x16(%rdi)
mov    %cl,0x17(%rdi)
mov    %al,0x18(%rdi)
ret

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