[前][次][番号順一覧][スレッド一覧]

ruby-changes:72881

From: Jeremy <ko1@a...>
Date: Wed, 10 Aug 2022 14:19:59 +0900 (JST)
Subject: [ruby-changes:72881] 9f8abd28ba (master): Add peephole optimizer for newarray(2)/expandarray(2, 0) -> swap

https://git.ruby-lang.org/ruby.git/commit/?id=9f8abd28ba

From 9f8abd28babf1ab84093fe0cc97f8d42cf62286c Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Wed, 20 Jul 2022 12:16:24 -0700
Subject: 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.
---
 compile.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

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 https://github.com/ruby/ruby/blob/trunk/compile.c#L3332
         }
     }
 
+    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;
         /*
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]