From 8fb36d5d36032f5fd9aeefe147aafc75e4c3d27c Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Mon, 22 Dec 2025 19:38:23 -0800 Subject: [PATCH] Cranelift: pulley: don't use call{1,2,3,4} opcodes with PreserveAll ABI. These Pulley instructions are an optimization: they incorporate moves from other registers to x0/x1/x2/x3 as part of the call itself. This works fine for the default calling convention, but the logic that absorbs these moves and removes them from the list given to the rest of the VCode/ABI machinery embeds a tacit assumption: the argument registers are volatile (caller-saved). In particular, this is because the call{1,2,3,4} instructions are *not* marked as clobbering x0/x1/x2/x3 explicitly. To fix this issue, this PR simply omits the magical folding that happens in the emission code. An alternative would be to try to add the clobbers to the special instructions, but actually we don't want these to be just "clobbers": we want the usual regalloc constraints to take effect and the values to be represented as continuing valid/live in the registers after return, and the proper way to do that is to leave the `args` on the call and let the regalloc operand pass add the fixed-reg operands. Discovered while trying to land #12183. --- .../src/isa/pulley_shared/lower/isle.rs | 30 +++++++----- .../isa/pulley32/patchable-call.clif | 46 +++++++++++-------- .../filetests/isa/pulley32/preserve-all.clif | 31 ++++++++++++- .../isa/pulley64/patchable-call.clif | 46 +++++++++++-------- .../filetests/isa/pulley64/preserve-all.clif | 2 +- 5 files changed, 106 insertions(+), 49 deletions(-) diff --git a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs index 1dd3ba587cec..d72b6a023789 100644 --- a/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs +++ b/cranelift/codegen/src/isa/pulley_shared/lower/isle.rs @@ -7,6 +7,7 @@ use inst::InstAndKind; // Types that the generated ISLE code uses via `use super::*`. use crate::ir::{condcodes::*, immediates::*, types::*, *}; +use crate::isa::CallConv; use crate::isa::pulley_shared::{ inst::{ FReg, OperandSize, PulleyCall, ReturnCallInfo, VReg, WritableFReg, WritableVReg, @@ -85,6 +86,7 @@ where self.lower_ctx .abi_mut() .accumulate_outgoing_args_size(stack_ret_space + stack_arg_space); + let call_conv = self.lower_ctx.sigs()[sig].call_conv(); // The first four integer arguments to a call can be handled via // special pulley call instructions. Assert here that @@ -92,19 +94,25 @@ where // they're present and move them from `uses` to // `dest.args` to be handled differently during register // allocation. + // + // We don't perform this optimization for callsites with the + // PreserveAll ABI because argument registers are not + // clobbered on those ISAs. let mut args = SmallVec::new(); uses.sort_by_key(|arg| arg.preg); - uses.retain(|arg| { - if arg.preg != regs::x0() - && arg.preg != regs::x1() - && arg.preg != regs::x2() - && arg.preg != regs::x3() - { - return true; - } - args.push(XReg::new(arg.vreg).unwrap()); - false - }); + if call_conv != CallConv::PreserveAll { + uses.retain(|arg| { + if arg.preg != regs::x0() + && arg.preg != regs::x1() + && arg.preg != regs::x2() + && arg.preg != regs::x3() + { + return true; + } + args.push(XReg::new(arg.vreg).unwrap()); + false + }); + } let dest = PulleyCall { name, args }; Box::new( self.lower_ctx diff --git a/cranelift/filetests/filetests/isa/pulley32/patchable-call.clif b/cranelift/filetests/filetests/isa/pulley32/patchable-call.clif index 50c2a7e333d0..b09e4e4bd33b 100644 --- a/cranelift/filetests/filetests/isa/pulley32/patchable-call.clif +++ b/cranelift/filetests/filetests/isa/pulley32/patchable-call.clif @@ -12,15 +12,21 @@ block0(v0: i64): ; VCode: ; push_frame ; block0: -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p0i), XReg(p0i), XReg(p0i), XReg(p0i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p0i), XReg(p0i), XReg(p0i), XReg(p0i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; xmov x3, x0 +; xmov x1, x3 +; xmov x2, x3 +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } ; pop_frame ; ret ; ; Disassembled: ; push_frame -; call4 x0, x0, x0, x0, 0x5 // target = 0x6 -; call4 x0, x0, x0, x0, 0x5 // target = 0xf +; xmov x3, x0 +; xmov x1, x3 +; xmov x2, x3 +; call 0x1 // target = 0xb +; call 0x1 // target = 0x10 ; pop_frame ; ret @@ -36,26 +42,32 @@ block0(v0: i64): ; push_frame ; block0: ; xmov x9, x0 +; xmov x1, x9 +; xmov x2, x9 +; xmov x3, x9 ; xmov x4, x9 ; xmov x5, x9 ; xmov x6, x9 ; xmov x7, x9 ; xmov x8, x9 -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p9i), XReg(p9i), XReg(p9i), XReg(p9i)] }, uses: [CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p9i), XReg(p9i), XReg(p9i), XReg(p9i)] }, uses: [CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } ; pop_frame ; ret ; ; Disassembled: ; push_frame ; xmov x9, x0 +; xmov x1, x9 +; xmov x2, x9 +; xmov x3, x9 ; xmov x4, x9 ; xmov x5, x9 ; xmov x6, x9 ; xmov x7, x9 ; xmov x8, x9 -; call4 x9, x9, x9, x9, 0x5 // target = 0x18 -; call4 x9, x9, x9, x9, 0x5 // target = 0x21 +; call 0x1 // target = 0x1d +; call 0x1 // target = 0x22 ; pop_frame ; ret @@ -76,12 +88,11 @@ block2(v1: i32): ; VCode: ; push_frame_save 144, {x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0} ; block0: -; xmov x8, x0 -; xmov x10, x0 -; xmov x11, x0 -; xmov x12, x0 ; xstore64 Slot(0), x0 // flags = notrap aligned -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p8i), XReg(p12i), XReg(p11i), XReg(p10i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I32) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I32) }], clobbers: PRegSet { bits: [4294967292, 4294967295, 4294967295, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: Some(TryCallInfo { continuation: MachLabel(1), exception_handlers: [Default(MachLabel(2))] }), patchable: true }; jump MachLabel(1); catch [default: MachLabel(2)] +; x1 = xload64 Slot(0) // flags = notrap aligned +; x2 = xload64 Slot(0) // flags = notrap aligned +; x3 = xload64 Slot(0) // flags = notrap aligned +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I32) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I32) }], clobbers: PRegSet { bits: [4294967292, 4294967295, 4294967295, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: Some(TryCallInfo { continuation: MachLabel(1), exception_handlers: [Default(MachLabel(2))] }), patchable: true }; jump MachLabel(1); catch [default: MachLabel(2)] ; block1: ; x0 = xload64 Slot(0) // flags = notrap aligned ; pop_frame_restore 144, {x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0} @@ -93,12 +104,11 @@ block2(v1: i32): ; ; Disassembled: ; push_frame_save 144, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0 -; xmov x8, x0 -; xmov x10, x0 -; xmov x11, x0 -; xmov x12, x0 ; xstore64le_o32 sp, 0, x0 -; call4 x8, x12, x11, x10, 0x5 // target = 0x1d +; xload64le_o32 x1, sp, 0 +; xload64le_o32 x2, sp, 0 +; xload64le_o32 x3, sp, 0 +; call 0x1 // target = 0x22 ; xload64le_o32 x0, sp, 0 ; pop_frame_restore 144, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0 ; ret diff --git a/cranelift/filetests/filetests/isa/pulley32/preserve-all.clif b/cranelift/filetests/filetests/isa/pulley32/preserve-all.clif index b5f75ff92999..26ad386ded42 100644 --- a/cranelift/filetests/filetests/isa/pulley32/preserve-all.clif +++ b/cranelift/filetests/filetests/isa/pulley32/preserve-all.clif @@ -380,7 +380,7 @@ block0(v0: i64): ; VCode: ; push_frame ; block0: -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p0i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: false } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: false } ; pop_frame ; ret ; @@ -390,3 +390,32 @@ block0(v0: i64): ; pop_frame ; ret +function %call_preserve_all_near(i64) system_v { + fn0 = colocated %f(i64, i64, i64, i64) preserve_all +block0(v0: i64): + call fn0(v0, v0, v0, v0) + call fn0(v0, v0, v0, v0) + return +} + +; VCode: +; push_frame +; block0: +; xmov x3, x0 +; xmov x1, x3 +; xmov x2, x3 +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: false } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: false } +; pop_frame +; ret +; +; Disassembled: +; push_frame +; xmov x3, x0 +; xmov x1, x3 +; xmov x2, x3 +; call 0x1 // target = 0xb +; call 0x1 // target = 0x10 +; pop_frame +; ret + diff --git a/cranelift/filetests/filetests/isa/pulley64/patchable-call.clif b/cranelift/filetests/filetests/isa/pulley64/patchable-call.clif index b110c3416551..4d211a110937 100644 --- a/cranelift/filetests/filetests/isa/pulley64/patchable-call.clif +++ b/cranelift/filetests/filetests/isa/pulley64/patchable-call.clif @@ -12,15 +12,21 @@ block0(v0: i64): ; VCode: ; push_frame ; block0: -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p0i), XReg(p0i), XReg(p0i), XReg(p0i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p0i), XReg(p0i), XReg(p0i), XReg(p0i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; xmov x3, x0 +; xmov x1, x3 +; xmov x2, x3 +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } ; pop_frame ; ret ; ; Disassembled: ; push_frame -; call4 x0, x0, x0, x0, 0x5 // target = 0x6 -; call4 x0, x0, x0, x0, 0x5 // target = 0xf +; xmov x3, x0 +; xmov x1, x3 +; xmov x2, x3 +; call 0x1 // target = 0xb +; call 0x1 // target = 0x10 ; pop_frame ; ret @@ -36,26 +42,32 @@ block0(v0: i64): ; push_frame ; block0: ; xmov x9, x0 +; xmov x1, x9 +; xmov x2, x9 +; xmov x3, x9 ; xmov x4, x9 ; xmov x5, x9 ; xmov x6, x9 ; xmov x7, x9 ; xmov x8, x9 -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p9i), XReg(p9i), XReg(p9i), XReg(p9i)] }, uses: [CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p9i), XReg(p9i), XReg(p9i), XReg(p9i)] }, uses: [CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }, CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: true } ; pop_frame ; ret ; ; Disassembled: ; push_frame ; xmov x9, x0 +; xmov x1, x9 +; xmov x2, x9 +; xmov x3, x9 ; xmov x4, x9 ; xmov x5, x9 ; xmov x6, x9 ; xmov x7, x9 ; xmov x8, x9 -; call4 x9, x9, x9, x9, 0x5 // target = 0x18 -; call4 x9, x9, x9, x9, 0x5 // target = 0x21 +; call 0x1 // target = 0x1d +; call 0x1 // target = 0x22 ; pop_frame ; ret @@ -75,12 +87,11 @@ block2(v1: i64): ; VCode: ; push_frame_save 144, {x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0} ; block0: -; xmov x7, x0 -; xmov x9, x0 -; xmov x10, x0 -; xmov x11, x0 ; xstore64 Slot(0), x0 // flags = notrap aligned -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p7i), XReg(p11i), XReg(p10i), XReg(p9i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I64) }], clobbers: PRegSet { bits: [4294967292, 4294967295, 4294967295, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: Some(TryCallInfo { continuation: MachLabel(1), exception_handlers: [Default(MachLabel(2))] }), patchable: true }; jump MachLabel(1); catch [default: MachLabel(2)] +; x1 = xload64 Slot(0) // flags = notrap aligned +; x2 = xload64 Slot(0) // flags = notrap aligned +; x3 = xload64 Slot(0) // flags = notrap aligned +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }, CallArgPair { vreg: p1i, preg: p1i }, CallArgPair { vreg: p2i, preg: p2i }, CallArgPair { vreg: p3i, preg: p3i }], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I64) }], clobbers: PRegSet { bits: [4294967292, 4294967295, 4294967295, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: Some(TryCallInfo { continuation: MachLabel(1), exception_handlers: [Default(MachLabel(2))] }), patchable: true }; jump MachLabel(1); catch [default: MachLabel(2)] ; block1: ; x0 = xload64 Slot(0) // flags = notrap aligned ; pop_frame_restore 144, {x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0} @@ -91,12 +102,11 @@ block2(v1: i64): ; ; Disassembled: ; push_frame_save 144, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0 -; xmov x7, x0 -; xmov x9, x0 -; xmov x10, x0 -; xmov x11, x0 ; xstore64le_o32 sp, 0, x0 -; call4 x7, x11, x10, x9, 0x5 // target = 0x1d +; xload64le_o32 x1, sp, 0 +; xload64le_o32 x2, sp, 0 +; xload64le_o32 x3, sp, 0 +; call 0x1 // target = 0x22 ; xload64le_o32 x0, sp, 0 ; pop_frame_restore 144, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, sp, spilltmp0 ; ret diff --git a/cranelift/filetests/filetests/isa/pulley64/preserve-all.clif b/cranelift/filetests/filetests/isa/pulley64/preserve-all.clif index ede637fc829d..e7cf31ce0306 100644 --- a/cranelift/filetests/filetests/isa/pulley64/preserve-all.clif +++ b/cranelift/filetests/filetests/isa/pulley64/preserve-all.clif @@ -380,7 +380,7 @@ block0(v0: i64): ; VCode: ; push_frame ; block0: -; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [XReg(p0i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: false } +; call CallInfo { dest: PulleyCall { name: TestCase(%f), args: [] }, uses: [CallArgPair { vreg: p0i, preg: p0i }], defs: [], clobbers: PRegSet { bits: [0, 0, 0, 0] }, callee_conv: PreserveAll, caller_conv: SystemV, callee_pop_size: 0, try_call_info: None, patchable: false } ; pop_frame ; ret ;