[clang] [CIR] Emit trailing-zero array constants as a compact split (PR #205918)

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 1 09:46:54 PDT 2026


erichkeane wrote:

> Benchmarked split vs full-materialization on `const int s[N] = {1,2,3};`, `clang -cc1 -fclangir`, peak RSS:
> N 	full array 	split
> 1M 	107 MB 	89 MB
> 10M 	313 MB 	89 MB
> 100M 	2.37 GB 	89 MB
> 
> Split is flat ~89 MB (O(1)); materialization is O(N). At `-O2` N=10M it's 0.58 s vs 0.02 s — the optimizer walks the inert 10M-element `ConstantDataArray`. The tail is unbounded but N=1M is modest (~17%), and nothing real reaches 10M+ (not Eigen, not the dense `insn-automata` tables), so this is a synthetic worst case rather than something we've actually hit.
> 

That is absurdly unfortunate, I was hoping we'd get away without doing this :)  Rust for example doesn't do this, and just leaves all the 0s in place.  Oh well looks like we probably should.

> Only one access is actually GEP-relative (the `cir.global_view` redirect); the rest of the 264 lines is bookkeeping to let the lowered type differ from the declared one. FAMs never reach this path — FAM-init is NYI in CIRGen (`errorNYI` + a pre-existing assert) before lowering.
> 
> Your zero-init + global-ctor avoids the type rewrite entirely and gets the same flat RSS, but it drops a `const` global from `.rodata` to `.bss` + ctor at `-O0`, where the split matches classic and stays in `.rodata`. A CIR→CIR canonicalization keeps `.rodata` without the LowerToLLVM machinery. Keep the split, take the ctor path, or canonicalize?

My idea of the zero-init+global-ctor was to do this during LowerToLLVM.  And yes, it gets another (private) entry into the rodata, but I'd hope that is reasonably sized/acceptable.  Does THAT implementation look particularly ugly?  



https://github.com/llvm/llvm-project/pull/205918


More information about the cfe-commits mailing list