array.push(Foo { ... }) should construct Foo in-place

089fc0f
Opened by Patrick Walton at 2023-04-05 17:41:28

Right now when you push an immediate we construct a temporary copy on the stack and then move it into place on the heap. This is wasteful and results in a good deal of code bloat. Can we do better (with MIR perhaps)?

One possible sketch of a solution is to implement MIR inlining and then use some variant of #32966 that can prove that the construction of the argument to push() does not touch the vector, enabling us to forward the move from the stack to the destination of ptr::write().

An alternative would be to implement rust-lang/rfcs#1426.

cc @eddyb @nikomatsakis

  1. See also #27779 and #30172

    Patrick Walton at 2016-08-08 21:59:50

  2. A simple test I put together quickly results in IR that looks like this:

      %6 = getelementptr inbounds %Struct, %Struct* %.pre, i64 %.pre.i, i32 0
      store i64 %1, i64* %6, align 8
      %7 = getelementptr inbounds %Struct, %Struct* %.pre, i64 %.pre.i, i32 1
      store i64 %2, i64* %7, align 8
    

    There %.pre is the data pointer loaded from the Vec itself.

    @pcwalton The problem occurs in more complex cases, could you try adjusting the one I linked to be more like what you're seeing copies with?

    Eduard-Mihai Burtescu at 2016-08-08 22:20:47

  3. I thought we had some initial impl of placement new?

    Niko Matsakis at 2016-08-08 22:44:33

  4. CC #32366.

    Andrew Paseltiner at 2016-08-09 02:41:04

  5. Is there a code example?

    Ariel Ben-Yehuda at 2016-09-25 09:27:39

  6. Bump; move elimination is one thing we want. @nikomatsakis MIR inlining is available today, what additionally do we need?

    Tatsuyuki Ishi at 2018-05-03 07:29:12