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

ruby-changes:73286

From: Kevin <ko1@a...>
Date: Tue, 30 Aug 2022 01:07:54 +0900 (JST)
Subject: [ruby-changes:73286] 7f4ab24f2b (master): Op::Xor for backend IR (https://github.com/Shopify/ruby/pull/397)

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

From 7f4ab24f2b99c87874a5540a55026ea5a3d43d3e Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Thu, 11 Aug 2022 08:32:06 -0400
Subject: Op::Xor for backend IR (https://github.com/Shopify/ruby/pull/397)

---
 yjit/src/asm/arm64/inst/logical_imm.rs | 16 ++++++++++++++++
 yjit/src/asm/arm64/inst/logical_reg.rs | 16 ++++++++++++++++
 yjit/src/asm/arm64/mod.rs              | 32 ++++++++++++++++++++++++++++++++
 yjit/src/backend/arm64/mod.rs          | 15 ++++++++++++++-
 yjit/src/backend/ir.rs                 |  5 +++++
 yjit/src/backend/x86_64/mod.rs         |  6 +++++-
 6 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/yjit/src/asm/arm64/inst/logical_imm.rs b/yjit/src/asm/arm64/inst/logical_imm.rs
index 13865697f6..73eec8b37c 100644
--- a/yjit/src/asm/arm64/inst/logical_imm.rs
+++ b/yjit/src/asm/arm64/inst/logical_imm.rs
@@ -8,6 +8,9 @@ enum Opc { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_imm.rs#L8
     /// The ORR operation.
     Orr = 0b01,
 
+    /// The EOR operation.
+    Eor = 0b10,
+
     /// The ANDS operation.
     Ands = 0b11
 }
@@ -52,6 +55,12 @@ impl LogicalImm { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_imm.rs#L55
         Self { rd, rn, imm, opc: Opc::Ands, sf: num_bits.into() }
     }
 
+    /// EOR (bitmask immediate)
+    /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/EOR--immediate---Bitwise-Exclusive-OR--immediate--
+    pub fn eor(rd: u8, rn: u8, imm: BitmaskImmediate, num_bits: u8) -> Self {
+        Self { rd, rn, imm, opc: Opc::Eor, sf: num_bits.into() }
+    }
+
     /// MOV (bitmask immediate)
     /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/MOV--bitmask-immediate---Move--bitmask-immediate---an-alias-of-ORR--immediate--?lang=en
     pub fn mov(rd: u8, imm: BitmaskImmediate, num_bits: u8) -> Self {
@@ -115,6 +124,13 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_imm.rs#L124
         assert_eq!(0xf2400820, result);
     }
 
+    #[test]
+    fn test_eor() {
+        let inst = LogicalImm::eor(0, 1, 7.try_into().unwrap(), 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xd2400820, result);
+    }
+
     #[test]
     fn test_mov() {
         let inst = LogicalImm::mov(0, 0x5555555555555555.try_into().unwrap(), 64);
diff --git a/yjit/src/asm/arm64/inst/logical_reg.rs b/yjit/src/asm/arm64/inst/logical_reg.rs
index 5d7954c587..83230ac5b2 100644
--- a/yjit/src/asm/arm64/inst/logical_reg.rs
+++ b/yjit/src/asm/arm64/inst/logical_reg.rs
@@ -25,6 +25,9 @@ enum Opc { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_reg.rs#L25
     /// The ORR operation.
     Orr = 0b01,
 
+    /// The EOR operation.
+    Eor = 0b10,
+
     /// The ANDS operation.
     Ands = 0b11
 }
@@ -78,6 +81,12 @@ impl LogicalReg { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_reg.rs#L81
         Self { rd, rn, imm6: 0, rm, n: N::No, shift: Shift::LSL, opc: Opc::Ands, sf: num_bits.into() }
     }
 
+    /// EOR (shifted register)
+    /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/EOR--shifted-register---Bitwise-Exclusive-OR--shifted-register--
+    pub fn eor(rd: u8, rn: u8, rm: u8, num_bits: u8) -> Self {
+        Self { rd, rn, imm6: 0, rm, n: N::No, shift: Shift::LSL, opc: Opc::Eor, sf: num_bits.into() }
+    }
+
     /// MOV (register)
     /// https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/MOV--register---Move--register---an-alias-of-ORR--shifted-register--?lang=en
     pub fn mov(rd: u8, rm: u8, num_bits: u8) -> Self {
@@ -156,6 +165,13 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/inst/logical_reg.rs#L165
         assert_eq!(0xea020020, result);
     }
 
+    #[test]
+    fn test_eor() {
+        let inst = LogicalReg::eor(0, 1, 2, 64);
+        let result: u32 = inst.into();
+        assert_eq!(0xca020020, result);
+    }
+
     #[test]
     fn test_mov() {
         let inst = LogicalReg::mov(0, 1, 64);
diff --git a/yjit/src/asm/arm64/mod.rs b/yjit/src/asm/arm64/mod.rs
index 93b44dba4b..e5ba2f81ea 100644
--- a/yjit/src/asm/arm64/mod.rs
+++ b/yjit/src/asm/arm64/mod.rs
@@ -309,6 +309,28 @@ pub fn csel(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, rm: A64Opnd, cond: u8) https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L309
     cb.write_bytes(&bytes);
 }
 
+/// EOR - perform a bitwise XOR of rn and rm, put the result in rd, don't update flags
+pub fn eor(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, rm: A64Opnd) {
+    let bytes: [u8; 4] = match (rd, rn, rm) {
+        (A64Opnd::Reg(rd), A64Opnd::Reg(rn), A64Opnd::Reg(rm)) => {
+            assert!(
+                rd.num_bits == rn.num_bits && rn.num_bits == rm.num_bits,
+                "All operands must be of the same size."
+            );
+
+            LogicalReg::eor(rd.reg_no, rn.reg_no, rm.reg_no, rd.num_bits).into()
+        },
+        (A64Opnd::Reg(rd), A64Opnd::Reg(rn), A64Opnd::UImm(imm)) => {
+            assert!(rd.num_bits == rn.num_bits, "rd and rn must be of the same size.");
+
+            LogicalImm::eor(rd.reg_no, rn.reg_no, imm.try_into().unwrap(), rd.num_bits).into()
+        },
+        _ => panic!("Invalid operand combination to eor instruction."),
+    };
+
+    cb.write_bytes(&bytes);
+}
+
 /// LDADDAL - atomic add with acquire and release semantics
 pub fn ldaddal(cb: &mut CodeBlock, rs: A64Opnd, rt: A64Opnd, rn: A64Opnd) {
     let bytes: [u8; 4] = match (rs, rt, rn) {
@@ -1023,6 +1045,16 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/asm/arm64/mod.rs#L1045
         check_bytes("6a018c9a", |cb| csel(cb, X10, X11, X12, Condition::EQ));
     }
 
+    #[test]
+    fn test_eor_register() {
+        check_bytes("6a010cca", |cb| eor(cb, X10, X11, X12));
+    }
+
+    #[test]
+    fn test_eor_immediate() {
+        check_bytes("6a0940d2", |cb| eor(cb, X10, X11, A64Opnd::new_uimm(7)));
+    }
+
     #[test]
     fn test_ldaddal() {
         check_bytes("8b01eaf8", |cb| ldaddal(cb, X10, X11, X12));
diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs
index 440c4368c5..2cd893923a 100644
--- a/yjit/src/backend/arm64/mod.rs
+++ b/yjit/src/backend/arm64/mod.rs
@@ -216,7 +216,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L216
                         }
                     }
                 },
-                Op::And | Op::Or => {
+                Op::And | Op::Or | Op::Xor => {
                     match (opnds[0], opnds[1]) {
                         (Opnd::Reg(_), Opnd::Reg(_)) => {
                             asm.push_insn(insn.op, vec![opnds[0], opnds[1]], insn.target, insn.text, insn.pos_marker);
@@ -615,6 +615,9 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L615
                 Op::Or => {
                     orr(cb, insn.out.into(), insn.opnds[0].into(), insn.opnds[1].into());
                 },
+                Op::Xor => {
+                    eor(cb, insn.out.into(), insn.opnds[0].into(), insn.opnds[1].into());
+                },
                 Op::Not => {
                     mvn(cb, insn.out.into(), insn.opnds[0].into());
                 },
@@ -1084,6 +1087,16 @@ mod tests { https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L1087
         assert_eq!(8, cb.get_write_pos());
     }
 
+    #[test]
+    fn test_emit_xor() {
+        let (mut asm, mut cb) = setup_asm();
+
+        let opnd = asm.xor(Opnd::Reg(X0_REG), Opnd::Reg(X1_REG));
+        asm.store(Opnd::mem(64, Opnd::Reg(X2_REG), 0), opnd);
+
+        asm.compile_with_num_regs(&mut cb, 1);
+    }
+
     #[test]
     #[cfg(feature = "disasm")]
     fn test_simple_disasm() -> std::result::Result<(), capstone::Error> {
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 2dfb859fe9..ef8cd5e872 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -63,6 +63,10 @@ pub enum Op https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L63
     // binary OR operation.
     Or,
 
+    // This is the same as the OP_ADD instruction, except that it performs the
+    // binary XOR operation.
+    Xor,
+
     // Perform the NOT operation on an individual operand, and return the result
     // as a new operand. This operand can then be used as the operand on another
     // instruction.
@@ -992,6 +996,7 @@ def_push_2_opnd!(add, Op::Add); https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L996
 def_push_2_opnd!(sub, Op::Sub);
 def_push_2_opnd!(and, Op::And);
 def_push_2_opnd!(or, Op::Or);
+def_push_2_opnd!(xor, Op::Xor);
 def_push_1_opnd!(not, Op::Not);
 def_push_2_opnd!(lshift, Op::LShift);
 def_push_2_opnd!(rshift, Op::RShift);
diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs
index 417474ee68..d474c9fe59 100644
--- a/yjit/src/backend/x86_64/mod.rs
+++ b/yjit/src/backend/x86_64/mod.rs
@@ -139,7 +139,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L139
             }).collect();
 
             match insn.op {
-                Op::Add | Op::Sub | Op::And | Op::Cmp | Op::Or | Op::Test => {
+                Op::Add | Op::Sub | Op::And | Op::Cmp | Op::Or | Op::Test | Op::Xor => {
                     let (opnd0, opnd1) = match (insn.opnds[0], insn.opnds[1]) {
                         (Opnd::Mem(_), Opnd::Mem(_)) => {
                             (asm.load(opnds[0]), asm.load(opnds[1]))
@@ -328,6 +328,10 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L328
                     or(cb, insn.opnds[0].into(), insn.opnds[1].into());
                 },
 
+                Op::Xor => {
+                    xor(cb, insn.opnds[0].into(), insn.opnds[1].into());
+                },
+
                 Op::Not => {
                     not(cb, insn.opn (... truncated)

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

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