void MixColumns(unsigned char state[][4]) {
  int i;
  unsigned char Tmp, Tm, t;
  for (i = 0; i < 4; i++) {
    t = state[0][i];
    Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i];
    Tm = state[0][i] ^ state[1][i];
    Tm = ((Tm << 1) ^ (((Tm >> 7) & 1) * 0x1b));
    state[0][i] ^= Tm ^ Tmp;
    Tm = state[1][i] ^ state[2][i];
    Tm = ((Tm << 1) ^ (((Tm >> 7) & 1) * 0x1b));
    state[1][i] ^= Tm ^ Tmp;
    Tm = state[2][i] ^ state[3][i];
    Tm = ((Tm << 1) ^ (((Tm >> 7) & 1) * 0x1b));
    state[2][i] ^= Tm ^ Tmp;
    Tm = state[3][i] ^ t;
    Tm = ((Tm << 1) ^ (((Tm >> 7) & 1) * 0x1b));
    state[3][i] ^= Tm ^ Tmp;
  }
  return;
}


x86 assembly (clang, -O0):
<MixColumns>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movl   $0x0,-0xc(%rbp)
cmpl   $0x4,-0xc(%rbp)
jge    12b9 <MixColumns+0x1b9>
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0xf(%rbp)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x8(%rbp),%rcx
movslq -0xc(%rbp),%rdx
movzbl 0x4(%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    -0x8(%rbp),%rcx
movslq -0xc(%rbp),%rdx
movzbl 0x8(%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    -0x8(%rbp),%rcx
movslq -0xc(%rbp),%rdx
movzbl 0xc(%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    %al,-0xd(%rbp)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x8(%rbp),%rcx
movslq -0xc(%rbp),%rdx
movzbl 0x4(%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%eax
shl    $0x1,%eax
movzbl -0xe(%rbp),%ecx
sar    $0x7,%ecx
and    $0x1,%ecx
imul   $0x1b,%ecx,%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%esi
movzbl -0xd(%rbp),%eax
xor    %eax,%esi
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl (%rax,%rcx,1),%edx
xor    %esi,%edx
mov    %dl,(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl 0x4(%rax,%rcx,1),%eax
mov    -0x8(%rbp),%rcx
movslq -0xc(%rbp),%rdx
movzbl 0x8(%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%eax
shl    $0x1,%eax
movzbl -0xe(%rbp),%ecx
sar    $0x7,%ecx
and    $0x1,%ecx
imul   $0x1b,%ecx,%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%esi
movzbl -0xd(%rbp),%eax
xor    %eax,%esi
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl 0x4(%rax,%rcx,1),%edx
xor    %esi,%edx
mov    %dl,0x4(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl 0x8(%rax,%rcx,1),%eax
mov    -0x8(%rbp),%rcx
movslq -0xc(%rbp),%rdx
movzbl 0xc(%rcx,%rdx,1),%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%eax
shl    $0x1,%eax
movzbl -0xe(%rbp),%ecx
sar    $0x7,%ecx
and    $0x1,%ecx
imul   $0x1b,%ecx,%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%esi
movzbl -0xd(%rbp),%eax
xor    %eax,%esi
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl 0x8(%rax,%rcx,1),%edx
xor    %esi,%edx
mov    %dl,0x8(%rax,%rcx,1)
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl 0xc(%rax,%rcx,1),%eax
movzbl -0xf(%rbp),%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%eax
shl    $0x1,%eax
movzbl -0xe(%rbp),%ecx
sar    $0x7,%ecx
and    $0x1,%ecx
imul   $0x1b,%ecx,%ecx
xor    %ecx,%eax
mov    %al,-0xe(%rbp)
movzbl -0xe(%rbp),%esi
movzbl -0xd(%rbp),%eax
xor    %eax,%esi
mov    -0x8(%rbp),%rax
movslq -0xc(%rbp),%rcx
movzbl 0xc(%rax,%rcx,1),%edx
xor    %esi,%edx
mov    %dl,0xc(%rax,%rcx,1)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    110f <MixColumns+0xf>
pop    %rbp
ret

x86 assembly (clang, -O2):
<MixColumns>:
mov    0x8(%rdi),%eax
mov    (%rdi),%r9d
mov    0x4(%rdi),%r8d
movd   %r9d,%xmm3
movd   %r8d,%xmm8
mov    %r8d,%edx
xor    %r9d,%edx
movd   %edx,%xmm4
mov    %edx,%ecx
xor    %eax,%ecx
movd   %ecx,%xmm5
mov    0xc(%rdi),%esi
xor    %esi,%ecx
movd   %ecx,%xmm2
pxor   %xmm1,%xmm1
pcmpgtb %xmm4,%xmm1
movdqa %xmm4,%xmm6
paddb  %xmm4,%xmm6
pxor   %xmm3,%xmm6
pxor   %xmm3,%xmm3
movdqa 0xeb1(%rip),%xmm4
pand   %xmm4,%xmm1
pxor   %xmm6,%xmm1
pxor   %xmm2,%xmm1
mov    %esi,%ecx
xor    %eax,%ecx
movd   %ecx,%xmm7
pxor   %xmm0,%xmm0
pcmpgtb %xmm7,%xmm0
paddb  %xmm7,%xmm7
pand   %xmm4,%xmm0
xor    %esi,%edx
movd   %edx,%xmm6
pxor   %xmm7,%xmm6
pxor   %xmm0,%xmm6
xor    %r9d,%esi
movd   %esi,%xmm0
pxor   %xmm7,%xmm7
pcmpgtb %xmm0,%xmm7
paddb  %xmm0,%xmm0
pxor   %xmm5,%xmm0
pand   %xmm4,%xmm7
pxor   %xmm0,%xmm7
punpckldq %xmm7,%xmm6
xor    %r8d,%eax
movd   %eax,%xmm0
pcmpgtb %xmm0,%xmm3
paddb  %xmm0,%xmm0
pxor   %xmm8,%xmm0
pand   %xmm4,%xmm3
pxor   %xmm2,%xmm0
pxor   %xmm3,%xmm0
punpckldq %xmm0,%xmm1
punpcklqdq %xmm6,%xmm1
movdqu %xmm1,(%rdi)
ret

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

LLVM IR (-O2):
define void @MixColumns([4 x i8]* nocapture %0) {
%2 = getelementptr [4 x i8], [4 x i8]* %0, i64 2, i64 0
%3 = bitcast i8* %2 to <4 x i8>*
%4 = load <4 x i8>, <4 x i8>* %3
%5 = bitcast [4 x i8]* %0 to <4 x i8>*
%6 = load <4 x i8>, <4 x i8>* %5
%7 = getelementptr inbounds [4 x i8], [4 x i8]* %0, i64 1, i64 0
%8 = bitcast i8* %7 to <4 x i8>*
%9 = load <4 x i8>, <4 x i8>* %8
%10 = xor <4 x i8> %9, %6
%11 = getelementptr inbounds [4 x i8], [4 x i8]* %0, i64 2, i64 0
%12 = xor <4 x i8> %10, %4
%13 = getelementptr inbounds [4 x i8], [4 x i8]* %0, i64 3, i64 0
%14 = bitcast i8* %13 to <4 x i8>*
%15 = load <4 x i8>, <4 x i8>* %14
%16 = xor <4 x i8> %12, %15
%17 = shl <4 x i8> %10, <i8 1, i8 1, i8 1, i8 1>
%18 = icmp slt <4 x i8> %10, zeroinitializer
%19 = select <4 x i1> %18, <4 x i8> <i8 27, i8 27, i8 27, i8 27>, <4 x i8> zeroinitializer
%20 = xor <4 x i8> %17, %6
%21 = xor <4 x i8> %20, %19
%22 = xor <4 x i8> %21, %16
%23 = bitcast [4 x i8]* %0 to <4 x i8>*
store <4 x i8> %22, <4 x i8>* %23
%24 = xor <4 x i8> %4, %9
%25 = shl <4 x i8> %24, <i8 1, i8 1, i8 1, i8 1>
%26 = icmp slt <4 x i8> %24, zeroinitializer
%27 = select <4 x i1> %26, <4 x i8> <i8 27, i8 27, i8 27, i8 27>, <4 x i8> zeroinitializer
%28 = xor <4 x i8> %25, %9
%29 = xor <4 x i8> %28, %16
%30 = xor <4 x i8> %29, %27
%31 = bitcast i8* %7 to <4 x i8>*
store <4 x i8> %30, <4 x i8>* %31
%32 = xor <4 x i8> %15, %4
%33 = shl <4 x i8> %32, <i8 1, i8 1, i8 1, i8 1>
%34 = icmp slt <4 x i8> %32, zeroinitializer
%35 = select <4 x i1> %34, <4 x i8> <i8 27, i8 27, i8 27, i8 27>, <4 x i8> zeroinitializer
%36 = xor <4 x i8> %10, %15
%37 = xor <4 x i8> %36, %33
%38 = xor <4 x i8> %37, %35
%39 = bitcast i8* %11 to <4 x i8>*
store <4 x i8> %38, <4 x i8>* %39
%40 = xor <4 x i8> %15, %6
%41 = shl <4 x i8> %40, <i8 1, i8 1, i8 1, i8 1>
%42 = icmp slt <4 x i8> %40, zeroinitializer
%43 = select <4 x i1> %42, <4 x i8> <i8 27, i8 27, i8 27, i8 27>, <4 x i8> zeroinitializer
%44 = xor <4 x i8> %41, %12
%45 = xor <4 x i8> %44, %43
%46 = bitcast i8* %13 to <4 x i8>*
store <4 x i8> %45, <4 x i8>* %46
ret void
}