ScheduleDAGInstrs.cpp revision fc626b62b877beec1cc3c0289eb794f28614e23f
1//===---- ScheduleDAG.cpp - Implement the ScheduleDAG class ---------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This implements the ScheduleDAG class, which is a base class used by 11// scheduling implementation classes. 12// 13//===----------------------------------------------------------------------===// 14 15#define DEBUG_TYPE "sched-instrs" 16#include "llvm/CodeGen/ScheduleDAGInstrs.h" 17#include "llvm/Target/TargetMachine.h" 18#include "llvm/Target/TargetInstrInfo.h" 19#include "llvm/Target/TargetRegisterInfo.h" 20#include "llvm/Support/Debug.h" 21#include "llvm/Support/raw_ostream.h" 22using namespace llvm; 23 24ScheduleDAGInstrs::ScheduleDAGInstrs(MachineBasicBlock *bb, 25 const TargetMachine &tm) 26 : ScheduleDAG(0, bb, tm) {} 27 28void ScheduleDAGInstrs::BuildSchedUnits() { 29 SUnits.clear(); 30 SUnits.reserve(BB->size()); 31 32 std::vector<SUnit *> PendingLoads; 33 SUnit *Terminator = 0; 34 SUnit *Chain = 0; 35 SUnit *Defs[TargetRegisterInfo::FirstVirtualRegister] = {}; 36 std::vector<SUnit *> Uses[TargetRegisterInfo::FirstVirtualRegister] = {}; 37 int Cost = 1; // FIXME 38 39 for (MachineBasicBlock::iterator MII = BB->end(), MIE = BB->begin(); 40 MII != MIE; --MII) { 41 MachineInstr *MI = prior(MII); 42 SUnit *SU = NewSUnit(MI); 43 44 for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) { 45 const MachineOperand &MO = MI->getOperand(j); 46 if (!MO.isReg()) continue; 47 unsigned Reg = MO.getReg(); 48 if (Reg == 0) continue; 49 50 assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!"); 51 std::vector<SUnit *> &UseList = Uses[Reg]; 52 SUnit *&Def = Defs[Reg]; 53 // Optionally add output and anti dependencies. 54 if (Def && Def != SU) 55 Def->addPred(SU, /*isCtrl=*/true, /*isArtificial=*/false, 56 /*PhyReg=*/Reg, Cost, /*isAntiDep=*/MO.isUse()); 57 for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { 58 SUnit *&Def = Defs[*Alias]; 59 if (Def && Def != SU) 60 Def->addPred(SU, /*isCtrl=*/true, /*isArtificial=*/false, 61 /*PhyReg=*/*Alias, Cost); 62 } 63 64 if (MO.isDef()) { 65 // Add any data dependencies. 66 for (unsigned i = 0, e = UseList.size(); i != e; ++i) 67 if (UseList[i] != SU) 68 UseList[i]->addPred(SU, /*isCtrl=*/false, /*isArtificial=*/false, 69 /*PhysReg=*/Reg, Cost); 70 for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { 71 std::vector<SUnit *> &UseList = Uses[*Alias]; 72 for (unsigned i = 0, e = UseList.size(); i != e; ++i) 73 if (UseList[i] != SU) 74 UseList[i]->addPred(SU, /*isCtrl=*/false, /*isArtificial=*/false, 75 /*PhysReg=*/*Alias, Cost); 76 } 77 78 UseList.clear(); 79 Def = SU; 80 } else { 81 UseList.push_back(SU); 82 } 83 } 84 bool False = false; 85 bool True = true; 86 if (!MI->isSafeToMove(TII, False)) { 87 if (Chain) 88 Chain->addPred(SU, /*isCtrl=*/false, /*isArtificial=*/false); 89 for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k) 90 PendingLoads[k]->addPred(SU, /*isCtrl=*/false, /*isArtificial=*/false); 91 PendingLoads.clear(); 92 Chain = SU; 93 } else if (!MI->isSafeToMove(TII, True)) { 94 if (Chain) 95 Chain->addPred(SU, /*isCtrl=*/false, /*isArtificial=*/false); 96 PendingLoads.push_back(SU); 97 } 98 if (Terminator && SU->Succs.empty()) 99 Terminator->addPred(SU, /*isCtrl=*/false, /*isArtificial=*/false); 100 if (MI->getDesc().isTerminator() || MI->isLabel()) 101 Terminator = SU; 102 103 // Assign the Latency field of SU using target-provided information. 104 ComputeLatency(SU); 105 } 106} 107 108void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) { 109 const InstrItineraryData &InstrItins = TM.getInstrItineraryData(); 110 111 // Compute the latency for the node. We use the sum of the latencies for 112 // all nodes flagged together into this SUnit. 113 SU->Latency = 114 InstrItins.getLatency(SU->getInstr()->getDesc().getSchedClass()); 115} 116 117void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const { 118 SU->getInstr()->dump(); 119} 120 121std::string ScheduleDAGInstrs::getGraphNodeLabel(const SUnit *SU) const { 122 std::string s; 123 raw_string_ostream oss(s); 124 SU->getInstr()->print(oss); 125 return oss.str(); 126} 127 128// EmitSchedule - Emit the machine code in scheduled order. 129MachineBasicBlock *ScheduleDAGInstrs::EmitSchedule() { 130 // For MachineInstr-based scheduling, we're rescheduling the instructions in 131 // the block, so start by removing them from the block. 132 while (!BB->empty()) 133 BB->remove(BB->begin()); 134 135 for (unsigned i = 0, e = Sequence.size(); i != e; i++) { 136 SUnit *SU = Sequence[i]; 137 if (!SU) { 138 // Null SUnit* is a noop. 139 EmitNoop(); 140 continue; 141 } 142 143 BB->push_back(SU->getInstr()); 144 } 145 146 return BB; 147} 148