Hi everyone,
I believe that by-move pattern bindings don't actually have to perform
any copying of bits for non-word-sized values. This applies to both
`let` and `match`. It surprised me too, which is why I thought I'd send
it to the mailing list first.
A by-move pattern binding is any binding not denoted by `ref`:
let x = Some(HashMap::new());
// ^
match x {
None => ...,
Some(map) => ...
// ^^^
}
You might think that, for each by-move pattern binding, we have to
generate a slot on the stack with the size of the binding and copy in
all the bytes that correspond to that stack slot. Indeed, this is what
we generate today. So, for the above code, we would have two stack
slots, each 88 bytes long. The match expression would generate a shallow
memory copy from the stack to the stack. Since there are 88 bytes,
that's a lot of bytes to copy. In fact, this function is 500-1000 bytes
of x86-64 assembly code, even when optimized.
I believe that we can eliminate this by converting non-word-sized
(non-"immediate" in the compiler jargon) pattern bindings to references
instead. Justification:
1. Every by-move pattern binding is moving out of something that can
legally be moved out of in Rust.
2. The only things that can be moved out of in Rust are locals and rvalues.
3. Locals have stack slots already assigned to them. Since those stack
slots are hoisted allocas, they will stick around for the lifetime of
the pattern binding, since pattern bindings are locals. So it makes no
sense to allocate a new slot for this.
4. Rvalues already have scratch space allocated for them (unless they
are "destination-passing-style" rvalues--more on that later), so a
similar argument applies.
5. We already treat non-word-sized values as pointers in codegen; we
don't use LLVM first class aggregates. So all of the code that deals
with aggregates in trans does not have to change.
Combined with the zeroing out optimization, this should remove a lot of
useless moves. The remaining, more difficult, issue is initialization of
aggregate data structures via constructor functions, which still
involves a bunch of moves, but I don't really see any way short of
macros to optimize that at the moment.
Thoughts? :)
Patrick
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev