#ifndef LLVM_CODEGEN_MODULOSCHEDULE_H
#define LLVM_CODEGEN_MODULOSCHEDULE_H
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineLoopUtils.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include <deque>
#include <vector>
namespace llvm {
class MachineBasicBlock;
class MachineLoop;
class MachineRegisterInfo;
class MachineInstr;
class LiveIntervals;
class ModuloSchedule {
private:
MachineLoop *Loop;
std::vector<MachineInstr *> ScheduledInstrs;
DenseMap<MachineInstr *, int> Cycle;
DenseMap<MachineInstr *, int> Stage;
int NumStages;
public:
ModuloSchedule(MachineFunction &MF, MachineLoop *Loop,
std::vector<MachineInstr *> ScheduledInstrs,
DenseMap<MachineInstr *, int> Cycle,
DenseMap<MachineInstr *, int> Stage)
: Loop(Loop), ScheduledInstrs(ScheduledInstrs), Cycle(std::move(Cycle)),
Stage(std::move(Stage)) {
NumStages = 0;
for (auto &KV : this->Stage)
NumStages = std::max(NumStages, KV.second);
++NumStages;
}
MachineLoop *getLoop() const { return Loop; }
int getNumStages() const { return NumStages; }
int getFirstCycle() { return Cycle[ScheduledInstrs.front()]; }
int getFinalCycle() { return Cycle[ScheduledInstrs.back()]; }
int getStage(MachineInstr *MI) {
auto I = Stage.find(MI);
return I == Stage.end() ? -1 : I->second;
}
int getCycle(MachineInstr *MI) {
auto I = Cycle.find(MI);
return I == Cycle.end() ? -1 : I->second;
}
void setStage(MachineInstr *MI, int MIStage) {
assert(Stage.count(MI) == 0);
Stage[MI] = MIStage;
}
ArrayRef<MachineInstr *> getInstructions() { return ScheduledInstrs; }
void dump() { print(dbgs()); }
void print(raw_ostream &OS);
};
class ModuloScheduleExpander {
public:
using InstrChangesTy = DenseMap<MachineInstr *, std::pair<unsigned, int64_t>>;
private:
using ValueMapTy = DenseMap<unsigned, unsigned>;
using MBBVectorTy = SmallVectorImpl<MachineBasicBlock *>;
using InstrMapTy = DenseMap<MachineInstr *, MachineInstr *>;
ModuloSchedule &Schedule;
MachineFunction &MF;
const TargetSubtargetInfo &ST;
MachineRegisterInfo &MRI;
const TargetInstrInfo *TII;
LiveIntervals &LIS;
MachineBasicBlock *BB;
MachineBasicBlock *Preheader;
MachineBasicBlock *NewKernel = nullptr;
std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo> LoopInfo;
std::map<unsigned, std::pair<unsigned, bool>> RegToStageDiff;
InstrChangesTy InstrChanges;
void generatePipelinedLoop();
void generateProlog(unsigned LastStage, MachineBasicBlock *KernelBB,
ValueMapTy *VRMap, MBBVectorTy &PrologBBs);
void generateEpilog(unsigned LastStage, MachineBasicBlock *KernelBB,
MachineBasicBlock *OrigBB, ValueMapTy *VRMap,
MBBVectorTy &EpilogBBs, MBBVectorTy &PrologBBs);
void generateExistingPhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1,
MachineBasicBlock *BB2, MachineBasicBlock *KernelBB,
ValueMapTy *VRMap, InstrMapTy &InstrMap,
unsigned LastStageNum, unsigned CurStageNum,
bool IsLast);
void generatePhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1,
MachineBasicBlock *BB2, MachineBasicBlock *KernelBB,
ValueMapTy *VRMap, InstrMapTy &InstrMap,
unsigned LastStageNum, unsigned CurStageNum, bool IsLast);
void removeDeadInstructions(MachineBasicBlock *KernelBB,
MBBVectorTy &EpilogBBs);
void splitLifetimes(MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs);
void addBranches(MachineBasicBlock &PreheaderBB, MBBVectorTy &PrologBBs,
MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs,
ValueMapTy *VRMap);
bool computeDelta(MachineInstr &MI, unsigned &Delta);
void updateMemOperands(MachineInstr &NewMI, MachineInstr &OldMI,
unsigned Num);
MachineInstr *cloneInstr(MachineInstr *OldMI, unsigned CurStageNum,
unsigned InstStageNum);
MachineInstr *cloneAndChangeInstr(MachineInstr *OldMI, unsigned CurStageNum,
unsigned InstStageNum);
void updateInstruction(MachineInstr *NewMI, bool LastDef,
unsigned CurStageNum, unsigned InstrStageNum,
ValueMapTy *VRMap);
MachineInstr *findDefInLoop(unsigned Reg);
unsigned getPrevMapVal(unsigned StageNum, unsigned PhiStage, unsigned LoopVal,
unsigned LoopStage, ValueMapTy *VRMap,
MachineBasicBlock *BB);
void rewritePhiValues(MachineBasicBlock *NewBB, unsigned StageNum,
ValueMapTy *VRMap, InstrMapTy &InstrMap);
void rewriteScheduledInstr(MachineBasicBlock *BB, InstrMapTy &InstrMap,
unsigned CurStageNum, unsigned PhiNum,
MachineInstr *Phi, unsigned OldReg,
unsigned NewReg, unsigned PrevReg = 0);
bool isLoopCarried(MachineInstr &Phi);
unsigned getStagesForReg(int Reg, unsigned CurStage) {
std::pair<unsigned, bool> Stages = RegToStageDiff[Reg];
if ((int)CurStage > Schedule.getNumStages() - 1 && Stages.first == 0 &&
Stages.second)
return 1;
return Stages.first;
}
unsigned getStagesForPhi(int Reg) {
std::pair<unsigned, bool> Stages = RegToStageDiff[Reg];
if (Stages.second)
return Stages.first;
return Stages.first - 1;
}
public:
ModuloScheduleExpander(MachineFunction &MF, ModuloSchedule &S,
LiveIntervals &LIS, InstrChangesTy InstrChanges)
: Schedule(S), MF(MF), ST(MF.getSubtarget()), MRI(MF.getRegInfo()),
TII(ST.getInstrInfo()), LIS(LIS),
InstrChanges(std::move(InstrChanges)) {}
void expand();
void cleanup();
MachineBasicBlock *getRewrittenKernel() { return NewKernel; }
};
class PeelingModuloScheduleExpander {
public:
PeelingModuloScheduleExpander(MachineFunction &MF, ModuloSchedule &S,
LiveIntervals *LIS)
: Schedule(S), MF(MF), ST(MF.getSubtarget()), MRI(MF.getRegInfo()),
TII(ST.getInstrInfo()), LIS(LIS) {}
void expand();
void validateAgainstModuloScheduleExpander();
protected:
ModuloSchedule &Schedule;
MachineFunction &MF;
const TargetSubtargetInfo &ST;
MachineRegisterInfo &MRI;
const TargetInstrInfo *TII;
LiveIntervals *LIS;
MachineBasicBlock *BB;
MachineBasicBlock *Preheader;
SmallVector<MachineBasicBlock *, 4> Prologs, Epilogs;
DenseMap<MachineBasicBlock *, BitVector> LiveStages;
DenseMap<MachineBasicBlock *, BitVector> AvailableStages;
DenseMap<MachineInstr *, unsigned> PhiNodeLoopIteration;
DenseMap<MachineInstr *, MachineInstr *> CanonicalMIs;
DenseMap<std::pair<MachineBasicBlock *, MachineInstr *>, MachineInstr *>
BlockMIs;
std::deque<MachineBasicBlock *> PeeledFront, PeeledBack;
SmallVector<MachineInstr *, 4> IllegalPhisToDelete;
void rewriteKernel();
MachineBasicBlock *peelKernel(LoopPeelDirection LPD);
void filterInstructions(MachineBasicBlock *MB, int MinStage);
void moveStageBetweenBlocks(MachineBasicBlock *DestBB,
MachineBasicBlock *SourceBB, unsigned Stage);
void peelPrologAndEpilogs();
Register getEquivalentRegisterIn(Register Reg, MachineBasicBlock *BB);
void rewriteUsesOf(MachineInstr *MI);
void fixupBranches();
MachineBasicBlock *CreateLCSSAExitingBlock();
unsigned getStage(MachineInstr *MI) {
if (CanonicalMIs.count(MI))
MI = CanonicalMIs[MI];
return Schedule.getStage(MI);
}
Register getPhiCanonicalReg(MachineInstr* CanonicalPhi, MachineInstr* Phi);
std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo> LoopInfo;
};
class ModuloScheduleTestAnnotater {
MachineFunction &MF;
ModuloSchedule &S;
public:
ModuloScheduleTestAnnotater(MachineFunction &MF, ModuloSchedule &S)
: MF(MF), S(S) {}
void annotate();
};
}
#endif