#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 */
short EOF;
short getchar();
int /*<<< orphan*/ putchar(short);
int /*<<< orphan*/ puts(char *);
void interpret_brainfuck(char *source) {
  if (!source) {
    return;
  }
  short bf_tape[30000] = {0};
  short *bf_ptr = bf_tape;
  char *i = source;
  char *stack[1024] = {0};
  char **stack_ptr = stack;
  while (*i != '\0') {
    switch (*i) {
    case '>':
      bf_ptr++;
      break;
    case '<':
      bf_ptr--;
      break;
    case '+':
      (*bf_ptr)++;
      break;
    case '-':
      (*bf_ptr)--;
      break;
    case '.':
      putchar(*bf_ptr);
      break;
    case ',':
      *bf_ptr = getchar();
      if (*bf_ptr == EOF) {
        *bf_ptr = -1;
      }
      break;
    case '[':
      if (!*bf_ptr) {
        int ctr = 0;
        while ((*(++i) != ']') || (ctr != 0))
          if (*i == '[') {
            ctr++;
          } else if (*i == ']') {
            ctr--;
          }
      } else {
        *stack_ptr++ = i;
      }
      break;
    case ']':
      if (!*bf_ptr) {
        stack_ptr--;
      } else {
        i = stack_ptr[-1];
      }
      break;
    default:
      puts("You should not see this. If you see this, the geese got loose "
           "(meaning, memory pointer is somewhere it's not supposed to be). "
           "Consider reporting a bug.");
      return;
    }
    i++;
  }
}


x86 assembly (clang, -O0):
<interpret_brainfuck>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10aa0,%rsp
mov    %rdi,-0x8(%rbp)
cmpq   $0x0,-0x8(%rbp)
jne    115f <interpret_brainfuck+0x1f>
jmp    13ef <interpret_brainfuck+0x2af>
lea    -0xea70(%rbp),%rdi
xor    %esi,%esi
mov    $0xea60,%edx
call   1050 <memset@plt>
lea    -0xea70(%rbp),%rax
mov    %rax,-0xea78(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0xea80(%rbp)
lea    -0x10a80(%rbp),%rdi
xor    %esi,%esi
mov    $0x2000,%edx
call   1050 <memset@plt>
lea    -0x10a80(%rbp),%rax
mov    %rax,-0x10a88(%rbp)
mov    -0xea80(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     13ef <interpret_brainfuck+0x2af>
mov    -0xea80(%rbp),%rax
movsbl (%rax),%eax
add    $0xffffffd5,%eax
mov    %eax,%ecx
mov    %rcx,-0x10a98(%rbp)
sub    $0x32,%eax
ja     13c7 <interpret_brainfuck+0x287>
mov    -0x10a98(%rbp),%rax
lea    0xe14(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
mov    -0xea78(%rbp),%rax
add    $0x2,%rax
mov    %rax,-0xea78(%rbp)
jmp    13d8 <interpret_brainfuck+0x298>
mov    -0xea78(%rbp),%rax
add    $0xfffffffffffffffe,%rax
mov    %rax,-0xea78(%rbp)
jmp    13d8 <interpret_brainfuck+0x298>
mov    -0xea78(%rbp),%rax
mov    (%rax),%cx
add    $0x1,%cx
mov    %cx,(%rax)
jmp    13d8 <interpret_brainfuck+0x298>
mov    -0xea78(%rbp),%rax
mov    (%rax),%cx
add    $0xffff,%cx
mov    %cx,(%rax)
jmp    13d8 <interpret_brainfuck+0x298>
mov    -0xea78(%rbp),%rax
movswl (%rax),%edi
call   1030 <putchar@plt>
jmp    13d8 <interpret_brainfuck+0x298>
mov    $0x0,%al
call   1060 <getchar@plt>
mov    %ax,%cx
mov    -0xea78(%rbp),%rax
mov    %cx,(%rax)
mov    -0xea78(%rbp),%rax
movswl (%rax),%eax
mov    0x2d60(%rip),%rcx
movswl (%rcx),%ecx
cmp    %ecx,%eax
jne    129f <interpret_brainfuck+0x15f>
mov    -0xea78(%rbp),%rax
movw   $0xffff,(%rax)
jmp    13d8 <interpret_brainfuck+0x298>
mov    -0xea78(%rbp),%rax
cmpw   $0x0,(%rax)
jne    1364 <interpret_brainfuck+0x224>
movl   $0x0,-0x10a8c(%rbp)
mov    -0xea80(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0xea80(%rbp)
movsbl 0x1(%rax),%ecx
mov    $0x1,%al
cmp    $0x5d,%ecx
mov    %al,-0x10a99(%rbp)
jne    12f9 <interpret_brainfuck+0x1b9>
cmpl   $0x0,-0x10a8c(%rbp)
setne  %al
mov    %al,-0x10a99(%rbp)
mov    -0x10a99(%rbp),%al
test   $0x1,%al
jne    130c <interpret_brainfuck+0x1cc>
jmp    135f <interpret_brainfuck+0x21f>
mov    -0xea80(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x5b,%eax
jne    1333 <interpret_brainfuck+0x1f3>
mov    -0x10a8c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10a8c(%rbp)
jmp    135a <interpret_brainfuck+0x21a>
mov    -0xea80(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x5d,%eax
jne    1355 <interpret_brainfuck+0x215>
mov    -0x10a8c(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x10a8c(%rbp)
jmp    135a <interpret_brainfuck+0x21a>
jmp    12bf <interpret_brainfuck+0x17f>
jmp    1383 <interpret_brainfuck+0x243>
mov    -0xea80(%rbp),%rcx
mov    -0x10a88(%rbp),%rax
mov    %rax,%rdx
add    $0x8,%rdx
mov    %rdx,-0x10a88(%rbp)
mov    %rcx,(%rax)
jmp    13d8 <interpret_brainfuck+0x298>
mov    -0xea78(%rbp),%rax
cmpw   $0x0,(%rax)
jne    13b0 <interpret_brainfuck+0x270>
mov    -0x10a88(%rbp),%rax
add    $0xfffffffffffffff8,%rax
mov    %rax,-0x10a88(%rbp)
jmp    13c2 <interpret_brainfuck+0x282>
mov    -0x10a88(%rbp),%rax
mov    -0x8(%rax),%rax
mov    %rax,-0xea80(%rbp)
jmp    13d8 <interpret_brainfuck+0x298>
lea    0xcfe(%rip),%rdi
call   1040 <puts@plt>
jmp    13ef <interpret_brainfuck+0x2af>
mov    -0xea80(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0xea80(%rbp)
jmp    11ac <interpret_brainfuck+0x6c>
add    $0x10aa0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<interpret_brainfuck>:
test   %rdi,%rdi
je     129e <interpret_brainfuck+0x15e>
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x10a68,%rsp
mov    %rdi,%rbx
lea    0x2000(%rsp),%r14
mov    $0xea60,%edx
mov    %r14,%rdi
xor    %esi,%esi
call   1050 <memset@plt>
mov    %rsp,%r15
mov    $0x2000,%edx
mov    %r15,%rdi
xor    %esi,%esi
call   1050 <memset@plt>
mov    (%rbx),%al
test   %al,%al
je     128d <interpret_brainfuck+0x14d>
lea    0xe69(%rip),%r12
mov    0x2e4a(%rip),%r13
mov    $0xffff,%ebp
jmp    11bf <interpret_brainfuck+0x7f>
add    $0x2,%r14
nopl   0x0(%rax)
mov    0x1(%rbx),%al
add    $0x1,%rbx
test   %al,%al
je     128d <interpret_brainfuck+0x14d>
movsbl %al,%eax
add    $0xffffffd5,%eax
cmp    $0x32,%eax
ja     1281 <interpret_brainfuck+0x141>
movslq (%r12,%rax,4),%rax
add    %r12,%rax
jmp    *%rax
addw   $0x1,(%r14)
jmp    11b0 <interpret_brainfuck+0x70>
xor    %eax,%eax
call   1060 <getchar@plt>
cmp    0x0(%r13),%ax
mov    %ax,(%r14)
cmove  %ebp,%eax
mov    %ax,(%r14)
jmp    11b0 <interpret_brainfuck+0x70>
addw   $0xffff,(%r14)
jmp    11b0 <interpret_brainfuck+0x70>
movswl (%r14),%edi
call   1030 <putchar@plt>
jmp    11b0 <interpret_brainfuck+0x70>
add    $0xfffffffffffffffe,%r14
jmp    11b0 <interpret_brainfuck+0x70>
cmpw   $0x0,(%r14)
je     122f <interpret_brainfuck+0xef>
mov    %rbx,(%r15)
add    $0x8,%r15
jmp    11b0 <interpret_brainfuck+0x70>
lea    -0x8(%r15),%rax
cmpw   $0x0,(%r14)
je     1279 <interpret_brainfuck+0x139>
mov    (%rax),%rbx
jmp    11b0 <interpret_brainfuck+0x70>
mov    0x1(%rbx),%cl
add    $0x1,%rbx
cmp    $0x5d,%cl
je     11b0 <interpret_brainfuck+0x70>
xor    %eax,%eax
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
cmp    $0x5d,%cl
je     1260 <interpret_brainfuck+0x120>
cmp    $0x5b,%cl
jne    1263 <interpret_brainfuck+0x123>
add    $0x1,%eax
jmp    1263 <interpret_brainfuck+0x123>
nop
add    $0xffffffff,%eax
movzbl 0x1(%rbx),%ecx
add    $0x1,%rbx
cmp    $0x5d,%cl
jne    1250 <interpret_brainfuck+0x110>
test   %eax,%eax
jne    1250 <interpret_brainfuck+0x110>
jmp    11b0 <interpret_brainfuck+0x70>
mov    %rax,%r15
jmp    11b0 <interpret_brainfuck+0x70>
lea    0xe44(%rip),%rdi
call   1040 <puts@plt>
add    $0x10a68,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@EOF = global i16 0
@.str = [152 x i8] c"You should not see this. If you see this, the geese got loose (meaning, memory pointer is somewhere it's not supposed to be). Consider reporting a bug.\00"
define void @interpret_brainfuck(i8* %0) {
%2 = alloca i8*
%3 = alloca [30000 x i16]
%4 = alloca i16*
%5 = alloca i8*
%6 = alloca [1024 x i8*]
%7 = alloca i8**
%8 = alloca i32
store i8* %0, i8** %2
%9 = load i8*, i8** %2
%10 = icmp ne i8* %9, null
br i1 %10, label %12, label %11
11: ; preds = %1
br label %114
12: ; preds = %1
%13 = bitcast [30000 x i16]* %3 to i8*
%14 = getelementptr inbounds [30000 x i16], [30000 x i16]* %3, i64 0, i64 0
store i16* %14, i16** %4
%15 = load i8*, i8** %2
store i8* %15, i8** %5
%16 = bitcast [1024 x i8*]* %6 to i8*
%17 = getelementptr inbounds [1024 x i8*], [1024 x i8*]* %6, i64 0, i64 0
store i8** %17, i8*** %7
br label %18
18: ; preds = %111, %12
%19 = load i8*, i8** %5
%20 = load i8, i8* %19
%21 = sext i8 %20 to i32
%22 = icmp ne i32 %21, 0
br i1 %22, label %23, label %114
23: ; preds = %18
%24 = load i8*, i8** %5
%25 = load i8, i8* %24
%26 = sext i8 %25 to i32
switch i32 %26, label %109 [
i32 62, label %27
i32 60, label %30
i32 43, label %33
i32 45, label %37
i32 46, label %41
i32 44, label %45
i32 91, label %57
i32 93, label %97
]
27: ; preds = %23
%28 = load i16*, i16** %4
%29 = getelementptr inbounds i16, i16* %28, i32 1
store i16* %29, i16** %4
br label %111
30: ; preds = %23
%31 = load i16*, i16** %4
%32 = getelementptr inbounds i16, i16* %31, i32 -1
store i16* %32, i16** %4
br label %111
33: ; preds = %23
%34 = load i16*, i16** %4
%35 = load i16, i16* %34
%36 = add i16 %35, 1
store i16 %36, i16* %34
br label %111
37: ; preds = %23
%38 = load i16*, i16** %4
%39 = load i16, i16* %38
%40 = add i16 %39, -1
store i16 %40, i16* %38
br label %111
41: ; preds = %23
%42 = load i16*, i16** %4
%43 = load i16, i16* %42
%44 = call i32 @putchar(i16 signext %43)
br label %111
45: ; preds = %23
%46 = call signext i16 (...) @getchar()
%47 = load i16*, i16** %4
store i16 %46, i16* %47
%48 = load i16*, i16** %4
%49 = load i16, i16* %48
%50 = sext i16 %49 to i32
%51 = load i16, i16* @EOF
%52 = sext i16 %51 to i32
%53 = icmp eq i32 %50, %52
br i1 %53, label %54, label %56
54: ; preds = %45
%55 = load i16*, i16** %4
store i16 -1, i16* %55
br label %56
56: ; preds = %54, %45
br label %111
57: ; preds = %23
%58 = load i16*, i16** %4
%59 = load i16, i16* %58
%60 = icmp ne i16 %59, 0
br i1 %60, label %92, label %61
61: ; preds = %57
store i32 0, i32* %8
br label %62
62: ; preds = %90, %61
%63 = load i8*, i8** %5
%64 = getelementptr inbounds i8, i8* %63, i32 1
store i8* %64, i8** %5
%65 = load i8, i8* %64
%66 = sext i8 %65 to i32
%67 = icmp ne i32 %66, 93
br i1 %67, label %71, label %68
68: ; preds = %62
%69 = load i32, i32* %8
%70 = icmp ne i32 %69, 0
br label %71
71: ; preds = %68, %62
%72 = phi i1 [ true, %62 ], [ %70, %68 ]
br i1 %72, label %73, label %91
73: ; preds = %71
%74 = load i8*, i8** %5
%75 = load i8, i8* %74
%76 = sext i8 %75 to i32
%77 = icmp eq i32 %76, 91
br i1 %77, label %78, label %81
78: ; preds = %73
%79 = load i32, i32* %8
%80 = add nsw i32 %79, 1
store i32 %80, i32* %8
br label %90
81: ; preds = %73
%82 = load i8*, i8** %5
%83 = load i8, i8* %82
%84 = sext i8 %83 to i32
%85 = icmp eq i32 %84, 93
br i1 %85, label %86, label %89
86: ; preds = %81
%87 = load i32, i32* %8
%88 = add nsw i32 %87, -1
store i32 %88, i32* %8
br label %89
89: ; preds = %86, %81
br label %90
90: ; preds = %89, %78
br label %62
91: ; preds = %71
br label %96
92: ; preds = %57
%93 = load i8*, i8** %5
%94 = load i8**, i8*** %7
%95 = getelementptr inbounds i8*, i8** %94, i32 1
store i8** %95, i8*** %7
store i8* %93, i8** %94
br label %96
96: ; preds = %92, %91
br label %111
97: ; preds = %23
%98 = load i16*, i16** %4
%99 = load i16, i16* %98
%100 = icmp ne i16 %99, 0
br i1 %100, label %104, label %101
101: ; preds = %97
%102 = load i8**, i8*** %7
%103 = getelementptr inbounds i8*, i8** %102, i32 -1
store i8** %103, i8*** %7
br label %108
104: ; preds = %97
%105 = load i8**, i8*** %7
%106 = getelementptr inbounds i8*, i8** %105, i64 -1
%107 = load i8*, i8** %106
store i8* %107, i8** %5
br label %108
108: ; preds = %104, %101
br label %111
109: ; preds = %23
%110 = call i32 @puts(i8* getelementptr inbounds ([152 x i8], [152 x i8]* @.str, i64 0, i64 0))
br label %114
111: ; preds = %108, %96, %56, %41, %37, %33, %30, %27
%112 = load i8*, i8** %5
%113 = getelementptr inbounds i8, i8* %112, i32 1
store i8* %113, i8** %5
br label %18
114: ; preds = %11, %109, %18
ret void
}

LLVM IR (-O2):
@EOF = global i16 0
@.str = [152 x i8] c"You should not see this. If you see this, the geese got loose (meaning, memory pointer is somewhere it's not supposed to be). Consider reporting a bug.\00"
define void @interpret_brainfuck(i8* %0) {
%2 = alloca [30000 x i16]
%3 = alloca [1024 x i8*]
%4 = icmp eq i8* %0, null
br i1 %4, label %77, label %5
5: ; preds = %1
%6 = bitcast [30000 x i16]* %2 to i8*
%7 = bitcast [1024 x i8*]* %3 to i8*
%8 = load i8, i8* %0
%9 = icmp eq i8 %8, 0
br i1 %9, label %76, label %10
10: ; preds = %5
%11 = getelementptr inbounds [1024 x i8*], [1024 x i8*]* %3, i64 0, i64 0
%12 = getelementptr inbounds [30000 x i16], [30000 x i16]* %2, i64 0, i64 0
br label %13
13: ; preds = %10, %69
%14 = phi i8 [ %74, %69 ], [ %8, %10 ]
%15 = phi i8** [ %72, %69 ], [ %11, %10 ]
%16 = phi i8* [ %73, %69 ], [ %0, %10 ]
%17 = phi i16* [ %70, %69 ], [ %12, %10 ]
%18 = sext i8 %14 to i32
switch i32 %18, label %67 [
i32 62, label %19
i32 60, label %21
i32 43, label %23
i32 45, label %26
i32 46, label %29
i32 44, label %32
i32 91, label %37
i32 93, label %61
]
19: ; preds = %13
%20 = getelementptr inbounds i16, i16* %17, i64 1
br label %69
21: ; preds = %13
%22 = getelementptr inbounds i16, i16* %17, i64 -1
br label %69
23: ; preds = %13
%24 = load i16, i16* %17
%25 = add i16 %24, 1
store i16 %25, i16* %17
br label %69
26: ; preds = %13
%27 = load i16, i16* %17
%28 = add i16 %27, -1
store i16 %28, i16* %17
br label %69
29: ; preds = %13
%30 = load i16, i16* %17
%31 = tail call i32 @putchar(i16 signext %30)
br label %69
32: ; preds = %13
%33 = tail call signext i16 (...) @getchar()
store i16 %33, i16* %17
%34 = load i16, i16* @EOF
%35 = icmp eq i16 %33, %34
%36 = select i1 %35, i16 -1, i16 %33
store i16 %36, i16* %17
br label %69
37: ; preds = %13
%38 = load i16, i16* %17
%39 = icmp eq i16 %38, 0
br i1 %39, label %40, label %59
40: ; preds = %37
%41 = getelementptr inbounds i8, i8* %16, i64 1
%42 = load i8, i8* %41
%43 = icmp eq i8 %42, 93
br i1 %43, label %69, label %44
44: ; preds = %40, %52
%45 = phi i8 [ %55, %52 ], [ %42, %40 ]
%46 = phi i8* [ %54, %52 ], [ %41, %40 ]
%47 = phi i32 [ %53, %52 ], [ 0, %40 ]
switch i8 %45, label %52 [
i8 91, label %48
i8 93, label %50
]
48: ; preds = %44
%49 = add nsw i32 %47, 1
br label %52
50: ; preds = %44
%51 = add nsw i32 %47, -1
br label %52
52: ; preds = %44, %50, %48
%53 = phi i32 [ %49, %48 ], [ %51, %50 ], [ %47, %44 ]
%54 = getelementptr inbounds i8, i8* %46, i64 1
%55 = load i8, i8* %54
%56 = icmp ne i8 %55, 93
%57 = icmp ne i32 %53, 0
%58 = select i1 %56, i1 true, i1 %57
br i1 %58, label %44, label %69
59: ; preds = %37
%60 = getelementptr inbounds i8*, i8** %15, i64 1
store i8* %16, i8** %15
br label %69
61: ; preds = %13
%62 = load i16, i16* %17
%63 = icmp eq i16 %62, 0
%64 = getelementptr inbounds i8*, i8** %15, i64 -1
br i1 %63, label %69, label %65
65: ; preds = %61
%66 = load i8*, i8** %64
br label %69
67: ; preds = %13
%68 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([152 x i8], [152 x i8]* @.str, i64 0, i64 0))
br label %76
69: ; preds = %52, %61, %40, %32, %65, %59, %29, %26, %23, %21, %19
%70 = phi i16* [ %17, %65 ], [ %17, %59 ], [ %17, %29 ], [ %17, %26 ], [ %17, %23 ], [ %22, %21 ], [ %20, %19 ], [ %17, %32 ], [ %17, %40 ], [ %17, %61 ], [ %17, %52 ]
%71 = phi i8* [ %66, %65 ], [ %16, %59 ], [ %16, %29 ], [ %16, %26 ], [ %16, %23 ], [ %16, %21 ], [ %16, %19 ], [ %16, %32 ], [ %41, %40 ], [ %16, %61 ], [ %54, %52 ]
%72 = phi i8** [ %15, %65 ], [ %60, %59 ], [ %15, %29 ], [ %15, %26 ], [ %15, %23 ], [ %15, %21 ], [ %15, %19 ], [ %15, %32 ], [ %15, %40 ], [ %64, %61 ], [ %15, %52 ]
%73 = getelementptr inbounds i8, i8* %71, i64 1
%74 = load i8, i8* %73
%75 = icmp eq i8 %74, 0
br i1 %75, label %76, label %13
76: ; preds = %69, %5, %67
br label %77
77: ; preds = %1, %76
ret void
}