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

ruby-changes:73272

From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 01:07:30 +0900 (JST)
Subject: [ruby-changes:73272] 3f42028e3e (master): Iterator (https://github.com/Shopify/ruby/pull/372)

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

From 3f42028e3e7df7d476e71cc995608e26208e3ae0 Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Thu, 4 Aug 2022 15:29:31 -0400
Subject: Iterator (https://github.com/Shopify/ruby/pull/372)

* Iterator

* Use the new iterator for the X86 backend split

* Use iterator for reg alloc, remove forward pass

* Fix up iterator usage on AArch64

* Update yjit/src/backend/ir.rs

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@g...>

* Various PR feedback for iterators for IR

* Use a local mutable reference for a64_split

* Move tests from ir.rs to tests.rs in backend

* Fix x86 shift instructions live range calculation

* Iterator

* Use the new iterator for the X86 backend split

* Fix up x86 iterator usage

* Fix ARM iterator usage

* Remove unintentionally duplicated tests
---
 yjit/src/backend/arm64/mod.rs  |  34 +++---
 yjit/src/backend/ir.rs         | 238 +++++++++++++++++++++++++++--------------
 yjit/src/backend/tests.rs      |  38 +++++++
 yjit/src/backend/x86_64/mod.rs | 114 +++++++++++---------
 4 files changed, 274 insertions(+), 150 deletions(-)

diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs
index 234339ca4e..fac77f972d 100644
--- a/yjit/src/backend/arm64/mod.rs
+++ b/yjit/src/backend/arm64/mod.rs
@@ -182,12 +182,14 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L182
             }
         }
 
-        self.forward_pass(|asm, index, op, opnds, target, text, pos_marker, original_opnds| {
-            // Load all Value operands into registers that aren't already a part
-            // of Load instructions.
-            let opnds = match op {
-                Op::Load => opnds,
-                _ => opnds.into_iter().map(|opnd| {
+        let mut asm_local = Assembler::new_with_label_names(std::mem::take(&mut self.label_names));
+        let asm = &mut asm_local;
+        let mut iterator = self.into_draining_iter();
+
+        while let Some((index, insn)) = iterator.next_mapped() {
+            let opnds = match insn.op {
+                Op::Load => insn.opnds,
+                _ => insn.opnds.into_iter().map(|opnd| {
                     if let Opnd::Value(_) = opnd {
                         asm.load(opnd)
                     } else {
@@ -196,7 +198,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L198
                 }).collect()
             };
 
-            match op {
+            match insn.op {
                 Op::Add => {
                     match (opnds[0], opnds[1]) {
                         (Opnd::Reg(_) | Opnd::InsnOut { .. }, Opnd::Reg(_) | Opnd::InsnOut { .. }) => {
@@ -217,17 +219,17 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L219
                 Op::And | Op::Or => {
                     match (opnds[0], opnds[1]) {
                         (Opnd::Reg(_), Opnd::Reg(_)) => {
-                            asm.push_insn(op, vec![opnds[0], opnds[1]], target, text, pos_marker);
+                            asm.push_insn(insn.op, vec![opnds[0], opnds[1]], insn.target, insn.text, insn.pos_marker);
                         },
                         (reg_opnd @ Opnd::Reg(_), other_opnd) |
                         (other_opnd, reg_opnd @ Opnd::Reg(_)) => {
                             let opnd1 = split_bitmask_immediate(asm, other_opnd);
-                            asm.push_insn(op, vec![reg_opnd, opnd1], target, text, pos_marker);
+                            asm.push_insn(insn.op, vec![reg_opnd, opnd1], insn.target, insn.text, insn.pos_marker);
                         },
                         _ => {
                             let opnd0 = split_load_operand(asm, opnds[0]);
                             let opnd1 = split_bitmask_immediate(asm, opnds[1]);
-                            asm.push_insn(op, vec![opnd0, opnd1], target, text, pos_marker);
+                            asm.push_insn(insn.op, vec![opnd0, opnd1], insn.target, insn.text, insn.pos_marker);
                         }
                     }
                 },
@@ -246,7 +248,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L248
 
                     // Now we push the CCall without any arguments so that it
                     // just performs the call.
-                    asm.ccall(target.unwrap().unwrap_fun_ptr(), vec![]);
+                    asm.ccall(insn.target.unwrap().unwrap_fun_ptr(), vec![]);
                 },
                 Op::Cmp => {
                     let opnd0 = match opnds[0] {
@@ -273,7 +275,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L275
                         }
                     }).collect();
 
-                    asm.push_insn(op, new_opnds, target, text, pos_marker);
+                    asm.push_insn(insn.op, new_opnds, insn.target, insn.text, insn.pos_marker);
                 },
                 Op::IncrCounter => {
                     // We'll use LDADD later which only works with registers
@@ -392,10 +394,14 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L394
                     asm.test(opnd0, opnd1);
                 },
                 _ => {
-                    asm.push_insn(op, opnds, target, text, pos_marker);
+                    asm.push_insn(insn.op, opnds, insn.target, insn.text, insn.pos_marker);
                 }
             };
-        })
+
+            iterator.map_insn_index(asm);
+        }
+
+        asm_local
     }
 
     /// Emit platform-specific machine code
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 5eee61b228..2dfb859fe9 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -2,8 +2,10 @@ https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L2
 #![allow(unused_variables)]
 #![allow(unused_imports)]
 
+use std::cell::Cell;
 use std::fmt;
 use std::convert::From;
+use std::mem::take;
 use crate::cruby::{VALUE};
 use crate::virtualmem::{CodePtr};
 use crate::asm::{CodeBlock, uimm_num_bits, imm_num_bits};
@@ -288,6 +290,20 @@ impl Opnd https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L290
             _ => unreachable!()
         }
     }
+
+    /// Maps the indices from a previous list of instructions to a new list of
+    /// instructions.
+    pub fn map_index(self, indices: &Vec<usize>) -> Opnd {
+        match self {
+            Opnd::InsnOut { idx, num_bits } => {
+                Opnd::InsnOut { idx: indices[idx], num_bits }
+            }
+            Opnd::Mem(Mem { base: MemBase::InsnOut(idx), disp, num_bits }) => {
+                Opnd::Mem(Mem { base: MemBase::InsnOut(indices[idx]), disp, num_bits })
+            },
+            _ => self
+        }
+    }
 }
 
 impl From<usize> for Opnd {
@@ -433,11 +449,15 @@ pub struct Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L449
 
 impl Assembler
 {
-    pub fn new() -> Assembler {
-        Assembler {
+    pub fn new() -> Self {
+        Self::new_with_label_names(Vec::default())
+    }
+
+    pub fn new_with_label_names(label_names: Vec<String>) -> Self {
+        Self {
             insns: Vec::default(),
             live_ranges: Vec::default(),
-            label_names: Vec::default(),
+            label_names
         }
     }
 
@@ -573,58 +593,6 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L593
         self.live_ranges.push(self.insns.len());
     }
 
-    /// Transform input instructions, consumes the input assembler
-    pub(super) fn forward_pass<F>(mut self, mut map_insn: F) -> Assembler
-        where F: FnMut(&mut Assembler, usize, Op, Vec<Opnd>, Option<Target>, Option<String>, Option<PosMarkerFn>, Vec<Opnd>)
-    {
-        let mut asm = Assembler {
-            insns: Vec::default(),
-            live_ranges: Vec::default(),
-            label_names: self.label_names,
-        };
-
-        // Indices maps from the old instruction index to the new instruction
-        // index.
-        let mut indices: Vec<usize> = Vec::default();
-
-        // Map an operand to the next set of instructions by correcting previous
-        // InsnOut indices.
-        fn map_opnd(opnd: Opnd, indices: &mut Vec<usize>) -> Opnd {
-            match opnd {
-                Opnd::InsnOut{ idx, num_bits } => {
-                    Opnd::InsnOut{ idx: indices[idx], num_bits }
-                }
-                Opnd::Mem(Mem{ base: MemBase::InsnOut(idx), disp, num_bits,  }) => {
-                    Opnd::Mem(Mem{ base:MemBase::InsnOut(indices[idx]), disp, num_bits })
-                }
-                _ => opnd
-            }
-        }
-
-        for (index, insn) in self.insns.drain(..).enumerate() {
-            let original_opnds = insn.opnds.clone();
-            let opnds: Vec<Opnd> = insn.opnds.into_iter().map(|opnd| map_opnd(opnd, &mut indices)).collect();
-
-            // For each instruction, either handle it here or allow the map_insn
-            // callback to handle it.
-            match insn.op {
-                Op::Comment => {
-                    asm.comment(insn.text.unwrap().as_str());
-                },
-                _ => {
-                    map_insn(&mut asm, index, insn.op, opnds, insn.target, insn.text, insn.pos_marker, original_opnds);
-                }
-            };
-
-            // Here we're assuming that if we've pushed multiple instructions,
-            // the output that we're using is still the final instruction that
-            // was pushed.
-            indices.push(asm.insns.len() - 1);
-        }
-
-        asm
-    }
-
     /// Sets the out field on the various instructions that require allocated
     /// registers because their output is used as the operand on a subsequent
     /// instruction. This is our implementation of the linear scan algorithm.
@@ -671,13 +639,15 @@ impl Assembler https://github.com/ruby (... truncated)

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

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