File indexing completed on 2026-05-10 08:43:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CODEGEN_MACHINEOUTLINER_H
0016 #define LLVM_CODEGEN_MACHINEOUTLINER_H
0017
0018 #include "llvm/CodeGen/LiveRegUnits.h"
0019 #include "llvm/CodeGen/MachineFunction.h"
0020 #include "llvm/CodeGen/MachineRegisterInfo.h"
0021 #include "llvm/CodeGen/MachineStableHash.h"
0022 #include <initializer_list>
0023
0024 namespace llvm {
0025 namespace outliner {
0026
0027
0028
0029
0030
0031
0032
0033
0034 enum InstrType { Legal, LegalTerminator, Illegal, Invisible };
0035
0036
0037
0038 struct Candidate {
0039 private:
0040
0041 unsigned StartIdx = 0;
0042
0043
0044 unsigned Len = 0;
0045
0046
0047 MachineBasicBlock::iterator FirstInst;
0048
0049
0050 MachineBasicBlock::iterator LastInst;
0051
0052
0053 MachineBasicBlock *MBB = nullptr;
0054
0055
0056
0057 unsigned CallOverhead = 0;
0058
0059
0060
0061
0062
0063
0064 LiveRegUnits FromEndOfBlockToStartOfSeq;
0065
0066
0067
0068
0069
0070 LiveRegUnits InSeq;
0071
0072
0073 bool FromEndOfBlockToStartOfSeqWasSet = false;
0074
0075
0076 bool InSeqWasSet = false;
0077
0078
0079 void initFromEndOfBlockToStartOfSeq(const TargetRegisterInfo &TRI) {
0080 assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
0081 "Candidate's Machine Function must track liveness");
0082
0083 if (FromEndOfBlockToStartOfSeqWasSet)
0084 return;
0085 FromEndOfBlockToStartOfSeqWasSet = true;
0086 FromEndOfBlockToStartOfSeq.init(TRI);
0087 FromEndOfBlockToStartOfSeq.addLiveOuts(*MBB);
0088
0089
0090 for (auto &MI : make_range(MBB->rbegin(),
0091 (MachineBasicBlock::reverse_iterator)begin()))
0092 FromEndOfBlockToStartOfSeq.stepBackward(MI);
0093 }
0094
0095
0096 void initInSeq(const TargetRegisterInfo &TRI) {
0097 assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
0098 "Candidate's Machine Function must track liveness");
0099
0100 if (InSeqWasSet)
0101 return;
0102 InSeqWasSet = true;
0103 InSeq.init(TRI);
0104 for (auto &MI : *this)
0105 InSeq.accumulate(MI);
0106 }
0107
0108 public:
0109
0110
0111 unsigned FunctionIdx = 0;
0112
0113
0114
0115 unsigned CallConstructionID = 0;
0116
0117
0118 unsigned Flags = 0x0;
0119
0120
0121 unsigned getLength() const { return Len; }
0122
0123
0124 unsigned getStartIdx() const { return StartIdx; }
0125
0126
0127 unsigned getEndIdx() const { return StartIdx + Len - 1; }
0128
0129
0130
0131 void setCallInfo(unsigned CID, unsigned CO) {
0132 CallConstructionID = CID;
0133 CallOverhead = CO;
0134 }
0135
0136
0137 unsigned getCallOverhead() const { return CallOverhead; }
0138
0139 MachineBasicBlock::iterator begin() { return FirstInst; }
0140 MachineBasicBlock::iterator end() { return std::next(LastInst); }
0141
0142 MachineInstr &front() { return *FirstInst; }
0143 MachineInstr &back() { return *LastInst; }
0144 MachineFunction *getMF() const { return MBB->getParent(); }
0145 MachineBasicBlock *getMBB() const { return MBB; }
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 bool isAvailableAcrossAndOutOfSeq(Register Reg,
0160 const TargetRegisterInfo &TRI) {
0161 if (!FromEndOfBlockToStartOfSeqWasSet)
0162 initFromEndOfBlockToStartOfSeq(TRI);
0163 return FromEndOfBlockToStartOfSeq.available(Reg);
0164 }
0165
0166
0167
0168 bool isAnyUnavailableAcrossOrOutOfSeq(std::initializer_list<Register> Regs,
0169 const TargetRegisterInfo &TRI) {
0170 if (!FromEndOfBlockToStartOfSeqWasSet)
0171 initFromEndOfBlockToStartOfSeq(TRI);
0172 return any_of(Regs, [&](Register Reg) {
0173 return !FromEndOfBlockToStartOfSeq.available(Reg);
0174 });
0175 }
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185 bool isAvailableInsideSeq(Register Reg, const TargetRegisterInfo &TRI) {
0186 if (!InSeqWasSet)
0187 initInSeq(TRI);
0188 return InSeq.available(Reg);
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198 unsigned Benefit = 0;
0199
0200 Candidate(unsigned StartIdx, unsigned Len,
0201 MachineBasicBlock::iterator &FirstInst,
0202 MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB,
0203 unsigned FunctionIdx, unsigned Flags)
0204 : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst),
0205 MBB(MBB), FunctionIdx(FunctionIdx), Flags(Flags) {}
0206 Candidate() = delete;
0207
0208
0209
0210 bool operator<(const Candidate &RHS) const {
0211 return getStartIdx() > RHS.getStartIdx();
0212 }
0213
0214 };
0215
0216
0217
0218 struct OutlinedFunction {
0219
0220 public:
0221 std::vector<Candidate> Candidates;
0222
0223
0224
0225 MachineFunction *MF = nullptr;
0226
0227
0228
0229 unsigned SequenceSize = 0;
0230
0231
0232 unsigned FrameOverhead = 0;
0233
0234
0235 unsigned FrameConstructionID = 0;
0236
0237
0238 virtual unsigned getOccurrenceCount() const { return Candidates.size(); }
0239
0240
0241
0242 virtual unsigned getOutliningCost() const {
0243 unsigned CallOverhead = 0;
0244 for (const Candidate &C : Candidates)
0245 CallOverhead += C.getCallOverhead();
0246 return CallOverhead + SequenceSize + FrameOverhead;
0247 }
0248
0249
0250 unsigned getNotOutlinedCost() const {
0251 return getOccurrenceCount() * SequenceSize;
0252 }
0253
0254
0255
0256 unsigned getBenefit() const {
0257 unsigned NotOutlinedCost = getNotOutlinedCost();
0258 unsigned OutlinedCost = getOutliningCost();
0259 return (NotOutlinedCost < OutlinedCost) ? 0
0260 : NotOutlinedCost - OutlinedCost;
0261 }
0262
0263
0264 unsigned getNumInstrs() const { return Candidates[0].getLength(); }
0265
0266 OutlinedFunction(std::vector<Candidate> &Candidates, unsigned SequenceSize,
0267 unsigned FrameOverhead, unsigned FrameConstructionID)
0268 : Candidates(Candidates), SequenceSize(SequenceSize),
0269 FrameOverhead(FrameOverhead), FrameConstructionID(FrameConstructionID) {
0270 const unsigned B = getBenefit();
0271 for (Candidate &C : Candidates)
0272 C.Benefit = B;
0273 }
0274
0275 OutlinedFunction() = delete;
0276 virtual ~OutlinedFunction() = default;
0277 };
0278
0279
0280
0281 struct GlobalOutlinedFunction : public OutlinedFunction {
0282 explicit GlobalOutlinedFunction(std::unique_ptr<OutlinedFunction> OF,
0283 unsigned GlobalOccurrenceCount)
0284 : OutlinedFunction(*OF), GlobalOccurrenceCount(GlobalOccurrenceCount) {}
0285
0286 unsigned GlobalOccurrenceCount;
0287
0288
0289
0290
0291
0292 unsigned getOccurrenceCount() const override {
0293 assert(Candidates.size() <= 1);
0294 return Candidates.empty() ? 0 : GlobalOccurrenceCount;
0295 }
0296
0297
0298
0299 unsigned getOutliningCost() const override {
0300 assert(Candidates.size() <= 1);
0301 unsigned CallOverhead =
0302 Candidates.empty()
0303 ? 0
0304 : Candidates[0].getCallOverhead() * getOccurrenceCount();
0305 return CallOverhead + SequenceSize + FrameOverhead;
0306 }
0307
0308 GlobalOutlinedFunction() = delete;
0309 ~GlobalOutlinedFunction() = default;
0310 };
0311
0312 }
0313 }
0314
0315 #endif