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

ruby-changes:72882

From: Jeremy <ko1@a...>
Date: Wed, 10 Aug 2022 14:20:00 +0900 (JST)
Subject: [ruby-changes:72882] fc4b4f2e8d (master): Expand newarray/expandarray optimization for unequal operands

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

From fc4b4f2e8db3d68b80b9c7580c40a0165736006c Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Wed, 20 Jul 2022 14:06:28 -0700
Subject: Expand newarray/expandarray optimization for unequal operands

This optimizes unbalanced multiple assignment cases such as:

```ruby
a.b, c.d = e, f, g
a.b, c.d, e.f = g, h
```

Previously, this would use:

```
newarray(3)
expandarray(2, 0)

newarray(2)
expandarray(3, 0)
```

These would both allocate arrays.  This switches to opt_reverse
with either pop or putnil:

```
pop
opt_reverse(2)

putnil
opt_reverse(3)
```

This avoids an unnecessary array allocation, and results in a 35-76%
performance increase in these types of unbalanced cases (tested with
benchmark/masgn.yml).
---
 compile.c | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/compile.c b/compile.c
index 9716f04374..8879e661fe 100644
--- a/compile.c
+++ b/compile.c
@@ -3335,16 +3335,20 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal https://github.com/ruby/ruby/blob/trunk/compile.c#L3335
     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)) {
-                ELEM_REMOVE(next);
+            VALUE op1, op2;
+            op1 = OPERAND_AT(iobj, 0);
+            op2 = OPERAND_AT(next, 0);
+            ELEM_REMOVE(next);
+
+            if (op1 == op2) {
                 /*
                  *  newarray 2
                  *  expandarray 2, 0
                  * =>
                  *  swap
                  */
-                if (OPERAND_AT(iobj, 0) == INT2FIX(2)) {
+                if (op1 == INT2FIX(2)) {
                     INSN_OF(iobj) = BIN(swap);
                     iobj->operand_size = 0;
                 }
@@ -3357,6 +3361,38 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal https://github.com/ruby/ruby/blob/trunk/compile.c#L3361
                 else {
                     INSN_OF(iobj) = BIN(opt_reverse);
                 }
+            }
+            else {
+                NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id);
+                long diff = FIX2LONG(op1) - FIX2LONG(op2);
+                INSN_OF(iobj) = BIN(opt_reverse);
+                OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0);
+
+                if (op1 > op2) {
+                    /* X > Y
+                     *  newarray X
+                     *  expandarray Y, 0
+                     * =>
+                     *  pop * (Y-X)
+                     *  opt_reverse Y
+                     */
+                    for (; diff > 0; diff--) {
+                        INSERT_BEFORE_INSN(iobj, &dummy_line_node, pop);
+                    }
+                }
+                else { /* (op1 < op2) */
+                    /* X < Y
+                     *  newarray X
+                     *  expandarray Y, 0
+                     * =>
+                     *  putnil * (Y-X)
+                     *  opt_reverse Y
+                     */
+                    for (; diff < 0; diff++) {
+                        INSERT_BEFORE_INSN(iobj, &dummy_line_node, putnil);
+                    }
+                }
+            }
         }
     }
 
-- 
cgit v1.2.1


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

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