Problem 933

Two-player impartial game on integer rectangles. A move cuts one rectangle once vertically and once horizontally into four smaller rectangles (all sides positive integers). No move means lose. Compute D(123, 1234567) via Sprague-Grundy nimbers and quadruple counting. Pure Flow port of the native C solver.

Answer5707485980743099
Output5707485980743099
StatusPASS
Native helperno
Runtime6700 ms
Peak memory14128 KB
Time complexityO(n^3) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

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

Flow source

# Project Euler 933: Paper Cutting.
# Two-player impartial game on integer rectangles. A move cuts one
# rectangle once vertically and once horizontally into four smaller
# rectangles (all sides positive integers). No move means lose.
# Compute D(123, 1234567) via Sprague-Grundy nimbers and quadruple counting.
# Pure Flow port of the native C solver.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
    function malloc(n: i64) -> ptr<void>
    function realloc(p: ptr<void>, n: i64) -> ptr<void>
    function memset(dst: ptr<void>, val: i32, n: i64) -> void
    function printf(fmt: ptr<i8>, ...) -> i32
}

let mut B_arr: ptr<i32> = null as ptr<i32>
let mut g_const_arr: ptr<i32> = null as ptr<i32>
let mut const_arr: ptr<i32> = null as ptr<i32>
let mut G_arr: ptr<ptr<i32> > = null as ptr<ptr<i32> >
let mut visited: ptr<i32> = null as ptr<i32>
let mut vis_size: i32 = 0
let mut stamp: i32 = 0
let mut prev_maxg: i32 = 0
let mut current_w: i32 = 0
let mut W_alloc: i32 = 0

function grundy_init() -> void {
    W_alloc = 4
    B_arr = (calloc((W_alloc as i64), 4)) as ptr<i32>
    g_const_arr = (calloc((W_alloc as i64), 4)) as ptr<i32>
    const_arr = (calloc((W_alloc as i64), 4)) as ptr<i32>
    G_arr = (calloc((W_alloc as i64), 8)) as ptr<ptr<i32> >
    B_arr[1] = 1
    g_const_arr[1] = 1
    G_arr[1] = (calloc(2, 4)) as ptr<i32>
    G_arr[1][0] = 0
    G_arr[1][1] = 0
    vis_size = 32768
    visited = (calloc((vis_size as i64), 4)) as ptr<i32>
    stamp = 1
    prev_maxg = 1
    current_w = 1
}

function ensure_size(n: i32) -> void {
    if n < W_alloc { return }
    let mut na: i32 = W_alloc
    while na <= n {
        na = na * 2
    }
    B_arr = (realloc(B_arr as ptr<void>, (na as i64) * 4)) as ptr<i32>
    g_const_arr = (realloc(g_const_arr as ptr<void>, (na as i64) * 4)) as ptr<i32>
    const_arr = (realloc(const_arr as ptr<void>, (na as i64) * 4)) as ptr<i32>
    G_arr = (realloc(G_arr as ptr<void>, (na as i64) * 8)) as ptr<ptr<i32> >
    memset((B_arr + W_alloc) as ptr<void>, 0, ((na - W_alloc) as i64) * 4)
    memset((g_const_arr + W_alloc) as ptr<void>, 0, ((na - W_alloc) as i64) * 4)
    memset((const_arr + W_alloc) as ptr<void>, 0, ((na - W_alloc) as i64) * 4)
    memset((G_arr + W_alloc) as ptr<void>, 0, ((na - W_alloc) as i64) * 8)
    W_alloc = na
}

function getG(wi0: i32, hi0: i32) -> i32 {
    let mut wi: i32 = wi0
    let mut hi: i32 = hi0
    if wi > hi {
        let t: i32 = wi
        wi = hi
        hi = t
    }
    if wi <= 1 { return 0 }
    if hi <= B_arr[wi] { return G_arr[wi][hi] }
    return const_arr[wi]
}

function mark_visited(v: i32) -> void {
    if v < vis_size {
        visited[v] = stamp
    } else {
        let mut ns: i32 = vis_size
        while ns <= v {
            ns = ns * 2
        }
        visited = (realloc(visited as ptr<void>, (ns as i64) * 4)) as ptr<i32>
        memset((visited + vis_size) as ptr<void>, 0, ((ns - vis_size) as i64) * 4)
        vis_size = ns
        visited[v] = stamp
    }
}

# Compute nimbers g_w[h] for h in [h_start..h_end].
function compute_h_range(h_start: i32, h_end: i32, g_w: ptr<i32>,
                         Vs: ptr<ptr<i32> >, t_as: ptr<i32>, half_w: i32) -> void {
    let mut h: i32 = h_start
    while h <= h_end {
        stamp = stamp + 1
        let half_h: i32 = h >> 1
        let mut a_idx: i32 = 0
        while a_idx < half_w {
            let V: ptr<i32> = Vs[a_idx]
            let ta: i32 = t_as[a_idx]
            let mut maxb: i32 = 0
            if half_h >= ta {
                visited[0] = stamp
                maxb = ta - 1
                if maxb > half_h { maxb = half_h }
            } else {
                maxb = half_h
            }
            let mut b: i32 = 1
            while b <= maxb {
                let v: i32 = V[b] ^ V[h - b]
                mark_visited(v)
                b = b + 1
            }
            a_idx = a_idx + 1
        }
        let mut m: i32 = 0
        while visited[m] == stamp {
            m = m + 1
        }
        g_w[h] = m
        h = h + 1
    }
}

function compute_next() -> void {
    let w: i32 = current_w + 1
    ensure_size(w)

    let mut limit: i32 = 0
    if w > 2 * prev_maxg {
        limit = w
    } else {
        limit = 2 * prev_maxg
    }

    let mut g_w: ptr<i32> = (calloc(((limit + 1) as i64), 4)) as ptr<i32>

    # Fill h < w by symmetry
    let mut upto: i32 = w
    if upto > limit + 1 { upto = limit + 1 }
    let mut h: i32 = 1
    while h < upto {
        g_w[h] = getG(h, w)
        h = h + 1
    }

    let half_w: i32 = w >> 1

    # Precompute V arrays and t_as for each vertical split
    let Vs: ptr<ptr<i32> > = (malloc((half_w as i64) * 8)) as ptr<ptr<i32> >
    let t_as: ptr<i32> = (malloc((half_w as i64) * 4)) as ptr<i32>
    let mut a: i32 = 1
    while a <= half_w {
        let bw: i32 = w - a
        let mut ta: i32 = g_const_arr[a]
        if g_const_arr[bw] > ta { ta = g_const_arr[bw] }
        t_as[a - 1] = ta
        let V: ptr<i32> = (calloc(((limit + 1) as i64), 4)) as ptr<i32>
        let mut b: i32 = 1
        while b <= limit {
            V[b] = getG(a, b) ^ getG(bw, b)
            b = b + 1
        }
        Vs[a - 1] = V
        a = a + 1
    }

    compute_h_range(w, limit, g_w, Vs, t_as, half_w)

    # Track last change index
    let mut last: i32 = 1
    let mut hh: i32 = 2
    while hh <= limit {
        if g_w[hh] != g_w[hh - 1] { last = hh }
        hh = hh + 1
    }

    # Extend until stability: constant on [last, 2*last] => constant forever
    while true {
        let need: i32 = 2 * last
        if need <= limit {
            let v0: i32 = g_w[last]
            let mut ok: i32 = 1
            let mut hhh: i32 = last + 1
            while hhh <= need {
                if g_w[hhh] != v0 {
                    ok = 0
                    break
                }
                hhh = hhh + 1
            }
            if ok != 0 { break }
        }

        let mut new_limit: i32 = limit * 2
        if need > new_limit { new_limit = need }
        if w > new_limit { new_limit = w }

        g_w = (realloc(g_w as ptr<void>, ((new_limit + 1) as i64) * 4)) as ptr<i32>
        memset((g_w + limit + 1) as ptr<void>, 0, ((new_limit - limit) as i64) * 4)

        let mut a_idx2: i32 = 0
        while a_idx2 < half_w {
            Vs[a_idx2] = (realloc(Vs[a_idx2] as ptr<void>, ((new_limit + 1) as i64) * 4)) as ptr<i32>
            let V: ptr<i32> = Vs[a_idx2]
            let mut b2: i32 = limit + 1
            while b2 <= new_limit {
                V[b2] = getG(a_idx2 + 1, b2) ^ getG(w - a_idx2 - 1, b2)
                b2 = b2 + 1
            }
            a_idx2 = a_idx2 + 1
        }

        compute_h_range(limit + 1, new_limit, g_w, Vs, t_as, half_w)
        limit = new_limit

        let mut h4: i32 = last + 1
        while h4 <= limit {
            if g_w[h4] != g_w[h4 - 1] { last = h4 }
            h4 = h4 + 1
        }
    }

    B_arr[w] = limit
    g_const_arr[w] = last
    const_arr[w] = g_w[last]
    G_arr[w] = g_w
    current_w = w
    if last > prev_maxg { prev_maxg = last }

    let mut a_idx3: i32 = 0
    while a_idx3 < half_w {
        free(Vs[a_idx3] as ptr<void>)
        a_idx3 = a_idx3 + 1
    }
    free(Vs as ptr<void>)
    free(t_as as ptr<void>)
}

function compute_upto(W: i32) -> void {
    while current_w < W {
        compute_next()
    }
}

# Directly count winning moves for a single rectangle w x h.
function count_winning_moves_C(w: i32, h: i32) -> i64 {
    let mut cnt: i64 = 0
    let mut x: i32 = 1
    while x < w {
        let mut y: i32 = 1
        while y < h {
            let v: i32 = getG(x, y) ^ getG(w - x, y) ^ getG(x, h - y) ^ getG(w - x, h - y)
            if v == 0 { cnt = cnt + 1 }
            y = y + 1
        }
        x = x + 1
    }
    return cnt
}

# Compute D(W,H) via quadruple counting over ordered splits.
function compute_D(W: i32, H: i64) -> i64 {
    let mut max_m: i32 = 0
    let mut w: i32 = 1
    while w <= W {
        if g_const_arr[w] > max_m { max_m = g_const_arr[w] }
        w = w + 1
    }

    let mut max_k: i32 = max_m
    if ((H - 1) as i32) < max_k { max_k = (H - 1) as i32 }

    # Precompute row[u][k] = G(u,k) for u=1..W, k=1..max_k
    let row: ptr<ptr<i32> > = (malloc(((W + 1) as i64) * 8)) as ptr<ptr<i32> >
    let mut u: i32 = 0
    while u <= W {
        row[u] = (calloc(((max_k + 1) as i64), 4)) as ptr<i32>
        u = u + 1
    }
    u = 1
    while u <= W {
        let mut k: i32 = 1
        while k <= max_k {
            row[u][k] = getG(u, k)
            k = k + 1
        }
        u = u + 1
    }

    # Stamp-based counting arrays for the fast branch
    let mut cnts_sz: i32 = 65536
    let mut cnts_stamp: ptr<i32> = (calloc((cnts_sz as i64), 4)) as ptr<i32>
    let mut cnts_count: ptr<i32> = (calloc((cnts_sz as i64), 4)) as ptr<i32>
    let mut cnts_list: ptr<i32> = (malloc((cnts_sz as i64) * 4)) as ptr<i32>
    let mut cur_stamp: i32 = 0

    let mut total: i64 = 0

    let mut i: i32 = 1
    while i < W {
        let ri: ptr<i32> = row[i]
        let mut j: i32 = 1
        while j <= W - i {
            let rj: ptr<i32> = row[j]
            let mut m: i32 = g_const_arr[i]
            if g_const_arr[j] > m { m = g_const_arr[j] }
            let const_t: i32 = const_arr[i] ^ const_arr[j]

            if H >= 2 * (m as i64) {
                # Fast branch
                let L: i32 = m - 1
                let mut countA: i64 = 0
                let mut countB: i64 = 0
                let mut countC: i64 = 0
                let mut count_eq: i64 = 0
                let mut sum_k_eq: i64 = 0

                if L > 0 {
                    cur_stamp = cur_stamp + 1
                    let mut nvisited: i32 = 0
                    let mut k: i32 = 1
                    while k <= L {
                        let t: i32 = ri[k] ^ rj[k]
                        if t >= cnts_sz {
                            let mut ns: i32 = cnts_sz
                            while ns <= t {
                                ns = ns * 2
                            }
                            cnts_stamp = (realloc(cnts_stamp as ptr<void>, (ns as i64) * 4)) as ptr<i32>
                            cnts_count = (realloc(cnts_count as ptr<void>, (ns as i64) * 4)) as ptr<i32>
                            cnts_list = (realloc(cnts_list as ptr<void>, (ns as i64) * 4)) as ptr<i32>
                            memset((cnts_stamp + cnts_sz) as ptr<void>, 0, ((ns - cnts_sz) as i64) * 4)
                            cnts_sz = ns
                        }
                        if cnts_stamp[t] != cur_stamp {
                            cnts_stamp[t] = cur_stamp
                            cnts_count[t] = 1
                            cnts_list[nvisited] = t
                            nvisited = nvisited + 1
                        } else {
                            cnts_count[t] = cnts_count[t] + 1
                        }
                        if t == const_t {
                            count_eq = count_eq + 1
                            sum_k_eq = sum_k_eq + (k as i64)
                        }
                        k = k + 1
                    }
                    let mut idx: i32 = 0
                    while idx < nvisited {
                        let c: i64 = (cnts_count[cnts_list[idx]]) as i64
                        countA = countA + c * c
                        idx = idx + 1
                    }
                }

                if count_eq != 0 {
                    countB = 2 * (count_eq * (H - (m as i64) + 1) - sum_k_eq)
                }

                let S: i64 = H - 2 * (m as i64)
                if S >= 0 {
                    countC = (S + 1) * (S + 2) / 2
                }

                total = total + countA + countB + countC
            } else {
                # Generic smaller-H branch
                let t_arr: ptr<i32> = (malloc((H as i64) * 4)) as ptr<i32>
                let mut k: i32 = 1
                while k < (H as i32) {
                    if k <= max_k {
                        t_arr[k] = ri[k] ^ rj[k]
                    } else {
                        t_arr[k] = const_t
                    }
                    k = k + 1
                }
                k = 1
                while k < (H as i32) {
                    let tk: i32 = t_arr[k]
                    let mut l: i32 = 1
                    while l <= (H as i32) - k {
                        if tk == t_arr[l] { total = total + 1 }
                        l = l + 1
                    }
                    k = k + 1
                }
                free(t_arr as ptr<void>)
            }
            j = j + 1
        }
        i = i + 1
    }

    u = 0
    while u <= W {
        free(row[u] as ptr<void>)
        u = u + 1
    }
    free(row as ptr<void>)
    free(cnts_stamp as ptr<void>)
    free(cnts_count as ptr<void>)
    free(cnts_list as ptr<void>)

    return total
}

function main() -> i32 {
    grundy_init()
    compute_upto(123)

    # Self-tests from the problem statement
    if count_winning_moves_C(5, 3) != 4 {
        printf("p933 self-test C(5,3) failed\n")
        return -1
    }
    if compute_D(12, 123) != 327398 {
        printf("p933 self-test D(12,123) failed\n")
        return -1
    }

    let result: i64 = compute_D(123, 1234567)
    printf("%lld\n", result)
    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; }

void grundy_init(void);
void ensure_size_i32(int32_t n);
int32_t getG_i32_i32(int32_t wi0, int32_t hi0);
void mark_visited_i32(int32_t v);
void compute_h_range_i32_i32_ptr_i32_ptr_ptr_i32_ptr_i32_i32(int32_t h_start, int32_t h_end, int32_t* g_w, int32_t** Vs, int32_t* t_as, int32_t half_w);
void compute_next(void);
void compute_upto_i32(int32_t W);
int64_t count_winning_moves_C_i32_i32(int32_t w, int32_t h);
int64_t compute_D_i32_i64(int32_t W, int64_t H);
int32_t main(void);

/* Module statics */
static int32_t* B_arr = ((int32_t*)(NULL));
static int32_t* g_const_arr = ((int32_t*)(NULL));
static int32_t* const_arr = ((int32_t*)(NULL));
static int32_t** G_arr = ((int32_t**)(NULL));
static int32_t* visited = ((int32_t*)(NULL));
static int32_t vis_size = 0;
static int32_t stamp = 0;
static int32_t prev_maxg = 0;
static int32_t current_w = 0;
static int32_t W_alloc = 0;







void grundy_init(void) {
    W_alloc = 4;
    B_arr = ((int32_t*)(calloc(((int64_t)(W_alloc)), 4)));
    g_const_arr = ((int32_t*)(calloc(((int64_t)(W_alloc)), 4)));
    const_arr = ((int32_t*)(calloc(((int64_t)(W_alloc)), 4)));
    G_arr = ((int32_t**)(calloc(((int64_t)(W_alloc)), 8)));
    B_arr[1] = 1;
    g_const_arr[1] = 1;
    G_arr[1] = ((int32_t*)(calloc(2, 4)));
    G_arr[1][0] = 0;
    G_arr[1][1] = 0;
    vis_size = 32768;
    visited = ((int32_t*)(calloc(((int64_t)(vis_size)), 4)));
    stamp = 1;
    prev_maxg = 1;
    current_w = 1;
}

void ensure_size_i32(int32_t n) {
    if (n < W_alloc) {
        return;
    }
    int32_t na = W_alloc;
    while (na <= n) {
        na = (na * 2);
    }
    B_arr = ((int32_t*)(realloc(((void*)(B_arr)), (((int64_t)(na)) * 4))));
    g_const_arr = ((int32_t*)(realloc(((void*)(g_const_arr)), (((int64_t)(na)) * 4))));
    const_arr = ((int32_t*)(realloc(((void*)(const_arr)), (((int64_t)(na)) * 4))));
    G_arr = ((int32_t**)(realloc(((void*)(G_arr)), (((int64_t)(na)) * 8))));
    memset(((void*)((B_arr + W_alloc))), 0, (((int64_t)((na - W_alloc))) * 4));
    memset(((void*)((g_const_arr + W_alloc))), 0, (((int64_t)((na - W_alloc))) * 4));
    memset(((void*)((const_arr + W_alloc))), 0, (((int64_t)((na - W_alloc))) * 4));
    memset(((void*)((G_arr + W_alloc))), 0, (((int64_t)((na - W_alloc))) * 8));
    W_alloc = na;
}

int32_t getG_i32_i32(int32_t wi0, int32_t hi0) {
    int32_t wi = wi0;
    int32_t hi = hi0;
    if (wi > hi) {
        int32_t t = wi;
        wi = hi;
        hi = t;
    }
    if (wi <= 1) {
        return 0;
    }
    if (hi <= B_arr[wi]) {
        return G_arr[wi][hi];
    }
    return const_arr[wi];
}

void mark_visited_i32(int32_t v) {
    if (v < vis_size) {
        visited[v] = stamp;
    } else {
        int32_t ns = vis_size;
        while (ns <= v) {
            ns = (ns * 2);
        }
        visited = ((int32_t*)(realloc(((void*)(visited)), (((int64_t)(ns)) * 4))));
        memset(((void*)((visited + vis_size))), 0, (((int64_t)((ns - vis_size))) * 4));
        vis_size = ns;
        visited[v] = stamp;
    }
}

void compute_h_range_i32_i32_ptr_i32_ptr_ptr_i32_ptr_i32_i32(int32_t h_start, int32_t h_end, int32_t* g_w, int32_t** Vs, int32_t* t_as, int32_t half_w) {
    int32_t h = h_start;
    while (h <= h_end) {
        stamp = (stamp + 1);
        int32_t half_h = FLOW_CHECKED_SHR((h), (1));
        int32_t a_idx = 0;
        while (a_idx < half_w) {
            int32_t* V = (int32_t*)(Vs[a_idx]);
            int32_t ta = t_as[a_idx];
            int32_t maxb = 0;
            if (half_h >= ta) {
                visited[0] = stamp;
                maxb = (ta - 1);
                if (maxb > half_h) {
                    maxb = half_h;
                }
            } else {
                maxb = half_h;
            }
            int32_t b = 1;
            while (b <= maxb) {
                int32_t v = (V[b] ^ V[(h - b)]);
                mark_visited_i32(v);
                b = (b + 1);
            }
            a_idx = (a_idx + 1);
        }
        int32_t m = 0;
        while (visited[m] == stamp) {
            m = (m + 1);
        }
        g_w[h] = m;
        h = (h + 1);
    }
}

void compute_next(void) {
    int32_t w = (current_w + 1);
    ensure_size_i32(w);
    int32_t limit = 0;
    if (w > (2 * prev_maxg)) {
        limit = w;
    } else {
        limit = (2 * prev_maxg);
    }
    int32_t* g_w = (int32_t*)(((int32_t*)(calloc(((int64_t)((limit + 1))), 4))));
    int32_t upto = w;
    if (upto > (limit + 1)) {
        upto = (limit + 1);
    }
    int32_t h = 1;
    while (h < upto) {
        g_w[h] = getG_i32_i32(h, w);
        h = (h + 1);
    }
    int32_t half_w = FLOW_CHECKED_SHR((w), (1));
    int32_t** Vs = (int32_t**)(((int32_t**)(malloc((((int64_t)(half_w)) * 8)))));
    int32_t* t_as = (int32_t*)(((int32_t*)(malloc((((int64_t)(half_w)) * 4)))));
    int32_t a = 1;
    while (a <= half_w) {
        int32_t bw = (w - a);
        int32_t ta = g_const_arr[a];
        if (g_const_arr[bw] > ta) {
            ta = g_const_arr[bw];
        }
        t_as[(a - 1)] = ta;
        int32_t* V = (int32_t*)(((int32_t*)(calloc(((int64_t)((limit + 1))), 4))));
        int32_t b = 1;
        while (b <= limit) {
            V[b] = (getG_i32_i32(a, b) ^ getG_i32_i32(bw, b));
            b = (b + 1);
        }
        Vs[(a - 1)] = V;
        a = (a + 1);
    }
    compute_h_range_i32_i32_ptr_i32_ptr_ptr_i32_ptr_i32_i32(w, limit, g_w, Vs, t_as, half_w);
    int32_t last = 1;
    int32_t hh = 2;
    while (hh <= limit) {
        if (g_w[hh] != g_w[(hh - 1)]) {
            last = hh;
        }
        hh = (hh + 1);
    }
    while (1) {
        int32_t need = (2 * last);
        if (need <= limit) {
            int32_t v0 = g_w[last];
            int32_t ok = 1;
            int32_t hhh = (last + 1);
            while (hhh <= need) {
                if (g_w[hhh] != v0) {
                    ok = 0;
                    break;
                }
                hhh = (hhh + 1);
            }
            if (ok != 0) {
                break;
            }
        }
        int32_t new_limit = (limit * 2);
        if (need > new_limit) {
            new_limit = need;
        }
        if (w > new_limit) {
            new_limit = w;
        }
        g_w = ((int32_t*)(realloc(((void*)(g_w)), (((int64_t)((new_limit + 1))) * 4))));
        memset(((void*)(((g_w + limit) + 1))), 0, (((int64_t)((new_limit - limit))) * 4));
        int32_t a_idx2 = 0;
        while (a_idx2 < half_w) {
            Vs[a_idx2] = ((int32_t*)(realloc(((void*)(Vs[a_idx2])), (((int64_t)((new_limit + 1))) * 4))));
            int32_t* V = (int32_t*)(Vs[a_idx2]);
            int32_t b2 = (limit + 1);
            while (b2 <= new_limit) {
                V[b2] = (getG_i32_i32((a_idx2 + 1), b2) ^ getG_i32_i32(((w - a_idx2) - 1), b2));
                b2 = (b2 + 1);
            }
            a_idx2 = (a_idx2 + 1);
        }
        compute_h_range_i32_i32_ptr_i32_ptr_ptr_i32_ptr_i32_i32((limit + 1), new_limit, g_w, Vs, t_as, half_w);
        limit = new_limit;
        int32_t h4 = (last + 1);
        while (h4 <= limit) {
            if (g_w[h4] != g_w[(h4 - 1)]) {
                last = h4;
            }
            h4 = (h4 + 1);
        }
    }
    B_arr[w] = limit;
    g_const_arr[w] = last;
    const_arr[w] = g_w[last];
    G_arr[w] = g_w;
    current_w = w;
    if (last > prev_maxg) {
        prev_maxg = last;
    }
    int32_t a_idx3 = 0;
    while (a_idx3 < half_w) {
        free(((void*)(Vs[a_idx3])));
        a_idx3 = (a_idx3 + 1);
    }
    free(((void*)(Vs)));
    free(((void*)(t_as)));
}

void compute_upto_i32(int32_t W) {
    while (current_w < W) {
        compute_next();
    }
}

int64_t count_winning_moves_C_i32_i32(int32_t w, int32_t h) {
    int64_t cnt = 0;
    int32_t x = 1;
    while (x < w) {
        int32_t y = 1;
        while (y < h) {
            int32_t v = (((getG_i32_i32(x, y) ^ getG_i32_i32((w - x), y)) ^ getG_i32_i32(x, (h - y))) ^ getG_i32_i32((w - x), (h - y)));
            if (v == 0) {
                cnt = (cnt + 1);
            }
            y = (y + 1);
        }
        x = (x + 1);
    }
    return cnt;
}

int64_t compute_D_i32_i64(int32_t W, int64_t H) {
    int32_t max_m = 0;
    int32_t w = 1;
    while (w <= W) {
        if (g_const_arr[w] > max_m) {
            max_m = g_const_arr[w];
        }
        w = (w + 1);
    }
    int32_t max_k = max_m;
    if (((int32_t)((H - 1))) < max_k) {
        max_k = ((int32_t)((H - 1)));
    }
    int32_t** row = (int32_t**)(((int32_t**)(malloc((((int64_t)((W + 1))) * 8)))));
    int32_t u = 0;
    while (u <= W) {
        row[u] = ((int32_t*)(calloc(((int64_t)((max_k + 1))), 4)));
        u = (u + 1);
    }
    u = 1;
    while (u <= W) {
        int32_t k = 1;
        while (k <= max_k) {
            row[u][k] = getG_i32_i32(u, k);
            k = (k + 1);
        }
        u = (u + 1);
    }
    int32_t cnts_sz = 65536;
    int32_t* cnts_stamp = (int32_t*)(((int32_t*)(calloc(((int64_t)(cnts_sz)), 4))));
    int32_t* cnts_count = (int32_t*)(((int32_t*)(calloc(((int64_t)(cnts_sz)), 4))));
    int32_t* cnts_list = (int32_t*)(((int32_t*)(malloc((((int64_t)(cnts_sz)) * 4)))));
    int32_t cur_stamp = 0;
    int64_t total = 0;
    int32_t i = 1;
    while (i < W) {
        int32_t* ri = (int32_t*)(row[i]);
        int32_t j = 1;
        while (j <= (W - i)) {
            int32_t* rj = (int32_t*)(row[j]);
            int32_t m = g_const_arr[i];
            if (g_const_arr[j] > m) {
                m = g_const_arr[j];
            }
            int32_t const_t = (const_arr[i] ^ const_arr[j]);
            if (H >= (2 * ((int64_t)(m)))) {
                int32_t L = (m - 1);
                int64_t countA = 0;
                int64_t countB = 0;
                int64_t countC = 0;
                int64_t count_eq = 0;
                int64_t sum_k_eq = 0;
                if (L > 0) {
                    cur_stamp = (cur_stamp + 1);
                    int32_t nvisited = 0;
                    int32_t k = 1;
                    while (k <= L) {
                        int32_t t = (ri[k] ^ rj[k]);
                        if (t >= cnts_sz) {
                            int32_t ns = cnts_sz;
                            while (ns <= t) {
                                ns = (ns * 2);
                            }
                            cnts_stamp = ((int32_t*)(realloc(((void*)(cnts_stamp)), (((int64_t)(ns)) * 4))));
                            cnts_count = ((int32_t*)(realloc(((void*)(cnts_count)), (((int64_t)(ns)) * 4))));
                            cnts_list = ((int32_t*)(realloc(((void*)(cnts_list)), (((int64_t)(ns)) * 4))));
                            memset(((void*)((cnts_stamp + cnts_sz))), 0, (((int64_t)((ns - cnts_sz))) * 4));
                            cnts_sz = ns;
                        }
                        if (cnts_stamp[t] != cur_stamp) {
                            cnts_stamp[t] = cur_stamp;
                            cnts_count[t] = 1;
                            cnts_list[nvisited] = t;
                            nvisited = (nvisited + 1);
                        } else {
                            cnts_count[t] = (cnts_count[t] + 1);
                        }
                        if (t == const_t) {
                            count_eq = (count_eq + 1);
                            sum_k_eq = (sum_k_eq + ((int64_t)(k)));
                        }
                        k = (k + 1);
                    }
                    int32_t idx = 0;
                    while (idx < nvisited) {
                        int64_t c = ((int64_t)(cnts_count[cnts_list[idx]]));
                        countA = (countA + (c * c));
                        idx = (idx + 1);
                    }
                }
                if (count_eq != 0) {
                    countB = (2 * ((count_eq * ((H - ((int64_t)(m))) + 1)) - sum_k_eq));
                }
                int64_t S = (H - (2 * ((int64_t)(m))));
                if (S >= 0) {
                    countC = FLOW_CHECKED_DIV((((S + 1) * (S + 2))), (2));
                }
                total = (((total + countA) + countB) + countC);
            } else {
                int32_t* t_arr = (int32_t*)(((int32_t*)(malloc((((int64_t)(H)) * 4)))));
                int32_t k = 1;
                while (k < ((int32_t)(H))) {
                    if (k <= max_k) {
                        t_arr[k] = (ri[k] ^ rj[k]);
                    } else {
                        t_arr[k] = const_t;
                    }
                    k = (k + 1);
                }
                k = 1;
                while (k < ((int32_t)(H))) {
                    int32_t tk = t_arr[k];
                    int32_t l = 1;
                    while (l <= (((int32_t)(H)) - k)) {
                        if (tk == t_arr[l]) {
                            total = (total + 1);
                        }
                        l = (l + 1);
                    }
                    k = (k + 1);
                }
                free(((void*)(t_arr)));
            }
            j = (j + 1);
        }
        i = (i + 1);
    }
    u = 0;
    while (u <= W) {
        free(((void*)(row[u])));
        u = (u + 1);
    }
    free(((void*)(row)));
    free(((void*)(cnts_stamp)));
    free(((void*)(cnts_count)));
    free(((void*)(cnts_list)));
    return total;
}

int32_t main(void) {
    grundy_init();
    compute_upto_i32(123);
    if (count_winning_moves_C_i32_i32(5, 3) != 4) {
        printf("p933 self-test C(5,3) failed\n");
        return (-1);
    }
    if (compute_D_i32_i64(12, 123) != 327398) {
        printf("p933 self-test D(12,123) failed\n");
        return (-1);
    }
    int64_t result = compute_D_i32_i64(123, 1234567);
    printf("%lld\n", result);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("p933 self-test C(5,3) failed\n\00") {addr_space = 0 : i32} : !llvm.array<30 x i8>
  llvm.mlir.global internal constant @str_1("p933 self-test D(12,123) failed\n\00") {addr_space = 0 : i32} : !llvm.array<33 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
  func.func private @realloc(!llvm.ptr, i64) -> !llvm.ptr
  func.func private @memset(!llvm.ptr, i32, i64) -> ()

  // Module static: B_arr
  llvm.mlir.global internal @B_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %0 = llvm.mlir.zero : !llvm.ptr
    llvm.return %0 : !llvm.ptr
  }
  // Module static: g_const_arr
  llvm.mlir.global internal @g_const_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %1 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1 : !llvm.ptr
  }
  // Module static: const_arr
  llvm.mlir.global internal @const_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %2 = llvm.mlir.zero : !llvm.ptr
    llvm.return %2 : !llvm.ptr
  }
  // Module static: G_arr
  llvm.mlir.global internal @G_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %3 = llvm.mlir.zero : !llvm.ptr
    llvm.return %3 : !llvm.ptr
  }
  // Module static: visited
  llvm.mlir.global internal @visited() {addr_space = 0 : i32} : !llvm.ptr {
    %4 = llvm.mlir.zero : !llvm.ptr
    llvm.return %4 : !llvm.ptr
  }
  // Module static: vis_size
  llvm.mlir.global internal @vis_size(0 : i32) : i32
  // Module static: stamp
  llvm.mlir.global internal @stamp(0 : i32) : i32
  // Module static: prev_maxg
  llvm.mlir.global internal @prev_maxg(0 : i32) : i32
  // Module static: current_w
  llvm.mlir.global internal @current_w(0 : i32) : i32
  // Module static: W_alloc
  llvm.mlir.global internal @W_alloc(0 : i32) : i32
  func.func @grundy_init() -> () {
    %5 = arith.constant 4 : i32
    %6 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    llvm.store %5, %6 : i32, !llvm.ptr
    %8 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %9 = llvm.load %8 : !llvm.ptr -> i32
    %10 = arith.extsi %9 : i32 to i64
    %11 = arith.constant 4 : i32
    %12 = arith.extsi %11 : i32 to i64
    %7 = func.call @calloc(%10, %12) : (i64, i64) -> !llvm.ptr
    %13 = llvm.mlir.addressof @B_arr : !llvm.ptr
    llvm.store %7, %13 : !llvm.ptr, !llvm.ptr
    %15 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %16 = llvm.load %15 : !llvm.ptr -> i32
    %17 = arith.extsi %16 : i32 to i64
    %18 = arith.constant 4 : i32
    %19 = arith.extsi %18 : i32 to i64
    %14 = func.call @calloc(%17, %19) : (i64, i64) -> !llvm.ptr
    %20 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
    llvm.store %14, %20 : !llvm.ptr, !llvm.ptr
    %22 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %23 = llvm.load %22 : !llvm.ptr -> i32
    %24 = arith.extsi %23 : i32 to i64
    %25 = arith.constant 4 : i32
    %26 = arith.extsi %25 : i32 to i64
    %21 = func.call @calloc(%24, %26) : (i64, i64) -> !llvm.ptr
    %27 = llvm.mlir.addressof @const_arr : !llvm.ptr
    llvm.store %21, %27 : !llvm.ptr, !llvm.ptr
    %29 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %30 = llvm.load %29 : !llvm.ptr -> i32
    %31 = arith.extsi %30 : i32 to i64
    %32 = arith.constant 8 : i32
    %33 = arith.extsi %32 : i32 to i64
    %28 = func.call @calloc(%31, %33) : (i64, i64) -> !llvm.ptr
    %34 = llvm.mlir.addressof @G_arr : !llvm.ptr
    llvm.store %28, %34 : !llvm.ptr, !llvm.ptr
    %35 = arith.constant 1 : i32
    %36 = llvm.mlir.addressof @B_arr : !llvm.ptr
    %37 = llvm.load %36 : !llvm.ptr -> !llvm.ptr
    %38 = arith.constant 1 : i32
    %39 = arith.extsi %38 : i32 to i64
    %40 = llvm.getelementptr %37[%39] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %35, %40 : i32, !llvm.ptr
    %41 = arith.constant 1 : i32
    %42 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
    %43 = llvm.load %42 : !llvm.ptr -> !llvm.ptr
    %44 = arith.constant 1 : i32
    %45 = arith.extsi %44 : i32 to i64
    %46 = llvm.getelementptr %43[%45] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %41, %46 : i32, !llvm.ptr
    %48 = arith.constant 2 : i32
    %49 = arith.constant 4 : i32
    %50 = arith.extsi %48 : i32 to i64
    %51 = arith.extsi %49 : i32 to i64
    %47 = func.call @calloc(%50, %51) : (i64, i64) -> !llvm.ptr
    %52 = llvm.mlir.addressof @G_arr : !llvm.ptr
    %53 = llvm.load %52 : !llvm.ptr -> !llvm.ptr
    %54 = arith.constant 1 : i32
    %55 = arith.extsi %54 : i32 to i64
    %56 = llvm.getelementptr %53[%55] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
    llvm.store %47, %56 : !llvm.ptr, !llvm.ptr
    %57 = arith.constant 0 : i32
    %59 = llvm.mlir.addressof @G_arr : !llvm.ptr
    %60 = llvm.load %59 : !llvm.ptr -> !llvm.ptr
    %61 = arith.constant 1 : i32
    %62 = arith.extsi %61 : i32 to i64
    %63 = llvm.getelementptr %60[%62] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
    %58 = llvm.load %63 : !llvm.ptr -> !llvm.ptr
    %64 = arith.constant 0 : i32
    %65 = arith.extsi %64 : i32 to i64
    %66 = llvm.getelementptr %58[%65] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %57, %66 : i32, !llvm.ptr
    %67 = arith.constant 0 : i32
    %69 = llvm.mlir.addressof @G_arr : !llvm.ptr
    %70 = llvm.load %69 : !llvm.ptr -> !llvm.ptr
    %71 = arith.constant 1 : i32
    %72 = arith.extsi %71 : i32 to i64
    %73 = llvm.getelementptr %70[%72] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
    %68 = llvm.load %73 : !llvm.ptr -> !llvm.ptr
    %74 = arith.constant 1 : i32
    %75 = arith.extsi %74 : i32 to i64
    %76 = llvm.getelementptr %68[%75] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %67, %76 : i32, !llvm.ptr
    %77 = arith.constant 32768 : i32
    %78 = llvm.mlir.addressof @vis_size : !llvm.ptr
    llvm.store %77, %78 : i32, !llvm.ptr
    %80 = llvm.mlir.addressof @vis_size : !llvm.ptr
    %81 = llvm.load %80 : !llvm.ptr -> i32
    %82 = arith.extsi %81 : i32 to i64
    %83 = arith.constant 4 : i32
    %84 = arith.extsi %83 : i32 to i64
    %79 = func.call @calloc(%82, %84) : (i64, i64) -> !llvm.ptr
    %85 = llvm.mlir.addressof @visited : !llvm.ptr
    llvm.store %79, %85 : !llvm.ptr, !llvm.ptr
    %86 = arith.constant 1 : i32
    %87 = llvm.mlir.addressof @stamp : !llvm.ptr
    llvm.store %86, %87 : i32, !llvm.ptr
    %88 = arith.constant 1 : i32
    %89 = llvm.mlir.addressof @prev_maxg : !llvm.ptr
    llvm.store %88, %89 : i32, !llvm.ptr
    %90 = arith.constant 1 : i32
    %91 = llvm.mlir.addressof @current_w : !llvm.ptr
    llvm.store %90, %91 : i32, !llvm.ptr
    func.return
  }
  func.func @ensure_size(%arg0: i32) -> () {
    %92 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %93 = llvm.load %92 : !llvm.ptr -> i32
    %94 = arith.cmpi slt, %arg0, %93 : i32
    cf.cond_br %94, ^bb0, ^bb1
    ^bb0:
      func.return
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %95 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %96 = llvm.load %95 : !llvm.ptr -> i32
    %97 = llvm.mlir.constant(1 : i64) : i64
    %98 = llvm.alloca %97 x i32 : (i64) -> !llvm.ptr
    llvm.store %96, %98 : i32, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %99 = llvm.load %98 : !llvm.ptr -> i32
    %100 = arith.cmpi sle, %99, %arg0 : i32
    cf.cond_br %100, ^bb4, ^bb5
    ^bb4:
      %101 = llvm.load %98 : !llvm.ptr -> i32
      %102 = arith.constant 2 : i32
      %103 = arith.muli %101, %102 : i32
      llvm.store %103, %98 : i32, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %105 = llvm.mlir.addressof @B_arr : !llvm.ptr
    %106 = llvm.load %105 : !llvm.ptr -> !llvm.ptr
    %107 = llvm.load %98 : !llvm.ptr -> i32
    %108 = arith.extsi %107 : i32 to i64
    %109 = arith.constant 4 : i32
    %111 = arith.extsi %109 : i32 to i64
    %110 = arith.muli %108, %111 : i64
    %104 = func.call @realloc(%106, %110) : (!llvm.ptr, i64) -> !llvm.ptr
    %112 = llvm.mlir.addressof @B_arr : !llvm.ptr
    llvm.store %104, %112 : !llvm.ptr, !llvm.ptr
    %114 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
    %115 = llvm.load %114 : !llvm.ptr -> !llvm.ptr
    %116 = llvm.load %98 : !llvm.ptr -> i32
    %117 = arith.extsi %116 : i32 to i64
    %118 = arith.constant 4 : i32
    %120 = arith.extsi %118 : i32 to i64
    %119 = arith.muli %117, %120 : i64
    %113 = func.call @realloc(%115, %119) : (!llvm.ptr, i64) -> !llvm.ptr
    %121 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
    llvm.store %113, %121 : !llvm.ptr, !llvm.ptr
    %123 = llvm.mlir.addressof @const_arr : !llvm.ptr
    %124 = llvm.load %123 : !llvm.ptr -> !llvm.ptr
    %125 = llvm.load %98 : !llvm.ptr -> i32
    %126 = arith.extsi %125 : i32 to i64
    %127 = arith.constant 4 : i32
    %129 = arith.extsi %127 : i32 to i64
    %128 = arith.muli %126, %129 : i64
    %122 = func.call @realloc(%124, %128) : (!llvm.ptr, i64) -> !llvm.ptr
    %130 = llvm.mlir.addressof @const_arr : !llvm.ptr
    llvm.store %122, %130 : !llvm.ptr, !llvm.ptr
    %132 = llvm.mlir.addressof @G_arr : !llvm.ptr
    %133 = llvm.load %132 : !llvm.ptr -> !llvm.ptr
    %134 = llvm.load %98 : !llvm.ptr -> i32
    %135 = arith.extsi %134 : i32 to i64
    %136 = arith.constant 8 : i32
    %138 = arith.extsi %136 : i32 to i64
    %137 = arith.muli %135, %138 : i64
    %131 = func.call @realloc(%133, %137) : (!llvm.ptr, i64) -> !llvm.ptr
    %139 = llvm.mlir.addressof @G_arr : !llvm.ptr
    llvm.store %131, %139 : !llvm.ptr, !llvm.ptr
    # String concatenation: !llvm.ptr + i32
    %142 = arith.constant 0 : i32
    %143 = llvm.load %98 : !llvm.ptr -> i32
    %144 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %145 = llvm.load %144 : !llvm.ptr -> i32
    %146 = arith.subi %143, %145 : i32
    %147 = arith.extsi %146 : i32 to i64
    %148 = arith.constant 4 : i32
    %150 = arith.extsi %148 : i32 to i64
    %149 = arith.muli %147, %150 : i64
    func.call @memset(%141, %142, %149) : (!llvm.ptr, i32, i64) -> ()
    # String concatenation: !llvm.ptr + i32
    %153 = arith.constant 0 : i32
    %154 = llvm.load %98 : !llvm.ptr -> i32
    %155 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %156 = llvm.load %155 : !llvm.ptr -> i32
    %157 = arith.subi %154, %156 : i32
    %158 = arith.extsi %157 : i32 to i64
    %159 = arith.constant 4 : i32
    %161 = arith.extsi %159 : i32 to i64
    %160 = arith.muli %158, %161 : i64
    func.call @memset(%152, %153, %160) : (!llvm.ptr, i32, i64) -> ()
    # String concatenation: !llvm.ptr + i32
    %164 = arith.constant 0 : i32
    %165 = llvm.load %98 : !llvm.ptr -> i32
    %166 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %167 = llvm.load %166 : !llvm.ptr -> i32
    %168 = arith.subi %165, %167 : i32
    %169 = arith.extsi %168 : i32 to i64
    %170 = arith.constant 4 : i32
    %172 = arith.extsi %170 : i32 to i64
    %171 = arith.muli %169, %172 : i64
    func.call @memset(%163, %164, %171) : (!llvm.ptr, i32, i64) -> ()
    # String concatenation: !llvm.ptr + i32
    %175 = arith.constant 0 : i32
    %176 = llvm.load %98 : !llvm.ptr -> i32
    %177 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    %178 = llvm.load %177 : !llvm.ptr -> i32
    %179 = arith.subi %176, %178 : i32
    %180 = arith.extsi %179 : i32 to i64
    %181 = arith.constant 8 : i32
    %183 = arith.extsi %181 : i32 to i64
    %182 = arith.muli %180, %183 : i64
    func.call @memset(%174, %175, %182) : (!llvm.ptr, i32, i64) -> ()
    %184 = llvm.load %98 : !llvm.ptr -> i32
    %185 = llvm.mlir.addressof @W_alloc : !llvm.ptr
    llvm.store %184, %185 : i32, !llvm.ptr
    func.return
  }
  func.func @getG(%arg0: i32, %arg1: i32) -> i32 {
    %186 = llvm.mlir.constant(1 : i64) : i64
    %187 = llvm.alloca %186 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg0, %187 : i32, !llvm.ptr
    %188 = llvm.mlir.constant(1 : i64) : i64
    %189 = llvm.alloca %188 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg1, %189 : i32, !llvm.ptr
    %190 = llvm.load %187 : !llvm.ptr -> i32
    %191 = llvm.load %189 : !llvm.ptr -> i32
    %192 = arith.cmpi sgt, %190, %191 : i32
    cf.cond_br %192, ^bb6, ^bb7
    ^bb6:
      %193 = llvm.load %187 : !llvm.ptr -> i32
      %194 = llvm.load %189 : !llvm.ptr -> i32
      llvm.store %194, %187 : i32, !llvm.ptr
      llvm.store %193, %189 : i32, !llvm.ptr
      cf.br ^bb8
    ^bb7:
      cf.br ^bb8
    ^bb8:
    %195 = llvm.load %187 : !llvm.ptr -> i32
    %196 = arith.constant 1 : i32
    %197 = arith.cmpi sle, %195, %196 : i32
    cf.cond_br %197, ^bb9, ^bb10
    ^bb9:
      %198 = arith.constant 0 : i32
      func.return %198 : i32
    ^bb10:
      cf.br ^bb11
    ^bb11:
    %199 = llvm.load %189 : !llvm.ptr -> i32
    %201 = llvm.mlir.addressof @B_arr : !llvm.ptr
    %202 = llvm.load %201 : !llvm.ptr -> !llvm.ptr
    %203 = llvm.load %187 : !llvm.ptr -> i32
    %204 = arith.extsi %203 : i32 to i64
    %205 = llvm.getelementptr %202[%204] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    %200 = llvm.load %205 : !llvm.ptr -> i32
    %206 = arith.cmpi sle, %199, %200 : i32
    cf.cond_br %206, ^bb12, ^bb13
    ^bb12:
      %209 = llvm.mlir.addressof @G_arr : !llvm.ptr
      %210 = llvm.load %209 : !llvm.ptr -> !llvm.ptr
      %211 = llvm.load %187 : !llvm.ptr -> i32
      %212 = arith.extsi %211 : i32 to i64
      %213 = llvm.getelementptr %210[%212] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %208 = llvm.load %213 : !llvm.ptr -> !llvm.ptr
      %214 = llvm.load %189 : !llvm.ptr -> i32
      %215 = arith.extsi %214 : i32 to i64
      %216 = llvm.getelementptr %208[%215] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %207 = llvm.load %216 : !llvm.ptr -> i32
      func.return %207 : i32
    ^bb13:
      cf.br ^bb14
    ^bb14:
    %218 = llvm.mlir.addressof @const_arr : !llvm.ptr
    %219 = llvm.load %218 : !llvm.ptr -> !llvm.ptr
    %220 = llvm.load %187 : !llvm.ptr -> i32
    %221 = arith.extsi %220 : i32 to i64
    %222 = llvm.getelementptr %219[%221] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    %217 = llvm.load %222 : !llvm.ptr -> i32
    func.return %217 : i32
  }
  func.func @mark_visited(%arg0: i32) -> () {
    %223 = llvm.mlir.addressof @vis_size : !llvm.ptr
    %224 = llvm.load %223 : !llvm.ptr -> i32
    %225 = arith.cmpi slt, %arg0, %224 : i32
    cf.cond_br %225, ^bb15, ^bb16
    ^bb15:
      %226 = llvm.mlir.addressof @stamp : !llvm.ptr
      %227 = llvm.load %226 : !llvm.ptr -> i32
      %228 = llvm.mlir.addressof @visited : !llvm.ptr
      %229 = llvm.load %228 : !llvm.ptr -> !llvm.ptr
      %230 = arith.extsi %arg0 : i32 to i64
      %231 = llvm.getelementptr %229[%230] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %227, %231 : i32, !llvm.ptr
      cf.br ^bb17
    ^bb16:
      %232 = llvm.mlir.addressof @vis_size : !llvm.ptr
      %233 = llvm.load %232 : !llvm.ptr -> i32
      %234 = llvm.mlir.constant(1 : i64) : i64
      %235 = llvm.alloca %234 x i32 : (i64) -> !llvm.ptr
      llvm.store %233, %235 : i32, !llvm.ptr
      cf.br ^bb18
      ^bb18:
      %236 = llvm.load %235 : !llvm.ptr -> i32
      %237 = arith.cmpi sle, %236, %arg0 : i32
      cf.cond_br %237, ^bb19, ^bb20
      ^bb19:
        %238 = llvm.load %235 : !llvm.ptr -> i32
        %239 = arith.constant 2 : i32
        %240 = arith.muli %238, %239 : i32
        llvm.store %240, %235 : i32, !llvm.ptr
        cf.br ^bb18
      ^bb20:
      %242 = llvm.mlir.addressof @visited : !llvm.ptr
      %243 = llvm.load %242 : !llvm.ptr -> !llvm.ptr
      %244 = llvm.load %235 : !llvm.ptr -> i32
      %245 = arith.extsi %244 : i32 to i64
      %246 = arith.constant 4 : i32
      %248 = arith.extsi %246 : i32 to i64
      %247 = arith.muli %245, %248 : i64
      %241 = func.call @realloc(%243, %247) : (!llvm.ptr, i64) -> !llvm.ptr
      %249 = llvm.mlir.addressof @visited : !llvm.ptr
      llvm.store %241, %249 : !llvm.ptr, !llvm.ptr
      # String concatenation: !llvm.ptr + i32
      %252 = arith.constant 0 : i32
      %253 = llvm.load %235 : !llvm.ptr -> i32
      %254 = llvm.mlir.addressof @vis_size : !llvm.ptr
      %255 = llvm.load %254 : !llvm.ptr -> i32
      %256 = arith.subi %253, %255 : i32
      %257 = arith.extsi %256 : i32 to i64
      %258 = arith.constant 4 : i32
      %260 = arith.extsi %258 : i32 to i64
      %259 = arith.muli %257, %260 : i64
      func.call @memset(%251, %252, %259) : (!llvm.ptr, i32, i64) -> ()
      %261 = llvm.load %235 : !llvm.ptr -> i32
      %262 = llvm.mlir.addressof @vis_size : !llvm.ptr
      llvm.store %261, %262 : i32, !llvm.ptr
      %263 = llvm.mlir.addressof @stamp : !llvm.ptr
      %264 = llvm.load %263 : !llvm.ptr -> i32
      %265 = llvm.mlir.addressof @visited : !llvm.ptr
      %266 = llvm.load %265 : !llvm.ptr -> !llvm.ptr
      %267 = arith.extsi %arg0 : i32 to i64
      %268 = llvm.getelementptr %266[%267] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %264, %268 : i32, !llvm.ptr
      cf.br ^bb17
    ^bb17:
    func.return
  }
  func.func @compute_h_range(%arg0: i32, %arg1: i32, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: i32) -> () {
    %269 = llvm.mlir.constant(1 : i64) : i64
    %270 = llvm.alloca %269 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg0, %270 : i32, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %271 = llvm.load %270 : !llvm.ptr -> i32
    %272 = arith.cmpi sle, %271, %arg1 : i32
    cf.cond_br %272, ^bb22, ^bb23
    ^bb22:
      %273 = llvm.mlir.addressof @stamp : !llvm.ptr
      %274 = llvm.load %273 : !llvm.ptr -> i32
      %275 = arith.constant 1 : i32
      %276 = arith.addi %274, %275 : i32
      %277 = llvm.mlir.addressof @stamp : !llvm.ptr
      llvm.store %276, %277 : i32, !llvm.ptr
      %278 = llvm.load %270 : !llvm.ptr -> i32
      %279 = arith.constant 1 : i32
      %280 = arith.shrsi %278, %279 : i32
      %281 = arith.constant 0 : i32
      %282 = llvm.mlir.constant(1 : i64) : i64
      %283 = llvm.alloca %282 x i32 : (i64) -> !llvm.ptr
      llvm.store %281, %283 : i32, !llvm.ptr
      cf.br ^bb24
      ^bb24:
      %284 = llvm.load %283 : !llvm.ptr -> i32
      %285 = arith.cmpi slt, %284, %arg5 : i32
      cf.cond_br %285, ^bb25, ^bb26
      ^bb25:
        %287 = llvm.load %283 : !llvm.ptr -> i32
        %288 = arith.extsi %287 : i32 to i64
        %289 = llvm.getelementptr %arg3[%288] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %286 = llvm.load %289 : !llvm.ptr -> !llvm.ptr
        %291 = llvm.load %283 : !llvm.ptr -> i32
        %292 = arith.extsi %291 : i32 to i64
        %293 = llvm.getelementptr %arg4[%292] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %290 = llvm.load %293 : !llvm.ptr -> i32
        %294 = arith.constant 0 : i32
        %295 = llvm.mlir.constant(1 : i64) : i64
        %296 = llvm.alloca %295 x i32 : (i64) -> !llvm.ptr
        llvm.store %294, %296 : i32, !llvm.ptr
        %297 = arith.cmpi sge, %280, %290 : i32
        cf.cond_br %297, ^bb27, ^bb28
        ^bb27:
          %298 = llvm.mlir.addressof @stamp : !llvm.ptr
          %299 = llvm.load %298 : !llvm.ptr -> i32
          %300 = llvm.mlir.addressof @visited : !llvm.ptr
          %301 = llvm.load %300 : !llvm.ptr -> !llvm.ptr
          %302 = arith.constant 0 : i32
          %303 = arith.extsi %302 : i32 to i64
          %304 = llvm.getelementptr %301[%303] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %299, %304 : i32, !llvm.ptr
          %305 = arith.constant 1 : i32
          %306 = arith.subi %290, %305 : i32
          llvm.store %306, %296 : i32, !llvm.ptr
          %307 = llvm.load %296 : !llvm.ptr -> i32
          %308 = arith.cmpi sgt, %307, %280 : i32
          cf.cond_br %308, ^bb30, ^bb31
          ^bb30:
            llvm.store %280, %296 : i32, !llvm.ptr
            cf.br ^bb32
          ^bb31:
            cf.br ^bb32
          ^bb32:
          cf.br ^bb29
        ^bb28:
          llvm.store %280, %296 : i32, !llvm.ptr
          cf.br ^bb29
        ^bb29:
        %309 = arith.constant 1 : i32
        %310 = llvm.mlir.constant(1 : i64) : i64
        %311 = llvm.alloca %310 x i32 : (i64) -> !llvm.ptr
        llvm.store %309, %311 : i32, !llvm.ptr
        cf.br ^bb33
        ^bb33:
        %312 = llvm.load %311 : !llvm.ptr -> i32
        %313 = llvm.load %296 : !llvm.ptr -> i32
        %314 = arith.cmpi sle, %312, %313 : i32
        cf.cond_br %314, ^bb34, ^bb35
        ^bb34:
          %316 = llvm.load %311 : !llvm.ptr -> i32
          %317 = arith.extsi %316 : i32 to i64
          %318 = llvm.getelementptr %286[%317] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %315 = llvm.load %318 : !llvm.ptr -> i32
          %320 = llvm.load %270 : !llvm.ptr -> i32
          %321 = llvm.load %311 : !llvm.ptr -> i32
          %322 = arith.subi %320, %321 : i32
          %323 = arith.extsi %322 : i32 to i64
          %324 = llvm.getelementptr %286[%323] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %319 = llvm.load %324 : !llvm.ptr -> i32
          %325 = arith.xori %315, %319 : i32
          func.call @mark_visited(%325) : (i32) -> ()
          %327 = llvm.load %311 : !llvm.ptr -> i32
          %328 = arith.constant 1 : i32
          %329 = arith.addi %327, %328 : i32
          llvm.store %329, %311 : i32, !llvm.ptr
          cf.br ^bb33
        ^bb35:
        %330 = llvm.load %283 : !llvm.ptr -> i32
        %331 = arith.constant 1 : i32
        %332 = arith.addi %330, %331 : i32
        llvm.store %332, %283 : i32, !llvm.ptr
        cf.br ^bb24
      ^bb26:
      %333 = arith.constant 0 : i32
      %334 = llvm.mlir.constant(1 : i64) : i64
      %335 = llvm.alloca %334 x i32 : (i64) -> !llvm.ptr
      llvm.store %333, %335 : i32, !llvm.ptr
      cf.br ^bb36
      ^bb36:
      %337 = llvm.mlir.addressof @visited : !llvm.ptr
      %338 = llvm.load %337 : !llvm.ptr -> !llvm.ptr
      %339 = llvm.load %335 : !llvm.ptr -> i32
      %340 = arith.extsi %339 : i32 to i64
      %341 = llvm.getelementptr %338[%340] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %336 = llvm.load %341 : !llvm.ptr -> i32
      %342 = llvm.mlir.addressof @stamp : !llvm.ptr
      %343 = llvm.load %342 : !llvm.ptr -> i32
      %344 = arith.cmpi eq, %336, %343 : i32
      cf.cond_br %344, ^bb37, ^bb38
      ^bb37:
        %345 = llvm.load %335 : !llvm.ptr -> i32
        %346 = arith.constant 1 : i32
        %347 = arith.addi %345, %346 : i32
        llvm.store %347, %335 : i32, !llvm.ptr
        cf.br ^bb36
      ^bb38:
      %348 = llvm.load %335 : !llvm.ptr -> i32
      %349 = llvm.load %270 : !llvm.ptr -> i32
      %350 = arith.extsi %349 : i32 to i64
      %351 = llvm.getelementptr %arg2[%350] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %348, %351 : i32, !llvm.ptr
      %352 = llvm.load %270 : !llvm.ptr -> i32
      %353 = arith.constant 1 : i32
      %354 = arith.addi %352, %353 : i32
      llvm.store %354, %270 : i32, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    func.return
  }
  func.func @compute_next() -> () {
    %355 = llvm.mlir.addressof @current_w : !llvm.ptr
    %356 = llvm.load %355 : !llvm.ptr -> i32
    %357 = arith.constant 1 : i32
    %358 = arith.addi %356, %357 : i32
    func.call @ensure_size(%358) : (i32) -> ()
    %360 = arith.constant 0 : i32
    %361 = llvm.mlir.constant(1 : i64) : i64
    %362 = llvm.alloca %361 x i32 : (i64) -> !llvm.ptr
    llvm.store %360, %362 : i32, !llvm.ptr
    %363 = arith.constant 2 : i32
    %364 = llvm.mlir.addressof @prev_maxg : !llvm.ptr
    %365 = llvm.load %364 : !llvm.ptr -> i32
    %366 = arith.muli %363, %365 : i32
    %367 = arith.cmpi sgt, %358, %366 : i32
    cf.cond_br %367, ^bb39, ^bb40
    ^bb39:
      llvm.store %358, %362 : i32, !llvm.ptr
      cf.br ^bb41
    ^bb40:
      %368 = arith.constant 2 : i32
      %369 = llvm.mlir.addressof @prev_maxg : !llvm.ptr
      %370 = llvm.load %369 : !llvm.ptr -> i32
      %371 = arith.muli %368, %370 : i32
      llvm.store %371, %362 : i32, !llvm.ptr
      cf.br ^bb41
    ^bb41:
    %373 = llvm.load %362 : !llvm.ptr -> i32
    %374 = arith.constant 1 : i32
    %375 = arith.addi %373, %374 : i32
    %376 = arith.extsi %375 : i32 to i64
    %377 = arith.constant 4 : i32
    %378 = arith.extsi %377 : i32 to i64
    %372 = func.call @calloc(%376, %378) : (i64, i64) -> !llvm.ptr
    %379 = llvm.mlir.constant(1 : i64) : i64
    %380 = llvm.alloca %379 x !llvm.ptr : (i64) -> !llvm.ptr
    llvm.store %372, %380 : !llvm.ptr, !llvm.ptr
    %381 = llvm.mlir.constant(1 : i64) : i64
    %382 = llvm.alloca %381 x i32 : (i64) -> !llvm.ptr
    llvm.store %358, %382 : i32, !llvm.ptr
    %383 = llvm.load %382 : !llvm.ptr -> i32
    %384 = llvm.load %362 : !llvm.ptr -> i32
    %385 = arith.constant 1 : i32
    %386 = arith.addi %384, %385 : i32
    %387 = arith.cmpi sgt, %383, %386 : i32
    cf.cond_br %387, ^bb42, ^bb43
    ^bb42:
      %388 = llvm.load %362 : !llvm.ptr -> i32
      %389 = arith.constant 1 : i32
      %390 = arith.addi %388, %389 : i32
      llvm.store %390, %382 : i32, !llvm.ptr
      cf.br ^bb44
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %391 = arith.constant 1 : i32
    %392 = llvm.mlir.constant(1 : i64) : i64
    %393 = llvm.alloca %392 x i32 : (i64) -> !llvm.ptr
    llvm.store %391, %393 : i32, !llvm.ptr
    cf.br ^bb45
    ^bb45:
    %394 = llvm.load %393 : !llvm.ptr -> i32
    %395 = llvm.load %382 : !llvm.ptr -> i32
    %396 = arith.cmpi slt, %394, %395 : i32
    cf.cond_br %396, ^bb46, ^bb47
    ^bb46:
      %398 = llvm.load %393 : !llvm.ptr -> i32
      %397 = func.call @getG(%398, %358) : (i32, i32) -> i32
      %399 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
      %400 = llvm.load %393 : !llvm.ptr -> i32
      %401 = arith.extsi %400 : i32 to i64
      %402 = llvm.getelementptr %399[%401] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %397, %402 : i32, !llvm.ptr
      %403 = llvm.load %393 : !llvm.ptr -> i32
      %404 = arith.constant 1 : i32
      %405 = arith.addi %403, %404 : i32
      llvm.store %405, %393 : i32, !llvm.ptr
      cf.br ^bb45
    ^bb47:
    %406 = arith.constant 1 : i32
    %407 = arith.shrsi %358, %406 : i32
    %409 = arith.extsi %407 : i32 to i64
    %410 = arith.constant 8 : i32
    %412 = arith.extsi %410 : i32 to i64
    %411 = arith.muli %409, %412 : i64
    %408 = func.call @malloc(%411) : (i64) -> !llvm.ptr
    %414 = arith.extsi %407 : i32 to i64
    %415 = arith.constant 4 : i32
    %417 = arith.extsi %415 : i32 to i64
    %416 = arith.muli %414, %417 : i64
    %413 = func.call @malloc(%416) : (i64) -> !llvm.ptr
    %418 = arith.constant 1 : i32
    %419 = llvm.mlir.constant(1 : i64) : i64
    %420 = llvm.alloca %419 x i32 : (i64) -> !llvm.ptr
    llvm.store %418, %420 : i32, !llvm.ptr
    cf.br ^bb48
    ^bb48:
    %421 = llvm.load %420 : !llvm.ptr -> i32
    %422 = arith.cmpi sle, %421, %407 : i32
    cf.cond_br %422, ^bb49, ^bb50
    ^bb49:
      %423 = llvm.load %420 : !llvm.ptr -> i32
      %424 = arith.subi %358, %423 : i32
      %426 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
      %427 = llvm.load %426 : !llvm.ptr -> !llvm.ptr
      %428 = llvm.load %420 : !llvm.ptr -> i32
      %429 = arith.extsi %428 : i32 to i64
      %430 = llvm.getelementptr %427[%429] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %425 = llvm.load %430 : !llvm.ptr -> i32
      %431 = llvm.mlir.constant(1 : i64) : i64
      %432 = llvm.alloca %431 x i32 : (i64) -> !llvm.ptr
      llvm.store %425, %432 : i32, !llvm.ptr
      %434 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
      %435 = llvm.load %434 : !llvm.ptr -> !llvm.ptr
      %436 = arith.extsi %424 : i32 to i64
      %437 = llvm.getelementptr %435[%436] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %433 = llvm.load %437 : !llvm.ptr -> i32
      %438 = llvm.load %432 : !llvm.ptr -> i32
      %439 = arith.cmpi sgt, %433, %438 : i32
      cf.cond_br %439, ^bb51, ^bb52
      ^bb51:
        %441 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
        %442 = llvm.load %441 : !llvm.ptr -> !llvm.ptr
        %443 = arith.extsi %424 : i32 to i64
        %444 = llvm.getelementptr %442[%443] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %440 = llvm.load %444 : !llvm.ptr -> i32
        llvm.store %440, %432 : i32, !llvm.ptr
        cf.br ^bb53
      ^bb52:
        cf.br ^bb53
      ^bb53:
      %445 = llvm.load %432 : !llvm.ptr -> i32
      %446 = llvm.load %420 : !llvm.ptr -> i32
      %447 = arith.constant 1 : i32
      %448 = arith.subi %446, %447 : i32
      %449 = arith.extsi %448 : i32 to i64
      %450 = llvm.getelementptr %413[%449] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %445, %450 : i32, !llvm.ptr
      %452 = llvm.load %362 : !llvm.ptr -> i32
      %453 = arith.constant 1 : i32
      %454 = arith.addi %452, %453 : i32
      %455 = arith.extsi %454 : i32 to i64
      %456 = arith.constant 4 : i32
      %457 = arith.extsi %456 : i32 to i64
      %451 = func.call @calloc(%455, %457) : (i64, i64) -> !llvm.ptr
      %458 = arith.constant 1 : i32
      %459 = llvm.mlir.constant(1 : i64) : i64
      %460 = llvm.alloca %459 x i32 : (i64) -> !llvm.ptr
      llvm.store %458, %460 : i32, !llvm.ptr
      cf.br ^bb54
      ^bb54:
      %461 = llvm.load %460 : !llvm.ptr -> i32
      %462 = llvm.load %362 : !llvm.ptr -> i32
      %463 = arith.cmpi sle, %461, %462 : i32
      cf.cond_br %463, ^bb55, ^bb56
      ^bb55:
        %465 = llvm.load %420 : !llvm.ptr -> i32
        %466 = llvm.load %460 : !llvm.ptr -> i32
        %464 = func.call @getG(%465, %466) : (i32, i32) -> i32
        %468 = llvm.load %460 : !llvm.ptr -> i32
        %467 = func.call @getG(%424, %468) : (i32, i32) -> i32
        %469 = arith.xori %464, %467 : i32
        %470 = llvm.load %460 : !llvm.ptr -> i32
        %471 = arith.extsi %470 : i32 to i64
        %472 = llvm.getelementptr %451[%471] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %469, %472 : i32, !llvm.ptr
        %473 = llvm.load %460 : !llvm.ptr -> i32
        %474 = arith.constant 1 : i32
        %475 = arith.addi %473, %474 : i32
        llvm.store %475, %460 : i32, !llvm.ptr
        cf.br ^bb54
      ^bb56:
      %476 = llvm.load %420 : !llvm.ptr -> i32
      %477 = arith.constant 1 : i32
      %478 = arith.subi %476, %477 : i32
      %479 = arith.extsi %478 : i32 to i64
      %480 = llvm.getelementptr %408[%479] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      llvm.store %451, %480 : !llvm.ptr, !llvm.ptr
      %481 = llvm.load %420 : !llvm.ptr -> i32
      %482 = arith.constant 1 : i32
      %483 = arith.addi %481, %482 : i32
      llvm.store %483, %420 : i32, !llvm.ptr
      cf.br ^bb48
    ^bb50:
    %485 = llvm.load %362 : !llvm.ptr -> i32
    %486 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
    func.call @compute_h_range(%358, %485, %486, %408, %413, %407) : (i32, i32, !llvm.ptr, !llvm.ptr, !llvm.ptr, i32) -> ()
    %487 = arith.constant 1 : i32
    %488 = llvm.mlir.constant(1 : i64) : i64
    %489 = llvm.alloca %488 x i32 : (i64) -> !llvm.ptr
    llvm.store %487, %489 : i32, !llvm.ptr
    %490 = arith.constant 2 : i32
    %491 = llvm.mlir.constant(1 : i64) : i64
    %492 = llvm.alloca %491 x i32 : (i64) -> !llvm.ptr
    llvm.store %490, %492 : i32, !llvm.ptr
    cf.br ^bb57
    ^bb57:
    %493 = llvm.load %492 : !llvm.ptr -> i32
    %494 = llvm.load %362 : !llvm.ptr -> i32
    %495 = arith.cmpi sle, %493, %494 : i32
    cf.cond_br %495, ^bb58, ^bb59
    ^bb58:
      %497 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
      %498 = llvm.load %492 : !llvm.ptr -> i32
      %499 = arith.extsi %498 : i32 to i64
      %500 = llvm.getelementptr %497[%499] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %496 = llvm.load %500 : !llvm.ptr -> i32
      %502 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
      %503 = llvm.load %492 : !llvm.ptr -> i32
      %504 = arith.constant 1 : i32
      %505 = arith.subi %503, %504 : i32
      %506 = arith.extsi %505 : i32 to i64
      %507 = llvm.getelementptr %502[%506] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %501 = llvm.load %507 : !llvm.ptr -> i32
      %508 = arith.cmpi ne, %496, %501 : i32
      cf.cond_br %508, ^bb60, ^bb61
      ^bb60:
        %509 = llvm.load %492 : !llvm.ptr -> i32
        llvm.store %509, %489 : i32, !llvm.ptr
        cf.br ^bb62
      ^bb61:
        cf.br ^bb62
      ^bb62:
      %510 = llvm.load %492 : !llvm.ptr -> i32
      %511 = arith.constant 1 : i32
      %512 = arith.addi %510, %511 : i32
      llvm.store %512, %492 : i32, !llvm.ptr
      cf.br ^bb57
    ^bb59:
    cf.br ^bb63
    ^bb63:
    %513 = arith.constant 1 : i1
    cf.cond_br %513, ^bb64, ^bb65
    ^bb64:
      %514 = arith.constant 2 : i32
      %515 = llvm.load %489 : !llvm.ptr -> i32
      %516 = arith.muli %514, %515 : i32
      %517 = llvm.load %362 : !llvm.ptr -> i32
      %518 = arith.cmpi sle, %516, %517 : i32
      cf.cond_br %518, ^bb66, ^bb67
      ^bb66:
        %520 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
        %521 = llvm.load %489 : !llvm.ptr -> i32
        %522 = arith.extsi %521 : i32 to i64
        %523 = llvm.getelementptr %520[%522] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %519 = llvm.load %523 : !llvm.ptr -> i32
        %524 = arith.constant 1 : i32
        %525 = llvm.mlir.constant(1 : i64) : i64
        %526 = llvm.alloca %525 x i32 : (i64) -> !llvm.ptr
        llvm.store %524, %526 : i32, !llvm.ptr
        %527 = llvm.load %489 : !llvm.ptr -> i32
        %528 = arith.constant 1 : i32
        %529 = arith.addi %527, %528 : i32
        %530 = llvm.mlir.constant(1 : i64) : i64
        %531 = llvm.alloca %530 x i32 : (i64) -> !llvm.ptr
        llvm.store %529, %531 : i32, !llvm.ptr
        cf.br ^bb69
        ^bb69:
        %532 = llvm.load %531 : !llvm.ptr -> i32
        %533 = arith.cmpi sle, %532, %516 : i32
        cf.cond_br %533, ^bb70, ^bb71
        ^bb70:
          %535 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
          %536 = llvm.load %531 : !llvm.ptr -> i32
          %537 = arith.extsi %536 : i32 to i64
          %538 = llvm.getelementptr %535[%537] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %534 = llvm.load %538 : !llvm.ptr -> i32
          %539 = arith.cmpi ne, %534, %519 : i32
          cf.cond_br %539, ^bb72, ^bb73
          ^bb72:
            %540 = arith.constant 0 : i32
            llvm.store %540, %526 : i32, !llvm.ptr
            cf.br ^bb71
          ^bb73:
            cf.br ^bb74
          ^bb74:
          %541 = llvm.load %531 : !llvm.ptr -> i32
          %542 = arith.constant 1 : i32
          %543 = arith.addi %541, %542 : i32
          llvm.store %543, %531 : i32, !llvm.ptr
          cf.br ^bb69
        ^bb71:
        %544 = llvm.load %526 : !llvm.ptr -> i32
        %545 = arith.constant 0 : i32
        %546 = arith.cmpi ne, %544, %545 : i32
        cf.cond_br %546, ^bb75, ^bb76
        ^bb75:
          cf.br ^bb65
        ^bb76:
          cf.br ^bb77
        ^bb77:
        cf.br ^bb68
      ^bb67:
        cf.br ^bb68
      ^bb68:
      %547 = llvm.load %362 : !llvm.ptr -> i32
      %548 = arith.constant 2 : i32
      %549 = arith.muli %547, %548 : i32
      %550 = llvm.mlir.constant(1 : i64) : i64
      %551 = llvm.alloca %550 x i32 : (i64) -> !llvm.ptr
      llvm.store %549, %551 : i32, !llvm.ptr
      %552 = llvm.load %551 : !llvm.ptr -> i32
      %553 = arith.cmpi sgt, %516, %552 : i32
      cf.cond_br %553, ^bb78, ^bb79
      ^bb78:
        llvm.store %516, %551 : i32, !llvm.ptr
        cf.br ^bb80
      ^bb79:
        cf.br ^bb80
      ^bb80:
      %554 = llvm.load %551 : !llvm.ptr -> i32
      %555 = arith.cmpi sgt, %358, %554 : i32
      cf.cond_br %555, ^bb81, ^bb82
      ^bb81:
        llvm.store %358, %551 : i32, !llvm.ptr
        cf.br ^bb83
      ^bb82:
        cf.br ^bb83
      ^bb83:
      %557 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
      %558 = llvm.load %551 : !llvm.ptr -> i32
      %559 = arith.constant 1 : i32
      %560 = arith.addi %558, %559 : i32
      %561 = arith.extsi %560 : i32 to i64
      %562 = arith.constant 4 : i32
      %564 = arith.extsi %562 : i32 to i64
      %563 = arith.muli %561, %564 : i64
      %556 = func.call @realloc(%557, %563) : (!llvm.ptr, i64) -> !llvm.ptr
      llvm.store %556, %380 : !llvm.ptr, !llvm.ptr
      # String concatenation: !llvm.ptr + i32
      %567 = arith.constant 0 : i32
      %568 = llvm.load %551 : !llvm.ptr -> i32
      %569 = llvm.load %362 : !llvm.ptr -> i32
      %570 = arith.subi %568, %569 : i32
      %571 = arith.extsi %570 : i32 to i64
      %572 = arith.constant 4 : i32
      %574 = arith.extsi %572 : i32 to i64
      %573 = arith.muli %571, %574 : i64
      func.call @memset(%566, %567, %573) : (!llvm.ptr, i32, i64) -> ()
      %575 = arith.constant 0 : i32
      %576 = llvm.mlir.constant(1 : i64) : i64
      %577 = llvm.alloca %576 x i32 : (i64) -> !llvm.ptr
      llvm.store %575, %577 : i32, !llvm.ptr
      cf.br ^bb84
      ^bb84:
      %578 = llvm.load %577 : !llvm.ptr -> i32
      %579 = arith.cmpi slt, %578, %407 : i32
      cf.cond_br %579, ^bb85, ^bb86
      ^bb85:
        %582 = llvm.load %577 : !llvm.ptr -> i32
        %583 = arith.extsi %582 : i32 to i64
        %584 = llvm.getelementptr %408[%583] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %581 = llvm.load %584 : !llvm.ptr -> !llvm.ptr
        %585 = llvm.load %551 : !llvm.ptr -> i32
        %586 = arith.constant 1 : i32
        %587 = arith.addi %585, %586 : i32
        %588 = arith.extsi %587 : i32 to i64
        %589 = arith.constant 4 : i32
        %591 = arith.extsi %589 : i32 to i64
        %590 = arith.muli %588, %591 : i64
        %580 = func.call @realloc(%581, %590) : (!llvm.ptr, i64) -> !llvm.ptr
        %592 = llvm.load %577 : !llvm.ptr -> i32
        %593 = arith.extsi %592 : i32 to i64
        %594 = llvm.getelementptr %408[%593] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        llvm.store %580, %594 : !llvm.ptr, !llvm.ptr
        %596 = llvm.load %577 : !llvm.ptr -> i32
        %597 = arith.extsi %596 : i32 to i64
        %598 = llvm.getelementptr %408[%597] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %595 = llvm.load %598 : !llvm.ptr -> !llvm.ptr
        %599 = llvm.load %362 : !llvm.ptr -> i32
        %600 = arith.constant 1 : i32
        %601 = arith.addi %599, %600 : i32
        %602 = llvm.mlir.constant(1 : i64) : i64
        %603 = llvm.alloca %602 x i32 : (i64) -> !llvm.ptr
        llvm.store %601, %603 : i32, !llvm.ptr
        cf.br ^bb87
        ^bb87:
        %604 = llvm.load %603 : !llvm.ptr -> i32
        %605 = llvm.load %551 : !llvm.ptr -> i32
        %606 = arith.cmpi sle, %604, %605 : i32
        cf.cond_br %606, ^bb88, ^bb89
        ^bb88:
          %608 = llvm.load %577 : !llvm.ptr -> i32
          %609 = arith.constant 1 : i32
          %610 = arith.addi %608, %609 : i32
          %611 = llvm.load %603 : !llvm.ptr -> i32
          %607 = func.call @getG(%610, %611) : (i32, i32) -> i32
          %613 = llvm.load %577 : !llvm.ptr -> i32
          %614 = arith.subi %358, %613 : i32
          %615 = arith.constant 1 : i32
          %616 = arith.subi %614, %615 : i32
          %617 = llvm.load %603 : !llvm.ptr -> i32
          %612 = func.call @getG(%616, %617) : (i32, i32) -> i32
          %618 = arith.xori %607, %612 : i32
          %619 = llvm.load %603 : !llvm.ptr -> i32
          %620 = arith.extsi %619 : i32 to i64
          %621 = llvm.getelementptr %595[%620] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          llvm.store %618, %621 : i32, !llvm.ptr
          %622 = llvm.load %603 : !llvm.ptr -> i32
          %623 = arith.constant 1 : i32
          %624 = arith.addi %622, %623 : i32
          llvm.store %624, %603 : i32, !llvm.ptr
          cf.br ^bb87
        ^bb89:
        %625 = llvm.load %577 : !llvm.ptr -> i32
        %626 = arith.constant 1 : i32
        %627 = arith.addi %625, %626 : i32
        llvm.store %627, %577 : i32, !llvm.ptr
        cf.br ^bb84
      ^bb86:
      %629 = llvm.load %362 : !llvm.ptr -> i32
      %630 = arith.constant 1 : i32
      %631 = arith.addi %629, %630 : i32
      %632 = llvm.load %551 : !llvm.ptr -> i32
      %633 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
      func.call @compute_h_range(%631, %632, %633, %408, %413, %407) : (i32, i32, !llvm.ptr, !llvm.ptr, !llvm.ptr, i32) -> ()
      %634 = llvm.load %551 : !llvm.ptr -> i32
      llvm.store %634, %362 : i32, !llvm.ptr
      %635 = llvm.load %489 : !llvm.ptr -> i32
      %636 = arith.constant 1 : i32
      %637 = arith.addi %635, %636 : i32
      %638 = llvm.mlir.constant(1 : i64) : i64
      %639 = llvm.alloca %638 x i32 : (i64) -> !llvm.ptr
      llvm.store %637, %639 : i32, !llvm.ptr
      cf.br ^bb90
      ^bb90:
      %640 = llvm.load %639 : !llvm.ptr -> i32
      %641 = llvm.load %362 : !llvm.ptr -> i32
      %642 = arith.cmpi sle, %640, %641 : i32
      cf.cond_br %642, ^bb91, ^bb92
      ^bb91:
        %644 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
        %645 = llvm.load %639 : !llvm.ptr -> i32
        %646 = arith.extsi %645 : i32 to i64
        %647 = llvm.getelementptr %644[%646] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %643 = llvm.load %647 : !llvm.ptr -> i32
        %649 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
        %650 = llvm.load %639 : !llvm.ptr -> i32
        %651 = arith.constant 1 : i32
        %652 = arith.subi %650, %651 : i32
        %653 = arith.extsi %652 : i32 to i64
        %654 = llvm.getelementptr %649[%653] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %648 = llvm.load %654 : !llvm.ptr -> i32
        %655 = arith.cmpi ne, %643, %648 : i32
        cf.cond_br %655, ^bb93, ^bb94
        ^bb93:
          %656 = llvm.load %639 : !llvm.ptr -> i32
          llvm.store %656, %489 : i32, !llvm.ptr
          cf.br ^bb95
        ^bb94:
          cf.br ^bb95
        ^bb95:
        %657 = llvm.load %639 : !llvm.ptr -> i32
        %658 = arith.constant 1 : i32
        %659 = arith.addi %657, %658 : i32
        llvm.store %659, %639 : i32, !llvm.ptr
        cf.br ^bb90
      ^bb92:
      cf.br ^bb63
    ^bb65:
    %660 = llvm.load %362 : !llvm.ptr -> i32
    %661 = llvm.mlir.addressof @B_arr : !llvm.ptr
    %662 = llvm.load %661 : !llvm.ptr -> !llvm.ptr
    %663 = arith.extsi %358 : i32 to i64
    %664 = llvm.getelementptr %662[%663] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %660, %664 : i32, !llvm.ptr
    %665 = llvm.load %489 : !llvm.ptr -> i32
    %666 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
    %667 = llvm.load %666 : !llvm.ptr -> !llvm.ptr
    %668 = arith.extsi %358 : i32 to i64
    %669 = llvm.getelementptr %667[%668] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %665, %669 : i32, !llvm.ptr
    %671 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
    %672 = llvm.load %489 : !llvm.ptr -> i32
    %673 = arith.extsi %672 : i32 to i64
    %674 = llvm.getelementptr %671[%673] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    %670 = llvm.load %674 : !llvm.ptr -> i32
    %675 = llvm.mlir.addressof @const_arr : !llvm.ptr
    %676 = llvm.load %675 : !llvm.ptr -> !llvm.ptr
    %677 = arith.extsi %358 : i32 to i64
    %678 = llvm.getelementptr %676[%677] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %670, %678 : i32, !llvm.ptr
    %679 = llvm.load %380 : !llvm.ptr -> !llvm.ptr
    %680 = llvm.mlir.addressof @G_arr : !llvm.ptr
    %681 = llvm.load %680 : !llvm.ptr -> !llvm.ptr
    %682 = arith.extsi %358 : i32 to i64
    %683 = llvm.getelementptr %681[%682] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
    llvm.store %679, %683 : !llvm.ptr, !llvm.ptr
    %684 = llvm.mlir.addressof @current_w : !llvm.ptr
    llvm.store %358, %684 : i32, !llvm.ptr
    %685 = llvm.load %489 : !llvm.ptr -> i32
    %686 = llvm.mlir.addressof @prev_maxg : !llvm.ptr
    %687 = llvm.load %686 : !llvm.ptr -> i32
    %688 = arith.cmpi sgt, %685, %687 : i32
    cf.cond_br %688, ^bb96, ^bb97
    ^bb96:
      %689 = llvm.load %489 : !llvm.ptr -> i32
      %690 = llvm.mlir.addressof @prev_maxg : !llvm.ptr
      llvm.store %689, %690 : i32, !llvm.ptr
      cf.br ^bb98
    ^bb97:
      cf.br ^bb98
    ^bb98:
    %691 = arith.constant 0 : i32
    %692 = llvm.mlir.constant(1 : i64) : i64
    %693 = llvm.alloca %692 x i32 : (i64) -> !llvm.ptr
    llvm.store %691, %693 : i32, !llvm.ptr
    cf.br ^bb99
    ^bb99:
    %694 = llvm.load %693 : !llvm.ptr -> i32
    %695 = arith.cmpi slt, %694, %407 : i32
    cf.cond_br %695, ^bb100, ^bb101
    ^bb100:
      %698 = llvm.load %693 : !llvm.ptr -> i32
      %699 = arith.extsi %698 : i32 to i64
      %700 = llvm.getelementptr %408[%699] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %697 = llvm.load %700 : !llvm.ptr -> !llvm.ptr
      func.call @free(%697) : (!llvm.ptr) -> ()
      %701 = llvm.load %693 : !llvm.ptr -> i32
      %702 = arith.constant 1 : i32
      %703 = arith.addi %701, %702 : i32
      llvm.store %703, %693 : i32, !llvm.ptr
      cf.br ^bb99
    ^bb101:
    func.call @free(%408) : (!llvm.ptr) -> ()
    func.call @free(%413) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @compute_upto(%arg0: i32) -> () {
    cf.br ^bb102
    ^bb102:
    %706 = llvm.mlir.addressof @current_w : !llvm.ptr
    %707 = llvm.load %706 : !llvm.ptr -> i32
    %708 = arith.cmpi slt, %707, %arg0 : i32
    cf.cond_br %708, ^bb103, ^bb104
    ^bb103:
      func.call @compute_next() : () -> ()
      cf.br ^bb102
    ^bb104:
    func.return
  }
  func.func @count_winning_moves_C(%arg0: i32, %arg1: i32) -> i64 {
    %710 = arith.constant 0 : i32
    %711 = arith.extsi %710 : i32 to i64
    %712 = llvm.mlir.constant(1 : i64) : i64
    %713 = llvm.alloca %712 x i64 : (i64) -> !llvm.ptr
    llvm.store %711, %713 : i64, !llvm.ptr
    %714 = arith.constant 1 : i32
    %715 = llvm.mlir.constant(1 : i64) : i64
    %716 = llvm.alloca %715 x i32 : (i64) -> !llvm.ptr
    llvm.store %714, %716 : i32, !llvm.ptr
    cf.br ^bb105
    ^bb105:
    %717 = llvm.load %716 : !llvm.ptr -> i32
    %718 = arith.cmpi slt, %717, %arg0 : i32
    cf.cond_br %718, ^bb106, ^bb107
    ^bb106:
      %719 = arith.constant 1 : i32
      %720 = llvm.mlir.constant(1 : i64) : i64
      %721 = llvm.alloca %720 x i32 : (i64) -> !llvm.ptr
      llvm.store %719, %721 : i32, !llvm.ptr
      cf.br ^bb108
      ^bb108:
      %722 = llvm.load %721 : !llvm.ptr -> i32
      %723 = arith.cmpi slt, %722, %arg1 : i32
      cf.cond_br %723, ^bb109, ^bb110
      ^bb109:
        %725 = llvm.load %716 : !llvm.ptr -> i32
        %726 = llvm.load %721 : !llvm.ptr -> i32
        %724 = func.call @getG(%725, %726) : (i32, i32) -> i32
        %728 = llvm.load %716 : !llvm.ptr -> i32
        %729 = arith.subi %arg0, %728 : i32
        %730 = llvm.load %721 : !llvm.ptr -> i32
        %727 = func.call @getG(%729, %730) : (i32, i32) -> i32
        %731 = arith.xori %724, %727 : i32
        %733 = llvm.load %716 : !llvm.ptr -> i32
        %734 = llvm.load %721 : !llvm.ptr -> i32
        %735 = arith.subi %arg1, %734 : i32
        %732 = func.call @getG(%733, %735) : (i32, i32) -> i32
        %736 = arith.xori %731, %732 : i32
        %738 = llvm.load %716 : !llvm.ptr -> i32
        %739 = arith.subi %arg0, %738 : i32
        %740 = llvm.load %721 : !llvm.ptr -> i32
        %741 = arith.subi %arg1, %740 : i32
        %737 = func.call @getG(%739, %741) : (i32, i32) -> i32
        %742 = arith.xori %736, %737 : i32
        %743 = arith.constant 0 : i32
        %744 = arith.cmpi eq, %742, %743 : i32
        cf.cond_br %744, ^bb111, ^bb112
        ^bb111:
          %745 = llvm.load %713 : !llvm.ptr -> i64
          %746 = arith.constant 1 : i32
          %748 = arith.extsi %746 : i32 to i64
          %747 = arith.addi %745, %748 : i64
          llvm.store %747, %713 : i64, !llvm.ptr
          cf.br ^bb113
        ^bb112:
          cf.br ^bb113
        ^bb113:
        %749 = llvm.load %721 : !llvm.ptr -> i32
        %750 = arith.constant 1 : i32
        %751 = arith.addi %749, %750 : i32
        llvm.store %751, %721 : i32, !llvm.ptr
        cf.br ^bb108
      ^bb110:
      %752 = llvm.load %716 : !llvm.ptr -> i32
      %753 = arith.constant 1 : i32
      %754 = arith.addi %752, %753 : i32
      llvm.store %754, %716 : i32, !llvm.ptr
      cf.br ^bb105
    ^bb107:
    %755 = llvm.load %713 : !llvm.ptr -> i64
    func.return %755 : i64
  }
  func.func @compute_D(%arg0: i32, %arg1: i64) -> i64 {
    %756 = arith.constant 0 : i32
    %757 = llvm.mlir.constant(1 : i64) : i64
    %758 = llvm.alloca %757 x i32 : (i64) -> !llvm.ptr
    llvm.store %756, %758 : i32, !llvm.ptr
    %759 = arith.constant 1 : i32
    %760 = llvm.mlir.constant(1 : i64) : i64
    %761 = llvm.alloca %760 x i32 : (i64) -> !llvm.ptr
    llvm.store %759, %761 : i32, !llvm.ptr
    cf.br ^bb114
    ^bb114:
    %762 = llvm.load %761 : !llvm.ptr -> i32
    %763 = arith.cmpi sle, %762, %arg0 : i32
    cf.cond_br %763, ^bb115, ^bb116
    ^bb115:
      %765 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
      %766 = llvm.load %765 : !llvm.ptr -> !llvm.ptr
      %767 = llvm.load %761 : !llvm.ptr -> i32
      %768 = arith.extsi %767 : i32 to i64
      %769 = llvm.getelementptr %766[%768] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %764 = llvm.load %769 : !llvm.ptr -> i32
      %770 = llvm.load %758 : !llvm.ptr -> i32
      %771 = arith.cmpi sgt, %764, %770 : i32
      cf.cond_br %771, ^bb117, ^bb118
      ^bb117:
        %773 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
        %774 = llvm.load %773 : !llvm.ptr -> !llvm.ptr
        %775 = llvm.load %761 : !llvm.ptr -> i32
        %776 = arith.extsi %775 : i32 to i64
        %777 = llvm.getelementptr %774[%776] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %772 = llvm.load %777 : !llvm.ptr -> i32
        llvm.store %772, %758 : i32, !llvm.ptr
        cf.br ^bb119
      ^bb118:
        cf.br ^bb119
      ^bb119:
      %778 = llvm.load %761 : !llvm.ptr -> i32
      %779 = arith.constant 1 : i32
      %780 = arith.addi %778, %779 : i32
      llvm.store %780, %761 : i32, !llvm.ptr
      cf.br ^bb114
    ^bb116:
    %781 = llvm.load %758 : !llvm.ptr -> i32
    %782 = llvm.mlir.constant(1 : i64) : i64
    %783 = llvm.alloca %782 x i32 : (i64) -> !llvm.ptr
    llvm.store %781, %783 : i32, !llvm.ptr
    %784 = arith.constant 1 : i32
    %786 = arith.extsi %784 : i32 to i64
    %785 = arith.subi %arg1, %786 : i64
    %787 = arith.trunci %785 : i64 to i32
    %788 = llvm.load %783 : !llvm.ptr -> i32
    %789 = arith.cmpi slt, %787, %788 : i32
    cf.cond_br %789, ^bb120, ^bb121
    ^bb120:
      %790 = arith.constant 1 : i32
      %792 = arith.extsi %790 : i32 to i64
      %791 = arith.subi %arg1, %792 : i64
      %793 = arith.trunci %791 : i64 to i32
      llvm.store %793, %783 : i32, !llvm.ptr
      cf.br ^bb122
    ^bb121:
      cf.br ^bb122
    ^bb122:
    %795 = arith.constant 1 : i32
    %796 = arith.addi %arg0, %795 : i32
    %797 = arith.extsi %796 : i32 to i64
    %798 = arith.constant 8 : i32
    %800 = arith.extsi %798 : i32 to i64
    %799 = arith.muli %797, %800 : i64
    %794 = func.call @malloc(%799) : (i64) -> !llvm.ptr
    %801 = arith.constant 0 : i32
    %802 = llvm.mlir.constant(1 : i64) : i64
    %803 = llvm.alloca %802 x i32 : (i64) -> !llvm.ptr
    llvm.store %801, %803 : i32, !llvm.ptr
    cf.br ^bb123
    ^bb123:
    %804 = llvm.load %803 : !llvm.ptr -> i32
    %805 = arith.cmpi sle, %804, %arg0 : i32
    cf.cond_br %805, ^bb124, ^bb125
    ^bb124:
      %807 = llvm.load %783 : !llvm.ptr -> i32
      %808 = arith.constant 1 : i32
      %809 = arith.addi %807, %808 : i32
      %810 = arith.extsi %809 : i32 to i64
      %811 = arith.constant 4 : i32
      %812 = arith.extsi %811 : i32 to i64
      %806 = func.call @calloc(%810, %812) : (i64, i64) -> !llvm.ptr
      %813 = llvm.load %803 : !llvm.ptr -> i32
      %814 = arith.extsi %813 : i32 to i64
      %815 = llvm.getelementptr %794[%814] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      llvm.store %806, %815 : !llvm.ptr, !llvm.ptr
      %816 = llvm.load %803 : !llvm.ptr -> i32
      %817 = arith.constant 1 : i32
      %818 = arith.addi %816, %817 : i32
      llvm.store %818, %803 : i32, !llvm.ptr
      cf.br ^bb123
    ^bb125:
    %819 = arith.constant 1 : i32
    llvm.store %819, %803 : i32, !llvm.ptr
    cf.br ^bb126
    ^bb126:
    %820 = llvm.load %803 : !llvm.ptr -> i32
    %821 = arith.cmpi sle, %820, %arg0 : i32
    cf.cond_br %821, ^bb127, ^bb128
    ^bb127:
      %822 = arith.constant 1 : i32
      %823 = llvm.mlir.constant(1 : i64) : i64
      %824 = llvm.alloca %823 x i32 : (i64) -> !llvm.ptr
      llvm.store %822, %824 : i32, !llvm.ptr
      cf.br ^bb129
      ^bb129:
      %825 = llvm.load %824 : !llvm.ptr -> i32
      %826 = llvm.load %783 : !llvm.ptr -> i32
      %827 = arith.cmpi sle, %825, %826 : i32
      cf.cond_br %827, ^bb130, ^bb131
      ^bb130:
        %829 = llvm.load %803 : !llvm.ptr -> i32
        %830 = llvm.load %824 : !llvm.ptr -> i32
        %828 = func.call @getG(%829, %830) : (i32, i32) -> i32
        %832 = llvm.load %803 : !llvm.ptr -> i32
        %833 = arith.extsi %832 : i32 to i64
        %834 = llvm.getelementptr %794[%833] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %831 = llvm.load %834 : !llvm.ptr -> !llvm.ptr
        %835 = llvm.load %824 : !llvm.ptr -> i32
        %836 = arith.extsi %835 : i32 to i64
        %837 = llvm.getelementptr %831[%836] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %828, %837 : i32, !llvm.ptr
        %838 = llvm.load %824 : !llvm.ptr -> i32
        %839 = arith.constant 1 : i32
        %840 = arith.addi %838, %839 : i32
        llvm.store %840, %824 : i32, !llvm.ptr
        cf.br ^bb129
      ^bb131:
      %841 = llvm.load %803 : !llvm.ptr -> i32
      %842 = arith.constant 1 : i32
      %843 = arith.addi %841, %842 : i32
      llvm.store %843, %803 : i32, !llvm.ptr
      cf.br ^bb126
    ^bb128:
    %844 = arith.constant 65536 : i32
    %845 = llvm.mlir.constant(1 : i64) : i64
    %846 = llvm.alloca %845 x i32 : (i64) -> !llvm.ptr
    llvm.store %844, %846 : i32, !llvm.ptr
    %848 = llvm.load %846 : !llvm.ptr -> i32
    %849 = arith.extsi %848 : i32 to i64
    %850 = arith.constant 4 : i32
    %851 = arith.extsi %850 : i32 to i64
    %847 = func.call @calloc(%849, %851) : (i64, i64) -> !llvm.ptr
    %852 = llvm.mlir.constant(1 : i64) : i64
    %853 = llvm.alloca %852 x !llvm.ptr : (i64) -> !llvm.ptr
    llvm.store %847, %853 : !llvm.ptr, !llvm.ptr
    %855 = llvm.load %846 : !llvm.ptr -> i32
    %856 = arith.extsi %855 : i32 to i64
    %857 = arith.constant 4 : i32
    %858 = arith.extsi %857 : i32 to i64
    %854 = func.call @calloc(%856, %858) : (i64, i64) -> !llvm.ptr
    %859 = llvm.mlir.constant(1 : i64) : i64
    %860 = llvm.alloca %859 x !llvm.ptr : (i64) -> !llvm.ptr
    llvm.store %854, %860 : !llvm.ptr, !llvm.ptr
    %862 = llvm.load %846 : !llvm.ptr -> i32
    %863 = arith.extsi %862 : i32 to i64
    %864 = arith.constant 4 : i32
    %866 = arith.extsi %864 : i32 to i64
    %865 = arith.muli %863, %866 : i64
    %861 = func.call @malloc(%865) : (i64) -> !llvm.ptr
    %867 = llvm.mlir.constant(1 : i64) : i64
    %868 = llvm.alloca %867 x !llvm.ptr : (i64) -> !llvm.ptr
    llvm.store %861, %868 : !llvm.ptr, !llvm.ptr
    %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
    %872 = arith.constant 0 : i32
    %873 = arith.extsi %872 : i32 to i64
    %874 = llvm.mlir.constant(1 : i64) : i64
    %875 = llvm.alloca %874 x i64 : (i64) -> !llvm.ptr
    llvm.store %873, %875 : i64, !llvm.ptr
    %876 = arith.constant 1 : i32
    %877 = llvm.mlir.constant(1 : i64) : i64
    %878 = llvm.alloca %877 x i32 : (i64) -> !llvm.ptr
    llvm.store %876, %878 : i32, !llvm.ptr
    cf.br ^bb132
    ^bb132:
    %879 = llvm.load %878 : !llvm.ptr -> i32
    %880 = arith.cmpi slt, %879, %arg0 : i32
    cf.cond_br %880, ^bb133, ^bb134
    ^bb133:
      %882 = llvm.load %878 : !llvm.ptr -> i32
      %883 = arith.extsi %882 : i32 to i64
      %884 = llvm.getelementptr %794[%883] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %881 = llvm.load %884 : !llvm.ptr -> !llvm.ptr
      %885 = arith.constant 1 : i32
      %886 = llvm.mlir.constant(1 : i64) : i64
      %887 = llvm.alloca %886 x i32 : (i64) -> !llvm.ptr
      llvm.store %885, %887 : i32, !llvm.ptr
      cf.br ^bb135
      ^bb135:
      %888 = llvm.load %887 : !llvm.ptr -> i32
      %889 = llvm.load %878 : !llvm.ptr -> i32
      %890 = arith.subi %arg0, %889 : i32
      %891 = arith.cmpi sle, %888, %890 : i32
      cf.cond_br %891, ^bb136, ^bb137
      ^bb136:
        %893 = llvm.load %887 : !llvm.ptr -> i32
        %894 = arith.extsi %893 : i32 to i64
        %895 = llvm.getelementptr %794[%894] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %892 = llvm.load %895 : !llvm.ptr -> !llvm.ptr
        %897 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
        %898 = llvm.load %897 : !llvm.ptr -> !llvm.ptr
        %899 = llvm.load %878 : !llvm.ptr -> i32
        %900 = arith.extsi %899 : i32 to i64
        %901 = llvm.getelementptr %898[%900] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %896 = llvm.load %901 : !llvm.ptr -> i32
        %902 = llvm.mlir.constant(1 : i64) : i64
        %903 = llvm.alloca %902 x i32 : (i64) -> !llvm.ptr
        llvm.store %896, %903 : i32, !llvm.ptr
        %905 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
        %906 = llvm.load %905 : !llvm.ptr -> !llvm.ptr
        %907 = llvm.load %887 : !llvm.ptr -> i32
        %908 = arith.extsi %907 : i32 to i64
        %909 = llvm.getelementptr %906[%908] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %904 = llvm.load %909 : !llvm.ptr -> i32
        %910 = llvm.load %903 : !llvm.ptr -> i32
        %911 = arith.cmpi sgt, %904, %910 : i32
        cf.cond_br %911, ^bb138, ^bb139
        ^bb138:
          %913 = llvm.mlir.addressof @g_const_arr : !llvm.ptr
          %914 = llvm.load %913 : !llvm.ptr -> !llvm.ptr
          %915 = llvm.load %887 : !llvm.ptr -> i32
          %916 = arith.extsi %915 : i32 to i64
          %917 = llvm.getelementptr %914[%916] : (!llvm.ptr, i64) -> !llvm.ptr, i32
          %912 = llvm.load %917 : !llvm.ptr -> i32
          llvm.store %912, %903 : i32, !llvm.ptr
          cf.br ^bb140
        ^bb139:
          cf.br ^bb140
        ^bb140:
        %919 = llvm.mlir.addressof @const_arr : !llvm.ptr
        %920 = llvm.load %919 : !llvm.ptr -> !llvm.ptr
        %921 = llvm.load %878 : !llvm.ptr -> i32
        %922 = arith.extsi %921 : i32 to i64
        %923 = llvm.getelementptr %920[%922] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %918 = llvm.load %923 : !llvm.ptr -> i32
        %925 = llvm.mlir.addressof @const_arr : !llvm.ptr
        %926 = llvm.load %925 : !llvm.ptr -> !llvm.ptr
        %927 = llvm.load %887 : !llvm.ptr -> i32
        %928 = arith.extsi %927 : i32 to i64
        %929 = llvm.getelementptr %926[%928] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %924 = llvm.load %929 : !llvm.ptr -> i32
        %930 = arith.xori %918, %924 : i32
        %931 = arith.constant 2 : i32
        %932 = llvm.load %903 : !llvm.ptr -> i32
        %933 = arith.extsi %932 : i32 to i64
        %935 = arith.extsi %931 : i32 to i64
        %934 = arith.muli %935, %933 : i64
        %936 = arith.cmpi sge, %arg1, %934 : i64
        cf.cond_br %936, ^bb141, ^bb142
        ^bb141:
          %937 = llvm.load %903 : !llvm.ptr -> i32
          %938 = arith.constant 1 : i32
          %939 = arith.subi %937, %938 : i32
          %940 = arith.constant 0 : i32
          %941 = arith.extsi %940 : i32 to i64
          %942 = llvm.mlir.constant(1 : i64) : i64
          %943 = llvm.alloca %942 x i64 : (i64) -> !llvm.ptr
          llvm.store %941, %943 : i64, !llvm.ptr
          %944 = arith.constant 0 : i32
          %945 = arith.extsi %944 : i32 to i64
          %946 = llvm.mlir.constant(1 : i64) : i64
          %947 = llvm.alloca %946 x i64 : (i64) -> !llvm.ptr
          llvm.store %945, %947 : i64, !llvm.ptr
          %948 = arith.constant 0 : i32
          %949 = arith.extsi %948 : i32 to i64
          %950 = llvm.mlir.constant(1 : i64) : i64
          %951 = llvm.alloca %950 x i64 : (i64) -> !llvm.ptr
          llvm.store %949, %951 : i64, !llvm.ptr
          %952 = arith.constant 0 : i32
          %953 = arith.extsi %952 : i32 to i64
          %954 = llvm.mlir.constant(1 : i64) : i64
          %955 = llvm.alloca %954 x i64 : (i64) -> !llvm.ptr
          llvm.store %953, %955 : i64, !llvm.ptr
          %956 = arith.constant 0 : i32
          %957 = arith.extsi %956 : i32 to i64
          %958 = llvm.mlir.constant(1 : i64) : i64
          %959 = llvm.alloca %958 x i64 : (i64) -> !llvm.ptr
          llvm.store %957, %959 : i64, !llvm.ptr
          %960 = arith.constant 0 : i32
          %961 = arith.cmpi sgt, %939, %960 : i32
          cf.cond_br %961, ^bb144, ^bb145
          ^bb144:
            %962 = llvm.load %871 : !llvm.ptr -> i32
            %963 = arith.constant 1 : i32
            %964 = arith.addi %962, %963 : i32
            llvm.store %964, %871 : i32, !llvm.ptr
            %965 = arith.constant 0 : i32
            %966 = llvm.mlir.constant(1 : i64) : i64
            %967 = llvm.alloca %966 x i32 : (i64) -> !llvm.ptr
            llvm.store %965, %967 : i32, !llvm.ptr
            %968 = arith.constant 1 : i32
            %969 = llvm.mlir.constant(1 : i64) : i64
            %970 = llvm.alloca %969 x i32 : (i64) -> !llvm.ptr
            llvm.store %968, %970 : i32, !llvm.ptr
            cf.br ^bb147
            ^bb147:
            %971 = llvm.load %970 : !llvm.ptr -> i32
            %972 = arith.cmpi sle, %971, %939 : i32
            cf.cond_br %972, ^bb148, ^bb149
            ^bb148:
              %974 = llvm.load %970 : !llvm.ptr -> i32
              %975 = arith.extsi %974 : i32 to i64
              %976 = llvm.getelementptr %881[%975] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %973 = llvm.load %976 : !llvm.ptr -> i32
              %978 = llvm.load %970 : !llvm.ptr -> i32
              %979 = arith.extsi %978 : i32 to i64
              %980 = llvm.getelementptr %892[%979] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %977 = llvm.load %980 : !llvm.ptr -> i32
              %981 = arith.xori %973, %977 : i32
              %982 = llvm.load %846 : !llvm.ptr -> i32
              %983 = arith.cmpi sge, %981, %982 : i32
              cf.cond_br %983, ^bb150, ^bb151
              ^bb150:
                %984 = llvm.load %846 : !llvm.ptr -> i32
                %985 = llvm.mlir.constant(1 : i64) : i64
                %986 = llvm.alloca %985 x i32 : (i64) -> !llvm.ptr
                llvm.store %984, %986 : i32, !llvm.ptr
                cf.br ^bb153
                ^bb153:
                %987 = llvm.load %986 : !llvm.ptr -> i32
                %988 = arith.cmpi sle, %987, %981 : i32
                cf.cond_br %988, ^bb154, ^bb155
                ^bb154:
                  %989 = llvm.load %986 : !llvm.ptr -> i32
                  %990 = arith.constant 2 : i32
                  %991 = arith.muli %989, %990 : i32
                  llvm.store %991, %986 : i32, !llvm.ptr
                  cf.br ^bb153
                ^bb155:
                %993 = llvm.load %853 : !llvm.ptr -> !llvm.ptr
                %994 = llvm.load %986 : !llvm.ptr -> i32
                %995 = arith.extsi %994 : i32 to i64
                %996 = arith.constant 4 : i32
                %998 = arith.extsi %996 : i32 to i64
                %997 = arith.muli %995, %998 : i64
                %992 = func.call @realloc(%993, %997) : (!llvm.ptr, i64) -> !llvm.ptr
                llvm.store %992, %853 : !llvm.ptr, !llvm.ptr
                %1000 = llvm.load %860 : !llvm.ptr -> !llvm.ptr
                %1001 = llvm.load %986 : !llvm.ptr -> i32
                %1002 = arith.extsi %1001 : i32 to i64
                %1003 = arith.constant 4 : i32
                %1005 = arith.extsi %1003 : i32 to i64
                %1004 = arith.muli %1002, %1005 : i64
                %999 = func.call @realloc(%1000, %1004) : (!llvm.ptr, i64) -> !llvm.ptr
                llvm.store %999, %860 : !llvm.ptr, !llvm.ptr
                %1007 = llvm.load %868 : !llvm.ptr -> !llvm.ptr
                %1008 = llvm.load %986 : !llvm.ptr -> i32
                %1009 = arith.extsi %1008 : i32 to i64
                %1010 = arith.constant 4 : i32
                %1012 = arith.extsi %1010 : i32 to i64
                %1011 = arith.muli %1009, %1012 : i64
                %1006 = func.call @realloc(%1007, %1011) : (!llvm.ptr, i64) -> !llvm.ptr
                llvm.store %1006, %868 : !llvm.ptr, !llvm.ptr
                # String concatenation: !llvm.ptr + i32
                %1015 = arith.constant 0 : i32
                %1016 = llvm.load %986 : !llvm.ptr -> i32
                %1017 = llvm.load %846 : !llvm.ptr -> i32
                %1018 = arith.subi %1016, %1017 : i32
                %1019 = arith.extsi %1018 : i32 to i64
                %1020 = arith.constant 4 : i32
                %1022 = arith.extsi %1020 : i32 to i64
                %1021 = arith.muli %1019, %1022 : i64
                func.call @memset(%1014, %1015, %1021) : (!llvm.ptr, i32, i64) -> ()
                %1023 = llvm.load %986 : !llvm.ptr -> i32
                llvm.store %1023, %846 : i32, !llvm.ptr
                cf.br ^bb152
              ^bb151:
                cf.br ^bb152
              ^bb152:
              %1025 = llvm.load %853 : !llvm.ptr -> !llvm.ptr
              %1026 = arith.extsi %981 : i32 to i64
              %1027 = llvm.getelementptr %1025[%1026] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1024 = llvm.load %1027 : !llvm.ptr -> i32
              %1028 = llvm.load %871 : !llvm.ptr -> i32
              %1029 = arith.cmpi ne, %1024, %1028 : i32
              cf.cond_br %1029, ^bb156, ^bb157
              ^bb156:
                %1030 = llvm.load %871 : !llvm.ptr -> i32
                %1031 = llvm.load %853 : !llvm.ptr -> !llvm.ptr
                %1032 = arith.extsi %981 : i32 to i64
                %1033 = llvm.getelementptr %1031[%1032] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %1030, %1033 : i32, !llvm.ptr
                %1034 = arith.constant 1 : i32
                %1035 = llvm.load %860 : !llvm.ptr -> !llvm.ptr
                %1036 = arith.extsi %981 : i32 to i64
                %1037 = llvm.getelementptr %1035[%1036] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %1034, %1037 : i32, !llvm.ptr
                %1038 = llvm.load %868 : !llvm.ptr -> !llvm.ptr
                %1039 = llvm.load %967 : !llvm.ptr -> i32
                %1040 = arith.extsi %1039 : i32 to i64
                %1041 = llvm.getelementptr %1038[%1040] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %981, %1041 : i32, !llvm.ptr
                %1042 = llvm.load %967 : !llvm.ptr -> i32
                %1043 = arith.constant 1 : i32
                %1044 = arith.addi %1042, %1043 : i32
                llvm.store %1044, %967 : i32, !llvm.ptr
                cf.br ^bb158
              ^bb157:
                %1046 = llvm.load %860 : !llvm.ptr -> !llvm.ptr
                %1047 = arith.extsi %981 : i32 to i64
                %1048 = llvm.getelementptr %1046[%1047] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                %1045 = llvm.load %1048 : !llvm.ptr -> i32
                %1049 = arith.constant 1 : i32
                %1050 = arith.addi %1045, %1049 : i32
                %1051 = llvm.load %860 : !llvm.ptr -> !llvm.ptr
                %1052 = arith.extsi %981 : i32 to i64
                %1053 = llvm.getelementptr %1051[%1052] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %1050, %1053 : i32, !llvm.ptr
                cf.br ^bb158
              ^bb158:
              %1054 = arith.cmpi eq, %981, %930 : i32
              cf.cond_br %1054, ^bb159, ^bb160
              ^bb159:
                %1055 = llvm.load %955 : !llvm.ptr -> i64
                %1056 = arith.constant 1 : i32
                %1058 = arith.extsi %1056 : i32 to i64
                %1057 = arith.addi %1055, %1058 : i64
                llvm.store %1057, %955 : i64, !llvm.ptr
                %1059 = llvm.load %959 : !llvm.ptr -> i64
                %1060 = llvm.load %970 : !llvm.ptr -> i32
                %1061 = arith.extsi %1060 : i32 to i64
                %1062 = arith.addi %1059, %1061 : i64
                llvm.store %1062, %959 : i64, !llvm.ptr
                cf.br ^bb161
              ^bb160:
                cf.br ^bb161
              ^bb161:
              %1063 = llvm.load %970 : !llvm.ptr -> i32
              %1064 = arith.constant 1 : i32
              %1065 = arith.addi %1063, %1064 : i32
              llvm.store %1065, %970 : i32, !llvm.ptr
              cf.br ^bb147
            ^bb149:
            %1066 = arith.constant 0 : i32
            %1067 = llvm.mlir.constant(1 : i64) : i64
            %1068 = llvm.alloca %1067 x i32 : (i64) -> !llvm.ptr
            llvm.store %1066, %1068 : i32, !llvm.ptr
            cf.br ^bb162
            ^bb162:
            %1069 = llvm.load %1068 : !llvm.ptr -> i32
            %1070 = llvm.load %967 : !llvm.ptr -> i32
            %1071 = arith.cmpi slt, %1069, %1070 : i32
            cf.cond_br %1071, ^bb163, ^bb164
            ^bb163:
              %1073 = llvm.load %860 : !llvm.ptr -> !llvm.ptr
              %1075 = llvm.load %868 : !llvm.ptr -> !llvm.ptr
              %1076 = llvm.load %1068 : !llvm.ptr -> i32
              %1077 = arith.extsi %1076 : i32 to i64
              %1078 = llvm.getelementptr %1075[%1077] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1074 = llvm.load %1078 : !llvm.ptr -> i32
              %1079 = arith.extsi %1074 : i32 to i64
              %1080 = llvm.getelementptr %1073[%1079] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1072 = llvm.load %1080 : !llvm.ptr -> i32
              %1081 = arith.extsi %1072 : i32 to i64
              %1082 = llvm.load %943 : !llvm.ptr -> i64
              %1083 = arith.muli %1081, %1081 : i64
              %1084 = arith.addi %1082, %1083 : i64
              llvm.store %1084, %943 : i64, !llvm.ptr
              %1085 = llvm.load %1068 : !llvm.ptr -> i32
              %1086 = arith.constant 1 : i32
              %1087 = arith.addi %1085, %1086 : i32
              llvm.store %1087, %1068 : i32, !llvm.ptr
              cf.br ^bb162
            ^bb164:
            cf.br ^bb146
          ^bb145:
            cf.br ^bb146
          ^bb146:
          %1088 = llvm.load %955 : !llvm.ptr -> i64
          %1089 = arith.constant 0 : i32
          %1091 = arith.extsi %1089 : i32 to i64
          %1090 = arith.cmpi ne, %1088, %1091 : i64
          cf.cond_br %1090, ^bb165, ^bb166
          ^bb165:
            %1092 = arith.constant 2 : i32
            %1093 = llvm.load %955 : !llvm.ptr -> i64
            %1094 = llvm.load %903 : !llvm.ptr -> i32
            %1095 = arith.extsi %1094 : i32 to i64
            %1096 = arith.subi %arg1, %1095 : i64
            %1097 = arith.constant 1 : i32
            %1099 = arith.extsi %1097 : i32 to i64
            %1098 = arith.addi %1096, %1099 : i64
            %1100 = arith.muli %1093, %1098 : i64
            %1101 = llvm.load %959 : !llvm.ptr -> i64
            %1102 = arith.subi %1100, %1101 : i64
            %1104 = arith.extsi %1092 : i32 to i64
            %1103 = arith.muli %1104, %1102 : i64
            llvm.store %1103, %947 : i64, !llvm.ptr
            cf.br ^bb167
          ^bb166:
            cf.br ^bb167
          ^bb167:
          %1105 = arith.constant 2 : i32
          %1106 = llvm.load %903 : !llvm.ptr -> i32
          %1107 = arith.extsi %1106 : i32 to i64
          %1109 = arith.extsi %1105 : i32 to i64
          %1108 = arith.muli %1109, %1107 : i64
          %1110 = arith.subi %arg1, %1108 : i64
          %1111 = arith.constant 0 : i32
          %1113 = arith.extsi %1111 : i32 to i64
          %1112 = arith.cmpi sge, %1110, %1113 : i64
          cf.cond_br %1112, ^bb168, ^bb169
          ^bb168:
            %1114 = arith.constant 1 : i32
            %1116 = arith.extsi %1114 : i32 to i64
            %1115 = arith.addi %1110, %1116 : i64
            %1117 = arith.constant 2 : i32
            %1119 = arith.extsi %1117 : i32 to i64
            %1118 = arith.addi %1110, %1119 : i64
            %1120 = arith.muli %1115, %1118 : i64
            %1121 = arith.constant 2 : i32
            %1123 = arith.extsi %1121 : i32 to i64
            %1122 = arith.divsi %1120, %1123 : i64
            llvm.store %1122, %951 : i64, !llvm.ptr
            cf.br ^bb170
          ^bb169:
            cf.br ^bb170
          ^bb170:
          %1124 = llvm.load %875 : !llvm.ptr -> i64
          %1125 = llvm.load %943 : !llvm.ptr -> i64
          %1126 = arith.addi %1124, %1125 : i64
          %1127 = llvm.load %947 : !llvm.ptr -> i64
          %1128 = arith.addi %1126, %1127 : i64
          %1129 = llvm.load %951 : !llvm.ptr -> i64
          %1130 = arith.addi %1128, %1129 : i64
          llvm.store %1130, %875 : i64, !llvm.ptr
          cf.br ^bb143
        ^bb142:
          %1132 = arith.constant 4 : i32
          %1134 = arith.extsi %1132 : i32 to i64
          %1133 = arith.muli %arg1, %1134 : i64
          %1131 = func.call @malloc(%1133) : (i64) -> !llvm.ptr
          %1135 = arith.constant 1 : i32
          %1136 = llvm.mlir.constant(1 : i64) : i64
          %1137 = llvm.alloca %1136 x i32 : (i64) -> !llvm.ptr
          llvm.store %1135, %1137 : i32, !llvm.ptr
          cf.br ^bb171
          ^bb171:
          %1138 = llvm.load %1137 : !llvm.ptr -> i32
          %1139 = arith.trunci %arg1 : i64 to i32
          %1140 = arith.cmpi slt, %1138, %1139 : i32
          cf.cond_br %1140, ^bb172, ^bb173
          ^bb172:
            %1141 = llvm.load %1137 : !llvm.ptr -> i32
            %1142 = llvm.load %783 : !llvm.ptr -> i32
            %1143 = arith.cmpi sle, %1141, %1142 : i32
            cf.cond_br %1143, ^bb174, ^bb175
            ^bb174:
              %1145 = llvm.load %1137 : !llvm.ptr -> i32
              %1146 = arith.extsi %1145 : i32 to i64
              %1147 = llvm.getelementptr %881[%1146] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1144 = llvm.load %1147 : !llvm.ptr -> i32
              %1149 = llvm.load %1137 : !llvm.ptr -> i32
              %1150 = arith.extsi %1149 : i32 to i64
              %1151 = llvm.getelementptr %892[%1150] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1148 = llvm.load %1151 : !llvm.ptr -> i32
              %1152 = arith.xori %1144, %1148 : i32
              %1153 = llvm.load %1137 : !llvm.ptr -> i32
              %1154 = arith.extsi %1153 : i32 to i64
              %1155 = llvm.getelementptr %1131[%1154] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              llvm.store %1152, %1155 : i32, !llvm.ptr
              cf.br ^bb176
            ^bb175:
              %1156 = llvm.load %1137 : !llvm.ptr -> i32
              %1157 = arith.extsi %1156 : i32 to i64
              %1158 = llvm.getelementptr %1131[%1157] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              llvm.store %930, %1158 : i32, !llvm.ptr
              cf.br ^bb176
            ^bb176:
            %1159 = llvm.load %1137 : !llvm.ptr -> i32
            %1160 = arith.constant 1 : i32
            %1161 = arith.addi %1159, %1160 : i32
            llvm.store %1161, %1137 : i32, !llvm.ptr
            cf.br ^bb171
          ^bb173:
          %1162 = arith.constant 1 : i32
          llvm.store %1162, %1137 : i32, !llvm.ptr
          cf.br ^bb177
          ^bb177:
          %1163 = llvm.load %1137 : !llvm.ptr -> i32
          %1164 = arith.trunci %arg1 : i64 to i32
          %1165 = arith.cmpi slt, %1163, %1164 : i32
          cf.cond_br %1165, ^bb178, ^bb179
          ^bb178:
            %1167 = llvm.load %1137 : !llvm.ptr -> i32
            %1168 = arith.extsi %1167 : i32 to i64
            %1169 = llvm.getelementptr %1131[%1168] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %1166 = llvm.load %1169 : !llvm.ptr -> i32
            %1170 = arith.constant 1 : i32
            %1171 = llvm.mlir.constant(1 : i64) : i64
            %1172 = llvm.alloca %1171 x i32 : (i64) -> !llvm.ptr
            llvm.store %1170, %1172 : i32, !llvm.ptr
            cf.br ^bb180
            ^bb180:
            %1173 = llvm.load %1172 : !llvm.ptr -> i32
            %1174 = arith.trunci %arg1 : i64 to i32
            %1175 = llvm.load %1137 : !llvm.ptr -> i32
            %1176 = arith.subi %1174, %1175 : i32
            %1177 = arith.cmpi sle, %1173, %1176 : i32
            cf.cond_br %1177, ^bb181, ^bb182
            ^bb181:
              %1179 = llvm.load %1172 : !llvm.ptr -> i32
              %1180 = arith.extsi %1179 : i32 to i64
              %1181 = llvm.getelementptr %1131[%1180] : (!llvm.ptr, i64) -> !llvm.ptr, i32
              %1178 = llvm.load %1181 : !llvm.ptr -> i32
              %1182 = arith.cmpi eq, %1166, %1178 : i32
              cf.cond_br %1182, ^bb183, ^bb184
              ^bb183:
                %1183 = llvm.load %875 : !llvm.ptr -> i64
                %1184 = arith.constant 1 : i32
                %1186 = arith.extsi %1184 : i32 to i64
                %1185 = arith.addi %1183, %1186 : i64
                llvm.store %1185, %875 : i64, !llvm.ptr
                cf.br ^bb185
              ^bb184:
                cf.br ^bb185
              ^bb185:
              %1187 = llvm.load %1172 : !llvm.ptr -> i32
              %1188 = arith.constant 1 : i32
              %1189 = arith.addi %1187, %1188 : i32
              llvm.store %1189, %1172 : i32, !llvm.ptr
              cf.br ^bb180
            ^bb182:
            %1190 = llvm.load %1137 : !llvm.ptr -> i32
            %1191 = arith.constant 1 : i32
            %1192 = arith.addi %1190, %1191 : i32
            llvm.store %1192, %1137 : i32, !llvm.ptr
            cf.br ^bb177
          ^bb179:
          func.call @free(%1131) : (!llvm.ptr) -> ()
          cf.br ^bb143
        ^bb143:
        %1194 = llvm.load %887 : !llvm.ptr -> i32
        %1195 = arith.constant 1 : i32
        %1196 = arith.addi %1194, %1195 : i32
        llvm.store %1196, %887 : i32, !llvm.ptr
        cf.br ^bb135
      ^bb137:
      %1197 = llvm.load %878 : !llvm.ptr -> i32
      %1198 = arith.constant 1 : i32
      %1199 = arith.addi %1197, %1198 : i32
      llvm.store %1199, %878 : i32, !llvm.ptr
      cf.br ^bb132
    ^bb134:
    %1200 = arith.constant 0 : i32
    llvm.store %1200, %803 : i32, !llvm.ptr
    cf.br ^bb186
    ^bb186:
    %1201 = llvm.load %803 : !llvm.ptr -> i32
    %1202 = arith.cmpi sle, %1201, %arg0 : i32
    cf.cond_br %1202, ^bb187, ^bb188
    ^bb187:
      %1205 = llvm.load %803 : !llvm.ptr -> i32
      %1206 = arith.extsi %1205 : i32 to i64
      %1207 = llvm.getelementptr %794[%1206] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %1204 = llvm.load %1207 : !llvm.ptr -> !llvm.ptr
      func.call @free(%1204) : (!llvm.ptr) -> ()
      %1208 = llvm.load %803 : !llvm.ptr -> i32
      %1209 = arith.constant 1 : i32
      %1210 = arith.addi %1208, %1209 : i32
      llvm.store %1210, %803 : i32, !llvm.ptr
      cf.br ^bb186
    ^bb188:
    func.call @free(%794) : (!llvm.ptr) -> ()
    %1213 = llvm.load %853 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1213) : (!llvm.ptr) -> ()
    %1215 = llvm.load %860 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1215) : (!llvm.ptr) -> ()
    %1217 = llvm.load %868 : !llvm.ptr -> !llvm.ptr
    func.call @free(%1217) : (!llvm.ptr) -> ()
    %1218 = llvm.load %875 : !llvm.ptr -> i64
    func.return %1218 : i64
  }
  func.func @main() -> i32 {
    func.call @grundy_init() : () -> ()
    %1221 = arith.constant 123 : i32
    func.call @compute_upto(%1221) : (i32) -> ()
    %1223 = arith.constant 5 : i32
    %1224 = arith.constant 3 : i32
    %1222 = func.call @count_winning_moves_C(%1223, %1224) : (i32, i32) -> i64
    %1225 = arith.constant 4 : i32
    %1227 = arith.extsi %1225 : i32 to i64
    %1226 = arith.cmpi ne, %1222, %1227 : i64
    cf.cond_br %1226, ^bb189, ^bb190
    ^bb189:
      %1228 = llvm.mlir.addressof @str_0 : !llvm.ptr
      %1229 = llvm.call @printf(%1228) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr) -> i32
      %1230 = arith.constant 1 : i32
      %1232 = arith.constant 0 : i32
      %1231 = arith.subi %1232, %1230 : i32
      func.return %1231 : i32
    ^bb190:
      cf.br ^bb191
    ^bb191:
    %1234 = arith.constant 12 : i32
    %1235 = arith.constant 123 : i32
    %1236 = arith.extsi %1235 : i32 to i64
    %1233 = func.call @compute_D(%1234, %1236) : (i32, i64) -> i64
    %1237 = arith.constant 327398 : i32
    %1239 = arith.extsi %1237 : i32 to i64
    %1238 = arith.cmpi ne, %1233, %1239 : i64
    cf.cond_br %1238, ^bb192, ^bb193
    ^bb192:
      %1240 = llvm.mlir.addressof @str_1 : !llvm.ptr
      %1241 = llvm.call @printf(%1240) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr) -> i32
      %1242 = arith.constant 1 : i32
      %1244 = arith.constant 0 : i32
      %1243 = arith.subi %1244, %1242 : i32
      func.return %1243 : i32
    ^bb193:
      cf.br ^bb194
    ^bb194:
    %1246 = arith.constant 123 : i32
    %1247 = arith.constant 1234567 : i32
    %1248 = arith.extsi %1247 : i32 to i64
    %1245 = func.call @compute_D(%1246, %1248) : (i32, i64) -> i64
    %1249 = llvm.mlir.addressof @str_2 : !llvm.ptr
    %1250 = llvm.call @printf(%1249, %1245) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %1251 = arith.constant 0 : i32
    func.return %1251 : i32
  }
}