Problem 943

Kolakoski-like sequence counts. Ported from native C to pure Flow. Uses a memoized recursive solver with an open-addressing hash table (generation-stamped) to count a-runs and b-runs.

Answer1038733707
Output1038733707
StatusPASS
Native helperno
Runtime4590 ms
Peak memory874128 KB
Time complexityO(n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n)?
Space complexityO(n^2)?
ApproachFlow solutionNot curated
VerdictUnknown

Flow source

# Project Euler 943
# Kolakoski-like sequence counts. Ported from native C to pure Flow.
# Uses a memoized recursive solver with an open-addressing hash table
# (generation-stamped) to count a-runs and b-runs.

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

struct Result {
    count_a: i64,
    count_b: i64,
    next_state: i64
}

# Simulate uint64_t left shift (wraps at 64 bits)
function u64_shl(val: i64, amt: i64) -> i64 {
    if amt >= 64 {
        return 0
    }
    let r: i128 = (val as i128) << amt
    let mask: i128 = ((1 as i128) << 64) - 1
    return (r & mask) as i64
}

# Hash table: separate arrays for each field
let mut ht_key: ptr<i64> = null
let mut ht_gen: ptr<i64> = null
let mut ht_ca: ptr<i64> = null
let mut ht_cb: ptr<i64> = null
let mut ht_ns: ptr<i64> = null
let mut ht_mask: i64 = 0
let mut ht_gen_val: i64 = 0
let mut ht_count: i64 = 0
let mut g_a: i64 = 0
let mut g_b: i64 = 0

function solver_init(a: i64, b: i64) -> void {
    g_a = a
    g_b = b
    ht_gen_val = ht_gen_val + 1
    ht_count = 0
}

function solver_ensure_table(need: i64) -> void {
    if ht_key == null as ptr<i64> {
        let mut sz: i64 = 1 << 16
        while sz < need * 3 {
            sz = sz << 1
        }
        ht_key = calloc(sz, 8) as ptr<i64>
        ht_gen = calloc(sz, 8) as ptr<i64>
        ht_ca = calloc(sz, 8) as ptr<i64>
        ht_cb = calloc(sz, 8) as ptr<i64>
        ht_ns = calloc(sz, 8) as ptr<i64>
        ht_mask = sz - 1
    } else {
        let cap: i64 = ht_mask + 1
        if ht_count * 3 >= cap {
            let mut newcap: i64 = cap
            while newcap < ht_count * 6 {
                newcap = newcap << 1
            }
            let old_key: ptr<i64> = ht_key
            let old_gen: ptr<i64> = ht_gen
            let old_ca: ptr<i64> = ht_ca
            let old_cb: ptr<i64> = ht_cb
            let old_ns: ptr<i64> = ht_ns
            let oldcap: i64 = cap
            ht_key = calloc(newcap, 8) as ptr<i64>
            ht_gen = calloc(newcap, 8) as ptr<i64>
            ht_ca = calloc(newcap, 8) as ptr<i64>
            ht_cb = calloc(newcap, 8) as ptr<i64>
            ht_ns = calloc(newcap, 8) as ptr<i64>
            ht_mask = newcap - 1
            let mut i: i64 = 0
            while i < oldcap {
                if old_gen[i] == ht_gen_val && old_key[i] != 0 {
                    let mut h: i64 = (((old_key[i] as i128) * (2654435761 as i128)) & (ht_mask as i128)) as i64
                    while ht_key[h] != 0 {
                        h = (h + 1) & ht_mask
                    }
                    ht_key[h] = old_key[i]
                    ht_gen[h] = old_gen[i]
                    ht_ca[h] = old_ca[i]
                    ht_cb[h] = old_cb[i]
                    ht_ns[h] = old_ns[i]
                }
                i = i + 1
            }
            free(old_key as ptr<void>)
            free(old_gen as ptr<void>)
            free(old_ca as ptr<void>)
            free(old_cb as ptr<void>)
            free(old_ns as ptr<void>)
        }
    }
}

# Returns the slot index for a key (empty or matching)
function solver_lookup(key: i64) -> i64 {
    let mut h: i64 = (((key as i128) * (2654435761 as i128)) & (ht_mask as i128)) as i64
    while true {
        if ht_key[h] == 0 || ht_gen[h] != ht_gen_val {
            return h
        }
        if ht_key[h] == key {
            return h
        }
        h = (h + 1) & ht_mask
    }
    return 0
}

function calc(state: i64, level: i64, maxlen: i64) -> Result {
    if maxlen == 0 {
        return Result { count_a: 0, count_b: 0, next_state: state }
    }

    let length_bit: i64 = u64_shl(2, level)
    let bit: i64 = state & length_bit
    let run_len: i64 = 0
    if bit != 0 {
        run_len = g_b
    } else {
        run_len = g_a
    }
    let count: i64 = 0
    if run_len < maxlen {
        count = run_len
    } else {
        count = maxlen
    }

    if level == 0 {
        if (state & 1) == 0 {
            return Result { count_a: count, count_b: 0, next_state: state ^ 1 }
        } else {
            return Result { count_a: 0, count_b: count, next_state: state ^ 1 }
        }
    }

    let mut produced_a: i64 = 0
    let mut produced_b: i64 = 0
    let mut substate: i64 = state ^ bit

    let mut i: i64 = 0
    while i < count {
        let child_key: i64 = substate + u64_shl(2, level)
        solver_ensure_table(ht_count + 1)
        let slot: i64 = solver_lookup(child_key)
        let mut child: Result = Result { count_a: 0, count_b: 0, next_state: 0 }
        if ht_key[slot] == child_key && ht_gen[slot] == ht_gen_val {
            child = Result { count_a: ht_ca[slot], count_b: ht_cb[slot], next_state: ht_ns[slot] }
            let child_total: i64 = child.count_a + child.count_b
            if produced_a + produced_b + child_total > maxlen {
                child = calc(substate, level - 1, maxlen - produced_a - produced_b)
            }
        } else {
            child = calc(substate, level - 1, maxlen - produced_a - produced_b)
        }
        produced_a = produced_a + child.count_a
        produced_b = produced_b + child.count_b
        substate = child.next_state
        i = i + 1
    }

    let res_ns: i64 = substate ^ bit ^ u64_shl(1, level)
    let res: Result = Result { count_a: produced_a, count_b: produced_b, next_state: res_ns }

    # Store in cache
    let cache_key: i64 = state + u64_shl(4, level)
    solver_ensure_table(ht_count + 1)
    let slot2: i64 = solver_lookup(cache_key)
    if ht_key[slot2] != cache_key || ht_gen[slot2] != ht_gen_val {
        ht_key[slot2] = cache_key
        ht_gen[slot2] = ht_gen_val
        ht_count = ht_count + 1
    }
    ht_ca[slot2] = res.count_a
    ht_cb[slot2] = res.count_b
    ht_ns[slot2] = res.next_state

    return res
}

function compute_T(a: i64, b: i64, limit: i64) -> i64 {
    solver_init(a, b)
    let mut level: i64 = 0
    let mut res: Result = Result { count_a: 0, count_b: 0, next_state: 0 }
    while true {
        res = calc(0, level, limit)
        level = level + 1
        if res.count_a + res.count_b >= limit {
            break
        }
        if level >= 64 {
            break
        }
    }
    return res.count_a * a + res.count_b * b
}

function main() -> i32 {
    # Self-tests
    if compute_T(2, 3, 10) != 25 {
        printf("self-test 1 failed\n")
        return 1
    }
    if compute_T(4, 2, 10000) != 30004 {
        printf("self-test 2 failed\n")
        return 1
    }

    let MOD: i64 = 2233222333
    let N: i64 = 22332223332233
    let mut total: i64 = 0
    let mut a: i64 = 2
    while a < 224 {
        let mut b: i64 = 2
        while b < 224 {
            if a != b {
                let contribution: i64 = compute_T(a, b, N) % MOD
                total = (total + contribution) % MOD
            }
            b = b + 1
        }
        a = a + 1
    }
    printf("%lld\n", total % MOD)
    return 0
}

Generated C

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

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

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

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

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

#include <math.h>

void* _ui_state = NULL;

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

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

typedef struct Result Result;

struct Result {
    int64_t count_a;
    int64_t count_b;
    int64_t next_state;
};

int64_t u64_shl_i64_i64(int64_t val, int64_t amt);
void solver_init_i64_i64(int64_t a, int64_t b);
void solver_ensure_table_i64(int64_t need);
int64_t solver_lookup_i64(int64_t key);
Result calc_i64_i64_i64(int64_t state, int64_t level, int64_t maxlen);
int64_t compute_T_i64_i64_i64(int64_t a, int64_t b, int64_t limit);
int32_t main(void);

/* Module statics */
static int64_t* ht_key = NULL;
static int64_t* ht_gen = NULL;
static int64_t* ht_ca = NULL;
static int64_t* ht_cb = NULL;
static int64_t* ht_ns = NULL;
static int64_t ht_mask = 0;
static int64_t ht_gen_val = 0;
static int64_t ht_count = 0;
static int64_t g_a = 0;
static int64_t g_b = 0;




int64_t u64_shl_i64_i64(int64_t val, int64_t amt) {
    if (amt >= 64) {
        return 0;
    }
    __int128 r = FLOW_CHECKED_SHL((((__int128)(val))), (amt));
    __int128 mask = (FLOW_CHECKED_SHL((((__int128)(1))), (64)) - 1);
    return ((int64_t)((r & mask)));
}

void solver_init_i64_i64(int64_t a, int64_t b) {
    g_a = a;
    g_b = b;
    ht_gen_val = (ht_gen_val + 1);
    ht_count = 0;
}

void solver_ensure_table_i64(int64_t need) {
    if (ht_key == ((int64_t*)(NULL))) {
        int64_t sz = FLOW_CHECKED_SHL((1), (16));
        while (sz < (need * 3)) {
            sz = FLOW_CHECKED_SHL((sz), (1));
        }
        ht_key = ((int64_t*)(calloc(sz, 8)));
        ht_gen = ((int64_t*)(calloc(sz, 8)));
        ht_ca = ((int64_t*)(calloc(sz, 8)));
        ht_cb = ((int64_t*)(calloc(sz, 8)));
        ht_ns = ((int64_t*)(calloc(sz, 8)));
        ht_mask = (sz - 1);
    } else {
        int64_t cap = (ht_mask + 1);
        if ((ht_count * 3) >= cap) {
            int64_t newcap = cap;
            while (newcap < (ht_count * 6)) {
                newcap = FLOW_CHECKED_SHL((newcap), (1));
            }
            int64_t* old_key = (int64_t*)(ht_key);
            int64_t* old_gen = (int64_t*)(ht_gen);
            int64_t* old_ca = (int64_t*)(ht_ca);
            int64_t* old_cb = (int64_t*)(ht_cb);
            int64_t* old_ns = (int64_t*)(ht_ns);
            int64_t oldcap = cap;
            ht_key = ((int64_t*)(calloc(newcap, 8)));
            ht_gen = ((int64_t*)(calloc(newcap, 8)));
            ht_ca = ((int64_t*)(calloc(newcap, 8)));
            ht_cb = ((int64_t*)(calloc(newcap, 8)));
            ht_ns = ((int64_t*)(calloc(newcap, 8)));
            ht_mask = (newcap - 1);
            int64_t i = 0;
            while (i < oldcap) {
                if ((old_gen[i] == ht_gen_val && old_key[i] != 0)) {
                    int64_t h = ((int64_t)(((((__int128)(old_key[i])) * ((__int128)(2654435761))) & ((__int128)(ht_mask)))));
                    while (ht_key[h] != 0) {
                        h = ((h + 1) & ht_mask);
                    }
                    ht_key[h] = old_key[i];
                    ht_gen[h] = old_gen[i];
                    ht_ca[h] = old_ca[i];
                    ht_cb[h] = old_cb[i];
                    ht_ns[h] = old_ns[i];
                }
                i = (i + 1);
            }
            free(((void*)(old_key)));
            free(((void*)(old_gen)));
            free(((void*)(old_ca)));
            free(((void*)(old_cb)));
            free(((void*)(old_ns)));
        }
    }
}

int64_t solver_lookup_i64(int64_t key) {
    int64_t h = ((int64_t)(((((__int128)(key)) * ((__int128)(2654435761))) & ((__int128)(ht_mask)))));
    while (1) {
        if ((ht_key[h] == 0 || ht_gen[h] != ht_gen_val)) {
            return h;
        }
        if (ht_key[h] == key) {
            return h;
        }
        h = ((h + 1) & ht_mask);
    }
    return 0;
}

Result calc_i64_i64_i64(int64_t state, int64_t level, int64_t maxlen) {
    if (maxlen == 0) {
        return (Result){ .count_a = 0, .count_b = 0, .next_state = state };
    }
    int64_t length_bit = u64_shl_i64_i64(2, level);
    int64_t bit = (state & length_bit);
    int64_t run_len = 0;
    if (bit != 0) {
        run_len = g_b;
    } else {
        run_len = g_a;
    }
    int64_t count = 0;
    if (run_len < maxlen) {
        count = run_len;
    } else {
        count = maxlen;
    }
    if (level == 0) {
        if ((state & 1) == 0) {
            return (Result){ .count_a = count, .count_b = 0, .next_state = (state ^ 1) };
        } else {
            return (Result){ .count_a = 0, .count_b = count, .next_state = (state ^ 1) };
        }
    }
    int64_t produced_a = 0;
    int64_t produced_b = 0;
    int64_t substate = (state ^ bit);
    int64_t i = 0;
    while (i < count) {
        int64_t child_key = (substate + u64_shl_i64_i64(2, level));
        solver_ensure_table_i64((ht_count + 1));
        int64_t slot = solver_lookup_i64(child_key);
        Result child = (Result){ .count_a = 0, .count_b = 0, .next_state = 0 };
        if ((ht_key[slot] == child_key && ht_gen[slot] == ht_gen_val)) {
            child = (Result){ .count_a = ht_ca[slot], .count_b = ht_cb[slot], .next_state = ht_ns[slot] };
            int64_t child_total = (child.count_a + child.count_b);
            if (((produced_a + produced_b) + child_total) > maxlen) {
                child = calc_i64_i64_i64(substate, (level - 1), ((maxlen - produced_a) - produced_b));
            }
        } else {
            child = calc_i64_i64_i64(substate, (level - 1), ((maxlen - produced_a) - produced_b));
        }
        produced_a = (produced_a + child.count_a);
        produced_b = (produced_b + child.count_b);
        substate = child.next_state;
        i = (i + 1);
    }
    int64_t res_ns = ((substate ^ bit) ^ u64_shl_i64_i64(1, level));
    Result res = (Result){ .count_a = produced_a, .count_b = produced_b, .next_state = res_ns };
    int64_t cache_key = (state + u64_shl_i64_i64(4, level));
    solver_ensure_table_i64((ht_count + 1));
    int64_t slot2 = solver_lookup_i64(cache_key);
    if ((ht_key[slot2] != cache_key || ht_gen[slot2] != ht_gen_val)) {
        ht_key[slot2] = cache_key;
        ht_gen[slot2] = ht_gen_val;
        ht_count = (ht_count + 1);
    }
    ht_ca[slot2] = res.count_a;
    ht_cb[slot2] = res.count_b;
    ht_ns[slot2] = res.next_state;
    return res;
}

int64_t compute_T_i64_i64_i64(int64_t a, int64_t b, int64_t limit) {
    solver_init_i64_i64(a, b);
    int64_t level = 0;
    Result res = (Result){ .count_a = 0, .count_b = 0, .next_state = 0 };
    while (1) {
        res = calc_i64_i64_i64(0, level, limit);
        level = (level + 1);
        if ((res.count_a + res.count_b) >= limit) {
            break;
        }
        if (level >= 64) {
            break;
        }
    }
    return ((res.count_a * a) + (res.count_b * b));
}

int32_t main(void) {
    if (compute_T_i64_i64_i64(2, 3, 10) != 25) {
        printf("self-test 1 failed\n");
        return 1;
    }
    if (compute_T_i64_i64_i64(4, 2, 10000) != 30004) {
        printf("self-test 2 failed\n");
        return 1;
    }
    int64_t MOD = 2233222333;
    int64_t N = 22332223332233;
    int64_t total = 0;
    int64_t a = 2;
    while (a < 224) {
        int64_t b = 2;
        while (b < 224) {
            if (a != b) {
                int64_t contribution = FLOW_CHECKED_MOD((compute_T_i64_i64_i64(a, b, N)), (MOD));
                total = FLOW_CHECKED_MOD(((total + contribution)), (MOD));
            }
            b = (b + 1);
        }
        a = (a + 1);
    }
    printf("%lld\n", FLOW_CHECKED_MOD((total), (MOD)));
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("self-test 1 failed\n\00") {addr_space = 0 : i32} : !llvm.array<20 x i8>
  llvm.mlir.global internal constant @str_1("self-test 2 failed\n\00") {addr_space = 0 : i32} : !llvm.array<20 x i8>
  llvm.mlir.global internal constant @str_2("%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 @malloc(i64) -> !llvm.ptr
  // Struct: Result
  // Fields:
  //   count_a: i64
  //   count_b: i64
  //   next_state: i64
  func.func @u64_shl(%arg0: i64, %arg1: i64) -> i64 {
    %0 = arith.constant 64 : i32
    %2 = arith.extsi %0 : i32 to i64
    %1 = arith.cmpi sge, %arg1, %2 : i64
    cf.cond_br %1, ^bb0, ^bb1
    ^bb0:
      %3 = arith.constant 0 : i32
      %4 = arith.extsi %3 : i32 to i64
      func.return %4 : i64
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %5 = arith.extsi %arg0 : i64 to i128
    %7 = arith.trunci %5 : i128 to i64
    %6 = arith.shli %7, %arg1 : i64
    %8 = arith.extsi %6 : i64 to i128
    %9 = arith.constant 1 : i32
    %10 = arith.extsi %9 : i32 to i128
    %11 = arith.constant 64 : i32
    %13 = arith.trunci %10 : i128 to i64
    %14 = arith.extsi %11 : i32 to i64
    %12 = arith.shli %13, %14 : i64
    %15 = arith.constant 1 : i32
    %17 = arith.extsi %15 : i32 to i64
    %16 = arith.subi %12, %17 : i64
    %18 = arith.extsi %16 : i64 to i128
    %20 = arith.trunci %8 : i128 to i64
    %21 = arith.trunci %18 : i128 to i64
    %19 = arith.andi %20, %21 : i64
    func.return %19 : i64
  }
  // Module static: ht_key
  llvm.mlir.global internal @ht_key() {addr_space = 0 : i32} : !llvm.ptr {
    %22 = llvm.mlir.zero : !llvm.ptr
    llvm.return %22 : !llvm.ptr
  }
  // Module static: ht_gen
  llvm.mlir.global internal @ht_gen() {addr_space = 0 : i32} : !llvm.ptr {
    %23 = llvm.mlir.zero : !llvm.ptr
    llvm.return %23 : !llvm.ptr
  }
  // Module static: ht_ca
  llvm.mlir.global internal @ht_ca() {addr_space = 0 : i32} : !llvm.ptr {
    %24 = llvm.mlir.zero : !llvm.ptr
    llvm.return %24 : !llvm.ptr
  }
  // Module static: ht_cb
  llvm.mlir.global internal @ht_cb() {addr_space = 0 : i32} : !llvm.ptr {
    %25 = llvm.mlir.zero : !llvm.ptr
    llvm.return %25 : !llvm.ptr
  }
  // Module static: ht_ns
  llvm.mlir.global internal @ht_ns() {addr_space = 0 : i32} : !llvm.ptr {
    %26 = llvm.mlir.zero : !llvm.ptr
    llvm.return %26 : !llvm.ptr
  }
  // Module static: ht_mask
  llvm.mlir.global internal @ht_mask(0 : i64) : i64
  // Module static: ht_gen_val
  llvm.mlir.global internal @ht_gen_val(0 : i64) : i64
  // Module static: ht_count
  llvm.mlir.global internal @ht_count(0 : i64) : i64
  // Module static: g_a
  llvm.mlir.global internal @g_a(0 : i64) : i64
  // Module static: g_b
  llvm.mlir.global internal @g_b(0 : i64) : i64
  func.func @solver_init(%arg0: i64, %arg1: i64) -> () {
    %27 = llvm.mlir.addressof @g_a : !llvm.ptr
    llvm.store %arg0, %27 : i64, !llvm.ptr
    %28 = llvm.mlir.addressof @g_b : !llvm.ptr
    llvm.store %arg1, %28 : i64, !llvm.ptr
    %29 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
    %30 = llvm.load %29 : !llvm.ptr -> i64
    %31 = arith.constant 1 : i32
    %33 = arith.extsi %31 : i32 to i64
    %32 = arith.addi %30, %33 : i64
    %34 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
    llvm.store %32, %34 : i64, !llvm.ptr
    %35 = arith.constant 0 : i32
    %36 = arith.extsi %35 : i32 to i64
    %37 = llvm.mlir.addressof @ht_count : !llvm.ptr
    llvm.store %36, %37 : i64, !llvm.ptr
    func.return
  }
  func.func @solver_ensure_table(%arg0: i64) -> () {
    %38 = llvm.mlir.addressof @ht_key : !llvm.ptr
    %39 = llvm.load %38 : !llvm.ptr -> !llvm.ptr
    %40 = llvm.mlir.zero : !llvm.ptr
    %41 = llvm.icmp "eq" %39, %40 : !llvm.ptr
    cf.cond_br %41, ^bb3, ^bb4
    ^bb3:
      %42 = arith.constant 1 : i32
      %43 = arith.constant 16 : i32
      %44 = arith.shli %42, %43 : i32
      %45 = arith.extsi %44 : i32 to i64
      %46 = llvm.mlir.constant(1 : i64) : i64
      %47 = llvm.alloca %46 x i64 : (i64) -> !llvm.ptr
      llvm.store %45, %47 : i64, !llvm.ptr
      cf.br ^bb6
      ^bb6:
      %48 = llvm.load %47 : !llvm.ptr -> i64
      %49 = arith.constant 3 : i32
      %51 = arith.extsi %49 : i32 to i64
      %50 = arith.muli %arg0, %51 : i64
      %52 = arith.cmpi slt, %48, %50 : i64
      cf.cond_br %52, ^bb7, ^bb8
      ^bb7:
        %53 = llvm.load %47 : !llvm.ptr -> i64
        %54 = arith.constant 1 : i32
        %56 = arith.extsi %54 : i32 to i64
        %55 = arith.shli %53, %56 : i64
        llvm.store %55, %47 : i64, !llvm.ptr
        cf.br ^bb6
      ^bb8:
      %58 = llvm.load %47 : !llvm.ptr -> i64
      %59 = arith.constant 8 : i32
      %60 = arith.extsi %59 : i32 to i64
      %57 = func.call @calloc(%58, %60) : (i64, i64) -> !llvm.ptr
      %61 = llvm.mlir.addressof @ht_key : !llvm.ptr
      llvm.store %57, %61 : !llvm.ptr, !llvm.ptr
      %63 = llvm.load %47 : !llvm.ptr -> i64
      %64 = arith.constant 8 : i32
      %65 = arith.extsi %64 : i32 to i64
      %62 = func.call @calloc(%63, %65) : (i64, i64) -> !llvm.ptr
      %66 = llvm.mlir.addressof @ht_gen : !llvm.ptr
      llvm.store %62, %66 : !llvm.ptr, !llvm.ptr
      %68 = llvm.load %47 : !llvm.ptr -> i64
      %69 = arith.constant 8 : i32
      %70 = arith.extsi %69 : i32 to i64
      %67 = func.call @calloc(%68, %70) : (i64, i64) -> !llvm.ptr
      %71 = llvm.mlir.addressof @ht_ca : !llvm.ptr
      llvm.store %67, %71 : !llvm.ptr, !llvm.ptr
      %73 = llvm.load %47 : !llvm.ptr -> i64
      %74 = arith.constant 8 : i32
      %75 = arith.extsi %74 : i32 to i64
      %72 = func.call @calloc(%73, %75) : (i64, i64) -> !llvm.ptr
      %76 = llvm.mlir.addressof @ht_cb : !llvm.ptr
      llvm.store %72, %76 : !llvm.ptr, !llvm.ptr
      %78 = llvm.load %47 : !llvm.ptr -> i64
      %79 = arith.constant 8 : i32
      %80 = arith.extsi %79 : i32 to i64
      %77 = func.call @calloc(%78, %80) : (i64, i64) -> !llvm.ptr
      %81 = llvm.mlir.addressof @ht_ns : !llvm.ptr
      llvm.store %77, %81 : !llvm.ptr, !llvm.ptr
      %82 = llvm.load %47 : !llvm.ptr -> i64
      %83 = arith.constant 1 : i32
      %85 = arith.extsi %83 : i32 to i64
      %84 = arith.subi %82, %85 : i64
      %86 = llvm.mlir.addressof @ht_mask : !llvm.ptr
      llvm.store %84, %86 : i64, !llvm.ptr
      cf.br ^bb5
    ^bb4:
      %87 = llvm.mlir.addressof @ht_mask : !llvm.ptr
      %88 = llvm.load %87 : !llvm.ptr -> i64
      %89 = arith.constant 1 : i32
      %91 = arith.extsi %89 : i32 to i64
      %90 = arith.addi %88, %91 : i64
      %92 = llvm.mlir.addressof @ht_count : !llvm.ptr
      %93 = llvm.load %92 : !llvm.ptr -> i64
      %94 = arith.constant 3 : i32
      %96 = arith.extsi %94 : i32 to i64
      %95 = arith.muli %93, %96 : i64
      %97 = arith.cmpi sge, %95, %90 : i64
      cf.cond_br %97, ^bb9, ^bb10
      ^bb9:
        %98 = llvm.mlir.constant(1 : i64) : i64
        %99 = llvm.alloca %98 x i64 : (i64) -> !llvm.ptr
        llvm.store %90, %99 : i64, !llvm.ptr
        cf.br ^bb12
        ^bb12:
        %100 = llvm.load %99 : !llvm.ptr -> i64
        %101 = llvm.mlir.addressof @ht_count : !llvm.ptr
        %102 = llvm.load %101 : !llvm.ptr -> i64
        %103 = arith.constant 6 : i32
        %105 = arith.extsi %103 : i32 to i64
        %104 = arith.muli %102, %105 : i64
        %106 = arith.cmpi slt, %100, %104 : i64
        cf.cond_br %106, ^bb13, ^bb14
        ^bb13:
          %107 = llvm.load %99 : !llvm.ptr -> i64
          %108 = arith.constant 1 : i32
          %110 = arith.extsi %108 : i32 to i64
          %109 = arith.shli %107, %110 : i64
          llvm.store %109, %99 : i64, !llvm.ptr
          cf.br ^bb12
        ^bb14:
        %111 = llvm.mlir.addressof @ht_key : !llvm.ptr
        %112 = llvm.load %111 : !llvm.ptr -> !llvm.ptr
        %113 = llvm.mlir.addressof @ht_gen : !llvm.ptr
        %114 = llvm.load %113 : !llvm.ptr -> !llvm.ptr
        %115 = llvm.mlir.addressof @ht_ca : !llvm.ptr
        %116 = llvm.load %115 : !llvm.ptr -> !llvm.ptr
        %117 = llvm.mlir.addressof @ht_cb : !llvm.ptr
        %118 = llvm.load %117 : !llvm.ptr -> !llvm.ptr
        %119 = llvm.mlir.addressof @ht_ns : !llvm.ptr
        %120 = llvm.load %119 : !llvm.ptr -> !llvm.ptr
        %122 = llvm.load %99 : !llvm.ptr -> i64
        %123 = arith.constant 8 : i32
        %124 = arith.extsi %123 : i32 to i64
        %121 = func.call @calloc(%122, %124) : (i64, i64) -> !llvm.ptr
        %125 = llvm.mlir.addressof @ht_key : !llvm.ptr
        llvm.store %121, %125 : !llvm.ptr, !llvm.ptr
        %127 = llvm.load %99 : !llvm.ptr -> i64
        %128 = arith.constant 8 : i32
        %129 = arith.extsi %128 : i32 to i64
        %126 = func.call @calloc(%127, %129) : (i64, i64) -> !llvm.ptr
        %130 = llvm.mlir.addressof @ht_gen : !llvm.ptr
        llvm.store %126, %130 : !llvm.ptr, !llvm.ptr
        %132 = llvm.load %99 : !llvm.ptr -> i64
        %133 = arith.constant 8 : i32
        %134 = arith.extsi %133 : i32 to i64
        %131 = func.call @calloc(%132, %134) : (i64, i64) -> !llvm.ptr
        %135 = llvm.mlir.addressof @ht_ca : !llvm.ptr
        llvm.store %131, %135 : !llvm.ptr, !llvm.ptr
        %137 = llvm.load %99 : !llvm.ptr -> i64
        %138 = arith.constant 8 : i32
        %139 = arith.extsi %138 : i32 to i64
        %136 = func.call @calloc(%137, %139) : (i64, i64) -> !llvm.ptr
        %140 = llvm.mlir.addressof @ht_cb : !llvm.ptr
        llvm.store %136, %140 : !llvm.ptr, !llvm.ptr
        %142 = llvm.load %99 : !llvm.ptr -> i64
        %143 = arith.constant 8 : i32
        %144 = arith.extsi %143 : i32 to i64
        %141 = func.call @calloc(%142, %144) : (i64, i64) -> !llvm.ptr
        %145 = llvm.mlir.addressof @ht_ns : !llvm.ptr
        llvm.store %141, %145 : !llvm.ptr, !llvm.ptr
        %146 = llvm.load %99 : !llvm.ptr -> i64
        %147 = arith.constant 1 : i32
        %149 = arith.extsi %147 : i32 to i64
        %148 = arith.subi %146, %149 : i64
        %150 = llvm.mlir.addressof @ht_mask : !llvm.ptr
        llvm.store %148, %150 : i64, !llvm.ptr
        %151 = arith.constant 0 : i32
        %152 = arith.extsi %151 : i32 to i64
        %153 = llvm.mlir.constant(1 : i64) : i64
        %154 = llvm.alloca %153 x i64 : (i64) -> !llvm.ptr
        llvm.store %152, %154 : i64, !llvm.ptr
        cf.br ^bb15
        ^bb15:
        %155 = llvm.load %154 : !llvm.ptr -> i64
        %156 = arith.cmpi slt, %155, %90 : i64
        cf.cond_br %156, ^bb16, ^bb17
        ^bb16:
          %158 = llvm.load %154 : !llvm.ptr -> i64
          %159 = llvm.getelementptr %114[%158] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %157 = llvm.load %159 : !llvm.ptr -> i64
          %160 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
          %161 = llvm.load %160 : !llvm.ptr -> i64
          %162 = arith.cmpi eq, %157, %161 : i64
          %163 = scf.if %162 -> (i1) {
            %165 = llvm.load %154 : !llvm.ptr -> i64
            %166 = llvm.getelementptr %112[%165] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %164 = llvm.load %166 : !llvm.ptr -> i64
            %167 = arith.constant 0 : i32
            %169 = arith.extsi %167 : i32 to i64
            %168 = arith.cmpi ne, %164, %169 : i64
            scf.yield %168 : i1
          } else {
            %170 = arith.constant false
            scf.yield %170 : i1
          }
          cf.cond_br %163, ^bb18, ^bb19
          ^bb18:
            %172 = llvm.load %154 : !llvm.ptr -> i64
            %173 = llvm.getelementptr %112[%172] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %171 = llvm.load %173 : !llvm.ptr -> i64
            %174 = arith.extsi %171 : i64 to i128
            %175 = arith.constant -1640531535 : i32
            %176 = arith.extsi %175 : i32 to i128
            %178 = arith.trunci %174 : i128 to i64
            %179 = arith.trunci %176 : i128 to i64
            %177 = arith.muli %178, %179 : i64
            %180 = llvm.mlir.addressof @ht_mask : !llvm.ptr
            %181 = llvm.load %180 : !llvm.ptr -> i64
            %182 = arith.extsi %181 : i64 to i128
            %184 = arith.trunci %182 : i128 to i64
            %183 = arith.andi %177, %184 : i64
            %185 = llvm.mlir.constant(1 : i64) : i64
            %186 = llvm.alloca %185 x i64 : (i64) -> !llvm.ptr
            llvm.store %183, %186 : i64, !llvm.ptr
            cf.br ^bb21
            ^bb21:
            %188 = llvm.mlir.addressof @ht_key : !llvm.ptr
            %189 = llvm.load %188 : !llvm.ptr -> !llvm.ptr
            %190 = llvm.load %186 : !llvm.ptr -> i64
            %191 = llvm.getelementptr %189[%190] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %187 = llvm.load %191 : !llvm.ptr -> i64
            %192 = arith.constant 0 : i32
            %194 = arith.extsi %192 : i32 to i64
            %193 = arith.cmpi ne, %187, %194 : i64
            cf.cond_br %193, ^bb22, ^bb23
            ^bb22:
              %195 = llvm.load %186 : !llvm.ptr -> i64
              %196 = arith.constant 1 : i32
              %198 = arith.extsi %196 : i32 to i64
              %197 = arith.addi %195, %198 : i64
              %199 = llvm.mlir.addressof @ht_mask : !llvm.ptr
              %200 = llvm.load %199 : !llvm.ptr -> i64
              %201 = arith.andi %197, %200 : i64
              llvm.store %201, %186 : i64, !llvm.ptr
              cf.br ^bb21
            ^bb23:
            %203 = llvm.load %154 : !llvm.ptr -> i64
            %204 = llvm.getelementptr %112[%203] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %202 = llvm.load %204 : !llvm.ptr -> i64
            %205 = llvm.mlir.addressof @ht_key : !llvm.ptr
            %206 = llvm.load %205 : !llvm.ptr -> !llvm.ptr
            %207 = llvm.load %186 : !llvm.ptr -> i64
            %208 = llvm.getelementptr %206[%207] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %202, %208 : i64, !llvm.ptr
            %210 = llvm.load %154 : !llvm.ptr -> i64
            %211 = llvm.getelementptr %114[%210] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %209 = llvm.load %211 : !llvm.ptr -> i64
            %212 = llvm.mlir.addressof @ht_gen : !llvm.ptr
            %213 = llvm.load %212 : !llvm.ptr -> !llvm.ptr
            %214 = llvm.load %186 : !llvm.ptr -> i64
            %215 = llvm.getelementptr %213[%214] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %209, %215 : i64, !llvm.ptr
            %217 = llvm.load %154 : !llvm.ptr -> i64
            %218 = llvm.getelementptr %116[%217] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %216 = llvm.load %218 : !llvm.ptr -> i64
            %219 = llvm.mlir.addressof @ht_ca : !llvm.ptr
            %220 = llvm.load %219 : !llvm.ptr -> !llvm.ptr
            %221 = llvm.load %186 : !llvm.ptr -> i64
            %222 = llvm.getelementptr %220[%221] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %216, %222 : i64, !llvm.ptr
            %224 = llvm.load %154 : !llvm.ptr -> i64
            %225 = llvm.getelementptr %118[%224] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %223 = llvm.load %225 : !llvm.ptr -> i64
            %226 = llvm.mlir.addressof @ht_cb : !llvm.ptr
            %227 = llvm.load %226 : !llvm.ptr -> !llvm.ptr
            %228 = llvm.load %186 : !llvm.ptr -> i64
            %229 = llvm.getelementptr %227[%228] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %223, %229 : i64, !llvm.ptr
            %231 = llvm.load %154 : !llvm.ptr -> i64
            %232 = llvm.getelementptr %120[%231] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %230 = llvm.load %232 : !llvm.ptr -> i64
            %233 = llvm.mlir.addressof @ht_ns : !llvm.ptr
            %234 = llvm.load %233 : !llvm.ptr -> !llvm.ptr
            %235 = llvm.load %186 : !llvm.ptr -> i64
            %236 = llvm.getelementptr %234[%235] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %230, %236 : i64, !llvm.ptr
            cf.br ^bb20
          ^bb19:
            cf.br ^bb20
          ^bb20:
          %237 = llvm.load %154 : !llvm.ptr -> i64
          %238 = arith.constant 1 : i32
          %240 = arith.extsi %238 : i32 to i64
          %239 = arith.addi %237, %240 : i64
          llvm.store %239, %154 : i64, !llvm.ptr
          cf.br ^bb15
        ^bb17:
        func.call @free(%112) : (!llvm.ptr) -> ()
        func.call @free(%114) : (!llvm.ptr) -> ()
        func.call @free(%116) : (!llvm.ptr) -> ()
        func.call @free(%118) : (!llvm.ptr) -> ()
        func.call @free(%120) : (!llvm.ptr) -> ()
        cf.br ^bb11
      ^bb10:
        cf.br ^bb11
      ^bb11:
      cf.br ^bb5
    ^bb5:
    func.return
  }
  func.func @solver_lookup(%arg0: i64) -> i64 {
    %246 = arith.extsi %arg0 : i64 to i128
    %247 = arith.constant -1640531535 : i32
    %248 = arith.extsi %247 : i32 to i128
    %250 = arith.trunci %246 : i128 to i64
    %251 = arith.trunci %248 : i128 to i64
    %249 = arith.muli %250, %251 : i64
    %252 = llvm.mlir.addressof @ht_mask : !llvm.ptr
    %253 = llvm.load %252 : !llvm.ptr -> i64
    %254 = arith.extsi %253 : i64 to i128
    %256 = arith.trunci %254 : i128 to i64
    %255 = arith.andi %249, %256 : i64
    %257 = llvm.mlir.constant(1 : i64) : i64
    %258 = llvm.alloca %257 x i64 : (i64) -> !llvm.ptr
    llvm.store %255, %258 : i64, !llvm.ptr
    cf.br ^bb24
    ^bb24:
    %259 = arith.constant 1 : i1
    cf.cond_br %259, ^bb25, ^bb26
    ^bb25:
      %261 = llvm.mlir.addressof @ht_key : !llvm.ptr
      %262 = llvm.load %261 : !llvm.ptr -> !llvm.ptr
      %263 = llvm.load %258 : !llvm.ptr -> i64
      %264 = llvm.getelementptr %262[%263] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %260 = llvm.load %264 : !llvm.ptr -> i64
      %265 = arith.constant 0 : i32
      %267 = arith.extsi %265 : i32 to i64
      %266 = arith.cmpi eq, %260, %267 : i64
      %268 = scf.if %266 -> (i1) {
        %269 = arith.constant true
        scf.yield %269 : i1
      } else {
        %271 = llvm.mlir.addressof @ht_gen : !llvm.ptr
        %272 = llvm.load %271 : !llvm.ptr -> !llvm.ptr
        %273 = llvm.load %258 : !llvm.ptr -> i64
        %274 = llvm.getelementptr %272[%273] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %270 = llvm.load %274 : !llvm.ptr -> i64
        %275 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
        %276 = llvm.load %275 : !llvm.ptr -> i64
        %277 = arith.cmpi ne, %270, %276 : i64
        scf.yield %277 : i1
      }
      cf.cond_br %268, ^bb27, ^bb28
      ^bb27:
        %278 = llvm.load %258 : !llvm.ptr -> i64
        func.return %278 : i64
      ^bb28:
        cf.br ^bb29
      ^bb29:
      %280 = llvm.mlir.addressof @ht_key : !llvm.ptr
      %281 = llvm.load %280 : !llvm.ptr -> !llvm.ptr
      %282 = llvm.load %258 : !llvm.ptr -> i64
      %283 = llvm.getelementptr %281[%282] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %279 = llvm.load %283 : !llvm.ptr -> i64
      %284 = arith.cmpi eq, %279, %arg0 : i64
      cf.cond_br %284, ^bb30, ^bb31
      ^bb30:
        %285 = llvm.load %258 : !llvm.ptr -> i64
        func.return %285 : i64
      ^bb31:
        cf.br ^bb32
      ^bb32:
      %286 = llvm.load %258 : !llvm.ptr -> i64
      %287 = arith.constant 1 : i32
      %289 = arith.extsi %287 : i32 to i64
      %288 = arith.addi %286, %289 : i64
      %290 = llvm.mlir.addressof @ht_mask : !llvm.ptr
      %291 = llvm.load %290 : !llvm.ptr -> i64
      %292 = arith.andi %288, %291 : i64
      llvm.store %292, %258 : i64, !llvm.ptr
      cf.br ^bb24
    ^bb26:
    %293 = arith.constant 0 : i32
    %294 = arith.extsi %293 : i32 to i64
    func.return %294 : i64
  }
  func.func @calc(%arg0: i64, %arg1: i64, %arg2: i64) -> !llvm.struct<(i64, i64, i64)> {
    %295 = arith.constant 0 : i32
    %297 = arith.extsi %295 : i32 to i64
    %296 = arith.cmpi eq, %arg2, %297 : i64
    cf.cond_br %296, ^bb33, ^bb34
    ^bb33:
      %298 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
      %299 = arith.constant 0 : i32
      %300 = arith.extsi %299 : i32 to i64
      %301 = llvm.insertvalue %300, %298[0] : !llvm.struct<(i64, i64, i64)>
      %302 = arith.constant 0 : i32
      %303 = arith.extsi %302 : i32 to i64
      %304 = llvm.insertvalue %303, %301[1] : !llvm.struct<(i64, i64, i64)>
      %305 = llvm.insertvalue %arg0, %304[2] : !llvm.struct<(i64, i64, i64)>
      %306 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
      %307 = llvm.extractvalue %305[0] : !llvm.struct<(i64, i64, i64)>
      %308 = llvm.insertvalue %307, %306[0] : !llvm.struct<(i64, i64, i64)>
      %309 = llvm.extractvalue %305[1] : !llvm.struct<(i64, i64, i64)>
      %310 = llvm.insertvalue %309, %308[1] : !llvm.struct<(i64, i64, i64)>
      %311 = llvm.extractvalue %305[2] : !llvm.struct<(i64, i64, i64)>
      %312 = llvm.insertvalue %311, %310[2] : !llvm.struct<(i64, i64, i64)>
      %313 = llvm.mlir.constant(1 : i64) : i64
      %314 = llvm.alloca %313 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
      llvm.store %312, %314 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
      %315 = llvm.load %314 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      func.return %315 : !llvm.struct<(i64, i64, i64)>
    ^bb34:
      cf.br ^bb35
    ^bb35:
    %317 = arith.constant 2 : i32
    %318 = arith.extsi %317 : i32 to i64
    %316 = func.call @u64_shl(%318, %arg1) : (i64, i64) -> i64
    %319 = arith.andi %arg0, %316 : i64
    %320 = arith.constant 0 : i32
    %321 = arith.extsi %320 : i32 to i64
    %322 = arith.constant 0 : i32
    %324 = arith.extsi %322 : i32 to i64
    %323 = arith.cmpi ne, %319, %324 : i64
    %325 = scf.if %323 -> (i64) {
      %326 = llvm.mlir.addressof @g_b : !llvm.ptr
      %327 = llvm.load %326 : !llvm.ptr -> i64
      scf.yield %327 : i64
    } else {
      %328 = llvm.mlir.addressof @g_a : !llvm.ptr
      %329 = llvm.load %328 : !llvm.ptr -> i64
      scf.yield %329 : i64
    }
    %330 = arith.constant 0 : i32
    %331 = arith.extsi %330 : i32 to i64
    %332 = arith.cmpi slt, %325, %arg2 : i64
    %333 = scf.if %332 -> (i64) {
      scf.yield %325 : i64
    } else {
      scf.yield %arg2 : i64
    }
    %334 = arith.constant 0 : i32
    %336 = arith.extsi %334 : i32 to i64
    %335 = arith.cmpi eq, %arg1, %336 : i64
    cf.cond_br %335, ^bb36, ^bb37
    ^bb36:
      %337 = arith.constant 1 : i32
      %339 = arith.extsi %337 : i32 to i64
      %338 = arith.andi %arg0, %339 : i64
      %340 = arith.constant 0 : i32
      %342 = arith.extsi %340 : i32 to i64
      %341 = arith.cmpi eq, %338, %342 : i64
      cf.cond_br %341, ^bb39, ^bb40
      ^bb39:
        %343 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
        %344 = llvm.insertvalue %333, %343[0] : !llvm.struct<(i64, i64, i64)>
        %345 = arith.constant 0 : i32
        %346 = arith.extsi %345 : i32 to i64
        %347 = llvm.insertvalue %346, %344[1] : !llvm.struct<(i64, i64, i64)>
        %348 = arith.constant 1 : i32
        %350 = arith.extsi %348 : i32 to i64
        %349 = arith.xori %arg0, %350 : i64
        %351 = llvm.insertvalue %349, %347[2] : !llvm.struct<(i64, i64, i64)>
        %352 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
        %353 = llvm.extractvalue %351[0] : !llvm.struct<(i64, i64, i64)>
        %354 = llvm.insertvalue %353, %352[0] : !llvm.struct<(i64, i64, i64)>
        %355 = llvm.extractvalue %351[1] : !llvm.struct<(i64, i64, i64)>
        %356 = llvm.insertvalue %355, %354[1] : !llvm.struct<(i64, i64, i64)>
        %357 = llvm.extractvalue %351[2] : !llvm.struct<(i64, i64, i64)>
        %358 = llvm.insertvalue %357, %356[2] : !llvm.struct<(i64, i64, i64)>
        %359 = llvm.mlir.constant(1 : i64) : i64
        %360 = llvm.alloca %359 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
        llvm.store %358, %360 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
        %361 = llvm.load %360 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
        func.return %361 : !llvm.struct<(i64, i64, i64)>
      ^bb40:
        %362 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
        %363 = arith.constant 0 : i32
        %364 = arith.extsi %363 : i32 to i64
        %365 = llvm.insertvalue %364, %362[0] : !llvm.struct<(i64, i64, i64)>
        %366 = llvm.insertvalue %333, %365[1] : !llvm.struct<(i64, i64, i64)>
        %367 = arith.constant 1 : i32
        %369 = arith.extsi %367 : i32 to i64
        %368 = arith.xori %arg0, %369 : i64
        %370 = llvm.insertvalue %368, %366[2] : !llvm.struct<(i64, i64, i64)>
        %371 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
        %372 = llvm.extractvalue %370[0] : !llvm.struct<(i64, i64, i64)>
        %373 = llvm.insertvalue %372, %371[0] : !llvm.struct<(i64, i64, i64)>
        %374 = llvm.extractvalue %370[1] : !llvm.struct<(i64, i64, i64)>
        %375 = llvm.insertvalue %374, %373[1] : !llvm.struct<(i64, i64, i64)>
        %376 = llvm.extractvalue %370[2] : !llvm.struct<(i64, i64, i64)>
        %377 = llvm.insertvalue %376, %375[2] : !llvm.struct<(i64, i64, i64)>
        %378 = llvm.mlir.constant(1 : i64) : i64
        %379 = llvm.alloca %378 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
        llvm.store %377, %379 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
        %380 = llvm.load %379 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
        func.return %380 : !llvm.struct<(i64, i64, i64)>
    ^bb37:
      cf.br ^bb38
    ^bb38:
    %381 = arith.constant 0 : i32
    %382 = arith.extsi %381 : i32 to i64
    %383 = llvm.mlir.constant(1 : i64) : i64
    %384 = llvm.alloca %383 x i64 : (i64) -> !llvm.ptr
    llvm.store %382, %384 : i64, !llvm.ptr
    %385 = arith.constant 0 : i32
    %386 = arith.extsi %385 : i32 to i64
    %387 = llvm.mlir.constant(1 : i64) : i64
    %388 = llvm.alloca %387 x i64 : (i64) -> !llvm.ptr
    llvm.store %386, %388 : i64, !llvm.ptr
    %389 = arith.xori %arg0, %319 : i64
    %390 = llvm.mlir.constant(1 : i64) : i64
    %391 = llvm.alloca %390 x i64 : (i64) -> !llvm.ptr
    llvm.store %389, %391 : i64, !llvm.ptr
    %392 = arith.constant 0 : i32
    %393 = arith.extsi %392 : i32 to i64
    %394 = llvm.mlir.constant(1 : i64) : i64
    %395 = llvm.alloca %394 x i64 : (i64) -> !llvm.ptr
    llvm.store %393, %395 : i64, !llvm.ptr
    cf.br ^bb42
    ^bb42:
    %396 = llvm.load %395 : !llvm.ptr -> i64
    %397 = arith.cmpi slt, %396, %333 : i64
    cf.cond_br %397, ^bb43, ^bb44
    ^bb43:
      %398 = llvm.load %391 : !llvm.ptr -> i64
      %400 = arith.constant 2 : i32
      %401 = arith.extsi %400 : i32 to i64
      %399 = func.call @u64_shl(%401, %arg1) : (i64, i64) -> i64
      %402 = arith.addi %398, %399 : i64
      %404 = llvm.mlir.addressof @ht_count : !llvm.ptr
      %405 = llvm.load %404 : !llvm.ptr -> i64
      %406 = arith.constant 1 : i32
      %408 = arith.extsi %406 : i32 to i64
      %407 = arith.addi %405, %408 : i64
      func.call @solver_ensure_table(%407) : (i64) -> ()
      %409 = func.call @solver_lookup(%402) : (i64) -> i64
      %410 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
      %411 = arith.constant 0 : i32
      %412 = arith.extsi %411 : i32 to i64
      %413 = llvm.insertvalue %412, %410[0] : !llvm.struct<(i64, i64, i64)>
      %414 = arith.constant 0 : i32
      %415 = arith.extsi %414 : i32 to i64
      %416 = llvm.insertvalue %415, %413[1] : !llvm.struct<(i64, i64, i64)>
      %417 = arith.constant 0 : i32
      %418 = arith.extsi %417 : i32 to i64
      %419 = llvm.insertvalue %418, %416[2] : !llvm.struct<(i64, i64, i64)>
      %420 = llvm.mlir.constant(1 : i64) : i64
      %421 = llvm.alloca %420 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
      llvm.store %419, %421 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
      %423 = llvm.mlir.addressof @ht_key : !llvm.ptr
      %424 = llvm.load %423 : !llvm.ptr -> !llvm.ptr
      %425 = llvm.getelementptr %424[%409] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %422 = llvm.load %425 : !llvm.ptr -> i64
      %426 = arith.cmpi eq, %422, %402 : i64
      %427 = scf.if %426 -> (i1) {
        %429 = llvm.mlir.addressof @ht_gen : !llvm.ptr
        %430 = llvm.load %429 : !llvm.ptr -> !llvm.ptr
        %431 = llvm.getelementptr %430[%409] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %428 = llvm.load %431 : !llvm.ptr -> i64
        %432 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
        %433 = llvm.load %432 : !llvm.ptr -> i64
        %434 = arith.cmpi eq, %428, %433 : i64
        scf.yield %434 : i1
      } else {
        %435 = arith.constant false
        scf.yield %435 : i1
      }
      cf.cond_br %427, ^bb45, ^bb46
      ^bb45:
        %436 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
        %438 = llvm.mlir.addressof @ht_ca : !llvm.ptr
        %439 = llvm.load %438 : !llvm.ptr -> !llvm.ptr
        %440 = llvm.getelementptr %439[%409] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %437 = llvm.load %440 : !llvm.ptr -> i64
        %441 = llvm.insertvalue %437, %436[0] : !llvm.struct<(i64, i64, i64)>
        %443 = llvm.mlir.addressof @ht_cb : !llvm.ptr
        %444 = llvm.load %443 : !llvm.ptr -> !llvm.ptr
        %445 = llvm.getelementptr %444[%409] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %442 = llvm.load %445 : !llvm.ptr -> i64
        %446 = llvm.insertvalue %442, %441[1] : !llvm.struct<(i64, i64, i64)>
        %448 = llvm.mlir.addressof @ht_ns : !llvm.ptr
        %449 = llvm.load %448 : !llvm.ptr -> !llvm.ptr
        %450 = llvm.getelementptr %449[%409] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %447 = llvm.load %450 : !llvm.ptr -> i64
        %451 = llvm.insertvalue %447, %446[2] : !llvm.struct<(i64, i64, i64)>
        llvm.store %451, %421 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
        %452 = llvm.load %421 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
        %453 = llvm.getelementptr %421[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
        %454 = llvm.load %453 : !llvm.ptr -> i64
        %455 = llvm.load %421 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
        %456 = llvm.getelementptr %421[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
        %457 = llvm.load %456 : !llvm.ptr -> i64
        %458 = arith.addi %454, %457 : i64
        %459 = llvm.load %384 : !llvm.ptr -> i64
        %460 = llvm.load %388 : !llvm.ptr -> i64
        %461 = arith.addi %459, %460 : i64
        %462 = arith.addi %461, %458 : i64
        %463 = arith.cmpi sgt, %462, %arg2 : i64
        cf.cond_br %463, ^bb48, ^bb49
        ^bb48:
          %465 = llvm.load %384 : !llvm.ptr -> i64
          %466 = arith.subi %arg2, %465 : i64
          %467 = llvm.load %388 : !llvm.ptr -> i64
          %468 = arith.subi %466, %467 : i64
          %469 = arith.constant 1 : i32
          %471 = arith.extsi %469 : i32 to i64
          %470 = arith.subi %arg1, %471 : i64
          %472 = llvm.load %391 : !llvm.ptr -> i64
          %464 = func.call @calc(%472, %470, %468) : (i64, i64, i64) -> !llvm.struct<(i64, i64, i64)>
          %473 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
          %474 = llvm.extractvalue %464[0] : !llvm.struct<(i64, i64, i64)>
          %475 = llvm.insertvalue %474, %473[0] : !llvm.struct<(i64, i64, i64)>
          %476 = llvm.extractvalue %464[1] : !llvm.struct<(i64, i64, i64)>
          %477 = llvm.insertvalue %476, %475[1] : !llvm.struct<(i64, i64, i64)>
          %478 = llvm.extractvalue %464[2] : !llvm.struct<(i64, i64, i64)>
          %479 = llvm.insertvalue %478, %477[2] : !llvm.struct<(i64, i64, i64)>
          %480 = llvm.mlir.constant(1 : i64) : i64
          %481 = llvm.alloca %480 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
          llvm.store %479, %481 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
          %482 = llvm.load %481 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
          llvm.store %482, %421 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
          cf.br ^bb50
        ^bb49:
          cf.br ^bb50
        ^bb50:
        cf.br ^bb47
      ^bb46:
        %484 = llvm.load %384 : !llvm.ptr -> i64
        %485 = arith.subi %arg2, %484 : i64
        %486 = llvm.load %388 : !llvm.ptr -> i64
        %487 = arith.subi %485, %486 : i64
        %488 = arith.constant 1 : i32
        %490 = arith.extsi %488 : i32 to i64
        %489 = arith.subi %arg1, %490 : i64
        %491 = llvm.load %391 : !llvm.ptr -> i64
        %483 = func.call @calc(%491, %489, %487) : (i64, i64, i64) -> !llvm.struct<(i64, i64, i64)>
        %492 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
        %493 = llvm.extractvalue %483[0] : !llvm.struct<(i64, i64, i64)>
        %494 = llvm.insertvalue %493, %492[0] : !llvm.struct<(i64, i64, i64)>
        %495 = llvm.extractvalue %483[1] : !llvm.struct<(i64, i64, i64)>
        %496 = llvm.insertvalue %495, %494[1] : !llvm.struct<(i64, i64, i64)>
        %497 = llvm.extractvalue %483[2] : !llvm.struct<(i64, i64, i64)>
        %498 = llvm.insertvalue %497, %496[2] : !llvm.struct<(i64, i64, i64)>
        %499 = llvm.mlir.constant(1 : i64) : i64
        %500 = llvm.alloca %499 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
        llvm.store %498, %500 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
        %501 = llvm.load %500 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
        llvm.store %501, %421 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
        cf.br ^bb47
      ^bb47:
      %502 = llvm.load %384 : !llvm.ptr -> i64
      %503 = llvm.load %421 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      %504 = llvm.getelementptr %421[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
      %505 = llvm.load %504 : !llvm.ptr -> i64
      %506 = arith.addi %502, %505 : i64
      llvm.store %506, %384 : i64, !llvm.ptr
      %507 = llvm.load %388 : !llvm.ptr -> i64
      %508 = llvm.load %421 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      %509 = llvm.getelementptr %421[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
      %510 = llvm.load %509 : !llvm.ptr -> i64
      %511 = arith.addi %507, %510 : i64
      llvm.store %511, %388 : i64, !llvm.ptr
      %512 = llvm.load %421 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      %513 = llvm.getelementptr %421[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
      %514 = llvm.load %513 : !llvm.ptr -> i64
      llvm.store %514, %391 : i64, !llvm.ptr
      %515 = llvm.load %395 : !llvm.ptr -> i64
      %516 = arith.constant 1 : i32
      %518 = arith.extsi %516 : i32 to i64
      %517 = arith.addi %515, %518 : i64
      llvm.store %517, %395 : i64, !llvm.ptr
      cf.br ^bb42
    ^bb44:
    %519 = llvm.load %391 : !llvm.ptr -> i64
    %520 = arith.xori %519, %319 : i64
    %522 = arith.constant 1 : i32
    %523 = arith.extsi %522 : i32 to i64
    %521 = func.call @u64_shl(%523, %arg1) : (i64, i64) -> i64
    %524 = arith.xori %520, %521 : i64
    %525 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
    %526 = llvm.load %384 : !llvm.ptr -> i64
    %527 = llvm.insertvalue %526, %525[0] : !llvm.struct<(i64, i64, i64)>
    %528 = llvm.load %388 : !llvm.ptr -> i64
    %529 = llvm.insertvalue %528, %527[1] : !llvm.struct<(i64, i64, i64)>
    %530 = llvm.insertvalue %524, %529[2] : !llvm.struct<(i64, i64, i64)>
    %531 = llvm.mlir.constant(1 : i64) : i64
    %532 = llvm.alloca %531 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
    llvm.store %530, %532 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
    %534 = arith.constant 4 : i32
    %535 = arith.extsi %534 : i32 to i64
    %533 = func.call @u64_shl(%535, %arg1) : (i64, i64) -> i64
    %536 = arith.addi %arg0, %533 : i64
    %538 = llvm.mlir.addressof @ht_count : !llvm.ptr
    %539 = llvm.load %538 : !llvm.ptr -> i64
    %540 = arith.constant 1 : i32
    %542 = arith.extsi %540 : i32 to i64
    %541 = arith.addi %539, %542 : i64
    func.call @solver_ensure_table(%541) : (i64) -> ()
    %543 = func.call @solver_lookup(%536) : (i64) -> i64
    %545 = llvm.mlir.addressof @ht_key : !llvm.ptr
    %546 = llvm.load %545 : !llvm.ptr -> !llvm.ptr
    %547 = llvm.getelementptr %546[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %544 = llvm.load %547 : !llvm.ptr -> i64
    %548 = arith.cmpi ne, %544, %536 : i64
    %549 = scf.if %548 -> (i1) {
      %550 = arith.constant true
      scf.yield %550 : i1
    } else {
      %552 = llvm.mlir.addressof @ht_gen : !llvm.ptr
      %553 = llvm.load %552 : !llvm.ptr -> !llvm.ptr
      %554 = llvm.getelementptr %553[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %551 = llvm.load %554 : !llvm.ptr -> i64
      %555 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
      %556 = llvm.load %555 : !llvm.ptr -> i64
      %557 = arith.cmpi ne, %551, %556 : i64
      scf.yield %557 : i1
    }
    cf.cond_br %549, ^bb51, ^bb52
    ^bb51:
      %558 = llvm.mlir.addressof @ht_key : !llvm.ptr
      %559 = llvm.load %558 : !llvm.ptr -> !llvm.ptr
      %560 = llvm.getelementptr %559[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %536, %560 : i64, !llvm.ptr
      %561 = llvm.mlir.addressof @ht_gen_val : !llvm.ptr
      %562 = llvm.load %561 : !llvm.ptr -> i64
      %563 = llvm.mlir.addressof @ht_gen : !llvm.ptr
      %564 = llvm.load %563 : !llvm.ptr -> !llvm.ptr
      %565 = llvm.getelementptr %564[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %562, %565 : i64, !llvm.ptr
      %566 = llvm.mlir.addressof @ht_count : !llvm.ptr
      %567 = llvm.load %566 : !llvm.ptr -> i64
      %568 = arith.constant 1 : i32
      %570 = arith.extsi %568 : i32 to i64
      %569 = arith.addi %567, %570 : i64
      %571 = llvm.mlir.addressof @ht_count : !llvm.ptr
      llvm.store %569, %571 : i64, !llvm.ptr
      cf.br ^bb53
    ^bb52:
      cf.br ^bb53
    ^bb53:
    %572 = llvm.load %532 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    %573 = llvm.getelementptr %532[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
    %574 = llvm.load %573 : !llvm.ptr -> i64
    %575 = llvm.mlir.addressof @ht_ca : !llvm.ptr
    %576 = llvm.load %575 : !llvm.ptr -> !llvm.ptr
    %577 = llvm.getelementptr %576[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %574, %577 : i64, !llvm.ptr
    %578 = llvm.load %532 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    %579 = llvm.getelementptr %532[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
    %580 = llvm.load %579 : !llvm.ptr -> i64
    %581 = llvm.mlir.addressof @ht_cb : !llvm.ptr
    %582 = llvm.load %581 : !llvm.ptr -> !llvm.ptr
    %583 = llvm.getelementptr %582[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %580, %583 : i64, !llvm.ptr
    %584 = llvm.load %532 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    %585 = llvm.getelementptr %532[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
    %586 = llvm.load %585 : !llvm.ptr -> i64
    %587 = llvm.mlir.addressof @ht_ns : !llvm.ptr
    %588 = llvm.load %587 : !llvm.ptr -> !llvm.ptr
    %589 = llvm.getelementptr %588[%543] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %586, %589 : i64, !llvm.ptr
    %590 = llvm.load %532 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    %591 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
    %592 = llvm.extractvalue %590[0] : !llvm.struct<(i64, i64, i64)>
    %593 = llvm.insertvalue %592, %591[0] : !llvm.struct<(i64, i64, i64)>
    %594 = llvm.extractvalue %590[1] : !llvm.struct<(i64, i64, i64)>
    %595 = llvm.insertvalue %594, %593[1] : !llvm.struct<(i64, i64, i64)>
    %596 = llvm.extractvalue %590[2] : !llvm.struct<(i64, i64, i64)>
    %597 = llvm.insertvalue %596, %595[2] : !llvm.struct<(i64, i64, i64)>
    %598 = llvm.mlir.constant(1 : i64) : i64
    %599 = llvm.alloca %598 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
    llvm.store %597, %599 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
    %600 = llvm.load %599 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    func.return %600 : !llvm.struct<(i64, i64, i64)>
  }
  func.func @compute_T(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    func.call @solver_init(%arg0, %arg1) : (i64, i64) -> ()
    %602 = arith.constant 0 : i32
    %603 = arith.extsi %602 : i32 to i64
    %604 = llvm.mlir.constant(1 : i64) : i64
    %605 = llvm.alloca %604 x i64 : (i64) -> !llvm.ptr
    llvm.store %603, %605 : i64, !llvm.ptr
    %606 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
    %607 = arith.constant 0 : i32
    %608 = arith.extsi %607 : i32 to i64
    %609 = llvm.insertvalue %608, %606[0] : !llvm.struct<(i64, i64, i64)>
    %610 = arith.constant 0 : i32
    %611 = arith.extsi %610 : i32 to i64
    %612 = llvm.insertvalue %611, %609[1] : !llvm.struct<(i64, i64, i64)>
    %613 = arith.constant 0 : i32
    %614 = arith.extsi %613 : i32 to i64
    %615 = llvm.insertvalue %614, %612[2] : !llvm.struct<(i64, i64, i64)>
    %616 = llvm.mlir.constant(1 : i64) : i64
    %617 = llvm.alloca %616 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
    llvm.store %615, %617 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
    cf.br ^bb54
    ^bb54:
    %618 = arith.constant 1 : i1
    cf.cond_br %618, ^bb55, ^bb56
    ^bb55:
      %620 = llvm.load %605 : !llvm.ptr -> i64
      %621 = arith.constant 0 : i32
      %622 = arith.extsi %621 : i32 to i64
      %619 = func.call @calc(%622, %620, %arg2) : (i64, i64, i64) -> !llvm.struct<(i64, i64, i64)>
      %623 = llvm.mlir.undef : !llvm.struct<(i64, i64, i64)>
      %624 = llvm.extractvalue %619[0] : !llvm.struct<(i64, i64, i64)>
      %625 = llvm.insertvalue %624, %623[0] : !llvm.struct<(i64, i64, i64)>
      %626 = llvm.extractvalue %619[1] : !llvm.struct<(i64, i64, i64)>
      %627 = llvm.insertvalue %626, %625[1] : !llvm.struct<(i64, i64, i64)>
      %628 = llvm.extractvalue %619[2] : !llvm.struct<(i64, i64, i64)>
      %629 = llvm.insertvalue %628, %627[2] : !llvm.struct<(i64, i64, i64)>
      %630 = llvm.mlir.constant(1 : i64) : i64
      %631 = llvm.alloca %630 x !llvm.struct<(i64, i64, i64)> : (i64) -> !llvm.ptr
      llvm.store %629, %631 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
      %632 = llvm.load %631 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      llvm.store %632, %617 : !llvm.struct<(i64, i64, i64)>, !llvm.ptr
      %633 = llvm.load %605 : !llvm.ptr -> i64
      %634 = arith.constant 1 : i32
      %636 = arith.extsi %634 : i32 to i64
      %635 = arith.addi %633, %636 : i64
      llvm.store %635, %605 : i64, !llvm.ptr
      %637 = llvm.load %617 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      %638 = llvm.getelementptr %617[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
      %639 = llvm.load %638 : !llvm.ptr -> i64
      %640 = llvm.load %617 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
      %641 = llvm.getelementptr %617[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
      %642 = llvm.load %641 : !llvm.ptr -> i64
      %643 = arith.addi %639, %642 : i64
      %644 = arith.cmpi sge, %643, %arg2 : i64
      cf.cond_br %644, ^bb57, ^bb58
      ^bb57:
        cf.br ^bb56
      ^bb58:
        cf.br ^bb59
      ^bb59:
      %645 = llvm.load %605 : !llvm.ptr -> i64
      %646 = arith.constant 64 : i32
      %648 = arith.extsi %646 : i32 to i64
      %647 = arith.cmpi sge, %645, %648 : i64
      cf.cond_br %647, ^bb60, ^bb61
      ^bb60:
        cf.br ^bb56
      ^bb61:
        cf.br ^bb62
      ^bb62:
      cf.br ^bb54
    ^bb56:
    %649 = llvm.load %617 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    %650 = llvm.getelementptr %617[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
    %651 = llvm.load %650 : !llvm.ptr -> i64
    %652 = arith.muli %651, %arg0 : i64
    %653 = llvm.load %617 : !llvm.ptr -> !llvm.struct<(i64, i64, i64)>
    %654 = llvm.getelementptr %617[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64)>
    %655 = llvm.load %654 : !llvm.ptr -> i64
    %656 = arith.muli %655, %arg1 : i64
    %657 = arith.addi %652, %656 : i64
    func.return %657 : i64
  }
  func.func @main() -> i32 {
    %659 = arith.constant 2 : i32
    %660 = arith.constant 3 : i32
    %661 = arith.constant 10 : i32
    %662 = arith.extsi %659 : i32 to i64
    %663 = arith.extsi %660 : i32 to i64
    %664 = arith.extsi %661 : i32 to i64
    %658 = func.call @compute_T(%662, %663, %664) : (i64, i64, i64) -> i64
    %665 = arith.constant 25 : i32
    %667 = arith.extsi %665 : i32 to i64
    %666 = arith.cmpi ne, %658, %667 : i64
    cf.cond_br %666, ^bb63, ^bb64
    ^bb63:
      %668 = llvm.mlir.addressof @str_0 : !llvm.ptr
      %669 = llvm.call @printf(%668) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr) -> i32
      %670 = arith.constant 1 : i32
      func.return %670 : i32
    ^bb64:
      cf.br ^bb65
    ^bb65:
    %672 = arith.constant 4 : i32
    %673 = arith.constant 2 : i32
    %674 = arith.constant 10000 : i32
    %675 = arith.extsi %672 : i32 to i64
    %676 = arith.extsi %673 : i32 to i64
    %677 = arith.extsi %674 : i32 to i64
    %671 = func.call @compute_T(%675, %676, %677) : (i64, i64, i64) -> i64
    %678 = arith.constant 30004 : i32
    %680 = arith.extsi %678 : i32 to i64
    %679 = arith.cmpi ne, %671, %680 : i64
    cf.cond_br %679, ^bb66, ^bb67
    ^bb66:
      %681 = llvm.mlir.addressof @str_1 : !llvm.ptr
      %682 = llvm.call @printf(%681) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr) -> i32
      %683 = arith.constant 1 : i32
      func.return %683 : i32
    ^bb67:
      cf.br ^bb68
    ^bb68:
    %684 = arith.constant -2061744963 : i32
    %685 = arith.extsi %684 : i32 to i64
    %686 = arith.constant 22327928364937 : i32
    %687 = arith.extsi %686 : i32 to i64
    %688 = arith.constant 0 : i32
    %689 = arith.extsi %688 : i32 to i64
    %690 = llvm.mlir.constant(1 : i64) : i64
    %691 = llvm.alloca %690 x i64 : (i64) -> !llvm.ptr
    llvm.store %689, %691 : i64, !llvm.ptr
    %692 = arith.constant 2 : i32
    %693 = arith.extsi %692 : i32 to i64
    %694 = llvm.mlir.constant(1 : i64) : i64
    %695 = llvm.alloca %694 x i64 : (i64) -> !llvm.ptr
    llvm.store %693, %695 : i64, !llvm.ptr
    cf.br ^bb69
    ^bb69:
    %696 = llvm.load %695 : !llvm.ptr -> i64
    %697 = arith.constant 224 : i32
    %699 = arith.extsi %697 : i32 to i64
    %698 = arith.cmpi slt, %696, %699 : i64
    cf.cond_br %698, ^bb70, ^bb71
    ^bb70:
      %700 = arith.constant 2 : i32
      %701 = arith.extsi %700 : i32 to i64
      %702 = llvm.mlir.constant(1 : i64) : i64
      %703 = llvm.alloca %702 x i64 : (i64) -> !llvm.ptr
      llvm.store %701, %703 : i64, !llvm.ptr
      cf.br ^bb72
      ^bb72:
      %704 = llvm.load %703 : !llvm.ptr -> i64
      %705 = arith.constant 224 : i32
      %707 = arith.extsi %705 : i32 to i64
      %706 = arith.cmpi slt, %704, %707 : i64
      cf.cond_br %706, ^bb73, ^bb74
      ^bb73:
        %708 = llvm.load %695 : !llvm.ptr -> i64
        %709 = llvm.load %703 : !llvm.ptr -> i64
        %710 = arith.cmpi ne, %708, %709 : i64
        cf.cond_br %710, ^bb75, ^bb76
        ^bb75:
          %712 = llvm.load %695 : !llvm.ptr -> i64
          %713 = llvm.load %703 : !llvm.ptr -> i64
          %711 = func.call @compute_T(%712, %713, %687) : (i64, i64, i64) -> i64
          %714 = arith.remsi %711, %685 : i64
          %715 = llvm.load %691 : !llvm.ptr -> i64
          %716 = arith.addi %715, %714 : i64
          %717 = arith.remsi %716, %685 : i64
          llvm.store %717, %691 : i64, !llvm.ptr
          cf.br ^bb77
        ^bb76:
          cf.br ^bb77
        ^bb77:
        %718 = llvm.load %703 : !llvm.ptr -> i64
        %719 = arith.constant 1 : i32
        %721 = arith.extsi %719 : i32 to i64
        %720 = arith.addi %718, %721 : i64
        llvm.store %720, %703 : i64, !llvm.ptr
        cf.br ^bb72
      ^bb74:
      %722 = llvm.load %695 : !llvm.ptr -> i64
      %723 = arith.constant 1 : i32
      %725 = arith.extsi %723 : i32 to i64
      %724 = arith.addi %722, %725 : i64
      llvm.store %724, %695 : i64, !llvm.ptr
      cf.br ^bb69
    ^bb71:
    %726 = llvm.mlir.addressof @str_2 : !llvm.ptr
    %727 = llvm.load %691 : !llvm.ptr -> i64
    %728 = arith.remsi %727, %685 : i64
    %729 = llvm.call @printf(%726, %728) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %730 = arith.constant 0 : i32
    func.return %730 : i32
  }
}