Index: lib/Target/X86/X86FrameLowering.h =================================================================== --- lib/Target/X86/X86FrameLowering.h +++ lib/Target/X86/X86FrameLowering.h @@ -171,6 +171,10 @@ unsigned getInitialCFARegister(const MachineFunction &MF) const override; + /// Return true if the function has a redzone (accessible bytes past the + /// frame of the top of stack function) as part of it's ABI. + bool has128ByteRedZone(const MachineFunction& MF) const; + private: uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -872,6 +872,17 @@ MI->getOperand(3).setIsDead(); } +bool X86FrameLowering::has128ByteRedZone(const MachineFunction& MF) const { + // x86-64 (non Win64) has a 128 byte red zone which is guaranteed not to be + // clobbered by any interrupt handler. + assert(&STI == &MF.getSubtarget() && + "MF used frame lowering for wrong subtarget"); + const Function &Fn = MF.getFunction(); + const bool IsWin64CC = STI.isCallingConvWin64(Fn.getCallingConv()); + return Is64Bit && !IsWin64CC && !Fn.hasFnAttribute(Attribute::NoRedZone); +} + + /// emitPrologue - Push callee-saved registers onto the stack, which /// automatically adjust the stack pointer. Adjust the stack pointer to allocate /// space for local variables. Also emit labels used by the exception handler to @@ -976,7 +987,6 @@ MF.hasEHFunclets() && Personality == EHPersonality::CoreCLR; bool IsClrFunclet = IsFunclet && FnHasClrFunclet; bool HasFP = hasFP(MF); - bool IsWin64CC = STI.isCallingConvWin64(Fn.getCallingConv()); bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); bool NeedsWin64CFI = IsWin64Prologue && Fn.needsUnwindTableEntry(); // FIXME: Emit FPO data for EH funclets. @@ -1030,12 +1040,11 @@ // pointer, calls, or dynamic alloca then we do not need to adjust the // stack pointer (we fit in the Red Zone). We also check that we don't // push and pop from the stack. - if (Is64Bit && !Fn.hasFnAttribute(Attribute::NoRedZone) && + if (has128ByteRedZone(MF) && !TRI->needsStackRealignment(MF) && !MFI.hasVarSizedObjects() && // No dynamic alloca. !MFI.adjustsStack() && // No calls. !UseStackProbe && // No stack probes. - !IsWin64CC && // Win64 has no Red Zone !MFI.hasCopyImplyingStackAdjustment() && // Don't push and pop. !MF.shouldSplitStack()) { // Regular stack uint64_t MinSize = X86FI->getCalleeSavedFrameSize(); Index: lib/Target/X86/X86InstrInfo.cpp =================================================================== --- lib/Target/X86/X86InstrInfo.cpp +++ lib/Target/X86/X86InstrInfo.cpp @@ -7464,7 +7464,7 @@ // Does the function use a red zone? If it does, then we can't risk messing // with the stack. - if (!F.hasFnAttribute(Attribute::NoRedZone)) { + if (Subtarget.getFrameLowering()->has128ByteRedZone(MF)) { // It could have a red zone. If it does, then we don't want to touch it. const X86MachineFunctionInfo *X86FI = MF.getInfo(); if (!X86FI || X86FI->getUsesRedZone()) Index: lib/Target/X86/X86SpeculativeLoadHardening.cpp =================================================================== --- lib/Target/X86/X86SpeculativeLoadHardening.cpp +++ lib/Target/X86/X86SpeculativeLoadHardening.cpp @@ -2465,7 +2465,7 @@ // If we have no red zones or if the function returns twice (possibly without // using the `ret` instruction) like setjmp, we need to save the expected // return address prior to the call. - if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone) || + if (!Subtarget->getFrameLowering()->has128ByteRedZone(MF) || MF.exposesReturnsTwice()) { // If we don't have red zones, we need to compute the expected return // address prior to the call and store it in a register that lives across