[llvm] Rebased save csr in ra (PR #131845)

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 18 10:26:54 PDT 2025


================
@@ -786,6 +788,153 @@ void RISCVFrameLowering::allocateStack(MachineBasicBlock &MBB,
   }
 }
 
+struct CFIBuildInfo {
+  MachineBasicBlock *MBB;
+  MachineInstr *InsertAfterMI; // nullptr means insert at MBB.begin()
+  DebugLoc DL;
+  unsigned CFIIndex;
+};
+
+static void trackRegisterAndEmitCFIs(
+    MachineFunction &MF, MachineInstr &MI, MCRegister Reg, int DwarfEHRegNum,
+    const ReachingDefAnalysis &RDA, const TargetInstrInfo &TII,
+    const MachineFrameInfo &MFI, const RISCVRegisterInfo &TRI,
+    std::vector<CFIBuildInfo> &CFIBuildInfos,
+    std::unordered_set<MachineInstr *> &VisitedRestorePoints,
+    std::unordered_set<MachineInstr *> &VisitedDefs) {
+
+  if (VisitedRestorePoints.find(&MI) != VisitedRestorePoints.end()) {
+    return;
+  }
+  VisitedRestorePoints.insert(&MI);
+  SmallPtrSet<MachineInstr *, 2> Defs;
+  RDA.getGlobalReachingDefs(&MI, Reg, Defs);
+  MachineBasicBlock &EntryMBB = MF.front();
+  if (Defs.empty()) {
+    // it's a live-in register at the entry block.
+    // unsigned CFIIndex =
+    // MF.addFrameInst(MCCFIInstruction::createSameValue(nullptr,
+    // DwarfEHRegNum)); CFIBuildInfos.push_back({&EntryMBB, nullptr, DebugLoc(),
+    // CFIIndex});
+    return;
+  }
+
+  int FrameIndex = std::numeric_limits<int>::min();
+  for (MachineInstr *Def : Defs) {
+    if (VisitedDefs.find(Def) != VisitedDefs.end())
+      continue;
+    VisitedDefs.insert(Def);
+
+    MachineBasicBlock &MBB = *Def->getParent();
+    const DebugLoc &DL = Def->getDebugLoc();
+
+    if (Register StoredReg = TII.isStoreToStackSlot(*Def, FrameIndex)) {
+      assert(FrameIndex == Register::stackSlot2Index(Reg));
+
+      Register FrameReg;
+      StackOffset Offset =
+          MF.getSubtarget().getFrameLowering()->getFrameIndexReference(
+              MF, FrameIndex, FrameReg);
+      int64_t FixedOffset = Offset.getFixed();
+      // TODO:
+      assert(Offset.getScalable() == 0);
+
+      std::string CommentBuffer;
+      llvm::raw_string_ostream Comment(CommentBuffer);
+      int DwarfEHFrameReg = TRI.getDwarfRegNum(FrameReg, true);
+      Register LLVMReg = *TRI.getLLVMRegNum(DwarfEHRegNum, true);
+      Comment << printReg(LLVMReg, &TRI) << " = *(";
+      Comment << printReg(FrameReg, &TRI) << " + ";
+      Comment << FixedOffset << ")";
+      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMRegOffset(
+          nullptr, DwarfEHRegNum, DwarfEHFrameReg, FixedOffset, SMLoc(), Comment.str()));
+
+      CFIBuildInfos.push_back({&MBB, Def, DL, CFIIndex});
+      trackRegisterAndEmitCFIs(MF, *Def, StoredReg, DwarfEHRegNum, RDA, TII,
+                               MFI, TRI, CFIBuildInfos, VisitedRestorePoints,
+                               VisitedDefs);
+    } else if (Register LoadedReg = TII.isLoadFromStackSlot(*Def, FrameIndex)) {
+      assert(LoadedReg == Reg);
+
+      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRegister(
+          nullptr, DwarfEHRegNum, TRI.getDwarfRegNum(LoadedReg, true)));
+      CFIBuildInfos.push_back({&MBB, Def, DL, CFIIndex});
+      trackRegisterAndEmitCFIs(MF, *Def, Register::index2StackSlot(FrameIndex),
+                               DwarfEHRegNum, RDA, TII, MFI, TRI, CFIBuildInfos,
+                               VisitedRestorePoints, VisitedDefs);
+    } else if (auto DstSrc = TII.isCopyInstr(*Def)) {
+      Register DstReg = DstSrc->Destination->getReg();
+      Register SrcReg = DstSrc->Source->getReg();
+      assert(DstReg == Reg);
+
+      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createRegister(
+          nullptr, DwarfEHRegNum, TRI.getDwarfRegNum(DstReg, true)));
+      CFIBuildInfos.push_back({&MBB, Def, DL, CFIIndex});
+      trackRegisterAndEmitCFIs(MF, *Def, SrcReg, DwarfEHRegNum, RDA, TII, MFI,
+                               TRI, CFIBuildInfos, VisitedRestorePoints,
+                               VisitedDefs);
+    } else {
+      llvm_unreachable("Unexpected instruction");
+    }
+  }
+  return;
+}
+
+int RISCVFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {
+  return 0;
+}
+
+Register
+RISCVFrameLowering::getInitialCFARegister(const MachineFunction &MF) const {
+  return RISCV::X2;
+}
+
+void RISCVFrameLowering::emitCFIsForCSRsHandledByRA(
+    MachineFunction &MF, ReachingDefAnalysis *RDA) const {
+  if (!STI.doCSRSavesInRA())
+    return;
+  const RISCVInstrInfo &TII = *STI.getInstrInfo();
+  const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  BitVector MustCalleeSavedRegs;
+  determineMustCalleeSaves(MF, MustCalleeSavedRegs);
+  const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
+  SmallVector<MCPhysReg, 4> EligibleRegs;
+  for (int i = 0; CSRegs[i]; ++i) {
+    unsigned Reg = CSRegs[i];
+    if (!MustCalleeSavedRegs.test(Reg))
+      EligibleRegs.push_back(CSRegs[i]);
+  }
+
+  SmallVector<MachineInstr *, 4> RestorePoints;
+  for (MachineBasicBlock &MBB : MF) {
+    if (MBB.isReturnBlock())
+      RestorePoints.push_back(&MBB.back());
+  }
+  // TODO: replace CFIBuildInfo with UnwindLocation from DebugInfo/DWARF/DWARFDebugFrame
+  std::vector<CFIBuildInfo> CFIBuildInfos;
+  for (MCPhysReg Reg : EligibleRegs) {
+    std::unordered_set<MachineInstr *> VisitedDefs;
+    for (MachineInstr *RestorePoint : RestorePoints) {
+      std::unordered_set<MachineInstr *> VisitedRestorePoints;
+      trackRegisterAndEmitCFIs(
+          MF, *RestorePoint, Reg, TRI.getDwarfRegNum(Reg, true), *RDA, TII, MFI,
+          TRI, CFIBuildInfos, VisitedRestorePoints, VisitedDefs);
+    }
+  }
+  for (CFIBuildInfo &Info : CFIBuildInfos) {
+    MachineBasicBlock::iterator InsertPos =
+        Info.InsertAfterMI ? ++(Info.InsertAfterMI->getIterator())
+                           : Info.MBB->begin();
+    BuildMI(*Info.MBB, InsertPos, Info.DL,
----------------
michaelmaitland wrote:

It looks like we are emitting CFI instruction here. Why did this not occur in `trackRegisterandEmitCFIs`?

https://github.com/llvm/llvm-project/pull/131845


More information about the llvm-commits mailing list