diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 6cf151c951b19..7f0ce7015d6dd 100644 --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -145,14 +145,6 @@ class MachineBasicBlock const BasicBlock *BB; int Number; - /// The call frame size on entry to this basic block due to call frame setup - /// instructions in a predecessor. This is usually zero, unless basic blocks - /// are split in the middle of a call sequence. - /// - /// This information is only maintained until PrologEpilogInserter eliminates - /// call frame pseudos. - unsigned CallFrameSize = 0; - MachineFunction *xParent; Instructions Insts; @@ -1215,11 +1207,6 @@ class MachineBasicBlock int getNumber() const { return Number; } void setNumber(int N) { Number = N; } - /// Return the call frame size on entry to this basic block. - unsigned getCallFrameSize() const { return CallFrameSize; } - /// Set the call frame size on entry to this basic block. - void setCallFrameSize(unsigned N) { CallFrameSize = N; } - /// Return the MCSymbol for this basic block. MCSymbol *getSymbol() const; diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 213b7ec6b3fbf..cdfdbc27fc6e4 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -26,6 +26,7 @@ class MachineFunction; class MachineBasicBlock; class BitVector; class AllocaInst; +class TargetInstrInfo; /// The CalleeSavedInfo class tracks the information need to locate where a /// callee saved register is in the current frame. @@ -846,6 +847,64 @@ class MachineFrameInfo { void dump(const MachineFunction &MF) const; }; +/// Computes and stores the call frame sizes at the entries and exits of +/// MachineBasicBlocks of a MachineFunction based on call frame setup and +/// destroy pseudo instructions. Usually, no call frame is open at block +/// boundaries, except if a call sequence has been split into multiple blocks. +/// Computing this information is deferred until it is queried. +/// +/// This class assumes that call frame instructions are placed properly, i.e., +/// every program path hits a frame destroy of equal size after hitting a frame +/// setup, and a frame setup of equal size before a frame destroy. Nested call +/// frame sequences are not allowed. +class MachineFrameSizeInfo { +public: + MachineFrameSizeInfo(MachineFunction &MF) : MF(MF) {} + + /// Get the call frame size just before MI. Contains no value if MI is not in + /// a call sequence. Zero-sized call frames are possible. + std::optional getCallFrameSizeAt(MachineInstr &MI); + + /// Get the call frame size just before MII. Contains no value if MII is not + /// in a call sequence. Zero-sized call frames are possible. + std::optional getCallFrameSizeAt(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MII); + + /// Get the call frame size at the entry of MBB. Contains no value if the + /// entry of MBB is not in a call sequence. Zero-sized call frames are + /// possible. Prefer this over getCallFrameSizeAt(MBB, MBB.begin()). + std::optional getCallFrameSizeAtBegin(MachineBasicBlock &MBB); + + /// Get the call frame size at the exit of MBB. Contains no value if the exit + /// of MBB is not in a call sequence. Zero-sized call frames are possible. + /// Prefer this over getCallFrameSizeAt(MBB, MBB.end()). + std::optional getCallFrameSizeAtEnd(MachineBasicBlock &MBB); + +private: + /// Stores the call frame sizes at the boundaries of a MachineBasicBlock. + struct MachineFrameSizeInfoForBB { + MachineFrameSizeInfoForBB() = default; + MachineFrameSizeInfoForBB(std::optional EntryVal, + std::optional ExitVal) + : Entry(EntryVal), Exit(ExitVal) {} + + std::optional Entry; + std::optional Exit; + }; + + /// Compute call frame sizes at the boundaries of each MachineBasicBlock. + void computeSizes(); + + MachineFunction &MF; + const TargetInstrInfo *TII; + unsigned FrameSetupOpcode = ~0u; + unsigned FrameDestroyOpcode = ~0u; + bool HasFrameOpcodes = false; + bool HasNoBrokenUpCallSeqs = false; + SmallVector State; + bool IsComputed = false; +}; + } // End llvm namespace #endif diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index 07b59b241d9f9..830bfcc7aaa4f 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -2265,9 +2265,6 @@ class TargetInstrInfo : public MCInstrInfo { return false; } - // Get the call frame size just before MI. - unsigned getCallFrameSizeAt(MachineInstr &MI) const; - /// Fills in the necessary MachineOperands to refer to a frame index. /// The best way to understand this is to print `asm(""::"m"(x));` after /// finalize-isel. Example: diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index 0809f88fde56b..a753aee9402fb 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -285,7 +285,6 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("ir-block-address-taken", MIToken::kw_ir_block_address_taken) .Case("machine-block-address-taken", MIToken::kw_machine_block_address_taken) - .Case("call-frame-size", MIToken::kw_call_frame_size) .Case("noconvergent", MIToken::kw_noconvergent) .Default(MIToken::Identifier); } diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 22547483a8a86..cd27d1a1c72b8 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -139,7 +139,6 @@ struct MIToken { kw_unknown_address, kw_ir_block_address_taken, kw_machine_block_address_taken, - kw_call_frame_size, kw_noconvergent, // Metadata types. diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 74f38e886a6b9..601af67aac75c 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -502,7 +502,6 @@ class MIParser { bool parseAddrspace(unsigned &Addrspace); bool parseSectionID(std::optional &SID); bool parseBBID(std::optional &BBID); - bool parseCallFrameSize(unsigned &CallFrameSize); bool parseOperandsOffset(MachineOperand &Op); bool parseIRValue(const Value *&V); bool parseMemoryOperandFlag(MachineMemOperand::Flags &Flags); @@ -684,18 +683,6 @@ bool MIParser::parseBBID(std::optional &BBID) { return false; } -// Parse basic block call frame size. -bool MIParser::parseCallFrameSize(unsigned &CallFrameSize) { - assert(Token.is(MIToken::kw_call_frame_size)); - lex(); - unsigned Value = 0; - if (getUnsigned(Value)) - return error("Unknown call frame size"); - CallFrameSize = Value; - lex(); - return false; -} - bool MIParser::parseBasicBlockDefinition( DenseMap &MBBSlots) { assert(Token.is(MIToken::MachineBasicBlockLabel)); @@ -713,7 +700,6 @@ bool MIParser::parseBasicBlockDefinition( std::optional SectionID; uint64_t Alignment = 0; std::optional BBID; - unsigned CallFrameSize = 0; BasicBlock *BB = nullptr; if (consumeIfPresent(MIToken::lparen)) { do { @@ -758,10 +744,6 @@ bool MIParser::parseBasicBlockDefinition( if (parseBBID(BBID)) return true; break; - case MIToken::kw_call_frame_size: - if (parseCallFrameSize(CallFrameSize)) - return true; - break; default: break; } @@ -799,7 +781,6 @@ bool MIParser::parseBasicBlockDefinition( MBB->setSectionID(*SectionID); MF.setBBSectionsType(BasicBlockSection::List); } - MBB->setCallFrameSize(CallFrameSize); return false; } diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp index 5d06af3ebf336..afa9827cda242 100644 --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -578,11 +578,6 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags, os << " " << getBBID()->CloneID; hasAttributes = true; } - if (CallFrameSize != 0) { - os << (hasAttributes ? ", " : " ("); - os << "call-frame-size " << CallFrameSize; - hasAttributes = true; - } } if (hasAttributes) @@ -1155,7 +1150,6 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge( MachineBasicBlock *PrevFallthrough = getNextNode(); MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(); - NMBB->setCallFrameSize(Succ->getCallFrameSize()); // Is there an indirect jump with jump table? bool ChangedIndirectJump = false; diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp index e4b993850f73d..1c4a8d52950a7 100644 --- a/llvm/lib/CodeGen/MachineFrameInfo.cpp +++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp @@ -13,6 +13,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetFrameLowering.h" @@ -23,6 +24,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include +#include #define DEBUG_TYPE "codegen" @@ -246,6 +248,152 @@ void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{ } } +std::optional +MachineFrameSizeInfo::getCallFrameSizeAt(MachineInstr &MI) { + return this->getCallFrameSizeAt(*MI.getParent(), MI.getIterator()); +} + +std::optional +MachineFrameSizeInfo::getCallFrameSizeAtBegin(MachineBasicBlock &MBB) { + if (!IsComputed) + computeSizes(); + if (HasNoBrokenUpCallSeqs || !HasFrameOpcodes) + return std::nullopt; + return State[MBB.getNumber()].Entry; +} + +std::optional +MachineFrameSizeInfo::getCallFrameSizeAtEnd(MachineBasicBlock &MBB) { + if (!IsComputed) + computeSizes(); + if (HasNoBrokenUpCallSeqs || !HasFrameOpcodes) + return std::nullopt; + return State[MBB.getNumber()].Exit; +} + +std::optional +MachineFrameSizeInfo::getCallFrameSizeAt(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MII) { + if (!IsComputed) + computeSizes(); + + if (!HasFrameOpcodes) + return std::nullopt; + + if (MII == MBB.end()) { + if (HasNoBrokenUpCallSeqs) + return std::nullopt; + return State[MBB.getNumber()].Exit; + } + + if (MII == MBB.begin()) { + if (HasNoBrokenUpCallSeqs) + return std::nullopt; + return State[MBB.getNumber()].Entry; + } + + // Search backwards from MI for the most recent call frame instruction. + for (auto &AdjI : reverse(make_range(MBB.begin(), MII))) { + if (AdjI.getOpcode() == FrameSetupOpcode) + return TII->getFrameTotalSize(AdjI); + if (AdjI.getOpcode() == FrameDestroyOpcode) + return std::nullopt; + } + + // If none was found, use the call frame size from the start of the basic + // block. + if (HasNoBrokenUpCallSeqs) + return std::nullopt; + return State[MBB.getNumber()].Entry; +} + +void MachineFrameSizeInfo::computeSizes() { + if (!IsComputed) { + // Populate fields that are only required once we compute the frame sizes. + TII = MF.getSubtarget().getInstrInfo(); + FrameSetupOpcode = TII->getCallFrameSetupOpcode(); + FrameDestroyOpcode = TII->getCallFrameDestroyOpcode(); + HasFrameOpcodes = FrameSetupOpcode != ~0u || FrameDestroyOpcode != ~0u; + assert(!HasFrameOpcodes || FrameSetupOpcode != FrameDestroyOpcode); + IsComputed = true; + } + // If the target has no call frame pseudo instructions, don't compute + // anything, we always return std::nullopt if queried. + if (!HasFrameOpcodes) + return; + + // Returns true if a call sequence in MF is broken up over multiple blocks. + auto FindBrokenUpCallSeq = [](const MachineFunction &MF, + unsigned FrameSetupOpcode, + unsigned FrameDestroyOpcode) { + for (const auto &MBB : MF) { + for (const auto &I : MBB) { + unsigned Opcode = I.getOpcode(); + if (Opcode == FrameSetupOpcode) + break; + if (Opcode == FrameDestroyOpcode) { + // A FrameDestroy without a preceeding FrameSetup in the MBB. If + // FrameInstructions are placed correctly (which we assume), this + // occurs if and only if a call sequence is broken into multiple + // blocks. + return true; + } + } + } + return false; + }; + + HasNoBrokenUpCallSeqs = + !FindBrokenUpCallSeq(MF, FrameSetupOpcode, FrameDestroyOpcode); + + // If every call sequence is limited to a single basic block, the frame sizes + // at entry and exit of each basic block need to be std::nullopt, so there is + // nothing to compute. + if (HasNoBrokenUpCallSeqs) + return; + + State.resize(MF.getNumBlockIDs()); + + df_iterator_default_set Reachable; + + // Visit the MBBs in DFS order. + for (df_ext_iterator> + DFI = df_ext_begin(&MF, Reachable), + DFE = df_ext_end(&MF, Reachable); + DFI != DFE; ++DFI) { + const MachineBasicBlock *MBB = *DFI; + + MachineFrameSizeInfoForBB BBState; + + // Use the exit state of the DFS stack predecessor as entry state for this + // block. With correctly placed call frame instructions, all other + // predecessors must have the same call frame size at exit. + if (DFI.getPathLength() >= 2) { + const MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); + assert(Reachable.count(StackPred) && + "DFS stack predecessor is already visited.\n"); + BBState.Entry = State[StackPred->getNumber()].Exit; + BBState.Exit = BBState.Entry; + } + + // Search backwards for the last call frame instruction and use its implied + // state for the block exit. Otherwise, the exit state remains equal to the + // entry state. + for (auto &AdjI : reverse(make_range(MBB->begin(), MBB->end()))) { + if (AdjI.getOpcode() == FrameSetupOpcode) { + BBState.Exit = TII->getFrameTotalSize(AdjI); + break; + } + if (AdjI.getOpcode() == FrameDestroyOpcode) { + BBState.Exit = std::nullopt; + break; + } + } + State[MBB->getNumber()] = BBState; + } +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MachineFrameInfo::dump(const MachineFunction &MF) const { print(MF, dbgs()); diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index b7218afdd3820..02c2b123481a5 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -3843,21 +3843,17 @@ void MachineVerifier::verifyLiveInterval(const LiveInterval &LI) { namespace { - // FrameSetup and FrameDestroy can have zero adjustment, so using a single - // integer, we can't tell whether it is a FrameSetup or FrameDestroy if the - // value is zero. - // We use a bool plus an integer to capture the stack state. +/// Store for each MachineBasicBlock the call frame size at its entry and its +/// exit. No value means that no call frame is open, zero means that a +/// zero-sized call frame is open. struct StackStateOfBB { StackStateOfBB() = default; - StackStateOfBB(int EntryVal, int ExitVal, bool EntrySetup, bool ExitSetup) - : EntryValue(EntryVal), ExitValue(ExitVal), EntryIsSetup(EntrySetup), - ExitIsSetup(ExitSetup) {} - - // Can be negative, which means we are setting up a frame. - int EntryValue = 0; - int ExitValue = 0; - bool EntryIsSetup = false; - bool ExitIsSetup = false; + StackStateOfBB(std::optional EntryVal, + std::optional ExitVal) + : Entry(EntryVal), Exit(ExitVal) {} + + std::optional Entry; + std::optional Exit; }; } // end anonymous namespace @@ -3866,19 +3862,20 @@ struct StackStateOfBB { /// by a FrameDestroy , stack adjustments are identical on all /// CFG edges to a merge point, and frame is destroyed at end of a return block. void MachineVerifier::verifyStackFrame() { - unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode(); + unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode(); unsigned FrameDestroyOpcode = TII->getCallFrameDestroyOpcode(); if (FrameSetupOpcode == ~0u && FrameDestroyOpcode == ~0u) return; SmallVector SPState; SPState.resize(MF->getNumBlockIDs()); - df_iterator_default_set Reachable; + df_iterator_default_set Reachable; // Visit the MBBs in DFS order. for (df_ext_iterator> - DFI = df_ext_begin(MF, Reachable), DFE = df_ext_end(MF, Reachable); + DFI = df_ext_begin(MF, Reachable), + DFE = df_ext_end(MF, Reachable); DFI != DFE; ++DFI) { const MachineBasicBlock *MBB = *DFI; @@ -3888,49 +3885,36 @@ void MachineVerifier::verifyStackFrame() { const MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); assert(Reachable.count(StackPred) && "DFS stack predecessor is already visited.\n"); - BBState.EntryValue = SPState[StackPred->getNumber()].ExitValue; - BBState.EntryIsSetup = SPState[StackPred->getNumber()].ExitIsSetup; - BBState.ExitValue = BBState.EntryValue; - BBState.ExitIsSetup = BBState.EntryIsSetup; - } - - if ((int)MBB->getCallFrameSize() != -BBState.EntryValue) { - report("Call frame size on entry does not match value computed from " - "predecessor", - MBB); - OS << "Call frame size on entry " << MBB->getCallFrameSize() - << " does not match value computed from predecessor " - << -BBState.EntryValue << '\n'; + BBState.Entry = SPState[StackPred->getNumber()].Exit; + BBState.Exit = BBState.Entry; } // Update stack state by checking contents of MBB. for (const auto &I : *MBB) { if (I.getOpcode() == FrameSetupOpcode) { - if (BBState.ExitIsSetup) + if (BBState.Exit.has_value()) report("FrameSetup is after another FrameSetup", &I); if (!MRI->isSSA() && !MF->getFrameInfo().adjustsStack()) report("AdjustsStack not set in presence of a frame pseudo " - "instruction.", &I); - BBState.ExitValue -= TII->getFrameTotalSize(I); - BBState.ExitIsSetup = true; + "instruction.", + &I); + BBState.Exit = TII->getFrameTotalSize(I); } if (I.getOpcode() == FrameDestroyOpcode) { - int Size = TII->getFrameTotalSize(I); - if (!BBState.ExitIsSetup) + int64_t Size = TII->getFrameTotalSize(I); + if (!BBState.Exit.has_value()) report("FrameDestroy is not after a FrameSetup", &I); - int AbsSPAdj = BBState.ExitValue < 0 ? -BBState.ExitValue : - BBState.ExitValue; - if (BBState.ExitIsSetup && AbsSPAdj != Size) { + else if ((int64_t)BBState.Exit.value() != Size) { report("FrameDestroy is after FrameSetup ", &I); OS << "FrameDestroy <" << Size << "> is after FrameSetup <" - << AbsSPAdj << ">.\n"; + << BBState.Exit.value() << ">.\n"; } if (!MRI->isSSA() && !MF->getFrameInfo().adjustsStack()) report("AdjustsStack not set in presence of a frame pseudo " - "instruction.", &I); - BBState.ExitValue += Size; - BBState.ExitIsSetup = false; + "instruction.", + &I); + BBState.Exit.reset(); } } SPState[MBB->getNumber()] = BBState; @@ -3939,14 +3923,12 @@ void MachineVerifier::verifyStackFrame() { // state. for (const MachineBasicBlock *Pred : MBB->predecessors()) { if (Reachable.count(Pred) && - (SPState[Pred->getNumber()].ExitValue != BBState.EntryValue || - SPState[Pred->getNumber()].ExitIsSetup != BBState.EntryIsSetup)) { + SPState[Pred->getNumber()].Exit != BBState.Entry) { report("The exit stack state of a predecessor is inconsistent.", MBB); - OS << "Predecessor " << printMBBReference(*Pred) << " has exit state (" - << SPState[Pred->getNumber()].ExitValue << ", " - << SPState[Pred->getNumber()].ExitIsSetup << "), while " - << printMBBReference(*MBB) << " has entry state (" - << BBState.EntryValue << ", " << BBState.EntryIsSetup << ").\n"; + OS << "Predecessor " << printMBBReference(*Pred) << " has exit state " + << SPState[Pred->getNumber()].Exit << ", while " + << printMBBReference(*MBB) << " has entry state " << BBState.Entry + << ".\n"; } } @@ -3954,23 +3936,19 @@ void MachineVerifier::verifyStackFrame() { // state. for (const MachineBasicBlock *Succ : MBB->successors()) { if (Reachable.count(Succ) && - (SPState[Succ->getNumber()].EntryValue != BBState.ExitValue || - SPState[Succ->getNumber()].EntryIsSetup != BBState.ExitIsSetup)) { + SPState[Succ->getNumber()].Entry != BBState.Exit) { report("The entry stack state of a successor is inconsistent.", MBB); - OS << "Successor " << printMBBReference(*Succ) << " has entry state (" - << SPState[Succ->getNumber()].EntryValue << ", " - << SPState[Succ->getNumber()].EntryIsSetup << "), while " - << printMBBReference(*MBB) << " has exit state (" - << BBState.ExitValue << ", " << BBState.ExitIsSetup << ").\n"; + OS << "Successor " << printMBBReference(*Succ) << " has entry state " + << SPState[Succ->getNumber()].Entry << ", while " + << printMBBReference(*MBB) << " has exit state " << BBState.Exit + << ".\n"; } } // Make sure a basic block with return ends with zero stack adjustment. if (!MBB->empty() && MBB->back().isReturn()) { - if (BBState.ExitIsSetup) + if (BBState.Exit.has_value()) report("A return block ends with a FrameSetup.", MBB); - if (BBState.ExitValue) - report("A return block ends with a nonzero stack adjustment.", MBB); } } } diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index ee03eaa8ae527..7548d87d45d86 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -390,11 +390,6 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) { // need to track the SP adjustment for frame index elimination. for (MachineBasicBlock::iterator I : FrameSDOps) TFI->eliminateCallFramePseudoInstr(MF, *I->getParent(), I); - - // We can't track the call frame size after call frame pseudos have been - // eliminated. Set it to zero everywhere to keep MachineVerifier happy. - for (MachineBasicBlock &MBB : MF) - MBB.setCallFrameSize(0); } } @@ -1343,27 +1338,14 @@ void PEI::insertZeroCallUsedRegs(MachineFunction &MF) { /// offsets. void PEI::replaceFrameIndicesBackward(MachineFunction &MF) { const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering(); + MachineFrameSizeInfo MFSI(MF); for (auto &MBB : MF) { - int SPAdj = 0; - if (!MBB.succ_empty()) { - // Get the SP adjustment for the end of MBB from the start of any of its - // successors. They should all be the same. - assert(all_of(MBB.successors(), [&MBB](const MachineBasicBlock *Succ) { - return Succ->getCallFrameSize() == - (*MBB.succ_begin())->getCallFrameSize(); - })); - const MachineBasicBlock &FirstSucc = **MBB.succ_begin(); - SPAdj = TFI.alignSPAdjust(FirstSucc.getCallFrameSize()); - if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp) - SPAdj = -SPAdj; - } + int SPAdj = TFI.alignSPAdjust(MFSI.getCallFrameSizeAtEnd(MBB).value_or(0)); + if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp) + SPAdj = -SPAdj; replaceFrameIndicesBackward(&MBB, MF, SPAdj); - - // We can't track the call frame size after call frame pseudos have been - // eliminated. Set it to zero everywhere to keep MachineVerifier happy. - MBB.setCallFrameSize(0); } } @@ -1371,17 +1353,15 @@ void PEI::replaceFrameIndicesBackward(MachineFunction &MF) { /// register references and actual offsets. void PEI::replaceFrameIndices(MachineFunction &MF) { const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering(); + MachineFrameSizeInfo MFSI(MF); for (auto &MBB : MF) { - int SPAdj = TFI.alignSPAdjust(MBB.getCallFrameSize()); + int SPAdj = + TFI.alignSPAdjust(MFSI.getCallFrameSizeAtBegin(MBB).value_or(0)); if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp) SPAdj = -SPAdj; replaceFrameIndices(&MBB, MF, SPAdj); - - // We can't track the call frame size after call frame pseudos have been - // eliminated. Set it to zero everywhere to keep MachineVerifier happy. - MBB.setCallFrameSize(0); } } diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp index 38bd0b0ba4114..0f86c9e19ccf4 100644 --- a/llvm/lib/CodeGen/TargetInstrInfo.cpp +++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -13,6 +13,7 @@ #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineCombinerPattern.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -1624,22 +1625,6 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI, return std::nullopt; } -// Get the call frame size just before MI. -unsigned TargetInstrInfo::getCallFrameSizeAt(MachineInstr &MI) const { - // Search backwards from MI for the most recent call frame instruction. - MachineBasicBlock *MBB = MI.getParent(); - for (auto &AdjI : reverse(make_range(MBB->instr_begin(), MI.getIterator()))) { - if (AdjI.getOpcode() == getCallFrameSetupOpcode()) - return getFrameTotalSize(AdjI); - if (AdjI.getOpcode() == getCallFrameDestroyOpcode()) - return 0; - } - - // If none was found, use the call frame size from the start of the basic - // block. - return MBB->getCallFrameSize(); -} - /// Both DefMI and UseMI must be valid. By default, call directly to the /// itinerary. This may be overriden by the target. std::optional TargetInstrInfo::getOperandLatency( diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index bf757edfa8589..3ef84bf88539c 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -11580,11 +11580,6 @@ ARMTargetLowering::EmitStructByval(MachineInstr &MI, MF->insert(It, loopMBB); MF->insert(It, exitMBB); - // Set the call frame size on entry to the new basic blocks. - unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); - loopMBB->setCallFrameSize(CallFrameSize); - exitMBB->setCallFrameSize(CallFrameSize); - // Transfer the remainder of BB and its successor edges to exitMBB. exitMBB->splice(exitMBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), BB->end()); @@ -12181,11 +12176,6 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, F->insert(It, copy0MBB); F->insert(It, sinkMBB); - // Set the call frame size on entry to the new basic blocks. - unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); - copy0MBB->setCallFrameSize(CallFrameSize); - sinkMBB->setCallFrameSize(CallFrameSize); - // Check whether CPSR is live past the tMOVCCr_pseudo. const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); if (!MI.killsRegister(ARM::CPSR, /*TRI=*/nullptr) && diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index 0046e757f4efa..f6e66b21279d1 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -2423,11 +2423,6 @@ AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MF->insert(I, trueMBB); MF->insert(I, falseMBB); - // Set the call frame size on entry to the new basic blocks. - unsigned CallFrameSize = TII.getCallFrameSizeAt(MI); - trueMBB->setCallFrameSize(CallFrameSize); - falseMBB->setCallFrameSize(CallFrameSize); - // Transfer remaining instructions and all successors of the current // block to the block which will contain the Phi node for the // select. diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp index 316a6eebc2db0..b95edc21f0f42 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -3198,11 +3198,6 @@ M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI, F->insert(It, Copy0MBB); F->insert(It, SinkMBB); - // Set the call frame size on entry to the new basic blocks. - unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); - Copy0MBB->setCallFrameSize(CallFrameSize); - SinkMBB->setCallFrameSize(CallFrameSize); - // If the CCR register isn't dead in the terminator, then claim that it's // live into the sink and copy blocks. const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index d9847a21489e6..d3b581b00b93c 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -13149,12 +13149,6 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, F->insert(It, copy0MBB); F->insert(It, sinkMBB); - // Set the call frame size on entry to the new basic blocks. - // See https://reviews.llvm.org/D156113. - unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); - copy0MBB->setCallFrameSize(CallFrameSize); - sinkMBB->setCallFrameSize(CallFrameSize); - // Transfer the remainder of BB and its successor edges to sinkMBB. sinkMBB->splice(sinkMBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), BB->end()); diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 01fa418e4dbdf..f86b830b6a0d6 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -18598,11 +18598,6 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI, F->insert(I, IfFalseMBB); F->insert(I, TailMBB); - // Set the call frame size on entry to the new basic blocks. - unsigned CallFrameSize = TII.getCallFrameSizeAt(*LastSelectPseudo); - IfFalseMBB->setCallFrameSize(CallFrameSize); - TailMBB->setCallFrameSize(CallFrameSize); - // Transfer debug instructions associated with the selects to TailMBB. for (MachineInstr *DebugInstr : SelectDebugValues) { TailMBB->push_back(DebugInstr->removeFromParent()); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 77c10baa31bd2..aca4d29549e9e 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -35646,11 +35646,6 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr &MI, F->insert(It, FalseMBB); F->insert(It, SinkMBB); - // Set the call frame size on entry to the new basic blocks. - unsigned CallFrameSize = TII->getCallFrameSizeAt(MI); - FalseMBB->setCallFrameSize(CallFrameSize); - SinkMBB->setCallFrameSize(CallFrameSize); - // If the EFLAGS register isn't dead in the terminator, then claim that it's // live into the sink and copy blocks. const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); diff --git a/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir b/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir index b4bbb9be8ae40..b0e942fdf503d 100644 --- a/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir +++ b/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir @@ -123,7 +123,7 @@ body: | %61:gpr = COPY killed %29 %62:gpr = COPY killed %4 %63:gpr = COPY killed %27 - bb.2 (call-frame-size 72): + bb.2: %35:gpr = COPY killed %63 %33:gpr = COPY killed %62 %31:gpr = COPY killed %61 @@ -136,7 +136,7 @@ body: | %62:gpr = COPY killed %32 %63:gpr = COPY killed %34 Bcc %bb.2, 1, killed $cpsr - bb.3 (call-frame-size 72): + bb.3: successors: %28:gpr = ADDri %stack.1.jb1, 0, 14, $noreg, $noreg $r0 = COPY killed %28 diff --git a/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir b/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir index d3e87120693cf..81b497db626c5 100644 --- a/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir +++ b/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir @@ -11,7 +11,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: ADJCALLSTACKDOWN 100, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: bb.1 (call-frame-size 100): + ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: %bb.2(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: ADJCALLSTACKUP 100, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp @@ -19,7 +19,29 @@ body: | ; CHECK-NEXT: bb.2: bb.0: ADJCALLSTACKDOWN 100, 0, 14, $noreg, implicit-def $sp, implicit $sp - bb.1 (call-frame-size 100): + bb.1: ADJCALLSTACKUP 100, 0, 14, $noreg, implicit-def $sp, implicit $sp bb.2: ... + +--- +name: callframesizezero +body: | + ; CHECK-LABEL: name: callframesizezero + ; CHECK: bb.0: + ; CHECK-NEXT: successors: %bb.1(0x80000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: successors: %bb.2(0x80000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2: + bb.0: + ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp + bb.1: + ADJCALLSTACKUP 0, 0, 14, $noreg, implicit-def $sp, implicit $sp + bb.2: +... diff --git a/llvm/test/CodeGen/RISCV/pr97304.ll b/llvm/test/CodeGen/RISCV/pr97304.ll index 694f6384b6855..6016f4149dd96 100644 --- a/llvm/test/CodeGen/RISCV/pr97304.ll +++ b/llvm/test/CodeGen/RISCV/pr97304.ll @@ -22,10 +22,10 @@ define i32 @_ZNK2cv12LMSolverImpl3runERKNS_17_InputOutputArrayE(i1 %cmp436) { ; CHECK-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI $x0, 32 ; CHECK-NEXT: BNE [[ANDI]], $x0, %bb.3 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: bb.2.for.cond (call-frame-size 8): + ; CHECK-NEXT: bb.2.for.cond: ; CHECK-NEXT: successors: %bb.3(0x80000000) ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: bb.3.for.cond (call-frame-size 8): + ; CHECK-NEXT: bb.3.for.cond: ; CHECK-NEXT: successors: %bb.1(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[PHI:%[0-9]+]]:gpr = PHI [[ADDI1]], %bb.1, [[ADDI]], %bb.2 diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp index 5f6a22cb3a974..e79c824f37e4c 100644 --- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp +++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp @@ -249,8 +249,6 @@ static std::unique_ptr cloneMF(MachineFunction *SrcMF, DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock()); Src2DstMBB[&SrcMBB] = DstMBB; - DstMBB->setCallFrameSize(SrcMBB.getCallFrameSize()); - if (SrcMBB.isIRBlockAddressTaken()) DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock()); if (SrcMBB.isMachineBlockAddressTaken())