// Hand-C reference for bench_mono_dispatch — DIRECT, NOINLINE variant.
//
// Same as bench_mono_direct.c, but `foo` is marked `noinline` so the
// compiler must emit a real call instruction at every iteration. This
// isolates the "real call" cost when the target is statically known —
// the upper bound on what monomorphised dispatch can achieve when the
// callee body is not inlinable.
//
// Pair this with bench_mono_indirect.c (same noinline, but called via
// fnptr) to isolate "direct vs indirect call" cost on this hardware.
//
// Build: clang -O2 -o bench_mono_direct_noinline bench_mono_direct_noinline.c

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

static int64_t foo(int64_t x) __attribute__((noinline));
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;
}
