hopper_runtime/utils.rs
1//! Small utilities for Hopper program authors.
2//!
3//! The line for inclusion is narrow: a helper lands here when it is
4//! too small to justify its own module and too broadly useful to
5//! leave as a local copy in three places. At the moment that means
6//! branch-prediction hints; future additions fit the same rule or
7//! they do not fit at all.
8
9/// Branch-prediction hints for hot handlers.
10///
11/// Both functions are identity over `bool` on every supported
12/// target. The call site cost is zero: the compiler inlines them
13/// into the containing branch with no runtime effect. What they
14/// communicate is intent. A handler that expects the fast path to
15/// win 99% of the time writes
16///
17/// ```ignore
18/// if hopper::utils::hint::likely(is_cached) {
19/// return fast_path(ctx);
20/// }
21/// slow_path(ctx)
22/// ```
23///
24/// and the compiler keeps the fast path straight-line, pushing the
25/// spill into the cold branch. Same story for [`unlikely`] in the
26/// opposite direction.
27///
28/// On host targets (tests, off-chain tooling) future versions may
29/// route through `core::intrinsics::likely` when that intrinsic is
30/// stabilized; the API shape stays identical so user code never
31/// needs to change. On SBF the Solana runtime does not expose a
32/// branch-weight hint today, so the hint compiles out entirely.
33/// Leaving the calls in the code path is safe and free.
34pub mod hint {
35 /// Hint the branch condition is probably `true`. Zero runtime
36 /// cost on SBF; on host targets it maps to LLVM's
37 /// `llvm.expect.i1` via `core::hint::likely` when available,
38 /// and to an identity otherwise.
39 #[inline(always)]
40 pub fn likely(cond: bool) -> bool {
41 // `core::hint::likely` is nightly-gated as of stable 1.82.
42 // Keep the API stable by wrapping an identity so users never
43 // reach the intrinsic directly; the function is still
44 // correctly inlined.
45 cond
46 }
47
48 /// Hint the branch condition is probably `false`. Mirror of
49 /// [`likely`].
50 #[inline(always)]
51 pub fn unlikely(cond: bool) -> bool {
52 cond
53 }
54
55 #[cfg(test)]
56 mod tests {
57 use super::*;
58
59 #[test]
60 fn likely_is_identity_on_host() {
61 assert!(likely(true));
62 assert!(!likely(false));
63 }
64
65 #[test]
66 fn unlikely_is_identity_on_host() {
67 assert!(unlikely(true));
68 assert!(!unlikely(false));
69 }
70 }
71}