#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 size_t ssize_t;

/* Variables and functions */
size_t partition(char *, size_t, size_t, size_t,
                 int (*)(void const *, void const *));
void quicksort(void *array, size_t len, size_t size,
               int (*compare)(const void *, const void *)) {
  char *arr = (char *)array;
  size_t low = 0;
  size_t up = (len - 1) * size;
  size_t stack[len - 1];
  ssize_t top = 0;
  stack[top] = low;
  stack[++top] = up;
  size_t part;
  while (top >= 0) {
    up = stack[top--];
    low = stack[top--];
    part = partition(arr, size, low, up, compare);
    if (part > low + size) {
      stack[++top] = low;
      stack[++top] = part - size;
    }
    if (part + size < up) {
      stack[++top] = part + size;
      stack[++top] = up;
    }
  }
}


x86 assembly (clang, -O0):
<quicksort>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
movq   $0x0,-0x30(%rbp)
mov    -0x10(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    -0x18(%rbp),%rcx
imul   %rcx,%rax
mov    %rax,-0x38(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rsp,%rdx
mov    %rdx,-0x40(%rbp)
lea    0x7(,%rax,8),%rdx
and    $0xfffffffffffffff0,%rdx
mov    %rsp,%rax
sub    %rdx,%rax
mov    %rax,-0x60(%rbp)
mov    %rax,%rsp
mov    %rcx,-0x48(%rbp)
movq   $0x0,-0x50(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x50(%rbp),%rcx
mov    %rdx,(%rax,%rcx,8)
mov    -0x38(%rbp),%rdx
mov    -0x50(%rbp),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x50(%rbp)
mov    %rdx,0x8(%rax,%rcx,8)
cmpq   $0x0,-0x50(%rbp)
jb     129d <quicksort+0x18d>
mov    -0x60(%rbp),%rax
mov    -0x50(%rbp),%rcx
mov    %rcx,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,-0x50(%rbp)
mov    (%rax,%rcx,8),%rcx
mov    %rcx,-0x38(%rbp)
mov    -0x50(%rbp),%rcx
mov    %rcx,%rdx
add    $0xffffffffffffffff,%rdx
mov    %rdx,-0x50(%rbp)
mov    (%rax,%rcx,8),%rax
mov    %rax,-0x30(%rbp)
mov    -0x28(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    -0x30(%rbp),%rdx
mov    -0x38(%rbp),%rcx
mov    -0x20(%rbp),%r8
call   1030 <partition@plt>
mov    %rax,-0x58(%rbp)
mov    -0x58(%rbp),%rax
mov    -0x30(%rbp),%rcx
add    -0x18(%rbp),%rcx
cmp    %rcx,%rax
jbe    124e <quicksort+0x13e>
mov    -0x60(%rbp),%rax
mov    -0x30(%rbp),%rdx
mov    -0x50(%rbp),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x50(%rbp)
mov    %rdx,0x8(%rax,%rcx,8)
mov    -0x58(%rbp),%rdx
sub    -0x18(%rbp),%rdx
mov    -0x50(%rbp),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x50(%rbp)
mov    %rdx,0x8(%rax,%rcx,8)
mov    -0x58(%rbp),%rax
add    -0x18(%rbp),%rax
cmp    -0x38(%rbp),%rax
jae    1298 <quicksort+0x188>
mov    -0x60(%rbp),%rax
mov    -0x58(%rbp),%rdx
add    -0x18(%rbp),%rdx
mov    -0x50(%rbp),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x50(%rbp)
mov    %rdx,0x8(%rax,%rcx,8)
mov    -0x38(%rbp),%rdx
mov    -0x50(%rbp),%rcx
mov    %rcx,%rsi
add    $0x1,%rsi
mov    %rsi,-0x50(%rbp)
mov    %rdx,0x8(%rax,%rcx,8)
jmp    11a7 <quicksort+0x97>
mov    -0x40(%rbp),%rax
mov    %rax,%rsp
mov    %rbp,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<quicksort>:
push   %rbp
mov    %rsp,%rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x18,%rsp
mov    %rcx,-0x38(%rbp)
mov    %rdx,%r13
mov    %rdi,-0x30(%rbp)
lea    -0x1(%rsi),%r12
imul   %rdx,%r12
mov    %rsp,%rax
lea    0x7(,%rsi,8),%rcx
and    $0xfffffffffffffff0,%rcx
mov    %rax,%r14
sub    %rcx,%r14
mov    %r14,%rsp
neg    %rcx
movq   $0x0,(%rax,%rcx,1)
mov    %r12,0x8(%r14)
mov    $0x1,%r15d
jmp    1190 <quicksort+0x80>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
mov    %rax,%rcx
sub    %r13,%rcx
mov    %rcx,(%r14,%r15,8)
add    %r13,%rax
cmp    %r12,%rax
jae    11b9 <quicksort+0xa9>
mov    %rax,0x8(%r14,%r15,8)
mov    %r12,0x10(%r14,%r15,8)
add    $0x2,%r15
mov    -0x8(%r14,%r15,8),%rbx
mov    -0x30(%rbp),%rdi
mov    %r13,%rsi
mov    %rbx,%rdx
mov    %r12,%rcx
mov    -0x38(%rbp),%r8
call   1030 <partition@plt>
add    %r13,%rbx
cmp    %rbx,%rax
ja     1170 <quicksort+0x60>
add    $0xfffffffffffffffe,%r15
jmp    117a <quicksort+0x6a>
mov    (%r14,%r15,8),%r12
jmp    1190 <quicksort+0x80>

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

LLVM IR (-O2):
define void @quicksort(i8* %0, i64 %1, i64 %2, i32 (i8*, i8*)* %3) {
%5 = add i64 %1, -1
%6 = mul i64 %5, %2
%7 = alloca i64, i64 %5
store i64 0, i64* %7
%8 = getelementptr inbounds i64, i64* %7, i64 1
store i64 %6, i64* %8
br label %9
9: ; preds = %28, %4
%10 = phi i64 [ %30, %28 ], [ %6, %4 ]
%11 = phi i64 [ %25, %28 ], [ 1, %4 ]
br label %12
12: ; preds = %9, %31
%13 = phi i64 [ %34, %31 ], [ %11, %9 ]
%14 = add i64 %13, -1
%15 = add i64 %13, -2
%16 = getelementptr inbounds i64, i64* %7, i64 %14
%17 = load i64, i64* %16
%18 = tail call i64 @partition(i8* %0, i64 %2, i64 %17, i64 %10, i32 (i8*, i8*)* %3)
%19 = add i64 %17, %2
%20 = icmp ugt i64 %18, %19
br i1 %20, label %21, label %24
21: ; preds = %12
%22 = getelementptr inbounds i64, i64* %7, i64 %13
%23 = sub i64 %18, %2
store i64 %23, i64* %22
br label %24
24: ; preds = %21, %12
%25 = phi i64 [ %13, %21 ], [ %15, %12 ]
%26 = add i64 %18, %2
%27 = icmp ult i64 %26, %10
br i1 %27, label %31, label %28
28: ; preds = %24
%29 = getelementptr inbounds i64, i64* %7, i64 %25
%30 = load i64, i64* %29
br label %9
31: ; preds = %24
%32 = add i64 %25, 1
%33 = getelementptr inbounds i64, i64* %7, i64 %32
store i64 %26, i64* %33
%34 = add i64 %25, 2
%35 = getelementptr inbounds i64, i64* %7, i64 %34
store i64 %10, i64* %35
br label %12
}