38#include "llvm/CodeGen/MachineInstr.h"
39#include "llvm/CodeGen/MachineBasicBlock.h"
40#include "llvm/CodeGen/MachineFunction.h"
41#include "tce_config.h"
42#include "llvm/CodeGen/TargetRegisterInfo.h"
43#include "llvm/IR/Function.h"
44#include <llvm/CodeGen/TargetSubtargetInfo.h>
67 llvm::MachineFunction& mf,
70 std::string(mf.getFunction().getName().str()) +
"_middg", true),
71 onlyTrueDeps_(onlyTrueDeps), mf_(mf),
72 regInfo_(mf_.getTarget().getSubtargetImpl(
73 mf_.getFunction())->getRegisterInfo())
74 , printOnlyCriticalPath_(
false) {
76 for (llvm::MachineFunction::const_iterator bbi = mf.begin();
77 bbi != mf.end(); ++bbi) {
78 const llvm::MachineBasicBlock& bb = *bbi;
79 for (llvm::MachineBasicBlock::const_iterator ii = bb.begin();
80 ii != bb.end(); ++ii) {
81 const llvm::MachineInstr& i = *ii;
87 for (
unsigned oi = 0; oi < i.getNumOperands(); ++oi) {
88 const llvm::MachineOperand& operand = i.getOperand(oi);
92 if (operand.isUndef()) {
97 if (operand.isImplicit()) {
102 if (llvm::Register::isPhysicalRegister(
109 <<
"found a phys reg " << operand.getReg()
111 if (operand.getType() == llvm::MachineOperand::MO_FrameIndex)
117 if (operand.isUse()) {
121 <<
"uses: " << operand.getReg() << std::endl;
123 }
else if (operand.isDef()) {
124 if (
definers_[operand.getReg()] != NULL) {
127 if (
definers_[operand.getReg()]->machineInstr()->
128 getParent() != &bb) {
131 <<
"found a potential back edge case, "
132 <<
"using the definer from another BB"
143 <<
"unknown operand " << oi << std::endl;
158 for (std::set<MIDDGNode*>::iterator u = users.begin(); u != users.end();
165 <<
"ignoring edge that would create a loop"
183 std::string(parent.name(), true)),
184 onlyTrueDeps_(parent.onlyTrueDeps_), mf_(parent.mf_) {
201std::pair<MIDDGNode*, MIDDGNode*>
205 std::pair<MIDDGNode*, MIDDGNode*> none = std::make_pair(null, null);
237 source = lastPhysRegUser;
247 if (lastPhysRegDefiner != NULL) {
248 dest = lastPhysRegDefiner;
250 dest = lastPhysRegUser;
256 if (dest != source &&
hasPath(*dest, *source))
259 return std::make_pair(source, dest);
283 std::pair<MIDDGNode*, MIDDGNode*> fdep =
286 int hdelta = INT_MIN;
287 if (fdep.first != NULL && fdep.second != NULL) {
288 if (fdep.first == fdep.second)
304 for (NodeSet::const_iterator i = users.begin(); i != users.end();
307 if (lastUse < node->sequentialAddress()) {
308 lastUse =
node->sequentialAddress();
327 for (NodeSet::const_iterator i = pred.begin(); i != pred.end(); ++i) {
330 for (
unsigned operand = 0; operand < instr->getNumOperands();
332 const llvm::MachineOperand& mo = instr->getOperand(operand);
335 if (mo.getReg() == physReg ||
342 if (instr->readsRegister(physReg) ||
343 instr->modifiesRegister(physReg,
regInfo_)) {
360 for (
int nc = 0; nc <
nodeCount(); ++nc) {
371 std::ostringstream s;
372 s <<
"digraph " <<
name() <<
" {" << std::endl;
374 const bool scheduled =
nodeCount() > 1 &&
node(0).optimalCycle() != -1;
378 s <<
"\t{" << std::endl
379 <<
"\t\tnode [shape=plaintext];" << std::endl
383 for (
int c = smallest; c <= largest; ++c) {
384 s <<
"\"cycle " << c <<
"\" -> ";
386 s <<
"\"cycle " << largest + 1 <<
"\"; "
387 << std::endl <<
"\t}" << std::endl;
390 for (
int c = smallest; c <= largest; ++c) {
391 std::list<MIDDGNode*> ops =
schedule_[c];
392 if (ops.size() > 0) {
393 s <<
"\t{ rank = same; \"cycle " << c <<
"\"; ";
394 for (std::list<MIDDGNode*>::iterator i = ops.begin();
395 i != ops.end(); ++i) {
401 s <<
"n" << n.
nodeID() <<
"; ";
403 s <<
"}" << std::endl;
408 typedef std::map<TCEString, int> OpCountMap;
412 OpCountMap maxParallelOps;
415 OpCountMap operationMix;
417 for (
int c = smallest; c <= largest; ++c) {
418 std::list<MIDDGNode*> ops =
schedule_[c];
419 if (ops.size() == 0)
continue;
421 std::map<TCEString, int> parallelOpsAtCycle;
422 for (std::list<MIDDGNode*>::iterator i = ops.begin();
423 i != ops.end(); ++i) {
426 if (opName ==
"" || opName ==
"?jump")
continue;
427 operationMix[opName]++;
428 parallelOpsAtCycle[opName]++;
431 for (OpCountMap::const_iterator i = parallelOpsAtCycle.begin();
432 i != parallelOpsAtCycle.end(); ++i) {
434 int count = (*i).second;
435 maxParallelOps[opName] =
436 std::max(maxParallelOps[opName], count);
440 const int COL_WIDTH = 14;
442 s <<
"/* statistics: " << std::endl << std::endl;
443 s << std::setw(COL_WIDTH) << std::right <<
"virtual regs: ";
444 s <<
definers_.size() << std::endl << std::endl;
445 s << std::setw(COL_WIDTH) << std::right <<
"operation stats: ";
446 s << std::endl << std::endl;
448 for (OpCountMap::const_iterator i = maxParallelOps.begin();
449 i != maxParallelOps.end(); ++i) {
451 int parCount = (*i).second;
452 int total = operationMix[opName];
453 s << std::setw(COL_WIDTH) << std::right << opName +
": ";
454 s << std::setw(COL_WIDTH) << std::right << total;
455 s <<
" total, " << std::setw(COL_WIDTH) << std::right
456 << parCount <<
" at most in parallel" << std::endl;
458 s <<
"*/" << std::endl;
471 s <<
",shape=box,color=\"red\"";
472 s <<
"]; " << std::endl;
476 for (
int count =
edgeCount(), i = 0; i < count ; ++i) {
485 s <<
"\tn" << tail.
nodeID() <<
" -> n"
490 s <<
"];" << std::endl;
493 s <<
"}" << std::endl;
514 if (lastDefiner == NULL ||
517 lastDefiner = previousDefiner;
520 if (lastDefiner != NULL) {
531 if (lastUser == NULL ||
537 if (lastUser != NULL) {
541 std::pair<MIDDGNode*, MIDDGNode*> fdep =
544 if (fdep.first != NULL && fdep.second != NULL &&
545 fdep.first != fdep.second) {
551 << fdep.first->sequentialAddress() <<
" to "
552 << fdep.second->sequentialAddress() << std::endl;
567 const llvm::TargetInstrInfo *TII =
570 machineInstr()->getParent()->getParent()->getFunction())->
576 if (
mi_->isInlineAsm()) {
577 unsigned numDefs = 0;
578 while (
mi_->getOperand(numDefs).isReg() &&
579 mi_->getOperand(numDefs).isDef())
581 opName =
mi_->getOperand(numDefs).getSymbolName();
583 opName = TII->getName(
mi_->getOpcode()).str();
590 for (
size_t i = 0; i < opName.size(); ++i) {
591 if (upper[i] == opName[i])
592 cleaned += opName[i];
#define assert(condition)
#define IGNORE_COMPILER_WARNING(X)
#define POP_COMPILER_DIAGS
find Finds info of the inner loops in the false
static std::ostream & logStream()
int maxSourceDistance(const MIDDGNode &node) const
virtual Node & headNode(const Edge &edge) const
virtual void addNode(Node &node)
Node & node(const int index) const
bool hasNode(const Node &) const
virtual const TCEString & name() const
bool hasPath(MIDDGNode &src, const MIDDGNode &dest) const
std::set< MIDDGNode *, typename GraphNode::Comparator > NodeSet
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
bool isInCriticalPath(const MIDDGNode &node) const
virtual Node & tailNode(const Edge &edge) const
virtual Edge & edge(const int index) const
virtual void connectNodes(const Node &nTail, const Node &nHead, Edge &e)
virtual TCEString toString() const
const llvm::TargetRegisterInfo * regInfo_
bool preceedingNodeUsesOrDefinesReg(const MIDDGNode &node, Register physReg) const
TCEString dotString() const
std::pair< MIDDGNode *, MIDDGNode * > createFalseDepEdge(Register vreg, Register physReg) const
int falseDepHeightDelta(Register vreg, Register physReg) const
void computeOptimalSchedule()
std::map< int, std::list< MIDDGNode * > > schedule_
std::map< Register, MIDDGNode * > lastPhysRegDefiners_
MIDDGNode * lastVregUser(Register vreg) const
std::set< MIDDGEdge * > edges_
virtual ~MachineInstrDDG()
MachineInstrDDG(const MachineInstrDDG &parent)
RegisterMap regAssignments_
void assignPhysReg(Register vreg, Register physReg)
MIDDGNode * vregDefiner(Register vreg) const
std::map< Register, MIDDGNode * > lastPhysRegUsers_
bool printOnlyCriticalPath_
RegisterSet allRegisters_
Operation & operation(const char *name)
TCEString dotString() const
int sequentialAddress() const
const llvm::MachineInstr * machineInstr() const
TCEString osalOperationName() const
std::string dotString() const
void setOptimalCycle(int cycle)
const llvm::MachineInstr * mi_