#include "llvm/CodeGen/DFAPacketizer.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
using namespace llvm;
DFAPacketizer::DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2],
const unsigned *SET):
InstrItins(I), CurrentState(0), DFAStateInputTable(SIT),
DFAStateEntryTable(SET) {}
void DFAPacketizer::ReadTable(unsigned int state) {
unsigned ThisState = DFAStateEntryTable[state];
unsigned NextStateInTable = DFAStateEntryTable[state+1];
if (CachedTable.count(UnsignPair(state,
DFAStateInputTable[ThisState][0])))
return;
for (unsigned i = ThisState; i < NextStateInTable; i++)
CachedTable[UnsignPair(state, DFAStateInputTable[i][0])] =
DFAStateInputTable[i][1];
}
bool DFAPacketizer::canReserveResources(const llvm::MCInstrDesc *MID) {
unsigned InsnClass = MID->getSchedClass();
const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);
unsigned FuncUnits = IS->getUnits();
UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits);
ReadTable(CurrentState);
return (CachedTable.count(StateTrans) != 0);
}
void DFAPacketizer::reserveResources(const llvm::MCInstrDesc *MID) {
unsigned InsnClass = MID->getSchedClass();
const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);
unsigned FuncUnits = IS->getUnits();
UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits);
ReadTable(CurrentState);
assert(CachedTable.count(StateTrans) != 0);
CurrentState = CachedTable[StateTrans];
}
bool DFAPacketizer::canReserveResources(llvm::MachineInstr *MI) {
const llvm::MCInstrDesc &MID = MI->getDesc();
return canReserveResources(&MID);
}
void DFAPacketizer::reserveResources(llvm::MachineInstr *MI) {
const llvm::MCInstrDesc &MID = MI->getDesc();
reserveResources(&MID);
}
namespace {
class DefaultVLIWScheduler : public ScheduleDAGInstrs {
public:
DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI,
MachineDominatorTree &MDT, bool IsPostRA);
void schedule();
};
}
DefaultVLIWScheduler::DefaultVLIWScheduler(
MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT,
bool IsPostRA) :
ScheduleDAGInstrs(MF, MLI, MDT, IsPostRA) {
}
void DefaultVLIWScheduler::schedule() {
buildSchedGraph(0);
}
VLIWPacketizerList::VLIWPacketizerList(
MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT,
bool IsPostRA) : TM(MF.getTarget()), MF(MF) {
TII = TM.getInstrInfo();
ResourceTracker = TII->CreateTargetScheduleState(&TM, 0);
SchedulerImpl = new DefaultVLIWScheduler(MF, MLI, MDT, IsPostRA);
}
VLIWPacketizerList::~VLIWPacketizerList() {
delete SchedulerImpl;
delete ResourceTracker;
}
bool VLIWPacketizerList::ignorePseudoInstruction(MachineInstr *MI,
MachineBasicBlock *MBB) {
if (MI->isDebugValue())
return true;
if (TII->isSchedulingBoundary(MI, MBB, MF))
return true;
return false;
}
bool VLIWPacketizerList::isSoloInstruction(MachineInstr *I) {
if (I->isInlineAsm())
return true;
return false;
}
void VLIWPacketizerList::addToPacket(MachineInstr *MI) {
CurrentPacketMIs.push_back(MI);
ResourceTracker->reserveResources(MI);
}
void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB,
MachineInstr *I) {
if (CurrentPacketMIs.size() > 1) {
MachineInstr *MIFirst = CurrentPacketMIs.front();
finalizeBundle(*MBB, MIFirst, I);
}
CurrentPacketMIs.clear();
ResourceTracker->clearResources();
}
void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB,
MachineBasicBlock::iterator BeginItr,
MachineBasicBlock::iterator EndItr) {
assert(MBB->end() == EndItr && "Bad EndIndex");
SchedulerImpl->enterRegion(MBB, BeginItr, EndItr, MBB->size());
SchedulerImpl->schedule();
SUnits = SchedulerImpl->SUnits;
for (; BeginItr != EndItr; ++BeginItr) {
MachineInstr *MI = BeginItr;
if (ignorePseudoInstruction(MI, MBB))
continue;
if (isSoloInstruction(MI)) {
endPacket(MBB, MI);
continue;
}
SUnit *SUI = SchedulerImpl->getSUnit(MI);
assert(SUI && "Missing SUnit Info!");
bool ResourceAvail = ResourceTracker->canReserveResources(MI);
if (ResourceAvail) {
for (std::vector<MachineInstr*>::iterator VI = CurrentPacketMIs.begin(),
VE = CurrentPacketMIs.end(); VI != VE; ++VI) {
MachineInstr *MJ = *VI;
SUnit *SUJ = SchedulerImpl->getSUnit(MJ);
assert(SUJ && "Missing SUnit Info!");
if (!isLegalToPacketizeTogether(SUI, SUJ)) {
if (!isLegalToPruneDependencies(SUI, SUJ)) {
endPacket(MBB, MI);
break;
} } } } else {
endPacket(MBB, MI);
}
addToPacket(MI);
}
endPacket(MBB, EndItr);
SchedulerImpl->exitRegion();
}