Index: llvm/lib/Target/AArch64/AArch64FrameLowering.h =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -67,6 +67,11 @@ bool hasFP(const MachineFunction &MF) const override; bool hasReservedCallFrame(const MachineFunction &MF) const override; + bool + assignCalleeSavedSpillSlots(MachineFunction &MF, + const TargetRegisterInfo *TRI, + std::vector &CSI) const override; + void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override; Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -2001,6 +2001,26 @@ return true; if (!NeedsWinCFI) return false; + // When the list of callee saved registers is backwards, we must choose + // not to pair e.g. x20+x21, as x20 should be paired with x19. If there's + // gaps in the list of callee saved registers, this might end up + // inefficient, but normally it should produce the canonical prologue format + // that matches the packed unwind format. + if (Reg1 >= AArch64::X0 && Reg1 <= AArch64::X28) { + int N = Reg1 - AArch64::X0; + // Reject pairs if the first reg isn't an odd register + if (N % 2 != 1) + return true; + } else if (Reg1 >= AArch64::D0 && Reg1 <= AArch64::D31) { + // Reject pairs if the first reg isn't an even register + int N = Reg1 - AArch64::D0; + if (N % 2 != 0) + return true; + } else if (Reg1 == AArch64::FP && Reg2 == AArch64::LR) { + return false; + } else { + return true; + } if (Reg2 == Reg1 + 1) return false; return true; @@ -2103,22 +2123,31 @@ // Add the next reg to the pair if it is in the same register class. if (i + 1 < Count) { + unsigned CurReg = RPI.Reg1; unsigned NextReg = CSI[i + 1].getReg(); + if (NeedsWinCFI) + std::swap(CurReg, NextReg); switch (RPI.Type) { case RegPairInfo::GPR: if (AArch64::GPR64RegClass.contains(NextReg) && - !invalidateRegisterPairing(RPI.Reg1, NextReg, IsWindows, NeedsWinCFI, - NeedsFrameRecord)) + !invalidateRegisterPairing(CurReg, NextReg, IsWindows, NeedsWinCFI, + NeedsFrameRecord)) { + RPI.Reg1 = CurReg; RPI.Reg2 = NextReg; + } break; case RegPairInfo::FPR64: - if (AArch64::FPR64RegClass.contains(NextReg) && - !invalidateWindowsRegisterPairing(RPI.Reg1, NextReg, NeedsWinCFI)) + if (AArch64::FPR64RegClass.contains(CurReg) && + !invalidateWindowsRegisterPairing(CurReg, NextReg, NeedsWinCFI)) { + RPI.Reg1 = CurReg; RPI.Reg2 = NextReg; + } break; case RegPairInfo::FPR128: - if (AArch64::FPR128RegClass.contains(NextReg)) + if (AArch64::FPR128RegClass.contains(NextReg)) { + RPI.Reg1 = CurReg; RPI.Reg2 = NextReg; + } break; case RegPairInfo::PPR: case RegPairInfo::ZPR: @@ -2176,14 +2205,24 @@ // Round up size of non-pair to pair size if we need to pad the // callee-save area to ensure 16-byte alignment. - if (AFI->hasCalleeSaveStackFreeSpace() && !FixupDone && - !RPI.isScalable() && RPI.Type != RegPairInfo::FPR128 && - !RPI.isPaired()) { - FixupDone = true; - ByteOffset -= 8; - assert(ByteOffset % 16 == 0); - assert(MFI.getObjectAlign(RPI.FrameIdx) <= Align(16)); - MFI.setObjectAlignment(RPI.FrameIdx, Align(16)); + if (AFI->hasCalleeSaveStackFreeSpace() && !FixupDone && !RPI.isScalable() && + RPI.Type != RegPairInfo::FPR128) { + bool DoFixup = false; + if (!NeedsWinCFI) { + DoFixup = !RPI.isPaired(); + } else { // NeedsWinCFI + // For WinCFI, do the fixup before the first register; in WinCFI + // one can have register pairs that aren't aligned to 16 bytes. + DoFixup = true; + } + if (DoFixup) { + FixupDone = true; + ByteOffset -= 8; + if (!NeedsWinCFI) + assert(ByteOffset % 16 == 0); + assert(MFI.getObjectAlign(RPI.FrameIdx) <= Align(16)); + MFI.setObjectAlignment(RPI.FrameIdx, Align(16)); + } } int Offset = RPI.isScalable() ? ScalableByteOffset : ByteOffset; @@ -2636,6 +2675,19 @@ AFI->setSVECalleeSavedStackSize(alignTo(SVECSStackSize, 16)); } +bool AArch64FrameLowering::assignCalleeSavedSpillSlots( + MachineFunction &MF, const TargetRegisterInfo *TRI, + std::vector &CSI) const { + bool NeedsWinCFI = needsWinCFI(MF); + // To match the canonical windows frame layout, reverse the list of + // callee saved registers to get them laid out in the desired order + // (lower registers at a lower stack address). + if (NeedsWinCFI) + std::reverse(CSI.begin(), CSI.end()); + // Let the generic code do the rest of the setup. + return false; +} + bool AArch64FrameLowering::enableStackSlotScavenging( const MachineFunction &MF) const { const AArch64FunctionInfo *AFI = MF.getInfo(); Index: llvm/test/CodeGen/AArch64/seh-finally.ll =================================================================== --- llvm/test/CodeGen/AArch64/seh-finally.ll +++ llvm/test/CodeGen/AArch64/seh-finally.ll @@ -86,12 +86,12 @@ define void @stack_realign() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { entry: ; CHECK-LABEL: stack_realign -; CHECK: mov x29, sp +; CHECK: add x29, sp, #8 ; CHECK: sub x9, sp, #16 ; CHECK: and sp, x9, #0xffffffffffffffe0 ; CHECK: mov x19, sp ; CHECK: mov x0, #-2 -; CHECK: stur x0, [x29, #32] +; CHECK: stur x0, [x29, #24] ; CHECK: .set .Lstack_realign$frame_escape_0, 0 ; CHECK: ldr w0, [x19] ; CHECK: bl foo @@ -205,17 +205,17 @@ define void @vla_and_realign(i32 %n) #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { entry: ; CHECK-LABEL: vla_and_realign -; CHECK: mov x29, sp +; CHECK: add x29, sp, #8 ; CHECK: sub x9, sp, #48 ; CHECK: and sp, x9, #0xffffffffffffffe0 ; CHECK: mov x19, sp ; CHECK: mov x1, #-2 -; CHECK: stur x1, [x29, #32] +; CHECK: stur x1, [x29, #24] ; CHECK: .set .Lvla_and_realign$frame_escape_0, 32 -; CHECK: str w0, [x29, #44] -; CHECK: ldr w8, [x29, #44] +; CHECK: str w0, [x29, #36] +; CHECK: ldr w8, [x29, #36] ; CHECK: mov x9, sp -; CHECK: str x9, [x29, #24] +; CHECK: str x9, [x29, #16] ; CHECK: str x8, [x19, #24] ; CHECK: ldr w0, [x19, #32] ; CHECK: bl foo Index: llvm/test/CodeGen/AArch64/sponentry.ll =================================================================== --- llvm/test/CodeGen/AArch64/sponentry.ll +++ llvm/test/CodeGen/AArch64/sponentry.ll @@ -38,8 +38,8 @@ ; CHECK: foo: ; CHECK: sub sp, sp, #448 -; CHECK: add x29, sp, #416 -; CHECK: add x1, x29, #32 +; CHECK: add x29, sp, #424 +; CHECK: add x1, x29, #24 ; CHECK: bl _setjmpex ; NOFP: sub sp, sp, #432 Index: llvm/test/CodeGen/AArch64/win64_vararg.ll =================================================================== --- llvm/test/CodeGen/AArch64/win64_vararg.ll +++ llvm/test/CodeGen/AArch64/win64_vararg.ll @@ -103,21 +103,21 @@ declare i64* @__local_stdio_printf_options() local_unnamed_addr #4 ; CHECK-LABEL: fp -; CHECK: stp x29, x30, [sp, #-96] +; CHECK: stp x19, x20, [sp, #-96] ; CHECK: str x21, [sp, #16] -; CHECK: stp x19, x20, [sp, #32] -; CHECK: mov x29, sp -; CHECK: add x8, x29, #56 +; CHECK: stp x29, x30, [sp, #24] +; CHECK: add x29, sp, #24 +; CHECK: add x8, x29, #32 ; CHECK: mov x19, x2 ; CHECK: mov x20, x1 ; CHECK: mov x21, x0 -; CHECK: stp x3, x4, [x29, #56] -; CHECK: stp x5, x6, [x29, #72] -; CHECK: str x7, [x29, #88] -; CHECK: str x8, [x29, #24] +; CHECK: stp x3, x4, [x29, #32] +; CHECK: stp x5, x6, [x29, #48] +; CHECK: str x7, [x29, #64] +; CHECK: str x8, [x29, #16] ; CHECK: bl __local_stdio_printf_options ; CHECK: ldr x8, [x0] -; CHECK: add x5, x29, #56 +; CHECK: add x5, x29, #32 ; CHECK: mov x1, x21 ; CHECK: mov x2, x20 ; CHECK: orr x0, x8, #0x2 @@ -126,9 +126,9 @@ ; CHECK: bl __stdio_common_vsprintf ; CHECK: cmp w0, #0 ; CHECK: csinv w0, w0, wzr, ge -; CHECK: ldp x19, x20, [sp, #32] +; CHECK: ldp x29, x30, [sp, #24] ; CHECK: ldr x21, [sp, #16] -; CHECK: ldp x29, x30, [sp], #96 +; CHECK: ldp x19, x20, [sp], #96 ; CHECK: ret define i32 @fp(i8*, i64, i8*, ...) local_unnamed_addr #6 { %4 = alloca i8*, align 8 @@ -150,26 +150,26 @@ attributes #6 = { "frame-pointer"="all" } ; CHECK-LABEL: vla -; CHECK: stp x29, x30, [sp, #-112]! -; CHECK: str x23, [sp, #16] -; CHECK: stp x21, x22, [sp, #32] -; CHECK: stp x19, x20, [sp, #48] -; CHECK: mov x29, sp -; CHECK: add x8, x29, #64 -; CHECK: str x8, [x29, #24] +; CHECK: stp x19, x20, [sp, #-112]! +; CHECK: stp x21, x22, [sp, #16] +; CHECK: str x23, [sp, #32] +; CHECK: stp x29, x30, [sp, #40] +; CHECK: add x29, sp, #40 +; CHECK: add x8, x29, #24 +; CHECK: str x8, [x29, #16] ; CHECK: mov w8, w0 ; CHECK: add x8, x8, #15 ; CHECK: lsr x15, x8, #4 ; CHECK: mov x19, x1 ; CHECK: mov [[REG2:x[0-9]+]], sp -; CHECK: stp x2, x3, [x29, #64] -; CHECK: stp x4, x5, [x29, #80] -; CHECK: stp x6, x7, [x29, #96] +; CHECK: stp x2, x3, [x29, #24] +; CHECK: stp x4, x5, [x29, #40] +; CHECK: stp x6, x7, [x29, #56] ; CHECK: bl __chkstk ; CHECK: mov x8, sp ; CHECK: sub [[REG:x[0-9]+]], x8, x15, lsl #4 ; CHECK: mov sp, [[REG]] -; CHECK: ldr [[REG3:x[0-9]+]], [x29, #24] +; CHECK: ldr [[REG3:x[0-9]+]], [x29, #16] ; CHECK: sxtw [[REG4:x[0-9]+]], w0 ; CHECK: bl __local_stdio_printf_options ; CHECK: ldr x8, [x0] @@ -181,11 +181,11 @@ ; CHECK: mov x5, [[REG3]] ; CHECK: bl __stdio_common_vsprintf ; CHECK: mov sp, [[REG2]] -; CHECK: mov sp, x29 -; CHECK: ldp x19, x20, [sp, #48] -; CHECK: ldp x21, x22, [sp, #32] -; CHECK: ldr x23, [sp, #16] -; CHECK: ldp x29, x30, [sp], #112 +; CHECK: sub sp, x29, #40 +; CHECK: ldp x29, x30, [sp, #40] +; CHECK: ldr x23, [sp, #32] +; CHECK: ldp x21, x22, [sp, #16] +; CHECK: ldp x19, x20, [sp], #112 ; CHECK: ret define void @vla(i32, i8*, ...) local_unnamed_addr { %3 = alloca i8*, align 8 @@ -212,9 +212,9 @@ ; CHECK-LABEL: snprintf ; CHECK-DAG: sub sp, sp, #96 -; CHECK-DAG: str x30, [sp, #16] -; CHECK-DAG: str x21, [sp, #24] -; CHECK-DAG: stp x19, x20, [sp, #32] +; CHECK-DAG: stp x19, x20, [sp, #16] +; CHECK-DAG: str x21, [sp, #32] +; CHECK-DAG: str x30, [sp, #40] ; CHECK-DAG: add x8, sp, #56 ; CHECK-DAG: mov x19, x2 ; CHECK-DAG: mov x20, x1 @@ -232,9 +232,9 @@ ; CHECK-DAG: mov x3, x19 ; CHECK-DAG: mov x4, xzr ; CHECK-DAG: bl __stdio_common_vsprintf -; CHECK-DAG: ldr x30, [sp, #16] -; CHECK-DAG: ldr x21, [sp, #24] -; CHECK-DAG: ldp x19, x20, [sp, #32] +; CHECK-DAG: ldr x30, [sp, #40] +; CHECK-DAG: ldr x21, [sp, #32] +; CHECK-DAG: ldp x19, x20, [sp, #16] ; CHECK-DAG: cmp w0, #0 ; CHECK-DAG: csinv w0, w0, wzr, ge ; CHECK-DAG: add sp, sp, #96 Index: llvm/test/CodeGen/AArch64/wineh-frame-scavenge.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/wineh-frame-scavenge.mir @@ -0,0 +1,89 @@ +# RUN: llc -o - %s -mtriple=aarch64-windows -start-before=prologepilog \ +# RUN: -stop-after=prologepilog | FileCheck %s +# Check where the stack variable is placed + +# CHECK: - { id: 0, name: '', type: default, offset: -4, size: 4, alignment: 4, +# CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, +# CHECK-NEXT: local-offset: -4, debug-info-variable: '', debug-info-expression: '', +# CHECK-NEXT: debug-info-location: '' } +# CHECK-NEXT: - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 16, +# CHECK-NEXT: stack-id: default, callee-saved-register: '$x23', callee-saved-restored: true, +# CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +# CHECK-NEXT: - { id: 2, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, +# CHECK-NEXT: stack-id: default, callee-saved-register: '$x22', callee-saved-restored: true, +# CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +# CHECK-NEXT: - { id: 3, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, +# CHECK-NEXT: stack-id: default, callee-saved-register: '$x21', callee-saved-restored: true, +# CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +# CHECK-NEXT: - { id: 4, name: '', type: spill-slot, offset: -40, size: 8, alignment: 8, +# CHECK-NEXT: stack-id: default, callee-saved-register: '$x20', callee-saved-restored: true, +# CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +# CHECK-NEXT: - { id: 5, name: '', type: spill-slot, offset: -48, size: 8, alignment: 8, +# CHECK-NEXT: stack-id: default, callee-saved-register: '$x19', callee-saved-restored: true, +# CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + +# CHECK: early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -6 :: (store 8 into %stack.4), (store 8 into %stack.5) +# CHECK-NEXT: frame-setup SEH_SaveRegP_X 19, 20, -48 +# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x22, $sp, 2 :: (store 8 into %stack.2), (store 8 into %stack.3) +# CHECK-NEXT: frame-setup SEH_SaveRegP 21, 22, 16 +# CHECK-NEXT: frame-setup STRXui killed $x23, $sp, 4 :: (store 8 into %stack.1) +# CHECK-NEXT: frame-setup SEH_SaveReg 23, 32 +# CHECK-NEXT: frame-setup SEH_PrologEnd + + +... +--- +name: func +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: [] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 4 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + local-offset: -4, debug-info-variable: '', debug-info-expression: '', + debug-info-location: '' } +callSites: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + liveins: $x0, $x23, $x21, $x22, $x19, $x20 + + renamable $x8 = ADDXri %stack.0, 0, 0 + $x19 = ADDXrr $x0, $x8 + $x20 = ADDXrr $x19, $x0 + $x21 = ADDXrr $x20, killed $x19 + $x22 = ADDXrr $x21, killed $x20 + $x23 = ADDXrr $x22, killed $x21 + $x0 = ADDXrr $x0, killed $x23 + + RET_ReallyLR + +... Index: llvm/test/CodeGen/AArch64/wineh-frame0.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh-frame0.mir +++ llvm/test/CodeGen/AArch64/wineh-frame0.mir @@ -2,28 +2,28 @@ # RUN: -stop-after=prologepilog | FileCheck %s # Check save_regp_x, save_regp -# CHECK: early-clobber $sp = frame-setup STPXpre killed $x27, killed $x28, $sp, -10 -# CHECK-NEXT: frame-setup SEH_SaveRegP_X 27, 28, -80 -# CHECK-NEXT: frame-setup STPXi killed $x25, killed $x26, $sp, 2 -# CHECK-NEXT: frame-setup SEH_SaveRegP 25, 26, 16 +# CHECK: early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -10 +# CHECK-NEXT: frame-setup SEH_SaveRegP_X 19, 20, -80 +# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x22, $sp, 2 +# CHECK-NEXT: frame-setup SEH_SaveRegP 21, 22, 16 # CHECK-NEXT: frame-setup STPXi killed $x23, killed $x24, $sp, 4 # CHECK-NEXT: frame-setup SEH_SaveRegP 23, 24, 32 -# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x22, $sp, 6 -# CHECK-NEXT: frame-setup SEH_SaveRegP 21, 22, 48 -# CHECK-NEXT: frame-setup STPXi killed $x19, killed $x20, $sp, 8 -# CHECK-NEXT: frame-setup SEH_SaveRegP 19, 20, 64 +# CHECK-NEXT: frame-setup STPXi killed $x25, killed $x26, $sp, 6 +# CHECK-NEXT: frame-setup SEH_SaveRegP 25, 26, 48 +# CHECK-NEXT: frame-setup STPXi killed $x27, killed $x28, $sp, 8 +# CHECK-NEXT: frame-setup SEH_SaveRegP 27, 28, 64 # CHECK-NEXT: frame-setup SEH_PrologEnd # CHECK: frame-destroy SEH_EpilogStart -# CHECK-NEXT: $x19, $x20 = frame-destroy LDPXi $sp, 8 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 19, 20, 64 -# CHECK-NEXT: $x21, $x22 = frame-destroy LDPXi $sp, 6 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 21, 22, 48 +# CHECK-NEXT: $x27, $x28 = frame-destroy LDPXi $sp, 8 +# CHECK-NEXT: frame-destroy SEH_SaveRegP 27, 28, 64 +# CHECK-NEXT: $x25, $x26 = frame-destroy LDPXi $sp, 6 +# CHECK-NEXT: frame-destroy SEH_SaveRegP 25, 26, 48 # CHECK-NEXT: $x23, $x24 = frame-destroy LDPXi $sp, 4 # CHECK-NEXT: frame-destroy SEH_SaveRegP 23, 24, 32 -# CHECK-NEXT: $x25, $x26 = frame-destroy LDPXi $sp, 2 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 25, 26, 16 -# CHECK-NEXT: early-clobber $sp, $x27, $x28 = frame-destroy LDPXpost $sp, 10 -# CHECK-NEXT: frame-destroy SEH_SaveRegP_X 27, 28, -80 +# CHECK-NEXT: $x21, $x22 = frame-destroy LDPXi $sp, 2 +# CHECK-NEXT: frame-destroy SEH_SaveRegP 21, 22, 16 +# CHECK-NEXT: early-clobber $sp, $x19, $x20 = frame-destroy LDPXpost $sp, 10 +# CHECK-NEXT: frame-destroy SEH_SaveRegP_X 19, 20, -80 # CHECK-NEXT: frame-destroy SEH_EpilogEnd # CHECK-NEXT: RET_ReallyLR implicit $x0 Index: llvm/test/CodeGen/AArch64/wineh-frame1.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh-frame1.mir +++ llvm/test/CodeGen/AArch64/wineh-frame1.mir @@ -2,36 +2,36 @@ # RUN: -stop-after=prologepilog | FileCheck %s # Check save_fregp_x, save_fregp -# CHECK: early-clobber $sp = frame-setup STPDpre killed $d10, killed $d11, $sp, -14 -# CHECK-NEXT: frame-setup SEH_SaveFRegP_X 10, 11, -112 -# CHECK-NEXT: frame-setup STPDi killed $d8, killed $d9, $sp, 2 -# CHECK-NEXT: frame-setup SEH_SaveFRegP 8, 9, 16 -# CHECK-NEXT: frame-setup STPXi killed $x27, killed $x28, $sp, 4 -# CHECK-NEXT: frame-setup SEH_SaveRegP 27, 28, 32 +# CHECK: early-clobber $sp = frame-setup STPXpre killed $x19, killed $x20, $sp, -14 +# CHECK-NEXT: frame-setup SEH_SaveRegP_X 19, 20, -112 +# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x22, $sp, 2 +# CHECK-NEXT: frame-setup SEH_SaveRegP 21, 22, 16 +# CHECK-NEXT: frame-setup STPXi killed $x23, killed $x24, $sp, 4 +# CHECK-NEXT: frame-setup SEH_SaveRegP 23, 24, 32 # CHECK-NEXT: frame-setup STPXi killed $x25, killed $x26, $sp, 6 # CHECK-NEXT: frame-setup SEH_SaveRegP 25, 26, 48 -# CHECK-NEXT: frame-setup STPXi killed $x23, killed $x24, $sp, 8 -# CHECK-NEXT: frame-setup SEH_SaveRegP 23, 24, 64 -# CHECK-NEXT: frame-setup STPXi killed $x21, killed $x22, $sp, 10 -# CHECK-NEXT: frame-setup SEH_SaveRegP 21, 22, 80 -# CHECK-NEXT: frame-setup STPXi killed $x19, killed $x20, $sp, 12 -# CHECK-NEXT: frame-setup SEH_SaveRegP 19, 20, 96 +# CHECK-NEXT: frame-setup STPXi killed $x27, killed $x28, $sp, 8 +# CHECK-NEXT: frame-setup SEH_SaveRegP 27, 28, 64 +# CHECK-NEXT: frame-setup STPDi killed $d8, killed $d9, $sp, 10 +# CHECK-NEXT: frame-setup SEH_SaveFRegP 8, 9, 80 +# CHECK-NEXT: frame-setup STPDi killed $d10, killed $d11, $sp, 12 +# CHECK-NEXT: frame-setup SEH_SaveFRegP 10, 11, 96 # CHECK-NEXT: frame-setup SEH_PrologEnd # CHECK: frame-destroy SEH_EpilogStart -# CHECK-NEXT: $x19, $x20 = frame-destroy LDPXi $sp, 12 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 19, 20, 96 -# CHECK-NEXT: $x21, $x22 = frame-destroy LDPXi $sp, 10 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 21, 22, 80 -# CHECK-NEXT: $x23, $x24 = frame-destroy LDPXi $sp, 8 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 23, 24, 64 +# CHECK-NEXT: $d10, $d11 = frame-destroy LDPDi $sp, 12 +# CHECK-NEXT: frame-destroy SEH_SaveFRegP 10, 11, 96 +# CHECK-NEXT: $d8, $d9 = frame-destroy LDPDi $sp, 10 +# CHECK-NEXT: frame-destroy SEH_SaveFRegP 8, 9, 80 +# CHECK-NEXT: $x27, $x28 = frame-destroy LDPXi $sp, 8 +# CHECK-NEXT: frame-destroy SEH_SaveRegP 27, 28, 64 # CHECK-NEXT: $x25, $x26 = frame-destroy LDPXi $sp, 6 # CHECK-NEXT: frame-destroy SEH_SaveRegP 25, 26, 48 -# CHECK-NEXT: $x27, $x28 = frame-destroy LDPXi $sp, 4 -# CHECK-NEXT: frame-destroy SEH_SaveRegP 27, 28, 32 -# CHECK-NEXT: $d8, $d9 = frame-destroy LDPDi $sp, 2 -# CHECK-NEXT: frame-destroy SEH_SaveFRegP 8, 9, 16 -# CHECK-NEXT: early-clobber $sp, $d10, $d11 = frame-destroy LDPDpost $sp, 14 -# CHECK-NEXT: frame-destroy SEH_SaveFRegP_X 10, 11, -112 +# CHECK-NEXT: $x23, $x24 = frame-destroy LDPXi $sp, 4 +# CHECK-NEXT: frame-destroy SEH_SaveRegP 23, 24, 32 +# CHECK-NEXT: $x21, $x22 = frame-destroy LDPXi $sp, 2 +# CHECK-NEXT: frame-destroy SEH_SaveRegP 21, 22, 16 +# CHECK-NEXT: early-clobber $sp, $x19, $x20 = frame-destroy LDPXpost $sp, 14 +# CHECK-NEXT: frame-destroy SEH_SaveRegP_X 19, 20, -112 # CHECK-NEXT: frame-destroy SEH_EpilogEnd # CHECK-NEXT: RET_ReallyLR implicit $x0 ... Index: llvm/test/CodeGen/AArch64/wineh-frame2.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh-frame2.mir +++ llvm/test/CodeGen/AArch64/wineh-frame2.mir @@ -2,24 +2,24 @@ # RUN: -stop-after=prologepilog | FileCheck %s # Check save_freg_x, save_frep, save_reg -# CHECK: early-clobber $sp = frame-setup STRDpre killed $d12, $sp, -48 -# CHECK-NEXT: frame-setup SEH_SaveFReg_X 12, -48 -# CHECK-NEXT: frame-setup STPDi killed $d10, killed $d11, $sp, 1 -# CHECK-NEXT: frame-setup SEH_SaveFRegP 10, 11, 8 -# CHECK-NEXT: frame-setup STPDi killed $d8, killed $d9, $sp, 3 -# CHECK-NEXT: frame-setup SEH_SaveFRegP 8, 9, 24 -# CHECK-NEXT: frame-setup STRXui killed $x19, $sp, 5 -# CHECK-NEXT: frame-setup SEH_SaveReg 19, 40 +# CHECK: early-clobber $sp = frame-setup STRXpre killed $x19, $sp, -48 +# CHECK-NEXT: frame-setup SEH_SaveReg_X 19, -48 +# CHECK-NEXT: frame-setup STPDi killed $d8, killed $d9, $sp, 1 +# CHECK-NEXT: frame-setup SEH_SaveFRegP 8, 9, 8 +# CHECK-NEXT: frame-setup STPDi killed $d10, killed $d11, $sp, 3 +# CHECK-NEXT: frame-setup SEH_SaveFRegP 10, 11, 24 +# CHECK-NEXT: frame-setup STRDui killed $d12, $sp, 5 +# CHECK-NEXT: frame-setup SEH_SaveFReg 12, 40 # CHECK-NEXT: frame-setup SEH_PrologEnd # CHECK: frame-destroy SEH_EpilogStart -# CHECK-NEXT: $x19 = frame-destroy LDRXui $sp, 5 -# CHECK-NEXT: frame-destroy SEH_SaveReg 19, 40 -# CHECK-NEXT: $d8, $d9 = frame-destroy LDPDi $sp, 3 -# CHECK-NEXT: frame-destroy SEH_SaveFRegP 8, 9, 24 -# CHECK-NEXT: $d10, $d11 = frame-destroy LDPDi $sp, 1 -# CHECK-NEXT: frame-destroy SEH_SaveFRegP 10, 11, 8 -# CHECK-NEXT: early-clobber $sp, $d12 = frame-destroy LDRDpost $sp, 48 -# CHECK-NEXT: frame-destroy SEH_SaveFReg_X 12, -48 +# CHECK-NEXT: $d12 = frame-destroy LDRDui $sp, 5 +# CHECK-NEXT: frame-destroy SEH_SaveFReg 12, 40 +# CHECK-NEXT: $d10, $d11 = frame-destroy LDPDi $sp, 3 +# CHECK-NEXT: frame-destroy SEH_SaveFRegP 10, 11, 24 +# CHECK-NEXT: $d8, $d9 = frame-destroy LDPDi $sp, 1 +# CHECK-NEXT: frame-destroy SEH_SaveFRegP 8, 9, 8 +# CHECK-NEXT: early-clobber $sp, $x19 = frame-destroy LDRXpost $sp, 48 +# CHECK-NEXT: frame-destroy SEH_SaveReg_X 19, -48 # CHECK-NEXT: frame-destroy SEH_EpilogEnd # CHECK-NEXT: RET_ReallyLR implicit $x0 ... Index: llvm/test/CodeGen/AArch64/wineh-frame3.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh-frame3.mir +++ llvm/test/CodeGen/AArch64/wineh-frame3.mir @@ -2,16 +2,16 @@ # RUN: -stop-after=prologepilog | FileCheck %s # Check save_reg_x, save_reg -# CHECK: early-clobber $sp = frame-setup STRXpre killed $x22, $sp, -16 -# CHECK-NEXT: frame-setup SEH_SaveReg_X 22, -16 -# CHECK-NEXT: frame-setup STRXui killed $x19, $sp, 1 -# CHECK-NEXT: frame-setup SEH_SaveReg 19, 8 +# CHECK: early-clobber $sp = frame-setup STRXpre killed $x19, $sp, -16 +# CHECK-NEXT: frame-setup SEH_SaveReg_X 19, -16 +# CHECK-NEXT: frame-setup STRXui killed $x22, $sp, 1 +# CHECK-NEXT: frame-setup SEH_SaveReg 22, 8 # CHECK-NEXT: frame-setup SEH_PrologEnd # CHECK: frame-destroy SEH_EpilogStart -# CHECK-NEXT: $x19 = frame-destroy LDRXui $sp, 1 -# CHECK-NEXT: frame-destroy SEH_SaveReg 19, 8 -# CHECK-NEXT: early-clobber $sp, $x22 = frame-destroy LDRXpost $sp, 16 -# CHECK-NEXT: frame-destroy SEH_SaveReg_X 22, -16 +# CHECK-NEXT: $x22 = frame-destroy LDRXui $sp, 1 +# CHECK-NEXT: frame-destroy SEH_SaveReg 22, 8 +# CHECK-NEXT: early-clobber $sp, $x19 = frame-destroy LDRXpost $sp, 16 +# CHECK-NEXT: frame-destroy SEH_SaveReg_X 19, -16 # CHECK-NEXT: frame-destroy SEH_EpilogEnd # CHECK-NEXT: RET_ReallyLR implicit $x0 ... Index: llvm/test/CodeGen/AArch64/wineh-frame4.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh-frame4.mir +++ llvm/test/CodeGen/AArch64/wineh-frame4.mir @@ -2,16 +2,16 @@ # RUN: -stop-after=prologepilog | FileCheck %s # Check save_freg_x, save_freg -# CHECK: early-clobber $sp = frame-setup STRDpre killed $d10, $sp, -16 -# CHECK-NEXT: frame-setup SEH_SaveFReg_X 10, -16 -# CHECK-NEXT: frame-setup STRDui killed $d8, $sp, 1 :: (store 8 into %stack.0) -# CHECK-NEXT: frame-setup SEH_SaveFReg 8, 8 +# CHECK: early-clobber $sp = frame-setup STRDpre killed $d8, $sp, -16 +# CHECK-NEXT: frame-setup SEH_SaveFReg_X 8, -16 +# CHECK-NEXT: frame-setup STRDui killed $d10, $sp, 1 :: (store 8 into %stack.0) +# CHECK-NEXT: frame-setup SEH_SaveFReg 10, 8 # CHECK-NEXT: frame-setup SEH_PrologEnd # CHECK: frame-destroy SEH_EpilogStart -# CHECK-NEXT: $d8 = frame-destroy LDRDui $sp, 1 :: (load 8 from %stack.0) -# CHECK-NEXT: frame-destroy SEH_SaveFReg 8, 8 -# CHECK-NEXT: early-clobber $sp, $d10 = frame-destroy LDRDpost $sp, 16 :: (load 8 from %stack.1) -# CHECK-NEXT: frame-destroy SEH_SaveFReg_X 10, -16 +# CHECK-NEXT: $d10 = frame-destroy LDRDui $sp, 1 :: (load 8 from %stack.0) +# CHECK-NEXT: frame-destroy SEH_SaveFReg 10, 8 +# CHECK-NEXT: early-clobber $sp, $d8 = frame-destroy LDRDpost $sp, 16 :: (load 8 from %stack.1) +# CHECK-NEXT: frame-destroy SEH_SaveFReg_X 8, -16 # CHECK-NEXT: frame-destroy SEH_EpilogEnd # CHECK-NEXT: RET_ReallyLR implicit $x0 ... Index: llvm/test/CodeGen/AArch64/wineh-frame5.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh-frame5.mir +++ llvm/test/CodeGen/AArch64/wineh-frame5.mir @@ -3,10 +3,10 @@ # Check multiple epilogues, save_reg, save_reg_x. # CHECK-LABEL: bb.0.entry: -# CHECK: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -4 -# CHECK-NEXT: frame-setup SEH_SaveFPLR_X -32 -# CHECK-NEXT: frame-setup STRXui killed $x19, $sp, 2 -# CHECK-NEXT: frame-setup SEH_SaveReg 19, 16 +# CHECK: early-clobber $sp = frame-setup STRXpre killed $x19, $sp, -32 +# CHECK-NEXT: frame-setup SEH_SaveReg_X 19, -32 +# CHECK-NEXT: frame-setup STPXi killed $fp, killed $lr, $sp, 1 +# CHECK-NEXT: frame-setup SEH_SaveFPLR 8 # CHECK-NEXT: $sp = frame-setup SUBXri $sp, 496, 0 # CHECK-NEXT: frame-setup SEH_StackAlloc 496 # CHECK-NEXT: frame-setup SEH_PrologEnd @@ -15,10 +15,10 @@ # CHECK: frame-destroy SEH_EpilogStart # CHECK-NEXT: $sp = frame-destroy ADDXri $sp, 496, 0 # CHECK-NEXT: frame-destroy SEH_StackAlloc 496 -# CHECK-NEXT: $x19 = frame-destroy LDRXui $sp, 2 -# CHECK-NEXT: frame-destroy SEH_SaveReg 19, 16 -# CHECK-NEXT: early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 4 -# CHECK-NEXT: frame-destroy SEH_SaveFPLR_X -32 +# CHECK-NEXT: $fp, $lr = frame-destroy LDPXi $sp, 1 +# CHECK-NEXT: frame-destroy SEH_SaveFPLR 8 +# CHECK-NEXT: early-clobber $sp, $x19 = frame-destroy LDRXpost $sp, 32 +# CHECK-NEXT: frame-destroy SEH_SaveReg_X 19, -32 # CHECK-NEXT: frame-destroy SEH_EpilogEnd # CHECK-NEXT: TCRETURNdi @"?func2@@YAHXZ", 0, csr_aarch64_aapcs, implicit $sp Index: llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll =================================================================== --- llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll +++ llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll @@ -9,12 +9,12 @@ ; it shouldn't access the parent's frame via sp, and the prologue and ; epilogue should be symmetrical. ; CHECK-LABEL: "?catch$2@?0??a@@YAXXZ@4HA": -; CHECK: stp x29, x30, [sp, #-32]! -; CHECK-NEXT: .seh_save_fplr_x 32 -; CHECK-NEXT: str x28, [sp, #16] -; CHECK-NEXT: .seh_save_reg x28, 16 -; CHECK-NEXT: str x19, [sp, #24] -; CHECK-NEXT: .seh_save_reg x19, 24 +; CHECK: str x19, [sp, #-32]! +; CHECK-NEXT: .seh_save_reg_x x19, 32 +; CHECK-NEXT: str x28, [sp, #8] +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: stp x29, x30, [sp, #16] +; CHECK-NEXT: .seh_save_fplr 16 ; CHECK-NEXT: .seh_endprologue ; CHECK-NEXT: add x0, x19, #0 ; CHECK-NEXT: mov w1, wzr @@ -22,12 +22,12 @@ ; CHECK-NEXT: adrp x0, .LBB0_1 ; CHECK-NEXT: add x0, x0, .LBB0_1 ; CHECK-NEXT: .seh_startepilogue -; CHECK-NEXT: ldr x19, [sp, #24] -; CHECK-NEXT: .seh_save_reg x19, 24 -; CHECK-NEXT: ldr x28, [sp, #16] -; CHECK-NEXT: .seh_save_reg x28, 16 -; CHECK-NEXT: ldp x29, x30, [sp], #32 -; CHECK-NEXT: .seh_save_fplr_x 32 +; CHECK-NEXT: ldp x29, x30, [sp, #16] +; CHECK-NEXT: .seh_save_fplr 16 +; CHECK-NEXT: ldr x28, [sp, #8] +; CHECK-NEXT: .seh_save_reg x28, 8 +; CHECK-NEXT: ldr x19, [sp], #32 +; CHECK-NEXT: .seh_save_reg_x x19, 32 ; CHECK-NEXT: .seh_endepilogue ; CHECK-NEXT: ret Index: llvm/test/CodeGen/AArch64/wineh-try-catch.ll =================================================================== --- llvm/test/CodeGen/AArch64/wineh-try-catch.ll +++ llvm/test/CodeGen/AArch64/wineh-try-catch.ll @@ -15,15 +15,15 @@ ; We check this offset in the table later on. ; CHECK-LABEL: "?func@@YAHXZ": -; CHECK: stp x29, x30, [sp, #-64]! -; CHECK: str x28, [sp, #16] -; CHECK: str x21, [sp, #24] -; CHECK: stp x19, x20, [sp, #32] -; CHECK: mov x29, sp +; CHECK: stp x19, x20, [sp, #-64]! +; CHECK: str x21, [sp, #16] +; CHECK: str x28, [sp, #24] +; CHECK: stp x29, x30, [sp, #32] +; CHECK: add x29, sp, #32 ; CHECK: sub sp, sp, #624 ; CHECK: mov x19, sp ; CHECK: mov x0, #-2 -; CHECK: stur x0, [x29, #48] +; CHECK: stur x0, [x29, #16] ; Now check that x is stored at fp - 20. We check that this is the same ; location accessed from the funclet to retrieve x. @@ -47,10 +47,10 @@ ; CHECK-LABEL: "?catch$2@?0??func@@YAHXZ@4HA": ; Check that the stack space is allocated only for the callee saved registers. -; CHECK: stp x29, x30, [sp, #-48]! -; CHECK: str x28, [sp, #16] -; CHECK: str x21, [sp, #24] -; CHECK: stp x19, x20, [sp, #32] +; CHECK: stp x19, x20, [sp, #-48]! +; CHECK: str x21, [sp, #16] +; CHECK: str x28, [sp, #24] +; CHECK: stp x29, x30, [sp, #32] ; CHECK: add x20, x19, #12 ; Check that there are no further stack updates. @@ -87,18 +87,18 @@ ; UNWIND: Prologue [ ; UNWIND-NEXT: ; nop ; UNWIND-NEXT: ; sub sp, #624 -; UNWIND-NEXT: ; mov fp, sp -; UNWIND-NEXT: ; stp x19, x20, [sp, #32] -; UNWIND-NEXT: ; str x21, [sp, #24] -; UNWIND-NEXT: ; str x28, [sp, #16] -; UNWIND-NEXT: ; stp x29, x30, [sp, #-64]! +; UNWIND-NEXT: ; add fp, sp, #32 +; UNWIND-NEXT: ; stp x29, x30, [sp, #32] +; UNWIND-NEXT: ; str x28, [sp, #24] +; UNWIND-NEXT: ; str x21, [sp, #16] +; UNWIND-NEXT: ; stp x19, x20, [sp, #-64]! ; UNWIND-NEXT: ; end ; UNWIND: Function: ?catch$2@?0??func@@YAHXZ@4HA ; UNWIND: Prologue [ -; UNWIND-NEXT: ; stp x19, x20, [sp, #32] -; UNWIND-NEXT: ; str x21, [sp, #24] -; UNWIND-NEXT: ; str x28, [sp, #16] -; UNWIND-NEXT: ; stp x29, x30, [sp, #-48]! +; UNWIND-NEXT: ; stp x29, x30, [sp, #32] +; UNWIND-NEXT: ; str x28, [sp, #24] +; UNWIND-NEXT: ; str x21, [sp, #16] +; UNWIND-NEXT: ; stp x19, x20, [sp, #-48]! ; UNWIND-NEXT: ; end target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128" Index: llvm/test/CodeGen/AArch64/wineh_shrinkwrap.mir =================================================================== --- llvm/test/CodeGen/AArch64/wineh_shrinkwrap.mir +++ llvm/test/CodeGen/AArch64/wineh_shrinkwrap.mir @@ -9,7 +9,7 @@ # The same test gets shrink wrapped on Linux ARM64. # WIN64-LABEL: bb.0.entry: -# WIN64: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -4 +# WIN64: early-clobber $sp = frame-setup STRXpre killed $x19, $sp, -32 # WIN64-LABEL: bb.1: # WIN64-LABEL: bb.2.if.then: