An optimizer for ARC (#14962)
* WIP: an optimizer for ARC * do not optimize away destructors in 'finally' if unstructured control flow is involved * optimized the optimizer * minor code cleanup * first steps to .cursor inference * cursor inference: big steps to a working solution * baby steps * better .cursor inference * new feature: expandArc for easy inspection of the AST after ARC transformations * added topt_cursor test * adapt tests * cleanups, make tests green * optimize common traversal patterns * moved test case * fixes .cursor inference so that npeg compiles once again * cursor inference: more bugfixes Co-authored-by: Clyybber <darkmine956@gmail.com>
This commit is contained in:
parent
813dd1b670
commit
c5358b0d4b
19 changed files with 895 additions and 62 deletions
|
|
@ -122,6 +122,8 @@ Advanced options:
|
|||
use the provided namespace for the generated C++ code,
|
||||
if no namespace is provided "Nim" will be used
|
||||
--expandMacro:MACRO dump every generated AST from MACRO
|
||||
--expandArc:PROCNAME show how PROCNAME looks like after diverse optimizations
|
||||
before the final backend phase (mostly ARC/ORC specific)
|
||||
--excludePath:PATH exclude a path from the list of search paths
|
||||
--dynlibOverride:SYMBOL marks SYMBOL so that dynlib:SYMBOL
|
||||
has no effect and can be statically linked instead;
|
||||
|
|
|
|||
|
|
@ -354,7 +354,8 @@ Destructor removal
|
|||
|
||||
``wasMoved(x);`` followed by a `=destroy(x)` operation cancel each other
|
||||
out. An implementation is encouraged to exploit this in order to improve
|
||||
efficiency and code sizes.
|
||||
efficiency and code sizes. The current implementation does perform this
|
||||
optimization.
|
||||
|
||||
|
||||
Self assignments
|
||||
|
|
@ -509,6 +510,31 @@ to be safe, but for ``ptr`` the compiler has to remain silent about possible
|
|||
problems.
|
||||
|
||||
|
||||
Cursor inference / copy elision
|
||||
===============================
|
||||
|
||||
The current implementation also performs `.cursor` inference. Cursor inference is
|
||||
a form of copy elision.
|
||||
|
||||
To see how and when we can do that, think about this question: In `dest = src` when
|
||||
do we really have to *materialize* the full copy? - Only if `dest` or `src` are mutated
|
||||
afterwards. If `dest` is a local variable that is simple to analyse. And if `src` is a
|
||||
location derived from a formal parameter, we also know it is not mutated! In other
|
||||
words, we do a compile-time copy-on-write analysis.
|
||||
|
||||
This means that "borrowed" views can be written naturally and without explicit pointer
|
||||
indirections:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
proc main(tab: Table[string, string]) =
|
||||
let v = tab["key"] # inferred as .cursor because 'tab' is not mutated.
|
||||
# no copy into 'v', no destruction of 'v'.
|
||||
use(v)
|
||||
useItAgain(v)
|
||||
|
||||
|
||||
|
||||
Owned refs
|
||||
==========
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue