#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 binary_to_base64(unsigned char);
unsigned int encode_base64_length(unsigned int);
unsigned int encode_base64(unsigned char input[], unsigned int input_length,
                           unsigned char output[]) {
  unsigned int full_sets = input_length / 3;
  for (unsigned int i = 0; i < full_sets; ++i) {
    output[0] = binary_to_base64(input[0] >> 2);
    output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
    output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
    output[3] = binary_to_base64(input[2] & 0x3F);
    input += 3;
    output += 4;
  }
  switch (input_length % 3) {
  case 0:
    output[0] = '\0';
    break;
  case 1:
    output[0] = binary_to_base64(input[0] >> 2);
    output[1] = binary_to_base64((input[0] & 0x03) << 4);
    output[2] = '=';
    output[3] = '=';
    output[4] = '\0';
    break;
  case 2:
    output[0] = binary_to_base64(input[0] >> 2);
    output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
    output[2] = binary_to_base64((input[1] & 0x0F) << 2);
    output[3] = '=';
    output[4] = '\0';
    break;
  }
  return encode_base64_length(input_length);
}


x86 assembly (clang, -O0):
<encode_base64>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0xc(%rbp),%eax
mov    $0x3,%ecx
xor    %edx,%edx
div    %ecx
mov    %eax,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jae    1208 <encode_base64+0xe8>
mov    -0x8(%rbp),%rax
movzbl (%rax),%eax
sar    $0x2,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,(%rax)
mov    -0x8(%rbp),%rax
movzbl (%rax),%eax
and    $0x3,%eax
shl    $0x4,%eax
mov    -0x8(%rbp),%rcx
movzbl 0x1(%rcx),%ecx
sar    $0x4,%ecx
or     %ecx,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0x8(%rbp),%rax
movzbl 0x1(%rax),%eax
and    $0xf,%eax
shl    $0x2,%eax
mov    -0x8(%rbp),%rcx
movzbl 0x2(%rcx),%ecx
sar    $0x6,%ecx
or     %ecx,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,0x2(%rax)
mov    -0x8(%rbp),%rax
movzbl 0x2(%rax),%eax
and    $0x3f,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,0x3(%rax)
mov    -0x8(%rbp),%rax
add    $0x3,%rax
mov    %rax,-0x8(%rbp)
mov    -0x18(%rbp),%rax
add    $0x4,%rax
mov    %rax,-0x18(%rbp)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    1149 <encode_base64+0x29>
mov    -0xc(%rbp),%eax
mov    %eax,%ecx
mov    %ecx,%eax
mov    $0xaaaaaaab,%edx
imul   %rdx,%rcx
shr    $0x21,%rcx
mov    %ecx,%edx
mov    %edx,%ecx
lea    (%rcx,%rcx,2),%ecx
sub    %ecx,%eax
mov    %eax,-0x24(%rbp)
je     1255 <encode_base64+0x135>
jmp    1233 <encode_base64+0x113>
mov    -0x24(%rbp),%eax
sub    $0x1,%eax
je     1261 <encode_base64+0x141>
jmp    1244 <encode_base64+0x124>
mov    -0x24(%rbp),%eax
sub    $0x2,%eax
je     12b6 <encode_base64+0x196>
jmp    132a <encode_base64+0x20a>
mov    -0x18(%rbp),%rax
movb   $0x0,(%rax)
jmp    132a <encode_base64+0x20a>
mov    -0x8(%rbp),%rax
movzbl (%rax),%eax
sar    $0x2,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,(%rax)
mov    -0x8(%rbp),%rax
movzbl (%rax),%eax
and    $0x3,%eax
shl    $0x4,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0x18(%rbp),%rax
movb   $0x3d,0x2(%rax)
mov    -0x18(%rbp),%rax
movb   $0x3d,0x3(%rax)
mov    -0x18(%rbp),%rax
movb   $0x0,0x4(%rax)
jmp    132a <encode_base64+0x20a>
mov    -0x8(%rbp),%rax
movzbl (%rax),%eax
sar    $0x2,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,(%rax)
mov    -0x8(%rbp),%rax
movzbl (%rax),%eax
and    $0x3,%eax
shl    $0x4,%eax
mov    -0x8(%rbp),%rcx
movzbl 0x1(%rcx),%ecx
sar    $0x4,%ecx
or     %ecx,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,0x1(%rax)
mov    -0x8(%rbp),%rax
movzbl 0x1(%rax),%eax
and    $0xf,%eax
shl    $0x2,%eax
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,%cl
mov    -0x18(%rbp),%rax
mov    %cl,0x2(%rax)
mov    -0x18(%rbp),%rax
movb   $0x3d,0x3(%rax)
mov    -0x18(%rbp),%rax
movb   $0x0,0x4(%rax)
mov    -0xc(%rbp),%edi
call   1040 <encode_base64_length@plt>
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<encode_base64>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
mov    %rdx,%r12
mov    %esi,%r14d
mov    %rdi,%rbp
mov    %esi,%r15d
cmp    $0x3,%esi
jb     11bf <encode_base64+0x9f>
mov    $0xaaaaaaab,%ebx
imul   %r15,%rbx
shr    $0x21,%rbx
nopw   0x0(%rax,%rax,1)
movzbl 0x0(%rbp),%eax
shr    $0x2,%al
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,(%r12)
movzbl 0x0(%rbp),%eax
movzbl 0x1(%rbp),%ecx
shr    $0x4,%cl
shl    $0x4,%al
or     %cl,%al
and    $0x3f,%al
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,0x1(%r12)
movzbl 0x1(%rbp),%eax
movzbl 0x2(%rbp),%ecx
shr    $0x6,%cl
shl    $0x2,%al
or     %cl,%al
and    $0x3f,%al
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,0x2(%r12)
movzbl 0x2(%rbp),%edi
and    $0x3f,%edi
call   1030 <binary_to_base64@plt>
mov    %al,0x3(%r12)
add    $0x3,%rbp
add    $0x4,%r12
add    $0xffffffff,%ebx
jne    1150 <encode_base64+0x30>
mov    $0xaaaaaaab,%eax
imul   %r15,%rax
shr    $0x21,%rax
lea    (%rax,%rax,2),%ecx
mov    %r14d,%eax
sub    %ecx,%eax
je     125b <encode_base64+0x13b>
cmp    $0x1,%eax
je     1224 <encode_base64+0x104>
cmp    $0x2,%eax
jne    1260 <encode_base64+0x140>
mov    0x0(%rbp),%al
shr    $0x2,%al
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,(%r12)
mov    0x0(%rbp),%al
mov    0x1(%rbp),%cl
shr    $0x4,%cl
shl    $0x4,%al
or     %cl,%al
and    $0x3f,%al
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,0x1(%r12)
movzbl 0x1(%rbp),%edi
shl    $0x2,%edi
and    $0x3c,%edi
call   1030 <binary_to_base64@plt>
jmp    124c <encode_base64+0x12c>
mov    0x0(%rbp),%al
shr    $0x2,%al
movzbl %al,%edi
call   1030 <binary_to_base64@plt>
mov    %al,(%r12)
movzbl 0x0(%rbp),%edi
shl    $0x4,%edi
and    $0x30,%edi
call   1030 <binary_to_base64@plt>
mov    %al,0x1(%r12)
mov    $0x3d,%al
mov    %al,0x2(%r12)
movb   $0x3d,0x3(%r12)
add    $0x4,%r12
movb   $0x0,(%r12)
mov    %r14d,%edi
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
jmp    1040 <encode_base64_length@plt>

LLVM IR (-O0):
define i32 @encode_base64(i8* %0, i32 %1, i8* %2) {
%4 = alloca i8*
%5 = alloca i32
%6 = alloca i8*
%7 = alloca i32
%8 = alloca i32
store i8* %0, i8** %4
store i32 %1, i32* %5
store i8* %2, i8** %6
%9 = load i32, i32* %5
%10 = udiv i32 %9, 3
store i32 %10, i32* %7
store i32 0, i32* %8
br label %11
11: ; preds = %70, %3
%12 = load i32, i32* %8
%13 = load i32, i32* %7
%14 = icmp ult i32 %12, %13
br i1 %14, label %15, label %73
15: ; preds = %11
%16 = load i8*, i8** %4
%17 = getelementptr inbounds i8, i8* %16, i64 0
%18 = load i8, i8* %17
%19 = zext i8 %18 to i32
%20 = ashr i32 %19, 2
%21 = trunc i32 %20 to i8
%22 = call zeroext i8 @binary_to_base64(i8 zeroext %21)
%23 = load i8*, i8** %6
%24 = getelementptr inbounds i8, i8* %23, i64 0
store i8 %22, i8* %24
%25 = load i8*, i8** %4
%26 = getelementptr inbounds i8, i8* %25, i64 0
%27 = load i8, i8* %26
%28 = zext i8 %27 to i32
%29 = and i32 %28, 3
%30 = shl i32 %29, 4
%31 = load i8*, i8** %4
%32 = getelementptr inbounds i8, i8* %31, i64 1
%33 = load i8, i8* %32
%34 = zext i8 %33 to i32
%35 = ashr i32 %34, 4
%36 = or i32 %30, %35
%37 = trunc i32 %36 to i8
%38 = call zeroext i8 @binary_to_base64(i8 zeroext %37)
%39 = load i8*, i8** %6
%40 = getelementptr inbounds i8, i8* %39, i64 1
store i8 %38, i8* %40
%41 = load i8*, i8** %4
%42 = getelementptr inbounds i8, i8* %41, i64 1
%43 = load i8, i8* %42
%44 = zext i8 %43 to i32
%45 = and i32 %44, 15
%46 = shl i32 %45, 2
%47 = load i8*, i8** %4
%48 = getelementptr inbounds i8, i8* %47, i64 2
%49 = load i8, i8* %48
%50 = zext i8 %49 to i32
%51 = ashr i32 %50, 6
%52 = or i32 %46, %51
%53 = trunc i32 %52 to i8
%54 = call zeroext i8 @binary_to_base64(i8 zeroext %53)
%55 = load i8*, i8** %6
%56 = getelementptr inbounds i8, i8* %55, i64 2
store i8 %54, i8* %56
%57 = load i8*, i8** %4
%58 = getelementptr inbounds i8, i8* %57, i64 2
%59 = load i8, i8* %58
%60 = zext i8 %59 to i32
%61 = and i32 %60, 63
%62 = trunc i32 %61 to i8
%63 = call zeroext i8 @binary_to_base64(i8 zeroext %62)
%64 = load i8*, i8** %6
%65 = getelementptr inbounds i8, i8* %64, i64 3
store i8 %63, i8* %65
%66 = load i8*, i8** %4
%67 = getelementptr inbounds i8, i8* %66, i64 3
store i8* %67, i8** %4
%68 = load i8*, i8** %6
%69 = getelementptr inbounds i8, i8* %68, i64 4
store i8* %69, i8** %6
br label %70
70: ; preds = %15
%71 = load i32, i32* %8
%72 = add i32 %71, 1
store i32 %72, i32* %8
br label %11
73: ; preds = %11
%74 = load i32, i32* %5
%75 = urem i32 %74, 3
switch i32 %75, label %145 [
i32 0, label %76
i32 1, label %79
i32 2, label %105
]
76: ; preds = %73
%77 = load i8*, i8** %6
%78 = getelementptr inbounds i8, i8* %77, i64 0
store i8 0, i8* %78
br label %145
79: ; preds = %73
%80 = load i8*, i8** %4
%81 = getelementptr inbounds i8, i8* %80, i64 0
%82 = load i8, i8* %81
%83 = zext i8 %82 to i32
%84 = ashr i32 %83, 2
%85 = trunc i32 %84 to i8
%86 = call zeroext i8 @binary_to_base64(i8 zeroext %85)
%87 = load i8*, i8** %6
%88 = getelementptr inbounds i8, i8* %87, i64 0
store i8 %86, i8* %88
%89 = load i8*, i8** %4
%90 = getelementptr inbounds i8, i8* %89, i64 0
%91 = load i8, i8* %90
%92 = zext i8 %91 to i32
%93 = and i32 %92, 3
%94 = shl i32 %93, 4
%95 = trunc i32 %94 to i8
%96 = call zeroext i8 @binary_to_base64(i8 zeroext %95)
%97 = load i8*, i8** %6
%98 = getelementptr inbounds i8, i8* %97, i64 1
store i8 %96, i8* %98
%99 = load i8*, i8** %6
%100 = getelementptr inbounds i8, i8* %99, i64 2
store i8 61, i8* %100
%101 = load i8*, i8** %6
%102 = getelementptr inbounds i8, i8* %101, i64 3
store i8 61, i8* %102
%103 = load i8*, i8** %6
%104 = getelementptr inbounds i8, i8* %103, i64 4
store i8 0, i8* %104
br label %145
105: ; preds = %73
%106 = load i8*, i8** %4
%107 = getelementptr inbounds i8, i8* %106, i64 0
%108 = load i8, i8* %107
%109 = zext i8 %108 to i32
%110 = ashr i32 %109, 2
%111 = trunc i32 %110 to i8
%112 = call zeroext i8 @binary_to_base64(i8 zeroext %111)
%113 = load i8*, i8** %6
%114 = getelementptr inbounds i8, i8* %113, i64 0
store i8 %112, i8* %114
%115 = load i8*, i8** %4
%116 = getelementptr inbounds i8, i8* %115, i64 0
%117 = load i8, i8* %116
%118 = zext i8 %117 to i32
%119 = and i32 %118, 3
%120 = shl i32 %119, 4
%121 = load i8*, i8** %4
%122 = getelementptr inbounds i8, i8* %121, i64 1
%123 = load i8, i8* %122
%124 = zext i8 %123 to i32
%125 = ashr i32 %124, 4
%126 = or i32 %120, %125
%127 = trunc i32 %126 to i8
%128 = call zeroext i8 @binary_to_base64(i8 zeroext %127)
%129 = load i8*, i8** %6
%130 = getelementptr inbounds i8, i8* %129, i64 1
store i8 %128, i8* %130
%131 = load i8*, i8** %4
%132 = getelementptr inbounds i8, i8* %131, i64 1
%133 = load i8, i8* %132
%134 = zext i8 %133 to i32
%135 = and i32 %134, 15
%136 = shl i32 %135, 2
%137 = trunc i32 %136 to i8
%138 = call zeroext i8 @binary_to_base64(i8 zeroext %137)
%139 = load i8*, i8** %6
%140 = getelementptr inbounds i8, i8* %139, i64 2
store i8 %138, i8* %140
%141 = load i8*, i8** %6
%142 = getelementptr inbounds i8, i8* %141, i64 3
store i8 61, i8* %142
%143 = load i8*, i8** %6
%144 = getelementptr inbounds i8, i8* %143, i64 4
store i8 0, i8* %144
br label %145
145: ; preds = %73, %105, %79, %76
%146 = load i32, i32* %5
%147 = call i32 @encode_base64_length(i32 %146)
ret i32 %147
}

LLVM IR (-O2):
define i32 @encode_base64(i8* nocapture %0, i32 %1, i8* nocapture writeonly %2) {
%4 = icmp ult i32 %1, 3
br i1 %4, label %7, label %5
5: ; preds = %3
%6 = udiv i32 %1, 3
br label %11
7: ; preds = %11, %3
%8 = phi i8* [ %2, %3 ], [ %41, %11 ]
%9 = phi i8* [ %0, %3 ], [ %40, %11 ]
%10 = urem i32 %1, 3
switch i32 %10, label %77 [
i32 0, label %75
i32 1, label %44
i32 2, label %53
]
11: ; preds = %5, %11
%12 = phi i32 [ %42, %11 ], [ 0, %5 ]
%13 = phi i8* [ %40, %11 ], [ %0, %5 ]
%14 = phi i8* [ %41, %11 ], [ %2, %5 ]
%15 = load i8, i8* %13
%16 = lshr i8 %15, 2
%17 = tail call zeroext i8 @binary_to_base64(i8 zeroext %16)
store i8 %17, i8* %14
%18 = load i8, i8* %13
%19 = shl i8 %18, 4
%20 = and i8 %19, 48
%21 = getelementptr inbounds i8, i8* %13, i64 1
%22 = load i8, i8* %21
%23 = lshr i8 %22, 4
%24 = or i8 %20, %23
%25 = tail call zeroext i8 @binary_to_base64(i8 zeroext %24)
%26 = getelementptr inbounds i8, i8* %14, i64 1
store i8 %25, i8* %26
%27 = load i8, i8* %21
%28 = shl i8 %27, 2
%29 = and i8 %28, 60
%30 = getelementptr inbounds i8, i8* %13, i64 2
%31 = load i8, i8* %30
%32 = lshr i8 %31, 6
%33 = or i8 %29, %32
%34 = tail call zeroext i8 @binary_to_base64(i8 zeroext %33)
%35 = getelementptr inbounds i8, i8* %14, i64 2
store i8 %34, i8* %35
%36 = load i8, i8* %30
%37 = and i8 %36, 63
%38 = tail call zeroext i8 @binary_to_base64(i8 zeroext %37)
%39 = getelementptr inbounds i8, i8* %14, i64 3
store i8 %38, i8* %39
%40 = getelementptr inbounds i8, i8* %13, i64 3
%41 = getelementptr inbounds i8, i8* %14, i64 4
%42 = add nuw nsw i32 %12, 1
%43 = icmp eq i32 %42, %6
br i1 %43, label %7, label %11
44: ; preds = %7
%45 = load i8, i8* %9
%46 = lshr i8 %45, 2
%47 = tail call zeroext i8 @binary_to_base64(i8 zeroext %46)
store i8 %47, i8* %8
%48 = load i8, i8* %9
%49 = shl i8 %48, 4
%50 = and i8 %49, 48
%51 = tail call zeroext i8 @binary_to_base64(i8 zeroext %50)
%52 = getelementptr inbounds i8, i8* %8, i64 1
store i8 %51, i8* %52
br label %70
53: ; preds = %7
%54 = load i8, i8* %9
%55 = lshr i8 %54, 2
%56 = tail call zeroext i8 @binary_to_base64(i8 zeroext %55)
store i8 %56, i8* %8
%57 = load i8, i8* %9
%58 = shl i8 %57, 4
%59 = and i8 %58, 48
%60 = getelementptr inbounds i8, i8* %9, i64 1
%61 = load i8, i8* %60
%62 = lshr i8 %61, 4
%63 = or i8 %59, %62
%64 = tail call zeroext i8 @binary_to_base64(i8 zeroext %63)
%65 = getelementptr inbounds i8, i8* %8, i64 1
store i8 %64, i8* %65
%66 = load i8, i8* %60
%67 = shl i8 %66, 2
%68 = and i8 %67, 60
%69 = tail call zeroext i8 @binary_to_base64(i8 zeroext %68)
br label %70
70: ; preds = %53, %44
%71 = phi i8 [ 61, %44 ], [ %69, %53 ]
%72 = getelementptr inbounds i8, i8* %8, i64 2
store i8 %71, i8* %72
%73 = getelementptr inbounds i8, i8* %8, i64 3
store i8 61, i8* %73
%74 = getelementptr inbounds i8, i8* %8, i64 4
br label %75
75: ; preds = %70, %7
%76 = phi i8* [ %8, %7 ], [ %74, %70 ]
store i8 0, i8* %76
br label %77
77: ; preds = %75, %7
%78 = tail call i32 @encode_base64_length(i32 %1)
ret i32 %78
}