owned this note changed 5 years ago
Linked with GitHub

MIR 2.0 to-do list

To-do list ideas

General plan:

  1. Decide on whether to use virtual locals or to make borrowck more powerful https://github.com/rust-lang/rust/issues/71265

Space optimizations and minor tweaks

  • intern entire places at the MIR level
    • interning (base, Vec<projection>) means less re-use overall though
    • nice hack: rfirst 128 (eddyb suggests 2^16) locals or so can be mapped to themselves
      • could even be extended for whatever the most common projections are if that proves useful
        • insert gratuitous reference to random compression methods here
  • intern the Vec<Projection> to a per-MIR integer (unlikely to be the first first step)
    • maybe we can retain MutVisitor in its current design if MIR still owns the Projection arrays
    • maybe an interesting intermediate step to start from, as it removes one of the challenges, and just leaves us with construction
    • but it comes with its own challenges, like now you can't just take a Place and get its data without a MIR (you have to do mir.projection_data(index))
  • Other interning alternatives like interning both projection and place?

Improving the "ergonomics" of MIR

  • Making MIR more readily mutated
    • Avoiding vectors and indices in favor of linked lists and persistent identifiers
    • can we remove the need for MIR patch and/or simplify it?
  • Merging optimizations, particularly peephole ones
    • Can we have only a single visitor pass?
  • Transactional MIR modifications (requires more design)
    • We can find a general solution where instead of modifying the MIR, you register a list of modifications and the compiler applies them after you have specified them all
      • Isn't thisMirPatch?
    • The alternative is to not have indices and invent some other scheme, that was also discussed
  • "Better" fix temporaries that lives across a yield

Specific optimizations

  • MIR inlining

Extending MIR to better support optimizations

  • Remove Deref and Index from the list of projections
    • observation: today's places are complex to reason about for optimizations and could be lower level
      • if would be nice to simplify &mut *(*foo.bar).baz for example into smaller operations
    • however: they were made to match borrowck, and we can't just introduce things like let tmp0 = &mut *foo.bar because it will cause new errors
    • there have been various threads about it where you can read up on more details:
    • one scheme would be to introduce
    • create a “pseudo-reborrow” Rvalue (or maybe an Operand?) which just takes a place
    • this means what was (*foo.bar).boo now becomes let tmp = &*foo.bar; tmp.boo
    • We can try out a compiler flag that makes mir building generate an intermediate temporary
    • We need to check borrowck and miri :)
    • nikomatsakis describes one scheme around here: I guess then that x = &*(*tmp.bar).baz would be something like
      ​​​​​​​​P0 = LOAD(tmp.bar) // P0 is a "place temporary", meaning that it is a pointer effectively
      ​​​​​​​​P1 = LOAD(P0.baz)
      ​​​​​​​​X = &P1
      
    • and borrowck would understand that (e.g.) tmp.bar was not borrowed
    • nikomatsakis: in some ways this might simplify borrowck, since right now I think we have to figure out which loads and other accesses occur as part of a borrow.. maybe? that maybe just falls out. nikomatsakis: anyway, I think we should table these details and turn back to the higher level questions?
  • Remove Index from the list of projections
    • The Local field for the actual index is slightly inconvenient
    • Add an Option<Local> field to Rvalue::Ref
    • Later refactor the Local to Operand
  • Remove field from Projection
    • essentially eliminate Projections entirely from places
    • instead we'd have Projection+Ref Rvalues that create a new local which is a pointer to the projected to place
  • Formalizing out parameters (or args passed by pointer because they are too large)
    • in other words, make it possible for MIR to express writing return values directly into the caller frame
    • see also notes on NRVO here

Cleanups

  • Make Local Copy
  • Make PlaceRef take just one lifetime
  • Make Operand Copy
  • Use place directly its copy
  • Local is Copy we can pass it by value in these cases
  • Replace fragile erroneous const sys
  • Tidy up Visitors
    • Now that there's no more base, just local a lot of things can be made simpler
    • Remove weird macro related to visit_place_projection
    • Remove cow on visitor
    • visit_place_base is just visit_local #71401
  • Remove PlaceRef
  • Match on self.projection (comment from oli)
  • Make a pattern to iterate over projection
  • Do we need ProjectionElem or are we ok with just PlaceElem
    • Today ProjectionElem is a generic and there are two concrete structures that use that PlaceElem and ProjectionKind. Unsure if after some changes we want to revisit this.
      not sure, I think we may want to make places not have a list of projections, and instead just refer to a local
      so niko has this idea where we have virtual locals
      so you can do _virt1 = _1.foo, which does not read from the foo field
      but it it makes _virt1 refer to that field
      now there was a problem he posted just yesterday I think where borrowck allows some fancy things around projection overlap
      https://github.com/rust-lang/rust/issues/71265

Documents from previous all hands

Select a repo