Problem 881

Pure Flow port. Branch-and-bound DFS over non-increasing exponent sequences.

Answer205702861096933200
Output205702861096933200
StatusPASS
Native helperno
Runtime0 ms
Peak memory1536 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

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

Flow source

# Project Euler 881: Divisor Graph Width
# Pure Flow port. Branch-and-bound DFS over non-increasing exponent sequences.

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

# Sieve primes up to limit, store into PRIMES array, return count.
function sieve_primes(limit: i64, PRIMES: ptr<i64>) -> i64 {
    let sieve: ptr<i8> = calloc(limit + 1, 1)
    memset(sieve, 1, limit + 1)
    sieve[0] = 0
    sieve[1] = 0
    let mut p: i64 = 2
    while p * p <= limit {
        if sieve[p] != 0 {
            let mut m: i64 = p * p
            while m <= limit {
                sieve[m] = 0
                m = m + p
            }
        }
        p = p + 1
    }
    let mut num: i64 = 0
    let mut i: i64 = 2
    while i <= limit {
        if sieve[i] != 0 {
            PRIMES[num] = i
            num = num + 1
        }
        i = i + 1
    }
    free(sieve)
    return num
}

# Convolve poly with (1 + x + ... + x^e), sliding window sum.
# Returns new array; writes length into out_len_ptr.
function convolve_with_ones(poly: ptr<i64>, poly_len: i64, e: i64, out_len_ptr: ptr<i64>) -> ptr<i64> {
    let out_len: i64 = poly_len + e
    out_len_ptr[0] = out_len
    let out: ptr<i64> = calloc(out_len, 8)
    let pref: ptr<i64> = calloc(poly_len + 1, 8)
    let mut s: i64 = 0
    let mut i: i64 = 0
    while i < poly_len {
        s = s + poly[i]
        pref[i + 1] = s
        i = i + 1
    }
    let mut j: i64 = 0
    while j < out_len {
        let mut lo: i64 = j - e
        if lo < 0 { lo = 0 }
        let mut hi: i64 = j
        if hi >= poly_len { hi = poly_len - 1 }
        if lo <= hi {
            out[j] = pref[hi + 1] - pref[lo]
        }
        j = j + 1
    }
    free(pref)
    return out
}

function max_array(arr: ptr<i64>, len: i64) -> i64 {
    let mut m: i64 = arr[0]
    let mut i: i64 = 1
    while i < len {
        if arr[i] > m {
            m = arr[i]
        }
        i = i + 1
    }
    return m
}

# dfs with best_n passed as ptr<i128> (mutable global replacement).
function dfs(idx: i64, prev_e: i64, poly: ptr<i64>, poly_len: i64, peak: i64, n: i128, target: i64, PRIMES: ptr<i64>, num_primes: i64, best_n_ptr: ptr<i128>) -> void {
    if n >= best_n_ptr[0] { return }
    if peak >= target {
        best_n_ptr[0] = n
        return
    }
    if idx >= num_primes { return }

    let p: i64 = PRIMES[idx]

    let mut max_e: i64 = 0
    let mut t: i128 = n
    while max_e < prev_e {
        t = t * (p as i128)
        if t >= best_n_ptr[0] { break }
        max_e = max_e + 1
    }
    if max_e == 0 { return }

    let powers: ptr<i128> = malloc(64 * 16)
    powers[0] = 1
    let mut e: i64 = 1
    while e <= max_e {
        powers[e] = powers[e - 1] * (p as i128)
        e = e + 1
    }

    e = max_e
    while e >= 1 {
        let n2: i128 = n * powers[e]
        if n2 < best_n_ptr[0] {
            let out_len_ptr: ptr<i64> = malloc(8)
            let poly2: ptr<i64> = convolve_with_ones(poly, poly_len, e, out_len_ptr)
            let out_len: i64 = out_len_ptr[0]
            let peak2: i64 = max_array(poly2, out_len)
            dfs(idx + 1, e, poly2, out_len, peak2, n2, target, PRIMES, num_primes, best_n_ptr)
            free(poly2)
            free(out_len_ptr)
        }
        e = e - 1
    }
    free(powers)
}

function initial_upper_bound(target: i64, PRIMES: ptr<i64>) -> i128 {
    let poly: ptr<i64> = malloc(8)
    poly[0] = 1
    let mut poly_len: i64 = 1
    let mut n: i128 = 1
    let mut i: i64 = 0
    while true {
        let out_len_ptr: ptr<i64> = malloc(8)
        let poly2: ptr<i64> = convolve_with_ones(poly, poly_len, 1, out_len_ptr)
        let out_len: i64 = out_len_ptr[0]
        free(poly)
        free(out_len_ptr)
        poly = poly2
        poly_len = out_len
        n = n * (PRIMES[i] as i128)
        i = i + 1
        if max_array(poly, poly_len) >= target {
            free(poly)
            return n
        }
    }
    return 0
}

function main() -> i32 {
    let PRIMES: ptr<i64> = malloc(400 * 8)
    let num_primes: i64 = sieve_primes(400, PRIMES)

    let target: i64 = 10000
    let best_n_ptr: ptr<i128> = malloc(16)
    best_n_ptr[0] = initial_upper_bound(target, PRIMES)

    let initial_poly: ptr<i64> = malloc(8)
    initial_poly[0] = 1
    dfs(0, 60, initial_poly, 1, 1, 1, target, PRIMES, num_primes, best_n_ptr)
    free(initial_poly)

    printf("%lld\n", (best_n_ptr[0]) as i64)
    free(PRIMES)
    free(best_n_ptr)
    return 0
}

Generated C

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

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

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

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

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

#include <math.h>

void* _ui_state = NULL;

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

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

int64_t sieve_primes_i64_ptr_i64(int64_t limit, int64_t* PRIMES);
int64_t* convolve_with_ones_ptr_i64_i64_i64_ptr_i64(int64_t* poly, int64_t poly_len, int64_t e, int64_t* out_len_ptr);
int64_t max_array_ptr_i64_i64(int64_t* arr, int64_t len);
void dfs_i64_i64_ptr_i64_i64_i64_i128_i64_ptr_i64_i64_ptr_i128(int64_t idx, int64_t prev_e, int64_t* poly, int64_t poly_len, int64_t peak, __int128 n, int64_t target, int64_t* PRIMES, int64_t num_primes, __int128* best_n_ptr);
__int128 initial_upper_bound_i64_ptr_i64(int64_t target, int64_t* PRIMES);
int32_t main(void);





int64_t sieve_primes_i64_ptr_i64(int64_t limit, int64_t* PRIMES) {
    int8_t* sieve = (int8_t*)(calloc((limit + 1), 1));
    memset(sieve, 1, (limit + 1));
    sieve[0] = 0;
    sieve[1] = 0;
    int64_t p = 2;
    while ((p * p) <= limit) {
        if (sieve[p] != 0) {
            int64_t m = (p * p);
            while (m <= limit) {
                sieve[m] = 0;
                m = (m + p);
            }
        }
        p = (p + 1);
    }
    int64_t num = 0;
    int64_t i = 2;
    while (i <= limit) {
        if (sieve[i] != 0) {
            PRIMES[num] = i;
            num = (num + 1);
        }
        i = (i + 1);
    }
    free(sieve);
    return num;
}

int64_t* convolve_with_ones_ptr_i64_i64_i64_ptr_i64(int64_t* poly, int64_t poly_len, int64_t e, int64_t* out_len_ptr) {
    int64_t out_len = (poly_len + e);
    out_len_ptr[0] = out_len;
    int64_t* out = (int64_t*)(calloc(out_len, 8));
    int64_t* pref = (int64_t*)(calloc((poly_len + 1), 8));
    int64_t s = 0;
    int64_t i = 0;
    while (i < poly_len) {
        s = (s + poly[i]);
        pref[(i + 1)] = s;
        i = (i + 1);
    }
    int64_t j = 0;
    while (j < out_len) {
        int64_t lo = (j - e);
        if (lo < 0) {
            lo = 0;
        }
        int64_t hi = j;
        if (hi >= poly_len) {
            hi = (poly_len - 1);
        }
        if (lo <= hi) {
            out[j] = (pref[(hi + 1)] - pref[lo]);
        }
        j = (j + 1);
    }
    free(pref);
    return out;
}

int64_t max_array_ptr_i64_i64(int64_t* arr, int64_t len) {
    int64_t m = arr[0];
    int64_t i = 1;
    while (i < len) {
        if (arr[i] > m) {
            m = arr[i];
        }
        i = (i + 1);
    }
    return m;
}

void dfs_i64_i64_ptr_i64_i64_i64_i128_i64_ptr_i64_i64_ptr_i128(int64_t idx, int64_t prev_e, int64_t* poly, int64_t poly_len, int64_t peak, __int128 n, int64_t target, int64_t* PRIMES, int64_t num_primes, __int128* best_n_ptr) {
    if (n >= best_n_ptr[0]) {
        return;
    }
    if (peak >= target) {
        best_n_ptr[0] = n;
        return;
    }
    if (idx >= num_primes) {
        return;
    }
    int64_t p = PRIMES[idx];
    int64_t max_e = 0;
    __int128 t = n;
    while (max_e < prev_e) {
        t = (t * ((__int128)(p)));
        if (t >= best_n_ptr[0]) {
            break;
        }
        max_e = (max_e + 1);
    }
    if (max_e == 0) {
        return;
    }
    __int128* powers = (__int128*)(malloc((64 * 16)));
    powers[0] = 1;
    int64_t e = 1;
    while (e <= max_e) {
        powers[e] = (powers[(e - 1)] * ((__int128)(p)));
        e = (e + 1);
    }
    e = max_e;
    while (e >= 1) {
        __int128 n2 = (n * powers[e]);
        if (n2 < best_n_ptr[0]) {
            int64_t* out_len_ptr = (int64_t*)(malloc(8));
            int64_t* poly2 = (int64_t*)(convolve_with_ones_ptr_i64_i64_i64_ptr_i64(poly, poly_len, e, out_len_ptr));
            int64_t out_len = out_len_ptr[0];
            int64_t peak2 = max_array_ptr_i64_i64(poly2, out_len);
            dfs_i64_i64_ptr_i64_i64_i64_i128_i64_ptr_i64_i64_ptr_i128((idx + 1), e, poly2, out_len, peak2, n2, target, PRIMES, num_primes, best_n_ptr);
            free(poly2);
            free(out_len_ptr);
        }
        e = (e - 1);
    }
    free(powers);
}

__int128 initial_upper_bound_i64_ptr_i64(int64_t target, int64_t* PRIMES) {
    int64_t* poly = (int64_t*)(malloc(8));
    poly[0] = 1;
    int64_t poly_len = 1;
    __int128 n = 1;
    int64_t i = 0;
    while (1) {
        int64_t* out_len_ptr = (int64_t*)(malloc(8));
        int64_t* poly2 = (int64_t*)(convolve_with_ones_ptr_i64_i64_i64_ptr_i64(poly, poly_len, 1, out_len_ptr));
        int64_t out_len = out_len_ptr[0];
        free(poly);
        free(out_len_ptr);
        poly = poly2;
        poly_len = out_len;
        n = (n * ((__int128)(PRIMES[i])));
        i = (i + 1);
        if (max_array_ptr_i64_i64(poly, poly_len) >= target) {
            free(poly);
            return n;
        }
    }
    return 0;
}

int32_t main(void) {
    int64_t* PRIMES = (int64_t*)(malloc((400 * 8)));
    int64_t num_primes = sieve_primes_i64_ptr_i64(400, PRIMES);
    int64_t target = 10000;
    __int128* best_n_ptr = (__int128*)(malloc(16));
    best_n_ptr[0] = initial_upper_bound_i64_ptr_i64(target, PRIMES);
    int64_t* initial_poly = (int64_t*)(malloc(8));
    initial_poly[0] = 1;
    dfs_i64_i64_ptr_i64_i64_i64_i128_i64_ptr_i64_i64_ptr_i128(0, 60, initial_poly, 1, 1, 1, target, PRIMES, num_primes, best_n_ptr);
    free(initial_poly);
    printf("%lld\n", ((int64_t)(best_n_ptr[0])));
    free(PRIMES);
    free(best_n_ptr);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @malloc(i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  func.func private @memset(!llvm.ptr, i64, i64) -> !llvm.ptr
  func.func @sieve_primes(%arg0: i64, %arg1: !llvm.ptr) -> i64 {
    %1 = arith.constant 1 : i32
    %3 = arith.extsi %1 : i32 to i64
    %2 = arith.addi %arg0, %3 : i64
    %4 = arith.constant 1 : i32
    %5 = arith.extsi %4 : i32 to i64
    %0 = func.call @calloc(%2, %5) : (i64, i64) -> !llvm.ptr
    %7 = arith.constant 1 : i32
    %8 = arith.constant 1 : i32
    %10 = arith.extsi %8 : i32 to i64
    %9 = arith.addi %arg0, %10 : i64
    %11 = arith.extsi %7 : i32 to i64
    %6 = func.call @memset(%0, %11, %9) : (!llvm.ptr, i64, i64) -> !llvm.ptr
    %12 = arith.constant 0 : i32
    %13 = arith.constant 0 : i32
    %14 = arith.trunci %12 : i32 to i8
    %15 = arith.extsi %13 : i32 to i64
    %16 = llvm.getelementptr %0[%15] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %14, %16 : i8, !llvm.ptr
    %17 = arith.constant 0 : i32
    %18 = arith.constant 1 : i32
    %19 = arith.trunci %17 : i32 to i8
    %20 = arith.extsi %18 : i32 to i64
    %21 = llvm.getelementptr %0[%20] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %19, %21 : i8, !llvm.ptr
    %22 = arith.constant 2 : i32
    %23 = arith.extsi %22 : i32 to i64
    %24 = llvm.mlir.constant(1 : i64) : i64
    %25 = llvm.alloca %24 x i64 : (i64) -> !llvm.ptr
    llvm.store %23, %25 : i64, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %26 = llvm.load %25 : !llvm.ptr -> i64
    %27 = llvm.load %25 : !llvm.ptr -> i64
    %28 = arith.muli %26, %27 : i64
    %29 = arith.cmpi sle, %28, %arg0 : i64
    cf.cond_br %29, ^bb1, ^bb2
    ^bb1:
      %31 = llvm.load %25 : !llvm.ptr -> i64
      %32 = llvm.getelementptr %0[%31] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %30 = llvm.load %32 : !llvm.ptr -> i8
      %33 = arith.constant 0 : i32
      %35 = arith.extsi %30 : i8 to i32
      %34 = arith.cmpi ne, %35, %33 : i32
      cf.cond_br %34, ^bb3, ^bb4
      ^bb3:
        %36 = llvm.load %25 : !llvm.ptr -> i64
        %37 = llvm.load %25 : !llvm.ptr -> i64
        %38 = arith.muli %36, %37 : i64
        %39 = llvm.mlir.constant(1 : i64) : i64
        %40 = llvm.alloca %39 x i64 : (i64) -> !llvm.ptr
        llvm.store %38, %40 : i64, !llvm.ptr
        cf.br ^bb6
        ^bb6:
        %41 = llvm.load %40 : !llvm.ptr -> i64
        %42 = arith.cmpi sle, %41, %arg0 : i64
        cf.cond_br %42, ^bb7, ^bb8
        ^bb7:
          %43 = arith.constant 0 : i32
          %44 = llvm.load %40 : !llvm.ptr -> i64
          %45 = arith.trunci %43 : i32 to i8
          %46 = llvm.getelementptr %0[%44] : (!llvm.ptr, i64) -> !llvm.ptr, i8
          llvm.store %45, %46 : i8, !llvm.ptr
          %47 = llvm.load %40 : !llvm.ptr -> i64
          %48 = llvm.load %25 : !llvm.ptr -> i64
          %49 = arith.addi %47, %48 : i64
          llvm.store %49, %40 : i64, !llvm.ptr
          cf.br ^bb6
        ^bb8:
        cf.br ^bb5
      ^bb4:
        cf.br ^bb5
      ^bb5:
      %50 = llvm.load %25 : !llvm.ptr -> i64
      %51 = arith.constant 1 : i32
      %53 = arith.extsi %51 : i32 to i64
      %52 = arith.addi %50, %53 : i64
      llvm.store %52, %25 : i64, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %54 = arith.constant 0 : i32
    %55 = arith.extsi %54 : i32 to 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 2 : 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 ^bb9
    ^bb9:
    %62 = llvm.load %61 : !llvm.ptr -> i64
    %63 = arith.cmpi sle, %62, %arg0 : i64
    cf.cond_br %63, ^bb10, ^bb11
    ^bb10:
      %65 = llvm.load %61 : !llvm.ptr -> i64
      %66 = llvm.getelementptr %0[%65] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %64 = llvm.load %66 : !llvm.ptr -> i8
      %67 = arith.constant 0 : i32
      %69 = arith.extsi %64 : i8 to i32
      %68 = arith.cmpi ne, %69, %67 : i32
      cf.cond_br %68, ^bb12, ^bb13
      ^bb12:
        %70 = llvm.load %61 : !llvm.ptr -> i64
        %71 = llvm.load %57 : !llvm.ptr -> i64
        %72 = llvm.getelementptr %arg1[%71] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %70, %72 : i64, !llvm.ptr
        %73 = llvm.load %57 : !llvm.ptr -> i64
        %74 = arith.constant 1 : i32
        %76 = arith.extsi %74 : i32 to i64
        %75 = arith.addi %73, %76 : i64
        llvm.store %75, %57 : i64, !llvm.ptr
        cf.br ^bb14
      ^bb13:
        cf.br ^bb14
      ^bb14:
      %77 = llvm.load %61 : !llvm.ptr -> i64
      %78 = arith.constant 1 : i32
      %80 = arith.extsi %78 : i32 to i64
      %79 = arith.addi %77, %80 : i64
      llvm.store %79, %61 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    func.call @free(%0) : (!llvm.ptr) -> ()
    %82 = llvm.load %57 : !llvm.ptr -> i64
    func.return %82 : i64
  }
  func.func @convolve_with_ones(%arg0: !llvm.ptr, %arg1: i64, %arg2: i64, %arg3: !llvm.ptr) -> !llvm.ptr {
    %83 = arith.addi %arg1, %arg2 : i64
    %84 = arith.constant 0 : i32
    %85 = arith.extsi %84 : i32 to i64
    %86 = llvm.getelementptr %arg3[%85] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %83, %86 : i64, !llvm.ptr
    %88 = arith.constant 8 : i32
    %89 = arith.extsi %88 : i32 to i64
    %87 = func.call @calloc(%83, %89) : (i64, i64) -> !llvm.ptr
    %91 = arith.constant 1 : i32
    %93 = arith.extsi %91 : i32 to i64
    %92 = arith.addi %arg1, %93 : i64
    %94 = arith.constant 8 : i32
    %95 = arith.extsi %94 : i32 to i64
    %90 = func.call @calloc(%92, %95) : (i64, i64) -> !llvm.ptr
    %96 = arith.constant 0 : i32
    %97 = arith.extsi %96 : i32 to i64
    %98 = llvm.mlir.constant(1 : i64) : i64
    %99 = llvm.alloca %98 x i64 : (i64) -> !llvm.ptr
    llvm.store %97, %99 : i64, !llvm.ptr
    %100 = arith.constant 0 : i32
    %101 = arith.extsi %100 : i32 to i64
    %102 = llvm.mlir.constant(1 : i64) : i64
    %103 = llvm.alloca %102 x i64 : (i64) -> !llvm.ptr
    llvm.store %101, %103 : i64, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %104 = llvm.load %103 : !llvm.ptr -> i64
    %105 = arith.cmpi slt, %104, %arg1 : i64
    cf.cond_br %105, ^bb16, ^bb17
    ^bb16:
      %106 = llvm.load %99 : !llvm.ptr -> i64
      %108 = llvm.load %103 : !llvm.ptr -> i64
      %109 = llvm.getelementptr %arg0[%108] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %107 = llvm.load %109 : !llvm.ptr -> i64
      %110 = arith.addi %106, %107 : i64
      llvm.store %110, %99 : i64, !llvm.ptr
      %111 = llvm.load %99 : !llvm.ptr -> i64
      %112 = llvm.load %103 : !llvm.ptr -> i64
      %113 = arith.constant 1 : i32
      %115 = arith.extsi %113 : i32 to i64
      %114 = arith.addi %112, %115 : i64
      %116 = llvm.getelementptr %90[%114] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %111, %116 : i64, !llvm.ptr
      %117 = llvm.load %103 : !llvm.ptr -> i64
      %118 = arith.constant 1 : i32
      %120 = arith.extsi %118 : i32 to i64
      %119 = arith.addi %117, %120 : i64
      llvm.store %119, %103 : i64, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    %121 = arith.constant 0 : i32
    %122 = arith.extsi %121 : i32 to i64
    %123 = llvm.mlir.constant(1 : i64) : i64
    %124 = llvm.alloca %123 x i64 : (i64) -> !llvm.ptr
    llvm.store %122, %124 : i64, !llvm.ptr
    cf.br ^bb18
    ^bb18:
    %125 = llvm.load %124 : !llvm.ptr -> i64
    %126 = arith.cmpi slt, %125, %83 : i64
    cf.cond_br %126, ^bb19, ^bb20
    ^bb19:
      %127 = llvm.load %124 : !llvm.ptr -> i64
      %128 = arith.subi %127, %arg2 : i64
      %129 = llvm.mlir.constant(1 : i64) : i64
      %130 = llvm.alloca %129 x i64 : (i64) -> !llvm.ptr
      llvm.store %128, %130 : i64, !llvm.ptr
      %131 = llvm.load %130 : !llvm.ptr -> i64
      %132 = arith.constant 0 : i32
      %134 = arith.extsi %132 : i32 to i64
      %133 = arith.cmpi slt, %131, %134 : i64
      cf.cond_br %133, ^bb21, ^bb22
      ^bb21:
        %135 = arith.constant 0 : i32
        %136 = arith.extsi %135 : i32 to i64
        llvm.store %136, %130 : i64, !llvm.ptr
        cf.br ^bb23
      ^bb22:
        cf.br ^bb23
      ^bb23:
      %137 = llvm.load %124 : !llvm.ptr -> i64
      %138 = llvm.mlir.constant(1 : i64) : i64
      %139 = llvm.alloca %138 x i64 : (i64) -> !llvm.ptr
      llvm.store %137, %139 : i64, !llvm.ptr
      %140 = llvm.load %139 : !llvm.ptr -> i64
      %141 = arith.cmpi sge, %140, %arg1 : i64
      cf.cond_br %141, ^bb24, ^bb25
      ^bb24:
        %142 = arith.constant 1 : i32
        %144 = arith.extsi %142 : i32 to i64
        %143 = arith.subi %arg1, %144 : i64
        llvm.store %143, %139 : i64, !llvm.ptr
        cf.br ^bb26
      ^bb25:
        cf.br ^bb26
      ^bb26:
      %145 = llvm.load %130 : !llvm.ptr -> i64
      %146 = llvm.load %139 : !llvm.ptr -> i64
      %147 = arith.cmpi sle, %145, %146 : i64
      cf.cond_br %147, ^bb27, ^bb28
      ^bb27:
        %149 = llvm.load %139 : !llvm.ptr -> i64
        %150 = arith.constant 1 : i32
        %152 = arith.extsi %150 : i32 to i64
        %151 = arith.addi %149, %152 : i64
        %153 = llvm.getelementptr %90[%151] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %148 = llvm.load %153 : !llvm.ptr -> i64
        %155 = llvm.load %130 : !llvm.ptr -> i64
        %156 = llvm.getelementptr %90[%155] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %154 = llvm.load %156 : !llvm.ptr -> i64
        %157 = arith.subi %148, %154 : i64
        %158 = llvm.load %124 : !llvm.ptr -> i64
        %159 = llvm.getelementptr %87[%158] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %157, %159 : i64, !llvm.ptr
        cf.br ^bb29
      ^bb28:
        cf.br ^bb29
      ^bb29:
      %160 = llvm.load %124 : !llvm.ptr -> i64
      %161 = arith.constant 1 : i32
      %163 = arith.extsi %161 : i32 to i64
      %162 = arith.addi %160, %163 : i64
      llvm.store %162, %124 : i64, !llvm.ptr
      cf.br ^bb18
    ^bb20:
    func.call @free(%90) : (!llvm.ptr) -> ()
    func.return %87 : !llvm.ptr
  }
  func.func @max_array(%arg0: !llvm.ptr, %arg1: i64) -> i64 {
    %166 = arith.constant 0 : i32
    %167 = arith.extsi %166 : i32 to i64
    %168 = llvm.getelementptr %arg0[%167] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %165 = llvm.load %168 : !llvm.ptr -> i64
    %169 = llvm.mlir.constant(1 : i64) : i64
    %170 = llvm.alloca %169 x i64 : (i64) -> !llvm.ptr
    llvm.store %165, %170 : i64, !llvm.ptr
    %171 = arith.constant 1 : i32
    %172 = arith.extsi %171 : i32 to i64
    %173 = llvm.mlir.constant(1 : i64) : i64
    %174 = llvm.alloca %173 x i64 : (i64) -> !llvm.ptr
    llvm.store %172, %174 : i64, !llvm.ptr
    cf.br ^bb30
    ^bb30:
    %175 = llvm.load %174 : !llvm.ptr -> i64
    %176 = arith.cmpi slt, %175, %arg1 : i64
    cf.cond_br %176, ^bb31, ^bb32
    ^bb31:
      %178 = llvm.load %174 : !llvm.ptr -> i64
      %179 = llvm.getelementptr %arg0[%178] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %177 = llvm.load %179 : !llvm.ptr -> i64
      %180 = llvm.load %170 : !llvm.ptr -> i64
      %181 = arith.cmpi sgt, %177, %180 : i64
      cf.cond_br %181, ^bb33, ^bb34
      ^bb33:
        %183 = llvm.load %174 : !llvm.ptr -> i64
        %184 = llvm.getelementptr %arg0[%183] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %182 = llvm.load %184 : !llvm.ptr -> i64
        llvm.store %182, %170 : i64, !llvm.ptr
        cf.br ^bb35
      ^bb34:
        cf.br ^bb35
      ^bb35:
      %185 = llvm.load %174 : !llvm.ptr -> i64
      %186 = arith.constant 1 : i32
      %188 = arith.extsi %186 : i32 to i64
      %187 = arith.addi %185, %188 : i64
      llvm.store %187, %174 : i64, !llvm.ptr
      cf.br ^bb30
    ^bb32:
    %189 = llvm.load %170 : !llvm.ptr -> i64
    func.return %189 : i64
  }
  func.func @dfs(%arg0: i64, %arg1: i64, %arg2: !llvm.ptr, %arg3: i64, %arg4: i64, %arg5: i128, %arg6: i64, %arg7: !llvm.ptr, %arg8: i64, %arg9: !llvm.ptr) -> () {
    %191 = arith.constant 0 : i32
    %192 = arith.extsi %191 : i32 to i64
    %193 = llvm.getelementptr %arg9[%192] : (!llvm.ptr, i64) -> !llvm.ptr, i128
    %190 = llvm.load %193 : !llvm.ptr -> i128
    %195 = arith.trunci %arg5 : i128 to i64
    %196 = arith.trunci %190 : i128 to i64
    %194 = arith.cmpi sge, %195, %196 : i64
    cf.cond_br %194, ^bb36, ^bb37
    ^bb36:
      func.return
    ^bb37:
      cf.br ^bb38
    ^bb38:
    %197 = arith.cmpi sge, %arg4, %arg6 : i64
    cf.cond_br %197, ^bb39, ^bb40
    ^bb39:
      %198 = arith.constant 0 : i32
      %199 = arith.extsi %198 : i32 to i64
      %200 = llvm.getelementptr %arg9[%199] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      llvm.store %arg5, %200 : i128, !llvm.ptr
      func.return
    ^bb40:
      cf.br ^bb41
    ^bb41:
    %201 = arith.cmpi sge, %arg0, %arg8 : i64
    cf.cond_br %201, ^bb42, ^bb43
    ^bb42:
      func.return
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %203 = llvm.getelementptr %arg7[%arg0] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %202 = llvm.load %203 : !llvm.ptr -> i64
    %204 = arith.constant 0 : i32
    %205 = arith.extsi %204 : i32 to i64
    %206 = llvm.mlir.constant(1 : i64) : i64
    %207 = llvm.alloca %206 x i64 : (i64) -> !llvm.ptr
    llvm.store %205, %207 : i64, !llvm.ptr
    %208 = llvm.mlir.constant(1 : i64) : i64
    %209 = llvm.alloca %208 x i128 : (i64) -> !llvm.ptr
    llvm.store %arg5, %209 : i128, !llvm.ptr
    cf.br ^bb45
    ^bb45:
    %210 = llvm.load %207 : !llvm.ptr -> i64
    %211 = arith.cmpi slt, %210, %arg1 : i64
    cf.cond_br %211, ^bb46, ^bb47
    ^bb46:
      %212 = llvm.load %209 : !llvm.ptr -> i128
      %213 = arith.extsi %202 : i64 to i128
      %215 = arith.trunci %212 : i128 to i64
      %216 = arith.trunci %213 : i128 to i64
      %214 = arith.muli %215, %216 : i64
      %217 = arith.extsi %214 : i64 to i128
      llvm.store %217, %209 : i128, !llvm.ptr
      %218 = llvm.load %209 : !llvm.ptr -> i128
      %220 = arith.constant 0 : i32
      %221 = arith.extsi %220 : i32 to i64
      %222 = llvm.getelementptr %arg9[%221] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %219 = llvm.load %222 : !llvm.ptr -> i128
      %224 = arith.trunci %218 : i128 to i64
      %225 = arith.trunci %219 : i128 to i64
      %223 = arith.cmpi sge, %224, %225 : i64
      cf.cond_br %223, ^bb48, ^bb49
      ^bb48:
        cf.br ^bb47
      ^bb49:
        cf.br ^bb50
      ^bb50:
      %226 = llvm.load %207 : !llvm.ptr -> i64
      %227 = arith.constant 1 : i32
      %229 = arith.extsi %227 : i32 to i64
      %228 = arith.addi %226, %229 : i64
      llvm.store %228, %207 : i64, !llvm.ptr
      cf.br ^bb45
    ^bb47:
    %230 = llvm.load %207 : !llvm.ptr -> i64
    %231 = arith.constant 0 : i32
    %233 = arith.extsi %231 : i32 to i64
    %232 = arith.cmpi eq, %230, %233 : i64
    cf.cond_br %232, ^bb51, ^bb52
    ^bb51:
      func.return
    ^bb52:
      cf.br ^bb53
    ^bb53:
    %235 = arith.constant 64 : i32
    %236 = arith.constant 16 : i32
    %237 = arith.muli %235, %236 : i32
    %238 = arith.extsi %237 : i32 to i64
    %234 = func.call @malloc(%238) : (i64) -> !llvm.ptr
    %239 = arith.constant 1 : i32
    %240 = arith.constant 0 : i32
    %241 = arith.extsi %239 : i32 to i128
    %242 = arith.extsi %240 : i32 to i64
    %243 = llvm.getelementptr %234[%242] : (!llvm.ptr, i64) -> !llvm.ptr, i128
    llvm.store %241, %243 : i128, !llvm.ptr
    %244 = arith.constant 1 : i32
    %245 = arith.extsi %244 : i32 to i64
    %246 = llvm.mlir.constant(1 : i64) : i64
    %247 = llvm.alloca %246 x i64 : (i64) -> !llvm.ptr
    llvm.store %245, %247 : i64, !llvm.ptr
    cf.br ^bb54
    ^bb54:
    %248 = llvm.load %247 : !llvm.ptr -> i64
    %249 = llvm.load %207 : !llvm.ptr -> i64
    %250 = arith.cmpi sle, %248, %249 : i64
    cf.cond_br %250, ^bb55, ^bb56
    ^bb55:
      %252 = llvm.load %247 : !llvm.ptr -> i64
      %253 = arith.constant 1 : i32
      %255 = arith.extsi %253 : i32 to i64
      %254 = arith.subi %252, %255 : i64
      %256 = llvm.getelementptr %234[%254] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %251 = llvm.load %256 : !llvm.ptr -> i128
      %257 = arith.extsi %202 : i64 to i128
      %259 = arith.trunci %251 : i128 to i64
      %260 = arith.trunci %257 : i128 to i64
      %258 = arith.muli %259, %260 : i64
      %261 = llvm.load %247 : !llvm.ptr -> i64
      %262 = arith.extsi %258 : i64 to i128
      %263 = llvm.getelementptr %234[%261] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      llvm.store %262, %263 : i128, !llvm.ptr
      %264 = llvm.load %247 : !llvm.ptr -> i64
      %265 = arith.constant 1 : i32
      %267 = arith.extsi %265 : i32 to i64
      %266 = arith.addi %264, %267 : i64
      llvm.store %266, %247 : i64, !llvm.ptr
      cf.br ^bb54
    ^bb56:
    %268 = llvm.load %207 : !llvm.ptr -> i64
    llvm.store %268, %247 : i64, !llvm.ptr
    cf.br ^bb57
    ^bb57:
    %269 = llvm.load %247 : !llvm.ptr -> i64
    %270 = arith.constant 1 : i32
    %272 = arith.extsi %270 : i32 to i64
    %271 = arith.cmpi sge, %269, %272 : i64
    cf.cond_br %271, ^bb58, ^bb59
    ^bb58:
      %274 = llvm.load %247 : !llvm.ptr -> i64
      %275 = llvm.getelementptr %234[%274] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %273 = llvm.load %275 : !llvm.ptr -> i128
      %277 = arith.trunci %arg5 : i128 to i64
      %278 = arith.trunci %273 : i128 to i64
      %276 = arith.muli %277, %278 : i64
      %279 = arith.extsi %276 : i64 to i128
      %281 = arith.constant 0 : i32
      %282 = arith.extsi %281 : i32 to i64
      %283 = llvm.getelementptr %arg9[%282] : (!llvm.ptr, i64) -> !llvm.ptr, i128
      %280 = llvm.load %283 : !llvm.ptr -> i128
      %285 = arith.trunci %279 : i128 to i64
      %286 = arith.trunci %280 : i128 to i64
      %284 = arith.cmpi slt, %285, %286 : i64
      cf.cond_br %284, ^bb60, ^bb61
      ^bb60:
        %288 = arith.constant 8 : i32
        %289 = arith.extsi %288 : i32 to i64
        %287 = func.call @malloc(%289) : (i64) -> !llvm.ptr
        %291 = llvm.load %247 : !llvm.ptr -> i64
        %290 = func.call @convolve_with_ones(%arg2, %arg3, %291, %287) : (!llvm.ptr, i64, i64, !llvm.ptr) -> !llvm.ptr
        %293 = arith.constant 0 : i32
        %294 = arith.extsi %293 : i32 to i64
        %295 = llvm.getelementptr %287[%294] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %292 = llvm.load %295 : !llvm.ptr -> i64
        %296 = func.call @max_array(%290, %292) : (!llvm.ptr, i64) -> i64
        %298 = arith.constant 1 : i32
        %300 = arith.extsi %298 : i32 to i64
        %299 = arith.addi %arg0, %300 : i64
        %301 = llvm.load %247 : !llvm.ptr -> i64
        func.call @dfs(%299, %301, %290, %292, %296, %279, %arg6, %arg7, %arg8, %arg9) : (i64, i64, !llvm.ptr, i64, i64, i128, i64, !llvm.ptr, i64, !llvm.ptr) -> ()
        func.call @free(%290) : (!llvm.ptr) -> ()
        func.call @free(%287) : (!llvm.ptr) -> ()
        cf.br ^bb62
      ^bb61:
        cf.br ^bb62
      ^bb62:
      %304 = llvm.load %247 : !llvm.ptr -> i64
      %305 = arith.constant 1 : i32
      %307 = arith.extsi %305 : i32 to i64
      %306 = arith.subi %304, %307 : i64
      llvm.store %306, %247 : i64, !llvm.ptr
      cf.br ^bb57
    ^bb59:
    func.call @free(%234) : (!llvm.ptr) -> ()
    func.return
  }
  func.func @initial_upper_bound(%arg0: i64, %arg1: !llvm.ptr) -> i128 {
    %310 = arith.constant 8 : i32
    %311 = arith.extsi %310 : i32 to i64
    %309 = func.call @malloc(%311) : (i64) -> !llvm.ptr
    %312 = arith.constant 1 : i32
    %313 = arith.constant 0 : i32
    %314 = arith.extsi %312 : i32 to i64
    %315 = arith.extsi %313 : i32 to i64
    %316 = llvm.getelementptr %309[%315] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %314, %316 : i64, !llvm.ptr
    %317 = arith.constant 1 : i32
    %318 = arith.extsi %317 : i32 to i64
    %319 = llvm.mlir.constant(1 : i64) : i64
    %320 = llvm.alloca %319 x i64 : (i64) -> !llvm.ptr
    llvm.store %318, %320 : i64, !llvm.ptr
    %321 = arith.constant 1 : i32
    %322 = arith.extsi %321 : i32 to i128
    %323 = llvm.mlir.constant(1 : i64) : i64
    %324 = llvm.alloca %323 x i128 : (i64) -> !llvm.ptr
    llvm.store %322, %324 : i128, !llvm.ptr
    %325 = arith.constant 0 : i32
    %326 = arith.extsi %325 : i32 to i64
    %327 = llvm.mlir.constant(1 : i64) : i64
    %328 = llvm.alloca %327 x i64 : (i64) -> !llvm.ptr
    llvm.store %326, %328 : i64, !llvm.ptr
    cf.br ^bb63(%309 : !llvm.ptr)
    ^bb63(%329: !llvm.ptr):
    %330 = arith.constant 1 : i1
    cf.cond_br %330, ^bb64(%329 : !llvm.ptr), ^bb65(%329 : !llvm.ptr)
    ^bb64(%331: !llvm.ptr):
      %333 = arith.constant 8 : i32
      %334 = arith.extsi %333 : i32 to i64
      %332 = func.call @malloc(%334) : (i64) -> !llvm.ptr
      %336 = llvm.load %320 : !llvm.ptr -> i64
      %337 = arith.constant 1 : i32
      %338 = arith.extsi %337 : i32 to i64
      %335 = func.call @convolve_with_ones(%331, %336, %338, %332) : (!llvm.ptr, i64, i64, !llvm.ptr) -> !llvm.ptr
      %340 = arith.constant 0 : i32
      %341 = arith.extsi %340 : i32 to i64
      %342 = llvm.getelementptr %332[%341] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %339 = llvm.load %342 : !llvm.ptr -> i64
      func.call @free(%331) : (!llvm.ptr) -> ()
      func.call @free(%332) : (!llvm.ptr) -> ()
      llvm.store %339, %320 : i64, !llvm.ptr
      %345 = llvm.load %324 : !llvm.ptr -> i128
      %347 = llvm.load %328 : !llvm.ptr -> i64
      %348 = llvm.getelementptr %arg1[%347] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %346 = llvm.load %348 : !llvm.ptr -> i64
      %349 = arith.extsi %346 : i64 to i128
      %351 = arith.trunci %345 : i128 to i64
      %352 = arith.trunci %349 : i128 to i64
      %350 = arith.muli %351, %352 : i64
      %353 = arith.extsi %350 : i64 to i128
      llvm.store %353, %324 : i128, !llvm.ptr
      %354 = llvm.load %328 : !llvm.ptr -> i64
      %355 = arith.constant 1 : i32
      %357 = arith.extsi %355 : i32 to i64
      %356 = arith.addi %354, %357 : i64
      llvm.store %356, %328 : i64, !llvm.ptr
      %359 = llvm.load %320 : !llvm.ptr -> i64
      %358 = func.call @max_array(%335, %359) : (!llvm.ptr, i64) -> i64
      %360 = arith.cmpi sge, %358, %arg0 : i64
      cf.cond_br %360, ^bb66, ^bb67
      ^bb66:
        func.call @free(%335) : (!llvm.ptr) -> ()
        %362 = llvm.load %324 : !llvm.ptr -> i128
        func.return %362 : i128
      ^bb67:
        cf.br ^bb68
      ^bb68:
      cf.br ^bb63(%335 : !llvm.ptr)
    ^bb65(%363: !llvm.ptr):
    %364 = arith.constant 0 : i32
    %365 = arith.extsi %364 : i32 to i128
    func.return %365 : i128
  }
  func.func @main() -> i32 {
    %367 = arith.constant 400 : i32
    %368 = arith.constant 8 : i32
    %369 = arith.muli %367, %368 : i32
    %370 = arith.extsi %369 : i32 to i64
    %366 = func.call @malloc(%370) : (i64) -> !llvm.ptr
    %372 = arith.constant 400 : i32
    %373 = arith.extsi %372 : i32 to i64
    %371 = func.call @sieve_primes(%373, %366) : (i64, !llvm.ptr) -> i64
    %374 = arith.constant 10000 : i32
    %375 = arith.extsi %374 : i32 to i64
    %377 = arith.constant 16 : i32
    %378 = arith.extsi %377 : i32 to i64
    %376 = func.call @malloc(%378) : (i64) -> !llvm.ptr
    %379 = func.call @initial_upper_bound(%375, %366) : (i64, !llvm.ptr) -> i128
    %380 = arith.constant 0 : i32
    %381 = arith.extsi %380 : i32 to i64
    %382 = llvm.getelementptr %376[%381] : (!llvm.ptr, i64) -> !llvm.ptr, i128
    llvm.store %379, %382 : i128, !llvm.ptr
    %384 = arith.constant 8 : i32
    %385 = arith.extsi %384 : i32 to i64
    %383 = func.call @malloc(%385) : (i64) -> !llvm.ptr
    %386 = arith.constant 1 : i32
    %387 = arith.constant 0 : i32
    %388 = arith.extsi %386 : i32 to i64
    %389 = arith.extsi %387 : i32 to i64
    %390 = llvm.getelementptr %383[%389] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %388, %390 : i64, !llvm.ptr
    %392 = arith.constant 0 : i32
    %393 = arith.constant 60 : i32
    %394 = arith.constant 1 : i32
    %395 = arith.constant 1 : i32
    %396 = arith.constant 1 : i32
    %397 = arith.extsi %392 : i32 to i64
    %398 = arith.extsi %393 : i32 to i64
    %399 = arith.extsi %394 : i32 to i64
    %400 = arith.extsi %395 : i32 to i64
    %401 = arith.extsi %396 : i32 to i128
    func.call @dfs(%397, %398, %383, %399, %400, %401, %375, %366, %371, %376) : (i64, i64, !llvm.ptr, i64, i64, i128, i64, !llvm.ptr, i64, !llvm.ptr) -> ()
    func.call @free(%383) : (!llvm.ptr) -> ()
    %403 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %405 = arith.constant 0 : i32
    %406 = arith.extsi %405 : i32 to i64
    %407 = llvm.getelementptr %376[%406] : (!llvm.ptr, i64) -> !llvm.ptr, i128
    %404 = llvm.load %407 : !llvm.ptr -> i128
    %408 = arith.trunci %404 : i128 to i64
    %409 = llvm.call @printf(%403, %408) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%366) : (!llvm.ptr) -> ()
    func.call @free(%376) : (!llvm.ptr) -> ()
    %412 = arith.constant 0 : i32
    func.return %412 : i32
  }
}