aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/PrologEpilogInserter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
commit145449b1e420787bb99721a429341fa6be3adfb6 (patch)
tree1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/CodeGen/PrologEpilogInserter.cpp
parentecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff)
Diffstat (limited to 'llvm/lib/CodeGen/PrologEpilogInserter.cpp')
-rw-r--r--llvm/lib/CodeGen/PrologEpilogInserter.cpp184
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) {