[llvm] [CodeGen] Distinguish zero-sized call frames from no call frame in MachineBB (PR #106964)

Fabian Ritter via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 10 03:15:57 PDT 2024


https://github.com/ritter-x2a updated https://github.com/llvm/llvm-project/pull/106964

>From 4f9d1e742124210728b5656ff0378fd2a2e2961d Mon Sep 17 00:00:00 2001
From: Fabian Ritter <fabian.ritter at amd.com>
Date: Mon, 2 Sep 2024 05:33:07 -0400
Subject: [PATCH 1/5] [CodeGen] Distinguish zero-sized call frames from no call
 frame in MachineBB

Call frames can be zero-sized. Distinguishing between instructions in a
zero-sized call frame and instructions outside of call frames via the
call frame size info stored in the MachineBBs is helpful to avoid nested
CALLSEQs (which are illegal and cause machine verifier errors).

This patch uses std::optional<unsigned> instead of unsigned to represent
call frame sizes. Locations outside of call frames are marked with
std::nullopt whereas locations in zero-sized call-frames are represented
with a std::optional that contains 0.
---
 llvm/include/llvm/CodeGen/MachineBasicBlock.h | 19 +++++++++++-----
 llvm/include/llvm/CodeGen/TargetInstrInfo.h   |  5 +++--
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       |  6 ++---
 llvm/lib/CodeGen/MachineBasicBlock.cpp        |  4 ++--
 llvm/lib/CodeGen/MachineVerifier.cpp          |  4 ++--
 llvm/lib/CodeGen/PrologEpilogInserter.cpp     | 20 ++++++++---------
 llvm/lib/CodeGen/TargetInstrInfo.cpp          |  6 ++---
 llvm/lib/Target/ARM/ARMISelLowering.cpp       |  4 ++--
 llvm/lib/Target/AVR/AVRISelLowering.cpp       |  2 +-
 llvm/lib/Target/M68k/M68kISelLowering.cpp     |  2 +-
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  2 +-
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |  3 ++-
 llvm/lib/Target/X86/X86ISelLowering.cpp       |  2 +-
 llvm/test/CodeGen/MIR/ARM/call-frame-size.mir | 22 +++++++++++++++++++
 14 files changed, 67 insertions(+), 34 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 6cf151c951b19f..4db1e0b60f87e3 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -146,12 +146,13 @@ class MachineBasicBlock
   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.
+  /// instructions in a predecessor. Usually does not contain a value, unless
+  /// basic blocks are split in the middle of a call sequence. Zero-sized call
+  /// frames are possible.
   ///
   /// This information is only maintained until PrologEpilogInserter eliminates
   /// call frame pseudos.
-  unsigned CallFrameSize = 0;
+  std::optional<unsigned> CallFrameSize;
 
   MachineFunction *xParent;
   Instructions Insts;
@@ -1216,9 +1217,17 @@ class MachineBasicBlock
   void setNumber(int N) { Number = N; }
 
   /// Return the call frame size on entry to this basic block.
-  unsigned getCallFrameSize() const { return CallFrameSize; }
+  std::optional<unsigned> getCallFrameSize() const { return CallFrameSize; }
+
+  /// Return the call frame size on entry to this basic block if it is part of a
+  /// call sequence and 0 otherwise.
+  unsigned getCallFrameSizeOrZero() const { return CallFrameSize.value_or(0); }
+
   /// Set the call frame size on entry to this basic block.
-  void setCallFrameSize(unsigned N) { CallFrameSize = N; }
+  void setCallFrameSize(std::optional<unsigned> N) { CallFrameSize = N; }
+
+  /// Reset the stored call frame size.
+  void clearCallFrameSize() { CallFrameSize.reset(); }
 
   /// Return the MCSymbol for this basic block.
   MCSymbol *getSymbol() const;
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 07b59b241d9f9a..29dc45c1ba2f8b 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2265,8 +2265,9 @@ class TargetInstrInfo : public MCInstrInfo {
     return false;
   }
 
-  // Get the call frame size just before MI.
-  unsigned getCallFrameSizeAt(MachineInstr &MI) const;
+  /// 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<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
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 74f38e886a6b97..08e106b743276d 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -502,7 +502,7 @@ class MIParser {
   bool parseAddrspace(unsigned &Addrspace);
   bool parseSectionID(std::optional<MBBSectionID> &SID);
   bool parseBBID(std::optional<UniqueBBID> &BBID);
-  bool parseCallFrameSize(unsigned &CallFrameSize);
+  bool parseCallFrameSize(std::optional<unsigned> &CallFrameSize);
   bool parseOperandsOffset(MachineOperand &Op);
   bool parseIRValue(const Value *&V);
   bool parseMemoryOperandFlag(MachineMemOperand::Flags &Flags);
@@ -685,7 +685,7 @@ bool MIParser::parseBBID(std::optional<UniqueBBID> &BBID) {
 }
 
 // Parse basic block call frame size.
-bool MIParser::parseCallFrameSize(unsigned &CallFrameSize) {
+bool MIParser::parseCallFrameSize(std::optional<unsigned> &CallFrameSize) {
   assert(Token.is(MIToken::kw_call_frame_size));
   lex();
   unsigned Value = 0;
@@ -713,7 +713,7 @@ bool MIParser::parseBasicBlockDefinition(
   std::optional<MBBSectionID> SectionID;
   uint64_t Alignment = 0;
   std::optional<UniqueBBID> BBID;
-  unsigned CallFrameSize = 0;
+  std::optional<unsigned> CallFrameSize;
   BasicBlock *BB = nullptr;
   if (consumeIfPresent(MIToken::lparen)) {
     do {
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 5d06af3ebf3360..a948efb41d7152 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -578,9 +578,9 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
         os << " " << getBBID()->CloneID;
       hasAttributes = true;
     }
-    if (CallFrameSize != 0) {
+    if (CallFrameSize.has_value()) {
       os << (hasAttributes ? ", " : " (");
-      os << "call-frame-size " << CallFrameSize;
+      os << "call-frame-size " << CallFrameSize.value();
       hasAttributes = true;
     }
   }
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index b7218afdd38206..d8f4c3ed6fc9ed 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -3894,11 +3894,11 @@ void MachineVerifier::verifyStackFrame() {
       BBState.ExitIsSetup = BBState.EntryIsSetup;
     }
 
-    if ((int)MBB->getCallFrameSize() != -BBState.EntryValue) {
+    if ((int)MBB->getCallFrameSizeOrZero() != -BBState.EntryValue) {
       report("Call frame size on entry does not match value computed from "
              "predecessor",
              MBB);
-      OS << "Call frame size on entry " << MBB->getCallFrameSize()
+      OS << "Call frame size on entry " << MBB->getCallFrameSizeOrZero()
          << " does not match value computed from predecessor "
          << -BBState.EntryValue << '\n';
     }
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index ee03eaa8ae527c..b2f355c0aa8ccf 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -392,9 +392,9 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) {
       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.
+    // eliminated. Clear it everywhere to keep MachineVerifier happy.
     for (MachineBasicBlock &MBB : MF)
-      MBB.setCallFrameSize(0);
+      MBB.clearCallFrameSize();
   }
 }
 
@@ -1350,11 +1350,11 @@ void PEI::replaceFrameIndicesBackward(MachineFunction &MF) {
       // 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();
+        return Succ->getCallFrameSizeOrZero() ==
+               (*MBB.succ_begin())->getCallFrameSizeOrZero();
       }));
       const MachineBasicBlock &FirstSucc = **MBB.succ_begin();
-      SPAdj = TFI.alignSPAdjust(FirstSucc.getCallFrameSize());
+      SPAdj = TFI.alignSPAdjust(FirstSucc.getCallFrameSizeOrZero());
       if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
         SPAdj = -SPAdj;
     }
@@ -1362,8 +1362,8 @@ void PEI::replaceFrameIndicesBackward(MachineFunction &MF) {
     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);
+    // eliminated. Clear it everywhere to keep MachineVerifier happy.
+    MBB.clearCallFrameSize();
   }
 }
 
@@ -1373,15 +1373,15 @@ void PEI::replaceFrameIndices(MachineFunction &MF) {
   const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
 
   for (auto &MBB : MF) {
-    int SPAdj = TFI.alignSPAdjust(MBB.getCallFrameSize());
+    int SPAdj = TFI.alignSPAdjust(MBB.getCallFrameSizeOrZero());
     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);
+    // eliminated. Clear it everywhere to keep MachineVerifier happy.
+    MBB.clearCallFrameSize();
   }
 }
 
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 38bd0b0ba4114c..f623ba0352de8b 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -1624,15 +1624,15 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
   return std::nullopt;
 }
 
-// Get the call frame size just before MI.
-unsigned TargetInstrInfo::getCallFrameSizeAt(MachineInstr &MI) const {
+std::optional<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;
+      return std::nullopt;
   }
 
   // If none was found, use the call frame size from the start of the basic
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index bf757edfa85890..aedb9646ba6dea 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -11581,7 +11581,7 @@ ARMTargetLowering::EmitStructByval(MachineInstr &MI,
   MF->insert(It, exitMBB);
 
   // Set the call frame size on entry to the new basic blocks.
-  unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
+  std::optional<unsigned> CallFrameSize = TII->getCallFrameSizeAt(MI);
   loopMBB->setCallFrameSize(CallFrameSize);
   exitMBB->setCallFrameSize(CallFrameSize);
 
@@ -12182,7 +12182,7 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     F->insert(It, sinkMBB);
 
     // Set the call frame size on entry to the new basic blocks.
-    unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
+    std::optional<unsigned> CallFrameSize = TII->getCallFrameSizeAt(MI);
     copy0MBB->setCallFrameSize(CallFrameSize);
     sinkMBB->setCallFrameSize(CallFrameSize);
 
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index 0046e757f4efa2..cf6f026869da80 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -2424,7 +2424,7 @@ AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
   MF->insert(I, falseMBB);
 
   // Set the call frame size on entry to the new basic blocks.
-  unsigned CallFrameSize = TII.getCallFrameSizeAt(MI);
+  std::optional<unsigned> CallFrameSize = TII.getCallFrameSizeAt(MI);
   trueMBB->setCallFrameSize(CallFrameSize);
   falseMBB->setCallFrameSize(CallFrameSize);
 
diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp
index 316a6eebc2db0f..3b0a0c83d94d16 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.cpp
+++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp
@@ -3199,7 +3199,7 @@ M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI,
   F->insert(It, SinkMBB);
 
   // Set the call frame size on entry to the new basic blocks.
-  unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
+  std::optional<unsigned> CallFrameSize = TII->getCallFrameSizeAt(MI);
   Copy0MBB->setCallFrameSize(CallFrameSize);
   SinkMBB->setCallFrameSize(CallFrameSize);
 
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index d9847a21489e63..77adfadb342388 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -13151,7 +13151,7 @@ PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
 
     // Set the call frame size on entry to the new basic blocks.
     // See https://reviews.llvm.org/D156113.
-    unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
+    std::optional<unsigned> CallFrameSize = TII->getCallFrameSizeAt(MI);
     copy0MBB->setCallFrameSize(CallFrameSize);
     sinkMBB->setCallFrameSize(CallFrameSize);
 
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 01fa418e4dbdf4..b0c1605be2fcb1 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -18599,7 +18599,8 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
   F->insert(I, TailMBB);
 
   // Set the call frame size on entry to the new basic blocks.
-  unsigned CallFrameSize = TII.getCallFrameSizeAt(*LastSelectPseudo);
+  std::optional<unsigned> CallFrameSize =
+      TII.getCallFrameSizeAt(*LastSelectPseudo);
   IfFalseMBB->setCallFrameSize(CallFrameSize);
   TailMBB->setCallFrameSize(CallFrameSize);
 
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 77c10baa31bd21..aa8e68910b7f3f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -35647,7 +35647,7 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr &MI,
   F->insert(It, SinkMBB);
 
   // Set the call frame size on entry to the new basic blocks.
-  unsigned CallFrameSize = TII->getCallFrameSizeAt(MI);
+  std::optional<unsigned> CallFrameSize = TII->getCallFrameSizeAt(MI);
   FalseMBB->setCallFrameSize(CallFrameSize);
   SinkMBB->setCallFrameSize(CallFrameSize);
 
diff --git a/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir b/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir
index d3e87120693cf3..58e7f50e583455 100644
--- a/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir
+++ b/llvm/test/CodeGen/MIR/ARM/call-frame-size.mir
@@ -23,3 +23,25 @@ body: |
     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 (call-frame-size 0):
+  ; 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 (call-frame-size 0):
+    ADJCALLSTACKUP 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
+  bb.2:
+...

>From e79cba6e6b13b70ed69aafe9525a846598175931 Mon Sep 17 00:00:00 2001
From: Fabian Ritter <fabian.ritter at amd.com>
Date: Thu, 5 Sep 2024 04:34:26 -0400
Subject: [PATCH 2/5] Use std::optional in the MachineVerifier to distinguish
 zero-sized from no call frames.

---
 llvm/lib/CodeGen/MachineVerifier.cpp | 95 ++++++++++++----------------
 1 file changed, 41 insertions(+), 54 deletions(-)

diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index d8f4c3ed6fc9ed..cdcd78225c7e12 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<unsigned> EntryVal,
+                 std::optional<unsigned> ExitVal)
+      : Entry(EntryVal), Exit(ExitVal) {}
+
+  std::optional<unsigned> Entry;
+  std::optional<unsigned> Exit;
 };
 
 } // end anonymous namespace
@@ -3866,19 +3862,20 @@ struct StackStateOfBB {
 /// by a FrameDestroy <n>, 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<StackStateOfBB, 8> SPState;
   SPState.resize(MF->getNumBlockIDs());
-  df_iterator_default_set<const MachineBasicBlock*> Reachable;
+  df_iterator_default_set<const MachineBasicBlock *> Reachable;
 
   // Visit the MBBs in DFS order.
   for (df_ext_iterator<const MachineFunction *,
                        df_iterator_default_set<const MachineBasicBlock *>>
-       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,45 @@ 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;
+      BBState.Entry = SPState[StackPred->getNumber()].Exit;
+      BBState.Exit = BBState.Entry;
     }
 
-    if ((int)MBB->getCallFrameSizeOrZero() != -BBState.EntryValue) {
+    if (MBB->getCallFrameSize() != BBState.Entry) {
       report("Call frame size on entry does not match value computed from "
              "predecessor",
              MBB);
-      OS << "Call frame size on entry " << MBB->getCallFrameSizeOrZero()
-         << " does not match value computed from predecessor "
-         << -BBState.EntryValue << '\n';
+      OS << "Call frame size on entry " << MBB->getCallFrameSize()
+         << " does not match value computed from predecessor " << BBState.Entry
+         << '\n';
     }
 
     // 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 <n> is after FrameSetup <m>", &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 +3932,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 +3945,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);
     }
   }
 }

>From 6019707973674efdf0cb047b06aefe4e709e1194 Mon Sep 17 00:00:00 2001
From: Fabian Ritter <fabian.ritter at amd.com>
Date: Thu, 5 Sep 2024 04:36:25 -0400
Subject: [PATCH 3/5] Catch some cases where the call frame size stored in
 MachineBasicBlocks was not set or updated.

---
 llvm/include/llvm/CodeGen/TargetInstrInfo.h   |  6 +++++
 llvm/lib/CodeGen/TargetInstrInfo.cpp          | 12 ++++++---
 .../Target/AMDGPU/AMDGPURegisterBankInfo.cpp  |  9 +++++++
 llvm/lib/Target/X86/X86FrameLowering.cpp      | 26 +++++++++++++++++++
 llvm/lib/Target/X86/X86ISelLowering.cpp       | 10 +++++++
 5 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 29dc45c1ba2f8b..276a4f08576061 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2269,6 +2269,12 @@ class TargetInstrInfo : public MCInstrInfo {
   /// a call sequence. Zero-sized call frames are possible.
   std::optional<unsigned> getCallFrameSizeAt(MachineInstr &MI) const;
 
+  /// 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<unsigned>
+  getCallFrameSizeAt(MachineBasicBlock &MBB,
+                     MachineBasicBlock::iterator MII) 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/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index f623ba0352de8b..9318e684fffd96 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"
@@ -1626,9 +1627,14 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
 
 std::optional<unsigned>
 TargetInstrInfo::getCallFrameSizeAt(MachineInstr &MI) const {
+  return this->getCallFrameSizeAt(*MI.getParent(), MI.getIterator());
+}
+
+std::optional<unsigned>
+TargetInstrInfo::getCallFrameSizeAt(MachineBasicBlock &MBB,
+                                    MachineBasicBlock::iterator MII) 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()))) {
+  for (auto &AdjI : reverse(make_range(MBB.begin(), MII))) {
     if (AdjI.getOpcode() == getCallFrameSetupOpcode())
       return getFrameTotalSize(AdjI);
     if (AdjI.getOpcode() == getCallFrameDestroyOpcode())
@@ -1637,7 +1643,7 @@ TargetInstrInfo::getCallFrameSizeAt(MachineInstr &MI) const {
 
   // If none was found, use the call frame size from the start of the basic
   // block.
-  return MBB->getCallFrameSize();
+  return MBB.getCallFrameSize();
 }
 
 /// Both DefMI and UseMI must be valid.  By default, call directly to the
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index 32dfbc98df581a..ea634ff54e3399 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -816,6 +816,15 @@ bool AMDGPURegisterBankInfo::executeInWaterfallLoop(
   MachineBasicBlock *BodyBB = MF->CreateMachineBasicBlock();
   MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
   MachineBasicBlock *RestoreExecBB = MF->CreateMachineBasicBlock();
+
+  // Set call-frame sizes in each new BB, in case we are in a call sequence.
+  std::optional<unsigned> CallFrameSizeBefore =
+      TII->getCallFrameSizeAt(MBB, Range.begin());
+  LoopBB->setCallFrameSize(CallFrameSizeBefore);
+  BodyBB->setCallFrameSize(CallFrameSizeBefore);
+  RemainderBB->setCallFrameSize(CallFrameSizeBefore);
+  RestoreExecBB->setCallFrameSize(CallFrameSizeBefore);
+
   MachineFunction::iterator MBBI(MBB);
   ++MBBI;
   MF->insert(MBBI, LoopBB);
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 4f83267c999e4a..0e48f7ff2b4ec2 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -790,6 +790,12 @@ void X86FrameLowering::emitStackProbeInlineGenericLoop(
   MachineBasicBlock *testMBB = MF.CreateMachineBasicBlock(LLVM_BB);
   MachineBasicBlock *tailMBB = MF.CreateMachineBasicBlock(LLVM_BB);
 
+  // Set call-frame sizes in each new BB, in case we are in a call sequence.
+  std::optional<unsigned> CallFrameSizeBefore =
+      TII.getCallFrameSizeAt(MBB, MBBI);
+  testMBB->setCallFrameSize(CallFrameSizeBefore);
+  tailMBB->setCallFrameSize(CallFrameSizeBefore);
+
   MachineFunction::iterator MBBIter = ++MBB.getIterator();
   MF.insert(MBBIter, testMBB);
   MF.insert(MBBIter, tailMBB);
@@ -932,6 +938,13 @@ void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
   MachineBasicBlock *LoopMBB = MF.CreateMachineBasicBlock(LLVM_BB);
   MachineBasicBlock *ContinueMBB = MF.CreateMachineBasicBlock(LLVM_BB);
 
+  // Set call-frame sizes in each new BB, in case we are in a call sequence.
+  std::optional<unsigned> CallFrameSizeBefore =
+      TII.getCallFrameSizeAt(MBB, MBBI);
+  RoundMBB->setCallFrameSize(CallFrameSizeBefore);
+  LoopMBB->setCallFrameSize(CallFrameSizeBefore);
+  ContinueMBB->setCallFrameSize(CallFrameSizeBefore);
+
   MachineFunction::iterator MBBIter = std::next(MBB.getIterator());
   MF.insert(MBBIter, RoundMBB);
   MF.insert(MBBIter, LoopMBB);
@@ -1286,6 +1299,19 @@ void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
                                   : Is64Bit         ? X86::R11D
                                                     : X86::EAX;
 
+      std::optional<unsigned> CallFrameSizeBefore =
+          TII.getCallFrameSizeAt(MBB, MBBI);
+      // entryMBB takes the place of MBB, so give it its stored call frame size.
+      entryMBB->setCallFrameSize(MBB.getCallFrameSize());
+      // MBB contains only a tail of its original instructions, so update its
+      // stored call frame size.
+      MBB.setCallFrameSize(CallFrameSizeBefore);
+      // For the other basic blocks, take the state at the insertion point as
+      // well.
+      headMBB->setCallFrameSize(CallFrameSizeBefore);
+      bodyMBB->setCallFrameSize(CallFrameSizeBefore);
+      footMBB->setCallFrameSize(CallFrameSizeBefore);
+
       // Setup entry block
       {
 
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index aa8e68910b7f3f..c7ea438a6afdd5 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -35720,6 +35720,16 @@ X86TargetLowering::EmitLoweredProbedAlloca(MachineInstr &MI,
   MachineBasicBlock *tailMBB = MF->CreateMachineBasicBlock(LLVM_BB);
   MachineBasicBlock *blockMBB = MF->CreateMachineBasicBlock(LLVM_BB);
 
+  // Set call-frame sizes in each new BB, in case we are in a call sequence.
+  // MBB is split at std::next(MachineBasicBlock::iterator(MI) and these blocks
+  // are inserted in between, so they should all have the call frame size at
+  // the split point.
+  std::optional<unsigned> CallFrameSizeAtSplit =
+      TII->getCallFrameSizeAt(*MBB, std::next(MachineBasicBlock::iterator(MI)));
+  testMBB->setCallFrameSize(CallFrameSizeAtSplit);
+  blockMBB->setCallFrameSize(CallFrameSizeAtSplit);
+  tailMBB->setCallFrameSize(CallFrameSizeAtSplit);
+
   MachineFunction::iterator MBBIter = ++MBB->getIterator();
   MF->insert(MBBIter, testMBB);
   MF->insert(MBBIter, blockMBB);

>From 00cf01744ad92785d025eb71857e2d040d8e2f6b Mon Sep 17 00:00:00 2001
From: Fabian Ritter <fabian.ritter at amd.com>
Date: Mon, 16 Sep 2024 03:03:55 -0400
Subject: [PATCH 4/5] [CodeGen] Compute call frame sizes instead of storing
 them in MachineBBs

Previously, we would need to update stored call frame sizes whenever a
MachineBB with a call sequence is split or call frame instructions are
moved. By recomputing them instead, this change avoids the need for
keeping track of the call frame sizes throughout transformations. It
also fixes several cases where updates of call frame sizes were missing.

The overhead according to the compile time tracker is < +0.03% executed
instructions on all CT benchmarks.

This also allows distinguishing a zero-sized call frame from no open
call frame, which is helpful to avoid nested CALLSEQs (which are illegal
and cause machine verifier errors).
---
 llvm/include/llvm/CodeGen/MachineBasicBlock.h |  22 ---
 llvm/include/llvm/CodeGen/MachineFrameInfo.h  |  80 ++++++++++
 llvm/include/llvm/CodeGen/TargetInstrInfo.h   |  10 --
 llvm/lib/CodeGen/MIRParser/MILexer.cpp        |   1 -
 llvm/lib/CodeGen/MIRParser/MILexer.h          |   1 -
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       |  19 ---
 llvm/lib/CodeGen/MachineBasicBlock.cpp        |   6 -
 llvm/lib/CodeGen/MachineFrameInfo.cpp         | 148 ++++++++++++++++++
 llvm/lib/CodeGen/MachineVerifier.cpp          |   9 --
 llvm/lib/CodeGen/PrologEpilogInserter.cpp     |  34 +---
 llvm/lib/CodeGen/TargetInstrInfo.cpp          |  21 ---
 .../Target/AMDGPU/AMDGPURegisterBankInfo.cpp  |   8 -
 llvm/lib/Target/ARM/ARMISelLowering.cpp       |  10 --
 llvm/lib/Target/AVR/AVRISelLowering.cpp       |   5 -
 llvm/lib/Target/M68k/M68kISelLowering.cpp     |   5 -
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |   6 -
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   |   6 -
 llvm/lib/Target/X86/X86FrameLowering.cpp      |  26 ---
 llvm/lib/Target/X86/X86ISelLowering.cpp       |  15 --
 ...no-register-coalescing-in-returnsTwice.mir |   4 +-
 llvm/test/CodeGen/MIR/ARM/call-frame-size.mir |   8 +-
 llvm/test/CodeGen/RISCV/pr97304.ll            |   4 +-
 llvm/tools/llvm-reduce/ReducerWorkItem.cpp    |   2 -
 23 files changed, 243 insertions(+), 207 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 4db1e0b60f87e3..7f0ce7015d6dd9 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -145,15 +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. Usually does not contain a value, unless
-  /// basic blocks are split in the middle of a call sequence. Zero-sized call
-  /// frames are possible.
-  ///
-  /// This information is only maintained until PrologEpilogInserter eliminates
-  /// call frame pseudos.
-  std::optional<unsigned> CallFrameSize;
-
   MachineFunction *xParent;
   Instructions Insts;
 
@@ -1216,19 +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.
-  std::optional<unsigned> getCallFrameSize() const { return CallFrameSize; }
-
-  /// Return the call frame size on entry to this basic block if it is part of a
-  /// call sequence and 0 otherwise.
-  unsigned getCallFrameSizeOrZero() const { return CallFrameSize.value_or(0); }
-
-  /// Set the call frame size on entry to this basic block.
-  void setCallFrameSize(std::optional<unsigned> N) { CallFrameSize = N; }
-
-  /// Reset the stored call frame size.
-  void clearCallFrameSize() { CallFrameSize.reset(); }
-
   /// 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 213b7ec6b3fbfb..9b53bf0dfb84d9 100644
--- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -26,6 +26,8 @@ class MachineFunction;
 class MachineBasicBlock;
 class BitVector;
 class AllocaInst;
+class MachineFrameSizeInfo;
+class TargetInstrInfo;
 
 /// The CalleeSavedInfo class tracks the information need to locate where a
 /// callee saved register is in the current frame.
@@ -282,6 +284,10 @@ class MachineFrameInfo {
   /// It is only valid during and after prolog/epilog code insertion.
   uint64_t MaxCallFrameSize = ~UINT64_C(0);
 
+  /// Call frame sizes for the MachineFunction's MachineBasicBlocks. This is set
+  /// by the MachineFrameSizeInfo constructor and cleared by its destructor.
+  MachineFrameSizeInfo *SizeInfo = nullptr;
+
   /// The number of bytes of callee saved registers that the target wants to
   /// report for the current function in the CodeView S_FRAMEPROC record.
   unsigned CVBytesOfCalleeSavedRegisters = 0;
@@ -675,6 +681,13 @@ class MachineFrameInfo {
   }
   void setMaxCallFrameSize(uint64_t S) { MaxCallFrameSize = S; }
 
+  /// Return an object that can be queried for call frame sizes at specific
+  /// locations in the MachineFunction. Constructing a MachineFrameSizeInfo
+  /// object for the MachineFunction automatically makes it available via this
+  /// field during the object's lifetime.
+  MachineFrameSizeInfo *getSizeInfo() const { return SizeInfo; }
+  void setSizeInfo(MachineFrameSizeInfo *SI) { SizeInfo = SI; }
+
   /// Returns how many bytes of callee-saved registers the target pushed in the
   /// prologue. Only used for debug info.
   unsigned getCVBytesOfCalleeSavedRegisters() const {
@@ -846,6 +859,73 @@ 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. Upon
+/// construction, a MachineFrameSizeInfo object registers itself in the
+/// MachineFunction's MachineFrameInfo (and it unregisters when destructed).
+/// While registered, it can be retrieved via MachineFrameInfo::getSizeInfo().
+///
+/// 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) {
+    assert(MF.getFrameInfo().getSizeInfo() == nullptr);
+    MF.getFrameInfo().setSizeInfo(this);
+  }
+
+  ~MachineFrameSizeInfo() { MF.getFrameInfo().setSizeInfo(nullptr); }
+
+  /// 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<unsigned> 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<unsigned> 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<unsigned> 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<unsigned> getCallFrameSizeAtEnd(MachineBasicBlock &MBB);
+
+private:
+  /// Stores the call frame sizes at the boundaries of a MachineBasicBlock.
+  struct MachineFrameSizeInfoForBB {
+    MachineFrameSizeInfoForBB() = default;
+    MachineFrameSizeInfoForBB(std::optional<unsigned> EntryVal,
+                              std::optional<unsigned> ExitVal)
+        : Entry(EntryVal), Exit(ExitVal) {}
+
+    std::optional<unsigned> Entry;
+    std::optional<unsigned> 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<MachineFrameSizeInfoForBB, 8> 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 276a4f08576061..830bfcc7aaa4f5 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2265,16 +2265,6 @@ class TargetInstrInfo : public MCInstrInfo {
     return false;
   }
 
-  /// 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<unsigned> getCallFrameSizeAt(MachineInstr &MI) const;
-
-  /// 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<unsigned>
-  getCallFrameSizeAt(MachineBasicBlock &MBB,
-                     MachineBasicBlock::iterator MII) 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 0809f88fde56b1..a753aee9402fb7 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 22547483a8a86b..cd27d1a1c72b8b 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 08e106b743276d..601af67aac75c6 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<MBBSectionID> &SID);
   bool parseBBID(std::optional<UniqueBBID> &BBID);
-  bool parseCallFrameSize(std::optional<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<UniqueBBID> &BBID) {
   return false;
 }
 
-// Parse basic block call frame size.
-bool MIParser::parseCallFrameSize(std::optional<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<unsigned, MachineBasicBlock *> &MBBSlots) {
   assert(Token.is(MIToken::MachineBasicBlockLabel));
@@ -713,7 +700,6 @@ bool MIParser::parseBasicBlockDefinition(
   std::optional<MBBSectionID> SectionID;
   uint64_t Alignment = 0;
   std::optional<UniqueBBID> BBID;
-  std::optional<unsigned> CallFrameSize;
   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 a948efb41d7152..afa9827cda242a 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.has_value()) {
-      os << (hasAttributes ? ", " : " (");
-      os << "call-frame-size " << CallFrameSize.value();
-      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 e4b993850f73dc..1c4a8d52950a72 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 <cassert>
+#include <optional>
 
 #define DEBUG_TYPE "codegen"
 
@@ -246,6 +248,152 @@ void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
   }
 }
 
+std::optional<unsigned>
+MachineFrameSizeInfo::getCallFrameSizeAt(MachineInstr &MI) {
+  return this->getCallFrameSizeAt(*MI.getParent(), MI.getIterator());
+}
+
+std::optional<unsigned>
+MachineFrameSizeInfo::getCallFrameSizeAtBegin(MachineBasicBlock &MBB) {
+  if (!IsComputed)
+    computeSizes();
+  if (HasNoBrokenUpCallSeqs || !HasFrameOpcodes)
+    return std::nullopt;
+  return State[MBB.getNumber()].Entry;
+}
+
+std::optional<unsigned>
+MachineFrameSizeInfo::getCallFrameSizeAtEnd(MachineBasicBlock &MBB) {
+  if (!IsComputed)
+    computeSizes();
+  if (HasNoBrokenUpCallSeqs || !HasFrameOpcodes)
+    return std::nullopt;
+  return State[MBB.getNumber()].Exit;
+}
+
+std::optional<unsigned>
+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<const MachineBasicBlock *> Reachable;
+
+  // Visit the MBBs in DFS order.
+  for (df_ext_iterator<MachineFunction *,
+                       df_iterator_default_set<const MachineBasicBlock *>>
+           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 cdcd78225c7e12..02c2b123481a5c 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -3889,15 +3889,6 @@ void MachineVerifier::verifyStackFrame() {
       BBState.Exit = BBState.Entry;
     }
 
-    if (MBB->getCallFrameSize() != BBState.Entry) {
-      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.Entry
-         << '\n';
-    }
-
     // Update stack state by checking contents of MBB.
     for (const auto &I : *MBB) {
       if (I.getOpcode() == FrameSetupOpcode) {
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index b2f355c0aa8ccf..7548d87d45d86c 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. Clear it everywhere to keep MachineVerifier happy.
-    for (MachineBasicBlock &MBB : MF)
-      MBB.clearCallFrameSize();
   }
 }
 
@@ -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->getCallFrameSizeOrZero() ==
-               (*MBB.succ_begin())->getCallFrameSizeOrZero();
-      }));
-      const MachineBasicBlock &FirstSucc = **MBB.succ_begin();
-      SPAdj = TFI.alignSPAdjust(FirstSucc.getCallFrameSizeOrZero());
-      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. Clear it everywhere to keep MachineVerifier happy.
-    MBB.clearCallFrameSize();
   }
 }
 
@@ -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.getCallFrameSizeOrZero());
+    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. Clear it everywhere to keep MachineVerifier happy.
-    MBB.clearCallFrameSize();
   }
 }
 
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 9318e684fffd96..0f86c9e19ccf4d 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -1625,27 +1625,6 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI,
   return std::nullopt;
 }
 
-std::optional<unsigned>
-TargetInstrInfo::getCallFrameSizeAt(MachineInstr &MI) const {
-  return this->getCallFrameSizeAt(*MI.getParent(), MI.getIterator());
-}
-
-std::optional<unsigned>
-TargetInstrInfo::getCallFrameSizeAt(MachineBasicBlock &MBB,
-                                    MachineBasicBlock::iterator MII) const {
-  // Search backwards from MI for the most recent call frame instruction.
-  for (auto &AdjI : reverse(make_range(MBB.begin(), MII))) {
-    if (AdjI.getOpcode() == getCallFrameSetupOpcode())
-      return getFrameTotalSize(AdjI);
-    if (AdjI.getOpcode() == getCallFrameDestroyOpcode())
-      return std::nullopt;
-  }
-
-  // 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<unsigned> TargetInstrInfo::getOperandLatency(
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index ea634ff54e3399..b215ad937d87a3 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -817,14 +817,6 @@ bool AMDGPURegisterBankInfo::executeInWaterfallLoop(
   MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
   MachineBasicBlock *RestoreExecBB = MF->CreateMachineBasicBlock();
 
-  // Set call-frame sizes in each new BB, in case we are in a call sequence.
-  std::optional<unsigned> CallFrameSizeBefore =
-      TII->getCallFrameSizeAt(MBB, Range.begin());
-  LoopBB->setCallFrameSize(CallFrameSizeBefore);
-  BodyBB->setCallFrameSize(CallFrameSizeBefore);
-  RemainderBB->setCallFrameSize(CallFrameSizeBefore);
-  RestoreExecBB->setCallFrameSize(CallFrameSizeBefore);
-
   MachineFunction::iterator MBBI(MBB);
   ++MBBI;
   MF->insert(MBBI, LoopBB);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index aedb9646ba6dea..3ef84bf88539c8 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.
-  std::optional<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.
-    std::optional<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 cf6f026869da80..f6e66b21279d13 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.
-  std::optional<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 3b0a0c83d94d16..b95edc21f0f422 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.
-  std::optional<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 77adfadb342388..d3b581b00b93cb 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.
-    std::optional<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 b0c1605be2fcb1..f86b830b6a0d64 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -18598,12 +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.
-  std::optional<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/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 0e48f7ff2b4ec2..4f83267c999e4a 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -790,12 +790,6 @@ void X86FrameLowering::emitStackProbeInlineGenericLoop(
   MachineBasicBlock *testMBB = MF.CreateMachineBasicBlock(LLVM_BB);
   MachineBasicBlock *tailMBB = MF.CreateMachineBasicBlock(LLVM_BB);
 
-  // Set call-frame sizes in each new BB, in case we are in a call sequence.
-  std::optional<unsigned> CallFrameSizeBefore =
-      TII.getCallFrameSizeAt(MBB, MBBI);
-  testMBB->setCallFrameSize(CallFrameSizeBefore);
-  tailMBB->setCallFrameSize(CallFrameSizeBefore);
-
   MachineFunction::iterator MBBIter = ++MBB.getIterator();
   MF.insert(MBBIter, testMBB);
   MF.insert(MBBIter, tailMBB);
@@ -938,13 +932,6 @@ void X86FrameLowering::emitStackProbeInlineWindowsCoreCLR64(
   MachineBasicBlock *LoopMBB = MF.CreateMachineBasicBlock(LLVM_BB);
   MachineBasicBlock *ContinueMBB = MF.CreateMachineBasicBlock(LLVM_BB);
 
-  // Set call-frame sizes in each new BB, in case we are in a call sequence.
-  std::optional<unsigned> CallFrameSizeBefore =
-      TII.getCallFrameSizeAt(MBB, MBBI);
-  RoundMBB->setCallFrameSize(CallFrameSizeBefore);
-  LoopMBB->setCallFrameSize(CallFrameSizeBefore);
-  ContinueMBB->setCallFrameSize(CallFrameSizeBefore);
-
   MachineFunction::iterator MBBIter = std::next(MBB.getIterator());
   MF.insert(MBBIter, RoundMBB);
   MF.insert(MBBIter, LoopMBB);
@@ -1299,19 +1286,6 @@ void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB,
                                   : Is64Bit         ? X86::R11D
                                                     : X86::EAX;
 
-      std::optional<unsigned> CallFrameSizeBefore =
-          TII.getCallFrameSizeAt(MBB, MBBI);
-      // entryMBB takes the place of MBB, so give it its stored call frame size.
-      entryMBB->setCallFrameSize(MBB.getCallFrameSize());
-      // MBB contains only a tail of its original instructions, so update its
-      // stored call frame size.
-      MBB.setCallFrameSize(CallFrameSizeBefore);
-      // For the other basic blocks, take the state at the insertion point as
-      // well.
-      headMBB->setCallFrameSize(CallFrameSizeBefore);
-      bodyMBB->setCallFrameSize(CallFrameSizeBefore);
-      footMBB->setCallFrameSize(CallFrameSizeBefore);
-
       // Setup entry block
       {
 
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c7ea438a6afdd5..aca4d29549e9e0 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.
-  std::optional<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();
@@ -35720,16 +35715,6 @@ X86TargetLowering::EmitLoweredProbedAlloca(MachineInstr &MI,
   MachineBasicBlock *tailMBB = MF->CreateMachineBasicBlock(LLVM_BB);
   MachineBasicBlock *blockMBB = MF->CreateMachineBasicBlock(LLVM_BB);
 
-  // Set call-frame sizes in each new BB, in case we are in a call sequence.
-  // MBB is split at std::next(MachineBasicBlock::iterator(MI) and these blocks
-  // are inserted in between, so they should all have the call frame size at
-  // the split point.
-  std::optional<unsigned> CallFrameSizeAtSplit =
-      TII->getCallFrameSizeAt(*MBB, std::next(MachineBasicBlock::iterator(MI)));
-  testMBB->setCallFrameSize(CallFrameSizeAtSplit);
-  blockMBB->setCallFrameSize(CallFrameSizeAtSplit);
-  tailMBB->setCallFrameSize(CallFrameSizeAtSplit);
-
   MachineFunction::iterator MBBIter = ++MBB->getIterator();
   MF->insert(MBBIter, testMBB);
   MF->insert(MBBIter, blockMBB);
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 b4bbb9be8ae405..b0e942fdf503d3 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 58e7f50e583455..81b497db626c53 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,7 @@ 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:
 ...
@@ -33,7 +33,7 @@ body: |
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT: bb.1 (call-frame-size 0):
+  ; 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
@@ -41,7 +41,7 @@ body: |
   ; CHECK-NEXT: bb.2:
   bb.0:
     ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
-  bb.1 (call-frame-size 0):
+  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 694f6384b6855b..6016f4149dd968 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 5f6a22cb3a9741..e79c824f37e4c3 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -249,8 +249,6 @@ static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF,
         DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock());
     Src2DstMBB[&SrcMBB] = DstMBB;
 
-    DstMBB->setCallFrameSize(SrcMBB.getCallFrameSize());
-
     if (SrcMBB.isIRBlockAddressTaken())
       DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock());
     if (SrcMBB.isMachineBlockAddressTaken())

>From 7020475297483e0a4ebacd6ebeacf3db0680a536 Mon Sep 17 00:00:00 2001
From: Fabian Ritter <fabian.ritter at amd.com>
Date: Fri, 20 Sep 2024 05:52:27 -0400
Subject: [PATCH 5/5] Remove MachineFrameSizeInfo ownership from
 MachineFrameInfo

Also remove an unintended newline.
---
 llvm/include/llvm/CodeGen/MachineFrameInfo.h  | 25 ++-----------------
 .../Target/AMDGPU/AMDGPURegisterBankInfo.cpp  |  1 -
 2 files changed, 2 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
index 9b53bf0dfb84d9..cdfdbc27fc6e41 100644
--- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -26,7 +26,6 @@ class MachineFunction;
 class MachineBasicBlock;
 class BitVector;
 class AllocaInst;
-class MachineFrameSizeInfo;
 class TargetInstrInfo;
 
 /// The CalleeSavedInfo class tracks the information need to locate where a
@@ -284,10 +283,6 @@ class MachineFrameInfo {
   /// It is only valid during and after prolog/epilog code insertion.
   uint64_t MaxCallFrameSize = ~UINT64_C(0);
 
-  /// Call frame sizes for the MachineFunction's MachineBasicBlocks. This is set
-  /// by the MachineFrameSizeInfo constructor and cleared by its destructor.
-  MachineFrameSizeInfo *SizeInfo = nullptr;
-
   /// The number of bytes of callee saved registers that the target wants to
   /// report for the current function in the CodeView S_FRAMEPROC record.
   unsigned CVBytesOfCalleeSavedRegisters = 0;
@@ -681,13 +676,6 @@ class MachineFrameInfo {
   }
   void setMaxCallFrameSize(uint64_t S) { MaxCallFrameSize = S; }
 
-  /// Return an object that can be queried for call frame sizes at specific
-  /// locations in the MachineFunction. Constructing a MachineFrameSizeInfo
-  /// object for the MachineFunction automatically makes it available via this
-  /// field during the object's lifetime.
-  MachineFrameSizeInfo *getSizeInfo() const { return SizeInfo; }
-  void setSizeInfo(MachineFrameSizeInfo *SI) { SizeInfo = SI; }
-
   /// Returns how many bytes of callee-saved registers the target pushed in the
   /// prologue. Only used for debug info.
   unsigned getCVBytesOfCalleeSavedRegisters() const {
@@ -863,11 +851,7 @@ class MachineFrameInfo {
 /// 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. Upon
-/// construction, a MachineFrameSizeInfo object registers itself in the
-/// MachineFunction's MachineFrameInfo (and it unregisters when destructed).
-/// While registered, it can be retrieved via MachineFrameInfo::getSizeInfo().
+/// 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
@@ -875,12 +859,7 @@ class MachineFrameInfo {
 /// frame sequences are not allowed.
 class MachineFrameSizeInfo {
 public:
-  MachineFrameSizeInfo(MachineFunction &MF) : MF(MF) {
-    assert(MF.getFrameInfo().getSizeInfo() == nullptr);
-    MF.getFrameInfo().setSizeInfo(this);
-  }
-
-  ~MachineFrameSizeInfo() { MF.getFrameInfo().setSizeInfo(nullptr); }
+  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.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index b215ad937d87a3..32dfbc98df581a 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -816,7 +816,6 @@ bool AMDGPURegisterBankInfo::executeInWaterfallLoop(
   MachineBasicBlock *BodyBB = MF->CreateMachineBasicBlock();
   MachineBasicBlock *RemainderBB = MF->CreateMachineBasicBlock();
   MachineBasicBlock *RestoreExecBB = MF->CreateMachineBasicBlock();
-
   MachineFunction::iterator MBBI(MBB);
   ++MBBI;
   MF->insert(MBBI, LoopBB);



More information about the llvm-commits mailing list