#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 int size;

/* Variables and functions */
int /*<<< orphan*/ exit(int);
int /*<<< orphan*/ *malloc(int);
void *_perm_alloc(size_t size) {
  static uint8_t *ptr;
  static size_t rem;
  void *ret;
  size = (((size) + ((2 * sizeof(void *)) - 1)) & ~((2 * sizeof(void *)) - 1));
  if (size > rem || rem == 0) {
    ptr = malloc((1 << 23));
    if (ptr == NULL)
      exit(1);
    rem = (1 << 23);
  }
  ret = ptr;
  rem -= size;
  ptr += size;
  return ret;
}


x86 assembly (clang, -O0):
<_perm_alloc>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %rdi,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0xf,%rax
and    $0xfffffffffffffff0,%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
cmp    0x2ef9(%rip),%rax
ja     115b <_perm_alloc+0x3b>
cmpq   $0x0,0x2eeb(%rip)
jne    118f <_perm_alloc+0x6f>
mov    $0x800000,%edi
call   1030 <malloc@plt>
mov    %rax,0x2ecc(%rip)
cmpq   $0x0,0x2ec4(%rip)
jne    1184 <_perm_alloc+0x64>
mov    $0x1,%edi
call   1040 <exit@plt>
movq   $0x800000,0x2eb1(%rip)
mov    0x2ea2(%rip),%rax
mov    %rax,-0x10(%rbp)
mov    -0x8(%rbp),%rcx
mov    0x2e9b(%rip),%rax
sub    %rcx,%rax
mov    %rax,0x2e91(%rip)
mov    -0x8(%rbp),%rax
shl    $0x2,%rax
add    0x2e7a(%rip),%rax
mov    %rax,0x2e73(%rip)
mov    -0x10(%rbp),%rax
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<_perm_alloc>:
push   %rbx
mov    %rdi,%rbx
add    $0xf,%rbx
and    $0xfffffffffffffff0,%rbx
mov    0x2f0d(%rip),%rcx
cmp    %rcx,%rbx
ja     1146 <_perm_alloc+0x26>
test   %rcx,%rcx
je     1146 <_perm_alloc+0x26>
mov    0x2ef4(%rip),%rax
jmp    1161 <_perm_alloc+0x41>
mov    $0x800000,%edi
call   1030 <malloc@plt>
mov    %rax,0x2ee1(%rip)
test   %rax,%rax
je     1178 <_perm_alloc+0x58>
mov    $0x800000,%ecx
sub    %rbx,%rcx
mov    %rcx,0x2ed5(%rip)
lea    (%rax,%rbx,4),%rcx
mov    %rcx,0x2ec2(%rip)
pop    %rbx
ret
mov    $0x1,%edi
call   1040 <exit@plt>

LLVM IR (-O0):
@_perm_alloc.ptr = internal global i32* null
@_perm_alloc.rem = internal global i64 0
define i8* @_perm_alloc(i64 %0) {
%2 = alloca i64
%3 = alloca i8*
store i64 %0, i64* %2
%4 = load i64, i64* %2
%5 = add i64 %4, 15
%6 = and i64 %5, -16
store i64 %6, i64* %2
%7 = load i64, i64* %2
%8 = load i64, i64* @_perm_alloc.rem
%9 = icmp ugt i64 %7, %8
br i1 %9, label %13, label %10
10: ; preds = %1
%11 = load i64, i64* @_perm_alloc.rem
%12 = icmp eq i64 %11, 0
br i1 %12, label %13, label %20
13: ; preds = %10, %1
%14 = call i32* @malloc(i32 8388608)
store i32* %14, i32** @_perm_alloc.ptr
%15 = load i32*, i32** @_perm_alloc.ptr
%16 = icmp eq i32* %15, null
br i1 %16, label %17, label %19
17: ; preds = %13
%18 = call i32 @exit(i32 1)
unreachable
19: ; preds = %13
store i64 8388608, i64* @_perm_alloc.rem
br label %20
20: ; preds = %19, %10
%21 = load i32*, i32** @_perm_alloc.ptr
%22 = bitcast i32* %21 to i8*
store i8* %22, i8** %3
%23 = load i64, i64* %2
%24 = load i64, i64* @_perm_alloc.rem
%25 = sub i64 %24, %23
store i64 %25, i64* @_perm_alloc.rem
%26 = load i64, i64* %2
%27 = load i32*, i32** @_perm_alloc.ptr
%28 = getelementptr inbounds i32, i32* %27, i64 %26
store i32* %28, i32** @_perm_alloc.ptr
%29 = load i8*, i8** %3
ret i8* %29
}

LLVM IR (-O2):
@_perm_alloc.ptr = internal unnamed_addr global i32* null
@_perm_alloc.rem = internal unnamed_addr global i64 0
define i8* @_perm_alloc(i64 %0) {
%2 = add i64 %0, 15
%3 = and i64 %2, -16
%4 = load i64, i64* @_perm_alloc.rem
%5 = icmp ugt i64 %3, %4
%6 = icmp eq i64 %4, 0
%7 = or i1 %5, %6
br i1 %7, label %10, label %8
8: ; preds = %1
%9 = load i8*, i8** bitcast (i32** @_perm_alloc.ptr to i8**)
br label %17
10: ; preds = %1
%11 = tail call i32* @malloc(i32 8388608)
store i32* %11, i32** @_perm_alloc.ptr
%12 = icmp eq i32* %11, null
br i1 %12, label %13, label %15
13: ; preds = %10
%14 = tail call i32 @exit(i32 1)
unreachable
15: ; preds = %10
%16 = bitcast i32* %11 to i8*
br label %17
17: ; preds = %8, %15
%18 = phi i64 [ %4, %8 ], [ 8388608, %15 ]
%19 = phi i8* [ %9, %8 ], [ %16, %15 ]
%20 = sub i64 %18, %3
store i64 %20, i64* @_perm_alloc.rem
%21 = bitcast i8* %19 to i32*
%22 = getelementptr inbounds i32, i32* %21, i64 %3
store i32* %22, i32** @_perm_alloc.ptr
ret i8* %19
}