Problem 843

Periodic Circles - S(100) = sum of all possible eventual periods for ring sizes 3..100. Uses 256-bit GF(2) polynomial arithmetic, Berlekamp factorization, and order computations.

Answer2816775424692
Output2816775424692
StatusPASS
Native helperno
Runtime10 ms
Peak memory5536 KB
Time complexityO(2^n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(2^n)O(sqrt(n))
Space complexityO(n^2)O(1)
ApproachFlow solutionTrial division or Pollard rho
VerdictSuboptimal

Flow source

# Project Euler 843
# Periodic Circles - S(100) = sum of all possible eventual periods for ring sizes 3..100.
# Uses 256-bit GF(2) polynomial arithmetic, Berlekamp factorization, and order computations.

import euler.nt { gcd }

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

# ==================== Poly struct (256-bit GF(2)) ====================

struct Poly {
    w0: u64,
    w1: u64,
    w2: u64,
    w3: u64
}

function poly_get_w(p: ptr<Poly>, i: i32) -> u64 {
    if i == 0 { return p[0].w0 }
    if i == 1 { return p[0].w1 }
    if i == 2 { return p[0].w2 }
    return p[0].w3
}

function poly_set_w(p: ptr<Poly>, i: i32, v: u64) -> void {
    if i == 0 { p[0].w0 = v; return }
    if i == 1 { p[0].w1 = v; return }
    if i == 2 { p[0].w2 = v; return }
    p[0].w3 = v
}

function poly_deg(p: ptr<Poly>) -> i32 {
    let mut i: i32 = 3
    while i >= 0 {
        let w: u64 = poly_get_w(p, i)
        if w != 0 {
            let mut v: u64 = w
            let mut bit: i32 = 0
            while v > 1 {
                v = v >> 1
                bit = bit + 1
            }
            return bit + 64 * i
        }
        i = i - 1
    }
    return -1
}

function poly_is_zero(p: ptr<Poly>) -> bool {
    return p[0].w0 == 0 && p[0].w1 == 0 && p[0].w2 == 0 && p[0].w3 == 0
}

function poly_is_one(p: ptr<Poly>) -> bool {
    return p[0].w0 == 1 && p[0].w1 == 0 && p[0].w2 == 0 && p[0].w3 == 0
}

function poly_zero(p: ptr<Poly>) -> void {
    p[0].w0 = 0; p[0].w1 = 0; p[0].w2 = 0; p[0].w3 = 0
}

function poly_one(p: ptr<Poly>) -> void {
    p[0].w0 = 1; p[0].w1 = 0; p[0].w2 = 0; p[0].w3 = 0
}

function poly_copy(dst: ptr<Poly>, src: ptr<Poly>) -> void {
    dst[0].w0 = src[0].w0; dst[0].w1 = src[0].w1
    dst[0].w2 = src[0].w2; dst[0].w3 = src[0].w3
}

function poly_equal(a: ptr<Poly>, b: ptr<Poly>) -> bool {
    return a[0].w0 == b[0].w0 && a[0].w1 == b[0].w1 &&
           a[0].w2 == b[0].w2 && a[0].w3 == b[0].w3
}

function poly_get_bit(p: ptr<Poly>, i: i32) -> i32 {
    let w: u64 = poly_get_w(p, i >> 6)
    return ((w >> (i & 63)) & 1) as i32
}

function poly_set_bit(p: ptr<Poly>, i: i32) -> void {
    let idx: i32 = i >> 6
    let one: u64 = 1
    let cur: u64 = poly_get_w(p, idx)
    poly_set_w(p, idx, cur | (one << ((i & 63) as u64)))
}

function poly_xor(dst: ptr<Poly>, src: ptr<Poly>) -> void {
    dst[0].w0 = dst[0].w0 ^ src[0].w0
    dst[0].w1 = dst[0].w1 ^ src[0].w1
    dst[0].w2 = dst[0].w2 ^ src[0].w2
    dst[0].w3 = dst[0].w3 ^ src[0].w3
}

function poly_shl(dst: ptr<Poly>, src: ptr<Poly>, shift: i32) -> void {
    let ws: i32 = shift >> 6
    let bs: i32 = shift & 63
    poly_zero(dst)
    let one: u64 = 1
    if bs == 0 {
        let mut i: i32 = 3
        while i >= 0 {
            let di: i32 = i + ws
            if di >= 0 && di < 4 {
                poly_set_w(dst, di, poly_get_w(src, i))
            }
            i = i - 1
        }
    } else {
        let mut i: i32 = 3
        while i >= 0 {
            let di: i32 = i + ws
            let sv: u64 = poly_get_w(src, i)
            if di >= 0 && di < 4 {
                let cur: u64 = poly_get_w(dst, di)
                poly_set_w(dst, di, cur | (sv << (bs as u64)))
            }
            if di + 1 >= 0 && di + 1 < 4 {
                let cur2: u64 = poly_get_w(dst, di + 1)
                poly_set_w(dst, di + 1, cur2 | (sv >> ((64 - bs) as u64)))
            }
            i = i - 1
        }
    }
}

function poly_mul(dst: ptr<Poly>, a: ptr<Poly>, b: ptr<Poly>) -> void {
    poly_zero(dst)
    let temp: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let db: i32 = poly_deg(b)
    let mut i: i32 = 0
    while i <= db {
        if poly_get_bit(b, i) != 0 {
            poly_shl(temp, a, i)
            poly_xor(dst, temp)
        }
        i = i + 1
    }
    free(temp as ptr<void>)
}

function poly_mod(dst: ptr<Poly>, a: ptr<Poly>, modv: ptr<Poly>) -> void {
    let r: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_copy(r, a)
    let shifted: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let md: i32 = poly_deg(modv)
    while !poly_is_zero(r) && poly_deg(r) >= md {
        let shift: i32 = poly_deg(r) - md
        poly_shl(shifted, modv, shift)
        poly_xor(r, shifted)
    }
    poly_copy(dst, r)
    free(r as ptr<void>)
    free(shifted as ptr<void>)
}

function poly_mul_mod(dst: ptr<Poly>, a: ptr<Poly>, b: ptr<Poly>, modv: ptr<Poly>) -> void {
    let prod: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_mul(prod, a, b)
    poly_mod(dst, prod, modv)
    free(prod as ptr<void>)
}

function poly_square(dst: ptr<Poly>, a: ptr<Poly>) -> void {
    poly_zero(dst)
    let da: i32 = poly_deg(a)
    let mut i: i32 = 0
    while i <= da {
        if poly_get_bit(a, i) != 0 {
            poly_set_bit(dst, 2 * i)
        }
        i = i + 1
    }
}

function poly_square_mod(dst: ptr<Poly>, a: ptr<Poly>, modv: ptr<Poly>) -> void {
    let sq: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_square(sq, a)
    poly_mod(dst, sq, modv)
    free(sq as ptr<void>)
}

function poly_pow_mod(dst: ptr<Poly>, a: ptr<Poly>, exp0: i64, modv: ptr<Poly>) -> void {
    let res: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let base: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let tmp: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_one(res)
    poly_mod(base, a, modv)
    let mut exp: i64 = exp0
    while exp > 0 {
        if exp % 2 == 1 {
            poly_mul_mod(tmp, res, base, modv)
            poly_copy(res, tmp)
        }
        exp = exp >> 1
        if exp != 0 {
            poly_square_mod(tmp, base, modv)
            poly_copy(base, tmp)
        }
    }
    poly_copy(dst, res)
    free(res as ptr<void>)
    free(base as ptr<void>)
    free(tmp as ptr<void>)
}

function poly_gcd(dst: ptr<Poly>, a: ptr<Poly>, b: ptr<Poly>) -> void {
    let x: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let y: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let r: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_copy(x, a)
    poly_copy(y, b)
    while !poly_is_zero(y) {
        poly_mod(r, x, y)
        poly_copy(x, y)
        poly_copy(y, r)
    }
    poly_copy(dst, x)
    free(x as ptr<void>)
    free(y as ptr<void>)
    free(r as ptr<void>)
}

function poly_div_exact(dst: ptr<Poly>, a: ptr<Poly>, b: ptr<Poly>) -> void {
    let r: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let q: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let shifted: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_copy(r, a)
    poly_zero(q)
    let db: i32 = poly_deg(b)
    while !poly_is_zero(r) && poly_deg(r) >= db {
        let shift: i32 = poly_deg(r) - db
        poly_set_bit(q, shift)
        poly_shl(shifted, b, shift)
        poly_xor(r, shifted)
    }
    poly_copy(dst, q)
    free(r as ptr<void>)
    free(q as ptr<void>)
    free(shifted as ptr<void>)
}

# ==================== Small integer factoring ====================

let mut sieve_arr: ptr<i8> = null
let mut small_primes: ptr<i32> = null
let mut num_small_primes: i32 = 0

function init_sieve() -> void {
    let limit: i64 = 2000000
    sieve_arr = calloc(limit + 1, 1) as ptr<i8>
    memset(sieve_arr as ptr<void>, 1, limit + 1)
    sieve_arr[0] = 0
    sieve_arr[1] = 0
    let mut p: i64 = 2
    while p * p <= limit {
        if sieve_arr[p] != 0 {
            let mut m: i64 = p * p
            while m <= limit {
                sieve_arr[m] = 0
                m = m + p
            }
        }
        p = p + 1
    }
    small_primes = calloc(200000, 4) as ptr<i32>
    num_small_primes = 0
    let mut i: i64 = 2
    while i <= limit {
        if sieve_arr[i] != 0 {
            small_primes[num_small_primes] = i as i32
            num_small_primes = num_small_primes + 1
        }
        i = i + 1
    }
}

function factor_small(n0: i64, factors: ptr<i64>) -> i32 {
    let mut n: i64 = n0
    let mut cnt: i32 = 0
    let mut i: i32 = 0
    while i < num_small_primes {
        let p: i32 = small_primes[i]
        if (p as i64) * (p as i64) > n { break }
        while n % (p as i64) == 0 {
            factors[cnt] = p as i64
            cnt = cnt + 1
            n = n / (p as i64)
        }
        i = i + 1
    }
    if n > 1 {
        factors[cnt] = n
        cnt = cnt + 1
    }
    return cnt
}

# ==================== Berlekamp factorization ====================

function berlekamp_nullspace(f: ptr<Poly>, basis: ptr<Poly>) -> i32 {
    let n: i32 = poly_deg(f)
    if n <= 0 { return 0 }

    let rows: ptr<i128> = calloc(128, 16) as ptr<i128>
    let one128: i128 = 1

    let mut j: i32 = 0
    while j < n {
        let xpow: ptr<Poly> = calloc(1, 32) as ptr<Poly>
        poly_zero(xpow)
        poly_set_bit(xpow, 2 * j)
        let col: ptr<Poly> = calloc(1, 32) as ptr<Poly>
        poly_mod(col, xpow, f)
        let mut i: i32 = 0
        while !poly_is_zero(col) {
            if (col[0].w0 & 1) != 0 {
                rows[i] = rows[i] | (one128 << (j as i128))
            }
            col[0].w0 = (col[0].w0 >> 1) | ((col[0].w1 & 1) << 63)
            col[0].w1 = (col[0].w1 >> 1) | ((col[0].w2 & 1) << 63)
            col[0].w2 = (col[0].w2 >> 1) | ((col[0].w3 & 1) << 63)
            col[0].w3 = col[0].w3 >> 1
            i = i + 1
        }
        free(xpow as ptr<void>)
        free(col as ptr<void>)
        j = j + 1
    }

    # Q - I
    let mut i2: i32 = 0
    while i2 < n {
        rows[i2] = rows[i2] ^ (one128 << (i2 as i128))
        i2 = i2 + 1
    }

    # Gauss-Jordan over GF(2)
    let pivot_cols: ptr<i32> = calloc(128, 4) as ptr<i32>
    let pivot_row_for_col: ptr<i32> = calloc(128, 4) as ptr<i32>
    let mut num_pivots: i32 = 0
    let mut r: i32 = 0
    let mut c: i32 = 0
    while c < n && r < n {
        let mut pivot: i32 = -1
        let mut i3: i32 = r
        while i3 < n {
            if ((rows[i3] >> (c as i128)) & 1) != 0 { pivot = i3; break }
            i3 = i3 + 1
        }
        if pivot < 0 { c = c + 1; continue }
        let tmp: i128 = rows[r]
        rows[r] = rows[pivot]
        rows[pivot] = tmp
        let pv: i128 = rows[r]
        let mut i4: i32 = 0
        while i4 < n {
            if i4 != r && ((rows[i4] >> (c as i128)) & 1) != 0 {
                rows[i4] = rows[i4] ^ pv
            }
            i4 = i4 + 1
        }
        pivot_cols[num_pivots] = c
        pivot_row_for_col[c] = r
        num_pivots = num_pivots + 1
        r = r + 1
        c = c + 1
    }

    # Free columns = non-pivot columns
    let free_cols: ptr<i32> = calloc(128, 4) as ptr<i32>
    let mut num_free: i32 = 0
    let mut c2: i32 = 0
    while c2 < n {
        let mut is_pivot: bool = false
        let mut j2: i32 = 0
        while j2 < num_pivots {
            if pivot_cols[j2] == c2 { is_pivot = true; break }
            j2 = j2 + 1
        }
        if !is_pivot {
            free_cols[num_free] = c2
            num_free = num_free + 1
        }
        c2 = c2 + 1
    }

    let mut fi: i32 = 0
    while fi < num_free {
        let fc: i32 = free_cols[fi]
        let v: ptr<Poly> = calloc(1, 32) as ptr<Poly>
        poly_zero(v)
        poly_set_bit(v, fc)
        let mut j3: i32 = 0
        while j3 < num_pivots {
            let pc: i32 = pivot_cols[j3]
            let row: i128 = rows[pivot_row_for_col[pc]]
            if ((row >> (fc as i128)) & 1) != 0 {
                poly_set_bit(v, pc)
            }
            j3 = j3 + 1
        }
        poly_copy(&basis[fi], v)
        free(v as ptr<void>)
        fi = fi + 1
    }

    free(rows as ptr<void>)
    free(pivot_cols as ptr<void>)
    free(pivot_row_for_col as ptr<void>)
    free(free_cols as ptr<void>)
    return num_free
}

# Factor a square-free monic polynomial into irreducibles (recursive)
function factor_squarefree(f: ptr<Poly>, out: ptr<Poly>) -> i32 {
    let n: i32 = poly_deg(f)
    if n <= 0 { return 0 }
    if n == 1 { poly_copy(&out[0], f); return 1 }

    let basis: ptr<Poly> = calloc(128, 32) as ptr<Poly>
    let nbasis: i32 = berlekamp_nullspace(f, basis)
    if nbasis <= 1 {
        poly_copy(&out[0], f)
        free(basis as ptr<void>)
        return 1
    }

    let total_subsets: i32 = 1 << (nbasis - 1)
    let comb: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let g: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let h: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let out2: ptr<Poly> = calloc(128, 32) as ptr<Poly>

    let mut mask: i32 = 1
    while mask < total_subsets {
        poly_zero(comb)
        let mut j: i32 = 0
        while j < nbasis - 1 {
            if (mask & (1 << j)) != 0 {
                poly_xor(comb, &basis[j + 1])
            }
            j = j + 1
        }
        if poly_is_zero(comb) || poly_is_one(comb) {
            mask = mask + 1
            continue
        }

        poly_gcd(g, f, comb)
        let dg: i32 = poly_deg(g)
        if dg > 0 && dg < n {
            poly_div_exact(h, f, g)
            let ng: i32 = factor_squarefree(g, out)
            let nh: i32 = factor_squarefree(h, out2)
            let mut i: i32 = 0
            while i < nh {
                poly_copy(&out[ng + i], &out2[i])
                i = i + 1
            }
            free(basis as ptr<void>)
            free(comb as ptr<void>)
            free(g as ptr<void>)
            free(h as ptr<void>)
            free(out2 as ptr<void>)
            return ng + nh
        }

        # Try comb ^ 1
        comb[0].w0 = comb[0].w0 ^ 1
        poly_gcd(g, f, comb)
        let dg2: i32 = poly_deg(g)
        if dg2 > 0 && dg2 < n {
            poly_div_exact(h, f, g)
            let ng: i32 = factor_squarefree(g, out)
            let nh: i32 = factor_squarefree(h, out2)
            let mut i: i32 = 0
            while i < nh {
                poly_copy(&out[ng + i], &out2[i])
                i = i + 1
            }
            free(basis as ptr<void>)
            free(comb as ptr<void>)
            free(g as ptr<void>)
            free(h as ptr<void>)
            free(out2 as ptr<void>)
            return ng + nh
        }
        mask = mask + 1
    }

    poly_copy(&out[0], f)
    free(basis as ptr<void>)
    free(comb as ptr<void>)
    free(g as ptr<void>)
    free(h as ptr<void>)
    free(out2 as ptr<void>)
    return 1
}

# ==================== Factor cache for x^m + 1 ====================

let mut factor_cache: ptr<ptr<Poly> > = null
let mut factor_cache_count: ptr<i32> = null
let mut factor_cache_done: ptr<i8> = null

function init_factor_cache() -> void {
    factor_cache = calloc(101, 8) as ptr<ptr<Poly> >
    factor_cache_count = calloc(101, 4) as ptr<i32>
    factor_cache_done = calloc(101, 1) as ptr<i8>
    let mut m: i32 = 0
    while m <= 100 {
        factor_cache[m] = calloc(128, 32) as ptr<Poly>
        m = m + 1
    }
}

function irreducible_factors_xm_plus_1(m: i32, out: ptr<Poly>) -> i32 {
    if factor_cache_done[m] != 0 {
        let mut i: i32 = 0
        while i < factor_cache_count[m] {
            poly_copy(&out[i], &factor_cache[m][i])
            i = i + 1
        }
        return factor_cache_count[m]
    }
    let f: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_zero(f)
    poly_set_bit(f, m)
    poly_set_bit(f, 0)
    let cnt: i32 = factor_squarefree(f, out)
    let mut i: i32 = 0
    while i < cnt {
        poly_copy(&factor_cache[m][i], &out[i])
        i = i + 1
    }
    factor_cache_count[m] = cnt
    factor_cache_done[m] = 1
    free(f as ptr<void>)
    return cnt
}

# ==================== Order computations ====================

function frobenius_orbit_degree(a: ptr<Poly>, mod_irred: ptr<Poly>) -> i32 {
    let t: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let sq: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_copy(t, a)
    let d: i32 = poly_deg(mod_irred)
    let mut k: i32 = 1
    while k <= d {
        poly_square_mod(sq, t, mod_irred)
        poly_copy(t, sq)
        if poly_equal(t, a) {
            free(t as ptr<void>)
            free(sq as ptr<void>)
            return k
        }
        k = k + 1
    }
    free(t as ptr<void>)
    free(sq as ptr<void>)
    return d
}

# Mersenne factors cache
let mut mersenne_cache: ptr<ptr<i64> > = null
let mut mersenne_cache_count: ptr<i32> = null
let mut mersenne_cache_done: ptr<i8> = null

function init_mersenne_cache() -> void {
    mersenne_cache = calloc(42, 8) as ptr<ptr<i64> >
    mersenne_cache_count = calloc(42, 4) as ptr<i32>
    mersenne_cache_done = calloc(42, 1) as ptr<i8>
    let mut k: i32 = 0
    while k < 42 {
        mersenne_cache[k] = calloc(64, 8) as ptr<i64>
        k = k + 1
    }
}

function mersenne_factors(k: i32, out: ptr<i64>) -> i32 {
    if mersenne_cache_done[k] != 0 {
        let mut i: i32 = 0
        while i < mersenne_cache_count[k] {
            out[i] = mersenne_cache[k][i]
            i = i + 1
        }
        return mersenne_cache_count[k]
    }
    let m: i64 = ((1 as i64) << k) - 1
    let cnt: i32 = factor_small(m, out)
    # Sort (bubble sort)
    let mut i: i32 = 0
    while i < cnt - 1 {
        let mut j: i32 = i + 1
        while j < cnt {
            if out[j] < out[i] {
                let tmp: i64 = out[i]
                out[i] = out[j]
                out[j] = tmp
            }
            j = j + 1
        }
        i = i + 1
    }
    i = 0
    while i < cnt {
        mersenne_cache[k][i] = out[i]
        i = i + 1
    }
    mersenne_cache_count[k] = cnt
    mersenne_cache_done[k] = 1
    return cnt
}

function multiplicative_order(a: ptr<Poly>, mod_irred: ptr<Poly>) -> i64 {
    if poly_is_zero(a) { return 0 }

    let k: i32 = frobenius_orbit_degree(a, mod_irred)
    let group_order: i64 = ((1 as i64) << k) - 1
    if group_order == 1 { return 1 }

    let mut order: i64 = group_order
    let facs: ptr<i64> = calloc(64, 8) as ptr<i64>
    let nfac: i32 = mersenne_factors(k, facs)
    let unique_primes: ptr<i64> = calloc(64, 8) as ptr<i64>
    let mut nunique: i32 = 0
    let mut i: i32 = 0
    while i < nfac {
        if i == 0 || facs[i] != facs[i - 1] {
            unique_primes[nunique] = facs[i]
            nunique = nunique + 1
        }
        i = i + 1
    }
    let result: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    i = 0
    while i < nunique {
        let p: i64 = unique_primes[i]
        while order % p == 0 {
            let cand: i64 = order / p
            poly_pow_mod(result, a, cand, mod_irred)
            if poly_is_one(result) {
                order = cand
            } else {
                break
            }
        }
        i = i + 1
    }
    free(facs as ptr<void>)
    free(unique_primes as ptr<void>)
    free(result as ptr<void>)
    return order
}

function max_two_lift_exponent(base_poly: ptr<Poly>, base_odd_order: i64,
                               p: ptr<Poly>, max_exp: i32) -> i32 {
    if max_exp <= 1 { return 0 }

    let mut order: i64 = base_odd_order
    let modv: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let tmp: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let result: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_copy(modv, p)
    let mut t: i32 = 2
    while t <= max_exp {
        poly_mul(tmp, modv, p)
        poly_copy(modv, tmp)
        poly_pow_mod(result, base_poly, order, modv)
        while !poly_is_one(result) {
            order = order * 2
            poly_pow_mod(result, base_poly, order, modv)
        }
        t = t + 1
    }

    let ratio: i64 = order / base_odd_order
    let mut exp: i32 = 0
    while ratio > 1 {
        ratio = ratio >> 1
        exp = exp + 1
    }
    free(modv as ptr<void>)
    free(tmp as ptr<void>)
    free(result as ptr<void>)
    return exp
}

# ==================== Integer GCD/LCM ====================

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

function ilcm(a: i64, b: i64) -> i64 {
    if a == 0 || b == 0 { return 0 }
    let r: i128 = (a / igcd(a, b)) as i128 * (b as i128)
    return r as i64
}

# ==================== Period enumeration ====================

struct DPEntry {
    odd_lcm: i64,
    smax: i32
}

let mut periods_set: ptr<i64> = null
let mut periods_set_count: i32 = 0

function periods_insert(val: i64) -> void {
    let mut i: i32 = 0
    while i < periods_set_count {
        if periods_set[i] == val { return }
        i = i + 1
    }
    periods_set[periods_set_count] = val
    periods_set_count = periods_set_count + 1
}

function periods_for_n(n: i32, out_periods: ptr<i64>, out_count: ptr<i32>) -> void {
    # n = 2^a * m with m odd
    let mut m: i32 = n
    let mut a: i32 = 0
    while m % 2 == 0 {
        m = m / 2
        a = a + 1
    }
    let max_exp: i32 = 1 << a

    # g(x) = x + x^(n-1)
    let g_poly: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    poly_zero(g_poly)
    poly_set_bit(g_poly, 1)
    poly_set_bit(g_poly, n - 1)

    # Factor x^m + 1
    let factors: ptr<Poly> = calloc(128, 32) as ptr<Poly>
    let nfactors: i32 = irreducible_factors_xm_plus_1(m, factors)

    # DP over odd parts
    let dp: ptr<DPEntry> = calloc(8192, 16) as ptr<DPEntry>
    let mut dp_count: i32 = 1
    dp[0].odd_lcm = 1
    dp[0].smax = 0

    let g_mod_p: ptr<Poly> = calloc(1, 32) as ptr<Poly>
    let g_gcd: ptr<Poly> = calloc(1, 32) as ptr<Poly>

    let mut fi: i32 = 0
    while fi < nfactors {
        let p: ptr<Poly> = &factors[fi]

        poly_mod(g_mod_p, g_poly, p)
        poly_gcd(g_gcd, g_mod_p, p)
        if poly_deg(g_gcd) > 0 {
            fi = fi + 1
            continue
        }

        let odd_order: i64 = multiplicative_order(g_mod_p, p)
        let smax: i32 = max_two_lift_exponent(g_poly, odd_order, p, max_exp)

        # Update DP
        let new_dp: ptr<DPEntry> = calloc(8192, 16) as ptr<DPEntry>
        let mut new_dp_count: i32 = 0

        let mut i: i32 = 0
        while i < dp_count {
            new_dp[new_dp_count] = dp[i]
            new_dp_count = new_dp_count + 1
            i = i + 1
        }

        i = 0
        while i < dp_count {
            let nl: i64 = ilcm(dp[i].odd_lcm, odd_order)
            let mut ns: i32 = dp[i].smax
            if smax > ns { ns = smax }

            let mut found: bool = false
            let mut j: i32 = 0
            while j < new_dp_count {
                if new_dp[j].odd_lcm == nl {
                    if ns > new_dp[j].smax { new_dp[j].smax = ns }
                    found = true
                    break
                }
                j = j + 1
            }
            if !found {
                new_dp[new_dp_count].odd_lcm = nl
                new_dp[new_dp_count].smax = ns
                new_dp_count = new_dp_count + 1
            }
            i = i + 1
        }

        let mut k: i32 = 0
        while k < new_dp_count {
            dp[k] = new_dp[k]
            k = k + 1
        }
        dp_count = new_dp_count
        free(new_dp as ptr<void>)
        fi = fi + 1
    }

    # Generate periods
    out_count[0] = 0
    let mut i: i32 = 0
    while i < dp_count {
        let mut e: i32 = 0
        while e <= dp[i].smax {
            out_periods[out_count[0]] = dp[i].odd_lcm << e
            out_count[0] = out_count[0] + 1
            e = e + 1
        }
        i = i + 1
    }

    free(g_poly as ptr<void>)
    free(factors as ptr<void>)
    free(dp as ptr<void>)
    free(g_mod_p as ptr<void>)
    free(g_gcd as ptr<void>)
}

# ==================== Main ====================

function main() -> i32 {
    init_sieve()
    init_factor_cache()
    init_mersenne_cache()

    periods_set = calloc(100000, 8) as ptr<i64>
    periods_set_count = 0

    let periods: ptr<i64> = calloc(10000, 8) as ptr<i64>
    let np_ptr: ptr<i32> = calloc(1, 4) as ptr<i32>

    let mut n: i32 = 3
    while n <= 100 {
        periods_for_n(n, periods, np_ptr)
        let np: i32 = np_ptr[0]
        let mut i: i32 = 0
        while i < np {
            periods_insert(periods[i])
            i = i + 1
        }
        n = n + 1
    }

    let mut total: i64 = 0
    let mut i: i32 = 0
    while i < periods_set_count {
        total = total + periods_set[i]
        i = i + 1
    }

    printf("%lld\n", total)

    free(periods as ptr<void>)
    free(np_ptr as ptr<void>)
    free(periods_set as ptr<void>)
    return 0
}

Generated C

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

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

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

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

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

#include <math.h>

void* _ui_state = NULL;

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

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

typedef struct DPEntry DPEntry;
typedef struct Poly Poly;

struct DPEntry {
    int64_t odd_lcm;
    int32_t smax;
};

struct Poly {
    uint64_t w0;
    uint64_t w1;
    uint64_t w2;
    uint64_t w3;
};

int64_t gcd_i64_i64(int64_t a0, int64_t b0);
int64_t lcm_i64_i64(int64_t a, int64_t b);
int64_t isqrt_i64(int64_t n);
int64_t mulmod_i64_i64_i64(int64_t a0, int64_t b0, int64_t mod);
int64_t mod_pow_i64_i64_i64(int64_t base, int64_t exp, int64_t mod);
bool is_prime_i64(int64_t n);
uint64_t poly_get_w_ptr_Poly_i32(Poly* p, int32_t i);
void poly_set_w_ptr_Poly_i32_u64(Poly* p, int32_t i, uint64_t v);
int32_t poly_deg_ptr_Poly(Poly* p);
bool poly_is_zero_ptr_Poly(Poly* p);
bool poly_is_one_ptr_Poly(Poly* p);
void poly_zero_ptr_Poly(Poly* p);
void poly_one_ptr_Poly(Poly* p);
void poly_copy_ptr_Poly_ptr_Poly(Poly* dst, Poly* src);
bool poly_equal_ptr_Poly_ptr_Poly(Poly* a, Poly* b);
int32_t poly_get_bit_ptr_Poly_i32(Poly* p, int32_t i);
void poly_set_bit_ptr_Poly_i32(Poly* p, int32_t i);
void poly_xor_ptr_Poly_ptr_Poly(Poly* dst, Poly* src);
void poly_shl_ptr_Poly_ptr_Poly_i32(Poly* dst, Poly* src, int32_t shift);
void poly_mul_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b);
void poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* modv);
void poly_mul_mod_ptr_Poly_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b, Poly* modv);
void poly_square_ptr_Poly_ptr_Poly(Poly* dst, Poly* a);
void poly_square_mod_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* modv);
void poly_pow_mod_ptr_Poly_ptr_Poly_i64_ptr_Poly(Poly* dst, Poly* a, int64_t exp0, Poly* modv);
void poly_gcd_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b);
void poly_div_exact_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b);
void init_sieve(void);
int32_t factor_small_i64_ptr_i64(int64_t n0, int64_t* factors);
int32_t berlekamp_nullspace_ptr_Poly_ptr_Poly(Poly* f, Poly* basis);
int32_t factor_squarefree_ptr_Poly_ptr_Poly(Poly* f, Poly* out);
void init_factor_cache(void);
int32_t irreducible_factors_xm_plus_1_i32_ptr_Poly(int32_t m, Poly* out);
int32_t frobenius_orbit_degree_ptr_Poly_ptr_Poly(Poly* a, Poly* mod_irred);
void init_mersenne_cache(void);
int32_t mersenne_factors_i32_ptr_i64(int32_t k, int64_t* out);
int64_t multiplicative_order_ptr_Poly_ptr_Poly(Poly* a, Poly* mod_irred);
int32_t max_two_lift_exponent_ptr_Poly_i64_ptr_Poly_i32(Poly* base_poly, int64_t base_odd_order, Poly* p, int32_t max_exp);
int64_t igcd_i64_i64(int64_t a0, int64_t b0);
int64_t ilcm_i64_i64(int64_t a, int64_t b);
void periods_insert_i64(int64_t val);
void periods_for_n_i32_ptr_i64_ptr_i32(int32_t n, int64_t* out_periods, int32_t* out_count);
int32_t main(void);

/* Module statics */
static int8_t* sieve_arr = NULL;
static int32_t* small_primes = NULL;
static int32_t num_small_primes = 0;
static Poly** factor_cache = NULL;
static int32_t* factor_cache_count = NULL;
static int8_t* factor_cache_done = NULL;
static int64_t** mersenne_cache = NULL;
static int32_t* mersenne_cache_count = NULL;
static int8_t* mersenne_cache_done = NULL;
static int64_t* periods_set = NULL;
static int32_t periods_set_count = 0;

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

int64_t lcm_i64_i64(int64_t a, int64_t b) {
    if ((a == 0 || b == 0)) {
        return 0;
    }
    return (FLOW_CHECKED_DIV((a), (gcd_i64_i64(a, b))) * b);
}

int64_t isqrt_i64(int64_t n) {
    if (n < 2) {
        return n;
    }
    int64_t x = n;
    int64_t y = FLOW_CHECKED_DIV(((x + 1)), (2));
    while (y < x) {
        x = y;
        y = FLOW_CHECKED_DIV(((x + FLOW_CHECKED_DIV((n), (x)))), (2));
    }
    return x;
}

int64_t mulmod_i64_i64_i64(int64_t a0, int64_t b0, int64_t mod) {
    int64_t a = FLOW_CHECKED_MOD((a0), (mod));
    int64_t b = FLOW_CHECKED_MOD((b0), (mod));
    int64_t result = 0;
    while (b > 0) {
        if (FLOW_CHECKED_MOD((b), (2)) == 1) {
            result = FLOW_CHECKED_MOD(((result + a)), (mod));
        }
        a = FLOW_CHECKED_MOD(((a * 2)), (mod));
        b = FLOW_CHECKED_DIV((b), (2));
    }
    return result;
}

int64_t mod_pow_i64_i64_i64(int64_t base, int64_t exp, int64_t mod) {
    if (mod == 1) {
        return 0;
    }
    int64_t result = 1;
    int64_t b = FLOW_CHECKED_MOD((base), (mod));
    int64_t e = exp;
    while (e > 0) {
        if (FLOW_CHECKED_MOD((e), (2)) == 1) {
            result = mulmod_i64_i64_i64(result, b, mod);
        }
        b = mulmod_i64_i64_i64(b, b, mod);
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return result;
}

bool is_prime_i64(int64_t n) {
    if (n < 2) {
        return 0;
    }
    if (n < 4) {
        return 1;
    }
    if ((FLOW_CHECKED_MOD((n), (2)) == 0 || FLOW_CHECKED_MOD((n), (3)) == 0)) {
        return 0;
    }
    int64_t i = 5;
    while ((i * i) <= n) {
        if ((FLOW_CHECKED_MOD((n), (i)) == 0 || FLOW_CHECKED_MOD((n), ((i + 2))) == 0)) {
            return 0;
        }
        i = (i + 6);
    }
    return 1;
}





uint64_t poly_get_w_ptr_Poly_i32(Poly* p, int32_t i) {
    if (i == 0) {
        return p[0].w0;
    }
    if (i == 1) {
        return p[0].w1;
    }
    if (i == 2) {
        return p[0].w2;
    }
    return p[0].w3;
}

void poly_set_w_ptr_Poly_i32_u64(Poly* p, int32_t i, uint64_t v) {
    if (i == 0) {
        p[0].w0 = v;
        return;
    }
    if (i == 1) {
        p[0].w1 = v;
        return;
    }
    if (i == 2) {
        p[0].w2 = v;
        return;
    }
    p[0].w3 = v;
}

int32_t poly_deg_ptr_Poly(Poly* p) {
    int32_t i = 3;
    while (i >= 0) {
        uint64_t w = poly_get_w_ptr_Poly_i32(p, i);
        if (w != 0) {
            uint64_t v = w;
            int32_t bit = 0;
            while (v > 1) {
                v = FLOW_CHECKED_SHR((v), (1));
                bit = (bit + 1);
            }
            return (bit + (64 * i));
        }
        i = (i - 1);
    }
    return (-1);
}

bool poly_is_zero_ptr_Poly(Poly* p) {
    return (((p[0].w0 == 0 && p[0].w1 == 0) && p[0].w2 == 0) && p[0].w3 == 0);
}

bool poly_is_one_ptr_Poly(Poly* p) {
    return (((p[0].w0 == 1 && p[0].w1 == 0) && p[0].w2 == 0) && p[0].w3 == 0);
}

void poly_zero_ptr_Poly(Poly* p) {
    p[0].w0 = 0;
    p[0].w1 = 0;
    p[0].w2 = 0;
    p[0].w3 = 0;
}

void poly_one_ptr_Poly(Poly* p) {
    p[0].w0 = 1;
    p[0].w1 = 0;
    p[0].w2 = 0;
    p[0].w3 = 0;
}

void poly_copy_ptr_Poly_ptr_Poly(Poly* dst, Poly* src) {
    dst[0].w0 = src[0].w0;
    dst[0].w1 = src[0].w1;
    dst[0].w2 = src[0].w2;
    dst[0].w3 = src[0].w3;
}

bool poly_equal_ptr_Poly_ptr_Poly(Poly* a, Poly* b) {
    return (((a[0].w0 == b[0].w0 && a[0].w1 == b[0].w1) && a[0].w2 == b[0].w2) && a[0].w3 == b[0].w3);
}

int32_t poly_get_bit_ptr_Poly_i32(Poly* p, int32_t i) {
    uint64_t w = poly_get_w_ptr_Poly_i32(p, FLOW_CHECKED_SHR((i), (6)));
    return ((int32_t)((FLOW_CHECKED_SHR((w), ((i & 63))) & 1)));
}

void poly_set_bit_ptr_Poly_i32(Poly* p, int32_t i) {
    int32_t idx = FLOW_CHECKED_SHR((i), (6));
    uint64_t one = 1;
    uint64_t cur = poly_get_w_ptr_Poly_i32(p, idx);
    poly_set_w_ptr_Poly_i32_u64(p, idx, (cur | FLOW_CHECKED_SHL((one), (((uint64_t)((i & 63)))))));
}

void poly_xor_ptr_Poly_ptr_Poly(Poly* dst, Poly* src) {
    dst[0].w0 = (dst[0].w0 ^ src[0].w0);
    dst[0].w1 = (dst[0].w1 ^ src[0].w1);
    dst[0].w2 = (dst[0].w2 ^ src[0].w2);
    dst[0].w3 = (dst[0].w3 ^ src[0].w3);
}

void poly_shl_ptr_Poly_ptr_Poly_i32(Poly* dst, Poly* src, int32_t shift) {
    int32_t ws = FLOW_CHECKED_SHR((shift), (6));
    int32_t bs = (shift & 63);
    poly_zero_ptr_Poly(dst);
    uint64_t one = 1;
    if (bs == 0) {
        int32_t i = 3;
        while (i >= 0) {
            int32_t di = (i + ws);
            if ((di >= 0 && di < 4)) {
                poly_set_w_ptr_Poly_i32_u64(dst, di, poly_get_w_ptr_Poly_i32(src, i));
            }
            i = (i - 1);
        }
    } else {
        int32_t i = 3;
        while (i >= 0) {
            int32_t di = (i + ws);
            uint64_t sv = poly_get_w_ptr_Poly_i32(src, i);
            if ((di >= 0 && di < 4)) {
                uint64_t cur = poly_get_w_ptr_Poly_i32(dst, di);
                poly_set_w_ptr_Poly_i32_u64(dst, di, (cur | FLOW_CHECKED_SHL((sv), (((uint64_t)(bs))))));
            }
            if (((di + 1) >= 0 && (di + 1) < 4)) {
                uint64_t cur2 = poly_get_w_ptr_Poly_i32(dst, (di + 1));
                poly_set_w_ptr_Poly_i32_u64(dst, (di + 1), (cur2 | FLOW_CHECKED_SHR((sv), (((uint64_t)((64 - bs)))))));
            }
            i = (i - 1);
        }
    }
}

void poly_mul_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b) {
    poly_zero_ptr_Poly(dst);
    Poly* temp = (Poly*)(((Poly*)(calloc(1, 32))));
    int32_t db = poly_deg_ptr_Poly(b);
    int32_t i = 0;
    while (i <= db) {
        if (poly_get_bit_ptr_Poly_i32(b, i) != 0) {
            poly_shl_ptr_Poly_ptr_Poly_i32(temp, a, i);
            poly_xor_ptr_Poly_ptr_Poly(dst, temp);
        }
        i = (i + 1);
    }
    free(((void*)(temp)));
}

void poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* modv) {
    Poly* r = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_copy_ptr_Poly_ptr_Poly(r, a);
    Poly* shifted = (Poly*)(((Poly*)(calloc(1, 32))));
    int32_t md = poly_deg_ptr_Poly(modv);
    while (((!(poly_is_zero_ptr_Poly(r))) && poly_deg_ptr_Poly(r) >= md)) {
        int32_t shift = (poly_deg_ptr_Poly(r) - md);
        poly_shl_ptr_Poly_ptr_Poly_i32(shifted, modv, shift);
        poly_xor_ptr_Poly_ptr_Poly(r, shifted);
    }
    poly_copy_ptr_Poly_ptr_Poly(dst, r);
    free(((void*)(r)));
    free(((void*)(shifted)));
}

void poly_mul_mod_ptr_Poly_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b, Poly* modv) {
    Poly* prod = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_mul_ptr_Poly_ptr_Poly_ptr_Poly(prod, a, b);
    poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(dst, prod, modv);
    free(((void*)(prod)));
}

void poly_square_ptr_Poly_ptr_Poly(Poly* dst, Poly* a) {
    poly_zero_ptr_Poly(dst);
    int32_t da = poly_deg_ptr_Poly(a);
    int32_t i = 0;
    while (i <= da) {
        if (poly_get_bit_ptr_Poly_i32(a, i) != 0) {
            poly_set_bit_ptr_Poly_i32(dst, (2 * i));
        }
        i = (i + 1);
    }
}

void poly_square_mod_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* modv) {
    Poly* sq = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_square_ptr_Poly_ptr_Poly(sq, a);
    poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(dst, sq, modv);
    free(((void*)(sq)));
}

void poly_pow_mod_ptr_Poly_ptr_Poly_i64_ptr_Poly(Poly* dst, Poly* a, int64_t exp0, Poly* modv) {
    Poly* res = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* base = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* tmp = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_one_ptr_Poly(res);
    poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(base, a, modv);
    int64_t exp = exp0;
    while (exp > 0) {
        if (FLOW_CHECKED_MOD((exp), (2)) == 1) {
            poly_mul_mod_ptr_Poly_ptr_Poly_ptr_Poly_ptr_Poly(tmp, res, base, modv);
            poly_copy_ptr_Poly_ptr_Poly(res, tmp);
        }
        exp = FLOW_CHECKED_SHR((exp), (1));
        if (exp != 0) {
            poly_square_mod_ptr_Poly_ptr_Poly_ptr_Poly(tmp, base, modv);
            poly_copy_ptr_Poly_ptr_Poly(base, tmp);
        }
    }
    poly_copy_ptr_Poly_ptr_Poly(dst, res);
    free(((void*)(res)));
    free(((void*)(base)));
    free(((void*)(tmp)));
}

void poly_gcd_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b) {
    Poly* x = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* y = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* r = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_copy_ptr_Poly_ptr_Poly(x, a);
    poly_copy_ptr_Poly_ptr_Poly(y, b);
    while ((!(poly_is_zero_ptr_Poly(y)))) {
        poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(r, x, y);
        poly_copy_ptr_Poly_ptr_Poly(x, y);
        poly_copy_ptr_Poly_ptr_Poly(y, r);
    }
    poly_copy_ptr_Poly_ptr_Poly(dst, x);
    free(((void*)(x)));
    free(((void*)(y)));
    free(((void*)(r)));
}

void poly_div_exact_ptr_Poly_ptr_Poly_ptr_Poly(Poly* dst, Poly* a, Poly* b) {
    Poly* r = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* q = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* shifted = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_copy_ptr_Poly_ptr_Poly(r, a);
    poly_zero_ptr_Poly(q);
    int32_t db = poly_deg_ptr_Poly(b);
    while (((!(poly_is_zero_ptr_Poly(r))) && poly_deg_ptr_Poly(r) >= db)) {
        int32_t shift = (poly_deg_ptr_Poly(r) - db);
        poly_set_bit_ptr_Poly_i32(q, shift);
        poly_shl_ptr_Poly_ptr_Poly_i32(shifted, b, shift);
        poly_xor_ptr_Poly_ptr_Poly(r, shifted);
    }
    poly_copy_ptr_Poly_ptr_Poly(dst, q);
    free(((void*)(r)));
    free(((void*)(q)));
    free(((void*)(shifted)));
}

void init_sieve(void) {
    int64_t limit = 2000000;
    sieve_arr = ((int8_t*)(calloc((limit + 1), 1)));
    memset(((void*)(sieve_arr)), 1, (limit + 1));
    sieve_arr[0] = 0;
    sieve_arr[1] = 0;
    int64_t p = 2;
    while ((p * p) <= limit) {
        if (sieve_arr[p] != 0) {
            int64_t m = (p * p);
            while (m <= limit) {
                sieve_arr[m] = 0;
                m = (m + p);
            }
        }
        p = (p + 1);
    }
    small_primes = ((int32_t*)(calloc(200000, 4)));
    num_small_primes = 0;
    int64_t i = 2;
    while (i <= limit) {
        if (sieve_arr[i] != 0) {
            small_primes[num_small_primes] = ((int32_t)(i));
            num_small_primes = (num_small_primes + 1);
        }
        i = (i + 1);
    }
}

int32_t factor_small_i64_ptr_i64(int64_t n0, int64_t* factors) {
    int64_t n = n0;
    int32_t cnt = 0;
    int32_t i = 0;
    while (i < num_small_primes) {
        int32_t p = small_primes[i];
        if ((((int64_t)(p)) * ((int64_t)(p))) > n) {
            break;
        }
        while (FLOW_CHECKED_MOD((n), (((int64_t)(p)))) == 0) {
            factors[cnt] = ((int64_t)(p));
            cnt = (cnt + 1);
            n = FLOW_CHECKED_DIV((n), (((int64_t)(p))));
        }
        i = (i + 1);
    }
    if (n > 1) {
        factors[cnt] = n;
        cnt = (cnt + 1);
    }
    return cnt;
}

int32_t berlekamp_nullspace_ptr_Poly_ptr_Poly(Poly* f, Poly* basis) {
    int32_t n = poly_deg_ptr_Poly(f);
    if (n <= 0) {
        return 0;
    }
    __int128* rows = (__int128*)(((__int128*)(calloc(128, 16))));
    __int128 one128 = 1;
    int32_t j = 0;
    while (j < n) {
        Poly* xpow = (Poly*)(((Poly*)(calloc(1, 32))));
        poly_zero_ptr_Poly(xpow);
        poly_set_bit_ptr_Poly_i32(xpow, (2 * j));
        Poly* col = (Poly*)(((Poly*)(calloc(1, 32))));
        poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(col, xpow, f);
        int32_t i = 0;
        while ((!(poly_is_zero_ptr_Poly(col)))) {
            if ((col[0].w0 & 1) != 0) {
                rows[i] = (rows[i] | FLOW_CHECKED_SHL((one128), (((__int128)(j)))));
            }
            col[0].w0 = (FLOW_CHECKED_SHR((col[0].w0), (1)) | FLOW_CHECKED_SHL(((col[0].w1 & 1)), (63)));
            col[0].w1 = (FLOW_CHECKED_SHR((col[0].w1), (1)) | FLOW_CHECKED_SHL(((col[0].w2 & 1)), (63)));
            col[0].w2 = (FLOW_CHECKED_SHR((col[0].w2), (1)) | FLOW_CHECKED_SHL(((col[0].w3 & 1)), (63)));
            col[0].w3 = FLOW_CHECKED_SHR((col[0].w3), (1));
            i = (i + 1);
        }
        free(((void*)(xpow)));
        free(((void*)(col)));
        j = (j + 1);
    }
    int32_t i2 = 0;
    while (i2 < n) {
        rows[i2] = (rows[i2] ^ FLOW_CHECKED_SHL((one128), (((__int128)(i2)))));
        i2 = (i2 + 1);
    }
    int32_t* pivot_cols = (int32_t*)(((int32_t*)(calloc(128, 4))));
    int32_t* pivot_row_for_col = (int32_t*)(((int32_t*)(calloc(128, 4))));
    int32_t num_pivots = 0;
    int32_t r = 0;
    int32_t c = 0;
    while ((c < n && r < n)) {
        int32_t pivot = (-1);
        int32_t i3 = r;
        while (i3 < n) {
            if ((FLOW_CHECKED_SHR((rows[i3]), (((__int128)(c)))) & 1) != 0) {
                pivot = i3;
                break;
            }
            i3 = (i3 + 1);
        }
        if (pivot < 0) {
            c = (c + 1);
            continue;
        }
        __int128 tmp = rows[r];
        rows[r] = rows[pivot];
        rows[pivot] = tmp;
        __int128 pv = rows[r];
        int32_t i4 = 0;
        while (i4 < n) {
            if ((i4 != r && (FLOW_CHECKED_SHR((rows[i4]), (((__int128)(c)))) & 1) != 0)) {
                rows[i4] = (rows[i4] ^ pv);
            }
            i4 = (i4 + 1);
        }
        pivot_cols[num_pivots] = c;
        pivot_row_for_col[c] = r;
        num_pivots = (num_pivots + 1);
        r = (r + 1);
        c = (c + 1);
    }
    int32_t* free_cols = (int32_t*)(((int32_t*)(calloc(128, 4))));
    int32_t num_free = 0;
    int32_t c2 = 0;
    while (c2 < n) {
        bool is_pivot = 0;
        int32_t j2 = 0;
        while (j2 < num_pivots) {
            if (pivot_cols[j2] == c2) {
                is_pivot = 1;
                break;
            }
            j2 = (j2 + 1);
        }
        if ((!(is_pivot))) {
            free_cols[num_free] = c2;
            num_free = (num_free + 1);
        }
        c2 = (c2 + 1);
    }
    int32_t fi = 0;
    while (fi < num_free) {
        int32_t fc = free_cols[fi];
        Poly* v = (Poly*)(((Poly*)(calloc(1, 32))));
        poly_zero_ptr_Poly(v);
        poly_set_bit_ptr_Poly_i32(v, fc);
        int32_t j3 = 0;
        while (j3 < num_pivots) {
            int32_t pc = pivot_cols[j3];
            __int128 row = rows[pivot_row_for_col[pc]];
            if ((FLOW_CHECKED_SHR((row), (((__int128)(fc)))) & 1) != 0) {
                poly_set_bit_ptr_Poly_i32(v, pc);
            }
            j3 = (j3 + 1);
        }
        poly_copy_ptr_Poly_ptr_Poly((&(basis[fi])), v);
        free(((void*)(v)));
        fi = (fi + 1);
    }
    free(((void*)(rows)));
    free(((void*)(pivot_cols)));
    free(((void*)(pivot_row_for_col)));
    free(((void*)(free_cols)));
    return num_free;
}

int32_t factor_squarefree_ptr_Poly_ptr_Poly(Poly* f, Poly* out) {
    int32_t n = poly_deg_ptr_Poly(f);
    if (n <= 0) {
        return 0;
    }
    if (n == 1) {
        poly_copy_ptr_Poly_ptr_Poly((&(out[0])), f);
        return 1;
    }
    Poly* basis = (Poly*)(((Poly*)(calloc(128, 32))));
    int32_t nbasis = berlekamp_nullspace_ptr_Poly_ptr_Poly(f, basis);
    if (nbasis <= 1) {
        poly_copy_ptr_Poly_ptr_Poly((&(out[0])), f);
        free(((void*)(basis)));
        return 1;
    }
    int32_t total_subsets = FLOW_CHECKED_SHL((1), ((nbasis - 1)));
    Poly* comb = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* g = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* h = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* out2 = (Poly*)(((Poly*)(calloc(128, 32))));
    int32_t mask = 1;
    while (mask < total_subsets) {
        poly_zero_ptr_Poly(comb);
        int32_t j = 0;
        while (j < (nbasis - 1)) {
            if ((mask & FLOW_CHECKED_SHL((1), (j))) != 0) {
                poly_xor_ptr_Poly_ptr_Poly(comb, (&(basis[(j + 1)])));
            }
            j = (j + 1);
        }
        if ((poly_is_zero_ptr_Poly(comb) || poly_is_one_ptr_Poly(comb))) {
            mask = (mask + 1);
            continue;
        }
        poly_gcd_ptr_Poly_ptr_Poly_ptr_Poly(g, f, comb);
        int32_t dg = poly_deg_ptr_Poly(g);
        if ((dg > 0 && dg < n)) {
            poly_div_exact_ptr_Poly_ptr_Poly_ptr_Poly(h, f, g);
            int32_t ng = factor_squarefree_ptr_Poly_ptr_Poly(g, out);
            int32_t nh = factor_squarefree_ptr_Poly_ptr_Poly(h, out2);
            int32_t i = 0;
            while (i < nh) {
                poly_copy_ptr_Poly_ptr_Poly((&(out[(ng + i)])), (&(out2[i])));
                i = (i + 1);
            }
            free(((void*)(basis)));
            free(((void*)(comb)));
            free(((void*)(g)));
            free(((void*)(h)));
            free(((void*)(out2)));
            return (ng + nh);
        }
        comb[0].w0 = (comb[0].w0 ^ 1);
        poly_gcd_ptr_Poly_ptr_Poly_ptr_Poly(g, f, comb);
        int32_t dg2 = poly_deg_ptr_Poly(g);
        if ((dg2 > 0 && dg2 < n)) {
            poly_div_exact_ptr_Poly_ptr_Poly_ptr_Poly(h, f, g);
            int32_t ng = factor_squarefree_ptr_Poly_ptr_Poly(g, out);
            int32_t nh = factor_squarefree_ptr_Poly_ptr_Poly(h, out2);
            int32_t i = 0;
            while (i < nh) {
                poly_copy_ptr_Poly_ptr_Poly((&(out[(ng + i)])), (&(out2[i])));
                i = (i + 1);
            }
            free(((void*)(basis)));
            free(((void*)(comb)));
            free(((void*)(g)));
            free(((void*)(h)));
            free(((void*)(out2)));
            return (ng + nh);
        }
        mask = (mask + 1);
    }
    poly_copy_ptr_Poly_ptr_Poly((&(out[0])), f);
    free(((void*)(basis)));
    free(((void*)(comb)));
    free(((void*)(g)));
    free(((void*)(h)));
    free(((void*)(out2)));
    return 1;
}

void init_factor_cache(void) {
    factor_cache = ((Poly**)(calloc(101, 8)));
    factor_cache_count = ((int32_t*)(calloc(101, 4)));
    factor_cache_done = ((int8_t*)(calloc(101, 1)));
    int32_t m = 0;
    while (m <= 100) {
        factor_cache[m] = ((Poly*)(calloc(128, 32)));
        m = (m + 1);
    }
}

int32_t irreducible_factors_xm_plus_1_i32_ptr_Poly(int32_t m, Poly* out) {
    if (factor_cache_done[m] != 0) {
        int32_t i = 0;
        while (i < factor_cache_count[m]) {
            poly_copy_ptr_Poly_ptr_Poly((&(out[i])), (&(factor_cache[m][i])));
            i = (i + 1);
        }
        return factor_cache_count[m];
    }
    Poly* f = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_zero_ptr_Poly(f);
    poly_set_bit_ptr_Poly_i32(f, m);
    poly_set_bit_ptr_Poly_i32(f, 0);
    int32_t cnt = factor_squarefree_ptr_Poly_ptr_Poly(f, out);
    int32_t i = 0;
    while (i < cnt) {
        poly_copy_ptr_Poly_ptr_Poly((&(factor_cache[m][i])), (&(out[i])));
        i = (i + 1);
    }
    factor_cache_count[m] = cnt;
    factor_cache_done[m] = 1;
    free(((void*)(f)));
    return cnt;
}

int32_t frobenius_orbit_degree_ptr_Poly_ptr_Poly(Poly* a, Poly* mod_irred) {
    Poly* t = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* sq = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_copy_ptr_Poly_ptr_Poly(t, a);
    int32_t d = poly_deg_ptr_Poly(mod_irred);
    int32_t k = 1;
    while (k <= d) {
        poly_square_mod_ptr_Poly_ptr_Poly_ptr_Poly(sq, t, mod_irred);
        poly_copy_ptr_Poly_ptr_Poly(t, sq);
        if (poly_equal_ptr_Poly_ptr_Poly(t, a)) {
            free(((void*)(t)));
            free(((void*)(sq)));
            return k;
        }
        k = (k + 1);
    }
    free(((void*)(t)));
    free(((void*)(sq)));
    return d;
}

void init_mersenne_cache(void) {
    mersenne_cache = ((int64_t**)(calloc(42, 8)));
    mersenne_cache_count = ((int32_t*)(calloc(42, 4)));
    mersenne_cache_done = ((int8_t*)(calloc(42, 1)));
    int32_t k = 0;
    while (k < 42) {
        mersenne_cache[k] = ((int64_t*)(calloc(64, 8)));
        k = (k + 1);
    }
}

int32_t mersenne_factors_i32_ptr_i64(int32_t k, int64_t* out) {
    if (mersenne_cache_done[k] != 0) {
        int32_t i = 0;
        while (i < mersenne_cache_count[k]) {
            out[i] = mersenne_cache[k][i];
            i = (i + 1);
        }
        return mersenne_cache_count[k];
    }
    int64_t m = (FLOW_CHECKED_SHL((((int64_t)(1))), (k)) - 1);
    int32_t cnt = factor_small_i64_ptr_i64(m, out);
    int32_t i = 0;
    while (i < (cnt - 1)) {
        int32_t j = (i + 1);
        while (j < cnt) {
            if (out[j] < out[i]) {
                int64_t tmp = out[i];
                out[i] = out[j];
                out[j] = tmp;
            }
            j = (j + 1);
        }
        i = (i + 1);
    }
    i = 0;
    while (i < cnt) {
        mersenne_cache[k][i] = out[i];
        i = (i + 1);
    }
    mersenne_cache_count[k] = cnt;
    mersenne_cache_done[k] = 1;
    return cnt;
}

int64_t multiplicative_order_ptr_Poly_ptr_Poly(Poly* a, Poly* mod_irred) {
    if (poly_is_zero_ptr_Poly(a)) {
        return 0;
    }
    int32_t k = frobenius_orbit_degree_ptr_Poly_ptr_Poly(a, mod_irred);
    int64_t group_order = (FLOW_CHECKED_SHL((((int64_t)(1))), (k)) - 1);
    if (group_order == 1) {
        return 1;
    }
    int64_t order = group_order;
    int64_t* facs = (int64_t*)(((int64_t*)(calloc(64, 8))));
    int32_t nfac = mersenne_factors_i32_ptr_i64(k, facs);
    int64_t* unique_primes = (int64_t*)(((int64_t*)(calloc(64, 8))));
    int32_t nunique = 0;
    int32_t i = 0;
    while (i < nfac) {
        if ((i == 0 || facs[i] != facs[(i - 1)])) {
            unique_primes[nunique] = facs[i];
            nunique = (nunique + 1);
        }
        i = (i + 1);
    }
    Poly* result = (Poly*)(((Poly*)(calloc(1, 32))));
    i = 0;
    while (i < nunique) {
        int64_t p = unique_primes[i];
        while (FLOW_CHECKED_MOD((order), (p)) == 0) {
            int64_t cand = FLOW_CHECKED_DIV((order), (p));
            poly_pow_mod_ptr_Poly_ptr_Poly_i64_ptr_Poly(result, a, cand, mod_irred);
            if (poly_is_one_ptr_Poly(result)) {
                order = cand;
            } else {
                break;
            }
        }
        i = (i + 1);
    }
    free(((void*)(facs)));
    free(((void*)(unique_primes)));
    free(((void*)(result)));
    return order;
}

int32_t max_two_lift_exponent_ptr_Poly_i64_ptr_Poly_i32(Poly* base_poly, int64_t base_odd_order, Poly* p, int32_t max_exp) {
    if (max_exp <= 1) {
        return 0;
    }
    int64_t order = base_odd_order;
    Poly* modv = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* tmp = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* result = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_copy_ptr_Poly_ptr_Poly(modv, p);
    int32_t t = 2;
    while (t <= max_exp) {
        poly_mul_ptr_Poly_ptr_Poly_ptr_Poly(tmp, modv, p);
        poly_copy_ptr_Poly_ptr_Poly(modv, tmp);
        poly_pow_mod_ptr_Poly_ptr_Poly_i64_ptr_Poly(result, base_poly, order, modv);
        while ((!(poly_is_one_ptr_Poly(result)))) {
            order = (order * 2);
            poly_pow_mod_ptr_Poly_ptr_Poly_i64_ptr_Poly(result, base_poly, order, modv);
        }
        t = (t + 1);
    }
    int64_t ratio = FLOW_CHECKED_DIV((order), (base_odd_order));
    int32_t exp = 0;
    while (ratio > 1) {
        ratio = FLOW_CHECKED_SHR((ratio), (1));
        exp = (exp + 1);
    }
    free(((void*)(modv)));
    free(((void*)(tmp)));
    free(((void*)(result)));
    return exp;
}

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

int64_t ilcm_i64_i64(int64_t a, int64_t b) {
    if ((a == 0 || b == 0)) {
        return 0;
    }
    __int128 r = (((__int128)(FLOW_CHECKED_DIV((a), (igcd_i64_i64(a, b))))) * ((__int128)(b)));
    return ((int64_t)(r));
}

void periods_insert_i64(int64_t val) {
    int32_t i = 0;
    while (i < periods_set_count) {
        if (periods_set[i] == val) {
            return;
        }
        i = (i + 1);
    }
    periods_set[periods_set_count] = val;
    periods_set_count = (periods_set_count + 1);
}

void periods_for_n_i32_ptr_i64_ptr_i32(int32_t n, int64_t* out_periods, int32_t* out_count) {
    int32_t m = n;
    int32_t a = 0;
    while (FLOW_CHECKED_MOD((m), (2)) == 0) {
        m = FLOW_CHECKED_DIV((m), (2));
        a = (a + 1);
    }
    int32_t max_exp = FLOW_CHECKED_SHL((1), (a));
    Poly* g_poly = (Poly*)(((Poly*)(calloc(1, 32))));
    poly_zero_ptr_Poly(g_poly);
    poly_set_bit_ptr_Poly_i32(g_poly, 1);
    poly_set_bit_ptr_Poly_i32(g_poly, (n - 1));
    Poly* factors = (Poly*)(((Poly*)(calloc(128, 32))));
    int32_t nfactors = irreducible_factors_xm_plus_1_i32_ptr_Poly(m, factors);
    DPEntry* dp = (DPEntry*)(((DPEntry*)(calloc(8192, 16))));
    int32_t dp_count = 1;
    dp[0].odd_lcm = 1;
    dp[0].smax = 0;
    Poly* g_mod_p = (Poly*)(((Poly*)(calloc(1, 32))));
    Poly* g_gcd = (Poly*)(((Poly*)(calloc(1, 32))));
    int32_t fi = 0;
    while (fi < nfactors) {
        Poly* p = (Poly*)((&(factors[fi])));
        poly_mod_ptr_Poly_ptr_Poly_ptr_Poly(g_mod_p, g_poly, p);
        poly_gcd_ptr_Poly_ptr_Poly_ptr_Poly(g_gcd, g_mod_p, p);
        if (poly_deg_ptr_Poly(g_gcd) > 0) {
            fi = (fi + 1);
            continue;
        }
        int64_t odd_order = multiplicative_order_ptr_Poly_ptr_Poly(g_mod_p, p);
        int32_t smax = max_two_lift_exponent_ptr_Poly_i64_ptr_Poly_i32(g_poly, odd_order, p, max_exp);
        DPEntry* new_dp = (DPEntry*)(((DPEntry*)(calloc(8192, 16))));
        int32_t new_dp_count = 0;
        int32_t i = 0;
        while (i < dp_count) {
            new_dp[new_dp_count] = dp[i];
            new_dp_count = (new_dp_count + 1);
            i = (i + 1);
        }
        i = 0;
        while (i < dp_count) {
            int64_t nl = ilcm_i64_i64(dp[i].odd_lcm, odd_order);
            int32_t ns = dp[i].smax;
            if (smax > ns) {
                ns = smax;
            }
            bool found = 0;
            int32_t j = 0;
            while (j < new_dp_count) {
                if (new_dp[j].odd_lcm == nl) {
                    if (ns > new_dp[j].smax) {
                        new_dp[j].smax = ns;
                    }
                    found = 1;
                    break;
                }
                j = (j + 1);
            }
            if ((!(found))) {
                new_dp[new_dp_count].odd_lcm = nl;
                new_dp[new_dp_count].smax = ns;
                new_dp_count = (new_dp_count + 1);
            }
            i = (i + 1);
        }
        int32_t k = 0;
        while (k < new_dp_count) {
            dp[k] = new_dp[k];
            k = (k + 1);
        }
        dp_count = new_dp_count;
        free(((void*)(new_dp)));
        fi = (fi + 1);
    }
    out_count[0] = 0;
    int32_t i = 0;
    while (i < dp_count) {
        int32_t e = 0;
        while (e <= dp[i].smax) {
            out_periods[out_count[0]] = FLOW_CHECKED_SHL((dp[i].odd_lcm), (e));
            out_count[0] = (out_count[0] + 1);
            e = (e + 1);
        }
        i = (i + 1);
    }
    free(((void*)(g_poly)));
    free(((void*)(factors)));
    free(((void*)(dp)));
    free(((void*)(g_mod_p)));
    free(((void*)(g_gcd)));
}

int32_t main(void) {
    init_sieve();
    init_factor_cache();
    init_mersenne_cache();
    periods_set = ((int64_t*)(calloc(100000, 8)));
    periods_set_count = 0;
    int64_t* periods = (int64_t*)(((int64_t*)(calloc(10000, 8))));
    int32_t* np_ptr = (int32_t*)(((int32_t*)(calloc(1, 4))));
    int32_t n = 3;
    while (n <= 100) {
        periods_for_n_i32_ptr_i64_ptr_i32(n, periods, np_ptr);
        int32_t np = np_ptr[0];
        int32_t i = 0;
        while (i < np) {
            periods_insert_i64(periods[i]);
            i = (i + 1);
        }
        n = (n + 1);
    }
    int64_t total = 0;
    int32_t i = 0;
    while (i < periods_set_count) {
        total = (total + periods_set[i]);
        i = (i + 1);
    }
    printf("%lld\n", total);
    free(((void*)(periods)));
    free(((void*)(np_ptr)));
    free(((void*)(periods_set)));
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func @gcd(%arg0: i64, %arg1: i64) -> i64 {
    %0 = llvm.mlir.constant(1 : i64) : i64
    %1 = llvm.alloca %0 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %1 : i64, !llvm.ptr
    %2 = llvm.mlir.constant(1 : i64) : i64
    %3 = llvm.alloca %2 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %3 : i64, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %4 = llvm.load %3 : !llvm.ptr -> i64
    %5 = arith.constant 0 : i32
    %7 = arith.extsi %5 : i32 to i64
    %6 = arith.cmpi ne, %4, %7 : i64
    cf.cond_br %6, ^bb1, ^bb2
    ^bb1:
      %8 = llvm.load %1 : !llvm.ptr -> i64
      %9 = llvm.load %3 : !llvm.ptr -> i64
      %10 = arith.remsi %8, %9 : i64
      %11 = llvm.load %3 : !llvm.ptr -> i64
      llvm.store %11, %1 : i64, !llvm.ptr
      llvm.store %10, %3 : i64, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %12 = llvm.load %1 : !llvm.ptr -> i64
    func.return %12 : i64
  }
  func.func @lcm(%arg0: i64, %arg1: i64) -> i64 {
    %13 = arith.constant 0 : i32
    %15 = arith.extsi %13 : i32 to i64
    %14 = arith.cmpi eq, %arg0, %15 : i64
    %16 = scf.if %14 -> (i1) {
      %17 = arith.constant true
      scf.yield %17 : i1
    } else {
      %18 = arith.constant 0 : i32
      %20 = arith.extsi %18 : i32 to i64
      %19 = arith.cmpi eq, %arg1, %20 : i64
      scf.yield %19 : i1
    }
    cf.cond_br %16, ^bb3, ^bb4
    ^bb3:
      %21 = arith.constant 0 : i32
      %22 = arith.extsi %21 : i32 to i64
      func.return %22 : i64
    ^bb4:
      cf.br ^bb5
    ^bb5:
    %23 = func.call @gcd(%arg0, %arg1) : (i64, i64) -> i64
    %24 = arith.divsi %arg0, %23 : i64
    %25 = arith.muli %24, %arg1 : i64
    func.return %25 : i64
  }
  func.func @isqrt(%arg0: i64) -> i64 {
    %26 = arith.constant 2 : i32
    %28 = arith.extsi %26 : i32 to i64
    %27 = arith.cmpi slt, %arg0, %28 : i64
    cf.cond_br %27, ^bb6, ^bb7
    ^bb6:
      func.return %arg0 : i64
    ^bb7:
      cf.br ^bb8
    ^bb8:
    %29 = llvm.mlir.constant(1 : i64) : i64
    %30 = llvm.alloca %29 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %30 : i64, !llvm.ptr
    %31 = llvm.load %30 : !llvm.ptr -> i64
    %32 = arith.constant 1 : i32
    %34 = arith.extsi %32 : i32 to i64
    %33 = arith.addi %31, %34 : i64
    %35 = arith.constant 2 : i32
    %37 = arith.extsi %35 : i32 to i64
    %36 = arith.divsi %33, %37 : i64
    %38 = llvm.mlir.constant(1 : i64) : i64
    %39 = llvm.alloca %38 x i64 : (i64) -> !llvm.ptr
    llvm.store %36, %39 : i64, !llvm.ptr
    cf.br ^bb9
    ^bb9:
    %40 = llvm.load %39 : !llvm.ptr -> i64
    %41 = llvm.load %30 : !llvm.ptr -> i64
    %42 = arith.cmpi slt, %40, %41 : i64
    cf.cond_br %42, ^bb10, ^bb11
    ^bb10:
      %43 = llvm.load %39 : !llvm.ptr -> i64
      llvm.store %43, %30 : i64, !llvm.ptr
      %44 = llvm.load %30 : !llvm.ptr -> i64
      %45 = llvm.load %30 : !llvm.ptr -> i64
      %46 = arith.divsi %arg0, %45 : i64
      %47 = arith.addi %44, %46 : i64
      %48 = arith.constant 2 : i32
      %50 = arith.extsi %48 : i32 to i64
      %49 = arith.divsi %47, %50 : i64
      llvm.store %49, %39 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %51 = llvm.load %30 : !llvm.ptr -> i64
    func.return %51 : i64
  }
  func.func @mulmod(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %52 = arith.remsi %arg0, %arg2 : i64
    %53 = llvm.mlir.constant(1 : i64) : i64
    %54 = llvm.alloca %53 x i64 : (i64) -> !llvm.ptr
    llvm.store %52, %54 : i64, !llvm.ptr
    %55 = arith.remsi %arg1, %arg2 : i64
    %56 = llvm.mlir.constant(1 : i64) : i64
    %57 = llvm.alloca %56 x i64 : (i64) -> !llvm.ptr
    llvm.store %55, %57 : i64, !llvm.ptr
    %58 = arith.constant 0 : i32
    %59 = arith.extsi %58 : i32 to i64
    %60 = llvm.mlir.constant(1 : i64) : i64
    %61 = llvm.alloca %60 x i64 : (i64) -> !llvm.ptr
    llvm.store %59, %61 : i64, !llvm.ptr
    cf.br ^bb12
    ^bb12:
    %62 = llvm.load %57 : !llvm.ptr -> i64
    %63 = arith.constant 0 : i32
    %65 = arith.extsi %63 : i32 to i64
    %64 = arith.cmpi sgt, %62, %65 : i64
    cf.cond_br %64, ^bb13, ^bb14
    ^bb13:
      %66 = llvm.load %57 : !llvm.ptr -> i64
      %67 = arith.constant 2 : i32
      %69 = arith.extsi %67 : i32 to i64
      %68 = arith.remsi %66, %69 : i64
      %70 = arith.constant 1 : i32
      %72 = arith.extsi %70 : i32 to i64
      %71 = arith.cmpi eq, %68, %72 : i64
      cf.cond_br %71, ^bb15, ^bb16
      ^bb15:
        %73 = llvm.load %61 : !llvm.ptr -> i64
        %74 = llvm.load %54 : !llvm.ptr -> i64
        %75 = arith.addi %73, %74 : i64
        %76 = arith.remsi %75, %arg2 : i64
        llvm.store %76, %61 : i64, !llvm.ptr
        cf.br ^bb17
      ^bb16:
        cf.br ^bb17
      ^bb17:
      %77 = llvm.load %54 : !llvm.ptr -> i64
      %78 = arith.constant 2 : i32
      %80 = arith.extsi %78 : i32 to i64
      %79 = arith.muli %77, %80 : i64
      %81 = arith.remsi %79, %arg2 : i64
      llvm.store %81, %54 : i64, !llvm.ptr
      %82 = llvm.load %57 : !llvm.ptr -> i64
      %83 = arith.constant 2 : i32
      %85 = arith.extsi %83 : i32 to i64
      %84 = arith.divsi %82, %85 : i64
      llvm.store %84, %57 : i64, !llvm.ptr
      cf.br ^bb12
    ^bb14:
    %86 = llvm.load %61 : !llvm.ptr -> i64
    func.return %86 : i64
  }
  func.func @mod_pow(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %87 = arith.constant 1 : i32
    %89 = arith.extsi %87 : i32 to i64
    %88 = arith.cmpi eq, %arg2, %89 : i64
    cf.cond_br %88, ^bb18, ^bb19
    ^bb18:
      %90 = arith.constant 0 : i32
      %91 = arith.extsi %90 : i32 to i64
      func.return %91 : i64
    ^bb19:
      cf.br ^bb20
    ^bb20:
    %92 = arith.constant 1 : i32
    %93 = arith.extsi %92 : i32 to i64
    %94 = llvm.mlir.constant(1 : i64) : i64
    %95 = llvm.alloca %94 x i64 : (i64) -> !llvm.ptr
    llvm.store %93, %95 : i64, !llvm.ptr
    %96 = arith.remsi %arg0, %arg2 : i64
    %97 = llvm.mlir.constant(1 : i64) : i64
    %98 = llvm.alloca %97 x i64 : (i64) -> !llvm.ptr
    llvm.store %96, %98 : i64, !llvm.ptr
    %99 = llvm.mlir.constant(1 : i64) : i64
    %100 = llvm.alloca %99 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %100 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %101 = llvm.load %100 : !llvm.ptr -> i64
    %102 = arith.constant 0 : i32
    %104 = arith.extsi %102 : i32 to i64
    %103 = arith.cmpi sgt, %101, %104 : i64
    cf.cond_br %103, ^bb22, ^bb23
    ^bb22:
      %105 = llvm.load %100 : !llvm.ptr -> i64
      %106 = arith.constant 2 : i32
      %108 = arith.extsi %106 : i32 to i64
      %107 = arith.remsi %105, %108 : i64
      %109 = arith.constant 1 : i32
      %111 = arith.extsi %109 : i32 to i64
      %110 = arith.cmpi eq, %107, %111 : i64
      cf.cond_br %110, ^bb24, ^bb25
      ^bb24:
        %113 = llvm.load %95 : !llvm.ptr -> i64
        %114 = llvm.load %98 : !llvm.ptr -> i64
        %112 = func.call @mulmod(%113, %114, %arg2) : (i64, i64, i64) -> i64
        llvm.store %112, %95 : i64, !llvm.ptr
        cf.br ^bb26
      ^bb25:
        cf.br ^bb26
      ^bb26:
      %116 = llvm.load %98 : !llvm.ptr -> i64
      %117 = llvm.load %98 : !llvm.ptr -> i64
      %115 = func.call @mulmod(%116, %117, %arg2) : (i64, i64, i64) -> i64
      llvm.store %115, %98 : i64, !llvm.ptr
      %118 = llvm.load %100 : !llvm.ptr -> i64
      %119 = arith.constant 2 : i32
      %121 = arith.extsi %119 : i32 to i64
      %120 = arith.divsi %118, %121 : i64
      llvm.store %120, %100 : i64, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    %122 = llvm.load %95 : !llvm.ptr -> i64
    func.return %122 : i64
  }
  func.func @is_prime(%arg0: i64) -> i1 {
    %123 = arith.constant 2 : i32
    %125 = arith.extsi %123 : i32 to i64
    %124 = arith.cmpi slt, %arg0, %125 : i64
    cf.cond_br %124, ^bb27, ^bb28
    ^bb27:
      %126 = arith.constant 0 : i1
      func.return %126 : i1
    ^bb28:
      cf.br ^bb29
    ^bb29:
    %127 = arith.constant 4 : i32
    %129 = arith.extsi %127 : i32 to i64
    %128 = arith.cmpi slt, %arg0, %129 : i64
    cf.cond_br %128, ^bb30, ^bb31
    ^bb30:
      %130 = arith.constant 1 : i1
      func.return %130 : i1
    ^bb31:
      cf.br ^bb32
    ^bb32:
    %131 = arith.constant 2 : i32
    %133 = arith.extsi %131 : i32 to i64
    %132 = arith.remsi %arg0, %133 : i64
    %134 = arith.constant 0 : i32
    %136 = arith.extsi %134 : i32 to i64
    %135 = arith.cmpi eq, %132, %136 : i64
    %137 = scf.if %135 -> (i1) {
      %138 = arith.constant true
      scf.yield %138 : i1
    } else {
      %139 = arith.constant 3 : i32
      %141 = arith.extsi %139 : i32 to i64
      %140 = arith.remsi %arg0, %141 : i64
      %142 = arith.constant 0 : i32
      %144 = arith.extsi %142 : i32 to i64
      %143 = arith.cmpi eq, %140, %144 : i64
      scf.yield %143 : i1
    }
    cf.cond_br %137, ^bb33, ^bb34
    ^bb33:
      %145 = arith.constant 0 : i1
      func.return %145 : i1
    ^bb34:
      cf.br ^bb35
    ^bb35:
    %146 = arith.constant 5 : i32
    %147 = arith.extsi %146 : i32 to i64
    %148 = llvm.mlir.constant(1 : i64) : i64
    %149 = llvm.alloca %148 x i64 : (i64) -> !llvm.ptr
    llvm.store %147, %149 : i64, !llvm.ptr
    cf.br ^bb36
    ^bb36:
    %150 = llvm.load %149 : !llvm.ptr -> i64
    %151 = llvm.load %149 : !llvm.ptr -> i64
    %152 = arith.muli %150, %151 : i64
    %153 = arith.cmpi sle, %152, %arg0 : i64
    cf.cond_br %153, ^bb37, ^bb38
    ^bb37:
      %154 = llvm.load %149 : !llvm.ptr -> i64
      %155 = arith.remsi %arg0, %154 : i64
      %156 = arith.constant 0 : i32
      %158 = arith.extsi %156 : i32 to i64
      %157 = arith.cmpi eq, %155, %158 : i64
      %159 = scf.if %157 -> (i1) {
        %160 = arith.constant true
        scf.yield %160 : i1
      } else {
        %161 = llvm.load %149 : !llvm.ptr -> i64
        %162 = arith.constant 2 : i32
        %164 = arith.extsi %162 : i32 to i64
        %163 = arith.addi %161, %164 : i64
        %165 = arith.remsi %arg0, %163 : i64
        %166 = arith.constant 0 : i32
        %168 = arith.extsi %166 : i32 to i64
        %167 = arith.cmpi eq, %165, %168 : i64
        scf.yield %167 : i1
      }
      cf.cond_br %159, ^bb39, ^bb40
      ^bb39:
        %169 = arith.constant 0 : i1
        func.return %169 : i1
      ^bb40:
        cf.br ^bb41
      ^bb41:
      %170 = llvm.load %149 : !llvm.ptr -> i64
      %171 = arith.constant 6 : i32
      %173 = arith.extsi %171 : i32 to i64
      %172 = arith.addi %170, %173 : i64
      llvm.store %172, %149 : i64, !llvm.ptr
      cf.br ^bb36
    ^bb38:
    %174 = arith.constant 1 : i1
    func.return %174 : i1
  }
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @malloc(i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  func.func private @memset(!llvm.ptr, i64, i64) -> !llvm.ptr
  // Struct: Poly
  // Fields:
  //   w0: i64
  //   w1: i64
  //   w2: i64
  //   w3: i64
  func.func @poly_get_w(%arg0: !llvm.ptr, %arg1: i32) -> i64 {
    %175 = arith.constant 0 : i32
    %176 = arith.cmpi eq, %arg1, %175 : i32
    cf.cond_br %176, ^bb42, ^bb43
    ^bb42:
      %178 = arith.constant 0 : i32
      %179 = arith.extsi %178 : i32 to i64
      %180 = llvm.getelementptr %arg0[%179] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %177 = llvm.load %180 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %181 = arith.constant 0 : i32
      %182 = arith.extsi %181 : i32 to i64
      %183 = llvm.getelementptr %arg0[%182] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %184 = llvm.getelementptr %183[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %185 = llvm.load %184 : !llvm.ptr -> i64
      func.return %185 : i64
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %186 = arith.constant 1 : i32
    %187 = arith.cmpi eq, %arg1, %186 : i32
    cf.cond_br %187, ^bb45, ^bb46
    ^bb45:
      %189 = arith.constant 0 : i32
      %190 = arith.extsi %189 : i32 to i64
      %191 = llvm.getelementptr %arg0[%190] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %188 = llvm.load %191 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %192 = arith.constant 0 : i32
      %193 = arith.extsi %192 : i32 to i64
      %194 = llvm.getelementptr %arg0[%193] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %195 = llvm.getelementptr %194[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %196 = llvm.load %195 : !llvm.ptr -> i64
      func.return %196 : i64
    ^bb46:
      cf.br ^bb47
    ^bb47:
    %197 = arith.constant 2 : i32
    %198 = arith.cmpi eq, %arg1, %197 : i32
    cf.cond_br %198, ^bb48, ^bb49
    ^bb48:
      %200 = arith.constant 0 : i32
      %201 = arith.extsi %200 : i32 to i64
      %202 = llvm.getelementptr %arg0[%201] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %199 = llvm.load %202 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %203 = arith.constant 0 : i32
      %204 = arith.extsi %203 : i32 to i64
      %205 = llvm.getelementptr %arg0[%204] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %206 = llvm.getelementptr %205[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %207 = llvm.load %206 : !llvm.ptr -> i64
      func.return %207 : i64
    ^bb49:
      cf.br ^bb50
    ^bb50:
    %209 = arith.constant 0 : i32
    %210 = arith.extsi %209 : i32 to i64
    %211 = llvm.getelementptr %arg0[%210] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %208 = llvm.load %211 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %212 = arith.constant 0 : i32
    %213 = arith.extsi %212 : i32 to i64
    %214 = llvm.getelementptr %arg0[%213] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %215 = llvm.getelementptr %214[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %216 = llvm.load %215 : !llvm.ptr -> i64
    func.return %216 : i64
  }
  func.func @poly_set_w(%arg0: !llvm.ptr, %arg1: i32, %arg2: i64) -> () {
    %217 = arith.constant 0 : i32
    %218 = arith.cmpi eq, %arg1, %217 : i32
    cf.cond_br %218, ^bb51, ^bb52
    ^bb51:
      %219 = arith.constant 0 : i32
      %220 = arith.extsi %219 : i32 to i64
      %221 = llvm.getelementptr %arg0[%220] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %222 = llvm.getelementptr %221[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      llvm.store %arg2, %222 : i64, !llvm.ptr
      func.return
    ^bb52:
      cf.br ^bb53
    ^bb53:
    %223 = arith.constant 1 : i32
    %224 = arith.cmpi eq, %arg1, %223 : i32
    cf.cond_br %224, ^bb54, ^bb55
    ^bb54:
      %225 = arith.constant 0 : i32
      %226 = arith.extsi %225 : i32 to i64
      %227 = llvm.getelementptr %arg0[%226] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %228 = llvm.getelementptr %227[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      llvm.store %arg2, %228 : i64, !llvm.ptr
      func.return
    ^bb55:
      cf.br ^bb56
    ^bb56:
    %229 = arith.constant 2 : i32
    %230 = arith.cmpi eq, %arg1, %229 : i32
    cf.cond_br %230, ^bb57, ^bb58
    ^bb57:
      %231 = arith.constant 0 : i32
      %232 = arith.extsi %231 : i32 to i64
      %233 = llvm.getelementptr %arg0[%232] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %234 = llvm.getelementptr %233[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      llvm.store %arg2, %234 : i64, !llvm.ptr
      func.return
    ^bb58:
      cf.br ^bb59
    ^bb59:
    %235 = arith.constant 0 : i32
    %236 = arith.extsi %235 : i32 to i64
    %237 = llvm.getelementptr %arg0[%236] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %238 = llvm.getelementptr %237[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %arg2, %238 : i64, !llvm.ptr
    func.return
  }
  func.func @poly_deg(%arg0: !llvm.ptr) -> i32 {
    %239 = arith.constant 3 : i32
    %240 = llvm.mlir.constant(1 : i64) : i64
    %241 = llvm.alloca %240 x i32 : (i64) -> !llvm.ptr
    llvm.store %239, %241 : i32, !llvm.ptr
    cf.br ^bb60
    ^bb60:
    %242 = llvm.load %241 : !llvm.ptr -> i32
    %243 = arith.constant 0 : i32
    %244 = arith.cmpi sge, %242, %243 : i32
    cf.cond_br %244, ^bb61, ^bb62
    ^bb61:
      %246 = llvm.load %241 : !llvm.ptr -> i32
      %245 = func.call @poly_get_w(%arg0, %246) : (!llvm.ptr, i32) -> i64
      %247 = arith.constant 0 : i32
      %249 = arith.extsi %247 : i32 to i64
      %248 = arith.cmpi ne, %245, %249 : i64
      cf.cond_br %248, ^bb63, ^bb64
      ^bb63:
        %250 = llvm.mlir.constant(1 : i64) : i64
        %251 = llvm.alloca %250 x i64 : (i64) -> !llvm.ptr
        llvm.store %245, %251 : i64, !llvm.ptr
        %252 = arith.constant 0 : i32
        %253 = llvm.mlir.constant(1 : i64) : i64
        %254 = llvm.alloca %253 x i32 : (i64) -> !llvm.ptr
        llvm.store %252, %254 : i32, !llvm.ptr
        cf.br ^bb66
        ^bb66:
        %255 = llvm.load %251 : !llvm.ptr -> i64
        %256 = arith.constant 1 : i32
        %258 = arith.extsi %256 : i32 to i64
        %257 = arith.cmpi ugt, %255, %258 : i64
        cf.cond_br %257, ^bb67, ^bb68
        ^bb67:
          %259 = llvm.load %251 : !llvm.ptr -> i64
          %260 = arith.constant 1 : i32
          %262 = arith.extsi %260 : i32 to i64
          %261 = arith.shrui %259, %262 : i64
          llvm.store %261, %251 : i64, !llvm.ptr
          %263 = llvm.load %254 : !llvm.ptr -> i32
          %264 = arith.constant 1 : i32
          %265 = arith.addi %263, %264 : i32
          llvm.store %265, %254 : i32, !llvm.ptr
          cf.br ^bb66
        ^bb68:
        %266 = llvm.load %254 : !llvm.ptr -> i32
        %267 = arith.constant 64 : i32
        %268 = llvm.load %241 : !llvm.ptr -> i32
        %269 = arith.muli %267, %268 : i32
        %270 = arith.addi %266, %269 : i32
        func.return %270 : i32
      ^bb64:
        cf.br ^bb65
      ^bb65:
      %271 = llvm.load %241 : !llvm.ptr -> i32
      %272 = arith.constant 1 : i32
      %273 = arith.subi %271, %272 : i32
      llvm.store %273, %241 : i32, !llvm.ptr
      cf.br ^bb60
    ^bb62:
    %274 = arith.constant 1 : i32
    %276 = arith.constant 0 : i32
    %275 = arith.subi %276, %274 : i32
    func.return %275 : i32
  }
  func.func @poly_is_zero(%arg0: !llvm.ptr) -> i1 {
    %278 = arith.constant 0 : i32
    %279 = arith.extsi %278 : i32 to i64
    %280 = llvm.getelementptr %arg0[%279] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %277 = llvm.load %280 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %281 = arith.constant 0 : i32
    %282 = arith.extsi %281 : i32 to i64
    %283 = llvm.getelementptr %arg0[%282] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %284 = llvm.getelementptr %283[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %285 = llvm.load %284 : !llvm.ptr -> i64
    %286 = arith.constant 0 : i32
    %288 = arith.extsi %286 : i32 to i64
    %287 = arith.cmpi eq, %285, %288 : i64
    %289 = scf.if %287 -> (i1) {
      %291 = arith.constant 0 : i32
      %292 = arith.extsi %291 : i32 to i64
      %293 = llvm.getelementptr %arg0[%292] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %290 = llvm.load %293 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %294 = arith.constant 0 : i32
      %295 = arith.extsi %294 : i32 to i64
      %296 = llvm.getelementptr %arg0[%295] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %297 = llvm.getelementptr %296[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %298 = llvm.load %297 : !llvm.ptr -> i64
      %299 = arith.constant 0 : i32
      %301 = arith.extsi %299 : i32 to i64
      %300 = arith.cmpi eq, %298, %301 : i64
      scf.yield %300 : i1
    } else {
      %302 = arith.constant false
      scf.yield %302 : i1
    }
    %303 = scf.if %289 -> (i1) {
      %305 = arith.constant 0 : i32
      %306 = arith.extsi %305 : i32 to i64
      %307 = llvm.getelementptr %arg0[%306] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %304 = llvm.load %307 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %308 = arith.constant 0 : i32
      %309 = arith.extsi %308 : i32 to i64
      %310 = llvm.getelementptr %arg0[%309] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %311 = llvm.getelementptr %310[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %312 = llvm.load %311 : !llvm.ptr -> i64
      %313 = arith.constant 0 : i32
      %315 = arith.extsi %313 : i32 to i64
      %314 = arith.cmpi eq, %312, %315 : i64
      scf.yield %314 : i1
    } else {
      %316 = arith.constant false
      scf.yield %316 : i1
    }
    %317 = scf.if %303 -> (i1) {
      %319 = arith.constant 0 : i32
      %320 = arith.extsi %319 : i32 to i64
      %321 = llvm.getelementptr %arg0[%320] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %318 = llvm.load %321 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %322 = arith.constant 0 : i32
      %323 = arith.extsi %322 : i32 to i64
      %324 = llvm.getelementptr %arg0[%323] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %325 = llvm.getelementptr %324[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %326 = llvm.load %325 : !llvm.ptr -> i64
      %327 = arith.constant 0 : i32
      %329 = arith.extsi %327 : i32 to i64
      %328 = arith.cmpi eq, %326, %329 : i64
      scf.yield %328 : i1
    } else {
      %330 = arith.constant false
      scf.yield %330 : i1
    }
    func.return %317 : i1
  }
  func.func @poly_is_one(%arg0: !llvm.ptr) -> i1 {
    %332 = arith.constant 0 : i32
    %333 = arith.extsi %332 : i32 to i64
    %334 = llvm.getelementptr %arg0[%333] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %331 = llvm.load %334 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %335 = arith.constant 0 : i32
    %336 = arith.extsi %335 : i32 to i64
    %337 = llvm.getelementptr %arg0[%336] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %338 = llvm.getelementptr %337[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %339 = llvm.load %338 : !llvm.ptr -> i64
    %340 = arith.constant 1 : i32
    %342 = arith.extsi %340 : i32 to i64
    %341 = arith.cmpi eq, %339, %342 : i64
    %343 = scf.if %341 -> (i1) {
      %345 = arith.constant 0 : i32
      %346 = arith.extsi %345 : i32 to i64
      %347 = llvm.getelementptr %arg0[%346] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %344 = llvm.load %347 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %348 = arith.constant 0 : i32
      %349 = arith.extsi %348 : i32 to i64
      %350 = llvm.getelementptr %arg0[%349] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %351 = llvm.getelementptr %350[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %352 = llvm.load %351 : !llvm.ptr -> i64
      %353 = arith.constant 0 : i32
      %355 = arith.extsi %353 : i32 to i64
      %354 = arith.cmpi eq, %352, %355 : i64
      scf.yield %354 : i1
    } else {
      %356 = arith.constant false
      scf.yield %356 : i1
    }
    %357 = scf.if %343 -> (i1) {
      %359 = arith.constant 0 : i32
      %360 = arith.extsi %359 : i32 to i64
      %361 = llvm.getelementptr %arg0[%360] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %358 = llvm.load %361 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %362 = arith.constant 0 : i32
      %363 = arith.extsi %362 : i32 to i64
      %364 = llvm.getelementptr %arg0[%363] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %365 = llvm.getelementptr %364[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %366 = llvm.load %365 : !llvm.ptr -> i64
      %367 = arith.constant 0 : i32
      %369 = arith.extsi %367 : i32 to i64
      %368 = arith.cmpi eq, %366, %369 : i64
      scf.yield %368 : i1
    } else {
      %370 = arith.constant false
      scf.yield %370 : i1
    }
    %371 = scf.if %357 -> (i1) {
      %373 = arith.constant 0 : i32
      %374 = arith.extsi %373 : i32 to i64
      %375 = llvm.getelementptr %arg0[%374] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %372 = llvm.load %375 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %376 = arith.constant 0 : i32
      %377 = arith.extsi %376 : i32 to i64
      %378 = llvm.getelementptr %arg0[%377] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %379 = llvm.getelementptr %378[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %380 = llvm.load %379 : !llvm.ptr -> i64
      %381 = arith.constant 0 : i32
      %383 = arith.extsi %381 : i32 to i64
      %382 = arith.cmpi eq, %380, %383 : i64
      scf.yield %382 : i1
    } else {
      %384 = arith.constant false
      scf.yield %384 : i1
    }
    func.return %371 : i1
  }
  func.func @poly_zero(%arg0: !llvm.ptr) -> () {
    %385 = arith.constant 0 : i32
    %386 = arith.constant 0 : i32
    %387 = arith.extsi %386 : i32 to i64
    %388 = llvm.getelementptr %arg0[%387] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %389 = arith.extsi %385 : i32 to i64
    %390 = llvm.getelementptr %388[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %389, %390 : i64, !llvm.ptr
    %391 = arith.constant 0 : i32
    %392 = arith.constant 0 : i32
    %393 = arith.extsi %392 : i32 to i64
    %394 = llvm.getelementptr %arg0[%393] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %395 = arith.extsi %391 : i32 to i64
    %396 = llvm.getelementptr %394[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %395, %396 : i64, !llvm.ptr
    %397 = arith.constant 0 : i32
    %398 = arith.constant 0 : i32
    %399 = arith.extsi %398 : i32 to i64
    %400 = llvm.getelementptr %arg0[%399] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %401 = arith.extsi %397 : i32 to i64
    %402 = llvm.getelementptr %400[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %401, %402 : i64, !llvm.ptr
    %403 = arith.constant 0 : i32
    %404 = arith.constant 0 : i32
    %405 = arith.extsi %404 : i32 to i64
    %406 = llvm.getelementptr %arg0[%405] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %407 = arith.extsi %403 : i32 to i64
    %408 = llvm.getelementptr %406[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %407, %408 : i64, !llvm.ptr
    func.return
  }
  func.func @poly_one(%arg0: !llvm.ptr) -> () {
    %409 = arith.constant 1 : i32
    %410 = arith.constant 0 : i32
    %411 = arith.extsi %410 : i32 to i64
    %412 = llvm.getelementptr %arg0[%411] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %413 = arith.extsi %409 : i32 to i64
    %414 = llvm.getelementptr %412[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %413, %414 : i64, !llvm.ptr
    %415 = arith.constant 0 : i32
    %416 = arith.constant 0 : i32
    %417 = arith.extsi %416 : i32 to i64
    %418 = llvm.getelementptr %arg0[%417] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %419 = arith.extsi %415 : i32 to i64
    %420 = llvm.getelementptr %418[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %419, %420 : i64, !llvm.ptr
    %421 = arith.constant 0 : i32
    %422 = arith.constant 0 : i32
    %423 = arith.extsi %422 : i32 to i64
    %424 = llvm.getelementptr %arg0[%423] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %425 = arith.extsi %421 : i32 to i64
    %426 = llvm.getelementptr %424[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %425, %426 : i64, !llvm.ptr
    %427 = arith.constant 0 : i32
    %428 = arith.constant 0 : i32
    %429 = arith.extsi %428 : i32 to i64
    %430 = llvm.getelementptr %arg0[%429] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %431 = arith.extsi %427 : i32 to i64
    %432 = llvm.getelementptr %430[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %431, %432 : i64, !llvm.ptr
    func.return
  }
  func.func @poly_copy(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
    %434 = arith.constant 0 : i32
    %435 = arith.extsi %434 : i32 to i64
    %436 = llvm.getelementptr %arg1[%435] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %433 = llvm.load %436 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %437 = arith.constant 0 : i32
    %438 = arith.extsi %437 : i32 to i64
    %439 = llvm.getelementptr %arg1[%438] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %440 = llvm.getelementptr %439[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %441 = llvm.load %440 : !llvm.ptr -> i64
    %442 = arith.constant 0 : i32
    %443 = arith.extsi %442 : i32 to i64
    %444 = llvm.getelementptr %arg0[%443] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %445 = llvm.getelementptr %444[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %441, %445 : i64, !llvm.ptr
    %447 = arith.constant 0 : i32
    %448 = arith.extsi %447 : i32 to i64
    %449 = llvm.getelementptr %arg1[%448] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %446 = llvm.load %449 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %450 = arith.constant 0 : i32
    %451 = arith.extsi %450 : i32 to i64
    %452 = llvm.getelementptr %arg1[%451] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %453 = llvm.getelementptr %452[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %454 = llvm.load %453 : !llvm.ptr -> i64
    %455 = arith.constant 0 : i32
    %456 = arith.extsi %455 : i32 to i64
    %457 = llvm.getelementptr %arg0[%456] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %458 = llvm.getelementptr %457[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %454, %458 : i64, !llvm.ptr
    %460 = arith.constant 0 : i32
    %461 = arith.extsi %460 : i32 to i64
    %462 = llvm.getelementptr %arg1[%461] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %459 = llvm.load %462 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %463 = arith.constant 0 : i32
    %464 = arith.extsi %463 : i32 to i64
    %465 = llvm.getelementptr %arg1[%464] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %466 = llvm.getelementptr %465[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %467 = llvm.load %466 : !llvm.ptr -> i64
    %468 = arith.constant 0 : i32
    %469 = arith.extsi %468 : i32 to i64
    %470 = llvm.getelementptr %arg0[%469] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %471 = llvm.getelementptr %470[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %467, %471 : i64, !llvm.ptr
    %473 = arith.constant 0 : i32
    %474 = arith.extsi %473 : i32 to i64
    %475 = llvm.getelementptr %arg1[%474] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %472 = llvm.load %475 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %476 = arith.constant 0 : i32
    %477 = arith.extsi %476 : i32 to i64
    %478 = llvm.getelementptr %arg1[%477] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %479 = llvm.getelementptr %478[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %480 = llvm.load %479 : !llvm.ptr -> i64
    %481 = arith.constant 0 : i32
    %482 = arith.extsi %481 : i32 to i64
    %483 = llvm.getelementptr %arg0[%482] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %484 = llvm.getelementptr %483[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %480, %484 : i64, !llvm.ptr
    func.return
  }
  func.func @poly_equal(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> i1 {
    %486 = arith.constant 0 : i32
    %487 = arith.extsi %486 : i32 to i64
    %488 = llvm.getelementptr %arg0[%487] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %485 = llvm.load %488 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %489 = arith.constant 0 : i32
    %490 = arith.extsi %489 : i32 to i64
    %491 = llvm.getelementptr %arg0[%490] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %492 = llvm.getelementptr %491[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %493 = llvm.load %492 : !llvm.ptr -> i64
    %495 = arith.constant 0 : i32
    %496 = arith.extsi %495 : i32 to i64
    %497 = llvm.getelementptr %arg1[%496] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %494 = llvm.load %497 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %498 = arith.constant 0 : i32
    %499 = arith.extsi %498 : i32 to i64
    %500 = llvm.getelementptr %arg1[%499] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %501 = llvm.getelementptr %500[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %502 = llvm.load %501 : !llvm.ptr -> i64
    %503 = arith.cmpi eq, %493, %502 : i64
    %504 = scf.if %503 -> (i1) {
      %506 = arith.constant 0 : i32
      %507 = arith.extsi %506 : i32 to i64
      %508 = llvm.getelementptr %arg0[%507] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %505 = llvm.load %508 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %509 = arith.constant 0 : i32
      %510 = arith.extsi %509 : i32 to i64
      %511 = llvm.getelementptr %arg0[%510] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %512 = llvm.getelementptr %511[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %513 = llvm.load %512 : !llvm.ptr -> i64
      %515 = arith.constant 0 : i32
      %516 = arith.extsi %515 : i32 to i64
      %517 = llvm.getelementptr %arg1[%516] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %514 = llvm.load %517 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %518 = arith.constant 0 : i32
      %519 = arith.extsi %518 : i32 to i64
      %520 = llvm.getelementptr %arg1[%519] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %521 = llvm.getelementptr %520[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %522 = llvm.load %521 : !llvm.ptr -> i64
      %523 = arith.cmpi eq, %513, %522 : i64
      scf.yield %523 : i1
    } else {
      %524 = arith.constant false
      scf.yield %524 : i1
    }
    %525 = scf.if %504 -> (i1) {
      %527 = arith.constant 0 : i32
      %528 = arith.extsi %527 : i32 to i64
      %529 = llvm.getelementptr %arg0[%528] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %526 = llvm.load %529 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %530 = arith.constant 0 : i32
      %531 = arith.extsi %530 : i32 to i64
      %532 = llvm.getelementptr %arg0[%531] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %533 = llvm.getelementptr %532[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %534 = llvm.load %533 : !llvm.ptr -> i64
      %536 = arith.constant 0 : i32
      %537 = arith.extsi %536 : i32 to i64
      %538 = llvm.getelementptr %arg1[%537] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %535 = llvm.load %538 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %539 = arith.constant 0 : i32
      %540 = arith.extsi %539 : i32 to i64
      %541 = llvm.getelementptr %arg1[%540] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %542 = llvm.getelementptr %541[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %543 = llvm.load %542 : !llvm.ptr -> i64
      %544 = arith.cmpi eq, %534, %543 : i64
      scf.yield %544 : i1
    } else {
      %545 = arith.constant false
      scf.yield %545 : i1
    }
    %546 = scf.if %525 -> (i1) {
      %548 = arith.constant 0 : i32
      %549 = arith.extsi %548 : i32 to i64
      %550 = llvm.getelementptr %arg0[%549] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %547 = llvm.load %550 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %551 = arith.constant 0 : i32
      %552 = arith.extsi %551 : i32 to i64
      %553 = llvm.getelementptr %arg0[%552] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %554 = llvm.getelementptr %553[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %555 = llvm.load %554 : !llvm.ptr -> i64
      %557 = arith.constant 0 : i32
      %558 = arith.extsi %557 : i32 to i64
      %559 = llvm.getelementptr %arg1[%558] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %556 = llvm.load %559 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %560 = arith.constant 0 : i32
      %561 = arith.extsi %560 : i32 to i64
      %562 = llvm.getelementptr %arg1[%561] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %563 = llvm.getelementptr %562[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %564 = llvm.load %563 : !llvm.ptr -> i64
      %565 = arith.cmpi eq, %555, %564 : i64
      scf.yield %565 : i1
    } else {
      %566 = arith.constant false
      scf.yield %566 : i1
    }
    func.return %546 : i1
  }
  func.func @poly_get_bit(%arg0: !llvm.ptr, %arg1: i32) -> i32 {
    %568 = arith.constant 6 : i32
    %569 = arith.shrsi %arg1, %568 : i32
    %567 = func.call @poly_get_w(%arg0, %569) : (!llvm.ptr, i32) -> i64
    %570 = arith.constant 63 : i32
    %571 = arith.andi %arg1, %570 : i32
    %573 = arith.extsi %571 : i32 to i64
    %572 = arith.shrui %567, %573 : i64
    %574 = arith.constant 1 : i32
    %576 = arith.extsi %574 : i32 to i64
    %575 = arith.andi %572, %576 : i64
    %577 = arith.trunci %575 : i64 to i32
    func.return %577 : i32
  }
  func.func @poly_set_bit(%arg0: !llvm.ptr, %arg1: i32) -> () {
    %578 = arith.constant 6 : i32
    %579 = arith.shrsi %arg1, %578 : i32
    %580 = arith.constant 1 : i32
    %581 = arith.extsi %580 : i32 to i64
    %582 = func.call @poly_get_w(%arg0, %579) : (!llvm.ptr, i32) -> i64
    %584 = arith.constant 63 : i32
    %585 = arith.andi %arg1, %584 : i32
    %586 = arith.extsi %585 : i32 to i64
    %587 = arith.shli %581, %586 : i64
    %588 = arith.ori %582, %587 : i64
    func.call @poly_set_w(%arg0, %579, %588) : (!llvm.ptr, i32, i64) -> ()
    func.return
  }
  func.func @poly_xor(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
    %590 = arith.constant 0 : i32
    %591 = arith.extsi %590 : i32 to i64
    %592 = llvm.getelementptr %arg0[%591] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %589 = llvm.load %592 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %593 = arith.constant 0 : i32
    %594 = arith.extsi %593 : i32 to i64
    %595 = llvm.getelementptr %arg0[%594] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %596 = llvm.getelementptr %595[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %597 = llvm.load %596 : !llvm.ptr -> i64
    %599 = arith.constant 0 : i32
    %600 = arith.extsi %599 : i32 to i64
    %601 = llvm.getelementptr %arg1[%600] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %598 = llvm.load %601 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %602 = arith.constant 0 : i32
    %603 = arith.extsi %602 : i32 to i64
    %604 = llvm.getelementptr %arg1[%603] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %605 = llvm.getelementptr %604[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %606 = llvm.load %605 : !llvm.ptr -> i64
    %607 = arith.xori %597, %606 : i64
    %608 = arith.constant 0 : i32
    %609 = arith.extsi %608 : i32 to i64
    %610 = llvm.getelementptr %arg0[%609] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %611 = llvm.getelementptr %610[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %607, %611 : i64, !llvm.ptr
    %613 = arith.constant 0 : i32
    %614 = arith.extsi %613 : i32 to i64
    %615 = llvm.getelementptr %arg0[%614] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %612 = llvm.load %615 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %616 = arith.constant 0 : i32
    %617 = arith.extsi %616 : i32 to i64
    %618 = llvm.getelementptr %arg0[%617] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %619 = llvm.getelementptr %618[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %620 = llvm.load %619 : !llvm.ptr -> i64
    %622 = arith.constant 0 : i32
    %623 = arith.extsi %622 : i32 to i64
    %624 = llvm.getelementptr %arg1[%623] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %621 = llvm.load %624 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %625 = arith.constant 0 : i32
    %626 = arith.extsi %625 : i32 to i64
    %627 = llvm.getelementptr %arg1[%626] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %628 = llvm.getelementptr %627[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %629 = llvm.load %628 : !llvm.ptr -> i64
    %630 = arith.xori %620, %629 : i64
    %631 = arith.constant 0 : i32
    %632 = arith.extsi %631 : i32 to i64
    %633 = llvm.getelementptr %arg0[%632] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %634 = llvm.getelementptr %633[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %630, %634 : i64, !llvm.ptr
    %636 = arith.constant 0 : i32
    %637 = arith.extsi %636 : i32 to i64
    %638 = llvm.getelementptr %arg0[%637] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %635 = llvm.load %638 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %639 = arith.constant 0 : i32
    %640 = arith.extsi %639 : i32 to i64
    %641 = llvm.getelementptr %arg0[%640] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %642 = llvm.getelementptr %641[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %643 = llvm.load %642 : !llvm.ptr -> i64
    %645 = arith.constant 0 : i32
    %646 = arith.extsi %645 : i32 to i64
    %647 = llvm.getelementptr %arg1[%646] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %644 = llvm.load %647 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %648 = arith.constant 0 : i32
    %649 = arith.extsi %648 : i32 to i64
    %650 = llvm.getelementptr %arg1[%649] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %651 = llvm.getelementptr %650[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %652 = llvm.load %651 : !llvm.ptr -> i64
    %653 = arith.xori %643, %652 : i64
    %654 = arith.constant 0 : i32
    %655 = arith.extsi %654 : i32 to i64
    %656 = llvm.getelementptr %arg0[%655] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %657 = llvm.getelementptr %656[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %653, %657 : i64, !llvm.ptr
    %659 = arith.constant 0 : i32
    %660 = arith.extsi %659 : i32 to i64
    %661 = llvm.getelementptr %arg0[%660] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %658 = llvm.load %661 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %662 = arith.constant 0 : i32
    %663 = arith.extsi %662 : i32 to i64
    %664 = llvm.getelementptr %arg0[%663] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %665 = llvm.getelementptr %664[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %666 = llvm.load %665 : !llvm.ptr -> i64
    %668 = arith.constant 0 : i32
    %669 = arith.extsi %668 : i32 to i64
    %670 = llvm.getelementptr %arg1[%669] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %667 = llvm.load %670 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
    %671 = arith.constant 0 : i32
    %672 = arith.extsi %671 : i32 to i64
    %673 = llvm.getelementptr %arg1[%672] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %674 = llvm.getelementptr %673[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %675 = llvm.load %674 : !llvm.ptr -> i64
    %676 = arith.xori %666, %675 : i64
    %677 = arith.constant 0 : i32
    %678 = arith.extsi %677 : i32 to i64
    %679 = llvm.getelementptr %arg0[%678] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    %680 = llvm.getelementptr %679[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    llvm.store %676, %680 : i64, !llvm.ptr
    func.return
  }
  func.func @poly_shl(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: i32) -> () {
    %681 = arith.constant 6 : i32
    %682 = arith.shrsi %arg2, %681 : i32
    %683 = arith.constant 63 : i32
    %684 = arith.andi %arg2, %683 : i32
    func.call @poly_zero(%arg0) : (!llvm.ptr) -> ()
    %686 = arith.constant 1 : i32
    %687 = arith.extsi %686 : i32 to i64
    %688 = arith.constant 0 : i32
    %689 = arith.cmpi eq, %684, %688 : i32
    cf.cond_br %689, ^bb69, ^bb70
    ^bb69:
      %690 = arith.constant 3 : i32
      %691 = llvm.mlir.constant(1 : i64) : i64
      %692 = llvm.alloca %691 x i32 : (i64) -> !llvm.ptr
      llvm.store %690, %692 : i32, !llvm.ptr
      cf.br ^bb72
      ^bb72:
      %693 = llvm.load %692 : !llvm.ptr -> i32
      %694 = arith.constant 0 : i32
      %695 = arith.cmpi sge, %693, %694 : i32
      cf.cond_br %695, ^bb73, ^bb74
      ^bb73:
        %696 = llvm.load %692 : !llvm.ptr -> i32
        %697 = arith.addi %696, %682 : i32
        %698 = arith.constant 0 : i32
        %699 = arith.cmpi sge, %697, %698 : i32
        %700 = scf.if %699 -> (i1) {
          %701 = arith.constant 4 : i32
          %702 = arith.cmpi slt, %697, %701 : i32
          scf.yield %702 : i1
        } else {
          %703 = arith.constant false
          scf.yield %703 : i1
        }
        cf.cond_br %700, ^bb75, ^bb76
        ^bb75:
          %706 = llvm.load %692 : !llvm.ptr -> i32
          %705 = func.call @poly_get_w(%arg1, %706) : (!llvm.ptr, i32) -> i64
          func.call @poly_set_w(%arg0, %697, %705) : (!llvm.ptr, i32, i64) -> ()
          cf.br ^bb77
        ^bb76:
          cf.br ^bb77
        ^bb77:
        %707 = llvm.load %692 : !llvm.ptr -> i32
        %708 = arith.constant 1 : i32
        %709 = arith.subi %707, %708 : i32
        llvm.store %709, %692 : i32, !llvm.ptr
        cf.br ^bb72
      ^bb74:
      cf.br ^bb71
    ^bb70:
      %710 = arith.constant 3 : i32
      %711 = llvm.mlir.constant(1 : i64) : i64
      %712 = llvm.alloca %711 x i32 : (i64) -> !llvm.ptr
      llvm.store %710, %712 : i32, !llvm.ptr
      cf.br ^bb78
      ^bb78:
      %713 = llvm.load %712 : !llvm.ptr -> i32
      %714 = arith.constant 0 : i32
      %715 = arith.cmpi sge, %713, %714 : i32
      cf.cond_br %715, ^bb79, ^bb80
      ^bb79:
        %716 = llvm.load %712 : !llvm.ptr -> i32
        %717 = arith.addi %716, %682 : i32
        %719 = llvm.load %712 : !llvm.ptr -> i32
        %718 = func.call @poly_get_w(%arg1, %719) : (!llvm.ptr, i32) -> i64
        %720 = arith.constant 0 : i32
        %721 = arith.cmpi sge, %717, %720 : i32
        %722 = scf.if %721 -> (i1) {
          %723 = arith.constant 4 : i32
          %724 = arith.cmpi slt, %717, %723 : i32
          scf.yield %724 : i1
        } else {
          %725 = arith.constant false
          scf.yield %725 : i1
        }
        cf.cond_br %722, ^bb81, ^bb82
        ^bb81:
          %726 = func.call @poly_get_w(%arg0, %717) : (!llvm.ptr, i32) -> i64
          %728 = arith.extsi %684 : i32 to i64
          %729 = arith.shli %718, %728 : i64
          %730 = arith.ori %726, %729 : i64
          func.call @poly_set_w(%arg0, %717, %730) : (!llvm.ptr, i32, i64) -> ()
          cf.br ^bb83
        ^bb82:
          cf.br ^bb83
        ^bb83:
        %731 = arith.constant 1 : i32
        %732 = arith.addi %717, %731 : i32
        %733 = arith.constant 0 : i32
        %734 = arith.cmpi sge, %732, %733 : i32
        %735 = scf.if %734 -> (i1) {
          %736 = arith.constant 1 : i32
          %737 = arith.addi %717, %736 : i32
          %738 = arith.constant 4 : i32
          %739 = arith.cmpi slt, %737, %738 : i32
          scf.yield %739 : i1
        } else {
          %740 = arith.constant false
          scf.yield %740 : i1
        }
        cf.cond_br %735, ^bb84, ^bb85
        ^bb84:
          %742 = arith.constant 1 : i32
          %743 = arith.addi %717, %742 : i32
          %741 = func.call @poly_get_w(%arg0, %743) : (!llvm.ptr, i32) -> i64
          %745 = arith.constant 1 : i32
          %746 = arith.addi %717, %745 : i32
          %747 = arith.constant 64 : i32
          %748 = arith.subi %747, %684 : i32
          %749 = arith.extsi %748 : i32 to i64
          %750 = arith.shrui %718, %749 : i64
          %751 = arith.ori %741, %750 : i64
          func.call @poly_set_w(%arg0, %746, %751) : (!llvm.ptr, i32, i64) -> ()
          cf.br ^bb86
        ^bb85:
          cf.br ^bb86
        ^bb86:
        %752 = llvm.load %712 : !llvm.ptr -> i32
        %753 = arith.constant 1 : i32
        %754 = arith.subi %752, %753 : i32
        llvm.store %754, %712 : i32, !llvm.ptr
        cf.br ^bb78
      ^bb80:
      cf.br ^bb71
    ^bb71:
    func.return
  }
  func.func @poly_mul(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    func.call @poly_zero(%arg0) : (!llvm.ptr) -> ()
    %757 = arith.constant 1 : i32
    %758 = arith.constant 32 : i32
    %759 = arith.extsi %757 : i32 to i64
    %760 = arith.extsi %758 : i32 to i64
    %756 = func.call @calloc(%759, %760) : (i64, i64) -> !llvm.ptr
    %761 = func.call @poly_deg(%arg2) : (!llvm.ptr) -> i32
    %762 = arith.constant 0 : i32
    %763 = llvm.mlir.constant(1 : i64) : i64
    %764 = llvm.alloca %763 x i32 : (i64) -> !llvm.ptr
    llvm.store %762, %764 : i32, !llvm.ptr
    cf.br ^bb87
    ^bb87:
    %765 = llvm.load %764 : !llvm.ptr -> i32
    %766 = arith.cmpi sle, %765, %761 : i32
    cf.cond_br %766, ^bb88, ^bb89
    ^bb88:
      %768 = llvm.load %764 : !llvm.ptr -> i32
      %767 = func.call @poly_get_bit(%arg2, %768) : (!llvm.ptr, i32) -> i32
      %769 = arith.constant 0 : i32
      %770 = arith.cmpi ne, %767, %769 : i32
      cf.cond_br %770, ^bb90, ^bb91
      ^bb90:
        %772 = llvm.load %764 : !llvm.ptr -> i32
        func.call @poly_shl(%756, %arg1, %772) : (!llvm.ptr, !llvm.ptr, i32) -> ()
        func.call @poly_xor(%arg0, %756) : (!llvm.ptr, !llvm.ptr) -> ()
        cf.br ^bb92
      ^bb91:
        cf.br ^bb92
      ^bb92:
      %774 = llvm.load %764 : !llvm.ptr -> i32
      %775 = arith.constant 1 : i32
      %776 = arith.addi %774, %775 : i32
      llvm.store %776, %764 : i32, !llvm.ptr
      cf.br ^bb87
    ^bb89:
    func.call @free(%756) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @poly_mod(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    %779 = arith.constant 1 : i32
    %780 = arith.constant 32 : i32
    %781 = arith.extsi %779 : i32 to i64
    %782 = arith.extsi %780 : i32 to i64
    %778 = func.call @calloc(%781, %782) : (i64, i64) -> !llvm.ptr
    func.call @poly_copy(%778, %arg1) : (!llvm.ptr, !llvm.ptr) -> ()
    %785 = arith.constant 1 : i32
    %786 = arith.constant 32 : i32
    %787 = arith.extsi %785 : i32 to i64
    %788 = arith.extsi %786 : i32 to i64
    %784 = func.call @calloc(%787, %788) : (i64, i64) -> !llvm.ptr
    %789 = func.call @poly_deg(%arg2) : (!llvm.ptr) -> i32
    cf.br ^bb93
    ^bb93:
    %790 = func.call @poly_is_zero(%778) : (!llvm.ptr) -> i1
    %792 = arith.constant 1 : i1
    %791 = arith.xori %790, %792 : i1
    %794 = scf.if %791 -> (i1) {
      %795 = func.call @poly_deg(%778) : (!llvm.ptr) -> i32
      %796 = arith.cmpi sge, %795, %789 : i32
      scf.yield %796 : i1
    } else {
      %797 = arith.constant false
      scf.yield %797 : i1
    }
    cf.cond_br %794, ^bb94, ^bb95
    ^bb94:
      %798 = func.call @poly_deg(%778) : (!llvm.ptr) -> i32
      %799 = arith.subi %798, %789 : i32
      func.call @poly_shl(%784, %arg2, %799) : (!llvm.ptr, !llvm.ptr, i32) -> ()
      func.call @poly_xor(%778, %784) : (!llvm.ptr, !llvm.ptr) -> ()
      cf.br ^bb93
    ^bb95:
    func.call @poly_copy(%arg0, %778) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%778) : (!llvm.ptr) -> ()
    func.call @free(%784) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @poly_mul_mod(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: !llvm.ptr) -> () {
    %806 = arith.constant 1 : i32
    %807 = arith.constant 32 : i32
    %808 = arith.extsi %806 : i32 to i64
    %809 = arith.extsi %807 : i32 to i64
    %805 = func.call @calloc(%808, %809) : (i64, i64) -> !llvm.ptr
    func.call @poly_mul(%805, %arg1, %arg2) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    func.call @poly_mod(%arg0, %805, %arg3) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%805) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @poly_square(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
    func.call @poly_zero(%arg0) : (!llvm.ptr) -> ()
    %814 = func.call @poly_deg(%arg1) : (!llvm.ptr) -> i32
    %815 = arith.constant 0 : i32
    %816 = llvm.mlir.constant(1 : i64) : i64
    %817 = llvm.alloca %816 x i32 : (i64) -> !llvm.ptr
    llvm.store %815, %817 : i32, !llvm.ptr
    cf.br ^bb96
    ^bb96:
    %818 = llvm.load %817 : !llvm.ptr -> i32
    %819 = arith.cmpi sle, %818, %814 : i32
    cf.cond_br %819, ^bb97, ^bb98
    ^bb97:
      %821 = llvm.load %817 : !llvm.ptr -> i32
      %820 = func.call @poly_get_bit(%arg1, %821) : (!llvm.ptr, i32) -> i32
      %822 = arith.constant 0 : i32
      %823 = arith.cmpi ne, %820, %822 : i32
      cf.cond_br %823, ^bb99, ^bb100
      ^bb99:
        %825 = arith.constant 2 : i32
        %826 = llvm.load %817 : !llvm.ptr -> i32
        %827 = arith.muli %825, %826 : i32
        func.call @poly_set_bit(%arg0, %827) : (!llvm.ptr, i32) -> ()
        cf.br ^bb101
      ^bb100:
        cf.br ^bb101
      ^bb101:
      %828 = llvm.load %817 : !llvm.ptr -> i32
      %829 = arith.constant 1 : i32
      %830 = arith.addi %828, %829 : i32
      llvm.store %830, %817 : i32, !llvm.ptr
      cf.br ^bb96
    ^bb98:
    func.return
  }
  func.func @poly_square_mod(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    %832 = arith.constant 1 : i32
    %833 = arith.constant 32 : i32
    %834 = arith.extsi %832 : i32 to i64
    %835 = arith.extsi %833 : i32 to i64
    %831 = func.call @calloc(%834, %835) : (i64, i64) -> !llvm.ptr
    func.call @poly_square(%831, %arg1) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @poly_mod(%arg0, %831, %arg2) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%831) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @poly_pow_mod(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: i64, %arg3: !llvm.ptr) -> () {
    %840 = arith.constant 1 : i32
    %841 = arith.constant 32 : i32
    %842 = arith.extsi %840 : i32 to i64
    %843 = arith.extsi %841 : i32 to i64
    %839 = func.call @calloc(%842, %843) : (i64, i64) -> !llvm.ptr
    %845 = arith.constant 1 : i32
    %846 = arith.constant 32 : i32
    %847 = arith.extsi %845 : i32 to i64
    %848 = arith.extsi %846 : i32 to i64
    %844 = func.call @calloc(%847, %848) : (i64, i64) -> !llvm.ptr
    %850 = arith.constant 1 : i32
    %851 = arith.constant 32 : i32
    %852 = arith.extsi %850 : i32 to i64
    %853 = arith.extsi %851 : i32 to i64
    %849 = func.call @calloc(%852, %853) : (i64, i64) -> !llvm.ptr
    func.call @poly_one(%839) : (!llvm.ptr) -> ()
    func.call @poly_mod(%844, %arg1, %arg3) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
    %856 = llvm.mlir.constant(1 : i64) : i64
    %857 = llvm.alloca %856 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg2, %857 : i64, !llvm.ptr
    cf.br ^bb102
    ^bb102:
    %858 = llvm.load %857 : !llvm.ptr -> i64
    %859 = arith.constant 0 : i32
    %861 = arith.extsi %859 : i32 to i64
    %860 = arith.cmpi sgt, %858, %861 : i64
    cf.cond_br %860, ^bb103, ^bb104
    ^bb103:
      %862 = llvm.load %857 : !llvm.ptr -> i64
      %863 = arith.constant 2 : i32
      %865 = arith.extsi %863 : i32 to i64
      %864 = arith.remsi %862, %865 : i64
      %866 = arith.constant 1 : i32
      %868 = arith.extsi %866 : i32 to i64
      %867 = arith.cmpi eq, %864, %868 : i64
      cf.cond_br %867, ^bb105, ^bb106
      ^bb105:
        func.call @poly_mul_mod(%849, %839, %844, %arg3) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
        func.call @poly_copy(%839, %849) : (!llvm.ptr, !llvm.ptr) -> ()
        cf.br ^bb107
      ^bb106:
        cf.br ^bb107
      ^bb107:
      %871 = llvm.load %857 : !llvm.ptr -> i64
      %872 = arith.constant 1 : i32
      %874 = arith.extsi %872 : i32 to i64
      %873 = arith.shrsi %871, %874 : i64
      llvm.store %873, %857 : i64, !llvm.ptr
      %875 = llvm.load %857 : !llvm.ptr -> i64
      %876 = arith.constant 0 : i32
      %878 = arith.extsi %876 : i32 to i64
      %877 = arith.cmpi ne, %875, %878 : i64
      cf.cond_br %877, ^bb108, ^bb109
      ^bb108:
        func.call @poly_square_mod(%849, %844, %arg3) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
        func.call @poly_copy(%844, %849) : (!llvm.ptr, !llvm.ptr) -> ()
        cf.br ^bb110
      ^bb109:
        cf.br ^bb110
      ^bb110:
      cf.br ^bb102
    ^bb104:
    func.call @poly_copy(%arg0, %839) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%839) : (!llvm.ptr) -> ()
    func.call @free(%844) : (!llvm.ptr) -> ()
    func.call @free(%849) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @poly_gcd(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    %886 = arith.constant 1 : i32
    %887 = arith.constant 32 : i32
    %888 = arith.extsi %886 : i32 to i64
    %889 = arith.extsi %887 : i32 to i64
    %885 = func.call @calloc(%888, %889) : (i64, i64) -> !llvm.ptr
    %891 = arith.constant 1 : i32
    %892 = arith.constant 32 : i32
    %893 = arith.extsi %891 : i32 to i64
    %894 = arith.extsi %892 : i32 to i64
    %890 = func.call @calloc(%893, %894) : (i64, i64) -> !llvm.ptr
    %896 = arith.constant 1 : i32
    %897 = arith.constant 32 : i32
    %898 = arith.extsi %896 : i32 to i64
    %899 = arith.extsi %897 : i32 to i64
    %895 = func.call @calloc(%898, %899) : (i64, i64) -> !llvm.ptr
    func.call @poly_copy(%885, %arg1) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @poly_copy(%890, %arg2) : (!llvm.ptr, !llvm.ptr) -> ()
    cf.br ^bb111
    ^bb111:
    %902 = func.call @poly_is_zero(%890) : (!llvm.ptr) -> i1
    %904 = arith.constant 1 : i1
    %903 = arith.xori %902, %904 : i1
    cf.cond_br %903, ^bb112, ^bb113
    ^bb112:
      func.call @poly_mod(%895, %885, %890) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      func.call @poly_copy(%885, %890) : (!llvm.ptr, !llvm.ptr) -> ()
      func.call @poly_copy(%890, %895) : (!llvm.ptr, !llvm.ptr) -> ()
      cf.br ^bb111
    ^bb113:
    func.call @poly_copy(%arg0, %885) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%885) : (!llvm.ptr) -> ()
    func.call @free(%890) : (!llvm.ptr) -> ()
    func.call @free(%895) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @poly_div_exact(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    %914 = arith.constant 1 : i32
    %915 = arith.constant 32 : i32
    %916 = arith.extsi %914 : i32 to i64
    %917 = arith.extsi %915 : i32 to i64
    %913 = func.call @calloc(%916, %917) : (i64, i64) -> !llvm.ptr
    %919 = arith.constant 1 : i32
    %920 = arith.constant 32 : i32
    %921 = arith.extsi %919 : i32 to i64
    %922 = arith.extsi %920 : i32 to i64
    %918 = func.call @calloc(%921, %922) : (i64, i64) -> !llvm.ptr
    %924 = arith.constant 1 : i32
    %925 = arith.constant 32 : i32
    %926 = arith.extsi %924 : i32 to i64
    %927 = arith.extsi %925 : i32 to i64
    %923 = func.call @calloc(%926, %927) : (i64, i64) -> !llvm.ptr
    func.call @poly_copy(%913, %arg1) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @poly_zero(%918) : (!llvm.ptr) -> ()
    %930 = func.call @poly_deg(%arg2) : (!llvm.ptr) -> i32
    cf.br ^bb114
    ^bb114:
    %931 = func.call @poly_is_zero(%913) : (!llvm.ptr) -> i1
    %933 = arith.constant 1 : i1
    %932 = arith.xori %931, %933 : i1
    %935 = scf.if %932 -> (i1) {
      %936 = func.call @poly_deg(%913) : (!llvm.ptr) -> i32
      %937 = arith.cmpi sge, %936, %930 : i32
      scf.yield %937 : i1
    } else {
      %938 = arith.constant false
      scf.yield %938 : i1
    }
    cf.cond_br %935, ^bb115, ^bb116
    ^bb115:
      %939 = func.call @poly_deg(%913) : (!llvm.ptr) -> i32
      %940 = arith.subi %939, %930 : i32
      func.call @poly_set_bit(%918, %940) : (!llvm.ptr, i32) -> ()
      func.call @poly_shl(%923, %arg2, %940) : (!llvm.ptr, !llvm.ptr, i32) -> ()
      func.call @poly_xor(%913, %923) : (!llvm.ptr, !llvm.ptr) -> ()
      cf.br ^bb114
    ^bb116:
    func.call @poly_copy(%arg0, %918) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%913) : (!llvm.ptr) -> ()
    func.call @free(%918) : (!llvm.ptr) -> ()
    func.call @free(%923) : (!llvm.ptr) -> ()
    func.return
  }
  // Module static: sieve_arr
  llvm.mlir.global internal @sieve_arr() {addr_space = 0 : i32} : !llvm.ptr {
    %948 = llvm.mlir.zero : !llvm.ptr
    llvm.return %948 : !llvm.ptr
  }
  // Module static: small_primes
  llvm.mlir.global internal @small_primes() {addr_space = 0 : i32} : !llvm.ptr {
    %949 = llvm.mlir.zero : !llvm.ptr
    llvm.return %949 : !llvm.ptr
  }
  // Module static: num_small_primes
  llvm.mlir.global internal @num_small_primes(0 : i32) : i32
  func.func @init_sieve() -> () {
    %950 = arith.constant 2000000 : i32
    %951 = arith.extsi %950 : i32 to i64
    %953 = arith.constant 1 : i32
    %955 = arith.extsi %953 : i32 to i64
    %954 = arith.addi %951, %955 : i64
    %956 = arith.constant 1 : i32
    %957 = arith.extsi %956 : i32 to i64
    %952 = func.call @calloc(%954, %957) : (i64, i64) -> !llvm.ptr
    %958 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
    llvm.store %952, %958 : !llvm.ptr, !llvm.ptr
    %960 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
    %961 = llvm.load %960 : !llvm.ptr -> !llvm.ptr
    %962 = arith.constant 1 : i32
    %963 = arith.constant 1 : i32
    %965 = arith.extsi %963 : i32 to i64
    %964 = arith.addi %951, %965 : i64
    %966 = arith.extsi %962 : i32 to i64
    %959 = func.call @memset(%961, %966, %964) : (!llvm.ptr, i64, i64) -> !llvm.ptr
    %967 = arith.constant 0 : i32
    %968 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
    %969 = llvm.load %968 : !llvm.ptr -> !llvm.ptr
    %970 = arith.constant 0 : i32
    %971 = arith.trunci %967 : i32 to i8
    %972 = arith.extsi %970 : i32 to i64
    %973 = llvm.getelementptr %969[%972] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %971, %973 : i8, !llvm.ptr
    %974 = arith.constant 0 : i32
    %975 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
    %976 = llvm.load %975 : !llvm.ptr -> !llvm.ptr
    %977 = arith.constant 1 : i32
    %978 = arith.trunci %974 : i32 to i8
    %979 = arith.extsi %977 : i32 to i64
    %980 = llvm.getelementptr %976[%979] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %978, %980 : i8, !llvm.ptr
    %981 = arith.constant 2 : i32
    %982 = arith.extsi %981 : i32 to i64
    %983 = llvm.mlir.constant(1 : i64) : i64
    %984 = llvm.alloca %983 x i64 : (i64) -> !llvm.ptr
    llvm.store %982, %984 : i64, !llvm.ptr
    cf.br ^bb117
    ^bb117:
    %985 = llvm.load %984 : !llvm.ptr -> i64
    %986 = llvm.load %984 : !llvm.ptr -> i64
    %987 = arith.muli %985, %986 : i64
    %988 = arith.cmpi sle, %987, %951 : i64
    cf.cond_br %988, ^bb118, ^bb119
    ^bb118:
      %990 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
      %991 = llvm.load %990 : !llvm.ptr -> !llvm.ptr
      %992 = llvm.load %984 : !llvm.ptr -> i64
      %993 = llvm.getelementptr %991[%992] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %989 = llvm.load %993 : !llvm.ptr -> i8
      %994 = arith.constant 0 : i32
      %996 = arith.extsi %989 : i8 to i32
      %995 = arith.cmpi ne, %996, %994 : i32
      cf.cond_br %995, ^bb120, ^bb121
      ^bb120:
        %997 = llvm.load %984 : !llvm.ptr -> i64
        %998 = llvm.load %984 : !llvm.ptr -> i64
        %999 = arith.muli %997, %998 : i64
        %1000 = llvm.mlir.constant(1 : i64) : i64
        %1001 = llvm.alloca %1000 x i64 : (i64) -> !llvm.ptr
        llvm.store %999, %1001 : i64, !llvm.ptr
        cf.br ^bb123
        ^bb123:
        %1002 = llvm.load %1001 : !llvm.ptr -> i64
        %1003 = arith.cmpi sle, %1002, %951 : i64
        cf.cond_br %1003, ^bb124, ^bb125
        ^bb124:
          %1004 = arith.constant 0 : i32
          %1005 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
          %1006 = llvm.load %1005 : !llvm.ptr -> !llvm.ptr
          %1007 = llvm.load %1001 : !llvm.ptr -> i64
          %1008 = arith.trunci %1004 : i32 to i8
          %1009 = llvm.getelementptr %1006[%1007] : (!llvm.ptr, i64) -> !llvm.ptr, i8
          llvm.store %1008, %1009 : i8, !llvm.ptr
          %1010 = llvm.load %1001 : !llvm.ptr -> i64
          %1011 = llvm.load %984 : !llvm.ptr -> i64
          %1012 = arith.addi %1010, %1011 : i64
          llvm.store %1012, %1001 : i64, !llvm.ptr
          cf.br ^bb123
        ^bb125:
        cf.br ^bb122
      ^bb121:
        cf.br ^bb122
      ^bb122:
      %1013 = llvm.load %984 : !llvm.ptr -> i64
      %1014 = arith.constant 1 : i32
      %1016 = arith.extsi %1014 : i32 to i64
      %1015 = arith.addi %1013, %1016 : i64
      llvm.store %1015, %984 : i64, !llvm.ptr
      cf.br ^bb117
    ^bb119:
    %1018 = arith.constant 200000 : i32
    %1019 = arith.constant 4 : i32
    %1020 = arith.extsi %1018 : i32 to i64
    %1021 = arith.extsi %1019 : i32 to i64
    %1017 = func.call @calloc(%1020, %1021) : (i64, i64) -> !llvm.ptr
    %1022 = llvm.mlir.addressof @small_primes : !llvm.ptr
    llvm.store %1017, %1022 : !llvm.ptr, !llvm.ptr
    %1023 = arith.constant 0 : i32
    %1024 = llvm.mlir.addressof @num_small_primes : !llvm.ptr
    llvm.store %1023, %1024 : i32, !llvm.ptr
    %1025 = arith.constant 2 : i32
    %1026 = arith.extsi %1025 : i32 to i64
    %1027 = llvm.mlir.constant(1 : i64) : i64
    %1028 = llvm.alloca %1027 x i64 : (i64) -> !llvm.ptr
    llvm.store %1026, %1028 : i64, !llvm.ptr
    cf.br ^bb126
    ^bb126:
    %1029 = llvm.load %1028 : !llvm.ptr -> i64
    %1030 = arith.cmpi sle, %1029, %951 : i64
    cf.cond_br %1030, ^bb127, ^bb128
    ^bb127:
      %1032 = llvm.mlir.addressof @sieve_arr : !llvm.ptr
      %1033 = llvm.load %1032 : !llvm.ptr -> !llvm.ptr
      %1034 = llvm.load %1028 : !llvm.ptr -> i64
      %1035 = llvm.getelementptr %1033[%1034] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %1031 = llvm.load %1035 : !llvm.ptr -> i8
      %1036 = arith.constant 0 : i32
      %1038 = arith.extsi %1031 : i8 to i32
      %1037 = arith.cmpi ne, %1038, %1036 : i32
      cf.cond_br %1037, ^bb129, ^bb130
      ^bb129:
        %1039 = llvm.load %1028 : !llvm.ptr -> i64
        %1040 = arith.trunci %1039 : i64 to i32
        %1041 = llvm.mlir.addressof @small_primes : !llvm.ptr
        %1042 = llvm.load %1041 : !llvm.ptr -> !llvm.ptr
        %1043 = llvm.mlir.addressof @num_small_primes : !llvm.ptr
        %1044 = llvm.load %1043 : !llvm.ptr -> i32
        %1045 = arith.extsi %1044 : i32 to i64
        %1046 = llvm.getelementptr %1042[%1045] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1040, %1046 : i32, !llvm.ptr
        %1047 = llvm.mlir.addressof @num_small_primes : !llvm.ptr
        %1048 = llvm.load %1047 : !llvm.ptr -> i32
        %1049 = arith.constant 1 : i32
        %1050 = arith.addi %1048, %1049 : i32
        %1051 = llvm.mlir.addressof @num_small_primes : !llvm.ptr
        llvm.store %1050, %1051 : i32, !llvm.ptr
        cf.br ^bb131
      ^bb130:
        cf.br ^bb131
      ^bb131:
      %1052 = llvm.load %1028 : !llvm.ptr -> i64
      %1053 = arith.constant 1 : i32
      %1055 = arith.extsi %1053 : i32 to i64
      %1054 = arith.addi %1052, %1055 : i64
      llvm.store %1054, %1028 : i64, !llvm.ptr
      cf.br ^bb126
    ^bb128:
    func.return
  }
  func.func @factor_small(%arg0: i64, %arg1: !llvm.ptr) -> i32 {
    %1056 = llvm.mlir.constant(1 : i64) : i64
    %1057 = llvm.alloca %1056 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %1057 : i64, !llvm.ptr
    %1058 = arith.constant 0 : i32
    %1059 = llvm.mlir.constant(1 : i64) : i64
    %1060 = llvm.alloca %1059 x i32 : (i64) -> !llvm.ptr
    llvm.store %1058, %1060 : i32, !llvm.ptr
    %1061 = arith.constant 0 : i32
    %1062 = llvm.mlir.constant(1 : i64) : i64
    %1063 = llvm.alloca %1062 x i32 : (i64) -> !llvm.ptr
    llvm.store %1061, %1063 : i32, !llvm.ptr
    cf.br ^bb132
    ^bb132:
    %1064 = llvm.load %1063 : !llvm.ptr -> i32
    %1065 = llvm.mlir.addressof @num_small_primes : !llvm.ptr
    %1066 = llvm.load %1065 : !llvm.ptr -> i32
    %1067 = arith.cmpi slt, %1064, %1066 : i32
    cf.cond_br %1067, ^bb133, ^bb134
    ^bb133:
      %1069 = llvm.mlir.addressof @small_primes : !llvm.ptr
      %1070 = llvm.load %1069 : !llvm.ptr -> !llvm.ptr
      %1071 = llvm.load %1063 : !llvm.ptr -> i32
      %1072 = arith.extsi %1071 : i32 to i64
      %1073 = llvm.getelementptr %1070[%1072] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1068 = llvm.load %1073 : !llvm.ptr -> i32
      %1074 = arith.extsi %1068 : i32 to i64
      %1075 = arith.extsi %1068 : i32 to i64
      %1076 = arith.muli %1074, %1075 : i64
      %1077 = llvm.load %1057 : !llvm.ptr -> i64
      %1078 = arith.cmpi sgt, %1076, %1077 : i64
      cf.cond_br %1078, ^bb135, ^bb136
      ^bb135:
        cf.br ^bb134
      ^bb136:
        cf.br ^bb137
      ^bb137:
      cf.br ^bb138
      ^bb138:
      %1079 = llvm.load %1057 : !llvm.ptr -> i64
      %1080 = arith.extsi %1068 : i32 to i64
      %1081 = arith.remsi %1079, %1080 : i64
      %1082 = arith.constant 0 : i32
      %1084 = arith.extsi %1082 : i32 to i64
      %1083 = arith.cmpi eq, %1081, %1084 : i64
      cf.cond_br %1083, ^bb139, ^bb140
      ^bb139:
        %1085 = arith.extsi %1068 : i32 to i64
        %1086 = llvm.load %1060 : !llvm.ptr -> i32
        %1087 = arith.extsi %1086 : i32 to i64
        %1088 = llvm.getelementptr %arg1[%1087] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %1085, %1088 : i64, !llvm.ptr
        %1089 = llvm.load %1060 : !llvm.ptr -> i32
        %1090 = arith.constant 1 : i32
        %1091 = arith.addi %1089, %1090 : i32
        llvm.store %1091, %1060 : i32, !llvm.ptr
        %1092 = llvm.load %1057 : !llvm.ptr -> i64
        %1093 = arith.extsi %1068 : i32 to i64
        %1094 = arith.divsi %1092, %1093 : i64
        llvm.store %1094, %1057 : i64, !llvm.ptr
        cf.br ^bb138
      ^bb140:
      %1095 = llvm.load %1063 : !llvm.ptr -> i32
      %1096 = arith.constant 1 : i32
      %1097 = arith.addi %1095, %1096 : i32
      llvm.store %1097, %1063 : i32, !llvm.ptr
      cf.br ^bb132
    ^bb134:
    %1098 = llvm.load %1057 : !llvm.ptr -> i64
    %1099 = arith.constant 1 : i32
    %1101 = arith.extsi %1099 : i32 to i64
    %1100 = arith.cmpi sgt, %1098, %1101 : i64
    cf.cond_br %1100, ^bb141, ^bb142
    ^bb141:
      %1102 = llvm.load %1057 : !llvm.ptr -> i64
      %1103 = llvm.load %1060 : !llvm.ptr -> i32
      %1104 = arith.extsi %1103 : i32 to i64
      %1105 = llvm.getelementptr %arg1[%1104] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %1102, %1105 : i64, !llvm.ptr
      %1106 = llvm.load %1060 : !llvm.ptr -> i32
      %1107 = arith.constant 1 : i32
      %1108 = arith.addi %1106, %1107 : i32
      llvm.store %1108, %1060 : i32, !llvm.ptr
      cf.br ^bb143
    ^bb142:
      cf.br ^bb143
    ^bb143:
    %1109 = llvm.load %1060 : !llvm.ptr -> i32
    func.return %1109 : i32
  }
  func.func @berlekamp_nullspace(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> i32 {
    %1110 = func.call @poly_deg(%arg0) : (!llvm.ptr) -> i32
    %1111 = arith.constant 0 : i32
    %1112 = arith.cmpi sle, %1110, %1111 : i32
    cf.cond_br %1112, ^bb144, ^bb145
    ^bb144:
      %1113 = arith.constant 0 : i32
      func.return %1113 : i32
    ^bb145:
      cf.br ^bb146
    ^bb146:
    %1115 = arith.constant 128 : i32
    %1116 = arith.constant 16 : i32
    %1117 = arith.extsi %1115 : i32 to i64
    %1118 = arith.extsi %1116 : i32 to i64
    %1114 = func.call @calloc(%1117, %1118) : (i64, i64) -> !llvm.ptr
    %1119 = arith.constant 1 : i32
    %1120 = arith.extsi %1119 : i32 to i128
    %1121 = arith.constant 0 : i32
    %1122 = llvm.mlir.constant(1 : i64) : i64
    %1123 = llvm.alloca %1122 x i32 : (i64) -> !llvm.ptr
    llvm.store %1121, %1123 : i32, !llvm.ptr
    cf.br ^bb147
    ^bb147:
    %1124 = llvm.load %1123 : !llvm.ptr -> i32
    %1125 = arith.cmpi slt, %1124, %1110 : i32
    cf.cond_br %1125, ^bb148, ^bb149
    ^bb148:
      %1127 = arith.constant 1 : i32
      %1128 = arith.constant 32 : i32
      %1129 = arith.extsi %1127 : i32 to i64
      %1130 = arith.extsi %1128 : i32 to i64
      %1126 = func.call @calloc(%1129, %1130) : (i64, i64) -> !llvm.ptr
      func.call @poly_zero(%1126) : (!llvm.ptr) -> ()
      %1133 = arith.constant 2 : i32
      %1134 = llvm.load %1123 : !llvm.ptr -> i32
      %1135 = arith.muli %1133, %1134 : i32
      func.call @poly_set_bit(%1126, %1135) : (!llvm.ptr, i32) -> ()
      %1137 = arith.constant 1 : i32
      %1138 = arith.constant 32 : i32
      %1139 = arith.extsi %1137 : i32 to i64
      %1140 = arith.extsi %1138 : i32 to i64
      %1136 = func.call @calloc(%1139, %1140) : (i64, i64) -> !llvm.ptr
      func.call @poly_mod(%1136, %1126, %arg0) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      %1142 = arith.constant 0 : i32
      %1143 = llvm.mlir.constant(1 : i64) : i64
      %1144 = llvm.alloca %1143 x i32 : (i64) -> !llvm.ptr
      llvm.store %1142, %1144 : i32, !llvm.ptr
      cf.br ^bb150
      ^bb150:
      %1145 = func.call @poly_is_zero(%1136) : (!llvm.ptr) -> i1
      %1147 = arith.constant 1 : i1
      %1146 = arith.xori %1145, %1147 : i1
      cf.cond_br %1146, ^bb151, ^bb152
      ^bb151:
        %1150 = arith.constant 0 : i32
        %1151 = arith.extsi %1150 : i32 to i64
        %1152 = llvm.getelementptr %1136[%1151] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1149 = llvm.load %1152 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1153 = arith.constant 0 : i32
        %1154 = arith.extsi %1153 : i32 to i64
        %1155 = llvm.getelementptr %1136[%1154] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1156 = llvm.getelementptr %1155[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1157 = llvm.load %1156 : !llvm.ptr -> i64
        %1158 = arith.constant 1 : i32
        %1160 = arith.extsi %1158 : i32 to i64
        %1159 = arith.andi %1157, %1160 : i64
        %1161 = arith.constant 0 : i32
        %1163 = arith.extsi %1161 : i32 to i64
        %1162 = arith.cmpi ne, %1159, %1163 : i64
        cf.cond_br %1162, ^bb153, ^bb154
        ^bb153:
          %1165 = llvm.load %1144 : !llvm.ptr -> i32
          %1166 = arith.extsi %1165 : i32 to i64
          %1167 = llvm.getelementptr %1114[%1166] : (!llvm.ptr, i64) -> !llvm.ptr, i128
          %1164 = llvm.load %1167 : !llvm.ptr -> i128
          %1168 = llvm.load %1123 : !llvm.ptr -> i32
          %1169 = arith.extsi %1168 : i32 to i128
          %1171 = arith.trunci %1120 : i128 to i64
          %1172 = arith.trunci %1169 : i128 to i64
          %1170 = arith.shli %1171, %1172 : i64
          %1174 = arith.trunci %1164 : i128 to i64
          %1173 = arith.ori %1174, %1170 : i64
          %1175 = llvm.load %1144 : !llvm.ptr -> i32
          %1176 = arith.extsi %1173 : i64 to i128
          %1177 = arith.extsi %1175 : i32 to i64
          %1178 = llvm.getelementptr %1114[%1177] : (!llvm.ptr, i64) -> !llvm.ptr, i128
          llvm.store %1176, %1178 : i128, !llvm.ptr
          cf.br ^bb155
        ^bb154:
          cf.br ^bb155
        ^bb155:
        %1180 = arith.constant 0 : i32
        %1181 = arith.extsi %1180 : i32 to i64
        %1182 = llvm.getelementptr %1136[%1181] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1179 = llvm.load %1182 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1183 = arith.constant 0 : i32
        %1184 = arith.extsi %1183 : i32 to i64
        %1185 = llvm.getelementptr %1136[%1184] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1186 = llvm.getelementptr %1185[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1187 = llvm.load %1186 : !llvm.ptr -> i64
        %1188 = arith.constant 1 : i32
        %1190 = arith.extsi %1188 : i32 to i64
        %1189 = arith.shrui %1187, %1190 : i64
        %1192 = arith.constant 0 : i32
        %1193 = arith.extsi %1192 : i32 to i64
        %1194 = llvm.getelementptr %1136[%1193] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1191 = llvm.load %1194 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1195 = arith.constant 0 : i32
        %1196 = arith.extsi %1195 : i32 to i64
        %1197 = llvm.getelementptr %1136[%1196] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1198 = llvm.getelementptr %1197[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1199 = llvm.load %1198 : !llvm.ptr -> i64
        %1200 = arith.constant 1 : i32
        %1202 = arith.extsi %1200 : i32 to i64
        %1201 = arith.andi %1199, %1202 : i64
        %1203 = arith.constant 63 : i32
        %1205 = arith.extsi %1203 : i32 to i64
        %1204 = arith.shli %1201, %1205 : i64
        %1206 = arith.ori %1189, %1204 : i64
        %1207 = arith.constant 0 : i32
        %1208 = arith.extsi %1207 : i32 to i64
        %1209 = llvm.getelementptr %1136[%1208] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1210 = llvm.getelementptr %1209[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        llvm.store %1206, %1210 : i64, !llvm.ptr
        %1212 = arith.constant 0 : i32
        %1213 = arith.extsi %1212 : i32 to i64
        %1214 = llvm.getelementptr %1136[%1213] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1211 = llvm.load %1214 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1215 = arith.constant 0 : i32
        %1216 = arith.extsi %1215 : i32 to i64
        %1217 = llvm.getelementptr %1136[%1216] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1218 = llvm.getelementptr %1217[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1219 = llvm.load %1218 : !llvm.ptr -> i64
        %1220 = arith.constant 1 : i32
        %1222 = arith.extsi %1220 : i32 to i64
        %1221 = arith.shrui %1219, %1222 : i64
        %1224 = arith.constant 0 : i32
        %1225 = arith.extsi %1224 : i32 to i64
        %1226 = llvm.getelementptr %1136[%1225] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1223 = llvm.load %1226 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1227 = arith.constant 0 : i32
        %1228 = arith.extsi %1227 : i32 to i64
        %1229 = llvm.getelementptr %1136[%1228] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1230 = llvm.getelementptr %1229[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1231 = llvm.load %1230 : !llvm.ptr -> i64
        %1232 = arith.constant 1 : i32
        %1234 = arith.extsi %1232 : i32 to i64
        %1233 = arith.andi %1231, %1234 : i64
        %1235 = arith.constant 63 : i32
        %1237 = arith.extsi %1235 : i32 to i64
        %1236 = arith.shli %1233, %1237 : i64
        %1238 = arith.ori %1221, %1236 : i64
        %1239 = arith.constant 0 : i32
        %1240 = arith.extsi %1239 : i32 to i64
        %1241 = llvm.getelementptr %1136[%1240] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1242 = llvm.getelementptr %1241[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        llvm.store %1238, %1242 : i64, !llvm.ptr
        %1244 = arith.constant 0 : i32
        %1245 = arith.extsi %1244 : i32 to i64
        %1246 = llvm.getelementptr %1136[%1245] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1243 = llvm.load %1246 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1247 = arith.constant 0 : i32
        %1248 = arith.extsi %1247 : i32 to i64
        %1249 = llvm.getelementptr %1136[%1248] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1250 = llvm.getelementptr %1249[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1251 = llvm.load %1250 : !llvm.ptr -> i64
        %1252 = arith.constant 1 : i32
        %1254 = arith.extsi %1252 : i32 to i64
        %1253 = arith.shrui %1251, %1254 : i64
        %1256 = arith.constant 0 : i32
        %1257 = arith.extsi %1256 : i32 to i64
        %1258 = llvm.getelementptr %1136[%1257] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1255 = llvm.load %1258 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1259 = arith.constant 0 : i32
        %1260 = arith.extsi %1259 : i32 to i64
        %1261 = llvm.getelementptr %1136[%1260] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1262 = llvm.getelementptr %1261[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1263 = llvm.load %1262 : !llvm.ptr -> i64
        %1264 = arith.constant 1 : i32
        %1266 = arith.extsi %1264 : i32 to i64
        %1265 = arith.andi %1263, %1266 : i64
        %1267 = arith.constant 63 : i32
        %1269 = arith.extsi %1267 : i32 to i64
        %1268 = arith.shli %1265, %1269 : i64
        %1270 = arith.ori %1253, %1268 : i64
        %1271 = arith.constant 0 : i32
        %1272 = arith.extsi %1271 : i32 to i64
        %1273 = llvm.getelementptr %1136[%1272] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1274 = llvm.getelementptr %1273[0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        llvm.store %1270, %1274 : i64, !llvm.ptr
        %1276 = arith.constant 0 : i32
        %1277 = arith.extsi %1276 : i32 to i64
        %1278 = llvm.getelementptr %1136[%1277] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1275 = llvm.load %1278 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
        %1279 = arith.constant 0 : i32
        %1280 = arith.extsi %1279 : i32 to i64
        %1281 = llvm.getelementptr %1136[%1280] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1282 = llvm.getelementptr %1281[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1283 = llvm.load %1282 : !llvm.ptr -> i64
        %1284 = arith.constant 1 : i32
        %1286 = arith.extsi %1284 : i32 to i64
        %1285 = arith.shrui %1283, %1286 : i64
        %1287 = arith.constant 0 : i32
        %1288 = arith.extsi %1287 : i32 to i64
        %1289 = llvm.getelementptr %1136[%1288] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1290 = llvm.getelementptr %1289[0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        llvm.store %1285, %1290 : i64, !llvm.ptr
        %1291 = llvm.load %1144 : !llvm.ptr -> i32
        %1292 = arith.constant 1 : i32
        %1293 = arith.addi %1291, %1292 : i32
        llvm.store %1293, %1144 : i32, !llvm.ptr
        cf.br ^bb150
      ^bb152:
      func.call @free(%1126) : (!llvm.ptr) -> ()
      func.call @free(%1136) : (!llvm.ptr) -> ()
      %1296 = llvm.load %1123 : !llvm.ptr -> i32
      %1297 = arith.constant 1 : i32
      %1298 = arith.addi %1296, %1297 : i32
      llvm.store %1298, %1123 : i32, !llvm.ptr
      cf.br ^bb147
    ^bb149:
    %1299 = arith.constant 0 : i32
    %1300 = llvm.mlir.constant(1 : i64) : i64
    %1301 = llvm.alloca %1300 x i32 : (i64) -> !llvm.ptr
    llvm.store %1299, %1301 : i32, !llvm.ptr
    cf.br ^bb156
    ^bb156:
    %1302 = llvm.load %1301 : !llvm.ptr -> i32
    %1303 = arith.cmpi slt, %1302, %1110 : i32
    cf.cond_br %1303, ^bb157, ^bb158
    ^bb157:
      %1305 = llvm.load %1301 : !llvm.ptr -> i32
      %1306 = arith.extsi %1305 : i32 to i64
      %1307 = llvm.getelementptr %1114[%1306] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %1304 = llvm.load %1307 : !llvm.ptr -> i128
      %1308 = llvm.load %1301 : !llvm.ptr -> i32
      %1309 = arith.extsi %1308 : i32 to i128
      %1311 = arith.trunci %1120 : i128 to i64
      %1312 = arith.trunci %1309 : i128 to i64
      %1310 = arith.shli %1311, %1312 : i64
      %1314 = arith.trunci %1304 : i128 to i64
      %1313 = arith.xori %1314, %1310 : i64
      %1315 = llvm.load %1301 : !llvm.ptr -> i32
      %1316 = arith.extsi %1313 : i64 to i128
      %1317 = arith.extsi %1315 : i32 to i64
      %1318 = llvm.getelementptr %1114[%1317] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      llvm.store %1316, %1318 : i128, !llvm.ptr
      %1319 = llvm.load %1301 : !llvm.ptr -> i32
      %1320 = arith.constant 1 : i32
      %1321 = arith.addi %1319, %1320 : i32
      llvm.store %1321, %1301 : i32, !llvm.ptr
      cf.br ^bb156
    ^bb158:
    %1323 = arith.constant 128 : i32
    %1324 = arith.constant 4 : i32
    %1325 = arith.extsi %1323 : i32 to i64
    %1326 = arith.extsi %1324 : i32 to i64
    %1322 = func.call @calloc(%1325, %1326) : (i64, i64) -> !llvm.ptr
    %1328 = arith.constant 128 : i32
    %1329 = arith.constant 4 : i32
    %1330 = arith.extsi %1328 : i32 to i64
    %1331 = arith.extsi %1329 : i32 to i64
    %1327 = func.call @calloc(%1330, %1331) : (i64, i64) -> !llvm.ptr
    %1332 = arith.constant 0 : i32
    %1333 = llvm.mlir.constant(1 : i64) : i64
    %1334 = llvm.alloca %1333 x i32 : (i64) -> !llvm.ptr
    llvm.store %1332, %1334 : i32, !llvm.ptr
    %1335 = arith.constant 0 : i32
    %1336 = llvm.mlir.constant(1 : i64) : i64
    %1337 = llvm.alloca %1336 x i32 : (i64) -> !llvm.ptr
    llvm.store %1335, %1337 : i32, !llvm.ptr
    %1338 = arith.constant 0 : i32
    %1339 = llvm.mlir.constant(1 : i64) : i64
    %1340 = llvm.alloca %1339 x i32 : (i64) -> !llvm.ptr
    llvm.store %1338, %1340 : i32, !llvm.ptr
    cf.br ^bb159
    ^bb159:
    %1341 = llvm.load %1340 : !llvm.ptr -> i32
    %1342 = arith.cmpi slt, %1341, %1110 : i32
    %1343 = scf.if %1342 -> (i1) {
      %1344 = llvm.load %1337 : !llvm.ptr -> i32
      %1345 = arith.cmpi slt, %1344, %1110 : i32
      scf.yield %1345 : i1
    } else {
      %1346 = arith.constant false
      scf.yield %1346 : i1
    }
    cf.cond_br %1343, ^bb160, ^bb161
    ^bb160:
      %1347 = arith.constant 1 : i32
      %1349 = arith.constant 0 : i32
      %1348 = arith.subi %1349, %1347 : i32
      %1350 = llvm.mlir.constant(1 : i64) : i64
      %1351 = llvm.alloca %1350 x i32 : (i64) -> !llvm.ptr
      llvm.store %1348, %1351 : i32, !llvm.ptr
      %1352 = llvm.load %1337 : !llvm.ptr -> i32
      %1353 = llvm.mlir.constant(1 : i64) : i64
      %1354 = llvm.alloca %1353 x i32 : (i64) -> !llvm.ptr
      llvm.store %1352, %1354 : i32, !llvm.ptr
      cf.br ^bb162
      ^bb162:
      %1355 = llvm.load %1354 : !llvm.ptr -> i32
      %1356 = arith.cmpi slt, %1355, %1110 : i32
      cf.cond_br %1356, ^bb163, ^bb164
      ^bb163:
        %1358 = llvm.load %1354 : !llvm.ptr -> i32
        %1359 = arith.extsi %1358 : i32 to i64
        %1360 = llvm.getelementptr %1114[%1359] : (!llvm.ptr, i64) -> !llvm.ptr, i128
        %1357 = llvm.load %1360 : !llvm.ptr -> i128
        %1361 = llvm.load %1340 : !llvm.ptr -> i32
        %1362 = arith.extsi %1361 : i32 to i128
        %1364 = arith.trunci %1357 : i128 to i64
        %1365 = arith.trunci %1362 : i128 to i64
        %1363 = arith.shrsi %1364, %1365 : i64
        %1366 = arith.constant 1 : i32
        %1368 = arith.extsi %1366 : i32 to i64
        %1367 = arith.andi %1363, %1368 : i64
        %1369 = arith.constant 0 : i32
        %1371 = arith.extsi %1369 : i32 to i64
        %1370 = arith.cmpi ne, %1367, %1371 : i64
        cf.cond_br %1370, ^bb165, ^bb166
        ^bb165:
          %1372 = llvm.load %1354 : !llvm.ptr -> i32
          llvm.store %1372, %1351 : i32, !llvm.ptr
          cf.br ^bb164
        ^bb166:
          cf.br ^bb167
        ^bb167:
        %1373 = llvm.load %1354 : !llvm.ptr -> i32
        %1374 = arith.constant 1 : i32
        %1375 = arith.addi %1373, %1374 : i32
        llvm.store %1375, %1354 : i32, !llvm.ptr
        cf.br ^bb162
      ^bb164:
      %1376 = llvm.load %1351 : !llvm.ptr -> i32
      %1377 = arith.constant 0 : i32
      %1378 = arith.cmpi slt, %1376, %1377 : i32
      cf.cond_br %1378, ^bb168, ^bb169
      ^bb168:
        %1379 = llvm.load %1340 : !llvm.ptr -> i32
        %1380 = arith.constant 1 : i32
        %1381 = arith.addi %1379, %1380 : i32
        llvm.store %1381, %1340 : i32, !llvm.ptr
        cf.br ^bb159
      ^bb169:
        cf.br ^bb170
      ^bb170:
      %1383 = llvm.load %1337 : !llvm.ptr -> i32
      %1384 = arith.extsi %1383 : i32 to i64
      %1385 = llvm.getelementptr %1114[%1384] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %1382 = llvm.load %1385 : !llvm.ptr -> i128
      %1387 = llvm.load %1351 : !llvm.ptr -> i32
      %1388 = arith.extsi %1387 : i32 to i64
      %1389 = llvm.getelementptr %1114[%1388] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %1386 = llvm.load %1389 : !llvm.ptr -> i128
      %1390 = llvm.load %1337 : !llvm.ptr -> i32
      %1391 = arith.extsi %1390 : i32 to i64
      %1392 = llvm.getelementptr %1114[%1391] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      llvm.store %1386, %1392 : i128, !llvm.ptr
      %1393 = llvm.load %1351 : !llvm.ptr -> i32
      %1394 = arith.extsi %1393 : i32 to i64
      %1395 = llvm.getelementptr %1114[%1394] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      llvm.store %1382, %1395 : i128, !llvm.ptr
      %1397 = llvm.load %1337 : !llvm.ptr -> i32
      %1398 = arith.extsi %1397 : i32 to i64
      %1399 = llvm.getelementptr %1114[%1398] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %1396 = llvm.load %1399 : !llvm.ptr -> i128
      %1400 = arith.constant 0 : i32
      %1401 = llvm.mlir.constant(1 : i64) : i64
      %1402 = llvm.alloca %1401 x i32 : (i64) -> !llvm.ptr
      llvm.store %1400, %1402 : i32, !llvm.ptr
      cf.br ^bb171
      ^bb171:
      %1403 = llvm.load %1402 : !llvm.ptr -> i32
      %1404 = arith.cmpi slt, %1403, %1110 : i32
      cf.cond_br %1404, ^bb172, ^bb173
      ^bb172:
        %1405 = llvm.load %1402 : !llvm.ptr -> i32
        %1406 = llvm.load %1337 : !llvm.ptr -> i32
        %1407 = arith.cmpi ne, %1405, %1406 : i32
        %1408 = scf.if %1407 -> (i1) {
          %1410 = llvm.load %1402 : !llvm.ptr -> i32
          %1411 = arith.extsi %1410 : i32 to i64
          %1412 = llvm.getelementptr %1114[%1411] : (!llvm.ptr, i64) -> !llvm.ptr, i128
          %1409 = llvm.load %1412 : !llvm.ptr -> i128
          %1413 = llvm.load %1340 : !llvm.ptr -> i32
          %1414 = arith.extsi %1413 : i32 to i128
          %1416 = arith.trunci %1409 : i128 to i64
          %1417 = arith.trunci %1414 : i128 to i64
          %1415 = arith.shrsi %1416, %1417 : i64
          %1418 = arith.constant 1 : i32
          %1420 = arith.extsi %1418 : i32 to i64
          %1419 = arith.andi %1415, %1420 : i64
          %1421 = arith.constant 0 : i32
          %1423 = arith.extsi %1421 : i32 to i64
          %1422 = arith.cmpi ne, %1419, %1423 : i64
          scf.yield %1422 : i1
        } else {
          %1424 = arith.constant false
          scf.yield %1424 : i1
        }
        cf.cond_br %1408, ^bb174, ^bb175
        ^bb174:
          %1426 = llvm.load %1402 : !llvm.ptr -> i32
          %1427 = arith.extsi %1426 : i32 to i64
          %1428 = llvm.getelementptr %1114[%1427] : (!llvm.ptr, i64) -> !llvm.ptr, i128
          %1425 = llvm.load %1428 : !llvm.ptr -> i128
          %1430 = arith.trunci %1425 : i128 to i64
          %1431 = arith.trunci %1396 : i128 to i64
          %1429 = arith.xori %1430, %1431 : i64
          %1432 = llvm.load %1402 : !llvm.ptr -> i32
          %1433 = arith.extsi %1429 : i64 to i128
          %1434 = arith.extsi %1432 : i32 to i64
          %1435 = llvm.getelementptr %1114[%1434] : (!llvm.ptr, i64) -> !llvm.ptr, i128
          llvm.store %1433, %1435 : i128, !llvm.ptr
          cf.br ^bb176
        ^bb175:
          cf.br ^bb176
        ^bb176:
        %1436 = llvm.load %1402 : !llvm.ptr -> i32
        %1437 = arith.constant 1 : i32
        %1438 = arith.addi %1436, %1437 : i32
        llvm.store %1438, %1402 : i32, !llvm.ptr
        cf.br ^bb171
      ^bb173:
      %1439 = llvm.load %1340 : !llvm.ptr -> i32
      %1440 = llvm.load %1334 : !llvm.ptr -> i32
      %1441 = arith.extsi %1440 : i32 to i64
      %1442 = llvm.getelementptr %1322[%1441] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1439, %1442 : i32, !llvm.ptr
      %1443 = llvm.load %1337 : !llvm.ptr -> i32
      %1444 = llvm.load %1340 : !llvm.ptr -> i32
      %1445 = arith.extsi %1444 : i32 to i64
      %1446 = llvm.getelementptr %1327[%1445] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %1443, %1446 : i32, !llvm.ptr
      %1447 = llvm.load %1334 : !llvm.ptr -> i32
      %1448 = arith.constant 1 : i32
      %1449 = arith.addi %1447, %1448 : i32
      llvm.store %1449, %1334 : i32, !llvm.ptr
      %1450 = llvm.load %1337 : !llvm.ptr -> i32
      %1451 = arith.constant 1 : i32
      %1452 = arith.addi %1450, %1451 : i32
      llvm.store %1452, %1337 : i32, !llvm.ptr
      %1453 = llvm.load %1340 : !llvm.ptr -> i32
      %1454 = arith.constant 1 : i32
      %1455 = arith.addi %1453, %1454 : i32
      llvm.store %1455, %1340 : i32, !llvm.ptr
      cf.br ^bb159
    ^bb161:
    %1457 = arith.constant 128 : i32
    %1458 = arith.constant 4 : i32
    %1459 = arith.extsi %1457 : i32 to i64
    %1460 = arith.extsi %1458 : i32 to i64
    %1456 = func.call @calloc(%1459, %1460) : (i64, i64) -> !llvm.ptr
    %1461 = arith.constant 0 : i32
    %1462 = llvm.mlir.constant(1 : i64) : i64
    %1463 = llvm.alloca %1462 x i32 : (i64) -> !llvm.ptr
    llvm.store %1461, %1463 : i32, !llvm.ptr
    %1464 = arith.constant 0 : i32
    %1465 = llvm.mlir.constant(1 : i64) : i64
    %1466 = llvm.alloca %1465 x i32 : (i64) -> !llvm.ptr
    llvm.store %1464, %1466 : i32, !llvm.ptr
    cf.br ^bb177
    ^bb177:
    %1467 = llvm.load %1466 : !llvm.ptr -> i32
    %1468 = arith.cmpi slt, %1467, %1110 : i32
    cf.cond_br %1468, ^bb178, ^bb179
    ^bb178:
      %1469 = arith.constant 0 : i1
      %1470 = llvm.mlir.constant(1 : i64) : i64
      %1471 = llvm.alloca %1470 x i1 : (i64) -> !llvm.ptr
      llvm.store %1469, %1471 : i1, !llvm.ptr
      %1472 = arith.constant 0 : i32
      %1473 = llvm.mlir.constant(1 : i64) : i64
      %1474 = llvm.alloca %1473 x i32 : (i64) -> !llvm.ptr
      llvm.store %1472, %1474 : i32, !llvm.ptr
      cf.br ^bb180
      ^bb180:
      %1475 = llvm.load %1474 : !llvm.ptr -> i32
      %1476 = llvm.load %1334 : !llvm.ptr -> i32
      %1477 = arith.cmpi slt, %1475, %1476 : i32
      cf.cond_br %1477, ^bb181, ^bb182
      ^bb181:
        %1479 = llvm.load %1474 : !llvm.ptr -> i32
        %1480 = arith.extsi %1479 : i32 to i64
        %1481 = llvm.getelementptr %1322[%1480] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1478 = llvm.load %1481 : !llvm.ptr -> i32
        %1482 = llvm.load %1466 : !llvm.ptr -> i32
        %1483 = arith.cmpi eq, %1478, %1482 : i32
        cf.cond_br %1483, ^bb183, ^bb184
        ^bb183:
          %1484 = arith.constant 1 : i1
          llvm.store %1484, %1471 : i1, !llvm.ptr
          cf.br ^bb182
        ^bb184:
          cf.br ^bb185
        ^bb185:
        %1485 = llvm.load %1474 : !llvm.ptr -> i32
        %1486 = arith.constant 1 : i32
        %1487 = arith.addi %1485, %1486 : i32
        llvm.store %1487, %1474 : i32, !llvm.ptr
        cf.br ^bb180
      ^bb182:
      %1488 = llvm.load %1471 : !llvm.ptr -> i1
      %1490 = arith.constant 1 : i1
      %1489 = arith.xori %1488, %1490 : i1
      cf.cond_br %1489, ^bb186, ^bb187
      ^bb186:
        %1492 = llvm.load %1466 : !llvm.ptr -> i32
        %1493 = llvm.load %1463 : !llvm.ptr -> i32
        %1494 = arith.extsi %1493 : i32 to i64
        %1495 = llvm.getelementptr %1456[%1494] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %1492, %1495 : i32, !llvm.ptr
        %1496 = llvm.load %1463 : !llvm.ptr -> i32
        %1497 = arith.constant 1 : i32
        %1498 = arith.addi %1496, %1497 : i32
        llvm.store %1498, %1463 : i32, !llvm.ptr
        cf.br ^bb188
      ^bb187:
        cf.br ^bb188
      ^bb188:
      %1499 = llvm.load %1466 : !llvm.ptr -> i32
      %1500 = arith.constant 1 : i32
      %1501 = arith.addi %1499, %1500 : i32
      llvm.store %1501, %1466 : i32, !llvm.ptr
      cf.br ^bb177
    ^bb179:
    %1502 = arith.constant 0 : i32
    %1503 = llvm.mlir.constant(1 : i64) : i64
    %1504 = llvm.alloca %1503 x i32 : (i64) -> !llvm.ptr
    llvm.store %1502, %1504 : i32, !llvm.ptr
    cf.br ^bb189
    ^bb189:
    %1505 = llvm.load %1504 : !llvm.ptr -> i32
    %1506 = llvm.load %1463 : !llvm.ptr -> i32
    %1507 = arith.cmpi slt, %1505, %1506 : i32
    cf.cond_br %1507, ^bb190, ^bb191
    ^bb190:
      %1509 = llvm.load %1504 : !llvm.ptr -> i32
      %1510 = arith.extsi %1509 : i32 to i64
      %1511 = llvm.getelementptr %1456[%1510] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1508 = llvm.load %1511 : !llvm.ptr -> i32
      %1513 = arith.constant 1 : i32
      %1514 = arith.constant 32 : i32
      %1515 = arith.extsi %1513 : i32 to i64
      %1516 = arith.extsi %1514 : i32 to i64
      %1512 = func.call @calloc(%1515, %1516) : (i64, i64) -> !llvm.ptr
      func.call @poly_zero(%1512) : (!llvm.ptr) -> ()
      func.call @poly_set_bit(%1512, %1508) : (!llvm.ptr, i32) -> ()
      %1519 = arith.constant 0 : i32
      %1520 = llvm.mlir.constant(1 : i64) : i64
      %1521 = llvm.alloca %1520 x i32 : (i64) -> !llvm.ptr
      llvm.store %1519, %1521 : i32, !llvm.ptr
      cf.br ^bb192
      ^bb192:
      %1522 = llvm.load %1521 : !llvm.ptr -> i32
      %1523 = llvm.load %1334 : !llvm.ptr -> i32
      %1524 = arith.cmpi slt, %1522, %1523 : i32
      cf.cond_br %1524, ^bb193, ^bb194
      ^bb193:
        %1526 = llvm.load %1521 : !llvm.ptr -> i32
        %1527 = arith.extsi %1526 : i32 to i64
        %1528 = llvm.getelementptr %1322[%1527] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1525 = llvm.load %1528 : !llvm.ptr -> i32
        %1531 = arith.extsi %1525 : i32 to i64
        %1532 = llvm.getelementptr %1327[%1531] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %1530 = llvm.load %1532 : !llvm.ptr -> i32
        %1533 = arith.extsi %1530 : i32 to i64
        %1534 = llvm.getelementptr %1114[%1533] : (!llvm.ptr, i64) -> !llvm.ptr, i128
        %1529 = llvm.load %1534 : !llvm.ptr -> i128
        %1535 = arith.extsi %1508 : i32 to i128
        %1537 = arith.trunci %1529 : i128 to i64
        %1538 = arith.trunci %1535 : i128 to i64
        %1536 = arith.shrsi %1537, %1538 : i64
        %1539 = arith.constant 1 : i32
        %1541 = arith.extsi %1539 : i32 to i64
        %1540 = arith.andi %1536, %1541 : i64
        %1542 = arith.constant 0 : i32
        %1544 = arith.extsi %1542 : i32 to i64
        %1543 = arith.cmpi ne, %1540, %1544 : i64
        cf.cond_br %1543, ^bb195, ^bb196
        ^bb195:
          func.call @poly_set_bit(%1512, %1525) : (!llvm.ptr, i32) -> ()
          cf.br ^bb197
        ^bb196:
          cf.br ^bb197
        ^bb197:
        %1546 = llvm.load %1521 : !llvm.ptr -> i32
        %1547 = arith.constant 1 : i32
        %1548 = arith.addi %1546, %1547 : i32
        llvm.store %1548, %1521 : i32, !llvm.ptr
        cf.br ^bb192
      ^bb194:
      %1550 = llvm.load %1504 : !llvm.ptr -> i32
      %1551 = arith.extsi %1550 : i32 to i64
      %1552 = llvm.getelementptr %arg1[%1551] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      func.call @poly_copy(%1552, %1512) : (!llvm.ptr, !llvm.ptr) -> ()
      func.call @free(%1512) : (!llvm.ptr) -> ()
      %1554 = llvm.load %1504 : !llvm.ptr -> i32
      %1555 = arith.constant 1 : i32
      %1556 = arith.addi %1554, %1555 : i32
      llvm.store %1556, %1504 : i32, !llvm.ptr
      cf.br ^bb189
    ^bb191:
    func.call @free(%1114) : (!llvm.ptr) -> ()
    func.call @free(%1322) : (!llvm.ptr) -> ()
    func.call @free(%1327) : (!llvm.ptr) -> ()
    func.call @free(%1456) : (!llvm.ptr) -> ()
    %1561 = llvm.load %1463 : !llvm.ptr -> i32
    func.return %1561 : i32
  }
  func.func @factor_squarefree(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> i32 {
    %1562 = func.call @poly_deg(%arg0) : (!llvm.ptr) -> i32
    %1563 = arith.constant 0 : i32
    %1564 = arith.cmpi sle, %1562, %1563 : i32
    cf.cond_br %1564, ^bb198, ^bb199
    ^bb198:
      %1565 = arith.constant 0 : i32
      func.return %1565 : i32
    ^bb199:
      cf.br ^bb200
    ^bb200:
    %1566 = arith.constant 1 : i32
    %1567 = arith.cmpi eq, %1562, %1566 : i32
    cf.cond_br %1567, ^bb201, ^bb202
    ^bb201:
      %1569 = arith.constant 0 : i32
      %1570 = arith.extsi %1569 : i32 to i64
      %1571 = llvm.getelementptr %arg1[%1570] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      func.call @poly_copy(%1571, %arg0) : (!llvm.ptr, !llvm.ptr) -> ()
      %1572 = arith.constant 1 : i32
      func.return %1572 : i32
    ^bb202:
      cf.br ^bb203
    ^bb203:
    %1574 = arith.constant 128 : i32
    %1575 = arith.constant 32 : i32
    %1576 = arith.extsi %1574 : i32 to i64
    %1577 = arith.extsi %1575 : i32 to i64
    %1573 = func.call @calloc(%1576, %1577) : (i64, i64) -> !llvm.ptr
    %1578 = func.call @berlekamp_nullspace(%arg0, %1573) : (!llvm.ptr, !llvm.ptr) -> i32
    %1579 = arith.constant 1 : i32
    %1580 = arith.cmpi sle, %1578, %1579 : i32
    cf.cond_br %1580, ^bb204, ^bb205
    ^bb204:
      %1582 = arith.constant 0 : i32
      %1583 = arith.extsi %1582 : i32 to i64
      %1584 = llvm.getelementptr %arg1[%1583] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      func.call @poly_copy(%1584, %arg0) : (!llvm.ptr, !llvm.ptr) -> ()
      func.call @free(%1573) : (!llvm.ptr) -> ()
      %1586 = arith.constant 1 : i32
      func.return %1586 : i32
    ^bb205:
      cf.br ^bb206
    ^bb206:
    %1587 = arith.constant 1 : i32
    %1588 = arith.constant 1 : i32
    %1589 = arith.subi %1578, %1588 : i32
    %1590 = arith.shli %1587, %1589 : i32
    %1592 = arith.constant 1 : i32
    %1593 = arith.constant 32 : i32
    %1594 = arith.extsi %1592 : i32 to i64
    %1595 = arith.extsi %1593 : i32 to i64
    %1591 = func.call @calloc(%1594, %1595) : (i64, i64) -> !llvm.ptr
    %1597 = arith.constant 1 : i32
    %1598 = arith.constant 32 : i32
    %1599 = arith.extsi %1597 : i32 to i64
    %1600 = arith.extsi %1598 : i32 to i64
    %1596 = func.call @calloc(%1599, %1600) : (i64, i64) -> !llvm.ptr
    %1602 = arith.constant 1 : i32
    %1603 = arith.constant 32 : i32
    %1604 = arith.extsi %1602 : i32 to i64
    %1605 = arith.extsi %1603 : i32 to i64
    %1601 = func.call @calloc(%1604, %1605) : (i64, i64) -> !llvm.ptr
    %1607 = arith.constant 128 : i32
    %1608 = arith.constant 32 : i32
    %1609 = arith.extsi %1607 : i32 to i64
    %1610 = arith.extsi %1608 : i32 to i64
    %1606 = func.call @calloc(%1609, %1610) : (i64, i64) -> !llvm.ptr
    %1611 = arith.constant 1 : i32
    %1612 = llvm.mlir.constant(1 : i64) : i64
    %1613 = llvm.alloca %1612 x i32 : (i64) -> !llvm.ptr
    llvm.store %1611, %1613 : i32, !llvm.ptr
    cf.br ^bb207
    ^bb207:
    %1614 = llvm.load %1613 : !llvm.ptr -> i32
    %1615 = arith.cmpi slt, %1614, %1590 : i32
    cf.cond_br %1615, ^bb208, ^bb209
    ^bb208:
      func.call @poly_zero(%1591) : (!llvm.ptr) -> ()
      %1617 = arith.constant 0 : i32
      %1618 = llvm.mlir.constant(1 : i64) : i64
      %1619 = llvm.alloca %1618 x i32 : (i64) -> !llvm.ptr
      llvm.store %1617, %1619 : i32, !llvm.ptr
      cf.br ^bb210
      ^bb210:
      %1620 = llvm.load %1619 : !llvm.ptr -> i32
      %1621 = arith.constant 1 : i32
      %1622 = arith.subi %1578, %1621 : i32
      %1623 = arith.cmpi slt, %1620, %1622 : i32
      cf.cond_br %1623, ^bb211, ^bb212
      ^bb211:
        %1624 = llvm.load %1613 : !llvm.ptr -> i32
        %1625 = arith.constant 1 : i32
        %1626 = llvm.load %1619 : !llvm.ptr -> i32
        %1627 = arith.shli %1625, %1626 : i32
        %1628 = arith.andi %1624, %1627 : i32
        %1629 = arith.constant 0 : i32
        %1630 = arith.cmpi ne, %1628, %1629 : i32
        cf.cond_br %1630, ^bb213, ^bb214
        ^bb213:
          %1632 = llvm.load %1619 : !llvm.ptr -> i32
          %1633 = arith.constant 1 : i32
          %1634 = arith.addi %1632, %1633 : i32
          %1635 = arith.extsi %1634 : i32 to i64
          %1636 = llvm.getelementptr %1573[%1635] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
          func.call @poly_xor(%1591, %1636) : (!llvm.ptr, !llvm.ptr) -> ()
          cf.br ^bb215
        ^bb214:
          cf.br ^bb215
        ^bb215:
        %1637 = llvm.load %1619 : !llvm.ptr -> i32
        %1638 = arith.constant 1 : i32
        %1639 = arith.addi %1637, %1638 : i32
        llvm.store %1639, %1619 : i32, !llvm.ptr
        cf.br ^bb210
      ^bb212:
      %1640 = func.call @poly_is_zero(%1591) : (!llvm.ptr) -> i1
      %1641 = scf.if %1640 -> (i1) {
        %1642 = arith.constant true
        scf.yield %1642 : i1
      } else {
        %1643 = func.call @poly_is_one(%1591) : (!llvm.ptr) -> i1
        scf.yield %1643 : i1
      }
      cf.cond_br %1641, ^bb216, ^bb217
      ^bb216:
        %1644 = llvm.load %1613 : !llvm.ptr -> i32
        %1645 = arith.constant 1 : i32
        %1646 = arith.addi %1644, %1645 : i32
        llvm.store %1646, %1613 : i32, !llvm.ptr
        cf.br ^bb207
      ^bb217:
        cf.br ^bb218
      ^bb218:
      func.call @poly_gcd(%1596, %arg0, %1591) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      %1648 = func.call @poly_deg(%1596) : (!llvm.ptr) -> i32
      %1649 = arith.constant 0 : i32
      %1650 = arith.cmpi sgt, %1648, %1649 : i32
      %1651 = scf.if %1650 -> (i1) {
        %1652 = arith.cmpi slt, %1648, %1562 : i32
        scf.yield %1652 : i1
      } else {
        %1653 = arith.constant false
        scf.yield %1653 : i1
      }
      cf.cond_br %1651, ^bb219, ^bb220
      ^bb219:
        func.call @poly_div_exact(%1601, %arg0, %1596) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
        %1655 = func.call @factor_squarefree(%1596, %arg1) : (!llvm.ptr, !llvm.ptr) -> i32
        %1656 = func.call @factor_squarefree(%1601, %1606) : (!llvm.ptr, !llvm.ptr) -> i32
        %1657 = arith.constant 0 : i32
        %1658 = llvm.mlir.constant(1 : i64) : i64
        %1659 = llvm.alloca %1658 x i32 : (i64) -> !llvm.ptr
        llvm.store %1657, %1659 : i32, !llvm.ptr
        cf.br ^bb222
        ^bb222:
        %1660 = llvm.load %1659 : !llvm.ptr -> i32
        %1661 = arith.cmpi slt, %1660, %1656 : i32
        cf.cond_br %1661, ^bb223, ^bb224
        ^bb223:
          %1663 = llvm.load %1659 : !llvm.ptr -> i32
          %1664 = arith.addi %1655, %1663 : i32
          %1665 = arith.extsi %1664 : i32 to i64
          %1666 = llvm.getelementptr %arg1[%1665] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
          %1667 = llvm.load %1659 : !llvm.ptr -> i32
          %1668 = arith.extsi %1667 : i32 to i64
          %1669 = llvm.getelementptr %1606[%1668] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
          func.call @poly_copy(%1666, %1669) : (!llvm.ptr, !llvm.ptr) -> ()
          %1670 = llvm.load %1659 : !llvm.ptr -> i32
          %1671 = arith.constant 1 : i32
          %1672 = arith.addi %1670, %1671 : i32
          llvm.store %1672, %1659 : i32, !llvm.ptr
          cf.br ^bb222
        ^bb224:
        func.call @free(%1573) : (!llvm.ptr) -> ()
        func.call @free(%1591) : (!llvm.ptr) -> ()
        func.call @free(%1596) : (!llvm.ptr) -> ()
        func.call @free(%1601) : (!llvm.ptr) -> ()
        func.call @free(%1606) : (!llvm.ptr) -> ()
        %1678 = arith.addi %1655, %1656 : i32
        func.return %1678 : i32
      ^bb220:
        cf.br ^bb221
      ^bb221:
      %1680 = arith.constant 0 : i32
      %1681 = arith.extsi %1680 : i32 to i64
      %1682 = llvm.getelementptr %1591[%1681] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %1679 = llvm.load %1682 : !llvm.ptr -> !llvm.struct<(i64, i64, i64, i64)>
      %1683 = arith.constant 0 : i32
      %1684 = arith.extsi %1683 : i32 to i64
      %1685 = llvm.getelementptr %1591[%1684] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %1686 = llvm.getelementptr %1685[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %1687 = llvm.load %1686 : !llvm.ptr -> i64
      %1688 = arith.constant 1 : i32
      %1690 = arith.extsi %1688 : i32 to i64
      %1689 = arith.xori %1687, %1690 : i64
      %1691 = arith.constant 0 : i32
      %1692 = arith.extsi %1691 : i32 to i64
      %1693 = llvm.getelementptr %1591[%1692] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %1694 = llvm.getelementptr %1693[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      llvm.store %1689, %1694 : i64, !llvm.ptr
      func.call @poly_gcd(%1596, %arg0, %1591) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      %1696 = func.call @poly_deg(%1596) : (!llvm.ptr) -> i32
      %1697 = arith.constant 0 : i32
      %1698 = arith.cmpi sgt, %1696, %1697 : i32
      %1699 = scf.if %1698 -> (i1) {
        %1700 = arith.cmpi slt, %1696, %1562 : i32
        scf.yield %1700 : i1
      } else {
        %1701 = arith.constant false
        scf.yield %1701 : i1
      }
      cf.cond_br %1699, ^bb225, ^bb226
      ^bb225:
        func.call @poly_div_exact(%1601, %arg0, %1596) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
        %1703 = func.call @factor_squarefree(%1596, %arg1) : (!llvm.ptr, !llvm.ptr) -> i32
        %1704 = func.call @factor_squarefree(%1601, %1606) : (!llvm.ptr, !llvm.ptr) -> i32
        %1705 = arith.constant 0 : i32
        %1706 = llvm.mlir.constant(1 : i64) : i64
        %1707 = llvm.alloca %1706 x i32 : (i64) -> !llvm.ptr
        llvm.store %1705, %1707 : i32, !llvm.ptr
        cf.br ^bb228
        ^bb228:
        %1708 = llvm.load %1707 : !llvm.ptr -> i32
        %1709 = arith.cmpi slt, %1708, %1704 : i32
        cf.cond_br %1709, ^bb229, ^bb230
        ^bb229:
          %1711 = llvm.load %1707 : !llvm.ptr -> i32
          %1712 = arith.addi %1703, %1711 : i32
          %1713 = arith.extsi %1712 : i32 to i64
          %1714 = llvm.getelementptr %arg1[%1713] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
          %1715 = llvm.load %1707 : !llvm.ptr -> i32
          %1716 = arith.extsi %1715 : i32 to i64
          %1717 = llvm.getelementptr %1606[%1716] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
          func.call @poly_copy(%1714, %1717) : (!llvm.ptr, !llvm.ptr) -> ()
          %1718 = llvm.load %1707 : !llvm.ptr -> i32
          %1719 = arith.constant 1 : i32
          %1720 = arith.addi %1718, %1719 : i32
          llvm.store %1720, %1707 : i32, !llvm.ptr
          cf.br ^bb228
        ^bb230:
        func.call @free(%1573) : (!llvm.ptr) -> ()
        func.call @free(%1591) : (!llvm.ptr) -> ()
        func.call @free(%1596) : (!llvm.ptr) -> ()
        func.call @free(%1601) : (!llvm.ptr) -> ()
        func.call @free(%1606) : (!llvm.ptr) -> ()
        %1726 = arith.addi %1703, %1704 : i32
        func.return %1726 : i32
      ^bb226:
        cf.br ^bb227
      ^bb227:
      %1727 = llvm.load %1613 : !llvm.ptr -> i32
      %1728 = arith.constant 1 : i32
      %1729 = arith.addi %1727, %1728 : i32
      llvm.store %1729, %1613 : i32, !llvm.ptr
      cf.br ^bb207
    ^bb209:
    %1731 = arith.constant 0 : i32
    %1732 = arith.extsi %1731 : i32 to i64
    %1733 = llvm.getelementptr %arg1[%1732] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
    func.call @poly_copy(%1733, %arg0) : (!llvm.ptr, !llvm.ptr) -> ()
    func.call @free(%1573) : (!llvm.ptr) -> ()
    func.call @free(%1591) : (!llvm.ptr) -> ()
    func.call @free(%1596) : (!llvm.ptr) -> ()
    func.call @free(%1601) : (!llvm.ptr) -> ()
    func.call @free(%1606) : (!llvm.ptr) -> ()
    %1739 = arith.constant 1 : i32
    func.return %1739 : i32
  }
  // Module static: factor_cache
  llvm.mlir.global internal @factor_cache() {addr_space = 0 : i32} : !llvm.ptr {
    %1740 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1740 : !llvm.ptr
  }
  // Module static: factor_cache_count
  llvm.mlir.global internal @factor_cache_count() {addr_space = 0 : i32} : !llvm.ptr {
    %1741 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1741 : !llvm.ptr
  }
  // Module static: factor_cache_done
  llvm.mlir.global internal @factor_cache_done() {addr_space = 0 : i32} : !llvm.ptr {
    %1742 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1742 : !llvm.ptr
  }
  func.func @init_factor_cache() -> () {
    %1744 = arith.constant 101 : i32
    %1745 = arith.constant 8 : i32
    %1746 = arith.extsi %1744 : i32 to i64
    %1747 = arith.extsi %1745 : i32 to i64
    %1743 = func.call @calloc(%1746, %1747) : (i64, i64) -> !llvm.ptr
    %1748 = llvm.mlir.addressof @factor_cache : !llvm.ptr
    llvm.store %1743, %1748 : !llvm.ptr, !llvm.ptr
    %1750 = arith.constant 101 : i32
    %1751 = arith.constant 4 : i32
    %1752 = arith.extsi %1750 : i32 to i64
    %1753 = arith.extsi %1751 : i32 to i64
    %1749 = func.call @calloc(%1752, %1753) : (i64, i64) -> !llvm.ptr
    %1754 = llvm.mlir.addressof @factor_cache_count : !llvm.ptr
    llvm.store %1749, %1754 : !llvm.ptr, !llvm.ptr
    %1756 = arith.constant 101 : i32
    %1757 = arith.constant 1 : i32
    %1758 = arith.extsi %1756 : i32 to i64
    %1759 = arith.extsi %1757 : i32 to i64
    %1755 = func.call @calloc(%1758, %1759) : (i64, i64) -> !llvm.ptr
    %1760 = llvm.mlir.addressof @factor_cache_done : !llvm.ptr
    llvm.store %1755, %1760 : !llvm.ptr, !llvm.ptr
    %1761 = arith.constant 0 : i32
    %1762 = llvm.mlir.constant(1 : i64) : i64
    %1763 = llvm.alloca %1762 x i32 : (i64) -> !llvm.ptr
    llvm.store %1761, %1763 : i32, !llvm.ptr
    cf.br ^bb231
    ^bb231:
    %1764 = llvm.load %1763 : !llvm.ptr -> i32
    %1765 = arith.constant 100 : i32
    %1766 = arith.cmpi sle, %1764, %1765 : i32
    cf.cond_br %1766, ^bb232, ^bb233
    ^bb232:
      %1768 = arith.constant 128 : i32
      %1769 = arith.constant 32 : i32
      %1770 = arith.extsi %1768 : i32 to i64
      %1771 = arith.extsi %1769 : i32 to i64
      %1767 = func.call @calloc(%1770, %1771) : (i64, i64) -> !llvm.ptr
      %1772 = llvm.mlir.addressof @factor_cache : !llvm.ptr
      %1773 = llvm.load %1772 : !llvm.ptr -> !llvm.ptr
      %1774 = llvm.load %1763 : !llvm.ptr -> i32
      %1775 = arith.extsi %1774 : i32 to i64
      %1776 = llvm.getelementptr %1773[%1775] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      llvm.store %1767, %1776 : !llvm.ptr, !llvm.ptr
      %1777 = llvm.load %1763 : !llvm.ptr -> i32
      %1778 = arith.constant 1 : i32
      %1779 = arith.addi %1777, %1778 : i32
      llvm.store %1779, %1763 : i32, !llvm.ptr
      cf.br ^bb231
    ^bb233:
    func.return
  }
  func.func @irreducible_factors_xm_plus_1(%arg0: i32, %arg1: !llvm.ptr) -> i32 {
    %1781 = llvm.mlir.addressof @factor_cache_done : !llvm.ptr
    %1782 = llvm.load %1781 : !llvm.ptr -> !llvm.ptr
    %1783 = arith.extsi %arg0 : i32 to i64
    %1784 = llvm.getelementptr %1782[%1783] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    %1780 = llvm.load %1784 : !llvm.ptr -> i8
    %1785 = arith.constant 0 : i32
    %1787 = arith.extsi %1780 : i8 to i32
    %1786 = arith.cmpi ne, %1787, %1785 : i32
    cf.cond_br %1786, ^bb234, ^bb235
    ^bb234:
      %1788 = arith.constant 0 : i32
      %1789 = llvm.mlir.constant(1 : i64) : i64
      %1790 = llvm.alloca %1789 x i32 : (i64) -> !llvm.ptr
      llvm.store %1788, %1790 : i32, !llvm.ptr
      cf.br ^bb237
      ^bb237:
      %1791 = llvm.load %1790 : !llvm.ptr -> i32
      %1793 = llvm.mlir.addressof @factor_cache_count : !llvm.ptr
      %1794 = llvm.load %1793 : !llvm.ptr -> !llvm.ptr
      %1795 = arith.extsi %arg0 : i32 to i64
      %1796 = llvm.getelementptr %1794[%1795] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1792 = llvm.load %1796 : !llvm.ptr -> i32
      %1797 = arith.cmpi slt, %1791, %1792 : i32
      cf.cond_br %1797, ^bb238, ^bb239
      ^bb238:
        %1799 = llvm.load %1790 : !llvm.ptr -> i32
        %1800 = arith.extsi %1799 : i32 to i64
        %1801 = llvm.getelementptr %arg1[%1800] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        %1804 = llvm.mlir.addressof @factor_cache : !llvm.ptr
        %1805 = llvm.load %1804 : !llvm.ptr -> !llvm.ptr
        %1806 = arith.extsi %arg0 : i32 to i64
        %1807 = llvm.getelementptr %1805[%1806] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %1803 = llvm.load %1807 : !llvm.ptr -> !llvm.ptr
        %1802 = llvm.load %1790 : !llvm.ptr -> i32
        %1808 = arith.extsi %1802 : i32 to i64
        %1809 = llvm.getelementptr %1803[%1808] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
        func.call @poly_copy(%1801, %1809) : (!llvm.ptr, !llvm.ptr) -> ()
        %1810 = llvm.load %1790 : !llvm.ptr -> i32
        %1811 = arith.constant 1 : i32
        %1812 = arith.addi %1810, %1811 : i32
        llvm.store %1812, %1790 : i32, !llvm.ptr
        cf.br ^bb237
      ^bb239:
      %1814 = llvm.mlir.addressof @factor_cache_count : !llvm.ptr
      %1815 = llvm.load %1814 : !llvm.ptr -> !llvm.ptr
      %1816 = arith.extsi %arg0 : i32 to i64
      %1817 = llvm.getelementptr %1815[%1816] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1813 = llvm.load %1817 : !llvm.ptr -> i32
      func.return %1813 : i32
    ^bb235:
      cf.br ^bb236
    ^bb236:
    %1819 = arith.constant 1 : i32
    %1820 = arith.constant 32 : i32
    %1821 = arith.extsi %1819 : i32 to i64
    %1822 = arith.extsi %1820 : i32 to i64
    %1818 = func.call @calloc(%1821, %1822) : (i64, i64) -> !llvm.ptr
    func.call @poly_zero(%1818) : (!llvm.ptr) -> ()
    func.call @poly_set_bit(%1818, %arg0) : (!llvm.ptr, i32) -> ()
    %1826 = arith.constant 0 : i32
    func.call @poly_set_bit(%1818, %1826) : (!llvm.ptr, i32) -> ()
    %1827 = func.call @factor_squarefree(%1818, %arg1) : (!llvm.ptr, !llvm.ptr) -> i32
    %1828 = arith.constant 0 : i32
    %1829 = llvm.mlir.constant(1 : i64) : i64
    %1830 = llvm.alloca %1829 x i32 : (i64) -> !llvm.ptr
    llvm.store %1828, %1830 : i32, !llvm.ptr
    cf.br ^bb240
    ^bb240:
    %1831 = llvm.load %1830 : !llvm.ptr -> i32
    %1832 = arith.cmpi slt, %1831, %1827 : i32
    cf.cond_br %1832, ^bb241, ^bb242
    ^bb241:
      %1836 = llvm.mlir.addressof @factor_cache : !llvm.ptr
      %1837 = llvm.load %1836 : !llvm.ptr -> !llvm.ptr
      %1838 = arith.extsi %arg0 : i32 to i64
      %1839 = llvm.getelementptr %1837[%1838] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %1835 = llvm.load %1839 : !llvm.ptr -> !llvm.ptr
      %1834 = llvm.load %1830 : !llvm.ptr -> i32
      %1840 = arith.extsi %1834 : i32 to i64
      %1841 = llvm.getelementptr %1835[%1840] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      %1842 = llvm.load %1830 : !llvm.ptr -> i32
      %1843 = arith.extsi %1842 : i32 to i64
      %1844 = llvm.getelementptr %arg1[%1843] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      func.call @poly_copy(%1841, %1844) : (!llvm.ptr, !llvm.ptr) -> ()
      %1845 = llvm.load %1830 : !llvm.ptr -> i32
      %1846 = arith.constant 1 : i32
      %1847 = arith.addi %1845, %1846 : i32
      llvm.store %1847, %1830 : i32, !llvm.ptr
      cf.br ^bb240
    ^bb242:
    %1848 = llvm.mlir.addressof @factor_cache_count : !llvm.ptr
    %1849 = llvm.load %1848 : !llvm.ptr -> !llvm.ptr
    %1850 = arith.extsi %arg0 : i32 to i64
    %1851 = llvm.getelementptr %1849[%1850] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %1827, %1851 : i32, !llvm.ptr
    %1852 = arith.constant 1 : i32
    %1853 = llvm.mlir.addressof @factor_cache_done : !llvm.ptr
    %1854 = llvm.load %1853 : !llvm.ptr -> !llvm.ptr
    %1855 = arith.trunci %1852 : i32 to i8
    %1856 = arith.extsi %arg0 : i32 to i64
    %1857 = llvm.getelementptr %1854[%1856] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %1855, %1857 : i8, !llvm.ptr
    func.call @free(%1818) : (!llvm.ptr) -> ()
    func.return %1827 : i32
  }
  func.func @frobenius_orbit_degree(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> i32 {
    %1860 = arith.constant 1 : i32
    %1861 = arith.constant 32 : i32
    %1862 = arith.extsi %1860 : i32 to i64
    %1863 = arith.extsi %1861 : i32 to i64
    %1859 = func.call @calloc(%1862, %1863) : (i64, i64) -> !llvm.ptr
    %1865 = arith.constant 1 : i32
    %1866 = arith.constant 32 : i32
    %1867 = arith.extsi %1865 : i32 to i64
    %1868 = arith.extsi %1866 : i32 to i64
    %1864 = func.call @calloc(%1867, %1868) : (i64, i64) -> !llvm.ptr
    func.call @poly_copy(%1859, %arg0) : (!llvm.ptr, !llvm.ptr) -> ()
    %1870 = func.call @poly_deg(%arg1) : (!llvm.ptr) -> i32
    %1871 = arith.constant 1 : i32
    %1872 = llvm.mlir.constant(1 : i64) : i64
    %1873 = llvm.alloca %1872 x i32 : (i64) -> !llvm.ptr
    llvm.store %1871, %1873 : i32, !llvm.ptr
    cf.br ^bb243
    ^bb243:
    %1874 = llvm.load %1873 : !llvm.ptr -> i32
    %1875 = arith.cmpi sle, %1874, %1870 : i32
    cf.cond_br %1875, ^bb244, ^bb245
    ^bb244:
      func.call @poly_square_mod(%1864, %1859, %arg1) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      func.call @poly_copy(%1859, %1864) : (!llvm.ptr, !llvm.ptr) -> ()
      %1878 = func.call @poly_equal(%1859, %arg0) : (!llvm.ptr, !llvm.ptr) -> i1
      cf.cond_br %1878, ^bb246, ^bb247
      ^bb246:
        func.call @free(%1859) : (!llvm.ptr) -> ()
        func.call @free(%1864) : (!llvm.ptr) -> ()
        %1881 = llvm.load %1873 : !llvm.ptr -> i32
        func.return %1881 : i32
      ^bb247:
        cf.br ^bb248
      ^bb248:
      %1882 = llvm.load %1873 : !llvm.ptr -> i32
      %1883 = arith.constant 1 : i32
      %1884 = arith.addi %1882, %1883 : i32
      llvm.store %1884, %1873 : i32, !llvm.ptr
      cf.br ^bb243
    ^bb245:
    func.call @free(%1859) : (!llvm.ptr) -> ()
    func.call @free(%1864) : (!llvm.ptr) -> ()
    func.return %1870 : i32
  }
  // Module static: mersenne_cache
  llvm.mlir.global internal @mersenne_cache() {addr_space = 0 : i32} : !llvm.ptr {
    %1887 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1887 : !llvm.ptr
  }
  // Module static: mersenne_cache_count
  llvm.mlir.global internal @mersenne_cache_count() {addr_space = 0 : i32} : !llvm.ptr {
    %1888 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1888 : !llvm.ptr
  }
  // Module static: mersenne_cache_done
  llvm.mlir.global internal @mersenne_cache_done() {addr_space = 0 : i32} : !llvm.ptr {
    %1889 = llvm.mlir.zero : !llvm.ptr
    llvm.return %1889 : !llvm.ptr
  }
  func.func @init_mersenne_cache() -> () {
    %1891 = arith.constant 42 : i32
    %1892 = arith.constant 8 : i32
    %1893 = arith.extsi %1891 : i32 to i64
    %1894 = arith.extsi %1892 : i32 to i64
    %1890 = func.call @calloc(%1893, %1894) : (i64, i64) -> !llvm.ptr
    %1895 = llvm.mlir.addressof @mersenne_cache : !llvm.ptr
    llvm.store %1890, %1895 : !llvm.ptr, !llvm.ptr
    %1897 = arith.constant 42 : i32
    %1898 = arith.constant 4 : i32
    %1899 = arith.extsi %1897 : i32 to i64
    %1900 = arith.extsi %1898 : i32 to i64
    %1896 = func.call @calloc(%1899, %1900) : (i64, i64) -> !llvm.ptr
    %1901 = llvm.mlir.addressof @mersenne_cache_count : !llvm.ptr
    llvm.store %1896, %1901 : !llvm.ptr, !llvm.ptr
    %1903 = arith.constant 42 : i32
    %1904 = arith.constant 1 : i32
    %1905 = arith.extsi %1903 : i32 to i64
    %1906 = arith.extsi %1904 : i32 to i64
    %1902 = func.call @calloc(%1905, %1906) : (i64, i64) -> !llvm.ptr
    %1907 = llvm.mlir.addressof @mersenne_cache_done : !llvm.ptr
    llvm.store %1902, %1907 : !llvm.ptr, !llvm.ptr
    %1908 = arith.constant 0 : i32
    %1909 = llvm.mlir.constant(1 : i64) : i64
    %1910 = llvm.alloca %1909 x i32 : (i64) -> !llvm.ptr
    llvm.store %1908, %1910 : i32, !llvm.ptr
    cf.br ^bb249
    ^bb249:
    %1911 = llvm.load %1910 : !llvm.ptr -> i32
    %1912 = arith.constant 42 : i32
    %1913 = arith.cmpi slt, %1911, %1912 : i32
    cf.cond_br %1913, ^bb250, ^bb251
    ^bb250:
      %1915 = arith.constant 64 : i32
      %1916 = arith.constant 8 : i32
      %1917 = arith.extsi %1915 : i32 to i64
      %1918 = arith.extsi %1916 : i32 to i64
      %1914 = func.call @calloc(%1917, %1918) : (i64, i64) -> !llvm.ptr
      %1919 = llvm.mlir.addressof @mersenne_cache : !llvm.ptr
      %1920 = llvm.load %1919 : !llvm.ptr -> !llvm.ptr
      %1921 = llvm.load %1910 : !llvm.ptr -> i32
      %1922 = arith.extsi %1921 : i32 to i64
      %1923 = llvm.getelementptr %1920[%1922] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      llvm.store %1914, %1923 : !llvm.ptr, !llvm.ptr
      %1924 = llvm.load %1910 : !llvm.ptr -> i32
      %1925 = arith.constant 1 : i32
      %1926 = arith.addi %1924, %1925 : i32
      llvm.store %1926, %1910 : i32, !llvm.ptr
      cf.br ^bb249
    ^bb251:
    func.return
  }
  func.func @mersenne_factors(%arg0: i32, %arg1: !llvm.ptr) -> i32 {
    %1928 = llvm.mlir.addressof @mersenne_cache_done : !llvm.ptr
    %1929 = llvm.load %1928 : !llvm.ptr -> !llvm.ptr
    %1930 = arith.extsi %arg0 : i32 to i64
    %1931 = llvm.getelementptr %1929[%1930] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    %1927 = llvm.load %1931 : !llvm.ptr -> i8
    %1932 = arith.constant 0 : i32
    %1934 = arith.extsi %1927 : i8 to i32
    %1933 = arith.cmpi ne, %1934, %1932 : i32
    cf.cond_br %1933, ^bb252, ^bb253
    ^bb252:
      %1935 = arith.constant 0 : i32
      %1936 = llvm.mlir.constant(1 : i64) : i64
      %1937 = llvm.alloca %1936 x i32 : (i64) -> !llvm.ptr
      llvm.store %1935, %1937 : i32, !llvm.ptr
      cf.br ^bb255
      ^bb255:
      %1938 = llvm.load %1937 : !llvm.ptr -> i32
      %1940 = llvm.mlir.addressof @mersenne_cache_count : !llvm.ptr
      %1941 = llvm.load %1940 : !llvm.ptr -> !llvm.ptr
      %1942 = arith.extsi %arg0 : i32 to i64
      %1943 = llvm.getelementptr %1941[%1942] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1939 = llvm.load %1943 : !llvm.ptr -> i32
      %1944 = arith.cmpi slt, %1938, %1939 : i32
      cf.cond_br %1944, ^bb256, ^bb257
      ^bb256:
        %1947 = llvm.mlir.addressof @mersenne_cache : !llvm.ptr
        %1948 = llvm.load %1947 : !llvm.ptr -> !llvm.ptr
        %1949 = arith.extsi %arg0 : i32 to i64
        %1950 = llvm.getelementptr %1948[%1949] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %1946 = llvm.load %1950 : !llvm.ptr -> !llvm.ptr
        %1951 = llvm.load %1937 : !llvm.ptr -> i32
        %1952 = arith.extsi %1951 : i32 to i64
        %1953 = llvm.getelementptr %1946[%1952] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %1945 = llvm.load %1953 : !llvm.ptr -> i64
        %1954 = llvm.load %1937 : !llvm.ptr -> i32
        %1955 = arith.extsi %1954 : i32 to i64
        %1956 = llvm.getelementptr %arg1[%1955] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %1945, %1956 : i64, !llvm.ptr
        %1957 = llvm.load %1937 : !llvm.ptr -> i32
        %1958 = arith.constant 1 : i32
        %1959 = arith.addi %1957, %1958 : i32
        llvm.store %1959, %1937 : i32, !llvm.ptr
        cf.br ^bb255
      ^bb257:
      %1961 = llvm.mlir.addressof @mersenne_cache_count : !llvm.ptr
      %1962 = llvm.load %1961 : !llvm.ptr -> !llvm.ptr
      %1963 = arith.extsi %arg0 : i32 to i64
      %1964 = llvm.getelementptr %1962[%1963] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %1960 = llvm.load %1964 : !llvm.ptr -> i32
      func.return %1960 : i32
    ^bb253:
      cf.br ^bb254
    ^bb254:
    %1965 = arith.constant 1 : i32
    %1966 = arith.extsi %1965 : i32 to i64
    %1968 = arith.extsi %arg0 : i32 to i64
    %1967 = arith.shli %1966, %1968 : i64
    %1969 = arith.constant 1 : i32
    %1971 = arith.extsi %1969 : i32 to i64
    %1970 = arith.subi %1967, %1971 : i64
    %1972 = func.call @factor_small(%1970, %arg1) : (i64, !llvm.ptr) -> i32
    %1973 = arith.constant 0 : i32
    %1974 = llvm.mlir.constant(1 : i64) : i64
    %1975 = llvm.alloca %1974 x i32 : (i64) -> !llvm.ptr
    llvm.store %1973, %1975 : i32, !llvm.ptr
    cf.br ^bb258
    ^bb258:
    %1976 = llvm.load %1975 : !llvm.ptr -> i32
    %1977 = arith.constant 1 : i32
    %1978 = arith.subi %1972, %1977 : i32
    %1979 = arith.cmpi slt, %1976, %1978 : i32
    cf.cond_br %1979, ^bb259, ^bb260
    ^bb259:
      %1980 = llvm.load %1975 : !llvm.ptr -> i32
      %1981 = arith.constant 1 : i32
      %1982 = arith.addi %1980, %1981 : i32
      %1983 = llvm.mlir.constant(1 : i64) : i64
      %1984 = llvm.alloca %1983 x i32 : (i64) -> !llvm.ptr
      llvm.store %1982, %1984 : i32, !llvm.ptr
      cf.br ^bb261
      ^bb261:
      %1985 = llvm.load %1984 : !llvm.ptr -> i32
      %1986 = arith.cmpi slt, %1985, %1972 : i32
      cf.cond_br %1986, ^bb262, ^bb263
      ^bb262:
        %1988 = llvm.load %1984 : !llvm.ptr -> i32
        %1989 = arith.extsi %1988 : i32 to i64
        %1990 = llvm.getelementptr %arg1[%1989] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %1987 = llvm.load %1990 : !llvm.ptr -> i64
        %1992 = llvm.load %1975 : !llvm.ptr -> i32
        %1993 = arith.extsi %1992 : i32 to i64
        %1994 = llvm.getelementptr %arg1[%1993] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %1991 = llvm.load %1994 : !llvm.ptr -> i64
        %1995 = arith.cmpi slt, %1987, %1991 : i64
        cf.cond_br %1995, ^bb264, ^bb265
        ^bb264:
          %1997 = llvm.load %1975 : !llvm.ptr -> i32
          %1998 = arith.extsi %1997 : i32 to i64
          %1999 = llvm.getelementptr %arg1[%1998] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %1996 = llvm.load %1999 : !llvm.ptr -> i64
          %2001 = llvm.load %1984 : !llvm.ptr -> i32
          %2002 = arith.extsi %2001 : i32 to i64
          %2003 = llvm.getelementptr %arg1[%2002] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %2000 = llvm.load %2003 : !llvm.ptr -> i64
          %2004 = llvm.load %1975 : !llvm.ptr -> i32
          %2005 = arith.extsi %2004 : i32 to i64
          %2006 = llvm.getelementptr %arg1[%2005] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %2000, %2006 : i64, !llvm.ptr
          %2007 = llvm.load %1984 : !llvm.ptr -> i32
          %2008 = arith.extsi %2007 : i32 to i64
          %2009 = llvm.getelementptr %arg1[%2008] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %1996, %2009 : i64, !llvm.ptr
          cf.br ^bb266
        ^bb265:
          cf.br ^bb266
        ^bb266:
        %2010 = llvm.load %1984 : !llvm.ptr -> i32
        %2011 = arith.constant 1 : i32
        %2012 = arith.addi %2010, %2011 : i32
        llvm.store %2012, %1984 : i32, !llvm.ptr
        cf.br ^bb261
      ^bb263:
      %2013 = llvm.load %1975 : !llvm.ptr -> i32
      %2014 = arith.constant 1 : i32
      %2015 = arith.addi %2013, %2014 : i32
      llvm.store %2015, %1975 : i32, !llvm.ptr
      cf.br ^bb258
    ^bb260:
    %2016 = arith.constant 0 : i32
    llvm.store %2016, %1975 : i32, !llvm.ptr
    cf.br ^bb267
    ^bb267:
    %2017 = llvm.load %1975 : !llvm.ptr -> i32
    %2018 = arith.cmpi slt, %2017, %1972 : i32
    cf.cond_br %2018, ^bb268, ^bb269
    ^bb268:
      %2020 = llvm.load %1975 : !llvm.ptr -> i32
      %2021 = arith.extsi %2020 : i32 to i64
      %2022 = llvm.getelementptr %arg1[%2021] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %2019 = llvm.load %2022 : !llvm.ptr -> i64
      %2024 = llvm.mlir.addressof @mersenne_cache : !llvm.ptr
      %2025 = llvm.load %2024 : !llvm.ptr -> !llvm.ptr
      %2026 = arith.extsi %arg0 : i32 to i64
      %2027 = llvm.getelementptr %2025[%2026] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %2023 = llvm.load %2027 : !llvm.ptr -> !llvm.ptr
      %2028 = llvm.load %1975 : !llvm.ptr -> i32
      %2029 = arith.extsi %2028 : i32 to i64
      %2030 = llvm.getelementptr %2023[%2029] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %2019, %2030 : i64, !llvm.ptr
      %2031 = llvm.load %1975 : !llvm.ptr -> i32
      %2032 = arith.constant 1 : i32
      %2033 = arith.addi %2031, %2032 : i32
      llvm.store %2033, %1975 : i32, !llvm.ptr
      cf.br ^bb267
    ^bb269:
    %2034 = llvm.mlir.addressof @mersenne_cache_count : !llvm.ptr
    %2035 = llvm.load %2034 : !llvm.ptr -> !llvm.ptr
    %2036 = arith.extsi %arg0 : i32 to i64
    %2037 = llvm.getelementptr %2035[%2036] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %1972, %2037 : i32, !llvm.ptr
    %2038 = arith.constant 1 : i32
    %2039 = llvm.mlir.addressof @mersenne_cache_done : !llvm.ptr
    %2040 = llvm.load %2039 : !llvm.ptr -> !llvm.ptr
    %2041 = arith.trunci %2038 : i32 to i8
    %2042 = arith.extsi %arg0 : i32 to i64
    %2043 = llvm.getelementptr %2040[%2042] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %2041, %2043 : i8, !llvm.ptr
    func.return %1972 : i32
  }
  func.func @multiplicative_order(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> i64 {
    %2044 = func.call @poly_is_zero(%arg0) : (!llvm.ptr) -> i1
    cf.cond_br %2044, ^bb270, ^bb271
    ^bb270:
      %2045 = arith.constant 0 : i32
      %2046 = arith.extsi %2045 : i32 to i64
      func.return %2046 : i64
    ^bb271:
      cf.br ^bb272
    ^bb272:
    %2047 = func.call @frobenius_orbit_degree(%arg0, %arg1) : (!llvm.ptr, !llvm.ptr) -> i32
    %2048 = arith.constant 1 : i32
    %2049 = arith.extsi %2048 : i32 to i64
    %2051 = arith.extsi %2047 : i32 to i64
    %2050 = arith.shli %2049, %2051 : i64
    %2052 = arith.constant 1 : i32
    %2054 = arith.extsi %2052 : i32 to i64
    %2053 = arith.subi %2050, %2054 : i64
    %2055 = arith.constant 1 : i32
    %2057 = arith.extsi %2055 : i32 to i64
    %2056 = arith.cmpi eq, %2053, %2057 : i64
    cf.cond_br %2056, ^bb273, ^bb274
    ^bb273:
      %2058 = arith.constant 1 : i32
      %2059 = arith.extsi %2058 : i32 to i64
      func.return %2059 : i64
    ^bb274:
      cf.br ^bb275
    ^bb275:
    %2060 = llvm.mlir.constant(1 : i64) : i64
    %2061 = llvm.alloca %2060 x i64 : (i64) -> !llvm.ptr
    llvm.store %2053, %2061 : i64, !llvm.ptr
    %2063 = arith.constant 64 : i32
    %2064 = arith.constant 8 : i32
    %2065 = arith.extsi %2063 : i32 to i64
    %2066 = arith.extsi %2064 : i32 to i64
    %2062 = func.call @calloc(%2065, %2066) : (i64, i64) -> !llvm.ptr
    %2067 = func.call @mersenne_factors(%2047, %2062) : (i32, !llvm.ptr) -> i32
    %2069 = arith.constant 64 : i32
    %2070 = arith.constant 8 : i32
    %2071 = arith.extsi %2069 : i32 to i64
    %2072 = arith.extsi %2070 : i32 to i64
    %2068 = func.call @calloc(%2071, %2072) : (i64, i64) -> !llvm.ptr
    %2073 = arith.constant 0 : i32
    %2074 = llvm.mlir.constant(1 : i64) : i64
    %2075 = llvm.alloca %2074 x i32 : (i64) -> !llvm.ptr
    llvm.store %2073, %2075 : i32, !llvm.ptr
    %2076 = arith.constant 0 : i32
    %2077 = llvm.mlir.constant(1 : i64) : i64
    %2078 = llvm.alloca %2077 x i32 : (i64) -> !llvm.ptr
    llvm.store %2076, %2078 : i32, !llvm.ptr
    cf.br ^bb276
    ^bb276:
    %2079 = llvm.load %2078 : !llvm.ptr -> i32
    %2080 = arith.cmpi slt, %2079, %2067 : i32
    cf.cond_br %2080, ^bb277, ^bb278
    ^bb277:
      %2081 = llvm.load %2078 : !llvm.ptr -> i32
      %2082 = arith.constant 0 : i32
      %2083 = arith.cmpi eq, %2081, %2082 : i32
      %2084 = scf.if %2083 -> (i1) {
        %2085 = arith.constant true
        scf.yield %2085 : i1
      } else {
        %2087 = llvm.load %2078 : !llvm.ptr -> i32
        %2088 = arith.extsi %2087 : i32 to i64
        %2089 = llvm.getelementptr %2062[%2088] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %2086 = llvm.load %2089 : !llvm.ptr -> i64
        %2091 = llvm.load %2078 : !llvm.ptr -> i32
        %2092 = arith.constant 1 : i32
        %2093 = arith.subi %2091, %2092 : i32
        %2094 = arith.extsi %2093 : i32 to i64
        %2095 = llvm.getelementptr %2062[%2094] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %2090 = llvm.load %2095 : !llvm.ptr -> i64
        %2096 = arith.cmpi ne, %2086, %2090 : i64
        scf.yield %2096 : i1
      }
      cf.cond_br %2084, ^bb279, ^bb280
      ^bb279:
        %2098 = llvm.load %2078 : !llvm.ptr -> i32
        %2099 = arith.extsi %2098 : i32 to i64
        %2100 = llvm.getelementptr %2062[%2099] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %2097 = llvm.load %2100 : !llvm.ptr -> i64
        %2101 = llvm.load %2075 : !llvm.ptr -> i32
        %2102 = arith.extsi %2101 : i32 to i64
        %2103 = llvm.getelementptr %2068[%2102] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %2097, %2103 : i64, !llvm.ptr
        %2104 = llvm.load %2075 : !llvm.ptr -> i32
        %2105 = arith.constant 1 : i32
        %2106 = arith.addi %2104, %2105 : i32
        llvm.store %2106, %2075 : i32, !llvm.ptr
        cf.br ^bb281
      ^bb280:
        cf.br ^bb281
      ^bb281:
      %2107 = llvm.load %2078 : !llvm.ptr -> i32
      %2108 = arith.constant 1 : i32
      %2109 = arith.addi %2107, %2108 : i32
      llvm.store %2109, %2078 : i32, !llvm.ptr
      cf.br ^bb276
    ^bb278:
    %2111 = arith.constant 1 : i32
    %2112 = arith.constant 32 : i32
    %2113 = arith.extsi %2111 : i32 to i64
    %2114 = arith.extsi %2112 : i32 to i64
    %2110 = func.call @calloc(%2113, %2114) : (i64, i64) -> !llvm.ptr
    %2115 = arith.constant 0 : i32
    llvm.store %2115, %2078 : i32, !llvm.ptr
    cf.br ^bb282
    ^bb282:
    %2116 = llvm.load %2078 : !llvm.ptr -> i32
    %2117 = llvm.load %2075 : !llvm.ptr -> i32
    %2118 = arith.cmpi slt, %2116, %2117 : i32
    cf.cond_br %2118, ^bb283, ^bb284
    ^bb283:
      %2120 = llvm.load %2078 : !llvm.ptr -> i32
      %2121 = arith.extsi %2120 : i32 to i64
      %2122 = llvm.getelementptr %2068[%2121] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %2119 = llvm.load %2122 : !llvm.ptr -> i64
      cf.br ^bb285
      ^bb285:
      %2123 = llvm.load %2061 : !llvm.ptr -> i64
      %2124 = arith.remsi %2123, %2119 : i64
      %2125 = arith.constant 0 : i32
      %2127 = arith.extsi %2125 : i32 to i64
      %2126 = arith.cmpi eq, %2124, %2127 : i64
      cf.cond_br %2126, ^bb286, ^bb287
      ^bb286:
        %2128 = llvm.load %2061 : !llvm.ptr -> i64
        %2129 = arith.divsi %2128, %2119 : i64
        func.call @poly_pow_mod(%2110, %arg0, %2129, %arg1) : (!llvm.ptr, !llvm.ptr, i64, !llvm.ptr) -> ()
        %2131 = func.call @poly_is_one(%2110) : (!llvm.ptr) -> i1
        cf.cond_br %2131, ^bb288, ^bb289
        ^bb288:
          llvm.store %2129, %2061 : i64, !llvm.ptr
          cf.br ^bb290
        ^bb289:
          cf.br ^bb287
        ^bb290:
        cf.br ^bb285
      ^bb287:
      %2132 = llvm.load %2078 : !llvm.ptr -> i32
      %2133 = arith.constant 1 : i32
      %2134 = arith.addi %2132, %2133 : i32
      llvm.store %2134, %2078 : i32, !llvm.ptr
      cf.br ^bb282
    ^bb284:
    func.call @free(%2062) : (!llvm.ptr) -> ()
    func.call @free(%2068) : (!llvm.ptr) -> ()
    func.call @free(%2110) : (!llvm.ptr) -> ()
    %2138 = llvm.load %2061 : !llvm.ptr -> i64
    func.return %2138 : i64
  }
  func.func @max_two_lift_exponent(%arg0: !llvm.ptr, %arg1: i64, %arg2: !llvm.ptr, %arg3: i32) -> i32 {
    %2139 = arith.constant 1 : i32
    %2140 = arith.cmpi sle, %arg3, %2139 : i32
    cf.cond_br %2140, ^bb291, ^bb292
    ^bb291:
      %2141 = arith.constant 0 : i32
      func.return %2141 : i32
    ^bb292:
      cf.br ^bb293
    ^bb293:
    %2142 = llvm.mlir.constant(1 : i64) : i64
    %2143 = llvm.alloca %2142 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %2143 : i64, !llvm.ptr
    %2145 = arith.constant 1 : i32
    %2146 = arith.constant 32 : i32
    %2147 = arith.extsi %2145 : i32 to i64
    %2148 = arith.extsi %2146 : i32 to i64
    %2144 = func.call @calloc(%2147, %2148) : (i64, i64) -> !llvm.ptr
    %2150 = arith.constant 1 : i32
    %2151 = arith.constant 32 : i32
    %2152 = arith.extsi %2150 : i32 to i64
    %2153 = arith.extsi %2151 : i32 to i64
    %2149 = func.call @calloc(%2152, %2153) : (i64, i64) -> !llvm.ptr
    %2155 = arith.constant 1 : i32
    %2156 = arith.constant 32 : i32
    %2157 = arith.extsi %2155 : i32 to i64
    %2158 = arith.extsi %2156 : i32 to i64
    %2154 = func.call @calloc(%2157, %2158) : (i64, i64) -> !llvm.ptr
    func.call @poly_copy(%2144, %arg2) : (!llvm.ptr, !llvm.ptr) -> ()
    %2160 = arith.constant 2 : i32
    %2161 = llvm.mlir.constant(1 : i64) : i64
    %2162 = llvm.alloca %2161 x i32 : (i64) -> !llvm.ptr
    llvm.store %2160, %2162 : i32, !llvm.ptr
    cf.br ^bb294
    ^bb294:
    %2163 = llvm.load %2162 : !llvm.ptr -> i32
    %2164 = arith.cmpi sle, %2163, %arg3 : i32
    cf.cond_br %2164, ^bb295, ^bb296
    ^bb295:
      func.call @poly_mul(%2149, %2144, %arg2) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      func.call @poly_copy(%2144, %2149) : (!llvm.ptr, !llvm.ptr) -> ()
      %2168 = llvm.load %2143 : !llvm.ptr -> i64
      func.call @poly_pow_mod(%2154, %arg0, %2168, %2144) : (!llvm.ptr, !llvm.ptr, i64, !llvm.ptr) -> ()
      cf.br ^bb297
      ^bb297:
      %2169 = func.call @poly_is_one(%2154) : (!llvm.ptr) -> i1
      %2171 = arith.constant 1 : i1
      %2170 = arith.xori %2169, %2171 : i1
      cf.cond_br %2170, ^bb298, ^bb299
      ^bb298:
        %2173 = llvm.load %2143 : !llvm.ptr -> i64
        %2174 = arith.constant 2 : i32
        %2176 = arith.extsi %2174 : i32 to i64
        %2175 = arith.muli %2173, %2176 : i64
        llvm.store %2175, %2143 : i64, !llvm.ptr
        %2178 = llvm.load %2143 : !llvm.ptr -> i64
        func.call @poly_pow_mod(%2154, %arg0, %2178, %2144) : (!llvm.ptr, !llvm.ptr, i64, !llvm.ptr) -> ()
        cf.br ^bb297
      ^bb299:
      %2179 = llvm.load %2162 : !llvm.ptr -> i32
      %2180 = arith.constant 1 : i32
      %2181 = arith.addi %2179, %2180 : i32
      llvm.store %2181, %2162 : i32, !llvm.ptr
      cf.br ^bb294
    ^bb296:
    %2182 = llvm.load %2143 : !llvm.ptr -> i64
    %2183 = arith.divsi %2182, %arg1 : i64
    %2184 = arith.constant 0 : i32
    %2185 = llvm.mlir.constant(1 : i64) : i64
    %2186 = llvm.alloca %2185 x i32 : (i64) -> !llvm.ptr
    llvm.store %2184, %2186 : i32, !llvm.ptr
    cf.br ^bb300(%2183 : i64)
    ^bb300(%2187: i64):
    %2188 = arith.constant 1 : i32
    %2190 = arith.extsi %2188 : i32 to i64
    %2189 = arith.cmpi sgt, %2187, %2190 : i64
    cf.cond_br %2189, ^bb301(%2187 : i64), ^bb302(%2187 : i64)
    ^bb301(%2191: i64):
      %2192 = arith.constant 1 : i32
      %2194 = arith.extsi %2192 : i32 to i64
      %2193 = arith.shrsi %2191, %2194 : i64
      %2195 = llvm.load %2186 : !llvm.ptr -> i32
      %2196 = arith.constant 1 : i32
      %2197 = arith.addi %2195, %2196 : i32
      llvm.store %2197, %2186 : i32, !llvm.ptr
      cf.br ^bb300(%2193 : i64)
    ^bb302(%2198: i64):
    func.call @free(%2144) : (!llvm.ptr) -> ()
    func.call @free(%2149) : (!llvm.ptr) -> ()
    func.call @free(%2154) : (!llvm.ptr) -> ()
    %2202 = llvm.load %2186 : !llvm.ptr -> i32
    func.return %2202 : i32
  }
  func.func @igcd(%arg0: i64, %arg1: i64) -> i64 {
    %2203 = llvm.mlir.constant(1 : i64) : i64
    %2204 = llvm.alloca %2203 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %2204 : i64, !llvm.ptr
    %2205 = llvm.mlir.constant(1 : i64) : i64
    %2206 = llvm.alloca %2205 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %2206 : i64, !llvm.ptr
    cf.br ^bb303
    ^bb303:
    %2207 = llvm.load %2206 : !llvm.ptr -> i64
    %2208 = arith.constant 0 : i32
    %2210 = arith.extsi %2208 : i32 to i64
    %2209 = arith.cmpi ne, %2207, %2210 : i64
    cf.cond_br %2209, ^bb304, ^bb305
    ^bb304:
      %2211 = llvm.load %2204 : !llvm.ptr -> i64
      %2212 = llvm.load %2206 : !llvm.ptr -> i64
      %2213 = arith.remsi %2211, %2212 : i64
      %2214 = llvm.load %2206 : !llvm.ptr -> i64
      llvm.store %2214, %2204 : i64, !llvm.ptr
      llvm.store %2213, %2206 : i64, !llvm.ptr
      cf.br ^bb303
    ^bb305:
    %2215 = llvm.load %2204 : !llvm.ptr -> i64
    func.return %2215 : i64
  }
  func.func @ilcm(%arg0: i64, %arg1: i64) -> i64 {
    %2216 = arith.constant 0 : i32
    %2218 = arith.extsi %2216 : i32 to i64
    %2217 = arith.cmpi eq, %arg0, %2218 : i64
    %2219 = scf.if %2217 -> (i1) {
      %2220 = arith.constant true
      scf.yield %2220 : i1
    } else {
      %2221 = arith.constant 0 : i32
      %2223 = arith.extsi %2221 : i32 to i64
      %2222 = arith.cmpi eq, %arg1, %2223 : i64
      scf.yield %2222 : i1
    }
    cf.cond_br %2219, ^bb306, ^bb307
    ^bb306:
      %2224 = arith.constant 0 : i32
      %2225 = arith.extsi %2224 : i32 to i64
      func.return %2225 : i64
    ^bb307:
      cf.br ^bb308
    ^bb308:
    %2226 = func.call @igcd(%arg0, %arg1) : (i64, i64) -> i64
    %2227 = arith.divsi %arg0, %2226 : i64
    %2228 = arith.extsi %2227 : i64 to i128
    %2229 = arith.extsi %arg1 : i64 to i128
    %2231 = arith.trunci %2228 : i128 to i64
    %2232 = arith.trunci %2229 : i128 to i64
    %2230 = arith.muli %2231, %2232 : i64
    %2233 = arith.extsi %2230 : i64 to i128
    %2234 = arith.trunci %2233 : i128 to i64
    func.return %2234 : i64
  }
  // Struct: DPEntry
  // Fields:
  //   odd_lcm: i64
  //   smax: i32
  // Module static: periods_set
  llvm.mlir.global internal @periods_set() {addr_space = 0 : i32} : !llvm.ptr {
    %2235 = llvm.mlir.zero : !llvm.ptr
    llvm.return %2235 : !llvm.ptr
  }
  // Module static: periods_set_count
  llvm.mlir.global internal @periods_set_count(0 : i32) : i32
  func.func @periods_insert(%arg0: i64) -> () {
    %2236 = arith.constant 0 : i32
    %2237 = llvm.mlir.constant(1 : i64) : i64
    %2238 = llvm.alloca %2237 x i32 : (i64) -> !llvm.ptr
    llvm.store %2236, %2238 : i32, !llvm.ptr
    cf.br ^bb309
    ^bb309:
    %2239 = llvm.load %2238 : !llvm.ptr -> i32
    %2240 = llvm.mlir.addressof @periods_set_count : !llvm.ptr
    %2241 = llvm.load %2240 : !llvm.ptr -> i32
    %2242 = arith.cmpi slt, %2239, %2241 : i32
    cf.cond_br %2242, ^bb310, ^bb311
    ^bb310:
      %2244 = llvm.mlir.addressof @periods_set : !llvm.ptr
      %2245 = llvm.load %2244 : !llvm.ptr -> !llvm.ptr
      %2246 = llvm.load %2238 : !llvm.ptr -> i32
      %2247 = arith.extsi %2246 : i32 to i64
      %2248 = llvm.getelementptr %2245[%2247] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %2243 = llvm.load %2248 : !llvm.ptr -> i64
      %2249 = arith.cmpi eq, %2243, %arg0 : i64
      cf.cond_br %2249, ^bb312, ^bb313
      ^bb312:
        func.return
      ^bb313:
        cf.br ^bb314
      ^bb314:
      %2250 = llvm.load %2238 : !llvm.ptr -> i32
      %2251 = arith.constant 1 : i32
      %2252 = arith.addi %2250, %2251 : i32
      llvm.store %2252, %2238 : i32, !llvm.ptr
      cf.br ^bb309
    ^bb311:
    %2253 = llvm.mlir.addressof @periods_set : !llvm.ptr
    %2254 = llvm.load %2253 : !llvm.ptr -> !llvm.ptr
    %2255 = llvm.mlir.addressof @periods_set_count : !llvm.ptr
    %2256 = llvm.load %2255 : !llvm.ptr -> i32
    %2257 = arith.extsi %2256 : i32 to i64
    %2258 = llvm.getelementptr %2254[%2257] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %arg0, %2258 : i64, !llvm.ptr
    %2259 = llvm.mlir.addressof @periods_set_count : !llvm.ptr
    %2260 = llvm.load %2259 : !llvm.ptr -> i32
    %2261 = arith.constant 1 : i32
    %2262 = arith.addi %2260, %2261 : i32
    %2263 = llvm.mlir.addressof @periods_set_count : !llvm.ptr
    llvm.store %2262, %2263 : i32, !llvm.ptr
    func.return
  }
  func.func @periods_for_n(%arg0: i32, %arg1: !llvm.ptr, %arg2: !llvm.ptr) -> () {
    %2264 = llvm.mlir.constant(1 : i64) : i64
    %2265 = llvm.alloca %2264 x i32 : (i64) -> !llvm.ptr
    llvm.store %arg0, %2265 : i32, !llvm.ptr
    %2266 = arith.constant 0 : i32
    %2267 = llvm.mlir.constant(1 : i64) : i64
    %2268 = llvm.alloca %2267 x i32 : (i64) -> !llvm.ptr
    llvm.store %2266, %2268 : i32, !llvm.ptr
    cf.br ^bb315
    ^bb315:
    %2269 = llvm.load %2265 : !llvm.ptr -> i32
    %2270 = arith.constant 2 : i32
    %2271 = arith.remsi %2269, %2270 : i32
    %2272 = arith.constant 0 : i32
    %2273 = arith.cmpi eq, %2271, %2272 : i32
    cf.cond_br %2273, ^bb316, ^bb317
    ^bb316:
      %2274 = llvm.load %2265 : !llvm.ptr -> i32
      %2275 = arith.constant 2 : i32
      %2276 = arith.divsi %2274, %2275 : i32
      llvm.store %2276, %2265 : i32, !llvm.ptr
      %2277 = llvm.load %2268 : !llvm.ptr -> i32
      %2278 = arith.constant 1 : i32
      %2279 = arith.addi %2277, %2278 : i32
      llvm.store %2279, %2268 : i32, !llvm.ptr
      cf.br ^bb315
    ^bb317:
    %2280 = arith.constant 1 : i32
    %2281 = llvm.load %2268 : !llvm.ptr -> i32
    %2282 = arith.shli %2280, %2281 : i32
    %2284 = arith.constant 1 : i32
    %2285 = arith.constant 32 : i32
    %2286 = arith.extsi %2284 : i32 to i64
    %2287 = arith.extsi %2285 : i32 to i64
    %2283 = func.call @calloc(%2286, %2287) : (i64, i64) -> !llvm.ptr
    func.call @poly_zero(%2283) : (!llvm.ptr) -> ()
    %2290 = arith.constant 1 : i32
    func.call @poly_set_bit(%2283, %2290) : (!llvm.ptr, i32) -> ()
    %2292 = arith.constant 1 : i32
    %2293 = arith.subi %arg0, %2292 : i32
    func.call @poly_set_bit(%2283, %2293) : (!llvm.ptr, i32) -> ()
    %2295 = arith.constant 128 : i32
    %2296 = arith.constant 32 : i32
    %2297 = arith.extsi %2295 : i32 to i64
    %2298 = arith.extsi %2296 : i32 to i64
    %2294 = func.call @calloc(%2297, %2298) : (i64, i64) -> !llvm.ptr
    %2300 = llvm.load %2265 : !llvm.ptr -> i32
    %2299 = func.call @irreducible_factors_xm_plus_1(%2300, %2294) : (i32, !llvm.ptr) -> i32
    %2302 = arith.constant 8192 : i32
    %2303 = arith.constant 16 : i32
    %2304 = arith.extsi %2302 : i32 to i64
    %2305 = arith.extsi %2303 : i32 to i64
    %2301 = func.call @calloc(%2304, %2305) : (i64, i64) -> !llvm.ptr
    %2306 = arith.constant 1 : i32
    %2307 = llvm.mlir.constant(1 : i64) : i64
    %2308 = llvm.alloca %2307 x i32 : (i64) -> !llvm.ptr
    llvm.store %2306, %2308 : i32, !llvm.ptr
    %2309 = arith.constant 1 : i32
    %2310 = arith.constant 0 : i32
    %2311 = arith.extsi %2310 : i32 to i64
    %2312 = llvm.getelementptr %2301[%2311] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
    %2313 = arith.extsi %2309 : i32 to i64
    %2314 = llvm.getelementptr %2312[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
    llvm.store %2313, %2314 : i64, !llvm.ptr
    %2315 = arith.constant 0 : i32
    %2316 = arith.constant 0 : i32
    %2317 = arith.extsi %2316 : i32 to i64
    %2318 = llvm.getelementptr %2301[%2317] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
    %2319 = llvm.getelementptr %2318[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
    llvm.store %2315, %2319 : i32, !llvm.ptr
    %2321 = arith.constant 1 : i32
    %2322 = arith.constant 32 : i32
    %2323 = arith.extsi %2321 : i32 to i64
    %2324 = arith.extsi %2322 : i32 to i64
    %2320 = func.call @calloc(%2323, %2324) : (i64, i64) -> !llvm.ptr
    %2326 = arith.constant 1 : i32
    %2327 = arith.constant 32 : i32
    %2328 = arith.extsi %2326 : i32 to i64
    %2329 = arith.extsi %2327 : i32 to i64
    %2325 = func.call @calloc(%2328, %2329) : (i64, i64) -> !llvm.ptr
    %2330 = arith.constant 0 : i32
    %2331 = llvm.mlir.constant(1 : i64) : i64
    %2332 = llvm.alloca %2331 x i32 : (i64) -> !llvm.ptr
    llvm.store %2330, %2332 : i32, !llvm.ptr
    cf.br ^bb318
    ^bb318:
    %2333 = llvm.load %2332 : !llvm.ptr -> i32
    %2334 = arith.cmpi slt, %2333, %2299 : i32
    cf.cond_br %2334, ^bb319, ^bb320
    ^bb319:
      %2335 = llvm.load %2332 : !llvm.ptr -> i32
      %2336 = arith.extsi %2335 : i32 to i64
      %2337 = llvm.getelementptr %2294[%2336] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i64, i64, i64)>
      func.call @poly_mod(%2320, %2283, %2337) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      func.call @poly_gcd(%2325, %2320, %2337) : (!llvm.ptr, !llvm.ptr, !llvm.ptr) -> ()
      %2340 = func.call @poly_deg(%2325) : (!llvm.ptr) -> i32
      %2341 = arith.constant 0 : i32
      %2342 = arith.cmpi sgt, %2340, %2341 : i32
      cf.cond_br %2342, ^bb321, ^bb322
      ^bb321:
        %2343 = llvm.load %2332 : !llvm.ptr -> i32
        %2344 = arith.constant 1 : i32
        %2345 = arith.addi %2343, %2344 : i32
        llvm.store %2345, %2332 : i32, !llvm.ptr
        cf.br ^bb318
      ^bb322:
        cf.br ^bb323
      ^bb323:
      %2346 = func.call @multiplicative_order(%2320, %2337) : (!llvm.ptr, !llvm.ptr) -> i64
      %2347 = func.call @max_two_lift_exponent(%2283, %2346, %2337, %2282) : (!llvm.ptr, i64, !llvm.ptr, i32) -> i32
      %2349 = arith.constant 8192 : i32
      %2350 = arith.constant 16 : i32
      %2351 = arith.extsi %2349 : i32 to i64
      %2352 = arith.extsi %2350 : i32 to i64
      %2348 = func.call @calloc(%2351, %2352) : (i64, i64) -> !llvm.ptr
      %2353 = arith.constant 0 : i32
      %2354 = llvm.mlir.constant(1 : i64) : i64
      %2355 = llvm.alloca %2354 x i32 : (i64) -> !llvm.ptr
      llvm.store %2353, %2355 : i32, !llvm.ptr
      %2356 = arith.constant 0 : i32
      %2357 = llvm.mlir.constant(1 : i64) : i64
      %2358 = llvm.alloca %2357 x i32 : (i64) -> !llvm.ptr
      llvm.store %2356, %2358 : i32, !llvm.ptr
      cf.br ^bb324
      ^bb324:
      %2359 = llvm.load %2358 : !llvm.ptr -> i32
      %2360 = llvm.load %2308 : !llvm.ptr -> i32
      %2361 = arith.cmpi slt, %2359, %2360 : i32
      cf.cond_br %2361, ^bb325, ^bb326
      ^bb325:
        %2363 = llvm.load %2358 : !llvm.ptr -> i32
        %2364 = arith.extsi %2363 : i32 to i64
        %2365 = llvm.getelementptr %2301[%2364] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2362 = llvm.load %2365 : !llvm.ptr -> !llvm.struct<(i64, i32)>
        %2366 = llvm.load %2355 : !llvm.ptr -> i32
        %2367 = arith.extsi %2366 : i32 to i64
        %2368 = llvm.getelementptr %2348[%2367] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        llvm.store %2362, %2368 : !llvm.struct<(i64, i32)>, !llvm.ptr
        %2369 = llvm.load %2355 : !llvm.ptr -> i32
        %2370 = arith.constant 1 : i32
        %2371 = arith.addi %2369, %2370 : i32
        llvm.store %2371, %2355 : i32, !llvm.ptr
        %2372 = llvm.load %2358 : !llvm.ptr -> i32
        %2373 = arith.constant 1 : i32
        %2374 = arith.addi %2372, %2373 : i32
        llvm.store %2374, %2358 : i32, !llvm.ptr
        cf.br ^bb324
      ^bb326:
      %2375 = arith.constant 0 : i32
      llvm.store %2375, %2358 : i32, !llvm.ptr
      cf.br ^bb327
      ^bb327:
      %2376 = llvm.load %2358 : !llvm.ptr -> i32
      %2377 = llvm.load %2308 : !llvm.ptr -> i32
      %2378 = arith.cmpi slt, %2376, %2377 : i32
      cf.cond_br %2378, ^bb328, ^bb329
      ^bb328:
        %2381 = llvm.load %2358 : !llvm.ptr -> i32
        %2382 = arith.extsi %2381 : i32 to i64
        %2383 = llvm.getelementptr %2301[%2382] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2380 = llvm.load %2383 : !llvm.ptr -> !llvm.struct<(i64, i32)>
        %2384 = llvm.load %2358 : !llvm.ptr -> i32
        %2385 = arith.extsi %2384 : i32 to i64
        %2386 = llvm.getelementptr %2301[%2385] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2387 = llvm.getelementptr %2386[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2388 = llvm.load %2387 : !llvm.ptr -> i64
        %2379 = func.call @ilcm(%2388, %2346) : (i64, i64) -> i64
        %2390 = llvm.load %2358 : !llvm.ptr -> i32
        %2391 = arith.extsi %2390 : i32 to i64
        %2392 = llvm.getelementptr %2301[%2391] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2389 = llvm.load %2392 : !llvm.ptr -> !llvm.struct<(i64, i32)>
        %2393 = llvm.load %2358 : !llvm.ptr -> i32
        %2394 = arith.extsi %2393 : i32 to i64
        %2395 = llvm.getelementptr %2301[%2394] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2396 = llvm.getelementptr %2395[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2397 = llvm.load %2396 : !llvm.ptr -> i32
        %2398 = llvm.mlir.constant(1 : i64) : i64
        %2399 = llvm.alloca %2398 x i32 : (i64) -> !llvm.ptr
        llvm.store %2397, %2399 : i32, !llvm.ptr
        %2400 = llvm.load %2399 : !llvm.ptr -> i32
        %2401 = arith.cmpi sgt, %2347, %2400 : i32
        cf.cond_br %2401, ^bb330, ^bb331
        ^bb330:
          llvm.store %2347, %2399 : i32, !llvm.ptr
          cf.br ^bb332
        ^bb331:
          cf.br ^bb332
        ^bb332:
        %2402 = arith.constant 0 : i1
        %2403 = llvm.mlir.constant(1 : i64) : i64
        %2404 = llvm.alloca %2403 x i1 : (i64) -> !llvm.ptr
        llvm.store %2402, %2404 : i1, !llvm.ptr
        %2405 = arith.constant 0 : i32
        %2406 = llvm.mlir.constant(1 : i64) : i64
        %2407 = llvm.alloca %2406 x i32 : (i64) -> !llvm.ptr
        llvm.store %2405, %2407 : i32, !llvm.ptr
        cf.br ^bb333
        ^bb333:
        %2408 = llvm.load %2407 : !llvm.ptr -> i32
        %2409 = llvm.load %2355 : !llvm.ptr -> i32
        %2410 = arith.cmpi slt, %2408, %2409 : i32
        cf.cond_br %2410, ^bb334, ^bb335
        ^bb334:
          %2412 = llvm.load %2407 : !llvm.ptr -> i32
          %2413 = arith.extsi %2412 : i32 to i64
          %2414 = llvm.getelementptr %2348[%2413] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          %2411 = llvm.load %2414 : !llvm.ptr -> !llvm.struct<(i64, i32)>
          %2415 = llvm.load %2407 : !llvm.ptr -> i32
          %2416 = arith.extsi %2415 : i32 to i64
          %2417 = llvm.getelementptr %2348[%2416] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          %2418 = llvm.getelementptr %2417[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          %2419 = llvm.load %2418 : !llvm.ptr -> i64
          %2420 = arith.cmpi eq, %2419, %2379 : i64
          cf.cond_br %2420, ^bb336, ^bb337
          ^bb336:
            %2421 = llvm.load %2399 : !llvm.ptr -> i32
            %2423 = llvm.load %2407 : !llvm.ptr -> i32
            %2424 = arith.extsi %2423 : i32 to i64
            %2425 = llvm.getelementptr %2348[%2424] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
            %2422 = llvm.load %2425 : !llvm.ptr -> !llvm.struct<(i64, i32)>
            %2426 = llvm.load %2407 : !llvm.ptr -> i32
            %2427 = arith.extsi %2426 : i32 to i64
            %2428 = llvm.getelementptr %2348[%2427] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
            %2429 = llvm.getelementptr %2428[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
            %2430 = llvm.load %2429 : !llvm.ptr -> i32
            %2431 = arith.cmpi sgt, %2421, %2430 : i32
            cf.cond_br %2431, ^bb339, ^bb340
            ^bb339:
              %2432 = llvm.load %2399 : !llvm.ptr -> i32
              %2433 = llvm.load %2407 : !llvm.ptr -> i32
              %2434 = arith.extsi %2433 : i32 to i64
              %2435 = llvm.getelementptr %2348[%2434] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
              %2436 = llvm.getelementptr %2435[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
              llvm.store %2432, %2436 : i32, !llvm.ptr
              cf.br ^bb341
            ^bb340:
              cf.br ^bb341
            ^bb341:
            %2437 = arith.constant 1 : i1
            llvm.store %2437, %2404 : i1, !llvm.ptr
            cf.br ^bb335
          ^bb337:
            cf.br ^bb338
          ^bb338:
          %2438 = llvm.load %2407 : !llvm.ptr -> i32
          %2439 = arith.constant 1 : i32
          %2440 = arith.addi %2438, %2439 : i32
          llvm.store %2440, %2407 : i32, !llvm.ptr
          cf.br ^bb333
        ^bb335:
        %2441 = llvm.load %2404 : !llvm.ptr -> i1
        %2443 = arith.constant 1 : i1
        %2442 = arith.xori %2441, %2443 : i1
        cf.cond_br %2442, ^bb342, ^bb343
        ^bb342:
          %2445 = llvm.load %2355 : !llvm.ptr -> i32
          %2446 = arith.extsi %2445 : i32 to i64
          %2447 = llvm.getelementptr %2348[%2446] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          %2448 = llvm.getelementptr %2447[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          llvm.store %2379, %2448 : i64, !llvm.ptr
          %2449 = llvm.load %2399 : !llvm.ptr -> i32
          %2450 = llvm.load %2355 : !llvm.ptr -> i32
          %2451 = arith.extsi %2450 : i32 to i64
          %2452 = llvm.getelementptr %2348[%2451] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          %2453 = llvm.getelementptr %2452[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
          llvm.store %2449, %2453 : i32, !llvm.ptr
          %2454 = llvm.load %2355 : !llvm.ptr -> i32
          %2455 = arith.constant 1 : i32
          %2456 = arith.addi %2454, %2455 : i32
          llvm.store %2456, %2355 : i32, !llvm.ptr
          cf.br ^bb344
        ^bb343:
          cf.br ^bb344
        ^bb344:
        %2457 = llvm.load %2358 : !llvm.ptr -> i32
        %2458 = arith.constant 1 : i32
        %2459 = arith.addi %2457, %2458 : i32
        llvm.store %2459, %2358 : i32, !llvm.ptr
        cf.br ^bb327
      ^bb329:
      %2460 = arith.constant 0 : i32
      %2461 = llvm.mlir.constant(1 : i64) : i64
      %2462 = llvm.alloca %2461 x i32 : (i64) -> !llvm.ptr
      llvm.store %2460, %2462 : i32, !llvm.ptr
      cf.br ^bb345
      ^bb345:
      %2463 = llvm.load %2462 : !llvm.ptr -> i32
      %2464 = llvm.load %2355 : !llvm.ptr -> i32
      %2465 = arith.cmpi slt, %2463, %2464 : i32
      cf.cond_br %2465, ^bb346, ^bb347
      ^bb346:
        %2467 = llvm.load %2462 : !llvm.ptr -> i32
        %2468 = arith.extsi %2467 : i32 to i64
        %2469 = llvm.getelementptr %2348[%2468] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2466 = llvm.load %2469 : !llvm.ptr -> !llvm.struct<(i64, i32)>
        %2470 = llvm.load %2462 : !llvm.ptr -> i32
        %2471 = arith.extsi %2470 : i32 to i64
        %2472 = llvm.getelementptr %2301[%2471] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        llvm.store %2466, %2472 : !llvm.struct<(i64, i32)>, !llvm.ptr
        %2473 = llvm.load %2462 : !llvm.ptr -> i32
        %2474 = arith.constant 1 : i32
        %2475 = arith.addi %2473, %2474 : i32
        llvm.store %2475, %2462 : i32, !llvm.ptr
        cf.br ^bb345
      ^bb347:
      %2476 = llvm.load %2355 : !llvm.ptr -> i32
      llvm.store %2476, %2308 : i32, !llvm.ptr
      func.call @free(%2348) : (!llvm.ptr) -> ()
      %2478 = llvm.load %2332 : !llvm.ptr -> i32
      %2479 = arith.constant 1 : i32
      %2480 = arith.addi %2478, %2479 : i32
      llvm.store %2480, %2332 : i32, !llvm.ptr
      cf.br ^bb318
    ^bb320:
    %2481 = arith.constant 0 : i32
    %2482 = arith.constant 0 : i32
    %2483 = arith.extsi %2482 : i32 to i64
    %2484 = llvm.getelementptr %arg2[%2483] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %2481, %2484 : i32, !llvm.ptr
    %2485 = arith.constant 0 : i32
    %2486 = llvm.mlir.constant(1 : i64) : i64
    %2487 = llvm.alloca %2486 x i32 : (i64) -> !llvm.ptr
    llvm.store %2485, %2487 : i32, !llvm.ptr
    cf.br ^bb348
    ^bb348:
    %2488 = llvm.load %2487 : !llvm.ptr -> i32
    %2489 = llvm.load %2308 : !llvm.ptr -> i32
    %2490 = arith.cmpi slt, %2488, %2489 : i32
    cf.cond_br %2490, ^bb349, ^bb350
    ^bb349:
      %2491 = arith.constant 0 : i32
      %2492 = llvm.mlir.constant(1 : i64) : i64
      %2493 = llvm.alloca %2492 x i32 : (i64) -> !llvm.ptr
      llvm.store %2491, %2493 : i32, !llvm.ptr
      cf.br ^bb351
      ^bb351:
      %2494 = llvm.load %2493 : !llvm.ptr -> i32
      %2496 = llvm.load %2487 : !llvm.ptr -> i32
      %2497 = arith.extsi %2496 : i32 to i64
      %2498 = llvm.getelementptr %2301[%2497] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
      %2495 = llvm.load %2498 : !llvm.ptr -> !llvm.struct<(i64, i32)>
      %2499 = llvm.load %2487 : !llvm.ptr -> i32
      %2500 = arith.extsi %2499 : i32 to i64
      %2501 = llvm.getelementptr %2301[%2500] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
      %2502 = llvm.getelementptr %2501[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
      %2503 = llvm.load %2502 : !llvm.ptr -> i32
      %2504 = arith.cmpi sle, %2494, %2503 : i32
      cf.cond_br %2504, ^bb352, ^bb353
      ^bb352:
        %2506 = llvm.load %2487 : !llvm.ptr -> i32
        %2507 = arith.extsi %2506 : i32 to i64
        %2508 = llvm.getelementptr %2301[%2507] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2505 = llvm.load %2508 : !llvm.ptr -> !llvm.struct<(i64, i32)>
        %2509 = llvm.load %2487 : !llvm.ptr -> i32
        %2510 = arith.extsi %2509 : i32 to i64
        %2511 = llvm.getelementptr %2301[%2510] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2512 = llvm.getelementptr %2511[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i64, i32)>
        %2513 = llvm.load %2512 : !llvm.ptr -> i64
        %2514 = llvm.load %2493 : !llvm.ptr -> i32
        %2516 = arith.extsi %2514 : i32 to i64
        %2515 = arith.shli %2513, %2516 : i64
        %2518 = arith.constant 0 : i32
        %2519 = arith.extsi %2518 : i32 to i64
        %2520 = llvm.getelementptr %arg2[%2519] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %2517 = llvm.load %2520 : !llvm.ptr -> i32
        %2521 = arith.extsi %2517 : i32 to i64
        %2522 = llvm.getelementptr %arg1[%2521] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %2515, %2522 : i64, !llvm.ptr
        %2524 = arith.constant 0 : i32
        %2525 = arith.extsi %2524 : i32 to i64
        %2526 = llvm.getelementptr %arg2[%2525] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %2523 = llvm.load %2526 : !llvm.ptr -> i32
        %2527 = arith.constant 1 : i32
        %2528 = arith.addi %2523, %2527 : i32
        %2529 = arith.constant 0 : i32
        %2530 = arith.extsi %2529 : i32 to i64
        %2531 = llvm.getelementptr %arg2[%2530] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %2528, %2531 : i32, !llvm.ptr
        %2532 = llvm.load %2493 : !llvm.ptr -> i32
        %2533 = arith.constant 1 : i32
        %2534 = arith.addi %2532, %2533 : i32
        llvm.store %2534, %2493 : i32, !llvm.ptr
        cf.br ^bb351
      ^bb353:
      %2535 = llvm.load %2487 : !llvm.ptr -> i32
      %2536 = arith.constant 1 : i32
      %2537 = arith.addi %2535, %2536 : i32
      llvm.store %2537, %2487 : i32, !llvm.ptr
      cf.br ^bb348
    ^bb350:
    func.call @free(%2283) : (!llvm.ptr) -> ()
    func.call @free(%2294) : (!llvm.ptr) -> ()
    func.call @free(%2301) : (!llvm.ptr) -> ()
    func.call @free(%2320) : (!llvm.ptr) -> ()
    func.call @free(%2325) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @main() -> i32 {
    func.call @init_sieve() : () -> ()
    func.call @init_factor_cache() : () -> ()
    func.call @init_mersenne_cache() : () -> ()
    %2547 = arith.constant 100000 : i32
    %2548 = arith.constant 8 : i32
    %2549 = arith.extsi %2547 : i32 to i64
    %2550 = arith.extsi %2548 : i32 to i64
    %2546 = func.call @calloc(%2549, %2550) : (i64, i64) -> !llvm.ptr
    %2551 = llvm.mlir.addressof @periods_set : !llvm.ptr
    llvm.store %2546, %2551 : !llvm.ptr, !llvm.ptr
    %2552 = arith.constant 0 : i32
    %2553 = llvm.mlir.addressof @periods_set_count : !llvm.ptr
    llvm.store %2552, %2553 : i32, !llvm.ptr
    %2555 = arith.constant 10000 : i32
    %2556 = arith.constant 8 : i32
    %2557 = arith.extsi %2555 : i32 to i64
    %2558 = arith.extsi %2556 : i32 to i64
    %2554 = func.call @calloc(%2557, %2558) : (i64, i64) -> !llvm.ptr
    %2560 = arith.constant 1 : i32
    %2561 = arith.constant 4 : i32
    %2562 = arith.extsi %2560 : i32 to i64
    %2563 = arith.extsi %2561 : i32 to i64
    %2559 = func.call @calloc(%2562, %2563) : (i64, i64) -> !llvm.ptr
    %2564 = arith.constant 3 : i32
    %2565 = llvm.mlir.constant(1 : i64) : i64
    %2566 = llvm.alloca %2565 x i32 : (i64) -> !llvm.ptr
    llvm.store %2564, %2566 : i32, !llvm.ptr
    cf.br ^bb354
    ^bb354:
    %2567 = llvm.load %2566 : !llvm.ptr -> i32
    %2568 = arith.constant 100 : i32
    %2569 = arith.cmpi sle, %2567, %2568 : i32
    cf.cond_br %2569, ^bb355, ^bb356
    ^bb355:
      %2571 = llvm.load %2566 : !llvm.ptr -> i32
      func.call @periods_for_n(%2571, %2554, %2559) : (i32, !llvm.ptr, !llvm.ptr) -> ()
      %2573 = arith.constant 0 : i32
      %2574 = arith.extsi %2573 : i32 to i64
      %2575 = llvm.getelementptr %2559[%2574] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %2572 = llvm.load %2575 : !llvm.ptr -> i32
      %2576 = arith.constant 0 : i32
      %2577 = llvm.mlir.constant(1 : i64) : i64
      %2578 = llvm.alloca %2577 x i32 : (i64) -> !llvm.ptr
      llvm.store %2576, %2578 : i32, !llvm.ptr
      cf.br ^bb357
      ^bb357:
      %2579 = llvm.load %2578 : !llvm.ptr -> i32
      %2580 = arith.cmpi slt, %2579, %2572 : i32
      cf.cond_br %2580, ^bb358, ^bb359
      ^bb358:
        %2583 = llvm.load %2578 : !llvm.ptr -> i32
        %2584 = arith.extsi %2583 : i32 to i64
        %2585 = llvm.getelementptr %2554[%2584] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %2582 = llvm.load %2585 : !llvm.ptr -> i64
        func.call @periods_insert(%2582) : (i64) -> ()
        %2586 = llvm.load %2578 : !llvm.ptr -> i32
        %2587 = arith.constant 1 : i32
        %2588 = arith.addi %2586, %2587 : i32
        llvm.store %2588, %2578 : i32, !llvm.ptr
        cf.br ^bb357
      ^bb359:
      %2589 = llvm.load %2566 : !llvm.ptr -> i32
      %2590 = arith.constant 1 : i32
      %2591 = arith.addi %2589, %2590 : i32
      llvm.store %2591, %2566 : i32, !llvm.ptr
      cf.br ^bb354
    ^bb356:
    %2592 = arith.constant 0 : i32
    %2593 = arith.extsi %2592 : i32 to i64
    %2594 = llvm.mlir.constant(1 : i64) : i64
    %2595 = llvm.alloca %2594 x i64 : (i64) -> !llvm.ptr
    llvm.store %2593, %2595 : i64, !llvm.ptr
    %2596 = arith.constant 0 : i32
    %2597 = llvm.mlir.constant(1 : i64) : i64
    %2598 = llvm.alloca %2597 x i32 : (i64) -> !llvm.ptr
    llvm.store %2596, %2598 : i32, !llvm.ptr
    cf.br ^bb360
    ^bb360:
    %2599 = llvm.load %2598 : !llvm.ptr -> i32
    %2600 = llvm.mlir.addressof @periods_set_count : !llvm.ptr
    %2601 = llvm.load %2600 : !llvm.ptr -> i32
    %2602 = arith.cmpi slt, %2599, %2601 : i32
    cf.cond_br %2602, ^bb361, ^bb362
    ^bb361:
      %2603 = llvm.load %2595 : !llvm.ptr -> i64
      %2605 = llvm.mlir.addressof @periods_set : !llvm.ptr
      %2606 = llvm.load %2605 : !llvm.ptr -> !llvm.ptr
      %2607 = llvm.load %2598 : !llvm.ptr -> i32
      %2608 = arith.extsi %2607 : i32 to i64
      %2609 = llvm.getelementptr %2606[%2608] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %2604 = llvm.load %2609 : !llvm.ptr -> i64
      %2610 = arith.addi %2603, %2604 : i64
      llvm.store %2610, %2595 : i64, !llvm.ptr
      %2611 = llvm.load %2598 : !llvm.ptr -> i32
      %2612 = arith.constant 1 : i32
      %2613 = arith.addi %2611, %2612 : i32
      llvm.store %2613, %2598 : i32, !llvm.ptr
      cf.br ^bb360
    ^bb362:
    %2614 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %2615 = llvm.load %2595 : !llvm.ptr -> i64
    %2616 = llvm.call @printf(%2614, %2615) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%2554) : (!llvm.ptr) -> ()
    func.call @free(%2559) : (!llvm.ptr) -> ()
    %2620 = llvm.mlir.addressof @periods_set : !llvm.ptr
    %2621 = llvm.load %2620 : !llvm.ptr -> !llvm.ptr
    func.call @free(%2621) : (!llvm.ptr) -> ()
    %2622 = arith.constant 0 : i32
    func.return %2622 : i32
  }
}