This follows the rest of the code base data structures, where we have a
mutable data structure builder; once the data structure is constructed,
it's immutable.
This also makes the definition of instructions easier, and it paves the
way for defining immediate variants.
This is also https://bugzilla.mozilla.org/show_bug.cgi?id=1552737.
Cranelift currently has a tendency to create redundant copies (self-copies) of
values from a stack slot back to the same stack slot. This generates a
pointless load and store and an unnecessary register use. The copies are
created by `visit_inst` in regalloc/reload.rs. They appear to occur mostly,
but not exclusively, at loop heads. It's unclear why this happens.
This patch adds a special case to `visit_inst` to find such copies. They are
converted into a new instruction, `copy_nop`, which takes and produces the
same SSA names, so as not to break any of the SSA invariants, but which has a
zero-length encoding, hence removing the copy at emission time.
`copy_nop`s source and destination operands must be stack slots and of course
the *same* stack slot. The verifier has been enhanced to check this, since
misuse of `copy_nop` will likely lead to hard-to-find incorrect-code bugs.
Attempts were made to write a standalone .clif test case. But these failed
because it appears the .clif parser accepts but ignores location hints that
are stack slots. So it's impossible to write, in clif, the exact form of
`copy` instruction that triggers the transformation.
- adds helpers used by other parts of the code
- allows cheap copies by having Instruction be a lightweight ref-cloned
wrapper of the actual instruction's content.
There might be a silent bug in the Python module which directly reads
from this type_set field; in particular, it does so when reading all
controlling type variables, which all seem to be free variables (i.e. no
parent typevar). So imitate this behavior here, until we're sure there
are no other meta generators that rely on this.
Fixes two issues:
- name of derived type variables wasn't correct. (This is used during
code generation.)
- the TypeVar::derived() function wasn't creating the correct type set
(and would instead propagate the parent's one).