int main() {
  const unsigned char key[16] = {0x98, 0xff, 0xf6, 0x7e, 0x64, 0xe4,
                                 0x6b, 0xe5, 0xee, 0x2e, 0x05, 0xcc,
                                 0x9a, 0xf6, 0xd0, 0x12};
  const unsigned char IV[12] = {0x2d, 0xfb, 0x42, 0x9a, 0x48, 0x69,
                                0x7c, 0x34, 0x00, 0x6d, 0xa8, 0x86};
  const unsigned char plaintext[3 * 16] = {
      0x29, 0xb9, 0x1b, 0x4a, 0x68, 0xa9, 0x9f, 0x97, 0xc4, 0x1c, 0x75, 0x08,
      0xf1, 0x7a, 0x5c, 0x7a, 0x7a, 0xfc, 0x9e, 0x1a, 0xca, 0x83, 0xe1, 0x29,
      0xb0, 0x85, 0xbd, 0x63, 0x7f, 0xf6, 0x7c, 0x01, 0x29, 0xb9, 0x1b, 0x4a,
      0x68, 0xa9, 0x9f, 0x97, 0xc4, 0x1c, 0x75, 0x08, 0xf1, 0x7a, 0x5c, 0x7a};
  const unsigned char add_data[3 * 16] = {
      0xa0, 0xca, 0x58, 0x61, 0xc0, 0x22, 0x6c, 0x5b, 0x5a, 0x65, 0x14, 0xc8,
      0x2b, 0x77, 0x81, 0x5a, 0x9e, 0x0e, 0xb3, 0x59, 0xd0, 0xd4, 0x6d, 0x03,
      0x33, 0xc3, 0xf2, 0xba, 0xe1, 0x4d, 0xa0, 0xc4, 0x03, 0x30, 0xc0, 0x02,
      0x16, 0xb4, 0xaa, 0x64, 0xb7, 0xc1, 0xed, 0xb8, 0x71, 0xc3, 0x28, 0xf6};
  const unsigned char tag_ref[16][16] = {
      {0xec, 0x1c, 0x5a, 0xff, 0xad, 0x2c, 0xad, 0xb9, 0xf5, 0xeb, 0xcf, 0x1d,
       0xee, 0x28, 0x95, 0xea},
      {0x7f, 0x05, 0x0d, 0x45, 0x4e, 0x55, 0x2d, 0x40, 0xf1, 0x73, 0xbb, 0xa9,
       0x2a, 0xd9, 0x23, 0xe0},
      {0x3e, 0xba, 0xc7, 0xcf, 0x15, 0xee, 0xf3, 0xe0, 0xee, 0xff, 0xf7, 0x96,
       0xd7, 0x87, 0x0f, 0x03},
      {0xfc, 0x89, 0x33, 0x0c, 0x1d, 0x86, 0xf3, 0x7d, 0x70, 0x0b, 0x4d, 0xcd,
       0x61, 0x1e, 0x94, 0x35},
      {0x01, 0xbf, 0xa5, 0xb2, 0x75, 0xc7, 0xcc, 0xf8, 0x52, 0xea, 0x28, 0x97,
       0x87, 0x76, 0xbe, 0x58},
      {0x9e, 0x27, 0xe2, 0x10, 0xd6, 0xe1, 0xef, 0x0f, 0x18, 0xde, 0x98, 0xf4,
       0xc3, 0xd0, 0xf9, 0x68},
      {0xaa, 0x2f, 0xe8, 0x0f, 0x1c, 0x21, 0xce, 0x8a, 0x5d, 0x7d, 0xf0, 0x10,
       0x39, 0x90, 0x25, 0x2e},
      {0xc7, 0x30, 0x2f, 0x77, 0xc8, 0x78, 0x68, 0x1f, 0xe9, 0x72, 0x8a, 0xd7,
       0x25, 0xfc, 0x74, 0x01},
      {0x54, 0x77, 0x45, 0x9e, 0x58, 0x74, 0x89, 0xa5, 0xb4, 0x95, 0xc7, 0x73,
       0xd1, 0x31, 0x9d, 0xe2},
      {0xb4, 0xdf, 0xfa, 0xcc, 0xdd, 0x27, 0x27, 0x17, 0xef, 0x9c, 0x73, 0x8e,
       0x7b, 0x00, 0xb9, 0x41},
      {0xe9, 0x1d, 0xbb, 0x07, 0xae, 0x09, 0xc2, 0x62, 0xe0, 0xcd, 0xa9, 0xb2,
       0x89, 0x91, 0xb5, 0x14},
      {0xf1, 0x96, 0xec, 0x54, 0x6c, 0x4c, 0x0a, 0xf0, 0x8b, 0xe0, 0x88, 0xba,
       0xb9, 0x71, 0x91, 0x75},
      {0x79, 0x4c, 0x36, 0xa8, 0x18, 0x23, 0x7e, 0x57, 0x68, 0x6f, 0xe9, 0x83,
       0xbd, 0x41, 0x83, 0x0d},
      {0x78, 0x8c, 0xda, 0x60, 0xfd, 0xf2, 0x79, 0x99, 0xea, 0x2e, 0x86, 0x47,
       0xd5, 0xb4, 0xc4, 0x90},
      {0x42, 0xeb, 0xba, 0x9c, 0xae, 0xdb, 0x79, 0x83, 0x21, 0x43, 0x95, 0x32,
       0x68, 0x36, 0xd2, 0xd7},
      {0x70, 0xfa, 0x28, 0x15, 0x5c, 0x47, 0x88, 0x70, 0x72, 0xaa, 0xe1, 0x2a,
       0x05, 0xde, 0x63, 0x08}};
  const unsigned char ciphertext_ref[3 * 16] = {
      0xc2, 0x2f, 0xee, 0xb3, 0xe2, 0x7d, 0xc3, 0x29, 0x93, 0x45, 0x03, 0x01,
      0x39, 0xee, 0x81, 0x67, 0x19, 0xa8, 0xa8, 0x99, 0x39, 0x03, 0x78, 0x95,
      0xd7, 0x49, 0x65, 0xfa, 0x02, 0x40, 0xaf, 0x5b, 0xe3, 0x19, 0x26, 0x59,
      0xd5, 0x66, 0x39, 0x8a, 0x5d, 0x95, 0xf3, 0xe0, 0x4b, 0xcd, 0x53, 0x57};
  unsigned char *ciphertext = malloc(3 * 16 * sizeof(unsigned char));
  unsigned char *tag = malloc(16 * sizeof(unsigned char));
  unsigned int len_p;
  unsigned int len_ad;
  for (len_p = 0; len_p <= 3; len_p++) {
    for (len_ad = 0; len_ad <= 3; len_ad++) {
      aes128gcm(ciphertext, tag, key, IV, plaintext, len_p, add_data, len_ad);
      printf("lenghts %d %d: ", len_p, len_ad);
      printf("ciphertext %s ",
             !memcmp(ciphertext, ciphertext_ref, (len_p)*16) ? "PASS" : "FAIL");
      printf("tag %s\n\n",
             !memcmp(tag, tag_ref[len_p * 4 + len_ad], 16) ? "PASS" : "FAIL");
    }
  }
  free(ciphertext);
  free(tag);
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x1f0,%rsp
movl   $0x0,-0x4(%rbp)
mov    0xe87(%rip),%rax
mov    %rax,-0x20(%rbp)
mov    0xe84(%rip),%rax
mov    %rax,-0x18(%rbp)
mov    0xe81(%rip),%rax
mov    %rax,-0x2c(%rbp)
mov    0xe7f(%rip),%eax
mov    %eax,-0x24(%rbp)
lea    -0x60(%rbp),%rdi
lea    0xe79(%rip),%rsi
mov    $0x30,%edx
call   1060 <memcpy@plt>
lea    -0x90(%rbp),%rdi
lea    0xe91(%rip),%rsi
mov    $0x30,%edx
call   1060 <memcpy@plt>
lea    -0x190(%rbp),%rdi
lea    0xea9(%rip),%rsi
mov    $0x100,%edx
call   1060 <memcpy@plt>
lea    -0x1c0(%rbp),%rdi
lea    0xf91(%rip),%rsi
mov    $0x30,%edx
call   1060 <memcpy@plt>
mov    $0x30,%edi
call   1070 <malloc@plt>
mov    %rax,-0x1c8(%rbp)
mov    $0x10,%edi
call   1070 <malloc@plt>
mov    %rax,-0x1d0(%rbp)
movl   $0x0,-0x1d4(%rbp)
cmpl   $0x3,-0x1d4(%rbp)
ja     1386 <main+0x226>
movl   $0x0,-0x1d8(%rbp)
cmpl   $0x3,-0x1d8(%rbp)
ja     136d <main+0x20d>
mov    -0x1c8(%rbp),%rdi
mov    -0x1d0(%rbp),%rsi
lea    -0x20(%rbp),%rdx
lea    -0x2c(%rbp),%rcx
lea    -0x60(%rbp),%r8
mov    -0x1d4(%rbp),%r9d
lea    -0x90(%rbp),%r10
mov    -0x1d8(%rbp),%eax
mov    %r10,(%rsp)
mov    %eax,0x8(%rsp)
mov    $0x0,%al
call   1080 <aes128gcm@plt>
mov    -0x1d4(%rbp),%esi
mov    -0x1d8(%rbp),%edx
lea    0xf17(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x1c8(%rbp),%rdi
lea    -0x1c0(%rbp),%rsi
mov    -0x1d4(%rbp),%eax
shl    $0x4,%eax
mov    %eax,%eax
mov    %eax,%edx
call   1050 <memcmp@plt>
cmp    $0x0,%eax
setne  %cl
xor    $0xff,%cl
lea    0xf04(%rip),%rsi
lea    0xef8(%rip),%rax
test   $0x1,%cl
cmovne %rax,%rsi
lea    0xedb(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x1d0(%rbp),%rax
mov    -0x1d4(%rbp),%ecx
shl    $0x2,%ecx
add    -0x1d8(%rbp),%ecx
mov    %ecx,%ecx
mov    %ecx,%edx
lea    -0x190(%rbp),%rcx
shl    $0x4,%rdx
add    %rdx,%rcx
movups (%rcx),%xmm1
movups (%rax),%xmm0
pcmpeqb %xmm1,%xmm0
pmovmskb %xmm0,%eax
sub    $0xffff,%eax
setne  %al
movzbl %al,%eax
cmp    $0x0,%eax
setne  %cl
xor    $0xff,%cl
lea    0xe97(%rip),%rsi
lea    0xe8b(%rip),%rax
test   $0x1,%cl
cmovne %rax,%rsi
lea    0xe87(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x1d8(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1d8(%rbp)
jmp    123c <main+0xdc>
jmp    1372 <main+0x212>
mov    -0x1d4(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1d4(%rbp)
jmp    1225 <main+0xc5>
mov    -0x1c8(%rbp),%rdi
call   1030 <free@plt>
mov    -0x1d0(%rbp),%rdi
call   1030 <free@plt>
xor    %eax,%eax
add    $0x1f0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0xa8,%rsp
movaps 0xe98(%rip),%xmm0
movaps %xmm0,0x30(%rsp)
movabs $0x347c69489a42fb2d,%rax
69 7c 34
mov    %rax,0x18(%rsp)
movl   $0x86a86d00,0x20(%rsp)
86
movaps 0xeb5(%rip),%xmm0
movaps %xmm0,0x90(%rsp)
movaps 0xe96(%rip),%xmm0
movaps %xmm0,0x80(%rsp)
movaps 0xe77(%rip),%xmm0
movaps %xmm0,0x70(%rsp)
movaps 0xebb(%rip),%xmm0
movaps %xmm0,0x60(%rsp)
movaps 0xe9f(%rip),%xmm0
movaps %xmm0,0x50(%rsp)
movdqa 0xe82(%rip),%xmm0
movdqa %xmm0,0x40(%rsp)
mov    $0x30,%edi
call   1050 <malloc@plt>
mov    %rax,0x28(%rsp)
mov    $0x10,%edi
call   1050 <malloc@plt>
mov    %rax,0x8(%rsp)
lea    0xe87(%rip),%r14
xor    %ebp,%ebp
xor    %r15d,%r15d
xchg   %ax,%ax
mov    0x28(%rsp),%r13
mov    %r13,%rdi
mov    0x8(%rsp),%rsi
mov    %rsi,%r12
lea    0x30(%rsp),%rdx
lea    0x18(%rsp),%rcx
lea    0x70(%rsp),%r8
mov    %r15d,%r9d
xor    %eax,%eax
push   $0x0
lea    0x48(%rsp),%rbx
push   %rbx
call   1070 <aes128gcm@plt>
add    $0x10,%rsp
lea    0xf74(%rip),%rdi
mov    %r15d,%esi
xor    %edx,%edx
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r13,%rdi
lea    0xf2e(%rip),%rsi
mov    %rbp,%rdx
call   1060 <bcmp@plt>
test   %eax,%eax
lea    0xf71(%rip),%rsi
lea    0xf65(%rip),%rbx
cmove  %rbx,%rsi
lea    0xf4b(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
movdqu (%r12),%xmm0
mov    %r14,0x10(%rsp)
movdqu (%r14),%xmm1
pcmpeqb %xmm0,%xmm1
pmovmskb %xmm1,%eax
cmp    $0xffff,%eax
lea    0xf34(%rip),%r14
mov    %r14,%rsi
cmove  %rbx,%rsi
lea    0xf2b(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r13,%rdi
mov    %r12,%rsi
lea    0x30(%rsp),%rdx
lea    0x18(%rsp),%rcx
lea    0x70(%rsp),%r8
mov    %r15d,%r9d
xor    %eax,%eax
push   $0x1
lea    0x48(%rsp),%rbx
push   %rbx
call   1070 <aes128gcm@plt>
add    $0x10,%rsp
lea    0xec9(%rip),%rdi
mov    %r15d,%esi
mov    $0x1,%edx
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r13,%rdi
lea    0xe80(%rip),%rsi
mov    %rbp,%rdx
call   1060 <bcmp@plt>
test   %eax,%eax
mov    %r14,%rsi
mov    %rbp,%rbx
lea    0xeb8(%rip),%rbp
cmove  %rbp,%rsi
lea    0xe9e(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
movdqu (%r12),%xmm0
mov    0x10(%rsp),%rax
movdqu 0x10(%rax),%xmm1
pcmpeqb %xmm0,%xmm1
pmovmskb %xmm1,%eax
cmp    $0xffff,%eax
mov    %r14,%rsi
cmove  %rbp,%rsi
mov    %rbx,%rbp
lea    0xe82(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r13,%rdi
mov    %r12,%rsi
lea    0x30(%rsp),%rdx
lea    0x18(%rsp),%rcx
lea    0x70(%rsp),%r8
mov    %r15d,%r9d
xor    %eax,%eax
push   $0x2
lea    0x48(%rsp),%rbx
push   %rbx
call   1070 <aes128gcm@plt>
add    $0x10,%rsp
lea    0xe20(%rip),%rdi
mov    %r15d,%esi
mov    $0x2,%edx
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r13,%rdi
mov    %r13,%rbx
lea    0xdd4(%rip),%rsi
mov    %rbp,%rdx
call   1060 <bcmp@plt>
test   %eax,%eax
mov    %r14,%rsi
lea    0xe0f(%rip),%r12
cmove  %r12,%rsi
lea    0xdf5(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
mov    0x8(%rsp),%r13
movdqu 0x0(%r13),%xmm0
mov    0x10(%rsp),%rax
movdqu 0x20(%rax),%xmm1
pcmpeqb %xmm0,%xmm1
pmovmskb %xmm1,%eax
cmp    $0xffff,%eax
mov    %r14,%rsi
cmove  %r12,%rsi
mov    %r12,%r14
lea    0xdd4(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
mov    %rbx,%rdi
mov    %rbx,%r12
mov    %r13,%rsi
lea    0x30(%rsp),%rdx
lea    0x18(%rsp),%rcx
lea    0x70(%rsp),%r8
mov    %r15d,%r9d
xor    %eax,%eax
push   $0x3
lea    0x48(%rsp),%rbx
push   %rbx
call   1070 <aes128gcm@plt>
add    $0x10,%rsp
lea    0xd6f(%rip),%rdi
mov    %r15d,%esi
mov    $0x3,%edx
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r12,%rdi
lea    0xd26(%rip),%rsi
mov    %rbp,%rdx
call   1060 <bcmp@plt>
test   %eax,%eax
lea    0xd69(%rip),%r12
mov    %r12,%rsi
cmove  %r14,%rsi
lea    0xd47(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
movdqu 0x0(%r13),%xmm0
mov    0x10(%rsp),%rbx
movdqu 0x30(%rbx),%xmm1
pcmpeqb %xmm0,%xmm1
pmovmskb %xmm1,%eax
cmp    $0xffff,%eax
cmove  %r14,%r12
lea    0xd31(%rip),%rdi
mov    %r12,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
add    $0x1,%r15
mov    %rbx,%r14
add    $0x40,%r14
add    $0x10,%rbp
cmp    $0x4,%r15
jne    1200 <main+0xb0>
mov    0x28(%rsp),%rdi
call   1030 <free@plt>
mov    0x8(%rsp),%rdi
call   1030 <free@plt>
xor    %eax,%eax
add    $0xa8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@__const.main.key = [16 x i8] c"\98\FF\F6~d\E4k\E5\EE.\05\CC\9A\F6\D0\12"
@__const.main.IV = [12 x i8] c"-\FBB\9AHi|4\00m\A8\86"
@__const.main.plaintext = [48 x i8] c")\B9\1BJh\A9\9F\97\C4\1Cu\08\F1z\\zz\FC\9E\1A\CA\83\E1)\B0\85\BDc\7F\F6|\01)\B9\1BJh\A9\9F\97\C4\1Cu\08\F1z\\z"
@__const.main.add_data = [48 x i8] c"\A0\CAXa\C0\22l[Ze\14\C8+w\81Z\9E\0E\B3Y\D0\D4m\033\C3\F2\BA\E1M\A0\C4\030\C0\02\16\B4\AAd\B7\C1\ED\B8q\C3(\F6"
@__const.main.tag_ref = [16 x [16 x i8]] [[16 x i8] c"\EC\1CZ\FF\AD,\AD\B9\F5\EB\CF\1D\EE(\95\EA", [16 x i8] c"\7F\05\0DENU-@\F1s\BB\A9*\D9#\E0", [16 x i8] c">\BA\C7\CF\15\EE\F3\E0\EE\FF\F7\96\D7\87\0F\03", [16 x i8] c"\FC\893\0C\1D\86\F3}p\0BM\CDa\1E\945", [16 x i8] c"\01\BF\A5\B2u\C7\CC\F8R\EA(\97\87v\BEX", [16 x i8] c"\9E'\E2\10\D6\E1\EF\0F\18\DE\98\F4\C3\D0\F9h", [16 x i8] c"\AA/\E8\0F\1C!\CE\8A]}\F0\109\90%.", [16 x i8] c"\C70/w\C8xh\1F\E9r\8A\D7%\FCt\01", [16 x i8] c"TwE\9EXt\89\A5\B4\95\C7s\D11\9D\E2", [16 x i8] c"\B4\DF\FA\CC\DD''\17\EF\9Cs\8E{\00\B9A", [16 x i8] c"\E9\1D\BB\07\AE\09\C2b\E0\CD\A9\B2\89\91\B5\14", [16 x i8] c"\F1\96\ECTlL\0A\F0\8B\E0\88\BA\B9q\91u", [16 x i8] c"yL6\A8\18#~Who\E9\83\BDA\83\0D", [16 x i8] c"x\8C\DA`\FD\F2y\99\EA.\86G\D5\B4\C4\90", [16 x i8] c"B\EB\BA\9C\AE\DBy\83!C\952h6\D2\D7", [16 x i8] c"p\FA(\15\\G\88pr\AA\E1*\05\DEc\08"]
@__const.main.ciphertext_ref = [48 x i8] c"\C2/\EE\B3\E2}\C3)\93E\03\019\EE\81g\19\A8\A8\999\03x\95\D7Ie\FA\02@\AF[\E3\19&Y\D5f9\8A]\95\F3\E0K\CDSW"
@.str = [16 x i8] c"lenghts %d %d: \00"
@.str.1 = [15 x i8] c"ciphertext %s \00"
@.str.2 = [5 x i8] c"PASS\00"
@.str.3 = [5 x i8] c"FAIL\00"
@.str.4 = [9 x i8] c"tag %s\0A\0A\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca [16 x i8]
%3 = alloca [12 x i8]
%4 = alloca [48 x i8]
%5 = alloca [48 x i8]
%6 = alloca [16 x [16 x i8]]
%7 = alloca [48 x i8]
%8 = alloca i8*
%9 = alloca i8*
%10 = alloca i32
%11 = alloca i32
store i32 0, i32* %1
%12 = bitcast [16 x i8]* %2 to i8*
%13 = bitcast [12 x i8]* %3 to i8*
%14 = bitcast [48 x i8]* %4 to i8*
%15 = bitcast [48 x i8]* %5 to i8*
%16 = bitcast [16 x [16 x i8]]* %6 to i8*
%17 = bitcast [48 x i8]* %7 to i8*
%18 = call i8* @malloc(i64 48)
store i8* %18, i8** %8
%19 = call i8* @malloc(i64 16)
store i8* %19, i8** %9
store i32 0, i32* %10
br label %20
20: ; preds = %69, %0
%21 = load i32, i32* %10
%22 = icmp ule i32 %21, 3
br i1 %22, label %23, label %72
23: ; preds = %20
store i32 0, i32* %11
br label %24
24: ; preds = %65, %23
%25 = load i32, i32* %11
%26 = icmp ule i32 %25, 3
br i1 %26, label %27, label %68
27: ; preds = %24
%28 = load i8*, i8** %8
%29 = load i8*, i8** %9
%30 = getelementptr inbounds [16 x i8], [16 x i8]* %2, i64 0, i64 0
%31 = getelementptr inbounds [12 x i8], [12 x i8]* %3, i64 0, i64 0
%32 = getelementptr inbounds [48 x i8], [48 x i8]* %4, i64 0, i64 0
%33 = load i32, i32* %10
%34 = getelementptr inbounds [48 x i8], [48 x i8]* %5, i64 0, i64 0
%35 = load i32, i32* %11
%36 = call i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...) bitcast (i32 (...)* @aes128gcm to i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...)*)(i8* %28, i8* %29, i8* %30, i8* %31, i8* %32, i32 %33, i8* %34, i32 %35)
%37 = load i32, i32* %10
%38 = load i32, i32* %11
%39 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), i32 %37, i32 %38)
%40 = load i8*, i8** %8
%41 = getelementptr inbounds [48 x i8], [48 x i8]* %7, i64 0, i64 0
%42 = load i32, i32* %10
%43 = mul i32 %42, 16
%44 = zext i32 %43 to i64
%45 = call i32 @memcmp(i8* %40, i8* %41, i64 %44)
%46 = icmp ne i32 %45, 0
%47 = xor i1 %46, true
%48 = zext i1 %47 to i64
%49 = select i1 %47, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%50 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i64 0, i64 0), i8* %49)
%51 = load i8*, i8** %9
%52 = load i32, i32* %10
%53 = mul i32 %52, 4
%54 = load i32, i32* %11
%55 = add i32 %53, %54
%56 = zext i32 %55 to i64
%57 = getelementptr inbounds [16 x [16 x i8]], [16 x [16 x i8]]* %6, i64 0, i64 %56
%58 = getelementptr inbounds [16 x i8], [16 x i8]* %57, i64 0, i64 0
%59 = call i32 @memcmp(i8* %51, i8* %58, i64 16)
%60 = icmp ne i32 %59, 0
%61 = xor i1 %60, true
%62 = zext i1 %61 to i64
%63 = select i1 %61, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%64 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i64 0, i64 0), i8* %63)
br label %65
65: ; preds = %27
%66 = load i32, i32* %11
%67 = add i32 %66, 1
store i32 %67, i32* %11
br label %24
68: ; preds = %24
br label %69
69: ; preds = %68
%70 = load i32, i32* %10
%71 = add i32 %70, 1
store i32 %71, i32* %10
br label %20
72: ; preds = %20
%73 = load i8*, i8** %8
%74 = load i8*, i8** %9
ret i32 0
}

LLVM IR (-O2):
@__const.main.key = [16 x i8] c"\98\FF\F6~d\E4k\E5\EE.\05\CC\9A\F6\D0\12"
@__const.main.IV = [12 x i8] c"-\FBB\9AHi|4\00m\A8\86"
@__const.main.plaintext = [48 x i8] c")\B9\1BJh\A9\9F\97\C4\1Cu\08\F1z\\zz\FC\9E\1A\CA\83\E1)\B0\85\BDc\7F\F6|\01)\B9\1BJh\A9\9F\97\C4\1Cu\08\F1z\\z"
@__const.main.add_data = [48 x i8] c"\A0\CAXa\C0\22l[Ze\14\C8+w\81Z\9E\0E\B3Y\D0\D4m\033\C3\F2\BA\E1M\A0\C4\030\C0\02\16\B4\AAd\B7\C1\ED\B8q\C3(\F6"
@__const.main.tag_ref = [16 x [16 x i8]] [[16 x i8] c"\EC\1CZ\FF\AD,\AD\B9\F5\EB\CF\1D\EE(\95\EA", [16 x i8] c"\7F\05\0DENU-@\F1s\BB\A9*\D9#\E0", [16 x i8] c">\BA\C7\CF\15\EE\F3\E0\EE\FF\F7\96\D7\87\0F\03", [16 x i8] c"\FC\893\0C\1D\86\F3}p\0BM\CDa\1E\945", [16 x i8] c"\01\BF\A5\B2u\C7\CC\F8R\EA(\97\87v\BEX", [16 x i8] c"\9E'\E2\10\D6\E1\EF\0F\18\DE\98\F4\C3\D0\F9h", [16 x i8] c"\AA/\E8\0F\1C!\CE\8A]}\F0\109\90%.", [16 x i8] c"\C70/w\C8xh\1F\E9r\8A\D7%\FCt\01", [16 x i8] c"TwE\9EXt\89\A5\B4\95\C7s\D11\9D\E2", [16 x i8] c"\B4\DF\FA\CC\DD''\17\EF\9Cs\8E{\00\B9A", [16 x i8] c"\E9\1D\BB\07\AE\09\C2b\E0\CD\A9\B2\89\91\B5\14", [16 x i8] c"\F1\96\ECTlL\0A\F0\8B\E0\88\BA\B9q\91u", [16 x i8] c"yL6\A8\18#~Who\E9\83\BDA\83\0D", [16 x i8] c"x\8C\DA`\FD\F2y\99\EA.\86G\D5\B4\C4\90", [16 x i8] c"B\EB\BA\9C\AE\DBy\83!C\952h6\D2\D7", [16 x i8] c"p\FA(\15\\G\88pr\AA\E1*\05\DEc\08"]
@__const.main.ciphertext_ref = [48 x i8] c"\C2/\EE\B3\E2}\C3)\93E\03\019\EE\81g\19\A8\A8\999\03x\95\D7Ie\FA\02@\AF[\E3\19&Y\D5f9\8A]\95\F3\E0K\CDSW"
@.str = [16 x i8] c"lenghts %d %d: \00"
@.str.1 = [15 x i8] c"ciphertext %s \00"
@.str.2 = [5 x i8] c"PASS\00"
@.str.3 = [5 x i8] c"FAIL\00"
@.str.4 = [9 x i8] c"tag %s\0A\0A\00"
define i32 @main() {
%1 = alloca [16 x i8]
%2 = alloca [12 x i8]
%3 = alloca [48 x i8]
%4 = alloca [48 x i8]
%5 = getelementptr inbounds [16 x i8], [16 x i8]* %1, i64 0, i64 0
%6 = getelementptr inbounds [12 x i8], [12 x i8]* %2, i64 0, i64 0
%7 = getelementptr inbounds [48 x i8], [48 x i8]* %3, i64 0, i64 0
%8 = getelementptr inbounds [48 x i8], [48 x i8]* %4, i64 0, i64 0
%9 = tail call dereferenceable_or_null(48) i8* @malloc(i64 48)
%10 = tail call dereferenceable_or_null(16) i8* @malloc(i64 16)
br label %11
11: ; preds = %0, %11
%12 = phi i64 [ 0, %0 ], [ %63, %11 ]
%13 = shl i64 %12, 4
%14 = shl i64 %12, 2
%15 = trunc i64 %12 to i32
%16 = call i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...) bitcast (i32 (...)* @aes128gcm to i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...)*)(i8* %9, i8* %10, i8* %5, i8* %6, i8* %7, i32 %15, i8* %8, i32 0)
%17 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), i32 %15, i32 0)
%18 = call i32 @bcmp(i8* %9, i8* getelementptr inbounds ([48 x i8], [48 x i8]* @__const.main.ciphertext_ref, i64 0, i64 0), i64 %13)
%19 = icmp eq i32 %18, 0
%20 = select i1 %19, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%21 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i64 0, i64 0), i8* %20)
%22 = getelementptr inbounds [16 x [16 x i8]], [16 x [16 x i8]]* @__const.main.tag_ref, i64 0, i64 %14, i64 0
%23 = call i32 @bcmp(i8* dereferenceable(16) %10, i8* dereferenceable(16) %22, i64 16)
%24 = icmp eq i32 %23, 0
%25 = select i1 %24, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%26 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i64 0, i64 0), i8* %25)
%27 = call i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...) bitcast (i32 (...)* @aes128gcm to i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...)*)(i8* %9, i8* %10, i8* %5, i8* %6, i8* %7, i32 %15, i8* %8, i32 1)
%28 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), i32 %15, i32 1)
%29 = call i32 @bcmp(i8* %9, i8* getelementptr inbounds ([48 x i8], [48 x i8]* @__const.main.ciphertext_ref, i64 0, i64 0), i64 %13)
%30 = icmp eq i32 %29, 0
%31 = select i1 %30, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%32 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i64 0, i64 0), i8* %31)
%33 = or i64 %14, 1
%34 = getelementptr inbounds [16 x [16 x i8]], [16 x [16 x i8]]* @__const.main.tag_ref, i64 0, i64 %33, i64 0
%35 = call i32 @bcmp(i8* dereferenceable(16) %10, i8* dereferenceable(16) %34, i64 16)
%36 = icmp eq i32 %35, 0
%37 = select i1 %36, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%38 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i64 0, i64 0), i8* %37)
%39 = call i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...) bitcast (i32 (...)* @aes128gcm to i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...)*)(i8* %9, i8* %10, i8* %5, i8* %6, i8* %7, i32 %15, i8* %8, i32 2)
%40 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), i32 %15, i32 2)
%41 = call i32 @bcmp(i8* %9, i8* getelementptr inbounds ([48 x i8], [48 x i8]* @__const.main.ciphertext_ref, i64 0, i64 0), i64 %13)
%42 = icmp eq i32 %41, 0
%43 = select i1 %42, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%44 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i64 0, i64 0), i8* %43)
%45 = or i64 %14, 2
%46 = getelementptr inbounds [16 x [16 x i8]], [16 x [16 x i8]]* @__const.main.tag_ref, i64 0, i64 %45, i64 0
%47 = call i32 @bcmp(i8* dereferenceable(16) %10, i8* dereferenceable(16) %46, i64 16)
%48 = icmp eq i32 %47, 0
%49 = select i1 %48, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%50 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i64 0, i64 0), i8* %49)
%51 = call i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...) bitcast (i32 (...)* @aes128gcm to i32 (i8*, i8*, i8*, i8*, i8*, i32, i8*, i32, ...)*)(i8* %9, i8* %10, i8* %5, i8* %6, i8* %7, i32 %15, i8* %8, i32 3)
%52 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), i32 %15, i32 3)
%53 = call i32 @bcmp(i8* %9, i8* getelementptr inbounds ([48 x i8], [48 x i8]* @__const.main.ciphertext_ref, i64 0, i64 0), i64 %13)
%54 = icmp eq i32 %53, 0
%55 = select i1 %54, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%56 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i64 0, i64 0), i8* %55)
%57 = or i64 %14, 3
%58 = getelementptr inbounds [16 x [16 x i8]], [16 x [16 x i8]]* @__const.main.tag_ref, i64 0, i64 %57, i64 0
%59 = call i32 @bcmp(i8* dereferenceable(16) %10, i8* dereferenceable(16) %58, i64 16)
%60 = icmp eq i32 %59, 0
%61 = select i1 %60, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.3, i64 0, i64 0)
%62 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @.str.4, i64 0, i64 0), i8* %61)
%63 = add nuw nsw i64 %12, 1
%64 = icmp eq i64 %63, 4
br i1 %64, label %65, label %11
65: ; preds = %11
ret i32 0
}