@@ -546,12 +546,25 @@ bool AArch64FrameLowering::hasFPImpl(const MachineFunction &MF) const {
546546 MFI.hasStackMap () || MFI.hasPatchPoint () ||
547547 RegInfo->hasStackRealignment (MF))
548548 return true ;
549- // If we have streaming mode changes and SVE registers on the stack we need a
550- // FP. This is as the stack size may depend on the VG at entry to the
551- // function, which is saved before the SVE area (so unrecoverable without a
552- // FP). Similar for locally streaming functions, but it is because we use
553- // ADDSVL to setup the SVE stack (which might not match VG, even without
554- // streaming-mode changes).
549+
550+ // If we:
551+ //
552+ // 1. Have streaming mode changes
553+ // OR:
554+ // 2. Have a streaming body with SVE stack objects
555+ //
556+ // Then the value of VG restored when unwinding to this function may not match
557+ // the value of VG used to set up the stack.
558+ //
559+ // This is a problem as the CFA can be described with an expression of the
560+ // form: CFA = SP + NumBytes + VG * NumScalableBytes.
561+ //
562+ // If the value of VG used in that expression does not match the value used to
563+ // set up the stack, an incorrect address for the CFA will be computed, and
564+ // unwinding will fail.
565+ //
566+ // We work around this issue by ensuring the frame-pointer can describe the
567+ // CFA in either of these cases.
555568 if (AFI.needsDwarfUnwindInfo (MF) &&
556569 ((requiresSaveVG (MF) || AFI.getSMEFnAttrs ().hasStreamingBody ()) &&
557570 (!AFI.hasCalculatedStackSizeSVE () || AFI.getStackSizeSVE () > 0 )))
@@ -1498,7 +1511,7 @@ bool isVGInstruction(MachineBasicBlock::iterator MBBI,
14981511 if (Opc == AArch64::BL)
14991512 return matchLibcall (TLI, MBBI->getOperand (0 ), RTLIB::SMEABI_GET_CURRENT_VG);
15001513
1501- return Opc == AArch64::ORRXrr ;
1514+ return Opc == TargetOpcode::COPY ;
15021515}
15031516
15041517// Convert callee-save register save/restore instruction to do stack pointer
@@ -3548,10 +3561,8 @@ bool AArch64FrameLowering::spillCalleeSavedRegisters(
35483561 unsigned X0Scratch = AArch64::NoRegister;
35493562 auto RestoreX0 = make_scope_exit ([&] {
35503563 if (X0Scratch != AArch64::NoRegister)
3551- BuildMI (MBB, MI, DL, TII.get (AArch64::ORRXrr), AArch64::X0)
3552- .addReg (AArch64::XZR)
3553- .addReg (X0Scratch, RegState::Undef)
3554- .addReg (X0Scratch, RegState::Implicit)
3564+ BuildMI (MBB, MI, DL, TII.get (TargetOpcode::COPY), AArch64::X0)
3565+ .addReg (X0Scratch)
35553566 .setMIFlag (MachineInstr::FrameSetup);
35563567 });
35573568
@@ -3570,15 +3581,12 @@ bool AArch64FrameLowering::spillCalleeSavedRegisters(
35703581 [&STI](const MachineBasicBlock::RegisterMaskPair &LiveIn) {
35713582 return STI.getRegisterInfo ()->isSuperOrSubRegisterEq (
35723583 AArch64::X0, LiveIn.PhysReg );
3573- }))
3584+ })) {
35743585 X0Scratch = Reg1;
3575-
3576- if (X0Scratch != AArch64::NoRegister)
3577- BuildMI (MBB, MI, DL, TII.get (AArch64::ORRXrr), Reg1)
3578- .addReg (AArch64::XZR)
3579- .addReg (AArch64::X0, RegState::Undef)
3580- .addReg (AArch64::X0, RegState::Implicit)
3586+ BuildMI (MBB, MI, DL, TII.get (TargetOpcode::COPY), X0Scratch)
3587+ .addReg (AArch64::X0)
35813588 .setMIFlag (MachineInstr::FrameSetup);
3589+ }
35823590
35833591 RTLIB::Libcall LC = RTLIB::SMEABI_GET_CURRENT_VG;
35843592 const uint32_t *RegMask =
@@ -4214,16 +4222,11 @@ bool AArch64FrameLowering::assignCalleeSavedSpillSlots(
42144222 // Insert VG into the list of CSRs, immediately before LR if saved.
42154223 if (requiresSaveVG (MF)) {
42164224 CalleeSavedInfo VGInfo (AArch64::VG);
4217-
4218- bool InsertedBeforeLR = false ;
4219- for (unsigned I = 0 ; I < CSI.size (); I++)
4220- if (CSI[I].getReg () == AArch64::LR) {
4221- InsertedBeforeLR = true ;
4222- CSI.insert (CSI.begin () + I, VGInfo);
4223- break ;
4224- }
4225-
4226- if (!InsertedBeforeLR)
4225+ auto It =
4226+ find_if (CSI, [](auto &Info) { return Info.getReg () == AArch64::LR; });
4227+ if (It != CSI.end ())
4228+ CSI.insert (It, VGInfo);
4229+ else
42274230 CSI.push_back (VGInfo);
42284231 }
42294232
0 commit comments