Skip to content

Commit ddb2a49

Browse files
committed
[llvm] support multiple save/restore points in prolog-epilog
With this patch the possibility to store multiple Save and Restore points in MachineFrameInfo appears. As the logical consequnce of it, the notions "Save point" / "Restore point" are no longer synonyms for "Prolog" / "Epilog". Currently, "Prolog" / "Epilog" is the place for stack allocation / deallocation and "Save point" / "Restore point" is the place for register spills and restores. So, now we need to store in MachineFrameInfo not only vector of Save and vector of Restore blocks, but Prolog and Epilog. As we assume to have multiple Save and Restore points we need to know the list of registers, we store / restore in each point. Threfore our SavePoint become a pair <MachineBasicBlock, std::vector<Register>>. The full support for operating with multiple Save / Restore points is supported only in RISCV backend.
1 parent 5bc9d8b commit ddb2a49

27 files changed

+815
-355
lines changed

llvm/include/llvm/CodeGen/MIRYamlMapping.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,15 +612,19 @@ namespace yaml {
612612

613613
struct SRPEntry {
614614
StringValue Point;
615+
std::vector<StringValue> Registers;
615616

616-
bool operator==(const SRPEntry &Other) const { return Point == Other.Point; }
617+
bool operator==(const SRPEntry &Other) const {
618+
return Point == Other.Point && Registers == Other.Registers;
619+
}
617620
};
618621

619622
using SaveRestorePoints = std::vector<SRPEntry>;
620623

621624
template <> struct MappingTraits<SRPEntry> {
622625
static void mapping(IO &YamlIO, SRPEntry &Entry) {
623626
YamlIO.mapRequired("point", Entry.Point);
627+
YamlIO.mapRequired("registers", Entry.Registers);
624628
}
625629
};
626630

llvm/include/llvm/CodeGen/MachineFrameInfo.h

Lines changed: 131 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ class MachineBasicBlock;
2727
class BitVector;
2828
class AllocaInst;
2929

30+
using SaveRestorePoints = DenseMap<MachineBasicBlock *, std::vector<Register>>;
31+
32+
class CalleeSavedInfoPerBB {
33+
DenseMap<MachineBasicBlock *, std::vector<CalleeSavedInfo>> Map;
34+
35+
public:
36+
std::vector<CalleeSavedInfo> get(MachineBasicBlock *MBB) const {
37+
return Map.lookup(MBB);
38+
}
39+
40+
void set(DenseMap<MachineBasicBlock *, std::vector<CalleeSavedInfo>> CSI) {
41+
Map = std::move(CSI);
42+
}
43+
};
44+
3045
/// The CalleeSavedInfo class tracks the information need to locate where a
3146
/// callee saved register is in the current frame.
3247
/// Callee saved reg can also be saved to a different register rather than
@@ -37,6 +52,8 @@ class CalleeSavedInfo {
3752
int FrameIdx;
3853
unsigned DstReg;
3954
};
55+
std::vector<MachineBasicBlock *> SpilledIn;
56+
std::vector<MachineBasicBlock *> RestoredIn;
4057
/// Flag indicating whether the register is actually restored in the epilog.
4158
/// In most cases, if a register is saved, it is also restored. There are
4259
/// some situations, though, when this is not the case. For example, the
@@ -58,9 +75,9 @@ class CalleeSavedInfo {
5875
explicit CalleeSavedInfo(unsigned R, int FI = 0) : Reg(R), FrameIdx(FI) {}
5976

6077
// Accessors.
61-
Register getReg() const { return Reg; }
62-
int getFrameIdx() const { return FrameIdx; }
63-
unsigned getDstReg() const { return DstReg; }
78+
Register getReg() const { return Reg; }
79+
int getFrameIdx() const { return FrameIdx; }
80+
unsigned getDstReg() const { return DstReg; }
6481
void setFrameIdx(int FI) {
6582
FrameIdx = FI;
6683
SpilledToReg = false;
@@ -72,6 +89,16 @@ class CalleeSavedInfo {
7289
bool isRestored() const { return Restored; }
7390
void setRestored(bool R) { Restored = R; }
7491
bool isSpilledToReg() const { return SpilledToReg; }
92+
ArrayRef<MachineBasicBlock *> spilledIn() const { return SpilledIn; }
93+
ArrayRef<MachineBasicBlock *> restoredIn() const { return RestoredIn; }
94+
void addSpilledIn(MachineBasicBlock *MBB) { SpilledIn.push_back(MBB); }
95+
void addRestoredIn(MachineBasicBlock *MBB) { RestoredIn.push_back(MBB); }
96+
void setSpilledIn(std::vector<MachineBasicBlock *> BBV) {
97+
SpilledIn = std::move(BBV);
98+
}
99+
void setRestoredIn(std::vector<MachineBasicBlock *> BBV) {
100+
RestoredIn = std::move(BBV);
101+
}
75102
};
76103

77104
/// The MachineFrameInfo class represents an abstract stack frame until
@@ -295,6 +322,10 @@ class MachineFrameInfo {
295322
/// Has CSInfo been set yet?
296323
bool CSIValid = false;
297324

325+
CalleeSavedInfoPerBB CSInfoPerSave;
326+
327+
CalleeSavedInfoPerBB CSInfoPerRestore;
328+
298329
/// References to frame indices which are mapped
299330
/// into the local frame allocation block. <FrameIdx, LocalOffset>
300331
SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects;
@@ -331,9 +362,16 @@ class MachineFrameInfo {
331362
bool HasTailCall = false;
332363

333364
/// Not null, if shrink-wrapping found a better place for the prologue.
334-
MachineBasicBlock *Save = nullptr;
365+
MachineBasicBlock *Prolog = nullptr;
335366
/// Not null, if shrink-wrapping found a better place for the epilogue.
336-
MachineBasicBlock *Restore = nullptr;
367+
MachineBasicBlock *Epilog = nullptr;
368+
369+
/// Not empty, if shrink-wrapping found a better place for saving callee
370+
/// saves.
371+
SaveRestorePoints SavePoints;
372+
/// Not empty, if shrink-wrapping found a better place for restoring callee
373+
/// saves.
374+
SaveRestorePoints RestorePoints;
337375

338376
/// Size of the UnsafeStack Frame
339377
uint64_t UnsafeStackSize = 0;
@@ -809,21 +847,105 @@ class MachineFrameInfo {
809847
/// \copydoc getCalleeSavedInfo()
810848
std::vector<CalleeSavedInfo> &getCalleeSavedInfo() { return CSInfo; }
811849

850+
/// Returns callee saved info vector for provided save point in
851+
/// the current function.
852+
std::vector<CalleeSavedInfo> getCSInfoPerSave(MachineBasicBlock *MBB) const {
853+
return CSInfoPerSave.get(MBB);
854+
}
855+
856+
/// Returns callee saved info vector for provided restore point
857+
/// in the current function.
858+
std::vector<CalleeSavedInfo>
859+
getCSInfoPerRestore(MachineBasicBlock *MBB) const {
860+
return CSInfoPerRestore.get(MBB);
861+
}
862+
812863
/// Used by prolog/epilog inserter to set the function's callee saved
813864
/// information.
814865
void setCalleeSavedInfo(std::vector<CalleeSavedInfo> CSI) {
815866
CSInfo = std::move(CSI);
816867
}
817868

869+
/// Used by prolog/epilog inserter to set the function's callee saved
870+
/// information for particular save point.
871+
void setCSInfoPerSave(
872+
DenseMap<MachineBasicBlock *, std::vector<CalleeSavedInfo>> CSI) {
873+
CSInfoPerSave.set(CSI);
874+
}
875+
876+
/// Used by prolog/epilog inserter to set the function's callee saved
877+
/// information for particular restore point.
878+
void setCSInfoPerRestore(
879+
DenseMap<MachineBasicBlock *, std::vector<CalleeSavedInfo>> CSI) {
880+
CSInfoPerRestore.set(CSI);
881+
}
882+
818883
/// Has the callee saved info been calculated yet?
819884
bool isCalleeSavedInfoValid() const { return CSIValid; }
820885

821886
void setCalleeSavedInfoValid(bool v) { CSIValid = v; }
822887

823-
MachineBasicBlock *getSavePoint() const { return Save; }
824-
void setSavePoint(MachineBasicBlock *NewSave) { Save = NewSave; }
825-
MachineBasicBlock *getRestorePoint() const { return Restore; }
826-
void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; }
888+
const SaveRestorePoints &getRestorePoints() const { return RestorePoints; }
889+
890+
const SaveRestorePoints &getSavePoints() const { return SavePoints; }
891+
892+
std::pair<MachineBasicBlock *, std::vector<Register>>
893+
getRestorePoint(MachineBasicBlock *MBB) const {
894+
if (auto It = RestorePoints.find(MBB); It != RestorePoints.end())
895+
return *It;
896+
897+
std::vector<Register> Regs = {};
898+
return std::make_pair(nullptr, Regs);
899+
}
900+
901+
std::pair<MachineBasicBlock *, std::vector<Register>>
902+
getSavePoint(MachineBasicBlock *MBB) const {
903+
if (auto It = SavePoints.find(MBB); It != SavePoints.end())
904+
return *It;
905+
906+
std::vector<Register> Regs = {};
907+
return std::make_pair(nullptr, Regs);
908+
}
909+
910+
void setSavePoints(SaveRestorePoints NewSavePoints) {
911+
SavePoints = std::move(NewSavePoints);
912+
}
913+
914+
void setRestorePoints(SaveRestorePoints NewRestorePoints) {
915+
RestorePoints = std::move(NewRestorePoints);
916+
}
917+
918+
void setSavePoint(MachineBasicBlock *MBB, std::vector<Register> &Regs) {
919+
if (SavePoints.contains(MBB))
920+
SavePoints[MBB] = Regs;
921+
else
922+
SavePoints.insert(std::make_pair(MBB, Regs));
923+
}
924+
925+
static const SaveRestorePoints constructSaveRestorePoints(
926+
const SaveRestorePoints &SRP,
927+
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &BBMap) {
928+
SaveRestorePoints Pts{};
929+
for (auto &Src : SRP) {
930+
Pts.insert(std::make_pair(BBMap.find(Src.first)->second, Src.second));
931+
}
932+
return Pts;
933+
}
934+
935+
void setRestorePoint(MachineBasicBlock *MBB, std::vector<Register> &Regs) {
936+
if (RestorePoints.contains(MBB))
937+
RestorePoints[MBB] = Regs;
938+
else
939+
RestorePoints.insert(std::make_pair(MBB, Regs));
940+
}
941+
942+
MachineBasicBlock *getProlog() const { return Prolog; }
943+
void setProlog(MachineBasicBlock *BB) { Prolog = BB; }
944+
MachineBasicBlock *getEpilog() const { return Epilog; }
945+
void setEpilog(MachineBasicBlock *BB) { Epilog = BB; }
946+
947+
void clearSavePoints() { SavePoints.clear(); }
948+
void clearRestorePoints() { RestorePoints.clear(); }
827949

828950
uint64_t getUnsafeStackSize() const { return UnsafeStackSize; }
829951
void setUnsafeStackSize(uint64_t Size) { UnsafeStackSize = Size; }

llvm/lib/CodeGen/MIRParser/MIRParser.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,20 +1056,32 @@ bool MIRParserImpl::initializeConstantPool(PerFunctionMIParsingState &PFS,
10561056
bool MIRParserImpl::initializeSaveRestorePoints(
10571057
PerFunctionMIParsingState &PFS, const yaml::SaveRestorePoints &YamlSRP,
10581058
bool IsSavePoints) {
1059+
SMDiagnostic Error;
10591060
MachineFunction &MF = PFS.MF;
10601061
MachineFrameInfo &MFI = MF.getFrameInfo();
1062+
llvm::SaveRestorePoints SRPoints;
10611063

1062-
if (!YamlSRP.empty()) {
1063-
const auto &Entry = YamlSRP.front();
1064+
for (const auto &Entry : YamlSRP) {
10641065
const auto &MBBSource = Entry.Point;
10651066
MachineBasicBlock *MBB = nullptr;
10661067
if (parseMBBReference(PFS, MBB, MBBSource.Value))
10671068
return true;
1068-
if (IsSavePoints)
1069-
MFI.setSavePoint(MBB);
1070-
else
1071-
MFI.setRestorePoint(MBB);
1069+
1070+
std::vector<Register> Registers{};
1071+
for (auto &RegStr : Entry.Registers) {
1072+
Register Reg;
1073+
if (parseNamedRegisterReference(PFS, Reg, RegStr.Value, Error))
1074+
return error(Error, RegStr.SourceRange);
1075+
1076+
Registers.push_back(Reg);
1077+
}
1078+
SRPoints.insert(std::make_pair(MBB, Registers));
10721079
}
1080+
1081+
if (IsSavePoints)
1082+
MFI.setSavePoints(SRPoints);
1083+
else
1084+
MFI.setRestorePoints(SRPoints);
10731085
return false;
10741086
}
10751087

llvm/lib/CodeGen/MIRPrinter.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,10 @@ class MIRPrinter {
117117
const MachineRegisterInfo &RegInfo,
118118
const TargetRegisterInfo *TRI);
119119
void convert(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
120-
const MachineFrameInfo &MFI);
120+
const MachineFrameInfo &MFI, const TargetRegisterInfo *TRI);
121121
void convert(ModuleSlotTracker &MST, yaml::SaveRestorePoints &YamlSRP,
122-
MachineBasicBlock *SaveRestorePoint);
122+
const DenseMap<MachineBasicBlock *, std::vector<Register>> &SRP,
123+
const TargetRegisterInfo *TRI);
123124
void convert(yaml::MachineFunction &MF,
124125
const MachineConstantPool &ConstantPool);
125126
void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
@@ -237,7 +238,8 @@ void MIRPrinter::print(const MachineFunction &MF) {
237238
convert(YamlMF, MF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
238239
MachineModuleSlotTracker MST(MMI, &MF);
239240
MST.incorporateFunction(MF.getFunction());
240-
convert(MST, YamlMF.FrameInfo, MF.getFrameInfo());
241+
convert(MST, YamlMF.FrameInfo, MF.getFrameInfo(),
242+
MF.getSubtarget().getRegisterInfo());
241243
convertStackObjects(YamlMF, MF, MST);
242244
convertEntryValueObjects(YamlMF, MF, MST);
243245
convertCallSiteObjects(YamlMF, MF, MST);
@@ -374,7 +376,8 @@ void MIRPrinter::convert(yaml::MachineFunction &YamlMF,
374376

375377
void MIRPrinter::convert(ModuleSlotTracker &MST,
376378
yaml::MachineFrameInfo &YamlMFI,
377-
const MachineFrameInfo &MFI) {
379+
const MachineFrameInfo &MFI,
380+
const TargetRegisterInfo *TRI) {
378381
YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken();
379382
YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken();
380383
YamlMFI.HasStackMap = MFI.hasStackMap();
@@ -394,10 +397,10 @@ void MIRPrinter::convert(ModuleSlotTracker &MST,
394397
YamlMFI.HasTailCall = MFI.hasTailCall();
395398
YamlMFI.IsCalleeSavedInfoValid = MFI.isCalleeSavedInfoValid();
396399
YamlMFI.LocalFrameSize = MFI.getLocalFrameSize();
397-
if (MFI.getSavePoint())
398-
convert(MST, YamlMFI.SavePoints, MFI.getSavePoint());
399-
if (MFI.getRestorePoint())
400-
convert(MST, YamlMFI.RestorePoints, MFI.getRestorePoint());
400+
if (!MFI.getSavePoints().empty())
401+
convert(MST, YamlMFI.SavePoints, MFI.getSavePoints(), TRI);
402+
if (!MFI.getRestorePoints().empty())
403+
convert(MST, YamlMFI.RestorePoints, MFI.getRestorePoints(), TRI);
401404
}
402405

403406
void MIRPrinter::convertEntryValueObjects(yaml::MachineFunction &YMF,
@@ -618,14 +621,24 @@ void MIRPrinter::convert(yaml::MachineFunction &MF,
618621

619622
void MIRPrinter::convert(ModuleSlotTracker &MST,
620623
yaml::SaveRestorePoints &YamlSRP,
621-
MachineBasicBlock *SRP) {
622-
std::string Str;
623-
yaml::SRPEntry Entry;
624-
raw_string_ostream StrOS(Str);
625-
StrOS << printMBBReference(*SRP);
626-
Entry.Point = StrOS.str();
627-
Str.clear();
628-
YamlSRP.push_back(Entry);
624+
const SaveRestorePoints &SRP,
625+
const TargetRegisterInfo *TRI) {
626+
for (const auto &MBBEntry : SRP) {
627+
std::string Str;
628+
yaml::SRPEntry Entry;
629+
raw_string_ostream StrOS(Str);
630+
StrOS << printMBBReference(*MBBEntry.first);
631+
Entry.Point = StrOS.str();
632+
Str.clear();
633+
for (auto &Reg : MBBEntry.second) {
634+
if (Reg != MCRegister::NoRegister) {
635+
StrOS << printReg(Reg, TRI);
636+
Entry.Registers.push_back(StrOS.str());
637+
Str.clear();
638+
}
639+
}
640+
YamlSRP.push_back(Entry);
641+
}
629642
}
630643

631644
void MIRPrinter::convert(ModuleSlotTracker &MST,

llvm/lib/CodeGen/MachineFrameInfo.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,23 @@ void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{
244244
}
245245
OS << "\n";
246246
}
247+
248+
OS << "save/restore points:\n";
249+
250+
if (!SavePoints.empty()) {
251+
OS << "save points:\n";
252+
253+
for (auto &item : SavePoints)
254+
OS << printMBBReference(*item.first) << "\n";
255+
} else
256+
OS << "save points are empty\n";
257+
258+
if (!RestorePoints.empty()) {
259+
OS << "restore points:\n";
260+
for (auto &item : RestorePoints)
261+
OS << printMBBReference(*item.first) << "\n";
262+
} else
263+
OS << "restore points are empty\n";
247264
}
248265

249266
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

0 commit comments

Comments
 (0)