Index: include/llvm/Target/TargetInstrInfo.h =================================================================== --- include/llvm/Target/TargetInstrInfo.h (revision 149586) +++ include/llvm/Target/TargetInstrInfo.h (working copy) @@ -17,6 +17,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/CodeGen/DFAPacketizer.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/ScheduleDAG.h" namespace llvm { @@ -818,6 +819,18 @@ return NULL; } + /// isLegalToPacketizeTogether - Ask the target if SUnits SUI and SUJ can + /// be packetized together. + virtual bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) const { + return false; + } + + /// isLegalToPruneDependencies - Ask the target if dependency between SUnits + /// SUI and SUJ can be pruned. + virtual bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) const { + return false; + } + private: int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h (revision 149586) +++ include/llvm/CodeGen/Passes.h (working copy) @@ -140,6 +140,10 @@ /// scheduling. FunctionPass *createPostRAScheduler(CodeGenOpt::Level OptLevel); + /// createVLIWPacketizer - This pass performs instruction packetization + /// on VLIW machines. + FunctionPass *createVLIWPacketizer(CodeGenOpt::Level OptLevel); + /// BranchFolding Pass - This pass performs machine code CFG based /// optimizations to delete branches to branches, eliminate branches to /// successor blocks (creating fall throughs), and eliminating branches over Index: lib/CodeGen/VLIWPacketizer.cpp =================================================================== --- lib/CodeGen/VLIWPacketizer.cpp (revision 0) +++ lib/CodeGen/VLIWPacketizer.cpp (revision 0) @@ -0,0 +1,271 @@ +//===----- VLIWPacketizer.cpp - VLIW Packetizer ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file 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 the current packet and +// machine resource is marked as taken. If any dependency is found, a target API +// call is made to prune the dependence. The current packed is closed and I is +// added to a new packet if dependency cannot be pruned. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "vliw-packet" +#include "ScheduleDAGInstrs.h" +#include "llvm/CodeGen/DFAPacketizer.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumBundles, "Number of BUNDLE instructions"); + +namespace { + class VLIWPacketizer : public MachineFunctionPass { + CodeGenOpt::Level OptLevel; + + public: + static char ID; + VLIWPacketizer(CodeGenOpt::Level ol) : + MachineFunctionPass(ID), OptLevel(ol) {} + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + const char *getPassName() const { + return "Target VLIW Packetizer"; + } + + bool runOnMachineFunction(MachineFunction &Fn); + }; + char VLIWPacketizer::ID = 0; + + class VLIWPacketizerList : public ScheduleDAGInstrs { + const TargetMachine &TM; + const TargetInstrInfo *TII; + // Vector of instructions assigned to the current packet. + std::vector CurrentPacketMIs; + DFAPacketizer *ResourceTracker; + + public: + VLIWPacketizerList( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT); + + ~VLIWPacketizerList(); + + // Schedule - Implement list based VLIW scheduler. + void Schedule(); + + // PacketizeMIs - Implement VLIW packetizer to bundle instructions. + void PacketizeMIs(MachineBasicBlock *MBB, + MachineBasicBlock::iterator BeginItr, + MachineBasicBlock::iterator EndItr); + + // getResourceTracker - return ResourceTracker + DFAPacketizer *getResourceTracker() {return ResourceTracker;} + + private: + // 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); + }; +} + +VLIWPacketizerList::VLIWPacketizerList( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT) + : ScheduleDAGInstrs(MF, MLI, MDT, true), TM(MF.getTarget()) +{ + TII = TM.getInstrInfo(); + ResourceTracker = TII->CreateTargetScheduleState(&TM, 0); +} + +VLIWPacketizerList::~VLIWPacketizerList() { + if (ResourceTracker) + delete ResourceTracker; +} + +bool VLIWPacketizer::runOnMachineFunction(MachineFunction &Fn) { + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + MachineLoopInfo &MLI = getAnalysis(); + MachineDominatorTree &MDT = getAnalysis(); + + // Instantiate the packetizer. + VLIWPacketizerList Packetizer(Fn, MLI, MDT); + + // If DFA state table is empty, return early. + if (!Packetizer.getResourceTracker()) + return false; + + // Loop over all of the basic blocks. + for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); + MBB != MBBe; ++MBB) { + // Find scheduling regions and schedule / packetize each region. + unsigned RemainingCount = MBB->size(); + for(MachineBasicBlock::iterator RegionEnd = MBB->end(); + RegionEnd != MBB->begin();) { + // The next region starts above the previous region. Look backward in the + // instruction stream until we find the nearest boundary. + MachineBasicBlock::iterator I = RegionEnd; + for(;I != MBB->begin(); --I, --RemainingCount) { + if (TII->isSchedulingBoundary(llvm::prior(I), MBB, Fn)) + break; + } + + // Skip empty scheduling regions. + if (I == RegionEnd) { + RegionEnd = llvm::prior(RegionEnd); + --RemainingCount; + continue; + } + // Skip regions with one instruction. + if (I == llvm::prior(RegionEnd)) { + RegionEnd = llvm::prior(RegionEnd); + continue; + } + + // Run the scheduler. + Packetizer.Run(MBB, I, RegionEnd, MBB->size()); + // Now we have dependency information, create VLIW bundles. + Packetizer.PacketizeMIs(MBB, I, RegionEnd); + + // Prepare for the next region. + RegionEnd = Packetizer.Begin; + } // For each scheduling region in BB + } // For eacho BB + + return true; +} + +/// Schedule - Schedule the DAG using list scheduling. +/// +void VLIWPacketizerList::Schedule() { + // Build the scheduling graph. + BuildSchedGraph(0); +} + +/// PacketizeMIs - Bundle machine instructions into packets. +/// +void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB, + MachineBasicBlock::iterator BeginItr, + MachineBasicBlock::iterator EndItr) { + // 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; + + // Inline ASM ends packet. + if (MI->isInlineAsm()) { + 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!"); + + // Ask the target if MI and MJ can go together in the same packet. + if (!TII->isLegalToPacketizeTogether(SUI, SUJ)) { + // Ask the target if dependency between MI and MJ can be pruned. + if (!TII->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); +} + +/// 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; +} + +/// AddToPakcet - 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); + ++NumBundles; + } + CurrentPacketMIs.clear(); + ResourceTracker->clearResources(); +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createVLIWPacketizer(CodeGenOpt::Level OptLevel) { + return new VLIWPacketizer(OptLevel); +} + Index: lib/CodeGen/LLVMTargetMachine.cpp =================================================================== --- lib/CodeGen/LLVMTargetMachine.cpp (revision 149586) +++ lib/CodeGen/LLVMTargetMachine.cpp (working copy) @@ -87,6 +87,9 @@ static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); +static cl::opt EnableVLIWPacketizer("vliw-packetizer", cl::Hidden, + cl::desc("Enable VLIW Packetizer"), + cl::init(false)); static cl::opt AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), @@ -511,5 +514,10 @@ if (addPreEmitPass(PM)) printNoVerify(PM, "After PreEmit passes"); + // Run the vliw packetizer to create bundles. + if (getOptLevel() != CodeGenOpt::None && EnableVLIWPacketizer) { + PM.add(createVLIWPacketizer(getOptLevel())); + printNoVerify(PM, "After VLIW packetizer"); + } return false; }