summaryrefslogtreecommitdiff
path: root/zjit/src/backend/arm64
AgeCommit message (Collapse)Author
2025-12-16Revert "ZJIT: Allow ccalls above 7 arguments"Alan Wu
This reverts commit 2f151e76b5dc578026706b31f054d5caf5374b05. The SP decrement (push) before the call do not match up with the pops after the call, so registers were restored incorrectly. Code from: ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e 'p Time.new(1992, 9, 23, 23, 0, 0, :std)' str x11, [sp, #-0x10]! str x12, [sp, #-0x10]! stur x7, [sp] # last argument mov x0, x20 mov x7, x6 mov x6, x5 mov x5, x4 mov x4, x3 mov x3, x2 mov x2, x1 ldur x1, [x29, #-0x20] mov x16, #0xccfc movk x16, #0x2e7, lsl #16 movk x16, #1, lsl #32 blr x16 ldr x12, [sp], #0x10 # supposed to match str x12, [sp, #-0x10]!, but got last argument ldr x11, [sp], #0x10
2025-12-12ZJIT: Allow ccalls above 7 arguments (#15312)Aiden Fox Ivey
ZJIT: Add stack support for CCalls
2025-12-10ZJIT: Re-compile ISEQs invalidated by PatchPoint (#15459)Takashi Kokubun
2025-12-10ZJIT: Use inline format args (#15482)Alex Rocha
2025-12-03ZJIT: Use the custom iteratorAaron Patterson
This commit uses the custom instruction iterator in arm64 / x86_64 instruction splitting. Once we introduce basic blocks to LIR, the custom iterator will ensure that instructions are added to the correct place.
2025-11-14ZJIT: Use Mem.num_bits in Mem split (#15177)Max Bernstein
Fix the ``` write(2, "ruby: ZJIT has panicked. More info to follow...\n", 48) = 48 write(2, "\nthread '<unnamed>' panicked at zjit/src/backend/lir.rs:160:17:\nassertion failed: num_bits <= out_num_bits\n", 107) = 107 ``` based on ``` #25 0x0000aaaaaae8fb14 in zjit::backend::lir::Opnd::mem (num_bits=64, base=..., disp=0) at zjit/src/backend/lir.rs:160 #26 zjit::backend::arm64::{impl#3}::arm64_split::split_memory_address (asm=<optimized out>, opnd=<error reading variable: Cannot access memory at address 0x0>) at zjit/src/backend/arm64/mod.rs:260 #27 zjit::backend::arm64::{impl#3}::arm64_split::split_load_operand (asm=<optimized out>, opnd=...) at zjit/src/backend/arm64/mod.rs:273 ```
2025-11-10ZJIT: Deduplicate side exits (#15105)Takashi Kokubun
2025-11-04ZJIT: Allow Store with 8-bit Opnd::MemTakashi Kokubun
2025-11-04ZJIT: Split LShift in arm64_scratch_splitTakashi Kokubun
2025-11-04ZJIT: Use a shared trampoline across all ISEQs (#15042)Takashi Kokubun
2025-11-03ZJIT: Implement register spill (#14936)Takashi Kokubun
2025-10-29ZJIT: Rename compile_side_exits to compile_exitsTakashi Kokubun
so that it can be easily specified with `--zjit-dump-lir=`.
2025-10-29ZJIT: Avoid cloning Assembler repeatedlyTakashi Kokubun
2025-10-29ZJIT: Refactor operand printerTakashi Kokubun
2025-10-29ZJIT: Introduce a better LIR printer (#14986)Takashi Kokubun
2025-10-28ZJIT: Migrate an arm64 register from emit to splitTakashi Kokubun
2025-10-28ZJIT: Support ParallelMov into memory (#14975)Takashi Kokubun
2025-10-28ZJIT: Move c_stack_slots to AssemblerTakashi Kokubun
2025-10-28ZJIT: Simplify Assembler constructorsTakashi Kokubun
2025-10-22ZJIT: Fix some dead code in the backend (#14897)Takashi Kokubun
2025-10-22ZJIT: A64: Fix Lea with large displacement and overlapping registerAlan Wu
Previously, when the output register and the base register are the same in `out = Lea(Mem(out, disp))`, we did out = disp out = out + out Which wasn't the desired `out = out + disp`. Fixes a SEGV with `--zjit-call-threshold=2` in `bootstraptest/test_yjit.rb`.
2025-10-15ZJIT: Rewrite arm64_split_with_scratch_reg for clarityAiden Fox Ivey
* The while loop pattern can be rewritten to be more idiomatic, which also allows the iterator to no longer be mutable.
2025-10-15ZJIT: Centralize the allocation of scratch registers (#14815)Takashi Kokubun
2025-10-03ZJIT: Make sure zjit-test-update works in asm tests (#14708)Takashi Kokubun
2025-09-23ZJIT: Allow testing JIT code on zjit-test (#14639)Takashi Kokubun
* ZJIT: Allow testing JIT code on zjit-test * Resurrect TestingAllocator tests
2025-09-19ZJIT: Remove unnecessary empty linesTakashi Kokubun
2025-09-19ZJIT: Fix disasm tests on release build (#14612)Takashi Kokubun
* ZJIT: Fix disasm tests on release build * Rename string() to hexdump()
2025-09-19ZJIT: Test disasm with insta (#14602)Takashi Kokubun
2025-09-12ZJIT: Share more code with YJIT in jit.c (#14520)Takashi Kokubun
* ZJIT: Share more code with YJIT in jit.c * Fix ZJIT references to JIT
2025-09-08ZJIT: Fix 30k if stmt test (#14446)Aiden Fox Ivey
* ZJIT: Allow label generation above 19 bits * Refactor emit_conditional_jump to use generate_branch * Make branching functionality generic across Label and CodePtr * ZJIT: Add > 19 bit jump test and helper function * Remove an empty line --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2025-09-03ZJIT: Ensure `clippy` passes and silence unnecessary warnings (#14439)Aiden Fox Ivey
2025-09-02ZJIT: Remove unnecessary return statementsAiden Fox Ivey
2025-09-02ZJIT: Remove unnecessary .into callsAiden Fox Ivey
2025-09-02ZJIT: Propagate and count CompileError on exits (#14408)Takashi Kokubun
2025-08-27ZJIT: Implement side exit stats (#14357)Takashi Kokubun
2025-08-21ZJIT: Allocate register for VRegs that begin and end at the same index (#14270)Max Bernstein
If the LiveRange looks like (idx, idx), we will currently not allocate a register. This change allocates a register and then immediately deallocates it. Fix https://github.com/Shopify/ruby/issues/614
2025-08-14ZJIT: Stop duplicating context-less side exits (#14215)Takashi Kokubun
2025-08-13ZJIT: Enable or remove comments from YJIT (#14214)Takashi Kokubun
2025-08-07ZJIT: Remove the need for unwrap() on with_num_bits() (#14144)Takashi Kokubun
* ZJIT: Remove the need for unwrap() on with_num_bits() * Fix arm64 tests * Track the caller of with_num_bits Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> --------- Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2025-08-01ZJIT: Enable IncrCounter for arm64 (#14086)Takashi Kokubun
2025-08-01ZJIT: Refer to scratch registers in operandsAlan Wu
Co-authored-by: Takashi Kokubun <takashi.kokubun@shopify.com>
2025-08-01ZJIT: Fix side-exit panicking when there's too many localsAlan Wu
Previously, ARM64 panicked due to compiled_side_exits() when the memory displacement got large enough to exceed the 9 bits limit. Usually, we split these kind of memory operands, but compiled_side_exits() runs after split. Using scratch registers, implement `Insn::Store` on ARM such that it can handle large displacements without split(). Do this for x86 as well, and remove arch specific code from compiled_side_exits(). We can now run `TestKeywordArguments`. Since `Insn::Store` doesn't need splitting now, users enjoy lower register pressure. Downside is, using `Assembler::SCRATCH_REG` as a base register is now sometimes an error, depending on whether `Insn::Store` also needs to use the register. It seems a fair trade off since `SCRATCH_REG` is not often used, and we don't put it as a base register anywhere at the moment.
2025-08-01ZJIT: A64: Use MOVN for small negative immediatesAlan Wu
Save a couple instructions to load a small negative constant into a register. In fact MOVN is speced to alias as `mov` in the official disassembly.
2025-07-31ZJIT: A64: Fix splitting for large memory displacementsAlan Wu
On the ruby side, this fixes a crash for methods with 39 or more parameters. We used to miscomp those entry points due to Insn::Lea picking ADDS which cannot reference SP: # set method params: 40 mov x0, #0xfee8 movk x0, #0xffff, lsl #16 movk x0, #0xffff, lsl #32 movk x0, #0xffff, lsl #48 adds x0, xzr, x0 Have Lea work for all i32 displacements and avoid involving the split pass. Previously, direct use of Insn::Lea directly from the user (as opposed to generated by the split pass for some memory operations) wasn't split, so being able to handle the whole range in arm64_emit() was implicitly required. Also, not going through split reduces register pressure.
2025-07-28ZJIT: Keep a frame pointer and use it for memory paramsAlan Wu
Previously, ZJIT miscompiled the following because of native SP interference. def a(n1,n2,n3,n4,n5,n6,n7,n8) = [n8] a(0,0,0,0,0,0,0, :ok) Commented problematic disassembly: ; call rb_ary_new_capa mov x0, #1 mov x16, #0x1278 movk x16, #0x4bc, lsl #16 movk x16, #1, lsl #32 blr x16 ; call rb_ary_push mov x1, x0 str x1, [sp, #-0x10]! ; c_push() from alloc_regs() mov x0, x1 ; arg0, the array ldur x1, [sp] ; meant to be arg1=n8, but sp just moved! mov x16, #0x3968 movk x16, #0x4bc, lsl #16 movk x16, #1, lsl #32 blr x16 Since the frame pointer stays constant in the body of the function, static offsets based on it don't run the risk of being invalidated by SP movements. Pass the registers to preserve through Insn::FrameSetup. This allows ARM to use STP and waste no gaps between EC, SP, and CFP. x86 now preserves and restores RBP since we use it as the frame pointer. Since all arches now have a frame pointer, remove offset based SP movement in the epilogue and restore registers using the frame pointer.
2025-07-24ZJIT: DRY up underscore rexport anti-patternAlan Wu
Keeping the same name makes re-exporting more concise.
2025-07-21ZJIT: Remove no-op movs after register allocationAlan Wu
Previously `no_dead_mov_from_vreg` generated: 0x0: ldur x0, [x0] 0x4: mov x0, x0 0x8: ret Because of phase ordering. Split couldn't recognize that the no-op mov because at that point it sees a `VReg`.
2025-07-16ZJIT: Split shift with immediate operand (#13914)Max Bernstein
Fix https://github.com/Shopify/ruby/issues/627
2025-07-16ZJIT: A64: Fix bad operand swapping in `asm.sub(imm, reg)`Alan Wu
Previously, my buggy optimization would turn `asm.sub(imm, reg)` into `subs out, reg, imm` since it runs through the addition path which relies on the commutative property. Don't do that because subtraction does not commute. Good thing no one seems to use this form. Also, delete the 2 regs match arm for Add because it's already covered by the fallback arm -- both split_load_operand() and split_shifted_immediate() are no-op when the input is a register. Fixes: 1317377fa74 ("ZJIT: A64: Have add/sub to SP be single-instruction")
2025-07-16ZJIT: A64: Fix the optimization merging `asm.add(reg, imm)` with MovAlan Wu
The raw bytes didn't disassemble to the disassembly, but we missed this since CI didn't run `make zjit-test` with the disasm feature. Fixes: 1317377fa74 ("ZJIT: A64: Have add/sub to SP be single-instruction")