#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 */
typedef int /*<<< orphan*/ uint8_t;
typedef scalar_t__ uint32_t;

/* Variables and functions */
int /*<<< orphan*/ chacha20_quarterround(scalar_t__ *, int, int, int, int);
int /*<<< orphan*/ chacha20_serialize(scalar_t__ *, int /*<<< orphan*/ *);
int /*<<< orphan*/ memcpy(scalar_t__ *, scalar_t__ *, int);
void chacha20_block(uint32_t in[16], uint8_t out[64], int num_rounds) {
  int i;
  uint32_t x[16];
  memcpy(x, in, sizeof(uint32_t) * 16);
  for (i = num_rounds; i > 0; i -= 2) {
    chacha20_quarterround(x, 0, 4, 8, 12);
    chacha20_quarterround(x, 1, 5, 9, 13);
    chacha20_quarterround(x, 2, 6, 10, 14);
    chacha20_quarterround(x, 3, 7, 11, 15);
    chacha20_quarterround(x, 0, 5, 10, 15);
    chacha20_quarterround(x, 1, 6, 11, 12);
    chacha20_quarterround(x, 2, 7, 8, 13);
    chacha20_quarterround(x, 3, 4, 9, 14);
  }
  for (i = 0; i < 16; i++) {
    x[i] += in[i];
  }
  chacha20_serialize(x, out);
}


x86 assembly (clang, -O0):
<chacha20_block>:
push   %rbp
mov    %rsp,%rbp
sub    $0xa0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
lea    -0xa0(%rbp),%rdi
mov    -0x8(%rbp),%rsi
mov    $0x80,%edx
call   1040 <memcpy@plt>
mov    -0x14(%rbp),%eax
mov    %eax,-0x18(%rbp)
cmpl   $0x0,-0x18(%rbp)
jle    127b <chacha20_block+0x14b>
lea    -0xa0(%rbp),%rdi
xor    %esi,%esi
mov    $0x4,%edx
mov    $0x8,%ecx
mov    $0xc,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
mov    $0x1,%esi
mov    $0x5,%edx
mov    $0x9,%ecx
mov    $0xd,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
mov    $0x2,%esi
mov    $0x6,%edx
mov    $0xa,%ecx
mov    $0xe,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
mov    $0x3,%esi
mov    $0x7,%edx
mov    $0xb,%ecx
mov    $0xf,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
xor    %esi,%esi
mov    $0x5,%edx
mov    $0xa,%ecx
mov    $0xf,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
mov    $0x1,%esi
mov    $0x6,%edx
mov    $0xb,%ecx
mov    $0xc,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
mov    $0x2,%esi
mov    $0x7,%edx
mov    $0x8,%ecx
mov    $0xd,%r8d
call   1050 <chacha20_quarterround@plt>
lea    -0xa0(%rbp),%rdi
mov    $0x3,%esi
mov    $0x4,%edx
mov    $0x9,%ecx
mov    $0xe,%r8d
call   1050 <chacha20_quarterround@plt>
mov    -0x18(%rbp),%eax
sub    $0x2,%eax
mov    %eax,-0x18(%rbp)
jmp    1161 <chacha20_block+0x31>
movl   $0x0,-0x18(%rbp)
cmpl   $0x10,-0x18(%rbp)
jge    12ba <chacha20_block+0x18a>
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    (%rax,%rcx,8),%rcx
movslq -0x18(%rbp),%rax
add    -0xa0(%rbp,%rax,8),%rcx
ff
mov    %rcx,-0xa0(%rbp,%rax,8)
ff
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1282 <chacha20_block+0x152>
lea    -0xa0(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1030 <chacha20_serialize@plt>
add    $0xa0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<chacha20_block>:
push   %rbp
push   %r15
push   %r14
push   %rbx
sub    $0x88,%rsp
mov    %edx,%ebp
mov    %rsi,%r14
mov    %rdi,%r15
mov    %rsp,%rdi
mov    %r15,%rsi
mov    $0x80,%edx
call   1040 <memcpy@plt>
test   %ebp,%ebp
jle    125e <chacha20_block+0x12e>
add    $0x2,%ebp
mov    %rsp,%rbx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
mov    %rbx,%rdi
xor    %esi,%esi
mov    $0x4,%edx
mov    $0x8,%ecx
mov    $0xc,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
mov    $0x1,%esi
mov    $0x5,%edx
mov    $0x9,%ecx
mov    $0xd,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
mov    $0x2,%esi
mov    $0x6,%edx
mov    $0xa,%ecx
mov    $0xe,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
mov    $0x3,%esi
mov    $0x7,%edx
mov    $0xb,%ecx
mov    $0xf,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
xor    %esi,%esi
mov    $0x5,%edx
mov    $0xa,%ecx
mov    $0xf,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
mov    $0x1,%esi
mov    $0x6,%edx
mov    $0xb,%ecx
mov    $0xc,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
mov    $0x2,%esi
mov    $0x7,%edx
mov    $0x8,%ecx
mov    $0xd,%r8d
call   1050 <chacha20_quarterround@plt>
mov    %rbx,%rdi
mov    $0x3,%esi
mov    $0x4,%edx
mov    $0x9,%ecx
mov    $0xe,%r8d
call   1050 <chacha20_quarterround@plt>
add    $0xfffffffe,%ebp
cmp    $0x2,%ebp
ja     1170 <chacha20_block+0x40>
movdqu (%r15),%xmm0
paddq  (%rsp),%xmm0
movdqa %xmm0,(%rsp)
movdqu 0x10(%r15),%xmm0
paddq  0x10(%rsp),%xmm0
movdqa %xmm0,0x10(%rsp)
movdqu 0x20(%r15),%xmm0
paddq  0x20(%rsp),%xmm0
movdqa %xmm0,0x20(%rsp)
movdqu 0x30(%r15),%xmm0
paddq  0x30(%rsp),%xmm0
movdqa %xmm0,0x30(%rsp)
movdqu 0x40(%r15),%xmm0
paddq  0x40(%rsp),%xmm0
movdqa %xmm0,0x40(%rsp)
movdqu 0x50(%r15),%xmm0
paddq  0x50(%rsp),%xmm0
movdqa %xmm0,0x50(%rsp)
movdqu 0x60(%r15),%xmm0
paddq  0x60(%rsp),%xmm0
movdqa %xmm0,0x60(%rsp)
movdqu 0x70(%r15),%xmm0
paddq  0x70(%rsp),%xmm0
movdqa %xmm0,0x70(%rsp)
mov    %rsp,%rdi
mov    %r14,%rsi
call   1030 <chacha20_serialize@plt>
add    $0x88,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @chacha20_block(i64* %0, i32* %1, i32 %2) {
%4 = alloca i64*
%5 = alloca i32*
%6 = alloca i32
%7 = alloca i32
%8 = alloca [16 x i64]
store i64* %0, i64** %4
store i32* %1, i32** %5
store i32 %2, i32* %6
%9 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%10 = load i64*, i64** %4
%11 = call i32 @memcpy(i64* %9, i64* %10, i32 128)
%12 = load i32, i32* %6
store i32 %12, i32* %7
br label %13
13: ; preds = %33, %3
%14 = load i32, i32* %7
%15 = icmp sgt i32 %14, 0
br i1 %15, label %16, label %36
16: ; preds = %13
%17 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%18 = call i32 @chacha20_quarterround(i64* %17, i32 0, i32 4, i32 8, i32 12)
%19 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%20 = call i32 @chacha20_quarterround(i64* %19, i32 1, i32 5, i32 9, i32 13)
%21 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%22 = call i32 @chacha20_quarterround(i64* %21, i32 2, i32 6, i32 10, i32 14)
%23 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%24 = call i32 @chacha20_quarterround(i64* %23, i32 3, i32 7, i32 11, i32 15)
%25 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%26 = call i32 @chacha20_quarterround(i64* %25, i32 0, i32 5, i32 10, i32 15)
%27 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%28 = call i32 @chacha20_quarterround(i64* %27, i32 1, i32 6, i32 11, i32 12)
%29 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%30 = call i32 @chacha20_quarterround(i64* %29, i32 2, i32 7, i32 8, i32 13)
%31 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%32 = call i32 @chacha20_quarterround(i64* %31, i32 3, i32 4, i32 9, i32 14)
br label %33
33: ; preds = %16
%34 = load i32, i32* %7
%35 = sub nsw i32 %34, 2
store i32 %35, i32* %7
br label %13
36: ; preds = %13
store i32 0, i32* %7
br label %37
37: ; preds = %51, %36
%38 = load i32, i32* %7
%39 = icmp slt i32 %38, 16
br i1 %39, label %40, label %54
40: ; preds = %37
%41 = load i64*, i64** %4
%42 = load i32, i32* %7
%43 = sext i32 %42 to i64
%44 = getelementptr inbounds i64, i64* %41, i64 %43
%45 = load i64, i64* %44
%46 = load i32, i32* %7
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 %47
%49 = load i64, i64* %48
%50 = add nsw i64 %49, %45
store i64 %50, i64* %48
br label %51
51: ; preds = %40
%52 = load i32, i32* %7
%53 = add nsw i32 %52, 1
store i32 %53, i32* %7
br label %37
54: ; preds = %37
%55 = getelementptr inbounds [16 x i64], [16 x i64]* %8, i64 0, i64 0
%56 = load i32*, i32** %5
%57 = call i32 @chacha20_serialize(i64* %55, i32* %56)
ret void
}

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