← All problems
Problem 883
Remarkable Triangles: count triangles on the hexagonal lattice with lattice-point incenter and inradius <= 10^6.
View problem on Project Euler
Performance comparison
Metric Our solution Best known
Time complexity O(n^2)O(n^2)
Space complexity O(n^2)O(n^2)
Approach Flow solution Combinatorial or DP counting
Verdict Optimal
Flow source
# Project Euler 883
# Remarkable Triangles: count triangles on the hexagonal lattice with
# lattice-point incenter and inradius <= 10^6.
extern {
function calloc(n: i64, size: i64) -> ptr<void>
function free(p: ptr<void>) -> void
function sqrt(x: f64) -> f64
}
# Cache for count_hex_points_leq
const CACHE_CAP: i64 = 1048576
const CACHE_MASK: i64 = 1048575
let mut g_cache_key: ptr<i64> = null
let mut g_cache_val: ptr<i64> = null
let mut g_cache_used: ptr<i8> = null
function isqrt_u64(n: i64) -> i64 {
if n == 0 { return 0 }
let mut x: i64 = sqrt(n as f64) as i64
while x * x > n { x = x - 1 }
while (x + 1) * (x + 1) <= n { x = x + 1 }
return x
}
function gcd_u64(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 cache_hash(key: i64) -> i64 {
let h: i64 = key ^ (key >> 16)
let h2: i64 = h * 2654435761
let h3: i64 = h2 ^ (h2 >> 16)
return h3 & CACHE_MASK
}
function cache_lookup(key: i64, found: ptr<i32>) -> i64 {
let mut h: i64 = cache_hash(key)
while g_cache_used[h] != 0 {
if g_cache_key[h] == key {
found[0] = 1
return g_cache_val[h]
}
h = (h + 1) & CACHE_MASK
}
found[0] = 0
return 0
}
function cache_insert(key: i64, val: i64) -> void {
let mut h: i64 = cache_hash(key)
while g_cache_used[h] != 0 {
if g_cache_key[h] == key {
g_cache_val[h] = val
return
}
h = (h + 1) & CACHE_MASK
}
g_cache_used[h] = 1
g_cache_key[h] = key
g_cache_val[h] = val
}
function chi_prefix(m: i64) -> i64 {
return (m + 2) / 3 - (m + 1) / 3
}
function count_hex_points_leq(B: i64) -> i64 {
if B == 0 { return 1 }
let found: ptr<i32> = calloc(1, 4)
let hit: i64 = cache_lookup(B, found)
if found[0] == 1 {
free(found)
return hit
}
free(found)
let mut total: i64 = 0
let n: i64 = B
let mut i: i64 = 1
while i <= n {
let q: i64 = n / i
let j: i64 = n / q
total = total + q * (chi_prefix(j) - chi_prefix(i - 1))
i = j + 1
}
let res: i64 = 1 + 6 * total
cache_insert(B, res)
return res
}
function remarkable_triangles(R_num: i64, R_den: i64) -> i64 {
let C_num: i64 = 12 * R_num * R_num
let C_den: i64 = R_den * R_den
let Dmax: i64 = isqrt_u64(C_num / C_den)
let M: ptr<i32> = calloc(Dmax + 1, 4)
# Family 1: d = 3*t, multiplicity = 2^{omega(t)-1} where t % 3 != 1
let Nmax: i64 = Dmax / 3
let omega: ptr<i8> = calloc(Nmax + 1, 1)
let mut p: i64 = 2
while p <= Nmax {
if omega[p] == 0 {
let mut k: i64 = p
while k <= Nmax {
omega[k] = omega[k] + 1
k = k + p
}
}
p = p + 1
}
let mut t: i64 = 2
while t <= Nmax {
if t % 3 != 1 {
M[3 * t] = M[3 * t] + (1 << (omega[t] - 1))
}
t = t + 1
}
free(omega)
# Family 2: d = a*(a+3v), gcd(u,v)=1, u mod 3 != v mod 3
let D: i64 = Dmax
let vmax: i64 = D / 3
let mut v: i64 = 1
while v <= vmax {
let disc: i64 = 9 * v * v + 4 * D
let sq: i64 = isqrt_u64(disc)
let amax: i64 = (sq - 3 * v) / 2
if amax <= 0 { v = v + 1; continue }
let mut a: i64 = 1
while a <= amax {
let u: i64 = v + a
if u % 3 != v % 3 {
if gcd_u64(u, v) == 1 {
let d: i64 = a * (a + 3 * v)
M[d] = M[d] + 1
}
}
a = a + 1
}
v = v + 1
}
# Sum contributions over d
let mut total_scalene: i64 = 0
let mut d: i64 = 1
while d <= Dmax {
let mult: i32 = M[d]
if mult == 0 { d = d + 1; continue }
let B: i64 = C_num / (C_den * d * d)
if B == 0 { d = d + 1; continue }
let pts: i64 = 0
if d % 3 == 0 {
pts = count_hex_points_leq(B) - 1
} else {
pts = count_hex_points_leq(B / 3) - 1
}
total_scalene = total_scalene + 2 * (mult as i64) * pts
d = d + 1
}
# Equilateral triangles
let Beq: i64 = (4 * R_num * R_num) / (R_den * R_den)
let equi_points: i64 = count_hex_points_leq(Beq) - 1
let total_equilateral: i64 = equi_points / 3
free(M)
return total_scalene + total_equilateral
}
function main() -> i32 {
g_cache_key = calloc(CACHE_CAP, 8)
g_cache_val = calloc(CACHE_CAP, 8)
g_cache_used = calloc(CACHE_CAP, 1)
let ans: i64 = remarkable_triangles(1000000, 1)
printf("%lld\n", ans)
free(g_cache_key)
free(g_cache_val)
free(g_cache_used)
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 isqrt_u64_i64(int64_t n);
int64_t gcd_u64_i64_i64(int64_t a0, int64_t b0);
int64_t cache_hash_i64(int64_t key);
int64_t cache_lookup_i64_ptr_i32(int64_t key, int32_t* found);
void cache_insert_i64_i64(int64_t key, int64_t val);
int64_t chi_prefix_i64(int64_t m);
int64_t count_hex_points_leq_i64(int64_t B);
int64_t remarkable_triangles_i64_i64(int64_t R_num, int64_t R_den);
int32_t main(void);
static const int64_t CACHE_CAP = 1048576;
static const int64_t CACHE_MASK = 1048575;
/* Module statics */
static int64_t* g_cache_key = NULL;
static int64_t* g_cache_val = NULL;
static int8_t* g_cache_used = NULL;
int64_t isqrt_u64_i64(int64_t n) {
if (n == 0) {
return 0;
}
int64_t x = ((int64_t)(sqrt(((double)(n)))));
while ((x * x) > n) {
x = (x - 1);
}
while (((x + 1) * (x + 1)) <= n) {
x = (x + 1);
}
return x;
}
int64_t gcd_u64_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 cache_hash_i64(int64_t key) {
int64_t h = (key ^ FLOW_CHECKED_SHR((key), (16)));
int64_t h2 = (h * 2654435761);
int64_t h3 = (h2 ^ FLOW_CHECKED_SHR((h2), (16)));
return (h3 & CACHE_MASK);
}
int64_t cache_lookup_i64_ptr_i32(int64_t key, int32_t* found) {
int64_t h = cache_hash_i64(key);
while (g_cache_used[h] != 0) {
if (g_cache_key[h] == key) {
found[0] = 1;
return g_cache_val[h];
}
h = ((h + 1) & CACHE_MASK);
}
found[0] = 0;
return 0;
}
void cache_insert_i64_i64(int64_t key, int64_t val) {
int64_t h = cache_hash_i64(key);
while (g_cache_used[h] != 0) {
if (g_cache_key[h] == key) {
g_cache_val[h] = val;
return;
}
h = ((h + 1) & CACHE_MASK);
}
g_cache_used[h] = 1;
g_cache_key[h] = key;
g_cache_val[h] = val;
}
int64_t chi_prefix_i64(int64_t m) {
return (FLOW_CHECKED_DIV(((m + 2)), (3)) - FLOW_CHECKED_DIV(((m + 1)), (3)));
}
int64_t count_hex_points_leq_i64(int64_t B) {
if (B == 0) {
return 1;
}
int32_t* found = (int32_t*)(calloc(1, 4));
int64_t hit = cache_lookup_i64_ptr_i32(B, found);
if (found[0] == 1) {
free(found);
return hit;
}
free(found);
int64_t total = 0;
int64_t n = B;
int64_t i = 1;
while (i <= n) {
int64_t q = FLOW_CHECKED_DIV((n), (i));
int64_t j = FLOW_CHECKED_DIV((n), (q));
total = (total + (q * (chi_prefix_i64(j) - chi_prefix_i64((i - 1)))));
i = (j + 1);
}
int64_t res = (1 + (6 * total));
cache_insert_i64_i64(B, res);
return res;
}
int64_t remarkable_triangles_i64_i64(int64_t R_num, int64_t R_den) {
int64_t C_num = ((12 * R_num) * R_num);
int64_t C_den = (R_den * R_den);
int64_t Dmax = isqrt_u64_i64(FLOW_CHECKED_DIV((C_num), (C_den)));
int32_t* M = (int32_t*)(calloc((Dmax + 1), 4));
int64_t Nmax = FLOW_CHECKED_DIV((Dmax), (3));
int8_t* omega = (int8_t*)(calloc((Nmax + 1), 1));
int64_t p = 2;
while (p <= Nmax) {
if (omega[p] == 0) {
int64_t k = p;
while (k <= Nmax) {
omega[k] = (omega[k] + 1);
k = (k + p);
}
}
p = (p + 1);
}
int64_t t = 2;
while (t <= Nmax) {
if (FLOW_CHECKED_MOD((t), (3)) != 1) {
M[(3 * t)] = (M[(3 * t)] + FLOW_CHECKED_SHL((1), ((omega[t] - 1))));
}
t = (t + 1);
}
free(omega);
int64_t D = Dmax;
int64_t vmax = FLOW_CHECKED_DIV((D), (3));
int64_t v = 1;
while (v <= vmax) {
int64_t disc = (((9 * v) * v) + (4 * D));
int64_t sq = isqrt_u64_i64(disc);
int64_t amax = FLOW_CHECKED_DIV(((sq - (3 * v))), (2));
if (amax <= 0) {
v = (v + 1);
continue;
}
int64_t a = 1;
while (a <= amax) {
int64_t u = (v + a);
if (FLOW_CHECKED_MOD((u), (3)) != FLOW_CHECKED_MOD((v), (3))) {
if (gcd_u64_i64_i64(u, v) == 1) {
int64_t d = (a * (a + (3 * v)));
M[d] = (M[d] + 1);
}
}
a = (a + 1);
}
v = (v + 1);
}
int64_t total_scalene = 0;
int64_t d = 1;
while (d <= Dmax) {
int32_t mult = M[d];
if (mult == 0) {
d = (d + 1);
continue;
}
int64_t B = FLOW_CHECKED_DIV((C_num), (((C_den * d) * d)));
if (B == 0) {
d = (d + 1);
continue;
}
int64_t pts = 0;
if (FLOW_CHECKED_MOD((d), (3)) == 0) {
pts = (count_hex_points_leq_i64(B) - 1);
} else {
pts = (count_hex_points_leq_i64(FLOW_CHECKED_DIV((B), (3))) - 1);
}
total_scalene = (total_scalene + ((2 * ((int64_t)(mult))) * pts));
d = (d + 1);
}
int64_t Beq = FLOW_CHECKED_DIV((((4 * R_num) * R_num)), ((R_den * R_den)));
int64_t equi_points = (count_hex_points_leq_i64(Beq) - 1);
int64_t total_equilateral = FLOW_CHECKED_DIV((equi_points), (3));
free(M);
return (total_scalene + total_equilateral);
}
int32_t main(void) {
g_cache_key = calloc(CACHE_CAP, 8);
g_cache_val = calloc(CACHE_CAP, 8);
g_cache_used = calloc(CACHE_CAP, 1);
int64_t ans = remarkable_triangles_i64_i64(1000000, 1);
printf("%lld\n", ans);
free(g_cache_key);
free(g_cache_val);
free(g_cache_used);
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 @free(!llvm.ptr) -> ()
func.func private @sqrt(f64) -> f64
// Constant: CACHE_CAP
llvm.mlir.global internal constant @CACHE_CAP(1048576 : i64) : i64
// Constant: CACHE_MASK
llvm.mlir.global internal constant @CACHE_MASK(1048575 : i64) : i64
// Module static: g_cache_key
llvm.mlir.global internal @g_cache_key() {addr_space = 0 : i32} : !llvm.ptr {
%0 = llvm.mlir.zero : !llvm.ptr
llvm.return %0 : !llvm.ptr
}
// Module static: g_cache_val
llvm.mlir.global internal @g_cache_val() {addr_space = 0 : i32} : !llvm.ptr {
%1 = llvm.mlir.zero : !llvm.ptr
llvm.return %1 : !llvm.ptr
}
// Module static: g_cache_used
llvm.mlir.global internal @g_cache_used() {addr_space = 0 : i32} : !llvm.ptr {
%2 = llvm.mlir.zero : !llvm.ptr
llvm.return %2 : !llvm.ptr
}
func.func @isqrt_u64(%arg0: i64) -> i64 {
%3 = arith.constant 0 : i32
%5 = arith.extsi %3 : i32 to i64
%4 = arith.cmpi eq, %arg0, %5 : i64
cf.cond_br %4, ^bb0, ^bb1
^bb0:
%6 = arith.constant 0 : i32
%7 = arith.extsi %6 : i32 to i64
func.return %7 : i64
^bb1:
cf.br ^bb2
^bb2:
%8 = arith.sitofp %arg0 : i64 to f64
%9 = math.sqrt %8 : f64
%10 = arith.fptosi %9 : f64 to i64
%11 = llvm.mlir.constant(1 : i64) : i64
%12 = llvm.alloca %11 x i64 : (i64) -> !llvm.ptr
llvm.store %10, %12 : i64, !llvm.ptr
cf.br ^bb3
^bb3:
%13 = llvm.load %12 : !llvm.ptr -> i64
%14 = llvm.load %12 : !llvm.ptr -> i64
%15 = arith.muli %13, %14 : i64
%16 = arith.cmpi sgt, %15, %arg0 : i64
cf.cond_br %16, ^bb4, ^bb5
^bb4:
%17 = llvm.load %12 : !llvm.ptr -> i64
%18 = arith.constant 1 : i32
%20 = arith.extsi %18 : i32 to i64
%19 = arith.subi %17, %20 : i64
llvm.store %19, %12 : i64, !llvm.ptr
cf.br ^bb3
^bb5:
cf.br ^bb6
^bb6:
%21 = llvm.load %12 : !llvm.ptr -> i64
%22 = arith.constant 1 : i32
%24 = arith.extsi %22 : i32 to i64
%23 = arith.addi %21, %24 : i64
%25 = llvm.load %12 : !llvm.ptr -> i64
%26 = arith.constant 1 : i32
%28 = arith.extsi %26 : i32 to i64
%27 = arith.addi %25, %28 : i64
%29 = arith.muli %23, %27 : i64
%30 = arith.cmpi sle, %29, %arg0 : i64
cf.cond_br %30, ^bb7, ^bb8
^bb7:
%31 = llvm.load %12 : !llvm.ptr -> i64
%32 = arith.constant 1 : i32
%34 = arith.extsi %32 : i32 to i64
%33 = arith.addi %31, %34 : i64
llvm.store %33, %12 : i64, !llvm.ptr
cf.br ^bb6
^bb8:
%35 = llvm.load %12 : !llvm.ptr -> i64
func.return %35 : i64
}
func.func @gcd_u64(%arg0: i64, %arg1: i64) -> i64 {
%36 = llvm.mlir.constant(1 : i64) : i64
%37 = llvm.alloca %36 x i64 : (i64) -> !llvm.ptr
llvm.store %arg0, %37 : i64, !llvm.ptr
%38 = llvm.mlir.constant(1 : i64) : i64
%39 = llvm.alloca %38 x i64 : (i64) -> !llvm.ptr
llvm.store %arg1, %39 : i64, !llvm.ptr
cf.br ^bb9
^bb9:
%40 = llvm.load %39 : !llvm.ptr -> i64
%41 = arith.constant 0 : i32
%43 = arith.extsi %41 : i32 to i64
%42 = arith.cmpi ne, %40, %43 : i64
cf.cond_br %42, ^bb10, ^bb11
^bb10:
%44 = llvm.load %37 : !llvm.ptr -> i64
%45 = llvm.load %39 : !llvm.ptr -> i64
%46 = arith.remsi %44, %45 : i64
%47 = llvm.load %39 : !llvm.ptr -> i64
llvm.store %47, %37 : i64, !llvm.ptr
llvm.store %46, %39 : i64, !llvm.ptr
cf.br ^bb9
^bb11:
%48 = llvm.load %37 : !llvm.ptr -> i64
func.return %48 : i64
}
func.func @cache_hash(%arg0: i64) -> i64 {
%49 = arith.constant 16 : i32
%51 = arith.extsi %49 : i32 to i64
%50 = arith.shrsi %arg0, %51 : i64
%52 = arith.xori %arg0, %50 : i64
%53 = arith.constant -1640531535 : i32
%55 = arith.extsi %53 : i32 to i64
%54 = arith.muli %52, %55 : i64
%56 = arith.constant 16 : i32
%58 = arith.extsi %56 : i32 to i64
%57 = arith.shrsi %54, %58 : i64
%59 = arith.xori %54, %57 : i64
%60 = llvm.mlir.addressof @CACHE_MASK : !llvm.ptr
%61 = llvm.load %60 : !llvm.ptr -> i64
%62 = arith.andi %59, %61 : i64
func.return %62 : i64
}
func.func @cache_lookup(%arg0: i64, %arg1: !llvm.ptr) -> i64 {
%63 = func.call @cache_hash(%arg0) : (i64) -> i64
%64 = llvm.mlir.constant(1 : i64) : i64
%65 = llvm.alloca %64 x i64 : (i64) -> !llvm.ptr
llvm.store %63, %65 : i64, !llvm.ptr
cf.br ^bb12
^bb12:
%67 = llvm.mlir.addressof @g_cache_used : !llvm.ptr
%68 = llvm.load %67 : !llvm.ptr -> !llvm.ptr
%69 = llvm.load %65 : !llvm.ptr -> i64
%70 = llvm.getelementptr %68[%69] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%66 = llvm.load %70 : !llvm.ptr -> i8
%71 = arith.constant 0 : i32
%73 = arith.extsi %66 : i8 to i32
%72 = arith.cmpi ne, %73, %71 : i32
cf.cond_br %72, ^bb13, ^bb14
^bb13:
%75 = llvm.mlir.addressof @g_cache_key : !llvm.ptr
%76 = llvm.load %75 : !llvm.ptr -> !llvm.ptr
%77 = llvm.load %65 : !llvm.ptr -> i64
%78 = llvm.getelementptr %76[%77] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%74 = llvm.load %78 : !llvm.ptr -> i64
%79 = arith.cmpi eq, %74, %arg0 : i64
cf.cond_br %79, ^bb15, ^bb16
^bb15:
%80 = arith.constant 1 : i32
%81 = arith.constant 0 : i32
%82 = arith.extsi %81 : i32 to i64
%83 = llvm.getelementptr %arg1[%82] : (!llvm.ptr, i64) -> !llvm.ptr, i32
llvm.store %80, %83 : i32, !llvm.ptr
%85 = llvm.mlir.addressof @g_cache_val : !llvm.ptr
%86 = llvm.load %85 : !llvm.ptr -> !llvm.ptr
%87 = llvm.load %65 : !llvm.ptr -> i64
%88 = llvm.getelementptr %86[%87] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%84 = llvm.load %88 : !llvm.ptr -> i64
func.return %84 : i64
^bb16:
cf.br ^bb17
^bb17:
%89 = llvm.load %65 : !llvm.ptr -> i64
%90 = arith.constant 1 : i32
%92 = arith.extsi %90 : i32 to i64
%91 = arith.addi %89, %92 : i64
%93 = llvm.mlir.addressof @CACHE_MASK : !llvm.ptr
%94 = llvm.load %93 : !llvm.ptr -> i64
%95 = arith.andi %91, %94 : i64
llvm.store %95, %65 : i64, !llvm.ptr
cf.br ^bb12
^bb14:
%96 = arith.constant 0 : i32
%97 = arith.constant 0 : i32
%98 = arith.extsi %97 : i32 to i64
%99 = llvm.getelementptr %arg1[%98] : (!llvm.ptr, i64) -> !llvm.ptr, i32
llvm.store %96, %99 : i32, !llvm.ptr
%100 = arith.constant 0 : i32
%101 = arith.extsi %100 : i32 to i64
func.return %101 : i64
}
func.func @cache_insert(%arg0: i64, %arg1: i64) -> () {
%102 = func.call @cache_hash(%arg0) : (i64) -> i64
%103 = llvm.mlir.constant(1 : i64) : i64
%104 = llvm.alloca %103 x i64 : (i64) -> !llvm.ptr
llvm.store %102, %104 : i64, !llvm.ptr
cf.br ^bb18
^bb18:
%106 = llvm.mlir.addressof @g_cache_used : !llvm.ptr
%107 = llvm.load %106 : !llvm.ptr -> !llvm.ptr
%108 = llvm.load %104 : !llvm.ptr -> i64
%109 = llvm.getelementptr %107[%108] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%105 = llvm.load %109 : !llvm.ptr -> i8
%110 = arith.constant 0 : i32
%112 = arith.extsi %105 : i8 to i32
%111 = arith.cmpi ne, %112, %110 : i32
cf.cond_br %111, ^bb19, ^bb20
^bb19:
%114 = llvm.mlir.addressof @g_cache_key : !llvm.ptr
%115 = llvm.load %114 : !llvm.ptr -> !llvm.ptr
%116 = llvm.load %104 : !llvm.ptr -> i64
%117 = llvm.getelementptr %115[%116] : (!llvm.ptr, i64) -> !llvm.ptr, i64
%113 = llvm.load %117 : !llvm.ptr -> i64
%118 = arith.cmpi eq, %113, %arg0 : i64
cf.cond_br %118, ^bb21, ^bb22
^bb21:
%119 = llvm.mlir.addressof @g_cache_val : !llvm.ptr
%120 = llvm.load %119 : !llvm.ptr -> !llvm.ptr
%121 = llvm.load %104 : !llvm.ptr -> i64
%122 = llvm.getelementptr %120[%121] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %arg1, %122 : i64, !llvm.ptr
func.return
^bb22:
cf.br ^bb23
^bb23:
%123 = llvm.load %104 : !llvm.ptr -> i64
%124 = arith.constant 1 : i32
%126 = arith.extsi %124 : i32 to i64
%125 = arith.addi %123, %126 : i64
%127 = llvm.mlir.addressof @CACHE_MASK : !llvm.ptr
%128 = llvm.load %127 : !llvm.ptr -> i64
%129 = arith.andi %125, %128 : i64
llvm.store %129, %104 : i64, !llvm.ptr
cf.br ^bb18
^bb20:
%130 = arith.constant 1 : i32
%131 = llvm.mlir.addressof @g_cache_used : !llvm.ptr
%132 = llvm.load %131 : !llvm.ptr -> !llvm.ptr
%133 = llvm.load %104 : !llvm.ptr -> i64
%134 = arith.trunci %130 : i32 to i8
%135 = llvm.getelementptr %132[%133] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %134, %135 : i8, !llvm.ptr
%136 = llvm.mlir.addressof @g_cache_key : !llvm.ptr
%137 = llvm.load %136 : !llvm.ptr -> !llvm.ptr
%138 = llvm.load %104 : !llvm.ptr -> i64
%139 = llvm.getelementptr %137[%138] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %arg0, %139 : i64, !llvm.ptr
%140 = llvm.mlir.addressof @g_cache_val : !llvm.ptr
%141 = llvm.load %140 : !llvm.ptr -> !llvm.ptr
%142 = llvm.load %104 : !llvm.ptr -> i64
%143 = llvm.getelementptr %141[%142] : (!llvm.ptr, i64) -> !llvm.ptr, i64
llvm.store %arg1, %143 : i64, !llvm.ptr
func.return
}
func.func @chi_prefix(%arg0: i64) -> i64 {
%144 = arith.constant 2 : i32
%146 = arith.extsi %144 : i32 to i64
%145 = arith.addi %arg0, %146 : i64
%147 = arith.constant 3 : i32
%149 = arith.extsi %147 : i32 to i64
%148 = arith.divsi %145, %149 : i64
%150 = arith.constant 1 : i32
%152 = arith.extsi %150 : i32 to i64
%151 = arith.addi %arg0, %152 : i64
%153 = arith.constant 3 : i32
%155 = arith.extsi %153 : i32 to i64
%154 = arith.divsi %151, %155 : i64
%156 = arith.subi %148, %154 : i64
func.return %156 : i64
}
func.func @count_hex_points_leq(%arg0: i64) -> i64 {
%157 = arith.constant 0 : i32
%159 = arith.extsi %157 : i32 to i64
%158 = arith.cmpi eq, %arg0, %159 : i64
cf.cond_br %158, ^bb24, ^bb25
^bb24:
%160 = arith.constant 1 : i32
%161 = arith.extsi %160 : i32 to i64
func.return %161 : i64
^bb25:
cf.br ^bb26
^bb26:
%163 = arith.constant 1 : i32
%164 = arith.constant 4 : i32
%165 = arith.extsi %163 : i32 to i64
%166 = arith.extsi %164 : i32 to i64
%162 = func.call @calloc(%165, %166) : (i64, i64) -> !llvm.ptr
%167 = func.call @cache_lookup(%arg0, %162) : (i64, !llvm.ptr) -> i64
%169 = arith.constant 0 : i32
%170 = arith.extsi %169 : i32 to i64
%171 = llvm.getelementptr %162[%170] : (!llvm.ptr, i64) -> !llvm.ptr, i32
%168 = llvm.load %171 : !llvm.ptr -> i32
%172 = arith.constant 1 : i32
%173 = arith.cmpi eq, %168, %172 : i32
cf.cond_br %173, ^bb27, ^bb28
^bb27:
func.call @free(%162) : (!llvm.ptr) -> ()
func.return %167 : i64
^bb28:
cf.br ^bb29
^bb29:
func.call @free(%162) : (!llvm.ptr) -> ()
%176 = arith.constant 0 : i32
%177 = arith.extsi %176 : i32 to i64
%178 = llvm.mlir.constant(1 : i64) : i64
%179 = llvm.alloca %178 x i64 : (i64) -> !llvm.ptr
llvm.store %177, %179 : i64, !llvm.ptr
%180 = arith.constant 1 : i32
%181 = arith.extsi %180 : i32 to i64
%182 = llvm.mlir.constant(1 : i64) : i64
%183 = llvm.alloca %182 x i64 : (i64) -> !llvm.ptr
llvm.store %181, %183 : i64, !llvm.ptr
cf.br ^bb30
^bb30:
%184 = llvm.load %183 : !llvm.ptr -> i64
%185 = arith.cmpi sle, %184, %arg0 : i64
cf.cond_br %185, ^bb31, ^bb32
^bb31:
%186 = llvm.load %183 : !llvm.ptr -> i64
%187 = arith.divsi %arg0, %186 : i64
%188 = arith.divsi %arg0, %187 : i64
%189 = llvm.load %179 : !llvm.ptr -> i64
%190 = func.call @chi_prefix(%188) : (i64) -> i64
%192 = llvm.load %183 : !llvm.ptr -> i64
%193 = arith.constant 1 : i32
%195 = arith.extsi %193 : i32 to i64
%194 = arith.subi %192, %195 : i64
%191 = func.call @chi_prefix(%194) : (i64) -> i64
%196 = arith.subi %190, %191 : i64
%197 = arith.muli %187, %196 : i64
%198 = arith.addi %189, %197 : i64
llvm.store %198, %179 : i64, !llvm.ptr
%199 = arith.constant 1 : i32
%201 = arith.extsi %199 : i32 to i64
%200 = arith.addi %188, %201 : i64
llvm.store %200, %183 : i64, !llvm.ptr
cf.br ^bb30
^bb32:
%202 = arith.constant 1 : i32
%203 = arith.constant 6 : i32
%204 = llvm.load %179 : !llvm.ptr -> i64
%206 = arith.extsi %203 : i32 to i64
%205 = arith.muli %206, %204 : i64
%208 = arith.extsi %202 : i32 to i64
%207 = arith.addi %208, %205 : i64
func.call @cache_insert(%arg0, %207) : (i64, i64) -> ()
func.return %207 : i64
}
func.func @remarkable_triangles(%arg0: i64, %arg1: i64) -> i64 {
%210 = arith.constant 12 : i32
%212 = arith.extsi %210 : i32 to i64
%211 = arith.muli %212, %arg0 : i64
%213 = arith.muli %211, %arg0 : i64
%214 = arith.muli %arg1, %arg1 : i64
%216 = arith.divsi %213, %214 : i64
%215 = func.call @isqrt_u64(%216) : (i64) -> i64
%218 = arith.constant 1 : i32
%220 = arith.extsi %218 : i32 to i64
%219 = arith.addi %215, %220 : i64
%221 = arith.constant 4 : i32
%222 = arith.extsi %221 : i32 to i64
%217 = func.call @calloc(%219, %222) : (i64, i64) -> !llvm.ptr
%223 = arith.constant 3 : i32
%225 = arith.extsi %223 : i32 to i64
%224 = arith.divsi %215, %225 : i64
%227 = arith.constant 1 : i32
%229 = arith.extsi %227 : i32 to i64
%228 = arith.addi %224, %229 : i64
%230 = arith.constant 1 : i32
%231 = arith.extsi %230 : i32 to i64
%226 = func.call @calloc(%228, %231) : (i64, i64) -> !llvm.ptr
%232 = arith.constant 2 : i32
%233 = arith.extsi %232 : i32 to i64
%234 = llvm.mlir.constant(1 : i64) : i64
%235 = llvm.alloca %234 x i64 : (i64) -> !llvm.ptr
llvm.store %233, %235 : i64, !llvm.ptr
cf.br ^bb33
^bb33:
%236 = llvm.load %235 : !llvm.ptr -> i64
%237 = arith.cmpi sle, %236, %224 : i64
cf.cond_br %237, ^bb34, ^bb35
^bb34:
%239 = llvm.load %235 : !llvm.ptr -> i64
%240 = llvm.getelementptr %226[%239] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%238 = llvm.load %240 : !llvm.ptr -> i8
%241 = arith.constant 0 : i32
%243 = arith.extsi %238 : i8 to i32
%242 = arith.cmpi eq, %243, %241 : i32
cf.cond_br %242, ^bb36, ^bb37
^bb36:
%244 = llvm.load %235 : !llvm.ptr -> i64
%245 = llvm.mlir.constant(1 : i64) : i64
%246 = llvm.alloca %245 x i64 : (i64) -> !llvm.ptr
llvm.store %244, %246 : i64, !llvm.ptr
cf.br ^bb39
^bb39:
%247 = llvm.load %246 : !llvm.ptr -> i64
%248 = arith.cmpi sle, %247, %224 : i64
cf.cond_br %248, ^bb40, ^bb41
^bb40:
%250 = llvm.load %246 : !llvm.ptr -> i64
%251 = llvm.getelementptr %226[%250] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%249 = llvm.load %251 : !llvm.ptr -> i8
%252 = arith.constant 1 : i32
%254 = arith.extsi %249 : i8 to i32
%253 = arith.addi %254, %252 : i32
%255 = llvm.load %246 : !llvm.ptr -> i64
%256 = arith.trunci %253 : i32 to i8
%257 = llvm.getelementptr %226[%255] : (!llvm.ptr, i64) -> !llvm.ptr, i8
llvm.store %256, %257 : i8, !llvm.ptr
%258 = llvm.load %246 : !llvm.ptr -> i64
%259 = llvm.load %235 : !llvm.ptr -> i64
%260 = arith.addi %258, %259 : i64
llvm.store %260, %246 : i64, !llvm.ptr
cf.br ^bb39
^bb41:
cf.br ^bb38
^bb37:
cf.br ^bb38
^bb38:
%261 = llvm.load %235 : !llvm.ptr -> i64
%262 = arith.constant 1 : i32
%264 = arith.extsi %262 : i32 to i64
%263 = arith.addi %261, %264 : i64
llvm.store %263, %235 : i64, !llvm.ptr
cf.br ^bb33
^bb35:
%265 = arith.constant 2 : i32
%266 = arith.extsi %265 : i32 to i64
%267 = llvm.mlir.constant(1 : i64) : i64
%268 = llvm.alloca %267 x i64 : (i64) -> !llvm.ptr
llvm.store %266, %268 : i64, !llvm.ptr
cf.br ^bb42
^bb42:
%269 = llvm.load %268 : !llvm.ptr -> i64
%270 = arith.cmpi sle, %269, %224 : i64
cf.cond_br %270, ^bb43, ^bb44
^bb43:
%271 = llvm.load %268 : !llvm.ptr -> i64
%272 = arith.constant 3 : i32
%274 = arith.extsi %272 : i32 to i64
%273 = arith.remsi %271, %274 : i64
%275 = arith.constant 1 : i32
%277 = arith.extsi %275 : i32 to i64
%276 = arith.cmpi ne, %273, %277 : i64
cf.cond_br %276, ^bb45, ^bb46
^bb45:
%279 = arith.constant 3 : i32
%280 = llvm.load %268 : !llvm.ptr -> i64
%282 = arith.extsi %279 : i32 to i64
%281 = arith.muli %282, %280 : i64
%283 = llvm.getelementptr %217[%281] : (!llvm.ptr, i64) -> !llvm.ptr, i32
%278 = llvm.load %283 : !llvm.ptr -> i32
%284 = arith.constant 1 : i32
%286 = llvm.load %268 : !llvm.ptr -> i64
%287 = llvm.getelementptr %226[%286] : (!llvm.ptr, i64) -> !llvm.ptr, i8
%285 = llvm.load %287 : !llvm.ptr -> i8
%288 = arith.constant 1 : i32
%290 = arith.extsi %285 : i8 to i32
%289 = arith.subi %290, %288 : i32
%291 = arith.shli %284, %289 : i32
%292 = arith.addi %278, %291 : i32
%293 = arith.constant 3 : i32
%294 = llvm.load %268 : !llvm.ptr -> i64
%296 = arith.extsi %293 : i32 to i64
%295 = arith.muli %296, %294 : i64
%297 = llvm.getelementptr %217[%295] : (!llvm.ptr, i64) -> !llvm.ptr, i32
llvm.store %292, %297 : i32, !llvm.ptr
cf.br ^bb47
^bb46:
cf.br ^bb47
^bb47:
%298 = llvm.load %268 : !llvm.ptr -> i64
%299 = arith.constant 1 : i32
%301 = arith.extsi %299 : i32 to i64
%300 = arith.addi %298, %301 : i64
llvm.store %300, %268 : i64, !llvm.ptr
cf.br ^bb42
^bb44:
func.call @free(%226) : (!llvm.ptr) -> ()
%303 = arith.constant 3 : i32
%305 = arith.extsi %303 : i32 to i64
%304 = arith.divsi %215, %305 : i64
%306 = arith.constant 1 : i32
%307 = arith.extsi %306 : i32 to i64
%308 = llvm.mlir.constant(1 : i64) : i64
%309 = llvm.alloca %308 x i64 : (i64) -> !llvm.ptr
llvm.store %307, %309 : i64, !llvm.ptr
cf.br ^bb48
^bb48:
%310 = llvm.load %309 : !llvm.ptr -> i64
%311 = arith.cmpi sle, %310, %304 : i64
cf.cond_br %311, ^bb49, ^bb50
^bb49:
%312 = arith.constant 9 : i32
%313 = llvm.load %309 : !llvm.ptr -> i64
%315 = arith.extsi %312 : i32 to i64
%314 = arith.muli %315, %313 : i64
%316 = llvm.load %309 : !llvm.ptr -> i64
%317 = arith.muli %314, %316 : i64
%318 = arith.constant 4 : i32
%320 = arith.extsi %318 : i32 to i64
%319 = arith.muli %320, %215 : i64
%321 = arith.addi %317, %319 : i64
%322 = func.call @isqrt_u64(%321) : (i64) -> i64
%323 = arith.constant 3 : i32
%324 = llvm.load %309 : !llvm.ptr -> i64
%326 = arith.extsi %323 : i32 to i64
%325 = arith.muli %326, %324 : i64
%327 = arith.subi %322, %325 : i64
%328 = arith.constant 2 : i32
%330 = arith.extsi %328 : i32 to i64
%329 = arith.divsi %327, %330 : i64
%331 = arith.constant 0 : i32
%333 = arith.extsi %331 : i32 to i64
%332 = arith.cmpi sle, %329, %333 : i64
cf.cond_br %332, ^bb51, ^bb52
^bb51:
%334 = llvm.load %309 : !llvm.ptr -> i64
%335 = arith.constant 1 : i32
%337 = arith.extsi %335 : i32 to i64
%336 = arith.addi %334, %337 : i64
llvm.store %336, %309 : i64, !llvm.ptr
cf.br ^bb48
^bb52:
cf.br ^bb53
^bb53:
%338 = arith.constant 1 : i32
%339 = arith.extsi %338 : i32 to i64
%340 = llvm.mlir.constant(1 : i64) : i64
%341 = llvm.alloca %340 x i64 : (i64) -> !llvm.ptr
llvm.store %339, %341 : i64, !llvm.ptr
cf.br ^bb54
^bb54:
%342 = llvm.load %341 : !llvm.ptr -> i64
%343 = arith.cmpi sle, %342, %329 : i64
cf.cond_br %343, ^bb55, ^bb56
^bb55:
%344 = llvm.load %309 : !llvm.ptr -> i64
%345 = llvm.load %341 : !llvm.ptr -> i64
%346 = arith.addi %344, %345 : i64
%347 = arith.constant 3 : i32
%349 = arith.extsi %347 : i32 to i64
%348 = arith.remsi %346, %349 : i64
%350 = llvm.load %309 : !llvm.ptr -> i64
%351 = arith.constant 3 : i32
%353 = arith.extsi %351 : i32 to i64
%352 = arith.remsi %350, %353 : i64
%354 = arith.cmpi ne, %348, %352 : i64
cf.cond_br %354, ^bb57, ^bb58
^bb57:
%356 = llvm.load %309 : !llvm.ptr -> i64
%355 = func.call @gcd_u64(%346, %356) : (i64, i64) -> i64
%357 = arith.constant 1 : i32
%359 = arith.extsi %357 : i32 to i64
%358 = arith.cmpi eq, %355, %359 : i64
cf.cond_br %358, ^bb60, ^bb61
^bb60:
%360 = llvm.load %341 : !llvm.ptr -> i64
%361 = llvm.load %341 : !llvm.ptr -> i64
%362 = arith.constant 3 : i32
%363 = llvm.load %309 : !llvm.ptr -> i64
%365 = arith.extsi %362 : i32 to i64
%364 = arith.muli %365, %363 : i64
%366 = arith.addi %361, %364 : i64
%367 = arith.muli %360, %366 : i64
%369 = llvm.getelementptr %217[%367] : (!llvm.ptr, i64) -> !llvm.ptr, i32
%368 = llvm.load %369 : !llvm.ptr -> i32
%370 = arith.constant 1 : i32
%371 = arith.addi %368, %370 : i32
%372 = llvm.getelementptr %217[%367] : (!llvm.ptr, i64) -> !llvm.ptr, i32
llvm.store %371, %372 : i32, !llvm.ptr
cf.br ^bb62
^bb61:
cf.br ^bb62
^bb62:
cf.br ^bb59
^bb58:
cf.br ^bb59
^bb59:
%373 = llvm.load %341 : !llvm.ptr -> i64
%374 = arith.constant 1 : i32
%376 = arith.extsi %374 : i32 to i64
%375 = arith.addi %373, %376 : i64
llvm.store %375, %341 : i64, !llvm.ptr
cf.br ^bb54
^bb56:
%377 = llvm.load %309 : !llvm.ptr -> i64
%378 = arith.constant 1 : i32
%380 = arith.extsi %378 : i32 to i64
%379 = arith.addi %377, %380 : i64
llvm.store %379, %309 : i64, !llvm.ptr
cf.br ^bb48
^bb50:
%381 = arith.constant 0 : i32
%382 = arith.extsi %381 : i32 to i64
%383 = llvm.mlir.constant(1 : i64) : i64
%384 = llvm.alloca %383 x i64 : (i64) -> !llvm.ptr
llvm.store %382, %384 : i64, !llvm.ptr
%385 = arith.constant 1 : i32
%386 = arith.extsi %385 : i32 to i64
%387 = llvm.mlir.constant(1 : i64) : i64
%388 = llvm.alloca %387 x i64 : (i64) -> !llvm.ptr
llvm.store %386, %388 : i64, !llvm.ptr
cf.br ^bb63
^bb63:
%389 = llvm.load %388 : !llvm.ptr -> i64
%390 = arith.cmpi sle, %389, %215 : i64
cf.cond_br %390, ^bb64, ^bb65
^bb64:
%392 = llvm.load %388 : !llvm.ptr -> i64
%393 = llvm.getelementptr %217[%392] : (!llvm.ptr, i64) -> !llvm.ptr, i32
%391 = llvm.load %393 : !llvm.ptr -> i32
%394 = arith.constant 0 : i32
%395 = arith.cmpi eq, %391, %394 : i32
cf.cond_br %395, ^bb66, ^bb67
^bb66:
%396 = llvm.load %388 : !llvm.ptr -> i64
%397 = arith.constant 1 : i32
%399 = arith.extsi %397 : i32 to i64
%398 = arith.addi %396, %399 : i64
llvm.store %398, %388 : i64, !llvm.ptr
cf.br ^bb63
^bb67:
cf.br ^bb68
^bb68:
%400 = llvm.load %388 : !llvm.ptr -> i64
%401 = arith.muli %214, %400 : i64
%402 = llvm.load %388 : !llvm.ptr -> i64
%403 = arith.muli %401, %402 : i64
%404 = arith.divsi %213, %403 : i64
%405 = arith.constant 0 : i32
%407 = arith.extsi %405 : i32 to i64
%406 = arith.cmpi eq, %404, %407 : i64
cf.cond_br %406, ^bb69, ^bb70
^bb69:
%408 = llvm.load %388 : !llvm.ptr -> i64
%409 = arith.constant 1 : i32
%411 = arith.extsi %409 : i32 to i64
%410 = arith.addi %408, %411 : i64
llvm.store %410, %388 : i64, !llvm.ptr
cf.br ^bb63
^bb70:
cf.br ^bb71
^bb71:
%412 = arith.constant 0 : i32
%413 = arith.extsi %412 : i32 to i64
%414 = llvm.load %388 : !llvm.ptr -> i64
%415 = arith.constant 3 : i32
%417 = arith.extsi %415 : i32 to i64
%416 = arith.remsi %414, %417 : i64
%418 = arith.constant 0 : i32
%420 = arith.extsi %418 : i32 to i64
%419 = arith.cmpi eq, %416, %420 : i64
%421 = scf.if %419 -> (i64) {
%422 = func.call @count_hex_points_leq(%404) : (i64) -> i64
%423 = arith.constant 1 : i32
%425 = arith.extsi %423 : i32 to i64
%424 = arith.subi %422, %425 : i64
scf.yield %424 : i64
} else {
%427 = arith.constant 3 : i32
%429 = arith.extsi %427 : i32 to i64
%428 = arith.divsi %404, %429 : i64
%426 = func.call @count_hex_points_leq(%428) : (i64) -> i64
%430 = arith.constant 1 : i32
%432 = arith.extsi %430 : i32 to i64
%431 = arith.subi %426, %432 : i64
scf.yield %431 : i64
}
%433 = llvm.load %384 : !llvm.ptr -> i64
%434 = arith.constant 2 : i32
%435 = arith.extsi %391 : i32 to i64
%437 = arith.extsi %434 : i32 to i64
%436 = arith.muli %437, %435 : i64
%438 = arith.muli %436, %421 : i64
%439 = arith.addi %433, %438 : i64
llvm.store %439, %384 : i64, !llvm.ptr
%440 = llvm.load %388 : !llvm.ptr -> i64
%441 = arith.constant 1 : i32
%443 = arith.extsi %441 : i32 to i64
%442 = arith.addi %440, %443 : i64
llvm.store %442, %388 : i64, !llvm.ptr
cf.br ^bb63
^bb65:
%444 = arith.constant 4 : i32
%446 = arith.extsi %444 : i32 to i64
%445 = arith.muli %446, %arg0 : i64
%447 = arith.muli %445, %arg0 : i64
%448 = arith.muli %arg1, %arg1 : i64
%449 = arith.divsi %447, %448 : i64
%450 = func.call @count_hex_points_leq(%449) : (i64) -> i64
%451 = arith.constant 1 : i32
%453 = arith.extsi %451 : i32 to i64
%452 = arith.subi %450, %453 : i64
%454 = arith.constant 3 : i32
%456 = arith.extsi %454 : i32 to i64
%455 = arith.divsi %452, %456 : i64
func.call @free(%217) : (!llvm.ptr) -> ()
%458 = llvm.load %384 : !llvm.ptr -> i64
%459 = arith.addi %458, %455 : i64
func.return %459 : i64
}
func.func @main() -> i32 {
%461 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
%462 = llvm.load %461 : !llvm.ptr -> i64
%463 = arith.constant 8 : i32
%464 = arith.extsi %463 : i32 to i64
%460 = func.call @calloc(%462, %464) : (i64, i64) -> !llvm.ptr
%465 = llvm.mlir.addressof @g_cache_key : !llvm.ptr
llvm.store %460, %465 : !llvm.ptr, !llvm.ptr
%467 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
%468 = llvm.load %467 : !llvm.ptr -> i64
%469 = arith.constant 8 : i32
%470 = arith.extsi %469 : i32 to i64
%466 = func.call @calloc(%468, %470) : (i64, i64) -> !llvm.ptr
%471 = llvm.mlir.addressof @g_cache_val : !llvm.ptr
llvm.store %466, %471 : !llvm.ptr, !llvm.ptr
%473 = llvm.mlir.addressof @CACHE_CAP : !llvm.ptr
%474 = llvm.load %473 : !llvm.ptr -> i64
%475 = arith.constant 1 : i32
%476 = arith.extsi %475 : i32 to i64
%472 = func.call @calloc(%474, %476) : (i64, i64) -> !llvm.ptr
%477 = llvm.mlir.addressof @g_cache_used : !llvm.ptr
llvm.store %472, %477 : !llvm.ptr, !llvm.ptr
%479 = arith.constant 1000000 : i32
%480 = arith.constant 1 : i32
%481 = arith.extsi %479 : i32 to i64
%482 = arith.extsi %480 : i32 to i64
%478 = func.call @remarkable_triangles(%481, %482) : (i64, i64) -> i64
%483 = llvm.mlir.addressof @str_0 : !llvm.ptr
%484 = llvm.call @printf(%483, %478) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
%486 = llvm.mlir.addressof @g_cache_key : !llvm.ptr
%487 = llvm.load %486 : !llvm.ptr -> !llvm.ptr
func.call @free(%487) : (!llvm.ptr) -> ()
%489 = llvm.mlir.addressof @g_cache_val : !llvm.ptr
%490 = llvm.load %489 : !llvm.ptr -> !llvm.ptr
func.call @free(%490) : (!llvm.ptr) -> ()
%492 = llvm.mlir.addressof @g_cache_used : !llvm.ptr
%493 = llvm.load %492 : !llvm.ptr -> !llvm.ptr
func.call @free(%493) : (!llvm.ptr) -> ()
%494 = arith.constant 0 : i32
func.return %494 : i32
}
}