← All problems
Problem 641
f(n) = count of dice showing 1 after the process. Uses Mobius sieve, Mertens function, squarefree counting.
View problem on Project Euler
Performance comparison
Metric Our solution Best known
Time complexity O(n)O(n log log n)
Space complexity O(n^2)O(n)
Approach Flow solution Mobius sieve
Verdict Optimal
Flow source
# Project Euler 641: A Long Row of Dice
# f(n) = count of dice showing 1 after the process.
# Uses Mobius sieve, Mertens function, squarefree counting.
import euler.nt { isqrt }
extern {
function calloc(n: i64, size: i64) -> ptr<void>
function free(p: ptr<void>) -> void
function memset(s: ptr<void>, c: i64, n: i64) -> ptr<void>
}
function icbrt(n: i64) -> i64 {
if n < 2 { return n }
let mut hi: i64 = 1
let mut bits: i64 = 0
let mut tmp: i64 = n
while tmp > 0 { bits = bits + 1; tmp = tmp >> 1 }
hi = 1 << ((bits + 2) / 3)
let mut lo: i64 = hi >> 1
while lo + 1 < hi {
let mid: i64 = (lo + hi) >> 1
let m3: i64 = mid * mid * mid
if m3 <= n { lo = mid } else { hi = mid }
}
return lo
}
function isqrt_i128(n: i128) -> i64 {
if n < 2 { return n as i64 }
let mut x: i128 = n
let mut y: i128 = (x + 1) / 2
while y < x {
x = y
y = (x + n / x) / 2
}
return x as i64
}
# Mobius sieve
let mut g_mu: ptr<i8> = null
let mut g_mertens_small: ptr<i64> = null
let mut g_sqfree_small: ptr<i64> = null
let mut g_limit: i64 = 0
function mobius_sieve(limit: i64) -> void {
g_mu = calloc(limit + 1, 1)
g_mu[1] = 1
let primes: ptr<i64> = calloc(limit / 10 + 100, 8)
let mut nprimes: i64 = 0
let is_comp: ptr<i8> = calloc(limit + 1, 1)
for i in 2..(limit + 1) {
if is_comp[i] == 0 {
primes[nprimes] = i
nprimes = nprimes + 1
g_mu[i] = -1
}
for j in 0..nprimes {
let p: i64 = primes[j]
let ip: i64 = i * p
if ip > limit { break }
is_comp[ip] = 1
if i % p == 0 {
g_mu[ip] = 0
break
} else {
g_mu[ip] = -g_mu[i]
}
}
}
g_mertens_small = calloc(limit + 1, 8)
g_sqfree_small = calloc(limit + 1, 8)
let mut s: i64 = 0
let mut q: i64 = 0
for i in 1..(limit + 1) {
s = s + (g_mu[i] as i64)
g_mertens_small[i] = s
if g_mu[i] != 0 { q = q + 1 }
g_sqfree_small[i] = q
}
g_limit = limit
free(is_comp)
free(primes)
}
# Mertens cache using hash map (open addressing)
const MEMO_SIZE: i64 = 2000003
let mut g_mertens_key: ptr<i64> = null
let mut g_mertens_val: ptr<i64> = null
function mertens(n: i64) -> i64 {
if n <= g_limit { return g_mertens_small[n] }
let h: i64 = n % MEMO_SIZE
if g_mertens_key[h] == n { return g_mertens_val[h] }
let mut res: i64 = 1
let mut i: i64 = 2
while i <= n {
let q: i64 = n / i
let j: i64 = n / q
res = res - (j - i + 1) * mertens(q)
i = j + 1
}
g_mertens_key[h] = n
g_mertens_val[h] = res
return res
}
function squarefree_count(n: i64) -> i64 {
if n <= 0 { return 0 }
if n <= g_limit { return g_sqfree_small[n] }
let m: i64 = isqrt(n)
let mut res: i64 = 0
let mut d: i64 = 1
while d <= m {
let k: i64 = n / (d * d)
let d_max: i64 = isqrt(n / k)
res = res + (g_mertens_small[d_max] - g_mertens_small[d - 1]) * k
d = d_max + 1
}
return res
}
function count_f(n: i128) -> i64 {
let M: i64 = isqrt_i128(n)
let z_max: i64 = isqrt(M)
let c: i64 = icbrt(z_max)
let limit: i64 = c * c + 10
let sq: i64 = isqrt(z_max) + 10
if sq > limit { limit = sq }
if 1000 > limit { limit = 1000 }
mobius_sieve(limit)
g_mertens_key = calloc(MEMO_SIZE, 8)
g_mertens_val = calloc(MEMO_SIZE, 8)
let Y: i64 = icbrt(M)
let mut S0: i64 = 0
let mut S1: i64 = 0
let mut y: i64 = 1
while y <= Y {
let y3: i64 = y * y * y
let R: i64 = isqrt(M / y3)
let yp1: i64 = y + 1
let yp13: i64 = yp1 * yp1 * yp1
let L: i64
if yp13 <= M { L = isqrt(M / yp13) } else { L = 0 }
if R != L {
S0 = S0 + y * (squarefree_count(R) - squarefree_count(L))
S1 = S1 + y * (mertens(R) - mertens(L))
}
y = y + 1
}
free(g_mertens_val)
free(g_mertens_key)
free(g_sqfree_small)
free(g_mertens_small)
free(g_mu)
return (S0 + S1) / 2
}
function main() -> i32 {
let n: i128 = 1000000000000000000000000000000000000 # 10^36
printf("%lld\n", count_f(n))
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 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);
int64_t icbrt_i64(int64_t n);
int64_t isqrt_i128_i128(__int128 n);
void mobius_sieve_i64(int64_t limit);
int64_t mertens_i64(int64_t n);
int64_t squarefree_count_i64(int64_t n);
int64_t count_f_i128(__int128 n);
int32_t main(void);
static const int64_t MEMO_SIZE = 2000003;
/* Module statics */
static int8_t* g_mu = NULL;
static int64_t* g_mertens_small = NULL;
static int64_t* g_sqfree_small = NULL;
static int64_t g_limit = 0;
static int64_t* g_mertens_key = NULL;
static int64_t* g_mertens_val = NULL;
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;
}
int64_t icbrt_i64(int64_t n) {
if (n < 2) {
return n;
}
int64_t hi = 1;
int64_t bits = 0;
int64_t tmp = n;
while (tmp > 0) {
bits = (bits + 1);
tmp = FLOW_CHECKED_SHR((tmp), (1));
}
hi = FLOW_CHECKED_SHL((1), (FLOW_CHECKED_DIV(((bits + 2)), (3))));
int64_t lo = FLOW_CHECKED_SHR((hi), (1));
while ((lo + 1) < hi) {
int64_t mid = FLOW_CHECKED_SHR(((lo + hi)), (1));
int64_t m3 = ((mid * mid) * mid);
if (m3 <= n) {
lo = mid;
} else {
hi = mid;
}
}
return lo;
}
int64_t isqrt_i128_i128(__int128 n) {
if (n < 2) {
return ((int64_t)(n));
}
__int128 x = n;
__int128 y = FLOW_CHECKED_DIV(((x + 1)), (2));
while (y < x) {
x = y;
y = FLOW_CHECKED_DIV(((x + FLOW_CHECKED_DIV((n), (x)))), (2));
}
return ((int64_t)(x));
}
void mobius_sieve_i64(int64_t limit) {
g_mu = calloc((limit + 1), 1);
g_mu[1] = 1;
int64_t* primes = (int64_t*)(calloc((FLOW_CHECKED_DIV((limit), (10)) + 100), 8));
int64_t nprimes = 0;
int8_t* is_comp = (int8_t*)(calloc((limit + 1), 1));
int32_t __flow_step_1 = 1;
for (int32_t i = 2; (2 <= (limit + 1)) ? i < (limit + 1) : i > (limit + 1); i += (2 <= (limit + 1)) ? 1 : -1) {
if (is_comp[i] == 0) {
primes[nprimes] = i;
nprimes = (nprimes + 1);
g_mu[i] = (-1);
}
int32_t __flow_step_2 = 1;
for (int32_t j = 0; (0 <= nprimes) ? j < nprimes : j > nprimes; j += (0 <= nprimes) ? 1 : -1) {
int64_t p = primes[j];
int64_t ip = (i * p);
if (ip > limit) {
break;
}
is_comp[ip] = 1;
if (FLOW_CHECKED_MOD((i), (p)) == 0) {
g_mu[ip] = 0;
break;
} else {
g_mu[ip] = (-g_mu[i]);
}
}
}
g_mertens_small = calloc((limit + 1), 8);
g_sqfree_small = calloc((limit + 1), 8);
int64_t s = 0;
int64_t q = 0;
int32_t __flow_step_3 = 1;
for (int32_t i = 1; (1 <= (limit + 1)) ? i < (limit + 1) : i > (limit + 1); i += (1 <= (limit + 1)) ? 1 : -1) {
s = (s + ((int64_t)(g_mu[i])));
g_mertens_small[i] = s;
if (g_mu[i] != 0) {
q = (q + 1);
}
g_sqfree_small[i] = q;
}
g_limit = limit;
free(is_comp);
free(primes);
}
int64_t mertens_i64(int64_t n) {
if (n <= g_limit) {
return g_mertens_small[n];
}
int64_t h = FLOW_CHECKED_MOD((n), (MEMO_SIZE));
if (g_mertens_key[h] == n) {
return g_mertens_val[h];
}
int64_t res = 1;
int64_t i = 2;
while (i <= n) {
int64_t q = FLOW_CHECKED_DIV((n), (i));
int64_t j = FLOW_CHECKED_DIV((n), (q));
res = (res - (((j - i) + 1) * mertens_i64(q)));
i = (j + 1);
}
g_mertens_key[h] = n;
g_mertens_val[h] = res;
return res;
}
int64_t squarefree_count_i64(int64_t n) {
if (n <= 0) {
return 0;
}
if (n <= g_limit) {
return g_sqfree_small[n];
}
int64_t m = isqrt_i64(n);
int64_t res = 0;
int64_t d = 1;
while (d <= m) {
int64_t k = FLOW_CHECKED_DIV((n), ((d * d)));
int64_t d_max = isqrt_i64(FLOW_CHECKED_DIV((n), (k)));
res = (res + ((g_mertens_small[d_max] - g_mertens_small[(d - 1)]) * k));
d = (d_max + 1);
}
return res;
}
int64_t count_f_i128(__int128 n) {
int64_t M = isqrt_i128_i128(n);
int64_t z_max = isqrt_i64(M);
int64_t c = icbrt_i64(z_max);
int64_t limit = ((c * c) + 10);
int64_t sq = (isqrt_i64(z_max) + 10);
if (sq > limit) {
limit = sq;
}
if (1000 > limit) {
limit = 1000;
}
mobius_sieve_i64(limit);
g_mertens_key = calloc(MEMO_SIZE, 8);
g_mertens_val = calloc(MEMO_SIZE, 8);
int64_t Y = icbrt_i64(M);
int64_t S0 = 0;
int64_t S1 = 0;
int64_t y = 1;
while (y <= Y) {
int64_t y3 = ((y * y) * y);
int64_t R = isqrt_i64(FLOW_CHECKED_DIV((M), (y3)));
int64_t yp1 = (y + 1);
int64_t yp13 = ((yp1 * yp1) * yp1);
int64_t L;
if (yp13 <= M) {
L = isqrt_i64(FLOW_CHECKED_DIV((M), (yp13)));
} else {
L = 0;
}
if (R != L) {
S0 = (S0 + (y * (squarefree_count_i64(R) - squarefree_count_i64(L))));
S1 = (S1 + (y * (mertens_i64(R) - mertens_i64(L))));
}
y = (y + 1);
}
free(g_mertens_val);
free(g_mertens_key);
free(g_sqfree_small);
free(g_mertens_small);
free(g_mu);
return FLOW_CHECKED_DIV(((S0 + S1)), (2));
}
int32_t main(void) {
__int128 n = ((__int128)0xC097CE7BC90715ULL << 64 | (__int128)0xB34B9F1000000000ULL);
printf("%lld\n", count_f_i128(n));
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 @free(!llvm.ptr) -> ()
func.func private @memset(!llvm.ptr, i64, i64) -> !llvm.ptr
func.func @icbrt(%arg0: i64) -> i64 {
%175 = arith.constant 2 : i32
%177 = arith.extsi %175 : i32 to i64
%176 = arith.cmpi slt, %arg0, %177 : i64
cf.cond_br %176, ^bb42, ^bb43
^bb42:
func.return %arg0 : i64
^bb43:
cf.br ^bb44
^bb44:
%178 = arith.constant 1 : i32
%179 = arith.extsi %178 : i32 to i64
%180 = llvm.mlir.constant(1 : i64) : i64
%181 = llvm.alloca %180 x i64 : (i64) -> !llvm.ptr
llvm.store %179, %181 : i64, !llvm.ptr
%182 = arith.constant 0 : i32
%183 = arith.extsi %182 : i32 to i64
%184 = llvm.mlir.constant(1 : i64) : i64
%185 = llvm.alloca %184 x i64 : (i64) -> !llvm.ptr
llvm.store %183, %185 : i64, !llvm.ptr
%186 = llvm.mlir.constant(1 : i64) : i64
%187 = llvm.alloca %186 x i64 : (i64) -> !llvm.ptr
llvm.store %arg0, %187 : i64, !llvm.ptr
cf.br ^bb45
^bb45:
%188 = llvm.load %187 : !llvm.ptr -> i64
%189 = arith.constant 0 : i32
%191 = arith.extsi %189 : i32 to i64
%190 = arith.cmpi sgt, %188, %191 : i64
cf.cond_br %190, ^bb46, ^bb47
^bb46:
%192 = llvm.load %185 : !llvm.ptr -> i64
%193 = arith.constant 1 : i32
%195 = arith.extsi %193 : i32 to i64
%194 = arith.addi %192, %195 : i64
llvm.store %194, %185 : i64, !llvm.ptr
%196 = llvm.load %187 : !llvm.ptr -> i64
%197 = arith.constant 1 : i32
%199 = arith.extsi %197 : i32 to i64
%198 = arith.shrsi %196, %199 : i64
llvm.store %198, %187 : i64, !llvm.ptr
cf.br ^bb45
^bb47:
%200 = arith.constant 1 : i32
%201 = llvm.load %185 : !llvm.ptr -> i64
%202 = arith.constant 2 : i32
%204 = arith.extsi %202 : i32 to i64
%203 = arith.addi %201, %204 : i64
%205 = arith.constant 3 : i32
%207 = arith.extsi %205 : i32 to i64
%206 = arith.divsi %203, %207 : i64
%209 = arith.extsi %200 : i32 to i64
%208 = arith.shli %209, %206 : i64
llvm.store %208, %181 : i64, !llvm.ptr
%210 = llvm.load %181 : !llvm.ptr -> i64
%211 = arith.constant 1 : i32
%213 = arith.extsi %211 : i32 to i64
%212 = arith.shrsi %210, %213 : i64
%214 = llvm.mlir.constant(1 : i64) : i64
%215 = llvm.alloca %214 x i64 : (i64) -> !llvm.ptr
llvm.store %212, %215 : i64, !llvm.ptr
cf.br ^bb48
^bb48:
%216 = llvm.load %215 : !llvm.ptr -> i64
%217 = arith.constant 1 : i32
%219 = arith.extsi %217 : i32 to i64
%218 = arith.addi %216, %219 : i64
%220 = llvm.load %181 : !llvm.ptr -> i64
%221 = arith.cmpi slt, %218, %220 : i64
cf.cond_br %221, ^bb49, ^bb50
^bb49:
%222 = llvm.load %215 : !llvm.ptr -> i64
%223 = llvm.load %181 : !llvm.ptr -> i64
%224 = arith.addi %222, %223 : i64
%225 = arith.constant 1 : i32
%227 = arith.extsi %225 : i32 to i64
%226 = arith.shrsi %224, %227 : i64
%228 = arith.muli %226, %226 : i64
%229 = arith.muli %228, %226 : i64
%230 = arith.cmpi sle, %229, %arg0 : i64
cf.cond_br %230, ^bb51, ^bb52
^bb51:
llvm.store %226, %215 : i64, !llvm.ptr
cf.br ^bb53
^bb52:
llvm.store %226, %181 : i64, !llvm.ptr
cf.br ^bb53
^bb53:
cf.br ^bb48
^bb50:
%231 = llvm.load %215 : !llvm.ptr -> i64
func.return %231 : i64
}
func.func @isqrt_i128(%arg0: i128) -> i64 {
%232 = arith.constant 2 : i32
%234 = arith.trunci %arg0 : i128 to i64
%235 = arith.extsi %232 : i32 to i64
%233 = arith.cmpi slt, %234, %235 : i64
cf.cond_br %233, ^bb54, ^bb55
^bb54:
%236 = arith.trunci %arg0 : i128 to i64
func.return %236 : i64
^bb55:
cf.br ^bb56
^bb56:
%237 = llvm.mlir.constant(1 : i64) : i64
%238 = llvm.alloca %237 x i128 : (i64) -> !llvm.ptr
llvm.store %arg0, %238 : i128, !llvm.ptr
%239 = llvm.load %238 : !llvm.ptr -> i128
%240 = arith.constant 1 : i32
%242 = arith.trunci %239 : i128 to i64
%243 = arith.extsi %240 : i32 to i64
%241 = arith.addi %242, %243 : i64
%244 = arith.constant 2 : i32
%246 = arith.extsi %244 : i32 to i64
%245 = arith.divsi %241, %246 : i64
%247 = arith.extsi %245 : i64 to i128
%248 = llvm.mlir.constant(1 : i64) : i64
%249 = llvm.alloca %248 x i128 : (i64) -> !llvm.ptr
llvm.store %247, %249 : i128, !llvm.ptr
cf.br ^bb57
^bb57:
%250 = llvm.load %249 : !llvm.ptr -> i128
%251 = llvm.load %238 : !llvm.ptr -> i128
%253 = arith.trunci %250 : i128 to i64
%254 = arith.trunci %251 : i128 to i64
%252 = arith.cmpi slt, %253, %254 : i64
cf.cond_br %252, ^bb58, ^bb59
^bb58:
%255 = llvm.load %249 : !llvm.ptr -> i128
llvm.store %255, %238 : i128, !llvm.ptr
%256 = llvm.load %238 : !llvm.ptr -> i128
%257 = llvm.load %238 : !llvm.ptr -> i128
%259 = arith.trunci %arg0 : i128 to i64
%260 = arith.trunci %257 : i128 to i64
%258 = arith.divsi %259, %260 : i64
%262 = arith.trunci %256 : i128 to i64
%261 = arith.addi %262, %258 : i64
%263 = arith.constant 2 : i32
%265 = arith.extsi %263 : i32 to i64
%264 = arith.divsi %261, %265 : i64
%266 = arith.extsi %264 : i64 to i128
llvm.store %266, %249 : i128, !llvm.ptr
cf.br ^bb57
^bb59:
%267 = llvm.load %238 : !llvm.ptr -> i128
%268 = arith.trunci %267 : i128 to i64
func.return %268 : i64
}
// Module static: g_mu
llvm.mlir.global internal @g_mu() {addr_space = 0 : i32} : !llvm.ptr {
%269 = llvm.mlir.zero : !llvm.ptr
llvm.return %269 : !llvm.ptr
}
// Module static: g_mertens_small
llvm.mlir.global internal @g_mertens_small() {addr_space = 0 : i32} : !llvm.ptr {
%270 = llvm.mlir.zero : !llvm.ptr
llvm.return %270 : !llvm.ptr
}
// Module static: g_sqfree_small
llvm.mlir.global internal @g_sqfree_small() {addr_space = 0 : i32} : !llvm.ptr {
%271 = llvm.mlir.zero : !llvm.ptr
llvm.return %271 : !llvm.ptr
}
// Module static: g_limit
llvm.mlir.global internal @g_limit(0 : i64) : i64
func.func @mobius_sieve(%arg0: i64) -> () {
%273 = arith.constant 1 : i32
%275 = arith.extsi %273 : i32 to i64
%274 = arith.addi %arg0, %275 : i64
%276 = arith.constant 1 : i32
%277 = arith.extsi %276 : i32 to i64
%272 = func.call @calloc(%274, %277) : (i64, i64) -> !llvm.ptr
%278 = llvm.mlir.addressof @g_mu : !llvm.ptr
llvm.store %272, %278 : !llvm.ptr, !llvm.ptr
%279 = arith.constant 1 : i32
%280 = llvm.mlir.addressof @g_mu : !llvm.ptr
%281 = llvm.load %280 : !llvm.ptr -> !llvm.ptr
%282 = arith.constant 1 : i32
%283 = arith.trunci %279 : i32 to i8
%284 = arith.extsi %282 : i32 to i64
%285 = llvm.getelementptr %281[%284] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %283, %285 : i8, !llvm.ptr
%287 = arith.constant 10 : i32
%289 = arith.extsi %287 : i32 to i64
%288 = arith.divsi %arg0, %289 : i64
%290 = arith.constant 100 : i32
%292 = arith.extsi %290 : i32 to i64
%291 = arith.addi %288, %292 : i64
%293 = arith.constant 8 : i32
%294 = arith.extsi %293 : i32 to i64
%286 = func.call @calloc(%291, %294) : (i64, i64) -> !llvm.ptr
%295 = arith.constant 0 : i32
%296 = arith.extsi %295 : i32 to i64
%297 = llvm.mlir.constant(1 : i64) : i64
%298 = llvm.alloca %297 x i64 : (i64) -> !llvm.ptr
llvm.store %296, %298 : i64, !llvm.ptr
%300 = arith.constant 1 : i32
%302 = arith.extsi %300 : i32 to i64
%301 = arith.addi %arg0, %302 : i64
%303 = arith.constant 1 : i32
%304 = arith.extsi %303 : i32 to i64
%299 = func.call @calloc(%301, %304) : (i64, i64) -> !llvm.ptr
%305 = arith.constant 2 : i32
%306 = arith.constant 1 : i32
%308 = arith.extsi %306 : i32 to i64
%307 = arith.addi %arg0, %308 : i64
%309 = arith.index_cast %305 : i32 to index
%310 = arith.index_cast %307 : i32 to index
%312 = arith.constant 1 : index
%313 = arith.constant -1 : index
%314 = arith.cmpi sle, %309, %310 : index
%311 = arith.select %314, %312, %313 : index
cf.br ^bb60(%309 : index)
^bb60(%315: index):
%316 = arith.cmpi slt, %315, %310 : index
%317 = arith.cmpi sgt, %315, %310 : index
%318 = arith.select %314, %316, %317 : i1
cf.cond_br %318, ^bb61(%315 : index), ^bb62(%315 : index)
^bb61(%319: index):
%321 = arith.index_cast %319 : index to i64
%322 = llvm.getelementptr %299[%321] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%320 = llvm.load %322 : !llvm.ptr -> i8
%323 = arith.constant 0 : i32
%325 = arith.extsi %320 : i8 to i32
%324 = arith.cmpi eq, %325, %323 : i32
cf.cond_br %324, ^bb63, ^bb64
^bb63:
%326 = llvm.load %298 : !llvm.ptr -> i64
%327 = arith.index_cast %319 : index to i64
%328 = llvm.getelementptr %286[%326] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %327, %328 : i64, !llvm.ptr
%329 = llvm.load %298 : !llvm.ptr -> i64
%330 = arith.constant 1 : i32
%332 = arith.extsi %330 : i32 to i64
%331 = arith.addi %329, %332 : i64
llvm.store %331, %298 : i64, !llvm.ptr
%333 = arith.constant 1 : i32
%335 = arith.constant 0 : i32
%334 = arith.subi %335, %333 : i32
%336 = llvm.mlir.addressof @g_mu : !llvm.ptr
%337 = llvm.load %336 : !llvm.ptr -> !llvm.ptr
%338 = arith.trunci %334 : i32 to i8
%339 = arith.index_cast %319 : index to i64
%340 = llvm.getelementptr %337[%339] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %338, %340 : i8, !llvm.ptr
cf.br ^bb65
^bb64:
cf.br ^bb65
^bb65:
%341 = arith.constant 0 : i32
%342 = llvm.load %298 : !llvm.ptr -> i64
%343 = arith.index_cast %341 : i32 to index
%344 = arith.index_cast %342 : i32 to index
%346 = arith.constant 1 : index
%347 = arith.constant -1 : index
%348 = arith.cmpi sle, %343, %344 : index
%345 = arith.select %348, %346, %347 : index
cf.br ^bb66(%343 : index)
^bb66(%349: index):
%350 = arith.cmpi slt, %349, %344 : index
%351 = arith.cmpi sgt, %349, %344 : index
%352 = arith.select %348, %350, %351 : i1
cf.cond_br %352, ^bb67(%349 : index), ^bb68(%349 : index)
^bb67(%353: index):
%355 = arith.index_cast %353 : index to i64
%356 = llvm.getelementptr %286[%355] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%354 = llvm.load %356 : !llvm.ptr -> i64
%358 = arith.index_cast %319 : index to i32
%359 = arith.trunci %354 : i64 to i32
%357 = arith.muli %358, %359 : i32
%360 = arith.extsi %357 : i32 to i64
%361 = arith.cmpi sgt, %360, %arg0 : i64
cf.cond_br %361, ^bb69, ^bb70
^bb69:
cf.br ^bb68(%353 : index)
^bb70:
cf.br ^bb71
^bb71:
%362 = arith.constant 1 : i32
%363 = arith.trunci %362 : i32 to i8
%364 = llvm.getelementptr %299[%360] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %363, %364 : i8, !llvm.ptr
%366 = arith.index_cast %319 : index to i32
%367 = arith.trunci %354 : i64 to i32
%365 = arith.remsi %366, %367 : i32
%368 = arith.constant 0 : i32
%369 = arith.cmpi eq, %365, %368 : i32
cf.cond_br %369, ^bb72, ^bb73
^bb72:
%370 = arith.constant 0 : i32
%371 = llvm.mlir.addressof @g_mu : !llvm.ptr
%372 = llvm.load %371 : !llvm.ptr -> !llvm.ptr
%373 = arith.trunci %370 : i32 to i8
%374 = llvm.getelementptr %372[%360] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %373, %374 : i8, !llvm.ptr
cf.br ^bb68(%353 : index)
^bb73:
%376 = llvm.mlir.addressof @g_mu : !llvm.ptr
%377 = llvm.load %376 : !llvm.ptr -> !llvm.ptr
%378 = arith.index_cast %319 : index to i64
%379 = llvm.getelementptr %377[%378] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%375 = llvm.load %379 : !llvm.ptr -> i8
%381 = arith.constant 0 : i8
%380 = arith.subi %381, %375 : i8
%382 = llvm.mlir.addressof @g_mu : !llvm.ptr
%383 = llvm.load %382 : !llvm.ptr -> !llvm.ptr
%384 = llvm.getelementptr %383[%360] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %380, %384 : i8, !llvm.ptr
cf.br ^bb74
^bb74:
%385 = arith.addi %353, %345 : index
cf.br ^bb66(%385 : index)
^bb68(%386: index):
%387 = arith.addi %319, %311 : index
cf.br ^bb60(%387 : index)
^bb62(%388: index):
%390 = arith.constant 1 : i32
%392 = arith.extsi %390 : i32 to i64
%391 = arith.addi %arg0, %392 : i64
%393 = arith.constant 8 : i32
%394 = arith.extsi %393 : i32 to i64
%389 = func.call @calloc(%391, %394) : (i64, i64) -> !llvm.ptr
%395 = llvm.mlir.addressof @g_mertens_small : !llvm.ptr
llvm.store %389, %395 : !llvm.ptr, !llvm.ptr
%397 = arith.constant 1 : i32
%399 = arith.extsi %397 : i32 to i64
%398 = arith.addi %arg0, %399 : i64
%400 = arith.constant 8 : i32
%401 = arith.extsi %400 : i32 to i64
%396 = func.call @calloc(%398, %401) : (i64, i64) -> !llvm.ptr
%402 = llvm.mlir.addressof @g_sqfree_small : !llvm.ptr
llvm.store %396, %402 : !llvm.ptr, !llvm.ptr
%403 = arith.constant 0 : i32
%404 = arith.extsi %403 : i32 to i64
%405 = llvm.mlir.constant(1 : i64) : i64
%406 = llvm.alloca %405 x i64 : (i64) -> !llvm.ptr
llvm.store %404, %406 : i64, !llvm.ptr
%407 = arith.constant 0 : i32
%408 = arith.extsi %407 : i32 to i64
%409 = llvm.mlir.constant(1 : i64) : i64
%410 = llvm.alloca %409 x i64 : (i64) -> !llvm.ptr
llvm.store %408, %410 : i64, !llvm.ptr
%411 = arith.constant 1 : i32
%412 = arith.constant 1 : i32
%414 = arith.extsi %412 : i32 to i64
%413 = arith.addi %arg0, %414 : i64
%415 = arith.index_cast %411 : i32 to index
%416 = arith.index_cast %413 : i32 to index
%418 = arith.constant 1 : index
%419 = arith.constant -1 : index
%420 = arith.cmpi sle, %415, %416 : index
%417 = arith.select %420, %418, %419 : index
cf.br ^bb75(%415 : index)
^bb75(%421: index):
%422 = arith.cmpi slt, %421, %416 : index
%423 = arith.cmpi sgt, %421, %416 : index
%424 = arith.select %420, %422, %423 : i1
cf.cond_br %424, ^bb76(%421 : index), ^bb77(%421 : index)
^bb76(%425: index):
%426 = llvm.load %406 : !llvm.ptr -> i64
%428 = llvm.mlir.addressof @g_mu : !llvm.ptr
%429 = llvm.load %428 : !llvm.ptr -> !llvm.ptr
%430 = arith.index_cast %425 : index to i64
%431 = llvm.getelementptr %429[%430] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%427 = llvm.load %431 : !llvm.ptr -> i8
%432 = arith.extsi %427 : i8 to i64
%433 = arith.addi %426, %432 : i64
llvm.store %433, %406 : i64, !llvm.ptr
%434 = llvm.load %406 : !llvm.ptr -> i64
%435 = llvm.mlir.addressof @g_mertens_small : !llvm.ptr
%436 = llvm.load %435 : !llvm.ptr -> !llvm.ptr
%437 = arith.index_cast %425 : index to i64
%438 = llvm.getelementptr %436[%437] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %434, %438 : i64, !llvm.ptr
%440 = llvm.mlir.addressof @g_mu : !llvm.ptr
%441 = llvm.load %440 : !llvm.ptr -> !llvm.ptr
%442 = arith.index_cast %425 : index to i64
%443 = llvm.getelementptr %441[%442] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%439 = llvm.load %443 : !llvm.ptr -> i8
%444 = arith.constant 0 : i32
%446 = arith.extsi %439 : i8 to i32
%445 = arith.cmpi ne, %446, %444 : i32
cf.cond_br %445, ^bb78, ^bb79
^bb78:
%447 = llvm.load %410 : !llvm.ptr -> i64
%448 = arith.constant 1 : i32
%450 = arith.extsi %448 : i32 to i64
%449 = arith.addi %447, %450 : i64
llvm.store %449, %410 : i64, !llvm.ptr
cf.br ^bb80
^bb79:
cf.br ^bb80
^bb80:
%451 = llvm.load %410 : !llvm.ptr -> i64
%452 = llvm.mlir.addressof @g_sqfree_small : !llvm.ptr
%453 = llvm.load %452 : !llvm.ptr -> !llvm.ptr
%454 = arith.index_cast %425 : index to i64
%455 = llvm.getelementptr %453[%454] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %451, %455 : i64, !llvm.ptr
%456 = arith.addi %425, %417 : index
cf.br ^bb75(%456 : index)
^bb77(%457: index):
%458 = llvm.mlir.addressof @g_limit : !llvm.ptr
llvm.store %arg0, %458 : i64, !llvm.ptr
func.call @free(%299) : (!llvm.ptr) -> ()
func.call @free(%286) : (!llvm.ptr) -> ()
func.return
}
// Constant: MEMO_SIZE
llvm.mlir.global internal constant @MEMO_SIZE(2000003 : i64) : i64
// Module static: g_mertens_key
llvm.mlir.global internal @g_mertens_key() {addr_space = 0 : i32} : !llvm.ptr {
%461 = llvm.mlir.zero : !llvm.ptr
llvm.return %461 : !llvm.ptr
}
// Module static: g_mertens_val
llvm.mlir.global internal @g_mertens_val() {addr_space = 0 : i32} : !llvm.ptr {
%462 = llvm.mlir.zero : !llvm.ptr
llvm.return %462 : !llvm.ptr
}
func.func @mertens(%arg0: i64) -> i64 {
%463 = llvm.mlir.addressof @g_limit : !llvm.ptr
%464 = llvm.load %463 : !llvm.ptr -> i64
%465 = arith.cmpi sle, %arg0, %464 : i64
cf.cond_br %465, ^bb81, ^bb82
^bb81:
%467 = llvm.mlir.addressof @g_mertens_small : !llvm.ptr
%468 = llvm.load %467 : !llvm.ptr -> !llvm.ptr
%469 = llvm.getelementptr %468[%arg0] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%466 = llvm.load %469 : !llvm.ptr -> i64
func.return %466 : i64
^bb82:
cf.br ^bb83
^bb83:
%470 = llvm.mlir.addressof @MEMO_SIZE : !llvm.ptr
%471 = llvm.load %470 : !llvm.ptr -> i64
%472 = arith.remsi %arg0, %471 : i64
%474 = llvm.mlir.addressof @g_mertens_key : !llvm.ptr
%475 = llvm.load %474 : !llvm.ptr -> !llvm.ptr
%476 = llvm.getelementptr %475[%472] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%473 = llvm.load %476 : !llvm.ptr -> i64
%477 = arith.cmpi eq, %473, %arg0 : i64
cf.cond_br %477, ^bb84, ^bb85
^bb84:
%479 = llvm.mlir.addressof @g_mertens_val : !llvm.ptr
%480 = llvm.load %479 : !llvm.ptr -> !llvm.ptr
%481 = llvm.getelementptr %480[%472] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%478 = llvm.load %481 : !llvm.ptr -> i64
func.return %478 : i64
^bb85:
cf.br ^bb86
^bb86:
%482 = arith.constant 1 : i32
%483 = arith.extsi %482 : i32 to i64
%484 = llvm.mlir.constant(1 : i64) : i64
%485 = llvm.alloca %484 x i64 : (i64) -> !llvm.ptr
llvm.store %483, %485 : i64, !llvm.ptr
%486 = arith.constant 2 : i32
%487 = arith.extsi %486 : i32 to i64
%488 = llvm.mlir.constant(1 : i64) : i64
%489 = llvm.alloca %488 x i64 : (i64) -> !llvm.ptr
llvm.store %487, %489 : i64, !llvm.ptr
cf.br ^bb87
^bb87:
%490 = llvm.load %489 : !llvm.ptr -> i64
%491 = arith.cmpi sle, %490, %arg0 : i64
cf.cond_br %491, ^bb88, ^bb89
^bb88:
%492 = llvm.load %489 : !llvm.ptr -> i64
%493 = arith.divsi %arg0, %492 : i64
%494 = arith.divsi %arg0, %493 : i64
%495 = llvm.load %485 : !llvm.ptr -> i64
%496 = llvm.load %489 : !llvm.ptr -> i64
%497 = arith.subi %494, %496 : i64
%498 = arith.constant 1 : i32
%500 = arith.extsi %498 : i32 to i64
%499 = arith.addi %497, %500 : i64
%501 = func.call @mertens(%493) : (i64) -> i64
%502 = arith.muli %499, %501 : i64
%503 = arith.subi %495, %502 : i64
llvm.store %503, %485 : i64, !llvm.ptr
%504 = arith.constant 1 : i32
%506 = arith.extsi %504 : i32 to i64
%505 = arith.addi %494, %506 : i64
llvm.store %505, %489 : i64, !llvm.ptr
cf.br ^bb87
^bb89:
%507 = llvm.mlir.addressof @g_mertens_key : !llvm.ptr
%508 = llvm.load %507 : !llvm.ptr -> !llvm.ptr
%509 = llvm.getelementptr %508[%472] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %arg0, %509 : i64, !llvm.ptr
%510 = llvm.load %485 : !llvm.ptr -> i64
%511 = llvm.mlir.addressof @g_mertens_val : !llvm.ptr
%512 = llvm.load %511 : !llvm.ptr -> !llvm.ptr
%513 = llvm.getelementptr %512[%472] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %510, %513 : i64, !llvm.ptr
%514 = llvm.load %485 : !llvm.ptr -> i64
func.return %514 : i64
}
func.func @squarefree_count(%arg0: i64) -> i64 {
%515 = arith.constant 0 : i32
%517 = arith.extsi %515 : i32 to i64
%516 = arith.cmpi sle, %arg0, %517 : i64
cf.cond_br %516, ^bb90, ^bb91
^bb90:
%518 = arith.constant 0 : i32
%519 = arith.extsi %518 : i32 to i64
func.return %519 : i64
^bb91:
cf.br ^bb92
^bb92:
%520 = llvm.mlir.addressof @g_limit : !llvm.ptr
%521 = llvm.load %520 : !llvm.ptr -> i64
%522 = arith.cmpi sle, %arg0, %521 : i64
cf.cond_br %522, ^bb93, ^bb94
^bb93:
%524 = llvm.mlir.addressof @g_sqfree_small : !llvm.ptr
%525 = llvm.load %524 : !llvm.ptr -> !llvm.ptr
%526 = llvm.getelementptr %525[%arg0] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%523 = llvm.load %526 : !llvm.ptr -> i64
func.return %523 : i64
^bb94:
cf.br ^bb95
^bb95:
%527 = func.call @isqrt(%arg0) : (i64) -> i64
%528 = arith.constant 0 : i32
%529 = arith.extsi %528 : i32 to i64
%530 = llvm.mlir.constant(1 : i64) : i64
%531 = llvm.alloca %530 x i64 : (i64) -> !llvm.ptr
llvm.store %529, %531 : i64, !llvm.ptr
%532 = arith.constant 1 : i32
%533 = arith.extsi %532 : i32 to i64
%534 = llvm.mlir.constant(1 : i64) : i64
%535 = llvm.alloca %534 x i64 : (i64) -> !llvm.ptr
llvm.store %533, %535 : i64, !llvm.ptr
cf.br ^bb96
^bb96:
%536 = llvm.load %535 : !llvm.ptr -> i64
%537 = arith.cmpi sle, %536, %527 : i64
cf.cond_br %537, ^bb97, ^bb98
^bb97:
%538 = llvm.load %535 : !llvm.ptr -> i64
%539 = llvm.load %535 : !llvm.ptr -> i64
%540 = arith.muli %538, %539 : i64
%541 = arith.divsi %arg0, %540 : i64
%543 = arith.divsi %arg0, %541 : i64
%542 = func.call @isqrt(%543) : (i64) -> i64
%544 = llvm.load %531 : !llvm.ptr -> i64
%546 = llvm.mlir.addressof @g_mertens_small : !llvm.ptr
%547 = llvm.load %546 : !llvm.ptr -> !llvm.ptr
%548 = llvm.getelementptr %547[%542] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%545 = llvm.load %548 : !llvm.ptr -> i64
%550 = llvm.mlir.addressof @g_mertens_small : !llvm.ptr
%551 = llvm.load %550 : !llvm.ptr -> !llvm.ptr
%552 = llvm.load %535 : !llvm.ptr -> i64
%553 = arith.constant 1 : i32
%555 = arith.extsi %553 : i32 to i64
%554 = arith.subi %552, %555 : i64
%556 = llvm.getelementptr %551[%554] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%549 = llvm.load %556 : !llvm.ptr -> i64
%557 = arith.subi %545, %549 : i64
%558 = arith.muli %557, %541 : i64
%559 = arith.addi %544, %558 : i64
llvm.store %559, %531 : i64, !llvm.ptr
%560 = arith.constant 1 : i32
%562 = arith.extsi %560 : i32 to i64
%561 = arith.addi %542, %562 : i64
llvm.store %561, %535 : i64, !llvm.ptr
cf.br ^bb96
^bb98:
%563 = llvm.load %531 : !llvm.ptr -> i64
func.return %563 : i64
}
func.func @count_f(%arg0: i128) -> i64 {
%564 = func.call @isqrt_i128(%arg0) : (i128) -> i64
%565 = func.call @isqrt(%564) : (i64) -> i64
%566 = func.call @icbrt(%565) : (i64) -> i64
%567 = arith.muli %566, %566 : i64
%568 = arith.constant 10 : i32
%570 = arith.extsi %568 : i32 to i64
%569 = arith.addi %567, %570 : i64
%571 = func.call @isqrt(%565) : (i64) -> i64
%572 = arith.constant 10 : i32
%574 = arith.extsi %572 : i32 to i64
%573 = arith.addi %571, %574 : i64
%575 = arith.cmpi sgt, %573, %569 : i64
%576 = scf.if %575 -> (i64) {
scf.yield %573 : i64
} else {
scf.yield %569 : i64
}
%577 = arith.constant 1000 : i32
%579 = arith.extsi %577 : i32 to i64
%578 = arith.cmpi sgt, %579, %576 : i64
%580 = scf.if %578 -> (i64) {
%581 = arith.constant 1000 : i32
%582 = arith.extsi %581 : i32 to i64
scf.yield %582 : i64
} else {
scf.yield %576 : i64
}
func.call @mobius_sieve(%580) : (i64) -> ()
%585 = llvm.mlir.addressof @MEMO_SIZE : !llvm.ptr
%586 = llvm.load %585 : !llvm.ptr -> i64
%587 = arith.constant 8 : i32
%588 = arith.extsi %587 : i32 to i64
%584 = func.call @calloc(%586, %588) : (i64, i64) -> !llvm.ptr
%589 = llvm.mlir.addressof @g_mertens_key : !llvm.ptr
llvm.store %584, %589 : !llvm.ptr, !llvm.ptr
%591 = llvm.mlir.addressof @MEMO_SIZE : !llvm.ptr
%592 = llvm.load %591 : !llvm.ptr -> i64
%593 = arith.constant 8 : i32
%594 = arith.extsi %593 : i32 to i64
%590 = func.call @calloc(%592, %594) : (i64, i64) -> !llvm.ptr
%595 = llvm.mlir.addressof @g_mertens_val : !llvm.ptr
llvm.store %590, %595 : !llvm.ptr, !llvm.ptr
%596 = func.call @icbrt(%564) : (i64) -> i64
%597 = arith.constant 0 : i32
%598 = arith.extsi %597 : i32 to i64
%599 = llvm.mlir.constant(1 : i64) : i64
%600 = llvm.alloca %599 x i64 : (i64) -> !llvm.ptr
llvm.store %598, %600 : i64, !llvm.ptr
%601 = arith.constant 0 : i32
%602 = arith.extsi %601 : i32 to i64
%603 = llvm.mlir.constant(1 : i64) : i64
%604 = llvm.alloca %603 x i64 : (i64) -> !llvm.ptr
llvm.store %602, %604 : i64, !llvm.ptr
%605 = arith.constant 1 : i32
%606 = arith.extsi %605 : i32 to i64
%607 = llvm.mlir.constant(1 : i64) : i64
%608 = llvm.alloca %607 x i64 : (i64) -> !llvm.ptr
llvm.store %606, %608 : i64, !llvm.ptr
cf.br ^bb99
^bb99:
%609 = llvm.load %608 : !llvm.ptr -> i64
%610 = arith.cmpi sle, %609, %596 : i64
cf.cond_br %610, ^bb100, ^bb101
^bb100:
%611 = llvm.load %608 : !llvm.ptr -> i64
%612 = llvm.load %608 : !llvm.ptr -> i64
%613 = arith.muli %611, %612 : i64
%614 = llvm.load %608 : !llvm.ptr -> i64
%615 = arith.muli %613, %614 : i64
%617 = arith.divsi %564, %615 : i64
%616 = func.call @isqrt(%617) : (i64) -> i64
%618 = llvm.load %608 : !llvm.ptr -> i64
%619 = arith.constant 1 : i32
%621 = arith.extsi %619 : i32 to i64
%620 = arith.addi %618, %621 : i64
%622 = arith.muli %620, %620 : i64
%623 = arith.muli %622, %620 : i64
%624 = llvm.mlir.undef : i64
%625 = arith.cmpi sle, %623, %564 : i64
%626 = scf.if %625 -> (i64) {
%628 = arith.divsi %564, %623 : i64
%627 = func.call @isqrt(%628) : (i64) -> i64
scf.yield %627 : i64
} else {
%629 = arith.constant 0 : i32
%630 = arith.extsi %629 : i32 to i64
scf.yield %630 : i64
}
%631 = arith.cmpi ne, %616, %626 : i64
cf.cond_br %631, ^bb102, ^bb103
^bb102:
%632 = llvm.load %600 : !llvm.ptr -> i64
%633 = llvm.load %608 : !llvm.ptr -> i64
%634 = func.call @squarefree_count(%616) : (i64) -> i64
%635 = func.call @squarefree_count(%626) : (i64) -> i64
%636 = arith.subi %634, %635 : i64
%637 = arith.muli %633, %636 : i64
%638 = arith.addi %632, %637 : i64
llvm.store %638, %600 : i64, !llvm.ptr
%639 = llvm.load %604 : !llvm.ptr -> i64
%640 = llvm.load %608 : !llvm.ptr -> i64
%641 = func.call @mertens(%616) : (i64) -> i64
%642 = func.call @mertens(%626) : (i64) -> i64
%643 = arith.subi %641, %642 : i64
%644 = arith.muli %640, %643 : i64
%645 = arith.addi %639, %644 : i64
llvm.store %645, %604 : i64, !llvm.ptr
cf.br ^bb104
^bb103:
cf.br ^bb104
^bb104:
%646 = llvm.load %608 : !llvm.ptr -> i64
%647 = arith.constant 1 : i32
%649 = arith.extsi %647 : i32 to i64
%648 = arith.addi %646, %649 : i64
llvm.store %648, %608 : i64, !llvm.ptr
cf.br ^bb99
^bb101:
%651 = llvm.mlir.addressof @g_mertens_val : !llvm.ptr
%652 = llvm.load %651 : !llvm.ptr -> !llvm.ptr
func.call @free(%652) : (!llvm.ptr) -> ()
%654 = llvm.mlir.addressof @g_mertens_key : !llvm.ptr
%655 = llvm.load %654 : !llvm.ptr -> !llvm.ptr
func.call @free(%655) : (!llvm.ptr) -> ()
%657 = llvm.mlir.addressof @g_sqfree_small : !llvm.ptr
%658 = llvm.load %657 : !llvm.ptr -> !llvm.ptr
func.call @free(%658) : (!llvm.ptr) -> ()
%660 = llvm.mlir.addressof @g_mertens_small : !llvm.ptr
%661 = llvm.load %660 : !llvm.ptr -> !llvm.ptr
func.call @free(%661) : (!llvm.ptr) -> ()
%663 = llvm.mlir.addressof @g_mu : !llvm.ptr
%664 = llvm.load %663 : !llvm.ptr -> !llvm.ptr
func.call @free(%664) : (!llvm.ptr) -> ()
%665 = llvm.load %600 : !llvm.ptr -> i64
%666 = llvm.load %604 : !llvm.ptr -> i64
%667 = arith.addi %665, %666 : i64
%668 = arith.constant 2 : i32
%670 = arith.extsi %668 : i32 to i64
%669 = arith.divsi %667, %670 : i64
func.return %669 : i64
}
func.func @main() -> i32 {
%671 = arith.constant 999999999999999999999999995705032704 : i32
%672 = arith.extsi %671 : i32 to i128
%673 = llvm.mlir.addressof @str_0 : !llvm.ptr
%674 = func.call @count_f(%672) : (i128) -> i64
%675 = llvm.call @printf(%673, %674) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
%676 = arith.constant 0 : i32
func.return %676 : i32
}
}