Repository: bytecodealliance/wasmtime
Pull request #8381 (2024-04-16 14:33:43)

Remove the `MmapVec::split_off` method
This method isn't actually correct if `split_off` is used on the returned values again as it's missing some extra indexing processing. That being said nothing in Wasmtime currently uses it, so remove it entirely instead of keeping it around.

found by @FrankReh, thanks!

alexcrichton: Notably @FrankReh recommended replacing with this:

```rust


pub fn split_off(&mut self, at: usize) -> MmapVec {
    assert!(at <= self.range.len());

    // Adjust the start of the range for the new part
    let new_start = self.range.start + at;

    // Create a new `MmapVec` which refers to the same underlying mmap, but
    // has a disjoint range from ours. Our own range is adjusted to be
    // disjoint just after `ret` is created.
    let ret = MmapVec {
        mmap: self.mmap.clone(),
        range: new_start..self.range.end,
    };
    self.range.end = new_start;
    return ret;
}
```

which I believe is correct, but also given that we don't need this it seems best to remove for now.

Patch:
diff --git a/.github/subscribe-to-label.json b/.github/subscribe-to-label.json
index a39d31632..6714782ca 100644
--- a/.github/subscribe-to-label.json
+++ b/.github/subscribe-to-label.json
@@ -1,6 +1,5 @@
 {
   "cfallin": ["isle"],
   "fitzgen": ["fuzzing", "isle", "wasmtime:ref-types"],
-  "peterhuene": ["wasmtime:api", "wasmtime:c-api"],
   "saulecabrera": ["winch"]
 }
diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs
index 98f746a4a..5327ee049 100644
--- a/cranelift/codegen/src/isa/aarch64/abi.rs
+++ b/cranelift/codegen/src/isa/aarch64/abi.rs
@@ -35,8 +35,9 @@ static STACK_ARG_RET_SIZE_LIMIT: u32 = 128 * 1024 * 1024;
 impl Into<AMode> for StackAMode {
     fn into(self) -> AMode {
         match self {
-            // Argument area begins after saved frame pointer + return address.
-            StackAMode::IncomingArg(off, _) => AMode::FPOffset { off: off + 16 },
+            StackAMode::IncomingArg(off, stack_args_size) => AMode::IncomingArg {
+                off: i64::from(stack_args_size) - off,
+            },
             StackAMode::Slot(off) => AMode::NominalSPOffset { off },
             StackAMode::OutgoingArg(off) => AMode::SPOffset { off },
         }
@@ -630,9 +631,9 @@ impl ABIMachineSpec for AArch64MachineDeps {
             });
         }
 
-        if call_conv == isa::CallConv::Tail && frame_layout.incoming_args_size > 0 {
+        if call_conv == isa::CallConv::Tail && frame_layout.tail_args_size > 0 {
             insts.extend(Self::gen_sp_reg_adjust(
-                frame_layout.incoming_args_size.try_into().unwrap(),
+                frame_layout.tail_args_size.try_into().unwrap(),
             ));
         }
 
@@ -701,8 +702,47 @@ impl ABIMachineSpec for AArch64MachineDeps {
         }
 
         let mut insts = SmallVec::new();
+        let setup_frame = frame_layout.setup_area_size > 0;
+
+        // When a return_call within this function required more stack arguments than we have
+        // present, resize the incoming argument area of the frame to accommodate those arguments.
+        let incoming_args_diff = frame_layout.tail_args_size - frame_layout.incoming_args_size;
+        if incoming_args_diff > 0 {
+            // Decrement SP to account for the additional space required by a tail call
+            insts.extend(Self::gen_sp_reg_adjust(-(incoming_args_diff as i32)));
+
+            // Move fp and lr down
+            if setup_frame {
+                // Reload the frame pointer from the stack
+                insts.push(Inst::ULoad64 {
+                    rd: regs::writable_fp_reg(),
+                    mem: AMode::SPOffset {
+                        off: i64::from(incoming_args_diff),
+                    },
+                    flags: MemFlags::trusted(),
+                });
+
+                // Store the frame pointer and link register again at the new SP
+                insts.push(Inst::StoreP64 {
+                    rt: fp_reg(),
+                    rt2: link_reg(),
+                    mem: PairAMode::SignedOffset {
+                        reg: regs::stack_reg(),
+                        simm7: SImm7Scaled::maybe_from_i64(0, types::I64).unwrap(),
+                    },
+                    flags: MemFlags::trusted(),
+                });
+
+                // Keep the frame pointer in sync
+                insts.push(Self::gen_move(
+                    regs::writable_fp_reg(),
+                    regs::stack_reg(),
+                    types::I64,
+                ));
+            }
+        }
 
-        if flags.unwind_info() && frame_layout.setup_area_size > 0 {
+        if flags.unwind_info() && setup_frame {
             // The *unwind* frame (but not the actual frame) starts at the
             // clobbers, just below the saved FP/LR pair.
             insts.push(Inst::Unwind {
@@ -1261,8 +1301,15 @@ impl AArch64CallSite {
         args: isle::ValueSlice,
         isa_flags: &aarch64_settings::Flags,
     ) {
-        let (new_stack_arg_size, old_stack_arg_size) =
-            self.emit_temporary_tail_call_frame(ctx, args);
+        let new_stack_arg_size =
+            u32::try_from(self.sig(ctx.sigs()).sized_stack_arg_space()).unwrap();
+
+        ctx.abi_mut().accumulate_tail_args_size(new_stack_arg_size);
+
+        // Put all arguments in registers and stack slots (within that newly
+        // allocated stack space).
+        self.emit_args(ctx, args);
+        self.emit_stack_ret_arg_for_tail_call(ctx);
 
         let dest = self.dest().clone();
         let opcode = self.opcode();
@@ -1270,7 +1317,6 @@ impl AArch64CallSite {
         let info = Box::new(ReturnCallInfo {
             uses,
             opcode,
-            old_stack_arg_size,
             new_stack_arg_size,
             key: select_api_key(isa_flags, isa::CallConv::Tail, true),
         });
diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle
index f706f8048..f45814ecc 100644
--- a/cranelift/codegen/src/isa/aarch64/inst.isle
+++ b/cranelift/codegen/src/isa/aarch64/inst.isle
@@ -1170,6 +1170,14 @@
         (Const
           (addr VCodeConstant))
 
+        ;; Offset from the beginning of the argument area to the argument
+        ;; referenced. This can only be determined when the function has been
+        ;; processed fully, as the size of the argument area after the prologue
+        ;; is only known once all return_call instructions in the function body
+        ;; have been processed.
+        (IncomingArg
+          (off i64))
+
         ;; Offset from the "nominal stack pointer", which is where the real SP is
         ;; just after stack and spill slots are allocated in the function prologue.
         ;; At emission time, this is converted to `SPOffset` with a fixup added to
diff --git a/cranelift/codegen/src/isa/aarch64/inst/args.rs b/cranelift/codegen/src/isa/aarch64/inst/args.rs
index 3375215d2..d91ada314 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/args.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/args.rs
@@ -183,6 +183,7 @@ impl AMode {
             | &AMode::SPPostIndexed { .. }
             | &AMode::FPOffset { .. }
             | &AMode::SPOffset { .. }
+            | &AMode::IncomingArg { .. }
             | &AMode::NominalSPOffset { .. }
             | &AMode::Const { .. }
             | AMode::Label { .. } => self.clone(),
@@ -455,6 +456,7 @@ impl PrettyPrint for AMode {
             // Eliminated by `mem_finalize()`.
             &AMode::SPOffset { .. }
             | &AMode::FPOffset { .. }
+            | &AMode::IncomingArg { .. }
             | &AMode::NominalSPOffset { .. }
             | &AMode::RegOffset { .. } => {
                 panic!("Unexpected pseudo mem-arg mode: {:?}", self)
diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs
index df840e5b1..73d11a5db 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs
@@ -22,14 +22,27 @@ pub fn mem_finalize(
         &AMode::RegOffset { off, .. }
         | &AMode::SPOffset { off }
         | &AMode::FPOffset { off }
+        | &AMode::IncomingArg { off }
         | &AMode::NominalSPOffset { off } => {
             let basereg = match mem {
                 &AMode::RegOffset { rn, .. } => rn,
-                &AMode::SPOffset { .. } | &AMode::NominalSPOffset { .. } => stack_reg(),
+                &AMode::SPOffset { .. }
+                | &AMode::NominalSPOffset { .. }
+                | &AMode::IncomingArg { .. } => stack_reg(),
                 &AMode::FPOffset { .. } => fp_reg(),
                 _ => unreachable!(),
             };
-            let adj = match mem {
+            let off = match mem {
+                &AMode::IncomingArg { .. } => {
+                    let frame_layout = state.frame_layout();
+                    i64::from(
+                        frame_layout.setup_area_size
+                            + frame_layout.tail_args_size
+                            + frame_layout.clobber_size
+                            + frame_layout.fixed_frame_storage_size
+                            + frame_layout.outgoing_args_size,
+                    ) - off
+                }
                 &AMode::NominalSPOffset { .. } => {
                     trace!(
                         "mem_finalize: nominal SP offset {} + adj {} -> {}",
@@ -37,11 +50,10 @@ pub fn mem_finalize(
                         state.virtual_sp_offset,
                         off + state.virtual_sp_offset
                     );
-                    state.virtual_sp_offset
+                    off + state.virtual_sp_offset
                 }
-                _ => 0,
+                _ => off,
             };
-            let off = off + adj;
 
             if let Some(simm9) = SImm9::maybe_from_i64(off) {
                 let mem = AMode::Unscaled { rn: basereg, simm9 };
@@ -659,6 +671,7 @@ pub struct EmitState {
     /// Only used during fuzz-testing. Otherwise, it is a zero-sized struct and
     /// optimized away at compiletime. See [cranelift_control].
     ctrl_plane: ControlPlane,
+    frame_layout: FrameLayout,
 }
 
 impl MachInstEmitState<Inst> for EmitState {
@@ -668,6 +681,7 @@ impl MachInstEmitState<Inst> for EmitState {
             nominal_sp_to_fp: abi.frame_size() as i64,
             stack_map: None,
             ctrl_plane,
+            frame_layout: abi.frame_layout().clone(),
         }
     }
 
@@ -692,6 +706,10 @@ impl EmitState {
     fn clear_post_insn(&mut self) {
         self.stack_map = None;
     }
+
+    fn frame_layout(&self) -> &FrameLayout {
+        &self.frame_layout
+    }
 }
 
 /// Constant state used during function compilation.
@@ -1103,6 +1121,7 @@ impl MachInstEmit for Inst {
                     // Eliminated by `mem_finalize()` above.
                     &AMode::SPOffset { .. }
                     | &AMode::FPOffset { .. }
+                    | &AMode::IncomingArg { .. }
                     | &AMode::NominalSPOffset { .. }
                     | &AMode::Const { .. }
                     | &AMode::RegOffset { .. } => {
@@ -1197,6 +1216,7 @@ impl MachInstEmit for Inst {
                     // Eliminated by `mem_finalize()` above.
                     &AMode::SPOffset { .. }
                     | &AMode::FPOffset { .. }
+                    | &AMode::IncomingArg { .. }
                     | &AMode::NominalSPOffset { .. }
                     | &AMode::Const { .. }
                     | &AMode::RegOffset { .. } => {
@@ -3778,145 +3798,42 @@ fn emit_return_call_common_sequence(
         let _ = allocs.next(u.vreg);
     }
 
-    // We are emitting a dynamic number of instructions and might need an
-    // island. We emit four instructions regardless of how many stack arguments
-    // we have, and then two instructions per word of stack argument space.
-    let new_stack_words = info.new_stack_arg_size / 8;
-    let insts = 4 + 2 * new_stack_words;
-    let size_of_inst = 4;
-    let space_needed = insts * size_of_inst;
-    if sink.island_needed(space_needed) {
-        let jump_around_label = sink.get_label();
-        let jmp = Inst::Jump {
-            dest: BranchTarget::Label(jump_around_label),
-        };
-        jmp.emit(&[], sink, emit_info, state);
-        sink.emit_island(space_needed + 4, &mut state.ctrl_plane);
-        sink.bind_label(jump_around_label, &mut state.ctrl_plane);
-    }
-
-    // Copy the new frame on top of our current frame.
-    //
-    // The current stack layout is the following:
-    //
-    //            | ...                 |
-    //            +---------------------+
-    //            | ...                 |
-    //            | stack arguments     |
-    //            | ...                 |
-    //    current | return address      |
-    //    frame   | old FP              | <-- FP
-    //            | ...                 |
-    //            | old stack slots     |
-    //            | ...                 |
-    //            +---------------------+
-    //            | ...                 |
-    //    new     | new stack arguments |
-    //    frame   | ...                 | <-- SP
-    //            +---------------------+
-    //
-    // We need to restore the old FP, restore the return address from the stack
-    // to the link register, copy the new stack arguments over the old stack
-    // arguments, adjust SP to point to the new stack arguments, and then jump
-    // to the callee (which will push the old FP and RA again). Note that the
-    // actual jump happens outside this helper function.
-
-    assert_eq!(
-        info.new_stack_arg_size % 8,
-        0,
-        "size of new stack arguments must be 8-byte aligned"
-    );
-
-    // The delta from our frame pointer to the (eventual) stack pointer value
-    // when we jump to the tail callee. This is the difference in size of stack
-    // arguments as well as accounting for the two words we pushed onto the
-    // stack upon entry to this function (the return address and old frame
-    // pointer).
-    let fp_to_callee_sp =
-        i64::from(info.old_stack_arg_size) - i64::from(info.new_stack_arg_size) + 16;
-
-    let tmp1 = regs::writable_spilltmp_reg();
-    let tmp2 = regs::writable_tmp2_reg();
-
-    // Restore the return address to the link register, and load the old FP into
-    // a temporary register.
-    //
-    // We can't put the old FP into the FP register until after we copy the
-    // stack arguments into place, since that uses address modes that are
-    // relative to our current FP.
-    //
-    // Note that the FP is saved in the function prologue for all non-leaf
-    // functions, even when `preserve_frame_pointers=false`. Note also that
-    // `return_call` instructions make it so that a function is considered
-    // non-leaf. Therefore we always have an FP to restore here.
-    Inst::LoadP64 {
-        rt: tmp1,
-        rt2: writable_link_reg(),
-        mem: PairAMode::SignedOffset {
-            reg: regs::fp_reg(),
-            simm7: SImm7Scaled::maybe_from_i64(0, types::I64).unwrap(),
-        },
-        flags: MemFlags::trusted(),
+    for inst in
+        AArch64MachineDeps::gen_clobber_restore(CallConv::Tail, &emit_info.0, state.frame_layout())
+    {
+        inst.emit(&[], sink, emit_info, state);
     }
-    .emit(&[], sink, emit_info, state);
-
-    // Copy the new stack arguments over the old stack arguments.
-    for i in (0..new_stack_words).rev() {
-        // Load the `i`th new stack argument word from the temporary stack
-        // space.
-        Inst::ULoad64 {
-            rd: tmp2,
-            mem: AMode::SPOffset {
-                off: i64::from(i * 8),
-            },
-            flags: ir::MemFlags::trusted(),
-        }
-        .emit(&[], sink, emit_info, state);
 
-        // Store it to its final destination on the stack, overwriting our
-        // current frame.
-        Inst::Store64 {
-            rd: tmp2.to_reg(),
-            mem: AMode::FPOffset {
-                off: fp_to_callee_sp + i64::from(i * 8),
+    let setup_area_size = state.frame_layout().setup_area_size;
+    if setup_area_size > 0 {
+        // N.B.: sp is already adjusted to the appropriate place by the
+        // clobber-restore code (which also frees the fixed frame). Hence, there
+        // is no need for the usual `mov sp, fp` here.
+
+        // `ldp fp, lr, [sp], #16`
+        Inst::LoadP64 {
+            rt: writable_fp_reg(),
+            rt2: writable_link_reg(),
+            mem: PairAMode::SPPostIndexed {
+                // TODO: we could fold the increment for incoming_args_diff here, as long as that
+                // value is less than 502*8, by adding it to `setup_area_size`.
+                // https://developer.arm.com/documentation/ddi0596/2020-12/Base-Instructions/LDP--Load-Pair-of-Registers-
+                simm7: SImm7Scaled::maybe_from_i64(i64::from(setup_area_size), types::I64).unwrap(),
             },
-            flags: ir::MemFlags::trusted(),
+            flags: MemFlags::trusted(),
         }
         .emit(&[], sink, emit_info, state);
     }
 
-    // Initialize the SP for the tail callee, deallocating the temporary stack
-    // argument space and our current frame at the same time.
-    let (off, alu_op) = if let Ok(off) = u64::try_from(fp_to_callee_sp) {
-        (off, ALUOp::Add)
-    } else {
-        let abs = fp_to_callee_sp.abs();
-        let off = u64::try_from(abs).unwrap();
-        (off, ALUOp::Sub)
-    };
-    Inst::AluRRImm12 {
-        alu_op,
-        size: OperandSize::Size64,
-        rd: regs::writable_stack_reg(),
-        rn: regs::fp_reg(),
-        imm12: Imm12::maybe_from_u64(off).unwrap(),
-    }
-    .emit(&[], sink, emit_info, state);
-
-    // Move the old FP value from the temporary into the FP register.
-    Inst::Mov {
-        size: OperandSize::Size64,
-        rd: regs::writable_fp_reg(),
-        rm: tmp1.to_reg(),
+    // Adjust SP to account for the possible over-allocation in the prologue.
+    let incoming_args_diff = state.frame_layout().tail_args_size - info.new_stack_arg_size;
+    if incoming_args_diff > 0 {
+        for inst in
+            AArch64MachineDeps::gen_sp_reg_adjust(i32::try_from(incoming_args_diff).unwrap())
+        {
+            inst.emit(&[], sink, emit_info, state);
+        }
     }
-    .emit(&[], sink, emit_info, state);
-
-    state.virtual_sp_offset -= i64::from(info.new_stack_arg_size);
-    trace!(
-        "return_call[_ind] adjusts virtual sp offset by {} -> {}",
-        info.new_stack_arg_size,
-        state.virtual_sp_offset
-    );
 
     if let Some(key) = info.key {
         sink.put4(key.enc_auti_hint());
diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs
index e1447d60a..9cc2a5740 100644
--- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs
+++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs
@@ -130,8 +130,6 @@ pub struct ReturnCallInfo {
     pub uses: CallArgList,
     /// Instruction opcode.
     pub opcode: Opcode,
-    /// The size of the current/old stack frame's stack arguments.
-    pub old_stack_arg_size: u32,
     /// The size of the new stack frame's stack arguments. This is necessary
     /// for copying the frame over our current frame. It must already be
     /// allocated on the stack.
@@ -413,7 +411,7 @@ fn memarg_operands<F: Fn(VReg) -> VReg>(memarg: &AMode, collector: &mut OperandC
         }
         &AMode::Label { .. } => {}
         &AMode::SPPreIndexed { .. } | &AMode::SPPostIndexed { .. } => {}
-        &AMode::FPOffset { .. } => {}
+        &AMode::FPOffset { .. } | &AMode::IncomingArg { .. } => {}
         &AMode::SPOffset { .. } | &AMode::NominalSPOffset { .. } => {}
         &AMode::RegOffset { rn, .. } => {
             collector.reg_use(rn);
@@ -2615,8 +2613,8 @@ impl Inst {
                 ref info,
             } => {
                 let mut s = format!(
-                    "return_call {callee:?} old_stack_arg_size:{} new_stack_arg_size:{}",
-                    info.old_stack_arg_size, info.new_stack_arg_size
+                    "return_call {callee:?} new_stack_arg_size:{}",
+                    info.new_stack_arg_size
                 );
                 for ret in &info.uses {
                     let preg = pretty_print_reg(ret.preg, &mut empty_allocs);
@@ -2628,8 +2626,8 @@ impl Inst {
             &Inst::ReturnCallInd { callee, ref info } => {
                 let callee = pretty_print_reg(callee, allocs);
                 let mut s = format!(
-                    "return_call_ind {callee} old_stack_arg_size:{} new_stack_arg_size:{}",
-                    info.old_stack_arg_size, info.new_stack_arg_size
+                    "return_call_ind {callee} new_stack_arg_size:{}",
+                    info.new_stack_arg_size
                 );
                 for ret in &info.uses {
                     let preg = pretty_print_reg(ret.preg, &mut empty_allocs);
diff --git a/cranelift/codegen/src/isa/aarch64/lower/isle.rs b/cranelift/codegen/src/isa/aarch64/lower/isle.rs
index 0f50361a7..36eda61e6 100644
--- a/cranelift/codegen/src/isa/aarch64/lower/isle.rs
+++ b/cranelift/codegen/src/isa/aarch64/lower/isle.rs
@@ -100,9 +100,7 @@ impl Context for IsleContext<'_, '_, MInst, AArch64Backend> {
             self.lower_ctx.sigs(),
             callee_sig,
             &callee,
-            // TODO: this should be Opcode::ReturnCall, once aarch64 has been ported to the new
-            // tail call strategy.
-            Opcode::Call,
+            Opcode::ReturnCall,
             distance,
             caller_conv,
             self.backend.flags().clone(),
@@ -131,9 +129,7 @@ impl Context for IsleContext<'_, '_, MInst, AArch64Backend> {
             self.lower_ctx.sigs(),
             callee_sig,
             callee,
-            // TODO: this should be Opcode::ReturnCallIndirect, once aarch64 has
-            // been ported to the new tail call strategy.
-            Opcode::CallIndirect,
+            Opcode::ReturnCallIndirect,
             caller_conv,
             self.backend.flags().clone(),
         );
diff --git a/cranelift/codegen/src/isa/aarch64/pcc.rs b/cranelift/codegen/src/isa/aarch64/pcc.rs
index cdc6ca42e..e8e38232b 100644
--- a/cranelift/codegen/src/isa/aarch64/pcc.rs
+++ b/cranelift/codegen/src/isa/aarch64/pcc.rs
@@ -505,6 +505,7 @@ fn check_addr<'a>(
         }
         &AMode::SPOffset { .. }
         | &AMode::FPOffset { .. }
+        | &AMode::IncomingArg { .. }
         | &AMode::NominalSPOffset { .. }
         | &AMode::SPPostIndexed { .. }
         | &AMode::SPPreIndexed { .. } => {
diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs
index b28e606c5..0e58660bb 100644
--- a/cranelift/codegen/src/machinst/abi.rs
+++ b/cranelift/codegen/src/machinst/abi.rs
@@ -2293,11 +2293,6 @@ impl<M: ABIMachineSpec> CallSite<M> {
                 }),
                 ArgLoc::Stack { offset, ty } => {
                     let amode = if self.is_tail_call() {
-                        assert!(
-                            self.flags.preserve_frame_pointers(),
-                            "tail calls require frame pointers to be enabled"
-                        );
-
                         StackAMode::IncomingArg(offset, ctx.sigs()[self.sig].sized_stack_arg_space)
                     } else {
                         StackAMode::OutgoingArg(offset)
diff --git a/crates/runtime/src/mmap_vec.rs b/crates/runtime/src/mmap_vec.rs
index 8710a23a3..1b089fc03 100644
--- a/crates/runtime/src/mmap_vec.rs
+++ b/crates/runtime/src/mmap_vec.rs
@@ -68,28 +68,6 @@ impl MmapVec {
         Ok(MmapVec::new(mmap, len))
     }
 
-    /// Splits the collection into two at the given index.
-    ///
-    /// Returns a separate `MmapVec` which shares the underlying mapping, but
-    /// only has access to elements in the range `[at, len)`. After the call,
-    /// the original `MmapVec` will be left with access to the elements in the
-    /// range `[0, at)`.
-    ///
-    /// This is an `O(1)` operation which does not involve copies.
-    pub fn split_off(&mut self, at: usize) -> MmapVec {
-        assert!(at <= self.range.len());
-
-        // Create a new `MmapVec` which refers to the same underlying mmap, but
-        // has a disjoint range from ours. Our own range is adjusted to be
-        // disjoint just after `ret` is created.
-        let ret = MmapVec {
-            mmap: self.mmap.clone(),
-            range: at..self.range.end,
-        };
-        self.range.end = self.range.start + at;
-        return ret;
-    }
-
     /// Makes the specified `range` within this `mmap` to be read/execute.
     pub unsafe fn make_executable(
         &self,
@@ -176,26 +154,4 @@ mod tests {
         assert_eq!(mmap[0], 1);
         assert_eq!(mmap[2], 3);
     }
-
-    #[test]
-    fn split_off() {
-        let mut vec = Vec::from([1, 2, 3, 4]);
-        let mut mmap = MmapVec::from_slice(&vec).unwrap();
-        assert_eq!(&mmap[..], &vec[..]);
-        // remove nothing; vec length remains 4
-        assert_eq!(&mmap.split_off(4)[..], &vec.split_off(4)[..]);
-        assert_eq!(&mmap[..], &vec[..]);
-        // remove 1 element; vec length is now 3
-        assert_eq!(&mmap.split_off(3)[..], &vec.split_off(3)[..]);
-        assert_eq!(&mmap[..], &vec[..]);
-        // remove 2 elements; vec length is now 1
-        assert_eq!(&mmap.split_off(1)[..], &vec.split_off(1)[..]);
-        assert_eq!(&mmap[..], &vec[..]);
-        // remove last element; vec length is now 0
-        assert_eq!(&mmap.split_off(0)[..], &vec.split_off(0)[..]);
-        assert_eq!(&mmap[..], &vec[..]);
-        // nothing left to remove, but that's okay
-        assert_eq!(&mmap.split_off(0)[..], &vec.split_off(0)[..]);
-        assert_eq!(&mmap[..], &vec[..]);
-    }
 }


Test patch:
diff --git a/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif b/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif
index 06e6ecc54..4393309de 100644
--- a/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/call-pauth-bkey.clif
@@ -100,7 +100,7 @@ block0(v0: i64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%g)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -112,9 +112,7 @@ block0(v0: i64):
 ;   b #0x1c
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   autibz
 ;   br x3
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif b/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif
index 74dbb2cfd..705b6fc66 100644
--- a/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/call-pauth.clif
@@ -101,7 +101,7 @@ block0(v0: i64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%g)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -113,9 +113,7 @@ block0(v0: i64):
 ;   b #0x1c
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %g 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   autiaz
 ;   br x3
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/call.clif b/cranelift/filetests/filetests/isa/aarch64/call.clif
index def87fb8b..d350af732 100644
--- a/cranelift/filetests/filetests/isa/aarch64/call.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/call.clif
@@ -670,8 +670,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128):
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x0, [fp, #16]
-;   ldr x1, [fp, #24]
+;   ldr x0, [sp, #16]
+;   ldr x1, [sp, #24]
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -680,8 +680,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128):
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x0, [x29, #0x10]
-;   ldur x1, [x29, #0x18]
+;   ldur x0, [sp, #0x10]
+;   ldur x1, [sp, #0x18]
 ;   ldp x29, x30, [sp], #0x10
 ;   ret
 
@@ -747,8 +747,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128):
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x0, [fp, #16]
-;   ldr x1, [fp, #24]
+;   ldr x0, [sp, #16]
+;   ldr x1, [sp, #24]
 ;   ldp fp, lr, [sp], #16
 ;   ret
 ;
@@ -757,8 +757,8 @@ block0(v0: i128, v1: i128, v2: i128, v3: i64, v4: i128):
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x0, [x29, #0x10]
-;   ldur x1, [x29, #0x18]
+;   ldur x0, [sp, #0x10]
+;   ldur x1, [sp, #0x18]
 ;   ldp x29, x30, [sp], #0x10
 ;   ret
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif b/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif
index d02b2b868..1e587efb4 100644
--- a/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/return-call-indirect.clif
@@ -34,7 +34,7 @@ block0(v0: i64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%callee_i64)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -45,9 +45,7 @@ block0(v0: i64):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_i64 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x3
 
 ;;;; Test colocated tail calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -66,7 +64,7 @@ block0(v0: i64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%callee_i64)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -77,9 +75,7 @@ block0(v0: i64):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_i64 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x3
 
 ;;;; Test passing `f64`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -117,7 +113,7 @@ block0(v0: f64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x2, TestCase(%callee_f64)+0
-;   return_call_ind x2 old_stack_arg_size:0 new_stack_arg_size:0 v0=v0
+;   return_call_ind x2 new_stack_arg_size:0 v0=v0
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -128,9 +124,7 @@ block0(v0: f64):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_f64 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x2
 
 ;;;; Test passing `i8`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -170,7 +164,7 @@ block0(v0: i8):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%callee_i8)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -181,9 +175,7 @@ block0(v0: i8):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_i8 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x3
 
 ;;;; Test passing many arguments on stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -226,6 +218,10 @@ block0:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ;   sub sp, sp, #16
+;   ldr fp, [sp, #16]
+;   stp fp, lr, [sp]
+;   mov fp, sp
+;   sub sp, sp, #16
 ; block0:
 ;   movz x2, #10
 ;   movz x3, #15
@@ -255,20 +251,22 @@ block0:
 ;   movz x0, #130
 ;   movz x1, #135
 ;   load_ext_name x10, TestCase(%tail_callee_stack_args)+0
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
-;   str x0, [sp]
-;   str x1, [sp, #8]
+;   str x0, [sp, #32]
+;   str x1, [sp, #40]
 ;   mov x0, x10
-;   ldr x10, [sp, #16]
-;   return_call_ind x0 old_stack_arg_size:0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   ldr x10, [sp]
+;   return_call_ind x0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ;   sub sp, sp, #0x10
-; block1: ; offset 0xc
+;   ldur x29, [sp, #0x10]
+;   stp x29, x30, [sp]
+;   mov x29, sp
+;   sub sp, sp, #0x10
+; block1: ; offset 0x1c
 ;   mov x2, #0xa
 ;   mov x3, #0xf
 ;   mov x4, #0x14
@@ -296,21 +294,15 @@ block0:
 ;   mov x28, #0x7d
 ;   mov x0, #0x82
 ;   mov x1, #0x87
-;   ldr x10, #0x80
-;   b #0x88
+;   ldr x10, #0x90
+;   b #0x98
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_args 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   sub sp, sp, #0x10
-;   stur x0, [sp]
-;   stur x1, [sp, #8]
+;   stur x0, [sp, #0x20]
+;   stur x1, [sp, #0x28]
 ;   mov x0, x10
-;   ldur x10, [sp, #0x10]
-;   ldp x16, x30, [x29]
-;   ldur x17, [sp, #8]
-;   stur x17, [x29, #8]
-;   ldur x17, [sp]
-;   stur x17, [x29]
-;   mov sp, x29
-;   mov x29, x16
+;   ldur x10, [sp]
+;   add sp, sp, #0x10
+;   ldp x29, x30, [sp], #0x10
 ;   br x0
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/return-call.clif b/cranelift/filetests/filetests/isa/aarch64/return-call.clif
index ebcc8a1e3..cd00960f1 100644
--- a/cranelift/filetests/filetests/isa/aarch64/return-call.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/return-call.clif
@@ -32,7 +32,7 @@ block0(v0: i64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%callee_i64)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -43,9 +43,7 @@ block0(v0: i64):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_i64 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x3
 
 ;;;; Test colocated tail calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -61,17 +59,15 @@ block0(v0: i64):
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   return_call TestCase(%callee_i64) old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call TestCase(%callee_i64) new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
-;   b #0x14 ; reloc_external Call %callee_i64 0
+;   ldp x29, x30, [sp], #0x10
+;   b #0xc ; reloc_external Call %callee_i64 0
 
 ;;;; Test passing `f64`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -106,7 +102,7 @@ block0(v0: f64):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x2, TestCase(%callee_f64)+0
-;   return_call_ind x2 old_stack_arg_size:0 new_stack_arg_size:0 v0=v0
+;   return_call_ind x2 new_stack_arg_size:0 v0=v0
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -117,9 +113,7 @@ block0(v0: f64):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_f64 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x2
 
 ;;;; Test passing `i8`s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -157,7 +151,7 @@ block0(v0: i8):
 ;   mov fp, sp
 ; block0:
 ;   load_ext_name x3, TestCase(%callee_i8)+0
-;   return_call_ind x3 old_stack_arg_size:0 new_stack_arg_size:0 x2=x2
+;   return_call_ind x3 new_stack_arg_size:0 x2=x2
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
@@ -168,9 +162,7 @@ block0(v0: i8):
 ;   b #0x18
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %callee_i8 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   add sp, x29, #0x10
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x3
 
 ;;;; Test passing many arguments on stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -184,8 +176,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [fp, #16]
-;   ldr x2, [fp, #24]
+;   ldr x9, [sp, #16]
+;   ldr x2, [sp, #24]
 ;   ldp fp, lr, [sp], #16
 ;   add sp, sp, #16
 ;   ret
@@ -195,8 +187,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [x29, #0x10]
-;   ldur x2, [x29, #0x18]
+;   ldur x9, [sp, #0x10]
+;   ldur x2, [sp, #0x18]
 ;   ldp x29, x30, [sp], #0x10
 ;   add sp, sp, #0x10
 ;   ret
@@ -237,6 +229,10 @@ block0:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
+;   sub sp, sp, #16
+;   ldr fp, [sp, #16]
+;   stp fp, lr, [sp]
+;   mov fp, sp
 ; block0:
 ;   movz x2, #10
 ;   movz x3, #15
@@ -264,18 +260,20 @@ block0:
 ;   movz x28, #125
 ;   movz x0, #130
 ;   movz x1, #135
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
-;   str x0, [sp]
-;   str x1, [sp, #8]
+;   str x0, [sp, #16]
+;   str x1, [sp, #24]
 ;   load_ext_name x0, TestCase(%tail_callee_stack_args)+0
-;   return_call_ind x0 old_stack_arg_size:0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   return_call_ind x0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
-; block1: ; offset 0x8
+;   sub sp, sp, #0x10
+;   ldur x29, [sp, #0x10]
+;   stp x29, x30, [sp]
+;   mov x29, sp
+; block1: ; offset 0x18
 ;   mov x2, #0xa
 ;   mov x3, #0xf
 ;   mov x4, #0x14
@@ -302,20 +300,13 @@ block0:
 ;   mov x28, #0x7d
 ;   mov x0, #0x82
 ;   mov x1, #0x87
-;   sub sp, sp, #0x10
-;   stur x0, [sp]
-;   stur x1, [sp, #8]
-;   ldr x0, #0x84
-;   b #0x8c
+;   stur x0, [sp, #0x10]
+;   stur x1, [sp, #0x18]
+;   ldr x0, #0x90
+;   b #0x98
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %tail_callee_stack_args 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   ldur x17, [sp, #8]
-;   stur x17, [x29, #8]
-;   ldur x17, [sp]
-;   stur x17, [x29]
-;   mov sp, x29
-;   mov x29, x16
+;   ldp x29, x30, [sp], #0x10
 ;   br x0
 
 ;;;; Test diff blocks with diff return calls with diff # of stack args ;;;;;;;;;
@@ -329,8 +320,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [fp, #16]
-;   ldr x2, [fp, #24]
+;   ldr x9, [sp, #16]
+;   ldr x2, [sp, #24]
 ;   ldp fp, lr, [sp], #16
 ;   add sp, sp, #16
 ;   ret
@@ -340,8 +331,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [x29, #0x10]
-;   ldur x2, [x29, #0x18]
+;   ldur x9, [sp, #0x10]
+;   ldur x2, [sp, #0x18]
 ;   ldp x29, x30, [sp], #0x10
 ;   add sp, sp, #0x10
 ;   ret
@@ -355,9 +346,9 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [fp, #16]
-;   ldr x11, [fp, #24]
-;   ldr x2, [fp, #32]
+;   ldr x9, [sp, #16]
+;   ldr x11, [sp, #24]
+;   ldr x2, [sp, #32]
 ;   ldp fp, lr, [sp], #16
 ;   add sp, sp, #32
 ;   ret
@@ -367,9 +358,9 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [x29, #0x10]
-;   ldur x11, [x29, #0x18]
-;   ldur x2, [x29, #0x20]
+;   ldur x9, [sp, #0x10]
+;   ldur x11, [sp, #0x18]
+;   ldur x2, [sp, #0x20]
 ;   ldp x29, x30, [sp], #0x10
 ;   add sp, sp, #0x20
 ;   ret
@@ -418,10 +409,15 @@ block2:
 ; VCode:
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
+;   sub sp, sp, #32
+;   ldr fp, [sp, #32]
+;   stp fp, lr, [sp]
+;   mov fp, sp
 ;   sub sp, sp, #16
 ; block0:
-;   movz x14, #10
-;   str x14, [sp]
+;   str x2, [sp]
+;   movz x2, #10
+;   str x2, [sp, #8]
 ;   movz x3, #15
 ;   movz x4, #20
 ;   movz x5, #25
@@ -447,34 +443,36 @@ block2:
 ;   movz x28, #125
 ;   movz x1, #130
 ;   movz x0, #135
+;   ldr x2, [sp]
 ;   cbnz x2, label2 ; b label1
 ; block1:
 ;   movz x2, #140
-;   sub sp, sp, #32
-;   virtual_sp_offset_adjust 32
-;   str x1, [sp]
-;   str x0, [sp, #8]
-;   str x2, [sp, #16]
+;   str x1, [sp, #32]
+;   str x0, [sp, #40]
+;   str x2, [sp, #48]
 ;   load_ext_name x0, TestCase(%different_callee2)+0
-;   ldr x2, [sp, #32]
-;   return_call_ind x0 old_stack_arg_size:0 new_stack_arg_size:32 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   ldr x2, [sp, #8]
+;   return_call_ind x0 new_stack_arg_size:32 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
 ; block2:
-;   ldr x2, [sp]
-;   sub sp, sp, #16
-;   virtual_sp_offset_adjust 16
-;   str x1, [sp]
-;   str x0, [sp, #8]
+;   ldr x2, [sp, #8]
+;   str x1, [sp, #48]
+;   str x0, [sp, #56]
 ;   load_ext_name x0, TestCase(%different_callee1)+0
-;   return_call_ind x0 old_stack_arg_size:0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
+;   return_call_ind x0 new_stack_arg_size:16 x2=x2 x3=x3 x4=x4 x5=x5 x6=x6 x7=x7 x8=x8 x9=x9 x10=x10 x11=x11 x12=x12 x13=x13 x14=x14 x15=x15 x19=x19 x20=x20 x21=x21 x22=x22 x23=x23 x24=x24 x25=x25 x26=x26 x27=x27 x28=x28
 ;
 ; Disassembled:
 ; block0: ; offset 0x0
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
+;   sub sp, sp, #0x20
+;   ldur x29, [sp, #0x20]
+;   stp x29, x30, [sp]
+;   mov x29, sp
 ;   sub sp, sp, #0x10
-; block1: ; offset 0xc
-;   mov x14, #0xa
-;   stur x14, [sp]
+; block1: ; offset 0x1c
+;   stur x2, [sp]
+;   mov x2, #0xa
+;   stur x2, [sp, #8]
 ;   mov x3, #0xf
 ;   mov x4, #0x14
 ;   mov x5, #0x19
@@ -500,45 +498,31 @@ block2:
 ;   mov x28, #0x7d
 ;   mov x1, #0x82
 ;   mov x0, #0x87
-;   cbnz x2, #0xd4
-; block2: ; offset 0x7c
+;   ldur x2, [sp]
+;   cbnz x2, #0xc4
+; block2: ; offset 0x94
 ;   mov x2, #0x8c
-;   sub sp, sp, #0x20
-;   stur x1, [sp]
-;   stur x0, [sp, #8]
-;   stur x2, [sp, #0x10]
-;   ldr x0, #0x98
-;   b #0xa0
+;   stur x1, [sp, #0x20]
+;   stur x0, [sp, #0x28]
+;   stur x2, [sp, #0x30]
+;   ldr x0, #0xac
+;   b #0xb4
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %different_callee2 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldur x2, [sp, #0x20]
-;   ldp x16, x30, [x29]
-;   ldur x17, [sp, #0x18]
-;   stur x17, [x29, #8]
-;   ldur x17, [sp, #0x10]
-;   stur x17, [x29]
-;   ldur x17, [sp, #8]
-;   stur x17, [x29, #-8]
-;   ldur x17, [sp]
-;   stur x17, [x29, #-0x10]
-;   sub sp, x29, #0x10
-;   mov x29, x16
+;   ldur x2, [sp, #8]
+;   add sp, sp, #0x10
+;   ldp x29, x30, [sp], #0x10
 ;   br x0
-; block3: ; offset 0xd4
-;   ldur x2, [sp]
-;   sub sp, sp, #0x10
-;   stur x1, [sp]
-;   stur x0, [sp, #8]
-;   ldr x0, #0xec
-;   b #0xf4
+; block3: ; offset 0xc4
+;   ldur x2, [sp, #8]
+;   stur x1, [sp, #0x30]
+;   stur x0, [sp, #0x38]
+;   ldr x0, #0xd8
+;   b #0xe0
 ;   .byte 0x00, 0x00, 0x00, 0x00 ; reloc_external Abs8 %different_callee1 0
 ;   .byte 0x00, 0x00, 0x00, 0x00
-;   ldp x16, x30, [x29]
-;   ldur x17, [sp, #8]
-;   stur x17, [x29, #8]
-;   ldur x17, [sp]
-;   stur x17, [x29]
-;   mov sp, x29
-;   mov x29, x16
+;   add sp, sp, #0x10
+;   ldp x29, x30, [sp], #0x10
+;   add sp, sp, #0x10
 ;   br x0
 
diff --git a/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif b/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif
index 64b8b4f4e..a68287270 100644
--- a/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif
+++ b/cranelift/filetests/filetests/isa/aarch64/tail-call-conv.clif
@@ -12,8 +12,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp fp, lr, [sp, #-16]!
 ;   mov fp, sp
 ; block0:
-;   ldr x9, [fp, #16]
-;   ldr x2, [fp, #24]
+;   ldr x9, [sp, #16]
+;   ldr x2, [sp, #24]
 ;   ldp fp, lr, [sp], #16
 ;   add sp, sp, #16
 ;   ret
@@ -23,8 +23,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   stp x29, x30, [sp, #-0x10]!
 ;   mov x29, sp
 ; block1: ; offset 0x8
-;   ldur x9, [x29, #0x10]
-;   ldur x2, [x29, #0x18]
+;   ldur x9, [sp, #0x10]
+;   ldur x2, [sp, #0x18]
 ;   ldp x29, x30, [sp], #0x10
 ;   add sp, sp, #0x10
 ;   ret
@@ -316,8 +316,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   sub sp, sp, #16
 ; block0:
 ;   str x9, [sp]
-;   ldr x9, [fp, #16]
-;   ldr x1, [fp, #24]
+;   ldr x9, [sp, #32]
+;   ldr x1, [sp, #40]
 ;   str x9, [x0]
 ;   str x1, [x0, #8]
 ;   ldr x9, [sp]
@@ -333,8 +333,8 @@ block0(v0: i64, v1: i64, v2: i64, v3: i64, v4: i64, v5: i64, v6: i64, v7: i64, v
 ;   sub sp, sp, #0x10
 ; block1: ; offset 0xc
 ;   stur x9, [sp]
-;   ldur x9, [x29, #0x10]
-;   ldur x1, [x29, #0x18]
+;   ldur x9, [sp, #0x20]
+;   ldur x1, [sp, #0x28]
 ;   stur x9, [x0]
 ;   stur x1, [x0, #8]
 ;   ldur x9, [sp]