summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-07-20 12:16:24 -0700
committerJeremy Evans <code@jeremyevans.net>2022-08-09 22:19:46 -0700
commit9f8abd28babf1ab84093fe0cc97f8d42cf62286c (patch)
treefc678b2ab6ffd8a554019383a2cd04850b43b92f
parent3569d1309501a5e8ae4656d90d521c7eaa3330c6 (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.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/compile.c b/compile.c
index 6a9ed2a5d0..f38a320b76 100644
--- a/compile.c
+++ b/compile.c
@@ -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;
/*