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

ruby-changes:73503

From: Maxime <ko1@a...>
Date: Sat, 10 Sep 2022 07:41:39 +0900 (JST)
Subject: [ruby-changes:73503] 5b5c627d37 (master): YJIT: eliminate redundant mov in csel/cmov on x86 (#6348)

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

From 5b5c627d37c1773dd280e0f14d9510f8fa8db04f Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Fri, 9 Sep 2022 18:41:19 -0400
Subject: YJIT: eliminate redundant mov in csel/cmov on x86 (#6348)

* Eliminate redundant mov in csel/cmov. Translate mov reg,0 into xor

* Fix x86 asm test

* Remove dbg!()

* xor optimization unsound because it resets flags
---
 yjit/src/backend/x86_64/mod.rs | 55 ++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 24 deletions(-)

diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs
index ca07d50ffc..2f770c2eac 100644
--- a/yjit/src/backend/x86_64/mod.rs
+++ b/yjit/src/backend/x86_64/mod.rs
@@ -145,7 +145,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L145
                     if !value.special_const_p() || imm_num_bits(value.as_i64()) > 32 {
                         asm.load(iterator.map_opnd(*opnd))
                     } else {
-                        iterator.map_opnd(*opnd)
+                        Opnd::UImm(value.as_u64())
                     }
                 } else {
                     iterator.map_opnd(*opnd)
@@ -221,18 +221,25 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L221
                 Insn::CSelLE { truthy, falsy, out } |
                 Insn::CSelG { truthy, falsy, out } |
                 Insn::CSelGE { truthy, falsy, out } => {
-                    match truthy {
-                        Opnd::Reg(_) | Opnd::InsnOut { .. } => {},
-                        _ => {
+                    match unmapped_opnds[0] {
+                        // If we have an instruction output whose live range
+                        // spans beyond this instruction, we have to load it.
+                        Opnd::InsnOut { idx, .. } => {
+                            if live_ranges[idx] > index {
+                                *truthy = asm.load(*truthy);
+                            }
+                        },
+                        Opnd::UImm(_) | Opnd::Imm(_) | Opnd::Value(_) => {
                             *truthy = asm.load(*truthy);
-                        }
+                        },
+                        _ => {}
                     };
 
                     match falsy {
-                        Opnd::Reg(_) | Opnd::InsnOut { .. } => {},
-                        _ => {
+                        Opnd::UImm(_) | Opnd::Imm(_) => {
                             *falsy = asm.load(*falsy);
-                        }
+                        },
+                        _ => {}
                     };
 
                     *out = asm.next_opnd_out(Opnd::match_num_bits(&[*truthy, *falsy]));
@@ -350,6 +357,14 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L357
             }
         }
 
+
+        fn emit_csel(cb: &mut CodeBlock, truthy: Opnd, falsy: Opnd, out: Opnd, cmov_fn: fn(&mut CodeBlock, X86Opnd, X86Opnd)) {
+            if out != truthy {
+                mov(cb, out.into(), truthy.into());
+            }
+            cmov_fn(cb, out.into(), falsy.into());
+        }
+
         //dbg!(&self.insns);
 
         // List of GC offsets
@@ -609,36 +624,28 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L624
                 Insn::Breakpoint => int3(cb),
 
                 Insn::CSelZ { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovnz(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovnz);
                 },
                 Insn::CSelNZ { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovz(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovz);
                 },
                 Insn::CSelE { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovne(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovne);
                 },
                 Insn::CSelNE { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmove(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmove);
                 },
                 Insn::CSelL { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovge(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovge);
                 },
                 Insn::CSelLE { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovg(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovg);
                 },
                 Insn::CSelG { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovle(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovle);
                 },
                 Insn::CSelGE { truthy, falsy, out } => {
-                    mov(cb, out.into(), truthy.into());
-                    cmovl(cb, out.into(), falsy.into());
+                    emit_csel(cb, *truthy, *falsy, *out, cmovl);
                 }
                 Insn::LiveReg { .. } => (), // just a reg alloc signal, no code
                 Insn::PadEntryExit => {
-- 
cgit v1.2.1


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

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