[llvm] [llvm][NFC]Support callee saved register info in save/restore points (PR #119358)

Elizaveta Noskova via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 04:02:46 PDT 2025


https://github.com/enoskova-sc updated https://github.com/llvm/llvm-project/pull/119358

>From 840ad78e534219094fd72e4e2c13ee308520ab76 Mon Sep 17 00:00:00 2001
From: Elizaveta Noskova <elizaveta.noskova at syntacore.com>
Date: Wed, 27 Aug 2025 13:29:23 +0300
Subject: [PATCH] [llvm][NFC]Support callee saved register info in save/restore
 points

Now each save/restore point contain info about registers
spilled/restored in it.
---
 llvm/include/llvm/CodeGen/MIRYamlMapping.h    |  22 ++-
 llvm/include/llvm/CodeGen/MachineFrameInfo.h  |  42 ++++-
 llvm/lib/CodeGen/MIRParser/MIRParser.cpp      |  20 ++-
 llvm/lib/CodeGen/MIRPrinter.cpp               |  39 ++++-
 llvm/lib/CodeGen/MachineFrameInfo.cpp         |   8 +-
 llvm/lib/CodeGen/PrologEpilogInserter.cpp     |  34 +++-
 llvm/lib/CodeGen/ShrinkWrap.cpp               |  12 +-
 llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp  |   6 +-
 llvm/lib/Target/PowerPC/PPCFrameLowering.cpp  |   5 +-
 ...nfo-multiple-save-restore-points-parse.mir |   4 +
 ...fo-save-restore-points-with-regs-parse.mir | 154 ++++++++++++++++++
 .../X86/frame-info-save-restore-points.mir    |   2 +
 llvm/test/CodeGen/RISCV/pr53662.mir           |   2 +
 .../RISCV/zcmp-prolog-epilog-crash.mir        |   2 +
 .../CodeGen/X86/cfi-epilogue-with-return.mir  |   2 +
 .../X86/cfi-epilogue-without-return.mir       |   2 +
 llvm/tools/llvm-reduce/ReducerWorkItem.cpp    |   8 +-
 17 files changed, 312 insertions(+), 52 deletions(-)
 create mode 100644 llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points-with-regs-parse.mir

diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index a91c26ee1122a..f4b486063fdfa 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -634,19 +634,35 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CalledGlobal)
 namespace llvm {
 namespace yaml {
 
-// Struct representing one save/restore point in the 'savePoint'/'restorePoint'
-// list
+// Struct representing one save/restore point in the 'savePoint' /
+// 'restorePoint' list. One point consists of machine basic block name and list
+// of registers saved/restored in this basic block. In MIR it looks like:
+//  savePoint:
+//    - point:           '%bb.1'
+//      registers:
+//        - '$rbx'
+//        - '$r12'
+//        ...
+//  restorePoint:
+//    - point:           '%bb.1'
+//      registers:
+//        - '$rbx'
+//        - '$r12'
+// If no register is saved/restored in the selected BB,
+// the empty list of register should be specified ( i.e. registers: [])
 struct SaveRestorePointEntry {
   StringValue Point;
+  std::vector<StringValue> Registers;
 
   bool operator==(const SaveRestorePointEntry &Other) const {
-    return Point == Other.Point;
+    return Point == Other.Point && Registers == Other.Registers;
   }
 };
 
 template <> struct MappingTraits<SaveRestorePointEntry> {
   static void mapping(IO &YamlIO, SaveRestorePointEntry &Entry) {
     YamlIO.mapRequired("point", Entry.Point);
+    YamlIO.mapRequired("registers", Entry.Registers);
   }
 };
 
diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
index e666001035deb..86094dad1c4d0 100644
--- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h
@@ -76,6 +76,22 @@ class CalleeSavedInfo {
   bool isSpilledToReg()                    const { return SpilledToReg; }
 };
 
+class SaveRestorePoints {
+public:
+  using PointsMap = DenseMap<MachineBasicBlock *, std::vector<CalleeSavedInfo>>;
+
+private:
+  PointsMap Map;
+
+public:
+  const PointsMap &get() const { return Map; }
+
+  void set(PointsMap &&CSI) { Map = std::move(CSI); }
+
+  void clear() { Map.clear(); }
+  bool empty() const { return Map.empty(); }
+};
+
 /// The MachineFrameInfo class represents an abstract stack frame until
 /// prolog/epilog code is inserted.  This class is key to allowing stack frame
 /// representation optimizations, such as frame pointer elimination.  It also
@@ -333,9 +349,9 @@ class MachineFrameInfo {
   bool HasTailCall = false;
 
   /// Not empty, if shrink-wrapping found a better place for the prologue.
-  SmallVector<MachineBasicBlock *, 4> SavePoints;
+  SaveRestorePoints SavePoints;
   /// Not empty, if shrink-wrapping found a better place for the epilogue.
-  SmallVector<MachineBasicBlock *, 4> RestorePoints;
+  SaveRestorePoints RestorePoints;
 
   /// Size of the UnsafeStack Frame
   uint64_t UnsafeStackSize = 0;
@@ -825,17 +841,25 @@ class MachineFrameInfo {
 
   void setCalleeSavedInfoValid(bool v) { CSIValid = v; }
 
-  ArrayRef<MachineBasicBlock *> getSavePoints() const { return SavePoints; }
-  void setSavePoints(ArrayRef<MachineBasicBlock *> NewSavePoints) {
-    SavePoints.assign(NewSavePoints.begin(), NewSavePoints.end());
+  const SaveRestorePoints::PointsMap &getRestorePoints() const {
+    return RestorePoints.get();
   }
-  ArrayRef<MachineBasicBlock *> getRestorePoints() const {
-    return RestorePoints;
+
+  const SaveRestorePoints::PointsMap &getSavePoints() const {
+    return SavePoints.get();
   }
-  void setRestorePoints(ArrayRef<MachineBasicBlock *> NewRestorePoints) {
-    RestorePoints.assign(NewRestorePoints.begin(), NewRestorePoints.end());
+
+  void setSavePoints(SaveRestorePoints::PointsMap NewSavePoints) {
+    SavePoints.set(std::move(NewSavePoints));
   }
 
+  void setRestorePoints(SaveRestorePoints::PointsMap NewRestorePoints) {
+    RestorePoints.set(std::move(NewRestorePoints));
+  }
+
+  void clearSavePoints() { SavePoints.clear(); }
+  void clearRestorePoints() { RestorePoints.clear(); }
+
   uint64_t getUnsafeStackSize() const { return UnsafeStackSize; }
   void setUnsafeStackSize(uint64_t Size) { UnsafeStackSize = Size; }
 
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index bb70e7805e818..1319d530fede5 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -127,7 +127,7 @@ class MIRParserImpl {
   bool initializeSaveRestorePoints(
       PerFunctionMIParsingState &PFS,
       const std::vector<yaml::SaveRestorePointEntry> &YamlSRPoints,
-      SmallVectorImpl<MachineBasicBlock *> &SaveRestorePoints);
+      llvm::SaveRestorePoints::PointsMap &SaveRestorePoints);
 
   bool initializeCallSiteInfo(PerFunctionMIParsingState &PFS,
                               const yaml::MachineFunction &YamlMF);
@@ -872,11 +872,11 @@ bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,
   MFI.setHasTailCall(YamlMFI.HasTailCall);
   MFI.setCalleeSavedInfoValid(YamlMFI.IsCalleeSavedInfoValid);
   MFI.setLocalFrameSize(YamlMFI.LocalFrameSize);
-  SmallVector<MachineBasicBlock *, 4> SavePoints;
+  llvm::SaveRestorePoints::PointsMap SavePoints;
   if (initializeSaveRestorePoints(PFS, YamlMFI.SavePoints, SavePoints))
     return true;
   MFI.setSavePoints(SavePoints);
-  SmallVector<MachineBasicBlock *, 4> RestorePoints;
+  llvm::SaveRestorePoints::PointsMap RestorePoints;
   if (initializeSaveRestorePoints(PFS, YamlMFI.RestorePoints, RestorePoints))
     return true;
   MFI.setRestorePoints(RestorePoints);
@@ -1098,14 +1098,22 @@ bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS,
 bool MIRParserImpl::initializeSaveRestorePoints(
     PerFunctionMIParsingState &PFS,
     const std::vector<yaml::SaveRestorePointEntry> &YamlSRPoints,
-    SmallVectorImpl<MachineBasicBlock *> &SaveRestorePoints) {
+    llvm::SaveRestorePoints::PointsMap &SaveRestorePoints) {
+  SMDiagnostic Error;
   MachineBasicBlock *MBB = nullptr;
   for (const yaml::SaveRestorePointEntry &Entry : YamlSRPoints) {
     if (parseMBBReference(PFS, MBB, Entry.Point.Value))
       return true;
-    SaveRestorePoints.push_back(MBB);
-  }
 
+    std::vector<CalleeSavedInfo> Registers;
+    for (auto &RegStr : Entry.Registers) {
+      Register Reg;
+      if (parseNamedRegisterReference(PFS, Reg, RegStr.Value, Error))
+        return error(Error, RegStr.SourceRange);
+      Registers.push_back(CalleeSavedInfo(Reg));
+    }
+    SaveRestorePoints.try_emplace(MBB, std::move(Registers));
+  }
   return false;
 }
 
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 7cc91925793a1..9b71f7f1fb7d4 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -149,11 +149,13 @@ static void convertMCP(yaml::MachineFunction &MF,
 static void convertMJTI(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
                         const MachineJumpTableInfo &JTI);
 static void convertMFI(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
-                       const MachineFrameInfo &MFI);
+                       const MachineFrameInfo &MFI,
+                       const TargetRegisterInfo *TRI);
 static void
 convertSRPoints(ModuleSlotTracker &MST,
                 std::vector<yaml::SaveRestorePointEntry> &YamlSRPoints,
-                ArrayRef<MachineBasicBlock *> SaveRestorePoints);
+                const llvm::SaveRestorePoints::PointsMap &SRPoints,
+                const TargetRegisterInfo *TRI);
 static void convertStackObjects(yaml::MachineFunction &YMF,
                                 const MachineFunction &MF,
                                 ModuleSlotTracker &MST, MFPrintState &State);
@@ -204,7 +206,8 @@ static void printMF(raw_ostream &OS, const MachineModuleInfo &MMI,
   convertMRI(YamlMF, MF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
   MachineModuleSlotTracker &MST = State.MST;
   MST.incorporateFunction(MF.getFunction());
-  convertMFI(MST, YamlMF.FrameInfo, MF.getFrameInfo());
+  convertMFI(MST, YamlMF.FrameInfo, MF.getFrameInfo(),
+             MF.getSubtarget().getRegisterInfo());
   convertStackObjects(YamlMF, MF, MST, State);
   convertEntryValueObjects(YamlMF, MF, MST);
   convertCallSiteObjects(YamlMF, MF, MST);
@@ -339,7 +342,8 @@ static void convertMRI(yaml::MachineFunction &YamlMF, const MachineFunction &MF,
 }
 
 static void convertMFI(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
-                       const MachineFrameInfo &MFI) {
+                       const MachineFrameInfo &MFI,
+                       const TargetRegisterInfo *TRI) {
   YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken();
   YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken();
   YamlMFI.HasStackMap = MFI.hasStackMap();
@@ -360,9 +364,9 @@ static void convertMFI(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
   YamlMFI.IsCalleeSavedInfoValid = MFI.isCalleeSavedInfoValid();
   YamlMFI.LocalFrameSize = MFI.getLocalFrameSize();
   if (!MFI.getSavePoints().empty())
-    convertSRPoints(MST, YamlMFI.SavePoints, MFI.getSavePoints());
+    convertSRPoints(MST, YamlMFI.SavePoints, MFI.getSavePoints(), TRI);
   if (!MFI.getRestorePoints().empty())
-    convertSRPoints(MST, YamlMFI.RestorePoints, MFI.getRestorePoints());
+    convertSRPoints(MST, YamlMFI.RestorePoints, MFI.getRestorePoints(), TRI);
 }
 
 static void convertEntryValueObjects(yaml::MachineFunction &YMF,
@@ -619,16 +623,35 @@ static void convertMCP(yaml::MachineFunction &MF,
 static void
 convertSRPoints(ModuleSlotTracker &MST,
                 std::vector<yaml::SaveRestorePointEntry> &YamlSRPoints,
-                ArrayRef<MachineBasicBlock *> SRPoints) {
-  for (const auto &MBB : SRPoints) {
+                const llvm::SaveRestorePoints::PointsMap &SRPoints,
+                const TargetRegisterInfo *TRI) {
+  for (const auto &[MBB, CSInfos] : SRPoints) {
     SmallString<16> Str;
     yaml::SaveRestorePointEntry Entry;
     raw_svector_ostream StrOS(Str);
     StrOS << printMBBReference(*MBB);
     Entry.Point = StrOS.str().str();
     Str.clear();
+    for (const CalleeSavedInfo &Info : CSInfos) {
+      if (Info.getReg()) {
+        StrOS << printReg(Info.getReg(), TRI);
+        Entry.Registers.push_back(StrOS.str().str());
+        Str.clear();
+      }
+    }
+    // Sort here needed for stable output for lit tests
+    std::sort(Entry.Registers.begin(), Entry.Registers.end(),
+              [](const yaml::StringValue &Lhs, const yaml::StringValue &Rhs) {
+                return Lhs.Value < Rhs.Value;
+              });
     YamlSRPoints.push_back(Entry);
   }
+  // Sort here needed for stable output for lit tests
+  std::sort(YamlSRPoints.begin(), YamlSRPoints.end(),
+            [](const yaml::SaveRestorePointEntry &Lhs,
+               const yaml::SaveRestorePointEntry &Rhs) {
+              return Lhs.Point.Value < Rhs.Point.Value;
+            });
 }
 
 static void convertMJTI(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp
index a8306b2ef2e5b..4eedc724f9167 100644
--- a/llvm/lib/CodeGen/MachineFrameInfo.cpp
+++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp
@@ -249,15 +249,15 @@ void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
   if (!SavePoints.empty()) {
     OS << "save points:\n";
 
-    for (auto &item : SavePoints)
-      OS << printMBBReference(*item) << "\n";
+    for (auto &item : SavePoints.get())
+      OS << printMBBReference(*item.first) << "\n";
   } else
     OS << "save points are empty\n";
 
   if (!RestorePoints.empty()) {
     OS << "restore points:\n";
-    for (auto &item : RestorePoints)
-      OS << printMBBReference(*item) << "\n";
+    for (auto &item : RestorePoints.get())
+      OS << printMBBReference(*item.first) << "\n";
   } else
     OS << "restore points are empty\n";
 }
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 8fc0748ecc0e3..c30c5b65a50d6 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -351,8 +351,8 @@ bool PEIImpl::run(MachineFunction &MF) {
   delete RS;
   SaveBlocks.clear();
   RestoreBlocks.clear();
-  MFI.setSavePoints({});
-  MFI.setRestorePoints({});
+  MFI.clearSavePoints();
+  MFI.clearRestorePoints();
   return true;
 }
 
@@ -431,10 +431,12 @@ void PEIImpl::calculateSaveRestoreBlocks(MachineFunction &MF) {
   if (!MFI.getSavePoints().empty()) {
     assert(MFI.getSavePoints().size() == 1 &&
            "Multiple save points are not yet supported!");
-    SaveBlocks.push_back(MFI.getSavePoints().front());
+    const auto &SavePoint = *MFI.getSavePoints().begin();
+    SaveBlocks.push_back(SavePoint.first);
     assert(MFI.getRestorePoints().size() == 1 &&
            "Multiple restore points are not yet supported!");
-    MachineBasicBlock *RestoreBlock = MFI.getRestorePoints().front();
+    const auto &RestorePoint = *MFI.getRestorePoints().begin();
+    MachineBasicBlock *RestoreBlock = RestorePoint.first;
     // If RestoreBlock does not have any successor and is not a return block
     // then the end point is unreachable and we do not need to insert any
     // epilogue.
@@ -563,8 +565,9 @@ static void updateLiveness(MachineFunction &MF) {
 
   assert(MFI.getSavePoints().size() < 2 &&
          "Multiple save points not yet supported!");
-  MachineBasicBlock *Save =
-      MFI.getSavePoints().empty() ? nullptr : MFI.getSavePoints().front();
+  MachineBasicBlock *Save = MFI.getSavePoints().empty()
+                                ? nullptr
+                                : (*MFI.getSavePoints().begin()).first;
 
   if (!Save)
     Save = Entry;
@@ -577,8 +580,9 @@ static void updateLiveness(MachineFunction &MF) {
 
   assert(MFI.getRestorePoints().size() < 2 &&
          "Multiple restore points not yet supported!");
-  MachineBasicBlock *Restore =
-      MFI.getRestorePoints().empty() ? nullptr : MFI.getRestorePoints().front();
+  MachineBasicBlock *Restore = MFI.getRestorePoints().empty()
+                                   ? nullptr
+                                   : (*MFI.getRestorePoints().begin()).first;
   if (Restore)
     // By construction Restore cannot be visited, otherwise it
     // means there exists a path to Restore that does not go
@@ -687,6 +691,20 @@ void PEIImpl::spillCalleeSavedRegs(MachineFunction &MF) {
     MFI.setCalleeSavedInfoValid(true);
 
     std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+
+    // Fill SavePoints and RestorePoints with CalleeSavedRegisters
+    if (!MFI.getSavePoints().empty()) {
+      SaveRestorePoints::PointsMap SaveRestorePts;
+      for (const auto &SavePoint : MFI.getSavePoints())
+        SaveRestorePts.insert({SavePoint.first, CSI});
+      MFI.setSavePoints(std::move(SaveRestorePts));
+
+      SaveRestorePts.clear();
+      for (const auto &RestorePoint : MFI.getRestorePoints())
+        SaveRestorePts.insert({RestorePoint.first, CSI});
+      MFI.setRestorePoints(std::move(SaveRestorePts));
+    }
+
     if (!CSI.empty()) {
       if (!MFI.hasCalls())
         NumLeafFuncWithSpills++;
diff --git a/llvm/lib/CodeGen/ShrinkWrap.cpp b/llvm/lib/CodeGen/ShrinkWrap.cpp
index 938f2d756bc87..7d6aaedb4de4d 100644
--- a/llvm/lib/CodeGen/ShrinkWrap.cpp
+++ b/llvm/lib/CodeGen/ShrinkWrap.cpp
@@ -967,12 +967,12 @@ bool ShrinkWrapImpl::run(MachineFunction &MF) {
                     << "\nRestore: " << printMBBReference(*Restore) << '\n');
 
   MachineFrameInfo &MFI = MF.getFrameInfo();
-  SmallVector<MachineBasicBlock *, 4> SavePoints;
-  SmallVector<MachineBasicBlock *, 4> RestorePoints;
-  if (Save) {
-    SavePoints.push_back(Save);
-    RestorePoints.push_back(Restore);
-  }
+
+  // List of CalleeSavedInfo for registers will be added during prologepilog
+  // pass
+  SaveRestorePoints::PointsMap SavePoints({{Save, {}}});
+  SaveRestorePoints::PointsMap RestorePoints({{Restore, {}}});
+
   MFI.setSavePoints(SavePoints);
   MFI.setRestorePoints(RestorePoints);
   ++NumCandidates;
diff --git a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
index 1a91bbd433553..40eeeb8a8630d 100644
--- a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
+++ b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp
@@ -213,10 +213,12 @@ void SILowerSGPRSpills::calculateSaveRestoreBlocks(MachineFunction &MF) {
   if (!MFI.getSavePoints().empty()) {
     assert(MFI.getSavePoints().size() == 1 &&
            "Multiple save points not yet supported!");
-    SaveBlocks.push_back(MFI.getSavePoints().front());
+    const auto &SavePoint = *MFI.getSavePoints().begin();
+    SaveBlocks.push_back(SavePoint.first);
     assert(MFI.getRestorePoints().size() == 1 &&
            "Multiple restore points not yet supported!");
-    MachineBasicBlock *RestoreBlock = MFI.getRestorePoints().front();
+    const auto &RestorePoint = *MFI.getRestorePoints().begin();
+    MachineBasicBlock *RestoreBlock = RestorePoint.first;
     // If RestoreBlock does not have any successor and is not a return block
     // then the end point is unreachable and we do not need to insert any
     // epilogue.
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index 2ad3ed21732ed..6300ace338db7 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -2081,9 +2081,10 @@ void PPCFrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
   if (!MFI.getSavePoints().empty() && MFI.hasTailCall()) {
     assert(MFI.getRestorePoints().size() < 2 &&
            "MFI can't contain multiple restore points!");
-    MachineBasicBlock *RestoreBlock = MFI.getRestorePoints().front();
+    const auto &RestorePoint = *MFI.getRestorePoints().begin();
+    MachineBasicBlock *RestoreBlock = RestorePoint.first;
     for (MachineBasicBlock &MBB : MF) {
-      if (MBB.isReturnBlock() && (&MBB) != RestoreBlock)
+      if (MBB.isReturnBlock() && (!MFI.getRestorePoints().contains(&MBB)))
         createTailCallBranchInstr(MBB);
     }
   }
diff --git a/llvm/test/CodeGen/MIR/X86/frame-info-multiple-save-restore-points-parse.mir b/llvm/test/CodeGen/MIR/X86/frame-info-multiple-save-restore-points-parse.mir
index 4c60ccd573595..f5ea96e3a7507 100644
--- a/llvm/test/CodeGen/MIR/X86/frame-info-multiple-save-restore-points-parse.mir
+++ b/llvm/test/CodeGen/MIR/X86/frame-info-multiple-save-restore-points-parse.mir
@@ -42,10 +42,14 @@ frameInfo:
   hasCalls:      true
   savePoint:
     - point:     '%bb.1'
+      registers: []
     - point:     '%bb.2'
+      registers: []
   restorePoint:  
     - point:     '%bb.2'
+      registers: []
     - point:     '%bb.3'
+      registers: []
 stack:
   - { id: 0, name: tmp, offset: 0, size: 4, alignment: 4 }
 body: |
diff --git a/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points-with-regs-parse.mir b/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points-with-regs-parse.mir
new file mode 100644
index 0000000000000..d23f2f7bd585e
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points-with-regs-parse.mir
@@ -0,0 +1,154 @@
+# RUN: llc -run-pass none -o - %s | FileCheck %s 
+
+--- |
+  define ptr @foo(ptr %ptr, i64 %p2, i64 %p3, i64 %p4, i64 %p5, i64 %p6) {
+  entry:
+    %tobool.not = icmp eq ptr %ptr, null
+    br i1 %tobool.not, label %if.then, label %if.end
+  
+  if.then:                                          ; preds = %entry
+    %call = tail call ptr @bar(ptr %ptr, i64 %p2, i64 %p3, i64 %p4, i64 %p5, i64 %p6)
+    br label %if.end
+  
+  if.end:                                           ; preds = %if.then, %entry
+    %ptr.addr.0 = phi ptr [ %call, %if.then ], [ %ptr, %entry ]
+    %incdec.ptr = getelementptr inbounds i8, ptr %ptr.addr.0, i64 1
+    %call2 = tail call ptr @qux(ptr %incdec.ptr, i64 %p2, i64 %p3, i64 %p4, i64 %p5, i64 %p6)
+    ret ptr %call2
+  }
+  
+  declare ptr @bar(ptr, i64, i64, i64, i64, i64)
+  
+  declare ptr @qux(ptr, i64, i64, i64, i64, i64)
+...
+---
+name:            foo
+alignment:       16
+exposesReturnsTwice: false
+legalized:       false
+regBankSelected: false
+selected:        false
+failedISel:      false
+tracksRegLiveness: true
+hasWinCFI:       false
+noPhis:          true
+isSSA:           false
+noVRegs:         true
+hasFakeUses:     false
+callsEHReturn:   false
+callsUnwindInit: false
+hasEHContTarget: false
+hasEHScopes:     false
+hasEHFunclets:   false
+isOutlined:      false
+debugInstrRef:   true
+failsVerification: false
+tracksDebugUserValues: true
+registers:       []
+liveins:
+  - { reg: '$rdi', virtual-reg: '' }
+  - { reg: '$rsi', virtual-reg: '' }
+  - { reg: '$rdx', virtual-reg: '' }
+  - { reg: '$rcx', virtual-reg: '' }
+  - { reg: '$r8', virtual-reg: '' }
+  - { reg: '$r9', virtual-reg: '' }
+frameInfo:
+  isFrameAddressTaken: false
+  isReturnAddressTaken: false
+  hasStackMap:     false
+  hasPatchPoint:   false
+  stackSize:       0
+  offsetAdjustment: 0
+  maxAlignment:    1
+  adjustsStack:    true
+  hasCalls:        true
+  stackProtector:  ''
+  functionContext: ''
+  maxCallFrameSize: 4294967295
+  cvBytesOfCalleeSavedRegisters: 0
+  hasOpaqueSPAdjustment: false
+  hasVAStart:      false
+  hasMustTailInVarArgFunc: false
+  hasTailCall:     true
+  isCalleeSavedInfoValid: false
+  localFrameSize:  0
+# CHECK:       savePoint:
+# CHECK-NEXT:   - point:           '%bb.2'
+# CHECK-NEXT:     registers:
+# CHECK-NEXT:       - '$r12'
+# CHECK-NEXT:       - '$r13'
+# CHECK-NEXT:       - '$r14'
+# CHECK-NEXT:       - '$r15'
+# CHECK-NEXT:       - '$rbx'
+# CHECK:      restorePoint:
+# CHECK-NEXT:   - point:           '%bb.2'
+# CHECK-NEXT:     registers:
+# CHECK-NEXT:       - '$r12'
+# CHECK-NEXT:       - '$r13'
+# CHECK-NEXT:       - '$r14'
+# CHECK-NEXT:       - '$r15'
+# CHECK-NEXT:       - '$rbx'
+  savePoint:
+    - point:           '%bb.1'
+      registers:
+        - '$rbx'
+        - '$r12'
+        - '$r13'
+        - '$r14'
+        - '$r15'
+  restorePoint:
+    - point:           '%bb.1'
+      registers:
+        - '$rbx'
+        - '$r12'
+        - '$r13'
+        - '$r14'
+        - '$r15'
+fixedStack:      []
+stack:           []
+entry_values:    []
+callSites:       []
+debugValueSubstitutions: []
+constants:       []
+machineFunctionInfo:
+  amxProgModel:    None
+body:             |
+  bb.0.entry:
+    successors: %bb.1(0x30000000), %bb.3(0x50000000)
+    liveins: $rcx, $rdi, $rdx, $rsi, $r8, $r9
+  
+    TEST64rr renamable $rdi, renamable $rdi, implicit-def $eflags
+    JCC_1 %bb.1, 4, implicit killed $eflags
+  
+  bb.3:
+    successors: %bb.2(0x80000000)
+    liveins: $rcx, $rdi, $rdx, $rsi, $r8, $r9
+  
+    JMP_1 %bb.2
+  
+  bb.1.if.then:
+    successors: %bb.2(0x80000000)
+    liveins: $rcx, $rdi, $rdx, $rsi, $r8, $r9
+  
+    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    renamable $rbx = COPY renamable $rsi
+    renamable $r14 = COPY renamable $rdx
+    renamable $r15 = COPY renamable $rcx
+    renamable $r12 = COPY renamable $r8
+    renamable $r13 = COPY renamable $r9
+    CALL64pcrel32 target-flags(x86-plt) @bar, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit $rcx, implicit $r8, implicit $r9, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
+    renamable $rsi = COPY killed renamable $rbx
+    renamable $rdx = COPY killed renamable $r14
+    renamable $rcx = COPY killed renamable $r15
+    renamable $r8 = COPY killed renamable $r12
+    renamable $r9 = COPY killed renamable $r13
+    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+    renamable $rdi = COPY killed $rax
+  
+  bb.2.if.end:
+    liveins: $rcx, $rdi, $rdx, $rsi, $r8, $r9
+  
+    renamable $rdi = nuw INC64r killed renamable $rdi, implicit-def dead $eflags
+    TCRETURNdi64 target-flags(x86-plt) @qux, 0, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit $rcx, implicit $r8, implicit $r9
+...
+
diff --git a/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points.mir b/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points.mir
index 6357c5a30da89..d3573035949b8 100644
--- a/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points.mir
+++ b/llvm/test/CodeGen/MIR/X86/frame-info-save-restore-points.mir
@@ -40,8 +40,10 @@ frameInfo:
   hasCalls:      true
   savePoint:
    - point:           '%bb.2'
+     registers: []
   restorePoint:
     - point:           '%bb.2'
+      registers: []
 stack:
   - { id: 0, name: tmp, offset: 0, size: 4, alignment: 4 }
 body: |
diff --git a/llvm/test/CodeGen/RISCV/pr53662.mir b/llvm/test/CodeGen/RISCV/pr53662.mir
index dccad40368111..d859984629086 100644
--- a/llvm/test/CodeGen/RISCV/pr53662.mir
+++ b/llvm/test/CodeGen/RISCV/pr53662.mir
@@ -12,8 +12,10 @@ name:            b
 frameInfo:
   savePoint:
     - point:           '%bb.0'
+      registers: []
   restorePoint:
     - point:           '%bb.1'
+      registers: []
 body:             |
   ; CHECK-LABEL: name: b
   ; CHECK: bb.0:
diff --git a/llvm/test/CodeGen/RISCV/zcmp-prolog-epilog-crash.mir b/llvm/test/CodeGen/RISCV/zcmp-prolog-epilog-crash.mir
index 979b8a4e17d5a..f8cc8f4b86c8e 100644
--- a/llvm/test/CodeGen/RISCV/zcmp-prolog-epilog-crash.mir
+++ b/llvm/test/CodeGen/RISCV/zcmp-prolog-epilog-crash.mir
@@ -40,8 +40,10 @@ frameInfo:
   localFrameSize:  32
   savePoint:
     - point:           '%bb.2'
+      registers: []
   restorePoint:
     - point:           '%bb.2'
+      registers: []
 stack:
   - { id: 0, size: 32, alignment: 1, local-offset: -32 }
 machineFunctionInfo:
diff --git a/llvm/test/CodeGen/X86/cfi-epilogue-with-return.mir b/llvm/test/CodeGen/X86/cfi-epilogue-with-return.mir
index 4f80f4f87dd0d..175e6970f4cba 100644
--- a/llvm/test/CodeGen/X86/cfi-epilogue-with-return.mir
+++ b/llvm/test/CodeGen/X86/cfi-epilogue-with-return.mir
@@ -23,8 +23,10 @@ frameInfo:
   hasCalls:        true
   savePoint:
     - point:           '%bb.1'
+      registers: []
   restorePoint:
     - point:           '%bb.1'
+      registers: []
 machineFunctionInfo: {}
 body:             |
   bb.0:
diff --git a/llvm/test/CodeGen/X86/cfi-epilogue-without-return.mir b/llvm/test/CodeGen/X86/cfi-epilogue-without-return.mir
index 38c081c94ab91..eed33f81d802c 100644
--- a/llvm/test/CodeGen/X86/cfi-epilogue-without-return.mir
+++ b/llvm/test/CodeGen/X86/cfi-epilogue-without-return.mir
@@ -30,8 +30,10 @@ frameInfo:
   hasCalls:        true
   savePoint:
     - point:           '%bb.1'
+      registers: []
   restorePoint:
     - point:           '%bb.1'
+      registers: []
 machineFunctionInfo: {}
 body:             |
   bb.0:
diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index b1138ef9d5289..cb1b6b007a621 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -62,12 +62,12 @@ static cl::opt<bool> TmpFilesAsBitcode(
     cl::desc("Always write temporary files as bitcode instead of textual IR"),
     cl::init(false), cl::cat(LLVMReduceOptions));
 
-static SmallVector<MachineBasicBlock *> constructSaveRestorePoints(
-    ArrayRef<MachineBasicBlock *> SRPoints,
+static SaveRestorePoints::PointsMap constructSaveRestorePoints(
+    const SaveRestorePoints::PointsMap &SRPoints,
     const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &BBMap) {
-  SmallVector<MachineBasicBlock *> Pts;
+  SaveRestorePoints::PointsMap Pts{};
   for (auto &Src : SRPoints)
-    Pts.push_back(BBMap.find(Src)->second);
+    Pts.insert({BBMap.find(Src.first)->second, Src.second});
   return Pts;
 }
 



More information about the llvm-commits mailing list