Index: include/llvm/CodeGen/DFAPacketizer.h =================================================================== --- include/llvm/CodeGen/DFAPacketizer.h (revision 149586) +++ include/llvm/CodeGen/DFAPacketizer.h (working copy) @@ -26,13 +26,18 @@ #ifndef LLVM_CODEGEN_DFAPACKETIZER_H #define LLVM_CODEGEN_DFAPACKETIZER_H +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/ADT/DenseMap.h" namespace llvm { class MCInstrDesc; class MachineInstr; +class MachineLoopInfo; +class MachineDominatorTree; class InstrItineraryData; +class DefaultVLIWScheduler; +class SUnit; class DFAPacketizer { private: @@ -73,6 +78,70 @@ // instruction and change the current state to reflect that change. void reserveResources(llvm::MachineInstr *MI); }; + +// VLIWPacketizerList - Implements a simple VLIW packetizer using DFA. The +// packetizer works on machine basic blocks. For each instruction I in BB, the +// packetizer consults the DFA to see if machine resources are available to +// execute I. If so, the packetizer checks if I depends on any instruction J in +// the current packet. If no dependency is found, I is added to current packet +// and machine resource is marked as taken. If any dependency is found, a target +// API call is made to prune the dependence. +class VLIWPacketizerList { + const TargetMachine &TM; + const MachineFunction &MF; + const TargetInstrInfo *TII; + + // The VLIW Scheduler. + DefaultVLIWScheduler *VLIWScheduler; + +protected: + // Vector of instructions assigned to the current packet. + std::vector CurrentPacketMIs; + // DFA resource tracker. + DFAPacketizer *ResourceTracker; + // Scheduling units. + std::vector SUnits; + +public: + VLIWPacketizerList( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, + bool IsPostRA); + + virtual ~VLIWPacketizerList(); + + // PacketizeMIs - Implement this API in the backend to bundle instructions. + void PacketizeMIs(MachineBasicBlock *MBB, + MachineBasicBlock::iterator BeginItr, + MachineBasicBlock::iterator EndItr); + + // getResourceTracker - return ResourceTracker + DFAPacketizer *getResourceTracker() {return ResourceTracker;} + + // addToPacket - Add MI to the current packet. + void addToPacket(MachineInstr *MI); + + // endPacket - End the current packet. + void endPacket(MachineBasicBlock *MBB, MachineInstr *I); + + // ignorePseudoInstruction - Ignore bundling of pseudo instructions. + bool ignorePseudoInstruction(MachineInstr *I, MachineBasicBlock *MBB); + + // isSoloInstruction - return true if instruction I must end previous + // packet. + bool isSoloInstruction(MachineInstr *I); + + // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ + // together. + virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) { + return false; + } + + // isLegalToPruneDependencies - Is it legal to prune dependece between SUI + // and SUJ. + virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) { + return false; + } +}; } #endif Index: lib/CodeGen/DFAPacketizer.cpp =================================================================== --- lib/CodeGen/DFAPacketizer.cpp (revision 149586) +++ lib/CodeGen/DFAPacketizer.cpp (working copy) @@ -23,8 +23,11 @@ // //===----------------------------------------------------------------------===// +#include "ScheduleDAGInstrs.h" #include "llvm/CodeGen/DFAPacketizer.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Target/TargetInstrInfo.h" #include "llvm/MC/MCInstrItineraries.h" using namespace llvm; @@ -96,3 +99,150 @@ const llvm::MCInstrDesc &MID = MI->getDesc(); reserveResources(&MID); } + +namespace llvm { +// DefaultVLIWScheduler - This class extends ScheduleDAGInstrs and overrides +// Schedule method to build the dependence graph. +class DefaultVLIWScheduler : public ScheduleDAGInstrs { +public: + DefaultVLIWScheduler(MachineFunction &MF, MachineLoopInfo &MLI, + MachineDominatorTree &MDT, bool IsPostRA); + // Schedule - Actual scheduling work. + void Schedule(); +}; +} + +DefaultVLIWScheduler::DefaultVLIWScheduler( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, + bool IsPostRA) : + ScheduleDAGInstrs(MF, MLI, MDT, IsPostRA) { +} + +void DefaultVLIWScheduler::Schedule() { + // Build the scheduling graph. + BuildSchedGraph(0); +} + +// VLIWPacketizerList Ctor +VLIWPacketizerList::VLIWPacketizerList( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, + bool IsPostRA) : TM(MF.getTarget()), MF(MF) { + TII = TM.getInstrInfo(); + ResourceTracker = TII->CreateTargetScheduleState(&TM, 0); + VLIWScheduler = new DefaultVLIWScheduler(MF, MLI, MDT, IsPostRA); +} + +// VLIWPacketizerList Dtor +VLIWPacketizerList::~VLIWPacketizerList() { + if (VLIWScheduler) + delete VLIWScheduler; + + if (ResourceTracker) + delete ResourceTracker; +} + +// ignorePseudoInstruction - ignore pseudo instructions. +bool VLIWPacketizerList::ignorePseudoInstruction(MachineInstr *MI, + MachineBasicBlock *MBB) { + if (MI->isDebugValue()) + return true; + + if (TII->isSchedulingBoundary(MI, MBB, MF)) + return true; + + return false; +} + +// isSoloInstruction - return true if instruction I must end previous +// packet. +bool VLIWPacketizerList::isSoloInstruction(MachineInstr *I) { + if (I->isInlineAsm()) + return true; + + return false; +} + +// addToPacket - Add I to the current packet and reserve resource. +void VLIWPacketizerList::addToPacket(MachineInstr *MI) { + CurrentPacketMIs.push_back(MI); + ResourceTracker->reserveResources(MI); +} + +// endPacket - End the current packet, bundle packet instructions and reset +// DFA state. +void VLIWPacketizerList::endPacket(MachineBasicBlock *MBB, + MachineInstr *I) { + if (CurrentPacketMIs.size() > 1) { + MachineInstr *MIFirst = CurrentPacketMIs.front(); + finalizeBundle(*MBB, MIFirst, I); + } + CurrentPacketMIs.clear(); + ResourceTracker->clearResources(); +} + +// PacketizeMIs - Bundle machine instructions into packets. +void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB, + MachineBasicBlock::iterator BeginItr, + MachineBasicBlock::iterator EndItr) { + assert(VLIWScheduler && "VLIW Scheduler is not initialized!"); + VLIWScheduler->Run(MBB, BeginItr, EndItr, MBB->size()); + + // Remember scheduling units. + SUnits = VLIWScheduler->SUnits; + + // Generate MI -> SU map. + std::map MIToSUnit; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + SUnit *SU = &SUnits[i]; + MIToSUnit[SU->getInstr()] = SU; + } + + // The main packetizer loop. + for (; BeginItr != EndItr; ++BeginItr) { + MachineInstr *MI = BeginItr; + + // Ignore pseudo instructions. + if (ignorePseudoInstruction(MI, MBB)) + continue; + + // End the current packet if needed. + if (isSoloInstruction(MI)) { + endPacket(MBB, MI); + continue; + } + + SUnit *SUI = MIToSUnit[MI]; + assert(SUI && "Missing SUnit Info!"); + + // Ask DFA if machine resource is available for MI. + bool ResourceAvail = ResourceTracker->canReserveResources(MI); + if (ResourceAvail) { + // Dependency check for MI with instructions in CurrentPacketMIs. + for (std::vector::iterator VI = CurrentPacketMIs.begin(), + VE = CurrentPacketMIs.end(); VI != VE; ++VI) { + MachineInstr *MJ = *VI; + SUnit *SUJ = MIToSUnit[MJ]; + assert(SUJ && "Missing SUnit Info!"); + + // Is it legal to packetize SUI and SUJ together. + if (!isLegalToPacketizeTogether(SUI, SUJ)) { + // Allow packetization if dependency can be pruned. + if (!isLegalToPruneDependencies(SUI, SUJ)) { + // End the packet if dependency cannot be pruned. + endPacket(MBB, MI); + break; + } // !isLegalToPruneDependencies. + } // !isLegalToPacketizeTogether. + } // For all instructions in CurrentPacketMIs. + } else { + // End the packet if resource is not available. + endPacket(MBB, MI); + } + + // Add MI to the current packet. + addToPacket(MI); + } // For all instructions in BB. + + // End any packet left behind. + endPacket(MBB, EndItr); +}