-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Discovered while investigating #36532
DDC's technique for emitting constants in its Analyzer backend ensured that large constants would only be emitted once, typically. It worked because users put large constants (e.g. lists, maps, objects) in a variable and refer to that variable, rather than copy+paste the constant expression into multiple locations.
That breaks down with Kernel with the constants flag on, because it's now inlining these constant nodes everywhere. The original Kernel tree is not kept around. So DDC only gets "InstanceConstant" or "ListConstant" for example. Since DDC is a modular compiler, it cannot do global canonicalization. By inlining constants, CFE removes DDC's primary means of optimizing constants (the fact that developers generally put large constants in variables).
I don't see any reasonable way for DDC to work around this on its own. We'll need some help from CFE/Kernel--some way to control constant inlining. Inlining numbers/bools/small strings is fine, but otherwise we don't want to inline, and need these to remain as StaticGet nodes.
The first step would be to prevent inlining when we're not in a const context, and let DDC perform const evaluation (if desired). For example if I refer to Zone.root in my method, that should remain a static get, and not be inlined.
EDIT: see comment below, this isn't as bad as I thought, because CFE can't inline constants across modules. So we could do per-module canonicalization. It's not as optimal as preventing the inlining, but it's not quite as bad as I'd feared, assuming we implement per-module canonicalization for constants in DDC. We'll need to override cacheConst from shared_compiler to do something different in DDC's Kernel backend.