// Hand-C reference for bench_mono_dispatch — DIRECT, INLINABLE variant.
//
// Mirrors the post-monomorphisation AILang IR: a tail-recursive loop
// that calls `foo(i)` at every step. `foo` here has no `noinline`
// attribute, so clang -O2 will inline it into the loop body. This is
// the OPTIMISTIC bound on what AILang's mono pass can achieve once
// LLVM optimises the resulting IR.
//
// Workload: loop_call(N, 0) with
//   acc' = acc + foo(acc + i)
//   foo(x) = x * 1103515245 + 12345     (LCG-ish, prevents closed-form)
//
// N = 100_000_000.
//
// The result is data-dependent on every prior iteration, so clang
// cannot algebraically close-form-fold the loop; the wall-time is
// dominated by the body.
//
// Build: clang -O2 -o bench_mono_direct bench_mono_direct.c

#include <stdio.h>
#include <stdint.h>

static int64_t foo(int64_t x) {
    return x * 1103515245 + 12345;
}

static int64_t loop_call(int64_t i, int64_t acc) {
    while (i != 0) {
        acc = acc + foo(acc + i);
        i = i - 1;
    }
    return acc;
}

int main(void) {
    printf("%lld\n", (long long)loop_call(100000000, 0));
    return 0;
}
