Problem 886

Coprime Permutations: P(34) mod 83456729.

Answer5570163
Output5570163
StatusPASS
Native helperno
Runtime740 ms
Peak memory19728 KB
Time complexityO(n^4) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^4)O(n log log n)
Space complexityO(n^2)O(n)
ApproachFlow solutionSieve of Eratosthenes
VerdictSuboptimal

Flow source

# Project Euler 886
# Coprime Permutations: P(34) mod 83456729.

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

const MOD: i64 = 83456729
const MAXN: i32 = 34

# Binomial table (flat 35*35)
let mut g_comb: ptr<i64> = null

# Grouped permanent context
let mut g_row_class_count: i32 = 0
let mut g_col_class_count: i32 = 0
let mut g_row_class_rep: ptr<i32> = null
let mut g_row_class_count_arr: ptr<i32> = null
let mut g_col_class_rep: ptr<i32> = null
let mut g_col_class_count_arr: ptr<i32> = null
let mut g_class_entry: ptr<i32> = null
let mut g_row_supports: ptr<i32> = null

# Permanent cache (hash table)
const PERM_CACHE_CAP: i64 = 1048576
const PERM_CACHE_MASK: i64 = 1048575
let mut g_perm_key: ptr<i64> = null
let mut g_perm_val: ptr<i64> = null
let mut g_perm_used: ptr<i8> = null

# rec_perm context
let mut g_active_col_classes: ptr<i32> = null
let mut g_active_col_counts: ptr<i32> = null
let mut g_active_count: i32 = 0
let mut g_supports: ptr<i32> = null
let mut g_row_counts_arr: ptr<i32> = null
let mut g_row_sums: ptr<i32> = null
let mut g_num_supports: i32 = 0
let mut g_row_total: i32 = 0
let mut g_total: i64 = 0

# affected arrays for rec_perm, indexed by col_pos * 256
let mut g_affected: ptr<i32> = null
let mut g_n_affected: ptr<i32> = null

function mulmod(a0: i64, b0: i64, m: i64) -> i64 {
    let a_w: i128 = a0 as i128
    let b_w: i128 = b0 as i128
    let m_w: i128 = m as i128
    let r: i128 = (a_w * b_w) % m_w
    return r as i64
}

function powmod(a0: i64, e0: i64, m: i64) -> i64 {
    let mut r: i64 = 1 % m
    let mut a: i64 = a0 % m
    if a < 0 { a = a + m }
    let mut e: i64 = e0
    while e > 0 {
        if (e & 1) == 1 { r = mulmod(r, a, m) }
        a = mulmod(a, a, m)
        e = e >> 1
    }
    return r
}

function gcd_ll(a0: i64, b0: i64) -> i64 {
    let mut a: i64 = a0
    let mut b: i64 = b0
    while b != 0 {
        let t: i64 = a % b
        a = b
        b = t
    }
    return a
}

function init_comb(n: i32) -> void {
    let mut i: i32 = 0
    while i <= n {
        g_comb[i * (MAXN + 1) + 0] = 1
        g_comb[i * (MAXN + 1) + i] = 1
        let mut j: i32 = 1
        while j < i {
            g_comb[i * (MAXN + 1) + j] = g_comb[(i - 1) * (MAXN + 1) + j - 1] + g_comb[(i - 1) * (MAXN + 1) + j]
            j = j + 1
        }
        i = i + 1
    }
}

function determinant_mod(mat: ptr<i64>, size: i32, mod: i64) -> i64 {
    if size == 0 { return 1 }
    let a: ptr<i64> = calloc((MAXN * MAXN) as i64, 8)
    let mut i: i32 = 0
    while i < size {
        let mut j: i32 = 0
        while j < size {
            a[i * MAXN + j] = mat[i * size + j] % mod
            if a[i * MAXN + j] < 0 { a[i * MAXN + j] = a[i * MAXN + j] + mod }
            j = j + 1
        }
        i = i + 1
    }
    let mut det: i64 = 1
    let mut col: i32 = 0
    while col < size {
        let mut pivot: i32 = -1
        let mut row: i32 = col
        while row < size {
            if a[row * MAXN + col] % mod != 0 { pivot = row; break }
            row = row + 1
        }
        if pivot < 0 { free(a); return 0 }
        if pivot != col {
            let mut j: i32 = 0
            while j < size {
                let t: i64 = a[col * MAXN + j]
                a[col * MAXN + j] = a[pivot * MAXN + j]
                a[pivot * MAXN + j] = t
                j = j + 1
            }
            det = 0 - det
        }
        let mut pv: i64 = a[col * MAXN + col] % mod
        if pv < 0 { pv = pv + mod }
        det = mulmod(det, pv, mod)
        let inv: i64 = powmod(pv, mod - 2, mod)
        let mut row2: i32 = col + 1
        while row2 < size {
            if a[row2 * MAXN + col] % mod != 0 {
                let factor: i64 = mulmod(a[row2 * MAXN + col], inv, mod)
                let mut j: i32 = col
                while j < size {
                    a[row2 * MAXN + j] = (a[row2 * MAXN + j] - mulmod(factor, a[col * MAXN + j], mod)) % mod
                    if a[row2 * MAXN + j] < 0 { a[row2 * MAXN + j] = a[row2 * MAXN + j] + mod }
                    j = j + 1
                }
            }
            row2 = row2 + 1
        }
        col = col + 1
    }
    det = det % mod
    if det < 0 { det = det + mod }
    free(a)
    return det
}

function perm_hash(key: i64) -> i64 {
    let h: i64 = key ^ (key >> 16)
    let h2: i64 = h * 2654435761
    let h3: i64 = h2 ^ (h2 >> 16)
    return h3 & PERM_CACHE_MASK
}

function perm_cache_lookup(key: i64, out: ptr<i64>) -> i32 {
    let mut h: i64 = perm_hash(key)
    while g_perm_used[h] != 0 {
        if g_perm_key[h] == key {
            out[0] = g_perm_val[h]
            return 1
        }
        h = (h + 1) & PERM_CACHE_MASK
    }
    return 0
}

function perm_cache_insert(key: i64, val: i64) -> void {
    let mut h: i64 = perm_hash(key)
    while g_perm_used[h] != 0 {
        if g_perm_key[h] == key {
            g_perm_val[h] = val
            return
        }
        h = (h + 1) & PERM_CACHE_MASK
    }
    g_perm_used[h] = 1
    g_perm_key[h] = key
    g_perm_val[h] = val
}

function rec_perm(col_pos: i32, chosen: i32, coeff: i64) -> void {
    if col_pos == g_active_count {
        let mut product: i64 = coeff
        let mut i: i32 = 0
        while i < g_num_supports {
            if g_row_sums[i] == 0 { return }
            product = mulmod(product, powmod(g_row_sums[i] as i64, g_row_counts_arr[i] as i64, MOD), MOD)
            i = i + 1
        }
        if (chosen & 1) == 1 { g_total = g_total - product }
        else { g_total = g_total + product }
        return
    }
    let class_size: i32 = g_active_col_counts[col_pos]
    let base_idx: i32 = col_pos * 256
    let mut n_aff: i32 = 0
    let mut idx: i32 = 0
    while idx < g_num_supports {
        if ((g_supports[idx] >> col_pos) & 1) == 1 {
            g_affected[base_idx + n_aff] = idx
            n_aff = n_aff + 1
        }
        idx = idx + 1
    }
    g_n_affected[col_pos] = n_aff

    let mut take: i32 = 0
    while take <= class_size {
        if take > 0 {
            let mut i: i32 = 0
            while i < n_aff {
                g_row_sums[g_affected[base_idx + i]] = g_row_sums[g_affected[base_idx + i]] + take
                i = i + 1
            }
        }
        rec_perm(col_pos + 1, chosen + take, mulmod(coeff, g_comb[class_size * (MAXN + 1) + take] % MOD, MOD))
        if take > 0 {
            let mut i: i32 = 0
            while i < n_aff {
                g_row_sums[g_affected[base_idx + i]] = g_row_sums[g_affected[base_idx + i]] - take
                i = i + 1
            }
        }
        take = take + 1
    }
}

function grouped_permanent(row_selected: i32, col_selected: i32) -> i64 {
    let key: i64 = ((row_selected as i64) << 20) | (col_selected as i64)
    let out: ptr<i64> = calloc(1, 8)
    if perm_cache_lookup(key, out) == 1 {
        let cached: i64 = out[0]
        free(out)
        return cached
    }
    free(out)

    # Build active col classes
    g_active_count = 0
    let mut cc: i32 = 0
    while cc < g_col_class_count {
        let remaining: i32 = g_col_class_count_arr[cc] - ((col_selected >> cc) & 1)
        if remaining > 0 {
            g_active_col_classes[g_active_count] = cc
            g_active_col_counts[g_active_count] = remaining
            g_active_count = g_active_count + 1
        }
        cc = cc + 1
    }

    # Build row groups indexed by support bitmask
    let row_group_counts: ptr<i32> = calloc(256, 4)
    row_group_counts[(1 << g_active_count) - 1] = 1
    let mut rc: i32 = 0
    while rc < g_row_class_count {
        let remaining: i32 = g_row_class_count_arr[rc] - ((row_selected >> rc) & 1)
        if remaining > 0 {
            let mut support: i32 = 0
            let orig: i32 = g_row_supports[rc]
            let mut nc: i32 = 0
            while nc < g_active_count {
                let old_col: i32 = g_active_col_classes[nc]
                if ((orig >> old_col) & 1) == 1 {
                    support = support | (1 << nc)
                }
                nc = nc + 1
            }
            row_group_counts[support] = row_group_counts[support] + remaining
        }
        rc = rc + 1
    }

    # Collect supports and counts
    g_num_supports = 0
    g_row_total = 0
    let mut s: i32 = 0
    while s < 256 {
        if row_group_counts[s] > 0 {
            g_supports[g_num_supports] = s
            g_row_counts_arr[g_num_supports] = row_group_counts[s]
            g_row_sums[g_num_supports] = 0
            g_row_total = g_row_total + row_group_counts[s]
            g_num_supports = g_num_supports + 1
        }
        s = s + 1
    }

    g_total = 0
    rec_perm(0, 0, 1)
    if (g_row_total & 1) == 1 { g_total = 0 - g_total }
    g_total = g_total % MOD
    if g_total < 0 { g_total = g_total + MOD }

    perm_cache_insert(key, g_total)
    free(row_group_counts)
    return g_total
}

function P_func(n: i32, mod: i64) -> i64 {
    # Clear permanent cache
    memset(g_perm_key, 0, PERM_CACHE_CAP * 8)
    memset(g_perm_val, 0, PERM_CACHE_CAP * 8)
    memset(g_perm_used, 0, PERM_CACHE_CAP)

    if n < 2 { return 0 }
    let m: i32 = n / 2

    # Build coprimality matrix
    let odds: ptr<i32> = calloc(m as i64, 4)
    let evens: ptr<i32> = calloc(m as i64, 4)
    let mut i: i32 = 0
    while i < m {
        odds[i] = 2 * i + 1
        evens[i] = 2 * (i + 1)
        i = i + 1
    }

    let matrix: ptr<i32> = calloc((MAXN * MAXN) as i64, 4)
    let mut i2: i32 = 0
    while i2 < m {
        let mut j: i32 = 0
        while j < m {
            if gcd_ll(odds[i2] as i64, evens[j] as i64) == 1 {
                matrix[i2 * MAXN + j] = 1
            } else {
                matrix[i2 * MAXN + j] = 0
            }
            j = j + 1
        }
        i2 = i2 + 1
    }

    # Row masks for rows 1..m-1
    let row_masks: ptr<i32> = calloc(MAXN as i64, 4)
    let mut row: i32 = 1
    while row < m {
        let mut mask: i32 = 0
        let mut col: i32 = 0
        while col < m {
            if matrix[row * MAXN + col] != 0 { mask = mask | (1 << col) }
            col = col + 1
        }
        row_masks[row - 1] = mask
        row = row + 1
    }

    # Col masks for all columns
    let col_masks: ptr<i32> = calloc(MAXN as i64, 4)
    let mut col2: i32 = 0
    while col2 < m {
        let mut mask: i32 = 0
        let mut row2: i32 = 0
        while row2 < m {
            if matrix[row2 * MAXN + col2] != 0 { mask = mask | (1 << row2) }
            row2 = row2 + 1
        }
        col_masks[col2] = mask
        col2 = col2 + 1
    }

    # Group rows by mask
    g_row_class_count = 0
    let row_seen: ptr<i32> = calloc(131072, 4)
    memset(row_seen, -1, 131072 * 4)
    let mut idx: i32 = 0
    while idx < m - 1 {
        let mask: i32 = row_masks[idx]
        if row_seen[mask] < 0 {
            row_seen[mask] = g_row_class_count
            g_row_class_rep[g_row_class_count] = idx
            g_row_class_count_arr[g_row_class_count] = 1
            g_row_class_count = g_row_class_count + 1
        } else {
            g_row_class_count_arr[row_seen[mask]] = g_row_class_count_arr[row_seen[mask]] + 1
        }
        idx = idx + 1
    }

    # Group cols by mask
    g_col_class_count = 0
    let col_seen: ptr<i32> = calloc(131072, 4)
    memset(col_seen, -1, 131072 * 4)
    idx = 0
    while idx < m {
        let mask: i32 = col_masks[idx]
        if col_seen[mask] < 0 {
            col_seen[mask] = g_col_class_count
            g_col_class_rep[g_col_class_count] = idx
            g_col_class_count_arr[g_col_class_count] = 1
            g_col_class_count = g_col_class_count + 1
        } else {
            g_col_class_count_arr[col_seen[mask]] = g_col_class_count_arr[col_seen[mask]] + 1
        }
        idx = idx + 1
    }

    # class_entry: [row_class][col_class]
    let mut rc2: i32 = 0
    while rc2 < g_row_class_count {
        let mut cc2: i32 = 0
        while cc2 < g_col_class_count {
            g_class_entry[rc2 * MAXN + cc2] = matrix[(g_row_class_rep[rc2] + 1) * MAXN + g_col_class_rep[cc2]]
            cc2 = cc2 + 1
        }
        rc2 = rc2 + 1
    }

    # row_supports: support over col classes
    rc2 = 0
    while rc2 < g_row_class_count {
        let mut support: i32 = 0
        let mut cc2: i32 = 0
        while cc2 < g_col_class_count {
            if matrix[(g_row_class_rep[rc2] + 1) * MAXN + g_col_class_rep[cc2]] != 0 {
                support = support | (1 << cc2)
            }
            cc2 = cc2 + 1
        }
        g_row_supports[rc2] = support
        rc2 = rc2 + 1
    }

    init_comb(m)

    # Enumerate combinations
    let mut answer: i64 = 0
    let rcc: i32 = g_row_class_count
    let ccc: i32 = g_col_class_count

    let row_subset: ptr<i32> = calloc(20, 4)
    let col_subset: ptr<i32> = calloc(20, 4)
    let det_mat: ptr<i64> = calloc(400, 8)

    let mut size: i32 = 0
    while size <= ccc && size <= rcc {
        let mut sign: i64 = 1
        if (size & 1) == 1 { sign = -1 }

        # Initialize row subset
        let mut i3: i32 = 0
        while i3 < size {
            row_subset[i3] = i3
            i3 = i3 + 1
        }

        let mut row_done: bool = false
        while !row_done {
            # Process current row subset
            let mut row_mask: i32 = 0
            let mut row_mult: i64 = 1
            let mut i4: i32 = 0
            while i4 < size {
                row_mask = row_mask | (1 << row_subset[i4])
                row_mult = mulmod(row_mult, g_row_class_count_arr[row_subset[i4]] as i64, mod)
                i4 = i4 + 1
            }

            # Initialize col subset
            let mut i5: i32 = 0
            while i5 < size {
                col_subset[i5] = i5
                i5 = i5 + 1
            }

            let mut col_done: bool = false
            while !col_done {
                let mut col_mask: i32 = 0
                let mut col_mult: i64 = 1
                let mut i6: i32 = 0
                while i6 < size {
                    col_mask = col_mask | (1 << col_subset[i6])
                    col_mult = mulmod(col_mult, g_col_class_count_arr[col_subset[i6]] as i64, mod)
                    i6 = i6 + 1
                }

                # Build det matrix
                let mut i7: i32 = 0
                while i7 < size {
                    let mut j7: i32 = 0
                    while j7 < size {
                        det_mat[i7 * size + j7] = g_class_entry[row_subset[i7] * MAXN + col_subset[j7]] as i64
                        j7 = j7 + 1
                    }
                    i7 = i7 + 1
                }

                let det: i64 = determinant_mod(det_mat, size, mod)
                if det != 0 {
                    let perm: i64 = grouped_permanent(row_mask, col_mask)
                    let term: i64 = mulmod(row_mult, col_mult, mod)
                    let term2: i64 = mulmod(term, mulmod(det, det, mod), mod)
                    let term3: i64 = mulmod(term2, mulmod(perm, perm, mod), mod)
                    answer = answer + sign * term3
                }

                # Next col subset
                if size == 0 { col_done = true }
                else {
                    let mut pos: i32 = size - 1
                    while pos >= 0 && col_subset[pos] == ccc - size + pos {
                        pos = pos - 1
                    }
                    if pos < 0 { col_done = true }
                    else {
                        col_subset[pos] = col_subset[pos] + 1
                        let mut i8v: i32 = pos + 1
                        while i8v < size {
                            col_subset[i8v] = col_subset[i8v - 1] + 1
                            i8v = i8v + 1
                        }
                    }
                }
            }

            # Next row subset
            if size == 0 { row_done = true }
            else {
                let mut pos: i32 = size - 1
                while pos >= 0 && row_subset[pos] == rcc - size + pos {
                    pos = pos - 1
                }
                if pos < 0 { row_done = true }
                else {
                    row_subset[pos] = row_subset[pos] + 1
                    let mut i9: i32 = pos + 1
                    while i9 < size {
                        row_subset[i9] = row_subset[i9 - 1] + 1
                        i9 = i9 + 1
                    }
                }
            }
        }
        size = size + 1
    }

    answer = answer % mod
    if answer < 0 { answer = answer + mod }

    free(odds)
    free(evens)
    free(matrix)
    free(row_masks)
    free(col_masks)
    free(row_seen)
    free(col_seen)
    free(row_subset)
    free(col_subset)
    free(det_mat)
    return answer
}

function main() -> i32 {
    # Allocate global arrays
    g_comb = calloc(((MAXN + 1) * (MAXN + 1)) as i64, 8)
    g_row_class_rep = calloc(MAXN as i64, 4)
    g_row_class_count_arr = calloc(MAXN as i64, 4)
    g_col_class_rep = calloc(MAXN as i64, 4)
    g_col_class_count_arr = calloc(MAXN as i64, 4)
    g_class_entry = calloc((MAXN * MAXN) as i64, 4)
    g_row_supports = calloc(MAXN as i64, 4)
    g_perm_key = calloc(PERM_CACHE_CAP, 8)
    g_perm_val = calloc(PERM_CACHE_CAP, 8)
    g_perm_used = calloc(PERM_CACHE_CAP, 1)
    g_active_col_classes = calloc(MAXN as i64, 4)
    g_active_col_counts = calloc(MAXN as i64, 4)
    g_supports = calloc(256, 4)
    g_row_counts_arr = calloc(256, 4)
    g_row_sums = calloc(256, 4)
    g_affected = calloc((MAXN * 256) as i64, 4)
    g_n_affected = calloc(MAXN as i64, 4)

    let ans: i64 = P_func(34, MOD)
    printf("%lld\n", ans)

    free(g_comb)
    free(g_row_class_rep)
    free(g_row_class_count_arr)
    free(g_col_class_rep)
    free(g_col_class_count_arr)
    free(g_class_entry)
    free(g_row_supports)
    free(g_perm_key)
    free(g_perm_val)
    free(g_perm_used)
    free(g_active_col_classes)
    free(g_active_col_counts)
    free(g_supports)
    free(g_row_counts_arr)
    free(g_row_sums)
    free(g_affected)
    free(g_n_affected)
    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; }

int64_t mulmod_i64_i64_i64(int64_t a0, int64_t b0, int64_t m);
int64_t powmod_i64_i64_i64(int64_t a0, int64_t e0, int64_t m);
int64_t gcd_ll_i64_i64(int64_t a0, int64_t b0);
void init_comb_i32(int32_t n);
int64_t determinant_mod_ptr_i64_i32_i64(int64_t* mat, int32_t size, int64_t mod);
int64_t perm_hash_i64(int64_t key);
int32_t perm_cache_lookup_i64_ptr_i64(int64_t key, int64_t* out);
void perm_cache_insert_i64_i64(int64_t key, int64_t val);
void rec_perm_i32_i32_i64(int32_t col_pos, int32_t chosen, int64_t coeff);
int64_t grouped_permanent_i32_i32(int32_t row_selected, int32_t col_selected);
int64_t P_func_i32_i64(int32_t n, int64_t mod);
int32_t main(void);

static const int64_t MOD = 83456729;
static const int32_t MAXN = 34;
static const int64_t PERM_CACHE_CAP = 1048576;
static const int64_t PERM_CACHE_MASK = 1048575;

/* Module statics */
static int64_t* g_comb = NULL;
static int32_t g_row_class_count = 0;
static int32_t g_col_class_count = 0;
static int32_t* g_row_class_rep = NULL;
static int32_t* g_row_class_count_arr = NULL;
static int32_t* g_col_class_rep = NULL;
static int32_t* g_col_class_count_arr = NULL;
static int32_t* g_class_entry = NULL;
static int32_t* g_row_supports = NULL;
static int64_t* g_perm_key = NULL;
static int64_t* g_perm_val = NULL;
static int8_t* g_perm_used = NULL;
static int32_t* g_active_col_classes = NULL;
static int32_t* g_active_col_counts = NULL;
static int32_t g_active_count = 0;
static int32_t* g_supports = NULL;
static int32_t* g_row_counts_arr = NULL;
static int32_t* g_row_sums = NULL;
static int32_t g_num_supports = 0;
static int32_t g_row_total = 0;
static int64_t g_total = 0;
static int32_t* g_affected = NULL;
static int32_t* g_n_affected = NULL;




int64_t mulmod_i64_i64_i64(int64_t a0, int64_t b0, int64_t m) {
    __int128 a_w = ((__int128)(a0));
    __int128 b_w = ((__int128)(b0));
    __int128 m_w = ((__int128)(m));
    __int128 r = FLOW_CHECKED_MOD(((a_w * b_w)), (m_w));
    return ((int64_t)(r));
}

int64_t powmod_i64_i64_i64(int64_t a0, int64_t e0, int64_t m) {
    int64_t r = FLOW_CHECKED_MOD((1), (m));
    int64_t a = FLOW_CHECKED_MOD((a0), (m));
    if (a < 0) {
        a = (a + m);
    }
    int64_t e = e0;
    while (e > 0) {
        if ((e & 1) == 1) {
            r = mulmod_i64_i64_i64(r, a, m);
        }
        a = mulmod_i64_i64_i64(a, a, m);
        e = FLOW_CHECKED_SHR((e), (1));
    }
    return r;
}

int64_t gcd_ll_i64_i64(int64_t a0, int64_t b0) {
    int64_t a = a0;
    int64_t b = b0;
    while (b != 0) {
        int64_t t = FLOW_CHECKED_MOD((a), (b));
        a = b;
        b = t;
    }
    return a;
}

void init_comb_i32(int32_t n) {
    int32_t i = 0;
    while (i <= n) {
        g_comb[((i * (MAXN + 1)) + 0)] = 1;
        g_comb[((i * (MAXN + 1)) + i)] = 1;
        int32_t j = 1;
        while (j < i) {
            g_comb[((i * (MAXN + 1)) + j)] = (g_comb[((((i - 1) * (MAXN + 1)) + j) - 1)] + g_comb[(((i - 1) * (MAXN + 1)) + j)]);
            j = (j + 1);
        }
        i = (i + 1);
    }
}

int64_t determinant_mod_ptr_i64_i32_i64(int64_t* mat, int32_t size, int64_t mod) {
    if (size == 0) {
        return 1;
    }
    int64_t* a = (int64_t*)(calloc(((int64_t)((MAXN * MAXN))), 8));
    int32_t i = 0;
    while (i < size) {
        int32_t j = 0;
        while (j < size) {
            a[((i * MAXN) + j)] = FLOW_CHECKED_MOD((mat[((i * size) + j)]), (mod));
            if (a[((i * MAXN) + j)] < 0) {
                a[((i * MAXN) + j)] = (a[((i * MAXN) + j)] + mod);
            }
            j = (j + 1);
        }
        i = (i + 1);
    }
    int64_t det = 1;
    int32_t col = 0;
    while (col < size) {
        int32_t pivot = (-1);
        int32_t row = col;
        while (row < size) {
            if (FLOW_CHECKED_MOD((a[((row * MAXN) + col)]), (mod)) != 0) {
                pivot = row;
                break;
            }
            row = (row + 1);
        }
        if (pivot < 0) {
            free(a);
            return 0;
        }
        if (pivot != col) {
            int32_t j = 0;
            while (j < size) {
                int64_t t = a[((col * MAXN) + j)];
                a[((col * MAXN) + j)] = a[((pivot * MAXN) + j)];
                a[((pivot * MAXN) + j)] = t;
                j = (j + 1);
            }
            det = (0 - det);
        }
        int64_t pv = FLOW_CHECKED_MOD((a[((col * MAXN) + col)]), (mod));
        if (pv < 0) {
            pv = (pv + mod);
        }
        det = mulmod_i64_i64_i64(det, pv, mod);
        int64_t inv = powmod_i64_i64_i64(pv, (mod - 2), mod);
        int32_t row2 = (col + 1);
        while (row2 < size) {
            if (FLOW_CHECKED_MOD((a[((row2 * MAXN) + col)]), (mod)) != 0) {
                int64_t factor = mulmod_i64_i64_i64(a[((row2 * MAXN) + col)], inv, mod);
                int32_t j = col;
                while (j < size) {
                    a[((row2 * MAXN) + j)] = FLOW_CHECKED_MOD(((a[((row2 * MAXN) + j)] - mulmod_i64_i64_i64(factor, a[((col * MAXN) + j)], mod))), (mod));
                    if (a[((row2 * MAXN) + j)] < 0) {
                        a[((row2 * MAXN) + j)] = (a[((row2 * MAXN) + j)] + mod);
                    }
                    j = (j + 1);
                }
            }
            row2 = (row2 + 1);
        }
        col = (col + 1);
    }
    det = FLOW_CHECKED_MOD((det), (mod));
    if (det < 0) {
        det = (det + mod);
    }
    free(a);
    return det;
}

int64_t perm_hash_i64(int64_t key) {
    int64_t h = (key ^ FLOW_CHECKED_SHR((key), (16)));
    int64_t h2 = (h * 2654435761);
    int64_t h3 = (h2 ^ FLOW_CHECKED_SHR((h2), (16)));
    return (h3 & PERM_CACHE_MASK);
}

int32_t perm_cache_lookup_i64_ptr_i64(int64_t key, int64_t* out) {
    int64_t h = perm_hash_i64(key);
    while (g_perm_used[h] != 0) {
        if (g_perm_key[h] == key) {
            out[0] = g_perm_val[h];
            return 1;
        }
        h = ((h + 1) & PERM_CACHE_MASK);
    }
    return 0;
}

void perm_cache_insert_i64_i64(int64_t key, int64_t val) {
    int64_t h = perm_hash_i64(key);
    while (g_perm_used[h] != 0) {
        if (g_perm_key[h] == key) {
            g_perm_val[h] = val;
            return;
        }
        h = ((h + 1) & PERM_CACHE_MASK);
    }
    g_perm_used[h] = 1;
    g_perm_key[h] = key;
    g_perm_val[h] = val;
}

void rec_perm_i32_i32_i64(int32_t col_pos, int32_t chosen, int64_t coeff) {
    if (col_pos == g_active_count) {
        int64_t product = coeff;
        int32_t i = 0;
        while (i < g_num_supports) {
            if (g_row_sums[i] == 0) {
                return;
            }
            product = mulmod_i64_i64_i64(product, powmod_i64_i64_i64(((int64_t)(g_row_sums[i])), ((int64_t)(g_row_counts_arr[i])), MOD), MOD);
            i = (i + 1);
        }
        if ((chosen & 1) == 1) {
            g_total = (g_total - product);
        } else {
            g_total = (g_total + product);
        }
        return;
    }
    int32_t class_size = g_active_col_counts[col_pos];
    int32_t base_idx = (col_pos * 256);
    int32_t n_aff = 0;
    int32_t idx = 0;
    while (idx < g_num_supports) {
        if ((FLOW_CHECKED_SHR((g_supports[idx]), (col_pos)) & 1) == 1) {
            g_affected[(base_idx + n_aff)] = idx;
            n_aff = (n_aff + 1);
        }
        idx = (idx + 1);
    }
    g_n_affected[col_pos] = n_aff;
    int32_t take = 0;
    while (take <= class_size) {
        if (take > 0) {
            int32_t i = 0;
            while (i < n_aff) {
                g_row_sums[g_affected[(base_idx + i)]] = (g_row_sums[g_affected[(base_idx + i)]] + take);
                i = (i + 1);
            }
        }
        rec_perm_i32_i32_i64((col_pos + 1), (chosen + take), mulmod_i64_i64_i64(coeff, FLOW_CHECKED_MOD((g_comb[((class_size * (MAXN + 1)) + take)]), (MOD)), MOD));
        if (take > 0) {
            int32_t i = 0;
            while (i < n_aff) {
                g_row_sums[g_affected[(base_idx + i)]] = (g_row_sums[g_affected[(base_idx + i)]] - take);
                i = (i + 1);
            }
        }
        take = (take + 1);
    }
}

int64_t grouped_permanent_i32_i32(int32_t row_selected, int32_t col_selected) {
    int64_t key = (FLOW_CHECKED_SHL((((int64_t)(row_selected))), (20)) | ((int64_t)(col_selected)));
    int64_t* out = (int64_t*)(calloc(1, 8));
    if (perm_cache_lookup_i64_ptr_i64(key, out) == 1) {
        int64_t cached = out[0];
        free(out);
        return cached;
    }
    free(out);
    g_active_count = 0;
    int32_t cc = 0;
    while (cc < g_col_class_count) {
        int32_t remaining = (g_col_class_count_arr[cc] - (FLOW_CHECKED_SHR((col_selected), (cc)) & 1));
        if (remaining > 0) {
            g_active_col_classes[g_active_count] = cc;
            g_active_col_counts[g_active_count] = remaining;
            g_active_count = (g_active_count + 1);
        }
        cc = (cc + 1);
    }
    int32_t* row_group_counts = (int32_t*)(calloc(256, 4));
    row_group_counts[(FLOW_CHECKED_SHL((1), (g_active_count)) - 1)] = 1;
    int32_t rc = 0;
    while (rc < g_row_class_count) {
        int32_t remaining = (g_row_class_count_arr[rc] - (FLOW_CHECKED_SHR((row_selected), (rc)) & 1));
        if (remaining > 0) {
            int32_t support = 0;
            int32_t orig = g_row_supports[rc];
            int32_t nc = 0;
            while (nc < g_active_count) {
                int32_t old_col = g_active_col_classes[nc];
                if ((FLOW_CHECKED_SHR((orig), (old_col)) & 1) == 1) {
                    support = (support | FLOW_CHECKED_SHL((1), (nc)));
                }
                nc = (nc + 1);
            }
            row_group_counts[support] = (row_group_counts[support] + remaining);
        }
        rc = (rc + 1);
    }
    g_num_supports = 0;
    g_row_total = 0;
    int32_t s = 0;
    while (s < 256) {
        if (row_group_counts[s] > 0) {
            g_supports[g_num_supports] = s;
            g_row_counts_arr[g_num_supports] = row_group_counts[s];
            g_row_sums[g_num_supports] = 0;
            g_row_total = (g_row_total + row_group_counts[s]);
            g_num_supports = (g_num_supports + 1);
        }
        s = (s + 1);
    }
    g_total = 0;
    rec_perm_i32_i32_i64(0, 0, 1);
    if ((g_row_total & 1) == 1) {
        g_total = (0 - g_total);
    }
    g_total = FLOW_CHECKED_MOD((g_total), (MOD));
    if (g_total < 0) {
        g_total = (g_total + MOD);
    }
    perm_cache_insert_i64_i64(key, g_total);
    free(row_group_counts);
    return g_total;
}

int64_t P_func_i32_i64(int32_t n, int64_t mod) {
    memset(g_perm_key, 0, (PERM_CACHE_CAP * 8));
    memset(g_perm_val, 0, (PERM_CACHE_CAP * 8));
    memset(g_perm_used, 0, PERM_CACHE_CAP);
    if (n < 2) {
        return 0;
    }
    int32_t m = FLOW_CHECKED_DIV((n), (2));
    int32_t* odds = (int32_t*)(calloc(((int64_t)(m)), 4));
    int32_t* evens = (int32_t*)(calloc(((int64_t)(m)), 4));
    int32_t i = 0;
    while (i < m) {
        odds[i] = ((2 * i) + 1);
        evens[i] = (2 * (i + 1));
        i = (i + 1);
    }
    int32_t* matrix = (int32_t*)(calloc(((int64_t)((MAXN * MAXN))), 4));
    int32_t i2 = 0;
    while (i2 < m) {
        int32_t j = 0;
        while (j < m) {
            if (gcd_ll_i64_i64(((int64_t)(odds[i2])), ((int64_t)(evens[j]))) == 1) {
                matrix[((i2 * MAXN) + j)] = 1;
            } else {
                matrix[((i2 * MAXN) + j)] = 0;
            }
            j = (j + 1);
        }
        i2 = (i2 + 1);
    }
    int32_t* row_masks = (int32_t*)(calloc(((int64_t)(MAXN)), 4));
    int32_t row = 1;
    while (row < m) {
        int32_t mask = 0;
        int32_t col = 0;
        while (col < m) {
            if (matrix[((row * MAXN) + col)] != 0) {
                mask = (mask | FLOW_CHECKED_SHL((1), (col)));
            }
            col = (col + 1);
        }
        row_masks[(row - 1)] = mask;
        row = (row + 1);
    }
    int32_t* col_masks = (int32_t*)(calloc(((int64_t)(MAXN)), 4));
    int32_t col2 = 0;
    while (col2 < m) {
        int32_t mask = 0;
        int32_t row2 = 0;
        while (row2 < m) {
            if (matrix[((row2 * MAXN) + col2)] != 0) {
                mask = (mask | FLOW_CHECKED_SHL((1), (row2)));
            }
            row2 = (row2 + 1);
        }
        col_masks[col2] = mask;
        col2 = (col2 + 1);
    }
    g_row_class_count = 0;
    int32_t* row_seen = (int32_t*)(calloc(131072, 4));
    memset(row_seen, (-1), (131072 * 4));
    int32_t idx = 0;
    while (idx < (m - 1)) {
        int32_t mask = row_masks[idx];
        if (row_seen[mask] < 0) {
            row_seen[mask] = g_row_class_count;
            g_row_class_rep[g_row_class_count] = idx;
            g_row_class_count_arr[g_row_class_count] = 1;
            g_row_class_count = (g_row_class_count + 1);
        } else {
            g_row_class_count_arr[row_seen[mask]] = (g_row_class_count_arr[row_seen[mask]] + 1);
        }
        idx = (idx + 1);
    }
    g_col_class_count = 0;
    int32_t* col_seen = (int32_t*)(calloc(131072, 4));
    memset(col_seen, (-1), (131072 * 4));
    idx = 0;
    while (idx < m) {
        int32_t mask = col_masks[idx];
        if (col_seen[mask] < 0) {
            col_seen[mask] = g_col_class_count;
            g_col_class_rep[g_col_class_count] = idx;
            g_col_class_count_arr[g_col_class_count] = 1;
            g_col_class_count = (g_col_class_count + 1);
        } else {
            g_col_class_count_arr[col_seen[mask]] = (g_col_class_count_arr[col_seen[mask]] + 1);
        }
        idx = (idx + 1);
    }
    int32_t rc2 = 0;
    while (rc2 < g_row_class_count) {
        int32_t cc2 = 0;
        while (cc2 < g_col_class_count) {
            g_class_entry[((rc2 * MAXN) + cc2)] = matrix[(((g_row_class_rep[rc2] + 1) * MAXN) + g_col_class_rep[cc2])];
            cc2 = (cc2 + 1);
        }
        rc2 = (rc2 + 1);
    }
    rc2 = 0;
    while (rc2 < g_row_class_count) {
        int32_t support = 0;
        int32_t cc2 = 0;
        while (cc2 < g_col_class_count) {
            if (matrix[(((g_row_class_rep[rc2] + 1) * MAXN) + g_col_class_rep[cc2])] != 0) {
                support = (support | FLOW_CHECKED_SHL((1), (cc2)));
            }
            cc2 = (cc2 + 1);
        }
        g_row_supports[rc2] = support;
        rc2 = (rc2 + 1);
    }
    init_comb_i32(m);
    int64_t answer = 0;
    int32_t rcc = g_row_class_count;
    int32_t ccc = g_col_class_count;
    int32_t* row_subset = (int32_t*)(calloc(20, 4));
    int32_t* col_subset = (int32_t*)(calloc(20, 4));
    int64_t* det_mat = (int64_t*)(calloc(400, 8));
    int32_t size = 0;
    while ((size <= ccc && size <= rcc)) {
        int64_t sign = 1;
        if ((size & 1) == 1) {
            sign = (-1);
        }
        int32_t i3 = 0;
        while (i3 < size) {
            row_subset[i3] = i3;
            i3 = (i3 + 1);
        }
        bool row_done = 0;
        while ((!(row_done))) {
            int32_t row_mask = 0;
            int64_t row_mult = 1;
            int32_t i4 = 0;
            while (i4 < size) {
                row_mask = (row_mask | FLOW_CHECKED_SHL((1), (row_subset[i4])));
                row_mult = mulmod_i64_i64_i64(row_mult, ((int64_t)(g_row_class_count_arr[row_subset[i4]])), mod);
                i4 = (i4 + 1);
            }
            int32_t i5 = 0;
            while (i5 < size) {
                col_subset[i5] = i5;
                i5 = (i5 + 1);
            }
            bool col_done = 0;
            while ((!(col_done))) {
                int32_t col_mask = 0;
                int64_t col_mult = 1;
                int32_t i6 = 0;
                while (i6 < size) {
                    col_mask = (col_mask | FLOW_CHECKED_SHL((1), (col_subset[i6])));
                    col_mult = mulmod_i64_i64_i64(col_mult, ((int64_t)(g_col_class_count_arr[col_subset[i6]])), mod);
                    i6 = (i6 + 1);
                }
                int32_t i7 = 0;
                while (i7 < size) {
                    int32_t j7 = 0;
                    while (j7 < size) {
                        det_mat[((i7 * size) + j7)] = ((int64_t)(g_class_entry[((row_subset[i7] * MAXN) + col_subset[j7])]));
                        j7 = (j7 + 1);
                    }
                    i7 = (i7 + 1);
                }
                int64_t det = determinant_mod_ptr_i64_i32_i64(det_mat, size, mod);
                if (det != 0) {
                    int64_t perm = grouped_permanent_i32_i32(row_mask, col_mask);
                    int64_t term = mulmod_i64_i64_i64(row_mult, col_mult, mod);
                    int64_t term2 = mulmod_i64_i64_i64(term, mulmod_i64_i64_i64(det, det, mod), mod);
                    int64_t term3 = mulmod_i64_i64_i64(term2, mulmod_i64_i64_i64(perm, perm, mod), mod);
                    answer = (answer + (sign * term3));
                }
                if (size == 0) {
                    col_done = 1;
                } else {
                    int32_t pos = (size - 1);
                    while ((pos >= 0 && col_subset[pos] == ((ccc - size) + pos))) {
                        pos = (pos - 1);
                    }
                    if (pos < 0) {
                        col_done = 1;
                    } else {
                        col_subset[pos] = (col_subset[pos] + 1);
                        int32_t i8v = (pos + 1);
                        while (i8v < size) {
                            col_subset[i8v] = (col_subset[(i8v - 1)] + 1);
                            i8v = (i8v + 1);
                        }
                    }
                }
            }
            if (size == 0) {
                row_done = 1;
            } else {
                int32_t pos = (size - 1);
                while ((pos >= 0 && row_subset[pos] == ((rcc - size) + pos))) {
                    pos = (pos - 1);
                }
                if (pos < 0) {
                    row_done = 1;
                } else {
                    row_subset[pos] = (row_subset[pos] + 1);
                    int32_t i9 = (pos + 1);
                    while (i9 < size) {
                        row_subset[i9] = (row_subset[(i9 - 1)] + 1);
                        i9 = (i9 + 1);
                    }
                }
            }
        }
        size = (size + 1);
    }
    answer = FLOW_CHECKED_MOD((answer), (mod));
    if (answer < 0) {
        answer = (answer + mod);
    }
    free(odds);
    free(evens);
    free(matrix);
    free(row_masks);
    free(col_masks);
    free(row_seen);
    free(col_seen);
    free(row_subset);
    free(col_subset);
    free(det_mat);
    return answer;
}

int32_t main(void) {
    g_comb = calloc(((int64_t)(((MAXN + 1) * (MAXN + 1)))), 8);
    g_row_class_rep = calloc(((int64_t)(MAXN)), 4);
    g_row_class_count_arr = calloc(((int64_t)(MAXN)), 4);
    g_col_class_rep = calloc(((int64_t)(MAXN)), 4);
    g_col_class_count_arr = calloc(((int64_t)(MAXN)), 4);
    g_class_entry = calloc(((int64_t)((MAXN * MAXN))), 4);
    g_row_supports = calloc(((int64_t)(MAXN)), 4);
    g_perm_key = calloc(PERM_CACHE_CAP, 8);
    g_perm_val = calloc(PERM_CACHE_CAP, 8);
    g_perm_used = calloc(PERM_CACHE_CAP, 1);
    g_active_col_classes = calloc(((int64_t)(MAXN)), 4);
    g_active_col_counts = calloc(((int64_t)(MAXN)), 4);
    g_supports = calloc(256, 4);
    g_row_counts_arr = calloc(256, 4);
    g_row_sums = calloc(256, 4);
    g_affected = calloc(((int64_t)((MAXN * 256))), 4);
    g_n_affected = calloc(((int64_t)(MAXN)), 4);
    int64_t ans = P_func_i32_i64(34, MOD);
    printf("%lld\n", ans);
    free(g_comb);
    free(g_row_class_rep);
    free(g_row_class_count_arr);
    free(g_col_class_rep);
    free(g_col_class_count_arr);
    free(g_class_entry);
    free(g_row_supports);
    free(g_perm_key);
    free(g_perm_val);
    free(g_perm_used);
    free(g_active_col_classes);
    free(g_active_col_counts);
    free(g_supports);
    free(g_row_counts_arr);
    free(g_row_sums);
    free(g_affected);
    free(g_n_affected);
    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) -> ()
  func.func private @memset(!llvm.ptr, i32, i64) -> !llvm.ptr
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(83456729 : i64) : i64
  // Constant: MAXN
  llvm.mlir.global internal constant @MAXN(34 : i32) : i32
  // Module static: g_comb
  llvm.mlir.global internal @g_comb() {addr_space = 0 : i32} : !llvm.ptr {
    %0 = llvm.mlir.zero : !llvm.ptr
    llvm.return %0 : !llvm.ptr
  }
  // Module static: g_row_class_count
  llvm.mlir.global internal @g_row_class_count(0 : i32) : i32
  // Module static: g_col_class_count
  llvm.mlir.global internal @g_col_class_count(0 : i32) : i32
  // Module static: g_row_class_rep
  llvm.mlir.global internal @g_row_class_rep() {addr_space = 0 : i32} : !llvm.ptr {
    %1 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1 : !llvm.ptr
  }
  // Module static: g_row_class_count_arr
  llvm.mlir.global internal @g_row_class_count_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %2 = llvm.mlir.zero : !llvm.ptr
    llvm.return %2 : !llvm.ptr
  }
  // Module static: g_col_class_rep
  llvm.mlir.global internal @g_col_class_rep() {addr_space = 0 : i32} : !llvm.ptr {
    %3 = llvm.mlir.zero : !llvm.ptr
    llvm.return %3 : !llvm.ptr
  }
  // Module static: g_col_class_count_arr
  llvm.mlir.global internal @g_col_class_count_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %4 = llvm.mlir.zero : !llvm.ptr
    llvm.return %4 : !llvm.ptr
  }
  // Module static: g_class_entry
  llvm.mlir.global internal @g_class_entry() {addr_space = 0 : i32} : !llvm.ptr {
    %5 = llvm.mlir.zero : !llvm.ptr
    llvm.return %5 : !llvm.ptr
  }
  // Module static: g_row_supports
  llvm.mlir.global internal @g_row_supports() {addr_space = 0 : i32} : !llvm.ptr {
    %6 = llvm.mlir.zero : !llvm.ptr
    llvm.return %6 : !llvm.ptr
  }
  // Constant: PERM_CACHE_CAP
  llvm.mlir.global internal constant @PERM_CACHE_CAP(1048576 : i64) : i64
  // Constant: PERM_CACHE_MASK
  llvm.mlir.global internal constant @PERM_CACHE_MASK(1048575 : i64) : i64
  // Module static: g_perm_key
  llvm.mlir.global internal @g_perm_key() {addr_space = 0 : i32} : !llvm.ptr {
    %7 = llvm.mlir.zero : !llvm.ptr
    llvm.return %7 : !llvm.ptr
  }
  // Module static: g_perm_val
  llvm.mlir.global internal @g_perm_val() {addr_space = 0 : i32} : !llvm.ptr {
    %8 = llvm.mlir.zero : !llvm.ptr
    llvm.return %8 : !llvm.ptr
  }
  // Module static: g_perm_used
  llvm.mlir.global internal @g_perm_used() {addr_space = 0 : i32} : !llvm.ptr {
    %9 = llvm.mlir.zero : !llvm.ptr
    llvm.return %9 : !llvm.ptr
  }
  // Module static: g_active_col_classes
  llvm.mlir.global internal @g_active_col_classes() {addr_space = 0 : i32} : !llvm.ptr {
    %10 = llvm.mlir.zero : !llvm.ptr
    llvm.return %10 : !llvm.ptr
  }
  // Module static: g_active_col_counts
  llvm.mlir.global internal @g_active_col_counts() {addr_space = 0 : i32} : !llvm.ptr {
    %11 = llvm.mlir.zero : !llvm.ptr
    llvm.return %11 : !llvm.ptr
  }
  // Module static: g_active_count
  llvm.mlir.global internal @g_active_count(0 : i32) : i32
  // Module static: g_supports
  llvm.mlir.global internal @g_supports() {addr_space = 0 : i32} : !llvm.ptr {
    %12 = llvm.mlir.zero : !llvm.ptr
    llvm.return %12 : !llvm.ptr
  }
  // Module static: g_row_counts_arr
  llvm.mlir.global internal @g_row_counts_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %13 = llvm.mlir.zero : !llvm.ptr
    llvm.return %13 : !llvm.ptr
  }
  // Module static: g_row_sums
  llvm.mlir.global internal @g_row_sums() {addr_space = 0 : i32} : !llvm.ptr {
    %14 = llvm.mlir.zero : !llvm.ptr
    llvm.return %14 : !llvm.ptr
  }
  // Module static: g_num_supports
  llvm.mlir.global internal @g_num_supports(0 : i32) : i32
  // Module static: g_row_total
  llvm.mlir.global internal @g_row_total(0 : i32) : i32
  // Module static: g_total
  llvm.mlir.global internal @g_total(0 : i64) : i64
  // Module static: g_affected
  llvm.mlir.global internal @g_affected() {addr_space = 0 : i32} : !llvm.ptr {
    %15 = llvm.mlir.zero : !llvm.ptr
    llvm.return %15 : !llvm.ptr
  }
  // Module static: g_n_affected
  llvm.mlir.global internal @g_n_affected() {addr_space = 0 : i32} : !llvm.ptr {
    %16 = llvm.mlir.zero : !llvm.ptr
    llvm.return %16 : !llvm.ptr
  }
  func.func @mulmod(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %17 = arith.extsi %arg0 : i64 to i128
    %18 = arith.extsi %arg1 : i64 to i128
    %19 = arith.extsi %arg2 : i64 to i128
    %21 = arith.trunci %17 : i128 to i64
    %22 = arith.trunci %18 : i128 to i64
    %20 = arith.muli %21, %22 : i64
    %24 = arith.trunci %19 : i128 to i64
    %23 = arith.remsi %20, %24 : i64
    %25 = arith.extsi %23 : i64 to i128
    %26 = arith.trunci %25 : i128 to i64
    func.return %26 : i64
  }
  func.func @powmod(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %27 = arith.constant 1 : i32
    %29 = arith.extsi %27 : i32 to i64
    %28 = arith.remsi %29, %arg2 : i64
    %30 = llvm.mlir.constant(1 : i64) : i64
    %31 = llvm.alloca %30 x i64 : (i64) -> !llvm.ptr
    llvm.store %28, %31 : i64, !llvm.ptr
    %32 = arith.remsi %arg0, %arg2 : i64
    %33 = llvm.mlir.constant(1 : i64) : i64
    %34 = llvm.alloca %33 x i64 : (i64) -> !llvm.ptr
    llvm.store %32, %34 : i64, !llvm.ptr
    %35 = llvm.load %34 : !llvm.ptr -> i64
    %36 = arith.constant 0 : i32
    %38 = arith.extsi %36 : i32 to i64
    %37 = arith.cmpi slt, %35, %38 : i64
    cf.cond_br %37, ^bb0, ^bb1
    ^bb0:
      %39 = llvm.load %34 : !llvm.ptr -> i64
      %40 = arith.addi %39, %arg2 : i64
      llvm.store %40, %34 : i64, !llvm.ptr
      cf.br ^bb2
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %41 = llvm.mlir.constant(1 : i64) : i64
    %42 = llvm.alloca %41 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %42 : i64, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %43 = llvm.load %42 : !llvm.ptr -> i64
    %44 = arith.constant 0 : i32
    %46 = arith.extsi %44 : i32 to i64
    %45 = arith.cmpi sgt, %43, %46 : i64
    cf.cond_br %45, ^bb4, ^bb5
    ^bb4:
      %47 = llvm.load %42 : !llvm.ptr -> i64
      %48 = arith.constant 1 : i32
      %50 = arith.extsi %48 : i32 to i64
      %49 = arith.andi %47, %50 : i64
      %51 = arith.constant 1 : i32
      %53 = arith.extsi %51 : i32 to i64
      %52 = arith.cmpi eq, %49, %53 : i64
      cf.cond_br %52, ^bb6, ^bb7
      ^bb6:
        %55 = llvm.load %31 : !llvm.ptr -> i64
        %56 = llvm.load %34 : !llvm.ptr -> i64
        %54 = func.call @mulmod(%55, %56, %arg2) : (i64, i64, i64) -> i64
        llvm.store %54, %31 : i64, !llvm.ptr
        cf.br ^bb8
      ^bb7:
        cf.br ^bb8
      ^bb8:
      %58 = llvm.load %34 : !llvm.ptr -> i64
      %59 = llvm.load %34 : !llvm.ptr -> i64
      %57 = func.call @mulmod(%58, %59, %arg2) : (i64, i64, i64) -> i64
      llvm.store %57, %34 : i64, !llvm.ptr
      %60 = llvm.load %42 : !llvm.ptr -> i64
      %61 = arith.constant 1 : i32
      %63 = arith.extsi %61 : i32 to i64
      %62 = arith.shrsi %60, %63 : i64
      llvm.store %62, %42 : i64, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %64 = llvm.load %31 : !llvm.ptr -> i64
    func.return %64 : i64
  }
  func.func @gcd_ll(%arg0: i64, %arg1: i64) -> i64 {
    %65 = llvm.mlir.constant(1 : i64) : i64
    %66 = llvm.alloca %65 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %66 : i64, !llvm.ptr
    %67 = llvm.mlir.constant(1 : i64) : i64
    %68 = llvm.alloca %67 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %68 : i64, !llvm.ptr
    cf.br ^bb9
    ^bb9:
    %69 = llvm.load %68 : !llvm.ptr -> i64
    %70 = arith.constant 0 : i32
    %72 = arith.extsi %70 : i32 to i64
    %71 = arith.cmpi ne, %69, %72 : i64
    cf.cond_br %71, ^bb10, ^bb11
    ^bb10:
      %73 = llvm.load %66 : !llvm.ptr -> i64
      %74 = llvm.load %68 : !llvm.ptr -> i64
      %75 = arith.remsi %73, %74 : i64
      %76 = llvm.load %68 : !llvm.ptr -> i64
      llvm.store %76, %66 : i64, !llvm.ptr
      llvm.store %75, %68 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %77 = llvm.load %66 : !llvm.ptr -> i64
    func.return %77 : i64
  }
  func.func @init_comb(%arg0: i32) -> () {
    %78 = arith.constant 0 : i32
    %79 = llvm.mlir.constant(1 : i64) : i64
    %80 = llvm.alloca %79 x i32 : (i64) -> !llvm.ptr
    llvm.store %78, %80 : i32, !llvm.ptr
    cf.br ^bb12
    ^bb12:
    %81 = llvm.load %80 : !llvm.ptr -> i32
    %82 = arith.cmpi sle, %81, %arg0 : i32
    cf.cond_br %82, ^bb13, ^bb14
    ^bb13:
      %83 = arith.constant 1 : i32
      %84 = llvm.mlir.addressof @g_comb : !llvm.ptr
      %85 = llvm.load %84 : !llvm.ptr -> !llvm.ptr
      %86 = llvm.load %80 : !llvm.ptr -> i32
      %87 = llvm.mlir.addressof @MAXN : !llvm.ptr
      %88 = llvm.load %87 : !llvm.ptr -> i32
      %89 = arith.constant 1 : i32
      %90 = arith.addi %88, %89 : i32
      %91 = arith.muli %86, %90 : i32
      %92 = arith.constant 0 : i32
      %93 = arith.addi %91, %92 : i32
      %94 = arith.extsi %83 : i32 to i64
      %95 = arith.extsi %93 : i32 to i64
      %96 = llvm.getelementptr %85[%95] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %94, %96 : i64, !llvm.ptr
      %97 = arith.constant 1 : i32
      %98 = llvm.mlir.addressof @g_comb : !llvm.ptr
      %99 = llvm.load %98 : !llvm.ptr -> !llvm.ptr
      %100 = llvm.load %80 : !llvm.ptr -> i32
      %101 = llvm.mlir.addressof @MAXN : !llvm.ptr
      %102 = llvm.load %101 : !llvm.ptr -> i32
      %103 = arith.constant 1 : i32
      %104 = arith.addi %102, %103 : i32
      %105 = arith.muli %100, %104 : i32
      %106 = llvm.load %80 : !llvm.ptr -> i32
      %107 = arith.addi %105, %106 : i32
      %108 = arith.extsi %97 : i32 to i64
      %109 = arith.extsi %107 : i32 to i64
      %110 = llvm.getelementptr %99[%109] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %108, %110 : i64, !llvm.ptr
      %111 = arith.constant 1 : i32
      %112 = llvm.mlir.constant(1 : i64) : i64
      %113 = llvm.alloca %112 x i32 : (i64) -> !llvm.ptr
      llvm.store %111, %113 : i32, !llvm.ptr
      cf.br ^bb15
      ^bb15:
      %114 = llvm.load %113 : !llvm.ptr -> i32
      %115 = llvm.load %80 : !llvm.ptr -> i32
      %116 = arith.cmpi slt, %114, %115 : i32
      cf.cond_br %116, ^bb16, ^bb17
      ^bb16:
        %118 = llvm.mlir.addressof @g_comb : !llvm.ptr
        %119 = llvm.load %118 : !llvm.ptr -> !llvm.ptr
        %120 = llvm.load %80 : !llvm.ptr -> i32
        %121 = arith.constant 1 : i32
        %122 = arith.subi %120, %121 : i32
        %123 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %124 = llvm.load %123 : !llvm.ptr -> i32
        %125 = arith.constant 1 : i32
        %126 = arith.addi %124, %125 : i32
        %127 = arith.muli %122, %126 : i32
        %128 = llvm.load %113 : !llvm.ptr -> i32
        %129 = arith.addi %127, %128 : i32
        %130 = arith.constant 1 : i32
        %131 = arith.subi %129, %130 : i32
        %132 = arith.extsi %131 : i32 to i64
        %133 = llvm.getelementptr %119[%132] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %117 = llvm.load %133 : !llvm.ptr -> i64
        %135 = llvm.mlir.addressof @g_comb : !llvm.ptr
        %136 = llvm.load %135 : !llvm.ptr -> !llvm.ptr
        %137 = llvm.load %80 : !llvm.ptr -> i32
        %138 = arith.constant 1 : i32
        %139 = arith.subi %137, %138 : i32
        %140 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %141 = llvm.load %140 : !llvm.ptr -> i32
        %142 = arith.constant 1 : i32
        %143 = arith.addi %141, %142 : i32
        %144 = arith.muli %139, %143 : i32
        %145 = llvm.load %113 : !llvm.ptr -> i32
        %146 = arith.addi %144, %145 : i32
        %147 = arith.extsi %146 : i32 to i64
        %148 = llvm.getelementptr %136[%147] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %134 = llvm.load %148 : !llvm.ptr -> i64
        %149 = arith.addi %117, %134 : i64
        %150 = llvm.mlir.addressof @g_comb : !llvm.ptr
        %151 = llvm.load %150 : !llvm.ptr -> !llvm.ptr
        %152 = llvm.load %80 : !llvm.ptr -> i32
        %153 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %154 = llvm.load %153 : !llvm.ptr -> i32
        %155 = arith.constant 1 : i32
        %156 = arith.addi %154, %155 : i32
        %157 = arith.muli %152, %156 : i32
        %158 = llvm.load %113 : !llvm.ptr -> i32
        %159 = arith.addi %157, %158 : i32
        %160 = arith.extsi %159 : i32 to i64
        %161 = llvm.getelementptr %151[%160] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %149, %161 : i64, !llvm.ptr
        %162 = llvm.load %113 : !llvm.ptr -> i32
        %163 = arith.constant 1 : i32
        %164 = arith.addi %162, %163 : i32
        llvm.store %164, %113 : i32, !llvm.ptr
        cf.br ^bb15
      ^bb17:
      %165 = llvm.load %80 : !llvm.ptr -> i32
      %166 = arith.constant 1 : i32
      %167 = arith.addi %165, %166 : i32
      llvm.store %167, %80 : i32, !llvm.ptr
      cf.br ^bb12
    ^bb14:
    func.return
  }
  func.func @determinant_mod(%arg0: !llvm.ptr, %arg1: i32, %arg2: i64) -> i64 {
    %168 = arith.constant 0 : i32
    %169 = arith.cmpi eq, %arg1, %168 : i32
    cf.cond_br %169, ^bb18, ^bb19
    ^bb18:
      %170 = arith.constant 1 : i32
      %171 = arith.extsi %170 : i32 to i64
      func.return %171 : i64
    ^bb19:
      cf.br ^bb20
    ^bb20:
    %173 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %174 = llvm.load %173 : !llvm.ptr -> i32
    %175 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %176 = llvm.load %175 : !llvm.ptr -> i32
    %177 = arith.muli %174, %176 : i32
    %178 = arith.extsi %177 : i32 to i64
    %179 = arith.constant 8 : i32
    %180 = arith.extsi %179 : i32 to i64
    %172 = func.call @calloc(%178, %180) : (i64, i64) -> !llvm.ptr
    %181 = arith.constant 0 : i32
    %182 = llvm.mlir.constant(1 : i64) : i64
    %183 = llvm.alloca %182 x i32 : (i64) -> !llvm.ptr
    llvm.store %181, %183 : i32, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %184 = llvm.load %183 : !llvm.ptr -> i32
    %185 = arith.cmpi slt, %184, %arg1 : i32
    cf.cond_br %185, ^bb22, ^bb23
    ^bb22:
      %186 = arith.constant 0 : i32
      %187 = llvm.mlir.constant(1 : i64) : i64
      %188 = llvm.alloca %187 x i32 : (i64) -> !llvm.ptr
      llvm.store %186, %188 : i32, !llvm.ptr
      cf.br ^bb24
      ^bb24:
      %189 = llvm.load %188 : !llvm.ptr -> i32
      %190 = arith.cmpi slt, %189, %arg1 : i32
      cf.cond_br %190, ^bb25, ^bb26
      ^bb25:
        %192 = llvm.load %183 : !llvm.ptr -> i32
        %193 = arith.muli %192, %arg1 : i32
        %194 = llvm.load %188 : !llvm.ptr -> i32
        %195 = arith.addi %193, %194 : i32
        %196 = arith.extsi %195 : i32 to i64
        %197 = llvm.getelementptr %arg0[%196] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %191 = llvm.load %197 : !llvm.ptr -> i64
        %198 = arith.remsi %191, %arg2 : i64
        %199 = llvm.load %183 : !llvm.ptr -> i32
        %200 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %201 = llvm.load %200 : !llvm.ptr -> i32
        %202 = arith.muli %199, %201 : i32
        %203 = llvm.load %188 : !llvm.ptr -> i32
        %204 = arith.addi %202, %203 : i32
        %205 = arith.extsi %204 : i32 to i64
        %206 = llvm.getelementptr %172[%205] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %198, %206 : i64, !llvm.ptr
        %208 = llvm.load %183 : !llvm.ptr -> i32
        %209 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %210 = llvm.load %209 : !llvm.ptr -> i32
        %211 = arith.muli %208, %210 : i32
        %212 = llvm.load %188 : !llvm.ptr -> i32
        %213 = arith.addi %211, %212 : i32
        %214 = arith.extsi %213 : i32 to i64
        %215 = llvm.getelementptr %172[%214] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %207 = llvm.load %215 : !llvm.ptr -> i64
        %216 = arith.constant 0 : i32
        %218 = arith.extsi %216 : i32 to i64
        %217 = arith.cmpi slt, %207, %218 : i64
        cf.cond_br %217, ^bb27, ^bb28
        ^bb27:
          %220 = llvm.load %183 : !llvm.ptr -> i32
          %221 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %222 = llvm.load %221 : !llvm.ptr -> i32
          %223 = arith.muli %220, %222 : i32
          %224 = llvm.load %188 : !llvm.ptr -> i32
          %225 = arith.addi %223, %224 : i32
          %226 = arith.extsi %225 : i32 to i64
          %227 = llvm.getelementptr %172[%226] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %219 = llvm.load %227 : !llvm.ptr -> i64
          %228 = arith.addi %219, %arg2 : i64
          %229 = llvm.load %183 : !llvm.ptr -> i32
          %230 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %231 = llvm.load %230 : !llvm.ptr -> i32
          %232 = arith.muli %229, %231 : i32
          %233 = llvm.load %188 : !llvm.ptr -> i32
          %234 = arith.addi %232, %233 : i32
          %235 = arith.extsi %234 : i32 to i64
          %236 = llvm.getelementptr %172[%235] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %228, %236 : i64, !llvm.ptr
          cf.br ^bb29
        ^bb28:
          cf.br ^bb29
        ^bb29:
        %237 = llvm.load %188 : !llvm.ptr -> i32
        %238 = arith.constant 1 : i32
        %239 = arith.addi %237, %238 : i32
        llvm.store %239, %188 : i32, !llvm.ptr
        cf.br ^bb24
      ^bb26:
      %240 = llvm.load %183 : !llvm.ptr -> i32
      %241 = arith.constant 1 : i32
      %242 = arith.addi %240, %241 : i32
      llvm.store %242, %183 : i32, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    %243 = arith.constant 1 : i32
    %244 = arith.extsi %243 : i32 to i64
    %245 = llvm.mlir.constant(1 : i64) : i64
    %246 = llvm.alloca %245 x i64 : (i64) -> !llvm.ptr
    llvm.store %244, %246 : i64, !llvm.ptr
    %247 = arith.constant 0 : i32
    %248 = llvm.mlir.constant(1 : i64) : i64
    %249 = llvm.alloca %248 x i32 : (i64) -> !llvm.ptr
    llvm.store %247, %249 : i32, !llvm.ptr
    cf.br ^bb30
    ^bb30:
    %250 = llvm.load %249 : !llvm.ptr -> i32
    %251 = arith.cmpi slt, %250, %arg1 : i32
    cf.cond_br %251, ^bb31, ^bb32
    ^bb31:
      %252 = arith.constant 1 : i32
      %254 = arith.constant 0 : i32
      %253 = arith.subi %254, %252 : i32
      %255 = llvm.mlir.constant(1 : i64) : i64
      %256 = llvm.alloca %255 x i32 : (i64) -> !llvm.ptr
      llvm.store %253, %256 : i32, !llvm.ptr
      %257 = llvm.load %249 : !llvm.ptr -> i32
      %258 = llvm.mlir.constant(1 : i64) : i64
      %259 = llvm.alloca %258 x i32 : (i64) -> !llvm.ptr
      llvm.store %257, %259 : i32, !llvm.ptr
      cf.br ^bb33
      ^bb33:
      %260 = llvm.load %259 : !llvm.ptr -> i32
      %261 = arith.cmpi slt, %260, %arg1 : i32
      cf.cond_br %261, ^bb34, ^bb35
      ^bb34:
        %263 = llvm.load %259 : !llvm.ptr -> i32
        %264 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %265 = llvm.load %264 : !llvm.ptr -> i32
        %266 = arith.muli %263, %265 : i32
        %267 = llvm.load %249 : !llvm.ptr -> i32
        %268 = arith.addi %266, %267 : i32
        %269 = arith.extsi %268 : i32 to i64
        %270 = llvm.getelementptr %172[%269] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %262 = llvm.load %270 : !llvm.ptr -> i64
        %271 = arith.remsi %262, %arg2 : i64
        %272 = arith.constant 0 : i32
        %274 = arith.extsi %272 : i32 to i64
        %273 = arith.cmpi ne, %271, %274 : i64
        cf.cond_br %273, ^bb36, ^bb37
        ^bb36:
          %275 = llvm.load %259 : !llvm.ptr -> i32
          llvm.store %275, %256 : i32, !llvm.ptr
          cf.br ^bb35
        ^bb37:
          cf.br ^bb38
        ^bb38:
        %276 = llvm.load %259 : !llvm.ptr -> i32
        %277 = arith.constant 1 : i32
        %278 = arith.addi %276, %277 : i32
        llvm.store %278, %259 : i32, !llvm.ptr
        cf.br ^bb33
      ^bb35:
      %279 = llvm.load %256 : !llvm.ptr -> i32
      %280 = arith.constant 0 : i32
      %281 = arith.cmpi slt, %279, %280 : i32
      cf.cond_br %281, ^bb39, ^bb40
      ^bb39:
        func.call @free(%172) : (!llvm.ptr) -> ()
        %283 = arith.constant 0 : i32
        %284 = arith.extsi %283 : i32 to i64
        func.return %284 : i64
      ^bb40:
        cf.br ^bb41
      ^bb41:
      %285 = llvm.load %256 : !llvm.ptr -> i32
      %286 = llvm.load %249 : !llvm.ptr -> i32
      %287 = arith.cmpi ne, %285, %286 : i32
      cf.cond_br %287, ^bb42, ^bb43
      ^bb42:
        %288 = arith.constant 0 : i32
        %289 = llvm.mlir.constant(1 : i64) : i64
        %290 = llvm.alloca %289 x i32 : (i64) -> !llvm.ptr
        llvm.store %288, %290 : i32, !llvm.ptr
        cf.br ^bb45
        ^bb45:
        %291 = llvm.load %290 : !llvm.ptr -> i32
        %292 = arith.cmpi slt, %291, %arg1 : i32
        cf.cond_br %292, ^bb46, ^bb47
        ^bb46:
          %294 = llvm.load %249 : !llvm.ptr -> i32
          %295 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %296 = llvm.load %295 : !llvm.ptr -> i32
          %297 = arith.muli %294, %296 : i32
          %298 = llvm.load %290 : !llvm.ptr -> i32
          %299 = arith.addi %297, %298 : i32
          %300 = arith.extsi %299 : i32 to i64
          %301 = llvm.getelementptr %172[%300] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %293 = llvm.load %301 : !llvm.ptr -> i64
          %303 = llvm.load %256 : !llvm.ptr -> i32
          %304 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %305 = llvm.load %304 : !llvm.ptr -> i32
          %306 = arith.muli %303, %305 : i32
          %307 = llvm.load %290 : !llvm.ptr -> i32
          %308 = arith.addi %306, %307 : i32
          %309 = arith.extsi %308 : i32 to i64
          %310 = llvm.getelementptr %172[%309] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %302 = llvm.load %310 : !llvm.ptr -> i64
          %311 = llvm.load %249 : !llvm.ptr -> i32
          %312 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %313 = llvm.load %312 : !llvm.ptr -> i32
          %314 = arith.muli %311, %313 : i32
          %315 = llvm.load %290 : !llvm.ptr -> i32
          %316 = arith.addi %314, %315 : i32
          %317 = arith.extsi %316 : i32 to i64
          %318 = llvm.getelementptr %172[%317] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %302, %318 : i64, !llvm.ptr
          %319 = llvm.load %256 : !llvm.ptr -> i32
          %320 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %321 = llvm.load %320 : !llvm.ptr -> i32
          %322 = arith.muli %319, %321 : i32
          %323 = llvm.load %290 : !llvm.ptr -> i32
          %324 = arith.addi %322, %323 : i32
          %325 = arith.extsi %324 : i32 to i64
          %326 = llvm.getelementptr %172[%325] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %293, %326 : i64, !llvm.ptr
          %327 = llvm.load %290 : !llvm.ptr -> i32
          %328 = arith.constant 1 : i32
          %329 = arith.addi %327, %328 : i32
          llvm.store %329, %290 : i32, !llvm.ptr
          cf.br ^bb45
        ^bb47:
        %330 = arith.constant 0 : i32
        %331 = llvm.load %246 : !llvm.ptr -> i64
        %333 = arith.extsi %330 : i32 to i64
        %332 = arith.subi %333, %331 : i64
        llvm.store %332, %246 : i64, !llvm.ptr
        cf.br ^bb44
      ^bb43:
        cf.br ^bb44
      ^bb44:
      %335 = llvm.load %249 : !llvm.ptr -> i32
      %336 = llvm.mlir.addressof @MAXN : !llvm.ptr
      %337 = llvm.load %336 : !llvm.ptr -> i32
      %338 = arith.muli %335, %337 : i32
      %339 = llvm.load %249 : !llvm.ptr -> i32
      %340 = arith.addi %338, %339 : i32
      %341 = arith.extsi %340 : i32 to i64
      %342 = llvm.getelementptr %172[%341] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %334 = llvm.load %342 : !llvm.ptr -> i64
      %343 = arith.remsi %334, %arg2 : i64
      %344 = llvm.mlir.constant(1 : i64) : i64
      %345 = llvm.alloca %344 x i64 : (i64) -> !llvm.ptr
      llvm.store %343, %345 : i64, !llvm.ptr
      %346 = llvm.load %345 : !llvm.ptr -> i64
      %347 = arith.constant 0 : i32
      %349 = arith.extsi %347 : i32 to i64
      %348 = arith.cmpi slt, %346, %349 : i64
      cf.cond_br %348, ^bb48, ^bb49
      ^bb48:
        %350 = llvm.load %345 : !llvm.ptr -> i64
        %351 = arith.addi %350, %arg2 : i64
        llvm.store %351, %345 : i64, !llvm.ptr
        cf.br ^bb50
      ^bb49:
        cf.br ^bb50
      ^bb50:
      %353 = llvm.load %246 : !llvm.ptr -> i64
      %354 = llvm.load %345 : !llvm.ptr -> i64
      %352 = func.call @mulmod(%353, %354, %arg2) : (i64, i64, i64) -> i64
      llvm.store %352, %246 : i64, !llvm.ptr
      %356 = llvm.load %345 : !llvm.ptr -> i64
      %357 = arith.constant 2 : i32
      %359 = arith.extsi %357 : i32 to i64
      %358 = arith.subi %arg2, %359 : i64
      %355 = func.call @powmod(%356, %358, %arg2) : (i64, i64, i64) -> i64
      %360 = llvm.load %249 : !llvm.ptr -> i32
      %361 = arith.constant 1 : i32
      %362 = arith.addi %360, %361 : i32
      %363 = llvm.mlir.constant(1 : i64) : i64
      %364 = llvm.alloca %363 x i32 : (i64) -> !llvm.ptr
      llvm.store %362, %364 : i32, !llvm.ptr
      cf.br ^bb51
      ^bb51:
      %365 = llvm.load %364 : !llvm.ptr -> i32
      %366 = arith.cmpi slt, %365, %arg1 : i32
      cf.cond_br %366, ^bb52, ^bb53
      ^bb52:
        %368 = llvm.load %364 : !llvm.ptr -> i32
        %369 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %370 = llvm.load %369 : !llvm.ptr -> i32
        %371 = arith.muli %368, %370 : i32
        %372 = llvm.load %249 : !llvm.ptr -> i32
        %373 = arith.addi %371, %372 : i32
        %374 = arith.extsi %373 : i32 to i64
        %375 = llvm.getelementptr %172[%374] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %367 = llvm.load %375 : !llvm.ptr -> i64
        %376 = arith.remsi %367, %arg2 : i64
        %377 = arith.constant 0 : i32
        %379 = arith.extsi %377 : i32 to i64
        %378 = arith.cmpi ne, %376, %379 : i64
        cf.cond_br %378, ^bb54, ^bb55
        ^bb54:
          %382 = llvm.load %364 : !llvm.ptr -> i32
          %383 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %384 = llvm.load %383 : !llvm.ptr -> i32
          %385 = arith.muli %382, %384 : i32
          %386 = llvm.load %249 : !llvm.ptr -> i32
          %387 = arith.addi %385, %386 : i32
          %388 = arith.extsi %387 : i32 to i64
          %389 = llvm.getelementptr %172[%388] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %381 = llvm.load %389 : !llvm.ptr -> i64
          %380 = func.call @mulmod(%381, %355, %arg2) : (i64, i64, i64) -> i64
          %390 = llvm.load %249 : !llvm.ptr -> i32
          %391 = llvm.mlir.constant(1 : i64) : i64
          %392 = llvm.alloca %391 x i32 : (i64) -> !llvm.ptr
          llvm.store %390, %392 : i32, !llvm.ptr
          cf.br ^bb57
          ^bb57:
          %393 = llvm.load %392 : !llvm.ptr -> i32
          %394 = arith.cmpi slt, %393, %arg1 : i32
          cf.cond_br %394, ^bb58, ^bb59
          ^bb58:
            %396 = llvm.load %364 : !llvm.ptr -> i32
            %397 = llvm.mlir.addressof @MAXN : !llvm.ptr
            %398 = llvm.load %397 : !llvm.ptr -> i32
            %399 = arith.muli %396, %398 : i32
            %400 = llvm.load %392 : !llvm.ptr -> i32
            %401 = arith.addi %399, %400 : i32
            %402 = arith.extsi %401 : i32 to i64
            %403 = llvm.getelementptr %172[%402] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %395 = llvm.load %403 : !llvm.ptr -> i64
            %406 = llvm.load %249 : !llvm.ptr -> i32
            %407 = llvm.mlir.addressof @MAXN : !llvm.ptr
            %408 = llvm.load %407 : !llvm.ptr -> i32
            %409 = arith.muli %406, %408 : i32
            %410 = llvm.load %392 : !llvm.ptr -> i32
            %411 = arith.addi %409, %410 : i32
            %412 = arith.extsi %411 : i32 to i64
            %413 = llvm.getelementptr %172[%412] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %405 = llvm.load %413 : !llvm.ptr -> i64
            %404 = func.call @mulmod(%380, %405, %arg2) : (i64, i64, i64) -> i64
            %414 = arith.subi %395, %404 : i64
            %415 = arith.remsi %414, %arg2 : i64
            %416 = llvm.load %364 : !llvm.ptr -> i32
            %417 = llvm.mlir.addressof @MAXN : !llvm.ptr
            %418 = llvm.load %417 : !llvm.ptr -> i32
            %419 = arith.muli %416, %418 : i32
            %420 = llvm.load %392 : !llvm.ptr -> i32
            %421 = arith.addi %419, %420 : i32
            %422 = arith.extsi %421 : i32 to i64
            %423 = llvm.getelementptr %172[%422] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %415, %423 : i64, !llvm.ptr
            %425 = llvm.load %364 : !llvm.ptr -> i32
            %426 = llvm.mlir.addressof @MAXN : !llvm.ptr
            %427 = llvm.load %426 : !llvm.ptr -> i32
            %428 = arith.muli %425, %427 : i32
            %429 = llvm.load %392 : !llvm.ptr -> i32
            %430 = arith.addi %428, %429 : i32
            %431 = arith.extsi %430 : i32 to i64
            %432 = llvm.getelementptr %172[%431] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %424 = llvm.load %432 : !llvm.ptr -> i64
            %433 = arith.constant 0 : i32
            %435 = arith.extsi %433 : i32 to i64
            %434 = arith.cmpi slt, %424, %435 : i64
            cf.cond_br %434, ^bb60, ^bb61
            ^bb60:
              %437 = llvm.load %364 : !llvm.ptr -> i32
              %438 = llvm.mlir.addressof @MAXN : !llvm.ptr
              %439 = llvm.load %438 : !llvm.ptr -> i32
              %440 = arith.muli %437, %439 : i32
              %441 = llvm.load %392 : !llvm.ptr -> i32
              %442 = arith.addi %440, %441 : i32
              %443 = arith.extsi %442 : i32 to i64
              %444 = llvm.getelementptr %172[%443] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %436 = llvm.load %444 : !llvm.ptr -> i64
              %445 = arith.addi %436, %arg2 : i64
              %446 = llvm.load %364 : !llvm.ptr -> i32
              %447 = llvm.mlir.addressof @MAXN : !llvm.ptr
              %448 = llvm.load %447 : !llvm.ptr -> i32
              %449 = arith.muli %446, %448 : i32
              %450 = llvm.load %392 : !llvm.ptr -> i32
              %451 = arith.addi %449, %450 : i32
              %452 = arith.extsi %451 : i32 to i64
              %453 = llvm.getelementptr %172[%452] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              llvm.store %445, %453 : i64, !llvm.ptr
              cf.br ^bb62
            ^bb61:
              cf.br ^bb62
            ^bb62:
            %454 = llvm.load %392 : !llvm.ptr -> i32
            %455 = arith.constant 1 : i32
            %456 = arith.addi %454, %455 : i32
            llvm.store %456, %392 : i32, !llvm.ptr
            cf.br ^bb57
          ^bb59:
          cf.br ^bb56
        ^bb55:
          cf.br ^bb56
        ^bb56:
        %457 = llvm.load %364 : !llvm.ptr -> i32
        %458 = arith.constant 1 : i32
        %459 = arith.addi %457, %458 : i32
        llvm.store %459, %364 : i32, !llvm.ptr
        cf.br ^bb51
      ^bb53:
      %460 = llvm.load %249 : !llvm.ptr -> i32
      %461 = arith.constant 1 : i32
      %462 = arith.addi %460, %461 : i32
      llvm.store %462, %249 : i32, !llvm.ptr
      cf.br ^bb30
    ^bb32:
    %463 = llvm.load %246 : !llvm.ptr -> i64
    %464 = arith.remsi %463, %arg2 : i64
    llvm.store %464, %246 : i64, !llvm.ptr
    %465 = llvm.load %246 : !llvm.ptr -> i64
    %466 = arith.constant 0 : i32
    %468 = arith.extsi %466 : i32 to i64
    %467 = arith.cmpi slt, %465, %468 : i64
    cf.cond_br %467, ^bb63, ^bb64
    ^bb63:
      %469 = llvm.load %246 : !llvm.ptr -> i64
      %470 = arith.addi %469, %arg2 : i64
      llvm.store %470, %246 : i64, !llvm.ptr
      cf.br ^bb65
    ^bb64:
      cf.br ^bb65
    ^bb65:
    func.call @free(%172) : (!llvm.ptr) -> ()
    %472 = llvm.load %246 : !llvm.ptr -> i64
    func.return %472 : i64
  }
  func.func @perm_hash(%arg0: i64) -> i64 {
    %473 = arith.constant 16 : i32
    %475 = arith.extsi %473 : i32 to i64
    %474 = arith.shrsi %arg0, %475 : i64
    %476 = arith.xori %arg0, %474 : i64
    %477 = arith.constant -1640531535 : i32
    %479 = arith.extsi %477 : i32 to i64
    %478 = arith.muli %476, %479 : i64
    %480 = arith.constant 16 : i32
    %482 = arith.extsi %480 : i32 to i64
    %481 = arith.shrsi %478, %482 : i64
    %483 = arith.xori %478, %481 : i64
    %484 = llvm.mlir.addressof @PERM_CACHE_MASK : !llvm.ptr
    %485 = llvm.load %484 : !llvm.ptr -> i64
    %486 = arith.andi %483, %485 : i64
    func.return %486 : i64
  }
  func.func @perm_cache_lookup(%arg0: i64, %arg1: !llvm.ptr) -> i32 {
    %487 = func.call @perm_hash(%arg0) : (i64) -> i64
    %488 = llvm.mlir.constant(1 : i64) : i64
    %489 = llvm.alloca %488 x i64 : (i64) -> !llvm.ptr
    llvm.store %487, %489 : i64, !llvm.ptr
    cf.br ^bb66
    ^bb66:
    %491 = llvm.mlir.addressof @g_perm_used : !llvm.ptr
    %492 = llvm.load %491 : !llvm.ptr -> !llvm.ptr
    %493 = llvm.load %489 : !llvm.ptr -> i64
    %494 = llvm.getelementptr %492[%493] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    %490 = llvm.load %494 : !llvm.ptr -> i8
    %495 = arith.constant 0 : i32
    %497 = arith.extsi %490 : i8 to i32
    %496 = arith.cmpi ne, %497, %495 : i32
    cf.cond_br %496, ^bb67, ^bb68
    ^bb67:
      %499 = llvm.mlir.addressof @g_perm_key : !llvm.ptr
      %500 = llvm.load %499 : !llvm.ptr -> !llvm.ptr
      %501 = llvm.load %489 : !llvm.ptr -> i64
      %502 = llvm.getelementptr %500[%501] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %498 = llvm.load %502 : !llvm.ptr -> i64
      %503 = arith.cmpi eq, %498, %arg0 : i64
      cf.cond_br %503, ^bb69, ^bb70
      ^bb69:
        %505 = llvm.mlir.addressof @g_perm_val : !llvm.ptr
        %506 = llvm.load %505 : !llvm.ptr -> !llvm.ptr
        %507 = llvm.load %489 : !llvm.ptr -> i64
        %508 = llvm.getelementptr %506[%507] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %504 = llvm.load %508 : !llvm.ptr -> i64
        %509 = arith.constant 0 : i32
        %510 = arith.extsi %509 : i32 to i64
        %511 = llvm.getelementptr %arg1[%510] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %504, %511 : i64, !llvm.ptr
        %512 = arith.constant 1 : i32
        func.return %512 : i32
      ^bb70:
        cf.br ^bb71
      ^bb71:
      %513 = llvm.load %489 : !llvm.ptr -> i64
      %514 = arith.constant 1 : i32
      %516 = arith.extsi %514 : i32 to i64
      %515 = arith.addi %513, %516 : i64
      %517 = llvm.mlir.addressof @PERM_CACHE_MASK : !llvm.ptr
      %518 = llvm.load %517 : !llvm.ptr -> i64
      %519 = arith.andi %515, %518 : i64
      llvm.store %519, %489 : i64, !llvm.ptr
      cf.br ^bb66
    ^bb68:
    %520 = arith.constant 0 : i32
    func.return %520 : i32
  }
  func.func @perm_cache_insert(%arg0: i64, %arg1: i64) -> () {
    %521 = func.call @perm_hash(%arg0) : (i64) -> i64
    %522 = llvm.mlir.constant(1 : i64) : i64
    %523 = llvm.alloca %522 x i64 : (i64) -> !llvm.ptr
    llvm.store %521, %523 : i64, !llvm.ptr
    cf.br ^bb72
    ^bb72:
    %525 = llvm.mlir.addressof @g_perm_used : !llvm.ptr
    %526 = llvm.load %525 : !llvm.ptr -> !llvm.ptr
    %527 = llvm.load %523 : !llvm.ptr -> i64
    %528 = llvm.getelementptr %526[%527] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    %524 = llvm.load %528 : !llvm.ptr -> i8
    %529 = arith.constant 0 : i32
    %531 = arith.extsi %524 : i8 to i32
    %530 = arith.cmpi ne, %531, %529 : i32
    cf.cond_br %530, ^bb73, ^bb74
    ^bb73:
      %533 = llvm.mlir.addressof @g_perm_key : !llvm.ptr
      %534 = llvm.load %533 : !llvm.ptr -> !llvm.ptr
      %535 = llvm.load %523 : !llvm.ptr -> i64
      %536 = llvm.getelementptr %534[%535] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %532 = llvm.load %536 : !llvm.ptr -> i64
      %537 = arith.cmpi eq, %532, %arg0 : i64
      cf.cond_br %537, ^bb75, ^bb76
      ^bb75:
        %538 = llvm.mlir.addressof @g_perm_val : !llvm.ptr
        %539 = llvm.load %538 : !llvm.ptr -> !llvm.ptr
        %540 = llvm.load %523 : !llvm.ptr -> i64
        %541 = llvm.getelementptr %539[%540] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %arg1, %541 : i64, !llvm.ptr
        func.return
      ^bb76:
        cf.br ^bb77
      ^bb77:
      %542 = llvm.load %523 : !llvm.ptr -> i64
      %543 = arith.constant 1 : i32
      %545 = arith.extsi %543 : i32 to i64
      %544 = arith.addi %542, %545 : i64
      %546 = llvm.mlir.addressof @PERM_CACHE_MASK : !llvm.ptr
      %547 = llvm.load %546 : !llvm.ptr -> i64
      %548 = arith.andi %544, %547 : i64
      llvm.store %548, %523 : i64, !llvm.ptr
      cf.br ^bb72
    ^bb74:
    %549 = arith.constant 1 : i32
    %550 = llvm.mlir.addressof @g_perm_used : !llvm.ptr
    %551 = llvm.load %550 : !llvm.ptr -> !llvm.ptr
    %552 = llvm.load %523 : !llvm.ptr -> i64
    %553 = arith.trunci %549 : i32 to i8
    %554 = llvm.getelementptr %551[%552] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %553, %554 : i8, !llvm.ptr
    %555 = llvm.mlir.addressof @g_perm_key : !llvm.ptr
    %556 = llvm.load %555 : !llvm.ptr -> !llvm.ptr
    %557 = llvm.load %523 : !llvm.ptr -> i64
    %558 = llvm.getelementptr %556[%557] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %arg0, %558 : i64, !llvm.ptr
    %559 = llvm.mlir.addressof @g_perm_val : !llvm.ptr
    %560 = llvm.load %559 : !llvm.ptr -> !llvm.ptr
    %561 = llvm.load %523 : !llvm.ptr -> i64
    %562 = llvm.getelementptr %560[%561] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %arg1, %562 : i64, !llvm.ptr
    func.return
  }
  func.func @rec_perm(%arg0: i32, %arg1: i32, %arg2: i64) -> () {
    %563 = llvm.mlir.addressof @g_active_count : !llvm.ptr
    %564 = llvm.load %563 : !llvm.ptr -> i32
    %565 = arith.cmpi eq, %arg0, %564 : i32
    cf.cond_br %565, ^bb78, ^bb79
    ^bb78:
      %566 = llvm.mlir.constant(1 : i64) : i64
      %567 = llvm.alloca %566 x i64 : (i64) -> !llvm.ptr
      llvm.store %arg2, %567 : i64, !llvm.ptr
      %568 = arith.constant 0 : i32
      %569 = llvm.mlir.constant(1 : i64) : i64
      %570 = llvm.alloca %569 x i32 : (i64) -> !llvm.ptr
      llvm.store %568, %570 : i32, !llvm.ptr
      cf.br ^bb81
      ^bb81:
      %571 = llvm.load %570 : !llvm.ptr -> i32
      %572 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
      %573 = llvm.load %572 : !llvm.ptr -> i32
      %574 = arith.cmpi slt, %571, %573 : i32
      cf.cond_br %574, ^bb82, ^bb83
      ^bb82:
        %576 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
        %577 = llvm.load %576 : !llvm.ptr -> !llvm.ptr
        %578 = llvm.load %570 : !llvm.ptr -> i32
        %579 = arith.extsi %578 : i32 to i64
        %580 = llvm.getelementptr %577[%579] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %575 = llvm.load %580 : !llvm.ptr -> i32
        %581 = arith.constant 0 : i32
        %582 = arith.cmpi eq, %575, %581 : i32
        cf.cond_br %582, ^bb84, ^bb85
        ^bb84:
          func.return
        ^bb85:
          cf.br ^bb86
        ^bb86:
        %584 = llvm.load %567 : !llvm.ptr -> i64
        %587 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
        %588 = llvm.load %587 : !llvm.ptr -> !llvm.ptr
        %589 = llvm.load %570 : !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.extsi %586 : i32 to i64
        %594 = llvm.mlir.addressof @g_row_counts_arr : !llvm.ptr
        %595 = llvm.load %594 : !llvm.ptr -> !llvm.ptr
        %596 = llvm.load %570 : !llvm.ptr -> i32
        %597 = arith.extsi %596 : i32 to i64
        %598 = llvm.getelementptr %595[%597] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %593 = llvm.load %598 : !llvm.ptr -> i32
        %599 = arith.extsi %593 : i32 to i64
        %600 = llvm.mlir.addressof @MOD : !llvm.ptr
        %601 = llvm.load %600 : !llvm.ptr -> i64
        %585 = func.call @powmod(%592, %599, %601) : (i64, i64, i64) -> i64
        %602 = llvm.mlir.addressof @MOD : !llvm.ptr
        %603 = llvm.load %602 : !llvm.ptr -> i64
        %583 = func.call @mulmod(%584, %585, %603) : (i64, i64, i64) -> i64
        llvm.store %583, %567 : i64, !llvm.ptr
        %604 = llvm.load %570 : !llvm.ptr -> i32
        %605 = arith.constant 1 : i32
        %606 = arith.addi %604, %605 : i32
        llvm.store %606, %570 : i32, !llvm.ptr
        cf.br ^bb81
      ^bb83:
      %607 = arith.constant 1 : i32
      %608 = arith.andi %arg1, %607 : i32
      %609 = arith.constant 1 : i32
      %610 = arith.cmpi eq, %608, %609 : i32
      cf.cond_br %610, ^bb87, ^bb88
      ^bb87:
        %611 = llvm.mlir.addressof @g_total : !llvm.ptr
        %612 = llvm.load %611 : !llvm.ptr -> i64
        %613 = llvm.load %567 : !llvm.ptr -> i64
        %614 = arith.subi %612, %613 : i64
        %615 = llvm.mlir.addressof @g_total : !llvm.ptr
        llvm.store %614, %615 : i64, !llvm.ptr
        cf.br ^bb89
      ^bb88:
        %616 = llvm.mlir.addressof @g_total : !llvm.ptr
        %617 = llvm.load %616 : !llvm.ptr -> i64
        %618 = llvm.load %567 : !llvm.ptr -> i64
        %619 = arith.addi %617, %618 : i64
        %620 = llvm.mlir.addressof @g_total : !llvm.ptr
        llvm.store %619, %620 : i64, !llvm.ptr
        cf.br ^bb89
      ^bb89:
      func.return
    ^bb79:
      cf.br ^bb80
    ^bb80:
    %622 = llvm.mlir.addressof @g_active_col_counts : !llvm.ptr
    %623 = llvm.load %622 : !llvm.ptr -> !llvm.ptr
    %624 = arith.extsi %arg0 : i32 to i64
    %625 = llvm.getelementptr %623[%624] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    %621 = llvm.load %625 : !llvm.ptr -> i32
    %626 = arith.constant 256 : i32
    %627 = arith.muli %arg0, %626 : i32
    %628 = arith.constant 0 : i32
    %629 = llvm.mlir.constant(1 : i64) : i64
    %630 = llvm.alloca %629 x i32 : (i64) -> !llvm.ptr
    llvm.store %628, %630 : i32, !llvm.ptr
    %631 = arith.constant 0 : i32
    %632 = llvm.mlir.constant(1 : i64) : i64
    %633 = llvm.alloca %632 x i32 : (i64) -> !llvm.ptr
    llvm.store %631, %633 : i32, !llvm.ptr
    cf.br ^bb90
    ^bb90:
    %634 = llvm.load %633 : !llvm.ptr -> i32
    %635 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
    %636 = llvm.load %635 : !llvm.ptr -> i32
    %637 = arith.cmpi slt, %634, %636 : i32
    cf.cond_br %637, ^bb91, ^bb92
    ^bb91:
      %639 = llvm.mlir.addressof @g_supports : !llvm.ptr
      %640 = llvm.load %639 : !llvm.ptr -> !llvm.ptr
      %641 = llvm.load %633 : !llvm.ptr -> i32
      %642 = arith.extsi %641 : i32 to i64
      %643 = llvm.getelementptr %640[%642] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %638 = llvm.load %643 : !llvm.ptr -> i32
      %644 = arith.shrsi %638, %arg0 : i32
      %645 = arith.constant 1 : i32
      %646 = arith.andi %644, %645 : i32
      %647 = arith.constant 1 : i32
      %648 = arith.cmpi eq, %646, %647 : i32
      cf.cond_br %648, ^bb93, ^bb94
      ^bb93:
        %649 = llvm.load %633 : !llvm.ptr -> i32
        %650 = llvm.mlir.addressof @g_affected : !llvm.ptr
        %651 = llvm.load %650 : !llvm.ptr -> !llvm.ptr
        %652 = llvm.load %630 : !llvm.ptr -> i32
        %653 = arith.addi %627, %652 : i32
        %654 = arith.extsi %653 : i32 to i64
        %655 = llvm.getelementptr %651[%654] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %649, %655 : i32, !llvm.ptr
        %656 = llvm.load %630 : !llvm.ptr -> i32
        %657 = arith.constant 1 : i32
        %658 = arith.addi %656, %657 : i32
        llvm.store %658, %630 : i32, !llvm.ptr
        cf.br ^bb95
      ^bb94:
        cf.br ^bb95
      ^bb95:
      %659 = llvm.load %633 : !llvm.ptr -> i32
      %660 = arith.constant 1 : i32
      %661 = arith.addi %659, %660 : i32
      llvm.store %661, %633 : i32, !llvm.ptr
      cf.br ^bb90
    ^bb92:
    %662 = llvm.load %630 : !llvm.ptr -> i32
    %663 = llvm.mlir.addressof @g_n_affected : !llvm.ptr
    %664 = llvm.load %663 : !llvm.ptr -> !llvm.ptr
    %665 = arith.extsi %arg0 : i32 to i64
    %666 = llvm.getelementptr %664[%665] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %662, %666 : i32, !llvm.ptr
    %667 = arith.constant 0 : i32
    %668 = llvm.mlir.constant(1 : i64) : i64
    %669 = llvm.alloca %668 x i32 : (i64) -> !llvm.ptr
    llvm.store %667, %669 : i32, !llvm.ptr
    cf.br ^bb96
    ^bb96:
    %670 = llvm.load %669 : !llvm.ptr -> i32
    %671 = arith.cmpi sle, %670, %621 : i32
    cf.cond_br %671, ^bb97, ^bb98
    ^bb97:
      %672 = llvm.load %669 : !llvm.ptr -> i32
      %673 = arith.constant 0 : i32
      %674 = arith.cmpi sgt, %672, %673 : i32
      cf.cond_br %674, ^bb99, ^bb100
      ^bb99:
        %675 = arith.constant 0 : i32
        %676 = llvm.mlir.constant(1 : i64) : i64
        %677 = llvm.alloca %676 x i32 : (i64) -> !llvm.ptr
        llvm.store %675, %677 : i32, !llvm.ptr
        cf.br ^bb102
        ^bb102:
        %678 = llvm.load %677 : !llvm.ptr -> i32
        %679 = llvm.load %630 : !llvm.ptr -> i32
        %680 = arith.cmpi slt, %678, %679 : i32
        cf.cond_br %680, ^bb103, ^bb104
        ^bb103:
          %682 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
          %683 = llvm.load %682 : !llvm.ptr -> !llvm.ptr
          %685 = llvm.mlir.addressof @g_affected : !llvm.ptr
          %686 = llvm.load %685 : !llvm.ptr -> !llvm.ptr
          %687 = llvm.load %677 : !llvm.ptr -> i32
          %688 = arith.addi %627, %687 : i32
          %689 = arith.extsi %688 : i32 to i64
          %690 = llvm.getelementptr %686[%689] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %684 = llvm.load %690 : !llvm.ptr -> i32
          %691 = arith.extsi %684 : i32 to i64
          %692 = llvm.getelementptr %683[%691] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %681 = llvm.load %692 : !llvm.ptr -> i32
          %693 = llvm.load %669 : !llvm.ptr -> i32
          %694 = arith.addi %681, %693 : i32
          %695 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
          %696 = llvm.load %695 : !llvm.ptr -> !llvm.ptr
          %698 = llvm.mlir.addressof @g_affected : !llvm.ptr
          %699 = llvm.load %698 : !llvm.ptr -> !llvm.ptr
          %700 = llvm.load %677 : !llvm.ptr -> i32
          %701 = arith.addi %627, %700 : i32
          %702 = arith.extsi %701 : i32 to i64
          %703 = llvm.getelementptr %699[%702] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %697 = llvm.load %703 : !llvm.ptr -> i32
          %704 = arith.extsi %697 : i32 to i64
          %705 = llvm.getelementptr %696[%704] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %694, %705 : i32, !llvm.ptr
          %706 = llvm.load %677 : !llvm.ptr -> i32
          %707 = arith.constant 1 : i32
          %708 = arith.addi %706, %707 : i32
          llvm.store %708, %677 : i32, !llvm.ptr
          cf.br ^bb102
        ^bb104:
        cf.br ^bb101
      ^bb100:
        cf.br ^bb101
      ^bb101:
      %710 = arith.constant 1 : i32
      %711 = arith.addi %arg0, %710 : i32
      %712 = llvm.load %669 : !llvm.ptr -> i32
      %713 = arith.addi %arg1, %712 : i32
      %716 = llvm.mlir.addressof @g_comb : !llvm.ptr
      %717 = llvm.load %716 : !llvm.ptr -> !llvm.ptr
      %718 = llvm.mlir.addressof @MAXN : !llvm.ptr
      %719 = llvm.load %718 : !llvm.ptr -> i32
      %720 = arith.constant 1 : i32
      %721 = arith.addi %719, %720 : i32
      %722 = arith.muli %621, %721 : i32
      %723 = llvm.load %669 : !llvm.ptr -> i32
      %724 = arith.addi %722, %723 : i32
      %725 = arith.extsi %724 : i32 to i64
      %726 = llvm.getelementptr %717[%725] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %715 = llvm.load %726 : !llvm.ptr -> i64
      %727 = llvm.mlir.addressof @MOD : !llvm.ptr
      %728 = llvm.load %727 : !llvm.ptr -> i64
      %729 = arith.remsi %715, %728 : i64
      %730 = llvm.mlir.addressof @MOD : !llvm.ptr
      %731 = llvm.load %730 : !llvm.ptr -> i64
      %714 = func.call @mulmod(%arg2, %729, %731) : (i64, i64, i64) -> i64
      func.call @rec_perm(%711, %713, %714) : (i32, i32, i64) -> ()
      %732 = llvm.load %669 : !llvm.ptr -> i32
      %733 = arith.constant 0 : i32
      %734 = arith.cmpi sgt, %732, %733 : i32
      cf.cond_br %734, ^bb105, ^bb106
      ^bb105:
        %735 = arith.constant 0 : i32
        %736 = llvm.mlir.constant(1 : i64) : i64
        %737 = llvm.alloca %736 x i32 : (i64) -> !llvm.ptr
        llvm.store %735, %737 : i32, !llvm.ptr
        cf.br ^bb108
        ^bb108:
        %738 = llvm.load %737 : !llvm.ptr -> i32
        %739 = llvm.load %630 : !llvm.ptr -> i32
        %740 = arith.cmpi slt, %738, %739 : i32
        cf.cond_br %740, ^bb109, ^bb110
        ^bb109:
          %742 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
          %743 = llvm.load %742 : !llvm.ptr -> !llvm.ptr
          %745 = llvm.mlir.addressof @g_affected : !llvm.ptr
          %746 = llvm.load %745 : !llvm.ptr -> !llvm.ptr
          %747 = llvm.load %737 : !llvm.ptr -> i32
          %748 = arith.addi %627, %747 : i32
          %749 = arith.extsi %748 : i32 to i64
          %750 = llvm.getelementptr %746[%749] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %744 = llvm.load %750 : !llvm.ptr -> i32
          %751 = arith.extsi %744 : i32 to i64
          %752 = llvm.getelementptr %743[%751] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %741 = llvm.load %752 : !llvm.ptr -> i32
          %753 = llvm.load %669 : !llvm.ptr -> i32
          %754 = arith.subi %741, %753 : i32
          %755 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
          %756 = llvm.load %755 : !llvm.ptr -> !llvm.ptr
          %758 = llvm.mlir.addressof @g_affected : !llvm.ptr
          %759 = llvm.load %758 : !llvm.ptr -> !llvm.ptr
          %760 = llvm.load %737 : !llvm.ptr -> i32
          %761 = arith.addi %627, %760 : i32
          %762 = arith.extsi %761 : i32 to i64
          %763 = llvm.getelementptr %759[%762] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %757 = llvm.load %763 : !llvm.ptr -> i32
          %764 = arith.extsi %757 : i32 to i64
          %765 = llvm.getelementptr %756[%764] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %754, %765 : i32, !llvm.ptr
          %766 = llvm.load %737 : !llvm.ptr -> i32
          %767 = arith.constant 1 : i32
          %768 = arith.addi %766, %767 : i32
          llvm.store %768, %737 : i32, !llvm.ptr
          cf.br ^bb108
        ^bb110:
        cf.br ^bb107
      ^bb106:
        cf.br ^bb107
      ^bb107:
      %769 = llvm.load %669 : !llvm.ptr -> i32
      %770 = arith.constant 1 : i32
      %771 = arith.addi %769, %770 : i32
      llvm.store %771, %669 : i32, !llvm.ptr
      cf.br ^bb96
    ^bb98:
    func.return
  }
  func.func @grouped_permanent(%arg0: i32, %arg1: i32) -> i64 {
    %772 = arith.extsi %arg0 : i32 to i64
    %773 = arith.constant 20 : i32
    %775 = arith.extsi %773 : i32 to i64
    %774 = arith.shli %772, %775 : i64
    %776 = arith.extsi %arg1 : i32 to i64
    %777 = arith.ori %774, %776 : i64
    %779 = arith.constant 1 : i32
    %780 = arith.constant 8 : i32
    %781 = arith.extsi %779 : i32 to i64
    %782 = arith.extsi %780 : i32 to i64
    %778 = func.call @calloc(%781, %782) : (i64, i64) -> !llvm.ptr
    %783 = func.call @perm_cache_lookup(%777, %778) : (i64, !llvm.ptr) -> i32
    %784 = arith.constant 1 : i32
    %785 = arith.cmpi eq, %783, %784 : i32
    cf.cond_br %785, ^bb111, ^bb112
    ^bb111:
      %787 = arith.constant 0 : i32
      %788 = arith.extsi %787 : i32 to i64
      %789 = llvm.getelementptr %778[%788] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %786 = llvm.load %789 : !llvm.ptr -> i64
      func.call @free(%778) : (!llvm.ptr) -> ()
      func.return %786 : i64
    ^bb112:
      cf.br ^bb113
    ^bb113:
    func.call @free(%778) : (!llvm.ptr) -> ()
    %792 = arith.constant 0 : i32
    %793 = llvm.mlir.addressof @g_active_count : !llvm.ptr
    llvm.store %792, %793 : i32, !llvm.ptr
    %794 = arith.constant 0 : i32
    %795 = llvm.mlir.constant(1 : i64) : i64
    %796 = llvm.alloca %795 x i32 : (i64) -> !llvm.ptr
    llvm.store %794, %796 : i32, !llvm.ptr
    cf.br ^bb114
    ^bb114:
    %797 = llvm.load %796 : !llvm.ptr -> i32
    %798 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
    %799 = llvm.load %798 : !llvm.ptr -> i32
    %800 = arith.cmpi slt, %797, %799 : i32
    cf.cond_br %800, ^bb115, ^bb116
    ^bb115:
      %802 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
      %803 = llvm.load %802 : !llvm.ptr -> !llvm.ptr
      %804 = llvm.load %796 : !llvm.ptr -> i32
      %805 = arith.extsi %804 : i32 to i64
      %806 = llvm.getelementptr %803[%805] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %801 = llvm.load %806 : !llvm.ptr -> i32
      %807 = llvm.load %796 : !llvm.ptr -> i32
      %808 = arith.shrsi %arg1, %807 : i32
      %809 = arith.constant 1 : i32
      %810 = arith.andi %808, %809 : i32
      %811 = arith.subi %801, %810 : i32
      %812 = arith.constant 0 : i32
      %813 = arith.cmpi sgt, %811, %812 : i32
      cf.cond_br %813, ^bb117, ^bb118
      ^bb117:
        %814 = llvm.load %796 : !llvm.ptr -> i32
        %815 = llvm.mlir.addressof @g_active_col_classes : !llvm.ptr
        %816 = llvm.load %815 : !llvm.ptr -> !llvm.ptr
        %817 = llvm.mlir.addressof @g_active_count : !llvm.ptr
        %818 = llvm.load %817 : !llvm.ptr -> i32
        %819 = arith.extsi %818 : i32 to i64
        %820 = llvm.getelementptr %816[%819] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %814, %820 : i32, !llvm.ptr
        %821 = llvm.mlir.addressof @g_active_col_counts : !llvm.ptr
        %822 = llvm.load %821 : !llvm.ptr -> !llvm.ptr
        %823 = llvm.mlir.addressof @g_active_count : !llvm.ptr
        %824 = llvm.load %823 : !llvm.ptr -> i32
        %825 = arith.extsi %824 : i32 to i64
        %826 = llvm.getelementptr %822[%825] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %811, %826 : i32, !llvm.ptr
        %827 = llvm.mlir.addressof @g_active_count : !llvm.ptr
        %828 = llvm.load %827 : !llvm.ptr -> i32
        %829 = arith.constant 1 : i32
        %830 = arith.addi %828, %829 : i32
        %831 = llvm.mlir.addressof @g_active_count : !llvm.ptr
        llvm.store %830, %831 : i32, !llvm.ptr
        cf.br ^bb119
      ^bb118:
        cf.br ^bb119
      ^bb119:
      %832 = llvm.load %796 : !llvm.ptr -> i32
      %833 = arith.constant 1 : i32
      %834 = arith.addi %832, %833 : i32
      llvm.store %834, %796 : i32, !llvm.ptr
      cf.br ^bb114
    ^bb116:
    %836 = arith.constant 256 : i32
    %837 = arith.constant 4 : i32
    %838 = arith.extsi %836 : i32 to i64
    %839 = arith.extsi %837 : i32 to i64
    %835 = func.call @calloc(%838, %839) : (i64, i64) -> !llvm.ptr
    %840 = arith.constant 1 : i32
    %841 = arith.constant 1 : i32
    %842 = llvm.mlir.addressof @g_active_count : !llvm.ptr
    %843 = llvm.load %842 : !llvm.ptr -> i32
    %844 = arith.shli %841, %843 : i32
    %845 = arith.constant 1 : i32
    %846 = arith.subi %844, %845 : i32
    %847 = arith.extsi %846 : i32 to i64
    %848 = llvm.getelementptr %835[%847] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %840, %848 : i32, !llvm.ptr
    %849 = arith.constant 0 : i32
    %850 = llvm.mlir.constant(1 : i64) : i64
    %851 = llvm.alloca %850 x i32 : (i64) -> !llvm.ptr
    llvm.store %849, %851 : i32, !llvm.ptr
    cf.br ^bb120
    ^bb120:
    %852 = llvm.load %851 : !llvm.ptr -> i32
    %853 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
    %854 = llvm.load %853 : !llvm.ptr -> i32
    %855 = arith.cmpi slt, %852, %854 : i32
    cf.cond_br %855, ^bb121, ^bb122
    ^bb121:
      %857 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
      %858 = llvm.load %857 : !llvm.ptr -> !llvm.ptr
      %859 = llvm.load %851 : !llvm.ptr -> i32
      %860 = arith.extsi %859 : i32 to i64
      %861 = llvm.getelementptr %858[%860] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %856 = llvm.load %861 : !llvm.ptr -> i32
      %862 = llvm.load %851 : !llvm.ptr -> i32
      %863 = arith.shrsi %arg0, %862 : i32
      %864 = arith.constant 1 : i32
      %865 = arith.andi %863, %864 : i32
      %866 = arith.subi %856, %865 : i32
      %867 = arith.constant 0 : i32
      %868 = arith.cmpi sgt, %866, %867 : i32
      cf.cond_br %868, ^bb123, ^bb124
      ^bb123:
        %869 = arith.constant 0 : i32
        %870 = llvm.mlir.constant(1 : i64) : i64
        %871 = llvm.alloca %870 x i32 : (i64) -> !llvm.ptr
        llvm.store %869, %871 : i32, !llvm.ptr
        %873 = llvm.mlir.addressof @g_row_supports : !llvm.ptr
        %874 = llvm.load %873 : !llvm.ptr -> !llvm.ptr
        %875 = llvm.load %851 : !llvm.ptr -> i32
        %876 = arith.extsi %875 : i32 to i64
        %877 = llvm.getelementptr %874[%876] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %872 = llvm.load %877 : !llvm.ptr -> i32
        %878 = arith.constant 0 : i32
        %879 = llvm.mlir.constant(1 : i64) : i64
        %880 = llvm.alloca %879 x i32 : (i64) -> !llvm.ptr
        llvm.store %878, %880 : i32, !llvm.ptr
        cf.br ^bb126
        ^bb126:
        %881 = llvm.load %880 : !llvm.ptr -> i32
        %882 = llvm.mlir.addressof @g_active_count : !llvm.ptr
        %883 = llvm.load %882 : !llvm.ptr -> i32
        %884 = arith.cmpi slt, %881, %883 : i32
        cf.cond_br %884, ^bb127, ^bb128
        ^bb127:
          %886 = llvm.mlir.addressof @g_active_col_classes : !llvm.ptr
          %887 = llvm.load %886 : !llvm.ptr -> !llvm.ptr
          %888 = llvm.load %880 : !llvm.ptr -> i32
          %889 = arith.extsi %888 : i32 to i64
          %890 = llvm.getelementptr %887[%889] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %885 = llvm.load %890 : !llvm.ptr -> i32
          %891 = arith.shrsi %872, %885 : i32
          %892 = arith.constant 1 : i32
          %893 = arith.andi %891, %892 : i32
          %894 = arith.constant 1 : i32
          %895 = arith.cmpi eq, %893, %894 : i32
          cf.cond_br %895, ^bb129, ^bb130
          ^bb129:
            %896 = llvm.load %871 : !llvm.ptr -> i32
            %897 = arith.constant 1 : i32
            %898 = llvm.load %880 : !llvm.ptr -> i32
            %899 = arith.shli %897, %898 : i32
            %900 = arith.ori %896, %899 : i32
            llvm.store %900, %871 : i32, !llvm.ptr
            cf.br ^bb131
          ^bb130:
            cf.br ^bb131
          ^bb131:
          %901 = llvm.load %880 : !llvm.ptr -> i32
          %902 = arith.constant 1 : i32
          %903 = arith.addi %901, %902 : i32
          llvm.store %903, %880 : i32, !llvm.ptr
          cf.br ^bb126
        ^bb128:
        %905 = llvm.load %871 : !llvm.ptr -> i32
        %906 = arith.extsi %905 : i32 to i64
        %907 = llvm.getelementptr %835[%906] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %904 = llvm.load %907 : !llvm.ptr -> i32
        %908 = arith.addi %904, %866 : i32
        %909 = llvm.load %871 : !llvm.ptr -> i32
        %910 = arith.extsi %909 : i32 to i64
        %911 = llvm.getelementptr %835[%910] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %908, %911 : i32, !llvm.ptr
        cf.br ^bb125
      ^bb124:
        cf.br ^bb125
      ^bb125:
      %912 = llvm.load %851 : !llvm.ptr -> i32
      %913 = arith.constant 1 : i32
      %914 = arith.addi %912, %913 : i32
      llvm.store %914, %851 : i32, !llvm.ptr
      cf.br ^bb120
    ^bb122:
    %915 = arith.constant 0 : i32
    %916 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
    llvm.store %915, %916 : i32, !llvm.ptr
    %917 = arith.constant 0 : i32
    %918 = llvm.mlir.addressof @g_row_total : !llvm.ptr
    llvm.store %917, %918 : i32, !llvm.ptr
    %919 = arith.constant 0 : i32
    %920 = llvm.mlir.constant(1 : i64) : i64
    %921 = llvm.alloca %920 x i32 : (i64) -> !llvm.ptr
    llvm.store %919, %921 : i32, !llvm.ptr
    cf.br ^bb132
    ^bb132:
    %922 = llvm.load %921 : !llvm.ptr -> i32
    %923 = arith.constant 256 : i32
    %924 = arith.cmpi slt, %922, %923 : i32
    cf.cond_br %924, ^bb133, ^bb134
    ^bb133:
      %926 = llvm.load %921 : !llvm.ptr -> i32
      %927 = arith.extsi %926 : i32 to i64
      %928 = llvm.getelementptr %835[%927] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %925 = llvm.load %928 : !llvm.ptr -> i32
      %929 = arith.constant 0 : i32
      %930 = arith.cmpi sgt, %925, %929 : i32
      cf.cond_br %930, ^bb135, ^bb136
      ^bb135:
        %931 = llvm.load %921 : !llvm.ptr -> i32
        %932 = llvm.mlir.addressof @g_supports : !llvm.ptr
        %933 = llvm.load %932 : !llvm.ptr -> !llvm.ptr
        %934 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
        %935 = llvm.load %934 : !llvm.ptr -> i32
        %936 = arith.extsi %935 : i32 to i64
        %937 = llvm.getelementptr %933[%936] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %931, %937 : i32, !llvm.ptr
        %939 = llvm.load %921 : !llvm.ptr -> i32
        %940 = arith.extsi %939 : i32 to i64
        %941 = llvm.getelementptr %835[%940] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %938 = llvm.load %941 : !llvm.ptr -> i32
        %942 = llvm.mlir.addressof @g_row_counts_arr : !llvm.ptr
        %943 = llvm.load %942 : !llvm.ptr -> !llvm.ptr
        %944 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
        %945 = llvm.load %944 : !llvm.ptr -> i32
        %946 = arith.extsi %945 : i32 to i64
        %947 = llvm.getelementptr %943[%946] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %938, %947 : i32, !llvm.ptr
        %948 = arith.constant 0 : i32
        %949 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
        %950 = llvm.load %949 : !llvm.ptr -> !llvm.ptr
        %951 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
        %952 = llvm.load %951 : !llvm.ptr -> i32
        %953 = arith.extsi %952 : i32 to i64
        %954 = llvm.getelementptr %950[%953] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %948, %954 : i32, !llvm.ptr
        %955 = llvm.mlir.addressof @g_row_total : !llvm.ptr
        %956 = llvm.load %955 : !llvm.ptr -> i32
        %958 = llvm.load %921 : !llvm.ptr -> i32
        %959 = arith.extsi %958 : i32 to i64
        %960 = llvm.getelementptr %835[%959] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %957 = llvm.load %960 : !llvm.ptr -> i32
        %961 = arith.addi %956, %957 : i32
        %962 = llvm.mlir.addressof @g_row_total : !llvm.ptr
        llvm.store %961, %962 : i32, !llvm.ptr
        %963 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
        %964 = llvm.load %963 : !llvm.ptr -> i32
        %965 = arith.constant 1 : i32
        %966 = arith.addi %964, %965 : i32
        %967 = llvm.mlir.addressof @g_num_supports : !llvm.ptr
        llvm.store %966, %967 : i32, !llvm.ptr
        cf.br ^bb137
      ^bb136:
        cf.br ^bb137
      ^bb137:
      %968 = llvm.load %921 : !llvm.ptr -> i32
      %969 = arith.constant 1 : i32
      %970 = arith.addi %968, %969 : i32
      llvm.store %970, %921 : i32, !llvm.ptr
      cf.br ^bb132
    ^bb134:
    %971 = arith.constant 0 : i32
    %972 = arith.extsi %971 : i32 to i64
    %973 = llvm.mlir.addressof @g_total : !llvm.ptr
    llvm.store %972, %973 : i64, !llvm.ptr
    %975 = arith.constant 0 : i32
    %976 = arith.constant 0 : i32
    %977 = arith.constant 1 : i32
    %978 = arith.extsi %977 : i32 to i64
    func.call @rec_perm(%975, %976, %978) : (i32, i32, i64) -> ()
    %979 = llvm.mlir.addressof @g_row_total : !llvm.ptr
    %980 = llvm.load %979 : !llvm.ptr -> i32
    %981 = arith.constant 1 : i32
    %982 = arith.andi %980, %981 : i32
    %983 = arith.constant 1 : i32
    %984 = arith.cmpi eq, %982, %983 : i32
    cf.cond_br %984, ^bb138, ^bb139
    ^bb138:
      %985 = arith.constant 0 : i32
      %986 = llvm.mlir.addressof @g_total : !llvm.ptr
      %987 = llvm.load %986 : !llvm.ptr -> i64
      %989 = arith.extsi %985 : i32 to i64
      %988 = arith.subi %989, %987 : i64
      %990 = llvm.mlir.addressof @g_total : !llvm.ptr
      llvm.store %988, %990 : i64, !llvm.ptr
      cf.br ^bb140
    ^bb139:
      cf.br ^bb140
    ^bb140:
    %991 = llvm.mlir.addressof @g_total : !llvm.ptr
    %992 = llvm.load %991 : !llvm.ptr -> i64
    %993 = llvm.mlir.addressof @MOD : !llvm.ptr
    %994 = llvm.load %993 : !llvm.ptr -> i64
    %995 = arith.remsi %992, %994 : i64
    %996 = llvm.mlir.addressof @g_total : !llvm.ptr
    llvm.store %995, %996 : i64, !llvm.ptr
    %997 = llvm.mlir.addressof @g_total : !llvm.ptr
    %998 = llvm.load %997 : !llvm.ptr -> i64
    %999 = arith.constant 0 : i32
    %1001 = arith.extsi %999 : i32 to i64
    %1000 = arith.cmpi slt, %998, %1001 : i64
    cf.cond_br %1000, ^bb141, ^bb142
    ^bb141:
      %1002 = llvm.mlir.addressof @g_total : !llvm.ptr
      %1003 = llvm.load %1002 : !llvm.ptr -> i64
      %1004 = llvm.mlir.addressof @MOD : !llvm.ptr
      %1005 = llvm.load %1004 : !llvm.ptr -> i64
      %1006 = arith.addi %1003, %1005 : i64
      %1007 = llvm.mlir.addressof @g_total : !llvm.ptr
      llvm.store %1006, %1007 : i64, !llvm.ptr
      cf.br ^bb143
    ^bb142:
      cf.br ^bb143
    ^bb143:
    %1009 = llvm.mlir.addressof @g_total : !llvm.ptr
    %1010 = llvm.load %1009 : !llvm.ptr -> i64
    func.call @perm_cache_insert(%777, %1010) : (i64, i64) -> ()
    func.call @free(%835) : (!llvm.ptr) -> ()
    %1012 = llvm.mlir.addressof @g_total : !llvm.ptr
    %1013 = llvm.load %1012 : !llvm.ptr -> i64
    func.return %1013 : i64
  }
  func.func @P_func(%arg0: i32, %arg1: i64) -> i64 {
    %1015 = llvm.mlir.addressof @g_perm_key : !llvm.ptr
    %1016 = llvm.load %1015 : !llvm.ptr -> !llvm.ptr
    %1017 = arith.constant 0 : i32
    %1018 = llvm.mlir.addressof @PERM_CACHE_CAP : !llvm.ptr
    %1019 = llvm.load %1018 : !llvm.ptr -> i64
    %1020 = arith.constant 8 : i32
    %1022 = arith.extsi %1020 : i32 to i64
    %1021 = arith.muli %1019, %1022 : i64
    %1014 = func.call @memset(%1016, %1017, %1021) : (!llvm.ptr, i32, i64) -> !llvm.ptr
    %1024 = llvm.mlir.addressof @g_perm_val : !llvm.ptr
    %1025 = llvm.load %1024 : !llvm.ptr -> !llvm.ptr
    %1026 = arith.constant 0 : i32
    %1027 = llvm.mlir.addressof @PERM_CACHE_CAP : !llvm.ptr
    %1028 = llvm.load %1027 : !llvm.ptr -> i64
    %1029 = arith.constant 8 : i32
    %1031 = arith.extsi %1029 : i32 to i64
    %1030 = arith.muli %1028, %1031 : i64
    %1023 = func.call @memset(%1025, %1026, %1030) : (!llvm.ptr, i32, i64) -> !llvm.ptr
    %1033 = llvm.mlir.addressof @g_perm_used : !llvm.ptr
    %1034 = llvm.load %1033 : !llvm.ptr -> !llvm.ptr
    %1035 = arith.constant 0 : i32
    %1036 = llvm.mlir.addressof @PERM_CACHE_CAP : !llvm.ptr
    %1037 = llvm.load %1036 : !llvm.ptr -> i64
    %1032 = func.call @memset(%1034, %1035, %1037) : (!llvm.ptr, i32, i64) -> !llvm.ptr
    %1038 = arith.constant 2 : i32
    %1039 = arith.cmpi slt, %arg0, %1038 : i32
    cf.cond_br %1039, ^bb144, ^bb145
    ^bb144:
      %1040 = arith.constant 0 : i32
      %1041 = arith.extsi %1040 : i32 to i64
      func.return %1041 : i64
    ^bb145:
      cf.br ^bb146
    ^bb146:
    %1042 = arith.constant 2 : i32
    %1043 = arith.divsi %arg0, %1042 : i32
    %1045 = arith.extsi %1043 : i32 to i64
    %1046 = arith.constant 4 : i32
    %1047 = arith.extsi %1046 : i32 to i64
    %1044 = func.call @calloc(%1045, %1047) : (i64, i64) -> !llvm.ptr
    %1049 = arith.extsi %1043 : i32 to i64
    %1050 = arith.constant 4 : i32
    %1051 = arith.extsi %1050 : i32 to i64
    %1048 = func.call @calloc(%1049, %1051) : (i64, i64) -> !llvm.ptr
    %1052 = arith.constant 0 : i32
    %1053 = llvm.mlir.constant(1 : i64) : i64
    %1054 = llvm.alloca %1053 x i32 : (i64) -> !llvm.ptr
    llvm.store %1052, %1054 : i32, !llvm.ptr
    cf.br ^bb147
    ^bb147:
    %1055 = llvm.load %1054 : !llvm.ptr -> i32
    %1056 = arith.cmpi slt, %1055, %1043 : i32
    cf.cond_br %1056, ^bb148, ^bb149
    ^bb148:
      %1057 = arith.constant 2 : i32
      %1058 = llvm.load %1054 : !llvm.ptr -> i32
      %1059 = arith.muli %1057, %1058 : i32
      %1060 = arith.constant 1 : i32
      %1061 = arith.addi %1059, %1060 : i32
      %1062 = llvm.load %1054 : !llvm.ptr -> i32
      %1063 = arith.extsi %1062 : i32 to i64
      %1064 = llvm.getelementptr %1044[%1063] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1061, %1064 : i32, !llvm.ptr
      %1065 = arith.constant 2 : i32
      %1066 = llvm.load %1054 : !llvm.ptr -> i32
      %1067 = arith.constant 1 : i32
      %1068 = arith.addi %1066, %1067 : i32
      %1069 = arith.muli %1065, %1068 : i32
      %1070 = llvm.load %1054 : !llvm.ptr -> i32
      %1071 = arith.extsi %1070 : i32 to i64
      %1072 = llvm.getelementptr %1048[%1071] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1069, %1072 : i32, !llvm.ptr
      %1073 = llvm.load %1054 : !llvm.ptr -> i32
      %1074 = arith.constant 1 : i32
      %1075 = arith.addi %1073, %1074 : i32
      llvm.store %1075, %1054 : i32, !llvm.ptr
      cf.br ^bb147
    ^bb149:
    %1077 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1078 = llvm.load %1077 : !llvm.ptr -> i32
    %1079 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1080 = llvm.load %1079 : !llvm.ptr -> i32
    %1081 = arith.muli %1078, %1080 : i32
    %1082 = arith.extsi %1081 : i32 to i64
    %1083 = arith.constant 4 : i32
    %1084 = arith.extsi %1083 : i32 to i64
    %1076 = func.call @calloc(%1082, %1084) : (i64, i64) -> !llvm.ptr
    %1085 = arith.constant 0 : i32
    %1086 = llvm.mlir.constant(1 : i64) : i64
    %1087 = llvm.alloca %1086 x i32 : (i64) -> !llvm.ptr
    llvm.store %1085, %1087 : i32, !llvm.ptr
    cf.br ^bb150
    ^bb150:
    %1088 = llvm.load %1087 : !llvm.ptr -> i32
    %1089 = arith.cmpi slt, %1088, %1043 : i32
    cf.cond_br %1089, ^bb151, ^bb152
    ^bb151:
      %1090 = arith.constant 0 : i32
      %1091 = llvm.mlir.constant(1 : i64) : i64
      %1092 = llvm.alloca %1091 x i32 : (i64) -> !llvm.ptr
      llvm.store %1090, %1092 : i32, !llvm.ptr
      cf.br ^bb153
      ^bb153:
      %1093 = llvm.load %1092 : !llvm.ptr -> i32
      %1094 = arith.cmpi slt, %1093, %1043 : i32
      cf.cond_br %1094, ^bb154, ^bb155
      ^bb154:
        %1097 = llvm.load %1087 : !llvm.ptr -> i32
        %1098 = arith.extsi %1097 : i32 to i64
        %1099 = llvm.getelementptr %1044[%1098] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1096 = llvm.load %1099 : !llvm.ptr -> i32
        %1100 = arith.extsi %1096 : i32 to i64
        %1102 = llvm.load %1092 : !llvm.ptr -> i32
        %1103 = arith.extsi %1102 : i32 to i64
        %1104 = llvm.getelementptr %1048[%1103] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1101 = llvm.load %1104 : !llvm.ptr -> i32
        %1105 = arith.extsi %1101 : i32 to i64
        %1095 = func.call @gcd_ll(%1100, %1105) : (i64, i64) -> i64
        %1106 = arith.constant 1 : i32
        %1108 = arith.extsi %1106 : i32 to i64
        %1107 = arith.cmpi eq, %1095, %1108 : i64
        cf.cond_br %1107, ^bb156, ^bb157
        ^bb156:
          %1109 = arith.constant 1 : i32
          %1110 = llvm.load %1087 : !llvm.ptr -> i32
          %1111 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %1112 = llvm.load %1111 : !llvm.ptr -> i32
          %1113 = arith.muli %1110, %1112 : i32
          %1114 = llvm.load %1092 : !llvm.ptr -> i32
          %1115 = arith.addi %1113, %1114 : i32
          %1116 = arith.extsi %1115 : i32 to i64
          %1117 = llvm.getelementptr %1076[%1116] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %1109, %1117 : i32, !llvm.ptr
          cf.br ^bb158
        ^bb157:
          %1118 = arith.constant 0 : i32
          %1119 = llvm.load %1087 : !llvm.ptr -> i32
          %1120 = llvm.mlir.addressof @MAXN : !llvm.ptr
          %1121 = llvm.load %1120 : !llvm.ptr -> i32
          %1122 = arith.muli %1119, %1121 : i32
          %1123 = llvm.load %1092 : !llvm.ptr -> i32
          %1124 = arith.addi %1122, %1123 : i32
          %1125 = arith.extsi %1124 : i32 to i64
          %1126 = llvm.getelementptr %1076[%1125] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %1118, %1126 : i32, !llvm.ptr
          cf.br ^bb158
        ^bb158:
        %1127 = llvm.load %1092 : !llvm.ptr -> i32
        %1128 = arith.constant 1 : i32
        %1129 = arith.addi %1127, %1128 : i32
        llvm.store %1129, %1092 : i32, !llvm.ptr
        cf.br ^bb153
      ^bb155:
      %1130 = llvm.load %1087 : !llvm.ptr -> i32
      %1131 = arith.constant 1 : i32
      %1132 = arith.addi %1130, %1131 : i32
      llvm.store %1132, %1087 : i32, !llvm.ptr
      cf.br ^bb150
    ^bb152:
    %1134 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1135 = llvm.load %1134 : !llvm.ptr -> i32
    %1136 = arith.extsi %1135 : i32 to i64
    %1137 = arith.constant 4 : i32
    %1138 = arith.extsi %1137 : i32 to i64
    %1133 = func.call @calloc(%1136, %1138) : (i64, i64) -> !llvm.ptr
    %1139 = arith.constant 1 : i32
    %1140 = llvm.mlir.constant(1 : i64) : i64
    %1141 = llvm.alloca %1140 x i32 : (i64) -> !llvm.ptr
    llvm.store %1139, %1141 : i32, !llvm.ptr
    cf.br ^bb159
    ^bb159:
    %1142 = llvm.load %1141 : !llvm.ptr -> i32
    %1143 = arith.cmpi slt, %1142, %1043 : i32
    cf.cond_br %1143, ^bb160, ^bb161
    ^bb160:
      %1144 = arith.constant 0 : i32
      %1145 = llvm.mlir.constant(1 : i64) : i64
      %1146 = llvm.alloca %1145 x i32 : (i64) -> !llvm.ptr
      llvm.store %1144, %1146 : i32, !llvm.ptr
      %1147 = arith.constant 0 : i32
      %1148 = llvm.mlir.constant(1 : i64) : i64
      %1149 = llvm.alloca %1148 x i32 : (i64) -> !llvm.ptr
      llvm.store %1147, %1149 : i32, !llvm.ptr
      cf.br ^bb162
      ^bb162:
      %1150 = llvm.load %1149 : !llvm.ptr -> i32
      %1151 = arith.cmpi slt, %1150, %1043 : i32
      cf.cond_br %1151, ^bb163, ^bb164
      ^bb163:
        %1153 = llvm.load %1141 : !llvm.ptr -> i32
        %1154 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %1155 = llvm.load %1154 : !llvm.ptr -> i32
        %1156 = arith.muli %1153, %1155 : i32
        %1157 = llvm.load %1149 : !llvm.ptr -> i32
        %1158 = arith.addi %1156, %1157 : i32
        %1159 = arith.extsi %1158 : i32 to i64
        %1160 = llvm.getelementptr %1076[%1159] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1152 = llvm.load %1160 : !llvm.ptr -> i32
        %1161 = arith.constant 0 : i32
        %1162 = arith.cmpi ne, %1152, %1161 : i32
        cf.cond_br %1162, ^bb165, ^bb166
        ^bb165:
          %1163 = llvm.load %1146 : !llvm.ptr -> i32
          %1164 = arith.constant 1 : i32
          %1165 = llvm.load %1149 : !llvm.ptr -> i32
          %1166 = arith.shli %1164, %1165 : i32
          %1167 = arith.ori %1163, %1166 : i32
          llvm.store %1167, %1146 : i32, !llvm.ptr
          cf.br ^bb167
        ^bb166:
          cf.br ^bb167
        ^bb167:
        %1168 = llvm.load %1149 : !llvm.ptr -> i32
        %1169 = arith.constant 1 : i32
        %1170 = arith.addi %1168, %1169 : i32
        llvm.store %1170, %1149 : i32, !llvm.ptr
        cf.br ^bb162
      ^bb164:
      %1171 = llvm.load %1146 : !llvm.ptr -> i32
      %1172 = llvm.load %1141 : !llvm.ptr -> i32
      %1173 = arith.constant 1 : i32
      %1174 = arith.subi %1172, %1173 : i32
      %1175 = arith.extsi %1174 : i32 to i64
      %1176 = llvm.getelementptr %1133[%1175] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1171, %1176 : i32, !llvm.ptr
      %1177 = llvm.load %1141 : !llvm.ptr -> i32
      %1178 = arith.constant 1 : i32
      %1179 = arith.addi %1177, %1178 : i32
      llvm.store %1179, %1141 : i32, !llvm.ptr
      cf.br ^bb159
    ^bb161:
    %1181 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1182 = llvm.load %1181 : !llvm.ptr -> i32
    %1183 = arith.extsi %1182 : i32 to i64
    %1184 = arith.constant 4 : i32
    %1185 = arith.extsi %1184 : i32 to i64
    %1180 = func.call @calloc(%1183, %1185) : (i64, i64) -> !llvm.ptr
    %1186 = arith.constant 0 : i32
    %1187 = llvm.mlir.constant(1 : i64) : i64
    %1188 = llvm.alloca %1187 x i32 : (i64) -> !llvm.ptr
    llvm.store %1186, %1188 : i32, !llvm.ptr
    cf.br ^bb168
    ^bb168:
    %1189 = llvm.load %1188 : !llvm.ptr -> i32
    %1190 = arith.cmpi slt, %1189, %1043 : i32
    cf.cond_br %1190, ^bb169, ^bb170
    ^bb169:
      %1191 = arith.constant 0 : i32
      %1192 = llvm.mlir.constant(1 : i64) : i64
      %1193 = llvm.alloca %1192 x i32 : (i64) -> !llvm.ptr
      llvm.store %1191, %1193 : i32, !llvm.ptr
      %1194 = arith.constant 0 : i32
      %1195 = llvm.mlir.constant(1 : i64) : i64
      %1196 = llvm.alloca %1195 x i32 : (i64) -> !llvm.ptr
      llvm.store %1194, %1196 : i32, !llvm.ptr
      cf.br ^bb171
      ^bb171:
      %1197 = llvm.load %1196 : !llvm.ptr -> i32
      %1198 = arith.cmpi slt, %1197, %1043 : i32
      cf.cond_br %1198, ^bb172, ^bb173
      ^bb172:
        %1200 = llvm.load %1196 : !llvm.ptr -> i32
        %1201 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %1202 = llvm.load %1201 : !llvm.ptr -> i32
        %1203 = arith.muli %1200, %1202 : i32
        %1204 = llvm.load %1188 : !llvm.ptr -> i32
        %1205 = arith.addi %1203, %1204 : i32
        %1206 = arith.extsi %1205 : i32 to i64
        %1207 = llvm.getelementptr %1076[%1206] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1199 = llvm.load %1207 : !llvm.ptr -> i32
        %1208 = arith.constant 0 : i32
        %1209 = arith.cmpi ne, %1199, %1208 : i32
        cf.cond_br %1209, ^bb174, ^bb175
        ^bb174:
          %1210 = llvm.load %1193 : !llvm.ptr -> i32
          %1211 = arith.constant 1 : i32
          %1212 = llvm.load %1196 : !llvm.ptr -> i32
          %1213 = arith.shli %1211, %1212 : i32
          %1214 = arith.ori %1210, %1213 : i32
          llvm.store %1214, %1193 : i32, !llvm.ptr
          cf.br ^bb176
        ^bb175:
          cf.br ^bb176
        ^bb176:
        %1215 = llvm.load %1196 : !llvm.ptr -> i32
        %1216 = arith.constant 1 : i32
        %1217 = arith.addi %1215, %1216 : i32
        llvm.store %1217, %1196 : i32, !llvm.ptr
        cf.br ^bb171
      ^bb173:
      %1218 = llvm.load %1193 : !llvm.ptr -> i32
      %1219 = llvm.load %1188 : !llvm.ptr -> i32
      %1220 = arith.extsi %1219 : i32 to i64
      %1221 = llvm.getelementptr %1180[%1220] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1218, %1221 : i32, !llvm.ptr
      %1222 = llvm.load %1188 : !llvm.ptr -> i32
      %1223 = arith.constant 1 : i32
      %1224 = arith.addi %1222, %1223 : i32
      llvm.store %1224, %1188 : i32, !llvm.ptr
      cf.br ^bb168
    ^bb170:
    %1225 = arith.constant 0 : i32
    %1226 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
    llvm.store %1225, %1226 : i32, !llvm.ptr
    %1228 = arith.constant 131072 : i32
    %1229 = arith.constant 4 : i32
    %1230 = arith.extsi %1228 : i32 to i64
    %1231 = arith.extsi %1229 : i32 to i64
    %1227 = func.call @calloc(%1230, %1231) : (i64, i64) -> !llvm.ptr
    %1233 = arith.constant 1 : i32
    %1235 = arith.constant 0 : i32
    %1234 = arith.subi %1235, %1233 : i32
    %1236 = arith.constant 131072 : i32
    %1237 = arith.constant 4 : i32
    %1238 = arith.muli %1236, %1237 : i32
    %1239 = arith.extsi %1238 : i32 to i64
    %1232 = func.call @memset(%1227, %1234, %1239) : (!llvm.ptr, i32, i64) -> !llvm.ptr
    %1240 = arith.constant 0 : i32
    %1241 = llvm.mlir.constant(1 : i64) : i64
    %1242 = llvm.alloca %1241 x i32 : (i64) -> !llvm.ptr
    llvm.store %1240, %1242 : i32, !llvm.ptr
    cf.br ^bb177
    ^bb177:
    %1243 = llvm.load %1242 : !llvm.ptr -> i32
    %1244 = arith.constant 1 : i32
    %1245 = arith.subi %1043, %1244 : i32
    %1246 = arith.cmpi slt, %1243, %1245 : i32
    cf.cond_br %1246, ^bb178, ^bb179
    ^bb178:
      %1248 = llvm.load %1242 : !llvm.ptr -> i32
      %1249 = arith.extsi %1248 : i32 to i64
      %1250 = llvm.getelementptr %1133[%1249] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1247 = llvm.load %1250 : !llvm.ptr -> i32
      %1252 = arith.extsi %1247 : i32 to i64
      %1253 = llvm.getelementptr %1227[%1252] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1251 = llvm.load %1253 : !llvm.ptr -> i32
      %1254 = arith.constant 0 : i32
      %1255 = arith.cmpi slt, %1251, %1254 : i32
      cf.cond_br %1255, ^bb180, ^bb181
      ^bb180:
        %1256 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
        %1257 = llvm.load %1256 : !llvm.ptr -> i32
        %1258 = arith.extsi %1247 : i32 to i64
        %1259 = llvm.getelementptr %1227[%1258] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1257, %1259 : i32, !llvm.ptr
        %1260 = llvm.load %1242 : !llvm.ptr -> i32
        %1261 = llvm.mlir.addressof @g_row_class_rep : !llvm.ptr
        %1262 = llvm.load %1261 : !llvm.ptr -> !llvm.ptr
        %1263 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
        %1264 = llvm.load %1263 : !llvm.ptr -> i32
        %1265 = arith.extsi %1264 : i32 to i64
        %1266 = llvm.getelementptr %1262[%1265] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1260, %1266 : i32, !llvm.ptr
        %1267 = arith.constant 1 : i32
        %1268 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
        %1269 = llvm.load %1268 : !llvm.ptr -> !llvm.ptr
        %1270 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
        %1271 = llvm.load %1270 : !llvm.ptr -> i32
        %1272 = arith.extsi %1271 : i32 to i64
        %1273 = llvm.getelementptr %1269[%1272] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1267, %1273 : i32, !llvm.ptr
        %1274 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
        %1275 = llvm.load %1274 : !llvm.ptr -> i32
        %1276 = arith.constant 1 : i32
        %1277 = arith.addi %1275, %1276 : i32
        %1278 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
        llvm.store %1277, %1278 : i32, !llvm.ptr
        cf.br ^bb182
      ^bb181:
        %1280 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
        %1281 = llvm.load %1280 : !llvm.ptr -> !llvm.ptr
        %1283 = arith.extsi %1247 : i32 to i64
        %1284 = llvm.getelementptr %1227[%1283] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1282 = llvm.load %1284 : !llvm.ptr -> i32
        %1285 = arith.extsi %1282 : i32 to i64
        %1286 = llvm.getelementptr %1281[%1285] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1279 = llvm.load %1286 : !llvm.ptr -> i32
        %1287 = arith.constant 1 : i32
        %1288 = arith.addi %1279, %1287 : i32
        %1289 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
        %1290 = llvm.load %1289 : !llvm.ptr -> !llvm.ptr
        %1292 = arith.extsi %1247 : i32 to i64
        %1293 = llvm.getelementptr %1227[%1292] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1291 = llvm.load %1293 : !llvm.ptr -> i32
        %1294 = arith.extsi %1291 : i32 to i64
        %1295 = llvm.getelementptr %1290[%1294] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1288, %1295 : i32, !llvm.ptr
        cf.br ^bb182
      ^bb182:
      %1296 = llvm.load %1242 : !llvm.ptr -> i32
      %1297 = arith.constant 1 : i32
      %1298 = arith.addi %1296, %1297 : i32
      llvm.store %1298, %1242 : i32, !llvm.ptr
      cf.br ^bb177
    ^bb179:
    %1299 = arith.constant 0 : i32
    %1300 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
    llvm.store %1299, %1300 : i32, !llvm.ptr
    %1302 = arith.constant 131072 : i32
    %1303 = arith.constant 4 : i32
    %1304 = arith.extsi %1302 : i32 to i64
    %1305 = arith.extsi %1303 : i32 to i64
    %1301 = func.call @calloc(%1304, %1305) : (i64, i64) -> !llvm.ptr
    %1307 = arith.constant 1 : i32
    %1309 = arith.constant 0 : i32
    %1308 = arith.subi %1309, %1307 : i32
    %1310 = arith.constant 131072 : i32
    %1311 = arith.constant 4 : i32
    %1312 = arith.muli %1310, %1311 : i32
    %1313 = arith.extsi %1312 : i32 to i64
    %1306 = func.call @memset(%1301, %1308, %1313) : (!llvm.ptr, i32, i64) -> !llvm.ptr
    %1314 = arith.constant 0 : i32
    llvm.store %1314, %1242 : i32, !llvm.ptr
    cf.br ^bb183
    ^bb183:
    %1315 = llvm.load %1242 : !llvm.ptr -> i32
    %1316 = arith.cmpi slt, %1315, %1043 : i32
    cf.cond_br %1316, ^bb184, ^bb185
    ^bb184:
      %1318 = llvm.load %1242 : !llvm.ptr -> i32
      %1319 = arith.extsi %1318 : i32 to i64
      %1320 = llvm.getelementptr %1180[%1319] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1317 = llvm.load %1320 : !llvm.ptr -> i32
      %1322 = arith.extsi %1317 : i32 to i64
      %1323 = llvm.getelementptr %1301[%1322] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1321 = llvm.load %1323 : !llvm.ptr -> i32
      %1324 = arith.constant 0 : i32
      %1325 = arith.cmpi slt, %1321, %1324 : i32
      cf.cond_br %1325, ^bb186, ^bb187
      ^bb186:
        %1326 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
        %1327 = llvm.load %1326 : !llvm.ptr -> i32
        %1328 = arith.extsi %1317 : i32 to i64
        %1329 = llvm.getelementptr %1301[%1328] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1327, %1329 : i32, !llvm.ptr
        %1330 = llvm.load %1242 : !llvm.ptr -> i32
        %1331 = llvm.mlir.addressof @g_col_class_rep : !llvm.ptr
        %1332 = llvm.load %1331 : !llvm.ptr -> !llvm.ptr
        %1333 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
        %1334 = llvm.load %1333 : !llvm.ptr -> i32
        %1335 = arith.extsi %1334 : i32 to i64
        %1336 = llvm.getelementptr %1332[%1335] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1330, %1336 : i32, !llvm.ptr
        %1337 = arith.constant 1 : i32
        %1338 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
        %1339 = llvm.load %1338 : !llvm.ptr -> !llvm.ptr
        %1340 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
        %1341 = llvm.load %1340 : !llvm.ptr -> i32
        %1342 = arith.extsi %1341 : i32 to i64
        %1343 = llvm.getelementptr %1339[%1342] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1337, %1343 : i32, !llvm.ptr
        %1344 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
        %1345 = llvm.load %1344 : !llvm.ptr -> i32
        %1346 = arith.constant 1 : i32
        %1347 = arith.addi %1345, %1346 : i32
        %1348 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
        llvm.store %1347, %1348 : i32, !llvm.ptr
        cf.br ^bb188
      ^bb187:
        %1350 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
        %1351 = llvm.load %1350 : !llvm.ptr -> !llvm.ptr
        %1353 = arith.extsi %1317 : i32 to i64
        %1354 = llvm.getelementptr %1301[%1353] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1352 = llvm.load %1354 : !llvm.ptr -> i32
        %1355 = arith.extsi %1352 : i32 to i64
        %1356 = llvm.getelementptr %1351[%1355] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1349 = llvm.load %1356 : !llvm.ptr -> i32
        %1357 = arith.constant 1 : i32
        %1358 = arith.addi %1349, %1357 : i32
        %1359 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
        %1360 = llvm.load %1359 : !llvm.ptr -> !llvm.ptr
        %1362 = arith.extsi %1317 : i32 to i64
        %1363 = llvm.getelementptr %1301[%1362] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1361 = llvm.load %1363 : !llvm.ptr -> i32
        %1364 = arith.extsi %1361 : i32 to i64
        %1365 = llvm.getelementptr %1360[%1364] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1358, %1365 : i32, !llvm.ptr
        cf.br ^bb188
      ^bb188:
      %1366 = llvm.load %1242 : !llvm.ptr -> i32
      %1367 = arith.constant 1 : i32
      %1368 = arith.addi %1366, %1367 : i32
      llvm.store %1368, %1242 : i32, !llvm.ptr
      cf.br ^bb183
    ^bb185:
    %1369 = arith.constant 0 : i32
    %1370 = llvm.mlir.constant(1 : i64) : i64
    %1371 = llvm.alloca %1370 x i32 : (i64) -> !llvm.ptr
    llvm.store %1369, %1371 : i32, !llvm.ptr
    cf.br ^bb189
    ^bb189:
    %1372 = llvm.load %1371 : !llvm.ptr -> i32
    %1373 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
    %1374 = llvm.load %1373 : !llvm.ptr -> i32
    %1375 = arith.cmpi slt, %1372, %1374 : i32
    cf.cond_br %1375, ^bb190, ^bb191
    ^bb190:
      %1376 = arith.constant 0 : i32
      %1377 = llvm.mlir.constant(1 : i64) : i64
      %1378 = llvm.alloca %1377 x i32 : (i64) -> !llvm.ptr
      llvm.store %1376, %1378 : i32, !llvm.ptr
      cf.br ^bb192
      ^bb192:
      %1379 = llvm.load %1378 : !llvm.ptr -> i32
      %1380 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
      %1381 = llvm.load %1380 : !llvm.ptr -> i32
      %1382 = arith.cmpi slt, %1379, %1381 : i32
      cf.cond_br %1382, ^bb193, ^bb194
      ^bb193:
        %1385 = llvm.mlir.addressof @g_row_class_rep : !llvm.ptr
        %1386 = llvm.load %1385 : !llvm.ptr -> !llvm.ptr
        %1387 = llvm.load %1371 : !llvm.ptr -> i32
        %1388 = arith.extsi %1387 : i32 to i64
        %1389 = llvm.getelementptr %1386[%1388] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1384 = llvm.load %1389 : !llvm.ptr -> i32
        %1390 = arith.constant 1 : i32
        %1391 = arith.addi %1384, %1390 : i32
        %1392 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %1393 = llvm.load %1392 : !llvm.ptr -> i32
        %1394 = arith.muli %1391, %1393 : i32
        %1396 = llvm.mlir.addressof @g_col_class_rep : !llvm.ptr
        %1397 = llvm.load %1396 : !llvm.ptr -> !llvm.ptr
        %1398 = llvm.load %1378 : !llvm.ptr -> i32
        %1399 = arith.extsi %1398 : i32 to i64
        %1400 = llvm.getelementptr %1397[%1399] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1395 = llvm.load %1400 : !llvm.ptr -> i32
        %1401 = arith.addi %1394, %1395 : i32
        %1402 = arith.extsi %1401 : i32 to i64
        %1403 = llvm.getelementptr %1076[%1402] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1383 = llvm.load %1403 : !llvm.ptr -> i32
        %1404 = llvm.mlir.addressof @g_class_entry : !llvm.ptr
        %1405 = llvm.load %1404 : !llvm.ptr -> !llvm.ptr
        %1406 = llvm.load %1371 : !llvm.ptr -> i32
        %1407 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %1408 = llvm.load %1407 : !llvm.ptr -> i32
        %1409 = arith.muli %1406, %1408 : i32
        %1410 = llvm.load %1378 : !llvm.ptr -> i32
        %1411 = arith.addi %1409, %1410 : i32
        %1412 = arith.extsi %1411 : i32 to i64
        %1413 = llvm.getelementptr %1405[%1412] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1383, %1413 : i32, !llvm.ptr
        %1414 = llvm.load %1378 : !llvm.ptr -> i32
        %1415 = arith.constant 1 : i32
        %1416 = arith.addi %1414, %1415 : i32
        llvm.store %1416, %1378 : i32, !llvm.ptr
        cf.br ^bb192
      ^bb194:
      %1417 = llvm.load %1371 : !llvm.ptr -> i32
      %1418 = arith.constant 1 : i32
      %1419 = arith.addi %1417, %1418 : i32
      llvm.store %1419, %1371 : i32, !llvm.ptr
      cf.br ^bb189
    ^bb191:
    %1420 = arith.constant 0 : i32
    llvm.store %1420, %1371 : i32, !llvm.ptr
    cf.br ^bb195
    ^bb195:
    %1421 = llvm.load %1371 : !llvm.ptr -> i32
    %1422 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
    %1423 = llvm.load %1422 : !llvm.ptr -> i32
    %1424 = arith.cmpi slt, %1421, %1423 : i32
    cf.cond_br %1424, ^bb196, ^bb197
    ^bb196:
      %1425 = arith.constant 0 : i32
      %1426 = llvm.mlir.constant(1 : i64) : i64
      %1427 = llvm.alloca %1426 x i32 : (i64) -> !llvm.ptr
      llvm.store %1425, %1427 : i32, !llvm.ptr
      %1428 = arith.constant 0 : i32
      %1429 = llvm.mlir.constant(1 : i64) : i64
      %1430 = llvm.alloca %1429 x i32 : (i64) -> !llvm.ptr
      llvm.store %1428, %1430 : i32, !llvm.ptr
      cf.br ^bb198
      ^bb198:
      %1431 = llvm.load %1430 : !llvm.ptr -> i32
      %1432 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
      %1433 = llvm.load %1432 : !llvm.ptr -> i32
      %1434 = arith.cmpi slt, %1431, %1433 : i32
      cf.cond_br %1434, ^bb199, ^bb200
      ^bb199:
        %1437 = llvm.mlir.addressof @g_row_class_rep : !llvm.ptr
        %1438 = llvm.load %1437 : !llvm.ptr -> !llvm.ptr
        %1439 = llvm.load %1371 : !llvm.ptr -> i32
        %1440 = arith.extsi %1439 : i32 to i64
        %1441 = llvm.getelementptr %1438[%1440] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1436 = llvm.load %1441 : !llvm.ptr -> i32
        %1442 = arith.constant 1 : i32
        %1443 = arith.addi %1436, %1442 : i32
        %1444 = llvm.mlir.addressof @MAXN : !llvm.ptr
        %1445 = llvm.load %1444 : !llvm.ptr -> i32
        %1446 = arith.muli %1443, %1445 : i32
        %1448 = llvm.mlir.addressof @g_col_class_rep : !llvm.ptr
        %1449 = llvm.load %1448 : !llvm.ptr -> !llvm.ptr
        %1450 = llvm.load %1430 : !llvm.ptr -> i32
        %1451 = arith.extsi %1450 : i32 to i64
        %1452 = llvm.getelementptr %1449[%1451] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1447 = llvm.load %1452 : !llvm.ptr -> i32
        %1453 = arith.addi %1446, %1447 : i32
        %1454 = arith.extsi %1453 : i32 to i64
        %1455 = llvm.getelementptr %1076[%1454] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1435 = llvm.load %1455 : !llvm.ptr -> i32
        %1456 = arith.constant 0 : i32
        %1457 = arith.cmpi ne, %1435, %1456 : i32
        cf.cond_br %1457, ^bb201, ^bb202
        ^bb201:
          %1458 = llvm.load %1427 : !llvm.ptr -> i32
          %1459 = arith.constant 1 : i32
          %1460 = llvm.load %1430 : !llvm.ptr -> i32
          %1461 = arith.shli %1459, %1460 : i32
          %1462 = arith.ori %1458, %1461 : i32
          llvm.store %1462, %1427 : i32, !llvm.ptr
          cf.br ^bb203
        ^bb202:
          cf.br ^bb203
        ^bb203:
        %1463 = llvm.load %1430 : !llvm.ptr -> i32
        %1464 = arith.constant 1 : i32
        %1465 = arith.addi %1463, %1464 : i32
        llvm.store %1465, %1430 : i32, !llvm.ptr
        cf.br ^bb198
      ^bb200:
      %1466 = llvm.load %1427 : !llvm.ptr -> i32
      %1467 = llvm.mlir.addressof @g_row_supports : !llvm.ptr
      %1468 = llvm.load %1467 : !llvm.ptr -> !llvm.ptr
      %1469 = llvm.load %1371 : !llvm.ptr -> i32
      %1470 = arith.extsi %1469 : i32 to i64
      %1471 = llvm.getelementptr %1468[%1470] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1466, %1471 : i32, !llvm.ptr
      %1472 = llvm.load %1371 : !llvm.ptr -> i32
      %1473 = arith.constant 1 : i32
      %1474 = arith.addi %1472, %1473 : i32
      llvm.store %1474, %1371 : i32, !llvm.ptr
      cf.br ^bb195
    ^bb197:
    func.call @init_comb(%1043) : (i32) -> ()
    %1476 = arith.constant 0 : i32
    %1477 = arith.extsi %1476 : i32 to i64
    %1478 = llvm.mlir.constant(1 : i64) : i64
    %1479 = llvm.alloca %1478 x i64 : (i64) -> !llvm.ptr
    llvm.store %1477, %1479 : i64, !llvm.ptr
    %1480 = llvm.mlir.addressof @g_row_class_count : !llvm.ptr
    %1481 = llvm.load %1480 : !llvm.ptr -> i32
    %1482 = llvm.mlir.addressof @g_col_class_count : !llvm.ptr
    %1483 = llvm.load %1482 : !llvm.ptr -> i32
    %1485 = arith.constant 20 : i32
    %1486 = arith.constant 4 : i32
    %1487 = arith.extsi %1485 : i32 to i64
    %1488 = arith.extsi %1486 : i32 to i64
    %1484 = func.call @calloc(%1487, %1488) : (i64, i64) -> !llvm.ptr
    %1490 = arith.constant 20 : i32
    %1491 = arith.constant 4 : i32
    %1492 = arith.extsi %1490 : i32 to i64
    %1493 = arith.extsi %1491 : i32 to i64
    %1489 = func.call @calloc(%1492, %1493) : (i64, i64) -> !llvm.ptr
    %1495 = arith.constant 400 : i32
    %1496 = arith.constant 8 : i32
    %1497 = arith.extsi %1495 : i32 to i64
    %1498 = arith.extsi %1496 : i32 to i64
    %1494 = func.call @calloc(%1497, %1498) : (i64, i64) -> !llvm.ptr
    %1499 = arith.constant 0 : i32
    %1500 = llvm.mlir.constant(1 : i64) : i64
    %1501 = llvm.alloca %1500 x i32 : (i64) -> !llvm.ptr
    llvm.store %1499, %1501 : i32, !llvm.ptr
    cf.br ^bb204
    ^bb204:
    %1502 = llvm.load %1501 : !llvm.ptr -> i32
    %1503 = arith.cmpi sle, %1502, %1483 : i32
    %1504 = scf.if %1503 -> (i1) {
      %1505 = llvm.load %1501 : !llvm.ptr -> i32
      %1506 = arith.cmpi sle, %1505, %1481 : i32
      scf.yield %1506 : i1
    } else {
      %1507 = arith.constant false
      scf.yield %1507 : i1
    }
    cf.cond_br %1504, ^bb205, ^bb206
    ^bb205:
      %1508 = arith.constant 1 : i32
      %1509 = arith.extsi %1508 : i32 to i64
      %1510 = llvm.mlir.constant(1 : i64) : i64
      %1511 = llvm.alloca %1510 x i64 : (i64) -> !llvm.ptr
      llvm.store %1509, %1511 : i64, !llvm.ptr
      %1512 = llvm.load %1501 : !llvm.ptr -> i32
      %1513 = arith.constant 1 : i32
      %1514 = arith.andi %1512, %1513 : i32
      %1515 = arith.constant 1 : i32
      %1516 = arith.cmpi eq, %1514, %1515 : i32
      cf.cond_br %1516, ^bb207, ^bb208
      ^bb207:
        %1517 = arith.constant 1 : i32
        %1519 = arith.constant 0 : i32
        %1518 = arith.subi %1519, %1517 : i32
        %1520 = arith.extsi %1518 : i32 to i64
        llvm.store %1520, %1511 : i64, !llvm.ptr
        cf.br ^bb209
      ^bb208:
        cf.br ^bb209
      ^bb209:
      %1521 = arith.constant 0 : i32
      %1522 = llvm.mlir.constant(1 : i64) : i64
      %1523 = llvm.alloca %1522 x i32 : (i64) -> !llvm.ptr
      llvm.store %1521, %1523 : i32, !llvm.ptr
      cf.br ^bb210
      ^bb210:
      %1524 = llvm.load %1523 : !llvm.ptr -> i32
      %1525 = llvm.load %1501 : !llvm.ptr -> i32
      %1526 = arith.cmpi slt, %1524, %1525 : i32
      cf.cond_br %1526, ^bb211, ^bb212
      ^bb211:
        %1527 = llvm.load %1523 : !llvm.ptr -> i32
        %1528 = llvm.load %1523 : !llvm.ptr -> i32
        %1529 = arith.extsi %1528 : i32 to i64
        %1530 = llvm.getelementptr %1484[%1529] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1527, %1530 : i32, !llvm.ptr
        %1531 = llvm.load %1523 : !llvm.ptr -> i32
        %1532 = arith.constant 1 : i32
        %1533 = arith.addi %1531, %1532 : i32
        llvm.store %1533, %1523 : i32, !llvm.ptr
        cf.br ^bb210
      ^bb212:
      %1534 = arith.constant 0 : i1
      %1535 = llvm.mlir.constant(1 : i64) : i64
      %1536 = llvm.alloca %1535 x i1 : (i64) -> !llvm.ptr
      llvm.store %1534, %1536 : i1, !llvm.ptr
      cf.br ^bb213
      ^bb213:
      %1537 = llvm.load %1536 : !llvm.ptr -> i1
      %1539 = arith.constant 1 : i1
      %1538 = arith.xori %1537, %1539 : i1
      cf.cond_br %1538, ^bb214, ^bb215
      ^bb214:
        %1541 = arith.constant 0 : i32
        %1542 = llvm.mlir.constant(1 : i64) : i64
        %1543 = llvm.alloca %1542 x i32 : (i64) -> !llvm.ptr
        llvm.store %1541, %1543 : i32, !llvm.ptr
        %1544 = arith.constant 1 : i32
        %1545 = arith.extsi %1544 : i32 to i64
        %1546 = llvm.mlir.constant(1 : i64) : i64
        %1547 = llvm.alloca %1546 x i64 : (i64) -> !llvm.ptr
        llvm.store %1545, %1547 : i64, !llvm.ptr
        %1548 = arith.constant 0 : i32
        %1549 = llvm.mlir.constant(1 : i64) : i64
        %1550 = llvm.alloca %1549 x i32 : (i64) -> !llvm.ptr
        llvm.store %1548, %1550 : i32, !llvm.ptr
        cf.br ^bb216
        ^bb216:
        %1551 = llvm.load %1550 : !llvm.ptr -> i32
        %1552 = llvm.load %1501 : !llvm.ptr -> i32
        %1553 = arith.cmpi slt, %1551, %1552 : i32
        cf.cond_br %1553, ^bb217, ^bb218
        ^bb217:
          %1554 = llvm.load %1543 : !llvm.ptr -> i32
          %1555 = arith.constant 1 : i32
          %1557 = llvm.load %1550 : !llvm.ptr -> i32
          %1558 = arith.extsi %1557 : i32 to i64
          %1559 = llvm.getelementptr %1484[%1558] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %1556 = llvm.load %1559 : !llvm.ptr -> i32
          %1560 = arith.shli %1555, %1556 : i32
          %1561 = arith.ori %1554, %1560 : i32
          llvm.store %1561, %1543 : i32, !llvm.ptr
          %1563 = llvm.load %1547 : !llvm.ptr -> i64
          %1565 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
          %1566 = llvm.load %1565 : !llvm.ptr -> !llvm.ptr
          %1568 = llvm.load %1550 : !llvm.ptr -> i32
          %1569 = arith.extsi %1568 : i32 to i64
          %1570 = llvm.getelementptr %1484[%1569] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %1567 = llvm.load %1570 : !llvm.ptr -> i32
          %1571 = arith.extsi %1567 : i32 to i64
          %1572 = llvm.getelementptr %1566[%1571] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %1564 = llvm.load %1572 : !llvm.ptr -> i32
          %1573 = arith.extsi %1564 : i32 to i64
          %1562 = func.call @mulmod(%1563, %1573, %arg1) : (i64, i64, i64) -> i64
          llvm.store %1562, %1547 : i64, !llvm.ptr
          %1574 = llvm.load %1550 : !llvm.ptr -> i32
          %1575 = arith.constant 1 : i32
          %1576 = arith.addi %1574, %1575 : i32
          llvm.store %1576, %1550 : i32, !llvm.ptr
          cf.br ^bb216
        ^bb218:
        %1577 = arith.constant 0 : i32
        %1578 = llvm.mlir.constant(1 : i64) : i64
        %1579 = llvm.alloca %1578 x i32 : (i64) -> !llvm.ptr
        llvm.store %1577, %1579 : i32, !llvm.ptr
        cf.br ^bb219
        ^bb219:
        %1580 = llvm.load %1579 : !llvm.ptr -> i32
        %1581 = llvm.load %1501 : !llvm.ptr -> i32
        %1582 = arith.cmpi slt, %1580, %1581 : i32
        cf.cond_br %1582, ^bb220, ^bb221
        ^bb220:
          %1583 = llvm.load %1579 : !llvm.ptr -> i32
          %1584 = llvm.load %1579 : !llvm.ptr -> i32
          %1585 = arith.extsi %1584 : i32 to i64
          %1586 = llvm.getelementptr %1489[%1585] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %1583, %1586 : i32, !llvm.ptr
          %1587 = llvm.load %1579 : !llvm.ptr -> i32
          %1588 = arith.constant 1 : i32
          %1589 = arith.addi %1587, %1588 : i32
          llvm.store %1589, %1579 : i32, !llvm.ptr
          cf.br ^bb219
        ^bb221:
        %1590 = arith.constant 0 : i1
        %1591 = llvm.mlir.constant(1 : i64) : i64
        %1592 = llvm.alloca %1591 x i1 : (i64) -> !llvm.ptr
        llvm.store %1590, %1592 : i1, !llvm.ptr
        cf.br ^bb222
        ^bb222:
        %1593 = llvm.load %1592 : !llvm.ptr -> i1
        %1595 = arith.constant 1 : i1
        %1594 = arith.xori %1593, %1595 : i1
        cf.cond_br %1594, ^bb223, ^bb224
        ^bb223:
          %1597 = arith.constant 0 : i32
          %1598 = llvm.mlir.constant(1 : i64) : i64
          %1599 = llvm.alloca %1598 x i32 : (i64) -> !llvm.ptr
          llvm.store %1597, %1599 : i32, !llvm.ptr
          %1600 = arith.constant 1 : i32
          %1601 = arith.extsi %1600 : i32 to i64
          %1602 = llvm.mlir.constant(1 : i64) : i64
          %1603 = llvm.alloca %1602 x i64 : (i64) -> !llvm.ptr
          llvm.store %1601, %1603 : i64, !llvm.ptr
          %1604 = arith.constant 0 : i32
          %1605 = llvm.mlir.constant(1 : i64) : i64
          %1606 = llvm.alloca %1605 x i32 : (i64) -> !llvm.ptr
          llvm.store %1604, %1606 : i32, !llvm.ptr
          cf.br ^bb225
          ^bb225:
          %1607 = llvm.load %1606 : !llvm.ptr -> i32
          %1608 = llvm.load %1501 : !llvm.ptr -> i32
          %1609 = arith.cmpi slt, %1607, %1608 : i32
          cf.cond_br %1609, ^bb226, ^bb227
          ^bb226:
            %1610 = llvm.load %1599 : !llvm.ptr -> i32
            %1611 = arith.constant 1 : i32
            %1613 = llvm.load %1606 : !llvm.ptr -> i32
            %1614 = arith.extsi %1613 : i32 to i64
            %1615 = llvm.getelementptr %1489[%1614] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %1612 = llvm.load %1615 : !llvm.ptr -> i32
            %1616 = arith.shli %1611, %1612 : i32
            %1617 = arith.ori %1610, %1616 : i32
            llvm.store %1617, %1599 : i32, !llvm.ptr
            %1619 = llvm.load %1603 : !llvm.ptr -> i64
            %1621 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
            %1622 = llvm.load %1621 : !llvm.ptr -> !llvm.ptr
            %1624 = llvm.load %1606 : !llvm.ptr -> i32
            %1625 = arith.extsi %1624 : i32 to i64
            %1626 = llvm.getelementptr %1489[%1625] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %1623 = llvm.load %1626 : !llvm.ptr -> i32
            %1627 = arith.extsi %1623 : i32 to i64
            %1628 = llvm.getelementptr %1622[%1627] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %1620 = llvm.load %1628 : !llvm.ptr -> i32
            %1629 = arith.extsi %1620 : i32 to i64
            %1618 = func.call @mulmod(%1619, %1629, %arg1) : (i64, i64, i64) -> i64
            llvm.store %1618, %1603 : i64, !llvm.ptr
            %1630 = llvm.load %1606 : !llvm.ptr -> i32
            %1631 = arith.constant 1 : i32
            %1632 = arith.addi %1630, %1631 : i32
            llvm.store %1632, %1606 : i32, !llvm.ptr
            cf.br ^bb225
          ^bb227:
          %1633 = arith.constant 0 : i32
          %1634 = llvm.mlir.constant(1 : i64) : i64
          %1635 = llvm.alloca %1634 x i32 : (i64) -> !llvm.ptr
          llvm.store %1633, %1635 : i32, !llvm.ptr
          cf.br ^bb228
          ^bb228:
          %1636 = llvm.load %1635 : !llvm.ptr -> i32
          %1637 = llvm.load %1501 : !llvm.ptr -> i32
          %1638 = arith.cmpi slt, %1636, %1637 : i32
          cf.cond_br %1638, ^bb229, ^bb230
          ^bb229:
            %1639 = arith.constant 0 : i32
            %1640 = llvm.mlir.constant(1 : i64) : i64
            %1641 = llvm.alloca %1640 x i32 : (i64) -> !llvm.ptr
            llvm.store %1639, %1641 : i32, !llvm.ptr
            cf.br ^bb231
            ^bb231:
            %1642 = llvm.load %1641 : !llvm.ptr -> i32
            %1643 = llvm.load %1501 : !llvm.ptr -> i32
            %1644 = arith.cmpi slt, %1642, %1643 : i32
            cf.cond_br %1644, ^bb232, ^bb233
            ^bb232:
              %1646 = llvm.mlir.addressof @g_class_entry : !llvm.ptr
              %1647 = llvm.load %1646 : !llvm.ptr -> !llvm.ptr
              %1649 = llvm.load %1635 : !llvm.ptr -> i32
              %1650 = arith.extsi %1649 : i32 to i64
              %1651 = llvm.getelementptr %1484[%1650] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1648 = llvm.load %1651 : !llvm.ptr -> i32
              %1652 = llvm.mlir.addressof @MAXN : !llvm.ptr
              %1653 = llvm.load %1652 : !llvm.ptr -> i32
              %1654 = arith.muli %1648, %1653 : i32
              %1656 = llvm.load %1641 : !llvm.ptr -> i32
              %1657 = arith.extsi %1656 : i32 to i64
              %1658 = llvm.getelementptr %1489[%1657] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1655 = llvm.load %1658 : !llvm.ptr -> i32
              %1659 = arith.addi %1654, %1655 : i32
              %1660 = arith.extsi %1659 : i32 to i64
              %1661 = llvm.getelementptr %1647[%1660] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1645 = llvm.load %1661 : !llvm.ptr -> i32
              %1662 = arith.extsi %1645 : i32 to i64
              %1663 = llvm.load %1635 : !llvm.ptr -> i32
              %1664 = llvm.load %1501 : !llvm.ptr -> i32
              %1665 = arith.muli %1663, %1664 : i32
              %1666 = llvm.load %1641 : !llvm.ptr -> i32
              %1667 = arith.addi %1665, %1666 : i32
              %1668 = arith.extsi %1667 : i32 to i64
              %1669 = llvm.getelementptr %1494[%1668] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              llvm.store %1662, %1669 : i64, !llvm.ptr
              %1670 = llvm.load %1641 : !llvm.ptr -> i32
              %1671 = arith.constant 1 : i32
              %1672 = arith.addi %1670, %1671 : i32
              llvm.store %1672, %1641 : i32, !llvm.ptr
              cf.br ^bb231
            ^bb233:
            %1673 = llvm.load %1635 : !llvm.ptr -> i32
            %1674 = arith.constant 1 : i32
            %1675 = arith.addi %1673, %1674 : i32
            llvm.store %1675, %1635 : i32, !llvm.ptr
            cf.br ^bb228
          ^bb230:
          %1677 = llvm.load %1501 : !llvm.ptr -> i32
          %1676 = func.call @determinant_mod(%1494, %1677, %arg1) : (!llvm.ptr, i32, i64) -> i64
          %1678 = arith.constant 0 : i32
          %1680 = arith.extsi %1678 : i32 to i64
          %1679 = arith.cmpi ne, %1676, %1680 : i64
          cf.cond_br %1679, ^bb234, ^bb235
          ^bb234:
            %1682 = llvm.load %1543 : !llvm.ptr -> i32
            %1683 = llvm.load %1599 : !llvm.ptr -> i32
            %1681 = func.call @grouped_permanent(%1682, %1683) : (i32, i32) -> i64
            %1685 = llvm.load %1547 : !llvm.ptr -> i64
            %1686 = llvm.load %1603 : !llvm.ptr -> i64
            %1684 = func.call @mulmod(%1685, %1686, %arg1) : (i64, i64, i64) -> i64
            %1688 = func.call @mulmod(%1676, %1676, %arg1) : (i64, i64, i64) -> i64
            %1687 = func.call @mulmod(%1684, %1688, %arg1) : (i64, i64, i64) -> i64
            %1690 = func.call @mulmod(%1681, %1681, %arg1) : (i64, i64, i64) -> i64
            %1689 = func.call @mulmod(%1687, %1690, %arg1) : (i64, i64, i64) -> i64
            %1691 = llvm.load %1479 : !llvm.ptr -> i64
            %1692 = llvm.load %1511 : !llvm.ptr -> i64
            %1693 = arith.muli %1692, %1689 : i64
            %1694 = arith.addi %1691, %1693 : i64
            llvm.store %1694, %1479 : i64, !llvm.ptr
            cf.br ^bb236
          ^bb235:
            cf.br ^bb236
          ^bb236:
          %1695 = llvm.load %1501 : !llvm.ptr -> i32
          %1696 = arith.constant 0 : i32
          %1697 = arith.cmpi eq, %1695, %1696 : i32
          cf.cond_br %1697, ^bb237, ^bb238
          ^bb237:
            %1698 = arith.constant 1 : i1
            llvm.store %1698, %1592 : i1, !llvm.ptr
            cf.br ^bb239
          ^bb238:
            %1699 = llvm.load %1501 : !llvm.ptr -> i32
            %1700 = arith.constant 1 : i32
            %1701 = arith.subi %1699, %1700 : i32
            %1702 = llvm.mlir.constant(1 : i64) : i64
            %1703 = llvm.alloca %1702 x i32 : (i64) -> !llvm.ptr
            llvm.store %1701, %1703 : i32, !llvm.ptr
            cf.br ^bb240
            ^bb240:
            %1704 = llvm.load %1703 : !llvm.ptr -> i32
            %1705 = arith.constant 0 : i32
            %1706 = arith.cmpi sge, %1704, %1705 : i32
            %1707 = scf.if %1706 -> (i1) {
              %1709 = llvm.load %1703 : !llvm.ptr -> i32
              %1710 = arith.extsi %1709 : i32 to i64
              %1711 = llvm.getelementptr %1489[%1710] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1708 = llvm.load %1711 : !llvm.ptr -> i32
              %1712 = llvm.load %1501 : !llvm.ptr -> i32
              %1713 = arith.subi %1483, %1712 : i32
              %1714 = llvm.load %1703 : !llvm.ptr -> i32
              %1715 = arith.addi %1713, %1714 : i32
              %1716 = arith.cmpi eq, %1708, %1715 : i32
              scf.yield %1716 : i1
            } else {
              %1717 = arith.constant false
              scf.yield %1717 : i1
            }
            cf.cond_br %1707, ^bb241, ^bb242
            ^bb241:
              %1718 = llvm.load %1703 : !llvm.ptr -> i32
              %1719 = arith.constant 1 : i32
              %1720 = arith.subi %1718, %1719 : i32
              llvm.store %1720, %1703 : i32, !llvm.ptr
              cf.br ^bb240
            ^bb242:
            %1721 = llvm.load %1703 : !llvm.ptr -> i32
            %1722 = arith.constant 0 : i32
            %1723 = arith.cmpi slt, %1721, %1722 : i32
            cf.cond_br %1723, ^bb243, ^bb244
            ^bb243:
              %1724 = arith.constant 1 : i1
              llvm.store %1724, %1592 : i1, !llvm.ptr
              cf.br ^bb245
            ^bb244:
              %1726 = llvm.load %1703 : !llvm.ptr -> i32
              %1727 = arith.extsi %1726 : i32 to i64
              %1728 = llvm.getelementptr %1489[%1727] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1725 = llvm.load %1728 : !llvm.ptr -> i32
              %1729 = arith.constant 1 : i32
              %1730 = arith.addi %1725, %1729 : i32
              %1731 = llvm.load %1703 : !llvm.ptr -> i32
              %1732 = arith.extsi %1731 : i32 to i64
              %1733 = llvm.getelementptr %1489[%1732] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              llvm.store %1730, %1733 : i32, !llvm.ptr
              %1734 = llvm.load %1703 : !llvm.ptr -> i32
              %1735 = arith.constant 1 : i32
              %1736 = arith.addi %1734, %1735 : i32
              %1737 = llvm.mlir.constant(1 : i64) : i64
              %1738 = llvm.alloca %1737 x i32 : (i64) -> !llvm.ptr
              llvm.store %1736, %1738 : i32, !llvm.ptr
              cf.br ^bb246
              ^bb246:
              %1739 = llvm.load %1738 : !llvm.ptr -> i32
              %1740 = llvm.load %1501 : !llvm.ptr -> i32
              %1741 = arith.cmpi slt, %1739, %1740 : i32
              cf.cond_br %1741, ^bb247, ^bb248
              ^bb247:
                %1743 = llvm.load %1738 : !llvm.ptr -> i32
                %1744 = arith.constant 1 : i32
                %1745 = arith.subi %1743, %1744 : i32
                %1746 = arith.extsi %1745 : i32 to i64
                %1747 = llvm.getelementptr %1489[%1746] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                %1742 = llvm.load %1747 : !llvm.ptr -> i32
                %1748 = arith.constant 1 : i32
                %1749 = arith.addi %1742, %1748 : i32
                %1750 = llvm.load %1738 : !llvm.ptr -> i32
                %1751 = arith.extsi %1750 : i32 to i64
                %1752 = llvm.getelementptr %1489[%1751] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %1749, %1752 : i32, !llvm.ptr
                %1753 = llvm.load %1738 : !llvm.ptr -> i32
                %1754 = arith.constant 1 : i32
                %1755 = arith.addi %1753, %1754 : i32
                llvm.store %1755, %1738 : i32, !llvm.ptr
                cf.br ^bb246
              ^bb248:
              cf.br ^bb245
            ^bb245:
            cf.br ^bb239
          ^bb239:
          cf.br ^bb222
        ^bb224:
        %1756 = llvm.load %1501 : !llvm.ptr -> i32
        %1757 = arith.constant 0 : i32
        %1758 = arith.cmpi eq, %1756, %1757 : i32
        cf.cond_br %1758, ^bb249, ^bb250
        ^bb249:
          %1759 = arith.constant 1 : i1
          llvm.store %1759, %1536 : i1, !llvm.ptr
          cf.br ^bb251
        ^bb250:
          %1760 = llvm.load %1501 : !llvm.ptr -> i32
          %1761 = arith.constant 1 : i32
          %1762 = arith.subi %1760, %1761 : i32
          %1763 = llvm.mlir.constant(1 : i64) : i64
          %1764 = llvm.alloca %1763 x i32 : (i64) -> !llvm.ptr
          llvm.store %1762, %1764 : i32, !llvm.ptr
          cf.br ^bb252
          ^bb252:
          %1765 = llvm.load %1764 : !llvm.ptr -> i32
          %1766 = arith.constant 0 : i32
          %1767 = arith.cmpi sge, %1765, %1766 : i32
          %1768 = scf.if %1767 -> (i1) {
            %1770 = llvm.load %1764 : !llvm.ptr -> i32
            %1771 = arith.extsi %1770 : i32 to i64
            %1772 = llvm.getelementptr %1484[%1771] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %1769 = llvm.load %1772 : !llvm.ptr -> i32
            %1773 = llvm.load %1501 : !llvm.ptr -> i32
            %1774 = arith.subi %1481, %1773 : i32
            %1775 = llvm.load %1764 : !llvm.ptr -> i32
            %1776 = arith.addi %1774, %1775 : i32
            %1777 = arith.cmpi eq, %1769, %1776 : i32
            scf.yield %1777 : i1
          } else {
            %1778 = arith.constant false
            scf.yield %1778 : i1
          }
          cf.cond_br %1768, ^bb253, ^bb254
          ^bb253:
            %1779 = llvm.load %1764 : !llvm.ptr -> i32
            %1780 = arith.constant 1 : i32
            %1781 = arith.subi %1779, %1780 : i32
            llvm.store %1781, %1764 : i32, !llvm.ptr
            cf.br ^bb252
          ^bb254:
          %1782 = llvm.load %1764 : !llvm.ptr -> i32
          %1783 = arith.constant 0 : i32
          %1784 = arith.cmpi slt, %1782, %1783 : i32
          cf.cond_br %1784, ^bb255, ^bb256
          ^bb255:
            %1785 = arith.constant 1 : i1
            llvm.store %1785, %1536 : i1, !llvm.ptr
            cf.br ^bb257
          ^bb256:
            %1787 = llvm.load %1764 : !llvm.ptr -> i32
            %1788 = arith.extsi %1787 : i32 to i64
            %1789 = llvm.getelementptr %1484[%1788] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %1786 = llvm.load %1789 : !llvm.ptr -> i32
            %1790 = arith.constant 1 : i32
            %1791 = arith.addi %1786, %1790 : i32
            %1792 = llvm.load %1764 : !llvm.ptr -> i32
            %1793 = arith.extsi %1792 : i32 to i64
            %1794 = llvm.getelementptr %1484[%1793] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            llvm.store %1791, %1794 : i32, !llvm.ptr
            %1795 = llvm.load %1764 : !llvm.ptr -> i32
            %1796 = arith.constant 1 : i32
            %1797 = arith.addi %1795, %1796 : i32
            %1798 = llvm.mlir.constant(1 : i64) : i64
            %1799 = llvm.alloca %1798 x i32 : (i64) -> !llvm.ptr
            llvm.store %1797, %1799 : i32, !llvm.ptr
            cf.br ^bb258
            ^bb258:
            %1800 = llvm.load %1799 : !llvm.ptr -> i32
            %1801 = llvm.load %1501 : !llvm.ptr -> i32
            %1802 = arith.cmpi slt, %1800, %1801 : i32
            cf.cond_br %1802, ^bb259, ^bb260
            ^bb259:
              %1804 = llvm.load %1799 : !llvm.ptr -> i32
              %1805 = arith.constant 1 : i32
              %1806 = arith.subi %1804, %1805 : i32
              %1807 = arith.extsi %1806 : i32 to i64
              %1808 = llvm.getelementptr %1484[%1807] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1803 = llvm.load %1808 : !llvm.ptr -> i32
              %1809 = arith.constant 1 : i32
              %1810 = arith.addi %1803, %1809 : i32
              %1811 = llvm.load %1799 : !llvm.ptr -> i32
              %1812 = arith.extsi %1811 : i32 to i64
              %1813 = llvm.getelementptr %1484[%1812] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              llvm.store %1810, %1813 : i32, !llvm.ptr
              %1814 = llvm.load %1799 : !llvm.ptr -> i32
              %1815 = arith.constant 1 : i32
              %1816 = arith.addi %1814, %1815 : i32
              llvm.store %1816, %1799 : i32, !llvm.ptr
              cf.br ^bb258
            ^bb260:
            cf.br ^bb257
          ^bb257:
          cf.br ^bb251
        ^bb251:
        cf.br ^bb213
      ^bb215:
      %1817 = llvm.load %1501 : !llvm.ptr -> i32
      %1818 = arith.constant 1 : i32
      %1819 = arith.addi %1817, %1818 : i32
      llvm.store %1819, %1501 : i32, !llvm.ptr
      cf.br ^bb204
    ^bb206:
    %1820 = llvm.load %1479 : !llvm.ptr -> i64
    %1821 = arith.remsi %1820, %arg1 : i64
    llvm.store %1821, %1479 : i64, !llvm.ptr
    %1822 = llvm.load %1479 : !llvm.ptr -> i64
    %1823 = arith.constant 0 : i32
    %1825 = arith.extsi %1823 : i32 to i64
    %1824 = arith.cmpi slt, %1822, %1825 : i64
    cf.cond_br %1824, ^bb261, ^bb262
    ^bb261:
      %1826 = llvm.load %1479 : !llvm.ptr -> i64
      %1827 = arith.addi %1826, %arg1 : i64
      llvm.store %1827, %1479 : i64, !llvm.ptr
      cf.br ^bb263
    ^bb262:
      cf.br ^bb263
    ^bb263:
    func.call @free(%1044) : (!llvm.ptr) -> ()
    func.call @free(%1048) : (!llvm.ptr) -> ()
    func.call @free(%1076) : (!llvm.ptr) -> ()
    func.call @free(%1133) : (!llvm.ptr) -> ()
    func.call @free(%1180) : (!llvm.ptr) -> ()
    func.call @free(%1227) : (!llvm.ptr) -> ()
    func.call @free(%1301) : (!llvm.ptr) -> ()
    func.call @free(%1484) : (!llvm.ptr) -> ()
    func.call @free(%1489) : (!llvm.ptr) -> ()
    func.call @free(%1494) : (!llvm.ptr) -> ()
    %1838 = llvm.load %1479 : !llvm.ptr -> i64
    func.return %1838 : i64
  }
  func.func @main() -> i32 {
    %1840 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1841 = llvm.load %1840 : !llvm.ptr -> i32
    %1842 = arith.constant 1 : i32
    %1843 = arith.addi %1841, %1842 : i32
    %1844 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1845 = llvm.load %1844 : !llvm.ptr -> i32
    %1846 = arith.constant 1 : i32
    %1847 = arith.addi %1845, %1846 : i32
    %1848 = arith.muli %1843, %1847 : i32
    %1849 = arith.extsi %1848 : i32 to i64
    %1850 = arith.constant 8 : i32
    %1851 = arith.extsi %1850 : i32 to i64
    %1839 = func.call @calloc(%1849, %1851) : (i64, i64) -> !llvm.ptr
    %1852 = llvm.mlir.addressof @g_comb : !llvm.ptr
    llvm.store %1839, %1852 : !llvm.ptr, !llvm.ptr
    %1854 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1855 = llvm.load %1854 : !llvm.ptr -> i32
    %1856 = arith.extsi %1855 : i32 to i64
    %1857 = arith.constant 4 : i32
    %1858 = arith.extsi %1857 : i32 to i64
    %1853 = func.call @calloc(%1856, %1858) : (i64, i64) -> !llvm.ptr
    %1859 = llvm.mlir.addressof @g_row_class_rep : !llvm.ptr
    llvm.store %1853, %1859 : !llvm.ptr, !llvm.ptr
    %1861 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1862 = llvm.load %1861 : !llvm.ptr -> i32
    %1863 = arith.extsi %1862 : i32 to i64
    %1864 = arith.constant 4 : i32
    %1865 = arith.extsi %1864 : i32 to i64
    %1860 = func.call @calloc(%1863, %1865) : (i64, i64) -> !llvm.ptr
    %1866 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
    llvm.store %1860, %1866 : !llvm.ptr, !llvm.ptr
    %1868 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1869 = llvm.load %1868 : !llvm.ptr -> i32
    %1870 = arith.extsi %1869 : i32 to i64
    %1871 = arith.constant 4 : i32
    %1872 = arith.extsi %1871 : i32 to i64
    %1867 = func.call @calloc(%1870, %1872) : (i64, i64) -> !llvm.ptr
    %1873 = llvm.mlir.addressof @g_col_class_rep : !llvm.ptr
    llvm.store %1867, %1873 : !llvm.ptr, !llvm.ptr
    %1875 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1876 = llvm.load %1875 : !llvm.ptr -> i32
    %1877 = arith.extsi %1876 : i32 to i64
    %1878 = arith.constant 4 : i32
    %1879 = arith.extsi %1878 : i32 to i64
    %1874 = func.call @calloc(%1877, %1879) : (i64, i64) -> !llvm.ptr
    %1880 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
    llvm.store %1874, %1880 : !llvm.ptr, !llvm.ptr
    %1882 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1883 = llvm.load %1882 : !llvm.ptr -> i32
    %1884 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1885 = llvm.load %1884 : !llvm.ptr -> i32
    %1886 = arith.muli %1883, %1885 : i32
    %1887 = arith.extsi %1886 : i32 to i64
    %1888 = arith.constant 4 : i32
    %1889 = arith.extsi %1888 : i32 to i64
    %1881 = func.call @calloc(%1887, %1889) : (i64, i64) -> !llvm.ptr
    %1890 = llvm.mlir.addressof @g_class_entry : !llvm.ptr
    llvm.store %1881, %1890 : !llvm.ptr, !llvm.ptr
    %1892 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1893 = llvm.load %1892 : !llvm.ptr -> i32
    %1894 = arith.extsi %1893 : i32 to i64
    %1895 = arith.constant 4 : i32
    %1896 = arith.extsi %1895 : i32 to i64
    %1891 = func.call @calloc(%1894, %1896) : (i64, i64) -> !llvm.ptr
    %1897 = llvm.mlir.addressof @g_row_supports : !llvm.ptr
    llvm.store %1891, %1897 : !llvm.ptr, !llvm.ptr
    %1899 = llvm.mlir.addressof @PERM_CACHE_CAP : !llvm.ptr
    %1900 = llvm.load %1899 : !llvm.ptr -> i64
    %1901 = arith.constant 8 : i32
    %1902 = arith.extsi %1901 : i32 to i64
    %1898 = func.call @calloc(%1900, %1902) : (i64, i64) -> !llvm.ptr
    %1903 = llvm.mlir.addressof @g_perm_key : !llvm.ptr
    llvm.store %1898, %1903 : !llvm.ptr, !llvm.ptr
    %1905 = llvm.mlir.addressof @PERM_CACHE_CAP : !llvm.ptr
    %1906 = llvm.load %1905 : !llvm.ptr -> i64
    %1907 = arith.constant 8 : i32
    %1908 = arith.extsi %1907 : i32 to i64
    %1904 = func.call @calloc(%1906, %1908) : (i64, i64) -> !llvm.ptr
    %1909 = llvm.mlir.addressof @g_perm_val : !llvm.ptr
    llvm.store %1904, %1909 : !llvm.ptr, !llvm.ptr
    %1911 = llvm.mlir.addressof @PERM_CACHE_CAP : !llvm.ptr
    %1912 = llvm.load %1911 : !llvm.ptr -> i64
    %1913 = arith.constant 1 : i32
    %1914 = arith.extsi %1913 : i32 to i64
    %1910 = func.call @calloc(%1912, %1914) : (i64, i64) -> !llvm.ptr
    %1915 = llvm.mlir.addressof @g_perm_used : !llvm.ptr
    llvm.store %1910, %1915 : !llvm.ptr, !llvm.ptr
    %1917 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1918 = llvm.load %1917 : !llvm.ptr -> i32
    %1919 = arith.extsi %1918 : i32 to i64
    %1920 = arith.constant 4 : i32
    %1921 = arith.extsi %1920 : i32 to i64
    %1916 = func.call @calloc(%1919, %1921) : (i64, i64) -> !llvm.ptr
    %1922 = llvm.mlir.addressof @g_active_col_classes : !llvm.ptr
    llvm.store %1916, %1922 : !llvm.ptr, !llvm.ptr
    %1924 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1925 = llvm.load %1924 : !llvm.ptr -> i32
    %1926 = arith.extsi %1925 : i32 to i64
    %1927 = arith.constant 4 : i32
    %1928 = arith.extsi %1927 : i32 to i64
    %1923 = func.call @calloc(%1926, %1928) : (i64, i64) -> !llvm.ptr
    %1929 = llvm.mlir.addressof @g_active_col_counts : !llvm.ptr
    llvm.store %1923, %1929 : !llvm.ptr, !llvm.ptr
    %1931 = arith.constant 256 : i32
    %1932 = arith.constant 4 : i32
    %1933 = arith.extsi %1931 : i32 to i64
    %1934 = arith.extsi %1932 : i32 to i64
    %1930 = func.call @calloc(%1933, %1934) : (i64, i64) -> !llvm.ptr
    %1935 = llvm.mlir.addressof @g_supports : !llvm.ptr
    llvm.store %1930, %1935 : !llvm.ptr, !llvm.ptr
    %1937 = arith.constant 256 : i32
    %1938 = arith.constant 4 : i32
    %1939 = arith.extsi %1937 : i32 to i64
    %1940 = arith.extsi %1938 : i32 to i64
    %1936 = func.call @calloc(%1939, %1940) : (i64, i64) -> !llvm.ptr
    %1941 = llvm.mlir.addressof @g_row_counts_arr : !llvm.ptr
    llvm.store %1936, %1941 : !llvm.ptr, !llvm.ptr
    %1943 = arith.constant 256 : i32
    %1944 = arith.constant 4 : i32
    %1945 = arith.extsi %1943 : i32 to i64
    %1946 = arith.extsi %1944 : i32 to i64
    %1942 = func.call @calloc(%1945, %1946) : (i64, i64) -> !llvm.ptr
    %1947 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
    llvm.store %1942, %1947 : !llvm.ptr, !llvm.ptr
    %1949 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1950 = llvm.load %1949 : !llvm.ptr -> i32
    %1951 = arith.constant 256 : i32
    %1952 = arith.muli %1950, %1951 : i32
    %1953 = arith.extsi %1952 : i32 to i64
    %1954 = arith.constant 4 : i32
    %1955 = arith.extsi %1954 : i32 to i64
    %1948 = func.call @calloc(%1953, %1955) : (i64, i64) -> !llvm.ptr
    %1956 = llvm.mlir.addressof @g_affected : !llvm.ptr
    llvm.store %1948, %1956 : !llvm.ptr, !llvm.ptr
    %1958 = llvm.mlir.addressof @MAXN : !llvm.ptr
    %1959 = llvm.load %1958 : !llvm.ptr -> i32
    %1960 = arith.extsi %1959 : i32 to i64
    %1961 = arith.constant 4 : i32
    %1962 = arith.extsi %1961 : i32 to i64
    %1957 = func.call @calloc(%1960, %1962) : (i64, i64) -> !llvm.ptr
    %1963 = llvm.mlir.addressof @g_n_affected : !llvm.ptr
    llvm.store %1957, %1963 : !llvm.ptr, !llvm.ptr
    %1965 = arith.constant 34 : i32
    %1966 = llvm.mlir.addressof @MOD : !llvm.ptr
    %1967 = llvm.load %1966 : !llvm.ptr -> i64
    %1964 = func.call @P_func(%1965, %1967) : (i32, i64) -> i64
    %1968 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %1969 = llvm.call @printf(%1968, %1964) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %1971 = llvm.mlir.addressof @g_comb : !llvm.ptr
    %1972 = llvm.load %1971 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1972) : (!llvm.ptr) -> ()
    %1974 = llvm.mlir.addressof @g_row_class_rep : !llvm.ptr
    %1975 = llvm.load %1974 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1975) : (!llvm.ptr) -> ()
    %1977 = llvm.mlir.addressof @g_row_class_count_arr : !llvm.ptr
    %1978 = llvm.load %1977 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1978) : (!llvm.ptr) -> ()
    %1980 = llvm.mlir.addressof @g_col_class_rep : !llvm.ptr
    %1981 = llvm.load %1980 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1981) : (!llvm.ptr) -> ()
    %1983 = llvm.mlir.addressof @g_col_class_count_arr : !llvm.ptr
    %1984 = llvm.load %1983 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1984) : (!llvm.ptr) -> ()
    %1986 = llvm.mlir.addressof @g_class_entry : !llvm.ptr
    %1987 = llvm.load %1986 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1987) : (!llvm.ptr) -> ()
    %1989 = llvm.mlir.addressof @g_row_supports : !llvm.ptr
    %1990 = llvm.load %1989 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1990) : (!llvm.ptr) -> ()
    %1992 = llvm.mlir.addressof @g_perm_key : !llvm.ptr
    %1993 = llvm.load %1992 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1993) : (!llvm.ptr) -> ()
    %1995 = llvm.mlir.addressof @g_perm_val : !llvm.ptr
    %1996 = llvm.load %1995 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1996) : (!llvm.ptr) -> ()
    %1998 = llvm.mlir.addressof @g_perm_used : !llvm.ptr
    %1999 = llvm.load %1998 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1999) : (!llvm.ptr) -> ()
    %2001 = llvm.mlir.addressof @g_active_col_classes : !llvm.ptr
    %2002 = llvm.load %2001 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2002) : (!llvm.ptr) -> ()
    %2004 = llvm.mlir.addressof @g_active_col_counts : !llvm.ptr
    %2005 = llvm.load %2004 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2005) : (!llvm.ptr) -> ()
    %2007 = llvm.mlir.addressof @g_supports : !llvm.ptr
    %2008 = llvm.load %2007 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2008) : (!llvm.ptr) -> ()
    %2010 = llvm.mlir.addressof @g_row_counts_arr : !llvm.ptr
    %2011 = llvm.load %2010 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2011) : (!llvm.ptr) -> ()
    %2013 = llvm.mlir.addressof @g_row_sums : !llvm.ptr
    %2014 = llvm.load %2013 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2014) : (!llvm.ptr) -> ()
    %2016 = llvm.mlir.addressof @g_affected : !llvm.ptr
    %2017 = llvm.load %2016 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2017) : (!llvm.ptr) -> ()
    %2019 = llvm.mlir.addressof @g_n_affected : !llvm.ptr
    %2020 = llvm.load %2019 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2020) : (!llvm.ptr) -> ()
    %2021 = arith.constant 0 : i32
    func.return %2021 : i32
  }
}