Skip to content

cl, ssa: fix zero-sized global init, fold composite literal alloc stores, and add LTO baseline benchmarks - #2376

Open
cpunion wants to merge 8 commits into
xgo-dev:mainfrom
cpunion:codex/static-init-on-main
Open

cl, ssa: fix zero-sized global init, fold composite literal alloc stores, and add LTO baseline benchmarks#2376
cpunion wants to merge 8 commits into
xgo-dev:mainfrom
cpunion:codex/static-init-on-main

Conversation

@cpunion

@cpunion cpunion commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Folds package-level composite literal initializers into LLVM static constants, removing runtime allocation loops in init() functions, fixes zero-sized global constant initializers, and adds baseline LTO workload measurements.


Key Changes

  1. Composite Literal Static Folding (cl/static_init.go):

    • Traverses package initializer SSA to detect global composite literals stored via pointer indirection (*(&alloc)).
    • Reconstructs constant AST/SSA trees via staticInitNode and compiles them directly into LLVM static constant globals (@global = constant ...).
    • Automatically suppresses all intermediate temporary stack allocs, GEPs, and element stores from the package init() function.
    • Hardened helper paths with defensive slice copying (appendStaticInitPath) and type kind checks (constant.Int).
  2. Zero-Sized Global Init Guard (ssa/decl.go):

    • Added guard ensuring zero-sized globals ([0]int{}) aliased to the shared __llgo.moduleZeroSizedAlloc$ sentinel (under LinkOnceODRLinkage) are not mutated by Init/InitNil.
  3. Baseline Benchmark Measurements (.github/workflows/benchmark.yml, benchmark/baseline/):

    • Added -lto=full workload measurements (cprintf_lto, println_lto, fmtprintf_lto).
    • Uses dynamic PR merge-base computation for exact baseline comparisons.
  4. Test Coverage (cl/rewrite_internal_test.go):

    • Added comprehensive edge-case tests (cycle detection, out-of-range indices, blank fields, type kind validation, negative indices), boosting statement coverage of cl/static_init.go to 86.6% (and all internal helper functions to 100%).

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FennoAI Review

This PR cleanly extends the static-init folding optimization to cover struct/array literals that the front-end materializes through a temporary stack alloc reached via pointer indirection (*(&tmp)). The recursive tracing is cycle-guarded (visited), the failure path is safe (partial stores/instrs are discarded when candidate.invalid short-circuits at static_init.go:177), appendStaticInitPath correctly avoids slice-aliasing, and staticInitConstIndex is now hardened against nil/non-int/out-of-range constants. Test coverage is thorough, and the benchmark -lto=full variants plus the merge-base checkout change are sound. The workflow uses the safe pull_request trigger with persist-credentials: false, so no injection risk.

One correctness gap is worth confirming before merge (inline), plus a couple of minor notes below.

Minor

  • cl/static_init.go:248-251 / 265-268: when handleStoreVal classifies a value as a constant, the element store is recorded both in out (→ staticInitStores) and in instrs (→ staticInitInstrs). This is harmless (both suppression checks are independent, and staticInitInstrs is checked first in compileInstr) but is easy to misread — a one-line comment noting the intentional double-tracking would help.
  • ssa/decl.go:177,186: the sentinel guard relies on a per-call g.impl.Name() string comparison. Since doNewVarEx already returns a distinguished aGlobal wrapping the shared sentinel Expr, comparing against the known sentinel value/pointer would make the invariant more explicit and avoid the string compare. Functionally correct as-is.

Note: a full go test ./cl/... could not be run in the review sandbox (LLVM C headers unavailable); findings are from static analysis of the diff.

Comment thread cl/static_init.go
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

LLGo baseline benchmarks

f9fc847450c4 | workflow run | long-term charts

Program measurements

Platform Workload File size vs base Build vs base Run vs base
Linux cprintf 19288 B 0 B / +0.0% 358.070 ms +40.93 ms / +12.9% (worse) 871.584 us -119.1 us / -12.0% (better)
Linux cprintf-lto 19120 B 0 B / +0.0% 368.123 ms +60.17 ms / +19.5% (worse) 905.383 us -253 us / -21.8% (better)
Linux fmtprintf 1860176 B 0 B / +0.0% 2.458 s +146.8 ms / +6.4% (worse) 2.407 ms -32.98 us / -1.4% (better)
Linux fmtprintf-lto 1777120 B 0 B / +0.0% 12.155 s +168.5 ms / +1.4% (worse) 2.330 ms +21.92 us / +0.9% (worse)
Linux println 68776 B 0 B / +0.0% 492.639 ms +226.1 ms / +84.8% (worse) 1.137 ms -24.57 us / -2.1% (better)
Linux println-lto 62464 B 0 B / +0.0% 490.055 ms +13.46 ms / +2.8% (worse) 1.213 ms +31.52 us / +2.7% (worse)
macOS cprintf 84672 B 0 B / +0.0% 347.176 ms -853 us / -0.2% (better) 3.009 ms +675.9 us / +29.0% (worse)
macOS cprintf-lto 100912 B 0 B / +0.0% 377.716 ms +53.18 ms / +16.4% (worse) 2.713 ms +502.5 us / +22.7% (worse)
macOS fmtprintf 1892720 B 0 B / +0.0% 2.724 s +569.5 ms / +26.4% (worse) 12.905 ms +2.13 ms / +19.8% (worse)
macOS fmtprintf-lto 1626416 B 0 B / +0.0% 19.856 s +1.151 s / +6.2% (worse) 8.643 ms +3.746 ms / +76.5% (worse)
macOS println 121360 B 0 B / +0.0% 396.762 ms +77.65 ms / +24.3% (worse) 3.821 ms +243.7 us / +6.8% (worse)
macOS println-lto 128528 B 0 B / +0.0% 508.646 ms +84.18 ms / +19.8% (worse) 3.693 ms +948.4 us / +34.6% (worse)
Core language and compiler benchmarks
Platform Benchmark ns/op vs base
Linux BenchmarkLookupPCRandom 9.597 ns/op +0.009 ns/op / +0.1% (worse)
Linux BenchmarkMergeCompilerFlags 119.600 ns/op -0.2 ns/op / -0.2% (better)
Linux BenchmarkMergeLinkerFlags 80.930 ns/op -0.26 ns/op / -0.3% (better)
Linux BenchmarkChannelBuffered 49.020 ns/op -0.27 ns/op / -0.5% (better)
Linux BenchmarkChannelHandoff 28205 ns/op +177 ns/op / +0.6% (worse)
Linux BenchmarkDefer 35.810 ns/op +0.25 ns/op / +0.7% (worse)
Linux BenchmarkDirectCall 0.960 ns/op -0.0151 ns/op / -1.5% (better)
Linux BenchmarkGlobalRead 0.964 ns/op -0.0858 ns/op / -8.2% (better)
Linux BenchmarkGlobalWrite 7.263 ns/op +0.008 ns/op / +0.1% (worse)
Linux BenchmarkGoroutine 33773 ns/op +2133 ns/op / +6.7% (worse)
Linux BenchmarkInterfaceCall 5.527 ns/op +0.023 ns/op / +0.4% (worse)
Linux BenchmarkRuntimeGetG 1.482 ns/op +0.056 ns/op / +3.9% (worse)
macOS BenchmarkLookupPCRandom 12.760 ns/op -1.72 ns/op / -11.9% (better)
macOS BenchmarkMergeCompilerFlags 137.100 ns/op +13 ns/op / +10.5% (worse)
macOS BenchmarkMergeLinkerFlags 72.690 ns/op -21.2 ns/op / -22.6% (better)
macOS BenchmarkChannelBuffered 21.640 ns/op +1.12 ns/op / +5.5% (worse)
macOS BenchmarkChannelHandoff 6988 ns/op +426 ns/op / +6.5% (worse)
macOS BenchmarkDefer 27.560 ns/op +1.09 ns/op / +4.1% (worse)
macOS BenchmarkDirectCall 0.988 ns/op +0.0256 ns/op / +2.7% (worse)
macOS BenchmarkGlobalRead 1.025 ns/op +0.011 ns/op / +1.1% (worse)
macOS BenchmarkGlobalWrite 1.089 ns/op +0.1146 ns/op / +11.8% (worse)
macOS BenchmarkGoroutine 55314 ns/op -1139 ns/op / -2.0% (better)
macOS BenchmarkInterfaceCall 4.241 ns/op +0.047 ns/op / +1.1% (worse)
macOS BenchmarkRuntimeGetG 2.146 ns/op +0.134 ns/op / +6.7% (worse)

Compared with 0314faeba69d measured in the same runner job.

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.19820% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cl/static_init.go 98.09% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant