diff options
author | Jeremy Evans <code@jeremyevans.net> | 2022-07-20 12:16:24 -0700 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2022-08-09 22:19:46 -0700 |
commit | 9f8abd28babf1ab84093fe0cc97f8d42cf62286c (patch) | |
tree | fc678b2ab6ffd8a554019383a2cd04850b43b92f | |
parent | 3569d1309501a5e8ae4656d90d521c7eaa3330c6 (diff) |
Add peephole optimizer for newarray(2)/expandarray(2, 0) -> swap
An optimization for multiple assignment in the popped case to avoid
array allocation was lost in my fix to make multiple assignment follow
left-to-right evaluation (50c54d40a81bb2a4794a6be5f1861152900b4fed).
Before, in the two element case, swap was used. Afterward, newarray(2)
and expandarray(2, 0) were used, which is the same as swap, with the
addition of an unnecessary allocation.
Because this issue is not specific to multiple assignment, and the
multiple assignment code is complex enough as it is, this updates
the peephole optimizer to do the newarray(2)/expandarray(2, 0) -> swap
conversion.
A more general optimization pass for
newarray(X)/expandarray(X, 0) -> reverse(X) will follow, but that
requires readding the reverse instruction.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6158
-rw-r--r-- | compile.c | 19 |
1 files changed, 19 insertions, 0 deletions
@@ -3332,6 +3332,25 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } + if (IS_INSN_ID(iobj, newarray)) { + LINK_ELEMENT *next = iobj->link.next; + if (IS_INSN(next) && IS_INSN_ID(next, expandarray) && + OPERAND_AT(iobj, 0) == OPERAND_AT(next, 0) && + OPERAND_AT(next, 1) == INT2FIX(0)) { + /* + * newarray 2 + * expandarray 2, 0 + * => + * swap + */ + if (OPERAND_AT(iobj, 0) == INT2FIX(2)) { + ELEM_REMOVE(next); + INSN_OF(iobj) = BIN(swap); + iobj->operand_size = 0; + } + } + } + if (IS_INSN_ID(iobj, anytostring)) { LINK_ELEMENT *next = iobj->link.next; /* |