Major change to how defs are found when adding dependences (they

are now found as part of the initial walk of the machine code).
Also memory load/store instructions can be generated for non-memory
LLVM instructions, which wasn't handled before.  It is now.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1199 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vikram S. Adve 2001-11-08 05:20:23 +00:00
parent af1d2c80e0
commit e64574ce71
4 changed files with 138 additions and 342 deletions

View File

@ -446,98 +446,64 @@ static const unsigned int SG_DepOrderArray[][3] = {
}; };
// Add a dependence edge between every pair of machine load/store/call
// instructions, where at least one is a store or a call.
// Use latency 1 just to ensure that memory operations are ordered;
// latency does not otherwise matter (true dependences enforce that).
//
void void
SchedGraph::addMemEdges(const vector<const Instruction*>& memVec, SchedGraph::addMemEdges(const vector<SchedGraphNode*>& memNodeVec,
const TargetMachine& target) const TargetMachine& target)
{ {
const MachineInstrInfo& mii = target.getInstrInfo(); const MachineInstrInfo& mii = target.getInstrInfo();
for (unsigned im=0, NM=memVec.size(); im < NM; im++) // Instructions in memNodeVec are in execution order within the basic block,
// so simply look at all pairs <memNodeVec[i], memNodeVec[j: j > i]>.
//
for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++)
{ {
const Instruction* fromInstr = memVec[im]; MachineOpCode fromOpCode = memNodeVec[im]->getOpCode();
int fromType = (fromInstr->getOpcode() == Instruction::Call int fromType = mii.isCall(fromOpCode)? SG_CALL_REF
? SG_CALL_REF : mii.isLoad(fromOpCode)? SG_LOAD_REF
: (fromInstr->getOpcode() == Instruction::Load : SG_STORE_REF;
? SG_LOAD_REF
: SG_STORE_REF));
for (unsigned jm=im+1; jm < NM; jm++) for (unsigned jm=im+1; jm < NM; jm++)
{ {
const Instruction* toInstr = memVec[jm]; MachineOpCode toOpCode = memNodeVec[jm]->getOpCode();
int toType = (fromInstr->getOpcode() == Instruction::Call? 2 int toType = mii.isCall(toOpCode)? SG_CALL_REF
: ((fromInstr->getOpcode()==Instruction::Load)? 0:1)); : mii.isLoad(toOpCode)? SG_LOAD_REF
: SG_STORE_REF;
if (fromType == SG_LOAD_REF && toType == SG_LOAD_REF) if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF)
continue; (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
SchedGraphEdge::MemoryDep,
unsigned int depOrderType = SG_DepOrderArray[fromType][toType]; SG_DepOrderArray[fromType][toType], 1);
}
MachineCodeForVMInstr& fromInstrMvec=fromInstr->getMachineInstrVec();
MachineCodeForVMInstr& toInstrMvec = toInstr->getMachineInstrVec();
// We have two VM memory instructions, and at least one is a store
// or a call. Add edges between all machine load/store/call instrs.
// Use a latency of 1 to ensure that memory operations are ordered;
// latency does not otherwise matter (true dependences enforce that).
//
for (unsigned i=0, N=fromInstrMvec.size(); i < N; i++)
{
MachineOpCode fromOpCode = fromInstrMvec[i]->getOpCode();
if (mii.isLoad(fromOpCode) || mii.isStore(fromOpCode) ||
mii.isCall(fromOpCode))
{
SchedGraphNode* fromNode =
this->getGraphNodeForInstr(fromInstrMvec[i]);
assert(fromNode && "No node for memory instr?");
for (unsigned j=0, M=toInstrMvec.size(); j < M; j++)
{
MachineOpCode toOpCode = toInstrMvec[j]->getOpCode();
if (mii.isLoad(toOpCode) || mii.isStore(toOpCode)
|| mii.isCall(fromOpCode))
{
SchedGraphNode* toNode =
this->getGraphNodeForInstr(toInstrMvec[j]);
assert(toNode && "No node for memory instr?");
(void) new SchedGraphEdge(fromNode, toNode,
SchedGraphEdge::MemoryDep,
depOrderType, 1);
}
}
}
}
}
} }
} }
// Add edges from/to CC reg instrs to/from call instrs.
// Essentially this prevents anything that sets or uses a CC reg from being
// reordered w.r.t. a call.
// Use a latency of 0 because we only need to prevent out-of-order issue,
// like with control dependences.
//
void void
SchedGraph::addCallCCEdges(const vector<const Instruction*>& memVec, SchedGraph::addCallCCEdges(const vector<SchedGraphNode*>& memNodeVec,
MachineCodeForBasicBlock& bbMvec, MachineCodeForBasicBlock& bbMvec,
const TargetMachine& target) const TargetMachine& target)
{ {
const MachineInstrInfo& mii = target.getInstrInfo(); const MachineInstrInfo& mii = target.getInstrInfo();
vector<SchedGraphNode*> callNodeVec; vector<SchedGraphNode*> callNodeVec;
// Find the call machine instructions and put them in a vector. // Find the call instruction nodes and put them in a vector.
// By using memVec, we avoid searching the entire machine code of the BB. for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++)
// if (mii.isCall(memNodeVec[im]->getOpCode()))
for (unsigned im=0, NM=memVec.size(); im < NM; im++) callNodeVec.push_back(memNodeVec[im]);
if (memVec[im]->getOpcode() == Instruction::Call)
{
MachineCodeForVMInstr& callMvec=memVec[im]->getMachineInstrVec();
for (unsigned i=0; i < callMvec.size(); ++i)
if (mii.isCall(callMvec[i]->getOpCode()))
callNodeVec.push_back(this->getGraphNodeForInstr(callMvec[i]));
}
// Now add additional edges from/to CC reg instrs to/from call instrs. // Now walk the entire basic block, looking for CC instructions *and*
// Essentially this prevents anything that sets or uses a CC reg from being // call instructions, and keep track of the order of the instructions.
// reordered w.r.t. a call. // Use the call node vec to quickly find earlier and later call nodes
// Use a latency of 0 because we only need to prevent out-of-order issue, // relative to the current CC instruction.
// like with control dependences.
// //
int lastCallNodeIdx = -1; int lastCallNodeIdx = -1;
for (unsigned i=0, N=bbMvec.size(); i < N; i++) for (unsigned i=0, N=bbMvec.size(); i < N; i++)
@ -610,81 +576,6 @@ SchedGraph::addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
} }
} }
#undef OLD_SSA_EDGE_CONSTRUCTION
#ifdef OLD_SSA_EDGE_CONSTRUCTION
//
// Delete this code once a few more tests pass.
//
inline void
CreateSSAEdge(SchedGraph* graph,
MachineInstr* defInstr,
SchedGraphNode* node,
const Value* val)
{
// this instruction does define value `val'.
// if there is a node for it in the same graph, add an edge.
SchedGraphNode* defNode = graph->getGraphNodeForInstr(defInstr);
if (defNode != NULL && defNode != node)
(void) new SchedGraphEdge(defNode, node, val);
}
void
SchedGraph::addSSAEdge(SchedGraphNode* destNode,
const Instruction* defVMInstr,
const Value* defValue,
const TargetMachine& target)
{
// Phi instructions are the only ones that produce a value but don't get
// any non-dummy machine instructions. Return here as an optimization.
//
if (isa<PHINode>(defVMInstr))
return;
// Now add the graph edge for the appropriate machine instruction(s).
// Note that multiple machine instructions generated for the
// def VM instruction may modify the register for the def value.
//
MachineCodeForVMInstr& defMvec = defVMInstr->getMachineInstrVec();
const MachineInstrInfo& mii = target.getInstrInfo();
for (unsigned i=0, N=defMvec.size(); i < N; i++)
{
bool edgeAddedForInstr = false;
// First check the explicit operands
for (int o=0, N=mii.getNumOperands(defMvec[i]->getOpCode()); o < N; o++)
{
const MachineOperand& defOp = defMvec[i]->getOperand(o);
if (defOp.opIsDef()
&& (defOp.getOperandType() == MachineOperand::MO_VirtualRegister
|| defOp.getOperandType() == MachineOperand::MO_CCRegister)
&& (defOp.getVRegValue() == defValue))
{
CreateSSAEdge(this, defMvec[i], destNode, defValue);
edgeAddedForInstr = true;
break;
}
}
// Then check the implicit operands
if (! edgeAddedForInstr)
{
for (unsigned o=0, N=defMvec[i]->getNumImplicitRefs(); o < N; ++o)
if (defMvec[i]->implicitRefIsDefined(o) &&
defMvec[i]->getImplicitRef(o) == defValue)
{
CreateSSAEdge(this, defMvec[i], destNode, defValue);
edgeAddedForInstr = true;
break;
}
}
}
}
#endif OLD_SSA_EDGE_CONSTRUCTION
void void
SchedGraph::addSSAEdge(SchedGraphNode* destNode, SchedGraph::addSSAEdge(SchedGraphNode* destNode,
@ -817,11 +708,17 @@ SchedGraph::addNonSSAEdgesForValue(const Instruction* instr,
void void
SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target, SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
SchedGraphNode* node, SchedGraphNode* node,
vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap) ValueToDefVecMap& valueToDefVecMap)
{ {
const MachineInstrInfo& mii = target.getInstrInfo(); const MachineInstrInfo& mii = target.getInstrInfo();
MachineOpCode opCode = node->getOpCode();
if (mii.isLoad(opCode) || mii.isStore(opCode) || mii.isCall(opCode))
memNodeVec.push_back(node);
// Collect the register references and value defs. for explicit operands // Collect the register references and value defs. for explicit operands
// //
const MachineInstr& minstr = * node->getMachineInstr(); const MachineInstr& minstr = * node->getMachineInstr();
@ -835,7 +732,8 @@ SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
{ {
int regNum = mop.getMachineRegNum(); int regNum = mop.getMachineRegNum();
if (regNum != target.getRegInfo().getZeroRegNum()) if (regNum != target.getRegInfo().getZeroRegNum())
regToRefVecMap[mop.getMachineRegNum()].push_back(make_pair(node, i)); regToRefVecMap[mop.getMachineRegNum()].push_back(make_pair(node,
i));
continue; // nothing more to do continue; // nothing more to do
} }
@ -869,7 +767,7 @@ SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
void void
SchedGraph::buildNodesforVMInstr(const TargetMachine& target, SchedGraph::buildNodesforVMInstr(const TargetMachine& target,
const Instruction* instr, const Instruction* instr,
vector<const Instruction*>& memVec, vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap) ValueToDefVecMap& valueToDefVecMap)
{ {
@ -883,14 +781,9 @@ SchedGraph::buildNodesforVMInstr(const TargetMachine& target,
this->noteGraphNodeForInstr(mvec[i], node); this->noteGraphNodeForInstr(mvec[i], node);
// Remember all register references and value defs // Remember all register references and value defs
findDefUseInfoAtInstr(target, node, regToRefVecMap, valueToDefVecMap); findDefUseInfoAtInstr(target, node,
memNodeVec, regToRefVecMap, valueToDefVecMap);
} }
// Remember load/store/call instructions to add memory deps later.
if (instr->getOpcode() == Instruction::Load ||
instr->getOpcode() == Instruction::Store ||
instr->getOpcode() == Instruction::Call)
memVec.push_back(instr);
} }
@ -908,10 +801,11 @@ SchedGraph::buildGraph(const TargetMachine& target)
// each Value. // each Value.
ValueToDefVecMap valueToDefVecMap; ValueToDefVecMap valueToDefVecMap;
// Use this data structure to note all LLVM memory instructions. // Use this data structure to note all memory instructions.
// We use this to add memory dependence edges without a second full walk. // We use this to add memory dependence edges without a second full walk.
// //
vector<const Instruction*> memVec; // vector<const Instruction*> memVec;
vector<SchedGraphNode*> memNodeVec;
// Use this data structure to note any uses or definitions of // Use this data structure to note any uses or definitions of
// machine registers so we can add edges for those later without // machine registers so we can add edges for those later without
@ -941,7 +835,7 @@ SchedGraph::buildGraph(const TargetMachine& target)
// Build graph nodes for this VM instruction and gather def/use info. // Build graph nodes for this VM instruction and gather def/use info.
// Do these together in a single pass over all machine instructions. // Do these together in a single pass over all machine instructions.
buildNodesforVMInstr(target, instr, buildNodesforVMInstr(target, instr,
memVec, regToRefVecMap, valueToDefVecMap); memNodeVec, regToRefVecMap, valueToDefVecMap);
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -967,10 +861,10 @@ SchedGraph::buildGraph(const TargetMachine& target)
// Then add memory dep edges: store->load, load->store, and store->store. // Then add memory dep edges: store->load, load->store, and store->store.
// Call instructions are treated as both load and store. // Call instructions are treated as both load and store.
this->addMemEdges(memVec, target); this->addMemEdges(memNodeVec, target);
// Then add edges between call instructions and CC set/use instructions // Then add edges between call instructions and CC set/use instructions
this->addCallCCEdges(memVec, bbMvec, target); this->addCallCCEdges(memNodeVec, bbMvec, target);
// Then add incoming def-use (SSA) edges for each machine instruction. // Then add incoming def-use (SSA) edges for each machine instruction.
for (unsigned i=0, N=bbMvec.size(); i < N; i++) for (unsigned i=0, N=bbMvec.size(); i < N; i++)

View File

@ -22,6 +22,8 @@
#include "llvm/Support/NonCopyable.h" #include "llvm/Support/NonCopyable.h"
#include "llvm/Support/HashExtras.h" #include "llvm/Support/HashExtras.h"
#include "llvm/Support/GraphTraits.h" #include "llvm/Support/GraphTraits.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include <hash_map> #include <hash_map>
class Value; class Value;
@ -159,6 +161,7 @@ public:
unsigned int getNodeId () const { return nodeId; } unsigned int getNodeId () const { return nodeId; }
const Instruction* getInstr () const { return instr; } const Instruction* getInstr () const { return instr; }
const MachineInstr* getMachineInstr () const { return minstr; } const MachineInstr* getMachineInstr () const { return minstr; }
const MachineOpCode getOpCode () const { return minstr->getOpCode();}
int getLatency () const { return latency; } int getLatency () const { return latency; }
unsigned int getNumInEdges () const { return inEdges.size(); } unsigned int getNumInEdges () const { return inEdges.size(); }
unsigned int getNumOutEdges () const { return outEdges.size(); } unsigned int getNumOutEdges () const { return outEdges.size(); }
@ -302,28 +305,29 @@ private:
void buildNodesforVMInstr (const TargetMachine& target, void buildNodesforVMInstr (const TargetMachine& target,
const Instruction* instr, const Instruction* instr,
vector<const Instruction*>& memVec, vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap); ValueToDefVecMap& valueToDefVecMap);
void findDefUseInfoAtInstr (const TargetMachine& target, void findDefUseInfoAtInstr (const TargetMachine& target,
SchedGraphNode* node, SchedGraphNode* node,
vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap); ValueToDefVecMap& valueToDefVecMap);
void addEdgesForInstruction (const MachineInstr& minstr, void addEdgesForInstruction(const MachineInstr& minstr,
const ValueToDefVecMap& valueToDefVecMap, const ValueToDefVecMap& valueToDefVecMap,
const TargetMachine& target); const TargetMachine& target);
void addCDEdges (const TerminatorInst* term, void addCDEdges (const TerminatorInst* term,
const TargetMachine& target); const TargetMachine& target);
void addMemEdges (const vector<const Instruction*>& memVec, void addMemEdges (const vector<SchedGraphNode*>& memNodeVec,
const TargetMachine& target); const TargetMachine& target);
void addCallCCEdges (const vector<const Instruction*>& memVec, void addCallCCEdges (const vector<SchedGraphNode*>& memNodeVec,
MachineCodeForBasicBlock& bbMvec, MachineCodeForBasicBlock& bbMvec,
const TargetMachine& target); const TargetMachine& target);
void addMachineRegEdges (RegToRefVecMap& regToRefVecMap, void addMachineRegEdges (RegToRefVecMap& regToRefVecMap,
const TargetMachine& target); const TargetMachine& target);

View File

@ -446,98 +446,64 @@ static const unsigned int SG_DepOrderArray[][3] = {
}; };
// Add a dependence edge between every pair of machine load/store/call
// instructions, where at least one is a store or a call.
// Use latency 1 just to ensure that memory operations are ordered;
// latency does not otherwise matter (true dependences enforce that).
//
void void
SchedGraph::addMemEdges(const vector<const Instruction*>& memVec, SchedGraph::addMemEdges(const vector<SchedGraphNode*>& memNodeVec,
const TargetMachine& target) const TargetMachine& target)
{ {
const MachineInstrInfo& mii = target.getInstrInfo(); const MachineInstrInfo& mii = target.getInstrInfo();
for (unsigned im=0, NM=memVec.size(); im < NM; im++) // Instructions in memNodeVec are in execution order within the basic block,
// so simply look at all pairs <memNodeVec[i], memNodeVec[j: j > i]>.
//
for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++)
{ {
const Instruction* fromInstr = memVec[im]; MachineOpCode fromOpCode = memNodeVec[im]->getOpCode();
int fromType = (fromInstr->getOpcode() == Instruction::Call int fromType = mii.isCall(fromOpCode)? SG_CALL_REF
? SG_CALL_REF : mii.isLoad(fromOpCode)? SG_LOAD_REF
: (fromInstr->getOpcode() == Instruction::Load : SG_STORE_REF;
? SG_LOAD_REF
: SG_STORE_REF));
for (unsigned jm=im+1; jm < NM; jm++) for (unsigned jm=im+1; jm < NM; jm++)
{ {
const Instruction* toInstr = memVec[jm]; MachineOpCode toOpCode = memNodeVec[jm]->getOpCode();
int toType = (fromInstr->getOpcode() == Instruction::Call? 2 int toType = mii.isCall(toOpCode)? SG_CALL_REF
: ((fromInstr->getOpcode()==Instruction::Load)? 0:1)); : mii.isLoad(toOpCode)? SG_LOAD_REF
: SG_STORE_REF;
if (fromType == SG_LOAD_REF && toType == SG_LOAD_REF) if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF)
continue; (void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
SchedGraphEdge::MemoryDep,
unsigned int depOrderType = SG_DepOrderArray[fromType][toType]; SG_DepOrderArray[fromType][toType], 1);
}
MachineCodeForVMInstr& fromInstrMvec=fromInstr->getMachineInstrVec();
MachineCodeForVMInstr& toInstrMvec = toInstr->getMachineInstrVec();
// We have two VM memory instructions, and at least one is a store
// or a call. Add edges between all machine load/store/call instrs.
// Use a latency of 1 to ensure that memory operations are ordered;
// latency does not otherwise matter (true dependences enforce that).
//
for (unsigned i=0, N=fromInstrMvec.size(); i < N; i++)
{
MachineOpCode fromOpCode = fromInstrMvec[i]->getOpCode();
if (mii.isLoad(fromOpCode) || mii.isStore(fromOpCode) ||
mii.isCall(fromOpCode))
{
SchedGraphNode* fromNode =
this->getGraphNodeForInstr(fromInstrMvec[i]);
assert(fromNode && "No node for memory instr?");
for (unsigned j=0, M=toInstrMvec.size(); j < M; j++)
{
MachineOpCode toOpCode = toInstrMvec[j]->getOpCode();
if (mii.isLoad(toOpCode) || mii.isStore(toOpCode)
|| mii.isCall(fromOpCode))
{
SchedGraphNode* toNode =
this->getGraphNodeForInstr(toInstrMvec[j]);
assert(toNode && "No node for memory instr?");
(void) new SchedGraphEdge(fromNode, toNode,
SchedGraphEdge::MemoryDep,
depOrderType, 1);
}
}
}
}
}
} }
} }
// Add edges from/to CC reg instrs to/from call instrs.
// Essentially this prevents anything that sets or uses a CC reg from being
// reordered w.r.t. a call.
// Use a latency of 0 because we only need to prevent out-of-order issue,
// like with control dependences.
//
void void
SchedGraph::addCallCCEdges(const vector<const Instruction*>& memVec, SchedGraph::addCallCCEdges(const vector<SchedGraphNode*>& memNodeVec,
MachineCodeForBasicBlock& bbMvec, MachineCodeForBasicBlock& bbMvec,
const TargetMachine& target) const TargetMachine& target)
{ {
const MachineInstrInfo& mii = target.getInstrInfo(); const MachineInstrInfo& mii = target.getInstrInfo();
vector<SchedGraphNode*> callNodeVec; vector<SchedGraphNode*> callNodeVec;
// Find the call machine instructions and put them in a vector. // Find the call instruction nodes and put them in a vector.
// By using memVec, we avoid searching the entire machine code of the BB. for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++)
// if (mii.isCall(memNodeVec[im]->getOpCode()))
for (unsigned im=0, NM=memVec.size(); im < NM; im++) callNodeVec.push_back(memNodeVec[im]);
if (memVec[im]->getOpcode() == Instruction::Call)
{
MachineCodeForVMInstr& callMvec=memVec[im]->getMachineInstrVec();
for (unsigned i=0; i < callMvec.size(); ++i)
if (mii.isCall(callMvec[i]->getOpCode()))
callNodeVec.push_back(this->getGraphNodeForInstr(callMvec[i]));
}
// Now add additional edges from/to CC reg instrs to/from call instrs. // Now walk the entire basic block, looking for CC instructions *and*
// Essentially this prevents anything that sets or uses a CC reg from being // call instructions, and keep track of the order of the instructions.
// reordered w.r.t. a call. // Use the call node vec to quickly find earlier and later call nodes
// Use a latency of 0 because we only need to prevent out-of-order issue, // relative to the current CC instruction.
// like with control dependences.
// //
int lastCallNodeIdx = -1; int lastCallNodeIdx = -1;
for (unsigned i=0, N=bbMvec.size(); i < N; i++) for (unsigned i=0, N=bbMvec.size(); i < N; i++)
@ -610,81 +576,6 @@ SchedGraph::addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
} }
} }
#undef OLD_SSA_EDGE_CONSTRUCTION
#ifdef OLD_SSA_EDGE_CONSTRUCTION
//
// Delete this code once a few more tests pass.
//
inline void
CreateSSAEdge(SchedGraph* graph,
MachineInstr* defInstr,
SchedGraphNode* node,
const Value* val)
{
// this instruction does define value `val'.
// if there is a node for it in the same graph, add an edge.
SchedGraphNode* defNode = graph->getGraphNodeForInstr(defInstr);
if (defNode != NULL && defNode != node)
(void) new SchedGraphEdge(defNode, node, val);
}
void
SchedGraph::addSSAEdge(SchedGraphNode* destNode,
const Instruction* defVMInstr,
const Value* defValue,
const TargetMachine& target)
{
// Phi instructions are the only ones that produce a value but don't get
// any non-dummy machine instructions. Return here as an optimization.
//
if (isa<PHINode>(defVMInstr))
return;
// Now add the graph edge for the appropriate machine instruction(s).
// Note that multiple machine instructions generated for the
// def VM instruction may modify the register for the def value.
//
MachineCodeForVMInstr& defMvec = defVMInstr->getMachineInstrVec();
const MachineInstrInfo& mii = target.getInstrInfo();
for (unsigned i=0, N=defMvec.size(); i < N; i++)
{
bool edgeAddedForInstr = false;
// First check the explicit operands
for (int o=0, N=mii.getNumOperands(defMvec[i]->getOpCode()); o < N; o++)
{
const MachineOperand& defOp = defMvec[i]->getOperand(o);
if (defOp.opIsDef()
&& (defOp.getOperandType() == MachineOperand::MO_VirtualRegister
|| defOp.getOperandType() == MachineOperand::MO_CCRegister)
&& (defOp.getVRegValue() == defValue))
{
CreateSSAEdge(this, defMvec[i], destNode, defValue);
edgeAddedForInstr = true;
break;
}
}
// Then check the implicit operands
if (! edgeAddedForInstr)
{
for (unsigned o=0, N=defMvec[i]->getNumImplicitRefs(); o < N; ++o)
if (defMvec[i]->implicitRefIsDefined(o) &&
defMvec[i]->getImplicitRef(o) == defValue)
{
CreateSSAEdge(this, defMvec[i], destNode, defValue);
edgeAddedForInstr = true;
break;
}
}
}
}
#endif OLD_SSA_EDGE_CONSTRUCTION
void void
SchedGraph::addSSAEdge(SchedGraphNode* destNode, SchedGraph::addSSAEdge(SchedGraphNode* destNode,
@ -817,11 +708,17 @@ SchedGraph::addNonSSAEdgesForValue(const Instruction* instr,
void void
SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target, SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
SchedGraphNode* node, SchedGraphNode* node,
vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap) ValueToDefVecMap& valueToDefVecMap)
{ {
const MachineInstrInfo& mii = target.getInstrInfo(); const MachineInstrInfo& mii = target.getInstrInfo();
MachineOpCode opCode = node->getOpCode();
if (mii.isLoad(opCode) || mii.isStore(opCode) || mii.isCall(opCode))
memNodeVec.push_back(node);
// Collect the register references and value defs. for explicit operands // Collect the register references and value defs. for explicit operands
// //
const MachineInstr& minstr = * node->getMachineInstr(); const MachineInstr& minstr = * node->getMachineInstr();
@ -835,7 +732,8 @@ SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
{ {
int regNum = mop.getMachineRegNum(); int regNum = mop.getMachineRegNum();
if (regNum != target.getRegInfo().getZeroRegNum()) if (regNum != target.getRegInfo().getZeroRegNum())
regToRefVecMap[mop.getMachineRegNum()].push_back(make_pair(node, i)); regToRefVecMap[mop.getMachineRegNum()].push_back(make_pair(node,
i));
continue; // nothing more to do continue; // nothing more to do
} }
@ -869,7 +767,7 @@ SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
void void
SchedGraph::buildNodesforVMInstr(const TargetMachine& target, SchedGraph::buildNodesforVMInstr(const TargetMachine& target,
const Instruction* instr, const Instruction* instr,
vector<const Instruction*>& memVec, vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap) ValueToDefVecMap& valueToDefVecMap)
{ {
@ -883,14 +781,9 @@ SchedGraph::buildNodesforVMInstr(const TargetMachine& target,
this->noteGraphNodeForInstr(mvec[i], node); this->noteGraphNodeForInstr(mvec[i], node);
// Remember all register references and value defs // Remember all register references and value defs
findDefUseInfoAtInstr(target, node, regToRefVecMap, valueToDefVecMap); findDefUseInfoAtInstr(target, node,
memNodeVec, regToRefVecMap, valueToDefVecMap);
} }
// Remember load/store/call instructions to add memory deps later.
if (instr->getOpcode() == Instruction::Load ||
instr->getOpcode() == Instruction::Store ||
instr->getOpcode() == Instruction::Call)
memVec.push_back(instr);
} }
@ -908,10 +801,11 @@ SchedGraph::buildGraph(const TargetMachine& target)
// each Value. // each Value.
ValueToDefVecMap valueToDefVecMap; ValueToDefVecMap valueToDefVecMap;
// Use this data structure to note all LLVM memory instructions. // Use this data structure to note all memory instructions.
// We use this to add memory dependence edges without a second full walk. // We use this to add memory dependence edges without a second full walk.
// //
vector<const Instruction*> memVec; // vector<const Instruction*> memVec;
vector<SchedGraphNode*> memNodeVec;
// Use this data structure to note any uses or definitions of // Use this data structure to note any uses or definitions of
// machine registers so we can add edges for those later without // machine registers so we can add edges for those later without
@ -941,7 +835,7 @@ SchedGraph::buildGraph(const TargetMachine& target)
// Build graph nodes for this VM instruction and gather def/use info. // Build graph nodes for this VM instruction and gather def/use info.
// Do these together in a single pass over all machine instructions. // Do these together in a single pass over all machine instructions.
buildNodesforVMInstr(target, instr, buildNodesforVMInstr(target, instr,
memVec, regToRefVecMap, valueToDefVecMap); memNodeVec, regToRefVecMap, valueToDefVecMap);
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -967,10 +861,10 @@ SchedGraph::buildGraph(const TargetMachine& target)
// Then add memory dep edges: store->load, load->store, and store->store. // Then add memory dep edges: store->load, load->store, and store->store.
// Call instructions are treated as both load and store. // Call instructions are treated as both load and store.
this->addMemEdges(memVec, target); this->addMemEdges(memNodeVec, target);
// Then add edges between call instructions and CC set/use instructions // Then add edges between call instructions and CC set/use instructions
this->addCallCCEdges(memVec, bbMvec, target); this->addCallCCEdges(memNodeVec, bbMvec, target);
// Then add incoming def-use (SSA) edges for each machine instruction. // Then add incoming def-use (SSA) edges for each machine instruction.
for (unsigned i=0, N=bbMvec.size(); i < N; i++) for (unsigned i=0, N=bbMvec.size(); i < N; i++)

View File

@ -22,6 +22,8 @@
#include "llvm/Support/NonCopyable.h" #include "llvm/Support/NonCopyable.h"
#include "llvm/Support/HashExtras.h" #include "llvm/Support/HashExtras.h"
#include "llvm/Support/GraphTraits.h" #include "llvm/Support/GraphTraits.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include <hash_map> #include <hash_map>
class Value; class Value;
@ -159,6 +161,7 @@ public:
unsigned int getNodeId () const { return nodeId; } unsigned int getNodeId () const { return nodeId; }
const Instruction* getInstr () const { return instr; } const Instruction* getInstr () const { return instr; }
const MachineInstr* getMachineInstr () const { return minstr; } const MachineInstr* getMachineInstr () const { return minstr; }
const MachineOpCode getOpCode () const { return minstr->getOpCode();}
int getLatency () const { return latency; } int getLatency () const { return latency; }
unsigned int getNumInEdges () const { return inEdges.size(); } unsigned int getNumInEdges () const { return inEdges.size(); }
unsigned int getNumOutEdges () const { return outEdges.size(); } unsigned int getNumOutEdges () const { return outEdges.size(); }
@ -302,28 +305,29 @@ private:
void buildNodesforVMInstr (const TargetMachine& target, void buildNodesforVMInstr (const TargetMachine& target,
const Instruction* instr, const Instruction* instr,
vector<const Instruction*>& memVec, vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap); ValueToDefVecMap& valueToDefVecMap);
void findDefUseInfoAtInstr (const TargetMachine& target, void findDefUseInfoAtInstr (const TargetMachine& target,
SchedGraphNode* node, SchedGraphNode* node,
vector<SchedGraphNode*>& memNodeVec,
RegToRefVecMap& regToRefVecMap, RegToRefVecMap& regToRefVecMap,
ValueToDefVecMap& valueToDefVecMap); ValueToDefVecMap& valueToDefVecMap);
void addEdgesForInstruction (const MachineInstr& minstr, void addEdgesForInstruction(const MachineInstr& minstr,
const ValueToDefVecMap& valueToDefVecMap, const ValueToDefVecMap& valueToDefVecMap,
const TargetMachine& target); const TargetMachine& target);
void addCDEdges (const TerminatorInst* term, void addCDEdges (const TerminatorInst* term,
const TargetMachine& target); const TargetMachine& target);
void addMemEdges (const vector<const Instruction*>& memVec, void addMemEdges (const vector<SchedGraphNode*>& memNodeVec,
const TargetMachine& target); const TargetMachine& target);
void addCallCCEdges (const vector<const Instruction*>& memVec, void addCallCCEdges (const vector<SchedGraphNode*>& memNodeVec,
MachineCodeForBasicBlock& bbMvec, MachineCodeForBasicBlock& bbMvec,
const TargetMachine& target); const TargetMachine& target);
void addMachineRegEdges (RegToRefVecMap& regToRefVecMap, void addMachineRegEdges (RegToRefVecMap& regToRefVecMap,
const TargetMachine& target); const TargetMachine& target);