Problem 1003

Lonely Singles: S(80), sum of sad integers leaving singletons only at positions < 80. Meet-in-the-middle enumeration with gap-3 constraint.

Answer16561580535729
Output16561580535729
StatusPASS
Native helperno
Runtime7620 ms
Peak memory225216 KB
Time complexityO(n^2) (estimated)
Space complexityO(1) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n!)
Space complexityO(1)O(n^2)
ApproachFlow solutionBacktracking search
VerdictOptimal

Flow source

# Project Euler 1003
# Lonely Singles: S(80), sum of sad integers leaving singletons only at positions < 80.
# Meet-in-the-middle enumeration with gap-3 constraint.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
}

struct Entry {
    boundary: i64,
    tail: i64,
    value: i64,
    prefix_mask: i32
}

# Global state
let mut h_arr: ptr<i64> = null
let mut boundary_arr: ptr<i64> = null
let mut tail_arr: ptr<i64> = null
let mut value_arr: ptr<i64> = null
let mut right_entries: ptr<Entry> = null
let mut right_prefix: ptr<i64> = null
let mut right_count: i32 = 0
let mut limit_val: i32 = 80
let mut split_val: i32 = 40
let mut total_sum: i64 = 0

# allowed_masks: flat array, mask*4 + i
let mut allowed_masks: ptr<i32> = null
let mut allowed_count: ptr<i32> = null

# ---- comparison helpers ----

function entry_less(a: Entry, b: Entry) -> bool {
    if a.boundary != b.boundary { return a.boundary < b.boundary }
    if a.prefix_mask != b.prefix_mask { return a.prefix_mask < b.prefix_mask }
    return a.tail < b.tail
}

function entry_greater(a: Entry, b: Entry) -> bool {
    if a.boundary != b.boundary { return a.boundary > b.boundary }
    if a.prefix_mask != b.prefix_mask { return a.prefix_mask > b.prefix_mask }
    return a.tail > b.tail
}

function entry_cmp_key(e: Entry, bd: i64, pm: i32, tl: i64) -> i32 {
    if e.boundary != bd {
        if e.boundary < bd { return -1 }
        return 1
    }
    if e.prefix_mask != pm {
        if e.prefix_mask < pm { return -1 }
        return 1
    }
    if e.tail != tl {
        if e.tail < tl { return -1 }
        return 1
    }
    return 0
}

# ---- heapsort ----

function sift_down(arr: ptr<Entry>, start: i32, endd: i32) -> void {
    let mut root: i32 = start
    let mut cont: bool = true
    while cont {
        let mut child: i32 = 2 * root + 1
        if child > endd {
            cont = false
        } else {
            if child + 1 <= endd && entry_greater(arr[child + 1], arr[child]) {
                child = child + 1
            }
            if entry_greater(arr[child], arr[root]) {
                let t: Entry = arr[root]
                arr[root] = arr[child]
                arr[child] = t
                root = child
            } else {
                cont = false
            }
        }
    }
}

function heapsort_entries(arr: ptr<Entry>, n: i32) -> void {
    if n <= 1 { return }
    let mut start: i32 = n / 2 - 1
    while start >= 0 {
        sift_down(arr, start, n - 1)
        start = start - 1
    }
    let mut endd: i32 = n - 1
    while endd > 0 {
        let t: Entry = arr[0]
        arr[0] = arr[endd]
        arr[endd] = t
        endd = endd - 1
        sift_down(arr, 0, endd)
    }
}

# ---- binary search (lower bound) ----

function lower_bound(arr: ptr<Entry>, n: i32, bd: i64, pm: i32, tl: i64) -> i32 {
    let mut lo: i32 = 0
    let mut hi: i32 = n
    while lo < hi {
        let mid: i32 = (lo + hi) / 2
        if entry_cmp_key(arr[mid], bd, pm, tl) < 0 {
            lo = mid + 1
        } else {
            hi = mid
        }
    }
    return lo
}

# ---- generate right half ----

function gen_right(pos: i32, prev1: i32, prev2: i32,
                   bs: i64, ts: i64, vs: i64, pm: i32) -> void {
    if pos == limit_val {
        right_entries[right_count] = Entry {
            boundary: bs,
            tail: ts,
            value: vs,
            prefix_mask: pm
        }
        right_count = right_count + 1
        return
    }
    # Don't place at pos
    gen_right(pos + 1, 0, prev1, bs, ts, vs, pm)
    if prev1 != 0 || prev2 != 0 { return }
    # Place at pos
    let npm: i32 = pm
    if pos == split_val {
        npm = npm | 1
    } else {
        if pos == split_val + 1 {
            npm = npm | 2
        }
    }
    gen_right(pos + 1, 1, prev1,
              bs + boundary_arr[pos], ts + tail_arr[pos], vs + value_arr[pos], npm)
}

# ---- generate left half and accumulate ----

function gen_left(pos: i32, prev1: i32, prev2: i32,
                  bs: i64, ts: i64, vs: i64) -> void {
    if pos == split_val {
        let last_mask: i32 = prev1 | (prev2 << 1)
        let needed_boundary: i64 = 0 - bs
        let needed_tail: i64 = 0 - ts
        let mut i: i32 = 0
        while i < allowed_count[last_mask] {
            let pm: i32 = allowed_masks[last_mask * 4 + i]
            # Find first entry >= (needed_boundary, pm, needed_tail)
            let start: i32 = lower_bound(right_entries, right_count, needed_boundary, pm, needed_tail)
            # Find first entry >= (needed_boundary, pm+1, -inf)
            let endd: i32 = lower_bound(right_entries, right_count, needed_boundary, pm + 1, -9223372036854775807)
            let count: i32 = endd - start
            if count > 0 {
                total_sum = total_sum + (count as i64) * vs + right_prefix[endd] - right_prefix[start]
            }
            i = i + 1
        }
        return
    }
    # Don't place at pos
    gen_left(pos + 1, 0, prev1, bs, ts, vs)
    if prev1 != 0 || prev2 != 0 { return }
    # Place at pos
    let add_b: i64 = 0
    let add_t: i64 = 0
    let add_v: i64 = 0
    if pos == 0 {
        add_v = 1
    } else {
        if pos == 1 {
            add_b = -1
        } else {
            if pos == 2 {
                add_b = 1
                add_t = -1
                add_v = -2
            } else {
                add_b = boundary_arr[pos]
                add_t = tail_arr[pos]
                add_v = value_arr[pos]
            }
        }
    }
    gen_left(pos + 1, 1, prev1, bs + add_b, ts + add_t, vs + add_v)
}

function init_allowed() -> void {
    allowed_masks = calloc(16, 4) as ptr<i32>
    allowed_count = calloc(4, 4) as ptr<i32>
    let mut mask: i32 = 0
    while mask < 4 {
        allowed_count[mask] = 0
        let mut prefix: i32 = 0
        while prefix < 4 {
            let skip: bool = false
            if (mask & 1) != 0 && (prefix & 3) != 0 {
                skip = true
            }
            if (mask & 2) != 0 && (prefix & 1) != 0 {
                skip = true
            }
            if !skip {
                allowed_masks[mask * 4 + allowed_count[mask]] = prefix
                allowed_count[mask] = allowed_count[mask] + 1
            }
            prefix = prefix + 1
        }
        mask = mask + 1
    }
}

function main() -> i32 {
    limit_val = 80
    split_val = limit_val / 2

    # Compute coefficients
    h_arr = calloc(84, 8) as ptr<i64>
    boundary_arr = calloc(80, 8) as ptr<i64>
    tail_arr = calloc(80, 8) as ptr<i64>
    value_arr = calloc(80, 8) as ptr<i64>

    h_arr[1] = 0
    h_arr[2] = 0
    h_arr[3] = 1
    let mut i: i32 = 4
    while i <= limit_val {
        h_arr[i] = 2 * h_arr[i - 3] - h_arr[i - 2]
        i = i + 1
    }
    let mut pos: i32 = 3
    while pos < limit_val {
        boundary_arr[pos] = h_arr[pos] - 3 * h_arr[pos - 1] + 2 * h_arr[pos - 2]
        tail_arr[pos] = h_arr[pos - 1] - 2 * h_arr[pos - 2]
        value_arr[pos] = 2 * (tail_arr[pos] + h_arr[pos])
        pos = pos + 1
    }

    init_allowed()

    # Allocate right entries
    right_entries = calloc(8000000, 32) as ptr<Entry>
    right_prefix = calloc(8000001, 8) as ptr<i64>
    right_count = 0

    gen_right(split_val, 0, 0, 0, 0, 0, 0)

    # Sort right entries
    heapsort_entries(right_entries, right_count)

    # Build prefix sums of value
    right_prefix[0] = 0
    let mut j: i32 = 0
    while j < right_count {
        right_prefix[j + 1] = right_prefix[j] + right_entries[j].value
        j = j + 1
    }

    # Generate left half and accumulate
    total_sum = 0
    gen_left(0, 0, 0, 0, 0, 0)

    printf("%lld\n", total_sum)

    free(h_arr as ptr<void>)
    free(boundary_arr as ptr<void>)
    free(tail_arr as ptr<void>)
    free(value_arr as ptr<void>)
    free(right_entries as ptr<void>)
    free(right_prefix as ptr<void>)
    free(allowed_masks as ptr<void>)
    free(allowed_count as ptr<void>)
    return 0
}

Generated C

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Flow runtime helpers */
typedef struct flow_temp_node { struct flow_temp_node* next; } flow_temp_node;
static flow_temp_node* flow_temp_head = NULL;
static int flow_temp_atexit_set = 0;
__attribute__((unused)) static void flow_temp_free_all(void) {
    while (flow_temp_head) {
        flow_temp_node* n = flow_temp_head;
        flow_temp_head = n->next;
        free(n);
    }
}
__attribute__((unused)) static void* flow_temp_alloc(size_t nbytes) {
    flow_temp_node* node = (flow_temp_node*)malloc(sizeof(flow_temp_node) + nbytes);
    if (!node) return NULL;
    node->next = flow_temp_head;
    flow_temp_head = node;
    if (!flow_temp_atexit_set) {
        flow_temp_atexit_set = 1;
        atexit(flow_temp_free_all);
    }
    return (void*)(node + 1);
}
#ifndef FLOW_DIAG
#define FLOW_DIAG(msg) fprintf(stderr, "%s", (msg))
#endif
#ifndef FLOW_LOG
#define FLOW_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
#ifndef FLOW_LOG_EMPTY
#define FLOW_LOG_EMPTY(fmt) printf(fmt)
#endif
static char* flow_strcat(const char* a, const char* b) {
    size_t la = strlen(a ? a : ""), lb = strlen(b ? b : "");
    char* r = (char*)flow_temp_alloc(la + lb + 1);
    if (!r) return NULL;
    if (la) memcpy(r, a, la);
    if (lb) memcpy(r + la, b, lb);
    r[la + lb] = '\0';
    return r;
}

#define __flow_in_arr(arr, val) __extension__ ({ \
    int _found = 0; \
    size_t _n = sizeof(arr)/sizeof((arr)[0]); \
    for (size_t _i = 0; _i < _n; _i++) { \
        if ((arr)[_i] == (val)) { _found = 1; break; } \
    } _found; })

/* Unified fault handler (MISRA #279) — override with -DFLOW_FAULT_HANDLER=fn */
#ifndef FLOW_FAULT_HANDLER
__attribute__((unused)) static inline void flow_fault_handler(const char* msg) {
    fprintf(stderr, "flow: %s\n", msg ? msg : "fault");
    abort();
#if defined(__GNUC__) || defined(__clang__)
    __builtin_unreachable();
#endif
}
#else
#define flow_fault_handler FLOW_FAULT_HANDLER
#endif
#define flow_div_by_zero_handler() flow_fault_handler("division by zero")
#define flow_shift_ub_handler() flow_fault_handler("invalid shift (amount out of range or left-shift of negative)")

#ifndef FLOW_CHECKED_DIV
#define FLOW_CHECKED_DIV(L, R) (((R) != 0) ? ((L) / (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_MOD
#define FLOW_CHECKED_MOD(L, R) (((R) != 0) ? ((L) % (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHL
#define FLOW_CHECKED_SHL(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull)) && ((L) >= 0)) ? ((L) << (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHR
#define FLOW_CHECKED_SHR(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull))) ? ((L) >> (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif

#include <math.h>

void* _ui_state = NULL;

static inline float i32_to_f32(int32_t v) { return (float)v; }

/* Host stub for @gpu kernels (device codegen replaces this). */
static inline int32_t gpu_thread_id(void) { return 0; }

typedef struct Entry Entry;

struct Entry {
    int64_t boundary;
    int64_t tail;
    int64_t value;
    int32_t prefix_mask;
};

bool entry_less_Entry_Entry(Entry a, Entry b);
bool entry_greater_Entry_Entry(Entry a, Entry b);
int32_t entry_cmp_key_Entry_i64_i32_i64(Entry e, int64_t bd, int32_t pm, int64_t tl);
void sift_down_ptr_Entry_i32_i32(Entry* arr, int32_t start, int32_t endd);
void heapsort_entries_ptr_Entry_i32(Entry* arr, int32_t n);
int32_t lower_bound_ptr_Entry_i32_i64_i32_i64(Entry* arr, int32_t n, int64_t bd, int32_t pm, int64_t tl);
void gen_right_i32_i32_i32_i64_i64_i64_i32(int32_t pos, int32_t prev1, int32_t prev2, int64_t bs, int64_t ts, int64_t vs, int32_t pm);
void gen_left_i32_i32_i32_i64_i64_i64(int32_t pos, int32_t prev1, int32_t prev2, int64_t bs, int64_t ts, int64_t vs);
void init_allowed(void);
int32_t main(void);

/* Module statics */
static int64_t* h_arr = NULL;
static int64_t* boundary_arr = NULL;
static int64_t* tail_arr = NULL;
static int64_t* value_arr = NULL;
static Entry* right_entries = NULL;
static int64_t* right_prefix = NULL;
static int32_t right_count = 0;
static int32_t limit_val = 80;
static int32_t split_val = 40;
static int64_t total_sum = 0;
static int32_t* allowed_masks = NULL;
static int32_t* allowed_count = NULL;



bool entry_less_Entry_Entry(Entry a, Entry b) {
    if (a.boundary != b.boundary) {
        return a.boundary < b.boundary;
    }
    if (a.prefix_mask != b.prefix_mask) {
        return a.prefix_mask < b.prefix_mask;
    }
    return a.tail < b.tail;
}

bool entry_greater_Entry_Entry(Entry a, Entry b) {
    if (a.boundary != b.boundary) {
        return a.boundary > b.boundary;
    }
    if (a.prefix_mask != b.prefix_mask) {
        return a.prefix_mask > b.prefix_mask;
    }
    return a.tail > b.tail;
}

int32_t entry_cmp_key_Entry_i64_i32_i64(Entry e, int64_t bd, int32_t pm, int64_t tl) {
    if (e.boundary != bd) {
        if (e.boundary < bd) {
            return (-1);
        }
        return 1;
    }
    if (e.prefix_mask != pm) {
        if (e.prefix_mask < pm) {
            return (-1);
        }
        return 1;
    }
    if (e.tail != tl) {
        if (e.tail < tl) {
            return (-1);
        }
        return 1;
    }
    return 0;
}

void sift_down_ptr_Entry_i32_i32(Entry* arr, int32_t start, int32_t endd) {
    int32_t root = start;
    bool cont = 1;
    while (cont) {
        int32_t child = ((2 * root) + 1);
        if (child > endd) {
            cont = 0;
        } else {
            if (((child + 1) <= endd && entry_greater_Entry_Entry(arr[(child + 1)], arr[child]))) {
                child = (child + 1);
            }
            if (entry_greater_Entry_Entry(arr[child], arr[root])) {
                Entry t = arr[root];
                arr[root] = arr[child];
                arr[child] = t;
                root = child;
            } else {
                cont = 0;
            }
        }
    }
}

void heapsort_entries_ptr_Entry_i32(Entry* arr, int32_t n) {
    if (n <= 1) {
        return;
    }
    int32_t start = (FLOW_CHECKED_DIV((n), (2)) - 1);
    while (start >= 0) {
        sift_down_ptr_Entry_i32_i32(arr, start, (n - 1));
        start = (start - 1);
    }
    int32_t endd = (n - 1);
    while (endd > 0) {
        Entry t = arr[0];
        arr[0] = arr[endd];
        arr[endd] = t;
        endd = (endd - 1);
        sift_down_ptr_Entry_i32_i32(arr, 0, endd);
    }
}

int32_t lower_bound_ptr_Entry_i32_i64_i32_i64(Entry* arr, int32_t n, int64_t bd, int32_t pm, int64_t tl) {
    int32_t lo = 0;
    int32_t hi = n;
    while (lo < hi) {
        int32_t mid = FLOW_CHECKED_DIV(((lo + hi)), (2));
        if (entry_cmp_key_Entry_i64_i32_i64(arr[mid], bd, pm, tl) < 0) {
            lo = (mid + 1);
        } else {
            hi = mid;
        }
    }
    return lo;
}

void gen_right_i32_i32_i32_i64_i64_i64_i32(int32_t pos, int32_t prev1, int32_t prev2, int64_t bs, int64_t ts, int64_t vs, int32_t pm) {
    if (pos == limit_val) {
        right_entries[right_count] = (Entry){ .boundary = bs, .tail = ts, .value = vs, .prefix_mask = pm };
        right_count = (right_count + 1);
        return;
    }
    gen_right_i32_i32_i32_i64_i64_i64_i32((pos + 1), 0, prev1, bs, ts, vs, pm);
    if ((prev1 != 0 || prev2 != 0)) {
        return;
    }
    int32_t npm = pm;
    if (pos == split_val) {
        npm = (npm | 1);
    } else {
        if (pos == (split_val + 1)) {
            npm = (npm | 2);
        }
    }
    gen_right_i32_i32_i32_i64_i64_i64_i32((pos + 1), 1, prev1, (bs + boundary_arr[pos]), (ts + tail_arr[pos]), (vs + value_arr[pos]), npm);
}

void gen_left_i32_i32_i32_i64_i64_i64(int32_t pos, int32_t prev1, int32_t prev2, int64_t bs, int64_t ts, int64_t vs) {
    if (pos == split_val) {
        int32_t last_mask = (prev1 | FLOW_CHECKED_SHL((prev2), (1)));
        int64_t needed_boundary = (0 - bs);
        int64_t needed_tail = (0 - ts);
        int32_t i = 0;
        while (i < allowed_count[last_mask]) {
            int32_t pm = allowed_masks[((last_mask * 4) + i)];
            int32_t start = lower_bound_ptr_Entry_i32_i64_i32_i64(right_entries, right_count, needed_boundary, pm, needed_tail);
            int32_t endd = lower_bound_ptr_Entry_i32_i64_i32_i64(right_entries, right_count, needed_boundary, (pm + 1), (-9223372036854775807));
            int32_t count = (endd - start);
            if (count > 0) {
                total_sum = (((total_sum + (((int64_t)(count)) * vs)) + right_prefix[endd]) - right_prefix[start]);
            }
            i = (i + 1);
        }
        return;
    }
    gen_left_i32_i32_i32_i64_i64_i64((pos + 1), 0, prev1, bs, ts, vs);
    if ((prev1 != 0 || prev2 != 0)) {
        return;
    }
    int64_t add_b = 0;
    int64_t add_t = 0;
    int64_t add_v = 0;
    if (pos == 0) {
        add_v = 1;
    } else {
        if (pos == 1) {
            add_b = (-1);
        } else {
            if (pos == 2) {
                add_b = 1;
                add_t = (-1);
                add_v = (-2);
            } else {
                add_b = boundary_arr[pos];
                add_t = tail_arr[pos];
                add_v = value_arr[pos];
            }
        }
    }
    gen_left_i32_i32_i32_i64_i64_i64((pos + 1), 1, prev1, (bs + add_b), (ts + add_t), (vs + add_v));
}

void init_allowed(void) {
    allowed_masks = ((int32_t*)(calloc(16, 4)));
    allowed_count = ((int32_t*)(calloc(4, 4)));
    int32_t mask = 0;
    while (mask < 4) {
        allowed_count[mask] = 0;
        int32_t prefix = 0;
        while (prefix < 4) {
            bool skip = 0;
            if (((mask & 1) != 0 && (prefix & 3) != 0)) {
                skip = 1;
            }
            if (((mask & 2) != 0 && (prefix & 1) != 0)) {
                skip = 1;
            }
            if ((!(skip))) {
                allowed_masks[((mask * 4) + allowed_count[mask])] = prefix;
                allowed_count[mask] = (allowed_count[mask] + 1);
            }
            prefix = (prefix + 1);
        }
        mask = (mask + 1);
    }
}

int32_t main(void) {
    limit_val = 80;
    split_val = FLOW_CHECKED_DIV((limit_val), (2));
    h_arr = ((int64_t*)(calloc(84, 8)));
    boundary_arr = ((int64_t*)(calloc(80, 8)));
    tail_arr = ((int64_t*)(calloc(80, 8)));
    value_arr = ((int64_t*)(calloc(80, 8)));
    h_arr[1] = 0;
    h_arr[2] = 0;
    h_arr[3] = 1;
    int32_t i = 4;
    while (i <= limit_val) {
        h_arr[i] = ((2 * h_arr[(i - 3)]) - h_arr[(i - 2)]);
        i = (i + 1);
    }
    int32_t pos = 3;
    while (pos < limit_val) {
        boundary_arr[pos] = ((h_arr[pos] - (3 * h_arr[(pos - 1)])) + (2 * h_arr[(pos - 2)]));
        tail_arr[pos] = (h_arr[(pos - 1)] - (2 * h_arr[(pos - 2)]));
        value_arr[pos] = (2 * (tail_arr[pos] + h_arr[pos]));
        pos = (pos + 1);
    }
    init_allowed();
    right_entries = ((Entry*)(calloc(8000000, 32)));
    right_prefix = ((int64_t*)(calloc(8000001, 8)));
    right_count = 0;
    gen_right_i32_i32_i32_i64_i64_i64_i32(split_val, 0, 0, 0, 0, 0, 0);
    heapsort_entries_ptr_Entry_i32(right_entries, right_count);
    right_prefix[0] = 0;
    int32_t j = 0;
    while (j < right_count) {
        right_prefix[(j + 1)] = (right_prefix[j] + right_entries[j].value);
        j = (j + 1);
    }
    total_sum = 0;
    gen_left_i32_i32_i32_i64_i64_i64(0, 0, 0, 0, 0, 0);
    printf("%lld\n", total_sum);
    free(((void*)(h_arr)));
    free(((void*)(boundary_arr)));
    free(((void*)(tail_arr)));
    free(((void*)(value_arr)));
    free(((void*)(right_entries)));
    free(((void*)(right_prefix)));
    free(((void*)(allowed_masks)));
    free(((void*)(allowed_count)));
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  // Struct: Entry
  // Fields:
  //   boundary: i64
  //   tail: i64
  //   value: i64
  //   prefix_mask: i32
  // Module static: h_arr
  llvm.mlir.global internal @h_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %0 = llvm.mlir.zero : !llvm.ptr
    llvm.return %0 : !llvm.ptr
  }
  // Module static: boundary_arr
  llvm.mlir.global internal @boundary_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %1 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1 : !llvm.ptr
  }
  // Module static: tail_arr
  llvm.mlir.global internal @tail_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %2 = llvm.mlir.zero : !llvm.ptr
    llvm.return %2 : !llvm.ptr
  }
  // Module static: value_arr
  llvm.mlir.global internal @value_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %3 = llvm.mlir.zero : !llvm.ptr
    llvm.return %3 : !llvm.ptr
  }
  // Module static: right_entries
  llvm.mlir.global internal @right_entries() {addr_space = 0 : i32} : !llvm.ptr {
    %4 = llvm.mlir.zero : !llvm.ptr
    llvm.return %4 : !llvm.ptr
  }
  // Module static: right_prefix
  llvm.mlir.global internal @right_prefix() {addr_space = 0 : i32} : !llvm.ptr {
    %5 = llvm.mlir.zero : !llvm.ptr
    llvm.return %5 : !llvm.ptr
  }
  // Module static: right_count
  llvm.mlir.global internal @right_count(0 : i32) : i32
  // Module static: limit_val
  llvm.mlir.global internal @limit_val(80 : i32) : i32
  // Module static: split_val
  llvm.mlir.global internal @split_val(40 : i32) : i32
  // Module static: total_sum
  llvm.mlir.global internal @total_sum(0 : i64) : i64
  // Module static: allowed_masks
  llvm.mlir.global internal @allowed_masks() {addr_space = 0 : i32} : !llvm.ptr {
    %6 = llvm.mlir.zero : !llvm.ptr
    llvm.return %6 : !llvm.ptr
  }
  // Module static: allowed_count
  llvm.mlir.global internal @allowed_count() {addr_space = 0 : i32} : !llvm.ptr {
    %7 = llvm.mlir.zero : !llvm.ptr
    llvm.return %7 : !llvm.ptr
  }
  func.func @entry_less(%arg0: !llvm.struct<(i64, i64, i64, i32)>, %arg1: !llvm.struct<(i64, i64, i64, i32)>) -> i1 {
    %8 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64, i32)>
    %9 = llvm.extractvalue %arg0[0] : !llvm.struct<(i64, i64, i64, i32)>
    %10 = llvm.insertvalue %9, %8[0] : !llvm.struct<(i64, i64, i64, i32)>
    %11 = llvm.extractvalue %arg0[1] : !llvm.struct<(i64, i64, i64, i32)>
    %12 = llvm.insertvalue %11, %10[1] : !llvm.struct<(i64, i64, i64, i32)>
    %13 = llvm.extractvalue %arg0[2] : !llvm.struct<(i64, i64, i64, i32)>
    %14 = llvm.insertvalue %13, %12[2] : !llvm.struct<(i64, i64, i64, i32)>
    %15 = llvm.extractvalue %arg0[3] : !llvm.struct<(i64, i64, i64, i32)>
    %16 = llvm.insertvalue %15, %14[3] : !llvm.struct<(i64, i64, i64, i32)>
    %17 = llvm.mlir.constant(1 : i64) : i64
    %18 = llvm.alloca %17 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
    llvm.store %16, %18 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
    %19 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64, i32)>
    %20 = llvm.extractvalue %arg1[0] : !llvm.struct<(i64, i64, i64, i32)>
    %21 = llvm.insertvalue %20, %19[0] : !llvm.struct<(i64, i64, i64, i32)>
    %22 = llvm.extractvalue %arg1[1] : !llvm.struct<(i64, i64, i64, i32)>
    %23 = llvm.insertvalue %22, %21[1] : !llvm.struct<(i64, i64, i64, i32)>
    %24 = llvm.extractvalue %arg1[2] : !llvm.struct<(i64, i64, i64, i32)>
    %25 = llvm.insertvalue %24, %23[2] : !llvm.struct<(i64, i64, i64, i32)>
    %26 = llvm.extractvalue %arg1[3] : !llvm.struct<(i64, i64, i64, i32)>
    %27 = llvm.insertvalue %26, %25[3] : !llvm.struct<(i64, i64, i64, i32)>
    %28 = llvm.mlir.constant(1 : i64) : i64
    %29 = llvm.alloca %28 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
    llvm.store %27, %29 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
    %30 = llvm.load %18 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %31 = llvm.getelementptr %18[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %32 = llvm.load %31 : !llvm.ptr -> i64
    %33 = llvm.load %29 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %34 = llvm.getelementptr %29[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %35 = llvm.load %34 : !llvm.ptr -> i64
    %36 = arith.cmpi ne, %32, %35 : i64
    cf.cond_br %36, ^bb0, ^bb1
    ^bb0:
      %37 = llvm.load %18 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %38 = llvm.getelementptr %18[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %39 = llvm.load %38 : !llvm.ptr -> i64
      %40 = llvm.load %29 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %41 = llvm.getelementptr %29[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %42 = llvm.load %41 : !llvm.ptr -> i64
      %43 = arith.cmpi slt, %39, %42 : i64
      func.return %43 : i1
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %44 = llvm.load %18 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %45 = llvm.getelementptr %18[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %46 = llvm.load %45 : !llvm.ptr -> i32
    %47 = llvm.load %29 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %48 = llvm.getelementptr %29[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %49 = llvm.load %48 : !llvm.ptr -> i32
    %50 = arith.cmpi ne, %46, %49 : i32
    cf.cond_br %50, ^bb3, ^bb4
    ^bb3:
      %51 = llvm.load %18 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %52 = llvm.getelementptr %18[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %53 = llvm.load %52 : !llvm.ptr -> i32
      %54 = llvm.load %29 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %55 = llvm.getelementptr %29[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %56 = llvm.load %55 : !llvm.ptr -> i32
      %57 = arith.cmpi slt, %53, %56 : i32
      func.return %57 : i1
    ^bb4:
      cf.br ^bb5
    ^bb5:
    %58 = llvm.load %18 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %59 = llvm.getelementptr %18[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %60 = llvm.load %59 : !llvm.ptr -> i64
    %61 = llvm.load %29 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %62 = llvm.getelementptr %29[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %63 = llvm.load %62 : !llvm.ptr -> i64
    %64 = arith.cmpi slt, %60, %63 : i64
    func.return %64 : i1
  }
  func.func @entry_greater(%arg0: !llvm.struct<(i64, i64, i64, i32)>, %arg1: !llvm.struct<(i64, i64, i64, i32)>) -> i1 {
    %65 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64, i32)>
    %66 = llvm.extractvalue %arg0[0] : !llvm.struct<(i64, i64, i64, i32)>
    %67 = llvm.insertvalue %66, %65[0] : !llvm.struct<(i64, i64, i64, i32)>
    %68 = llvm.extractvalue %arg0[1] : !llvm.struct<(i64, i64, i64, i32)>
    %69 = llvm.insertvalue %68, %67[1] : !llvm.struct<(i64, i64, i64, i32)>
    %70 = llvm.extractvalue %arg0[2] : !llvm.struct<(i64, i64, i64, i32)>
    %71 = llvm.insertvalue %70, %69[2] : !llvm.struct<(i64, i64, i64, i32)>
    %72 = llvm.extractvalue %arg0[3] : !llvm.struct<(i64, i64, i64, i32)>
    %73 = llvm.insertvalue %72, %71[3] : !llvm.struct<(i64, i64, i64, i32)>
    %74 = llvm.mlir.constant(1 : i64) : i64
    %75 = llvm.alloca %74 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
    llvm.store %73, %75 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
    %76 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64, i32)>
    %77 = llvm.extractvalue %arg1[0] : !llvm.struct<(i64, i64, i64, i32)>
    %78 = llvm.insertvalue %77, %76[0] : !llvm.struct<(i64, i64, i64, i32)>
    %79 = llvm.extractvalue %arg1[1] : !llvm.struct<(i64, i64, i64, i32)>
    %80 = llvm.insertvalue %79, %78[1] : !llvm.struct<(i64, i64, i64, i32)>
    %81 = llvm.extractvalue %arg1[2] : !llvm.struct<(i64, i64, i64, i32)>
    %82 = llvm.insertvalue %81, %80[2] : !llvm.struct<(i64, i64, i64, i32)>
    %83 = llvm.extractvalue %arg1[3] : !llvm.struct<(i64, i64, i64, i32)>
    %84 = llvm.insertvalue %83, %82[3] : !llvm.struct<(i64, i64, i64, i32)>
    %85 = llvm.mlir.constant(1 : i64) : i64
    %86 = llvm.alloca %85 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
    llvm.store %84, %86 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
    %87 = llvm.load %75 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %88 = llvm.getelementptr %75[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %89 = llvm.load %88 : !llvm.ptr -> i64
    %90 = llvm.load %86 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %91 = llvm.getelementptr %86[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %92 = llvm.load %91 : !llvm.ptr -> i64
    %93 = arith.cmpi ne, %89, %92 : i64
    cf.cond_br %93, ^bb6, ^bb7
    ^bb6:
      %94 = llvm.load %75 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %95 = llvm.getelementptr %75[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %96 = llvm.load %95 : !llvm.ptr -> i64
      %97 = llvm.load %86 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %98 = llvm.getelementptr %86[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %99 = llvm.load %98 : !llvm.ptr -> i64
      %100 = arith.cmpi sgt, %96, %99 : i64
      func.return %100 : i1
    ^bb7:
      cf.br ^bb8
    ^bb8:
    %101 = llvm.load %75 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %102 = llvm.getelementptr %75[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %103 = llvm.load %102 : !llvm.ptr -> i32
    %104 = llvm.load %86 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %105 = llvm.getelementptr %86[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %106 = llvm.load %105 : !llvm.ptr -> i32
    %107 = arith.cmpi ne, %103, %106 : i32
    cf.cond_br %107, ^bb9, ^bb10
    ^bb9:
      %108 = llvm.load %75 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %109 = llvm.getelementptr %75[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %110 = llvm.load %109 : !llvm.ptr -> i32
      %111 = llvm.load %86 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %112 = llvm.getelementptr %86[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %113 = llvm.load %112 : !llvm.ptr -> i32
      %114 = arith.cmpi sgt, %110, %113 : i32
      func.return %114 : i1
    ^bb10:
      cf.br ^bb11
    ^bb11:
    %115 = llvm.load %75 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %116 = llvm.getelementptr %75[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %117 = llvm.load %116 : !llvm.ptr -> i64
    %118 = llvm.load %86 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %119 = llvm.getelementptr %86[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %120 = llvm.load %119 : !llvm.ptr -> i64
    %121 = arith.cmpi sgt, %117, %120 : i64
    func.return %121 : i1
  }
  func.func @entry_cmp_key(%arg0: !llvm.struct<(i64, i64, i64, i32)>, %arg1: i64, %arg2: i32, %arg3: i64) -> i32 {
    %122 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64, i32)>
    %123 = llvm.extractvalue %arg0[0] : !llvm.struct<(i64, i64, i64, i32)>
    %124 = llvm.insertvalue %123, %122[0] : !llvm.struct<(i64, i64, i64, i32)>
    %125 = llvm.extractvalue %arg0[1] : !llvm.struct<(i64, i64, i64, i32)>
    %126 = llvm.insertvalue %125, %124[1] : !llvm.struct<(i64, i64, i64, i32)>
    %127 = llvm.extractvalue %arg0[2] : !llvm.struct<(i64, i64, i64, i32)>
    %128 = llvm.insertvalue %127, %126[2] : !llvm.struct<(i64, i64, i64, i32)>
    %129 = llvm.extractvalue %arg0[3] : !llvm.struct<(i64, i64, i64, i32)>
    %130 = llvm.insertvalue %129, %128[3] : !llvm.struct<(i64, i64, i64, i32)>
    %131 = llvm.mlir.constant(1 : i64) : i64
    %132 = llvm.alloca %131 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
    llvm.store %130, %132 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
    %133 = llvm.load %132 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %134 = llvm.getelementptr %132[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %135 = llvm.load %134 : !llvm.ptr -> i64
    %136 = arith.cmpi ne, %135, %arg1 : i64
    cf.cond_br %136, ^bb12, ^bb13
    ^bb12:
      %137 = llvm.load %132 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %138 = llvm.getelementptr %132[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %139 = llvm.load %138 : !llvm.ptr -> i64
      %140 = arith.cmpi slt, %139, %arg1 : i64
      cf.cond_br %140, ^bb15, ^bb16
      ^bb15:
        %141 = arith.constant 1 : i32
        %143 = arith.constant 0 : i32
        %142 = arith.subi %143, %141 : i32
        func.return %142 : i32
      ^bb16:
        cf.br ^bb17
      ^bb17:
      %144 = arith.constant 1 : i32
      func.return %144 : i32
    ^bb13:
      cf.br ^bb14
    ^bb14:
    %145 = llvm.load %132 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %146 = llvm.getelementptr %132[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %147 = llvm.load %146 : !llvm.ptr -> i32
    %148 = arith.cmpi ne, %147, %arg2 : i32
    cf.cond_br %148, ^bb18, ^bb19
    ^bb18:
      %149 = llvm.load %132 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %150 = llvm.getelementptr %132[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %151 = llvm.load %150 : !llvm.ptr -> i32
      %152 = arith.cmpi slt, %151, %arg2 : i32
      cf.cond_br %152, ^bb21, ^bb22
      ^bb21:
        %153 = arith.constant 1 : i32
        %155 = arith.constant 0 : i32
        %154 = arith.subi %155, %153 : i32
        func.return %154 : i32
      ^bb22:
        cf.br ^bb23
      ^bb23:
      %156 = arith.constant 1 : i32
      func.return %156 : i32
    ^bb19:
      cf.br ^bb20
    ^bb20:
    %157 = llvm.load %132 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
    %158 = llvm.getelementptr %132[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
    %159 = llvm.load %158 : !llvm.ptr -> i64
    %160 = arith.cmpi ne, %159, %arg3 : i64
    cf.cond_br %160, ^bb24, ^bb25
    ^bb24:
      %161 = llvm.load %132 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %162 = llvm.getelementptr %132[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %163 = llvm.load %162 : !llvm.ptr -> i64
      %164 = arith.cmpi slt, %163, %arg3 : i64
      cf.cond_br %164, ^bb27, ^bb28
      ^bb27:
        %165 = arith.constant 1 : i32
        %167 = arith.constant 0 : i32
        %166 = arith.subi %167, %165 : i32
        func.return %166 : i32
      ^bb28:
        cf.br ^bb29
      ^bb29:
      %168 = arith.constant 1 : i32
      func.return %168 : i32
    ^bb25:
      cf.br ^bb26
    ^bb26:
    %169 = arith.constant 0 : i32
    func.return %169 : i32
  }
  func.func @sift_down(%arg0: !llvm.ptr, %arg1: i32, %arg2: i32) -> () {
    %170 = llvm.mlir.constant(1 : i64) : i64
    %171 = llvm.alloca %170 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg1, %171 : i32, !llvm.ptr
    %172 = arith.constant 1 : i1
    %173 = llvm.mlir.constant(1 : i64) : i64
    %174 = llvm.alloca %173 x i1 : (i64) -> !llvm.ptr
    llvm.store %172, %174 : i1, !llvm.ptr
    cf.br ^bb30
    ^bb30:
    %175 = llvm.load %174 : !llvm.ptr -> i1
    cf.cond_br %175, ^bb31, ^bb32
    ^bb31:
      %176 = arith.constant 2 : i32
      %177 = llvm.load %171 : !llvm.ptr -> i32
      %178 = arith.muli %176, %177 : i32
      %179 = arith.constant 1 : i32
      %180 = arith.addi %178, %179 : i32
      %181 = llvm.mlir.constant(1 : i64) : i64
      %182 = llvm.alloca %181 x i32 : (i64) -> !llvm.ptr
      llvm.store %180, %182 : i32, !llvm.ptr
      %183 = llvm.load %182 : !llvm.ptr -> i32
      %184 = arith.cmpi sgt, %183, %arg2 : i32
      cf.cond_br %184, ^bb33, ^bb34
      ^bb33:
        %185 = arith.constant 0 : i1
        llvm.store %185, %174 : i1, !llvm.ptr
        cf.br ^bb35
      ^bb34:
        %186 = llvm.load %182 : !llvm.ptr -> i32
        %187 = arith.constant 1 : i32
        %188 = arith.addi %186, %187 : i32
        %189 = arith.cmpi sle, %188, %arg2 : i32
        %190 = scf.if %189 -> (i1) {
          %193 = llvm.load %182 : !llvm.ptr -> i32
          %194 = arith.constant 1 : i32
          %195 = arith.addi %193, %194 : i32
          %196 = arith.extsi %195 : i32 to i64
          %197 = llvm.getelementptr %arg0[%196] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
          %192 = llvm.load %197 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
          %199 = llvm.load %182 : !llvm.ptr -> i32
          %200 = arith.extsi %199 : i32 to i64
          %201 = llvm.getelementptr %arg0[%200] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
          %198 = llvm.load %201 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
          %191 = func.call @entry_greater(%192, %198) : (!llvm.struct<(i64, i64, i64, i32)>, !llvm.struct<(i64, i64, i64, i32)>) -> i1
          scf.yield %191 : i1
        } else {
          %202 = arith.constant false
          scf.yield %202 : i1
        }
        cf.cond_br %190, ^bb36, ^bb37
        ^bb36:
          %203 = llvm.load %182 : !llvm.ptr -> i32
          %204 = arith.constant 1 : i32
          %205 = arith.addi %203, %204 : i32
          llvm.store %205, %182 : i32, !llvm.ptr
          cf.br ^bb38
        ^bb37:
          cf.br ^bb38
        ^bb38:
        %208 = llvm.load %182 : !llvm.ptr -> i32
        %209 = arith.extsi %208 : i32 to i64
        %210 = llvm.getelementptr %arg0[%209] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
        %207 = llvm.load %210 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
        %212 = llvm.load %171 : !llvm.ptr -> i32
        %213 = arith.extsi %212 : i32 to i64
        %214 = llvm.getelementptr %arg0[%213] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
        %211 = llvm.load %214 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
        %206 = func.call @entry_greater(%207, %211) : (!llvm.struct<(i64, i64, i64, i32)>, !llvm.struct<(i64, i64, i64, i32)>) -> i1
        cf.cond_br %206, ^bb39, ^bb40
        ^bb39:
          %216 = llvm.load %171 : !llvm.ptr -> i32
          %217 = arith.extsi %216 : i32 to i64
          %218 = llvm.getelementptr %arg0[%217] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
          %215 = llvm.load %218 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
          %219 = llvm.mlir.constant(1 : i64) : i64
          %220 = llvm.alloca %219 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
          llvm.store %215, %220 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
          %222 = llvm.load %182 : !llvm.ptr -> i32
          %223 = arith.extsi %222 : i32 to i64
          %224 = llvm.getelementptr %arg0[%223] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
          %221 = llvm.load %224 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
          %225 = llvm.load %171 : !llvm.ptr -> i32
          %226 = arith.extsi %225 : i32 to i64
          %227 = llvm.getelementptr %arg0[%226] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
          llvm.store %221, %227 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
          %228 = llvm.load %220 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
          %229 = llvm.load %182 : !llvm.ptr -> i32
          %230 = arith.extsi %229 : i32 to i64
          %231 = llvm.getelementptr %arg0[%230] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
          llvm.store %228, %231 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
          %232 = llvm.load %182 : !llvm.ptr -> i32
          llvm.store %232, %171 : i32, !llvm.ptr
          cf.br ^bb41
        ^bb40:
          %233 = arith.constant 0 : i1
          llvm.store %233, %174 : i1, !llvm.ptr
          cf.br ^bb41
        ^bb41:
        cf.br ^bb35
      ^bb35:
      cf.br ^bb30
    ^bb32:
    func.return
  }
  func.func @heapsort_entries(%arg0: !llvm.ptr, %arg1: i32) -> () {
    %234 = arith.constant 1 : i32
    %235 = arith.cmpi sle, %arg1, %234 : i32
    cf.cond_br %235, ^bb42, ^bb43
    ^bb42:
      func.return
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %236 = arith.constant 2 : i32
    %237 = arith.divsi %arg1, %236 : i32
    %238 = arith.constant 1 : i32
    %239 = arith.subi %237, %238 : i32
    %240 = llvm.mlir.constant(1 : i64) : i64
    %241 = llvm.alloca %240 x i32 : (i64) -> !llvm.ptr
    llvm.store %239, %241 : i32, !llvm.ptr
    cf.br ^bb45
    ^bb45:
    %242 = llvm.load %241 : !llvm.ptr -> i32
    %243 = arith.constant 0 : i32
    %244 = arith.cmpi sge, %242, %243 : i32
    cf.cond_br %244, ^bb46, ^bb47
    ^bb46:
      %246 = llvm.load %241 : !llvm.ptr -> i32
      %247 = arith.constant 1 : i32
      %248 = arith.subi %arg1, %247 : i32
      func.call @sift_down(%arg0, %246, %248) : (!llvm.ptr, i32, i32) -> ()
      %249 = llvm.load %241 : !llvm.ptr -> i32
      %250 = arith.constant 1 : i32
      %251 = arith.subi %249, %250 : i32
      llvm.store %251, %241 : i32, !llvm.ptr
      cf.br ^bb45
    ^bb47:
    %252 = arith.constant 1 : i32
    %253 = arith.subi %arg1, %252 : i32
    %254 = llvm.mlir.constant(1 : i64) : i64
    %255 = llvm.alloca %254 x i32 : (i64) -> !llvm.ptr
    llvm.store %253, %255 : i32, !llvm.ptr
    cf.br ^bb48
    ^bb48:
    %256 = llvm.load %255 : !llvm.ptr -> i32
    %257 = arith.constant 0 : i32
    %258 = arith.cmpi sgt, %256, %257 : i32
    cf.cond_br %258, ^bb49, ^bb50
    ^bb49:
      %260 = arith.constant 0 : i32
      %261 = arith.extsi %260 : i32 to i64
      %262 = llvm.getelementptr %arg0[%261] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %259 = llvm.load %262 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %263 = llvm.mlir.constant(1 : i64) : i64
      %264 = llvm.alloca %263 x !llvm.struct<(i64, i64, i64, i32)> : (i64) -> !llvm.ptr
      llvm.store %259, %264 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
      %266 = llvm.load %255 : !llvm.ptr -> i32
      %267 = arith.extsi %266 : i32 to i64
      %268 = llvm.getelementptr %arg0[%267] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %265 = llvm.load %268 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %269 = arith.constant 0 : i32
      %270 = arith.extsi %269 : i32 to i64
      %271 = llvm.getelementptr %arg0[%270] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      llvm.store %265, %271 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
      %272 = llvm.load %264 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %273 = llvm.load %255 : !llvm.ptr -> i32
      %274 = arith.extsi %273 : i32 to i64
      %275 = llvm.getelementptr %arg0[%274] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      llvm.store %272, %275 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
      %276 = llvm.load %255 : !llvm.ptr -> i32
      %277 = arith.constant 1 : i32
      %278 = arith.subi %276, %277 : i32
      llvm.store %278, %255 : i32, !llvm.ptr
      %280 = arith.constant 0 : i32
      %281 = llvm.load %255 : !llvm.ptr -> i32
      func.call @sift_down(%arg0, %280, %281) : (!llvm.ptr, i32, i32) -> ()
      cf.br ^bb48
    ^bb50:
    func.return
  }
  func.func @lower_bound(%arg0: !llvm.ptr, %arg1: i32, %arg2: i64, %arg3: i32, %arg4: i64) -> i32 {
    %282 = arith.constant 0 : i32
    %283 = llvm.mlir.constant(1 : i64) : i64
    %284 = llvm.alloca %283 x i32 : (i64) -> !llvm.ptr
    llvm.store %282, %284 : i32, !llvm.ptr
    %285 = llvm.mlir.constant(1 : i64) : i64
    %286 = llvm.alloca %285 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg1, %286 : i32, !llvm.ptr
    cf.br ^bb51
    ^bb51:
    %287 = llvm.load %284 : !llvm.ptr -> i32
    %288 = llvm.load %286 : !llvm.ptr -> i32
    %289 = arith.cmpi slt, %287, %288 : i32
    cf.cond_br %289, ^bb52, ^bb53
    ^bb52:
      %290 = llvm.load %284 : !llvm.ptr -> i32
      %291 = llvm.load %286 : !llvm.ptr -> i32
      %292 = arith.addi %290, %291 : i32
      %293 = arith.constant 2 : i32
      %294 = arith.divsi %292, %293 : i32
      %297 = arith.extsi %294 : i32 to i64
      %298 = llvm.getelementptr %arg0[%297] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %296 = llvm.load %298 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %295 = func.call @entry_cmp_key(%296, %arg2, %arg3, %arg4) : (!llvm.struct<(i64, i64, i64, i32)>, i64, i32, i64) -> i32
      %299 = arith.constant 0 : i32
      %300 = arith.cmpi slt, %295, %299 : i32
      cf.cond_br %300, ^bb54, ^bb55
      ^bb54:
        %301 = arith.constant 1 : i32
        %302 = arith.addi %294, %301 : i32
        llvm.store %302, %284 : i32, !llvm.ptr
        cf.br ^bb56
      ^bb55:
        llvm.store %294, %286 : i32, !llvm.ptr
        cf.br ^bb56
      ^bb56:
      cf.br ^bb51
    ^bb53:
    %303 = llvm.load %284 : !llvm.ptr -> i32
    func.return %303 : i32
  }
  func.func @gen_right(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i64, %arg4: i64, %arg5: i64, %arg6: i32) -> () {
    %304 = llvm.mlir.addressof @limit_val : !llvm.ptr
    %305 = llvm.load %304 : !llvm.ptr -> i32
    %306 = arith.cmpi eq, %arg0, %305 : i32
    cf.cond_br %306, ^bb57, ^bb58
    ^bb57:
      %307 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64, i32)>
      %308 = llvm.insertvalue %arg3, %307[0] : !llvm.struct<(i64, i64, i64, i32)>
      %309 = llvm.insertvalue %arg4, %308[1] : !llvm.struct<(i64, i64, i64, i32)>
      %310 = llvm.insertvalue %arg5, %309[2] : !llvm.struct<(i64, i64, i64, i32)>
      %311 = llvm.insertvalue %arg6, %310[3] : !llvm.struct<(i64, i64, i64, i32)>
      %312 = llvm.mlir.addressof @right_entries : !llvm.ptr
      %313 = llvm.load %312 : !llvm.ptr -> !llvm.ptr
      %314 = llvm.mlir.addressof @right_count : !llvm.ptr
      %315 = llvm.load %314 : !llvm.ptr -> i32
      %316 = arith.extsi %315 : i32 to i64
      %317 = llvm.getelementptr %313[%316] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      llvm.store %311, %317 : !llvm.struct<(i64, i64, i64, i32)>, !llvm.ptr
      %318 = llvm.mlir.addressof @right_count : !llvm.ptr
      %319 = llvm.load %318 : !llvm.ptr -> i32
      %320 = arith.constant 1 : i32
      %321 = arith.addi %319, %320 : i32
      %322 = llvm.mlir.addressof @right_count : !llvm.ptr
      llvm.store %321, %322 : i32, !llvm.ptr
      func.return
    ^bb58:
      cf.br ^bb59
    ^bb59:
    %324 = arith.constant 1 : i32
    %325 = arith.addi %arg0, %324 : i32
    %326 = arith.constant 0 : i32
    func.call @gen_right(%325, %326, %arg1, %arg3, %arg4, %arg5, %arg6) : (i32, i32, i32, i64, i64, i64, i32) -> ()
    %327 = arith.constant 0 : i32
    %328 = arith.cmpi ne, %arg1, %327 : i32
    %329 = scf.if %328 -> (i1) {
      %330 = arith.constant true
      scf.yield %330 : i1
    } else {
      %331 = arith.constant 0 : i32
      %332 = arith.cmpi ne, %arg2, %331 : i32
      scf.yield %332 : i1
    }
    cf.cond_br %329, ^bb60, ^bb61
    ^bb60:
      func.return
    ^bb61:
      cf.br ^bb62
    ^bb62:
    %333 = llvm.mlir.addressof @split_val : !llvm.ptr
    %334 = llvm.load %333 : !llvm.ptr -> i32
    %335 = arith.cmpi eq, %arg0, %334 : i32
    cf.cond_br %335, ^bb63, ^bb64
    ^bb63:
      %336 = arith.constant 1 : i32
      %337 = arith.ori %arg6, %336 : i32
      cf.br ^bb65(%337 : i32)
    ^bb64:
      %338 = llvm.mlir.addressof @split_val : !llvm.ptr
      %339 = llvm.load %338 : !llvm.ptr -> i32
      %340 = arith.constant 1 : i32
      %341 = arith.addi %339, %340 : i32
      %342 = arith.cmpi eq, %arg0, %341 : i32
      %343 = scf.if %342 -> (i32) {
        %344 = arith.constant 2 : i32
        %345 = arith.ori %arg6, %344 : i32
        scf.yield %345 : i32
      } else {
        scf.yield %arg6 : i32
      }
      cf.br ^bb65(%343 : i32)
    ^bb65(%346: i32):
    %348 = arith.constant 1 : i32
    %349 = arith.addi %arg0, %348 : i32
    %350 = arith.constant 1 : i32
    %352 = llvm.mlir.addressof @boundary_arr : !llvm.ptr
    %353 = llvm.load %352 : !llvm.ptr -> !llvm.ptr
    %354 = arith.extsi %arg0 : i32 to i64
    %355 = llvm.getelementptr %353[%354] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %351 = llvm.load %355 : !llvm.ptr -> i64
    %356 = arith.addi %arg3, %351 : i64
    %358 = llvm.mlir.addressof @tail_arr : !llvm.ptr
    %359 = llvm.load %358 : !llvm.ptr -> !llvm.ptr
    %360 = arith.extsi %arg0 : i32 to i64
    %361 = llvm.getelementptr %359[%360] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %357 = llvm.load %361 : !llvm.ptr -> i64
    %362 = arith.addi %arg4, %357 : i64
    %364 = llvm.mlir.addressof @value_arr : !llvm.ptr
    %365 = llvm.load %364 : !llvm.ptr -> !llvm.ptr
    %366 = arith.extsi %arg0 : i32 to i64
    %367 = llvm.getelementptr %365[%366] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %363 = llvm.load %367 : !llvm.ptr -> i64
    %368 = arith.addi %arg5, %363 : i64
    func.call @gen_right(%349, %350, %arg1, %356, %362, %368, %346) : (i32, i32, i32, i64, i64, i64, i32) -> ()
    func.return
  }
  func.func @gen_left(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i64, %arg4: i64, %arg5: i64) -> () {
    %369 = llvm.mlir.addressof @split_val : !llvm.ptr
    %370 = llvm.load %369 : !llvm.ptr -> i32
    %371 = arith.cmpi eq, %arg0, %370 : i32
    cf.cond_br %371, ^bb66, ^bb67
    ^bb66:
      %372 = arith.constant 1 : i32
      %373 = arith.shli %arg2, %372 : i32
      %374 = arith.ori %arg1, %373 : i32
      %375 = arith.constant 0 : i32
      %377 = arith.extsi %375 : i32 to i64
      %376 = arith.subi %377, %arg3 : i64
      %378 = arith.constant 0 : i32
      %380 = arith.extsi %378 : i32 to i64
      %379 = arith.subi %380, %arg4 : i64
      %381 = arith.constant 0 : i32
      %382 = llvm.mlir.constant(1 : i64) : i64
      %383 = llvm.alloca %382 x i32 : (i64) -> !llvm.ptr
      llvm.store %381, %383 : i32, !llvm.ptr
      cf.br ^bb69
      ^bb69:
      %384 = llvm.load %383 : !llvm.ptr -> i32
      %386 = llvm.mlir.addressof @allowed_count : !llvm.ptr
      %387 = llvm.load %386 : !llvm.ptr -> !llvm.ptr
      %388 = arith.extsi %374 : i32 to i64
      %389 = llvm.getelementptr %387[%388] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %385 = llvm.load %389 : !llvm.ptr -> i32
      %390 = arith.cmpi slt, %384, %385 : i32
      cf.cond_br %390, ^bb70, ^bb71
      ^bb70:
        %392 = llvm.mlir.addressof @allowed_masks : !llvm.ptr
        %393 = llvm.load %392 : !llvm.ptr -> !llvm.ptr
        %394 = arith.constant 4 : i32
        %395 = arith.muli %374, %394 : i32
        %396 = llvm.load %383 : !llvm.ptr -> i32
        %397 = arith.addi %395, %396 : i32
        %398 = arith.extsi %397 : i32 to i64
        %399 = llvm.getelementptr %393[%398] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %391 = llvm.load %399 : !llvm.ptr -> i32
        %401 = llvm.mlir.addressof @right_entries : !llvm.ptr
        %402 = llvm.load %401 : !llvm.ptr -> !llvm.ptr
        %403 = llvm.mlir.addressof @right_count : !llvm.ptr
        %404 = llvm.load %403 : !llvm.ptr -> i32
        %400 = func.call @lower_bound(%402, %404, %376, %391, %379) : (!llvm.ptr, i32, i64, i32, i64) -> i32
        %406 = llvm.mlir.addressof @right_entries : !llvm.ptr
        %407 = llvm.load %406 : !llvm.ptr -> !llvm.ptr
        %408 = llvm.mlir.addressof @right_count : !llvm.ptr
        %409 = llvm.load %408 : !llvm.ptr -> i32
        %410 = arith.constant 1 : i32
        %411 = arith.addi %391, %410 : i32
        %412 = arith.constant 9223372032559808511 : i32
        %414 = arith.constant 0 : i32
        %413 = arith.subi %414, %412 : i32
        %415 = arith.extsi %413 : i32 to i64
        %405 = func.call @lower_bound(%407, %409, %376, %411, %415) : (!llvm.ptr, i32, i64, i32, i64) -> i32
        %416 = arith.subi %405, %400 : i32
        %417 = arith.constant 0 : i32
        %418 = arith.cmpi sgt, %416, %417 : i32
        cf.cond_br %418, ^bb72, ^bb73
        ^bb72:
          %419 = llvm.mlir.addressof @total_sum : !llvm.ptr
          %420 = llvm.load %419 : !llvm.ptr -> i64
          %421 = arith.extsi %416 : i32 to i64
          %422 = arith.muli %421, %arg5 : i64
          %423 = arith.addi %420, %422 : i64
          %425 = llvm.mlir.addressof @right_prefix : !llvm.ptr
          %426 = llvm.load %425 : !llvm.ptr -> !llvm.ptr
          %427 = arith.extsi %405 : i32 to i64
          %428 = llvm.getelementptr %426[%427] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %424 = llvm.load %428 : !llvm.ptr -> i64
          %429 = arith.addi %423, %424 : i64
          %431 = llvm.mlir.addressof @right_prefix : !llvm.ptr
          %432 = llvm.load %431 : !llvm.ptr -> !llvm.ptr
          %433 = arith.extsi %400 : i32 to i64
          %434 = llvm.getelementptr %432[%433] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %430 = llvm.load %434 : !llvm.ptr -> i64
          %435 = arith.subi %429, %430 : i64
          %436 = llvm.mlir.addressof @total_sum : !llvm.ptr
          llvm.store %435, %436 : i64, !llvm.ptr
          cf.br ^bb74
        ^bb73:
          cf.br ^bb74
        ^bb74:
        %437 = llvm.load %383 : !llvm.ptr -> i32
        %438 = arith.constant 1 : i32
        %439 = arith.addi %437, %438 : i32
        llvm.store %439, %383 : i32, !llvm.ptr
        cf.br ^bb69
      ^bb71:
      func.return
    ^bb67:
      cf.br ^bb68
    ^bb68:
    %441 = arith.constant 1 : i32
    %442 = arith.addi %arg0, %441 : i32
    %443 = arith.constant 0 : i32
    func.call @gen_left(%442, %443, %arg1, %arg3, %arg4, %arg5) : (i32, i32, i32, i64, i64, i64) -> ()
    %444 = arith.constant 0 : i32
    %445 = arith.cmpi ne, %arg1, %444 : i32
    %446 = scf.if %445 -> (i1) {
      %447 = arith.constant true
      scf.yield %447 : i1
    } else {
      %448 = arith.constant 0 : i32
      %449 = arith.cmpi ne, %arg2, %448 : i32
      scf.yield %449 : i1
    }
    cf.cond_br %446, ^bb75, ^bb76
    ^bb75:
      func.return
    ^bb76:
      cf.br ^bb77
    ^bb77:
    %450 = arith.constant 0 : i32
    %451 = arith.extsi %450 : i32 to i64
    %452 = arith.constant 0 : i32
    %453 = arith.extsi %452 : i32 to i64
    %454 = arith.constant 0 : i32
    %455 = arith.extsi %454 : i32 to i64
    %456 = arith.constant 0 : i32
    %457 = arith.cmpi eq, %arg0, %456 : i32
    cf.cond_br %457, ^bb78, ^bb79
    ^bb78:
      %458 = arith.constant 1 : i32
      %459 = arith.extsi %458 : i32 to i64
      cf.br ^bb80(%459, %451, %453 : i64, i64, i64)
    ^bb79:
      %460 = arith.constant 1 : i32
      %461 = arith.cmpi eq, %arg0, %460 : i32
      cf.cond_br %461, ^bb81, ^bb82
      ^bb81:
        %462 = arith.constant 1 : i32
        %464 = arith.constant 0 : i32
        %463 = arith.subi %464, %462 : i32
        %465 = arith.extsi %463 : i32 to i64
        cf.br ^bb83(%465, %453, %455 : i64, i64, i64)
      ^bb82:
        %466 = arith.constant 2 : i32
        %467 = arith.cmpi eq, %arg0, %466 : i32
        %468, %469, %470 = scf.if %467 -> (i64, i64, i64) {
          %471 = arith.constant 1 : i32
          %472 = arith.extsi %471 : i32 to i64
          %473 = arith.constant 1 : i32
          %475 = arith.constant 0 : i32
          %474 = arith.subi %475, %473 : i32
          %476 = arith.extsi %474 : i32 to i64
          %477 = arith.constant 2 : i32
          %479 = arith.constant 0 : i32
          %478 = arith.subi %479, %477 : i32
          %480 = arith.extsi %478 : i32 to i64
          scf.yield %472, %476, %480 : i64, i64, i64
        } else {
          %482 = llvm.mlir.addressof @boundary_arr : !llvm.ptr
          %483 = llvm.load %482 : !llvm.ptr -> !llvm.ptr
          %484 = arith.extsi %arg0 : i32 to i64
          %485 = llvm.getelementptr %483[%484] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %481 = llvm.load %485 : !llvm.ptr -> i64
          %487 = llvm.mlir.addressof @tail_arr : !llvm.ptr
          %488 = llvm.load %487 : !llvm.ptr -> !llvm.ptr
          %489 = arith.extsi %arg0 : i32 to i64
          %490 = llvm.getelementptr %488[%489] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %486 = llvm.load %490 : !llvm.ptr -> i64
          %492 = llvm.mlir.addressof @value_arr : !llvm.ptr
          %493 = llvm.load %492 : !llvm.ptr -> !llvm.ptr
          %494 = arith.extsi %arg0 : i32 to i64
          %495 = llvm.getelementptr %493[%494] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %491 = llvm.load %495 : !llvm.ptr -> i64
          scf.yield %481, %486, %491 : i64, i64, i64
        }
        cf.br ^bb83(%468, %469, %470 : i64, i64, i64)
      ^bb83(%496: i64, %497: i64, %498: i64):
      cf.br ^bb80(%498, %496, %497 : i64, i64, i64)
    ^bb80(%499: i64, %500: i64, %501: i64):
    %503 = arith.constant 1 : i32
    %504 = arith.addi %arg0, %503 : i32
    %505 = arith.constant 1 : i32
    %506 = arith.addi %arg3, %500 : i64
    %507 = arith.addi %arg4, %501 : i64
    %508 = arith.addi %arg5, %499 : i64
    func.call @gen_left(%504, %505, %arg1, %506, %507, %508) : (i32, i32, i32, i64, i64, i64) -> ()
    func.return
  }
  func.func @init_allowed() -> () {
    %510 = arith.constant 16 : i32
    %511 = arith.constant 4 : i32
    %512 = arith.extsi %510 : i32 to i64
    %513 = arith.extsi %511 : i32 to i64
    %509 = func.call @calloc(%512, %513) : (i64, i64) -> !llvm.ptr
    %514 = llvm.mlir.addressof @allowed_masks : !llvm.ptr
    llvm.store %509, %514 : !llvm.ptr, !llvm.ptr
    %516 = arith.constant 4 : i32
    %517 = arith.constant 4 : i32
    %518 = arith.extsi %516 : i32 to i64
    %519 = arith.extsi %517 : i32 to i64
    %515 = func.call @calloc(%518, %519) : (i64, i64) -> !llvm.ptr
    %520 = llvm.mlir.addressof @allowed_count : !llvm.ptr
    llvm.store %515, %520 : !llvm.ptr, !llvm.ptr
    %521 = arith.constant 0 : i32
    %522 = llvm.mlir.constant(1 : i64) : i64
    %523 = llvm.alloca %522 x i32 : (i64) -> !llvm.ptr
    llvm.store %521, %523 : i32, !llvm.ptr
    cf.br ^bb84
    ^bb84:
    %524 = llvm.load %523 : !llvm.ptr -> i32
    %525 = arith.constant 4 : i32
    %526 = arith.cmpi slt, %524, %525 : i32
    cf.cond_br %526, ^bb85, ^bb86
    ^bb85:
      %527 = arith.constant 0 : i32
      %528 = llvm.mlir.addressof @allowed_count : !llvm.ptr
      %529 = llvm.load %528 : !llvm.ptr -> !llvm.ptr
      %530 = llvm.load %523 : !llvm.ptr -> i32
      %531 = arith.extsi %530 : i32 to i64
      %532 = llvm.getelementptr %529[%531] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %527, %532 : i32, !llvm.ptr
      %533 = arith.constant 0 : i32
      %534 = llvm.mlir.constant(1 : i64) : i64
      %535 = llvm.alloca %534 x i32 : (i64) -> !llvm.ptr
      llvm.store %533, %535 : i32, !llvm.ptr
      cf.br ^bb87
      ^bb87:
      %536 = llvm.load %535 : !llvm.ptr -> i32
      %537 = arith.constant 4 : i32
      %538 = arith.cmpi slt, %536, %537 : i32
      cf.cond_br %538, ^bb88, ^bb89
      ^bb88:
        %539 = arith.constant 0 : i1
        %540 = llvm.load %523 : !llvm.ptr -> i32
        %541 = arith.constant 1 : i32
        %542 = arith.andi %540, %541 : i32
        %543 = arith.constant 0 : i32
        %544 = arith.cmpi ne, %542, %543 : i32
        %545 = scf.if %544 -> (i1) {
          %546 = llvm.load %535 : !llvm.ptr -> i32
          %547 = arith.constant 3 : i32
          %548 = arith.andi %546, %547 : i32
          %549 = arith.constant 0 : i32
          %550 = arith.cmpi ne, %548, %549 : i32
          scf.yield %550 : i1
        } else {
          %551 = arith.constant false
          scf.yield %551 : i1
        }
        %552 = scf.if %545 -> (i1) {
          %553 = arith.constant 1 : i1
          scf.yield %553 : i1
        } else {
          scf.yield %539 : i1
        }
        %554 = llvm.load %523 : !llvm.ptr -> i32
        %555 = arith.constant 2 : i32
        %556 = arith.andi %554, %555 : i32
        %557 = arith.constant 0 : i32
        %558 = arith.cmpi ne, %556, %557 : i32
        %559 = scf.if %558 -> (i1) {
          %560 = llvm.load %535 : !llvm.ptr -> i32
          %561 = arith.constant 1 : i32
          %562 = arith.andi %560, %561 : i32
          %563 = arith.constant 0 : i32
          %564 = arith.cmpi ne, %562, %563 : i32
          scf.yield %564 : i1
        } else {
          %565 = arith.constant false
          scf.yield %565 : i1
        }
        %566 = scf.if %559 -> (i1) {
          %567 = arith.constant 1 : i1
          scf.yield %567 : i1
        } else {
          scf.yield %552 : i1
        }
        %569 = arith.constant 1 : i1
        %568 = arith.xori %566, %569 : i1
        cf.cond_br %568, ^bb90, ^bb91
        ^bb90:
          %571 = llvm.load %535 : !llvm.ptr -> i32
          %572 = llvm.mlir.addressof @allowed_masks : !llvm.ptr
          %573 = llvm.load %572 : !llvm.ptr -> !llvm.ptr
          %574 = llvm.load %523 : !llvm.ptr -> i32
          %575 = arith.constant 4 : i32
          %576 = arith.muli %574, %575 : i32
          %578 = llvm.mlir.addressof @allowed_count : !llvm.ptr
          %579 = llvm.load %578 : !llvm.ptr -> !llvm.ptr
          %580 = llvm.load %523 : !llvm.ptr -> i32
          %581 = arith.extsi %580 : i32 to i64
          %582 = llvm.getelementptr %579[%581] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %577 = llvm.load %582 : !llvm.ptr -> i32
          %583 = arith.addi %576, %577 : i32
          %584 = arith.extsi %583 : i32 to i64
          %585 = llvm.getelementptr %573[%584] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %571, %585 : i32, !llvm.ptr
          %587 = llvm.mlir.addressof @allowed_count : !llvm.ptr
          %588 = llvm.load %587 : !llvm.ptr -> !llvm.ptr
          %589 = llvm.load %523 : !llvm.ptr -> i32
          %590 = arith.extsi %589 : i32 to i64
          %591 = llvm.getelementptr %588[%590] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %586 = llvm.load %591 : !llvm.ptr -> i32
          %592 = arith.constant 1 : i32
          %593 = arith.addi %586, %592 : i32
          %594 = llvm.mlir.addressof @allowed_count : !llvm.ptr
          %595 = llvm.load %594 : !llvm.ptr -> !llvm.ptr
          %596 = llvm.load %523 : !llvm.ptr -> i32
          %597 = arith.extsi %596 : i32 to i64
          %598 = llvm.getelementptr %595[%597] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %593, %598 : i32, !llvm.ptr
          cf.br ^bb92
        ^bb91:
          cf.br ^bb92
        ^bb92:
        %599 = llvm.load %535 : !llvm.ptr -> i32
        %600 = arith.constant 1 : i32
        %601 = arith.addi %599, %600 : i32
        llvm.store %601, %535 : i32, !llvm.ptr
        cf.br ^bb87
      ^bb89:
      %602 = llvm.load %523 : !llvm.ptr -> i32
      %603 = arith.constant 1 : i32
      %604 = arith.addi %602, %603 : i32
      llvm.store %604, %523 : i32, !llvm.ptr
      cf.br ^bb84
    ^bb86:
    func.return
  }
  func.func @main() -> i32 {
    %605 = arith.constant 80 : i32
    %606 = llvm.mlir.addressof @limit_val : !llvm.ptr
    llvm.store %605, %606 : i32, !llvm.ptr
    %607 = llvm.mlir.addressof @limit_val : !llvm.ptr
    %608 = llvm.load %607 : !llvm.ptr -> i32
    %609 = arith.constant 2 : i32
    %610 = arith.divsi %608, %609 : i32
    %611 = llvm.mlir.addressof @split_val : !llvm.ptr
    llvm.store %610, %611 : i32, !llvm.ptr
    %613 = arith.constant 84 : i32
    %614 = arith.constant 8 : i32
    %615 = arith.extsi %613 : i32 to i64
    %616 = arith.extsi %614 : i32 to i64
    %612 = func.call @calloc(%615, %616) : (i64, i64) -> !llvm.ptr
    %617 = llvm.mlir.addressof @h_arr : !llvm.ptr
    llvm.store %612, %617 : !llvm.ptr, !llvm.ptr
    %619 = arith.constant 80 : i32
    %620 = arith.constant 8 : i32
    %621 = arith.extsi %619 : i32 to i64
    %622 = arith.extsi %620 : i32 to i64
    %618 = func.call @calloc(%621, %622) : (i64, i64) -> !llvm.ptr
    %623 = llvm.mlir.addressof @boundary_arr : !llvm.ptr
    llvm.store %618, %623 : !llvm.ptr, !llvm.ptr
    %625 = arith.constant 80 : i32
    %626 = arith.constant 8 : i32
    %627 = arith.extsi %625 : i32 to i64
    %628 = arith.extsi %626 : i32 to i64
    %624 = func.call @calloc(%627, %628) : (i64, i64) -> !llvm.ptr
    %629 = llvm.mlir.addressof @tail_arr : !llvm.ptr
    llvm.store %624, %629 : !llvm.ptr, !llvm.ptr
    %631 = arith.constant 80 : i32
    %632 = arith.constant 8 : i32
    %633 = arith.extsi %631 : i32 to i64
    %634 = arith.extsi %632 : i32 to i64
    %630 = func.call @calloc(%633, %634) : (i64, i64) -> !llvm.ptr
    %635 = llvm.mlir.addressof @value_arr : !llvm.ptr
    llvm.store %630, %635 : !llvm.ptr, !llvm.ptr
    %636 = arith.constant 0 : i32
    %637 = llvm.mlir.addressof @h_arr : !llvm.ptr
    %638 = llvm.load %637 : !llvm.ptr -> !llvm.ptr
    %639 = arith.constant 1 : i32
    %640 = arith.extsi %636 : i32 to i64
    %641 = arith.extsi %639 : i32 to i64
    %642 = llvm.getelementptr %638[%641] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %640, %642 : i64, !llvm.ptr
    %643 = arith.constant 0 : i32
    %644 = llvm.mlir.addressof @h_arr : !llvm.ptr
    %645 = llvm.load %644 : !llvm.ptr -> !llvm.ptr
    %646 = arith.constant 2 : i32
    %647 = arith.extsi %643 : i32 to i64
    %648 = arith.extsi %646 : i32 to i64
    %649 = llvm.getelementptr %645[%648] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %647, %649 : i64, !llvm.ptr
    %650 = arith.constant 1 : i32
    %651 = llvm.mlir.addressof @h_arr : !llvm.ptr
    %652 = llvm.load %651 : !llvm.ptr -> !llvm.ptr
    %653 = arith.constant 3 : i32
    %654 = arith.extsi %650 : i32 to i64
    %655 = arith.extsi %653 : i32 to i64
    %656 = llvm.getelementptr %652[%655] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %654, %656 : i64, !llvm.ptr
    %657 = arith.constant 4 : i32
    %658 = llvm.mlir.constant(1 : i64) : i64
    %659 = llvm.alloca %658 x i32 : (i64) -> !llvm.ptr
    llvm.store %657, %659 : i32, !llvm.ptr
    cf.br ^bb93
    ^bb93:
    %660 = llvm.load %659 : !llvm.ptr -> i32
    %661 = llvm.mlir.addressof @limit_val : !llvm.ptr
    %662 = llvm.load %661 : !llvm.ptr -> i32
    %663 = arith.cmpi sle, %660, %662 : i32
    cf.cond_br %663, ^bb94, ^bb95
    ^bb94:
      %664 = arith.constant 2 : i32
      %666 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %667 = llvm.load %666 : !llvm.ptr -> !llvm.ptr
      %668 = llvm.load %659 : !llvm.ptr -> i32
      %669 = arith.constant 3 : i32
      %670 = arith.subi %668, %669 : i32
      %671 = arith.extsi %670 : i32 to i64
      %672 = llvm.getelementptr %667[%671] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %665 = llvm.load %672 : !llvm.ptr -> i64
      %674 = arith.extsi %664 : i32 to i64
      %673 = arith.muli %674, %665 : i64
      %676 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %677 = llvm.load %676 : !llvm.ptr -> !llvm.ptr
      %678 = llvm.load %659 : !llvm.ptr -> i32
      %679 = arith.constant 2 : i32
      %680 = arith.subi %678, %679 : i32
      %681 = arith.extsi %680 : i32 to i64
      %682 = llvm.getelementptr %677[%681] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %675 = llvm.load %682 : !llvm.ptr -> i64
      %683 = arith.subi %673, %675 : i64
      %684 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %685 = llvm.load %684 : !llvm.ptr -> !llvm.ptr
      %686 = llvm.load %659 : !llvm.ptr -> i32
      %687 = arith.extsi %686 : i32 to i64
      %688 = llvm.getelementptr %685[%687] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %683, %688 : i64, !llvm.ptr
      %689 = llvm.load %659 : !llvm.ptr -> i32
      %690 = arith.constant 1 : i32
      %691 = arith.addi %689, %690 : i32
      llvm.store %691, %659 : i32, !llvm.ptr
      cf.br ^bb93
    ^bb95:
    %692 = arith.constant 3 : i32
    %693 = llvm.mlir.constant(1 : i64) : i64
    %694 = llvm.alloca %693 x i32 : (i64) -> !llvm.ptr
    llvm.store %692, %694 : i32, !llvm.ptr
    cf.br ^bb96
    ^bb96:
    %695 = llvm.load %694 : !llvm.ptr -> i32
    %696 = llvm.mlir.addressof @limit_val : !llvm.ptr
    %697 = llvm.load %696 : !llvm.ptr -> i32
    %698 = arith.cmpi slt, %695, %697 : i32
    cf.cond_br %698, ^bb97, ^bb98
    ^bb97:
      %700 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %701 = llvm.load %700 : !llvm.ptr -> !llvm.ptr
      %702 = llvm.load %694 : !llvm.ptr -> i32
      %703 = arith.extsi %702 : i32 to i64
      %704 = llvm.getelementptr %701[%703] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %699 = llvm.load %704 : !llvm.ptr -> i64
      %705 = arith.constant 3 : i32
      %707 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %708 = llvm.load %707 : !llvm.ptr -> !llvm.ptr
      %709 = llvm.load %694 : !llvm.ptr -> i32
      %710 = arith.constant 1 : i32
      %711 = arith.subi %709, %710 : i32
      %712 = arith.extsi %711 : i32 to i64
      %713 = llvm.getelementptr %708[%712] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %706 = llvm.load %713 : !llvm.ptr -> i64
      %715 = arith.extsi %705 : i32 to i64
      %714 = arith.muli %715, %706 : i64
      %716 = arith.subi %699, %714 : i64
      %717 = arith.constant 2 : i32
      %719 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %720 = llvm.load %719 : !llvm.ptr -> !llvm.ptr
      %721 = llvm.load %694 : !llvm.ptr -> i32
      %722 = arith.constant 2 : i32
      %723 = arith.subi %721, %722 : i32
      %724 = arith.extsi %723 : i32 to i64
      %725 = llvm.getelementptr %720[%724] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %718 = llvm.load %725 : !llvm.ptr -> i64
      %727 = arith.extsi %717 : i32 to i64
      %726 = arith.muli %727, %718 : i64
      %728 = arith.addi %716, %726 : i64
      %729 = llvm.mlir.addressof @boundary_arr : !llvm.ptr
      %730 = llvm.load %729 : !llvm.ptr -> !llvm.ptr
      %731 = llvm.load %694 : !llvm.ptr -> i32
      %732 = arith.extsi %731 : i32 to i64
      %733 = llvm.getelementptr %730[%732] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %728, %733 : i64, !llvm.ptr
      %735 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %736 = llvm.load %735 : !llvm.ptr -> !llvm.ptr
      %737 = llvm.load %694 : !llvm.ptr -> i32
      %738 = arith.constant 1 : i32
      %739 = arith.subi %737, %738 : i32
      %740 = arith.extsi %739 : i32 to i64
      %741 = llvm.getelementptr %736[%740] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %734 = llvm.load %741 : !llvm.ptr -> i64
      %742 = arith.constant 2 : i32
      %744 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %745 = llvm.load %744 : !llvm.ptr -> !llvm.ptr
      %746 = llvm.load %694 : !llvm.ptr -> i32
      %747 = arith.constant 2 : i32
      %748 = arith.subi %746, %747 : i32
      %749 = arith.extsi %748 : i32 to i64
      %750 = llvm.getelementptr %745[%749] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %743 = llvm.load %750 : !llvm.ptr -> i64
      %752 = arith.extsi %742 : i32 to i64
      %751 = arith.muli %752, %743 : i64
      %753 = arith.subi %734, %751 : i64
      %754 = llvm.mlir.addressof @tail_arr : !llvm.ptr
      %755 = llvm.load %754 : !llvm.ptr -> !llvm.ptr
      %756 = llvm.load %694 : !llvm.ptr -> i32
      %757 = arith.extsi %756 : i32 to i64
      %758 = llvm.getelementptr %755[%757] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %753, %758 : i64, !llvm.ptr
      %759 = arith.constant 2 : i32
      %761 = llvm.mlir.addressof @tail_arr : !llvm.ptr
      %762 = llvm.load %761 : !llvm.ptr -> !llvm.ptr
      %763 = llvm.load %694 : !llvm.ptr -> i32
      %764 = arith.extsi %763 : i32 to i64
      %765 = llvm.getelementptr %762[%764] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %760 = llvm.load %765 : !llvm.ptr -> i64
      %767 = llvm.mlir.addressof @h_arr : !llvm.ptr
      %768 = llvm.load %767 : !llvm.ptr -> !llvm.ptr
      %769 = llvm.load %694 : !llvm.ptr -> i32
      %770 = arith.extsi %769 : i32 to i64
      %771 = llvm.getelementptr %768[%770] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %766 = llvm.load %771 : !llvm.ptr -> i64
      %772 = arith.addi %760, %766 : i64
      %774 = arith.extsi %759 : i32 to i64
      %773 = arith.muli %774, %772 : i64
      %775 = llvm.mlir.addressof @value_arr : !llvm.ptr
      %776 = llvm.load %775 : !llvm.ptr -> !llvm.ptr
      %777 = llvm.load %694 : !llvm.ptr -> i32
      %778 = arith.extsi %777 : i32 to i64
      %779 = llvm.getelementptr %776[%778] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %773, %779 : i64, !llvm.ptr
      %780 = llvm.load %694 : !llvm.ptr -> i32
      %781 = arith.constant 1 : i32
      %782 = arith.addi %780, %781 : i32
      llvm.store %782, %694 : i32, !llvm.ptr
      cf.br ^bb96
    ^bb98:
    func.call @init_allowed() : () -> ()
    %785 = arith.constant 8000000 : i32
    %786 = arith.constant 32 : i32
    %787 = arith.extsi %785 : i32 to i64
    %788 = arith.extsi %786 : i32 to i64
    %784 = func.call @calloc(%787, %788) : (i64, i64) -> !llvm.ptr
    %789 = llvm.mlir.addressof @right_entries : !llvm.ptr
    llvm.store %784, %789 : !llvm.ptr, !llvm.ptr
    %791 = arith.constant 8000001 : i32
    %792 = arith.constant 8 : i32
    %793 = arith.extsi %791 : i32 to i64
    %794 = arith.extsi %792 : i32 to i64
    %790 = func.call @calloc(%793, %794) : (i64, i64) -> !llvm.ptr
    %795 = llvm.mlir.addressof @right_prefix : !llvm.ptr
    llvm.store %790, %795 : !llvm.ptr, !llvm.ptr
    %796 = arith.constant 0 : i32
    %797 = llvm.mlir.addressof @right_count : !llvm.ptr
    llvm.store %796, %797 : i32, !llvm.ptr
    %799 = llvm.mlir.addressof @split_val : !llvm.ptr
    %800 = llvm.load %799 : !llvm.ptr -> i32
    %801 = arith.constant 0 : i32
    %802 = arith.constant 0 : i32
    %803 = arith.constant 0 : i32
    %804 = arith.constant 0 : i32
    %805 = arith.constant 0 : i32
    %806 = arith.constant 0 : i32
    %807 = arith.extsi %803 : i32 to i64
    %808 = arith.extsi %804 : i32 to i64
    %809 = arith.extsi %805 : i32 to i64
    func.call @gen_right(%800, %801, %802, %807, %808, %809, %806) : (i32, i32, i32, i64, i64, i64, i32) -> ()
    %811 = llvm.mlir.addressof @right_entries : !llvm.ptr
    %812 = llvm.load %811 : !llvm.ptr -> !llvm.ptr
    %813 = llvm.mlir.addressof @right_count : !llvm.ptr
    %814 = llvm.load %813 : !llvm.ptr -> i32
    func.call @heapsort_entries(%812, %814) : (!llvm.ptr, i32) -> ()
    %815 = arith.constant 0 : i32
    %816 = llvm.mlir.addressof @right_prefix : !llvm.ptr
    %817 = llvm.load %816 : !llvm.ptr -> !llvm.ptr
    %818 = arith.constant 0 : i32
    %819 = arith.extsi %815 : i32 to i64
    %820 = arith.extsi %818 : i32 to i64
    %821 = llvm.getelementptr %817[%820] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %819, %821 : i64, !llvm.ptr
    %822 = arith.constant 0 : i32
    %823 = llvm.mlir.constant(1 : i64) : i64
    %824 = llvm.alloca %823 x i32 : (i64) -> !llvm.ptr
    llvm.store %822, %824 : i32, !llvm.ptr
    cf.br ^bb99
    ^bb99:
    %825 = llvm.load %824 : !llvm.ptr -> i32
    %826 = llvm.mlir.addressof @right_count : !llvm.ptr
    %827 = llvm.load %826 : !llvm.ptr -> i32
    %828 = arith.cmpi slt, %825, %827 : i32
    cf.cond_br %828, ^bb100, ^bb101
    ^bb100:
      %830 = llvm.mlir.addressof @right_prefix : !llvm.ptr
      %831 = llvm.load %830 : !llvm.ptr -> !llvm.ptr
      %832 = llvm.load %824 : !llvm.ptr -> i32
      %833 = arith.extsi %832 : i32 to i64
      %834 = llvm.getelementptr %831[%833] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %829 = llvm.load %834 : !llvm.ptr -> i64
      %836 = llvm.mlir.addressof @right_entries : !llvm.ptr
      %837 = llvm.load %836 : !llvm.ptr -> !llvm.ptr
      %838 = llvm.load %824 : !llvm.ptr -> i32
      %839 = arith.extsi %838 : i32 to i64
      %840 = llvm.getelementptr %837[%839] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %835 = llvm.load %840 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i32)>
      %841 = llvm.mlir.addressof @right_entries : !llvm.ptr
      %842 = llvm.load %841 : !llvm.ptr -> !llvm.ptr
      %843 = llvm.load %824 : !llvm.ptr -> i32
      %844 = arith.extsi %843 : i32 to i64
      %845 = llvm.getelementptr %842[%844] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %846 = llvm.getelementptr %845[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i32)>
      %847 = llvm.load %846 : !llvm.ptr -> i64
      %848 = arith.addi %829, %847 : i64
      %849 = llvm.mlir.addressof @right_prefix : !llvm.ptr
      %850 = llvm.load %849 : !llvm.ptr -> !llvm.ptr
      %851 = llvm.load %824 : !llvm.ptr -> i32
      %852 = arith.constant 1 : i32
      %853 = arith.addi %851, %852 : i32
      %854 = arith.extsi %853 : i32 to i64
      %855 = llvm.getelementptr %850[%854] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %848, %855 : i64, !llvm.ptr
      %856 = llvm.load %824 : !llvm.ptr -> i32
      %857 = arith.constant 1 : i32
      %858 = arith.addi %856, %857 : i32
      llvm.store %858, %824 : i32, !llvm.ptr
      cf.br ^bb99
    ^bb101:
    %859 = arith.constant 0 : i32
    %860 = arith.extsi %859 : i32 to i64
    %861 = llvm.mlir.addressof @total_sum : !llvm.ptr
    llvm.store %860, %861 : i64, !llvm.ptr
    %863 = arith.constant 0 : i32
    %864 = arith.constant 0 : i32
    %865 = arith.constant 0 : i32
    %866 = arith.constant 0 : i32
    %867 = arith.constant 0 : i32
    %868 = arith.constant 0 : i32
    %869 = arith.extsi %866 : i32 to i64
    %870 = arith.extsi %867 : i32 to i64
    %871 = arith.extsi %868 : i32 to i64
    func.call @gen_left(%863, %864, %865, %869, %870, %871) : (i32, i32, i32, i64, i64, i64) -> ()
    %872 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %873 = llvm.mlir.addressof @total_sum : !llvm.ptr
    %874 = llvm.load %873 : !llvm.ptr -> i64
    %875 = llvm.call @printf(%872, %874) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %877 = llvm.mlir.addressof @h_arr : !llvm.ptr
    %878 = llvm.load %877 : !llvm.ptr -> !llvm.ptr
    func.call @free(%878) : (!llvm.ptr) -> ()
    %880 = llvm.mlir.addressof @boundary_arr : !llvm.ptr
    %881 = llvm.load %880 : !llvm.ptr -> !llvm.ptr
    func.call @free(%881) : (!llvm.ptr) -> ()
    %883 = llvm.mlir.addressof @tail_arr : !llvm.ptr
    %884 = llvm.load %883 : !llvm.ptr -> !llvm.ptr
    func.call @free(%884) : (!llvm.ptr) -> ()
    %886 = llvm.mlir.addressof @value_arr : !llvm.ptr
    %887 = llvm.load %886 : !llvm.ptr -> !llvm.ptr
    func.call @free(%887) : (!llvm.ptr) -> ()
    %889 = llvm.mlir.addressof @right_entries : !llvm.ptr
    %890 = llvm.load %889 : !llvm.ptr -> !llvm.ptr
    func.call @free(%890) : (!llvm.ptr) -> ()
    %892 = llvm.mlir.addressof @right_prefix : !llvm.ptr
    %893 = llvm.load %892 : !llvm.ptr -> !llvm.ptr
    func.call @free(%893) : (!llvm.ptr) -> ()
    %895 = llvm.mlir.addressof @allowed_masks : !llvm.ptr
    %896 = llvm.load %895 : !llvm.ptr -> !llvm.ptr
    func.call @free(%896) : (!llvm.ptr) -> ()
    %898 = llvm.mlir.addressof @allowed_count : !llvm.ptr
    %899 = llvm.load %898 : !llvm.ptr -> !llvm.ptr
    func.call @free(%899) : (!llvm.ptr) -> ()
    %900 = arith.constant 0 : i32
    func.return %900 : i32
  }
}