#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 */

/* Variables and functions */
unsigned char aes_mul2(unsigned char);
void aes_mix_columns(unsigned char *state) {
  unsigned char temp[16];
  for (int i = 0; i < 16; i++) {
    temp[i] = state[i];
  }
  unsigned char x3, x2, x1, x0;
  for (int j = 0; j < 4; j++) {
    x3 = temp[0 + j * 4] ^ temp[1 + j * 4];
    x2 = temp[1 + j * 4] ^ temp[2 + j * 4];
    x1 = temp[2 + j * 4] ^ temp[3 + j * 4];
    x0 = temp[3 + j * 4] ^ temp[0 + j * 4];
    state[0 + j * 4] = aes_mul2(x3) ^ x1 ^ temp[1 + j * 4];
    state[1 + j * 4] = aes_mul2(x2) ^ x1 ^ temp[0 + j * 4];
    state[2 + j * 4] = aes_mul2(x1) ^ x3 ^ temp[3 + j * 4];
    state[3 + j * 4] = aes_mul2(x0) ^ x3 ^ temp[2 + j * 4];
  }
  return;
}


x86 assembly (clang, -O0):
<aes_mix_columns>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
movl   $0x0,-0x24(%rbp)
cmpl   $0x10,-0x24(%rbp)
jge    114e <aes_mix_columns+0x3e>
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
mov    (%rax,%rcx,1),%cl
movslq -0x24(%rbp),%rax
mov    %cl,-0x20(%rbp,%rax,1)
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    1123 <aes_mix_columns+0x13>
movl   $0x0,-0x2c(%rbp)
cmpl   $0x4,-0x2c(%rbp)
jge    12ed <aes_mix_columns+0x1dd>
mov    -0x2c(%rbp),%eax
shl    $0x2,%eax
add    $0x0,%eax
cltq
movzbl -0x20(%rbp,%rax,1),%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,-0x25(%rbp)
mov    -0x2c(%rbp),%eax
shl    $0x2,%eax
add    $0x1,%eax
cltq
movzbl -0x20(%rbp,%rax,1),%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,-0x26(%rbp)
mov    -0x2c(%rbp),%eax
shl    $0x2,%eax
add    $0x2,%eax
cltq
movzbl -0x20(%rbp,%rax,1),%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,-0x27(%rbp)
mov    -0x2c(%rbp),%eax
shl    $0x2,%eax
add    $0x3,%eax
cltq
movzbl -0x20(%rbp,%rax,1),%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,-0x28(%rbp)
movzbl -0x25(%rbp),%edi
call   1030 <aes_mul2@plt>
movzbl %al,%eax
movzbl -0x27(%rbp),%ecx
xor    %ecx,%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
movzbl -0x26(%rbp),%edi
call   1030 <aes_mul2@plt>
movzbl %al,%eax
movzbl -0x27(%rbp),%ecx
xor    %ecx,%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x0,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
movzbl -0x27(%rbp),%edi
call   1030 <aes_mul2@plt>
movzbl %al,%eax
movzbl -0x25(%rbp),%ecx
xor    %ecx,%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
movzbl -0x28(%rbp),%edi
call   1030 <aes_mul2@plt>
movzbl %al,%eax
movzbl -0x25(%rbp),%ecx
xor    %ecx,%eax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movzbl -0x20(%rbp,%rcx,1),%ecx
xor    %ecx,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x2c(%rbp),%ecx
shl    $0x2,%ecx
add    $0x3,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1155 <aes_mix_columns+0x45>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<aes_mix_columns>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x28,%rsp
mov    %rdi,0x20(%rsp)
movups (%rdi),%xmm0
movaps %xmm0,0x10(%rsp)
xor    %ebx,%ebx
nopl   (%rax)
movzbl 0x10(%rsp,%rbx,4),%r14d
movzbl 0x11(%rsp,%rbx,4),%ebp
mov    %ebp,%eax
xor    %r14b,%al
movzbl 0x12(%rsp,%rbx,4),%r15d
mov    %r15d,%ecx
xor    %bpl,%cl
mov    %cl,0xa(%rsp)
movzbl 0x13(%rsp,%rbx,4),%r12d
mov    %r12d,%r13d
xor    %r15b,%r13b
mov    %r12d,%ecx
xor    %r14b,%cl
mov    %cl,0xb(%rsp)
movzbl %al,%edi
mov    %edi,0xc(%rsp)
call   1030 <aes_mul2@plt>
xor    %r13b,%bpl
xor    %al,%bpl
mov    0x20(%rsp),%rax
mov    %bpl,(%rax,%rbx,4)
mov    %rax,%rbp
movzbl 0xa(%rsp),%edi
call   1030 <aes_mul2@plt>
xor    %r13b,%r14b
xor    %al,%r14b
mov    %r14b,0x1(%rbp,%rbx,4)
mov    %rbp,%r14
movzbl %r13b,%edi
call   1030 <aes_mul2@plt>
mov    0xc(%rsp),%ebp
xor    %bpl,%r12b
xor    %al,%r12b
mov    %r12b,0x2(%r14,%rbx,4)
movzbl 0xb(%rsp),%edi
call   1030 <aes_mul2@plt>
xor    %bpl,%r15b
xor    %al,%r15b
mov    %r15b,0x3(%r14,%rbx,4)
add    $0x1,%rbx
cmp    $0x4,%rbx
jne    1130 <aes_mix_columns+0x20>
add    $0x28,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @aes_mix_columns(i8* %0) {
%2 = alloca i8*
%3 = alloca [16 x i8]
%4 = alloca i32
%5 = alloca i8
%6 = alloca i8
%7 = alloca i8
%8 = alloca i8
%9 = alloca i32
store i8* %0, i8** %2
store i32 0, i32* %4
br label %10
10: ; preds = %22, %1
%11 = load i32, i32* %4
%12 = icmp slt i32 %11, 16
br i1 %12, label %13, label %25
13: ; preds = %10
%14 = load i8*, i8** %2
%15 = load i32, i32* %4
%16 = sext i32 %15 to i64
%17 = getelementptr inbounds i8, i8* %14, i64 %16
%18 = load i8, i8* %17
%19 = load i32, i32* %4
%20 = sext i32 %19 to i64
%21 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %20
store i8 %18, i8* %21
br label %22
22: ; preds = %13
%23 = load i32, i32* %4
%24 = add nsw i32 %23, 1
store i32 %24, i32* %4
br label %10
25: ; preds = %10
store i32 0, i32* %9
br label %26
26: ; preds = %178, %25
%27 = load i32, i32* %9
%28 = icmp slt i32 %27, 4
br i1 %28, label %29, label %181
29: ; preds = %26
%30 = load i32, i32* %9
%31 = mul nsw i32 %30, 4
%32 = add nsw i32 0, %31
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %33
%35 = load i8, i8* %34
%36 = zext i8 %35 to i32
%37 = load i32, i32* %9
%38 = mul nsw i32 %37, 4
%39 = add nsw i32 1, %38
%40 = sext i32 %39 to i64
%41 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %40
%42 = load i8, i8* %41
%43 = zext i8 %42 to i32
%44 = xor i32 %36, %43
%45 = trunc i32 %44 to i8
store i8 %45, i8* %5
%46 = load i32, i32* %9
%47 = mul nsw i32 %46, 4
%48 = add nsw i32 1, %47
%49 = sext i32 %48 to i64
%50 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %49
%51 = load i8, i8* %50
%52 = zext i8 %51 to i32
%53 = load i32, i32* %9
%54 = mul nsw i32 %53, 4
%55 = add nsw i32 2, %54
%56 = sext i32 %55 to i64
%57 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %56
%58 = load i8, i8* %57
%59 = zext i8 %58 to i32
%60 = xor i32 %52, %59
%61 = trunc i32 %60 to i8
store i8 %61, i8* %6
%62 = load i32, i32* %9
%63 = mul nsw i32 %62, 4
%64 = add nsw i32 2, %63
%65 = sext i32 %64 to i64
%66 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %65
%67 = load i8, i8* %66
%68 = zext i8 %67 to i32
%69 = load i32, i32* %9
%70 = mul nsw i32 %69, 4
%71 = add nsw i32 3, %70
%72 = sext i32 %71 to i64
%73 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %72
%74 = load i8, i8* %73
%75 = zext i8 %74 to i32
%76 = xor i32 %68, %75
%77 = trunc i32 %76 to i8
store i8 %77, i8* %7
%78 = load i32, i32* %9
%79 = mul nsw i32 %78, 4
%80 = add nsw i32 3, %79
%81 = sext i32 %80 to i64
%82 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %81
%83 = load i8, i8* %82
%84 = zext i8 %83 to i32
%85 = load i32, i32* %9
%86 = mul nsw i32 %85, 4
%87 = add nsw i32 0, %86
%88 = sext i32 %87 to i64
%89 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %88
%90 = load i8, i8* %89
%91 = zext i8 %90 to i32
%92 = xor i32 %84, %91
%93 = trunc i32 %92 to i8
store i8 %93, i8* %8
%94 = load i8, i8* %5
%95 = call zeroext i8 @aes_mul2(i8 zeroext %94)
%96 = zext i8 %95 to i32
%97 = load i8, i8* %7
%98 = zext i8 %97 to i32
%99 = xor i32 %96, %98
%100 = load i32, i32* %9
%101 = mul nsw i32 %100, 4
%102 = add nsw i32 1, %101
%103 = sext i32 %102 to i64
%104 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %103
%105 = load i8, i8* %104
%106 = zext i8 %105 to i32
%107 = xor i32 %99, %106
%108 = trunc i32 %107 to i8
%109 = load i8*, i8** %2
%110 = load i32, i32* %9
%111 = mul nsw i32 %110, 4
%112 = add nsw i32 0, %111
%113 = sext i32 %112 to i64
%114 = getelementptr inbounds i8, i8* %109, i64 %113
store i8 %108, i8* %114
%115 = load i8, i8* %6
%116 = call zeroext i8 @aes_mul2(i8 zeroext %115)
%117 = zext i8 %116 to i32
%118 = load i8, i8* %7
%119 = zext i8 %118 to i32
%120 = xor i32 %117, %119
%121 = load i32, i32* %9
%122 = mul nsw i32 %121, 4
%123 = add nsw i32 0, %122
%124 = sext i32 %123 to i64
%125 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %124
%126 = load i8, i8* %125
%127 = zext i8 %126 to i32
%128 = xor i32 %120, %127
%129 = trunc i32 %128 to i8
%130 = load i8*, i8** %2
%131 = load i32, i32* %9
%132 = mul nsw i32 %131, 4
%133 = add nsw i32 1, %132
%134 = sext i32 %133 to i64
%135 = getelementptr inbounds i8, i8* %130, i64 %134
store i8 %129, i8* %135
%136 = load i8, i8* %7
%137 = call zeroext i8 @aes_mul2(i8 zeroext %136)
%138 = zext i8 %137 to i32
%139 = load i8, i8* %5
%140 = zext i8 %139 to i32
%141 = xor i32 %138, %140
%142 = load i32, i32* %9
%143 = mul nsw i32 %142, 4
%144 = add nsw i32 3, %143
%145 = sext i32 %144 to i64
%146 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %145
%147 = load i8, i8* %146
%148 = zext i8 %147 to i32
%149 = xor i32 %141, %148
%150 = trunc i32 %149 to i8
%151 = load i8*, i8** %2
%152 = load i32, i32* %9
%153 = mul nsw i32 %152, 4
%154 = add nsw i32 2, %153
%155 = sext i32 %154 to i64
%156 = getelementptr inbounds i8, i8* %151, i64 %155
store i8 %150, i8* %156
%157 = load i8, i8* %8
%158 = call zeroext i8 @aes_mul2(i8 zeroext %157)
%159 = zext i8 %158 to i32
%160 = load i8, i8* %5
%161 = zext i8 %160 to i32
%162 = xor i32 %159, %161
%163 = load i32, i32* %9
%164 = mul nsw i32 %163, 4
%165 = add nsw i32 2, %164
%166 = sext i32 %165 to i64
%167 = getelementptr inbounds [16 x i8], [16 x i8]* %3, i64 0, i64 %166
%168 = load i8, i8* %167
%169 = zext i8 %168 to i32
%170 = xor i32 %162, %169
%171 = trunc i32 %170 to i8
%172 = load i8*, i8** %2
%173 = load i32, i32* %9
%174 = mul nsw i32 %173, 4
%175 = add nsw i32 3, %174
%176 = sext i32 %175 to i64
%177 = getelementptr inbounds i8, i8* %172, i64 %176
store i8 %171, i8* %177
br label %178
178: ; preds = %29
%179 = load i32, i32* %9
%180 = add nsw i32 %179, 1
store i32 %180, i32* %9
br label %26
181: ; preds = %26
ret void
}

LLVM IR (-O2):
define void @aes_mix_columns(i8* nocapture %0) {
%2 = alloca [16 x i8]
%3 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 0
%4 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 0
br label %6
5: ; preds = %6
ret void
6: ; preds = %1, %6
%7 = phi i64 [ 0, %1 ], [ %40, %6 ]
%8 = shl nuw nsw i64 %7, 2
%9 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 %8
%10 = load i8, i8* %9
%11 = or i64 %8, 1
%12 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 %11
%13 = load i8, i8* %12
%14 = xor i8 %13, %10
%15 = or i64 %8, 2
%16 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 %15
%17 = load i8, i8* %16
%18 = xor i8 %17, %13
%19 = or i64 %8, 3
%20 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 %19
%21 = load i8, i8* %20
%22 = xor i8 %21, %17
%23 = xor i8 %21, %10
%24 = tail call zeroext i8 @aes_mul2(i8 zeroext %14)
%25 = xor i8 %22, %13
%26 = xor i8 %25, %24
%27 = getelementptr inbounds i8, i8* %0, i64 %8
store i8 %26, i8* %27
%28 = tail call zeroext i8 @aes_mul2(i8 zeroext %18)
%29 = xor i8 %22, %10
%30 = xor i8 %29, %28
%31 = getelementptr inbounds i8, i8* %0, i64 %11
store i8 %30, i8* %31
%32 = tail call zeroext i8 @aes_mul2(i8 zeroext %22)
%33 = xor i8 %21, %14
%34 = xor i8 %33, %32
%35 = getelementptr inbounds i8, i8* %0, i64 %15
store i8 %34, i8* %35
%36 = tail call zeroext i8 @aes_mul2(i8 zeroext %23)
%37 = xor i8 %17, %14
%38 = xor i8 %37, %36
%39 = getelementptr inbounds i8, i8* %0, i64 %19
store i8 %38, i8* %39
%40 = add nuw nsw i64 %7, 1
%41 = icmp eq i64 %40, 4
br i1 %41, label %5, label %6
}