summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yjit/src/backend/arm64/mod.rs27
1 files changed, 24 insertions, 3 deletions
diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs
index 092df6326f..a62ea45e7e 100644
--- a/yjit/src/backend/arm64/mod.rs
+++ b/yjit/src/backend/arm64/mod.rs
@@ -431,12 +431,33 @@ impl Assembler
}
}
},
- Insn::And { left, right, .. } |
- Insn::Or { left, right, .. } |
- Insn::Xor { left, right, .. } => {
+ Insn::And { left, right, out } |
+ Insn::Or { left, right, out } |
+ Insn::Xor { left, right, out } => {
let (opnd0, opnd1) = split_boolean_operands(asm, *left, *right);
*left = opnd0;
*right = opnd1;
+
+ // Since these instructions are lowered to an instruction that have 2 input
+ // registers and an output register, look to merge with an `Insn::Mov` that
+ // follows which puts the output in another register. For example:
+ // `Add a, b => out` followed by `Mov c, out` becomes `Add a, b => c`.
+ if let (Opnd::Reg(_), Opnd::Reg(_), Some(Insn::Mov { dest, src })) = (left, right, iterator.peek()) {
+ if live_ranges[index] == index + 1 {
+ // Check after potentially lowering a stack operand to a register operand
+ let lowered_dest = if let Opnd::Stack { .. } = dest {
+ asm.lower_stack_opnd(dest)
+ } else {
+ *dest
+ };
+ if out == src && matches!(lowered_dest, Opnd::Reg(_)) {
+ *out = lowered_dest;
+ iterator.map_insn_index(asm);
+ iterator.next_unmapped(); // Pop merged Insn::Mov
+ }
+ }
+ }
+
asm.push_insn(insn);
},
Insn::CCall { opnds, fptr, .. } => {