diff options
author | Alan Wu <[email protected]> | 2024-04-15 11:59:45 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2024-04-15 11:59:45 -0400 |
commit | 2eafed0f3bd33d5a4e6103259e1aba6400e5146e (patch) | |
tree | 530629bcdb2fc57db88e17fc9f1594c4a7b94347 | |
parent | 0a4e3f23e6f872537faedb8d728a5696f63a7f89 (diff) |
YJIT: A64: Avoid intermediate register in `opt_and` and friends (#10509)
Same idea as the x64 equivalent in c2622b52536c5, removing the register
shuffle coming from the pop two, push one stack motion these VM
instructions perform.
```
# Insn: 0004 opt_or (stack_size: 2)
- orr x11, x1, x9
- mov x1, x11
+ orr x1, x1, x9
```
-rw-r--r-- | yjit/src/backend/arm64/mod.rs | 27 |
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, .. } => { |