diff options
Diffstat (limited to 'llvm/lib/CodeGen/PrologEpilogInserter.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/PrologEpilogInserter.cpp | 184 |
1 files changed, 143 insertions, 41 deletions
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 8d8a6126dad0..1a0f296d5fdc 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -55,10 +55,8 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -130,6 +128,7 @@ private: void replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &MF, int &SPAdj); void insertPrologEpilogCode(MachineFunction &MF); + void insertZeroCallUsedRegs(MachineFunction &MF); }; } // end anonymous namespace @@ -284,6 +283,9 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { assert(!Failed && "Invalid warn-stack-size fn attr value"); (void)Failed; } + if (MF.getFunction().hasFnAttribute(Attribute::SafeStack)) { + StackSize += MFI.getUnsafeStackSize(); + } if (StackSize > Threshold) { DiagnosticInfoStackSize DiagStackSize(F, StackSize, Threshold, DS_Warning); F.getContext().diagnose(DiagStackSize); @@ -837,8 +839,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { // Adjust 'Offset' to point to the end of last fixed sized preallocated // object. for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) { - if (MFI.getStackID(i) != - TargetStackID::Default) // Only allocate objects on the default stack. + // Only allocate objects on the default stack. + if (MFI.getStackID(i) != TargetStackID::Default) continue; int64_t FixedOff; @@ -855,47 +857,34 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { if (FixedOff > Offset) Offset = FixedOff; } + Align MaxAlign = MFI.getMaxAlign(); // First assign frame offsets to stack objects that are used to spill // callee saved registers. - if (StackGrowsDown && MaxCSFrameIndex >= MinCSFrameIndex) { - for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) { - if (MFI.getStackID(i) != - TargetStackID::Default) // Only allocate objects on the default stack. - continue; - - // If the stack grows down, we need to add the size to find the lowest - // address of the object. - Offset += MFI.getObjectSize(i); - - // Adjust to alignment boundary - Offset = alignTo(Offset, MFI.getObjectAlign(i), Skew); + if (MaxCSFrameIndex >= MinCSFrameIndex) { + for (unsigned i = 0; i <= MaxCSFrameIndex - MinCSFrameIndex; ++i) { + unsigned FrameIndex = + StackGrowsDown ? MinCSFrameIndex + i : MaxCSFrameIndex - i; - LLVM_DEBUG(dbgs() << "alloc FI(" << i << ") at SP[" << -Offset << "]\n"); - MFI.setObjectOffset(i, -Offset); // Set the computed offset - } - } else if (MaxCSFrameIndex >= MinCSFrameIndex) { - // Be careful about underflow in comparisons agains MinCSFrameIndex. - for (unsigned i = MaxCSFrameIndex; i != MinCSFrameIndex - 1; --i) { - if (MFI.getStackID(i) != - TargetStackID::Default) // Only allocate objects on the default stack. + // Only allocate objects on the default stack. + if (MFI.getStackID(FrameIndex) != TargetStackID::Default) continue; - if (MFI.isDeadObjectIndex(i)) + // TODO: should this just be if (MFI.isDeadObjectIndex(FrameIndex)) + if (!StackGrowsDown && MFI.isDeadObjectIndex(FrameIndex)) continue; - // Adjust to alignment boundary - Offset = alignTo(Offset, MFI.getObjectAlign(i), Skew); - - LLVM_DEBUG(dbgs() << "alloc FI(" << i << ") at SP[" << Offset << "]\n"); - MFI.setObjectOffset(i, Offset); - Offset += MFI.getObjectSize(i); + AdjustStackOffset(MFI, FrameIndex, StackGrowsDown, Offset, MaxAlign, + Skew); } } + assert(MaxAlign == MFI.getMaxAlign() && + "MFI.getMaxAlign should already account for all callee-saved " + "registers without a fixed stack slot"); + // FixedCSEnd is the stack offset to the end of the fixed and callee-save // stack area. int64_t FixedCSEnd = Offset; - Align MaxAlign = MFI.getMaxAlign(); // Make sure the special register scavenging spill slot is closest to the // incoming stack pointer if a frame pointer is required and is closer @@ -982,8 +971,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { continue; if (StackProtectorFI == (int)i || EHRegNodeFrameIndex == (int)i) continue; - if (MFI.getStackID(i) != - TargetStackID::Default) // Only allocate objects on the default stack. + // Only allocate objects on the default stack. + if (MFI.getStackID(i) != TargetStackID::Default) continue; switch (MFI.getObjectSSPLayout(i)) { @@ -1036,8 +1025,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { continue; if (ProtectedObjs.count(i)) continue; - if (MFI.getStackID(i) != - TargetStackID::Default) // Only allocate objects on the default stack. + // Only allocate objects on the default stack. + if (MFI.getStackID(i) != TargetStackID::Default) continue; // Add the objects that we need to allocate to our working set. @@ -1145,6 +1134,9 @@ void PEI::insertPrologEpilogCode(MachineFunction &MF) { for (MachineBasicBlock *RestoreBlock : RestoreBlocks) TFI.emitEpilogue(MF, *RestoreBlock); + // Zero call used registers before restoring callee-saved registers. + insertZeroCallUsedRegs(MF); + for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.inlineStackProbe(MF, *SaveBlock); @@ -1155,11 +1147,7 @@ void PEI::insertPrologEpilogCode(MachineFunction &MF) { if (MF.shouldSplitStack()) { for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForSegmentedStacks(MF, *SaveBlock); - // Record that there are split-stack functions, so we will emit a - // special section to tell the linker. - MF.getMMI().setHasSplitStack(true); - } else - MF.getMMI().setHasNosplitStack(true); + } // Emit additional code that is required to explicitly handle the stack in // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The @@ -1171,6 +1159,120 @@ void PEI::insertPrologEpilogCode(MachineFunction &MF) { TFI.adjustForHiPEPrologue(MF, *SaveBlock); } +/// insertZeroCallUsedRegs - Zero out call used registers. +void PEI::insertZeroCallUsedRegs(MachineFunction &MF) { + const Function &F = MF.getFunction(); + + if (!F.hasFnAttribute("zero-call-used-regs")) + return; + + using namespace ZeroCallUsedRegs; + + ZeroCallUsedRegsKind ZeroRegsKind = + StringSwitch<ZeroCallUsedRegsKind>( + F.getFnAttribute("zero-call-used-regs").getValueAsString()) + .Case("skip", ZeroCallUsedRegsKind::Skip) + .Case("used-gpr-arg", ZeroCallUsedRegsKind::UsedGPRArg) + .Case("used-gpr", ZeroCallUsedRegsKind::UsedGPR) + .Case("used-arg", ZeroCallUsedRegsKind::UsedArg) + .Case("used", ZeroCallUsedRegsKind::Used) + .Case("all-gpr-arg", ZeroCallUsedRegsKind::AllGPRArg) + .Case("all-gpr", ZeroCallUsedRegsKind::AllGPR) + .Case("all-arg", ZeroCallUsedRegsKind::AllArg) + .Case("all", ZeroCallUsedRegsKind::All); + + if (ZeroRegsKind == ZeroCallUsedRegsKind::Skip) + return; + + const bool OnlyGPR = static_cast<unsigned>(ZeroRegsKind) & ONLY_GPR; + const bool OnlyUsed = static_cast<unsigned>(ZeroRegsKind) & ONLY_USED; + const bool OnlyArg = static_cast<unsigned>(ZeroRegsKind) & ONLY_ARG; + + const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + const BitVector AllocatableSet(TRI.getAllocatableSet(MF)); + + // Mark all used registers. + BitVector UsedRegs(TRI.getNumRegs()); + if (OnlyUsed) + for (const MachineBasicBlock &MBB : MF) + for (const MachineInstr &MI : MBB) + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isReg()) + continue; + + MCRegister Reg = MO.getReg(); + if (AllocatableSet[Reg] && !MO.isImplicit() && + (MO.isDef() || MO.isUse())) + UsedRegs.set(Reg); + } + + BitVector RegsToZero(TRI.getNumRegs()); + for (MCRegister Reg : AllocatableSet.set_bits()) { + // Skip over fixed registers. + if (TRI.isFixedRegister(MF, Reg)) + continue; + + // Want only general purpose registers. + if (OnlyGPR && !TRI.isGeneralPurposeRegister(MF, Reg)) + continue; + + // Want only used registers. + if (OnlyUsed && !UsedRegs[Reg]) + continue; + + // Want only registers used for arguments. + if (OnlyArg && !TRI.isArgumentRegister(MF, Reg)) + continue; + + RegsToZero.set(Reg); + } + + // Don't clear registers that are live when leaving the function. + for (const MachineBasicBlock &MBB : MF) + for (const MachineInstr &MI : MBB.terminators()) { + if (!MI.isReturn()) + continue; + + for (const auto &MO : MI.operands()) { + if (!MO.isReg()) + continue; + + for (MCPhysReg SReg : TRI.sub_and_superregs_inclusive(MO.getReg())) + RegsToZero.reset(SReg); + } + } + + // Don't need to clear registers that are used/clobbered by terminating + // instructions. + for (const MachineBasicBlock &MBB : MF) { + if (!MBB.isReturnBlock()) + continue; + + MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator(); + for (MachineBasicBlock::const_iterator I = MBBI, E = MBB.end(); I != E; + ++I) { + for (const MachineOperand &MO : I->operands()) { + if (!MO.isReg()) + continue; + + for (const MCPhysReg &Reg : + TRI.sub_and_superregs_inclusive(MO.getReg())) + RegsToZero.reset(Reg); + } + } + } + + // Don't clear registers that are reset before exiting. + for (const CalleeSavedInfo &CSI : MF.getFrameInfo().getCalleeSavedInfo()) + for (MCRegister Reg : TRI.sub_and_superregs_inclusive(CSI.getReg())) + RegsToZero.reset(Reg); + + const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering(); + for (MachineBasicBlock &MBB : MF) + if (MBB.isReturnBlock()) + TFI.emitZeroCallUsedRegs(RegsToZero, MBB); +} + /// replaceFrameIndices - Replace all MO_FrameIndex operands with physical /// register references and actual offsets. void PEI::replaceFrameIndices(MachineFunction &MF) { |
